diff options
913 files changed, 311 insertions, 305214 deletions
diff --git a/Android.bp b/Android.bp deleted file mode 100644 index 5c41f75c7..000000000 --- a/Android.bp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2017 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. - -subdirs = [ - "libwifi_system", - "libwifi_system_iface", - "service", - "service/apex", - "service/proto", - "tests", -] diff --git a/MOVED.txt b/MOVED.txt new file mode 100644 index 000000000..c71b6867b --- /dev/null +++ b/MOVED.txt @@ -0,0 +1,10 @@ +Source code and tests for Wifi service have moved to +packages/modules/Wifi/service. + +- frameworks/opt/net/wifi/service/apex -> packages/modules/Wifi/apex +- frameworks/opt/net/wifi/service/java -> packages/modules/Wifi/service/java +- frameworks/opt/net/wifi/service/res -> packages/modules/Wifi/service/ServiceWifiResources/res +- frameworks/opt/net/wifi/tests/ -> packages/modules/Wifi/service/tests + +What remains in frameworks/opt/net/wifi are Wifi libraries that +are not part of the Wifi module. @@ -1,4 +1 @@ -etancohen@google.com -mplass@google.com -rpius@google.com -satk@google.com
\ No newline at end of file +include platform/packages/modules/Wifi:/OWNERS diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 32b4e3bb6..2673295d9 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -1,6 +1,5 @@ [Hook Scripts] checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} -metrics_pdd_hook = ${REPO_ROOT}/frameworks/opt/net/wifi/metrics_pdd_hook.py "service/proto/src/metrics.proto" ${PREUPLOAD_COMMIT_MESSAGE} ${PREUPLOAD_FILES} [Builtin Hooks] commit_msg_bug_field = true diff --git a/TEST_MAPPING b/TEST_MAPPING deleted file mode 100644 index fe5ba48d4..000000000 --- a/TEST_MAPPING +++ /dev/null @@ -1,15 +0,0 @@ -{ - "presubmit": [ - { - "name": "FrameworksWifiTests" - }, - { - "name": "CtsBackupHostTestCases", - "options": [ - { - "include-filter": "android.cts.backup.OtherSoundsSettingsHostSideTest" - } - ] - } - ] -} diff --git a/libs/WifiTrackerLib/Android.bp b/libs/WifiTrackerLib/Android.bp index 5355d0037..eea49521b 100644 --- a/libs/WifiTrackerLib/Android.bp +++ b/libs/WifiTrackerLib/Android.bp @@ -1,3 +1,7 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + android_library { name: "WifiTrackerLib", srcs: ["src/**/*.java"], diff --git a/libs/WifiTrackerLib/res/values-af/strings.xml b/libs/WifiTrackerLib/res/values-af/strings.xml index 1246b1074..6c946a02d 100644 --- a/libs/WifiTrackerLib/res/values-af/strings.xml +++ b/libs/WifiTrackerLib/res/values-af/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Outomatiese koppeling is af"</string> <string name="saved_network" msgid="6241977554502802914">"Gestoor deur <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Sal nie outomaties koppel nie"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Sal nie outomaties koppel nie"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Geen internettoegang nie"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Stawingsprobleem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Gaan wagwoord na en probeer weer"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Beperk"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Onbeperk"</string> <string name="connected_via_app" msgid="1818040967936972127">"Gekoppel via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Beskikbaar deur <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Outomaties gekoppel deur <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Outomaties deur %1$s gekoppel"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Outomaties deur netwerkgraderingverskaffer gekoppel"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Beperkte verbinding"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Daar kan nie by private DNS-bediener ingegaan word nie"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Geen internet nie"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lae gehalte"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Geen"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Verval"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tik om aan te meld"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tik om intekening te hernu en te koppel"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Maak tans <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> oop"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Kon nie koppel nie"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Voltooi tans aanmelding …"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Kon nie aanmelding voltooi nie. Tik om weer te probeer."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Aanmelding is voltooi. Koppel tans …"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Hierdie netwerk ontvang \'n SIM-ID wat gebruik kan word om toestelligging na te spoor. "<annotation id="url">"Kom meer te wete"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Baie stadig"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Stadig"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Middelmatig"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Vinnig"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Baie vinnig"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-am/strings.xml b/libs/WifiTrackerLib/res/values-am/strings.xml index 78c66a2da..001f59d18 100644 --- a/libs/WifiTrackerLib/res/values-am/strings.xml +++ b/libs/WifiTrackerLib/res/values-am/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ራስ-ተገናኝ ጠፍቷል"</string> <string name="saved_network" msgid="6241977554502802914">"የተቀመጠው በ<xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"በራስ-ሰር አይገናኝም"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"በራስ-ሰር አይገናኝም"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ምንም የበይነመረብ መዳረሻ የለም"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"የማረጋገጥ ችግር"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"የይለፍ ቃልን ይፈትሹ እና እንደገና ይሞክሩ"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"የሚለካ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"ያልተለካ"</string> <string name="connected_via_app" msgid="1818040967936972127">"በ <xliff:g id="NAME">%1$s</xliff:g> በኩል ተገናኝተዋል"</string> - <string name="available_via_app" msgid="9110324040292242769">"በ<xliff:g id="NAME">%1$s</xliff:g> በኩል የሚገኝ"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"በ<xliff:g id="NAME">%1$s</xliff:g> በኩል በራስ-ሰር ተገናኝቷል"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"በ%1$s በኩል በራስ-ሰር ተገናኝቷል"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"በአውታረ መረብ ደረጃ ሰጪ አቅራቢ በኩል በራስ-ሰር ተገናኝቷል"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"የተገደበ ግንኙነት"</string> <string name="private_dns_broken" msgid="2212227512243587416">"የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ምንም በይነመረብ የለም"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"አነስተኛ ጥራት"</string> <string name="wifi_security_none" msgid="6680263031386719053">"የለም"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ጊዜው አልፏል"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"ለመመዝገብ መታ ያድርጉ"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"የደንበኝነት ምዝገባን ዳግም ለማደስ እና ለማገናኘት መታ ይድርጉ"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>ን በመክፈት ላይ"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"መገናኘት አልተቻለም"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"መመዝገብን በማጠናቀቅ ላይ…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ምዝገባን ማጠናቀቅ አልተቻለም። እንደገና ለመሞከር መታ ያድርጉ።"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ምዝገባ ተጠናቋል። በማገናኘት ላይ…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"ይህ አውታረ መረብ የመሣሪያ አካባቢን ለመከታተል ሥራ ላይ ሊውል የሚችል የሲም መታወቂያ ይቀበላል። "<annotation id="url">"የበለጠ ለመረዳት"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"በጣም ቀርፋፋ"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"አዘግይ"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"እሺ"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"መካከለኛ"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"ፈጣን"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"እጅግ በጣም ፈጣን"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ar/strings.xml b/libs/WifiTrackerLib/res/values-ar/strings.xml index 40ac14995..5d9f97466 100644 --- a/libs/WifiTrackerLib/res/values-ar/strings.xml +++ b/libs/WifiTrackerLib/res/values-ar/strings.xml @@ -17,41 +17,26 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"الاتصال التلقائي غير مفعّل"</string> + <!-- no translation found for auto_connect_disable (1078319396240632542) --> + <skip /> <string name="saved_network" msgid="6241977554502802914">"تم الحفظ بواسطة <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"لن يتم الاتصال بالإنترنت تلقائيًا."</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"لن يتم الاتصال تلقائيًا"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"لا يتوفّر اتصال بالإنترنت"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"مشكلة في المصادقة"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"يُرجى التحقق من كلمة المرور وإعادة المحاولة"</string> - <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"تعذّر إعداد عنوان IP"</string> + <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"تعذّرت تهيئة عنوان IP"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"غير مفعّلة"</string> - <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"نقطة الوصول ممتلئة مؤقتًا"</string> + <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"نقطة الدخول ممتلئة مؤقتًا"</string> <string name="wifi_disconnected" msgid="3720926757662831062">"غير متصلة"</string> <string name="wifi_remembered" msgid="5126903736498678708">"تم الحفظ"</string> <string name="wifi_metered_label" msgid="1362621600006544014">"تفرض تكلفة استخدام"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"بدون قياس"</string> <string name="connected_via_app" msgid="1818040967936972127">"تم الاتصال عبر <xliff:g id="NAME">%1$s</xliff:g>."</string> - <string name="available_via_app" msgid="9110324040292242769">"متاحة من خلال <xliff:g id="NAME">%1$s</xliff:g>."</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"تم تلقائيًا توصيل الجهاز بشبكة <xliff:g id="NAME">%1$s</xliff:g>."</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"تم الاتصال تلقائيًا عبر %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"تم الاتصال تلقائيًا عبر مقدم خدمة تقييم الشبكة"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"اتصال محدود"</string> <string name="private_dns_broken" msgid="2212227512243587416">"لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"لا يتوفر اتصال إنترنت."</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"جودة منخفضة"</string> <string name="wifi_security_none" msgid="6680263031386719053">"بلا أمان"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"منتهية الصلاحية"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"انقر للاشتراك."</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"انقر لتجديد الاشتراك والاتصال بالشبكة."</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"جارٍ فتح <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"تعذّر الاتصال بالإنترنت."</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"جارٍ إكمال الاشتراك…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"تعذّر إكمال الاشتراك. انقر لإعادة المحاولة."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"اكتمل الاشتراك. جارٍ الاتصال…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"تتلقّى هذه الشبكة رقم تعريف لشريحة SIM يمكن استخدامه لتتبُّع الموقع الجغرافي للجهاز. "<annotation id="url">"مزيد من المعلومات"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"بطيئة جدًا"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"بطيئة"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"حسنًا"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"متوسطة"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"سريعة"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"سريعة جدًا"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-as/strings.xml b/libs/WifiTrackerLib/res/values-as/strings.xml index a9a17b3fe..a8a4458b9 100644 --- a/libs/WifiTrackerLib/res/values-as/strings.xml +++ b/libs/WifiTrackerLib/res/values-as/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"স্বয়ংক্ৰিয়ভাৱে সংযোগ হোৱা সুবিধাটো অফ কৰা আছে"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g>এ ছেভ কৰিছে"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"স্বয়ংক্ৰিয়ভাৱে সংযোগ নহ’ব"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"স্বয়ংক্ৰিয়ভাৱে সংযোগ নহ’ব"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ইণ্টাৰনেটৰ এক্সেছ নাই"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণত সমস্যা হৈছে"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"পাছৱৰ্ড পৰীক্ষা কৰি আকৌ চেষ্টা কৰক"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"নিৰিখ-নিৰ্দিষ্ট"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"নিৰিখ অনিৰ্দিষ্ট"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g>ৰ জৰিয়তে সংযুক্ত"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g>ৰ জৰিয়তে উপলব্ধ"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g>ৰ জৰিয়তে স্বয়ংক্ৰিয়ভাৱে সংযুক্ত"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s মাধ্যমেদি স্বয়ংক্ৰিয়ভাৱে সংযোগ কৰা হৈছে"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"নেটৱৰ্ক ৰেটিং প্ৰদানকাৰীৰ জৰিয়তে স্বয়ং সংয়োগ কৰা হ’ল"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"ইণ্টাৰনেট সংযোগ সীমিত"</string> <string name="private_dns_broken" msgid="2212227512243587416">"ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ইণ্টাৰনেট সংযোগ নাই"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"নিম্ন মানৰ"</string> <string name="wifi_security_none" msgid="6680263031386719053">"নাই"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ম্যাদ উকলিছে"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"ছাইন আপ কৰিবলৈ টিপক"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"ছাবস্ক্ৰিপশ্বন নৱীকৰণ আৰু সংযোগ কৰিবলৈ টিপক"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> খুলি থকা হৈছে"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"সংযোগ কৰিব পৰা নগ’ল"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"ছাইন আপ সম্পূৰ্ণ কৰি থকা হৈছে…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ছাইন আপ সম্পূৰ্ণ কৰিব পৰা নগ’ল। পুনৰ চেষ্টা কৰিবলৈ টিপক।"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ছাইন আপ সম্পূৰ্ণ হৈছে। সংযোগ কৰি থকা হৈছে…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"এই নেটৱৰ্কটোৱে এটা ছিম আইডি পায়, যিটো ডিভাইচৰ অৱস্থান ট্ৰেক কৰিবলৈ ব্যৱহাৰ কৰিব পাৰি। "<annotation id="url">"অধিক জানক"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"অতি লেহেম"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"লেহেমীয়া"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ঠিক"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"মধ্যমীয়া"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"দ্ৰুত"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"অতি দ্ৰুত"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-az/strings.xml b/libs/WifiTrackerLib/res/values-az/strings.xml index 8752985ed..851b88f43 100644 --- a/libs/WifiTrackerLib/res/values-az/strings.xml +++ b/libs/WifiTrackerLib/res/values-az/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Avtomatik qoşulma sönülüdür"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> tərəfindən saxlandı"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Avtomatik qoşulmayacaq"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Avtomatik qoşulmayacaq"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"İnternetə giriş yoxdur"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Doğrulama problemi"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Parolu yoxlayın və yenidən cəhd edin"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Ödənişli"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Limitsiz"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> ilə qoşulub"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> vasitəsilə əlçatandır"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> vasitəsilə avtomatik qoşulub"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s üzərindən avtomatik qoşuldu"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Avtomatik olaraq şəbəkə reytinq provayderi ilə qoşuludur"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Məhdud bağlantı"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Özəl DNS serverinə giriş mümkün deyil"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"İnternet yoxdur"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Aşağı keyfiyyət"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Heç biri"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Vaxtı keçib"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Qeydiyyatdan keçmək üçün toxunun"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Abunəliyi yeniləmək və qoşulmaq üçün toxunun"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> açılır"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Qoşulmaq mümkün olmadı"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Qeydiyyat tamamlanır…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Qeydiyyat tamamlanmadı. Yenidən cəhd etmək üçün toxunun."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Qeydiyyat tamamlandı. Qoşulur…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Bu şəbəkə cihaz məkanını izləmək üçün istifadə edilə biləcək SIM ID qəbul edir. "<annotation id="url">"Ətraflı məlumat"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Çox Yavaş"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Yavaş"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Orta"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Sürətli"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Çox Sürətli"</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 4a36f1b27..30a224071 100644 --- a/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml +++ b/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatsko povezivanje je isključeno"</string> <string name="saved_network" msgid="6241977554502802914">"Sačuvao/la je <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Automatsko povezivanje nije uspelo"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Automatsko povezivanje nije uspelo"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nema pristupa internetu"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problem sa potvrdom identiteta"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Proverite lozinku i probajte ponovo"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Sa ograničenjem"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Bez ograničenja"</string> <string name="connected_via_app" msgid="1818040967936972127">"Povezano preko: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Dostupno preko aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatski povezano preko: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatski povezano preko %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatski povezano preko dobavljača ocene mreže"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ograničena veza"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Pristup privatnom DNS serveru nije uspeo"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nema interneta"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Loš kvalitet"</string> - <string name="wifi_security_none" msgid="6680263031386719053">"Ništa"</string> + <string name="wifi_security_none" msgid="6680263031386719053">"Nema"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Isteklo"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Dodirnite da biste se registrovali"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Dodirnite da biste obnovili pretplatu i povezali"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Otvara se <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Povezivanje nije uspelo"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registracija se dovršava…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Dovršavanje registracije nije uspelo. Dodirnite da biste probali ponovo."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registracija je dovršena. Povezuje se…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ova mreža dobija ID SIM kartice koji može da se koristi za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Veoma spora"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Spora"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Potvrdi"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Srednja"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Brza"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Veoma brza"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-be/strings.xml b/libs/WifiTrackerLib/res/values-be/strings.xml index e8f0f7cea..5dfdab113 100644 --- a/libs/WifiTrackerLib/res/values-be/strings.xml +++ b/libs/WifiTrackerLib/res/values-be/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Аўтападключэнне выключана"</string> <string name="saved_network" msgid="6241977554502802914">"Захавана праз: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Не будзе аўтаматычна падключацца"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Не будзе аўтаматычна падключацца"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Няма доступу да інтэрнэту"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Памылка аўтэнтыфікацыі"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Праверце пароль і паўтарыце спробу"</string> @@ -28,30 +28,14 @@ <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"Пункт доступу часова заняты"</string> <string name="wifi_disconnected" msgid="3720926757662831062">"Адключана"</string> <string name="wifi_remembered" msgid="5126903736498678708">"Захавана"</string> - <string name="wifi_metered_label" msgid="1362621600006544014">"Сетка з падлікам трафіка"</string> + <string name="wifi_metered_label" msgid="1362621600006544014">"Сетка з улікам трафіка"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Сетка без уліку трафіка"</string> <string name="connected_via_app" msgid="1818040967936972127">"Падключана праз праграму \"<xliff:g id="NAME">%1$s</xliff:g>\""</string> - <string name="available_via_app" msgid="9110324040292242769">"Даступна праз: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Аўтаматычна падключана праз: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Аўтаматычна падключана праз %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Аўтаматычна падключана праз пастаўшчыка паслугі ацэнкі сеткі"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Абмежаваныя магчымасці падключэння"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Не ўдалося атрымаць доступ да прыватнага DNS-сервера"</string> - <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Няма падключэння да інтэрнэту"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Нізкая якасць"</string> + <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Не падключана да інтэрнэту"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Няма"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Тэрмін скончыўся"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Націсніце, каб зарэгістравацца"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Націсніце, каб падоўжыць падпіску і падключыцца"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Адкрываецца <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Не ўдалося падключыцца"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Рэгістрацыя завяршаецца…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Не ўдалося выканаць рэгістрацыю. Дакраніцеся, каб паўтарыць спробу."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Рэгістрацыя завершана. Ідзе падключэнне…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Гэта сетка атрымлівае ідэнтыфікатар SIM-карты, які можа выкарыстоўвацца для адсочвання месцазнаходжання прылады. "<annotation id="url">"Даведацца больш"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Вельмі павольная"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Павольная"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ОК"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Сярэдняя"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Хуткая"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Вельмі хуткая"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-bg/strings.xml b/libs/WifiTrackerLib/res/values-bg/strings.xml index 83230d881..3284e2290 100644 --- a/libs/WifiTrackerLib/res/values-bg/strings.xml +++ b/libs/WifiTrackerLib/res/values-bg/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"Изкл. авт. свързване"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"Функцията за автоматично свързване е изключена"</string> <string name="saved_network" msgid="6241977554502802914">"Запазено от <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Няма да се свърже автоматично"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Няма да се свърже автоматично"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Няма достъп до интернет"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Проблем при удостоверяването"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Проверете паролата и опитайте отново"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"С отчитане"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Без отчитане"</string> <string name="connected_via_app" msgid="1818040967936972127">"Установена е връзка през <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Достъпно чрез <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Автоматично бе установена връзка през <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Автоматично е установена връзка чрез %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Автоматично е установена връзка чрез доставчик на услуги за оценяване на мрежите"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ограничена връзка"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Не може да се осъществи достъп до частния DNS сървър"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Няма интернет"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ниско качество"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Няма"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Изтекло"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Докоснете, за да се регистрирате"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Докоснете, за да подновите абонамента и да установите връзка"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> се отваря"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Не можа да се установи връзка"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Регистрацията се завършва…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Регистрацията не можа да бъде завършена. Докоснете, за да опитате отново."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Регистрацията е завършена. Установява се връзка…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Тази мрежа получава идентификатор за SIM карта, който може да се използва за проследяване на местоположението на устройството. "<annotation id="url">"Научете повече"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Много бавна"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Бавна"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ОK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Средна"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Бърза"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Много бърза"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-bn/strings.xml b/libs/WifiTrackerLib/res/values-bn/strings.xml index 0528cb756..cc8c00bfb 100644 --- a/libs/WifiTrackerLib/res/values-bn/strings.xml +++ b/libs/WifiTrackerLib/res/values-bn/strings.xml @@ -17,9 +17,10 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"নিজে থেকে কানেক্ট করার ফিচার বন্ধ আছে"</string> + <!-- no translation found for auto_connect_disable (1078319396240632542) --> + <skip /> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> দ্বারা সেভ করা"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"অটোমেটিক কানেক্ট করবে না"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"অটোমেটিক কানেক্ট করবে না"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ইন্টারনেট অ্যাক্সেসের সুবিধা নেই"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"যাচাইকরণের সমস্যা"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"পাসওয়ার্ড দেখে আবার চেষ্টা করুন"</string> @@ -31,27 +32,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"মিটার্ড"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"পরিমাপ করা নয়"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g>-এর মাধ্যমে কানেক্ট করা আছে"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g>-এর মাধ্যমে উপলভ্য"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g>-এর মাধ্যমে অটোমেটিক কানেক্ট করা আছে"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"স্বয়ংক্রিয়ভাবে %1$s এর মাধ্যমে কানেক্ট হয়েছে"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"নেটওয়ার্কের রেটিং প্রদানকারীর মাধ্যমে অটোমেটিক কানেক্ট"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"সীমিত কানেকশন"</string> <string name="private_dns_broken" msgid="2212227512243587416">"ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ইন্টারনেট কানেকশন নেই"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"খারাপ কোয়ালিটি"</string> - <string name="wifi_security_none" msgid="6680263031386719053">"কোনও কিছুই নয়"</string> + <string name="wifi_security_none" msgid="6680263031386719053">"কোনো কিছুই নয়"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"মেয়াদ শেষ হয়ে গেছে"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"সাইন-আপ করতে ট্যাপ করুন"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"সাবস্ক্রিপশন রিনিউ করে কানেক্ট করতে ট্যাপ করুন"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> খোলা হচ্ছে"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"কানেক্ট করা যায়নি"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"সাইন-আপ করা হচ্ছে…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"সাইন-আপ করা যায়নি। আবার চেষ্টা করতে ট্যাপ করুন।"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"সাইন-আপ করা হয়ে গেছে। কানেক্ট করা হচ্ছে…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"এই নেটওয়ার্কের কাছে একটি সিম আইডি থাকে যা ব্যবহার করে ডিভাইসের লোকেশন ট্র্যাক করা যাবে। "<annotation id="url">"আরও জানুন"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"খুব ধীরে"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"ধীরে"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ঠিক আছে"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"মাঝারি"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"দ্রুত"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"খুব দ্রুত"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-bs/arrays.xml b/libs/WifiTrackerLib/res/values-bs/arrays.xml index 9428a3763..727f5d75a 100644 --- a/libs/WifiTrackerLib/res/values-bs/arrays.xml +++ b/libs/WifiTrackerLib/res/values-bs/arrays.xml @@ -27,7 +27,7 @@ <item msgid="1176401854208153464">"Autentifikacija…"</item> <item msgid="1377026397901197257">"Dobivanje IP adrese…"</item> <item msgid="7627139816052121509">"Povezano"</item> - <item msgid="1598801023719359130">"Obustavljeno"</item> + <item msgid="1598801023719359130">"Suspendirano"</item> <item msgid="9160765456671002324">"Prekidanje veze…"</item> <item msgid="8013176736494493734">"Veza je prekinuta"</item> <item msgid="4077393480368783785">"Neuspješno"</item> diff --git a/libs/WifiTrackerLib/res/values-bs/strings.xml b/libs/WifiTrackerLib/res/values-bs/strings.xml index 148c02050..6f36807d5 100644 --- a/libs/WifiTrackerLib/res/values-bs/strings.xml +++ b/libs/WifiTrackerLib/res/values-bs/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatsko povezivanje je isključeno"</string> <string name="saved_network" msgid="6241977554502802914">"Sačuvano: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Automatsko povezivanje nije moguće"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Neće se automatski povezati"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nema pristupa internetu"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problem pri autentifikaciji"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Provjerite lozinku i pokušajte ponovo"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"S naplatom"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Mreža bez naplate"</string> <string name="connected_via_app" msgid="1818040967936972127">"Povezano preko <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Dostupno putem mreže <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatski povezano putem mreže <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatski povezano koristeći %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatski povezano putem ocjenjivača mreže"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ograničena veza"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Nije moguće pristupiti privatnom DNS serveru"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nema internetske veze"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nizak kvalitet"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ništa"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Isteklo"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Dodirnite za registraciju"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Dodirnite da obnovite pretplatu i povežete se"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Otvaranje <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Povezivanje nije uspjelo"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Završavanje registracije…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registraciju nije moguće izvršiti. Dodirnite da pokušate ponovo."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registracija je završena. Povezivanje…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ova mreža prima ID SIM-a koji se može koristiti za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Veoma sporo"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Sporo"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Uredu"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Srednja brzina"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Brzo"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Veoma brzo"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Istekao"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ca/strings.xml b/libs/WifiTrackerLib/res/values-ca/strings.xml index a07ee2e4a..63a40a006 100644 --- a/libs/WifiTrackerLib/res/values-ca/strings.xml +++ b/libs/WifiTrackerLib/res/values-ca/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Connexió automàtica desactivada"</string> <string name="saved_network" msgid="6241977554502802914">"Desada per <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"No es connectarà automàticament"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"No es connectarà automàticament"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"No hi ha accés a Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problema d\'autenticació"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Comprova la contrasenya i torna-ho a provar"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"D\'ús mesurat"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"D\'ús no mesurat"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connectat mitjançant <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponible mitjançant <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Connectada automàticament a través de: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Connectada automàticament a través de: %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Connectada automàticament a través d\'un proveïdor de valoració de xarxes"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Connexió limitada"</string> <string name="private_dns_broken" msgid="2212227512243587416">"No es pot accedir al servidor DNS privat"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sense connexió a Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Qualitat baixa"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Cap"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Caducada"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Toca per registrar-te"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Toca per renovar la subscripció i connectar-te"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"S\'està obrint <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"No s\'ha pogut connectar"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"S\'està completant el registre…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"No s\'ha pogut completar el registre. Toca per tornar-ho a provar."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"S\'ha completat el registre. S\'està connectant…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Aquesta xarxa rep un identificador de SIM que es pot utilitzar per fer el seguiment de la ubicació del dispositiu. "<annotation id="url">"Més informació"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Molt lenta"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Correcta"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Mitjana"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Ràpida"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Molt ràpida"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Caducat"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-cs/strings.xml b/libs/WifiTrackerLib/res/values-cs/strings.xml index 6562a2873..bd207468e 100644 --- a/libs/WifiTrackerLib/res/values-cs/strings.xml +++ b/libs/WifiTrackerLib/res/values-cs/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatické připojení je vypnuté"</string> <string name="saved_network" msgid="6241977554502802914">"Uloženo uživatelem <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Nelze se automaticky připojit"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Připojení nebude automaticky navázáno"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nejste připojeni k internetu"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problém s ověřením"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Zkontrolujte heslo a zkuste to znovu"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Měřená"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Neměřená"</string> <string name="connected_via_app" msgid="1818040967936972127">"Připojeno přes <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Dostupné přes <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automaticky připojeno přes <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automaticky připojeno přes poskytovatele %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automaticky připojeno přes poskytovatele hodnocení sítí"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Omezené připojení"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Nelze získat přístup k soukromému serveru DNS"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nejste připojeni k internetu"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nízká kvalita"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Žádné"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Platnost vypršela"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Klepnutím se zaregistrujete"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Klepnutím obnovíte předplatné a připojíte se"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Spouštění aplikace <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Nelze se připojit"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Dokončování registrace…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registraci se nepodařilo dokončit. Klepnutím opakujte akci."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrace byla dokončena. Připojování…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Tato síť dostane identifikátor SIM karty, pomocí kterého lze sledovat polohu zařízení. "<annotation id="url">"Další informace"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Velmi pomalá"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Pomalá"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Střední"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rychlá"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Velmi rychlá"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-da/strings.xml b/libs/WifiTrackerLib/res/values-da/strings.xml index d8a2cb96f..5f82c1216 100644 --- a/libs/WifiTrackerLib/res/values-da/strings.xml +++ b/libs/WifiTrackerLib/res/values-da/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatisk forbindelse til Wi-Fi er deaktiveret"</string> <string name="saved_network" msgid="6241977554502802914">"Gemt af <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Der oprettes ikke automatisk forbindelse"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Der oprettes ikke automatisk forbindelse"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Ingen internetadgang"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problem med godkendelse"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Tjek adgangskoden, og prøv igen"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Forbrugsafregnet"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Ikke forbrugsafregnet"</string> <string name="connected_via_app" msgid="1818040967936972127">"Forbundet via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Tilgængeligt via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Der er oprettet automatisk forbindelse via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatisk tilsluttet via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatisk forbundet via udbyder af netværksvurdering"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Begrænset forbindelse"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Der er ikke adgang til den private DNS-server"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Intet internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Dårlig kvalitet"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ingen"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Udløbet"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tryk for at registrere"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tryk for at forny abonnementet, og opret forbindelse"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Åbner <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Der kunne ikke oprettes forbindelse"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Fuldfører registrering…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registreringen kunne ikke fuldføres. Tryk for at prøve igen."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registreringen er fuldført. Opretter forbindelse…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Dette netværk kræver et SIM-id, der kan bruges til at spore enhedens placering. "<annotation id="url">"Få flere oplysninger"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Meget langsom"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Langsom"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Middel"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Hurtig"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Meget hurtig"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-de/strings.xml b/libs/WifiTrackerLib/res/values-de/strings.xml index c6a554e48..12305f4c9 100644 --- a/libs/WifiTrackerLib/res/values-de/strings.xml +++ b/libs/WifiTrackerLib/res/values-de/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatische Verbindung ist deaktiviert"</string> <string name="saved_network" msgid="6241977554502802914">"Gespeichert von <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Kein automatischer Verbindungsaufbau"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Kein automatischer Verbindungsaufbau"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Kein Internetzugriff"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Authentifizierungsproblem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Prüfe das Passwort und versuch es noch einmal"</string> @@ -29,29 +29,13 @@ <string name="wifi_disconnected" msgid="3720926757662831062">"Nicht verbunden"</string> <string name="wifi_remembered" msgid="5126903736498678708">"Gespeichert"</string> <string name="wifi_metered_label" msgid="1362621600006544014">"Kostenpflichtig"</string> - <string name="wifi_unmetered_label" msgid="499466875639448350">"Ohne Datenlimit"</string> + <string name="wifi_unmetered_label" msgid="499466875639448350">"Kostenlos"</string> <string name="connected_via_app" msgid="1818040967936972127">"Verbunden über <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Über <xliff:g id="NAME">%1$s</xliff:g> verfügbar"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatisch verbunden über <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatisch über %1$s verbunden"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatisch über Anbieter von Netzwerkbewertungen verbunden"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Eingeschränkte Verbindung"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Auf den privaten DNS-Server kann nicht zugegriffen werden"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Kein Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niedrige Qualität"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Keine"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Abgelaufen"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Zum Registrieren tippen"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tippen, um das Abo zu verlängern und eine Verbindung herzustellen"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> wird geöffnet"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Verbindung nicht möglich"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registrierung wird abgeschlossen…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registrierung konnte nicht abgeschlossen werden. Tippe, um es noch einmal zu versuchen."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrierung abgeschlossen. Verbindung wird hergestellt…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Dieses Netzwerk empfängt eine SIM-ID, mit der der Gerätestandort erfasst werden kann. "<annotation id="url">"Weitere Informationen."</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Sehr langsam"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Langsam"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Ok"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Mittel"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Schnell"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Sehr schnell"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-el/strings.xml b/libs/WifiTrackerLib/res/values-el/strings.xml index 4ae7d7424..34f687412 100644 --- a/libs/WifiTrackerLib/res/values-el/strings.xml +++ b/libs/WifiTrackerLib/res/values-el/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Η αυτόματη σύνδεση είναι απενεργοποιημένη"</string> <string name="saved_network" msgid="6241977554502802914">"Αποθηκεύτηκε από <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Δεν συνδέεται αυτόματα"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Δεν θα συνδεθεί αυτόματα"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Δεν υπάρχει πρόσβαση στο διαδίκτυο."</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Πρόβλημα ελέγχου ταυτότητας"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Ελέγξτε τον κωδικό πρόσβασης και δοκιμάστε ξανά"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Μέτρηση με βάση τη χρήση"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Χωρίς μέτρηση με βάση τη χρήση"</string> <string name="connected_via_app" msgid="1818040967936972127">"Συνδέθηκε μέσω <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Διαθέσιμο μέσω <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Συνδέθηκε αυτόματα μέσω <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Συνδέθηκε αυτόματα μέσω %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Συνδέθηκε αυτόματα μέσω παρόχου αξιολόγησης δικτύου"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Περιορισμένη σύνδεση"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS."</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Χωρίς σύνδεση στο διαδίκτυο"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Χαμηλή ποιότητα"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Καμία"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Έληξε"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Πατήστε για εγγραφή"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Πατήστε για να ανανεώσετε τη συνδρομή σας και να συνδεθείτε."</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Άνοιγμα <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Αδυναμία σύνδεσης"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Ολοκλήρωση εγγραφής…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Δεν ήταν δυνατή η ολοκλήρωση της εγγραφής. Πατήστε για να δοκιμάσετε ξανά."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Η εγγραφή ολοκληρώθηκε. Σύνδεση…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Αυτό το δίκτυο λαμβάνει ένα αναγνωριστικό SIM το οποίο μπορεί να χρησιμοποιηθεί για τον εντοπισμό της τοποθεσίας της συσκευής. "<annotation id="url">"Μάθετε περισσότερα"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Πολύ αργή"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Αργή"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ΟΚ"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Μέτρια"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Γρήγορη"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Πολύ γρήγορη"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-en-rAU/strings.xml b/libs/WifiTrackerLib/res/values-en-rAU/strings.xml index 70d1a9cf6..514f33eef 100644 --- a/libs/WifiTrackerLib/res/values-en-rAU/strings.xml +++ b/libs/WifiTrackerLib/res/values-en-rAU/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Auto-connect is off"</string> <string name="saved_network" msgid="6241977554502802914">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Won’t automatically connect"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Won\'t automatically connect"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"No Internet access"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Authentication problem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Check password and try again"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Metered"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Unmetered"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Available via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatically connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatically connected via network rating provider"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string> <string name="wifi_security_none" msgid="6680263031386719053">"None"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tap to renew subscription and connect"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Opening <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Couldn’t connect"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completing sign-up…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Couldn’t complete sign-up. Tap to try again."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Sign-up complete. Connecting…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Very slow"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Slow"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Medium"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Fast"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Very fast"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-en-rCA/strings.xml b/libs/WifiTrackerLib/res/values-en-rCA/strings.xml index 70d1a9cf6..514f33eef 100644 --- a/libs/WifiTrackerLib/res/values-en-rCA/strings.xml +++ b/libs/WifiTrackerLib/res/values-en-rCA/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Auto-connect is off"</string> <string name="saved_network" msgid="6241977554502802914">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Won’t automatically connect"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Won\'t automatically connect"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"No Internet access"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Authentication problem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Check password and try again"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Metered"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Unmetered"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Available via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatically connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatically connected via network rating provider"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string> <string name="wifi_security_none" msgid="6680263031386719053">"None"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tap to renew subscription and connect"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Opening <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Couldn’t connect"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completing sign-up…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Couldn’t complete sign-up. Tap to try again."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Sign-up complete. Connecting…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Very slow"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Slow"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Medium"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Fast"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Very fast"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-en-rGB/strings.xml b/libs/WifiTrackerLib/res/values-en-rGB/strings.xml index 70d1a9cf6..514f33eef 100644 --- a/libs/WifiTrackerLib/res/values-en-rGB/strings.xml +++ b/libs/WifiTrackerLib/res/values-en-rGB/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Auto-connect is off"</string> <string name="saved_network" msgid="6241977554502802914">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Won’t automatically connect"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Won\'t automatically connect"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"No Internet access"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Authentication problem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Check password and try again"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Metered"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Unmetered"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Available via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatically connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatically connected via network rating provider"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string> <string name="wifi_security_none" msgid="6680263031386719053">"None"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tap to renew subscription and connect"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Opening <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Couldn’t connect"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completing sign-up…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Couldn’t complete sign-up. Tap to try again."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Sign-up complete. Connecting…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Very slow"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Slow"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Medium"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Fast"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Very fast"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-en-rIN/strings.xml b/libs/WifiTrackerLib/res/values-en-rIN/strings.xml index 70d1a9cf6..514f33eef 100644 --- a/libs/WifiTrackerLib/res/values-en-rIN/strings.xml +++ b/libs/WifiTrackerLib/res/values-en-rIN/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Auto-connect is off"</string> <string name="saved_network" msgid="6241977554502802914">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Won’t automatically connect"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Won\'t automatically connect"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"No Internet access"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Authentication problem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Check password and try again"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Metered"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Unmetered"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Available via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatically connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatically connected via network rating provider"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string> <string name="wifi_security_none" msgid="6680263031386719053">"None"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tap to renew subscription and connect"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Opening <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Couldn’t connect"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completing sign-up…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Couldn’t complete sign-up. Tap to try again."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Sign-up complete. Connecting…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Very slow"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Slow"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Medium"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Fast"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Very fast"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-en-rXC/strings.xml b/libs/WifiTrackerLib/res/values-en-rXC/strings.xml index 2a7fadcdb..f48ddb231 100644 --- a/libs/WifiTrackerLib/res/values-en-rXC/strings.xml +++ b/libs/WifiTrackerLib/res/values-en-rXC/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Auto-connect is off"</string> <string name="saved_network" msgid="6241977554502802914">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Won’t automatically connect"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Won\'t automatically connect"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"No internet access"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Authentication problem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Check password and try again"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Metered"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Unmetered"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Available via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatically connected via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatically connected via network rating provider"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string> <string name="wifi_security_none" msgid="6680263031386719053">"None"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tap to renew subscription and connect"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Opening <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Couldn’t connect"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completing sign-up…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Couldn’t complete sign-up. Tap to try again."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Sign-up complete. Connecting…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation>""</string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Very Slow"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Slow"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Medium"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Fast"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Very Fast"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-es-rUS/strings.xml b/libs/WifiTrackerLib/res/values-es-rUS/strings.xml index 65a769775..06c9fce92 100644 --- a/libs/WifiTrackerLib/res/values-es-rUS/strings.xml +++ b/libs/WifiTrackerLib/res/values-es-rUS/strings.xml @@ -19,39 +19,23 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"La conexión automática está desactivada"</string> <string name="saved_network" msgid="6241977554502802914">"Guardada por <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"No se conectará automáticamente"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"No se conectará automáticamente"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"No hay acceso a Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problema de autenticación"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Revisa la contraseña y vuelve a intentarlo"</string> <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"Error de configuración de IP"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"Inhabilitada"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"El punto de acceso está completo temporalmente"</string> - <string name="wifi_disconnected" msgid="3720926757662831062">"Desconectado"</string> - <string name="wifi_remembered" msgid="5126903736498678708">"Guardado"</string> - <string name="wifi_metered_label" msgid="1362621600006544014">"De uso medido"</string> + <string name="wifi_disconnected" msgid="3720926757662831062">"Desconectada"</string> + <string name="wifi_remembered" msgid="5126903736498678708">"Guardada"</string> + <string name="wifi_metered_label" msgid="1362621600006544014">"Con uso medido"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Sin tarifa plana"</string> <string name="connected_via_app" msgid="1818040967936972127">"Conexión a través de <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponible a través de <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Se conectó automáticamente a través de <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Conexión automática mediante %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Conectado automáticamente mediante proveedor de calificación de red"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexión limitada"</string> <string name="private_dns_broken" msgid="2212227512243587416">"No se puede acceder al servidor DNS privado"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sin Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Baja calidad"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ninguna"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Vencida"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Presiona para registrarte"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Presiona para renovar la suscripción y conectarte"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Abriendo <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"No se pudo establecer conexión"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completando registro…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"No se pudo completar el registro. Presiona para volver a intentarlo."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Se completó el registro. Conectando…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Esta red recibe un ID de SIM que se puede usar para realizar el seguimiento de la ubicación del dispositivo. "<annotation id="url">"Más información"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Muy lenta"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Aceptar"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Media"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rápida"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Muy rápida"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Vencido"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-es/arrays.xml b/libs/WifiTrackerLib/res/values-es/arrays.xml index c9352b9b3..0b7fafc91 100644 --- a/libs/WifiTrackerLib/res/values-es/arrays.xml +++ b/libs/WifiTrackerLib/res/values-es/arrays.xml @@ -26,7 +26,7 @@ <item msgid="6222852518007967736">"Conectando…"</item> <item msgid="1176401854208153464">"Autenticando…"</item> <item msgid="1377026397901197257">"Obteniendo dirección IP…"</item> - <item msgid="7627139816052121509">"Conectado"</item> + <item msgid="7627139816052121509">"Conectada"</item> <item msgid="1598801023719359130">"Suspendida"</item> <item msgid="9160765456671002324">"Desconectando…"</item> <item msgid="8013176736494493734">"Desconectada"</item> diff --git a/libs/WifiTrackerLib/res/values-es/strings.xml b/libs/WifiTrackerLib/res/values-es/strings.xml index a9435e3ff..e2c10c2d3 100644 --- a/libs/WifiTrackerLib/res/values-es/strings.xml +++ b/libs/WifiTrackerLib/res/values-es/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"Conexión automática desactivada"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"La función Conexión automática está desactivada"</string> <string name="saved_network" msgid="6241977554502802914">"Guardada por <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"No se conectará automáticamente"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"No se establecerá conexión automáticamente"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"No hay acceso a Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problema de autenticación"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Comprueba la contraseña y vuelve a intentarlo"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Medida"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"No medida"</string> <string name="connected_via_app" msgid="1818040967936972127">"Conectado a través de <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponible a través de <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Conectada automáticamente mediante <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Conectada automáticamente a través de %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Conectado automáticamente a través de un proveedor de valoración de redes"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexión limitada"</string> <string name="private_dns_broken" msgid="2212227512243587416">"No se ha podido acceder al servidor DNS privado"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sin Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Calidad baja"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ninguna"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Caducada"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Toca para registrarte"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Toca para renovar la suscripción y conectarte"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Abriendo <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"No se ha podido conectar"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completando registro…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"No se ha podido completar el registro. Toca para volver a intentarlo."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Se ha completado el registro. Conectando…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Esta red recibe un ID de SIM con el que se puede rastrear la ubicación del dispositivo. "<annotation id="url">"Más información"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Muy lenta"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Aceptable"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Media"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rápida"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Muy rápida"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Caducado"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-et/strings.xml b/libs/WifiTrackerLib/res/values-et/strings.xml index aa919290d..3a0d22280 100644 --- a/libs/WifiTrackerLib/res/values-et/strings.xml +++ b/libs/WifiTrackerLib/res/values-et/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automaatne ühendamine on väljas"</string> <string name="saved_network" msgid="6241977554502802914">"Salvestas: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Ei ühendata automaatselt"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Automaatselt ei ühendata"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Juurdepääs internetile puudub"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Autentimise probleem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Kontrollige parooli ja proovige uuesti"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Mahupõhine"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Mittemahupõhine"</string> <string name="connected_via_app" msgid="1818040967936972127">"Ühendatud võrgu <xliff:g id="NAME">%1$s</xliff:g> kaudu"</string> - <string name="available_via_app" msgid="9110324040292242769">"Saadaval teenuse <xliff:g id="NAME">%1$s</xliff:g> kaudu"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automaatselt ühendatud teenusepakkuja <xliff:g id="NAME">%1$s</xliff:g> kaudu"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Ühendus loodi automaatselt teenusega %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Ühendus loodi automaatselt võrgukvaliteedi hinnangute pakkuja kaudu"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Piiratud ühendus"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Privaatsele DNS-serverile ei pääse juurde"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Interneti pole"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kehva kvaliteediga"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Puudub"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Aegunud"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Puudutage registreerimiseks"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Puudutage tellimuse uuendamiseks ja ühenduse loomiseks"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Teenuse <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> avamine"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Ühendust ei saanud luua"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registreerimise lõpuleviimine …"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registreerimist ei saanud lõpule viia. Puudutage, et uuesti proovida."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registreerimine on lõpule viidud. Ühendamine …"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"See võrk saab SIM-i ID, mida saab kasutada seadme asukoha jälgimiseks. "<annotation id="url">"Lisateave"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Väga aeglane"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Aeglane"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Hea"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Keskmine"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Kiire"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Väga kiire"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-eu/strings.xml b/libs/WifiTrackerLib/res/values-eu/strings.xml index da6fa13e4..a7b2ced4d 100644 --- a/libs/WifiTrackerLib/res/values-eu/strings.xml +++ b/libs/WifiTrackerLib/res/values-eu/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Konexio automatikoa desaktibatuta dago"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> aplikazioak gorde du"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Ez da konektatuko automatikoki"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Ez da konektatuko automatikoki"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Ez dago Interneteko konexiorik"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Autentifikazio-arazoa"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Egiaztatu pasahitza zuzena dela eta saiatu berriro"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Sare neurtua"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Neurtu gabeko sarea"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> bidez konektatuta"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> bidez erabilgarri"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatikoki konektatu da <xliff:g id="NAME">%1$s</xliff:g> bidez"</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatikoki konektatuta sare-balorazioen hornitzailearen bidez"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s bidez automatikoki konektatuta"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatikoki konektatuta sareen balorazioen hornitzailearen bidez"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Konexio mugatua"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Ezin da atzitu DNS zerbitzari pribatua"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ez dago Interneteko konexiorik"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kalitate txikia"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Bat ere ez"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Iraungita"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Sakatu izena emateko"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Sakatu harpidetza berritzeko eta konektatu ahal izateko"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> irekitzen"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Ezin izan da konektatu"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Izena ematen…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Ezin izan da eman izena. Berriro saiatzeko, ukitu hau."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Eman da izena. Konektatzen…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Gailuaren kokapenaren jarraipena egiteko balio duen SIM ID esklusibo bat jasotzen du sare honek. "<annotation id="url">"Lortu informazio gehiago"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Oso motela"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Motela"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Ados"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Tartekoa"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Bizkorra"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Oso bizkorra"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-fa/arrays.xml b/libs/WifiTrackerLib/res/values-fa/arrays.xml index 51ef4b84b..af40e8f4c 100644 --- a/libs/WifiTrackerLib/res/values-fa/arrays.xml +++ b/libs/WifiTrackerLib/res/values-fa/arrays.xml @@ -24,7 +24,7 @@ <item msgid="8763475525292171481"></item> <item msgid="903308535197209786">"درحال اسکن کردن…"</item> <item msgid="6222852518007967736">"درحال اتصال…"</item> - <item msgid="1176401854208153464">"درحال اصالتسنجی…"</item> + <item msgid="1176401854208153464">"درحال احراز هویت…"</item> <item msgid="1377026397901197257">"درحال دریافت نشانی IP…"</item> <item msgid="7627139816052121509">"متصل"</item> <item msgid="1598801023719359130">"معلق"</item> diff --git a/libs/WifiTrackerLib/res/values-fa/strings.xml b/libs/WifiTrackerLib/res/values-fa/strings.xml index ec535eb65..f000c7946 100644 --- a/libs/WifiTrackerLib/res/values-fa/strings.xml +++ b/libs/WifiTrackerLib/res/values-fa/strings.xml @@ -19,9 +19,9 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"اتصال خودکار خاموش است"</string> <string name="saved_network" msgid="6241977554502802914">"ذخیرهشده توسط <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"اتصال بهطور خودکار انجام نمیشود"</string> - <string name="wifi_no_internet" msgid="4461212237521310895">"دسترسی به اینترنت ندارد"</string> - <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"مشکل اصالتسنجی"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"اتصال بهصورت خودکار انجام نمیشود"</string> + <string name="wifi_no_internet" msgid="4461212237521310895">"بدون دسترسی به اینترنت"</string> + <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"مشکل احراز هویت"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"گذرواژه را بررسی و دوباره امتحان کنید"</string> <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"پیکربندی IP انجام نشد"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"غیرفعال شد"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"محدودشده"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"محدودنشده"</string> <string name="connected_via_app" msgid="1818040967936972127">"متصل شده ازطریق <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"در دسترس ازطریق <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"بهطور خودکار ازطریق <xliff:g id="NAME">%1$s</xliff:g> متصل شد"</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"اتصال خودکار ازطریق ارائهدهنده ردهبندی شبکه"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"اتصال خودکار ازطریق %1$s"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"اتصال خودکار ازطریق ارائهدهنده رتبهبندی شبکه"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"اتصال محدود"</string> <string name="private_dns_broken" msgid="2212227512243587416">"سرور DNS خصوصی قابل دسترسی نیست"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"عدم اتصال به اینترنت"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"کیفیت پایین"</string> <string name="wifi_security_none" msgid="6680263031386719053">"خالی"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"منقضیشده"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"برای ثبتنام ضربه بزنید"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"برای تمدید اشتراک و متصل شدن، ضربه بزنید"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"درحال بازکردن <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"متصل نشد"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"درحال تکمیل ثبتنام…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ثبتنام تکمیل نشد. برای امتحان مجدد ضربه بزنید."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ثبتنام کامل شد. درحال اتصال…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"این شبکه شناسه سیمکارتی را دریافت میکند که میتوان از آن برای ردیابی مکان دستگاه استفاده کرد. "<annotation id="url">"بیشتر بدانید"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"بسیار آهسته"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"آهسته"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"تأیید"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"متوسط"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"سریع"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"خیلی سریع"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-fi/strings.xml b/libs/WifiTrackerLib/res/values-fi/strings.xml index e8c7b7249..818e055f0 100644 --- a/libs/WifiTrackerLib/res/values-fi/strings.xml +++ b/libs/WifiTrackerLib/res/values-fi/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automaattinen yhdistäminen on pois päältä"</string> <string name="saved_network" msgid="6241977554502802914">"Tallentaja: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Yhteyttä ei muodosteta automaattisesti"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Yhteyttä ei muodosteta automaattisesti"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Ei internetyhteyttä"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Todennusvirhe"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Tarkista salasana ja yritä uudelleen."</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Maksullinen"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Maksuton"</string> <string name="connected_via_app" msgid="1818040967936972127">"Yhdistetty (<xliff:g id="NAME">%1$s</xliff:g>)"</string> - <string name="available_via_app" msgid="9110324040292242769">"Saatavilla tämän kautta: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automaattisesti yhdistetty tämän kautta: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automaattinen yhteys muodostettu palvelun %1$s kautta"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Yhdistetty automaattisesti verkon arviointipalvelun kautta"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Rajallinen yhteys"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Ei pääsyä yksityiselle DNS-palvelimelle"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ei internetyhteyttä"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Heikko laatu"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ei mitään"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Vanhentunut"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Rekisteröidy napauttamalla"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Kosketa, jos haluat uusia tilauksen ja muodostaa yhteyden"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Avataan <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Ei yhteyttä"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Viimeistellään rekisteröitymistä…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Rekisteröityminen ei onnistunut. Yritä uudelleen napauttamalla."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Rekisteröityminen valmis. Yhdistetään…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Tälle verkolle luodaan SIM-tunnus, jolla voidaan seurata laitteen sijaintia. "<annotation id="url">"Lue lisää"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Hyvin hidas"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Hidas"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Kohtuullinen"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Nopea"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Hyvin nopea"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml b/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml index abc03f440..bc6c33258 100644 --- a/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml +++ b/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"La connexion automatique est désactivée"</string> <string name="saved_network" msgid="6241977554502802914">"Enregistrés par <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Reconnexion automatique impossible"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Reconnexion automatique impossible"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Aucun accès à Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problème d\'authentification"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Vérifiez le mot de passe et réessayez"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Facturé à l\'usage"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Non mesuré"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connecté sur le réseau <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Accessible dans <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Connecté automatiquement par le réseau <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatiquement connecté par %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Connecté automatiquement par le fournisseur d\'avis sur le réseau"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Connexion limitée"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Impossible d\'accéder au serveur DNS privé"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Aucune connexion Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Faible qualité"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Aucune"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expiré"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Toucher pour vous inscrire"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Touchez pour renouveler l\'abonnement et vous connecter"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Ouverture de <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> en cours…"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Impossible de se connecter"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Finalisation de l\'inscription en cours…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Impossible de terminer l\'inscription. Touchez pour réessayer."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscription terminée. Connexion en cours…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ce réseau reçoit un identifiant SIM qui peut être utilisé pour faire le suivi de la position de l\'appareil. "<annotation id="url">"En savoir plus"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Très lente"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lente"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Moyenne"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Élevée"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Très rapide"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-fr/strings.xml b/libs/WifiTrackerLib/res/values-fr/strings.xml index 3a6e68e16..5bb6a05ac 100644 --- a/libs/WifiTrackerLib/res/values-fr/strings.xml +++ b/libs/WifiTrackerLib/res/values-fr/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Connexion automatique désactivée"</string> <string name="saved_network" msgid="6241977554502802914">"Enregistré lors de : <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Connexion automatique impossible"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Reconnexion automatique impossible"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Aucun accès à Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problème d\'authentification"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Vérifiez le mot de passe et réessayez"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Facturé à l\'usage"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Non facturé à l\'usage"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connecté via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponible via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Connecté automatiquement via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Connecté automatiquement via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Connecté automatiquement via un fournisseur d\'évaluation de l\'état du réseau"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Connexion limitée"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Impossible d\'accéder au serveur DNS privé"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Aucun accès à Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Faible qualité"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Aucune"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Arrivé à expiration"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Appuyez ici pour vous connecter"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Appuyez pour renouveler l\'abonnement et vous connecter"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Ouverture de <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>…"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Impossible de se connecter"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Finalisation de l\'inscription…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Impossible de finaliser l\'inscription. Appuyez ici pour réessayer."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscription terminée. Connexion…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ce réseau reçoit un ID de carte SIM qui peut être utilisé pour suivre la position de l\'appareil. "<annotation id="url">"En savoir plus"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Très lente"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lente"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Correcte"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Moyenne"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Élevée"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Très rapide"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-gl/strings.xml b/libs/WifiTrackerLib/res/values-gl/strings.xml index c0788f9bb..94f50d138 100644 --- a/libs/WifiTrackerLib/res/values-gl/strings.xml +++ b/libs/WifiTrackerLib/res/values-gl/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"A conexión automática está desactivada"</string> <string name="saved_network" msgid="6241977554502802914">"Gardada por <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"A rede non se conectará automaticamente"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Non se conectará automaticamente"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Sen acceso a Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Produciuse un problema de autenticación"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Comproba o contrasinal e téntao de novo"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Sen tarifa plana"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Con tarifa plana"</string> <string name="connected_via_app" msgid="1818040967936972127">"Wifi conectada a través de <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Dispoñible a través de <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Wifi conectada automaticamente a través de: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Conectada automaticamente a través dun provedor de valoración de redes"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Conectouse automaticamente a través de %1$s"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Conectada automaticamente a través dun provedor de valoración de rede"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Pouca conexión"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Non se puido acceder ao servidor DNS privado"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Non hai conexión a Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Pouca calidade"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ningunha"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Caducou"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Toca para rexistrarte"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Toca para renovar a subscrición e conectarte"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Abrindo <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Non se puido conectar"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completando rexistro…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Non se puido completar o rexistro. Toca para tentalo de novo."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Completouse o rexistro. Conectando…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Esta rede recibe un código SIM que se pode utilizar para realizar un seguimento da localización do dispositivo. "<annotation id="url">"Máis información"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Moi lenta"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Aceptar"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Media"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rápida"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Moi rápida"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-gu/strings.xml b/libs/WifiTrackerLib/res/values-gu/strings.xml index 91ab28936..e62877520 100644 --- a/libs/WifiTrackerLib/res/values-gu/strings.xml +++ b/libs/WifiTrackerLib/res/values-gu/strings.xml @@ -17,9 +17,10 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"ઑટો-કનેક્ટ બંધ છે"</string> + <!-- no translation found for auto_connect_disable (1078319396240632542) --> + <skip /> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા સચવાયું"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"ઑટોમૅટિક રીતે કનેક્ટ થશે નહીં"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"આપમેળે કનેક્ટ કરશે નહીં"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"કોઈ ઇન્ટરનેટ ઍક્સેસ નથી"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"પ્રમાણીકરણમાં સમસ્યા"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"પાસવર્ડ તપાસો અને ફરી પ્રયાસ કરો"</string> @@ -31,27 +32,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"મીટર કરેલ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"મીટર ન કરેલ"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કનેક્ટ થયેલ"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> મારફતે ઉપલબ્ધ"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> મારફતે ઑટોમૅટિક રીતે કનેક્ટ કર્યું છે"</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"નેટવર્ક રેટિંગ પ્રદાતા દ્વારા ઑટોમૅટિક રીતે કનેક્ટ થયું"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s દ્વારા સ્વત: કનેક્ટ થયેલ"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"નેટવર્ક રેટિંગ પ્રદાતા દ્વારા આપમેળે કનેક્ટ થયું"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"મર્યાદિત કનેક્શન"</string> <string name="private_dns_broken" msgid="2212227512243587416">"ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"કોઈ ઇન્ટરનેટ નથી"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ઓછી ક્વૉલિટી"</string> <string name="wifi_security_none" msgid="6680263031386719053">"કોઈ નહીં"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"સમય સમાપ્ત થયો"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"સાઇન અપ કરવા માટે ટૅપ કરો"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"સબ્સ્ક્રિપ્શનને રિન્યૂ કરવા માટે ટૅપ કરો અને કનેક્ટ કરો"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ખોલી રહ્યાં છીએ"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"કનેક્ટ કરી શક્યા નથી"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"સાઇન અપ પૂર્ણ કરી રહ્યા છીએ…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"સાઇન અપ પૂર્ણ કરી શકાયું નથી. ફરી પ્રયાસ કરવા માટે ટૅપ કરો."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"સાઇન અપ પૂર્ણ. કનેક્ટ કરી રહ્યાં છીએ…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"આ નેટવર્કને સિમ ID મળે છે જેનો ઉપયોગ ડિવાઇસનું સ્થાન ટ્રૅક કરવા માટે થઈ શકે છે. "<annotation id="url">"વધુ જાણો"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"ખૂબ જ ધીમી"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"ધીમી"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ઓકે"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"મધ્યમ"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"ઝડપી"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"ખૂબ ઝડપી"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-hi/arrays.xml b/libs/WifiTrackerLib/res/values-hi/arrays.xml index 4302269a8..b5f948d5c 100644 --- a/libs/WifiTrackerLib/res/values-hi/arrays.xml +++ b/libs/WifiTrackerLib/res/values-hi/arrays.xml @@ -26,7 +26,7 @@ <item msgid="6222852518007967736">"कनेक्ट हो रहा है…"</item> <item msgid="1176401854208153464">"पुष्टि की जा रही है…"</item> <item msgid="1377026397901197257">"आईपी पते की जानकारी ली जा रही है…"</item> - <item msgid="7627139816052121509">"कनेक्ट है"</item> + <item msgid="7627139816052121509">"कनेक्ट किया गया"</item> <item msgid="1598801023719359130">"निलंबित"</item> <item msgid="9160765456671002324">"डिसकनेक्ट किया जा रहा है…"</item> <item msgid="8013176736494493734">"डिसकनेक्ट किया गया"</item> diff --git a/libs/WifiTrackerLib/res/values-hi/strings.xml b/libs/WifiTrackerLib/res/values-hi/strings.xml index 8cb064976..48ded1a9f 100644 --- a/libs/WifiTrackerLib/res/values-hi/strings.xml +++ b/libs/WifiTrackerLib/res/values-hi/strings.xml @@ -17,9 +17,10 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"अपने-आप कनेक्ट होने की सुविधा बंद है"</string> + <!-- no translation found for auto_connect_disable (1078319396240632542) --> + <skip /> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> के द्वारा सहेजा गया"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"अपने-आप कनेक्ट नहीं होगा"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"अपने आप कनेक्ट नहीं होगा"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"इंटरनेट नहीं है"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"पुष्टि नहीं हो सकी"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"पासवर्ड जाँचें और दोबारा कोशिश करें"</string> @@ -31,27 +32,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"डेटा इस्तेमाल करने की सीमा तय की गई है"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"डेटा इस्तेमाल करने की सीमा तय नहीं की गई है"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> के ज़रिए कनेक्ट किया गया"</string> - <string name="available_via_app" msgid="9110324040292242769">"यह <xliff:g id="NAME">%1$s</xliff:g> के ज़रिए उपलब्ध है"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> के ज़रिए अपने-आप कनेक्ट किया गया"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s के ज़रिए ऑटोमैटिक रूप से कनेक्ट है"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"नेटवर्क रेटिंग कंपनी के ज़रिए अपने आप कनेक्ट है"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"सीमित कनेक्शन"</string> <string name="private_dns_broken" msgid="2212227512243587416">"निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"इंटरनेट कनेक्शन नहीं है"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"खराब कनेक्शन"</string> <string name="wifi_security_none" msgid="6680263031386719053">"कोई नहीं"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"समयसीमा खत्म हो गई"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"साइन अप करने के लिए टैप करें"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"सदस्यता रिन्यू करने के लिए टैप करें और कनेक्ट करें"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> खोला जा रहा है"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"कनेक्ट नहीं किया जा सका"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"साइन अप किया जा रहा है…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"साइन अप नहीं हो सका. फिर से कोशिश करने के लिए टैप करें."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"साइन अप की प्रक्रिया पूरी हो गई. कनेक्ट हो रहा है…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"इस नेटवर्क को एक सिम आईडी दिया जाता है जिसका इस्तेमाल डिवाइस की जगह की जानकारी का पता लगाने के लिए किया जा सकता है. "<annotation id="url">"ज़्यादा जानें"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"अत्यधिक धीमी"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"धीमी"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ठीक है"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"मध्यम"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"तेज़"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"बहुत ज़्यादा तेज़"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-hr/strings.xml b/libs/WifiTrackerLib/res/values-hr/strings.xml index 6d1b01004..3a0bca900 100644 --- a/libs/WifiTrackerLib/res/values-hr/strings.xml +++ b/libs/WifiTrackerLib/res/values-hr/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatsko povezivanje je isključeno"</string> <string name="saved_network" msgid="6241977554502802914">"Spremila aplik. <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Neće se povezati automatski"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Neće se povezati automatski"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nema pristupa internetu"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problem u autentifikaciji"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Provjerite zaporku i pokušajte ponovo"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"S ograničenim prometom"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Bez ograničenja prometa"</string> <string name="connected_via_app" msgid="1818040967936972127">"Povezan putem mreže <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Dostupno putem mreže <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatski povezano putem mreže <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatski povezan putem %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatski povezan putem ocjenjivača mreže"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ograničena veza"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Nije moguće pristupiti privatnom DNS poslužitelju"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nema interneta"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niska kvaliteta"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Nema"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Isteklo"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Dodirnite da biste se registrirali"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Dodirnite da biste obnovili pretplatu i povezali se"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Otvaranje usluge <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Povezivanje nije uspjelo"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Dovršavanje registracije…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registracija nije dovršena. Dodirnite za ponovni pokušaj."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registracija je dovršena. Povezivanje…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ova mreža prima jedinstveni ID SIM-a koji se može koristiti za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Vrlo sporo"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Sporo"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"U redu"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Srednje"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Brzo"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Vrlo brzo"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-hu/strings.xml b/libs/WifiTrackerLib/res/values-hu/strings.xml index f8fd55460..65bc3b0fd 100644 --- a/libs/WifiTrackerLib/res/values-hu/strings.xml +++ b/libs/WifiTrackerLib/res/values-hu/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"Automatikus csatlakozás kikapcsolva"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"Az automatikus csatlakozás ki van kapcsolva"</string> <string name="saved_network" msgid="6241977554502802914">"Mentette: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Nem csatlakozik automatikusan"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Nem csatlakozik automatikusan"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nincs internet-hozzáférés"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Hitelesítési probléma"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Ellenőrizze a jelszót, majd próbálkozzon újra"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Forgalomkorlátos"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Nem forgalomkorlátos"</string> <string name="connected_via_app" msgid="1818040967936972127">"Kapcsolódva a következőn keresztül: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Rendelkezésre áll a(z) <xliff:g id="NAME">%1$s</xliff:g> alkalmazáson keresztül"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatikusan csatlakozva a következőn keresztül: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatikusan csatlakozott a következőn keresztül: %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatikusan csatlakozott a hálózatértékelés szolgáltatóján keresztül"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Korlátozott kapcsolat"</string> <string name="private_dns_broken" msgid="2212227512243587416">"A privát DNS-kiszolgálóhoz nem lehet hozzáférni"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nincs internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Gyenge minőségű"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Nincs"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Lejárt"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Koppintson a regisztrációhoz"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Koppintson az előfizetés megújításához és a csatlakozáshoz"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> megnyitása"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Nem sikerült csatlakozni"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Regisztráció befejezése…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nem sikerült a regisztráció befejezése. Koppintással újrapróbálkozhat."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"A regisztráció befejeződött. Csatlakozás…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ez a hálózat SIM-azonosítót kap, amely felhasználható az eszköz helyadatainak követésére. "<annotation id="url">"További információ"</annotation>"."</string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Nagyon lassú"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lassú"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Rendben"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Közepes"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Gyors"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Nagyon gyors"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-hy/strings.xml b/libs/WifiTrackerLib/res/values-hy/strings.xml index c6125f9c9..802a53f04 100644 --- a/libs/WifiTrackerLib/res/values-hy/strings.xml +++ b/libs/WifiTrackerLib/res/values-hy/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Ավտոմատ միացումն անջատված է"</string> <string name="saved_network" msgid="6241977554502802914">"Ով է պահել՝ <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Չի միանա ավտոմատ"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Չի միանա ավտոմատ"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Ինտերնետ կապ չկա"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Նույնականացման խնդիր"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Ստուգեք գաղտնաբառը և նորից փորձեք"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Վճարովի թրաֆիկ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Անսահմանափակ թրաֆիկ"</string> <string name="connected_via_app" msgid="1818040967936972127">"Միացված է <xliff:g id="NAME">%1$s</xliff:g>-ի միջոցով"</string> - <string name="available_via_app" msgid="9110324040292242769">"Հասանելի է հետևյալ հավելվածի միջոցով՝ <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Ավտոմատ միացված է <xliff:g id="NAME">%1$s</xliff:g>-ի միջոցով"</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Ավտոմատ միացել է ցանցերի վարկանիշի մատակարարի միջոցով"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Ավտոմատ կերպով կապակցվել է %1$s-ի միջոցով"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Ավտոմատ կերպով միացել է ցանցի վարկանիշի ծառայության մատակարարի միջոցով"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Սահմանափակ կապ"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Մասնավոր DNS սերվերն անհասանելի է"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Կապ չկա"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ցածր որակ"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ոչ մեկը"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Սպառվել է"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Հպեք՝ գրանցվելու համար"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Հպեք՝ բաժանորդագրությունը նորացնելու և միանալու համար"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>, բացվում է"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Չհաջողվեց միանալ"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Գրանցումն ավարտվում է…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Չհաջողվեց ավարտել գրանցումը։ Հպեք՝ նորից փորձելու համար։"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Գրանցումն ավարտված է։ Միացում…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Այս ցանցը ստանում է եզակի ID, որի օգնությամբ հնարավոր է հետագծել սարքի տեղադրությունը։ "<annotation id="url">"Իմանալ ավելին"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Շատ դանդաղ"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Դանդաղ"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Լավ"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Միջին"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Արագ"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Շատ արագ"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-in/strings.xml b/libs/WifiTrackerLib/res/values-in/strings.xml index f1b067aaa..11f0e4cdd 100644 --- a/libs/WifiTrackerLib/res/values-in/strings.xml +++ b/libs/WifiTrackerLib/res/values-in/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Sambung-otomatis nonaktif"</string> <string name="saved_network" msgid="6241977554502802914">"Disimpan oleh <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Tidak akan terhubung otomatis"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Tidak akan tersambung otomatis"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Tidak ada akses internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Masalah autentikasi"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Periksa sandi dan coba lagi"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Berbayar"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Tidak berbayar"</string> <string name="connected_via_app" msgid="1818040967936972127">"Tersambung melalui <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Tersedia melalui <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Terhubung otomatis melalui <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Tersambung otomatis melalui %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Otomatis tersambung melalui penyedia rating jaringan"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Koneksi terbatas"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Server DNS pribadi tidak dapat diakses"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Tidak ada internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kualitas rendah"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Tidak ada"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Sudah tidak berlaku"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Ketuk untuk mendaftar"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Ketuk untuk memperpanjang langganan dan menyambungkan"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Membuka <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Tidak dapat terhubung"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Menyelesaikan pendaftaran…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Tidak dapat menyelesaikan pendaftaran. Ketuk untuk mencoba lagi."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Pendaftaran selesai. Menyambungkan…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Jaringan ini menerima ID SIM yang dapat digunakan untuk melacak lokasi perangkat. "<annotation id="url">"Pelajari lebih lanjut"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Sangat Lambat"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lambat"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Oke"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Sedang"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Cepat"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Sangat Cepat"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-is/strings.xml b/libs/WifiTrackerLib/res/values-is/strings.xml index 5e7dbdfb7..9f9d82028 100644 --- a/libs/WifiTrackerLib/res/values-is/strings.xml +++ b/libs/WifiTrackerLib/res/values-is/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Slökkt er á sjálfvirkri tengingu"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> vistaði"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Mun ekki tengjast sjálfkrafa"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Mun ekki tengjast sjálfkrafa"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Enginn netaðgangur"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Vandamál við auðkenningu"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Athugaðu aðgangsorðið og reyndu aftur"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Mæld notkun"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Notkun ekki mæld"</string> <string name="connected_via_app" msgid="1818040967936972127">"Tenging í gegnum <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Í boði með <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Tengt sjálfkrafa með <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Sjálfkrafa tengt um %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Sjálfkrafa tengt um netgæðaveitu"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Takmörkuð tenging"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Ekki næst í DNS-einkaþjón"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Engin nettenging"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lítil gæði"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ekkert"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Útrunnin"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Ýttu til að skrá þig"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Ýttu til að endurnýja áskrift og tengjast"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Opnar <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Ekki tókst að tengjast"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Gengur frá skráningu…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Ekki tókst að ljúka við skráningu. Ýttu til að reyna aftur."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Skráningu lokið. Tengist…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Þetta net fær SIM-auðkenni sem hægt er að nota til að rekja staðsetningu tækisins. "<annotation id="url">"Frekari upplýsingar"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Mjög hægt"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Hægt"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Í lagi"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Miðlungshratt"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Hratt"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Mjög hratt"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Útrunninn"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-it/strings.xml b/libs/WifiTrackerLib/res/values-it/strings.xml index 3b9c1e120..5b854ec8d 100644 --- a/libs/WifiTrackerLib/res/values-it/strings.xml +++ b/libs/WifiTrackerLib/res/values-it/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Connessione automatica disattivata"</string> <string name="saved_network" msgid="6241977554502802914">"Salvata da <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Non verrà eseguita la connessione automatica"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Non verrà eseguita la connessione automatica"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nessun accesso a Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problema di autenticazione"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Controlla la password e riprova"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"A consumo"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Non a consumo"</string> <string name="connected_via_app" msgid="1818040967936972127">"Connesso tramite <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponibile tramite <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Connessa automaticamente tramite <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Collegato automaticamente tramite %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Collegato automaticamente tramite fornitore di servizi di valutazione rete"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Connessione limitata"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Non è possibile accedere al server DNS privato"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Internet assente"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Bassa qualità"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Nessuna"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Scaduta"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tocca per registrarti"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tocca per rinnovare l\'abbonamento e connetterti"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Apertura di <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Impossibile connettersi"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completamento della registrazione…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Impossibile completare la registrazione. Tocca per riprovare."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrazione completata. Connessione…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Questa rete riceve un ID SIM che può essere usato per monitorare la posizione del dispositivo. "<annotation id="url">"Ulteriori informazioni"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Molto lenta"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Media"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Veloce"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Molto veloce"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Scaduto"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-iw/strings.xml b/libs/WifiTrackerLib/res/values-iw/strings.xml index 9be702339..f96819b89 100644 --- a/libs/WifiTrackerLib/res/values-iw/strings.xml +++ b/libs/WifiTrackerLib/res/values-iw/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"החיבור האוטומטי כבוי"</string> <string name="saved_network" msgid="6241977554502802914">"נשמר על ידי <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"לא יתבצע חיבור באופן אוטומטי"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"לא יתבצע חיבור באופן אוטומטי"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"אין גישה לאינטרנט"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"בעיית אימות"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"בדוק את הסיסמה ונסה שוב"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"נמדדת"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"לא נמדדת"</string> <string name="connected_via_app" msgid="1818040967936972127">"מחוברת באמצעות <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"זמינה דרך <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"מחוברת אוטומטית באמצעות <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"מחובר אוטומטית דרך %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"מחובר אוטומטית דרך ספק של דירוג רשת"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"חיבור מוגבל"</string> <string name="private_dns_broken" msgid="2212227512243587416">"לא ניתן לגשת לשרת DNS הפרטי"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"אין אינטרנט"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"איכות נמוכה"</string> <string name="wifi_security_none" msgid="6680263031386719053">"ללא"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"התוקף פג"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"יש להקיש כדי להירשם"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"יש להקיש כדי לחדש את המינוי ולהתחבר"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"מתבצעת פתיחה של <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"לא ניתן להתחבר"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"מתבצעת השלמה של ההרשמה…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"לא ניתן היה להשלים את ההרשמה. יש להקיש כדי לנסות שוב."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"תהליך ההרשמה הסתיים. בתהליך התחברות…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"הרשת הזו מקבלת מזהה SIM שיכול לשמש למעקב אחר מיקום המכשיר. "<annotation id="url">"מידע נוסף"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"איטית מאוד"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"איטית"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"אישור"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"בינונית"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"מהירה"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"מהירה מאוד"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ja/strings.xml b/libs/WifiTrackerLib/res/values-ja/strings.xml index b6fc09e33..0d9b2cde4 100644 --- a/libs/WifiTrackerLib/res/values-ja/strings.xml +++ b/libs/WifiTrackerLib/res/values-ja/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"自動接続が OFF です"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"自動接続がオフです"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g>で保存"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"自動的に接続されません"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"自動的に接続されません"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"インターネット接続なし"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"認証エラー"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"パスワードを確認して、もう一度お試しください"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"従量制"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"定額制"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> で接続しました"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g>で利用可能"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> で自動的に接続しました"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s 経由で自動的に接続しています"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"ネットワーク評価プロバイダ経由で自動的に接続しています"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"接続が制限されています"</string> <string name="private_dns_broken" msgid="2212227512243587416">"プライベート DNS サーバーにアクセスできません"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"インターネットに接続されていません"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"低品質"</string> <string name="wifi_security_none" msgid="6680263031386719053">"なし"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"期限切れ"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"タップして登録してください"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"タップして定期購入を更新し、接続してください"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> を開いています"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"接続できませんでした"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"登録を完了しています…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"登録を完了できませんでした。タップしてもう一度お試しください。"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"登録が完了しました。接続しています…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"このネットワークは SIM ID を受信します。この ID を使ってデバイスの位置情報が追跡される可能性があります。"<annotation id="url">"詳細"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"とても遅い"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"遅い"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"普通"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"速い"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"非常に速い"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ka/strings.xml b/libs/WifiTrackerLib/res/values-ka/strings.xml index 1c72c3c65..040145f2c 100644 --- a/libs/WifiTrackerLib/res/values-ka/strings.xml +++ b/libs/WifiTrackerLib/res/values-ka/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"ავტოდაკავშირება გამორთულია"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"ავტომატური დაკავშირება გამორთულია"</string> <string name="saved_network" msgid="6241977554502802914">"შენახული <xliff:g id="NAME">%1$s</xliff:g>-ის მიერ"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"ავტომატურად დაკავშირება ვერ ხერხდება"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"ავტომატურად დაკავშირება ვერ მოხერხდება"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ინტერნეტ-კავშირი არ არის"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ავთენტიკაციის პრობლემა"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"გადაამოწმეთ პაროლი და ხელახლა ცადეთ"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"ლიმიტირებული"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"არალიმიტირებული"</string> <string name="connected_via_app" msgid="1818040967936972127">"დაკავშირებულია <xliff:g id="NAME">%1$s</xliff:g>-ით"</string> - <string name="available_via_app" msgid="9110324040292242769">"ხელმისაწვდომია <xliff:g id="NAME">%1$s</xliff:g>-ის მეშვეობით"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"ავტომატურად დაკავშირებულია <xliff:g id="NAME">%1$s</xliff:g>-ით"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"ავტომატურად დაკავშირდა %1$s-ის მეშვეობით"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"ავტომატურად დაკავშირდა ქსელის ხარისხის შეფასების პროვაიდერის მეშვეობით"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"შეზღუდული კავშირი"</string> <string name="private_dns_broken" msgid="2212227512243587416">"პირად DNS სერვერზე წვდომა შეუძლებელია"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ინტერნეტ-კავშირი არ არის"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"დაბალი ხარისხი"</string> <string name="wifi_security_none" msgid="6680263031386719053">"არცერთი"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ვადაგასულია"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"შეეხეთ რეგისტრაციისთვის"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"შეეხეთ, რათა გაანაახლოთ გამოწერა და დაუკავშირდეთ"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"მიმდინარეობს <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>-ის გახსნა"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"დაკავშირება ვერ მოხერხდა"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"მიმდინარეობს რეგისტრაციის დასრულება…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"რეგისტრაციის დასრულება ვერ მოხერხდა. შეეხეთ ხელახლა საცდელად."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"რეგისტრაცია დასრულდა. მიმდინარეობს დაკავშირება…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"ეს ქსელი მიიღებს SIM-ის ID-ს, რომლის მეშვეობითაც შესაძლებელია მოწყობილობის მდებარეობაზე თვალის დევნება. "<annotation id="url">"შეიტყვეთ მეტი"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"ძალიან ნელი"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"ნელი"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"კარგი"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"საშუალო"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"სწრაფი"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"ძალიან სწრაფი"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-kk/strings.xml b/libs/WifiTrackerLib/res/values-kk/strings.xml index ef5c850bf..c0e5aa91e 100644 --- a/libs/WifiTrackerLib/res/values-kk/strings.xml +++ b/libs/WifiTrackerLib/res/values-kk/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"Автоматты жалғау өшірулі"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"Автоматты жалғау өшірулі."</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> сақтаған"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Автоматты байланыстырылмайды."</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Автоматты қосылмайды"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Интернетпен байланыс жоқ"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Аутентификация қатесі"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Құпия сөзді тексеріп, әрекетті қайталаңыз"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Трафик саналады"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Трафик саналмайды"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> арқылы жалғанған"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> арқылы қолжетімді"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> арқылы автоматты байланыстырылды."</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Желіні бағалау провайдері арқылы автоматты түрде қосылған"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s арқылы автоматты қосылды"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Желі рейтингі провайдері арқылы автоматты түрде қосылған"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Шектеулі байланыс"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Жеке DNS серверіне кіру мүмкін емес."</string> - <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Интернетпен байланыс жоқ"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Төмен сапа"</string> + <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Интернетпен байланыс жоқ."</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ешқандай"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Мерзімі өтті"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Тіркелу үшін түртіңіз."</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Жазылымды қайта жаңартып, қосылу үшін түртіңіз."</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ашылуда."</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Байланыстырылмады."</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Тіркелу аяқталуда…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Тіркелу аяқталмады. Әрекетті қайталау үшін түртіңіз."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Тіркелу аяқталды. Байланыс орнатылуда…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Бұл желіге SIM идентификаторы беріледі, оның көмегімен құрылғының орналасқан жері қадағаланады. "<annotation id="url">"Толығырақ"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Өте баяу"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Баяу"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Жарайды"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Орташа"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Жылдам"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Өте жылдам"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Мерзімі өтті."</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-km/strings.xml b/libs/WifiTrackerLib/res/values-km/strings.xml index ca88fa58b..d8bdff7a4 100644 --- a/libs/WifiTrackerLib/res/values-km/strings.xml +++ b/libs/WifiTrackerLib/res/values-km/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ការភ្ជាប់ដោយស្វ័យប្រវត្តិត្រូវបានបិទ"</string> <string name="saved_network" msgid="6241977554502802914">"បានរក្សាទុកដោយ <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"នឹងមិនភ្ជាប់ដោយស្វ័យប្រវត្តិទេ"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"នឹងមិនភ្ជាប់ដោយស្វ័យប្រវត្តិទេ"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"មិនមានការតភ្ជាប់អ៊ីនធឺណិតទេ"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"បញ្ហាក្នុងការផ្ទៀងផ្ទាត់"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"សូមពិនិត្យមើលពាក្យសម្ងាត់ រួចព្យាយាមម្ដងទៀត"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"មានការកំណត់"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"មិនមានការកំណត់"</string> <string name="connected_via_app" msgid="1818040967936972127">"ភ្ជាប់តាម <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"អាចប្រើបានតាមរយៈ <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"បានភ្ជាប់ដោយស្វ័យប្រវត្តិតាមរយៈ <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"បានភ្ជាប់ដោយស្វ័យប្រវត្តិតាមរយៈ %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"បានភ្ជាប់ដោយស្វ័យប្រវត្តិតាមរយៈក្រុមហ៊ុនផ្តល់ការវាយតម្លៃលើបណ្តាញ"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"ការតភ្ជាប់មានកម្រិត"</string> <string name="private_dns_broken" msgid="2212227512243587416">"មិនអាចចូលប្រើម៉ាស៊ីនមេ DNS ឯកជនបានទេ"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"គ្មានអ៊ីនធឺណិតទេ"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"គុណភាពទាប"</string> <string name="wifi_security_none" msgid="6680263031386719053">"គ្មាន"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"បានផុតកំណត់"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"ចុចដើម្បីចុះឈ្មោះ"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"ចុច ដើម្បីបន្តការជាវជាថ្មី និងភ្ជាប់"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"កំពុងបើក <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"មិនអាចភ្ជាប់បានទេ"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"កំពុងបញ្ចប់ការចុះឈ្មោះ…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"មិនអាចបញ្ចប់ការចុះឈ្មោះបានទេ។ សូមចុច ដើម្បីព្យាយាមម្ដងទៀត។"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ការចុះឈ្មោះបានបញ្ចប់។ កំពុងភ្ជាប់…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"បណ្ដាញនេះទទួលបានលេខសម្គាល់ស៊ីម ដែលអាចប្រើដើម្បីតាមដានទីតាំងឧបករណ៍។ "<annotation id="url">"ស្វែងយល់បន្ថែម"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"យឺតណាស់"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"យឺត"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"យល់ព្រម"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"មធ្យម"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"លឿន"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"លឿនខ្លាំង"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ផុតកំណត់"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-kn/strings.xml b/libs/WifiTrackerLib/res/values-kn/strings.xml index 1340a6677..743fb8b2b 100644 --- a/libs/WifiTrackerLib/res/values-kn/strings.xml +++ b/libs/WifiTrackerLib/res/values-kn/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ಸ್ವಯಂ ಕನೆಕ್ಟ್ ಆಫ್ ಆಗಿದೆ"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> ನಿಂದ ಉಳಿಸಲಾಗಿದೆ"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವಿಲ್ಲ"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ಪ್ರಮಾಣೀಕರಣ ಸಮಸ್ಯೆ"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"ಪಾಸ್ವರ್ಡ್ ಪರಿಶೀಲಿಸಿ ಮತ್ತು ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"ಮೀಟರ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"ಮೀಟರ್ ಮಾಡಲಾಗಿಲ್ಲ"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> ಆ್ಯಪ್ ಮೂಲಕ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> ಮೂಲಕ ಲಭ್ಯವಿದೆ"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"ನೆಟ್ವರ್ಕ್ ರೇಟಿಂಗ್ ಒದಗಿಸುವವರ ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"ಸೀಮಿತ ಸಂಪರ್ಕ"</string> <string name="private_dns_broken" msgid="2212227512243587416">"ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ಕಳಪೆ ಕನೆಕ್ಷನ್"</string> <string name="wifi_security_none" msgid="6680263031386719053">"ಯಾವುದೂ ಇಲ್ಲ"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ಅವಧಿ ಮುಕ್ತಾಯವಾಗಿದೆ"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"ಸೈನ್ ಅಪ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"ಸಬ್ಸ್ಕ್ರಿಪ್ಶನ್ ನವೀಕರಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಸಂಪರ್ಕಿಸಿ"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಲಾಗುತ್ತಿದೆ"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"ಸೈನ್-ಅಪ್ ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ಸೈನ್-ಅಪ್ ಪೂರ್ಣಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ಮತ್ತೊಮ್ಮೆ ಪ್ರಯತ್ನಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ಸೈನ್-ಅಪ್ ಪೂರ್ಣಗೊಂಡಿದೆ. ಕನೆಕ್ಟ್ ಆಗುತ್ತಿದೆ…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಬಳಸಬಹುದಾದ ಅನನ್ಯ ಐಡಿಯನ್ನು ಈ ನೆಟ್ವರ್ಕ್ ಸ್ವೀಕರಿಸುತ್ತದೆ. "<annotation id="url">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"ತುಂಬಾ ನಿಧಾನವಾಗಿದೆ"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"ನಿಧಾನ"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ಸರಿ"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"ಮಧ್ಯಮ"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"ವೇಗ"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"ತುಂಬಾ ವೇಗವಾಗಿದೆ"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ko/strings.xml b/libs/WifiTrackerLib/res/values-ko/strings.xml index ee9d54c67..c6c9b8ea7 100644 --- a/libs/WifiTrackerLib/res/values-ko/strings.xml +++ b/libs/WifiTrackerLib/res/values-ko/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"자동 연결 꺼짐"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g>(으)로 저장됨"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"자동으로 연결되지 않음"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"자동으로 연결되지 않습니다."</string> <string name="wifi_no_internet" msgid="4461212237521310895">"인터넷에 연결되어 있지 않음"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"인증 문제"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"비밀번호를 확인하고 다시 시도하세요."</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"종량제 네트워크"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"무제한 네트워크"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g>을(를) 통해 연결됨"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g>을(를) 통해 사용 가능"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g>을(를) 통해 자동으로 연결됨"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s을(를) 통해 자동으로 연결됨"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"네트워크 평가 제공업체를 통해 자동으로 연결됨"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"제한된 연결"</string> <string name="private_dns_broken" msgid="2212227512243587416">"비공개 DNS 서버에 액세스할 수 없습니다."</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"인터넷 연결 없음"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"품질 낮음"</string> <string name="wifi_security_none" msgid="6680263031386719053">"없음"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"만료됨"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"가입하려면 탭하세요."</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"가입을 갱신하고 연결하려면 탭하세요."</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> 여는 중"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"연결할 수 없습니다."</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"가입 완료 중…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"가입을 완료할 수 없습니다. 다시 시도하려면 탭하세요."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"가입이 완료되었습니다. 연결 중…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"이 네트워크는 기기 위치 추적에 사용될 수 있는 SIM ID를 수신합니다. "<annotation id="url">"자세히 알아보기"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"매우 느림"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"느림"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"보통"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"보통"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"빠름"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"매우 빠름"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ky/arrays.xml b/libs/WifiTrackerLib/res/values-ky/arrays.xml index 00ab8f678..8bcf77784 100644 --- a/libs/WifiTrackerLib/res/values-ky/arrays.xml +++ b/libs/WifiTrackerLib/res/values-ky/arrays.xml @@ -26,7 +26,7 @@ <item msgid="6222852518007967736">"Туташууда…"</item> <item msgid="1176401854208153464">"Аныктыгы текшерилүүдө…"</item> <item msgid="1377026397901197257">"IP дареги алынууда…"</item> - <item msgid="7627139816052121509">"Туташып турат"</item> + <item msgid="7627139816052121509">"Туташты"</item> <item msgid="1598801023719359130">"Убактылуу токтотулду"</item> <item msgid="9160765456671002324">"Ажыратылууда…"</item> <item msgid="8013176736494493734">"Ажыратылды"</item> diff --git a/libs/WifiTrackerLib/res/values-ky/strings.xml b/libs/WifiTrackerLib/res/values-ky/strings.xml index f38ae79fe..676f10bdf 100644 --- a/libs/WifiTrackerLib/res/values-ky/strings.xml +++ b/libs/WifiTrackerLib/res/values-ky/strings.xml @@ -17,9 +17,10 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"Автоматтык түрдө туташуу өчүк"</string> + <!-- no translation found for auto_connect_disable (1078319396240632542) --> + <skip /> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> тарабынан сакталды"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Автоматтык түрдө туташпайт"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Автоматтык түрдө туташпайт"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Интернетке туташпай турат"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Аутентификация маселеси бар"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Сырсөздү текшерип, кайталап көрүңүз."</string> @@ -31,27 +32,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Трафик ченелет"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Чектелбеген тармак"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> аркылуу туташты"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> аркылуу жеткиликтүү"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> аркылуу автоматтык түрдө туташты"</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Тармактар рейтингинин булагы аркылуу автоматтык түрдө туташты"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s аркылуу автоматтык түрдө туташты"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Тармактар рейтингинин автору аркылуу автоматтык түрдө туташты"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Байланыш чектелген"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Жеке DNS сервери жеткиликсиз"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Интернет жок"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Начар сапат"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Жок"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Эскирип калган"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Катталуу үчүн таптап коюңуз"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Жазылууну жаңыртып, туташуу үчүн таптап коюңуз"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ачылууда"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Туташпай койду"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Катталуу аяктоодо…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Катталуу аягына чыккан жок. Кайра аракет кылуу үчүн таптап коюңуз."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Катталуу аягына чыкты. Туташууда…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Бул тармакка SIM-картанын идентификатору берилет жана аны түзмөктүн жайгашкан жерин көзөмөлдөп туруу үчүн колдонууга болот. "<annotation id="url">"Кеңири маалымат"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Өтө жай"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Жай"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Жарайт"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Орто"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Ылдам"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Абдан ылдам"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Мөөнөтү бүткөн"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-lo/strings.xml b/libs/WifiTrackerLib/res/values-lo/strings.xml index c1f28f21c..caebd45d9 100644 --- a/libs/WifiTrackerLib/res/values-lo/strings.xml +++ b/libs/WifiTrackerLib/res/values-lo/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ການເຊື່ອມຕໍ່ອັດຕະໂນມັດປິດຢູ່"</string> <string name="saved_network" msgid="6241977554502802914">"ບັນທຶກໂດຍ <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"ຈະບໍ່ເຊື່ອມຕໍ່ອັດຕະໂນມັດ"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"ຈະບໍ່ເຊື່ອມຕໍ່ອັດຕະໂນມັດ"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ເກີດບັນຫາການພິສູດຢືນຢັນ"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"ກະລຸນາກວດສອບລະຫັດຜ່ານແລ້ວລອງໃໝ່ອີກຄັ້ງ"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"ມີການວັດແທກ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"ບໍ່ໄດ້ວັດແທກ"</string> <string name="connected_via_app" msgid="1818040967936972127">"ເຊື່ອມຕໍ່ຜ່ານ <xliff:g id="NAME">%1$s</xliff:g> ແລ້ວ"</string> - <string name="available_via_app" msgid="9110324040292242769">"ສາມາດໃຊ້ໄດ້ຜ່ານ <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"ເຊື່ອມຕໍ່ອັດຕະໂນມັດຜ່ານ <xliff:g id="NAME">%1$s</xliff:g> ແລ້ວ"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"ເຊື່ອມຕໍ່ຜ່ານທາງ %1$s ໂດຍອັດຕະໂນມັດ"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"ເຊື່ອມຕໍ່ກັບອັດຕະໂນມັດແລ້ວຜ່ານຜູ້ໃຫ້ບໍລິການຄະແນນເຄືອຂ່າຍ"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"ການເຊື່ອມຕໍ່ຈຳກັດ"</string> <string name="private_dns_broken" msgid="2212227512243587416">"ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ບໍ່ມີອິນເຕີເນັດ"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ຄຸນນະພາບຕໍ່າ"</string> <string name="wifi_security_none" msgid="6680263031386719053">"ບໍ່ໃຊ້"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ໝົດອາຍຸແລ້ວ"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"ແຕະເພື່ອສະໝັກ"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"ແຕະເພື່ອຕໍ່ອາຍຸການສະໝັກໃຊ້ ແລະ ເຊື່ອມຕ"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"ກຳລັງເປີດ <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"ກຳລັງສຳເລັດການສະໝັກ…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ບໍ່ສາມາດສຳເລັດການສະໝັກໄດ້. ແຕະເພື່ອລອງໃໝ່."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ສະໝັກສຳເລັດແລ້ວ. ກຳລັງເຊື່ອມຕໍ່…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"ເຄືອຂ່າຍນີ້ຈະຮັບ ID ຊິມທີ່ສາມາດໃຊ້ເພື່ອຕິດຕາມສະຖານທີ່ອຸປະກອນ "<annotation id="url">"ສຶກສາເພີ່ມເຕີມ"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"ຊ້າຫຼາຍ"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"ຊ້າ"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ຕົກລົງ"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"ປານກາງ"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"ໄວ"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"ໄວຫຼາຍ"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-lt/strings.xml b/libs/WifiTrackerLib/res/values-lt/strings.xml index 40d3f1e4d..45237d37a 100644 --- a/libs/WifiTrackerLib/res/values-lt/strings.xml +++ b/libs/WifiTrackerLib/res/values-lt/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatinio prisijungimo funkcija išjungta"</string> <string name="saved_network" msgid="6241977554502802914">"Išsaugojo <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Nebus automatiškai prisijungiama"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Nebus automatiškai prisijungiama"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nėra interneto ryšio"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Autentifikavimo problema"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Patikrinkite slaptažodį ir bandykite dar kartą"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Matuojamas"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Neišmatuotas"</string> <string name="connected_via_app" msgid="1818040967936972127">"Prisijungta naudojant programą „<xliff:g id="NAME">%1$s</xliff:g>“"</string> - <string name="available_via_app" msgid="9110324040292242769">"Pasiekiama naudojant „<xliff:g id="NAME">%1$s</xliff:g>“"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatiškai prisijungta per „<xliff:g id="NAME">%1$s</xliff:g>“"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatiškai prisijungta naudojant „%1$s“"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatiškai prisijungta naudojant tinklo įvertinimo paslaugos teikėjo paslaugomis"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ribotas ryšys"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Privataus DNS serverio negalima pasiekti"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nėra interneto ryšio"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Prastas ryšys"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Nėra"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Baigėsi galiojimo laikas"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Palieskite, kad prisiregistruotumėte"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Palieskite, kad atnaujintumėte prenumeratą ir prisijungtumėte"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Atidaroma: „<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>“"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Nepavyko prisijungti"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Baigiamas prisiregistravimas…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nepavyko užbaigti prisiregistravimo. Jei norite bandyti dar kartą, palieskite."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Prisiregistravimas baigtas. Prijungiama…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Šis tinklas gauna SIM kortelės ID, kurį galima naudoti įrenginio vietovei stebėti. "<annotation id="url">"Sužinokite daugiau"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Labai lėtas"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lėtas"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Gerai"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Vidutinis"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Greitas"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Labai greitas"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-lv/strings.xml b/libs/WifiTrackerLib/res/values-lv/strings.xml index 1450cfcd0..e55b0261d 100644 --- a/libs/WifiTrackerLib/res/values-lv/strings.xml +++ b/libs/WifiTrackerLib/res/values-lv/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Savienojuma automātiskā izveide ir izslēgta."</string> <string name="saved_network" msgid="6241977554502802914">"Saglabāja: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Savienojums netiks izveidots automātiski"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Savienojums netiks izveidots automātiski"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nav piekļuves internetam"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Autentificēšanas problēma"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Pārbaudiet paroli un mēģiniet vēlreiz."</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Maksas"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Bezmaksas"</string> <string name="connected_via_app" msgid="1818040967936972127">"Savienojums ar <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Pieejams, izmantojot <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automātiski izveidots savienojums, izmantojot <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automātiski savienots, izmantojot %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automātiski izveidots savienojums, izmantojot tīkla vērtējuma sniedzēju"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ierobežots savienojums"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Nevar piekļūt privātam DNS serverim."</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nav interneta"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Zema kvalitāte"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Nav"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Beidzies derīguma termiņš"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Pieskarieties, lai reģistrētos."</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Pieskarieties, lai atjaunotu abonementu un izveidotu savienojumu"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Notiek nodrošinātāja <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> atvēršana."</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Nevarēja izveidot savienojumu."</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Notiek reģistrācijas pabeigšana…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nevarēja pabeigt reģistrāciju. Pieskarieties, lai mēģinātu vēlreiz."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Reģistrācija ir pabeigta. Notiek savienojuma izveide…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Šis tīkls saņem SIM ID, ko var izmantot, lai izsekotu ierīces atrašanās vietai. "<annotation id="url">"Uzziniet vairāk"</annotation>"."</string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Ļoti lēns"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lēns"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Labi"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Vidējs"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Ātrs"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Ļoti ātrs"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-mk/strings.xml b/libs/WifiTrackerLib/res/values-mk/strings.xml index 93d47f910..e934ebba6 100644 --- a/libs/WifiTrackerLib/res/values-mk/strings.xml +++ b/libs/WifiTrackerLib/res/values-mk/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Автоматското поврзување е исклучено"</string> <string name="saved_network" msgid="6241977554502802914">"Зачувано од <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Не може да се поврзе автоматски"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Не може да се поврзе автоматски"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Нема пристап до интернет"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Проблем при проверката"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Проверете ја лозинката и обидете се повторно"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Со ограничен интернет"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Без ограничен интернет"</string> <string name="connected_via_app" msgid="1818040967936972127">"Поврзано преку <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Достапна преку <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Автоматски поврзано преку <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Автоматски поврзано преку оценувач на мрежа"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Автоматски поврзано преку %1$s"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Автоматски поврзано преку оператор за оценување мрежа"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ограничена врска"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Не може да се пристапи до приватниот DNS-сервер"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Нема интернет"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Лош квалитет"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ниедна"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Истечено"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Допрете за да се регистрирате"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Допрете за обновување на претплатата и поврзување"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Се отвора <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Не може да се поврзе"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Се завршува регистрацијата…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Не може да се заврши регистрацијата. Допрете за да се обидете повторно."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Регистрацијата е завршена. Се поврзува…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Мрежава прима ID на SIM-картичка што може да се користи за следење на локацијата на уредот. "<annotation id="url">"Дознајте повеќе"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Многу бавна"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Бавна"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Во ред"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Средна"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Брза"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Многу брза"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ml/strings.xml b/libs/WifiTrackerLib/res/values-ml/strings.xml index 2a69021ca..04c00f9eb 100644 --- a/libs/WifiTrackerLib/res/values-ml/strings.xml +++ b/libs/WifiTrackerLib/res/values-ml/strings.xml @@ -17,9 +17,10 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"ഓട്ടോ-കണക്റ്റ് ഓഫാണ്"</string> + <!-- no translation found for auto_connect_disable (1078319396240632542) --> + <skip /> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> സംരക്ഷിച്ചത്"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"സ്വയമേവ കണക്റ്റ് ചെയ്യില്ല"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"സ്വയമേവ കണക്റ്റുചെയ്യില്ല"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ഇന്റർനെറ്റ് ആക്സസ് ഇല്ല"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"പരിശോധിച്ചുറപ്പിക്കുന്നതിലെ പ്രശ്നം"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"പാസ്വേഡ് പരിശോധിച്ച് വീണ്ടും ശ്രമിക്കുക"</string> @@ -28,30 +29,14 @@ <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"ആക്സസ് പോയിന്റ് താൽക്കാലികമായി നിറഞ്ഞിരിക്കുന്നു"</string> <string name="wifi_disconnected" msgid="3720926757662831062">"വിച്ഛേദിച്ചു"</string> <string name="wifi_remembered" msgid="5126903736498678708">"സംരക്ഷിച്ചു"</string> - <string name="wifi_metered_label" msgid="1362621600006544014">"മീറ്റർ ചെയ്തത്"</string> + <string name="wifi_metered_label" msgid="1362621600006544014">"മീറ്റർചെയ്ത"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"മീറ്റർമാപകമല്ലാത്തത്"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> മുഖേന കണക്റ്റ് ചെയ്തു"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> വഴി ലഭ്യമാണ്"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> മുഖേന സ്വയമേവ കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s വഴി സ്വയമേവ ബന്ധിപ്പിച്ചു"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"നെറ്റ്വർക്ക് റേറ്റിംഗ് ദാതാവുമായി സ്വയം കണക്റ്റുചെയ്തു"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"പരിമിത കണക്ഷൻ"</string> <string name="private_dns_broken" msgid="2212227512243587416">"സ്വകാര്യ DNS സെർവർ ആക്സസ് ചെയ്യാനാവില്ല"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ഇന്റർനെറ്റ് ഇല്ല"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"കുറഞ്ഞ നിലവാരം"</string> <string name="wifi_security_none" msgid="6680263031386719053">"ഒന്നുമില്ല"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"കാലഹരണപ്പെട്ടത്"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"സൈൻ അപ്പ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"സബ്സ്ക്രിപ്ഷൻ പുതുക്കാൻ ടാപ്പ് ചെയ്ത് കണക്റ്റ് ചെയ്യുക"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> തുറക്കുന്നു"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"കണക്റ്റ് ചെയ്യാനായില്ല"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"സൈൻ അപ്പ് പൂർത്തിയാക്കുന്നു…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"സൈൻ അപ്പ് പൂർത്തിയാക്കാനായില്ല. വീണ്ടും ശ്രമിക്കാൻ ടാപ്പ് ചെയ്യുക."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"സൈൻ അപ്പ് പൂർത്തിയായി. കണക്റ്റ് ചെയ്യുന്നു…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"ഉപകരണ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ ഉപയോഗിക്കാവുന്ന സിം ഐഡി ഈ നെറ്റ്വർക്കിന് ലഭിക്കും. "<annotation id="url">"കൂടുതലറിയുക"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"വളരെ കുറഞ്ഞ വേഗത്തിൽ"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"കുറഞ്ഞ വേഗത്തിൽ"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ശരി"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"ഇടത്തരം"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"വേഗത്തിൽ"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"അതിവേഗം"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-mn/strings.xml b/libs/WifiTrackerLib/res/values-mn/strings.xml index 9e9b247e6..75de960d6 100644 --- a/libs/WifiTrackerLib/res/values-mn/strings.xml +++ b/libs/WifiTrackerLib/res/values-mn/strings.xml @@ -19,9 +19,9 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Автомат холболт унтраалттай байна"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> хадгалсан"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Автоматаар холбогдохгүй"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Автоматаар холбогдохгүй"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Интернэт хандалт байхгүй байна"</string> - <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Баталгаажуулалтын асуудал"</string> + <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Нотолгооны асуудал"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Нууц үгийг шалгаад дахин оролдоно уу"</string> <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP тохируулга амжилтгүй боллоо"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"Идэвхгүйжүүлсэн"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Хязгаартай"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Хязгааргүй"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g>-р холбогдсон"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g>-р боломжтой байна"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g>-р автоматаар холбогдсон"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s-р автоматаар холбогдсон"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Сүлжээний үнэлгээ үзүүлэгчээр автоматаар холбогдох"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Хязгаарлагдмал холболт"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Хувийн DNS серверт хандах боломжгүй байна"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Интернэт алга"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Чанар муу"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Байхгүй"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Хугацаа дууссан"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Бүртгүүлэхийн тулд товшино уу"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Захиалгыг шинэчилж, холбогдохын тулд товшино уу"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>-г нээж байна"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Холбогдож чадсангүй"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Бүртгэлийг дуусгаж байна…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Бүртгэлийг дуусгаж чадсангүй. Дахин оролдохын тулд товшино уу."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Бүртгэлийг дуусгалаа. Холбогдож байна…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Энэ сүлжээ нь төхөөрөмжийн байршлыг тандахад ашиглах боломжтой SIM ID-г хүлээн авдаг. "<annotation id="url">"Нэмэлт мэдээлэл авах"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Маш удаан"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Удаан"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ЗА"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Дунд"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Хурдан"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Маш хурдан"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-mr/strings.xml b/libs/WifiTrackerLib/res/values-mr/strings.xml index 963956f51..f19a6ced7 100644 --- a/libs/WifiTrackerLib/res/values-mr/strings.xml +++ b/libs/WifiTrackerLib/res/values-mr/strings.xml @@ -19,11 +19,11 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ऑटो-कनेक्ट बंद आहे"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> द्वारे सेव्ह केले"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"आपोआप कनेक्ट झाले नाही"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"स्वयंचलितपणे कनेक्ट करणार नाही"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"इंटरनेट अॅक्सेस नाही"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ऑथेंटिकेशन समस्या"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"पासवर्ड तपासा आणि पुन्हा प्रयत्न करा"</string> - <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP कॉंफिगरेशन अयशस्वी"</string> + <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP कॉन्फिगरेशन अयशस्वी"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"अक्षम"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"अॅक्सेस पॉइंट तात्पुरते भरलेले"</string> <string name="wifi_disconnected" msgid="3720926757662831062">"डिस्कनेक्ट केले"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"मीटरने मोजलेले"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"मीटरने न मोजलेले"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> द्वारे कनेक्ट केले"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> द्वारे उपलब्ध"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> वरून आपोआप कनेक्ट केले आहे"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s द्वारे स्वयंचलितपणे कनेक्ट केले"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"नेटवर्क रेटिंग प्रदात्याद्वारे स्वयंचलितपणे कनेक्ट केले"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"मर्यादित कनेक्शन"</string> <string name="private_dns_broken" msgid="2212227512243587416">"खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"इंटरनेट नाही"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"कमी गुणवत्ता"</string> <string name="wifi_security_none" msgid="6680263031386719053">"काहीही नाही"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"मुदत संपली"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"साइन अप करण्यासाठी टॅप करा"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"सदस्यत्व रिन्यू करण्यासाठी टॅप करा आणि कनेक्ट करा"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> उघडत आहे"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"कनेक्ट करता आले नाही"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"साइन-अप पूर्ण होत आहे…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"साइन-अप पूर्ण करता आले नाही. पुन्हा प्रयत्न करण्यासाठी टॅप करा."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"साइन-अप पूर्ण झाले आहे. कनेक्ट करत आहे…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"हे नेटवर्क डिव्हाइसच्या स्थानाचा माग ठेवण्यासाठी वापरता येणारा सिम आयडी मिळवते. "<annotation id="url">"अधिक जाणून घ्या"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"खूप हळू"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"हळू"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ठीक आहे"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"मध्यम"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"जलद"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"खूप जलद"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ms/strings.xml b/libs/WifiTrackerLib/res/values-ms/strings.xml index 8d06b4208..744f52605 100644 --- a/libs/WifiTrackerLib/res/values-ms/strings.xml +++ b/libs/WifiTrackerLib/res/values-ms/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Autosambung dimatikan"</string> <string name="saved_network" msgid="6241977554502802914">"Diselamatkan oleh <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Tidak akan menyambung secara automatik"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Tidak akan menyambung secara automatik"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Tiada akses Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Masalah pengesahan"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Semak kata laluan, kemudian cuba lagi"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Bermeter"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Tidak bermeter"</string> <string name="connected_via_app" msgid="1818040967936972127">"Disambungkan melalui <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Tersedia melalui <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Disambungkan secara automatik melalui <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Disambungkan secara automatik melalui %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Disambungkan secara automatik melalui pembekal penilaian rangkaian"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Sambungan terhad"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Pelayan DNS peribadi tidak boleh diakses"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Tiada Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kualiti rendah"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Tiada"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Tamat tempoh"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Ketik untuk daftar"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Ketik untuk membaharui langganan dan sambung"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Membuka <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Tidak dapat menyambung"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Menyelesaikan pendaftaran…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Tidak dapat menyelesaikan pendaftaran. Ketik untuk mencuba lagi."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Pendaftaran selesai. Menyambung…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Rangkaian ini menerima ID SIM yang boleh digunakan untuk menjejak lokasi peranti. "<annotation id="url">"Ketahui lebih lanjut"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Sangat Perlahan"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Perlahan"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Sederhana"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Laju"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Sangat Laju"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-my/strings.xml b/libs/WifiTrackerLib/res/values-my/strings.xml index 524fbb612..df19c1d41 100644 --- a/libs/WifiTrackerLib/res/values-my/strings.xml +++ b/libs/WifiTrackerLib/res/values-my/strings.xml @@ -19,9 +19,9 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"အလိုအလျောက်ချိတ်ဆက်မှုကို ပိတ်ထားသည်"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> က သိမ်းဆည်းခဲ့သည်"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"အလိုအလျောက် ချိတ်ဆက်မည်မဟုတ်ပါ"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"အလိုအလျောက်ချိတ်ဆက်မည်မဟုတ်ပါ"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"အင်တာနက် ချိတ်ဆက်မှု မရှိပါ"</string> - <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"အထောက်အထားစိစစ်မှု ပြဿနာ"</string> + <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"အထောက်အထားစိစစ်ခြင်း ပြဿနာ"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"စကားဝှက်ကို စစ်ဆေးပြီး ထပ်လုပ်ကြည့်ပါ"</string> <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP စီစဉ်သတ်မှတ်ခြင်း မအောင်မြင်ပါ"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"ပိတ်ထားသည်"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"အခမဲ့ မဟုတ်ပါ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"အခမဲ့"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> မှတစ်ဆင့် ချိတ်ဆက်ထားသည်"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g>မှတစ်ဆင့် ရနိုင်သည်"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> မှတစ်ဆင့် အလိုအလျောက် ချိတ်ဆက်ထားသည်"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s မှတစ်ဆင့် အလိုအလျောက် ချိတ်ဆက်ထားပါသည်"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"ကွန်ရက်အဆင့်သတ်မှတ်ပေးသူ မှတစ်ဆင့် အလိုအလျောက် ချိတ်ဆက်ထားပါသည်"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"ချိတ်ဆက်မှု ကန့်သတ်ထားသည်"</string> <string name="private_dns_broken" msgid="2212227512243587416">"သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"အင်တာနက် မရှိပါ"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"အရည်အသွေး နိမ့်သည်"</string> <string name="wifi_security_none" msgid="6680263031386719053">"မရှိ"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"သက်တမ်းကုန်သွားပါပြီ"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"အကောင့်ဖွင့်ရန် တို့ပါ"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"စာရင်းသွင်းမှာယူမှုကို သက်တမ်းတိုးပြီး ချိတ်ဆက်ရန် တို့ပါ"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ကို ဖွင့်နေသည်"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"ချိတ်ဆက်၍ မရပါ"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"အကောင့်ဖွင့်ခြင်း အပြီးသတ်နေသည်…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"အကောင့်ဖွင့်ခြင်း အပြီးသတ်၍ မရပါ။ ထပ်စမ်းကြည့်ရန် တို့ပါ။"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"အကောင့်ဖွင့်ပြီးပါပြီ။ ချိတ်ဆက်နေသည်…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"ဤကွန်ရက်က စက်တည်နေရာကို ခြေရာခံရန် အသုံးပြုနိုင်သည့် SIM ID တစ်ခုကို ရရှိပါသည်။ "<annotation id="url">"ပိုမိုလေ့လာရန်"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"အလွန်နှေး"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"နှေး"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"အတော်အသင့်"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"မြန်"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"အလွန်မြန်"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-nb/strings.xml b/libs/WifiTrackerLib/res/values-nb/strings.xml index 0a670a83f..f0494e671 100644 --- a/libs/WifiTrackerLib/res/values-nb/strings.xml +++ b/libs/WifiTrackerLib/res/values-nb/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatisk tilkobling er av"</string> <string name="saved_network" msgid="6241977554502802914">"Lagret av <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Kobler ikke til automatisk"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Kobler ikke til automatisk"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Ingen internettilgang"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Autentiseringsproblem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Sjekk passordet og prøv igjen"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Med datamåling"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Uten datamåling"</string> <string name="connected_via_app" msgid="1818040967936972127">"Tilkoblet via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Tilgjengelig via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatisk tilkoblet via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatisk tilkoblet via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatisk tilkoblet via leverandør av nettverksvurdering"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Begrenset tilkobling"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Den private DNS-tjeneren kan ikke nås"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ingen internettilkobling"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lav kvalitet"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ingen"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Utløpt"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Trykk for å registrere deg"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Trykk for å fornye abonnementet og koble til"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Åpner <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Kunne ikke koble til"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Fullfører registreringen …"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Kunne ikke fullføre registreringen. Trykk for å prøve på nytt."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registreringen er fullført. Kobler til …"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Dette nettverket mottar en SIM-ID som kan brukes til å spore enhetsposisjonen. "<annotation id="url">"Finn ut mer"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Veldig treg"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Treg"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Ok"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Middels"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rask"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Veldig rask"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ne/strings.xml b/libs/WifiTrackerLib/res/values-ne/strings.xml index cc330a577..17914b2de 100644 --- a/libs/WifiTrackerLib/res/values-ne/strings.xml +++ b/libs/WifiTrackerLib/res/values-ne/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"स्वतः कनेक्ट गर्ने सुविधा अफ छ"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"स्वतः जोडिने सुविधा निष्क्रिय छ"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> द्वारा सुरक्षित गरियो"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"स्वतः जोडिने छैन"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"स्वतः जडान हुने छैन"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"इन्टरनेटमाथिको पहुँच छैन"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"प्रमाणीकरणसम्बन्धी समस्या"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"पासवर्ड जाँच गरेर फेरि प्रयास गर्नुहोस्"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"सशुल्क वाइफाइ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"मिटर नगरिएको"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> मार्फत जडान गरिएको"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> मार्फत उपलब्ध"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> मार्फत स्वतः जोडियो"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s मार्फत् स्वतः जडान गरिएको"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"नेटवर्कको दर्जा प्रदायक मार्फत स्वत: जडान गरिएको"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"सीमित जडान"</string> <string name="private_dns_broken" msgid="2212227512243587416">"निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"इन्टरनेट छैन"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"न्यून गुणस्तर"</string> <string name="wifi_security_none" msgid="6680263031386719053">"कुनै पनि होइन"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"म्याद सकियो"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"साइन अप गर्न ट्याप गर्नुहोस्"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"ट्याप गरेर सदस्यता नवीकरण गर्नुहोस् र इन्टरनेटमा कनेक्ट गर्नुहोस्"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> खोल्दै"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"जोडिन सकिएन"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"साइन अप गर्ने कार्य सम्पन्न गर्दै…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"साइन अप गर्ने कार्य सम्पन्न गर्न सकिएन। फेरि प्रयास गर्न ट्याप गर्नुहोस्।"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"साइन अप गर्ने कार्य सम्पन्न भयो। जोड्दै…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"यो नेटवर्कलाई यन्त्रको स्थान पहिल्याउन प्रयोग गर्न मिल्ने एउटा अद्वितीय SIM कार्ड ID उपलब्ध गराइन्छ। "<annotation id="url">"थप जान्नुहोस्"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"धेरै ढिलो"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"बिस्तारै"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ठिक छ"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"मध्यम"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"छिटो"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"धेरै छिटो"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-nl/strings.xml b/libs/WifiTrackerLib/res/values-nl/strings.xml index f9081a5c7..766c4576e 100644 --- a/libs/WifiTrackerLib/res/values-nl/strings.xml +++ b/libs/WifiTrackerLib/res/values-nl/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"\'Automatisch verbinding maken\' staat uit"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"Automatisch verbinden is uitgeschakeld"</string> <string name="saved_network" msgid="6241977554502802914">"Opgeslagen door \'<xliff:g id="NAME">%1$s</xliff:g>\'"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Er wordt niet automatisch verbinding gemaakt"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Er wordt niet automatisch verbinding gemaakt"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Geen internettoegang"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Verificatieprobleem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Controleer het wachtwoord en probeer het opnieuw"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Met datalimiet"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Gratis"</string> <string name="connected_via_app" msgid="1818040967936972127">"Verbonden via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Beschikbaar via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatisch verbonden via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatisch verbonden via provider van netwerkbeoordelingen"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatisch verbonden via %1$s"</string> + <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatisch verbonden via netwerkbeoordelaar"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Beperkte verbinding"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Geen toegang tot privé-DNS-server"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Geen internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lage kwaliteit"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Geen"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Verlopen"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tik om aan te melden"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tik om het abonnement te verlengen en verbinding te maken"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> openen"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Kan geen verbinding maken"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Aanmelding voltooien…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Kan aanmelding niet voltooien. Tik om het opnieuw te proberen."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Aanmelding voltooid. Verbinden…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Dit netwerk ontvangt een simkaart-ID die kan worden gebruikt om de apparaatlocatie bij te houden. "<annotation id="url">"Meer informatie"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Zeer langzaam"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Langzaam"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Redelijk"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Gemiddeld"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Snel"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Zeer snel"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-or/strings.xml b/libs/WifiTrackerLib/res/values-or/strings.xml index 15b645990..defd6ff24 100644 --- a/libs/WifiTrackerLib/res/values-or/strings.xml +++ b/libs/WifiTrackerLib/res/values-or/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ସ୍ୱତଃ-ସଂଯୋଗ ବନ୍ଦ ଅଛି"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> ଦ୍ୱାରା ସେଭ କରାଯାଇଛି"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"ସ୍ୱଚାଳିତ ଭାବେ ସଂଯୋଗ ହେବ ନାହିଁ"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"ସ୍ୱଚାଳିତ ଭାବେ ସଂଯୁକ୍ତ ହେବନାହିଁ"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"କୌଣସି ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ପ୍ରମାଣିକତା ସମସ୍ୟା"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"ପାସ୍ୱର୍ଡ ଯାଞ୍ଚ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"ମପାଯାଉଥିବା"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"ମପାଯାଉନଥିବା"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> ଦ୍ବାରା ସଂଯୋଗ କରାଯାଇଛି"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> ମାଧ୍ୟମରେ ଉପଲବ୍ଧ ଅଛି"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> ମାଧ୍ୟମରେ ସ୍ୱଚାଳିତ ଭାବେ ସଂଯୋଗ କରାଯାଇଛି"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s ମାଧ୍ୟମରେ ଅଟୋମେଟିକାଲୀ ସଂଯୁକ୍ତ"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"ନେଟୱର୍କ ମୂଲ୍ୟାୟନ ପ୍ରଦାତାଙ୍କ ମାଧ୍ୟମରେ ଅଟୋମେଟିକାଲ୍ୟ ସଂଯୁକ୍ତ"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"ସୀମିତ ସଂଯୋଗ"</string> <string name="private_dns_broken" msgid="2212227512243587416">"ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ଇଣ୍ଟର୍ନେଟ୍ ସଂଯୋଗ ନାହିଁ"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ନିମ୍ନ ଗୁଣବତ୍ତା"</string> <string name="wifi_security_none" msgid="6680263031386719053">"କିଛି ନାହିଁ"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ମିଆଦ ଶେଷ ହୋଇଯାଇଛି"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"ସାଇନ୍ ଅପ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"ସଦସ୍ୟତାକୁ ନବୀକରଣ କରି ସଂଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ଖୋଲୁଛି"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"ସଂଯୋଗ କରିହେଲା ନାହିଁ"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"ସାଇନ୍ ଅପ୍ ଶେଷ ହେଉଛି…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ସାଇନ୍ ଅପ୍ ଶେଷ ହୋଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ସାଇନ୍ ଅପ୍ ଶେଷ ହୋଇଛି। ସଂଯୋଗ କରୁଛି…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"ଏହି ନେଟୱାର୍କ ଏକ SIM ID ପ୍ରାପ୍ତ କରେ ଯାହା ଡିଭାଇସ୍ ଲୋକେସନ୍ ଟ୍ରାକ୍ କରିବାକୁ ବ୍ୟବହାର କରାଯାଇପାରିବ। "<annotation id="url">"ଅଧିକ ଜାଣନ୍ତୁ"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"ବହୁତ ମନ୍ଥର"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"କମ୍ ବେଗ"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ଠିକ୍ ଅଛି"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"ମଧ୍ୟମ"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"ଦ୍ରୁତ"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"ଅତି ଦ୍ରୁତ"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-pa/strings.xml b/libs/WifiTrackerLib/res/values-pa/strings.xml index de3c29f41..414e54259 100644 --- a/libs/WifiTrackerLib/res/values-pa/strings.xml +++ b/libs/WifiTrackerLib/res/values-pa/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ਸਵੈ-ਕਨੈਕਟ ਬੰਦ ਹੈ"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> ਵੱਲੋਂ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ਕੋਈ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ਪ੍ਰਮਾਣੀਕਰਨ ਸਮੱਸਿਆ"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"ਪਾਸਵਰਡ ਦੀ ਜਾਂਚ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"ਮੀਟਰਬੱਧ ਕੀਤਾ ਗਿਆ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"ਗੈਰ-ਮੀਟਰਬੱਧ ਕੀਤਾ ਗਿਆ"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> ਰਾਹੀਂ ਉਪਲਬਧ"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> ਰਾਹੀਂ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s ਰਾਹੀਂ ਆਪਣੇ-ਆਪ ਕਨੈਕਟ ਹੋਇਆ"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"ਨੈੱਟਵਰਕ ਰੇਟਿੰਗ ਪ੍ਰਦਾਨਕ ਰਾਹੀਂ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਹੋਇਆ"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"ਸੀਮਤ ਕਨੈਕਸ਼ਨ"</string> <string name="private_dns_broken" msgid="2212227512243587416">"ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ਠੀਕ-ਠਾਕ ਕਨੈਕਸ਼ਨ"</string> <string name="wifi_security_none" msgid="6680263031386719053">"ਕੋਈ ਨਹੀਂ"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ਮਿਆਦ ਮੁੱਕ ਗਈ"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"ਸਾਈਨ-ਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"ਗਾਹਕੀ ਦੇ ਨਵੀਨੀਕਰਨ ਲਈ ਅਤੇ ਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ਨੂੰ ਖੋਲ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਹੋਇਆ। ਕਨੈਕਟ ਹੋ ਰਿਹਾ ਹੈ…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"ਇਹ ਨੈੱਟਵਰਕ ਇੱਕ ਸਿਮ ਆਈਡੀ ਪ੍ਰਾਪਤ ਕਰਦਾ ਹੈ ਜਿਸਨੂੰ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਨੂੰ ਟਰੈਕ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ। "<annotation id="url">"ਹੋਰ ਜਾਣੋ"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"ਬਹੁਤ ਹੌਲੀ"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"ਹੌਲੀ"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ਠੀਕ ਹੈ"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"ਔਸਤ"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"ਤੇਜ਼"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"ਬਹੁਤ ਤੇਜ਼"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-pl/strings.xml b/libs/WifiTrackerLib/res/values-pl/strings.xml index 222627de7..2d41511fd 100644 --- a/libs/WifiTrackerLib/res/values-pl/strings.xml +++ b/libs/WifiTrackerLib/res/values-pl/strings.xml @@ -19,39 +19,23 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Łączenie automatyczne wyłączone"</string> <string name="saved_network" msgid="6241977554502802914">"Zapisane przez: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Nie można połączyć automatycznie"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Nie można połączyć automatycznie"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Brak dostępu do internetu"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problem z uwierzytelnianiem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Sprawdź hasło i spróbuj ponownie"</string> <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"Błąd konfiguracji IP"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"Wyłączona"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"Punkt dostępu jest tymczasowo zajęty"</string> - <string name="wifi_disconnected" msgid="3720926757662831062">"Rozłączono"</string> + <string name="wifi_disconnected" msgid="3720926757662831062">"Rozłączona"</string> <string name="wifi_remembered" msgid="5126903736498678708">"Zapisana"</string> <string name="wifi_metered_label" msgid="1362621600006544014">"Użycie danych jest mierzone"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Użycie danych nie jest mierzone"</string> <string name="connected_via_app" msgid="1818040967936972127">"Połączenie przez: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Dostęp przez aplikację <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatyczne połączenie przez <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatycznie połączono przez: %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatycznie połączono przez dostawcę ocen jakości sieci"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ograniczone połączenie"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Brak dostępu do prywatnego serwera DNS"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Brak internetu"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niska jakość"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Brak"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Ważność wygasła"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Kliknij, by się zarejestrować"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Kliknij, by odnowić subskrypcję i nawiązać połączenie"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Otwieram: <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Nie udało się połączyć"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Kończę rejestrować…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nie udało się dokończyć rejestracji. Kliknij, by spróbować ponownie."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Rejestracja zakończona. Łączę…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ta sieć otrzymuje unikalny identyfikator karty SIM, który można wykorzystać do śledzenia lokalizacji urządzenia. "<annotation id="url">"Więcej informacji"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Bardzo wolna"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Wolna"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Średnia"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Szybka"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Bardzo szybka"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml b/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml index 3b86fa621..421dab074 100644 --- a/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml +++ b/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"A conexão automática está desativada"</string> <string name="saved_network" msgid="6241977554502802914">"Salva por <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Não se conectará automaticamente"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Não se conectará automaticamente"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Sem acesso à Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problema de autenticação"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Verifique a senha e tente novamente"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Limitada"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Ilimitada"</string> <string name="connected_via_app" msgid="1818040967936972127">"Conectado via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponível via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Conectada automaticamente via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Conectado automaticamente via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Conectado automaticamente via provedor de avaliação de rede"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexão limitada"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Não é possível acessar o servidor DNS privado"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sem Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Conexão lenta"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Nenhuma"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirada"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Toque para se inscrever"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Toque para renovar a assinatura e se conectar"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Abrindo <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Não foi possível conectar"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Concluindo inscrição…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Não foi possível concluir a inscrição. Toque para tentar novamente."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscrição concluída. Conectando…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Essa rede recebe um ID de chip que pode ser usado para monitorar o local do dispositivo. "<annotation id="url">"Saiba mais"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Muito lenta"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Ok"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Média"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rápida"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Muito rápida"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirado"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml b/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml index f96f6f096..b8dd2e3e1 100644 --- a/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml +++ b/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"A ligação automática está desativada."</string> <string name="saved_network" msgid="6241977554502802914">"Guardada por <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Não é efetuada uma ligação automaticamente."</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Não é efetuada uma ligação automaticamente"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Sem acesso à Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problema de autenticação"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Verifique a palavra-passe e tente novamente"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Acesso limitado"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Acesso ilimitado"</string> <string name="connected_via_app" msgid="1818040967936972127">"Ligado via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponível através da app <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Ligado automaticamente através de <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Ligado automaticamente através de %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Ligado automaticamente através do fornecedor de classificação de rede"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ligação limitada"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Não é possível aceder ao servidor DNS."</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sem Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Baixa qualidade"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Nenhuma"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirada"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Toque para se inscrever."</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Toque para renovar a subscrição e estabelecer ligação."</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"A abrir <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>…"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Não foi possível estabelecer ligação."</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"A concluir a inscrição…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Não foi possível concluir a inscrição. Toque para tentar novamente."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscrição concluída. A estabelecer ligação…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Esta rede recebe um ID do SIM que pode ser utilizado para monitorizar a localização do dispositivo. "<annotation id="url">"Saiba mais"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Muito lenta"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Média"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rápida"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Muito rápida"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirado"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-pt/strings.xml b/libs/WifiTrackerLib/res/values-pt/strings.xml index 3b86fa621..421dab074 100644 --- a/libs/WifiTrackerLib/res/values-pt/strings.xml +++ b/libs/WifiTrackerLib/res/values-pt/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"A conexão automática está desativada"</string> <string name="saved_network" msgid="6241977554502802914">"Salva por <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Não se conectará automaticamente"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Não se conectará automaticamente"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Sem acesso à Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problema de autenticação"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Verifique a senha e tente novamente"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Limitada"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Ilimitada"</string> <string name="connected_via_app" msgid="1818040967936972127">"Conectado via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponível via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Conectada automaticamente via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Conectado automaticamente via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Conectado automaticamente via provedor de avaliação de rede"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexão limitada"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Não é possível acessar o servidor DNS privado"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sem Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Conexão lenta"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Nenhuma"</string> - <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirada"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Toque para se inscrever"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Toque para renovar a assinatura e se conectar"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Abrindo <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Não foi possível conectar"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Concluindo inscrição…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Não foi possível concluir a inscrição. Toque para tentar novamente."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscrição concluída. Conectando…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Essa rede recebe um ID de chip que pode ser usado para monitorar o local do dispositivo. "<annotation id="url">"Saiba mais"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Muito lenta"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Ok"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Média"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rápida"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Muito rápida"</string> + <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirado"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ro/strings.xml b/libs/WifiTrackerLib/res/values-ro/strings.xml index 219e4c44d..4e3e921b4 100644 --- a/libs/WifiTrackerLib/res/values-ro/strings.xml +++ b/libs/WifiTrackerLib/res/values-ro/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Conectarea automată este dezactivată"</string> <string name="saved_network" msgid="6241977554502802914">"Salvată de <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Nu se va conecta automat"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Nu se va conecta automat"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nu există acces la internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problemă la autentificare"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Verificați parola și încercați din nou"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Contorizată"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Necontorizată"</string> <string name="connected_via_app" msgid="1818040967936972127">"Conectat prin <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Disponibil prin <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Conectată automat prin <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Conectată automat prin %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Conectată automat prin furnizor de evaluări ale rețelei"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexiune limitată"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Serverul DNS privat nu poate fi accesat"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Fără conexiune la internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Calitate slabă"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Niciuna"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirat"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Atingeți pentru a vă înscrie"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Atingeți pentru a reînnoi abonamentul și a vă conecta"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Se deschide <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Nu s-a putut conecta"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Se finalizează înscrierea…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nu s-a putut finaliza înscrierea. Atingeți pentru a încerca din nou."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Înscrierea a fost finalizată. Se conectează…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Această rețea primește un cod SIM care se poate folosi pentru a urmări locația dispozitivului. "<annotation id="url">"Aflați mai multe"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Foarte lentă"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Lentă"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Bine"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Medie"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rapidă"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Foarte rapidă"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ru/strings.xml b/libs/WifiTrackerLib/res/values-ru/strings.xml index 672781b73..137c77b84 100644 --- a/libs/WifiTrackerLib/res/values-ru/strings.xml +++ b/libs/WifiTrackerLib/res/values-ru/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Автоподключение выключено"</string> <string name="saved_network" msgid="6241977554502802914">"Кто сохранил: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Подключение не будет выполняться автоматически"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Подключение не будет выполняться автоматически"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Без доступа к Интернету"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Ошибка аутентификации"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Возможно, вы указали неверный пароль. Повторите попытку."</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Сеть с тарификацией трафика"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Сеть без тарификации трафика"</string> <string name="connected_via_app" msgid="1818040967936972127">"Подключено через приложение \"<xliff:g id="NAME">%1$s</xliff:g>\"."</string> - <string name="available_via_app" msgid="9110324040292242769">"Доступно через приложение \"<xliff:g id="NAME">%1$s</xliff:g>\""</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Автоматически подключено через <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Автоматически подключено к %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Автоматически подключено через автора рейтинга сетей"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Подключение к сети ограничено."</string> <string name="private_dns_broken" msgid="2212227512243587416">"Доступа к частному DNS-серверу нет."</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Нет подключения к Интернету"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"низкое качество"</string> - <string name="wifi_security_none" msgid="6680263031386719053">"Без защиты"</string> + <string name="wifi_security_none" msgid="6680263031386719053">"Нет"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Срок действия истек"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Нажмите, чтобы зарегистрироваться."</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Нажмите, чтобы обновить подписку и установить подключение"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Открывается <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>…"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Не удалось подключиться."</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Завершение регистрации…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Не удалось завершить регистрацию. Нажмите, чтобы повторить попытку."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Регистрация завершена. Подключение…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Этой сети будет передан идентификатор SIM-карты, с помощью которого можно отследить местоположение устройства. "<annotation id="url">"Подробнее…"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Очень медленная"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Медленная"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ОК"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Средняя"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Быстрая"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Очень быстрая"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-si/strings.xml b/libs/WifiTrackerLib/res/values-si/strings.xml index cee255f56..cf09c70dd 100644 --- a/libs/WifiTrackerLib/res/values-si/strings.xml +++ b/libs/WifiTrackerLib/res/values-si/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ස්වයං සබැඳීම ක්රියාවිරහිතයි"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> විසින් සුරකින ලදී"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"ස්වයංක්රියව නැවත සම්බන්ධ නොවනු ඇත"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"ස්වයංක්රිය නැවත සම්බන්ධ නොවනු ඇත"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"අන්තර්ජාල ප්රවේශය නැත"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"සත්යාපනයේ ගැටලුවකි"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"මුරපදය පරික්ෂා කර නැවත උත්සාහ කරන්න"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"මනිනු ලැබේ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"මනින්නේ නැත"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> හරහා සම්බන්ධයි"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> හරහා ලබා ගත හැකිය"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> හරහා ස්වයංක්රියව සම්බන්ධ විය"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s හරහා ස්වයංක්රියව සම්බන්ධ විය"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"ජාල ශ්රේණිගත සපයන්නා හරහා ස්වයංක්රියව සම්බන්ධ විය"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"සීමිත සම්බන්ධතාව"</string> <string name="private_dns_broken" msgid="2212227512243587416">"පුද්ගලික DNS සේවාදායකයට ප්රවේශ වීමට නොහැකිය"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"අන්තර්ජාලය නැත"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"අඩු ගුණත්වය"</string> <string name="wifi_security_none" msgid="6680263031386719053">"කිසිවක් නැත"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"කල් ඉකුත් විය"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"ලියාපදිංචි වීමට තට්ටු කරන්න"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"දායකත්වය අලුත් කිරීමට තට්ටු කර සම්බන්ධ වන්න"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> විවෘත කරමින්"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"සබැඳීමට නොහැකි විය"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"ලියාපදිංචිය සම්පූර්ණ කරමින්…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ලියාපදිංචිය සම්පූර්ණ කළ නොහැකි විය. නැවත උත්සාහ කිරීමට තට්ටු කරන්න."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"ලියාපදිංචිය සම්පූර්ණයි. සබැඳෙමින්…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"උපාංග ස්ථානය නිරීක්ෂණය කිරීමට භාවිත කළ හැකි SIM ID එකක් මෙම ජාලයට ලැබේ. "<annotation id="url">"තව දැන ගන්න"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"ඉතා මන්දගාමී"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"මන්දගාමී"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"හරි"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"මධ්යම"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"වේගවත්"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"ඉතා වේගවත්"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-sk/strings.xml b/libs/WifiTrackerLib/res/values-sk/strings.xml index 11fd338e1..7ff4e22ad 100644 --- a/libs/WifiTrackerLib/res/values-sk/strings.xml +++ b/libs/WifiTrackerLib/res/values-sk/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatické pripojenie je vypnuté"</string> <string name="saved_network" msgid="6241977554502802914">"Uložila aplikácia <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Nedôjde k automatickému pripojeniu"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Nedôjde k automatickému pripojeniu"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Žiadny prístup k internetu"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problém s overením"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Skontrolujte heslo a skúste to znova"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Merané"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Bez merania dát"</string> <string name="connected_via_app" msgid="1818040967936972127">"Pripojené prostredníctvom siete <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"K dispozícii prostredníctvom aplikácie <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automaticky pripojené prostredníctvom poskytovateľa <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automaticky pripojené prostredníctvom %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automaticky pripojené prostredníctvom poskytovateľa hodnotenia siete"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Obmedzené pripojenie"</string> <string name="private_dns_broken" msgid="2212227512243587416">"K súkromnému serveru DNS sa nepodarilo získať prístup"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Bez internetu"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nízka kvalita"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Žiadne"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Platnosť vypršala"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Prihláste sa klepnutím"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Klepnutím obnovíte odber a pripojíte sa"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Otvára sa <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Nepodarilo sa pripojiť"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Dokončuje sa registrácia…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registráciu sa nepodarilo dokončiť. Klepnutím to skúste znova."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrácia je dokončená. Pripája sa…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Táto sieť dostáva jedinečný identifikátor SIM karty, pomocou ktorého je možné sledovať polohu zariadenia. "<annotation id="url">"Ďalšie informácie"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Veľmi pomalá"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Pomalá"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Stredná"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Rýchla"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Veľmi rýchla"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-sl/strings.xml b/libs/WifiTrackerLib/res/values-sl/strings.xml index 8cd9ef55b..8460a267d 100644 --- a/libs/WifiTrackerLib/res/values-sl/strings.xml +++ b/libs/WifiTrackerLib/res/values-sl/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"Samodejno povezovanje izklopljeno"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"Samodejno povezovanje je izklopljeno"</string> <string name="saved_network" msgid="6241977554502802914">"Shranil(-a): <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Povezava ne bo samodejno vzpostavljena"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Samodejna vnovična vzpostavitev povezave se ne bo izvedla"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Ni dostopa do interneta"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Težava pri preverjanju pristnosti"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Preverite geslo in poskusite znova"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Omejen prenos podatkov"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Z neomejenim prenosom podatkov"</string> <string name="connected_via_app" msgid="1818040967936972127">"Povezava vzpostavljena prek omrežja <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Na voljo prek aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Povezava je samodejno vzpostavljena prek: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Samodejno vzpostavljena povezava prek: %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Samodejno vzpostavljena povezava prek ponudnika ocenjevanja omrežij"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Omejena povezava"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Do zasebnega strežnika DNS ni mogoče dostopati"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ni internetne povezave"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nizka kakovost"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Brez"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Poteklo"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Dotaknite se, če se želite registrirati"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Dotaknite se za podaljšanje naročnine in vzpostavitev povezave"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Odpiranje ponudnika <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Povezave ni bilo mogoče vzpostaviti"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Dokončevanje registracije …"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registracije ni bilo mogoče dokončati. Če želite poskusiti znova, se dotaknite."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registracija je končana. Povezovanje …"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"To omrežje prejme ID kartice SIM, s katerim je mogoče spremljati lokacijo naprave. "<annotation id="url">"Več o tem"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Zelo počasna"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Počasna"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"V redu"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Srednje hitra"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Hitra"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Zelo hitra"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-sq/strings.xml b/libs/WifiTrackerLib/res/values-sq/strings.xml index 90c72ac56..cd0c04c04 100644 --- a/libs/WifiTrackerLib/res/values-sq/strings.xml +++ b/libs/WifiTrackerLib/res/values-sq/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Lidhja automatike është joaktive"</string> <string name="saved_network" msgid="6241977554502802914">"E ruajtur nga <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Nuk do të lidhet automatikisht"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Nuk do të lidhet automatikisht"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Nuk ka qasje në internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problem me vërtetimin"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Kontrollo fjalëkalimin dhe provo sërish"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Me matje"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Pa matje"</string> <string name="connected_via_app" msgid="1818040967936972127">"Lidhur përmes <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Ofrohet përmes <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Është lidhur automatikisht nëpërmjet <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Lidhur automatikisht përmes %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Lidhur automatikisht nëpërmjet ofruesit të vlerësimit të rrjetit"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Lidhje e kufizuar"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Serveri privat DNS nuk mund të qaset"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nuk ka internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Cilësi e ulët"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Asnjë"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Skaduar"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Trokit për t\'u regjistruar"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Trokit për të rinovuar abonimin dhe për t\'u lidhur"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Po hapet <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Nuk mund të lidhej"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Po përfundon regjistrimin…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Regjistrimi nuk mund të përfundonte. Trokit për të provuar përsëri."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Regjistrimi përfundoi. Po lidhet…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ky rrjet merr një ID karte SIM që mund të përdoret për të monitoruar vendndodhjen e pajisjes. "<annotation id="url">"Mëso më shumë"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Shumë e ulët"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"E ngadaltë"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Në rregull"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Mesatare"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"E shpejtë"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Shumë e shpejtë"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-sr/strings.xml b/libs/WifiTrackerLib/res/values-sr/strings.xml index 007e58ebe..ae05d4979 100644 --- a/libs/WifiTrackerLib/res/values-sr/strings.xml +++ b/libs/WifiTrackerLib/res/values-sr/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Аутоматско повезивање је искључено"</string> <string name="saved_network" msgid="6241977554502802914">"Сачувао/ла је <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Аутоматско повезивање није успело"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Аутоматско повезивање није успело"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Нема приступа интернету"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Проблем са потврдом идентитета"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Проверите лозинку и пробајте поново"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Са ограничењем"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Без ограничења"</string> <string name="connected_via_app" msgid="1818040967936972127">"Повезано преко: <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Доступно преко апликације <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Аутоматски повезано преко: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Аутоматски повезано преко %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Аутоматски повезано преко добављача оцене мреже"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Ограничена веза"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Приступ приватном DNS серверу није успео"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Нема интернета"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Лош квалитет"</string> - <string name="wifi_security_none" msgid="6680263031386719053">"Ништа"</string> + <string name="wifi_security_none" msgid="6680263031386719053">"Нема"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Истекло"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Додирните да бисте се регистровали"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Додирните да бисте обновили претплату и повезали"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Отвара се <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Повезивање није успело"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Регистрација се довршава…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Довршавање регистрације није успело. Додирните да бисте пробали поново."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Регистрација је довршена. Повезује се…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ова мрежа добија ИД SIM картице који може да се користи за праћење локације уређаја. "<annotation id="url">"Сазнајте више"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Веома спора"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Спора"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Потврди"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Средња"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Брза"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Веома брза"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-sv/strings.xml b/libs/WifiTrackerLib/res/values-sv/strings.xml index af1f0c4ff..1c56bf5dd 100644 --- a/libs/WifiTrackerLib/res/values-sv/strings.xml +++ b/libs/WifiTrackerLib/res/values-sv/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Automatisk anslutning har inaktiverats"</string> <string name="saved_network" msgid="6241977554502802914">"Sparades av <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Det går inte att ansluta automatiskt"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Det går inte att ansluta automatiskt"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Ingen internetåtkomst"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Autentiseringsproblem"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Kontrollera lösenordet och försök igen"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Med datapriser"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Utan datapriser"</string> <string name="connected_via_app" msgid="1818040967936972127">"Anslutet via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Tillgängligt via <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatiskt ansluten via <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Automatiskt ansluten via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Automatiskt ansluten via leverantör av nätverksbetyg"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Begränsad anslutning"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Det går inte att komma åt den privata DNS-servern."</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Inget internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Låg kvalitet"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Ingen"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Har upphört att gälla"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Tryck för att registrera dig"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Tryck här om du vill förnya prenumerationen och ansluta"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Öppnar <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Det gick inte att ansluta"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registreringen slutförs …"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Det gick inte att slutföra registreringen. Tryck för att försöka igen."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrering har slutförts. Ansluter …"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Det här nätverket får ett SIM-id som kan användas till att spåra enhetens plats. "<annotation id="url">"Läs mer"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Mycket långsam"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Långsam"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Okej"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Medelsnabb"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Snabb"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Mycket snabb"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-sw/strings.xml b/libs/WifiTrackerLib/res/values-sw/strings.xml index a4bc8aaf6..f6208b942 100644 --- a/libs/WifiTrackerLib/res/values-sw/strings.xml +++ b/libs/WifiTrackerLib/res/values-sw/strings.xml @@ -17,9 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"Kuunganisha kiotomatiki kumezimwa"</string> + <string name="auto_connect_disable" msgid="1078319396240632542">"Kipengele cha kuunganisha kiotomatiki kimezimwa"</string> <string name="saved_network" msgid="6241977554502802914">"Ilihifadhiwa na <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Haiwezi kuunganisha kiotomatiki"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Haiwezi kuunganisha kiotomatiki"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Hakuna muunganisho wa intaneti"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Tatizo la uthibitishaji"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Angalia nenosiri na ujaribu tena"</string> @@ -27,31 +27,15 @@ <string name="wifi_disabled_generic" msgid="8307050327779256414">"Imezimwa"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"Lango la mtandao lina shughuli nyingi kwa sasa"</string> <string name="wifi_disconnected" msgid="3720926757662831062">"Hujaunganishwa"</string> - <string name="wifi_remembered" msgid="5126903736498678708">"Umehifadhiwa"</string> + <string name="wifi_remembered" msgid="5126903736498678708">"Imehifadhiwa"</string> <string name="wifi_metered_label" msgid="1362621600006544014">"Mtandao unapima data"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Mtandao usiopima data"</string> <string name="connected_via_app" msgid="1818040967936972127">"Imeunganishwa kupitia <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Inapatikana kupitia <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Umeunganishwa kiotomatiki kupitia <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Imeunganishwa kiotomatiki kupitia %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Imeunganishwa kiotomatiki kupitia mtoa huduma wa ukadiriaji wa mtandao"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Muunganisho hafifu"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Seva ya faragha ya DNS haiwezi kufikiwa"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Hakuna intaneti"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ubora wa chini"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Hamna"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Muda umeisha"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Gusa ili ujisajili"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Gusa ili usasishe usajili na uunganishe"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Inafungua <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Imeshindwa kuunganisha"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Inakamilisha usajili…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Imeshindwa kukamilisha usajili. Gusa ili ujaribu tena."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Imekamilisha usajili. Inaunganisha…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Mtandao huu hupokea kitambulisho cha SIM ambacho kinaweza kutumiwa kufuatilia mahali kifaa kilipo. "<annotation id="url">"Pata maelezo zaidi"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Polepole Sana"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Polepole"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Sawa"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Wastani"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Haraka"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Haraka Sana"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ta/strings.xml b/libs/WifiTrackerLib/res/values-ta/strings.xml index 720698115..905ad605d 100644 --- a/libs/WifiTrackerLib/res/values-ta/strings.xml +++ b/libs/WifiTrackerLib/res/values-ta/strings.xml @@ -17,9 +17,10 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> - <string name="auto_connect_disable" msgid="1078319396240632542">"தானியங்கு இணைப்பு ஆஃப் செய்யப்பட்டுள்ளது"</string> + <!-- no translation found for auto_connect_disable (1078319396240632542) --> + <skip /> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> சேமித்தது"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"தானாக இணைக்கப்படாது"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"தானாக இணைக்கப்படாது"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"இணைய அணுகல் இல்லை"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"அங்கீகரிப்புச் சிக்கல்"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"கடவுச்சொல்லைச் சரிபார்த்து, மீண்டும் முயலவும்"</string> @@ -31,27 +32,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"கட்டண நெட்வொர்க்"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"கட்டணமில்லா நெட்வொர்க்"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> மூலம் இணைக்கப்பட்டது"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> மூலம் கிடைக்கும்"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> மூலம் தானாக இணைக்கப்பட்டது"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s மூலம் தானாக இணைக்கப்பட்டது"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"நெட்வொர்க் மதிப்பீடு வழங்குநரால் தானாக இணைக்கப்பட்டது"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"வரம்பிற்கு உட்பட்ட இணைப்பு"</string> <string name="private_dns_broken" msgid="2212227512243587416">"தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"இணைய இணைப்பு இல்லை"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"குறைந்த தரம்"</string> <string name="wifi_security_none" msgid="6680263031386719053">"ஏதுமில்லை"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"காலாவதியாகிவிட்டது"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"பதிவு செய்ய தட்டவும்"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"சந்தாவைப் புதுப்பித்து இணைக்க தட்டவும்"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> திறக்கப்படுகிறது"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"இணைக்க இயலவில்லை"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"பதிவு செய்தல் நிறைவடைகிறது…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"பதிவு செய்தலை நிறைவுசெய்ய முடியவில்லை. மீண்டும் முயல தட்டவும்."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"பதிவு செய்தல் நிறைவடைந்தது. இணைக்கிறது…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"சாதன இருப்பிடத்தைக் கண்காணிக்கப் பயன்படுத்தப்படும் சிம் ஐடியை இந்த நெட்வொர்க் பெறும். "<annotation id="url">"மேலும் அறிக"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"மிகவும் வேகம் குறைவானது"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"வேகம் குறைவு"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"சரி"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"நடுத்தரம்"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"வேகம்"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"மிகவும் வேகமானது"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-te/strings.xml b/libs/WifiTrackerLib/res/values-te/strings.xml index ede7edf00..dc4b248e5 100644 --- a/libs/WifiTrackerLib/res/values-te/strings.xml +++ b/libs/WifiTrackerLib/res/values-te/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"ఆటో-కనెక్ట్ ఆఫ్లో ఉంది"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> ద్వారా సేవ్ చేయబడింది"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"ఆటోమేటిక్గా కనెక్ట్ కాదు"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"స్వయంచాలకంగా కనెక్ట్ కాదు"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"ఇంటర్నెట్ యాక్సెస్ లేదు"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ప్రామాణీకరణ సమస్య"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"పాస్వర్డ్ను తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"గణించబడుతోంది"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"గణించబడటం లేదు"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> ద్వారా కనెక్ట్ చేయబడింది"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> ద్వారా అందుబాటులో ఉంది"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> ద్వారా ఆటోమేటిక్గా కనెక్ట్ చేయబడింది"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s ద్వారా స్వయంచాలకంగా కనెక్ట్ చేయబడింది"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"నెట్వర్క్ రేటింగ్ ప్రదాత ద్వారా స్వయంచాలకంగా కనెక్ట్ చేయబడింది"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"పరిమిత కనెక్షన్"</string> <string name="private_dns_broken" msgid="2212227512243587416">"ప్రైవేట్ DNS సర్వర్ను యాక్సెస్ చేయడం సాధ్యపడదు"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ఇంటర్నెట్ లేదు"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"తక్కువ క్వాలిటీ"</string> <string name="wifi_security_none" msgid="6680263031386719053">"ఏదీ లేదు"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"గడువు ముగిసింది"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"సైన్ అప్ చేయడానికి ట్యాప్ చేయండి"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"సభ్యత్వాన్ని రెన్యూ చేసి, కనెక్ట్ చేయడానికి నొక్కండి"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> తెరవబడుతోంది"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"కనెక్ట్ చేయడం సాధ్యపడలేదు"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"సైన్ అప్ పూర్తవుతోంది…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"సైన్ అప్ను పూర్తి చేయడం సాధ్యపడలేదు. మళ్ళీ ప్రయత్నించడానికి ట్యాప్ చేయండి."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"సైన్ అప్ పూర్తయింది. కనెక్ట్ చేయబడుతోంది…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"పరికరం లొకేషన్ను ట్రాక్ చేయడానికి ఉపయోగపడే SIM IDని ఈ నెట్వర్క్ అందుకుంటుంది. "<annotation id="url">"మరింత తెలుసుకోండి"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"చాలా నెమ్మది"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"నెమ్మది"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"సరే"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"మధ్యస్థం"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"వేగవంతం"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"చాలా వేగవంతం"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-th/strings.xml b/libs/WifiTrackerLib/res/values-th/strings.xml index cc18e7fec..61e5607e3 100644 --- a/libs/WifiTrackerLib/res/values-th/strings.xml +++ b/libs/WifiTrackerLib/res/values-th/strings.xml @@ -18,40 +18,24 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"การเชื่อมต่ออัตโนมัติปิดอยู่"</string> - <string name="saved_network" msgid="6241977554502802914">"บันทึกโดย<xliff:g id="NAME">%1$s</xliff:g> แล้ว"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"จะไม่เชื่อมต่อโดยอัตโนมัติ"</string> + <string name="saved_network" msgid="6241977554502802914">"บันทึกโดย <xliff:g id="NAME">%1$s</xliff:g> แล้ว"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"จะไม่เชื่อมต่อโดยอัตโนมัติ"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"เข้าถึงอินเทอร์เน็ตไม่ได้"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ปัญหาในการตรวจสอบสิทธิ์"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"ตรวจสอบรหัสผ่านและลองอีกครั้ง"</string> <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"การกำหนดค่า IP ล้มเหลว"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"ปิดอยู่"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"จุดเข้าใช้งานเต็มชั่วคราว"</string> - <string name="wifi_disconnected" msgid="3720926757662831062">"ยกเลิกการเชื่อมต่อแล้ว"</string> + <string name="wifi_disconnected" msgid="3720926757662831062">"เลิกเชื่อมต่อแล้ว"</string> <string name="wifi_remembered" msgid="5126903736498678708">"บันทึกแล้ว"</string> - <string name="wifi_metered_label" msgid="1362621600006544014">"แบบจำกัดปริมาณ"</string> + <string name="wifi_metered_label" msgid="1362621600006544014">"มีการวัดปริมาณอินเทอร์เน็ต"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"ไม่มีการวัดปริมาณอินเทอร์เน็ต"</string> <string name="connected_via_app" msgid="1818040967936972127">"เชื่อมต่อแล้วผ่าน <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"ใช้งานได้ผ่านทาง <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"เชื่อมต่อโดยอัตโนมัติผ่าน <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"เชื่อมต่ออัตโนมัติผ่าน %1$s แล้ว"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"เชื่อมต่ออัตโนมัติผ่านผู้ให้บริการการจัดอันดับเครือข่าย"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"การเชื่อมต่อที่จำกัด"</string> <string name="private_dns_broken" msgid="2212227512243587416">"เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ไม่มีอินเทอร์เน็ต"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"คุณภาพต่ำ"</string> <string name="wifi_security_none" msgid="6680263031386719053">"ไม่มี"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"หมดอายุแล้ว"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"แตะเพื่อลงชื่อสมัครใช้"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"แตะเพื่อต่ออายุการสมัครใช้บริการและเชื่อมต่อ"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"กำลังเปิด <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"เชื่อมต่อไม่สำเร็จ"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"กำลังลงชื่อสมัครใช้ให้เสร็จสิ้น…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"ลงชื่อสมัครใช้ไม่สำเร็จ แตะเพื่อลองอีกครั้ง"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"การลงชื่อสมัครใช้เสร็จสมบูรณ์ กำลังเชื่อมต่อ…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"เครือข่ายนี้จะได้รับรหัส SIM ซึ่งใช้ติดตามตำแหน่งอุปกรณ์ได้ "<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"ช้ามาก"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"ช้า"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ตกลง"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"ปานกลาง"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"เร็ว"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"เร็วมาก"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-tl/strings.xml b/libs/WifiTrackerLib/res/values-tl/strings.xml index ccb973ac8..1a3a39f1e 100644 --- a/libs/WifiTrackerLib/res/values-tl/strings.xml +++ b/libs/WifiTrackerLib/res/values-tl/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Naka-off ang Auto-connect"</string> <string name="saved_network" msgid="6241977554502802914">"Na-save ng <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Hindi awtomatikong kokonekta"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Hindi awtomatikong kokonekta"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Walang access sa internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Problema sa pag-authenticate"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Suriin ang password at subukang muli"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Nakametro"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Hindi Nakametro"</string> <string name="connected_via_app" msgid="1818040967936972127">"Nakakonekta sa pamamagitan ng <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Available sa pamamagitan ng <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Awtomatikong nakakonekta sa pamamagitan ng <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Awtomatikong nakakonekta sa pamamagitan ng %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Awtomatikong nakakonekta sa pamamagitan ng provider ng rating ng network"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Limitadong koneksyon"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Hindi ma-access ang pribadong DNS server"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Walang internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Mababang kalidad"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Wala"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Nag-expire na"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"I-tap para mag-sign up"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"I-tap para i-renew ang subscription at kumonekta"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Binubuksan ang <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Hindi makakonekta"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Kinukumpleto ang pag-sign up…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Hindi makumpleto ang pag-sign up. I-tap para subukan ulit."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Kumpleto na ang pag-sign up. Kumokonekta…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Tumatanggap ang network na ito ng SIM ID na magagamit sa pagsubaybay ng lokasyon ng device. "<annotation id="url">"Matuto pa"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Napakabagal"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Mabagal"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Katamtaman"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Mabilis"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Napakabilis"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-tr/strings.xml b/libs/WifiTrackerLib/res/values-tr/strings.xml index a480a3d06..6ac173bfa 100644 --- a/libs/WifiTrackerLib/res/values-tr/strings.xml +++ b/libs/WifiTrackerLib/res/values-tr/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Otomatik bağlanma kapalı"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> tarafından kaydedildi"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Otomatik olarak bağlanmayacak"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Otomatik olarak bağlanma"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"İnternet erişimi yok"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Kimlik doğrulama sorunu"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Şifreyi kontrol edin ve tekrar deneyin"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Sayaçlı"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Sayaçsız"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> ile bağlandı"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> ile kullanılabilir"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> ile otomatik olarak bağlandı"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s üzerinden otomatik olarak bağlı"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Ağ derecelendirme sağlayıcı aracılığıyla otomatik olarak bağlandı"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Sınırlı bağlantı"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Gizli DNS sunucusuna erişilemiyor"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"İnternet yok"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Düşük kalite"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Yok"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Süresi sona erdi"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Kaydolmak için dokunun"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Aboneliği yenilemek ve bağlanmak için dokunun"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> açılıyor"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Bağlanılamadı"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Kayıt işlemi tamamlanıyor…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Kayıt işlemi tamamlanamadı. Tekrar denemek için dokunun."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Kayıt tamamlandı. Bağlanıyor…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Bu ağ, cihaz konumunu izlemek için kullanılabilecek bir SIM kimliği alır. "<annotation id="url">"Daha fazla bilgi"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Çok Yavaş"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Yavaş"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Tamam"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Orta"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Hızlı"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Çok Hızlı"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-uk/strings.xml b/libs/WifiTrackerLib/res/values-uk/strings.xml index 8a6965818..6c0901ea6 100644 --- a/libs/WifiTrackerLib/res/values-uk/strings.xml +++ b/libs/WifiTrackerLib/res/values-uk/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Автоматичне підключення вимкнено"</string> <string name="saved_network" msgid="6241977554502802914">"Збережено додатком <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Не підключатиметься автоматично"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Не під’єднуватиметься автоматично"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Немає доступу до Інтернету"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Проблема з автентифікацією"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Перевірте пароль і повторіть спробу"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"З тарифікацією трафіку"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Без тарифікації трафіку"</string> <string name="connected_via_app" msgid="1818040967936972127">"Підключено через додаток <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Доступно в додатку <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Автоматично підключено через <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Автоматично під’єднано через %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Автоматично під’єднано через постачальника оцінки якості мережі"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Обмежене з’єднання"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Немає доступу до приватного DNS-сервера"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Немає Інтернету"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Низька якість"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Немає"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Термін дії минув"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Торкніться, щоб зареєструватись"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Натисніть, щоб поновити підписку та підключитися"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> відкривається"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Не вдалося підключитись"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Завершення реєстрації…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Не вдалося завершити реєстрацію. Торкніться, щоб повторити спробу."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Реєстрацію завершено. Підключення…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Ця мережа отримує ідентифікатор SIM-карти, за допомогою якого можна відстежити місцезнаходження пристрою. "<annotation id="url">"Докладніше"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Дуже повільна"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Повільна"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ОК"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Середня"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Швидка"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Дуже швидка"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-ur/strings.xml b/libs/WifiTrackerLib/res/values-ur/strings.xml index 2bc36a53b..7ebe2143e 100644 --- a/libs/WifiTrackerLib/res/values-ur/strings.xml +++ b/libs/WifiTrackerLib/res/values-ur/strings.xml @@ -19,10 +19,10 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"خود کار طور پر منسلک کریں آف ہے"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> کی جانب سے محفوظ کردہ"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"خودکار طور پر منسلک نہیں ہو گا"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"خودکار طور پر منسلک نہیں ہو گا"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"انٹرنیٹ تک کوئی رسائی نہیں"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"توثیق کا مسئلہ"</string> - <string name="wifi_check_password_try_again" msgid="2643230209986217827">"پاس ورڈ چیک کر کے دوبارہ کوشش کریں"</string> + <string name="wifi_check_password_try_again" msgid="2643230209986217827">"پاسورڈ چیک کر کے دوبارہ کوشش کریں"</string> <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP کنفیگریشن کی ناکامی"</string> <string name="wifi_disabled_generic" msgid="8307050327779256414">"غیر فعال"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"رسائی پوائنٹ عارضی طور پر فُل ہے"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"میٹرڈ"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"غیر میٹر شدہ"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> کے ذریعے منسلک"</string> - <string name="available_via_app" msgid="9110324040292242769">"دستیاب بذریعہ <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"خودکار طور پر <xliff:g id="NAME">%1$s</xliff:g> کے ذریعے منسلک"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s کے ذریعے از خود منسلک کردہ"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"نیٹ ورک درجہ بندی کے فراہم کنندہ کے ذریعے از خود منسلک"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"محدود کنکشن"</string> <string name="private_dns_broken" msgid="2212227512243587416">"نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"انٹرنیٹ نہیں ہے"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ادنٰی معیار"</string> <string name="wifi_security_none" msgid="6680263031386719053">"کوئی نہیں"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"میعاد ختم ہو گئی"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"سائن اپ کے لیے تھپتھپائیں"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"سبسکرپشن کی تجدید کرنے اور منسلک ہونے کے لیے تھپتھپائیں"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> کھل رہا ہے"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"منسلک نہیں کیا جا سکا"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"سائن اپ مکمل ہو رہا ہے…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"سائن اپ مکمل نہیں ہو سکا۔ دوبارہ کوشش کرنے کے لیے تھپتھپائیں۔"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"سائن اپ مکمل ہو گیا۔ منسلک ہو رہا ہے…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"اس نیٹ ورک کو ایک SIM ID موصول ہوتی ہے جو آلہ کے مقام کو ٹریک کرنے کیلئے استعمال ہو سکتی ہے۔ "<annotation id="url">"مزید جانیں"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"بہت سست"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"سست"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"ٹھیک ہے"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"متوسط"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"تیز"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"بہت تیز"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-uz/strings.xml b/libs/WifiTrackerLib/res/values-uz/strings.xml index f19791ea1..5c4d8996a 100644 --- a/libs/WifiTrackerLib/res/values-uz/strings.xml +++ b/libs/WifiTrackerLib/res/values-uz/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Avtomatik ulash yoqilmagan"</string> <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> tomonidan saqlangan"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Avtomatik ravishda ulanilmaydi"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Avtomatik ravishda ulanilmaydi"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Internetga ulanmagan"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Haqiqiylikni tekshirishda muammo"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Parolni tekshirib, qaytadan urining"</string> @@ -27,31 +27,15 @@ <string name="wifi_disabled_generic" msgid="8307050327779256414">"Yoqilmagan"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"Internet kirish nuqtasi vaqtinchalik to‘lgan"</string> <string name="wifi_disconnected" msgid="3720926757662831062">"Ulanmagan"</string> - <string name="wifi_remembered" msgid="5126903736498678708">"Saqlangan"</string> + <string name="wifi_remembered" msgid="5126903736498678708">"Saqlandi"</string> <string name="wifi_metered_label" msgid="1362621600006544014">"Trafik hisoblanadigan tarmoq"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Trafik hisobi yuritilmaydigan tarmoq"</string> <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> orqali ulandi"</string> - <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> ilovasi orqali mavjud"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> orqali avtomatik ulandi"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"%1$s orqali avtomatik ulandi"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Tarmoqlar reytingi muallifi orqali avtomatik ulandi"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Cheklangan aloqa"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Xususiy DNS server ishlamayapti"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Internetga ulanmagansiz"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Sifati past"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Hech qanday"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Muddati tugagan"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Registratsiya qilish uchun bosing"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Obunani davom ettirish va ulanish uchun bosing"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ochilmoqda"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Ulanmadi"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registratsiya tamomlanmoqda…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registratsiya tamomlanmadi. Qayta urinish uchun tegining."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registratsiya qilindi. Ulanmoqda…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Bu tarmoqqa qurilma joylashuvini aniqlash imkonini beruvchi SIM identifikator beriladi. "<annotation id="url">"Batafsil"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Juda sekin"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Sekin"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"O‘rtacha"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Tez"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Juda tez"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-vi/strings.xml b/libs/WifiTrackerLib/res/values-vi/strings.xml index 90a0a1038..b89be9a5e 100644 --- a/libs/WifiTrackerLib/res/values-vi/strings.xml +++ b/libs/WifiTrackerLib/res/values-vi/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Tính năng tự động kết nối đang tắt"</string> <string name="saved_network" msgid="6241977554502802914">"Do <xliff:g id="NAME">%1$s</xliff:g> lưu"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Sẽ không tự động kết nối"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Sẽ không tự động kết nối"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Không có kết nối Internet"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Sự cố xác thực"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Kiểm tra mật khẩu và thử lại"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Đo lượng dữ liệu"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Không đo lượng dữ liệu"</string> <string name="connected_via_app" msgid="1818040967936972127">"Đã kết nối qua <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Được cung cấp qua <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Đã tự động kết nối qua <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Tự động được kết nối qua %1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Tự động được kết nối qua nhà cung cấp dịch vụ xếp hạng mạng"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Kết nối giới hạn"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Không thể truy cập máy chủ DNS riêng tư"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Không có Internet"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Chất lượng thấp"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Không"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Đã hết hạn"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Nhấn để đăng ký"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Nhấn để gia hạn gói đăng ký và kết nối"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Đang mở <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Không thể kết nối"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Đang hoàn tất việc đăng ký…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Không thể hoàn tất việc đăng ký. Hãy nhấn để thử lại."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Đã đăng ký xong. Đang kết nối…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Mạng này nhận được một mã nhận dạng SIM có thể dùng để theo dõi vị trí của thiết bị. "<annotation id="url">"Tìm hiểu thêm"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Rất chậm"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Chậm"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"Khá tốt"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Trung bình"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Nhanh"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Rất nhanh"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml b/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml index f3bf193b5..aec658768 100644 --- a/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml +++ b/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"自动连接已关闭"</string> <string name="saved_network" msgid="6241977554502802914">"由“<xliff:g id="NAME">%1$s</xliff:g>”保存"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"无法自动连接"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"无法自动连接"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"无法访问互联网"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"身份验证出现问题"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"请检查密码,然后重试"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"按流量计费"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"不按流量计费"</string> <string name="connected_via_app" msgid="1818040967936972127">"已通过<xliff:g id="NAME">%1$s</xliff:g>连接到网络"</string> - <string name="available_via_app" msgid="9110324040292242769">"可通过“<xliff:g id="NAME">%1$s</xliff:g>”使用"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"已通过<xliff:g id="NAME">%1$s</xliff:g>自动连接"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"已通过%1$s自动连接"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"已自动连接(通过网络评分服务提供方)"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"网络连接受限"</string> <string name="private_dns_broken" msgid="2212227512243587416">"无法访问私人 DNS 服务器"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"无法访问互联网"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"质量不佳"</string> <string name="wifi_security_none" msgid="6680263031386719053">"无"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"已失效"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"点按即可注册"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"点按即可续订并连接"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"正在打开<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"无法连接"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"正在完成注册…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"无法完成注册。点按即可重试。"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"注册完毕。正在连接…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"此网络会收到可用于跟踪设备位置的 SIM 卡 ID。"<annotation id="url">"了解详情"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"很慢"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"慢"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"良好"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"适中"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"快"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"很快"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml b/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml index e0639708b..2b0d11137 100644 --- a/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml +++ b/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"自動連線功能已關閉"</string> <string name="saved_network" msgid="6241977554502802914">"由「<xliff:g id="NAME">%1$s</xliff:g>」儲存"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"不會自動連線"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"不會自動連線"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"無法連接互聯網"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"驗證問題"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"請檢查密碼,然後再試一次"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"按用量收費"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"不限數據用量收費"</string> <string name="connected_via_app" msgid="1818040967936972127">"已透過「<xliff:g id="NAME">%1$s</xliff:g>」連線"</string> - <string name="available_via_app" msgid="9110324040292242769">"可透過「<xliff:g id="NAME">%1$s</xliff:g>」連線"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"已透過「<xliff:g id="NAME">%1$s</xliff:g>」自動連線"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"已透過 %1$s 自動連線"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"已透過網絡評分供應商自動連線"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"連線受限"</string> <string name="private_dns_broken" msgid="2212227512243587416">"無法存取私人 DNS 伺服器"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"沒有互聯網連線"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"品質欠佳"</string> <string name="wifi_security_none" msgid="6680263031386719053">"無"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"已過期"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"輕按即可登入"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"輕按即可續購訂閱並連線"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"正在開啟 <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"無法連接"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"正在完成申請…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"無法完成申請。輕按即可重試。"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"已完成申請。連接中…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"此網絡會接收可用於追蹤裝置位置的 SIM 卡 ID。"<annotation id="url">"瞭解詳情"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"非常慢"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"慢"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"良好"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"適中"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"快"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"非常快"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml b/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml index 35f21eb5c..e06dee791 100644 --- a/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml +++ b/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"自動連線功能已關閉"</string> <string name="saved_network" msgid="6241977554502802914">"由「<xliff:g id="NAME">%1$s</xliff:g>」儲存"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"不會自動連線"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"無法自動連線"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"沒有可用的網際網路連線"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"驗證問題"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"請檢查密碼,然後再試一次"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"計量付費"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"非計量付費"</string> <string name="connected_via_app" msgid="1818040967936972127">"透過「<xliff:g id="NAME">%1$s</xliff:g>」連線"</string> - <string name="available_via_app" msgid="9110324040292242769">"可透過「<xliff:g id="NAME">%1$s</xliff:g>」使用"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"透過「<xliff:g id="NAME">%1$s</xliff:g>」自動連線"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"已透過 %1$s 自動連線"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"已透過網路評分供應商自動連線"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"連線能力受限"</string> <string name="private_dns_broken" msgid="2212227512243587416">"無法存取私人 DNS 伺服器"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"沒有網際網路連線"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"品質不佳"</string> <string name="wifi_security_none" msgid="6680263031386719053">"無"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"已失效"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"輕觸即可註冊"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"輕觸即可續訂並連線"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"正在開啟「<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>」"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"無法連線"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"正在完成註冊程序…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"無法完成註冊程序。輕觸即可重試。"</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"註冊完成。連線中…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"這個網路會收到可用於追蹤裝置位置的 SIM 卡 ID。"<annotation id="url">"瞭解詳情"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"非常慢"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"慢"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"確定"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"適中"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"快"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"非常快"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values-zu/strings.xml b/libs/WifiTrackerLib/res/values-zu/strings.xml index b0a54ced0..113e2ce2d 100644 --- a/libs/WifiTrackerLib/res/values-zu/strings.xml +++ b/libs/WifiTrackerLib/res/values-zu/strings.xml @@ -19,7 +19,7 @@ <string name="summary_separator" msgid="6533720408587140819">" / "</string> <string name="auto_connect_disable" msgid="1078319396240632542">"Ukuxhuma ngokuzenzakalelayo kuvaliwe"</string> <string name="saved_network" msgid="6241977554502802914">"Kulondolozwe ngu-<xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Ngeke ixhume ngokuzenzekelayo"</string> + <string name="wifi_no_internet_no_reconnect" msgid="4378129479815195671">"Ngeke ize ixhumeke ngokuzenzakalela"</string> <string name="wifi_no_internet" msgid="4461212237521310895">"Akukho ukufinyelela kwe-inthanethi"</string> <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Inkinga yokufakazela ubuqiniso"</string> <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Hlola iphasiwedi uphinde uzame futhi"</string> @@ -31,27 +31,11 @@ <string name="wifi_metered_label" msgid="1362621600006544014">"Kulinganisiwe"</string> <string name="wifi_unmetered_label" msgid="499466875639448350">"Akulinganiselwa"</string> <string name="connected_via_app" msgid="1818040967936972127">"Ixhumeke nge-<xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="available_via_app" msgid="9110324040292242769">"Kutholakala nge-<xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="connected_via_network_scorer" msgid="209764314005159012">"Kuxhunywe ngokuzenzekelayo nge-<xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="8081366798449871179">"Ixhumeke ngokuzenzakalela nge-%1$s"</string> <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"Kuxhunywe ngokuzenzakalelayo ngomhlinzeki wesilinganiso wenethiwekhi"</string> <string name="wifi_limited_connection" msgid="3646701342701276239">"Iqoqo elikhawulelwe"</string> <string name="private_dns_broken" msgid="2212227512243587416">"Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa"</string> <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ayikho i-inthanethi"</string> - <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ikhwalithi ephansi"</string> <string name="wifi_security_none" msgid="6680263031386719053">"Lutho"</string> <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Iphelelwe isikhathi"</string> - <string name="tap_to_sign_up" msgid="2409214576606918295">"Thepha ukuze ubhalisele"</string> - <string name="tap_to_renew_subscription_and_connect" msgid="375976298920840105">"Thepha ukuze wenze kabusha okubhalisile futhi uxhume"</string> - <string name="osu_opening_provider" msgid="5633521771769175139">"Ivula i-<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string> - <string name="osu_connect_failed" msgid="8503501619299851793">"Ayikwazanga ukuxhumeka"</string> - <string name="osu_completing_sign_up" msgid="7188493241442946231">"Iqedela ukubhalisa…"</string> - <string name="osu_sign_up_failed" msgid="2725057866968590279">"Ayikwazanga ukuqedelela ukubhalisa. Thepha ukuze uzame futhi."</string> - <string name="osu_sign_up_complete" msgid="7013805426618985953">"Ukubhalisa kuqediwe. Iyaxhuma…"</string> - <string name="imsi_protection_warning" msgid="5231726821588271569">"Le nethiwekhi ithola i-SIM ID engasetshenziselwa ukulandelela indawo yedivayisi. "<annotation id="url">"Funda kabanzi"</annotation></string> - <string name="speed_label_very_slow" msgid="2401582671941367179">"Phansi kakhulu"</string> - <string name="speed_label_slow" msgid="8410385703344502127">"Phansi"</string> - <string name="speed_label_okay" msgid="3741857805086997968">"KULUNGILE"</string> - <string name="speed_label_medium" msgid="3175703848952862009">"Okumaphakathi"</string> - <string name="speed_label_fast" msgid="8344116097613544322">"Sheshayo"</string> - <string name="speed_label_very_fast" msgid="1595806641512447877">"Kushesha kakhulu"</string> </resources> diff --git a/libs/WifiTrackerLib/res/values/strings.xml b/libs/WifiTrackerLib/res/values/strings.xml index c47e28939..04369824a 100644 --- a/libs/WifiTrackerLib/res/values/strings.xml +++ b/libs/WifiTrackerLib/res/values/strings.xml @@ -173,7 +173,7 @@ <string name="osu_sign_up_complete">Sign-up complete. Connecting\u2026</string> <!-- IMSI protection warning for non-protection network [CHAR LIMIT=NONE] --> - <string name="imsi_protection_warning">This network receives a SIM ID that can be used to track device location. <annotation id="url">Learn more</annotation></string> + <string name="imsi_protection_warning">This network receives a unique ID that can be used to track device location. <annotation id="url">Learn more</annotation></string> <!-- Help URL, IMSI protection [DO NOT TRANSLATE] --> <string name="help_url_imsi_protection" translatable="false"></string> diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java index 5a14ec4ba..90d62f280 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java @@ -701,6 +701,11 @@ class Utils { /** Find the annotation of specified id in rawText and linkify it with helpUriString. */ static CharSequence linkifyAnnotation(Context context, CharSequence rawText, String id, String helpUriString) { + // Return original string when helpUriString is empty. + if (TextUtils.isEmpty(helpUriString)) { + return rawText; + } + SpannableString spannableText = new SpannableString(rawText); Annotation[] annotations = spannableText.getSpans(0, spannableText.length(), Annotation.class); diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java index 675c80d0a..09a2a3ffe 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java @@ -26,7 +26,6 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkCapabilities; import android.net.NetworkInfo; -import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; @@ -42,6 +41,8 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.annotation.WorkerThread; +import com.android.net.module.util.NetUtils; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.Inet4Address; @@ -689,7 +690,7 @@ public abstract class WifiEntry implements Comparable<WifiEntry> { try { InetAddress all = InetAddress.getByAddress( new byte[]{(byte) 255, (byte) 255, (byte) 255, (byte) 255}); - mConnectedInfo.subnetMask = NetworkUtils.getNetworkPart( + mConnectedInfo.subnetMask = NetUtils.getNetworkPart( all, addr.getPrefixLength()).getHostAddress(); } catch (UnknownHostException e) { // Leave subnet null; diff --git a/libs/WifiTrackerLib/tests/Android.bp b/libs/WifiTrackerLib/tests/Android.bp index a9c51e7a8..202674446 100644 --- a/libs/WifiTrackerLib/tests/Android.bp +++ b/libs/WifiTrackerLib/tests/Android.bp @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + android_test { name: "WifiTrackerLibTests", srcs: ["src/**/*.java"], diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java index 5532a2304..b009ac066 100644 --- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java +++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java @@ -415,6 +415,24 @@ public class UtilsTest { } @Test + public void testLinkifyAnnotation_annotationWithEmptyUriString_returnOriginalText() { + final String annotationId = "url"; + final CharSequence testText = "test text "; + final CharSequence testLink = "Learn More"; + final CharSequence expectedText = "test text Learn More"; + final SpannableStringBuilder builder = new SpannableStringBuilder(testText); + builder.append(testLink, new Annotation("key", annotationId), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + + final CharSequence output = linkifyAnnotation(mMockContext, builder, annotationId, ""); + + final SpannableString outputSpannableString = new SpannableString(output); + assertEquals(output.toString(), expectedText.toString()); + assertEquals(outputSpannableString.getSpans(0, outputSpannableString.length(), + ClickableSpan.class).length, 0); + } + + @Test public void testGetNetworkSelectionDescription_disabledWrongPassword_showsWrongPasswordLabel() { String expected = " (NETWORK_SELECTION_TEMPORARY_DISABLED 1:02:03) " + "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD=2"; diff --git a/libwifi_hal/Android.mk b/libwifi_hal/Android.mk index 7bdbc3259..6d100b179 100644 --- a/libwifi_hal/Android.mk +++ b/libwifi_hal/Android.mk @@ -64,6 +64,8 @@ endif # ============================================================ include $(CLEAR_VARS) LOCAL_MODULE := libwifi-hal-common +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice LOCAL_VENDOR_MODULE := true LOCAL_CFLAGS := $(wifi_hal_cflags) LOCAL_C_INCLUDES := $(LOCAL_PATH)/include @@ -77,6 +79,8 @@ include $(BUILD_STATIC_LIBRARY) # ============================================================ include $(CLEAR_VARS) LOCAL_MODULE := libwifi-hal-fallback +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice LOCAL_VENDOR_MODULE := true LOCAL_CFLAGS := $(wifi_hal_cflags) LOCAL_SRC_FILES := wifi_hal_fallback.cpp @@ -105,12 +109,16 @@ else ifeq ($(BOARD_WLAN_DEVICE), realtek) LIB_WIFI_HAL := libwifi-hal-rtk else ifeq ($(BOARD_WLAN_DEVICE), emulator) LIB_WIFI_HAL := libwifi-hal-emu +else ifeq ($(BOARD_WLAN_DEVICE), slsi) + LIB_WIFI_HAL := libwifi-hal-slsi endif # The WiFi HAL that you should be linking. # ============================================================ include $(CLEAR_VARS) LOCAL_MODULE := libwifi-hal +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice LOCAL_PROPRIETARY_MODULE := true LOCAL_CFLAGS := $(wifi_hal_cflags) LOCAL_C_INCLUDES := $(LOCAL_PATH)/include @@ -135,6 +143,8 @@ include $(BUILD_SHARED_LIBRARY) # ============================================================ include $(CLEAR_VARS) LOCAL_MODULE := libwifi-hal-test +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice LOCAL_CFLAGS := $(wifi_hal_cflags) LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include \ diff --git a/libwifi_system/Android.bp b/libwifi_system/Android.bp index a3aa7034a..ec0201248 100644 --- a/libwifi_system/Android.bp +++ b/libwifi_system/Android.bp @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + cc_defaults { name: "libwifi-system-defaults", cflags: [ diff --git a/libwifi_system_iface/Android.bp b/libwifi_system_iface/Android.bp index 80249ef3c..0ea30f4de 100644 --- a/libwifi_system_iface/Android.bp +++ b/libwifi_system_iface/Android.bp @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + wifi_system_iface_cflags = [ "-Wall", "-Werror", @@ -29,6 +33,7 @@ wifi_system_iface_cflags = [ cc_library { name: "libwifi-system-iface", vendor_available: true, + product_available: true, vndk: { enabled: true, }, diff --git a/metrics_pdd_hook.py b/metrics_pdd_hook.py deleted file mode 100755 index fa858553a..000000000 --- a/metrics_pdd_hook.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/python - -# -# Copyright 2020, 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. -# - -from __future__ import print_function - -from argparse import ArgumentParser -import subprocess -import sys - - -def is_in_aosp(): - branches = subprocess.check_output(['git', 'branch', '-vv']).splitlines() - - for branch in branches: - # current branch starts with a '*' - if branch.startswith('*'): - return '[aosp/' in branch - - # otherwise assume in AOSP - return True - - -def is_commit_msg_valid(commit_msg): - for line in commit_msg.splitlines(): - line = line.strip().lower() - if line.startswith('updated-pdd'): - return True - - return False - - -def main(): - parser = ArgumentParser(description='Check if the Privacy Design Doc (PDD) has been updated') - parser.add_argument('metrics_file', type=str, help='path to the metrics Protobuf file') - parser.add_argument('commit_msg', type=str, help='commit message') - parser.add_argument('commit_files', type=str, nargs='*', help='files changed in the commit') - args = parser.parse_args() - - metrics_file = args.metrics_file - commit_msg = args.commit_msg - commit_files = args.commit_files - - if is_in_aosp(): - return 0 - - if metrics_file not in commit_files: - return 0 - - if is_commit_msg_valid(commit_msg): - return 0 - - print('This commit has changed {metrics_file}.'.format(metrics_file=metrics_file)) - print('If this change added/changed/removed metrics collected from the device,') - print('please update the Wifi Metrics Privacy Design Doc (PDD) at go/wifi-metrics-pdd') - print('and acknowledge you have done so by adding this line to your commit message:') - print() - print('Updated-PDD: TRUE') - print() - print('Otherwise, please explain why the PDD does not need to be updated:') - print() - print('Updated-PDD: Not applicable - reformatted file') - print() - print('Please reach out to the OWNERS for more information about the Wifi Metrics PDD.') - return 1 - - -if __name__ == '__main__': - exit_code = main() - sys.exit(exit_code) diff --git a/service/Android.bp b/service/Android.bp deleted file mode 100644 index 71cf728de..000000000 --- a/service/Android.bp +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (C) 2018 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. -// -java_defaults { - name: "wifi-service-common", - defaults: ["wifi-module-sdk-version-defaults"], - errorprone: { - javacflags: ["-Xep:CheckReturnValue:ERROR"], - }, - product_variables: { - pdk: { - enabled: false, - }, - }, -} - -filegroup { - name: "wifi-service-srcs", - srcs: [ - "java/**/*.java", - "java/**/*.logtags", - ":framework-wifi-service-shared-srcs", - ":net-utils-wifi-service-common-srcs", - ":statslog-wifi-java-gen", - ], -} - -filegroup { - name: "wifi-service-BaseWifiService", - srcs: ["java/com/android/server/wifi/BaseWifiService.java"], - path: "java", -} - -// pre-jarjar version of wifi-service that builds against pre-jarjar version of framework-wifi -java_library { - name: "wifi-service-pre-jarjar", - installable: false, - defaults: ["wifi-service-common"], - srcs: [ ":wifi-service-srcs" ], - // java_api_finder must accompany `srcs` - plugins: ["java_api_finder"], - - sdk_version: "system_server_current", - libs: [ - "error_prone_annotations", - "jsr305", - "framework-annotations-lib", - // load the resources from the resources APK. - "ServiceWifiResources", - // need pre-jarjar symbols so that wifi-service can reference the original class names at - // compile time - "framework-wifi-pre-jarjar", - "framework-statsd.stubs.module_lib", - "framework-tethering.stubs.module_lib", - "unsupportedappusage", - ], - - static_libs: [ - "android.hardware.wifi-V1.0-java", - "android.hardware.wifi-V1.1-java", - "android.hardware.wifi-V1.2-java", - "android.hardware.wifi-V1.3-java", - "android.hardware.wifi-V1.4-java", - "android.hardware.wifi.hostapd-V1.0-java", - "android.hardware.wifi.hostapd-V1.1-java", - "android.hardware.wifi.hostapd-V1.2-java", - "android.hardware.wifi.supplicant-V1.0-java", - "android.hardware.wifi.supplicant-V1.1-java", - "android.hardware.wifi.supplicant-V1.2-java", - "android.hardware.wifi.supplicant-V1.3-java", - "android.hidl.manager-V1.2-java", - "androidx.annotation_annotation", - "bouncycastle-unbundled", - "ksoap2", - // Note: libprotobuf-java-lite uses a few core platform APIs which - // does show up as @hide API usage. But, this can be safely ignored - // since the library uses reflection to ensure that the OS does provide - // the necessary core platform APIs. - "libprotobuf-java-lite", - "libnanohttpd", - "services.net-module-wifi", - "wifi-lite-protos", - "wifi-nano-protos" - ], -} - -// wifi-service static library -// ============================================================ -java_library { - name: "service-wifi", - defaults: ["wifi-service-common"], - installable: true, - static_libs: ["wifi-service-pre-jarjar"], - - // need to include `libs` so that Soong doesn't complain about missing classes after jarjaring - libs: [ - "framework-wifi.impl", - ], - - sdk_version: "system_server_current", - - jarjar_rules: ":wifi-jarjar-rules", - optimize: { - enabled: true, - shrink: true, - proguard_flags_files: ["proguard.flags"], - }, - dex_preopt: { - enabled: false, - app_image: false, - }, - - visibility: [ - "//frameworks/opt/net/wifi/service/apex", - "//frameworks/opt/net/wifi/tests/wifitests/apex", - ], - apex_available: [ - "com.android.wifi", - "test_com.android.wifi", - ], -} - -// Statsd auto-generated code -// ============================================================ -genrule { - name: "statslog-wifi-java-gen", - tools: ["stats-log-api-gen"], - cmd: "$(location stats-log-api-gen) --java $(out) --module wifi " + - " --javaPackage com.android.server.wifi.proto --javaClass WifiStatsLog", - out: ["com/android/server/wifi/proto/WifiStatsLog.java"], -} - -// APK to hold all the wifi overlayable resources. -// ============================================================ -android_app { - name: "ServiceWifiResources", - defaults: ["wifi-service-common"], - resource_dirs: [ - "res", - ], - privileged: true, - sdk_version: "system_current", - export_package_resources: true, - manifest: "AndroidManifest_Resources.xml", - apex_available: [ - "com.android.wifi", - "test_com.android.wifi", - ], - certificate: ":com.android.wifi.resources.certificate", -} - -android_app_certificate { - name: "com.android.wifi.resources.certificate", - certificate: "resources-certs/com.android.wifi.resources" -} - -// Prebuilt for the wifi.rc file. -prebuilt_etc { - name: "wifi.rc", - src: "wifi.rc", - sub_dir: "init" -} diff --git a/service/AndroidManifest_Resources.xml b/service/AndroidManifest_Resources.xml deleted file mode 100644 index 04ba1d38b..000000000 --- a/service/AndroidManifest_Resources.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * Copyright (C) 2019 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. - */ ---> -<!-- Manifest for wifi resources APK --> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.wifi.resources" - coreApp="true" - android:versionCode="1" - android:versionName="R-initial"> - <protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_CLICKED" /> - <application - android:label="@string/wifiResourcesAppLabel" - android:defaultToDeviceProtectedStorage="true" - android:directBootAware="true" - android:usesCleartextTraffic="true"> - <!-- This is only used to identify this app by resolving the action. - The activity is never actually triggered. --> - <activity android:name="android.app.Activity" android:exported="true" android:enabled="true"> - <intent-filter> - <action android:name="com.android.server.wifi.intent.action.SERVICE_WIFI_RESOURCES_APK" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/service/CleanSpec.mk b/service/CleanSpec.mk deleted file mode 100644 index 2b4e16617..000000000 --- a/service/CleanSpec.mk +++ /dev/null @@ -1,61 +0,0 @@ -# -*- mode: makefile -*- -# Copyright (C) 2019 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. -# -# -# If you don't need to do a full clean build but would like to touch -# a file or delete some intermediate files, add a clean step to the end -# of the list. These steps will only be run once, if they haven't been -# run before. -# -# E.g.: -# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) -# $(call add-clean-step, rm -rf $(OUT_DIR)/obj/STATIC_LIBRARIES/libz_intermediates) -# -# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with -# files that are missing or have been moved. -# -# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. -# Use $(OUT_DIR) to refer to the "out" directory. -# -# If you need to re-do something that's already mentioned, just copy -# the command and add it to the bottom of the list. E.g., if a change -# that you made last week required touching a file and a change you -# made today requires touching the same file, just copy the old -# touch step and add it to the end of the list. -# -# ************************************************ -# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST -# ************************************************ -# -# For example: -#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) -#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) -#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) -#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) -#$(call add-clean-step, rm -rf $(OUT_DIR)/obj/SHARED_LIBRARIES/libdvm*) - -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/wifi.rc) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/WifiStack) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/wifi_inprocess.rc) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/InProcessWifiStack) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/wifi-service.jar) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/wifi-service-resources) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libwifi-jni.so) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libwifi-jni.so) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex/com.android.wifi.apex) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/apex/com.android.wifi) -# ************************************************ -# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST -# ************************************************ diff --git a/service/apex/Android.bp b/service/apex/Android.bp deleted file mode 100644 index e23d9cc8f..000000000 --- a/service/apex/Android.bp +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (C) 2019 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. -// - -apex_defaults { - name: "com.android.wifi-defaults", - androidManifest: ":com.android.wifi-androidManifest", - java_libs: [ - "service-wifi", - "framework-wifi", - ], - // from build rule `cacerts_wfa` - prebuilts: [ - "target-cacert-wifi-674b5f5b.0", - "target-cacert-wifi-21125ccd.0", - "target-cacert-wifi-ea93cb5b.0", - ], - key: "com.android.wifi.key", - certificate: ":com.android.wifi.certificate", - apps: [ - "OsuLogin", - "ServiceWifiResources", - ], -} - -filegroup { - name: "com.android.wifi-androidManifest", - srcs: ["AndroidManifest.xml"], -} - -// Mainline wifi apex module. -apex { - name: "com.android.wifi", - defaults: ["com.android.wifi-defaults"], - manifest: "apex_manifest.json", -} - -apex_key { - name: "com.android.wifi.key", - public_key: "com.android.wifi.avbpubkey", - private_key: "com.android.wifi.pem", -} - -android_app_certificate { - name: "com.android.wifi.certificate", - certificate: "com.android.wifi", -} diff --git a/service/apex/AndroidManifest.xml b/service/apex/AndroidManifest.xml deleted file mode 100644 index 31d2514d8..000000000 --- a/service/apex/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2019 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. - --> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.wifi"> - <!-- APEX does not have classes.dex --> - <application android:hasCode="false" /> - <!-- TODO: Uncomment this when the R API level is fixed. b/148281152 --> - <!-- Setting maxSdk to lock the module to R. minSdk is auto-set by build system --> - <!--uses-sdk android:maxSdkVersion="30" android:targetSdkVersion="30"/> - --> -</manifest> - diff --git a/service/apex/apex_manifest.json b/service/apex/apex_manifest.json deleted file mode 100644 index 30e46b4aa..000000000 --- a/service/apex/apex_manifest.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "com.android.wifi", - "version": 300000000 -} - diff --git a/service/apex/com.android.wifi.avbpubkey b/service/apex/com.android.wifi.avbpubkey Binary files differdeleted file mode 100644 index e98ee34db..000000000 --- a/service/apex/com.android.wifi.avbpubkey +++ /dev/null diff --git a/service/apex/com.android.wifi.pem b/service/apex/com.android.wifi.pem deleted file mode 100644 index 3d080f1e7..000000000 --- a/service/apex/com.android.wifi.pem +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKQIBAAKCAgEAzIaI6k0LMCiFu60Bh8vO4CSjbDbZvk9V7Nkguu7G4KL2nQel -9M+zph5lmvqMguAoWbLfwIOOlrOMb2BDO65HtuCZO8gBvoHRPI1DWTJViLjpyW0F -0vHRZGe8nQfEhhL7RSVO1A/hJkyMPVEc/IOXIssiW8VIaT27li5pTF/u9zkihwtc -tWKgC5Tc+qrfGvtjF+1mNtbf3AOR+8/a0UnYmmw7OJkH8g9qio1EBKM3YNBl04Df -pF1tkspo30sY5sxKOz4sihq/fXDaIm9N8CoESXUuicPZ5Ko2uh9q9pHK8jDpNxyJ -vUbWO7CSupvtonWVd0rD/CuaBHt8vMDHbnXsrUJRQEZzyYDZmQKrxQz0l/+5+Xn9 -x6/qE5EHt9ektg+nlFpcclCvro8ir6K7GtUJSMhdYfIyP9t/yb6A2b0O5ja48XFN -mFfosHHOSJ9IB2n2cQ+N+Gb03kJge4cO34c3Pl7ohIc5ZYErMHknF5Ode9b2gv5R -gnHnWV/LEmTxW/PyTtgZYPfuFKU0bhC9xsdRzFdU+fEYREGGRR8O7gY7A62s4JR0 -ment24/SMrND5lzK44e/u6R6lwI0ajZFlaKFPIBtZNXThSke0jgkpld7dBX5uFQX -8VV7cNdZxbzEZZRfAr2KRDWZQ2fNpdMMHUI4mvbn7H6q7QvSg7zkvENnLl8CAwEA -AQKCAgBrXEvOwjaXRw48YCqngALOgi0PBxPx5G90bt3Rgrn+/Ux7TaJ+CfGBx/8K -BW9w2/4SZ+Uwh154GTQk2uEwGOIoS2nkia7ws/CD2pt53QQtSvPd+k7OVoXWMOY/ -f+5XeutPdrAUfWlw00nifgu7OdBCQWN9zOef5vnrcd1wbANi3ykSvpIh3O2qZrBB -HSUUYtW3n7TCILVOJsmg55Ezv5HmLd5AbYRQOmtw44rK7GqLdZmeFs5O14RHQ90d -KayeqqpkwtRagoP2cyDuZoMBCO1LKioNwzND513nAcsCN7HSxH4HogFjzCV1G9FK -B8QMPbEB98s9Oh4VMEVgR8noYBqmPwU8eius7IE6vQnbcqMh2zYwUIq0SKL1j6Nu -+6M3Sc5DVcKQcgZyhv1OdTNIJaFAQjzWdFH+8EuIGEH0+ebxFT2lcITM5OYP0NSl -jxlYVaROv6lEOGW6cltS7fYJFhYvZvgD6aUBUAKktg8tfQoN5lQMggc4Fee0QzSa -h/Kqum2VMla5yaFXxae/0fGiUQYX+6UEfwKpx2WN6As70olroefhoTJPe9ihC6pH -68/Cwiwl9N1n3yTv86eq9y/aOMU9Ogfbx4fBVJEA9Zh/m+PMqKtEUHCJkBAY0uDR -6uXlLV4FJI3UScjDS6UewD19gwYxK+ODxYNbvEQYYykgo7CAUQKCAQEA/DXlngtF -uDQpuGXvNaIyvdkXWMfRVSul1Iyg4JQ9oQsM2zeh7RpIFYaX07ES8qH+sNUd6MmE -i0C9q356FhNDqSeiCWGhLJvuXQJyCwl7zMv3jaDQr0kouG/j2U/hK2OWxSw9LeUq -+q8kwZykOdX0N/9KEEslfRVS2wBxwW7RLbQcB5+1Hi5eRE50ioPA3JHs7LeypOiM -Ox/pLeaLMU1iC8ueERq1AU2q84IvVSSfRMvohUUVzr4t8lIZfL8/V2BSKQ/fK9CD -cwDu+9BnNn8J3nPeRpWIc4O7ABAMUxBymUdUZjhT+Q9PMwNpP+cI8Fywox32iSLc -JfK2ZRcb8krEFQKCAQEAz5k44NAqbP8YPQH7EwcOCo78ipa1qeGzFf5pUaACOY6x -0sV1QcNavJV1mMNqoBcG6h3VVFdHlQvVFWt/OEjt36+P3MPnvORGcVWbG+yxod02 -/wvjnbNWd21gK8RUKE7Iy6v5tSY/k/Qwj8ofcIYZBgt086cRPScUaZvltLhxWKh+ -oNIp73v8KCOBHAMDnsEsx4zkNRRfh/XGiTjoMt/dDLpBW+1J9k1gAqMfQegaS/1u -hdrUiIC41Go8X5yAhsTYubQCAAIjF1vdBmmcAoZzBigvx7t0por8BXE/SUoaCfdp -Q/cSg7sLYDM/QipZiT2H0Sv/JikHmVU85UDlO7dBowKCAQEA3ftKGCpvuMsglU4S -lrAl3PbAF8H3OvFpyYPk7QVMoPuq2x9CBAAHxfpqk0XdGXT/SACrjIIhiLb4uYJe -TiOyf6WEdqFZTHwJ9g769T/pmL1FK4CJbF4F2x+P+WrXEmta/jwLtONpSq7wuP/3 -g3gOtWKae3DIlCk6fcsMVGYG8iT+Lq+gp+nDyncLGAcSrpA5abfdIkwTcM6LW3z4 -sfIcA6m5e/B3s6f6eMzygAv1qoWWKAZARXEZ25frGuLxCySZ684ubM/fgk8mCLjK -vypdM0/kKVffe1xMMKfvUQS++K3RWQ7myeVxncK41iewtG3AgjETFmx6O2Q+qQcH -799iaQKCAQBxXf42ntccUK4e2s8OlAKx92WoFSc9j1hqAVXoUlYEso0fSd9/uzv4 -0jG267h1lj2bahFOjp8zoJOLr/l4djMYvVn1uDH78DkbuSEMPdS/TPu0ifyR6Ral -/1/OZteCb4ut1ct2hl2f4XEHhNxoaYKOz4DdcfWzDH1UMuNdLoAPZ2xHTJ3D/1Qz -YzglYOwALQPUMXeKGQcWSzxRQXdkGOYxBiGdHtcOHzD4H7Z5GlQJ/Wr2xAreRFUr -ApzXpbJ2ZlboCooxEPmyzuLDlrawllWIHjgBfbf1Ht8D5dUmo8XWfXrJt8ovj9xl -e3bnHhNpI+Xgb4NVhoB01px7oVXNp4S7AoIBAQDU5VsyDmdL1a8hVLL0rLzAjBh/ -RSK2IGqibfOITLcmvCn46JOVmytc2F+odjrsAvHUmU+yQNgMpmDNch292TXR2aJq -kqxV1HsNJ/Pb9wFHb8xP29MgMeLMhfo35EPUdYVtsHTzH+5cbDT50PpOnXff6+h0 -fhrMElXYu4wg6ZPZ4BYt/PY+qhiRZ47MtAqw3byaCe2+sLNSpU/tt+klIYuWvTyV -pE/suflS3/JnJCzs8MrP0mX73AoILauqGEsc8+hsf5X2Rra2sllV4YfiGKSUoISq -u9wRjoGkB8SSg1GywotyXFJc3dQoLtMCk0ABBQCM9zp+xjdB9AeWS4tjSBO3 ------END RSA PRIVATE KEY----- diff --git a/service/apex/com.android.wifi.pk8 b/service/apex/com.android.wifi.pk8 Binary files differdeleted file mode 100644 index a47b169eb..000000000 --- a/service/apex/com.android.wifi.pk8 +++ /dev/null diff --git a/service/apex/com.android.wifi.x509.pem b/service/apex/com.android.wifi.x509.pem deleted file mode 100644 index fbc798dfc..000000000 --- a/service/apex/com.android.wifi.x509.pem +++ /dev/null @@ -1,35 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGJzCCBA+gAwIBAgIUYfh1Zzu3M79bdOVvnEraqzmHwFAwDQYJKoZIhvcNAQEL -BQAwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH -DA1Nb3VudGFpbiBWaWV3MQ8wDQYDVQQKDAZHb29nbGUxEDAOBgNVBAsMB0FuZHJv -aWQxFTATBgNVBAMMDGFuZHJvaWQtd2lmaTErMCkGCSqGSIb3DQEJARYcYW5kcm9p -ZC13aWZpLXRlYW1AZ29vZ2xlLmNvbTAgFw0xOTExMjExNzIwMzZaGA80NzU3MTAx -NzE3MjAzNlowgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYw -FAYDVQQHDA1Nb3VudGFpbiBWaWV3MQ8wDQYDVQQKDAZHb29nbGUxEDAOBgNVBAsM -B0FuZHJvaWQxFTATBgNVBAMMDGFuZHJvaWQtd2lmaTErMCkGCSqGSIb3DQEJARYc -YW5kcm9pZC13aWZpLXRlYW1AZ29vZ2xlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAKZmFJJiKPBqWfJ1jt0T1WEQ/6PzDOxF8smQql8TDeO2hbNK -v75hrZ668RkyQfx5kejU0sY3lG7xj7TouYUlRJys0FqfyVbhUCDC4+gOvX/U5i9F -VhOS4PLPTEQ7k8/siDkCp412uYkOTbK4TGTL/21vD0aLJKqf/ofSbDS8HWfmhEVJ -vMIL+bOGdGTQ+wbDp3Pus1zob+yRPE66iQQ7ZKFCVcX0+hSWjzf7nS2Fmf0E952c -A2KnI0CpSxWogS4YLSbvZPDueo+kwfdHsQkl3H8VNUTbKNwAdVCeemrtkqFjy/s7 -c8Igm4gAPyyh9PDAzw+Qgquy+11NMiln06oKAAZpz26V7ylMkAqR2OMACZqkLRP7 -lWX+qp79NVcXtaz/RJi8/UKSCo5jAlsUoDgz8ddozUXswK1lvlN7BS9wQ4XS5JXY -IxGjz2ipaWI+cjD+rctaS1d2stujL1Iu93eAgFv0uzCbm8jI1XT/qWhZir0f5KcH -ihqiMPiY2psob4tA4zdccOTYw545XA/sT7kS2DuTlRXQv7y2Yt62EOsxpAhGEWKr -Rw+aBuk8Vs/6xST5WfqU0H8syaVqWNlevLC8ltLIF1MJpBC8FXKS1L2QNMGVTDyh -UDrxnVCRU0gsr7fE39cNTFyobh9Uq3qXAkAbA50zgo2vuEp5htdy1s4QaJKJAgMB -AAGjUzBRMB0GA1UdDgQWBBS4m2DrPxP8E3qgWUFlFe/25emNFDAfBgNVHSMEGDAW -gBS4m2DrPxP8E3qgWUFlFe/25emNFDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 -DQEBCwUAA4ICAQBxlQ16HQXTVMPPOmuDlfSZOoWdYyK8cCxVEsuco1uN0pMd5ekl -EoTE6GrcjBI1LIoI9n3s/3lnYZrdgQ/kIXNHHutizONz6jgT8m4m3w8BqC9QOXKQ -d7qElOesp4ruJZoAGuQOoDuNg544ypQZGhBwFQi3RPvk/W1U2ZrXNYO1ONHNFE1/ -ZXotGkNxhB9E+eVYo16MKpyxEpT5vE+k0LK/VRFDGrZF2p2C7DXmMOE66lY3iyRP -ynKVbzoI0dyyVl/BZ/9dGCCgvhJWo3oUfwRLxqwOt81DOiDUT2DV2XB2TEPFLTwQ -gwlw5Lkmd7ecj7J0E4QIkAPsQYLI/fVelC6QUeqvbKORur4vvkVdhOj2GBpb/6tQ -F5i8osLk1kqBwMpnDZCGKSS22JqY7lBPmlkCPCfRd3uVmK42ItAUpYcdLk7lb90o -wO5OgpOPajl6ImYe8kpqoeLBUK4E6qrve3MLMukhCSwR8hrteAEL86R631P6A747 -mkZUgbKPqkeUSFd+0AfzLTjvaevgfIEF/wz5HDHGAloWkd45m5Tdd5I06fqPVu/2 -rxzqZChKW2XHtwaTl5qkYUHi6pqkq+oWhpjWCS84wCNmlX8j4lrZ5mumoOaPpElK -Tbj1WZ16OOPDXWONclE29gfC/+XaOKLLhjdfh0+ZEJ7BZSCBCMyQWXxbcQ== ------END CERTIFICATE----- diff --git a/service/java/com/android/server/wifi/ActiveModeManager.java b/service/java/com/android/server/wifi/ActiveModeManager.java deleted file mode 100644 index 0983e9b93..000000000 --- a/service/java/com/android/server/wifi/ActiveModeManager.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.annotation.IntDef; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Arrays; -import java.util.List; - -/** - * Base class for available WiFi operating modes. - * - * Currently supported modes include Client, ScanOnly and SoftAp. - */ -public interface ActiveModeManager { - /** - * Listener for ActiveModeManager state changes. - */ - interface Listener { - /** - * Invoked when mode manager completes start or on mode switch. - */ - void onStarted(); - /** - * Invoked when mode manager completes stop. - */ - void onStopped(); - /** - * Invoked when mode manager encountered a failure on start or on mode switch. - */ - void onStartFailure(); - } - - /** - * Method used to start the Manager for a given Wifi operational mode. - */ - void start(); - - /** - * Method used to stop the Manager for a given Wifi operational mode. - */ - void stop(); - - /** - * Method used to indicate if the mode manager is still stopping. - */ - boolean isStopping(); - - /** Roles assigned to each mode manager. */ - int ROLE_UNSPECIFIED = -1; - // SoftApManager - Tethering, will respond to public APIs. - int ROLE_SOFTAP_TETHERED = 0; - // SoftApManager - Local only hotspot. - int ROLE_SOFTAP_LOCAL_ONLY = 1; - // ClientModeManager, primary STA, will respond to public APIs - int ROLE_CLIENT_PRIMARY = 2; - // ClientModeManager, secondary STA, can switch to primary later. - int ROLE_CLIENT_SECONDARY = 3; - // ClientModeManager, secondary STA created for local connection (no internet connectivity). - int ROLE_CLIENT_LOCAL_ONLY = 4; - // ClientModeManager, STA created for scans only. - int ROLE_CLIENT_SCAN_ONLY = 5; - - @IntDef(prefix = { "ROLE_" }, value = { - ROLE_SOFTAP_TETHERED, - ROLE_SOFTAP_LOCAL_ONLY, - ROLE_CLIENT_PRIMARY, - ROLE_CLIENT_SECONDARY, - ROLE_CLIENT_LOCAL_ONLY, - ROLE_CLIENT_SCAN_ONLY - }) - @Retention(RetentionPolicy.SOURCE) - @interface Role{} - - /** List of Client roles */ - List<Integer> CLIENT_ROLES = Arrays.asList( - ROLE_CLIENT_PRIMARY, - ROLE_CLIENT_SECONDARY, - ROLE_CLIENT_LOCAL_ONLY, - ROLE_CLIENT_SCAN_ONLY); - /** List of Client roles that could initiate a wifi connection */ - List<Integer> CLIENT_CONNECTIVITY_ROLES = Arrays.asList( - ROLE_CLIENT_PRIMARY, - ROLE_CLIENT_SECONDARY, - ROLE_CLIENT_LOCAL_ONLY); - /** List of Client roles that could initiate a wifi connection for internet connectivity */ - List<Integer> CLIENT_INTERNET_CONNECTIVITY_ROLES = Arrays.asList( - ROLE_CLIENT_PRIMARY, - ROLE_CLIENT_SECONDARY); - /** List of SoftAp roles */ - List<Integer> SOFTAP_ROLES = Arrays.asList( - ROLE_SOFTAP_LOCAL_ONLY, - ROLE_SOFTAP_TETHERED); - - /** - * Method to get the role for a mode manager. - */ - @Role int getRole(); - - /** - * Method to set the role for a mode manager. - */ - void setRole(@Role int role); - - /** - * Method to dump for logging state. - */ - void dump(FileDescriptor fd, PrintWriter pw, String[] args); -} diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java deleted file mode 100644 index cf54e328b..000000000 --- a/service/java/com/android/server/wifi/ActiveModeWarden.java +++ /dev/null @@ -1,969 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; - -import android.annotation.NonNull; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.location.LocationManager; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiManager; -import android.os.BatteryStatsManager; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.ArraySet; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IState; -import com.android.internal.util.Preconditions; -import com.android.internal.util.Protocol; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.List; - -/** - * This class provides the implementation for different WiFi operating modes. - */ -public class ActiveModeWarden { - private static final String TAG = "WifiActiveModeWarden"; - private static final String STATE_MACHINE_EXITED_STATE_NAME = "STATE_MACHINE_EXITED"; - - // Holder for active mode managers - private final ArraySet<ActiveModeManager> mActiveModeManagers; - // DefaultModeManager used to service API calls when there are not active mode managers. - private final DefaultModeManager mDefaultModeManager; - - private final WifiInjector mWifiInjector; - private final Looper mLooper; - private final Handler mHandler; - private final Context mContext; - private final ClientModeImpl mClientModeImpl; - private final WifiSettingsStore mSettingsStore; - private final FrameworkFacade mFacade; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final BatteryStatsManager mBatteryStatsManager; - private final ScanRequestProxy mScanRequestProxy; - private final WifiNative mWifiNative; - private final WifiController mWifiController; - - private WifiManager.SoftApCallback mSoftApCallback; - private WifiManager.SoftApCallback mLohsCallback; - - private boolean mCanRequestMoreClientModeManagers = false; - private boolean mCanRequestMoreSoftApManagers = false; - private boolean mIsShuttingdown = false; - - /** - * Called from WifiServiceImpl to register a callback for notifications from SoftApManager - */ - public void registerSoftApCallback(@NonNull WifiManager.SoftApCallback callback) { - mSoftApCallback = callback; - } - - /** - * Called from WifiServiceImpl to register a callback for notifications from SoftApManager - * for local-only hotspot. - */ - public void registerLohsCallback(@NonNull WifiManager.SoftApCallback callback) { - mLohsCallback = callback; - } - - ActiveModeWarden(WifiInjector wifiInjector, - Looper looper, - WifiNative wifiNative, - DefaultModeManager defaultModeManager, - BatteryStatsManager batteryStatsManager, - BaseWifiDiagnostics wifiDiagnostics, - Context context, - ClientModeImpl clientModeImpl, - WifiSettingsStore settingsStore, - FrameworkFacade facade, - WifiPermissionsUtil wifiPermissionsUtil) { - mWifiInjector = wifiInjector; - mLooper = looper; - mHandler = new Handler(looper); - mContext = context; - mClientModeImpl = clientModeImpl; - mSettingsStore = settingsStore; - mFacade = facade; - mWifiPermissionsUtil = wifiPermissionsUtil; - mActiveModeManagers = new ArraySet<>(); - mDefaultModeManager = defaultModeManager; - mBatteryStatsManager = batteryStatsManager; - mScanRequestProxy = wifiInjector.getScanRequestProxy(); - mWifiNative = wifiNative; - mWifiController = new WifiController(); - - wifiNative.registerStatusListener(isReady -> { - if (!isReady && !mIsShuttingdown) { - mHandler.post(() -> { - Log.e(TAG, "One of the native daemons died. Triggering recovery"); - wifiDiagnostics.captureBugReportData( - WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); - - // immediately trigger SelfRecovery if we receive a notice about an - // underlying daemon failure - // Note: SelfRecovery has a circular dependency with ActiveModeWarden and is - // instantiated after ActiveModeWarden, so use WifiInjector to get the instance - // instead of directly passing in SelfRecovery in the constructor. - mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - }); - } - }); - - wifiNative.registerClientInterfaceAvailabilityListener( - (isAvailable) -> mHandler.post(() -> { - mCanRequestMoreClientModeManagers = isAvailable; - })); - wifiNative.registerSoftApInterfaceAvailabilityListener( - (isAvailable) -> mHandler.post(() -> { - mCanRequestMoreSoftApManagers = isAvailable; - })); - } - - /** - * Notify that device is shutting down - * Keep it simple and don't add collection access codes - * to avoid concurrentModificationException when it is directly called from a different thread - */ - public void notifyShuttingDown() { - mIsShuttingdown = true; - } - - /** - * @return Returns whether we can create more client mode managers or not. - */ - public boolean canRequestMoreClientModeManagers() { - return mCanRequestMoreClientModeManagers; - } - - /** - * @return Returns whether we can create more SoftAp managers or not. - */ - public boolean canRequestMoreSoftApManagers() { - return mCanRequestMoreSoftApManagers; - } - - /** - * @return Returns whether the device can support at least one concurrent client mode manager & - * softap manager. - */ - public boolean isStaApConcurrencySupported() { - return mWifiNative.isStaApConcurrencySupported(); - } - - /** Begin listening to broadcasts and start the internal state machine. */ - public void start() { - mWifiController.start(); - } - - /** Disable Wifi for recovery purposes. */ - public void recoveryDisableWifi() { - mWifiController.sendMessage(WifiController.CMD_RECOVERY_DISABLE_WIFI); - } - - /** - * Restart Wifi for recovery purposes. - * @param reason One of {@link SelfRecovery.RecoveryReason} - */ - public void recoveryRestartWifi(@SelfRecovery.RecoveryReason int reason) { - mWifiController.sendMessage(WifiController.CMD_RECOVERY_RESTART_WIFI, reason); - } - - /** Wifi has been toggled. */ - public void wifiToggled() { - mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED); - } - - /** Airplane Mode has been toggled. */ - public void airplaneModeToggled() { - mWifiController.sendMessage(WifiController.CMD_AIRPLANE_TOGGLED); - } - - /** Starts SoftAp. */ - public void startSoftAp(SoftApModeConfiguration softApConfig) { - mWifiController.sendMessage(WifiController.CMD_SET_AP, 1, 0, softApConfig); - } - - /** Stop SoftAp. */ - public void stopSoftAp(int mode) { - mWifiController.sendMessage(WifiController.CMD_SET_AP, 0, mode); - } - - /** Update SoftAp Capability. */ - public void updateSoftApCapability(SoftApCapability capability) { - mWifiController.sendMessage(WifiController.CMD_UPDATE_AP_CAPABILITY, capability); - } - - /** Update SoftAp Configuration. */ - public void updateSoftApConfiguration(SoftApConfiguration config) { - mWifiController.sendMessage(WifiController.CMD_UPDATE_AP_CONFIG, config); - } - - /** Emergency Callback Mode has changed. */ - public void emergencyCallbackModeChanged(boolean isInEmergencyCallbackMode) { - mWifiController.sendMessage( - WifiController.CMD_EMERGENCY_MODE_CHANGED, isInEmergencyCallbackMode ? 1 : 0); - } - - /** Emergency Call state has changed. */ - public void emergencyCallStateChanged(boolean isInEmergencyCall) { - mWifiController.sendMessage( - WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED, isInEmergencyCall ? 1 : 0); - } - - /** Scan always mode has changed. */ - public void scanAlwaysModeChanged() { - mWifiController.sendMessage(WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED); - } - - private boolean hasAnyModeManager() { - return !mActiveModeManagers.isEmpty(); - } - - /** - * @return true if any mode managers in specified role. - */ - private boolean hasAnyModeManagerInRole(@ActiveModeManager.Role int role) { - for (ActiveModeManager manager : mActiveModeManagers) { - if (manager.getRole() == role) return true; - } - return false; - } - - /** - * @return true if any mode managers in one of the specified roles. - */ - private boolean hasAnyModeManagerInOneOfRoles(List<Integer> rolesList) { - for (ActiveModeManager manager : mActiveModeManagers) { - if (rolesList.contains(manager.getRole())) return true; - } - return false; - } - - private boolean hasAnyClientModeManager() { - return hasAnyModeManagerInOneOfRoles(ActiveModeManager.CLIENT_ROLES); - } - - private boolean hasAnyClientModeManagerInConnectivityRole() { - return hasAnyModeManagerInOneOfRoles(ActiveModeManager.CLIENT_CONNECTIVITY_ROLES); - } - - private boolean hasAnySoftApManager() { - return hasAnyModeManagerInOneOfRoles(ActiveModeManager.SOFTAP_ROLES); - } - - /** - * @return true if any mode manager is stopping - */ - private boolean hasAnyModeManagerStopping() { - for (ActiveModeManager manager : mActiveModeManagers) { - if (manager.isStopping()) return true; - } - return false; - } - - /** - * @return true if all the client mode managers are in scan only role, - * false if there are no client mode managers present or if any of them are not in scan only - * role. - */ - private boolean areAllClientModeManagersInScanOnlyRole() { - boolean hasAnyClientModeManager = false; - for (ActiveModeManager manager : mActiveModeManagers) { - if (ActiveModeManager.CLIENT_ROLES.contains(manager.getRole())) { - hasAnyClientModeManager = true; - if (manager.getRole() != ActiveModeManager.ROLE_CLIENT_SCAN_ONLY) return false; - } - } - return hasAnyClientModeManager; - } - - private @ActiveModeManager.Role int getRoleForSoftApIpMode(int ipMode) { - return ipMode == IFACE_IP_MODE_TETHERED - ? ActiveModeManager.ROLE_SOFTAP_TETHERED : ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY; - } - - /** - * Method to enable soft ap for wifi hotspot. - * - * The supplied SoftApModeConfiguration includes the target softap WifiConfiguration (or null if - * the persisted config is to be used) and the target operating mode (ex, - * {@link WifiManager#IFACE_IP_MODE_TETHERED} {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}). - * - * @param softApConfig SoftApModeConfiguration for the hostapd softap - */ - private void startSoftApModeManager(@NonNull SoftApModeConfiguration softApConfig) { - Log.d(TAG, "Starting SoftApModeManager config = " - + softApConfig.getSoftApConfiguration()); - Preconditions.checkState(softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY - || softApConfig.getTargetMode() == IFACE_IP_MODE_TETHERED); - - WifiManager.SoftApCallback callback = - softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY - ? mLohsCallback : mSoftApCallback; - SoftApListener listener = new SoftApListener(); - ActiveModeManager manager = - mWifiInjector.makeSoftApManager(listener, callback, softApConfig); - listener.setActiveModeManager(manager); - manager.start(); - manager.setRole(getRoleForSoftApIpMode(softApConfig.getTargetMode())); - mActiveModeManagers.add(manager); - } - - /** - * Method to stop all soft ap for the specified mode. - * - * This method will stop any active softAp mode managers. - * - * @param ipMode the operating mode of APs to bring down (ex, - * {@link WifiManager#IFACE_IP_MODE_TETHERED} or - * {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}). - * Use {@link WifiManager#IFACE_IP_MODE_UNSPECIFIED} to stop all APs. - */ - private void stopSoftApModeManagers(int ipMode) { - Log.d(TAG, "Shutting down all softap mode managers in mode " + ipMode); - for (ActiveModeManager manager : mActiveModeManagers) { - if (!(manager instanceof SoftApManager)) continue; - SoftApManager softApManager = (SoftApManager) manager; - - if (ipMode == WifiManager.IFACE_IP_MODE_UNSPECIFIED - || getRoleForSoftApIpMode(ipMode) == softApManager.getRole()) { - softApManager.stop(); - } - } - } - - private void updateCapabilityToSoftApModeManager(SoftApCapability capability) { - for (ActiveModeManager manager : mActiveModeManagers) { - if (!(manager instanceof SoftApManager)) continue; - SoftApManager softApManager = (SoftApManager) manager; - softApManager.updateCapability(capability); - } - } - - private void updateConfigurationToSoftApModeManager(SoftApConfiguration config) { - for (ActiveModeManager manager : mActiveModeManagers) { - if (!(manager instanceof SoftApManager)) continue; - SoftApManager softApManager = (SoftApManager) manager; - softApManager.updateConfiguration(config); - } - } - - /** - * Method to enable a new client mode manager. - */ - private boolean startClientModeManager() { - Log.d(TAG, "Starting ClientModeManager"); - ClientListener listener = new ClientListener(); - ClientModeManager manager = mWifiInjector.makeClientModeManager(listener); - listener.setActiveModeManager(manager); - manager.start(); - if (!switchClientModeManagerRole(manager)) { - return false; - } - mActiveModeManagers.add(manager); - return true; - } - - /** - * Method to stop all client mode mangers. - */ - private void stopAllClientModeManagers() { - Log.d(TAG, "Shutting down all client mode managers"); - for (ActiveModeManager manager : mActiveModeManagers) { - if (!(manager instanceof ClientModeManager)) continue; - ClientModeManager clientModeManager = (ClientModeManager) manager; - clientModeManager.stop(); - } - } - - /** - * Method to switch all client mode manager mode of operation (from ScanOnly To Connect & - * vice-versa) based on the toggle state. - */ - private boolean switchAllClientModeManagers() { - Log.d(TAG, "Switching all client mode managers"); - for (ActiveModeManager manager : mActiveModeManagers) { - if (!(manager instanceof ClientModeManager)) continue; - ClientModeManager clientModeManager = (ClientModeManager) manager; - if (!switchClientModeManagerRole(clientModeManager)) { - return false; - } - } - updateBatteryStats(); - return true; - } - - /** - * Method to switch a client mode manager mode of operation (from ScanOnly To Connect & - * vice-versa) based on the toggle state. - */ - private boolean switchClientModeManagerRole(@NonNull ClientModeManager modeManager) { - if (mSettingsStore.isWifiToggleEnabled()) { - modeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - } else if (checkScanOnlyModeAvailable()) { - modeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - } else { - Log.e(TAG, "Something is wrong, no client mode toggles enabled"); - return false; - } - return true; - } - - /** - * Method to stop all active modes, for example, when toggling airplane mode. - */ - private void shutdownWifi() { - Log.d(TAG, "Shutting down all mode managers"); - for (ActiveModeManager manager : mActiveModeManagers) { - manager.stop(); - } - } - - /** - * Dump current state for active mode managers. - * - * Must be called from the main Wifi thread. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of " + TAG); - pw.println("Current wifi mode: " + getCurrentMode()); - pw.println("NumActiveModeManagers: " + mActiveModeManagers.size()); - mWifiController.dump(fd, pw, args); - for (ActiveModeManager manager : mActiveModeManagers) { - manager.dump(fd, pw, args); - } - } - - @VisibleForTesting - String getCurrentMode() { - IState state = mWifiController.getCurrentState(); - return state == null ? STATE_MACHINE_EXITED_STATE_NAME : state.getName(); - } - - @VisibleForTesting - Collection<ActiveModeManager> getActiveModeManagers() { - return new ArraySet<>(mActiveModeManagers); - } - - @VisibleForTesting - boolean isInEmergencyMode() { - IState state = mWifiController.getCurrentState(); - return ((WifiController.BaseState) state).isInEmergencyMode(); - } - - /** - * Helper class to wrap the ActiveModeManager callback objects. - */ - private static class ModeCallback { - private ActiveModeManager mActiveManager; - - void setActiveModeManager(ActiveModeManager manager) { - mActiveManager = manager; - } - - ActiveModeManager getActiveModeManager() { - return mActiveManager; - } - } - - private void updateBatteryStats() { - updateBatteryStatsWifiState(hasAnyModeManager()); - if (areAllClientModeManagersInScanOnlyRole()) { - updateBatteryStatsScanModeActive(); - } - } - - private class SoftApListener extends ModeCallback implements ActiveModeManager.Listener { - @Override - public void onStarted() { - updateBatteryStats(); - } - - @Override - public void onStopped() { - mActiveModeManagers.remove(getActiveModeManager()); - updateBatteryStats(); - mWifiController.sendMessage(WifiController.CMD_AP_STOPPED); - } - - @Override - public void onStartFailure() { - mActiveModeManagers.remove(getActiveModeManager()); - updateBatteryStats(); - mWifiController.sendMessage(WifiController.CMD_AP_START_FAILURE); - } - } - - private class ClientListener extends ModeCallback implements ActiveModeManager.Listener { - @Override - public void onStarted() { - updateClientScanMode(); - updateBatteryStats(); - } - - @Override - public void onStopped() { - mActiveModeManagers.remove(getActiveModeManager()); - updateClientScanMode(); - updateBatteryStats(); - mWifiController.sendMessage(WifiController.CMD_STA_STOPPED); - } - - @Override - public void onStartFailure() { - mActiveModeManagers.remove(getActiveModeManager()); - updateClientScanMode(); - updateBatteryStats(); - mWifiController.sendMessage(WifiController.CMD_STA_START_FAILURE); - } - } - - // Update the scan state based on all active mode managers. - private void updateClientScanMode() { - boolean scanEnabled = hasAnyClientModeManager(); - boolean scanningForHiddenNetworksEnabled; - - if (mContext.getResources().getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) { - scanningForHiddenNetworksEnabled = hasAnyClientModeManager(); - } else { - scanningForHiddenNetworksEnabled = hasAnyClientModeManagerInConnectivityRole(); - } - mScanRequestProxy.enableScanning(scanEnabled, scanningForHiddenNetworksEnabled); - } - - /** - * Helper method to report wifi state as on/off (doesn't matter which mode). - * - * @param enabled boolean indicating that some mode has been turned on or off - */ - private void updateBatteryStatsWifiState(boolean enabled) { - if (enabled) { - if (mActiveModeManagers.size() == 1) { - // only report wifi on if we haven't already - mBatteryStatsManager.reportWifiOn(); - } - } else { - if (mActiveModeManagers.size() == 0) { - // only report if we don't have any active modes - mBatteryStatsManager.reportWifiOff(); - } - } - } - - private void updateBatteryStatsScanModeActive() { - mBatteryStatsManager.reportWifiState(BatteryStatsManager.WIFI_STATE_OFF_SCANNING, null); - } - - private boolean checkScanOnlyModeAvailable() { - return mWifiPermissionsUtil.isLocationModeEnabled() - && mSettingsStore.isScanAlwaysAvailable(); - } - - /** - * WifiController is the class used to manage wifi state for various operating - * modes (normal, airplane, wifi hotspot, etc.). - */ - private class WifiController extends StateMachine { - private static final String TAG = "WifiController"; - - // Maximum limit to use for timeout delay if the value from overlay setting is too large. - private static final int MAX_RECOVERY_TIMEOUT_DELAY_MS = 4000; - - private static final int BASE = Protocol.BASE_WIFI_CONTROLLER; - - static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1; - static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7; - static final int CMD_WIFI_TOGGLED = BASE + 8; - static final int CMD_AIRPLANE_TOGGLED = BASE + 9; - static final int CMD_SET_AP = BASE + 10; - static final int CMD_EMERGENCY_CALL_STATE_CHANGED = BASE + 14; - static final int CMD_AP_STOPPED = BASE + 15; - static final int CMD_STA_START_FAILURE = BASE + 16; - // Command used to trigger a wifi stack restart when in active mode - static final int CMD_RECOVERY_RESTART_WIFI = BASE + 17; - // Internal command used to complete wifi stack restart - private static final int CMD_RECOVERY_RESTART_WIFI_CONTINUE = BASE + 18; - // Command to disable wifi when SelfRecovery is throttled or otherwise not doing full - // recovery - static final int CMD_RECOVERY_DISABLE_WIFI = BASE + 19; - static final int CMD_STA_STOPPED = BASE + 20; - static final int CMD_DEFERRED_RECOVERY_RESTART_WIFI = BASE + 22; - static final int CMD_AP_START_FAILURE = BASE + 23; - static final int CMD_UPDATE_AP_CAPABILITY = BASE + 24; - static final int CMD_UPDATE_AP_CONFIG = BASE + 25; - - private final EnabledState mEnabledState = new EnabledState(); - private final DisabledState mDisabledState = new DisabledState(); - - private boolean mIsInEmergencyCall = false; - private boolean mIsInEmergencyCallbackMode = false; - - WifiController() { - super(TAG, mLooper); - - DefaultState defaultState = new DefaultState(); - addState(defaultState); { - addState(mDisabledState, defaultState); - addState(mEnabledState, defaultState); - } - - setLogRecSize(100); - setLogOnlyTransitions(false); - - } - - @Override - public void start() { - boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn(); - boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled(); - boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable(); - boolean isLocationModeActive = mWifiPermissionsUtil.isLocationModeEnabled(); - - log("isAirplaneModeOn = " + isAirplaneModeOn - + ", isWifiEnabled = " + isWifiEnabled - + ", isScanningAvailable = " + isScanningAlwaysAvailable - + ", isLocationModeActive = " + isLocationModeActive); - - if (shouldEnableSta()) { - startClientModeManager(); - setInitialState(mEnabledState); - } else { - setInitialState(mDisabledState); - } - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - // Location mode has been toggled... trigger with the scan change - // update to make sure we are in the correct mode - scanAlwaysModeChanged(); - } - }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); - super.start(); - } - - private int readWifiRecoveryDelay() { - int recoveryDelayMillis = mContext.getResources().getInteger( - R.integer.config_wifi_framework_recovery_timeout_delay); - if (recoveryDelayMillis > MAX_RECOVERY_TIMEOUT_DELAY_MS) { - recoveryDelayMillis = MAX_RECOVERY_TIMEOUT_DELAY_MS; - Log.w(TAG, "Overriding timeout delay with maximum limit value"); - } - return recoveryDelayMillis; - } - - abstract class BaseState extends State { - @VisibleForTesting - boolean isInEmergencyMode() { - return mIsInEmergencyCall || mIsInEmergencyCallbackMode; - } - - private void updateEmergencyMode(Message msg) { - if (msg.what == CMD_EMERGENCY_CALL_STATE_CHANGED) { - mIsInEmergencyCall = msg.arg1 == 1; - } else if (msg.what == CMD_EMERGENCY_MODE_CHANGED) { - mIsInEmergencyCallbackMode = msg.arg1 == 1; - } - } - - private void enterEmergencyMode() { - stopSoftApModeManagers(WifiManager.IFACE_IP_MODE_UNSPECIFIED); - boolean configWiFiDisableInECBM = mFacade.getConfigWiFiDisableInECBM(mContext); - log("WifiController msg getConfigWiFiDisableInECBM " + configWiFiDisableInECBM); - if (configWiFiDisableInECBM) { - shutdownWifi(); - } - } - - private void exitEmergencyMode() { - if (shouldEnableSta()) { - startClientModeManager(); - transitionTo(mEnabledState); - } else { - transitionTo(mDisabledState); - } - } - - @Override - public final boolean processMessage(Message msg) { - // potentially enter emergency mode - if (msg.what == CMD_EMERGENCY_CALL_STATE_CHANGED - || msg.what == CMD_EMERGENCY_MODE_CHANGED) { - boolean wasInEmergencyMode = isInEmergencyMode(); - updateEmergencyMode(msg); - boolean isInEmergencyMode = isInEmergencyMode(); - if (!wasInEmergencyMode && isInEmergencyMode) { - enterEmergencyMode(); - } else if (wasInEmergencyMode && !isInEmergencyMode) { - exitEmergencyMode(); - } - return HANDLED; - } else if (isInEmergencyMode()) { - // already in emergency mode, drop all messages other than mode stop messages - // triggered by emergency mode start. - if (msg.what == CMD_STA_STOPPED || msg.what == CMD_AP_STOPPED) { - if (!hasAnyModeManager()) { - log("No active mode managers, return to DisabledState."); - transitionTo(mDisabledState); - } - } - return HANDLED; - } - // not in emergency mode, process messages normally - return processMessageFiltered(msg); - } - - protected abstract boolean processMessageFiltered(Message msg); - } - - class DefaultState extends State { - @Override - public boolean processMessage(Message msg) { - switch (msg.what) { - case CMD_SCAN_ALWAYS_MODE_CHANGED: - case CMD_WIFI_TOGGLED: - case CMD_STA_STOPPED: - case CMD_STA_START_FAILURE: - case CMD_AP_STOPPED: - case CMD_AP_START_FAILURE: - case CMD_RECOVERY_RESTART_WIFI: - case CMD_RECOVERY_RESTART_WIFI_CONTINUE: - case CMD_DEFERRED_RECOVERY_RESTART_WIFI: - break; - case CMD_RECOVERY_DISABLE_WIFI: - log("Recovery has been throttled, disable wifi"); - shutdownWifi(); - // onStopped will move the state machine to "DisabledState". - break; - case CMD_AIRPLANE_TOGGLED: - if (mSettingsStore.isAirplaneModeOn()) { - log("Airplane mode toggled, shutdown all modes"); - shutdownWifi(); - // onStopped will move the state machine to "DisabledState". - } else { - log("Airplane mode disabled, determine next state"); - if (shouldEnableSta()) { - startClientModeManager(); - transitionTo(mEnabledState); - } - // wifi should remain disabled, do not need to transition - } - break; - case CMD_UPDATE_AP_CAPABILITY: - updateCapabilityToSoftApModeManager((SoftApCapability) msg.obj); - break; - case CMD_UPDATE_AP_CONFIG: - updateConfigurationToSoftApModeManager((SoftApConfiguration) msg.obj); - break; - default: - throw new RuntimeException("WifiController.handleMessage " + msg.what); - } - return HANDLED; - } - } - - private boolean shouldEnableSta() { - return mSettingsStore.isWifiToggleEnabled() || checkScanOnlyModeAvailable(); - } - - class DisabledState extends BaseState { - @Override - public void enter() { - log("DisabledState.enter()"); - super.enter(); - if (hasAnyModeManager()) { - Log.e(TAG, "Entered DisabledState, but has active mode managers"); - } - } - - @Override - public void exit() { - log("DisabledState.exit()"); - super.exit(); - } - - @Override - public boolean processMessageFiltered(Message msg) { - switch (msg.what) { - case CMD_WIFI_TOGGLED: - case CMD_SCAN_ALWAYS_MODE_CHANGED: - if (shouldEnableSta()) { - startClientModeManager(); - transitionTo(mEnabledState); - } - break; - case CMD_SET_AP: - // note: CMD_SET_AP is handled/dropped in ECM mode - will not start here - if (msg.arg1 == 1) { - startSoftApModeManager((SoftApModeConfiguration) msg.obj); - transitionTo(mEnabledState); - } - break; - case CMD_RECOVERY_RESTART_WIFI: - log("Recovery triggered, already in disabled state"); - // intentional fallthrough - case CMD_DEFERRED_RECOVERY_RESTART_WIFI: - // wait mRecoveryDelayMillis for letting driver clean reset. - sendMessageDelayed(CMD_RECOVERY_RESTART_WIFI_CONTINUE, - readWifiRecoveryDelay()); - break; - case CMD_RECOVERY_RESTART_WIFI_CONTINUE: - if (shouldEnableSta()) { - startClientModeManager(); - transitionTo(mEnabledState); - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class EnabledState extends BaseState { - - private boolean mIsDisablingDueToAirplaneMode; - - @Override - public void enter() { - log("EnabledState.enter()"); - super.enter(); - if (!hasAnyModeManager()) { - Log.e(TAG, "Entered EnabledState, but no active mode managers"); - } - mIsDisablingDueToAirplaneMode = false; - } - - @Override - public void exit() { - log("EnabledState.exit()"); - if (hasAnyModeManager()) { - Log.e(TAG, "Existing EnabledState, but has active mode managers"); - } - super.exit(); - } - - @Override - public boolean processMessageFiltered(Message msg) { - switch (msg.what) { - case CMD_WIFI_TOGGLED: - case CMD_SCAN_ALWAYS_MODE_CHANGED: - if (shouldEnableSta()) { - if (hasAnyClientModeManager()) { - switchAllClientModeManagers(); - } else { - startClientModeManager(); - } - } else { - stopAllClientModeManagers(); - } - break; - case CMD_SET_AP: - // note: CMD_SET_AP is handled/dropped in ECM mode - will not start here - if (msg.arg1 == 1) { - startSoftApModeManager((SoftApModeConfiguration) msg.obj); - } else { - stopSoftApModeManagers(msg.arg2); - } - break; - case CMD_AIRPLANE_TOGGLED: - // airplane mode toggled on is handled in the default state - if (mSettingsStore.isAirplaneModeOn()) { - mIsDisablingDueToAirplaneMode = true; - return NOT_HANDLED; - } else { - if (mIsDisablingDueToAirplaneMode) { - // Previous airplane mode toggle on is being processed, defer the - // message toggle off until previous processing is completed. - // Once previous airplane mode toggle is complete, we should - // transition to DisabledState. There, we will process the deferred - // airplane mode toggle message to disable airplane mode. - deferMessage(msg); - } else { - // when airplane mode is toggled off, but wifi is on, we can keep it - // on - log("airplane mode toggled - and airplane mode is off. return " - + "handled"); - } - return HANDLED; - } - case CMD_AP_STOPPED: - case CMD_AP_START_FAILURE: - if (!hasAnyModeManager()) { - if (shouldEnableSta()) { - log("SoftAp disabled, start client mode"); - startClientModeManager(); - } else { - log("SoftAp mode disabled, return to DisabledState"); - transitionTo(mDisabledState); - } - } else { - log("AP disabled, remain in EnabledState."); - } - break; - case CMD_STA_START_FAILURE: - case CMD_STA_STOPPED: - // Client mode stopped. Head to Disabled to wait for next command if there - // no active mode managers. - if (!hasAnyModeManager()) { - log("STA disabled, return to DisabledState."); - transitionTo(mDisabledState); - } else { - log("STA disabled, remain in EnabledState."); - } - break; - case CMD_RECOVERY_RESTART_WIFI: - final String bugTitle; - final String bugDetail; - if (msg.arg1 < SelfRecovery.REASON_STRINGS.length && msg.arg1 >= 0) { - bugDetail = SelfRecovery.REASON_STRINGS[msg.arg1]; - bugTitle = "Wi-Fi BugReport: " + bugDetail; - } else { - bugDetail = ""; - bugTitle = "Wi-Fi BugReport"; - } - if (msg.arg1 != SelfRecovery.REASON_LAST_RESORT_WATCHDOG) { - mHandler.post(() -> mClientModeImpl.takeBugReport(bugTitle, bugDetail)); - } - log("Recovery triggered, disable wifi"); - deferMessage(obtainMessage(CMD_DEFERRED_RECOVERY_RESTART_WIFI)); - shutdownWifi(); - // onStopped will move the state machine to "DisabledState". - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - } -} diff --git a/service/java/com/android/server/wifi/AggressiveConnectedScore.java b/service/java/com/android/server/wifi/AggressiveConnectedScore.java deleted file mode 100644 index c8ad00d77..000000000 --- a/service/java/com/android/server/wifi/AggressiveConnectedScore.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.net.wifi.WifiInfo; - -/** - * Experimental scorer - */ -public class AggressiveConnectedScore extends ConnectedScore { - - private final ScoringParams mScoringParams; - - private int mFrequencyMHz = 5000; - private int mRssi = 0; - - public AggressiveConnectedScore(ScoringParams scoringParams, Clock clock) { - super(clock); - mScoringParams = scoringParams; - } - - @Override - public void updateUsingRssi(int rssi, long millis, double standardDeviation) { - mRssi = rssi; - } - - @Override - public void updateUsingWifiInfo(WifiInfo wifiInfo, long millis) { - mFrequencyMHz = wifiInfo.getFrequency(); - mRssi = wifiInfo.getRssi(); - } - - @Override - public void reset() { - mFrequencyMHz = 5000; - } - - @Override - public int generateScore() { - int threshRssi = mScoringParams.getSufficientRssi(mFrequencyMHz); - int score = (mRssi - threshRssi) + WIFI_TRANSITION_SCORE; - return score; - } -} diff --git a/service/java/com/android/server/wifi/AvailableNetworkNotifier.java b/service/java/com/android/server/wifi/AvailableNetworkNotifier.java deleted file mode 100644 index 7243193cd..000000000 --- a/service/java/com/android/server/wifi/AvailableNetworkNotifier.java +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK; -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK; -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE; -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_USER_DISMISSED_NOTIFICATION; -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.AVAILABLE_NETWORK_NOTIFIER_TAG; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.app.Notification; -import android.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.database.ContentObserver; -import android.net.wifi.IActionListener; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.os.Binder; -import android.os.Handler; -import android.os.Looper; -import android.os.Process; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.proto.nano.WifiMetricsProto - .ConnectToNetworkNotificationAndActionCount; -import com.android.server.wifi.util.ScanResultUtil; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.List; -import java.util.Set; - -/** - * Base class for all network notifiers (e.g. OpenNetworkNotifier). - * - * NOTE: These API's are not thread safe and should only be used from WifiCoreThread. - */ -public class AvailableNetworkNotifier { - - /** Time in milliseconds to display the Connecting notification. */ - private static final int TIME_TO_SHOW_CONNECTING_MILLIS = 10000; - - /** Time in milliseconds to display the Connected notification. */ - private static final int TIME_TO_SHOW_CONNECTED_MILLIS = 5000; - - /** Time in milliseconds to display the Failed To Connect notification. */ - private static final int TIME_TO_SHOW_FAILED_MILLIS = 5000; - - /** The state of the notification */ - @IntDef({ - STATE_NO_NOTIFICATION, - STATE_SHOWING_RECOMMENDATION_NOTIFICATION, - STATE_CONNECTING_IN_NOTIFICATION, - STATE_CONNECTED_NOTIFICATION, - STATE_CONNECT_FAILED_NOTIFICATION - }) - @Retention(RetentionPolicy.SOURCE) - private @interface State {} - - /** No recommendation is made and no notifications are shown. */ - private static final int STATE_NO_NOTIFICATION = 0; - /** The initial notification recommending a network to connect to is shown. */ - private static final int STATE_SHOWING_RECOMMENDATION_NOTIFICATION = 1; - /** The notification of status of connecting to the recommended network is shown. */ - private static final int STATE_CONNECTING_IN_NOTIFICATION = 2; - /** The notification that the connection to the recommended network was successful is shown. */ - private static final int STATE_CONNECTED_NOTIFICATION = 3; - /** The notification to show that connection to the recommended network failed is shown. */ - private static final int STATE_CONNECT_FAILED_NOTIFICATION = 4; - - /** Current state of the notification. */ - @State private int mState = STATE_NO_NOTIFICATION; - - /** - * The {@link Clock#getWallClockMillis()} must be at least this value for us - * to show the notification again. - */ - private long mNotificationRepeatTime; - /** - * When a notification is shown, we wait this amount before possibly showing it again. - */ - private final long mNotificationRepeatDelay; - /** Default repeat delay in seconds. */ - @VisibleForTesting - static final int DEFAULT_REPEAT_DELAY_SEC = 900; - - /** Whether the user has set the setting to show the 'available networks' notification. */ - private boolean mSettingEnabled; - /** Whether the screen is on or not. */ - private boolean mScreenOn; - - /** List of SSIDs blacklisted from recommendation. */ - private final Set<String> mBlacklistedSsids = new ArraySet<>(); - - private final Context mContext; - private final Handler mHandler; - private final FrameworkFacade mFrameworkFacade; - private final WifiMetrics mWifiMetrics; - private final Clock mClock; - private final WifiConfigManager mConfigManager; - private final ClientModeImpl mClientModeImpl; - private final ConnectToNetworkNotificationBuilder mNotificationBuilder; - - private ScanResult mRecommendedNetwork; - - /** Tag used for logs and metrics */ - private final String mTag; - /** Identifier of the {@link SsidSetStoreData}. */ - private final String mStoreDataIdentifier; - /** Identifier for the settings toggle, used for registering ContentObserver */ - private final String mToggleSettingsName; - - /** System wide identifier for notification in Notification Manager */ - private final int mSystemMessageNotificationId; - - /** - * The nominator id for this class, from - * {@link com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectionEvent. - * ConnectionNominator} - */ - private final int mNominatorId; - - public AvailableNetworkNotifier( - String tag, - String storeDataIdentifier, - String toggleSettingsName, - int notificationIdentifier, - int nominatorId, - Context context, - Looper looper, - FrameworkFacade framework, - Clock clock, - WifiMetrics wifiMetrics, - WifiConfigManager wifiConfigManager, - WifiConfigStore wifiConfigStore, - ClientModeImpl clientModeImpl, - ConnectToNetworkNotificationBuilder connectToNetworkNotificationBuilder) { - mTag = tag; - mStoreDataIdentifier = storeDataIdentifier; - mToggleSettingsName = toggleSettingsName; - mSystemMessageNotificationId = notificationIdentifier; - mNominatorId = nominatorId; - mContext = context; - mHandler = new Handler(looper); - mFrameworkFacade = framework; - mWifiMetrics = wifiMetrics; - mClock = clock; - mConfigManager = wifiConfigManager; - mClientModeImpl = clientModeImpl; - mNotificationBuilder = connectToNetworkNotificationBuilder; - mScreenOn = false; - wifiConfigStore.registerStoreData(new SsidSetStoreData(mStoreDataIdentifier, - new AvailableNetworkNotifierStoreData())); - - // Setting is in seconds - mNotificationRepeatDelay = mFrameworkFacade.getIntegerSetting(context, - Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, - DEFAULT_REPEAT_DELAY_SEC) * 1000L; - NotificationEnabledSettingObserver settingObserver = new NotificationEnabledSettingObserver( - mHandler); - settingObserver.register(); - - IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_USER_DISMISSED_NOTIFICATION); - filter.addAction(ACTION_CONNECT_TO_NETWORK); - filter.addAction(ACTION_PICK_WIFI_NETWORK); - filter.addAction(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE); - mContext.registerReceiver( - mBroadcastReceiver, filter, null /* broadcastPermission */, mHandler); - } - - private final BroadcastReceiver mBroadcastReceiver = - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (!mTag.equals(intent.getStringExtra(AVAILABLE_NETWORK_NOTIFIER_TAG))) { - return; - } - switch (intent.getAction()) { - case ACTION_USER_DISMISSED_NOTIFICATION: - handleUserDismissedAction(); - break; - case ACTION_CONNECT_TO_NETWORK: - handleConnectToNetworkAction(); - break; - case ACTION_PICK_WIFI_NETWORK: - handleSeeAllNetworksAction(); - break; - case ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE: - handlePickWifiNetworkAfterConnectFailure(); - break; - default: - Log.e(mTag, "Unknown action " + intent.getAction()); - } - } - }; - - private final class ConnectActionListener extends IActionListener.Stub { - @Override - public void onSuccess() { - // Success here means that an attempt to connect to the network has been initiated. - // Successful connection updates are received via the - // WifiConnectivityManager#handleConnectionStateChanged() callback. - } - - @Override - public void onFailure(int reason) { - handleConnectionAttemptFailedToSend(); - } - } - - /** - * Clears the pending notification. This is called by {@link WifiConnectivityManager} on stop. - * - * @param resetRepeatTime resets the time delay for repeated notification if true. - */ - public void clearPendingNotification(boolean resetRepeatTime) { - if (resetRepeatTime) { - mNotificationRepeatTime = 0; - } - - if (mState != STATE_NO_NOTIFICATION) { - getNotificationManager().cancel(mSystemMessageNotificationId); - - if (mRecommendedNetwork != null) { - Log.d(mTag, "Notification with state=" - + mState - + " was cleared for recommended network: " - + "\"" + mRecommendedNetwork.SSID + "\""); - } - mState = STATE_NO_NOTIFICATION; - mRecommendedNetwork = null; - } - } - - private boolean isControllerEnabled() { - return mSettingEnabled && !mContext.getSystemService(UserManager.class) - .hasUserRestrictionForUser(UserManager.DISALLOW_CONFIG_WIFI, - UserHandle.CURRENT); - } - - /** - * If there are available networks, attempt to post a network notification. - * - * @param availableNetworks Available networks to choose from and possibly show notification - */ - public void handleScanResults(@NonNull List<ScanDetail> availableNetworks) { - if (!isControllerEnabled()) { - clearPendingNotification(true /* resetRepeatTime */); - return; - } - if (availableNetworks.isEmpty() && mState == STATE_SHOWING_RECOMMENDATION_NOTIFICATION) { - clearPendingNotification(false /* resetRepeatTime */); - return; - } - - // Not enough time has passed to show a recommendation notification again - if (mState == STATE_NO_NOTIFICATION - && mClock.getWallClockMillis() < mNotificationRepeatTime) { - return; - } - - // Do nothing when the screen is off and no notification is showing. - if (mState == STATE_NO_NOTIFICATION && !mScreenOn) { - return; - } - - // Only show a new or update an existing recommendation notification. - if (mState == STATE_NO_NOTIFICATION - || mState == STATE_SHOWING_RECOMMENDATION_NOTIFICATION) { - ScanResult recommendation = - recommendNetwork(availableNetworks); - - if (recommendation != null) { - postInitialNotification(recommendation); - } else { - clearPendingNotification(false /* resetRepeatTime */); - } - } - } - - /** - * Recommends a network to connect to from a list of available networks, while ignoring the - * SSIDs in the blacklist. - * - * @param networks List of networks to select from - */ - public ScanResult recommendNetwork(@NonNull List<ScanDetail> networks) { - ScanResult result = null; - int highestRssi = Integer.MIN_VALUE; - for (ScanDetail scanDetail : networks) { - ScanResult scanResult = scanDetail.getScanResult(); - - if (scanResult.level > highestRssi) { - result = scanResult; - highestRssi = scanResult.level; - } - } - - if (result != null && mBlacklistedSsids.contains(result.SSID)) { - result = null; - } - return result; - } - - /** Handles screen state changes. */ - public void handleScreenStateChanged(boolean screenOn) { - mScreenOn = screenOn; - } - - /** - * Called by {@link WifiConnectivityManager} when Wi-Fi is connected. If the notification - * was in the connecting state, update the notification to show that it has connected to the - * recommended network. - * - * @param ssid The connected network's ssid - */ - public void handleWifiConnected(String ssid) { - removeNetworkFromBlacklist(ssid); - if (mState != STATE_CONNECTING_IN_NOTIFICATION) { - clearPendingNotification(true /* resetRepeatTime */); - return; - } - - postNotification(mNotificationBuilder.createNetworkConnectedNotification(mTag, - mRecommendedNetwork)); - - Log.d(mTag, "User connected to recommended network: " - + "\"" + mRecommendedNetwork.SSID + "\""); - mWifiMetrics.incrementConnectToNetworkNotification(mTag, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTED_TO_NETWORK); - mState = STATE_CONNECTED_NOTIFICATION; - mHandler.postDelayed( - () -> { - if (mState == STATE_CONNECTED_NOTIFICATION) { - clearPendingNotification(true /* resetRepeatTime */); - } - }, - TIME_TO_SHOW_CONNECTED_MILLIS); - } - - /** - * Handles when a Wi-Fi connection attempt failed. - */ - public void handleConnectionFailure() { - if (mState != STATE_CONNECTING_IN_NOTIFICATION) { - return; - } - postNotification(mNotificationBuilder.createNetworkFailedNotification(mTag)); - - Log.d(mTag, "User failed to connect to recommended network: " - + "\"" + mRecommendedNetwork.SSID + "\""); - mWifiMetrics.incrementConnectToNetworkNotification(mTag, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT); - mState = STATE_CONNECT_FAILED_NOTIFICATION; - mHandler.postDelayed( - () -> { - if (mState == STATE_CONNECT_FAILED_NOTIFICATION) { - clearPendingNotification(false /* resetRepeatTime */); - } - }, - TIME_TO_SHOW_FAILED_MILLIS); - } - - private NotificationManager getNotificationManager() { - return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); - } - - private void postInitialNotification(ScanResult recommendedNetwork) { - if (mRecommendedNetwork != null - && TextUtils.equals(mRecommendedNetwork.SSID, recommendedNetwork.SSID)) { - return; - } - - postNotification(mNotificationBuilder.createConnectToAvailableNetworkNotification(mTag, - recommendedNetwork)); - - if (mState == STATE_NO_NOTIFICATION) { - mWifiMetrics.incrementConnectToNetworkNotification(mTag, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - } else { - mWifiMetrics.incrementNumNetworkRecommendationUpdates(mTag); - } - mState = STATE_SHOWING_RECOMMENDATION_NOTIFICATION; - mRecommendedNetwork = recommendedNetwork; - mNotificationRepeatTime = mClock.getWallClockMillis() + mNotificationRepeatDelay; - } - - private void postNotification(Notification notification) { - getNotificationManager().notify(mSystemMessageNotificationId, notification); - } - - private void handleConnectToNetworkAction() { - mWifiMetrics.incrementConnectToNetworkNotificationAction(mTag, mState, - ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); - if (mState != STATE_SHOWING_RECOMMENDATION_NOTIFICATION) { - return; - } - postNotification(mNotificationBuilder.createNetworkConnectingNotification(mTag, - mRecommendedNetwork)); - mWifiMetrics.incrementConnectToNetworkNotification(mTag, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); - - Log.d(mTag, - "User initiated connection to recommended network: " - + "\"" + mRecommendedNetwork.SSID + "\""); - WifiConfiguration network = createRecommendedNetworkConfig(mRecommendedNetwork); - - NetworkUpdateResult result = mConfigManager.addOrUpdateNetwork(network, Process.WIFI_UID); - if (result.isSuccess()) { - mWifiMetrics.setNominatorForNetwork(result.netId, mNominatorId); - ConnectActionListener connectActionListener = new ConnectActionListener(); - mClientModeImpl.connect(null, result.netId, new Binder(), connectActionListener, - connectActionListener.hashCode(), Process.SYSTEM_UID); - addNetworkToBlacklist(mRecommendedNetwork.SSID); - } - - mState = STATE_CONNECTING_IN_NOTIFICATION; - mHandler.postDelayed( - () -> { - if (mState == STATE_CONNECTING_IN_NOTIFICATION) { - handleConnectionFailure(); - } - }, - TIME_TO_SHOW_CONNECTING_MILLIS); - } - - private void addNetworkToBlacklist(String ssid) { - mBlacklistedSsids.add(ssid); - mWifiMetrics.setNetworkRecommenderBlacklistSize(mTag, mBlacklistedSsids.size()); - mConfigManager.saveToStore(false /* forceWrite */); - Log.d(mTag, "Network is added to the network notification blacklist: " - + "\"" + ssid + "\""); - } - - private void removeNetworkFromBlacklist(String ssid) { - if (ssid == null) { - return; - } - if (!mBlacklistedSsids.remove(ssid)) { - return; - } - mWifiMetrics.setNetworkRecommenderBlacklistSize(mTag, mBlacklistedSsids.size()); - mConfigManager.saveToStore(false /* forceWrite */); - Log.d(mTag, "Network is removed from the network notification blacklist: " - + "\"" + ssid + "\""); - } - - WifiConfiguration createRecommendedNetworkConfig(ScanResult recommendedNetwork) { - return ScanResultUtil.createNetworkFromScanResult(recommendedNetwork); - } - - private void handleSeeAllNetworksAction() { - mWifiMetrics.incrementConnectToNetworkNotificationAction(mTag, mState, - ConnectToNetworkNotificationAndActionCount.ACTION_PICK_WIFI_NETWORK); - startWifiSettings(); - } - - private void startWifiSettings() { - // Close notification drawer before opening the picker. - mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); - mContext.startActivity( - new Intent(Settings.ACTION_WIFI_SETTINGS) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - clearPendingNotification(false /* resetRepeatTime */); - } - - private void handleConnectionAttemptFailedToSend() { - handleConnectionFailure(); - mWifiMetrics.incrementNumNetworkConnectMessageFailedToSend(mTag); - } - - private void handlePickWifiNetworkAfterConnectFailure() { - mWifiMetrics.incrementConnectToNetworkNotificationAction(mTag, mState, - ConnectToNetworkNotificationAndActionCount - .ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE); - startWifiSettings(); - } - - private void handleUserDismissedAction() { - Log.d(mTag, "User dismissed notification with state=" + mState); - mWifiMetrics.incrementConnectToNetworkNotificationAction(mTag, mState, - ConnectToNetworkNotificationAndActionCount.ACTION_USER_DISMISSED_NOTIFICATION); - if (mState == STATE_SHOWING_RECOMMENDATION_NOTIFICATION) { - // blacklist dismissed network - addNetworkToBlacklist(mRecommendedNetwork.SSID); - } - resetStateAndDelayNotification(); - } - - private void resetStateAndDelayNotification() { - mState = STATE_NO_NOTIFICATION; - mNotificationRepeatTime = System.currentTimeMillis() + mNotificationRepeatDelay; - mRecommendedNetwork = null; - } - - /** Dump this network notifier's state. */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(mTag + ": "); - pw.println("mSettingEnabled " + mSettingEnabled); - pw.println("currentTime: " + mClock.getWallClockMillis()); - pw.println("mNotificationRepeatTime: " + mNotificationRepeatTime); - pw.println("mState: " + mState); - pw.println("mBlacklistedSsids: " + mBlacklistedSsids.toString()); - } - - private class AvailableNetworkNotifierStoreData implements SsidSetStoreData.DataSource { - @Override - public Set<String> getSsids() { - return new ArraySet<>(mBlacklistedSsids); - } - - @Override - public void setSsids(Set<String> ssidList) { - mBlacklistedSsids.addAll(ssidList); - mWifiMetrics.setNetworkRecommenderBlacklistSize(mTag, mBlacklistedSsids.size()); - } - } - - private class NotificationEnabledSettingObserver extends ContentObserver { - NotificationEnabledSettingObserver(Handler handler) { - super(handler); - } - - public void register() { - mFrameworkFacade.registerContentObserver(mContext, - Settings.Global.getUriFor(mToggleSettingsName), true, this); - mSettingEnabled = getValue(); - } - - @Override - public void onChange(boolean selfChange) { - super.onChange(selfChange); - mSettingEnabled = getValue(); - clearPendingNotification(true /* resetRepeatTime */); - } - - private boolean getValue() { - boolean enabled = - mFrameworkFacade.getIntegerSetting(mContext, mToggleSettingsName, 1) == 1; - mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(mTag, enabled); - Log.d(mTag, "Settings toggle enabled=" + enabled); - return enabled; - } - } -} diff --git a/service/java/com/android/server/wifi/BackupManagerProxy.java b/service/java/com/android/server/wifi/BackupManagerProxy.java deleted file mode 100644 index 4cd40c3da..000000000 --- a/service/java/com/android/server/wifi/BackupManagerProxy.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.app.backup.BackupManager; - -/** - * Wrapper around BackupManager, to allow use of mock during unit test. - */ -public class BackupManagerProxy { - - /** - * Notify BackupManager of dataChanged event. - * Hardcode to use SettingsProvider package for backup. - */ - public void notifyDataChanged() { - BackupManager.dataChanged("com.android.providers.settings"); - } -} diff --git a/service/java/com/android/server/wifi/BaseWifiDiagnostics.java b/service/java/com/android/server/wifi/BaseWifiDiagnostics.java deleted file mode 100644 index 3abf5100f..000000000 --- a/service/java/com/android/server/wifi/BaseWifiDiagnostics.java +++ /dev/null @@ -1,84 +0,0 @@ - -package com.android.server.wifi; - -import android.annotation.NonNull; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * - */ -public class BaseWifiDiagnostics { - public static final byte CONNECTION_EVENT_STARTED = 0; - public static final byte CONNECTION_EVENT_SUCCEEDED = 1; - public static final byte CONNECTION_EVENT_FAILED = 2; - public static final byte CONNECTION_EVENT_TIMEOUT = 3; - - protected final WifiNative mWifiNative; - - protected String mFirmwareVersion; - protected String mDriverVersion; - protected int mSupportedFeatureSet; - - public BaseWifiDiagnostics(WifiNative wifiNative) { - mWifiNative = wifiNative; - } - - /** - * start wifi HAL dependent logging features - * @param ifaceName requesting to start logging - */ - public synchronized void startLogging(@NonNull String ifaceName) { - mFirmwareVersion = mWifiNative.getFirmwareVersion(); - mDriverVersion = mWifiNative.getDriverVersion(); - mSupportedFeatureSet = mWifiNative.getSupportedLoggerFeatureSet(); - } - - public synchronized void startPacketLog() { } - - public synchronized void stopPacketLog() { } - - /** - * stop wifi HAL dependent logging features - * @param ifaceName requesting to stop logging - */ - public synchronized void stopLogging(@NonNull String ifaceName) { } - - /** - * Inform the diagnostics module of a connection event. - * @param event The type of connection event (see CONNECTION_EVENT_* constants) - */ - public synchronized void reportConnectionEvent(byte event) {} - - public synchronized void captureBugReportData(int reason) { } - - public synchronized void captureAlertData(int errorCode, byte[] alertData) { } - - public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - dump(pw); - pw.println("*** logging disabled, no debug data ****"); - } - - /** - * Starts taking a standard android bugreport - * android will prompt the user to send the bugreport when it's complete - * @param bugTitle Title of bugreport to generate - * @param bugDetail Description of the bugreport to generate - */ - public void takeBugReport(String bugTitle, String bugDetail) { } - - protected synchronized void dump(PrintWriter pw) { - pw.println("Chipset information :-----------------------------------------------"); - pw.println("FW Version is: " + mFirmwareVersion); - pw.println("Driver Version is: " + mDriverVersion); - pw.println("Supported Feature set: " + mSupportedFeatureSet); - } - - /** enables/disables wifi verbose logging */ - public synchronized void enableVerboseLogging(boolean verboseEnabled) { } - - /** enables packet fate monitoring */ - public void startPktFateMonitoring(@NonNull String ifaceName) {} - -} diff --git a/service/java/com/android/server/wifi/BaseWifiService.java b/service/java/com/android/server/wifi/BaseWifiService.java deleted file mode 100644 index 7614cf6eb..000000000 --- a/service/java/com/android/server/wifi/BaseWifiService.java +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright (c) 2018 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.server.wifi; - -import android.content.pm.ParceledListSlice; -import android.net.DhcpInfo; -import android.net.Network; -import android.net.wifi.IActionListener; -import android.net.wifi.IDppCallback; -import android.net.wifi.ILocalOnlyHotspotCallback; -import android.net.wifi.INetworkRequestMatchCallback; -import android.net.wifi.IOnWifiActivityEnergyInfoListener; -import android.net.wifi.IOnWifiUsabilityStatsListener; -import android.net.wifi.IScanResultsCallback; -import android.net.wifi.ISoftApCallback; -import android.net.wifi.ISuggestionConnectionStatusListener; -import android.net.wifi.ITrafficStateCallback; -import android.net.wifi.ITxPacketCountListener; -import android.net.wifi.IWifiConnectedNetworkScorer; -import android.net.wifi.IWifiManager; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.os.WorkSource; -import android.os.connectivity.WifiActivityEnergyInfo; - -import java.util.List; -import java.util.Map; - -/** - * Empty concrete class implementing IWifiManager with stub methods throwing runtime exceptions. - * - * This class is meant to be extended by real implementations of IWifiManager in order to facilitate - * cross-repo changes to WiFi internal APIs, including the introduction of new APIs, the removal of - * deprecated APIs, or the migration of existing API signatures. - * - * When an existing API is scheduled for removal, it can be removed from IWifiManager.aidl - * immediately and marked as @Deprecated first in this class. Children inheriting this class are - * then given a short grace period to update themselves before the @Deprecated stub is removed for - * good. If the API scheduled for removal has a replacement or an overload (signature change), - * these should be introduced before the stub is removed to allow children to migrate. - * - * When a new API is added to IWifiManager.aidl, a stub should be added in BaseWifiService as - * well otherwise compilation will fail. - */ -public class BaseWifiService extends IWifiManager.Stub { - - private static final String TAG = BaseWifiService.class.getSimpleName(); - - @Override - public long getSupportedFeatures() { - throw new UnsupportedOperationException(); - } - - /** @deprecated use {@link #getWifiActivityEnergyInfoAsync} instead */ - @Deprecated - public WifiActivityEnergyInfo reportActivityInfo() { - throw new UnsupportedOperationException(); - } - - /** @deprecated use {@link #getWifiActivityEnergyInfoAsync} instead */ - @Deprecated - public void requestActivityInfo(ResultReceiver result) { - throw new UnsupportedOperationException(); - } - - @Override - public void getWifiActivityEnergyInfoAsync(IOnWifiActivityEnergyInfoListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public ParceledListSlice getConfiguredNetworks(String packageName, String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public ParceledListSlice getPrivilegedConfiguredNetworks(String packageName, String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public Map<String, Map<Integer, List<ScanResult>>> getAllMatchingFqdnsForScanResults( - List<ScanResult> scanResults) { - throw new UnsupportedOperationException(); - } - - @Override - public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( - List<ScanResult> scanResults) { - throw new UnsupportedOperationException(); - } - - @Override - public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( - List<OsuProvider> osuProviders) { - throw new UnsupportedOperationException(); - } - - @Override - public int addOrUpdateNetwork(WifiConfiguration config, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean addOrUpdatePasspointConfiguration( - PasspointConfiguration config, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removePasspointConfiguration(String fqdn, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public List<PasspointConfiguration> getPasspointConfigurations(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public List<WifiConfiguration> getWifiConfigsForPasspointProfiles(List<String> fqdnList) { - throw new UnsupportedOperationException(); - } - - @Override - public void queryPasspointIcon(long bssid, String fileName) { - throw new UnsupportedOperationException(); - } - - @Override - public int matchProviderWithCurrentNetwork(String fqdn) { - throw new UnsupportedOperationException(); - } - - @Override - public void deauthenticateNetwork(long holdoff, boolean ess) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeNetwork(int netId, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean enableNetwork(int netId, boolean disableOthers, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean disableNetwork(int netId, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void allowAutojoinGlobal(boolean choice) { - throw new UnsupportedOperationException(); - } - - @Override - public void allowAutojoin(int netId, boolean choice) { - throw new UnsupportedOperationException(); - } - - @Override - public void allowAutojoinPasspoint(String fqdn, boolean enableAutoJoin) { - throw new UnsupportedOperationException(); - } - - @Override - public void setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable) { - throw new UnsupportedOperationException(); - } - - /** @deprecated use {@link #setPasspointMeteredOverride} instead */ - @Deprecated - public void setMeteredOverridePasspoint(String fqdn, int meteredOverride) { - throw new UnsupportedOperationException(); - } - - @Override - public void setPasspointMeteredOverride(String fqdn, int meteredOverride) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean startScan(String packageName, String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public List<ScanResult> getScanResults(String callingPackage, String callingFeatureId) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean disconnect(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean reconnect(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean reassociate(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public WifiInfo getConnectionInfo(String callingPackage, String callingFeatureId) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setWifiEnabled(String packageName, boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public int getWifiEnabledState() { - throw new UnsupportedOperationException(); - } - - @Override - public String getCountryCode() { - throw new UnsupportedOperationException(); - } - - /** @deprecated use {@link #is5GHzBandSupported} instead */ - @Deprecated - public boolean isDualBandSupported() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean is5GHzBandSupported() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean is6GHzBandSupported() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isWifiStandardSupported(int standard) { - throw new UnsupportedOperationException(); - } - - /** @deprecated use {@link WifiManager#isStaApConcurrencySupported()} */ - @Deprecated - public boolean needs5GHzToAnyApBandConversion() { - throw new UnsupportedOperationException(); - } - - @Override - public DhcpInfo getDhcpInfo() { - throw new UnsupportedOperationException(); - } - - @Override - public void setScanAlwaysAvailable(boolean isAvailable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isScanAlwaysAvailable() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean acquireWifiLock(IBinder lock, int lockType, String tag, WorkSource ws) { - throw new UnsupportedOperationException(); - } - - @Override - public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean releaseWifiLock(IBinder lock) { - throw new UnsupportedOperationException(); - } - - @Override - public void initializeMulticastFiltering() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isMulticastEnabled() { - throw new UnsupportedOperationException(); - } - - @Override - public void acquireMulticastLock(IBinder binder, String tag) { - throw new UnsupportedOperationException(); - } - - @Override - public void releaseMulticastLock(String tag) { - throw new UnsupportedOperationException(); - } - - @Override - public void updateInterfaceIpState(String ifaceName, int mode) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean startSoftAp(WifiConfiguration wifiConfig) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean startTetheredHotspot(SoftApConfiguration softApConfig) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean stopSoftAp() { - throw new UnsupportedOperationException(); - } - - @Override - public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName, - String featureId, SoftApConfiguration customConfig) { - throw new UnsupportedOperationException(); - } - - @Override - public void stopLocalOnlyHotspot() { - throw new UnsupportedOperationException(); - } - - @Override - public void startWatchLocalOnlyHotspot(ILocalOnlyHotspotCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void stopWatchLocalOnlyHotspot() { - throw new UnsupportedOperationException(); - } - - @Override - public int getWifiApEnabledState() { - throw new UnsupportedOperationException(); - } - - @Override - public WifiConfiguration getWifiApConfiguration() { - throw new UnsupportedOperationException(); - } - - @Override - public SoftApConfiguration getSoftApConfiguration() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setSoftApConfiguration(SoftApConfiguration softApConfig, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void notifyUserOfApBandConversion(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void enableTdls(String remoteIPAddress, boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public String getCurrentNetworkWpsNfcConfigurationToken() { - throw new UnsupportedOperationException(); - } - - @Override - public void enableVerboseLogging(int verbose) { - throw new UnsupportedOperationException(); - } - - @Override - public int getVerboseLoggingLevel() { - throw new UnsupportedOperationException(); - } - - /** @deprecated use {@link #allowAutojoinGlobal(boolean)} instead */ - @Deprecated - public void enableWifiConnectivityManager(boolean enabled) { - throw new UnsupportedOperationException(); - } - - @Override - public void disableEphemeralNetwork(String SSID, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void factoryReset(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public Network getCurrentNetwork() { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] retrieveBackupData() { - throw new UnsupportedOperationException(); - } - - @Override - public void restoreBackupData(byte[] data) { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] retrieveSoftApBackupData() { - throw new UnsupportedOperationException(); - } - - @Override - public SoftApConfiguration restoreSoftApBackupData(byte[] data) { - throw new UnsupportedOperationException(); - } - - @Override - public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { - throw new UnsupportedOperationException(); - } - - @Override - public void startSubscriptionProvisioning( - OsuProvider provider, IProvisioningCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerSoftApCallback( - IBinder binder, ISoftApCallback callback, int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterSoftApCallback(int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerTrafficStateCallback( - IBinder binder, ITrafficStateCallback callback, int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterTrafficStateCallback(int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerNetworkRequestMatchCallback( - IBinder binder, INetworkRequestMatchCallback callback, int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterNetworkRequestMatchCallback(int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public int addNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, - String callingFeatureId) { - throw new UnsupportedOperationException(); - } - - @Override - public int removeNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName) { - throw new UnsupportedOperationException(); - } - - @Override - public List<WifiNetworkSuggestion> getNetworkSuggestions(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public String[] getFactoryMacAddresses() { - throw new UnsupportedOperationException(); - } - - @Override - public void setDeviceMobilityState(int state) { - throw new UnsupportedOperationException(); - } - - @Override - public void startDppAsConfiguratorInitiator(IBinder binder, String enrolleeUri, - int selectedNetworkId, int netRole, IDppCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void startDppAsEnrolleeInitiator(IBinder binder, String configuratorUri, - IDppCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void stopDppSession() throws RemoteException { - throw new UnsupportedOperationException(); - } - - @Override - public void addOnWifiUsabilityStatsListener( - IBinder binder, IOnWifiUsabilityStatsListener listener, int listenerIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeOnWifiUsabilityStatsListener(int listenerIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { - throw new UnsupportedOperationException(); - } - - @Override - public void connect(WifiConfiguration config, int netId, IBinder binder, - IActionListener callback, int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void save(WifiConfiguration config, IBinder binder, IActionListener callback, - int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void forget(int netId, IBinder binder, IActionListener callback, - int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - /** - * @deprecated was only used by CTS test, now fully removed. Please also remove - * ITxPacketCountListener.aidl when removing this method. - */ - @Deprecated - public void getTxPacketCount(String packageName, IBinder binder, - ITxPacketCountListener callback, int callbackIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerScanResultsCallback(IScanResultsCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterScanResultsCallback(IScanResultsCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerSuggestionConnectionStatusListener(IBinder binder, - ISuggestionConnectionStatusListener listener, - int listenerIdentifier, String packageName, String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterSuggestionConnectionStatusListener(int listenerIdentifier, - String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public int calculateSignalLevel(int rssi) { - throw new UnsupportedOperationException(); - } - - @Override - public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( - List<ScanResult> scanResults) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setWifiConnectedNetworkScorer(IBinder binder, - IWifiConnectedNetworkScorer scorer) { - throw new UnsupportedOperationException(); - } - - @Override - public void clearWifiConnectedNetworkScorer() { - throw new UnsupportedOperationException(); - } - - @Override - public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( - List<WifiNetworkSuggestion> networkSuggestions, - List<ScanResult> scanResults, - String callingPackage, String callingFeatureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void setScanThrottleEnabled(boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isScanThrottleEnabled() { - throw new UnsupportedOperationException(); - } - - @Override - public Map<String, Map<Integer, List<ScanResult>>> - getAllMatchingPasspointProfilesForScanResults(List<ScanResult> scanResults) { - throw new UnsupportedOperationException(); - } - - @Override - public void setAutoWakeupEnabled(boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isAutoWakeupEnabled() { - throw new UnsupportedOperationException(); - } -} diff --git a/service/java/com/android/server/wifi/BssidBlocklistMonitor.java b/service/java/com/android/server/wifi/BssidBlocklistMonitor.java deleted file mode 100644 index e3fe32ab7..000000000 --- a/service/java/com/android/server/wifi/BssidBlocklistMonitor.java +++ /dev/null @@ -1,745 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.LocalLog; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * This class manages the addition and removal of BSSIDs to the BSSID blocklist, which is used - * for firmware roaming and network selection. - */ -public class BssidBlocklistMonitor { - // A special type association rejection - public static final int REASON_AP_UNABLE_TO_HANDLE_NEW_STA = 0; - // No internet - public static final int REASON_NETWORK_VALIDATION_FAILURE = 1; - // Wrong password error - public static final int REASON_WRONG_PASSWORD = 2; - // Incorrect EAP credentials - public static final int REASON_EAP_FAILURE = 3; - // Other association rejection failures - public static final int REASON_ASSOCIATION_REJECTION = 4; - // Association timeout failures. - public static final int REASON_ASSOCIATION_TIMEOUT = 5; - // Other authentication failures - public static final int REASON_AUTHENTICATION_FAILURE = 6; - // DHCP failures - public static final int REASON_DHCP_FAILURE = 7; - // Abnormal disconnect error - public static final int REASON_ABNORMAL_DISCONNECT = 8; - // AP initiated disconnect for a given duration. - public static final int REASON_FRAMEWORK_DISCONNECT_MBO_OCE = 9; - // Avoid connecting to the failed AP when trying to reconnect on other available candidates. - public static final int REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT = 10; - // The connected scorer has disconnected this network. - public static final int REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE = 11; - // Constant being used to keep track of how many failure reasons there are. - public static final int NUMBER_REASON_CODES = 12; - public static final int INVALID_REASON = -1; - - @IntDef(prefix = { "REASON_" }, value = { - REASON_AP_UNABLE_TO_HANDLE_NEW_STA, - REASON_NETWORK_VALIDATION_FAILURE, - REASON_WRONG_PASSWORD, - REASON_EAP_FAILURE, - REASON_ASSOCIATION_REJECTION, - REASON_ASSOCIATION_TIMEOUT, - REASON_AUTHENTICATION_FAILURE, - REASON_DHCP_FAILURE, - REASON_ABNORMAL_DISCONNECT, - REASON_FRAMEWORK_DISCONNECT_MBO_OCE, - REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT, - REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE - }) - @Retention(RetentionPolicy.SOURCE) - public @interface FailureReason {} - - // To be filled with values from the overlay. - private static final int[] FAILURE_COUNT_DISABLE_THRESHOLD = new int[NUMBER_REASON_CODES]; - private boolean mFailureCountDisableThresholdArrayInitialized = false; - private static final String[] FAILURE_REASON_STRINGS = { - "REASON_AP_UNABLE_TO_HANDLE_NEW_STA", - "REASON_NETWORK_VALIDATION_FAILURE", - "REASON_WRONG_PASSWORD", - "REASON_EAP_FAILURE", - "REASON_ASSOCIATION_REJECTION", - "REASON_ASSOCIATION_TIMEOUT", - "REASON_AUTHENTICATION_FAILURE", - "REASON_DHCP_FAILURE", - "REASON_ABNORMAL_DISCONNECT", - "REASON_FRAMEWORK_DISCONNECT_MBO_OCE", - "REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT", - "REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE" - }; - private static final Set<Integer> LOW_RSSI_SENSITIVE_FAILURES = new ArraySet<>(Arrays.asList( - REASON_NETWORK_VALIDATION_FAILURE, - REASON_EAP_FAILURE, - REASON_ASSOCIATION_REJECTION, - REASON_ASSOCIATION_TIMEOUT, - REASON_AUTHENTICATION_FAILURE, - REASON_DHCP_FAILURE, - REASON_ABNORMAL_DISCONNECT, - REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE - )); - private static final long ABNORMAL_DISCONNECT_RESET_TIME_MS = TimeUnit.HOURS.toMillis(3); - private static final int MIN_RSSI_DIFF_TO_UNBLOCK_BSSID = 5; - private static final String TAG = "BssidBlocklistMonitor"; - - private final Context mContext; - private final WifiLastResortWatchdog mWifiLastResortWatchdog; - private final WifiConnectivityHelper mConnectivityHelper; - private final Clock mClock; - private final LocalLog mLocalLog; - private final Calendar mCalendar; - private final WifiScoreCard mWifiScoreCard; - private final ScoringParams mScoringParams; - - // Map of bssid to BssidStatus - private Map<String, BssidStatus> mBssidStatusMap = new ArrayMap<>(); - - // Keeps history of 30 blocked BSSIDs that were most recently removed. - private BssidStatusHistoryLogger mBssidStatusHistoryLogger = new BssidStatusHistoryLogger(30); - - /** - * Create a new instance of BssidBlocklistMonitor - */ - BssidBlocklistMonitor(Context context, WifiConnectivityHelper connectivityHelper, - WifiLastResortWatchdog wifiLastResortWatchdog, Clock clock, LocalLog localLog, - WifiScoreCard wifiScoreCard, ScoringParams scoringParams) { - mContext = context; - mConnectivityHelper = connectivityHelper; - mWifiLastResortWatchdog = wifiLastResortWatchdog; - mClock = clock; - mLocalLog = localLog; - mCalendar = Calendar.getInstance(); - mWifiScoreCard = wifiScoreCard; - mScoringParams = scoringParams; - } - - // A helper to log debugging information in the local log buffer, which can - // be retrieved in bugreport. - private void localLog(String log) { - mLocalLog.log(log); - } - - /** - * calculates the blocklist duration based on the current failure streak with exponential - * backoff. - * @param failureStreak should be greater or equal to 0. - * @return duration to block the BSSID in milliseconds - */ - private long getBlocklistDurationWithExponentialBackoff(int failureStreak, - int baseBlocklistDurationMs) { - failureStreak = Math.min(failureStreak, mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorFailureStreakCap)); - if (failureStreak < 1) { - return baseBlocklistDurationMs; - } - return (long) (Math.pow(2.0, (double) failureStreak) * baseBlocklistDurationMs); - } - - /** - * Dump the local log buffer and other internal state of BssidBlocklistMonitor. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of BssidBlocklistMonitor"); - pw.println("BssidBlocklistMonitor - Bssid blocklist begin ----"); - mBssidStatusMap.values().stream().forEach(entry -> pw.println(entry)); - pw.println("BssidBlocklistMonitor - Bssid blocklist end ----"); - mBssidStatusHistoryLogger.dump(pw); - } - - private void addToBlocklist(@NonNull BssidStatus entry, long durationMs, - @FailureReason int reason, int rssi) { - entry.setAsBlocked(durationMs, reason, rssi); - localLog(TAG + " addToBlocklist: bssid=" + entry.bssid + ", ssid=" + entry.ssid - + ", durationMs=" + durationMs + ", reason=" + getFailureReasonString(reason) - + ", rssi=" + rssi); - } - - /** - * increments the number of failures for the given bssid and returns the number of failures so - * far. - * @return the BssidStatus for the BSSID - */ - private @NonNull BssidStatus incrementFailureCountForBssid( - @NonNull String bssid, @NonNull String ssid, int reasonCode) { - BssidStatus status = getOrCreateBssidStatus(bssid, ssid); - status.incrementFailureCount(reasonCode); - return status; - } - - /** - * Get the BssidStatus representing the BSSID or create a new one if it doesn't exist. - */ - private @NonNull BssidStatus getOrCreateBssidStatus(@NonNull String bssid, - @NonNull String ssid) { - BssidStatus status = mBssidStatusMap.get(bssid); - if (status == null || !ssid.equals(status.ssid)) { - if (status != null) { - localLog("getOrCreateBssidStatus: BSSID=" + bssid + ", SSID changed from " - + status.ssid + " to " + ssid); - } - status = new BssidStatus(bssid, ssid); - mBssidStatusMap.put(bssid, status); - } - return status; - } - - private boolean isValidNetworkAndFailureReason(String bssid, String ssid, - @FailureReason int reasonCode) { - if (bssid == null || ssid == null || WifiManager.UNKNOWN_SSID.equals(ssid) - || bssid.equals(ClientModeImpl.SUPPLICANT_BSSID_ANY) - || reasonCode < 0 || reasonCode >= NUMBER_REASON_CODES) { - Log.e(TAG, "Invalid input: BSSID=" + bssid + ", SSID=" + ssid - + ", reasonCode=" + reasonCode); - return false; - } - return true; - } - - private boolean shouldWaitForWatchdogToTriggerFirst(String bssid, - @FailureReason int reasonCode) { - boolean isWatchdogRelatedFailure = reasonCode == REASON_ASSOCIATION_REJECTION - || reasonCode == REASON_AUTHENTICATION_FAILURE - || reasonCode == REASON_DHCP_FAILURE; - return isWatchdogRelatedFailure && mWifiLastResortWatchdog.shouldIgnoreBssidUpdate(bssid); - } - - /** - * Block any attempts to auto-connect to the BSSID for the specified duration. - * This is meant to be used by features that need wifi to avoid a BSSID for a certain duration, - * and thus will not increase the failure streak counters. - * @param bssid identifies the AP to block. - * @param ssid identifies the SSID the AP belongs to. - * @param durationMs duration in millis to block. - * @param blockReason reason for blocking the BSSID. - * @param rssi the latest RSSI observed. - */ - public void blockBssidForDurationMs(@NonNull String bssid, @NonNull String ssid, - long durationMs, @FailureReason int blockReason, int rssi) { - if (durationMs <= 0 || !isValidNetworkAndFailureReason(bssid, ssid, blockReason)) { - Log.e(TAG, "Invalid input: BSSID=" + bssid + ", SSID=" + ssid - + ", durationMs=" + durationMs + ", blockReason=" + blockReason - + ", rssi=" + rssi); - return; - } - BssidStatus status = getOrCreateBssidStatus(bssid, ssid); - if (status.isInBlocklist - && status.blocklistEndTimeMs - mClock.getWallClockMillis() > durationMs) { - // Return because this BSSID is already being blocked for a longer time. - return; - } - addToBlocklist(status, durationMs, blockReason, rssi); - } - - private String getFailureReasonString(@FailureReason int reasonCode) { - if (reasonCode == INVALID_REASON) { - return "INVALID_REASON"; - } else if (reasonCode < 0 || reasonCode >= FAILURE_REASON_STRINGS.length) { - return "REASON_UNKNOWN"; - } - return FAILURE_REASON_STRINGS[reasonCode]; - } - - private int getFailureThresholdForReason(@FailureReason int reasonCode) { - if (mFailureCountDisableThresholdArrayInitialized) { - return FAILURE_COUNT_DISABLE_THRESHOLD[reasonCode]; - } - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_AP_UNABLE_TO_HANDLE_NEW_STA] = - mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorApUnableToHandleNewStaThreshold); - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_NETWORK_VALIDATION_FAILURE] = - mContext.getResources().getInteger(R.integer - .config_wifiBssidBlocklistMonitorNetworkValidationFailureThreshold); - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_WRONG_PASSWORD] = - mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorWrongPasswordThreshold); - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_EAP_FAILURE] = - mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorEapFailureThreshold); - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_ASSOCIATION_REJECTION] = - mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorAssociationRejectionThreshold); - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_ASSOCIATION_TIMEOUT] = - mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorAssociationTimeoutThreshold); - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_AUTHENTICATION_FAILURE] = - mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorAuthenticationFailureThreshold); - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_DHCP_FAILURE] = - mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorDhcpFailureThreshold); - FAILURE_COUNT_DISABLE_THRESHOLD[REASON_ABNORMAL_DISCONNECT] = - mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorAbnormalDisconnectThreshold); - mFailureCountDisableThresholdArrayInitialized = true; - return FAILURE_COUNT_DISABLE_THRESHOLD[reasonCode]; - } - - private boolean handleBssidConnectionFailureInternal(String bssid, String ssid, - @FailureReason int reasonCode, int rssi) { - BssidStatus entry = incrementFailureCountForBssid(bssid, ssid, reasonCode); - int failureThreshold = getFailureThresholdForReason(reasonCode); - int currentStreak = mWifiScoreCard.getBssidBlocklistStreak(ssid, bssid, reasonCode); - if (currentStreak > 0 || entry.failureCount[reasonCode] >= failureThreshold) { - // To rule out potential device side issues, don't add to blocklist if - // WifiLastResortWatchdog is still not triggered - if (shouldWaitForWatchdogToTriggerFirst(bssid, reasonCode)) { - return false; - } - int baseBlockDurationMs = getBaseBlockDurationForReason(reasonCode); - addToBlocklist(entry, - getBlocklistDurationWithExponentialBackoff(currentStreak, baseBlockDurationMs), - reasonCode, rssi); - mWifiScoreCard.incrementBssidBlocklistStreak(ssid, bssid, reasonCode); - return true; - } - return false; - } - - private int getBaseBlockDurationForReason(int blockReason) { - switch (blockReason) { - case REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE: - return mContext.getResources().getInteger(R.integer - .config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs); - default: - return mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorBaseBlockDurationMs); - } - } - - /** - * Note a failure event on a bssid and perform appropriate actions. - * @return True if the blocklist has been modified. - */ - public boolean handleBssidConnectionFailure(String bssid, String ssid, - @FailureReason int reasonCode, int rssi) { - if (!isValidNetworkAndFailureReason(bssid, ssid, reasonCode)) { - return false; - } - if (reasonCode == REASON_ABNORMAL_DISCONNECT) { - long connectionTime = mWifiScoreCard.getBssidConnectionTimestampMs(ssid, bssid); - // only count disconnects that happen shortly after a connection. - if (mClock.getWallClockMillis() - connectionTime - > mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistAbnormalDisconnectTimeWindowMs)) { - return false; - } - } - return handleBssidConnectionFailureInternal(bssid, ssid, reasonCode, rssi); - } - - /** - * Note a connection success event on a bssid and clear appropriate failure counters. - */ - public void handleBssidConnectionSuccess(@NonNull String bssid, @NonNull String ssid) { - /** - * First reset the blocklist streak. - * This needs to be done even if a BssidStatus is not found, since the BssidStatus may - * have been removed due to blocklist timeout. - */ - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_AP_UNABLE_TO_HANDLE_NEW_STA); - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_WRONG_PASSWORD); - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_EAP_FAILURE); - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_ASSOCIATION_REJECTION); - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_ASSOCIATION_TIMEOUT); - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_AUTHENTICATION_FAILURE); - - long connectionTime = mClock.getWallClockMillis(); - long prevConnectionTime = mWifiScoreCard.setBssidConnectionTimestampMs( - ssid, bssid, connectionTime); - if (connectionTime - prevConnectionTime > ABNORMAL_DISCONNECT_RESET_TIME_MS) { - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_ABNORMAL_DISCONNECT); - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, - REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE); - } - - BssidStatus status = mBssidStatusMap.get(bssid); - if (status == null) { - return; - } - // Clear the L2 failure counters - status.failureCount[REASON_AP_UNABLE_TO_HANDLE_NEW_STA] = 0; - status.failureCount[REASON_WRONG_PASSWORD] = 0; - status.failureCount[REASON_EAP_FAILURE] = 0; - status.failureCount[REASON_ASSOCIATION_REJECTION] = 0; - status.failureCount[REASON_ASSOCIATION_TIMEOUT] = 0; - status.failureCount[REASON_AUTHENTICATION_FAILURE] = 0; - if (connectionTime - prevConnectionTime > ABNORMAL_DISCONNECT_RESET_TIME_MS) { - status.failureCount[REASON_ABNORMAL_DISCONNECT] = 0; - } - } - - /** - * Note a successful network validation on a BSSID and clear appropriate failure counters. - * And then remove the BSSID from blocklist. - */ - public void handleNetworkValidationSuccess(@NonNull String bssid, @NonNull String ssid) { - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_NETWORK_VALIDATION_FAILURE); - BssidStatus status = mBssidStatusMap.get(bssid); - if (status == null) { - return; - } - status.failureCount[REASON_NETWORK_VALIDATION_FAILURE] = 0; - /** - * Network validation may take more than 1 tries to succeed. - * remove the BSSID from blocklist to make sure we are not accidentally blocking good - * BSSIDs. - **/ - if (status.isInBlocklist) { - mBssidStatusHistoryLogger.add(status, "Network validation success"); - mBssidStatusMap.remove(bssid); - } - } - - /** - * Note a successful DHCP provisioning and clear appropriate faliure counters. - */ - public void handleDhcpProvisioningSuccess(@NonNull String bssid, @NonNull String ssid) { - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_DHCP_FAILURE); - BssidStatus status = mBssidStatusMap.get(bssid); - if (status == null) { - return; - } - status.failureCount[REASON_DHCP_FAILURE] = 0; - } - - /** - * Note the removal of a network from the Wifi stack's internal database and reset - * appropriate failure counters. - * @param ssid - */ - public void handleNetworkRemoved(@NonNull String ssid) { - clearBssidBlocklistForSsid(ssid); - mWifiScoreCard.resetBssidBlocklistStreakForSsid(ssid); - } - - /** - * Clears the blocklist for BSSIDs associated with the input SSID only. - * @param ssid - */ - public void clearBssidBlocklistForSsid(@NonNull String ssid) { - int prevSize = mBssidStatusMap.size(); - mBssidStatusMap.entrySet().removeIf(e -> { - BssidStatus status = e.getValue(); - if (status.ssid == null) { - return false; - } - if (status.ssid.equals(ssid)) { - mBssidStatusHistoryLogger.add(status, "clearBssidBlocklistForSsid"); - return true; - } - return false; - }); - int diff = prevSize - mBssidStatusMap.size(); - if (diff > 0) { - localLog(TAG + " clearBssidBlocklistForSsid: SSID=" + ssid - + ", num BSSIDs cleared=" + diff); - } - } - - /** - * Clears the BSSID blocklist and failure counters. - */ - public void clearBssidBlocklist() { - if (mBssidStatusMap.size() > 0) { - int prevSize = mBssidStatusMap.size(); - for (BssidStatus status : mBssidStatusMap.values()) { - mBssidStatusHistoryLogger.add(status, "clearBssidBlocklist"); - } - mBssidStatusMap.clear(); - localLog(TAG + " clearBssidBlocklist: num BSSIDs cleared=" - + (prevSize - mBssidStatusMap.size())); - } - } - - /** - * @param ssid - * @return the number of BSSIDs currently in the blocklist for the |ssid|. - */ - public int updateAndGetNumBlockedBssidsForSsid(@NonNull String ssid) { - return (int) updateAndGetBssidBlocklistInternal() - .filter(entry -> ssid.equals(entry.ssid)).count(); - } - - private int getNumBlockedBssidsForSsid(@Nullable String ssid) { - if (ssid == null) { - return 0; - } - return (int) mBssidStatusMap.values().stream() - .filter(entry -> entry.isInBlocklist && ssid.equals(entry.ssid)) - .count(); - } - - /** - * Overloaded version of updateAndGetBssidBlocklist. - * Accepts a @Nullable String ssid as input, and updates the firmware roaming - * configuration if the blocklist for the input ssid has been changed. - * @param ssid to update firmware roaming configuration for. - * @return Set of BSSIDs currently in the blocklist - */ - public Set<String> updateAndGetBssidBlocklistForSsid(@Nullable String ssid) { - int numBefore = getNumBlockedBssidsForSsid(ssid); - Set<String> bssidBlocklist = updateAndGetBssidBlocklist(); - if (getNumBlockedBssidsForSsid(ssid) != numBefore) { - updateFirmwareRoamingConfiguration(ssid); - } - return bssidBlocklist; - } - - /** - * Gets the BSSIDs that are currently in the blocklist. - * @return Set of BSSIDs currently in the blocklist - */ - public Set<String> updateAndGetBssidBlocklist() { - return updateAndGetBssidBlocklistInternal() - .map(entry -> entry.bssid) - .collect(Collectors.toSet()); - } - - /** - * Gets the list of block reasons for BSSIDs currently in the blocklist. - * @return The set of unique reasons for blocking BSSIDs with this SSID. - */ - public Set<Integer> getFailureReasonsForSsid(@NonNull String ssid) { - if (ssid == null) { - return Collections.emptySet(); - } - return mBssidStatusMap.values().stream() - .filter(entry -> entry.isInBlocklist && ssid.equals(entry.ssid)) - .map(entry -> entry.blockReason) - .collect(Collectors.toSet()); - } - - /** - * Attempts to re-enable BSSIDs that likely experienced failures due to low RSSI. - * @param scanDetails - */ - public void tryEnablingBlockedBssids(List<ScanDetail> scanDetails) { - if (scanDetails == null) { - return; - } - for (ScanDetail scanDetail : scanDetails) { - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult == null) { - continue; - } - BssidStatus status = mBssidStatusMap.get(scanResult.BSSID); - if (status == null || !status.isInBlocklist - || !LOW_RSSI_SENSITIVE_FAILURES.contains(status.blockReason)) { - continue; - } - int sufficientRssi = mScoringParams.getSufficientRssi(scanResult.frequency); - if (status.lastRssi < sufficientRssi && scanResult.level >= sufficientRssi - && scanResult.level - status.lastRssi >= MIN_RSSI_DIFF_TO_UNBLOCK_BSSID) { - mBssidStatusHistoryLogger.add(status, "rssi significantly improved"); - mBssidStatusMap.remove(status.bssid); - } - } - } - - /** - * Removes expired BssidStatus entries and then return remaining entries in the blocklist. - * @return Stream of BssidStatus for BSSIDs that are in the blocklist. - */ - private Stream<BssidStatus> updateAndGetBssidBlocklistInternal() { - Stream.Builder<BssidStatus> builder = Stream.builder(); - long curTime = mClock.getWallClockMillis(); - mBssidStatusMap.entrySet().removeIf(e -> { - BssidStatus status = e.getValue(); - if (status.isInBlocklist) { - if (status.blocklistEndTimeMs < curTime) { - mBssidStatusHistoryLogger.add(status, "updateAndGetBssidBlocklistInternal"); - return true; - } - builder.accept(status); - } - return false; - }); - return builder.build(); - } - - /** - * Sends the BSSIDs belonging to the input SSID down to the firmware to prevent auto-roaming - * to those BSSIDs. - * @param ssid - */ - public void updateFirmwareRoamingConfiguration(@NonNull String ssid) { - if (!mConnectivityHelper.isFirmwareRoamingSupported()) { - return; - } - ArrayList<String> bssidBlocklist = updateAndGetBssidBlocklistInternal() - .filter(entry -> ssid.equals(entry.ssid)) - .sorted((o1, o2) -> (int) (o2.blocklistEndTimeMs - o1.blocklistEndTimeMs)) - .map(entry -> entry.bssid) - .collect(Collectors.toCollection(ArrayList::new)); - int fwMaxBlocklistSize = mConnectivityHelper.getMaxNumBlacklistBssid(); - if (fwMaxBlocklistSize <= 0) { - Log.e(TAG, "Invalid max BSSID blocklist size: " + fwMaxBlocklistSize); - return; - } - // Having the blocklist size exceeding firmware max limit is unlikely because we have - // already flitered based on SSID. But just in case this happens, we are prioritizing - // sending down BSSIDs blocked for the longest time. - if (bssidBlocklist.size() > fwMaxBlocklistSize) { - bssidBlocklist = new ArrayList<String>(bssidBlocklist.subList(0, - fwMaxBlocklistSize)); - } - // plumb down to HAL - if (!mConnectivityHelper.setFirmwareRoamingConfiguration(bssidBlocklist, - new ArrayList<String>())) { // TODO(b/36488259): SSID whitelist management. - } - } - - @VisibleForTesting - public int getBssidStatusHistoryLoggerSize() { - return mBssidStatusHistoryLogger.size(); - } - - private class BssidStatusHistoryLogger { - private LinkedList<String> mLogHistory = new LinkedList<>(); - private int mBufferSize; - - BssidStatusHistoryLogger(int bufferSize) { - mBufferSize = bufferSize; - } - - public void add(BssidStatus bssidStatus, String trigger) { - // only log history for Bssids that had been blocked. - if (bssidStatus == null || !bssidStatus.isInBlocklist) { - return; - } - StringBuilder sb = new StringBuilder(); - mCalendar.setTimeInMillis(mClock.getWallClockMillis()); - sb.append(", logTimeMs=" - + String.format("%tm-%td %tH:%tM:%tS.%tL", mCalendar, mCalendar, - mCalendar, mCalendar, mCalendar, mCalendar)); - sb.append(", trigger=" + trigger); - mLogHistory.add(bssidStatus.toString() + sb.toString()); - if (mLogHistory.size() > mBufferSize) { - mLogHistory.removeFirst(); - } - } - - @VisibleForTesting - public int size() { - return mLogHistory.size(); - } - - public void dump(PrintWriter pw) { - pw.println("BssidBlocklistMonitor - Bssid blocklist history begin ----"); - for (String line : mLogHistory) { - pw.println(line); - } - pw.println("BssidBlocklistMonitor - Bssid blocklist history end ----"); - } - } - - /** - * Helper class that counts the number of failures per BSSID. - */ - private class BssidStatus { - public final String bssid; - public final String ssid; - public final int[] failureCount = new int[NUMBER_REASON_CODES]; - public int blockReason = INVALID_REASON; // reason of blocking this BSSID - // The latest RSSI that's seen before this BSSID is added to blocklist. - public int lastRssi = 0; - - // The following are used to flag how long this BSSID stays in the blocklist. - public boolean isInBlocklist; - public long blocklistEndTimeMs; - public long blocklistStartTimeMs; - - BssidStatus(String bssid, String ssid) { - this.bssid = bssid; - this.ssid = ssid; - } - - /** - * increments the failure count for the reasonCode by 1. - * @return the incremented failure count - */ - public int incrementFailureCount(int reasonCode) { - return ++failureCount[reasonCode]; - } - - /** - * Set this BSSID as blocked for the specified duration. - * @param durationMs - * @param blockReason - * @param rssi - */ - public void setAsBlocked(long durationMs, @FailureReason int blockReason, int rssi) { - isInBlocklist = true; - blocklistStartTimeMs = mClock.getWallClockMillis(); - blocklistEndTimeMs = blocklistStartTimeMs + durationMs; - this.blockReason = blockReason; - lastRssi = rssi; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("BSSID=" + bssid); - sb.append(", SSID=" + ssid); - sb.append(", isInBlocklist=" + isInBlocklist); - if (isInBlocklist) { - sb.append(", blockReason=" + getFailureReasonString(blockReason)); - sb.append(", lastRssi=" + lastRssi); - mCalendar.setTimeInMillis(blocklistStartTimeMs); - sb.append(", blocklistStartTimeMs=" - + String.format("%tm-%td %tH:%tM:%tS.%tL", mCalendar, mCalendar, - mCalendar, mCalendar, mCalendar, mCalendar)); - mCalendar.setTimeInMillis(blocklistEndTimeMs); - sb.append(", blocklistEndTimeMs=" - + String.format("%tm-%td %tH:%tM:%tS.%tL", mCalendar, mCalendar, - mCalendar, mCalendar, mCalendar, mCalendar)); - } - return sb.toString(); - } - } -} diff --git a/service/java/com/android/server/wifi/BubbleFunScorer.java b/service/java/com/android/server/wifi/BubbleFunScorer.java deleted file mode 100644 index fd18c14eb..000000000 --- a/service/java/com/android/server/wifi/BubbleFunScorer.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.net.wifi.ScanResult; - -import com.android.server.wifi.WifiCandidates.Candidate; -import com.android.server.wifi.WifiCandidates.ScoredCandidate; - -import java.util.Collection; - -/** - * A CandidateScorer that weights the RSSIs for more compactly-shaped - * regions of selection around access points. - */ -final class BubbleFunScorer implements WifiCandidates.CandidateScorer { - - /** - * This should match WifiNetworkSelector.experimentIdFromIdentifier(getIdentifier()) - * when using the default ScoringParams. - */ - public static final int BUBBLE_FUN_SCORER_DEFAULT_EXPID = 42598152; - - private static final double SECURITY_AWARD = 44.0; - private static final double CURRENT_NETWORK_BOOST = 22.0; - private static final double LAST_SELECTION_BOOST = 250.0; - private static final double LOW_BAND_FACTOR = 0.25; - private static final double TYPICAL_SCAN_RSSI_STD = 4.0; - private static final boolean USE_USER_CONNECT_CHOICE = true; - - private final ScoringParams mScoringParams; - - BubbleFunScorer(ScoringParams scoringParams) { - mScoringParams = scoringParams; - } - - @Override - public String getIdentifier() { - return "BubbleFunScorer_v2"; - } - - /** - * Calculates an individual candidate's score. - * - * Ideally, this is a pure function of the candidate, and side-effect free. - */ - private ScoredCandidate scoreCandidate(Candidate candidate) { - final int rssi = candidate.getScanRssi(); - final int rssiEntryThreshold = mScoringParams.getEntryRssi(candidate.getFrequency()); - - double score = shapeFunction(rssi) - shapeFunction(rssiEntryThreshold); - - // If we are below the entry threshold, make the score more negative - if (score < 0.0) score *= 2.0; - - // The gain is approximately the derivative of shapeFunction at the given rssi - // This is used to estimate the error - double gain = shapeFunction(rssi + 0.5) - - shapeFunction(rssi - 0.5); - - // Prefer 5GHz/6GHz when all are strong, but at the fringes, 2.4 might be better - // Typically the entry rssi is lower for the 2.4 band, which provides the fringe boost - if (ScanResult.is24GHz(candidate.getFrequency())) { - score *= LOW_BAND_FACTOR; - gain *= LOW_BAND_FACTOR; - } - - // A recently selected network gets a large boost - score += candidate.getLastSelectionWeight() * LAST_SELECTION_BOOST; - - // Hysteresis to prefer staying on the current network. - if (candidate.isCurrentNetwork()) { - score += CURRENT_NETWORK_BOOST; - } - - if (!candidate.isOpenNetwork()) { - score += SECURITY_AWARD; - } - - return new ScoredCandidate(score, TYPICAL_SCAN_RSSI_STD * gain, - USE_USER_CONNECT_CHOICE, candidate); - } - - /** - * Reshapes raw RSSI into a value that varies more usefully for scoring purposes. - * - * The most important aspect of this function is that it is monotone (has - * positive slope). The offset and scale are not important, because the - * calculation above uses differences that cancel out the offset, and - * a rescaling here effects all the candidates' scores in the same way. - * However, we choose to scale things for an overall range of about 100 for - * useful values of RSSI. - */ - private static double unscaledShapeFunction(double rssi) { - return -Math.exp(-rssi * BELS_PER_DECIBEL); - } - private static final double BELS_PER_DECIBEL = 0.1; - - private static final double RESCALE_FACTOR = 100.0 / ( - unscaledShapeFunction(0.0) - unscaledShapeFunction(-85.0)); - private static double shapeFunction(double rssi) { - return unscaledShapeFunction(rssi) * RESCALE_FACTOR; - } - - @Override - public ScoredCandidate scoreCandidates(@NonNull Collection<Candidate> candidates) { - ScoredCandidate choice = ScoredCandidate.NONE; - for (Candidate candidate : candidates) { - ScoredCandidate scoredCandidate = scoreCandidate(candidate); - if (scoredCandidate.value > choice.value) { - choice = scoredCandidate; - } - } - // Here we just return the highest scored candidate; we could - // compute a new score, if desired. - return choice; - } - -} diff --git a/service/java/com/android/server/wifi/BuildProperties.java b/service/java/com/android/server/wifi/BuildProperties.java deleted file mode 100644 index 9b9204bbe..000000000 --- a/service/java/com/android/server/wifi/BuildProperties.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import com.android.internal.annotations.VisibleForTesting; - -/** Abstraction of android.os.Build, to enable mocking statics for testing. */ -@VisibleForTesting -public interface BuildProperties { - /** Returns true iff this is an eng build. */ - boolean isEngBuild(); - - /** Returns true iff this is a userdebug build. */ - boolean isUserdebugBuild(); - - /** Returns true iff this a normal user build (not userdebug). */ - boolean isUserBuild(); -} diff --git a/service/java/com/android/server/wifi/ByteBufferReader.java b/service/java/com/android/server/wifi/ByteBufferReader.java deleted file mode 100644 index 91598af5f..000000000 --- a/service/java/com/android/server/wifi/ByteBufferReader.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2016 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.Wifi - */ - -package com.android.server.wifi; - -import com.android.internal.annotations.VisibleForTesting; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.Charset; - -/** - * Utility class for reading generic data (e.g. various length integer, string) from ByteBuffer. - */ -public class ByteBufferReader { - @VisibleForTesting - public static final int MINIMUM_INTEGER_SIZE = Byte.BYTES; - - @VisibleForTesting - public static final int MAXIMUM_INTEGER_SIZE = Long.BYTES; - - /** - * Read an integer value from a buffer. - * - * @param payload The buffer to read from - * @param byteOrder Byte order of the buffer - * @param size The number of bytes to read from the buffer - * @return The integer value - * @throws BufferUnderflowException - * @throws IllegalArgumentException - */ - public static long readInteger(ByteBuffer payload, ByteOrder byteOrder, int size) { - if (size < MINIMUM_INTEGER_SIZE || size > MAXIMUM_INTEGER_SIZE) { - throw new IllegalArgumentException("Invalid size " + size); - } - - // Read the necessary bytes. - byte[] octets = new byte[size]; - payload.get(octets); - - // Format the value based on byte order. - long value = 0; - if (byteOrder == ByteOrder.LITTLE_ENDIAN) { - for (int n = octets.length - 1; n >= 0; n--) { - value = (value << Byte.SIZE) | (octets[n] & 0xFF); - } - } else { - for (byte octet : octets) { - value = (value << Byte.SIZE) | (octet & 0xFF); - } - } - return value; - } - - /** - * Read a string from a buffer. An empty String will be returned for a String with 0 length. - * - * @param payload The buffer to read from - * @param length Number of bytes to read from the buffer - * @param charset The character set of the string - * @return {@link String} - * @throws BufferUnderflowException - * @throws NegativeArraySizeException - */ - public static String readString(ByteBuffer payload, int length, Charset charset) { - byte[] octets = new byte[length]; - payload.get(octets); - return new String(octets, charset); - } - - /** - * Read a string from a buffer where the string value is preceded by the length of the string - * (1 byte) in the buffer. - * - * @param payload The buffer to read from - * @param charset The character set of the string - * @return {@link String} - * @throws BufferUnderflowException - */ - public static String readStringWithByteLength(ByteBuffer payload, Charset charset) { - int length = payload.get() & 0xFF; - return readString(payload, length, charset); - } -} diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java deleted file mode 100644 index 3a24f3580..000000000 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ /dev/null @@ -1,6602 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT; -import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY; -import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256; -import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384; -import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; -import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; -import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; -import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; -import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; - -import static com.android.server.wifi.WifiDataStall.INVALID_THROUGHPUT; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.bluetooth.BluetoothAdapter; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.DhcpResultsParcelable; -import android.net.InvalidPacketException; -import android.net.IpConfiguration; -import android.net.KeepalivePacketData; -import android.net.Layer2PacketParcelable; -import android.net.LinkProperties; -import android.net.MacAddress; -import android.net.MatchAllNetworkSpecifier; -import android.net.NattKeepalivePacketData; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; -import android.net.NetworkProvider; -import android.net.SocketKeepalive; -import android.net.StaticIpConfiguration; -import android.net.TcpKeepalivePacketData; -import android.net.Uri; -import android.net.ip.IIpClient; -import android.net.ip.IpClientCallbacks; -import android.net.ip.IpClientManager; -import android.net.shared.Layer2Information; -import android.net.shared.ProvisioningConfiguration; -import android.net.shared.ProvisioningConfiguration.ScanResultInfo; -import android.net.util.MacAddressUtils; -import android.net.util.NetUtils; -import android.net.wifi.IActionListener; -import android.net.wifi.INetworkRequestMatchCallback; -import android.net.wifi.ScanResult; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiAnnotations.WifiStandard; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.DeviceMobilityState; -import android.net.wifi.WifiNetworkAgentSpecifier; -import android.net.wifi.WifiScanner; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.nl80211.DeviceWiphyCapabilities; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.net.wifi.p2p.WifiP2pManager; -import android.os.BatteryStatsManager; -import android.os.Bundle; -import android.os.ConditionVariable; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.PowerManager; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.WorkSource; -import android.provider.Settings; -import android.system.OsConstants; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; -import android.util.SparseArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; -import com.android.internal.util.MessageUtils; -import com.android.internal.util.Protocol; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import com.android.net.module.util.Inet4AddressUtils; -import com.android.server.wifi.MboOceController.BtmFrameData; -import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData; -import com.android.server.wifi.WifiCarrierInfoManager.SimAuthResponseData; -import com.android.server.wifi.hotspot2.AnqpEvent; -import com.android.server.wifi.hotspot2.IconEvent; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.hotspot2.WnmData; -import com.android.server.wifi.p2p.WifiP2pServiceImpl; -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; -import com.android.server.wifi.util.ExternalCallbackTracker; -import com.android.server.wifi.util.NativeUtil; -import com.android.server.wifi.util.RssiUtil; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; -import com.android.wifi.resources.R; - -import java.io.BufferedReader; -import java.io.FileDescriptor; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Implementation of ClientMode. Event handling for Client mode logic is done here, - * and all changes in connectivity state are initiated here. - * - * @hide - */ -public class ClientModeImpl extends StateMachine { - - private static final String NETWORKTYPE = "WIFI"; - @VisibleForTesting public static final short NUM_LOG_RECS_NORMAL = 100; - @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE_LOW_MEMORY = 200; - @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE = 3000; - - // Association rejection reason codes - @VisibleForTesting - protected static final int REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; - - private static final String TAG = "WifiClientModeImpl"; - - private static final int ONE_HOUR_MILLI = 1000 * 60 * 60; - - private static final String GOOGLE_OUI = "DA-A1-19"; - - private static final String EXTRA_OSU_ICON_QUERY_BSSID = "BSSID"; - private static final String EXTRA_OSU_ICON_QUERY_FILENAME = "FILENAME"; - private static final String EXTRA_OSU_PROVIDER = "OsuProvider"; - private static final String EXTRA_UID = "uid"; - private static final String EXTRA_PACKAGE_NAME = "PackageName"; - private static final String EXTRA_PASSPOINT_CONFIGURATION = "PasspointConfiguration"; - private static final int IPCLIENT_STARTUP_TIMEOUT_MS = 20 * 60 * 1000; // 20 minutes! - private static final int IPCLIENT_SHUTDOWN_TIMEOUT_MS = 60_000; // 60 seconds - - private boolean mVerboseLoggingEnabled = false; - private final WifiPermissionsWrapper mWifiPermissionsWrapper; - - /* debug flag, indicating if handling of ASSOCIATION_REJECT ended up blacklisting - * the corresponding BSSID. - */ - private boolean mDidBlackListBSSID = false; - - /** - * Log with error attribute - * - * @param s is string log - */ - @Override - protected void loge(String s) { - Log.e(getName(), s); - } - @Override - protected void logd(String s) { - Log.d(getName(), s); - } - @Override - protected void log(String s) { - Log.d(getName(), s); - } - private final WifiMetrics mWifiMetrics; - private final WifiInjector mWifiInjector; - private final WifiMonitor mWifiMonitor; - private final WifiNative mWifiNative; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final WifiConfigManager mWifiConfigManager; - private final WifiConnectivityManager mWifiConnectivityManager; - private final BssidBlocklistMonitor mBssidBlocklistMonitor; - private ConnectivityManager mCm; - private BaseWifiDiagnostics mWifiDiagnostics; - private final boolean mP2pSupported; - private final AtomicBoolean mP2pConnected = new AtomicBoolean(false); - private boolean mTemporarilyDisconnectWifi = false; - private final Clock mClock; - private final PropertyService mPropertyService; - private final BuildProperties mBuildProperties; - private final WifiCountryCode mCountryCode; - private final WifiScoreCard mWifiScoreCard; - private final WifiHealthMonitor mWifiHealthMonitor; - private final WifiScoreReport mWifiScoreReport; - private final SarManager mSarManager; - private final WifiTrafficPoller mWifiTrafficPoller; - public WifiScoreReport getWifiScoreReport() { - return mWifiScoreReport; - } - private final PasspointManager mPasspointManager; - private final WifiDataStall mWifiDataStall; - private final LinkProbeManager mLinkProbeManager; - private final MboOceController mMboOceController; - - private final McastLockManagerFilterController mMcastLockManagerFilterController; - private final ActivityManager mActivityManager; - - private boolean mScreenOn = false; - - private String mInterfaceName; - - private int mLastSignalLevel = -1; - private String mLastBssid; - private int mLastNetworkId; // The network Id we successfully joined - // The subId used by WifiConfiguration with SIM credential which was connected successfully - private int mLastSubId; - private String mLastSimBasedConnectionCarrierName; - - private boolean mIpReachabilityDisconnectEnabled = true; - - private void processRssiThreshold(byte curRssi, int reason, - WifiNative.WifiRssiEventHandler rssiHandler) { - if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) { - Log.wtf(TAG, "processRssiThreshold: Invalid rssi " + curRssi); - return; - } - for (int i = 0; i < mRssiRanges.length; i++) { - if (curRssi < mRssiRanges[i]) { - // Assume sorted values(ascending order) for rssi, - // bounded by high(127) and low(-128) at extremeties - byte maxRssi = mRssiRanges[i]; - byte minRssi = mRssiRanges[i - 1]; - // This value of hw has to be believed as this value is averaged and has breached - // the rssi thresholds and raised event to host. This would be eggregious if this - // value is invalid - mWifiInfo.setRssi(curRssi); - updateCapabilities(); - int ret = startRssiMonitoringOffload(maxRssi, minRssi, rssiHandler); - Log.d(TAG, "Re-program RSSI thresholds for " + getWhatToString(reason) - + ": [" + minRssi + ", " + maxRssi + "], curRssi=" + curRssi - + " ret=" + ret); - break; - } - } - } - - private boolean mEnableRssiPolling = false; - // Accessed via Binder thread ({get,set}PollRssiIntervalMsecs), and the main Wifi thread. - private volatile int mPollRssiIntervalMsecs = -1; - private int mRssiPollToken = 0; - /* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE - * In CONNECT_MODE, the STA can scan and connect to an access point - * In SCAN_ONLY_MODE, the STA can only scan for access points - * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off - */ - private int mOperationalMode = DISABLED_MODE; - - // variable indicating we are expecting a mode switch - do not attempt recovery for failures - private boolean mModeChange = false; - - private ClientModeManager.Listener mClientModeCallback = null; - - private boolean mBluetoothConnectionActive = false; - - private PowerManager.WakeLock mSuspendWakeLock; - - /** - * Maximum allowable interval in milliseconds between polling for RSSI and linkspeed - * information. This is also used as the polling interval for WifiTrafficPoller, which updates - * its data activity on every CMD_RSSI_POLL. - */ - private static final int MAXIMUM_POLL_RSSI_INTERVAL_MSECS = 6000; - - /** - * Interval in milliseconds between receiving a disconnect event - * while connected to a good AP, and handling the disconnect proper - */ - private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 4000; - - /** - * Delay between supplicant restarts upon failure to establish connection - */ - private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000; - - /** - * Number of times we attempt to restart supplicant - */ - private static final int SUPPLICANT_RESTART_TRIES = 5; - - /** - * Value to set in wpa_supplicant "bssid" field when we don't want to restrict connection to - * a specific AP. - */ - public static final String SUPPLICANT_BSSID_ANY = "any"; - - /** - * The link properties of the wifi interface. - * Do not modify this directly; use updateLinkProperties instead. - */ - private LinkProperties mLinkProperties; - - /* Tracks sequence number on a periodic scan message */ - private int mPeriodicScanToken = 0; - - private Context mContext; - - private final Object mDhcpResultsParcelableLock = new Object(); - @NonNull - private DhcpResultsParcelable mDhcpResultsParcelable = new DhcpResultsParcelable(); - - // NOTE: Do not return to clients - see syncRequestConnectionInfo() - private final ExtendedWifiInfo mWifiInfo; - // TODO : remove this member. It should be possible to only call sendNetworkChangeBroadcast when - // the state actually changed, and to deduce the state of the agent from the state of the - // machine when generating the NetworkInfo for the broadcast. - private DetailedState mNetworkAgentState; - private SupplicantStateTracker mSupplicantStateTracker; - - // Indicates that framework is attempting to roam, set true on CMD_START_ROAM, set false when - // wifi connects or fails to connect - private boolean mIsAutoRoaming = false; - - // Roaming failure count - private int mRoamFailCount = 0; - - // This is the BSSID we are trying to associate to, it can be set to SUPPLICANT_BSSID_ANY - // if we havent selected a BSSID for joining. - private String mTargetBssid = SUPPLICANT_BSSID_ANY; - // This one is used to track the current target network ID. This is used for error - // handling during connection setup since many error message from supplicant does not report - // SSID. Once connected, it will be set to invalid - private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - private long mLastDriverRoamAttempt = 0; - private WifiConfiguration mTargetWifiConfiguration = null; - - int getPollRssiIntervalMsecs() { - if (mPollRssiIntervalMsecs > 0) { - return mPollRssiIntervalMsecs; - } - return Math.min(mContext.getResources().getInteger( - R.integer.config_wifiPollRssiIntervalMilliseconds), - MAXIMUM_POLL_RSSI_INTERVAL_MSECS); - } - - void setPollRssiIntervalMsecs(int newPollIntervalMsecs) { - mPollRssiIntervalMsecs = newPollIntervalMsecs; - } - - /** - * Method to clear {@link #mTargetBssid} and reset the current connected network's - * bssid in wpa_supplicant after a roam/connect attempt. - */ - public boolean clearTargetBssid(String dbg) { - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); - if (config == null) { - return false; - } - String bssid = SUPPLICANT_BSSID_ANY; - if (config.BSSID != null) { - bssid = config.BSSID; - if (mVerboseLoggingEnabled) { - Log.d(TAG, "force BSSID to " + bssid + "due to config"); - } - } - if (mVerboseLoggingEnabled) { - logd(dbg + " clearTargetBssid " + bssid + " key=" + config.getKey()); - } - mTargetBssid = bssid; - return mWifiNative.setConfiguredNetworkBSSID(mInterfaceName, bssid); - } - - /** - * Set Config's default BSSID (for association purpose) and {@link #mTargetBssid} - * @param config config need set BSSID - * @param bssid default BSSID to assocaite with when connect to this network - * @return false -- does not change the current default BSSID of the configure - * true -- change the current default BSSID of the configur - */ - private boolean setTargetBssid(WifiConfiguration config, String bssid) { - if (config == null || bssid == null) { - return false; - } - if (config.BSSID != null) { - bssid = config.BSSID; - if (mVerboseLoggingEnabled) { - Log.d(TAG, "force BSSID to " + bssid + "due to config"); - } - } - if (mVerboseLoggingEnabled) { - Log.d(TAG, "setTargetBssid set to " + bssid + " key=" + config.getKey()); - } - mTargetBssid = bssid; - config.getNetworkSelectionStatus().setNetworkSelectionBSSID(bssid); - return true; - } - - private volatile IpClientManager mIpClient; - private IpClientCallbacksImpl mIpClientCallbacks; - - // Channel for sending replies. - private AsyncChannel mReplyChannel = new AsyncChannel(); - - // Used to initiate a connection with WifiP2pService - private AsyncChannel mWifiP2pChannel; - - private WifiNetworkFactory mNetworkFactory; - private UntrustedWifiNetworkFactory mUntrustedNetworkFactory; - private WifiNetworkAgent mNetworkAgent; - - private byte[] mRssiRanges; - - // Used to filter out requests we couldn't possibly satisfy. - private final NetworkCapabilities mNetworkCapabilitiesFilter; - - private final ExternalCallbackTracker<IActionListener> mProcessingActionListeners; - - /* The base for wifi message types */ - static final int BASE = Protocol.BASE_WIFI; - /* BT state change, e.g., on or off */ - static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31; - /* BT connection state change, e.g., connected or disconnected */ - static final int CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE = BASE + 32; - - /* Get adaptors */ - static final int CMD_GET_SUPPORTED_FEATURES = BASE + 61; - /* Get Link Layer Stats thru HAL */ - static final int CMD_GET_LINK_LAYER_STATS = BASE + 63; - /* Supplicant commands after driver start*/ - /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */ - static final int CMD_SET_OPERATIONAL_MODE = BASE + 72; - /* Disconnect from a network */ - static final int CMD_DISCONNECT = BASE + 73; - /* Reconnect to a network */ - static final int CMD_RECONNECT = BASE + 74; - /* Reassociate to a network */ - static final int CMD_REASSOCIATE = BASE + 75; - - /* Controls suspend mode optimizations - * - * When high perf mode is enabled, suspend mode optimizations are disabled - * - * When high perf mode is disabled, suspend mode optimizations are enabled - * - * Suspend mode optimizations include: - * - packet filtering - * - turn off roaming - * - DTIM wake up settings - */ - static final int CMD_SET_HIGH_PERF_MODE = BASE + 77; - /* Enables RSSI poll */ - static final int CMD_ENABLE_RSSI_POLL = BASE + 82; - /* RSSI poll */ - static final int CMD_RSSI_POLL = BASE + 83; - /** Runs RSSI poll once */ - static final int CMD_ONESHOT_RSSI_POLL = BASE + 84; - /* Enable suspend mode optimizations in the driver */ - static final int CMD_SET_SUSPEND_OPT_ENABLED = BASE + 86; - - /* Enable TDLS on a specific MAC address */ - static final int CMD_ENABLE_TDLS = BASE + 92; - - /** - * Watchdog for protecting against b/16823537 - * Leave time for 4-way handshake to succeed - */ - static final int ROAM_GUARD_TIMER_MSEC = 15000; - - int mRoamWatchdogCount = 0; - /* Roam state watchdog */ - static final int CMD_ROAM_WATCHDOG_TIMER = BASE + 94; - /* Screen change intent handling */ - static final int CMD_SCREEN_STATE_CHANGED = BASE + 95; - - /* Disconnecting state watchdog */ - static final int CMD_DISCONNECTING_WATCHDOG_TIMER = BASE + 96; - - /* SIM is removed; reset any cached data for it */ - static final int CMD_RESET_SIM_NETWORKS = BASE + 101; - - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"RESET_SIM_REASON_"}, - value = { - RESET_SIM_REASON_SIM_REMOVED, - RESET_SIM_REASON_SIM_INSERTED, - RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED}) - @interface ResetSimReason {} - static final int RESET_SIM_REASON_SIM_REMOVED = 0; - static final int RESET_SIM_REASON_SIM_INSERTED = 1; - static final int RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED = 2; - - /* OSU APIs */ - static final int CMD_QUERY_OSU_ICON = BASE + 104; - - /* Commands from/to the SupplicantStateTracker */ - /* Reset the supplicant state tracker */ - static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111; - - int mDisconnectingWatchdogCount = 0; - static final int DISCONNECTING_GUARD_TIMER_MSEC = 5000; - - /** - * Indicates the end of boot process, should be used to trigger load from config store, - * initiate connection attempt, etc. - * */ - static final int CMD_BOOT_COMPLETED = BASE + 134; - /** - * Initialize ClientModeImpl. This is currently used to initialize the - * {@link HalDeviceManager} module. - */ - static final int CMD_INITIALIZE = BASE + 135; - - /* We now have a valid IP configuration. */ - static final int CMD_IP_CONFIGURATION_SUCCESSFUL = BASE + 138; - /* We no longer have a valid IP configuration. */ - static final int CMD_IP_CONFIGURATION_LOST = BASE + 139; - /* Link configuration (IP address, DNS, ...) changes notified via netlink */ - static final int CMD_UPDATE_LINKPROPERTIES = BASE + 140; - - static final int CMD_START_CONNECT = BASE + 143; - - private static final int NETWORK_STATUS_UNWANTED_DISCONNECT = 0; - private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED = 1; - private static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN = 2; - - static final int CMD_UNWANTED_NETWORK = BASE + 144; - - static final int CMD_START_ROAM = BASE + 145; - - static final int CMD_NETWORK_STATUS = BASE + 148; - - /* A layer 3 neighbor on the Wi-Fi link became unreachable. */ - static final int CMD_IP_REACHABILITY_LOST = BASE + 149; - - static final int CMD_ACCEPT_UNVALIDATED = BASE + 153; - - /* used to offload sending IP packet */ - static final int CMD_START_IP_PACKET_OFFLOAD = BASE + 160; - - /* used to stop offload sending IP packet */ - static final int CMD_STOP_IP_PACKET_OFFLOAD = BASE + 161; - - /* used to start rssi monitoring in hw */ - static final int CMD_START_RSSI_MONITORING_OFFLOAD = BASE + 162; - - /* used to stop rssi moniroting in hw */ - static final int CMD_STOP_RSSI_MONITORING_OFFLOAD = BASE + 163; - - /* used to indicated RSSI threshold breach in hw */ - static final int CMD_RSSI_THRESHOLD_BREACHED = BASE + 164; - - /** - * Used to handle messages bounced between ClientModeImpl and IpClient. - */ - static final int CMD_IPV4_PROVISIONING_SUCCESS = BASE + 200; - static final int CMD_IPV4_PROVISIONING_FAILURE = BASE + 201; - - /* Push a new APF program to the HAL */ - static final int CMD_INSTALL_PACKET_FILTER = BASE + 202; - - /* Enable/disable fallback packet filtering */ - static final int CMD_SET_FALLBACK_PACKET_FILTERING = BASE + 203; - - /* Enable/disable Neighbor Discovery offload functionality. */ - static final int CMD_CONFIG_ND_OFFLOAD = BASE + 204; - - /* Read the APF program & data buffer */ - static final int CMD_READ_PACKET_FILTER = BASE + 208; - - /** Used to add packet filter to apf. */ - static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = BASE + 209; - - /** Used to remove packet filter from apf. */ - static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = BASE + 210; - - /* Indicates that diagnostics should time out a connection start event. */ - static final int CMD_DIAGS_CONNECT_TIMEOUT = BASE + 252; - - // Start subscription provisioning with a given provider - private static final int CMD_START_SUBSCRIPTION_PROVISIONING = BASE + 254; - - @VisibleForTesting - static final int CMD_PRE_DHCP_ACTION = BASE + 255; - private static final int CMD_PRE_DHCP_ACTION_COMPLETE = BASE + 256; - private static final int CMD_POST_DHCP_ACTION = BASE + 257; - - private static final int CMD_CONNECT_NETWORK = BASE + 258; - private static final int CMD_SAVE_NETWORK = BASE + 259; - - /* Start connection to FILS AP*/ - static final int CMD_START_FILS_CONNECTION = BASE + 262; - - private static final int CMD_GET_CURRENT_NETWORK = BASE + 263; - - // For message logging. - private static final Class[] sMessageClasses = { - AsyncChannel.class, ClientModeImpl.class }; - private static final SparseArray<String> sGetWhatToString = - MessageUtils.findMessageNames(sMessageClasses); - - - /* Wifi state machine modes of operation */ - /* CONNECT_MODE - connect to any 'known' AP when it becomes available */ - public static final int CONNECT_MODE = 1; - /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */ - public static final int SCAN_ONLY_MODE = 2; - /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */ - public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3; - /* DISABLED_MODE - Don't connect, don't scan, don't be an AP */ - public static final int DISABLED_MODE = 4; - - private static final int SUCCESS = 1; - private static final int FAILURE = -1; - - /* Tracks if suspend optimizations need to be disabled by DHCP, - * screen or due to high perf mode. - * When any of them needs to disable it, we keep the suspend optimizations - * disabled - */ - private int mSuspendOptNeedsDisabled = 0; - - private static final int SUSPEND_DUE_TO_DHCP = 1; - private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1; - private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2; - - /** - * Time window in milliseconds for which we send - * {@link NetworkAgent#explicitlySelected(boolean, boolean)} - * after connecting to the network which the user last selected. - */ - @VisibleForTesting - public static final int LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS = 30 * 1000; - - /* Tracks if user has enabled Connected Mac Randomization through settings */ - - /** - * Supplicant scan interval in milliseconds. - * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or - * from the default config if the setting is not set - */ - private long mSupplicantScanIntervalMs; - - int mRunningBeaconCount = 0; - - /* Default parent state */ - private State mDefaultState = new DefaultState(); - /* Connecting to an access point */ - private State mConnectModeState = new ConnectModeState(); - /* Connected at 802.11 (L2) level */ - private State mL2ConnectedState = new L2ConnectedState(); - /* fetching IP after connection to access point (assoc+auth complete) */ - private State mObtainingIpState = new ObtainingIpState(); - /* Connected with IP addr */ - private State mConnectedState = new ConnectedState(); - /* Roaming */ - private State mRoamingState = new RoamingState(); - /* disconnect issued, waiting for network disconnect confirmation */ - private State mDisconnectingState = new DisconnectingState(); - /* Network is not connected, supplicant assoc+auth is not complete */ - private State mDisconnectedState = new DisconnectedState(); - - /* - * FILS connection related variables. - */ - /* To indicate to IpClient whether HLP IEs were included or not in assoc request */ - private boolean mSentHLPs = false; - /* Tracks IpClient start state until (FILS_)NETWORK_CONNECTION_EVENT event */ - private boolean mIpClientWithPreConnection = false; - - /** - * One of {@link WifiManager#WIFI_STATE_DISABLED}, - * {@link WifiManager#WIFI_STATE_DISABLING}, - * {@link WifiManager#WIFI_STATE_ENABLED}, - * {@link WifiManager#WIFI_STATE_ENABLING}, - * {@link WifiManager#WIFI_STATE_UNKNOWN} - */ - private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED); - - /** - * Work source to use to blame usage on the WiFi service - */ - public static final WorkSource WIFI_WORK_SOURCE = new WorkSource(Process.WIFI_UID); - - private final BatteryStatsManager mBatteryStatsManager; - - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - - - // Used for debug and stats gathering - private static int sScanAlarmIntentCount = 0; - - private FrameworkFacade mFacade; - private WifiStateTracker mWifiStateTracker; - private final BackupManagerProxy mBackupManagerProxy; - private final WrongPasswordNotifier mWrongPasswordNotifier; - private final EapFailureNotifier mEapFailureNotifier; - private final SimRequiredNotifier mSimRequiredNotifier; - private final ConnectionFailureNotifier mConnectionFailureNotifier; - private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - // Maximum duration to continue to log Wifi usability stats after a data stall is triggered. - @VisibleForTesting - public static final long DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS = 30 * 1000; - private long mDataStallTriggerTimeMs = -1; - private int mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN; - - public ClientModeImpl(Context context, FrameworkFacade facade, Looper looper, - UserManager userManager, WifiInjector wifiInjector, - BackupManagerProxy backupManagerProxy, WifiCountryCode countryCode, - WifiNative wifiNative, WrongPasswordNotifier wrongPasswordNotifier, - SarManager sarManager, WifiTrafficPoller wifiTrafficPoller, - LinkProbeManager linkProbeManager, - BatteryStatsManager batteryStatsManager, - SupplicantStateTracker supplicantStateTracker, - MboOceController mboOceController, - WifiCarrierInfoManager wifiCarrierInfoManager, - EapFailureNotifier eapFailureNotifier, - SimRequiredNotifier simRequiredNotifier) { - super(TAG, looper); - mWifiInjector = wifiInjector; - mWifiMetrics = mWifiInjector.getWifiMetrics(); - mClock = wifiInjector.getClock(); - mPropertyService = wifiInjector.getPropertyService(); - mBuildProperties = wifiInjector.getBuildProperties(); - mWifiScoreCard = wifiInjector.getWifiScoreCard(); - mContext = context; - mFacade = facade; - mWifiNative = wifiNative; - mBackupManagerProxy = backupManagerProxy; - mWrongPasswordNotifier = wrongPasswordNotifier; - mEapFailureNotifier = eapFailureNotifier; - mSimRequiredNotifier = simRequiredNotifier; - mSarManager = sarManager; - mWifiTrafficPoller = wifiTrafficPoller; - mLinkProbeManager = linkProbeManager; - mMboOceController = mboOceController; - mWifiCarrierInfoManager = wifiCarrierInfoManager; - mNetworkAgentState = DetailedState.DISCONNECTED; - - mBatteryStatsManager = batteryStatsManager; - mWifiStateTracker = wifiInjector.getWifiStateTracker(); - - mP2pSupported = mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_DIRECT); - - mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); - mWifiConfigManager = mWifiInjector.getWifiConfigManager(); - - mPasspointManager = mWifiInjector.getPasspointManager(); - - mWifiMonitor = mWifiInjector.getWifiMonitor(); - mWifiDiagnostics = mWifiInjector.getWifiDiagnostics(); - mWifiPermissionsWrapper = mWifiInjector.getWifiPermissionsWrapper(); - mWifiDataStall = mWifiInjector.getWifiDataStall(); - - mWifiInfo = new ExtendedWifiInfo(context); - mSupplicantStateTracker = supplicantStateTracker; - mWifiConnectivityManager = mWifiInjector.makeWifiConnectivityManager(this); - mBssidBlocklistMonitor = mWifiInjector.getBssidBlocklistMonitor(); - mConnectionFailureNotifier = mWifiInjector.makeConnectionFailureNotifier( - mWifiConnectivityManager); - - mLinkProperties = new LinkProperties(); - mMcastLockManagerFilterController = new McastLockManagerFilterController(); - mActivityManager = context.getSystemService(ActivityManager.class); - - mLastBssid = null; - mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - mLastSimBasedConnectionCarrierName = null; - mLastSignalLevel = -1; - - mCountryCode = countryCode; - - mWifiScoreReport = new WifiScoreReport(mWifiInjector.getScoringParams(), mClock, - mWifiMetrics, mWifiInfo, mWifiNative, mBssidBlocklistMonitor, - mWifiInjector.getWifiThreadRunner(), mWifiInjector.getDeviceConfigFacade(), - mContext, looper, mFacade); - - mNetworkCapabilitiesFilter = new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) - // TODO - needs to be a bit more dynamic - .setLinkUpstreamBandwidthKbps(1024 * 1024) - .setLinkDownstreamBandwidthKbps(1024 * 1024) - .setNetworkSpecifier(new MatchAllNetworkSpecifier()) - .build(); - // Make the network factories. - mNetworkFactory = mWifiInjector.makeWifiNetworkFactory( - mNetworkCapabilitiesFilter, mWifiConnectivityManager); - // We can't filter untrusted network in the capabilities filter because a trusted - // network would still satisfy a request that accepts untrusted ones. - // We need a second network factory for untrusted network requests because we need a - // different score filter for these requests. - mUntrustedNetworkFactory = mWifiInjector.makeUntrustedWifiNetworkFactory( - mNetworkCapabilitiesFilter, mWifiConnectivityManager); - - mWifiNetworkSuggestionsManager = mWifiInjector.getWifiNetworkSuggestionsManager(); - mProcessingActionListeners = new ExternalCallbackTracker<>(getHandler()); - mWifiHealthMonitor = mWifiInjector.getWifiHealthMonitor(); - - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_SCREEN_ON); - filter.addAction(Intent.ACTION_SCREEN_OFF); - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - - if (action.equals(Intent.ACTION_SCREEN_ON)) { - sendMessage(CMD_SCREEN_STATE_CHANGED, 1); - } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { - sendMessage(CMD_SCREEN_STATE_CHANGED, 0); - } - } - }, filter); - - PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - - mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend"); - mSuspendWakeLock.setReferenceCounted(false); - - mWifiConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener()); - - // CHECKSTYLE:OFF IndentationCheck - addState(mDefaultState); - addState(mConnectModeState, mDefaultState); - addState(mL2ConnectedState, mConnectModeState); - addState(mObtainingIpState, mL2ConnectedState); - addState(mConnectedState, mL2ConnectedState); - addState(mRoamingState, mL2ConnectedState); - addState(mDisconnectingState, mConnectModeState); - addState(mDisconnectedState, mConnectModeState); - // CHECKSTYLE:ON IndentationCheck - - setInitialState(mDefaultState); - - setLogRecSize(NUM_LOG_RECS_NORMAL); - setLogOnlyTransitions(false); - } - - @Override - public void start() { - super.start(); - - PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - - // Learn the initial state of whether the screen is on. - // We update this field when we receive broadcasts from the system. - handleScreenStateChanged(powerManager.isInteractive()); - } - - private void registerForWifiMonitorEvents() { - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.TARGET_BSSID_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATED_BSSID_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ANQP_DONE_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_DONE_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_START_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.HS20_REMEDIATION_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_IDENTITY, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_SIM_AUTH, - getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, - mWifiMetrics.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - mWifiMetrics.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, - mWifiMetrics.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT, - mWifiMetrics.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, - mWifiMetrics.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATED_BSSID_EVENT, - mWifiMetrics.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.TARGET_BSSID_EVENT, - mWifiMetrics.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, - mWifiInjector.getWifiLastResortWatchdog().getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, - mSupplicantStateTracker.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - mSupplicantStateTracker.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, - mSupplicantStateTracker.getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, - getHandler()); - } - - private void setMulticastFilter(boolean enabled) { - if (mIpClient != null) { - mIpClient.setMulticastFilter(enabled); - } - } - - /** - * Class to implement the MulticastLockManager.FilterController callback. - */ - class McastLockManagerFilterController implements WifiMulticastLockManager.FilterController { - /** - * Start filtering Multicast v4 packets - */ - public void startFilteringMulticastPackets() { - setMulticastFilter(true); - } - - /** - * Stop filtering Multicast v4 packets - */ - public void stopFilteringMulticastPackets() { - setMulticastFilter(false); - } - } - - class IpClientCallbacksImpl extends IpClientCallbacks { - private final ConditionVariable mWaitForCreationCv = new ConditionVariable(false); - private final ConditionVariable mWaitForStopCv = new ConditionVariable(false); - - @Override - public void onIpClientCreated(IIpClient ipClient) { - mIpClient = new IpClientManager(ipClient, getName()); - mWaitForCreationCv.open(); - } - - @Override - public void onPreDhcpAction() { - sendMessage(CMD_PRE_DHCP_ACTION); - } - - @Override - public void onPostDhcpAction() { - sendMessage(CMD_POST_DHCP_ACTION); - } - - @Override - public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { - if (dhcpResults != null) { - sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults); - } else { - sendMessage(CMD_IPV4_PROVISIONING_FAILURE); - } - } - - @Override - public void onProvisioningSuccess(LinkProperties newLp) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL); - sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); - sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL); - } - - @Override - public void onProvisioningFailure(LinkProperties newLp) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST); - sendMessage(CMD_IP_CONFIGURATION_LOST); - } - - @Override - public void onLinkPropertiesChange(LinkProperties newLp) { - sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); - } - - @Override - public void onReachabilityLost(String logMsg) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_REACHABILITY_LOST); - sendMessage(CMD_IP_REACHABILITY_LOST, logMsg); - } - - @Override - public void installPacketFilter(byte[] filter) { - sendMessage(CMD_INSTALL_PACKET_FILTER, filter); - } - - @Override - public void startReadPacketFilter() { - sendMessage(CMD_READ_PACKET_FILTER); - } - - @Override - public void setFallbackMulticastFilter(boolean enabled) { - sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled); - } - - @Override - public void setNeighborDiscoveryOffload(boolean enabled) { - sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0)); - } - - @Override - public void onPreconnectionStart(List<Layer2PacketParcelable> packets) { - sendMessage(CMD_START_FILS_CONNECTION, 0, 0, packets); - } - - @Override - public void onQuit() { - mWaitForStopCv.open(); - } - - boolean awaitCreation() { - return mWaitForCreationCv.block(IPCLIENT_STARTUP_TIMEOUT_MS); - } - - boolean awaitShutdown() { - return mWaitForStopCv.block(IPCLIENT_SHUTDOWN_TIMEOUT_MS); - } - } - - private void stopIpClient() { - // TODO(b/157943924): Adding more log to debug the issue. - Log.v(TAG, "stopIpClient IpClientWithPreConnection: " + mIpClientWithPreConnection, - new Throwable()); - if (mIpClient != null) { - if (mIpClientWithPreConnection) { - mIpClient.notifyPreconnectionComplete(false); - } - mIpClient.stop(); - } - mIpClientWithPreConnection = false; - mSentHLPs = false; - } - - private void stopDhcpSetup() { - /* Restore power save and suspend optimizations */ - handlePostDhcpSetup(); - stopIpClient(); - } - - /** - * Listener for config manager network config related events. - * TODO (b/117601161) : Move some of the existing handling in WifiConnectivityManager's listener - * for the same events. - */ - private class OnNetworkUpdateListener implements - WifiConfigManager.OnNetworkUpdateListener { - @Override - public void onNetworkAdded(WifiConfiguration config) { } - - @Override - public void onNetworkEnabled(WifiConfiguration config) { } - - @Override - public void onNetworkRemoved(WifiConfiguration config) { - // The current connected or connecting network has been removed, trigger a disconnect. - if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { - // Disconnect and let autojoin reselect a new network - sendMessage(CMD_DISCONNECT); - } - mWifiNative.removeNetworkCachedData(config.networkId); - } - - @Override - public void onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig) { - // Clear invalid cached data. - mWifiNative.removeNetworkCachedData(oldConfig.networkId); - - if (WifiConfigurationUtil.hasCredentialChanged(oldConfig, newConfig)) { - mBssidBlocklistMonitor.handleNetworkRemoved(newConfig.SSID); - } - - // Check if user/app change meteredOverride for connected network. - if (newConfig.networkId != mLastNetworkId - || newConfig.meteredOverride == oldConfig.meteredOverride) { - // nothing to do. - return; - } - boolean isMetered = WifiConfiguration.isMetered(newConfig, mWifiInfo); - boolean wasMetered = WifiConfiguration.isMetered(oldConfig, mWifiInfo); - if (isMetered == wasMetered) { - // no meteredness change, nothing to do. - if (mVerboseLoggingEnabled) { - Log.v(TAG, "User/app changed meteredOverride, but no change in meteredness"); - } - return; - } - // If unmetered->metered trigger a disconnect. - // If metered->unmetered update capabilities. - if (isMetered) { - Log.w(TAG, "Network marked metered, triggering disconnect"); - sendMessage(CMD_DISCONNECT); - } else { - Log.i(TAG, "Network marked unmetered, triggering capabilities update"); - updateCapabilities(newConfig); - } - } - - @Override - public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) { - if (disableReason == DISABLED_NO_INTERNET_TEMPORARY) return; - if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { - // Disconnect and let autojoin reselect a new network - sendMessage(CMD_DISCONNECT); - } - - } - - @Override - public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) { - // For DISABLED_NO_INTERNET_PERMANENT we do not need to remove the network - // because supplicant won't be trying to reconnect. If this is due to a - // preventAutomaticReconnect request from ConnectivityService, that service - // will disconnect as appropriate. - if (disableReason == DISABLED_NO_INTERNET_PERMANENT) return; - if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { - // Disconnect and let autojoin reselect a new network - sendMessage(CMD_DISCONNECT); - } - } - } - - /** - * Set wpa_supplicant log level using |mVerboseLoggingLevel| flag. - */ - void setSupplicantLogLevel() { - mWifiNative.setSupplicantLogLevel(mVerboseLoggingEnabled); - } - - /** - * Method to update logging level in wifi service related classes. - * - * @param verbose int logging level to use - */ - public void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mVerboseLoggingEnabled = true; - setLogRecSize(mActivityManager.isLowRamDevice() - ? NUM_LOG_RECS_VERBOSE_LOW_MEMORY : NUM_LOG_RECS_VERBOSE); - } else { - mVerboseLoggingEnabled = false; - setLogRecSize(NUM_LOG_RECS_NORMAL); - } - setSupplicantLogLevel(); - mCountryCode.enableVerboseLogging(verbose); - mWifiScoreReport.enableVerboseLogging(mVerboseLoggingEnabled); - mWifiDiagnostics.enableVerboseLogging(mVerboseLoggingEnabled); - mWifiMonitor.enableVerboseLogging(verbose); - mWifiNative.enableVerboseLogging(verbose); - mWifiConfigManager.enableVerboseLogging(verbose); - mSupplicantStateTracker.enableVerboseLogging(verbose); - mPasspointManager.enableVerboseLogging(verbose); - mNetworkFactory.enableVerboseLogging(verbose); - mLinkProbeManager.enableVerboseLogging(mVerboseLoggingEnabled); - mMboOceController.enableVerboseLogging(mVerboseLoggingEnabled); - mWifiScoreCard.enableVerboseLogging(mVerboseLoggingEnabled); - mWifiHealthMonitor.enableVerboseLogging(mVerboseLoggingEnabled); - mWifiInjector.getThroughputPredictor().enableVerboseLogging(mVerboseLoggingEnabled); - mWifiDataStall.enableVerboseLogging(mVerboseLoggingEnabled); - mWifiConnectivityManager.enableVerboseLogging(mVerboseLoggingEnabled); - } - - /** - * Initiates connection to a network specified by the user/app. This method checks if the - * requesting app holds the NETWORK_SETTINGS permission. - * - * @param netId Id network to initiate connection. - * @param uid UID of the app requesting the connection. - * @param forceReconnect Whether to force a connection even if we're connected to the same - * network currently. - */ - private void connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect) { - logd("connectToUserSelectNetwork netId " + netId + ", uid " + uid - + ", forceReconnect = " + forceReconnect); - if (!forceReconnect && (mLastNetworkId == netId || mTargetNetworkId == netId)) { - // We're already connecting/connected to the user specified network, don't trigger a - // reconnection unless it was forced. - logi("connectToUserSelectNetwork already connecting/connected=" + netId); - } else { - mWifiConnectivityManager.prepareForForcedConnection(netId); - if (uid == Process.SYSTEM_UID) { - mWifiMetrics.setNominatorForNetwork(netId, - WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL); - } - startConnectToNetwork(netId, uid, SUPPLICANT_BSSID_ANY); - } - } - - /** - * ****************************************************** - * Methods exposed for public use - * ****************************************************** - */ - - /** - * Retrieve a Messenger for the ClientModeImpl Handler - * - * @return Messenger - */ - public Messenger getMessenger() { - return new Messenger(getHandler()); - } - - // Last connect attempt is used to prevent scan requests: - // - for a period of 10 seconds after attempting to connect - private long mLastConnectAttemptTimestamp = 0; - - // For debugging, keep track of last message status handling - // TODO, find an equivalent mechanism as part of parent class - private static final int MESSAGE_HANDLING_STATUS_PROCESSED = 2; - private static final int MESSAGE_HANDLING_STATUS_OK = 1; - private static final int MESSAGE_HANDLING_STATUS_UNKNOWN = 0; - private static final int MESSAGE_HANDLING_STATUS_REFUSED = -1; - private static final int MESSAGE_HANDLING_STATUS_FAIL = -2; - private static final int MESSAGE_HANDLING_STATUS_OBSOLETE = -3; - private static final int MESSAGE_HANDLING_STATUS_DEFERRED = -4; - private static final int MESSAGE_HANDLING_STATUS_DISCARD = -5; - private static final int MESSAGE_HANDLING_STATUS_LOOPED = -6; - private static final int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7; - - private int mMessageHandlingStatus = 0; - - private int mOnTime = 0; - private int mTxTime = 0; - private int mRxTime = 0; - - private int mOnTimeScreenStateChange = 0; - private long mLastOntimeReportTimeStamp = 0; - private long mLastScreenStateChangeTimeStamp = 0; - private int mOnTimeLastReport = 0; - private int mTxTimeLastReport = 0; - private int mRxTimeLastReport = 0; - - private WifiLinkLayerStats mLastLinkLayerStats; - private long mLastLinkLayerStatsUpdate = 0; - - String reportOnTime() { - long now = mClock.getWallClockMillis(); - StringBuilder sb = new StringBuilder(); - // Report stats since last report - int on = mOnTime - mOnTimeLastReport; - mOnTimeLastReport = mOnTime; - int tx = mTxTime - mTxTimeLastReport; - mTxTimeLastReport = mTxTime; - int rx = mRxTime - mRxTimeLastReport; - mRxTimeLastReport = mRxTime; - int period = (int) (now - mLastOntimeReportTimeStamp); - mLastOntimeReportTimeStamp = now; - sb.append(String.format("[on:%d tx:%d rx:%d period:%d]", on, tx, rx, period)); - // Report stats since Screen State Changed - on = mOnTime - mOnTimeScreenStateChange; - period = (int) (now - mLastScreenStateChangeTimeStamp); - sb.append(String.format(" from screen [on:%d period:%d]", on, period)); - return sb.toString(); - } - - WifiLinkLayerStats getWifiLinkLayerStats() { - if (mInterfaceName == null) { - loge("getWifiLinkLayerStats called without an interface"); - return null; - } - mLastLinkLayerStatsUpdate = mClock.getWallClockMillis(); - WifiLinkLayerStats stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName); - if (stats != null) { - mOnTime = stats.on_time; - mTxTime = stats.tx_time; - mRxTime = stats.rx_time; - mRunningBeaconCount = stats.beacon_rx; - mWifiInfo.updatePacketRates(stats, mLastLinkLayerStatsUpdate); - } else { - long mTxPkts = mFacade.getTxPackets(mInterfaceName); - long mRxPkts = mFacade.getRxPackets(mInterfaceName); - mWifiInfo.updatePacketRates(mTxPkts, mRxPkts, mLastLinkLayerStatsUpdate); - } - return stats; - } - - /** - * Check if a Wi-Fi band is supported - * - * @param band A value from {@link WifiScanner.WIFI_BAND_5_GHZ} or - * {@link WifiScanner.WIFI_BAND_6_GHZ} - * @return {@code true} if band is supported, {@code false} otherwise. - */ - public boolean isWifiBandSupported(int band) { - if (band == WifiScanner.WIFI_BAND_5_GHZ) { - // In some cases, devices override the value by the overlay configs - if (mContext.getResources().getBoolean(R.bool.config_wifi5ghzSupport)) { - return true; - } - return (mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ).length > 0); - } - - if (band == WifiScanner.WIFI_BAND_6_GHZ) { - if (mContext.getResources().getBoolean(R.bool.config_wifi6ghzSupport)) { - return true; - } - return (mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ).length > 0); - } - - return false; - } - - /** - * Update interface capabilities - * This method is used to update some of interface capabilities defined in overlay - * - * @param ifaceName name of interface to update - */ - private void updateInterfaceCapabilities(@NonNull String ifaceName) { - DeviceWiphyCapabilities cap = mWifiNative.getDeviceWiphyCapabilities(ifaceName); - if (cap != null) { - // Some devices don't have support of 11ax indicated by the chip, - // so an override config value is used - if (mContext.getResources().getBoolean(R.bool.config_wifi11axSupportOverride)) { - cap.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, true); - } - - mWifiNative.setDeviceWiphyCapabilities(ifaceName, cap); - } - } - - /** - * Check if a Wi-Fi standard is supported - * - * @param standard A value from {@link ScanResult}'s {@code WIFI_STANDARD_} - * @return {@code true} if standard is supported, {@code false} otherwise. - */ - public boolean isWifiStandardSupported(@WifiStandard int standard) { - return mWifiNative.isWifiStandardSupported(mInterfaceName, standard); - } - - private byte[] getDstMacForKeepalive(KeepalivePacketData packetData) - throws InvalidPacketException { - try { - InetAddress gateway = NetUtils.selectBestRoute( - mLinkProperties.getRoutes(), packetData.getDstAddress()).getGateway(); - String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); - return NativeUtil.macAddressToByteArray(dstMacStr); - } catch (NullPointerException | IllegalArgumentException e) { - throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS); - } - } - - private static int getEtherProtoForKeepalive(KeepalivePacketData packetData) - throws InvalidPacketException { - if (packetData.getDstAddress() instanceof Inet4Address) { - return OsConstants.ETH_P_IP; - } else if (packetData.getDstAddress() instanceof Inet6Address) { - return OsConstants.ETH_P_IPV6; - } else { - throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS); - } - } - - private int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, - int intervalSeconds) { - byte[] packet = null; - byte[] dstMac = null; - int proto = 0; - - try { - packet = packetData.getPacket(); - dstMac = getDstMacForKeepalive(packetData); - proto = getEtherProtoForKeepalive(packetData); - } catch (InvalidPacketException e) { - return e.getError(); - } - - int ret = mWifiNative.startSendingOffloadedPacket( - mInterfaceName, slot, dstMac, packet, proto, intervalSeconds * 1000); - if (ret != 0) { - loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds - + "): hardware error " + ret); - return SocketKeepalive.ERROR_HARDWARE_ERROR; - } else { - return SocketKeepalive.SUCCESS; - } - } - - private int stopWifiIPPacketOffload(int slot) { - int ret = mWifiNative.stopSendingOffloadedPacket(mInterfaceName, slot); - if (ret != 0) { - loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret); - return SocketKeepalive.ERROR_HARDWARE_ERROR; - } else { - return SocketKeepalive.SUCCESS; - } - } - - private int startRssiMonitoringOffload(byte maxRssi, byte minRssi, - WifiNative.WifiRssiEventHandler rssiHandler) { - return mWifiNative.startRssiMonitoring(mInterfaceName, maxRssi, minRssi, rssiHandler); - } - - private int stopRssiMonitoringOffload() { - return mWifiNative.stopRssiMonitoring(mInterfaceName); - } - - /** - * Temporary method that allows the active ClientModeManager to set the wifi state that is - * retrieved by API calls. This will be removed when WifiServiceImpl no longer directly calls - * this class (b/31479117). - * - * @param newState new state to set, invalid states are ignored. - */ - public void setWifiStateForApiCalls(int newState) { - switch (newState) { - case WIFI_STATE_DISABLING: - case WIFI_STATE_DISABLED: - case WIFI_STATE_ENABLING: - case WIFI_STATE_ENABLED: - case WIFI_STATE_UNKNOWN: - if (mVerboseLoggingEnabled) { - Log.d(TAG, "setting wifi state to: " + newState); - } - mWifiState.set(newState); - return; - default: - Log.d(TAG, "attempted to set an invalid state: " + newState); - return; - } - } - - /** - * Method used by WifiServiceImpl to get the current state of Wifi (in client mode) for API - * calls. This will be removed when WifiService no longer directly calls this class - * (b/31479117). - */ - public int syncGetWifiState() { - return mWifiState.get(); - } - - /** - * Converts the current wifi state to a printable form. - */ - public String syncGetWifiStateByName() { - switch (mWifiState.get()) { - case WIFI_STATE_DISABLING: - return "disabling"; - case WIFI_STATE_DISABLED: - return "disabled"; - case WIFI_STATE_ENABLING: - return "enabling"; - case WIFI_STATE_ENABLED: - return "enabled"; - case WIFI_STATE_UNKNOWN: - return "unknown state"; - default: - return "[invalid state]"; - } - } - - public boolean isConnected() { - return getCurrentState() == mConnectedState; - } - - public boolean isDisconnected() { - return getCurrentState() == mDisconnectedState; - } - - /** - * Method checking if supplicant is in a transient state - * - * @return boolean true if in transient state - */ - public boolean isSupplicantTransientState() { - SupplicantState supplicantState = mWifiInfo.getSupplicantState(); - if (supplicantState == SupplicantState.ASSOCIATING - || supplicantState == SupplicantState.AUTHENTICATING - || supplicantState == SupplicantState.FOUR_WAY_HANDSHAKE - || supplicantState == SupplicantState.GROUP_HANDSHAKE) { - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Supplicant is under transient state: " + supplicantState); - } - return true; - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Supplicant is under steady state: " + supplicantState); - } - } - - return false; - } - - /** - * Get status information for the current connection, if any. - * - * @return a {@link WifiInfo} object containing information about the current connection - */ - public WifiInfo syncRequestConnectionInfo() { - WifiInfo result = new WifiInfo(mWifiInfo); - return result; - } - - /** - * Method to retrieve the current WifiInfo - * - * @returns WifiInfo - */ - public WifiInfo getWifiInfo() { - return mWifiInfo; - } - - /** - * Blocking call to get the current DHCP results - * - * @return DhcpResultsParcelable current results - */ - @NonNull - public DhcpResultsParcelable syncGetDhcpResultsParcelable() { - synchronized (mDhcpResultsParcelableLock) { - return mDhcpResultsParcelable; - } - } - - /** - * When the underlying interface is destroyed, we must immediately tell connectivity service to - * mark network agent as disconnected and stop the ip client. - */ - public void handleIfaceDestroyed() { - handleNetworkDisconnect(); - } - - /** - * TODO: doc - */ - public void setOperationalMode(int mode, String ifaceName) { - if (mVerboseLoggingEnabled) { - log("setting operational mode to " + String.valueOf(mode) + " for iface: " + ifaceName); - } - mModeChange = true; - if (mode != CONNECT_MODE) { - // we are disabling client mode... need to exit connect mode now - transitionTo(mDefaultState); - } else { - // do a quick sanity check on the iface name, make sure it isn't null - if (ifaceName != null) { - mInterfaceName = ifaceName; - updateInterfaceCapabilities(ifaceName); - transitionTo(mDisconnectedState); - mWifiScoreReport.setInterfaceName(ifaceName); - } else { - Log.e(TAG, "supposed to enter connect mode, but iface is null -> DefaultState"); - transitionTo(mDefaultState); - } - } - // use the CMD_SET_OPERATIONAL_MODE to force the transitions before other messages are - // handled. - sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE); - } - - private void checkAbnormalConnectionFailureAndTakeBugReport(String ssid) { - if (mWifiInjector.getDeviceConfigFacade() - .isAbnormalConnectionFailureBugreportEnabled()) { - int reasonCode = mWifiScoreCard.detectAbnormalConnectionFailure(ssid); - if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) { - String bugTitle = "Wi-Fi BugReport"; - String bugDetail = "Detect abnormal " - + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode]; - takeBugReport(bugTitle, bugDetail); - } - } - } - - private void checkAbnormalDisconnectionAndTakeBugReport() { - if (mWifiInjector.getDeviceConfigFacade() - .isAbnormalDisconnectionBugreportEnabled()) { - int reasonCode = mWifiScoreCard.detectAbnormalDisconnection(); - if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) { - String bugTitle = "Wi-Fi BugReport"; - String bugDetail = "Detect abnormal " - + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode]; - takeBugReport(bugTitle, bugDetail); - } - } - } - - /** - * Initiates a system-level bugreport, in a non-blocking fashion. - */ - public void takeBugReport(String bugTitle, String bugDetail) { - mWifiDiagnostics.takeBugReport(bugTitle, bugDetail); - } - - /** - * Allow tests to confirm the operational mode for ClientModeImpl for testing. - */ - @VisibleForTesting - protected int getOperationalModeForTest() { - return mOperationalMode; - } - - /** - * Retrieve the WifiMulticastLockManager.FilterController callback for registration. - */ - protected WifiMulticastLockManager.FilterController getMcastLockManagerFilterController() { - return mMcastLockManagerFilterController; - } - - /** - * Blocking method to retrieve the passpoint icon. - * - * @param channel AsyncChannel for the response - * @param bssid representation of the bssid as a long - * @param fileName name of the file - * - * @return boolean returning the result of the call - */ - public boolean syncQueryPasspointIcon(AsyncChannel channel, long bssid, String fileName) { - Bundle bundle = new Bundle(); - bundle.putLong(EXTRA_OSU_ICON_QUERY_BSSID, bssid); - bundle.putString(EXTRA_OSU_ICON_QUERY_FILENAME, fileName); - Message resultMsg = channel.sendMessageSynchronously(CMD_QUERY_OSU_ICON, bundle); - int result = resultMsg.arg1; - resultMsg.recycle(); - return result == 1; - } - - /** - * Deauthenticate and set the re-authentication hold off time for the current network - * @param holdoff hold off time in milliseconds - * @param ess set if the hold off pertains to an ESS rather than a BSS - */ - public void deauthenticateNetwork(AsyncChannel channel, long holdoff, boolean ess) { - // TODO: This needs an implementation - } - - /** - * Disconnect from Access Point - */ - public void disconnectCommand() { - sendMessage(CMD_DISCONNECT); - } - - /** - * Method to trigger a disconnect. - * - * @param uid UID of requesting caller - * @param reason disconnect reason - */ - public void disconnectCommand(int uid, int reason) { - sendMessage(CMD_DISCONNECT, uid, reason); - } - - /** - * Initiate a reconnection to AP - */ - public void reconnectCommand(WorkSource workSource) { - sendMessage(CMD_RECONNECT, workSource); - } - - /** - * Initiate a re-association to AP - */ - public void reassociateCommand() { - sendMessage(CMD_REASSOCIATE); - } - - /** - * Checks for a null Message. - * - * This can happen with sendMessageSynchronously, for example if an - * InterruptedException occurs. If this just happens once, silently - * ignore it, because it is probably a side effect of shutting down. - * If it happens a second time, generate a WTF. - */ - private boolean messageIsNull(Message resultMsg) { - if (resultMsg != null) return false; - if (mNullMessageCounter.getAndIncrement() > 0) { - Log.wtf(TAG, "Persistent null Message", new RuntimeException()); - } - return true; - } - private AtomicInteger mNullMessageCounter = new AtomicInteger(0); - - /** - * Start subscription provisioning synchronously - * - * @param provider {@link OsuProvider} the provider to provision with - * @param callback {@link IProvisioningCallback} callback for provisioning status - * @return boolean true indicates provisioning was started, false otherwise - */ - public boolean syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, - IProvisioningCallback callback, AsyncChannel channel) { - Message msg = Message.obtain(); - msg.what = CMD_START_SUBSCRIPTION_PROVISIONING; - msg.arg1 = callingUid; - msg.obj = callback; - msg.getData().putParcelable(EXTRA_OSU_PROVIDER, provider); - Message resultMsg = channel.sendMessageSynchronously(msg); - if (messageIsNull(resultMsg)) return false; - boolean result = resultMsg.arg1 != 0; - resultMsg.recycle(); - return result; - } - - /** - * Get the supported feature set synchronously - */ - public long syncGetSupportedFeatures(AsyncChannel channel) { - Message resultMsg = channel.sendMessageSynchronously(CMD_GET_SUPPORTED_FEATURES); - if (messageIsNull(resultMsg)) return 0; - long supportedFeatureSet = ((Long) resultMsg.obj).longValue(); - resultMsg.recycle(); - return supportedFeatureSet; - } - - /** - * Get link layers stats for adapter synchronously - */ - public WifiLinkLayerStats syncGetLinkLayerStats(AsyncChannel channel) { - Message resultMsg = channel.sendMessageSynchronously(CMD_GET_LINK_LAYER_STATS); - if (messageIsNull(resultMsg)) return null; - WifiLinkLayerStats result = (WifiLinkLayerStats) resultMsg.obj; - resultMsg.recycle(); - return result; - } - - /** - * Method to enable/disable RSSI polling - * @param enabled boolean idicating if polling should start - */ - public void enableRssiPolling(boolean enabled) { - sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0); - } - - /** - * Set high performance mode of operation. - * Enabling would set active power mode and disable suspend optimizations; - * disabling would set auto power mode and enable suspend optimizations - * - * @param enable true if enable, false otherwise - */ - public void setHighPerfModeEnabled(boolean enable) { - sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0); - } - - - /** - * reset cached SIM credential data - */ - public synchronized void resetSimAuthNetworks(@ResetSimReason int resetReason) { - sendMessage(CMD_RESET_SIM_NETWORKS, resetReason); - } - - /** - * Should only be used internally. - * External callers should use {@link #syncGetCurrentNetwork(AsyncChannel)}. - */ - private Network getCurrentNetwork() { - if (mNetworkAgent != null) { - return mNetworkAgent.getNetwork(); - } else { - return null; - } - } - - /** - * Get Network object of currently connected wifi network, or null if not connected. - * @return Network object of current wifi network - */ - public Network syncGetCurrentNetwork(AsyncChannel channel) { - Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CURRENT_NETWORK); - if (messageIsNull(resultMsg)) return null; - Network network = (Network) resultMsg.obj; - resultMsg.recycle(); - return network; - } - - /** - * Enable TDLS for a specific MAC address - */ - public void enableTdls(String remoteMacAddress, boolean enable) { - int enabler = enable ? 1 : 0; - sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress); - } - - /** - * Send a message indicating bluetooth adapter state changed, e.g., turn on or ff - */ - public void sendBluetoothAdapterStateChange(int state) { - sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0); - } - - /** - * Send a message indicating bluetooth adapter connection state changed, e.g., connected - * or disconnected. Note that turning off BT after pairing success keeps connection state in - * connected state. - */ - public void sendBluetoothAdapterConnectionStateChange(int state) { - sendMessage(CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE, state, 0); - } - - /** - * Trigger dump on the class IpClient object. - */ - public void dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mIpClient != null) { - // All dumpIpClient does is print this log message. - // TODO: consider deleting this, since it's not useful. - pw.println("IpClient logs have moved to dumpsys network_stack"); - } - } - - private static String dhcpResultsParcelableToString(DhcpResultsParcelable dhcpResults) { - return new StringBuilder() - .append("baseConfiguration ").append(dhcpResults.baseConfiguration) - .append("leaseDuration ").append(dhcpResults.leaseDuration) - .append("mtu ").append(dhcpResults.mtu) - .append("serverAddress ").append(dhcpResults.serverAddress) - .append("serverHostName ").append(dhcpResults.serverHostName) - .append("vendorInfo ").append(dhcpResults.vendorInfo) - .toString(); - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - super.dump(fd, pw, args); - mSupplicantStateTracker.dump(fd, pw, args); - pw.println("mLinkProperties " + mLinkProperties); - pw.println("mWifiInfo " + mWifiInfo); - pw.println("mDhcpResultsParcelable " - + dhcpResultsParcelableToString(mDhcpResultsParcelable)); - pw.println("mLastSignalLevel " + mLastSignalLevel); - pw.println("mLastBssid " + mLastBssid); - pw.println("mLastNetworkId " + mLastNetworkId); - pw.println("mLastSubId " + mLastSubId); - pw.println("mLastSimBasedConnectionCarrierName " + mLastSimBasedConnectionCarrierName); - pw.println("mOperationalMode " + mOperationalMode); - pw.println("mSuspendOptimizationsEnabled " + mContext.getResources().getBoolean( - R.bool.config_wifiSuspendOptimizationsEnabled)); - pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); - mCountryCode.dump(fd, pw, args); - mNetworkFactory.dump(fd, pw, args); - mUntrustedNetworkFactory.dump(fd, pw, args); - pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount()); - pw.println(); - - mWifiConfigManager.dump(fd, pw, args); - pw.println(); - mPasspointManager.dump(pw); - pw.println(); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_USER_ACTION); - mWifiDiagnostics.dump(fd, pw, args); - dumpIpClient(fd, pw, args); - mWifiConnectivityManager.dump(fd, pw, args); - mWifiHealthMonitor.dump(fd, pw, args); - mWifiInjector.getWakeupController().dump(fd, pw, args); - mLinkProbeManager.dump(fd, pw, args); - mWifiInjector.getWifiLastResortWatchdog().dump(fd, pw, args); - } - - /** - * Trigger message to handle boot completed event. - */ - public void handleBootCompleted() { - sendMessage(CMD_BOOT_COMPLETED); - } - - /** - * ****************************************************** - * Internal private functions - * ****************************************************** - */ - - private void logStateAndMessage(Message message, State state) { - mMessageHandlingStatus = 0; - if (mVerboseLoggingEnabled) { - logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message)); - } - } - - @Override - protected boolean recordLogRec(Message msg) { - switch (msg.what) { - case CMD_RSSI_POLL: - return mVerboseLoggingEnabled; - default: - return true; - } - } - - /** - * Return the additional string to be logged by LogRec, default - * - * @param msg that was processed - * @return information to be logged as a String - */ - @Override - protected String getLogRecString(Message msg) { - WifiConfiguration config; - Long now; - String report; - String key; - StringBuilder sb = new StringBuilder(); - sb.append("screen=").append(mScreenOn ? "on" : "off"); - if (mMessageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) { - sb.append("(").append(mMessageHandlingStatus).append(")"); - } - if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) { - sb.append(" uid=" + msg.sendingUid); - } - switch (msg.what) { - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; - if (stateChangeResult != null) { - sb.append(stateChangeResult.toString()); - } - break; - case CMD_CONNECT_NETWORK: - case CMD_SAVE_NETWORK: { - NetworkUpdateResult result = (NetworkUpdateResult) msg.obj; - sb.append(" "); - sb.append(Integer.toString(result.netId)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - config = mWifiConfigManager.getConfiguredNetwork(result.netId); - if (config != null) { - sb.append(" ").append(config.getKey()); - sb.append(" nid=").append(config.networkId); - if (config.hiddenSSID) { - sb.append(" hidden"); - } - if (config.preSharedKey != null - && !config.preSharedKey.equals("*")) { - sb.append(" hasPSK"); - } - if (config.ephemeral) { - sb.append(" ephemeral"); - } - sb.append(" cuid=").append(config.creatorUid); - sb.append(" suid=").append(config.lastUpdateUid); - } - break; - } - case WifiMonitor.ASSOCIATION_REJECTION_EVENT: - sb.append(" "); - sb.append(" timedOut=" + Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - String bssid = (String) msg.obj; - if (bssid != null && bssid.length() > 0) { - sb.append(" "); - sb.append(bssid); - } - sb.append(" blacklist=" + Boolean.toString(mDidBlackListBSSID)); - break; - case WifiMonitor.NETWORK_CONNECTION_EVENT: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - sb.append(" ").append(mLastBssid); - sb.append(" nid=").append(mLastNetworkId); - config = getCurrentWifiConfiguration(); - if (config != null) { - sb.append(" ").append(config.getKey()); - } - key = mWifiConfigManager.getLastSelectedNetworkConfigKey(); - if (key != null) { - sb.append(" last=").append(key); - } - break; - case WifiMonitor.TARGET_BSSID_EVENT: - case WifiMonitor.ASSOCIATED_BSSID_EVENT: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - if (msg.obj != null) { - sb.append(" BSSID=").append((String) msg.obj); - } - if (mTargetBssid != null) { - sb.append(" Target=").append(mTargetBssid); - } - sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); - break; - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - if (msg.obj != null) { - sb.append(" ").append((String) msg.obj); - } - sb.append(" nid=").append(msg.arg1); - sb.append(" reason=").append(msg.arg2); - if (mLastBssid != null) { - sb.append(" lastbssid=").append(mLastBssid); - } - if (mWifiInfo.getFrequency() != -1) { - sb.append(" freq=").append(mWifiInfo.getFrequency()); - sb.append(" rssi=").append(mWifiInfo.getRssi()); - } - break; - case CMD_RSSI_POLL: - case CMD_ONESHOT_RSSI_POLL: - case CMD_UNWANTED_NETWORK: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - if (mWifiInfo.getSSID() != null) { - if (mWifiInfo.getSSID() != null) { - sb.append(" ").append(mWifiInfo.getSSID()); - } - } - if (mWifiInfo.getBSSID() != null) { - sb.append(" ").append(mWifiInfo.getBSSID()); - } - sb.append(" rssi=").append(mWifiInfo.getRssi()); - sb.append(" f=").append(mWifiInfo.getFrequency()); - sb.append(" sc=").append(mWifiInfo.getScore()); - sb.append(" link=").append(mWifiInfo.getLinkSpeed()); - sb.append(String.format(" tx=%.1f,", mWifiInfo.getSuccessfulTxPacketsPerSecond())); - sb.append(String.format(" %.1f,", mWifiInfo.getRetriedTxPacketsPerSecond())); - sb.append(String.format(" %.1f ", mWifiInfo.getLostTxPacketsPerSecond())); - sb.append(String.format(" rx=%.1f", mWifiInfo.getSuccessfulRxPacketsPerSecond())); - sb.append(String.format(" bcn=%d", mRunningBeaconCount)); - report = reportOnTime(); - if (report != null) { - sb.append(" ").append(report); - } - sb.append(String.format(" score=%d", mWifiInfo.getScore())); - break; - case CMD_START_CONNECT: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - config = mWifiConfigManager.getConfiguredNetwork(msg.arg1); - if (config != null) { - sb.append(" targetConfigKey=").append(config.getKey()); - sb.append(" BSSID=" + config.BSSID); - } - if (mTargetBssid != null) { - sb.append(" targetBssid=").append(mTargetBssid); - } - sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); - config = getCurrentWifiConfiguration(); - if (config != null) { - sb.append(" currentConfigKey=").append(config.getKey()); - } - break; - case CMD_START_ROAM: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - ScanResult result = (ScanResult) msg.obj; - if (result != null) { - now = mClock.getWallClockMillis(); - sb.append(" bssid=").append(result.BSSID); - sb.append(" rssi=").append(result.level); - sb.append(" freq=").append(result.frequency); - if (result.seen > 0 && result.seen < now) { - sb.append(" seen=").append(now - result.seen); - } else { - // Somehow the timestamp for this scan result is inconsistent - sb.append(" !seen=").append(result.seen); - } - } - if (mTargetBssid != null) { - sb.append(" ").append(mTargetBssid); - } - sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming)); - sb.append(" fail count=").append(Integer.toString(mRoamFailCount)); - break; - case CMD_PRE_DHCP_ACTION: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - sb.append(" txpkts=").append(mWifiInfo.txSuccess); - sb.append(",").append(mWifiInfo.txBad); - sb.append(",").append(mWifiInfo.txRetries); - break; - case CMD_POST_DHCP_ACTION: - if (mLinkProperties != null) { - sb.append(" "); - sb.append(getLinkPropertiesSummary(mLinkProperties)); - } - break; - case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - if (msg.obj != null) { - NetworkInfo info = (NetworkInfo) msg.obj; - NetworkInfo.State state = info.getState(); - NetworkInfo.DetailedState detailedState = info.getDetailedState(); - if (state != null) { - sb.append(" st=").append(state); - } - if (detailedState != null) { - sb.append("/").append(detailedState); - } - } - break; - case CMD_IP_CONFIGURATION_LOST: - int count = -1; - WifiConfiguration c = getCurrentWifiConfiguration(); - if (c != null) { - count = c.getNetworkSelectionStatus().getDisableReasonCounter( - WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); - } - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - sb.append(" failures: "); - sb.append(Integer.toString(count)); - sb.append("/"); - sb.append(Integer.toString(mFacade.getIntegerSetting( - mContext, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT, 0))); - if (mWifiInfo.getBSSID() != null) { - sb.append(" ").append(mWifiInfo.getBSSID()); - } - sb.append(String.format(" bcn=%d", mRunningBeaconCount)); - break; - case CMD_UPDATE_LINKPROPERTIES: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - if (mLinkProperties != null) { - sb.append(" "); - sb.append(getLinkPropertiesSummary(mLinkProperties)); - } - break; - case CMD_IP_REACHABILITY_LOST: - if (msg.obj != null) { - sb.append(" ").append((String) msg.obj); - } - break; - case CMD_INSTALL_PACKET_FILTER: - sb.append(" len=" + ((byte[]) msg.obj).length); - break; - case CMD_SET_FALLBACK_PACKET_FILTERING: - sb.append(" enabled=" + (boolean) msg.obj); - break; - case CMD_ROAM_WATCHDOG_TIMER: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - sb.append(" cur=").append(mRoamWatchdogCount); - break; - case CMD_DISCONNECTING_WATCHDOG_TIMER: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - sb.append(" cur=").append(mDisconnectingWatchdogCount); - break; - case CMD_START_RSSI_MONITORING_OFFLOAD: - case CMD_STOP_RSSI_MONITORING_OFFLOAD: - case CMD_RSSI_THRESHOLD_BREACHED: - sb.append(" rssi="); - sb.append(Integer.toString(msg.arg1)); - sb.append(" thresholds="); - sb.append(Arrays.toString(mRssiRanges)); - break; - case CMD_IPV4_PROVISIONING_SUCCESS: - sb.append(" "); - sb.append(/* DhcpResultsParcelable */ msg.obj); - break; - case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: - BtmFrameData frameData = (BtmFrameData) msg.obj; - if (frameData != null) { - sb.append(" ").append(frameData.toString()); - } - break; - default: - sb.append(" "); - sb.append(Integer.toString(msg.arg1)); - sb.append(" "); - sb.append(Integer.toString(msg.arg2)); - break; - } - - return sb.toString(); - } - - @Override - protected String getWhatToString(int what) { - String s = sGetWhatToString.get(what); - if (s != null) { - return s; - } - switch (what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - s = "CMD_CHANNEL_HALF_CONNECTED"; - break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - s = "CMD_CHANNEL_DISCONNECTED"; - break; - case CMD_CONNECT_NETWORK: - s = "CMD_CONNECT_NETWORK"; - break; - case CMD_SAVE_NETWORK: - s = "CMD_SAVE_NETWORK"; - break; - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - s = "SUPPLICANT_STATE_CHANGE_EVENT"; - break; - case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: - s = "AUTHENTICATION_FAILURE_EVENT"; - break; - case WifiMonitor.SUP_REQUEST_IDENTITY: - s = "SUP_REQUEST_IDENTITY"; - break; - case WifiMonitor.NETWORK_CONNECTION_EVENT: - s = "NETWORK_CONNECTION_EVENT"; - break; - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - s = "NETWORK_DISCONNECTION_EVENT"; - break; - case WifiMonitor.ASSOCIATION_REJECTION_EVENT: - s = "ASSOCIATION_REJECTION_EVENT"; - break; - case WifiMonitor.ANQP_DONE_EVENT: - s = "ANQP_DONE_EVENT"; - break; - case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: - s = "RX_HS20_ANQP_ICON_EVENT"; - break; - case WifiMonitor.GAS_QUERY_DONE_EVENT: - s = "GAS_QUERY_DONE_EVENT"; - break; - case WifiMonitor.HS20_REMEDIATION_EVENT: - s = "HS20_REMEDIATION_EVENT"; - break; - case WifiMonitor.GAS_QUERY_START_EVENT: - s = "GAS_QUERY_START_EVENT"; - break; - case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: - s = "MBO_OCE_BSS_TM_HANDLING_DONE"; - break; - case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: - s = "GROUP_CREATING_TIMED_OUT"; - break; - case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: - s = "P2P_CONNECTION_CHANGED"; - break; - case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: - s = "DISCONNECT_WIFI_REQUEST"; - break; - case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: - s = "DISCONNECT_WIFI_RESPONSE"; - break; - case WifiP2pServiceImpl.SET_MIRACAST_MODE: - s = "SET_MIRACAST_MODE"; - break; - case WifiP2pServiceImpl.BLOCK_DISCOVERY: - s = "BLOCK_DISCOVERY"; - break; - default: - s = "what:" + Integer.toString(what); - break; - } - return s; - } - - private void handleScreenStateChanged(boolean screenOn) { - mScreenOn = screenOn; - if (mVerboseLoggingEnabled) { - logd(" handleScreenStateChanged Enter: screenOn=" + screenOn - + " mSuspendOptimizationsEnabled=" - + mContext.getResources().getBoolean( - R.bool.config_wifiSuspendOptimizationsEnabled) - + " state " + getCurrentState().getName()); - } - enableRssiPolling(screenOn); - if (mContext.getResources().getBoolean(R.bool.config_wifiSuspendOptimizationsEnabled)) { - int shouldReleaseWakeLock = 0; - if (screenOn) { - sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, shouldReleaseWakeLock); - } else { - if (isConnected()) { - // Allow 2s for suspend optimizations to be set - mSuspendWakeLock.acquire(2000); - shouldReleaseWakeLock = 1; - } - sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, shouldReleaseWakeLock); - } - } - - getWifiLinkLayerStats(); - mOnTimeScreenStateChange = mOnTime; - mLastScreenStateChangeTimeStamp = mLastLinkLayerStatsUpdate; - - mWifiMetrics.setScreenState(screenOn); - - mWifiConnectivityManager.handleScreenStateChanged(screenOn); - mNetworkFactory.handleScreenStateChanged(screenOn); - - WifiLockManager wifiLockManager = mWifiInjector.getWifiLockManager(); - if (wifiLockManager == null) { - Log.w(TAG, "WifiLockManager not initialized, skipping screen state notification"); - } else { - wifiLockManager.handleScreenStateChanged(screenOn); - } - - mSarManager.handleScreenStateChanged(screenOn); - - if (mVerboseLoggingEnabled) log("handleScreenStateChanged Exit: " + screenOn); - } - - private boolean checkAndSetConnectivityInstance() { - if (mCm == null) { - mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - } - if (mCm == null) { - Log.e(TAG, "Cannot retrieve connectivity service"); - return false; - } - return true; - } - - private void setSuspendOptimizationsNative(int reason, boolean enabled) { - if (mVerboseLoggingEnabled) { - log("setSuspendOptimizationsNative: " + reason + " " + enabled - + " -want " + mContext.getResources().getBoolean( - R.bool.config_wifiSuspendOptimizationsEnabled) - + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); - } - //mWifiNative.setSuspendOptimizations(enabled); - - if (enabled) { - mSuspendOptNeedsDisabled &= ~reason; - /* None of dhcp, screen or highperf need it disabled and user wants it enabled */ - if (mSuspendOptNeedsDisabled == 0 - && mContext.getResources().getBoolean( - R.bool.config_wifiSuspendOptimizationsEnabled)) { - if (mVerboseLoggingEnabled) { - log("setSuspendOptimizationsNative do it " + reason + " " + enabled - + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); - } - mWifiNative.setSuspendOptimizations(mInterfaceName, true); - } - } else { - mSuspendOptNeedsDisabled |= reason; - mWifiNative.setSuspendOptimizations(mInterfaceName, false); - } - } - - /** - * Makes a record of the user intent about suspend optimizations. - */ - private void setSuspendOptimizations(int reason, boolean enabled) { - if (mVerboseLoggingEnabled) log("setSuspendOptimizations: " + reason + " " + enabled); - if (enabled) { - mSuspendOptNeedsDisabled &= ~reason; - } else { - mSuspendOptNeedsDisabled |= reason; - } - if (mVerboseLoggingEnabled) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); - } - - /* - * Fetch RSSI, linkspeed, and frequency on current connection - */ - private void fetchRssiLinkSpeedAndFrequencyNative() { - WifiNl80211Manager.SignalPollResult pollResult = mWifiNative.signalPoll(mInterfaceName); - if (pollResult == null) { - return; - } - - int newRssi = pollResult.currentRssiDbm; - int newTxLinkSpeed = pollResult.txBitrateMbps; - int newFrequency = pollResult.associationFrequencyMHz; - int newRxLinkSpeed = pollResult.rxBitrateMbps; - - if (mVerboseLoggingEnabled) { - logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi - + " TxLinkspeed=" + newTxLinkSpeed + " freq=" + newFrequency - + " RxLinkSpeed=" + newRxLinkSpeed); - } - - if (newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) { - /* - * Positive RSSI is possible when devices are close(~0m apart) to each other. - * And there are some driver/firmware implementation, where they avoid - * reporting large negative rssi values by adding 256. - * so adjust the valid rssi reports for such implementations. - */ - if (newRssi > (WifiInfo.INVALID_RSSI + 256)) { - Log.wtf(TAG, "Error! +ve value RSSI: " + newRssi); - newRssi -= 256; - } - mWifiInfo.setRssi(newRssi); - /* - * Rather then sending the raw RSSI out every time it - * changes, we precalculate the signal level that would - * be displayed in the status bar, and only send the - * broadcast if that much more coarse-grained number - * changes. This cuts down greatly on the number of - * broadcasts, at the cost of not informing others - * interested in RSSI of all the changes in signal - * level. - */ - int newSignalLevel = RssiUtil.calculateSignalLevel(mContext, newRssi); - if (newSignalLevel != mLastSignalLevel) { - updateCapabilities(); - sendRssiChangeBroadcast(newRssi); - } - mLastSignalLevel = newSignalLevel; - } else { - mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); - updateCapabilities(); - } - /* - * set Tx link speed only if it is valid - */ - if (newTxLinkSpeed > 0) { - mWifiInfo.setLinkSpeed(newTxLinkSpeed); - mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed); - } - /* - * set Rx link speed only if it is valid - */ - if (newRxLinkSpeed > 0) { - mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed); - } - if (newFrequency > 0) { - mWifiInfo.setFrequency(newFrequency); - } - mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo); - /* - * Increment various performance metrics - */ - mWifiMetrics.handlePollResult(mWifiInfo); - } - - // Polling has completed, hence we won't have a score anymore - private void cleanWifiScore() { - mWifiInfo.setLostTxPacketsPerSecond(0); - mWifiInfo.setSuccessfulTxPacketsPerSecond(0); - mWifiInfo.setRetriedTxPacketsRate(0); - mWifiInfo.setSuccessfulRxPacketsPerSecond(0); - mWifiScoreReport.reset(); - mLastLinkLayerStats = null; - } - - private void updateLinkProperties(LinkProperties newLp) { - if (mVerboseLoggingEnabled) { - log("Link configuration changed for netId: " + mLastNetworkId - + " old: " + mLinkProperties + " new: " + newLp); - } - // We own this instance of LinkProperties because IpClient passes us a copy. - mLinkProperties = newLp; - if (mNetworkAgent != null) { - mNetworkAgent.sendLinkProperties(mLinkProperties); - } - - if (mNetworkAgentState == DetailedState.CONNECTED) { - // If anything has changed and we're already connected, send out a notification. - // TODO: Update all callers to use NetworkCallbacks and delete this. - sendLinkConfigurationChangedBroadcast(); - } - - if (mVerboseLoggingEnabled) { - StringBuilder sb = new StringBuilder(); - sb.append("updateLinkProperties nid: " + mLastNetworkId); - sb.append(" state: " + mNetworkAgentState); - - if (mLinkProperties != null) { - sb.append(" "); - sb.append(getLinkPropertiesSummary(mLinkProperties)); - } - logd(sb.toString()); - } - } - - /** - * Clears all our link properties. - */ - private void clearLinkProperties() { - // Clear the link properties obtained from DHCP. The only caller of this - // function has already called IpClient#stop(), which clears its state. - synchronized (mDhcpResultsParcelableLock) { - mDhcpResultsParcelable = new DhcpResultsParcelable(); - } - - // Now clear the merged link properties. - mLinkProperties.clear(); - if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties); - } - - private void sendRssiChangeBroadcast(final int newRssi) { - mBatteryStatsManager.reportWifiRssiChanged(newRssi); - WifiStatsLog.write(WifiStatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, - RssiUtil.calculateSignalLevel(mContext, newRssi)); - - Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, - android.Manifest.permission.ACCESS_WIFI_STATE); - } - - private void sendLinkConfigurationChangedBroadcast() { - Intent intent = new Intent(WifiManager.ACTION_LINK_CONFIGURATION_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - /** - * Helper method used to send state about supplicant - This is NOT information about the current - * wifi connection state. - * - * TODO: b/79504296 This broadcast has been deprecated and should be removed - */ - private void sendSupplicantConnectionChangedBroadcast(boolean connected) { - Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - /** - * Record the detailed state of a network. - * - * @param state the new {@code DetailedState} - */ - private void sendNetworkChangeBroadcast(NetworkInfo.DetailedState state) { - boolean hidden = false; - - if (mIsAutoRoaming) { - // There is generally a confusion in the system about colluding - // WiFi Layer 2 state (as reported by supplicant) and the Network state - // which leads to multiple confusion. - // - // If link is roaming, we already have an IP address - // as well we were connected and are doing L2 cycles of - // reconnecting or renewing IP address to check that we still have it - // This L2 link flapping should not be reflected into the Network state - // which is the state of the WiFi Network visible to Layer 3 and applications - // Note that once roaming is completed, we will - // set the Network state to where it should be, or leave it as unchanged - // - hidden = true; - } - if (mVerboseLoggingEnabled) { - log("setDetailed state, old =" - + mNetworkAgentState + " and new state=" + state - + " hidden=" + hidden); - } - if (hidden || state == mNetworkAgentState) return; - mNetworkAgentState = state; - - Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - NetworkInfo networkInfo = makeNetworkInfo(); - intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo); - //TODO(b/69974497) This should be non-sticky, but settings needs fixing first. - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private NetworkInfo makeNetworkInfo() { - final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, ""); - ni.setDetailedState(mNetworkAgentState, null, null); - return ni; - } - - private SupplicantState handleSupplicantStateChange(Message message) { - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - SupplicantState state = stateChangeResult.state; - mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, state); - // Supplicant state change - // [31-13] Reserved for future use - // [8 - 0] Supplicant state (as defined in SupplicantState.java) - // 50023 supplicant_state_changed (custom|1|5) - mWifiInfo.setSupplicantState(state); - // Network id and SSID are only valid when we start connecting - if (SupplicantState.isConnecting(state)) { - mWifiInfo.setNetworkId(stateChangeResult.networkId); - mWifiInfo.setBSSID(stateChangeResult.BSSID); - mWifiInfo.setSSID(stateChangeResult.wifiSsid); - if (state == SupplicantState.ASSOCIATED) { - updateWifiInfoAfterAssociation(); - } - } else { - // Reset parameters according to WifiInfo.reset() - mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); - mWifiInfo.setBSSID(null); - mWifiInfo.setSSID(null); - mWifiInfo.setWifiStandard(ScanResult.WIFI_STANDARD_UNKNOWN); - } - updateLayer2Information(); - // SSID might have been updated, so call updateCapabilities - updateCapabilities(); - - WifiConfiguration config = getCurrentWifiConfiguration(); - if (config == null) { - // If not connected, this should be non-null. - config = getTargetWifiConfiguration(); - } - if (config != null && config.networkId == mWifiInfo.getNetworkId()) { - mWifiInfo.setEphemeral(config.ephemeral); - mWifiInfo.setTrusted(config.trusted); - mWifiInfo.setOsuAp(config.osu); - if (config.fromWifiNetworkSpecifier || config.fromWifiNetworkSuggestion) { - mWifiInfo.setRequestingPackageName(config.creatorName); - } - - // Set meteredHint if scan result says network is expensive - ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork( - config.networkId); - if (scanDetailCache != null) { - ScanDetail scanDetail = scanDetailCache.getScanDetail(stateChangeResult.BSSID); - if (scanDetail != null) { - mWifiInfo.setFrequency(scanDetail.getScanResult().frequency); - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - if (networkDetail != null - && networkDetail.getAnt() == NetworkDetail.Ant.ChargeablePublic) { - mWifiInfo.setMeteredHint(true); - } - } - } - } - mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); - return state; - } - - private void updateWifiInfoAfterAssociation() { - WifiNative.ConnectionCapabilities capabilities = - mWifiNative.getConnectionCapabilities(mInterfaceName); - ThroughputPredictor throughputPredictor = mWifiInjector.getThroughputPredictor(); - int maxTxLinkSpeedMbps = throughputPredictor.predictMaxTxThroughput(capabilities); - int maxRxLinkSpeedMbps = throughputPredictor.predictMaxRxThroughput(capabilities); - mWifiInfo.setWifiStandard(capabilities.wifiStandard); - mWifiInfo.setMaxSupportedTxLinkSpeedMbps(maxTxLinkSpeedMbps); - mWifiInfo.setMaxSupportedRxLinkSpeedMbps(maxRxLinkSpeedMbps); - mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps( - maxTxLinkSpeedMbps, maxRxLinkSpeedMbps); - mWifiDataStall.setConnectionCapabilities(capabilities); - if (mVerboseLoggingEnabled) { - StringBuilder sb = new StringBuilder(); - logd(sb.append("WifiStandard: ").append(capabilities.wifiStandard) - .append(" maxTxSpeed: ").append(maxTxLinkSpeedMbps) - .append(" maxRxSpeed: ").append(maxRxLinkSpeedMbps) - .toString()); - } - } - - /** - * Tells IpClient what BSSID, L2Key and GroupHint to use for IpMemoryStore. - */ - private void updateLayer2Information() { - if (mIpClient != null) { - Pair<String, String> p = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); - if (!p.equals(mLastL2KeyAndGroupHint)) { - final MacAddress lastBssid = getCurrentBssid(); - final Layer2Information l2Information = new Layer2Information( - p.first, p.second, lastBssid); - // Update current BSSID on IpClient side whenever l2Key and groupHint - // pair changes (i.e. the initial connection establishment or L2 roaming - // happened). If we have COMPLETED the roaming to a different BSSID, start - // doing DNAv4/DNAv6 -style probing for on-link neighbors of interest (e.g. - // routers/DNS servers/default gateway). - if (mIpClient.updateLayer2Information(l2Information)) { - mLastL2KeyAndGroupHint = p; - } else { - mLastL2KeyAndGroupHint = null; - } - } - } - } - private @Nullable Pair<String, String> mLastL2KeyAndGroupHint = null; - - /** - * Resets the Wi-Fi Connections by clearing any state, resetting any sockets - * using the interface, stopping DHCP & disabling interface - */ - private void handleNetworkDisconnect() { - if (mVerboseLoggingEnabled) { - log("handleNetworkDisconnect:" - + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); - } - - WifiConfiguration wifiConfig = getCurrentWifiConfiguration(); - if (wifiConfig != null) { - ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromWifiConfiguration(wifiConfig); - mWifiInjector.getWakeupController().setLastDisconnectInfo(matchInfo); - mWifiNetworkSuggestionsManager.handleDisconnect(wifiConfig, getCurrentBSSID()); - } - stopRssiMonitoringOffload(); - - clearTargetBssid("handleNetworkDisconnect"); - - // Don't stop DHCP if Fils connection is in progress. - if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID - && mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID - && mLastNetworkId != mTargetNetworkId && mIpClientWithPreConnection) { - if (mVerboseLoggingEnabled) { - log("handleNetworkDisconnect: Don't stop IpClient as fils connection in progress: " - + " mLastNetworkId: " + mLastNetworkId - + " mTargetNetworkId" + mTargetNetworkId); - } - } else { - stopDhcpSetup(); - } - - mWifiScoreReport.stopConnectedNetworkScorer(); - /* Reset data structures */ - mWifiScoreReport.reset(); - mWifiInfo.reset(); - /* Reset roaming parameters */ - mIsAutoRoaming = false; - - sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); - if (mNetworkAgent != null) { - mNetworkAgent.unregister(); - mNetworkAgent = null; - } - - /* Clear network properties */ - clearLinkProperties(); - - mLastBssid = null; - mLastLinkLayerStats = null; - registerDisconnected(); - mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - mLastSimBasedConnectionCarrierName = null; - checkAbnormalDisconnectionAndTakeBugReport(); - mWifiScoreCard.resetConnectionState(); - mWifiDataStall.reset(); - updateLayer2Information(); - } - - void handlePreDhcpSetup() { - if (!mBluetoothConnectionActive) { - /* - * There are problems setting the Wi-Fi driver's power - * mode to active when bluetooth coexistence mode is - * enabled or sense. - * <p> - * We set Wi-Fi to active mode when - * obtaining an IP address because we've found - * compatibility issues with some routers with low power - * mode. - * <p> - * In order for this active power mode to properly be set, - * we disable coexistence mode until we're done with - * obtaining an IP address. One exception is if we - * are currently connected to a headset, since disabling - * coexistence would interrupt that connection. - */ - // Disable the coexistence mode - mWifiNative.setBluetoothCoexistenceMode( - mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); - } - - // Disable power save and suspend optimizations during DHCP - // Note: The order here is important for now. Brcm driver changes - // power settings when we control suspend mode optimizations. - // TODO: Remove this comment when the driver is fixed. - setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); - setPowerSave(false); - - // Update link layer stats - getWifiLinkLayerStats(); - - if (mWifiP2pChannel != null) { - /* P2p discovery breaks dhcp, shut it down in order to get through this */ - Message msg = new Message(); - msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY; - msg.arg1 = WifiP2pServiceImpl.ENABLED; - msg.arg2 = CMD_PRE_DHCP_ACTION_COMPLETE; - mWifiP2pChannel.sendMessage(msg); - } else { - // If the p2p service is not running, we can proceed directly. - sendMessage(CMD_PRE_DHCP_ACTION_COMPLETE); - } - } - - void addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets) { - List<Layer2PacketParcelable> mLayer2Packet = packets; - if ((mLayer2Packet != null) && (mLayer2Packet.size() > 0)) { - mWifiNative.flushAllHlp(mInterfaceName); - - for (int j = 0; j < mLayer2Packet.size(); j++) { - byte [] bytes = mLayer2Packet.get(j).payload; - byte [] payloadBytes = Arrays.copyOfRange(bytes, 12, bytes.length); - MacAddress dstAddress = mLayer2Packet.get(j).dstMacAddress; - - mWifiNative.addHlpReq(mInterfaceName, dstAddress, payloadBytes); - } - } - } - - void handlePostDhcpSetup() { - /* Restore power save and suspend optimizations */ - setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); - setPowerSave(true); - - p2pSendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, WifiP2pServiceImpl.DISABLED); - - // Set the coexistence mode back to its default value - mWifiNative.setBluetoothCoexistenceMode( - mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); - } - - /** - * Set power save mode - * - * @param ps true to enable power save (default behavior) - * false to disable power save. - * @return true for success, false for failure - */ - public boolean setPowerSave(boolean ps) { - if (mInterfaceName != null) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Setting power save for: " + mInterfaceName + " to: " + ps); - } - mWifiNative.setPowerSave(mInterfaceName, ps); - } else { - Log.e(TAG, "Failed to setPowerSave, interfaceName is null"); - return false; - } - return true; - } - - /** - * Set low latency mode - * - * @param enabled true to enable low latency - * false to disable low latency (default behavior). - * @return true for success, false for failure - */ - public boolean setLowLatencyMode(boolean enabled) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Setting low latency mode to " + enabled); - } - if (!mWifiNative.setLowLatencyMode(enabled)) { - Log.e(TAG, "Failed to setLowLatencyMode"); - return false; - } - return true; - } - - @VisibleForTesting - public static final long DIAGS_CONNECT_TIMEOUT_MILLIS = 60 * 1000; - /** - * Inform other components that a new connection attempt is starting. - */ - private void reportConnectionAttemptStart( - WifiConfiguration config, String targetBSSID, int roamType) { - int overlapWithLastConnectionMs = - mWifiMetrics.startConnectionEvent(config, targetBSSID, roamType); - DeviceConfigFacade deviceConfigFacade = mWifiInjector.getDeviceConfigFacade(); - if (deviceConfigFacade.isOverlappingConnectionBugreportEnabled() - && overlapWithLastConnectionMs - > deviceConfigFacade.getOverlappingConnectionDurationThresholdMs()) { - String bugTitle = "Wi-Fi BugReport"; - String bugDetail = "Detect abnormal overlapping connection"; - takeBugReport(bugTitle, bugDetail); - } - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED); - mWrongPasswordNotifier.onNewConnectionAttempt(); - removeMessages(CMD_DIAGS_CONNECT_TIMEOUT); - sendMessageDelayed(CMD_DIAGS_CONNECT_TIMEOUT, DIAGS_CONNECT_TIMEOUT_MILLIS); - } - - private void handleConnectionAttemptEndForDiagnostics(int level2FailureCode) { - switch (level2FailureCode) { - case WifiMetrics.ConnectionEvent.FAILURE_NONE: - break; - case WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED: - // WifiDiagnostics doesn't care about pre-empted connections, or cases - // where we failed to initiate a connection attempt with supplicant. - break; - default: - removeMessages(CMD_DIAGS_CONNECT_TIMEOUT); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - } - } - - /** - * Inform other components (WifiMetrics, WifiDiagnostics, WifiConnectivityManager, etc.) that - * the current connection attempt has concluded. - */ - private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode, - int level2FailureReason) { - // if connected, this should be non-null. - WifiConfiguration configuration = getCurrentWifiConfiguration(); - if (configuration == null) { - // If not connected, this should be non-null. - configuration = getTargetWifiConfiguration(); - } - - String bssid = mLastBssid == null ? mTargetBssid : mLastBssid; - String ssid = mWifiInfo.getSSID(); - if (WifiManager.UNKNOWN_SSID.equals(ssid)) { - ssid = getTargetSsid(); - } - if (level2FailureCode != WifiMetrics.ConnectionEvent.FAILURE_NONE) { - int blocklistReason = convertToBssidBlocklistMonitorFailureReason( - level2FailureCode, level2FailureReason); - if (blocklistReason != -1) { - int networkId = (configuration == null) ? WifiConfiguration.INVALID_NETWORK_ID - : configuration.networkId; - int scanRssi = mWifiConfigManager.findScanRssi(networkId, - mWifiHealthMonitor.getScanRssiValidTimeMs()); - mWifiScoreCard.noteConnectionFailure(mWifiInfo, scanRssi, ssid, blocklistReason); - checkAbnormalConnectionFailureAndTakeBugReport(ssid); - mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid, ssid, blocklistReason, - scanRssi); - } - } - - if (configuration != null - && configuration.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { - if (level2FailureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) { - mWifiMetrics.incrementNumOfCarrierWifiConnectionSuccess(); - } else if (level2FailureCode - == WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE - && level2FailureReason - != WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE) { - mWifiMetrics.incrementNumOfCarrierWifiConnectionAuthFailure(); - } else { - mWifiMetrics.incrementNumOfCarrierWifiConnectionNonAuthFailure(); - } - } - - boolean isAssociationRejection = level2FailureCode - == WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION; - boolean isAuthenticationFailure = level2FailureCode - == WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE - && level2FailureReason != WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD; - if ((isAssociationRejection || isAuthenticationFailure) - && mWifiConfigManager.isInFlakyRandomizationSsidHotlist(mTargetNetworkId)) { - mConnectionFailureNotifier - .showFailedToConnectDueToNoRandomizedMacSupportNotification(mTargetNetworkId); - } - - mWifiMetrics.endConnectionEvent(level2FailureCode, connectivityFailureCode, - level2FailureReason); - mWifiConnectivityManager.handleConnectionAttemptEnded(level2FailureCode, bssid, ssid); - if (configuration != null) { - mNetworkFactory.handleConnectionAttemptEnded(level2FailureCode, configuration); - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - level2FailureCode, configuration, getCurrentBSSID()); - ScanResult candidate = configuration.getNetworkSelectionStatus().getCandidate(); - if (candidate != null && !TextUtils.equals(candidate.BSSID, getCurrentBSSID())) { - mWifiMetrics.incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware(); - } - } - handleConnectionAttemptEndForDiagnostics(level2FailureCode); - } - - /* If this connection attempt fails after 802.1x stage, clear intermediate cached data. */ - void clearNetworkCachedDataIfNeeded(WifiConfiguration config, int reason) { - if (config == null) return; - - switch(reason) { - case 14: // MICHAEL_MIC_FAILURE - case 15: // 4WAY_HANDSHAKE_TIMEOUT - case 16: // GROUP_KEY_UPDATE_TIMEOUT - case 17: // IE_IN_4WAY_DIFFERS - case 18: // GROUP_CIPHER_NOT_VALID - case 19: // PAIRWISE_CIPHER_NOT_VALID - case 20: // AKMP_NOT_VALID - case 23: // IEEE_802_1X_AUTH_FAILED - case 24: // CIPHER_SUITE_REJECTED - case 29: // BAD_CIPHER_OR_AKM - case 45: // PEERKEY_MISMATCH - case 49: // INVALID_PMKID - mWifiNative.removeNetworkCachedData(config.networkId); - break; - default: - logi("Keep PMK cache for network disconnection reason " + reason); - break; - } - } - - /** - * Returns the sufficient RSSI for the frequency that this network is last seen on. - */ - private int getSufficientRssi(int networkId, String bssid) { - ScanDetailCache scanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(networkId); - if (scanDetailCache == null) { - return WifiInfo.INVALID_RSSI; - } - ScanResult scanResult = scanDetailCache.getScanResult(bssid); - if (scanResult == null) { - return WifiInfo.INVALID_RSSI; - } - return mWifiInjector.getScoringParams().getSufficientRssi(scanResult.frequency); - } - - private int convertToBssidBlocklistMonitorFailureReason( - int level2FailureCode, int failureReason) { - switch (level2FailureCode) { - case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT: - return BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT; - case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION: - if (failureReason == WifiMetricsProto.ConnectionEvent - .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA) { - return BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA; - } - return BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION; - case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE: - if (failureReason == WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD) { - return BssidBlocklistMonitor.REASON_WRONG_PASSWORD; - } else if (failureReason == WifiMetricsProto.ConnectionEvent - .AUTH_FAILURE_EAP_FAILURE) { - return BssidBlocklistMonitor.REASON_EAP_FAILURE; - } - return BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE; - case WifiMetrics.ConnectionEvent.FAILURE_DHCP: - return BssidBlocklistMonitor.REASON_DHCP_FAILURE; - default: - return -1; - } - } - - private void handleIPv4Success(DhcpResultsParcelable dhcpResults) { - if (mVerboseLoggingEnabled) { - logd("handleIPv4Success <" + dhcpResults.toString() + ">"); - logd("link address " + dhcpResults.baseConfiguration.getIpAddress()); - } - - Inet4Address addr; - synchronized (mDhcpResultsParcelableLock) { - mDhcpResultsParcelable = dhcpResults; - addr = (Inet4Address) dhcpResults.baseConfiguration.getIpAddress().getAddress(); - } - - if (mIsAutoRoaming) { - int previousAddress = mWifiInfo.getIpAddress(); - int newAddress = Inet4AddressUtils.inet4AddressToIntHTL(addr); - if (previousAddress != newAddress) { - logd("handleIPv4Success, roaming and address changed" - + mWifiInfo + " got: " + addr); - } - } - - mWifiInfo.setInetAddress(addr); - - final WifiConfiguration config = getCurrentWifiConfiguration(); - if (config != null) { - mWifiInfo.setEphemeral(config.ephemeral); - mWifiInfo.setTrusted(config.trusted); - mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpResults.leaseDuration); - mBssidBlocklistMonitor.handleDhcpProvisioningSuccess(mLastBssid, mWifiInfo.getSSID()); - } - - // Set meteredHint if DHCP result says network is metered - if (dhcpResults.vendorInfo != null && dhcpResults.vendorInfo.contains("ANDROID_METERED")) { - mWifiInfo.setMeteredHint(true); - mWifiMetrics.addMeteredStat(config, true); - } else { - mWifiMetrics.addMeteredStat(config, false); - } - - updateCapabilities(config); - } - - private void handleSuccessfulIpConfiguration() { - mLastSignalLevel = -1; // Force update of signal strength - WifiConfiguration c = getCurrentWifiConfiguration(); - if (c != null) { - // Reset IP failure tracking - c.getNetworkSelectionStatus().clearDisableReasonCounter( - WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); - - // Tell the framework whether the newly connected network is trusted or untrusted. - updateCapabilities(c); - } - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - } - - private void handleIPv4Failure() { - // TODO: Move this to provisioning failure, not DHCP failure. - // DHCPv4 failure is expected on an IPv6-only network. - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_DHCP_FAILURE); - if (mVerboseLoggingEnabled) { - int count = -1; - WifiConfiguration config = getCurrentWifiConfiguration(); - if (config != null) { - count = config.getNetworkSelectionStatus().getDisableReasonCounter( - WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); - } - log("DHCP failure count=" + count); - } - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, - WifiMetricsProto.ConnectionEvent.HLF_DHCP, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - synchronized (mDhcpResultsParcelableLock) { - mDhcpResultsParcelable = new DhcpResultsParcelable(); - } - if (mVerboseLoggingEnabled) { - logd("handleIPv4Failure"); - } - } - - private void handleIpConfigurationLost() { - mWifiInfo.setInetAddress(null); - mWifiInfo.setMeteredHint(false); - - mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, - WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); - - /* DHCP times out after about 30 seconds, we do a - * disconnect thru supplicant, we will let autojoin retry connecting to the network - */ - mWifiNative.disconnect(mInterfaceName); - } - - private void handleIpReachabilityLost() { - mWifiScoreCard.noteIpReachabilityLost(mWifiInfo); - mWifiInfo.setInetAddress(null); - mWifiInfo.setMeteredHint(false); - - // Disconnect via supplicant, and let autojoin retry connecting to the network. - mWifiNative.disconnect(mInterfaceName); - } - - /* - * Read a MAC address in /proc/arp/table, used by ClientModeImpl - * so as to record MAC address of default gateway. - **/ - private String macAddressFromRoute(String ipAddress) { - String macAddress = null; - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader("/proc/net/arp")); - - // Skip over the line bearing column titles - String line = reader.readLine(); - - while ((line = reader.readLine()) != null) { - String[] tokens = line.split("[ ]+"); - if (tokens.length < 6) { - continue; - } - - // ARP column format is - // Address HWType HWAddress Flags Mask IFace - String ip = tokens[0]; - String mac = tokens[3]; - - if (ipAddress.equals(ip)) { - macAddress = mac; - break; - } - } - - if (macAddress == null) { - loge("Did not find remoteAddress {" + ipAddress + "} in /proc/net/arp"); - } - - } catch (FileNotFoundException e) { - loge("Could not open /proc/net/arp to lookup mac address"); - } catch (IOException e) { - loge("Could not read /proc/net/arp to lookup mac address"); - } finally { - try { - if (reader != null) { - reader.close(); - } - } catch (IOException e) { - // Do nothing - } - } - return macAddress; - - } - - /** - * Determine if the specified auth failure is considered to be a permanent wrong password - * failure. The criteria for such failure is when wrong password error is detected - * and the network had never been connected before. - * - * For networks that have previously connected successfully, we consider wrong password - * failures to be temporary, to be on the conservative side. Since this might be the - * case where we are trying to connect to a wrong network (e.g. A network with same SSID - * but different password). - */ - private boolean isPermanentWrongPasswordFailure(int networkId, int reasonCode) { - if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD) { - return false; - } - WifiConfiguration network = mWifiConfigManager.getConfiguredNetwork(networkId); - if (network != null && network.getNetworkSelectionStatus().hasEverConnected()) { - return false; - } - return true; - } - - void registerNetworkFactory() { - if (!checkAndSetConnectivityInstance()) return; - mNetworkFactory.register(); - mUntrustedNetworkFactory.register(); - } - - /** - * ClientModeImpl needs to enable/disable other services when wifi is in client mode. This - * method allows ClientModeImpl to get these additional system services. - * - * At this time, this method is used to setup variables for P2P service and Wifi Aware. - */ - private void getAdditionalWifiServiceInterfaces() { - // First set up Wifi Direct - if (mP2pSupported) { - WifiP2pManager wifiP2pService = mContext.getSystemService(WifiP2pManager.class); - - if (wifiP2pService != null) { - mWifiP2pChannel = new AsyncChannel(); - mWifiP2pChannel.connect(mContext, getHandler(), - wifiP2pService.getP2pStateMachineMessenger()); - } - } - } - - /** - * Dynamically change the MAC address to use the locally randomized - * MAC address generated for each network. - * @param config WifiConfiguration with mRandomizedMacAddress to change into. If the address - * is masked out or not set, it will generate a new random MAC address. - */ - private void configureRandomizedMacAddress(WifiConfiguration config) { - if (config == null) { - Log.e(TAG, "No config to change MAC address to"); - return; - } - String currentMacString = mWifiNative.getMacAddress(mInterfaceName); - MacAddress currentMac = currentMacString == null ? null : - MacAddress.fromString(currentMacString); - MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config); - if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) { - Log.wtf(TAG, "Config generated an invalid MAC address"); - } else if (newMac.equals(currentMac)) { - Log.d(TAG, "No changes in MAC address"); - } else { - mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config); - boolean setMacSuccess = - mWifiNative.setMacAddress(mInterfaceName, newMac); - if (setMacSuccess) { - mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, newMac); - } - Log.d(TAG, "ConnectedMacRandomization SSID(" + config.getPrintableSsid() - + "). setMacAddress(" + newMac.toString() + ") from " - + currentMacString + " = " + setMacSuccess); - } - } - - /** - * Sets the current MAC to the factory MAC address. - */ - private void setCurrentMacToFactoryMac(WifiConfiguration config) { - MacAddress factoryMac = mWifiNative.getFactoryMacAddress(mInterfaceName); - if (factoryMac == null) { - Log.e(TAG, "Fail to set factory MAC address. Factory MAC is null."); - return; - } - String currentMacStr = mWifiNative.getMacAddress(mInterfaceName); - if (!TextUtils.equals(currentMacStr, factoryMac.toString())) { - if (mWifiNative.setMacAddress(mInterfaceName, factoryMac)) { - mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, factoryMac); - mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config); - } else { - Log.e(TAG, "Failed to set MAC address to " + "'" + factoryMac.toString() + "'"); - } - } - } - - /** - * Helper method to check if Connected MAC Randomization is supported - onDown events are - * skipped if this feature is enabled (b/72459123). - * - * @return boolean true if Connected MAC randomization is supported, false otherwise - */ - public boolean isConnectedMacRandomizationEnabled() { - return mContext.getResources().getBoolean( - R.bool.config_wifi_connected_mac_randomization_supported); - } - - /** - * Helper method allowing ClientModeManager to report an error (interface went down) and trigger - * recovery. - * - * @param reason int indicating the SelfRecovery failure type. - */ - public void failureDetected(int reason) { - // report a failure - mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_STA_IFACE_DOWN); - } - - /** - * Helper method to check if WPA2 network upgrade feature is enabled in the framework - * - * @return boolean true if feature is enabled. - */ - private boolean isWpa3SaeUpgradeEnabled() { - return mContext.getResources().getBoolean(R.bool.config_wifiSaeUpgradeEnabled); - } - - /** - * Helper method to check if WPA2 network upgrade offload is enabled in the driver/fw - * - * @return boolean true if feature is enabled. - */ - private boolean isWpa3SaeUpgradeOffloadEnabled() { - return mContext.getResources().getBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled); - } - - /******************************************************** - * HSM states - *******************************************************/ - - class DefaultState extends State { - - @Override - public boolean processMessage(Message message) { - boolean handleStatus = HANDLED; - int callbackIdentifier = -1; - int netId; - boolean ok; - - switch (message.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { - AsyncChannel ac = (AsyncChannel) message.obj; - if (ac == mWifiP2pChannel) { - if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - p2pSendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); - } else { - // TODO: We should probably do some cleanup or attempt a retry - // b/34283611 - loge("WifiP2pService connection failure, error=" + message.arg1); - } - } else { - loge("got HALF_CONNECTED for unknown channel"); - } - break; - } - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { - AsyncChannel ac = (AsyncChannel) message.obj; - if (ac == mWifiP2pChannel) { - loge("WifiP2pService channel lost, message.arg1 =" + message.arg1); - //TODO: Re-establish connection to state machine after a delay (b/34283611) - // mWifiP2pChannel.connect(mContext, getHandler(), - // mWifiP2pManager.getMessenger()); - } - break; - } - case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: - // If BT was connected and then turned off, there is no CONNECTION_STATE_CHANGE - // message. So we need to rely on STATE_CHANGE message to detect on->off - // transition and update mBluetoothConnectionActive status correctly. - mBluetoothConnectionActive = mBluetoothConnectionActive - && message.arg1 != BluetoothAdapter.STATE_OFF; - mWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive); - break; - case CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE: - // Transition to a non-disconnected state does correctly - // indicate BT is connected or being connected. - mBluetoothConnectionActive = - message.arg1 != BluetoothAdapter.STATE_DISCONNECTED; - mWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive); - break; - case CMD_ENABLE_RSSI_POLL: - mEnableRssiPolling = (message.arg1 == 1); - break; - case CMD_SET_HIGH_PERF_MODE: - if (message.arg1 == 1) { - setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false); - } else { - setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true); - } - break; - case CMD_INITIALIZE: - mWifiNative.initialize(); - mWifiScoreReport.initialize(); - break; - case CMD_BOOT_COMPLETED: - // get other services that we need to manage - getAdditionalWifiServiceInterfaces(); - registerNetworkFactory(); - mSarManager.handleBootCompleted(); - break; - case CMD_SCREEN_STATE_CHANGED: - handleScreenStateChanged(message.arg1 != 0); - break; - case CMD_DISCONNECT: - case CMD_RECONNECT: - case CMD_REASSOCIATE: - case WifiMonitor.NETWORK_CONNECTION_EVENT: - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: - case WifiMonitor.ASSOCIATION_REJECTION_EVENT: - case CMD_RSSI_POLL: - case CMD_ONESHOT_RSSI_POLL: - case CMD_PRE_DHCP_ACTION: - case CMD_PRE_DHCP_ACTION_COMPLETE: - case CMD_POST_DHCP_ACTION: - case WifiMonitor.SUP_REQUEST_IDENTITY: - case WifiMonitor.SUP_REQUEST_SIM_AUTH: - case WifiMonitor.TARGET_BSSID_EVENT: - case CMD_START_CONNECT: - case CMD_START_ROAM: - case WifiMonitor.ASSOCIATED_BSSID_EVENT: - case CMD_UNWANTED_NETWORK: - case CMD_DISCONNECTING_WATCHDOG_TIMER: - case CMD_ROAM_WATCHDOG_TIMER: - case CMD_SET_OPERATIONAL_MODE: - // using the CMD_SET_OPERATIONAL_MODE (sent at front of queue) to trigger the - // state transitions performed in setOperationalMode. - break; - case CMD_SET_SUSPEND_OPT_ENABLED: - if (message.arg1 == 1) { - if (message.arg2 == 1) { - mSuspendWakeLock.release(); - } - setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true); - } else { - setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false); - } - break; - case CMD_CONNECT_NETWORK: - // wifi off, can't connect. - callbackIdentifier = message.arg2; - sendActionListenerFailure(callbackIdentifier, WifiManager.BUSY); - break; - case CMD_SAVE_NETWORK: - // wifi off, nothing more to do here. - callbackIdentifier = message.arg2; - sendActionListenerSuccess(callbackIdentifier); - break; - case CMD_GET_SUPPORTED_FEATURES: - long featureSet = (mWifiNative.getSupportedFeatureSet(mInterfaceName)); - replyToMessage(message, message.what, Long.valueOf(featureSet)); - break; - case CMD_GET_LINK_LAYER_STATS: - case CMD_GET_CURRENT_NETWORK: - // Not supported hence reply with null message.obj - replyToMessage(message, message.what, null); - break; - case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: - NetworkInfo info = (NetworkInfo) message.obj; - mP2pConnected.set(info.isConnected()); - break; - case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: - mTemporarilyDisconnectWifi = (message.arg1 == 1); - replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); - break; - /* Link configuration (IP address, DNS, ...) changes notified via netlink */ - case CMD_UPDATE_LINKPROPERTIES: - updateLinkProperties((LinkProperties) message.obj); - break; - case CMD_START_SUBSCRIPTION_PROVISIONING: - replyToMessage(message, message.what, 0); - break; - case CMD_IP_CONFIGURATION_SUCCESSFUL: - case CMD_IP_CONFIGURATION_LOST: - case CMD_IP_REACHABILITY_LOST: - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; - break; - case CMD_START_IP_PACKET_OFFLOAD: - /* fall-through */ - case CMD_STOP_IP_PACKET_OFFLOAD: - case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: - case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: - if (mNetworkAgent != null) { - mNetworkAgent.sendSocketKeepaliveEvent(message.arg1, - SocketKeepalive.ERROR_INVALID_NETWORK); - } - break; - case CMD_START_RSSI_MONITORING_OFFLOAD: - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; - break; - case CMD_STOP_RSSI_MONITORING_OFFLOAD: - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; - break; - case CMD_QUERY_OSU_ICON: - /* reply with arg1 = 0 - it returns API failure to the calling app - * (message.what is not looked at) - */ - replyToMessage(message, message.what); - break; - case CMD_RESET_SIM_NETWORKS: - /* Defer this message until supplicant is started. */ - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; - deferMessage(message); - break; - case CMD_INSTALL_PACKET_FILTER: - mWifiNative.installPacketFilter(mInterfaceName, (byte[]) message.obj); - break; - case CMD_READ_PACKET_FILTER: - byte[] data = mWifiNative.readPacketFilter(mInterfaceName); - if (mIpClient != null) { - mIpClient.readPacketFilterComplete(data); - } - break; - case CMD_SET_FALLBACK_PACKET_FILTERING: - if ((boolean) message.obj) { - mWifiNative.startFilteringMulticastV4Packets(mInterfaceName); - } else { - mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName); - } - break; - case CMD_DIAGS_CONNECT_TIMEOUT: - mWifiDiagnostics.reportConnectionEvent( - BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT); - break; - case 0: - // We want to notice any empty messages (with what == 0) that might crop up. - // For example, we may have recycled a message sent to multiple handlers. - Log.wtf(TAG, "Error! empty message encountered"); - break; - default: - loge("Error! unhandled message" + message); - break; - } - - if (handleStatus == HANDLED) { - logStateAndMessage(message, this); - } - - return handleStatus; - } - } - - /** - * Helper method to start other services and get state ready for client mode - */ - private void setupClientMode() { - Log.d(TAG, "setupClientMode() ifacename = " + mInterfaceName); - - setHighPerfModeEnabled(false); - - mWifiStateTracker.updateState(WifiStateTracker.INVALID); - mIpClientCallbacks = new IpClientCallbacksImpl(); - mFacade.makeIpClient(mContext, mInterfaceName, mIpClientCallbacks); - if (!mIpClientCallbacks.awaitCreation()) { - Log.wtf(getName(), "Timeout waiting for IpClient"); - } - - setMulticastFilter(true); - registerForWifiMonitorEvents(); - mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts(); - setSupplicantLogLevel(); - - // reset state related to supplicant starting - mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); - // Initialize data structures - mLastBssid = null; - mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - mLastSimBasedConnectionCarrierName = null; - mLastSignalLevel = -1; - if (isConnectedMacRandomizationEnabled()) { - mWifiNative.setMacAddress(mInterfaceName, MacAddressUtils.createRandomUnicastAddress()); - } - mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); - // TODO: b/79504296 This broadcast has been deprecated and should be removed - sendSupplicantConnectionChangedBroadcast(true); - - mWifiNative.setExternalSim(mInterfaceName, true); - - mCountryCode.setReadyForChange(true); - - mWifiDiagnostics.startPktFateMonitoring(mInterfaceName); - mWifiDiagnostics.startLogging(mInterfaceName); - - mMboOceController.enable(); - mWifiDataStall.enablePhoneStateListener(); - - /** - * Enable bluetooth coexistence scan mode when bluetooth connection is active. - * When this mode is on, some of the low-level scan parameters used by the - * driver are changed to reduce interference with bluetooth - */ - mWifiNative.setBluetoothCoexistenceScanMode(mInterfaceName, mBluetoothConnectionActive); - sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); - - // Disable legacy multicast filtering, which on some chipsets defaults to enabled. - // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 - // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via - // IpClient.Callback.setFallbackMulticastFilter() - mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName); - mWifiNative.stopFilteringMulticastV6Packets(mInterfaceName); - - // Set the right suspend mode settings - mWifiNative.setSuspendOptimizations(mInterfaceName, mSuspendOptNeedsDisabled == 0 - && mContext.getResources().getBoolean( - R.bool.config_wifiSuspendOptimizationsEnabled)); - - setPowerSave(true); - - // Disable wpa_supplicant from auto reconnecting. - mWifiNative.enableStaAutoReconnect(mInterfaceName, false); - // STA has higher priority over P2P - mWifiNative.setConcurrencyPriority(true); - } - - /** - * Helper method to stop external services and clean up state from client mode. - */ - private void stopClientMode() { - handleNetworkDisconnect(); - // exiting supplicant started state is now only applicable to client mode - mWifiDiagnostics.stopLogging(mInterfaceName); - - mMboOceController.disable(); - mWifiDataStall.disablePhoneStateListener(); - if (mIpClient != null && mIpClient.shutdown()) { - // Block to make sure IpClient has really shut down, lest cleanup - // race with, say, bringup code over in tethering. - mIpClientCallbacks.awaitShutdown(); - } - mCountryCode.setReadyForChange(false); - mInterfaceName = null; - mWifiScoreReport.setInterfaceName(null); - // TODO: b/79504296 This broadcast has been deprecated and should be removed - sendSupplicantConnectionChangedBroadcast(false); - - // Remove any ephemeral or Passpoint networks, flush ANQP cache - mWifiConfigManager.removeAllEphemeralOrPasspointConfiguredNetworks(); - mWifiConfigManager.clearUserTemporarilyDisabledList(); - mPasspointManager.clearAnqpRequestsAndFlushCache(); - } - - void registerConnected() { - if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { - mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId); - // Notify PasspointManager of Passpoint network connected event. - WifiConfiguration currentNetwork = getCurrentWifiConfiguration(); - if (currentNetwork != null && currentNetwork.isPasspoint()) { - mPasspointManager.onPasspointNetworkConnected(currentNetwork.getKey()); - } - } - } - - void registerDisconnected() { - if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { - mWifiConfigManager.updateNetworkAfterDisconnect(mLastNetworkId); - } - } - - /** - * Returns WifiConfiguration object corresponding to the currently connected network, null if - * not connected. - */ - public WifiConfiguration getCurrentWifiConfiguration() { - if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { - return null; - } - return mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); - } - - private WifiConfiguration getTargetWifiConfiguration() { - if (mTargetNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { - return null; - } - return mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); - } - - ScanResult getCurrentScanResult() { - WifiConfiguration config = getCurrentWifiConfiguration(); - if (config == null) { - return null; - } - String bssid = mWifiInfo.getBSSID(); - if (bssid == null) { - bssid = mTargetBssid; - } - ScanDetailCache scanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); - - if (scanDetailCache == null) { - return null; - } - - return scanDetailCache.getScanResult(bssid); - } - - String getCurrentBSSID() { - return mLastBssid; - } - - MacAddress getCurrentBssid() { - MacAddress bssid = null; - try { - bssid = (mLastBssid != null) ? MacAddress.fromString(mLastBssid) : null; - } catch (IllegalArgumentException e) { - Log.e(TAG, "Invalid BSSID format: " + mLastBssid); - } - return bssid; - } - - void connectToNetwork(WifiConfiguration config) { - if ((config != null) && mWifiNative.connectToNetwork(mInterfaceName, config)) { - mWifiInjector.getWifiLastResortWatchdog().noteStartConnectTime(); - mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT, config); - mLastConnectAttemptTimestamp = mClock.getWallClockMillis(); - mIsAutoRoaming = false; - if (getCurrentState() != mDisconnectedState) { - transitionTo(mDisconnectingState); - } - } else { - loge("CMD_START_CONNECT Failed to start connection to network " + config); - mTargetWifiConfiguration = null; - stopIpClient(); - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - } - } - - class ConnectModeState extends State { - - @Override - public void enter() { - Log.d(TAG, "entering ConnectModeState: ifaceName = " + mInterfaceName); - mOperationalMode = CONNECT_MODE; - setupClientMode(); - if (!mWifiNative.removeAllNetworks(mInterfaceName)) { - loge("Failed to remove networks on entering connect mode"); - } - mWifiInfo.reset(); - mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); - - mWifiInjector.getWakeupController().reset(); - sendNetworkChangeBroadcast(DetailedState.DISCONNECTED); - - // Inform WifiConnectivityManager that Wifi is enabled - mWifiConnectivityManager.setWifiEnabled(true); - mNetworkFactory.setWifiState(true); - // Inform metrics that Wifi is Enabled (but not yet connected) - mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); - mWifiMetrics.logStaEvent(StaEvent.TYPE_WIFI_ENABLED); - mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); - mWifiHealthMonitor.setWifiEnabled(true); - mWifiDataStall.init(); - } - - @Override - public void exit() { - mOperationalMode = DISABLED_MODE; - - // Inform WifiConnectivityManager that Wifi is disabled - mWifiConnectivityManager.setWifiEnabled(false); - mNetworkFactory.setWifiState(false); - // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) - mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); - mWifiMetrics.logStaEvent(StaEvent.TYPE_WIFI_DISABLED); - // Inform scorecard that wifi is being disabled - mWifiScoreCard.noteWifiDisabled(mWifiInfo); - - if (!mWifiNative.removeAllNetworks(mInterfaceName)) { - loge("Failed to remove networks on exiting connect mode"); - } - mWifiInfo.reset(); - mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); - mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); - mWifiHealthMonitor.setWifiEnabled(false); - mWifiDataStall.reset(); - stopClientMode(); - } - - @Override - public boolean processMessage(Message message) { - WifiConfiguration config; - int netId; - boolean ok; - boolean didDisconnect; - String bssid; - String ssid; - NetworkUpdateResult result; - Set<Integer> removedNetworkIds; - int reasonCode; - boolean timedOut; - boolean handleStatus = HANDLED; - int callbackIdentifier = -1; - - int level2FailureReason = - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN; - switch (message.what) { - case WifiMonitor.ASSOCIATION_REJECTION_EVENT: - stopIpClient(); - mWifiDiagnostics.captureBugReportData( - WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE); - mDidBlackListBSSID = false; - bssid = (String) message.obj; - timedOut = message.arg1 > 0; - reasonCode = message.arg2; - Log.d(TAG, "Association Rejection event: bssid=" + bssid + " reason code=" - + reasonCode + " timedOut=" + Boolean.toString(timedOut)); - if (bssid == null || TextUtils.isEmpty(bssid)) { - // If BSSID is null, use the target roam BSSID - bssid = mTargetBssid; - } else if (mTargetBssid == SUPPLICANT_BSSID_ANY) { - // This is needed by BssidBlocklistMonitor to block continuously - // failing BSSIDs. Need to set here because mTargetBssid is currently - // not being set until association success. - mTargetBssid = bssid; - } - mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, - WifiConfiguration.NetworkSelectionStatus - .DISABLED_ASSOCIATION_REJECTION); - mWifiConfigManager.setRecentFailureAssociationStatus(mTargetNetworkId, - reasonCode); - - if (reasonCode == REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA) { - level2FailureReason = WifiMetricsProto.ConnectionEvent - .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA; - } - // If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. - reportConnectionAttemptEnd( - timedOut - ? WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT - : WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - level2FailureReason); - if (reasonCode != REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA) { - mWifiInjector.getWifiLastResortWatchdog() - .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), bssid, - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - break; - case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: - stopIpClient(); - mWifiDiagnostics.captureBugReportData( - WifiDiagnostics.REPORT_REASON_AUTH_FAILURE); - int disableReason = WifiConfiguration.NetworkSelectionStatus - .DISABLED_AUTHENTICATION_FAILURE; - reasonCode = message.arg1; - WifiConfiguration targetedNetwork = - mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); - // Check if this is a permanent wrong password failure. - if (isPermanentWrongPasswordFailure(mTargetNetworkId, reasonCode)) { - disableReason = WifiConfiguration.NetworkSelectionStatus - .DISABLED_BY_WRONG_PASSWORD; - if (targetedNetwork != null) { - mWrongPasswordNotifier.onWrongPasswordError( - targetedNetwork.SSID); - } - } else if (reasonCode == WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) { - int errorCode = message.arg2; - if (targetedNetwork != null && targetedNetwork.enterpriseConfig != null - && targetedNetwork.enterpriseConfig.isAuthenticationSimBased()) { - mEapFailureNotifier.onEapFailure(errorCode, targetedNetwork); - } - handleEapAuthFailure(mTargetNetworkId, errorCode); - if (errorCode == WifiNative.EAP_SIM_NOT_SUBSCRIBED) { - disableReason = WifiConfiguration.NetworkSelectionStatus - .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION; - } - } - mWifiConfigManager.updateNetworkSelectionStatus( - mTargetNetworkId, disableReason); - mWifiConfigManager.clearRecentFailureReason(mTargetNetworkId); - - //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. - switch (reasonCode) { - case WifiManager.ERROR_AUTH_FAILURE_NONE: - level2FailureReason = - WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE; - break; - case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT: - level2FailureReason = - WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT; - break; - case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD: - level2FailureReason = - WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD; - break; - case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE: - level2FailureReason = - WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE; - break; - default: - level2FailureReason = - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN; - break; - } - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - level2FailureReason); - if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD && reasonCode - != WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) { - mWifiInjector.getWifiLastResortWatchdog() - .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), - (mLastBssid == null) ? mTargetBssid : mLastBssid, - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - break; - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - SupplicantState state = handleSupplicantStateChange(message); - - // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT - // when authentication times out after a successful connection, - // we can figure this from the supplicant state. If supplicant - // state is DISCONNECTED, but the agent is not disconnected, we - // need to handle a disconnection - if (state == SupplicantState.DISCONNECTED && mNetworkAgent != null) { - if (mVerboseLoggingEnabled) { - log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); - } - handleNetworkDisconnect(); - transitionTo(mDisconnectedState); - } - - if (state == SupplicantState.COMPLETED) { - mWifiScoreReport.noteIpCheck(); - } - break; - case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: - if (message.arg1 == 1) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); - mWifiNative.disconnect(mInterfaceName); - mTemporarilyDisconnectWifi = true; - } else { - mWifiNative.reconnect(mInterfaceName); - mTemporarilyDisconnectWifi = false; - } - break; - case WifiMonitor.SUP_REQUEST_IDENTITY: - netId = message.arg2; - boolean identitySent = false; - // For SIM & AKA/AKA' EAP method Only, get identity from ICC - if (mTargetWifiConfiguration != null - && mTargetWifiConfiguration.networkId == netId - && mTargetWifiConfiguration.enterpriseConfig != null - && mTargetWifiConfiguration.enterpriseConfig - .isAuthenticationSimBased()) { - // Pair<identity, encrypted identity> - Pair<String, String> identityPair = mWifiCarrierInfoManager - .getSimIdentity(mTargetWifiConfiguration); - if (identityPair != null && identityPair.first != null) { - Log.i(TAG, "SUP_REQUEST_IDENTITY: identityPair=[" - + ((identityPair.first.length() >= 7) - ? identityPair.first.substring(0, 7 /* Prefix+PLMN ID */) - + "****" - : identityPair.first) + ", " - + (!TextUtils.isEmpty(identityPair.second) ? identityPair.second - : "<NONE>") + "]"); - mWifiNative.simIdentityResponse(mInterfaceName, identityPair.first, - identityPair.second); - identitySent = true; - } else { - Log.e(TAG, "Unable to retrieve identity from Telephony"); - } - } - - if (!identitySent) { - // Supplicant lacks credentials to connect to that network, hence black list - ssid = (String) message.obj; - if (mTargetWifiConfiguration != null && ssid != null - && mTargetWifiConfiguration.SSID != null - && mTargetWifiConfiguration.SSID.equals("\"" + ssid + "\"")) { - mWifiConfigManager.updateNetworkSelectionStatus( - mTargetWifiConfiguration.networkId, - WifiConfiguration.NetworkSelectionStatus - .DISABLED_AUTHENTICATION_NO_CREDENTIALS); - } - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_GENERIC); - mWifiNative.disconnect(mInterfaceName); - } - break; - case WifiMonitor.SUP_REQUEST_SIM_AUTH: - logd("Received SUP_REQUEST_SIM_AUTH"); - SimAuthRequestData requestData = (SimAuthRequestData) message.obj; - if (requestData != null) { - if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { - handleGsmAuthRequest(requestData); - } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA - || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { - handle3GAuthRequest(requestData); - } - } else { - loge("Invalid SIM auth request"); - } - break; - case CMD_START_SUBSCRIPTION_PROVISIONING: - IProvisioningCallback callback = (IProvisioningCallback) message.obj; - OsuProvider provider = - (OsuProvider) message.getData().getParcelable(EXTRA_OSU_PROVIDER); - int res = mPasspointManager.startSubscriptionProvisioning( - message.arg1, provider, callback) ? 1 : 0; - replyToMessage(message, message.what, res); - break; - case CMD_RECONNECT: - WorkSource workSource = (WorkSource) message.obj; - mWifiConnectivityManager.forceConnectivityScan(workSource); - break; - case CMD_REASSOCIATE: - mLastConnectAttemptTimestamp = mClock.getWallClockMillis(); - mWifiNative.reassociate(mInterfaceName); - break; - case CMD_START_ROAM: - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; - break; - case CMD_START_CONNECT: - /* connect command coming from auto-join */ - netId = message.arg1; - int uid = message.arg2; - bssid = (String) message.obj; - mSentHLPs = false; - - if (!hasConnectionRequests()) { - if (mNetworkAgent == null) { - loge("CMD_START_CONNECT but no requests and not connected," - + " bailing"); - break; - } else if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { - loge("CMD_START_CONNECT but no requests and connected, but app " - + "does not have sufficient permissions, bailing"); - break; - } - } - config = mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId); - logd("CMD_START_CONNECT " - + " my state " + getCurrentState().getName() - + " nid=" + Integer.toString(netId) - + " roam=" + Boolean.toString(mIsAutoRoaming)); - if (config == null) { - loge("CMD_START_CONNECT and no config, bail out..."); - break; - } - mTargetNetworkId = netId; - // Update scorecard while there is still state from existing connection - int scanRssi = mWifiConfigManager.findScanRssi(netId, - mWifiHealthMonitor.getScanRssiValidTimeMs()); - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID); - mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(config.SSID); - - updateWifiConfigOnStartConnection(config, bssid); - reportConnectionAttemptStart(config, mTargetBssid, - WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); - - String currentMacAddress = mWifiNative.getMacAddress(mInterfaceName); - mWifiInfo.setMacAddress(currentMacAddress); - Log.i(TAG, "Connecting with " + currentMacAddress + " as the mac address"); - - mTargetWifiConfiguration = config; - /* Check for FILS configuration again after updating the config */ - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256) - || config.allowedKeyManagement.get( - WifiConfiguration.KeyMgmt.FILS_SHA384)) { - - boolean isIpClientStarted = startIpClient(config, true); - if (isIpClientStarted) { - mIpClientWithPreConnection = true; - break; - } - } - connectToNetwork(config); - break; - case CMD_START_FILS_CONNECTION: - mWifiMetrics.incrementConnectRequestWithFilsAkmCount(); - List<Layer2PacketParcelable> packets; - packets = (List<Layer2PacketParcelable>) message.obj; - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Send HLP IEs to supplicant"); - } - addLayer2PacketsToHlpReq(packets); - config = mTargetWifiConfiguration; - connectToNetwork(config); - break; - case CMD_CONNECT_NETWORK: - callbackIdentifier = message.arg2; - result = (NetworkUpdateResult) message.obj; - netId = result.getNetworkId(); - connectToUserSelectNetwork( - netId, message.sendingUid, result.hasCredentialChanged()); - mWifiMetrics.logStaEvent( - StaEvent.TYPE_CONNECT_NETWORK, - mWifiConfigManager.getConfiguredNetwork(netId)); - sendActionListenerSuccess(callbackIdentifier); - break; - case CMD_SAVE_NETWORK: - callbackIdentifier = message.arg2; - result = (NetworkUpdateResult) message.obj; - netId = result.getNetworkId(); - if (mWifiInfo.getNetworkId() == netId) { - if (result.hasCredentialChanged()) { - // The network credentials changed and we're connected to this network, - // start a new connection with the updated credentials. - logi("CMD_SAVE_NETWORK credential changed for nid=" - + netId + ". Reconnecting."); - startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY); - } else { - if (result.hasProxyChanged()) { - if (mIpClient != null) { - log("Reconfiguring proxy on connection"); - WifiConfiguration currentConfig = getCurrentWifiConfiguration(); - if (currentConfig != null) { - mIpClient.setHttpProxy(currentConfig.getHttpProxy()); - } else { - Log.w(TAG, - "CMD_SAVE_NETWORK proxy change - but no current " - + "Wi-Fi config"); - } - } - } - if (result.hasIpChanged()) { - // The current connection configuration was changed - // We switched from DHCP to static or from static to DHCP, or the - // static IP address has changed. - log("Reconfiguring IP on connection"); - WifiConfiguration currentConfig = getCurrentWifiConfiguration(); - if (currentConfig != null) { - transitionTo(mObtainingIpState); - } else { - Log.w(TAG, "CMD_SAVE_NETWORK Ip change - but no current " - + "Wi-Fi config"); - } - } - } - } else if (mWifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID - && result.hasCredentialChanged()) { - logi("CMD_SAVE_NETWORK credential changed for nid=" - + netId + " while disconnected. Connecting."); - startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY); - } - sendActionListenerSuccess(callbackIdentifier); - break; - case WifiMonitor.ASSOCIATED_BSSID_EVENT: - // This is where we can confirm the connection BSSID. Use it to find the - // right ScanDetail to populate metrics. - String someBssid = (String) message.obj; - if (someBssid != null) { - // Get the ScanDetail associated with this BSSID. - ScanDetailCache scanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(mTargetNetworkId); - if (scanDetailCache != null) { - mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( - someBssid)); - } - // Update last associated BSSID - mLastBssid = someBssid; - } - handleStatus = NOT_HANDLED; - break; - case WifiMonitor.NETWORK_CONNECTION_EVENT: - if (mVerboseLoggingEnabled) log("Network connection established"); - mLastNetworkId = message.arg1; - mSentHLPs = message.arg2 == 1; - if (mSentHLPs) mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount(); - mWifiConfigManager.clearRecentFailureReason(mLastNetworkId); - mLastBssid = (String) message.obj; - reasonCode = message.arg2; - // TODO: This check should not be needed after ClientModeImpl refactor. - // Currently, the last connected network configuration is left in - // wpa_supplicant, this may result in wpa_supplicant initiating connection - // to it after a config store reload. Hence the old network Id lookups may not - // work, so disconnect the network and let network selector reselect a new - // network. - config = getCurrentWifiConfiguration(); - if (config != null) { - mWifiInfo.setBSSID(mLastBssid); - mWifiInfo.setNetworkId(mLastNetworkId); - mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); - - ScanDetailCache scanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); - if (scanDetailCache != null && mLastBssid != null) { - ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid); - if (scanResult != null) { - mWifiInfo.setFrequency(scanResult.frequency); - } - } - - // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA' - if (config.enterpriseConfig != null - && config.enterpriseConfig.isAuthenticationSimBased()) { - mLastSubId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config); - mLastSimBasedConnectionCarrierName = - mWifiCarrierInfoManager.getCarrierNameforSubId(mLastSubId); - String anonymousIdentity = - mWifiNative.getEapAnonymousIdentity(mInterfaceName); - if (!TextUtils.isEmpty(anonymousIdentity) - && !WifiCarrierInfoManager - .isAnonymousAtRealmIdentity(anonymousIdentity)) { - String decoratedPseudonym = mWifiCarrierInfoManager - .decoratePseudonymWith3GppRealm(config, - anonymousIdentity); - if (decoratedPseudonym != null) { - anonymousIdentity = decoratedPseudonym; - } - if (mVerboseLoggingEnabled) { - log("EAP Pseudonym: " + anonymousIdentity); - } - // Save the pseudonym only if it is a real one - config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity); - } else { - // Clear any stored pseudonyms - config.enterpriseConfig.setAnonymousIdentity(null); - } - mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID); - } - transitionTo(mObtainingIpState); - } else { - logw("Connected to unknown networkId " + mLastNetworkId - + ", disconnecting..."); - sendMessage(CMD_DISCONNECT); - } - break; - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - // Calling handleNetworkDisconnect here is redundant because we might already - // have called it when leaving L2ConnectedState to go to disconnecting state - // or thru other path - // We should normally check the mWifiInfo or mLastNetworkId so as to check - // if they are valid, and only in this case call handleNEtworkDisconnect, - // TODO: this should be fixed for a L MR release - // The side effect of calling handleNetworkDisconnect twice is that a bunch of - // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode - // at the chip etc... - if (mVerboseLoggingEnabled) log("ConnectModeState: Network connection lost "); - clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2); - handleNetworkDisconnect(); - transitionTo(mDisconnectedState); - break; - case CMD_QUERY_OSU_ICON: - mPasspointManager.queryPasspointIcon( - ((Bundle) message.obj).getLong(EXTRA_OSU_ICON_QUERY_BSSID), - ((Bundle) message.obj).getString(EXTRA_OSU_ICON_QUERY_FILENAME)); - break; - case WifiMonitor.TARGET_BSSID_EVENT: - // Trying to associate to this BSSID - if (message.obj != null) { - mTargetBssid = (String) message.obj; - } - break; - case CMD_GET_LINK_LAYER_STATS: - WifiLinkLayerStats stats = getWifiLinkLayerStats(); - replyToMessage(message, message.what, stats); - break; - case CMD_RESET_SIM_NETWORKS: - log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed"); - int resetReason = message.arg1; - if (resetReason == RESET_SIM_REASON_SIM_INSERTED) { - // whenever a SIM is inserted clear all SIM related notifications - mSimRequiredNotifier.dismissSimRequiredNotification(); - } else { - mWifiConfigManager.resetSimNetworks(); - } - if (resetReason != RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED) { - mWifiNetworkSuggestionsManager.resetCarrierPrivilegedApps(); - } - break; - case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: - // If BT was connected and then turned off, there is no CONNECTION_STATE_CHANGE - // message. So we need to rely on STATE_CHANGE message to detect on->off - // transition and update mBluetoothConnectionActive status correctly. - mBluetoothConnectionActive = mBluetoothConnectionActive - && message.arg1 != BluetoothAdapter.STATE_OFF; - mWifiNative.setBluetoothCoexistenceScanMode( - mInterfaceName, mBluetoothConnectionActive); - mWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive); - break; - case CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE: - // Transition to a non-disconnected state does correctly - // indicate BT is connected or being connected. - mBluetoothConnectionActive = - message.arg1 != BluetoothAdapter.STATE_DISCONNECTED; - mWifiNative.setBluetoothCoexistenceScanMode( - mInterfaceName, mBluetoothConnectionActive); - mWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive); - break; - case CMD_SET_SUSPEND_OPT_ENABLED: - if (message.arg1 == 1) { - setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); - if (message.arg2 == 1) { - mSuspendWakeLock.release(); - } - } else { - setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); - } - break; - case CMD_SET_HIGH_PERF_MODE: - if (message.arg1 == 1) { - setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); - } else { - setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); - } - break; - case CMD_ENABLE_TDLS: - if (message.obj != null) { - String remoteAddress = (String) message.obj; - boolean enable = (message.arg1 == 1); - mWifiNative.startTdls(mInterfaceName, remoteAddress, enable); - } - break; - case WifiMonitor.ANQP_DONE_EVENT: - // TODO(zqiu): remove this when switch over to wificond for ANQP requests. - mPasspointManager.notifyANQPDone((AnqpEvent) message.obj); - break; - case CMD_STOP_IP_PACKET_OFFLOAD: { - int slot = message.arg1; - int ret = stopWifiIPPacketOffload(slot); - if (mNetworkAgent != null) { - mNetworkAgent.sendSocketKeepaliveEvent(slot, ret); - } - break; - } - case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: - // TODO(zqiu): remove this when switch over to wificond for icon requests. - mPasspointManager.notifyIconDone((IconEvent) message.obj); - break; - case WifiMonitor.HS20_REMEDIATION_EVENT: - // TODO(zqiu): remove this when switch over to wificond for WNM frames - // monitoring. - mPasspointManager.receivedWnmFrame((WnmData) message.obj); - break; - case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: - handleBssTransitionRequest((BtmFrameData) message.obj); - break; - case CMD_CONFIG_ND_OFFLOAD: - final boolean enabled = (message.arg1 > 0); - mWifiNative.configureNeighborDiscoveryOffload(mInterfaceName, enabled); - break; - case CMD_PRE_DHCP_ACTION: - case CMD_PRE_DHCP_ACTION_COMPLETE: - case CMD_POST_DHCP_ACTION: - case CMD_IPV4_PROVISIONING_SUCCESS: - case CMD_IP_CONFIGURATION_SUCCESSFUL: - case CMD_IPV4_PROVISIONING_FAILURE: - handleStatus = handleL3MessagesWhenNotConnected(message); - break; - default: - handleStatus = NOT_HANDLED; - break; - } - - if (handleStatus == HANDLED) { - logStateAndMessage(message, this); - } - - return handleStatus; - } - } - - private boolean handleL3MessagesWhenNotConnected(Message message) { - boolean handleStatus = HANDLED; - - if (!mIpClientWithPreConnection) { - return NOT_HANDLED; - } - - switch (message.what) { - case CMD_PRE_DHCP_ACTION: - handlePreDhcpSetup(); - break; - case CMD_PRE_DHCP_ACTION_COMPLETE: - if (mIpClient != null) { - mIpClient.completedPreDhcpAction(); - } - break; - case CMD_IPV4_PROVISIONING_FAILURE: - stopDhcpSetup(); - deferMessage(message); - break; - case CMD_POST_DHCP_ACTION: - case CMD_IPV4_PROVISIONING_SUCCESS: - case CMD_IP_CONFIGURATION_SUCCESSFUL: - deferMessage(message); - break; - default: - return NOT_HANDLED; - } - - return handleStatus; - } - - private WifiNetworkAgentSpecifier createNetworkAgentSpecifier( - @NonNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid) { - currentWifiConfiguration.BSSID = currentBssid; - WifiNetworkAgentSpecifier wns = - new WifiNetworkAgentSpecifier(currentWifiConfiguration); - return wns; - } - - private NetworkCapabilities getCapabilities(WifiConfiguration currentWifiConfiguration) { - final NetworkCapabilities.Builder builder = - new NetworkCapabilities.Builder(mNetworkCapabilitiesFilter); - // MatchAllNetworkSpecifier set in the mNetworkCapabilitiesFilter should never be set in the - // agent's specifier. - builder.setNetworkSpecifier(null); - if (currentWifiConfiguration == null) { - return builder.build(); - } - - if (mWifiInfo.isTrusted()) { - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); - } else { - builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); - } - - builder.setOwnerUid(currentWifiConfiguration.creatorUid); - builder.setAdministratorUids(new int[] {currentWifiConfiguration.creatorUid}); - - if (!WifiConfiguration.isMetered(currentWifiConfiguration, mWifiInfo)) { - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - } else { - builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - } - - if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) { - builder.setSignalStrength(mWifiInfo.getRssi()); - } else { - builder.setSignalStrength(NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); - } - - if (currentWifiConfiguration.osu) { - builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - } - - if (!mWifiInfo.getSSID().equals(WifiManager.UNKNOWN_SSID)) { - builder.setSsid(mWifiInfo.getSSID()); - } - Pair<Integer, String> specificRequestUidAndPackageName = - mNetworkFactory.getSpecificNetworkRequestUidAndPackageName( - currentWifiConfiguration); - // There is an active specific request. - if (specificRequestUidAndPackageName.first != Process.INVALID_UID) { - // Remove internet capability. - builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - // Fill up the uid/packageName for this connection. - builder.setRequestorUid(specificRequestUidAndPackageName.first); - builder.setRequestorPackageName(specificRequestUidAndPackageName.second); - // Fill up the network agent specifier for this connection. - builder.setNetworkSpecifier(createNetworkAgentSpecifier( - currentWifiConfiguration, getCurrentBSSID())); - } - updateLinkBandwidth(builder); - return builder.build(); - } - - private void updateLinkBandwidth(NetworkCapabilities.Builder networkCapabilitiesBuilder) { - int rssiDbm = mWifiInfo.getRssi(); - int txTputKbps = INVALID_THROUGHPUT; - int rxTputKbps = INVALID_THROUGHPUT; - // If RSSI is available, check if throughput is available - if (rssiDbm != WifiInfo.INVALID_RSSI && mWifiDataStall != null) { - txTputKbps = mWifiDataStall.getTxThroughputKbps(); - rxTputKbps = mWifiDataStall.getRxThroughputKbps(); - } - if (txTputKbps == INVALID_THROUGHPUT && rxTputKbps != INVALID_THROUGHPUT) { - txTputKbps = rxTputKbps; - } else if (rxTputKbps == INVALID_THROUGHPUT && txTputKbps != INVALID_THROUGHPUT) { - rxTputKbps = txTputKbps; - } else if (txTputKbps == INVALID_THROUGHPUT && rxTputKbps == INVALID_THROUGHPUT) { - int maxTxLinkSpeedMbps = mWifiInfo.getMaxSupportedTxLinkSpeedMbps(); - int maxRxLinkSpeedMbps = mWifiInfo.getMaxSupportedRxLinkSpeedMbps(); - if (maxTxLinkSpeedMbps > 0) { - txTputKbps = maxTxLinkSpeedMbps * 1000; - } - if (maxRxLinkSpeedMbps > 0) { - rxTputKbps = maxRxLinkSpeedMbps * 1000; - } - } - if (mVerboseLoggingEnabled) { - logd("tx tput in kbps: " + txTputKbps); - logd("rx tput in kbps: " + rxTputKbps); - } - if (txTputKbps > 0) { - networkCapabilitiesBuilder.setLinkUpstreamBandwidthKbps(txTputKbps); - } - if (rxTputKbps > 0) { - networkCapabilitiesBuilder.setLinkDownstreamBandwidthKbps(rxTputKbps); - } - } - - /** - * Method to update network capabilities from the current WifiConfiguration. - */ - public void updateCapabilities() { - updateCapabilities(getCurrentWifiConfiguration()); - } - - private void updateCapabilities(WifiConfiguration currentWifiConfiguration) { - updateCapabilities(getCapabilities(currentWifiConfiguration)); - } - - private void updateCapabilities(NetworkCapabilities networkCapabilities) { - if (mNetworkAgent == null) { - return; - } - mNetworkAgent.sendNetworkCapabilities(networkCapabilities); - } - - private void handleEapAuthFailure(int networkId, int errorCode) { - WifiConfiguration targetedNetwork = - mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); - if (targetedNetwork != null) { - switch (targetedNetwork.enterpriseConfig.getEapMethod()) { - case WifiEnterpriseConfig.Eap.SIM: - case WifiEnterpriseConfig.Eap.AKA: - case WifiEnterpriseConfig.Eap.AKA_PRIME: - if (errorCode == WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED) { - mWifiCarrierInfoManager.resetCarrierKeysForImsiEncryption(targetedNetwork); - } - break; - - default: - // Do Nothing - } - } - } - - private class WifiNetworkAgent extends NetworkAgent { - WifiNetworkAgent(Context c, Looper l, String tag, NetworkCapabilities nc, LinkProperties lp, - int score, NetworkAgentConfig config, NetworkProvider provider) { - super(c, l, tag, nc, lp, score, config, provider); - register(); - } - private int mLastNetworkStatus = -1; // To detect when the status really changes - - @Override - public void onNetworkUnwanted() { - // Ignore if we're not the current networkAgent. - if (this != mNetworkAgent) return; - if (mVerboseLoggingEnabled) { - logd("WifiNetworkAgent -> Wifi unwanted score " + Integer.toString( - mWifiInfo.getScore())); - } - unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); - } - - @Override - public void onValidationStatus(int status, @Nullable Uri redirectUri) { - if (this != mNetworkAgent) return; - if (status == mLastNetworkStatus) return; - mLastNetworkStatus = status; - if (status == NetworkAgent.VALIDATION_STATUS_NOT_VALID) { - if (mVerboseLoggingEnabled) { - logd("WifiNetworkAgent -> Wifi networkStatus invalid, score=" - + Integer.toString(mWifiInfo.getScore())); - } - unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); - } else if (status == NetworkAgent.VALIDATION_STATUS_VALID) { - if (mVerboseLoggingEnabled) { - logd("WifiNetworkAgent -> Wifi networkStatus valid, score= " - + Integer.toString(mWifiInfo.getScore())); - } - mWifiMetrics.logStaEvent(StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK); - doNetworkStatus(status); - } - } - - @Override - public void onSaveAcceptUnvalidated(boolean accept) { - if (this != mNetworkAgent) return; - ClientModeImpl.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); - } - - @Override - public void onStartSocketKeepalive(int slot, @NonNull Duration interval, - @NonNull KeepalivePacketData packet) { - if (this != mNetworkAgent) return; - ClientModeImpl.this.sendMessage( - CMD_START_IP_PACKET_OFFLOAD, slot, (int) interval.getSeconds(), packet); - } - - @Override - public void onStopSocketKeepalive(int slot) { - if (this != mNetworkAgent) return; - ClientModeImpl.this.sendMessage(CMD_STOP_IP_PACKET_OFFLOAD, slot); - } - - @Override - public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) { - if (this != mNetworkAgent) return; - ClientModeImpl.this.sendMessage( - CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0, packet); - } - - @Override - public void onRemoveKeepalivePacketFilter(int slot) { - if (this != mNetworkAgent) return; - ClientModeImpl.this.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF, slot); - } - - @Override - public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { - if (this != mNetworkAgent) return; - // 0. If there are no thresholds, or if the thresholds are invalid, - // stop RSSI monitoring. - // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and - // MAX_VALUE at the start/end of the thresholds array if necessary. - // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware - // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then - // re-arm the hardware event. This needs to be done on the state machine thread to - // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one - // sent in the NetworkCapabilities) must be the one received from the hardware event - // received, or we might skip callbacks. - // 3. Ensure that when we disconnect, RSSI monitoring is stopped. - logd("Received signal strength thresholds: " + Arrays.toString(thresholds)); - if (thresholds.length == 0) { - ClientModeImpl.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, - mWifiInfo.getRssi()); - return; - } - int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); - rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; - rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; - Arrays.sort(rssiVals); - byte[] rssiRange = new byte[rssiVals.length]; - for (int i = 0; i < rssiVals.length; i++) { - int val = rssiVals[i]; - if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { - rssiRange[i] = (byte) val; - } else { - Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " - + Arrays.toString(rssiVals)); - ClientModeImpl.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, - mWifiInfo.getRssi()); - return; - } - } - // TODO: Do we quash rssi values in this sorted array which are very close? - mRssiRanges = rssiRange; - ClientModeImpl.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, - mWifiInfo.getRssi()); - } - - @Override - public void onAutomaticReconnectDisabled() { - if (this != mNetworkAgent) return; - unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); - } - } - - void unwantedNetwork(int reason) { - sendMessage(CMD_UNWANTED_NETWORK, reason); - } - - void doNetworkStatus(int status) { - sendMessage(CMD_NETWORK_STATUS, status); - } - - class L2ConnectedState extends State { - class RssiEventHandler implements WifiNative.WifiRssiEventHandler { - @Override - public void onRssiThresholdBreached(byte curRssi) { - if (mVerboseLoggingEnabled) { - Log.e(TAG, "onRssiThresholdBreach event. Cur Rssi = " + curRssi); - } - sendMessage(CMD_RSSI_THRESHOLD_BREACHED, curRssi); - } - } - - RssiEventHandler mRssiEventHandler = new RssiEventHandler(); - - @Override - public void enter() { - mRssiPollToken++; - if (mEnableRssiPolling) { - mLinkProbeManager.resetOnNewConnection(); - sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); - } - sendNetworkChangeBroadcast(DetailedState.CONNECTING); - - // If this network was explicitly selected by the user, evaluate whether to inform - // ConnectivityService of that fact so the system can treat it appropriately. - final WifiConfiguration config = getCurrentWifiConfiguration(); - - boolean explicitlySelected = false; - if (shouldEvaluateWhetherToSendExplicitlySelected(config)) { - // If explicitlySelected is true, the network was selected by the user via Settings - // or QuickSettings. If this network has Internet access, switch to it. Otherwise, - // switch to it only if the user confirms that they really want to switch, or has - // already confirmed and selected "Don't ask again". - explicitlySelected = - mWifiPermissionsUtil.checkNetworkSettingsPermission(config.lastConnectUid); - if (mVerboseLoggingEnabled) { - log("Network selected by UID " + config.lastConnectUid + " explicitlySelected=" - + explicitlySelected); - } - } - - if (mVerboseLoggingEnabled) { - log("explicitlySelected=" + explicitlySelected + " acceptUnvalidated=" - + config.noInternetAccessExpected); - } - - final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder() - .setLegacyType(ConnectivityManager.TYPE_WIFI) - .setLegacyTypeName(NETWORKTYPE) - .setExplicitlySelected(explicitlySelected) - .setUnvalidatedConnectivityAcceptable( - explicitlySelected && config.noInternetAccessExpected) - .setPartialConnectivityAcceptable(config.noInternetAccessExpected) - .build(); - final NetworkCapabilities nc = getCapabilities(getCurrentWifiConfiguration()); - // This should never happen. - if (mNetworkAgent != null) { - Log.wtf(TAG, "mNetworkAgent is not null: " + mNetworkAgent); - mNetworkAgent.unregister(); - } - mNetworkAgent = new WifiNetworkAgent(mContext, getHandler().getLooper(), - "WifiNetworkAgent", nc, mLinkProperties, 60, naConfig, - mNetworkFactory.getProvider()); - mWifiScoreReport.setNetworkAgent(mNetworkAgent); - - // We must clear the config BSSID, as the wifi chipset may decide to roam - // from this point on and having the BSSID specified in the network block would - // cause the roam to faile and the device to disconnect - clearTargetBssid("L2ConnectedState"); - mCountryCode.setReadyForChange(false); - mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); - mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo, - mNetworkAgent.getNetwork().getNetId()); - mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, mWifiInfo.getSSID()); - } - - @Override - public void exit() { - // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState - // Bug: 15347363 - // For paranoia's sake, call handleNetworkDisconnect - // only if BSSID is null or last networkId - // is not invalid. - if (mVerboseLoggingEnabled) { - StringBuilder sb = new StringBuilder(); - sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); - if (mLastBssid != null) { - sb.append(" ").append(mLastBssid); - } - } - mCountryCode.setReadyForChange(true); - mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); - mWifiStateTracker.updateState(WifiStateTracker.DISCONNECTED); - //Inform WifiLockManager - WifiLockManager wifiLockManager = mWifiInjector.getWifiLockManager(); - wifiLockManager.updateWifiClientConnected(false); - } - - @Override - public boolean processMessage(Message message) { - boolean handleStatus = HANDLED; - int callbackIdentifier = -1; - - switch (message.what) { - case CMD_PRE_DHCP_ACTION: - handlePreDhcpSetup(); - break; - case CMD_PRE_DHCP_ACTION_COMPLETE: - if (mIpClient != null) { - mIpClient.completedPreDhcpAction(); - } - break; - case CMD_POST_DHCP_ACTION: - handlePostDhcpSetup(); - // We advance to mConnectedState because IpClient will also send a - // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), - // which calls updateLinkProperties, which then sends - // CMD_IP_CONFIGURATION_SUCCESSFUL. - // - // In the event of failure, we transition to mDisconnectingState - // similarly--via messages sent back from IpClient. - break; - case CMD_IPV4_PROVISIONING_SUCCESS: { - handleIPv4Success((DhcpResultsParcelable) message.obj); - break; - } - case CMD_IPV4_PROVISIONING_FAILURE: { - handleIPv4Failure(); - mWifiInjector.getWifiLastResortWatchdog() - .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), - (mLastBssid == null) ? mTargetBssid : mLastBssid, - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - break; - } - case CMD_IP_CONFIGURATION_SUCCESSFUL: - if (getCurrentWifiConfiguration() == null) { - // The current config may have been removed while we were connecting, - // trigger a disconnect to clear up state. - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiNative.disconnect(mInterfaceName); - transitionTo(mDisconnectingState); - } else { - handleSuccessfulIpConfiguration(); - sendConnectedState(); - transitionTo(mConnectedState); - } - break; - case CMD_IP_CONFIGURATION_LOST: - // Get Link layer stats so that we get fresh tx packet counters. - getWifiLinkLayerStats(); - handleIpConfigurationLost(); - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiInjector.getWifiLastResortWatchdog() - .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), - (mLastBssid == null) ? mTargetBssid : mLastBssid, - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - transitionTo(mDisconnectingState); - break; - case CMD_IP_REACHABILITY_LOST: - if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj); - mWifiDiagnostics.captureBugReportData( - WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST); - mWifiMetrics.logWifiIsUnusableEvent( - WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST); - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1); - if (mIpReachabilityDisconnectEnabled) { - handleIpReachabilityLost(); - transitionTo(mDisconnectingState); - } else { - logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore"); - } - break; - case CMD_DISCONNECT: - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_GENERIC); - mWifiNative.disconnect(mInterfaceName); - transitionTo(mDisconnectingState); - break; - case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: - if (message.arg1 == 1) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); - mWifiNative.disconnect(mInterfaceName); - mTemporarilyDisconnectWifi = true; - transitionTo(mDisconnectingState); - } - break; - case WifiMonitor.NETWORK_CONNECTION_EVENT: - mWifiInfo.setBSSID((String) message.obj); - mLastNetworkId = message.arg1; - mWifiInfo.setNetworkId(mLastNetworkId); - mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); - mLastBssid = (String) message.obj; - break; - case CMD_ONESHOT_RSSI_POLL: - if (!mEnableRssiPolling) { - updateLinkLayerStatsRssiAndScoreReportInternal(); - } - break; - case CMD_RSSI_POLL: - if (message.arg1 == mRssiPollToken) { - WifiLinkLayerStats stats = updateLinkLayerStatsRssiAndScoreReportInternal(); - mWifiMetrics.updateWifiUsabilityStatsEntries(mWifiInfo, stats); - if (mWifiScoreReport.shouldCheckIpLayer()) { - if (mIpClient != null) { - mIpClient.confirmConfiguration(); - } - mWifiScoreReport.noteIpCheck(); - } - int statusDataStall = mWifiDataStall.checkDataStallAndThroughputSufficiency( - mLastLinkLayerStats, stats, mWifiInfo); - if (mDataStallTriggerTimeMs == -1 - && statusDataStall != WifiIsUnusableEvent.TYPE_UNKNOWN) { - mDataStallTriggerTimeMs = mClock.getElapsedSinceBootMillis(); - mLastStatusDataStall = statusDataStall; - } - if (mDataStallTriggerTimeMs != -1) { - long elapsedTime = mClock.getElapsedSinceBootMillis() - - mDataStallTriggerTimeMs; - if (elapsedTime >= DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS) { - mDataStallTriggerTimeMs = -1; - mWifiMetrics.addToWifiUsabilityStatsList( - WifiUsabilityStats.LABEL_BAD, - convertToUsabilityStatsTriggerType(mLastStatusDataStall), - -1); - mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN; - } - } - mWifiMetrics.incrementWifiLinkLayerUsageStats(stats); - mLastLinkLayerStats = stats; - mWifiScoreCard.noteSignalPoll(mWifiInfo); - mLinkProbeManager.updateConnectionStats( - mWifiInfo, mInterfaceName); - sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), - getPollRssiIntervalMsecs()); - if (mVerboseLoggingEnabled) sendRssiChangeBroadcast(mWifiInfo.getRssi()); - mWifiTrafficPoller.notifyOnDataActivity(mWifiInfo.txSuccess, - mWifiInfo.rxSuccess); - } else { - // Polling has completed - } - break; - case CMD_ENABLE_RSSI_POLL: - cleanWifiScore(); - mEnableRssiPolling = (message.arg1 == 1); - mRssiPollToken++; - if (mEnableRssiPolling) { - // First poll - mLastSignalLevel = -1; - mLinkProbeManager.resetOnScreenTurnedOn(); - fetchRssiLinkSpeedAndFrequencyNative(); - sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), - getPollRssiIntervalMsecs()); - } - break; - case WifiMonitor.ASSOCIATED_BSSID_EVENT: - if ((String) message.obj == null) { - logw("Associated command w/o BSSID"); - break; - } - mLastBssid = (String) message.obj; - if (mLastBssid != null && (mWifiInfo.getBSSID() == null - || !mLastBssid.equals(mWifiInfo.getBSSID()))) { - mWifiInfo.setBSSID(mLastBssid); - WifiConfiguration config = getCurrentWifiConfiguration(); - if (config != null) { - ScanDetailCache scanDetailCache = mWifiConfigManager - .getScanDetailCacheForNetwork(config.networkId); - if (scanDetailCache != null) { - ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid); - if (scanResult != null) { - mWifiInfo.setFrequency(scanResult.frequency); - } - } - } - } - break; - case CMD_START_RSSI_MONITORING_OFFLOAD: - case CMD_RSSI_THRESHOLD_BREACHED: - byte currRssi = (byte) message.arg1; - processRssiThreshold(currRssi, message.what, mRssiEventHandler); - break; - case CMD_STOP_RSSI_MONITORING_OFFLOAD: - stopRssiMonitoringOffload(); - break; - case CMD_RECONNECT: - log(" Ignore CMD_RECONNECT request because wifi is already connected"); - break; - case CMD_RESET_SIM_NETWORKS: - if (message.arg1 != RESET_SIM_REASON_SIM_INSERTED - && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { - WifiConfiguration config = - mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); - if (config != null - && ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED - && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) - || (config.enterpriseConfig != null - && config.enterpriseConfig.isAuthenticationSimBased() - && !mWifiCarrierInfoManager.isSimPresent(mLastSubId)))) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_RESET_SIM_NETWORKS); - // remove local PMKSA cache in framework - mWifiNative.removeNetworkCachedData(mLastNetworkId); - // remove network so that supplicant's PMKSA cache is cleared - mWifiNative.removeAllNetworks(mInterfaceName); - mSimRequiredNotifier.showSimRequiredNotification( - config, mLastSimBasedConnectionCarrierName); - transitionTo(mDisconnectingState); - } - } - /* allow parent state to reset data for other networks */ - handleStatus = NOT_HANDLED; - break; - case CMD_START_IP_PACKET_OFFLOAD: { - int slot = message.arg1; - int intervalSeconds = message.arg2; - KeepalivePacketData pkt = (KeepalivePacketData) message.obj; - int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); - if (mNetworkAgent != null) { - mNetworkAgent.sendSocketKeepaliveEvent(slot, result); - } - break; - } - case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: { - if (mIpClient != null) { - final int slot = message.arg1; - if (message.obj instanceof NattKeepalivePacketData) { - final NattKeepalivePacketData pkt = - (NattKeepalivePacketData) message.obj; - mIpClient.addKeepalivePacketFilter(slot, pkt); - } else if (message.obj instanceof TcpKeepalivePacketData) { - final TcpKeepalivePacketData pkt = - (TcpKeepalivePacketData) message.obj; - mIpClient.addKeepalivePacketFilter(slot, pkt); - } - } - break; - } - case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: { - if (mIpClient != null) { - mIpClient.removeKeepalivePacketFilter(message.arg1); - } - break; - } - default: - handleStatus = NOT_HANDLED; - break; - } - - if (handleStatus == HANDLED) { - logStateAndMessage(message, this); - } - - return handleStatus; - } - - /** - * Fetches link stats and updates Wifi Score Report. - */ - private WifiLinkLayerStats updateLinkLayerStatsRssiAndScoreReportInternal() { - WifiLinkLayerStats stats = getWifiLinkLayerStats(); - // Get Info and continue polling - fetchRssiLinkSpeedAndFrequencyNative(); - // Send the update score to network agent. - mWifiScoreReport.calculateAndReportScore(); - return stats; - } - } - - /** - * Fetches link stats and updates Wifi Score Report. - */ - public void updateLinkLayerStatsRssiAndScoreReport() { - sendMessage(CMD_ONESHOT_RSSI_POLL); - } - - private static int convertToUsabilityStatsTriggerType(int unusableEventTriggerType) { - int triggerType; - switch (unusableEventTriggerType) { - case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX: - triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX; - break; - case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX: - triggerType = WifiUsabilityStats.TYPE_DATA_STALL_TX_WITHOUT_RX; - break; - case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH: - triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BOTH; - break; - case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT: - triggerType = WifiUsabilityStats.TYPE_FIRMWARE_ALERT; - break; - case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST: - triggerType = WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST; - break; - default: - triggerType = WifiUsabilityStats.TYPE_UNKNOWN; - Log.e(TAG, "Unknown WifiIsUnusableEvent: " + unusableEventTriggerType); - } - return triggerType; - } - - class ObtainingIpState extends State { - @Override - public void enter() { - WifiConfiguration currentConfig = getCurrentWifiConfiguration(); - if (mIpClientWithPreConnection && mIpClient != null) { - mIpClient.notifyPreconnectionComplete(mSentHLPs); - mIpClientWithPreConnection = false; - mSentHLPs = false; - } else { - startIpClient(currentConfig, false); - } - // Get Link layer stats so as we get fresh tx packet counters - getWifiLinkLayerStats(); - } - - @Override - public boolean processMessage(Message message) { - boolean handleStatus = HANDLED; - - switch(message.what) { - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiInjector.getWifiLastResortWatchdog() - .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), - (message.obj == null) - ? mTargetBssid : (String) message.obj, - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - handleStatus = NOT_HANDLED; - break; - case CMD_SET_HIGH_PERF_MODE: - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; - deferMessage(message); - break; - default: - handleStatus = NOT_HANDLED; - break; - } - - if (handleStatus == HANDLED) { - logStateAndMessage(message, this); - } - return handleStatus; - } - } - - /** - * Helper function to check if we need to invoke - * {@link NetworkAgent#explicitlySelected(boolean, boolean)} to indicate that we connected to a - * network which the user just chose - * (i.e less than {@link #LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS) before). - */ - @VisibleForTesting - public boolean shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration currentConfig) { - if (currentConfig == null) { - Log.wtf(TAG, "Current WifiConfiguration is null, but IP provisioning just succeeded"); - return false; - } - long currentTimeMillis = mClock.getElapsedSinceBootMillis(); - return (mWifiConfigManager.getLastSelectedNetwork() == currentConfig.networkId - && currentTimeMillis - mWifiConfigManager.getLastSelectedTimeStamp() - < LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS); - } - - private void sendConnectedState() { - mNetworkAgent.markConnected(); - sendNetworkChangeBroadcast(DetailedState.CONNECTED); - } - - class RoamingState extends State { - boolean mAssociated; - @Override - public void enter() { - if (mVerboseLoggingEnabled) { - log("RoamingState Enter mScreenOn=" + mScreenOn); - } - - // Make sure we disconnect if roaming fails - mRoamWatchdogCount++; - logd("Start Roam Watchdog " + mRoamWatchdogCount); - sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, - mRoamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); - mAssociated = false; - } - @Override - public boolean processMessage(Message message) { - WifiConfiguration config; - boolean handleStatus = HANDLED; - - switch (message.what) { - case CMD_IP_CONFIGURATION_LOST: - config = getCurrentWifiConfiguration(); - if (config != null) { - mWifiDiagnostics.captureBugReportData( - WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE); - } - handleStatus = NOT_HANDLED; - break; - case CMD_UNWANTED_NETWORK: - if (mVerboseLoggingEnabled) { - log("Roaming and CS doesn't want the network -> ignore"); - } - break; - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - /** - * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT - * before NETWORK_DISCONNECTION_EVENT - * And there is an associated BSSID corresponding to our target BSSID, then - * we have missed the network disconnection, transition to mDisconnectedState - * and handle the rest of the events there. - */ - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - if (stateChangeResult.state == SupplicantState.DISCONNECTED - || stateChangeResult.state == SupplicantState.INACTIVE - || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { - if (mVerboseLoggingEnabled) { - log("STATE_CHANGE_EVENT in roaming state " - + stateChangeResult.toString()); - } - if (stateChangeResult.BSSID != null - && stateChangeResult.BSSID.equals(mTargetBssid)) { - handleNetworkDisconnect(); - transitionTo(mDisconnectedState); - } - } - if (stateChangeResult.state == SupplicantState.ASSOCIATED) { - // We completed the layer2 roaming part - mAssociated = true; - if (stateChangeResult.BSSID != null) { - mTargetBssid = stateChangeResult.BSSID; - } - } - break; - case CMD_ROAM_WATCHDOG_TIMER: - if (mRoamWatchdogCount == message.arg1) { - if (mVerboseLoggingEnabled) log("roaming watchdog! -> disconnect"); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mRoamFailCount++; - handleNetworkDisconnect(); - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER); - mWifiNative.disconnect(mInterfaceName); - transitionTo(mDisconnectedState); - } - break; - case WifiMonitor.NETWORK_CONNECTION_EVENT: - if (mAssociated) { - if (mVerboseLoggingEnabled) { - log("roaming and Network connection established"); - } - mLastNetworkId = message.arg1; - mLastBssid = (String) message.obj; - mWifiInfo.setBSSID(mLastBssid); - mWifiInfo.setNetworkId(mLastNetworkId); - - // Successful framework roam! (probably) - mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, - mWifiInfo.getSSID()); - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - // We must clear the config BSSID, as the wifi chipset may decide to roam - // from this point on and having the BSSID specified by QNS would cause - // the roam to fail and the device to disconnect. - // When transition from RoamingState to DisconnectingState or - // DisconnectedState, the config BSSID is cleared by - // handleNetworkDisconnect(). - clearTargetBssid("RoamingCompleted"); - - // We used to transition to ObtainingIpState in an - // attempt to do DHCPv4 RENEWs on framework roams. - // DHCP can take too long to time out, and we now rely - // upon IpClient's use of IpReachabilityMonitor to - // confirm our current network configuration. - // - // mIpClient.confirmConfiguration() is called within - // the handling of SupplicantState.COMPLETED. - transitionTo(mConnectedState); - } else { - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; - } - break; - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - // Throw away but only if it corresponds to the network we're roaming to - String bssid = (String) message.obj; - if (true) { - String target = ""; - if (mTargetBssid != null) target = mTargetBssid; - log("NETWORK_DISCONNECTION_EVENT in roaming state" - + " BSSID=" + bssid - + " target=" + target); - } - clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2); - if (bssid != null && bssid.equals(mTargetBssid)) { - handleNetworkDisconnect(); - transitionTo(mDisconnectedState); - } - break; - case CMD_GET_CURRENT_NETWORK: - replyToMessage(message, message.what, getCurrentNetwork()); - break; - default: - handleStatus = NOT_HANDLED; - break; - } - - if (handleStatus == HANDLED) { - logStateAndMessage(message, this); - } - return handleStatus; - } - - @Override - public void exit() { - logd("ClientModeImpl: Leaving Roaming state"); - } - } - - class ConnectedState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) { - log("Enter ConnectedState mScreenOn=" + mScreenOn); - } - - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - registerConnected(); - mLastConnectAttemptTimestamp = 0; - mTargetWifiConfiguration = null; - mWifiScoreReport.reset(); - mLastSignalLevel = -1; - - // Not roaming anymore - mIsAutoRoaming = false; - - mLastDriverRoamAttempt = 0; - mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(true); - mWifiStateTracker.updateState(WifiStateTracker.CONNECTED); - //Inform WifiLockManager - WifiLockManager wifiLockManager = mWifiInjector.getWifiLockManager(); - wifiLockManager.updateWifiClientConnected(true); - mWifiScoreReport.startConnectedNetworkScorer(mNetworkAgent.getNetwork().getNetId()); - updateLinkLayerStatsRssiAndScoreReport(); - } - @Override - public boolean processMessage(Message message) { - WifiConfiguration config = null; - boolean handleStatus = HANDLED; - - switch (message.what) { - case CMD_UNWANTED_NETWORK: - if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_UNWANTED); - mWifiNative.disconnect(mInterfaceName); - transitionTo(mDisconnectingState); - } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN - || message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { - Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN - ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" - : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); - config = getCurrentWifiConfiguration(); - if (config != null) { - // Disable autojoin - if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { - mWifiConfigManager.setNetworkValidatedInternetAccess( - config.networkId, false); - mWifiConfigManager.updateNetworkSelectionStatus(config.networkId, - DISABLED_NO_INTERNET_PERMANENT); - } else { - // stop collect last-mile stats since validation fail - removeMessages(CMD_DIAGS_CONNECT_TIMEOUT); - mWifiDiagnostics.reportConnectionEvent( - WifiDiagnostics.CONNECTION_EVENT_FAILED); - mWifiConfigManager.incrementNetworkNoInternetAccessReports( - config.networkId); - // If this was not the last selected network, update network - // selection status to temporarily disable the network. - if (mWifiConfigManager.getLastSelectedNetwork() != config.networkId - && !config.noInternetAccessExpected) { - Log.i(TAG, "Temporarily disabling network because of" - + "no-internet access"); - mWifiConfigManager.updateNetworkSelectionStatus( - config.networkId, - DISABLED_NO_INTERNET_TEMPORARY); - mBssidBlocklistMonitor.handleBssidConnectionFailure( - mLastBssid, config.SSID, - BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, - mWifiInfo.getRssi()); - } - mWifiScoreCard.noteValidationFailure(mWifiInfo); - } - } - } - break; - case CMD_NETWORK_STATUS: - if (message.arg1 == NetworkAgent.VALIDATION_STATUS_VALID) { - // stop collect last-mile stats since validation pass - removeMessages(CMD_DIAGS_CONNECT_TIMEOUT); - mWifiDiagnostics.reportConnectionEvent( - WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); - mWifiScoreCard.noteValidationSuccess(mWifiInfo); - mBssidBlocklistMonitor.handleNetworkValidationSuccess(mLastBssid, - mWifiInfo.getSSID()); - config = getCurrentWifiConfiguration(); - if (config != null) { - // re-enable autojoin - mWifiConfigManager.updateNetworkSelectionStatus( - config.networkId, - WifiConfiguration.NetworkSelectionStatus - .DISABLED_NONE); - mWifiConfigManager.setNetworkValidatedInternetAccess( - config.networkId, true); - } - } - break; - case CMD_ACCEPT_UNVALIDATED: - boolean accept = (message.arg1 != 0); - mWifiConfigManager.setNetworkNoInternetAccessExpected(mLastNetworkId, accept); - break; - case WifiMonitor.ASSOCIATED_BSSID_EVENT: - // ASSOCIATING to a new BSSID while already connected, indicates - // that driver is roaming - mLastDriverRoamAttempt = mClock.getWallClockMillis(); - handleStatus = NOT_HANDLED; - break; - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - long lastRoam = 0; - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - if (mLastDriverRoamAttempt != 0) { - // Calculate time since last driver roam attempt - lastRoam = mClock.getWallClockMillis() - mLastDriverRoamAttempt; - mLastDriverRoamAttempt = 0; - } - if (unexpectedDisconnectedReason(message.arg2)) { - mWifiDiagnostics.captureBugReportData( - WifiDiagnostics.REPORT_REASON_UNEXPECTED_DISCONNECT); - } - - boolean localGen = message.arg1 == 1; - if (!localGen) { // ignore disconnects initiated by wpa_supplicant. - mWifiScoreCard.noteNonlocalDisconnect(message.arg2); - mBssidBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(), - mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, - mWifiInfo.getRssi()); - } - config = getCurrentWifiConfiguration(); - - if (mVerboseLoggingEnabled) { - log("NETWORK_DISCONNECTION_EVENT in connected state" - + " BSSID=" + mWifiInfo.getBSSID() - + " RSSI=" + mWifiInfo.getRssi() - + " freq=" + mWifiInfo.getFrequency() - + " reason=" + message.arg2 - + " Network Selection Status=" + (config == null ? "Unavailable" - : config.getNetworkSelectionStatus().getNetworkStatusString())); - } - break; - case CMD_START_ROAM: - // Clear the driver roam indication since we are attempting a framework roam - mLastDriverRoamAttempt = 0; - - /* Connect command coming from auto-join */ - int netId = message.arg1; - ScanResult candidate = (ScanResult) message.obj; - String bssid = SUPPLICANT_BSSID_ANY; - if (candidate != null) { - bssid = candidate.BSSID; - } - config = mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId); - if (config == null) { - loge("CMD_START_ROAM and no config, bail out..."); - break; - } - int scanRssi = mWifiConfigManager.findScanRssi(netId, - mWifiHealthMonitor.getScanRssiValidTimeMs()); - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID); - setTargetBssid(config, bssid); - mTargetNetworkId = netId; - - logd("CMD_START_ROAM sup state " - + " my state " + getCurrentState().getName() - + " nid=" + Integer.toString(netId) - + " config " + config.getKey() - + " targetRoamBSSID " + mTargetBssid); - - reportConnectionAttemptStart(config, mTargetBssid, - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - if (mWifiNative.roamToNetwork(mInterfaceName, config)) { - mLastConnectAttemptTimestamp = mClock.getWallClockMillis(); - mTargetWifiConfiguration = config; - mIsAutoRoaming = true; - mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_ROAM, config); - transitionTo(mRoamingState); - } else { - loge("CMD_START_ROAM Failed to start roaming to network " + config); - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; - break; - } - break; - case CMD_IP_CONFIGURATION_LOST: - mWifiMetrics.incrementIpRenewalFailure(); - handleStatus = NOT_HANDLED; - break; - case CMD_GET_CURRENT_NETWORK: - replyToMessage(message, message.what, getCurrentNetwork()); - break; - default: - handleStatus = NOT_HANDLED; - break; - } - - if (handleStatus == HANDLED) { - logStateAndMessage(message, this); - } - - return handleStatus; - } - - @Override - public void exit() { - logd("ClientModeImpl: Leaving Connected state"); - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_TRANSITIONING); - - mLastDriverRoamAttempt = 0; - mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(false); - } - } - - class DisconnectingState extends State { - - @Override - public void enter() { - - if (mVerboseLoggingEnabled) { - logd(" Enter DisconnectingState State screenOn=" + mScreenOn); - } - - // Make sure we disconnect: we enter this state prior to connecting to a new - // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE - // event which in this case will be indicating that supplicant started to associate. - // In some cases supplicant doesn't ignore the connect requests (it might not - // find the target SSID in its cache), - // Therefore we end up stuck that state, hence the need for the watchdog. - mDisconnectingWatchdogCount++; - logd("Start Disconnecting Watchdog " + mDisconnectingWatchdogCount); - sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, - mDisconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); - } - - @Override - public boolean processMessage(Message message) { - boolean handleStatus = HANDLED; - - switch (message.what) { - case CMD_CONNECT_NETWORK: - case CMD_SAVE_NETWORK: - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; - deferMessage(message); - break; - case CMD_DISCONNECT: - if (mVerboseLoggingEnabled) { - log("Ignore CMD_DISCONNECT when already disconnecting."); - } - break; - case WifiMonitor.NETWORK_CONNECTION_EVENT: - if (mVerboseLoggingEnabled) { - log("Ignore NETWORK_CONNECTION_EVENT when already disconnecting."); - } - break; - case CMD_DISCONNECTING_WATCHDOG_TIMER: - if (mDisconnectingWatchdogCount == message.arg1) { - if (mVerboseLoggingEnabled) log("disconnecting watchdog! -> disconnect"); - handleNetworkDisconnect(); - transitionTo(mDisconnectedState); - } - break; - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - /** - * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT - * we have missed the network disconnection, transition to mDisconnectedState - * and handle the rest of the events there - */ - mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; - deferMessage(message); - handleNetworkDisconnect(); - transitionTo(mDisconnectedState); - break; - default: - handleStatus = NOT_HANDLED; - break; - } - - if (handleStatus == HANDLED) { - logStateAndMessage(message, this); - } - return handleStatus; - } - } - - class DisconnectedState extends State { - @Override - public void enter() { - Log.i(TAG, "disconnectedstate enter"); - // We don't scan frequently if this is a temporary disconnect - // due to p2p - if (mTemporarilyDisconnectWifi) { - p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); - return; - } - - if (mVerboseLoggingEnabled) { - logd(" Enter DisconnectedState screenOn=" + mScreenOn); - } - - /** clear the roaming state, if we were roaming, we failed */ - mIsAutoRoaming = false; - - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - } - - @Override - public boolean processMessage(Message message) { - boolean handleStatus = HANDLED; - - switch (message.what) { - case CMD_DISCONNECT: - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_GENERIC); - mWifiNative.disconnect(mInterfaceName); - break; - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - stopIpClient(); - if (message.arg2 == 15 /* FOURWAY_HANDSHAKE_TIMEOUT */) { - String bssid = (message.obj == null) - ? mTargetBssid : (String) message.obj; - mWifiInjector.getWifiLastResortWatchdog() - .noteConnectionFailureAndTriggerIfNeeded( - getTargetSsid(), bssid, - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2); - mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - mWifiInfo.reset(); - break; - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - if (mVerboseLoggingEnabled) { - logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state - + " -> state= " - + WifiInfo.getDetailedStateOf(stateChangeResult.state)); - } - if (SupplicantState.isConnecting(stateChangeResult.state)) { - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork( - stateChangeResult.networkId); - - // Update Passpoint information before setNetworkDetailedState as - // WifiTracker monitors NETWORK_STATE_CHANGED_ACTION to update UI. - mWifiInfo.setFQDN(null); - mWifiInfo.setPasspointUniqueId(null); - mWifiInfo.setOsuAp(false); - mWifiInfo.setProviderFriendlyName(null); - if (config != null && (config.isPasspoint() || config.osu)) { - if (config.isPasspoint()) { - mWifiInfo.setFQDN(config.FQDN); - mWifiInfo.setPasspointUniqueId(config.getPasspointUniqueId()); - } else { - mWifiInfo.setOsuAp(true); - } - mWifiInfo.setProviderFriendlyName(config.providerFriendlyName); - } - } - sendNetworkChangeBroadcast( - WifiInfo.getDetailedStateOf(stateChangeResult.state)); - /* ConnectModeState does the rest of the handling */ - handleStatus = NOT_HANDLED; - break; - case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: - NetworkInfo info = (NetworkInfo) message.obj; - mP2pConnected.set(info.isConnected()); - break; - case CMD_RECONNECT: - case CMD_REASSOCIATE: - if (mTemporarilyDisconnectWifi) { - // Drop a third party reconnect/reassociate if STA is - // temporarily disconnected for p2p - break; - } else { - // ConnectModeState handles it - handleStatus = NOT_HANDLED; - } - break; - case CMD_SCREEN_STATE_CHANGED: - handleScreenStateChanged(message.arg1 != 0); - break; - default: - handleStatus = NOT_HANDLED; - break; - } - - if (handleStatus == HANDLED) { - logStateAndMessage(message, this); - } - return handleStatus; - } - - @Override - public void exit() { - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_TRANSITIONING); - } - } - - /** - * State machine initiated requests can have replyTo set to null, indicating - * there are no recipients, we ignore those reply actions. - */ - private void replyToMessage(Message msg, int what) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private void replyToMessage(Message msg, int what, int arg1) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); - dstMsg.arg1 = arg1; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private void replyToMessage(Message msg, int what, Object obj) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); - dstMsg.obj = obj; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - /** - * arg2 on the source message has a unique id that needs to be retained in replies - * to match the request - * <p>see WifiManager for details - */ - private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { - Message msg = Message.obtain(); - msg.what = what; - msg.arg2 = srcMsg.arg2; - return msg; - } - - /** - * Notify interested parties if a wifi config has been changed. - * - * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT - * @param config Must have a WifiConfiguration object to succeed - * TODO: b/35258354 investigate if this can be removed. Is the broadcast sent by - * WifiConfigManager sufficient? - */ - private void broadcastWifiCredentialChanged(int wifiCredentialEventType, - WifiConfiguration config) { - Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); - if (config != null && config.SSID != null && mWifiPermissionsUtil.isLocationModeEnabled()) { - intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); - } - intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, wifiCredentialEventType); - mContext.createContextAsUser(UserHandle.CURRENT, 0) - .sendBroadcastWithMultiplePermissions( - intent, - new String[]{ - android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE, - android.Manifest.permission.ACCESS_FINE_LOCATION, - }); - } - - void handleGsmAuthRequest(SimAuthRequestData requestData) { - WifiConfiguration requestingWifiConfiguration = null; - if (mTargetWifiConfiguration != null - && mTargetWifiConfiguration.networkId - == requestData.networkId) { - requestingWifiConfiguration = mTargetWifiConfiguration; - logd("id matches targetWifiConfiguration"); - } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID - && mLastNetworkId == requestData.networkId) { - requestingWifiConfiguration = getCurrentWifiConfiguration(); - logd("id matches currentWifiConfiguration"); - } - - if (requestingWifiConfiguration == null) { - logd("GsmAuthRequest received with null target/current WifiConfiguration."); - return; - } - - /* - * Try authentication in the following order. - * - * Standard Cellular_auth Type Command - * - * 1. 3GPP TS 31.102 3G_authentication [Length][RAND][Length][AUTN] - * [Length][RES][Length][CK][Length][IK] and more - * 2. 3GPP TS 31.102 2G_authentication [Length][RAND] - * [Length][SRES][Length][Cipher Key Kc] - * 3. 3GPP TS 11.11 2G_authentication [RAND] - * [SRES][Cipher Key Kc] - */ - String response = mWifiCarrierInfoManager - .getGsmSimAuthResponse(requestData.data, requestingWifiConfiguration); - if (response == null) { - // In case of failure, issue may be due to sim type, retry as No.2 case - response = mWifiCarrierInfoManager - .getGsmSimpleSimAuthResponse(requestData.data, requestingWifiConfiguration); - if (response == null) { - // In case of failure, issue may be due to sim type, retry as No.3 case - response = mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse( - requestData.data, requestingWifiConfiguration); - } - } - if (response == null || response.length() == 0) { - mWifiNative.simAuthFailedResponse(mInterfaceName); - } else { - logv("Supplicant Response -" + response); - mWifiNative.simAuthResponse( - mInterfaceName, WifiNative.SIM_AUTH_RESP_TYPE_GSM_AUTH, response); - } - } - - void handle3GAuthRequest(SimAuthRequestData requestData) { - WifiConfiguration requestingWifiConfiguration = null; - if (mTargetWifiConfiguration != null - && mTargetWifiConfiguration.networkId - == requestData.networkId) { - requestingWifiConfiguration = mTargetWifiConfiguration; - logd("id matches targetWifiConfiguration"); - } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID - && mLastNetworkId == requestData.networkId) { - requestingWifiConfiguration = getCurrentWifiConfiguration(); - logd("id matches currentWifiConfiguration"); - } - - if (requestingWifiConfiguration == null) { - logd("3GAuthRequest received with null target/current WifiConfiguration."); - return; - } - - SimAuthResponseData response = mWifiCarrierInfoManager - .get3GAuthResponse(requestData, requestingWifiConfiguration); - if (response != null) { - mWifiNative.simAuthResponse( - mInterfaceName, response.type, response.response); - } else { - mWifiNative.umtsAuthFailedResponse(mInterfaceName); - } - } - - /** - * Automatically connect to the network specified - * - * @param networkId ID of the network to connect to - * @param uid UID of the app triggering the connection. - * @param bssid BSSID of the network - */ - public void startConnectToNetwork(int networkId, int uid, String bssid) { - sendMessage(CMD_START_CONNECT, networkId, uid, bssid); - } - - /** - * Automatically roam to the network specified - * - * @param networkId ID of the network to roam to - * @param scanResult scan result which identifies the network to roam to - */ - public void startRoamToNetwork(int networkId, ScanResult scanResult) { - sendMessage(CMD_START_ROAM, networkId, 0, scanResult); - } - - /** - * Dynamically turn on/off WifiConnectivityManager - * - * @param choice true-enable; false-disable - */ - public void allowAutoJoinGlobal(boolean choice) { - mWifiConnectivityManager.setAutoJoinEnabledExternal(choice); - } - - /** - * @param reason reason code from supplicant on network disconnected event - * @return true if this is a suspicious disconnect - */ - static boolean unexpectedDisconnectedReason(int reason) { - return reason == 2 // PREV_AUTH_NOT_VALID - || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA - || reason == 7 // FRAME_FROM_NONASSOC_STA - || reason == 8 // STA_HAS_LEFT - || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH - || reason == 14 // MICHAEL_MIC_FAILURE - || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT - || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT - || reason == 18 // GROUP_CIPHER_NOT_VALID - || reason == 19 // PAIRWISE_CIPHER_NOT_VALID - || reason == 23 // IEEE_802_1X_AUTH_FAILED - || reason == 34; // DISASSOC_LOW_ACK - } - - private static String getLinkPropertiesSummary(LinkProperties lp) { - List<String> attributes = new ArrayList<>(6); - if (lp.hasIpv4Address()) { - attributes.add("v4"); - } - if (lp.hasIpv4DefaultRoute()) { - attributes.add("v4r"); - } - if (lp.hasIpv4DnsServer()) { - attributes.add("v4dns"); - } - if (lp.hasGlobalIpv6Address()) { - attributes.add("v6"); - } - if (lp.hasIpv6DefaultRoute()) { - attributes.add("v6r"); - } - if (lp.hasIpv6DnsServer()) { - attributes.add("v6dns"); - } - - return TextUtils.join(" ", attributes); - } - - /** - * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId' - * This should match the network config framework is attempting to connect to. - */ - private String getTargetSsid() { - WifiConfiguration currentConfig = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); - if (currentConfig != null) { - return currentConfig.SSID; - } - return null; - } - - /** - * Send message to WifiP2pServiceImpl. - * @return true if message is sent. - * false if there is no channel configured for WifiP2pServiceImpl. - */ - private boolean p2pSendMessage(int what) { - if (mWifiP2pChannel != null) { - mWifiP2pChannel.sendMessage(what); - return true; - } - return false; - } - - /** - * Send message to WifiP2pServiceImpl with an additional param |arg1|. - * @return true if message is sent. - * false if there is no channel configured for WifiP2pServiceImpl. - */ - private boolean p2pSendMessage(int what, int arg1) { - if (mWifiP2pChannel != null) { - mWifiP2pChannel.sendMessage(what, arg1); - return true; - } - return false; - } - - /** - * Check if there is any connection request for WiFi network. - */ - private boolean hasConnectionRequests() { - return mNetworkFactory.hasConnectionRequests() - || mUntrustedNetworkFactory.hasConnectionRequests(); - } - - /** - * Returns whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. - */ - public boolean getIpReachabilityDisconnectEnabled() { - return mIpReachabilityDisconnectEnabled; - } - - /** - * Sets whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. - */ - public void setIpReachabilityDisconnectEnabled(boolean enabled) { - mIpReachabilityDisconnectEnabled = enabled; - } - - /** - * Sends a message to initialize the ClientModeImpl. - */ - public void initialize() { - sendMessage(CMD_INITIALIZE); - } - - /** - * Add a network request match callback to {@link WifiNetworkFactory}. - */ - public void addNetworkRequestMatchCallback(IBinder binder, - INetworkRequestMatchCallback callback, - int callbackIdentifier) { - mNetworkFactory.addCallback(binder, callback, callbackIdentifier); - } - - /** - * Remove a network request match callback from {@link WifiNetworkFactory}. - */ - public void removeNetworkRequestMatchCallback(int callbackIdentifier) { - mNetworkFactory.removeCallback(callbackIdentifier); - } - - /** - * Approve all access points from {@link WifiNetworkFactory} for the provided package. - * Used by shell commands. - */ - public void setNetworkRequestUserApprovedApp(@NonNull String packageName, boolean approved) { - mNetworkFactory.setUserApprovedApp(packageName, approved); - } - - /** - * Whether all access points are approved for the specified app. - * Used by shell commands. - */ - public boolean hasNetworkRequestUserApprovedApp(@NonNull String packageName) { - return mNetworkFactory.hasUserApprovedApp(packageName); - } - - /** - * Remove all approved access points from {@link WifiNetworkFactory} for the provided package. - */ - public void removeNetworkRequestUserApprovedAccessPointsForApp(@NonNull String packageName) { - mNetworkFactory.removeUserApprovedAccessPointsForApp(packageName); - } - - /** - * Clear all approved access points from {@link WifiNetworkFactory}. - */ - public void clearNetworkRequestUserApprovedAccessPoints() { - mNetworkFactory.clear(); - } - - /** - * Gets the factory MAC address of wlan0 (station interface). - * @return String representation of the factory MAC address. - */ - public String getFactoryMacAddress() { - MacAddress macAddress = mWifiNative.getFactoryMacAddress(mInterfaceName); - if (macAddress != null) { - return macAddress.toString(); - } - if (!isConnectedMacRandomizationEnabled()) { - return mWifiNative.getMacAddress(mInterfaceName); - } - return null; - } - - /** - * Sets the current device mobility state. - * @param state the new device mobility state - */ - public void setDeviceMobilityState(@DeviceMobilityState int state) { - mWifiConnectivityManager.setDeviceMobilityState(state); - mWifiHealthMonitor.setDeviceMobilityState(state); - mWifiDataStall.setDeviceMobilityState(state); - } - - /** - * Updates the Wi-Fi usability score. - * @param seqNum Sequence number of the Wi-Fi usability score. - * @param score The Wi-Fi usability score. - * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score. - */ - public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { - mWifiMetrics.incrementWifiUsabilityScoreCount(seqNum, score, predictionHorizonSec); - } - - /** - * Sends a link probe. - */ - @VisibleForTesting - public void probeLink(WifiNl80211Manager.SendMgmtFrameCallback callback, int mcs) { - mWifiNative.probeLink(mInterfaceName, MacAddress.fromString(mWifiInfo.getBSSID()), - callback, mcs); - } - - private void sendActionListenerFailure(int callbackIdentifier, int reason) { - IActionListener actionListener; - synchronized (mProcessingActionListeners) { - actionListener = mProcessingActionListeners.remove(callbackIdentifier); - } - if (actionListener != null) { - try { - actionListener.onFailure(reason); - } catch (RemoteException e) { - // no-op (client may be dead, nothing to be done) - } - } - } - - private void sendActionListenerSuccess(int callbackIdentifier) { - IActionListener actionListener; - synchronized (mProcessingActionListeners) { - actionListener = mProcessingActionListeners.remove(callbackIdentifier); - } - if (actionListener != null) { - try { - actionListener.onSuccess(); - } catch (RemoteException e) { - // no-op (client may be dead, nothing to be done) - } - } - } - - /** - * Trigger network connection and provide status via the provided callback. - */ - public void connect(WifiConfiguration config, int netId, @Nullable IBinder binder, - @Nullable IActionListener callback, int callbackIdentifier, int callingUid) { - mWifiInjector.getWifiThreadRunner().post(() -> { - if (callback != null && binder != null) { - mProcessingActionListeners.add(binder, callback, callbackIdentifier); - } - /** - * The connect message can contain a network id passed as arg1 on message or - * or a config passed as obj on message. - * For a new network, a config is passed to create and connect. - * For an existing network, a network id is passed - */ - NetworkUpdateResult result = null; - if (config != null) { - result = mWifiConfigManager.addOrUpdateNetwork(config, callingUid); - if (!result.isSuccess()) { - loge("connectNetwork adding/updating config=" + config + " failed"); - sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); - return; - } - broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); - } else { - if (mWifiConfigManager.getConfiguredNetwork(netId) == null) { - loge("connectNetwork Invalid network Id=" + netId); - sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); - return; - } - result = new NetworkUpdateResult(netId); - } - final int networkId = result.getNetworkId(); - mWifiConfigManager.userEnabledNetwork(networkId); - if (!mWifiConfigManager.enableNetwork(networkId, true, callingUid, null) - || !mWifiConfigManager.updateLastConnectUid(networkId, callingUid)) { - logi("connect Allowing uid " + callingUid - + " with insufficient permissions to connect=" + networkId); - } else if (mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)) { - // Note user connect choice here, so that it will be considered in the - // next network selection. - mWifiConnectivityManager.setUserConnectChoice(networkId); - } - Message message = - obtainMessage(CMD_CONNECT_NETWORK, -1, callbackIdentifier, result); - message.sendingUid = callingUid; - sendMessage(message); - }); - } - - /** - * Trigger network save and provide status via the provided callback. - */ - public void save(WifiConfiguration config, @Nullable IBinder binder, - @Nullable IActionListener callback, int callbackIdentifier, int callingUid) { - mWifiInjector.getWifiThreadRunner().post(() -> { - if (callback != null && binder != null) { - mProcessingActionListeners.add(binder, callback, callbackIdentifier); - } - if (config == null) { - loge("saveNetwork with null configuration my state " - + getCurrentState().getName()); - sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); - return; - } - NetworkUpdateResult result = - mWifiConfigManager.addOrUpdateNetwork(config, callingUid); - if (!result.isSuccess()) { - loge("saveNetwork adding/updating config=" + config + " failed"); - sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); - return; - } - if (!mWifiConfigManager.enableNetwork( - result.getNetworkId(), false, callingUid, null)) { - loge("saveNetwork enabling config=" + config + " failed"); - sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); - return; - } - broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); - Message message = - obtainMessage(CMD_SAVE_NETWORK, -1 , callbackIdentifier, result); - message.sendingUid = callingUid; - sendMessage(message); - }); - } - - /** - * Trigger network forget and provide status via the provided callback. - */ - public void forget(int netId, @Nullable IBinder binder, @Nullable IActionListener callback, - int callbackIdentifier, int callingUid) { - mWifiInjector.getWifiThreadRunner().post(() -> { - if (callback != null && binder != null) { - mProcessingActionListeners.add(binder, callback, callbackIdentifier); - } - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); - boolean success = mWifiConfigManager.removeNetwork(netId, callingUid, null); - if (!success) { - loge("Failed to remove network"); - sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR); - } - sendActionListenerSuccess(callbackIdentifier); - broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, config); - }); - } - - /** - * Handle BSS transition request from Connected BSS. - * - * @param frameData Data retrieved from received BTM request frame. - */ - private void handleBssTransitionRequest(BtmFrameData frameData) { - if (frameData == null) { - return; - } - - String bssid = mWifiInfo.getBSSID(); - String ssid = mWifiInfo.getSSID(); - if ((bssid == null) || (ssid == null) || WifiManager.UNKNOWN_SSID.equals(ssid)) { - Log.e(TAG, "Failed to handle BSS transition: bssid: " + bssid + " ssid: " + ssid); - return; - } - - if ((frameData.mBssTmDataFlagsMask - & MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED) - != 0) { - mWifiMetrics.incrementMboCellularSwitchRequestCount(); - } - - - if ((frameData.mBssTmDataFlagsMask - & MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT) != 0) { - long duration = 0; - if ((frameData.mBssTmDataFlagsMask - & MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED) != 0) { - mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay(); - duration = frameData.mBlockListDurationMs; - } - if (duration == 0) { - /* - * When disassoc imminent bit alone is set or MBO assoc retry delay is - * set to zero(reserved as per spec), blocklist the BSS for sometime to - * avoid AP rejecting the re-connect request. - */ - duration = MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS; - } - // Blocklist the current BSS - mBssidBlocklistMonitor.blockBssidForDurationMs(bssid, ssid, duration, - BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE, 0); - } - - if (frameData.mStatus != MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT) { - // Trigger the network selection and re-connect to new network if available. - mWifiMetrics.incrementForceScanCountDueToSteeringRequest(); - mWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); - } - } - - /** - * @return true if this device supports FILS-SHA256 - */ - private boolean isFilsSha256Supported() { - return (mWifiNative.getSupportedFeatureSet(mInterfaceName) & WIFI_FEATURE_FILS_SHA256) != 0; - } - - /** - * @return true if this device supports FILS-SHA384 - */ - private boolean isFilsSha384Supported() { - return (mWifiNative.getSupportedFeatureSet(mInterfaceName) & WIFI_FEATURE_FILS_SHA384) != 0; - } - - /** - * Helper method to set the allowed key management schemes from - * scan result. - */ - private void updateAllowedKeyManagementSchemesFromScanResult( - WifiConfiguration config, ScanResult scanResult) { - if (isFilsSha256Supported() - && ScanResultUtil.isScanResultForFilsSha256Network(scanResult)) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FILS_SHA256); - } - if (isFilsSha384Supported() - && ScanResultUtil.isScanResultForFilsSha384Network(scanResult)) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FILS_SHA384); - } - } - /** - * Update wifi configuration based on the matching scan result. - * - * @param config Wifi configuration object. - * @param scanResult Scan result matching the network. - */ - private void updateWifiConfigFromMatchingScanResult(WifiConfiguration config, - ScanResult scanResult) { - updateAllowedKeyManagementSchemesFromScanResult(config, scanResult); - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256) - || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA384)) { - config.enterpriseConfig.setFieldValue(WifiEnterpriseConfig.EAP_ERP, "1"); - } - } - - /** - * Update the wifi configuration before sending connect to - * supplicant/driver. - * - * @param config wifi configuration object. - * @param bssid BSSID to assocaite with. - */ - void updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid) { - boolean canUpgradePskToSae = false; - boolean isFrameworkWpa3SaeUpgradePossible = false; - boolean isLegacyWpa2ApInScanResult = false; - - setTargetBssid(config, bssid); - - if (isWpa3SaeUpgradeEnabled() && config.allowedKeyManagement.get( - WifiConfiguration.KeyMgmt.WPA_PSK)) { - isFrameworkWpa3SaeUpgradePossible = true; - } - - if (isFrameworkWpa3SaeUpgradePossible && isWpa3SaeUpgradeOffloadEnabled()) { - // Driver offload of upgrading legacy WPA/WPA2 connection to WPA3 - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Driver upgrade legacy WPA/WPA2 connection to WPA3"); - } - config.allowedAuthAlgorithms.clear(); - // Note: KeyMgmt.WPA2_PSK is already enabled, enable SAE as well - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - isFrameworkWpa3SaeUpgradePossible = false; - } - // Check if network selection selected a good WPA3 candidate AP for a WPA2 - // saved network. - ScanResult scanResultCandidate = config.getNetworkSelectionStatus().getCandidate(); - if (isFrameworkWpa3SaeUpgradePossible && scanResultCandidate != null) { - ScanResultMatchInfo scanResultMatchInfo = ScanResultMatchInfo - .fromScanResult(scanResultCandidate); - if ((scanResultMatchInfo.networkType == WifiConfiguration.SECURITY_TYPE_SAE)) { - canUpgradePskToSae = true; - } else { - // No SAE candidate - isFrameworkWpa3SaeUpgradePossible = false; - } - } - - /** - * Go through the matching scan results and update wifi config. - */ - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(config); - ScanRequestProxy scanRequestProxy = mWifiInjector.getScanRequestProxy(); - List<ScanResult> scanResults = scanRequestProxy.getScanResults(); - for (ScanResult scanResult : scanResults) { - if (!config.SSID.equals(ScanResultUtil.createQuotedSSID(scanResult.SSID))) { - continue; - } - if (isFrameworkWpa3SaeUpgradePossible && !isLegacyWpa2ApInScanResult) { - if (ScanResultUtil.isScanResultForPskNetwork(scanResult) - && !ScanResultUtil.isScanResultForSaeNetwork(scanResult)) { - // Found a legacy WPA2 AP in range. Do not upgrade the connection to WPA3 to - // allow seamless roaming within the ESS. - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Found legacy WPA2 AP, do not upgrade to WPA3"); - } - isLegacyWpa2ApInScanResult = true; - canUpgradePskToSae = false; - } - if (ScanResultUtil.isScanResultForSaeNetwork(scanResult) - && scanResultCandidate == null) { - // When the user manually selected a network from the Wi-Fi picker, evaluate - // if to upgrade based on the scan results. The most typical use case during - // the WPA3 transition mode is to have a WPA2/WPA3 AP in transition mode. In - // this case, we would like to upgrade the connection. - canUpgradePskToSae = true; - } - } - - ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanResult); - if (!key1.equals(key2)) { - continue; - } - updateWifiConfigFromMatchingScanResult(config, scanResult); - } - - if (isFrameworkWpa3SaeUpgradePossible && canUpgradePskToSae - && !(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256) - || config.allowedKeyManagement.get( - WifiConfiguration.KeyMgmt.FILS_SHA384))) { - // Upgrade legacy WPA/WPA2 connection to WPA3 - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Upgrade legacy WPA/WPA2 connection to WPA3"); - } - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); - } - - if (isConnectedMacRandomizationEnabled()) { - if (config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) { - configureRandomizedMacAddress(config); - } else { - setCurrentMacToFactoryMac(config); - } - } - - if (config.enterpriseConfig != null - && config.enterpriseConfig.isAuthenticationSimBased() - && mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable( - mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)) - && TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())) { - String anonAtRealm = mWifiCarrierInfoManager - .getAnonymousIdentityWith3GppRealm(config); - // Use anonymous@<realm> when pseudonym is not available - config.enterpriseConfig.setAnonymousIdentity(anonAtRealm); - } - } - - private void setConfigurationsPriorToIpClientProvisioning(WifiConfiguration config) { - mIpClient.setHttpProxy(config.getHttpProxy()); - if (!TextUtils.isEmpty(mContext.getResources().getString( - R.string.config_wifi_tcp_buffers))) { - mIpClient.setTcpBufferSizes(mContext.getResources().getString( - R.string.config_wifi_tcp_buffers)); - } - } - - private boolean startIpClient(WifiConfiguration config, boolean isFilsConnection) { - if (mIpClient == null) { - return false; - } - - final boolean isUsingStaticIp = - (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC); - final boolean isUsingMacRandomization = - config.macRandomizationSetting - == WifiConfiguration.RANDOMIZATION_PERSISTENT - && isConnectedMacRandomizationEnabled(); - if (mVerboseLoggingEnabled) { - final String key = config.getKey(); - log("startIpClient netId=" + Integer.toString(mLastNetworkId) - + " " + key + " " - + " roam=" + mIsAutoRoaming - + " static=" + isUsingStaticIp - + " randomMac=" + isUsingMacRandomization - + " isFilsConnection=" + isFilsConnection); - } - - final MacAddress currentBssid = getCurrentBssid(); - final String l2Key = mLastL2KeyAndGroupHint != null - ? mLastL2KeyAndGroupHint.first : null; - final String groupHint = mLastL2KeyAndGroupHint != null - ? mLastL2KeyAndGroupHint.second : null; - final Layer2Information layer2Info = new Layer2Information(l2Key, groupHint, - currentBssid); - - if (isFilsConnection) { - stopIpClient(); - if (isUsingStaticIp) { - mWifiNative.flushAllHlp(mInterfaceName); - return false; - } - setConfigurationsPriorToIpClientProvisioning(config); - final ProvisioningConfiguration.Builder prov = - new ProvisioningConfiguration.Builder() - .withPreDhcpAction() - .withPreconnection() - .withApfCapabilities( - mWifiNative.getApfCapabilities(mInterfaceName)) - .withLayer2Information(layer2Info); - if (isUsingMacRandomization) { - // Use EUI64 address generation for link-local IPv6 addresses. - prov.withRandomMacAddress(); - } - mIpClient.startProvisioning(prov.build()); - } else { - sendNetworkChangeBroadcast(DetailedState.OBTAINING_IPADDR); - // We must clear the config BSSID, as the wifi chipset may decide to roam - // from this point on and having the BSSID specified in the network block would - // cause the roam to fail and the device to disconnect. - clearTargetBssid("ObtainingIpAddress"); - - // Stop IpClient in case we're switching from DHCP to static - // configuration or vice versa. - // - // When we transition from static configuration to DHCP in - // particular, we must tell ConnectivityService that we're - // disconnected, because DHCP might take a long time during which - // connectivity APIs such as getActiveNetworkInfo should not return - // CONNECTED. - stopDhcpSetup(); - setConfigurationsPriorToIpClientProvisioning(config); - ScanDetailCache scanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); - ScanResult scanResult = null; - if (mLastBssid != null) { - if (scanDetailCache != null) { - scanResult = scanDetailCache.getScanResult(mLastBssid); - } - - // The cached scan result of connected network would be null at the first - // connection, try to check full scan result list again to look up matched - // scan result associated to the current SSID and BSSID. - if (scanResult == null) { - ScanRequestProxy scanRequestProxy = mWifiInjector.getScanRequestProxy(); - List<ScanResult> scanResults = scanRequestProxy.getScanResults(); - for (ScanResult result : scanResults) { - if (result.SSID.equals(WifiInfo.removeDoubleQuotes(config.SSID)) - && result.BSSID.equals(mLastBssid)) { - scanResult = result; - break; - } - } - } - } - - final ProvisioningConfiguration.Builder prov; - ProvisioningConfiguration.ScanResultInfo scanResultInfo = null; - if (scanResult != null) { - final List<ScanResultInfo.InformationElement> ies = - new ArrayList<ScanResultInfo.InformationElement>(); - for (ScanResult.InformationElement ie : scanResult.getInformationElements()) { - ScanResultInfo.InformationElement scanResultInfoIe = - new ScanResultInfo.InformationElement(ie.getId(), ie.getBytes()); - ies.add(scanResultInfoIe); - } - scanResultInfo = new ProvisioningConfiguration.ScanResultInfo(scanResult.SSID, - scanResult.BSSID, ies); - } - - if (!isUsingStaticIp) { - prov = new ProvisioningConfiguration.Builder() - .withPreDhcpAction() - .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName)) - .withNetwork(getCurrentNetwork()) - .withDisplayName(config.SSID) - .withScanResultInfo(scanResultInfo) - .withLayer2Information(layer2Info); - } else { - StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration(); - prov = new ProvisioningConfiguration.Builder() - .withStaticConfiguration(staticIpConfig) - .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName)) - .withNetwork(getCurrentNetwork()) - .withDisplayName(config.SSID) - .withLayer2Information(layer2Info); - } - if (isUsingMacRandomization) { - // Use EUI64 address generation for link-local IPv6 addresses. - prov.withRandomMacAddress(); - } - mIpClient.startProvisioning(prov.build()); - } - - return true; - } - -} diff --git a/service/java/com/android/server/wifi/ClientModeManager.java b/service/java/com/android/server/wifi/ClientModeManager.java deleted file mode 100644 index 4fb4b870d..000000000 --- a/service/java/com/android/server/wifi/ClientModeManager.java +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.annotation.NonNull; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.Looper; -import android.os.Message; -import android.os.PersistableBundle; -import android.os.UserHandle; -import android.telephony.AccessNetworkConstants; -import android.telephony.CarrierConfigManager; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.telephony.ims.ImsException; -import android.telephony.ims.ImsMmTelManager; -import android.telephony.ims.ImsReasonInfo; -import android.telephony.ims.RegistrationManager; -import android.telephony.ims.feature.MmTelFeature; -import android.telephony.ims.stub.ImsRegistrationImplBase; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.util.IState; -import com.android.internal.util.Preconditions; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import com.android.server.wifi.WifiNative.InterfaceCallback; -import com.android.server.wifi.util.WifiHandler; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.List; - -/** - * Manager WiFi in Client Mode where we connect to configured networks. - */ -public class ClientModeManager implements ActiveModeManager { - private static final String TAG = "WifiClientModeManager"; - - private final ClientModeStateMachine mStateMachine; - - private final Context mContext; - private final Clock mClock; - private final WifiNative mWifiNative; - private final WifiMetrics mWifiMetrics; - private final SarManager mSarManager; - private final WakeupController mWakeupController; - private final Listener mModeListener; - private final ClientModeImpl mClientModeImpl; - - private String mClientInterfaceName; - private boolean mIfaceIsUp = false; - private DeferStopHandler mDeferStopHandler; - private @Role int mRole = ROLE_UNSPECIFIED; - private @Role int mTargetRole = ROLE_UNSPECIFIED; - private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - - ClientModeManager(Context context, @NonNull Looper looper, Clock clock, WifiNative wifiNative, - Listener listener, WifiMetrics wifiMetrics, SarManager sarManager, - WakeupController wakeupController, ClientModeImpl clientModeImpl) { - mContext = context; - mClock = clock; - mWifiNative = wifiNative; - mModeListener = listener; - mWifiMetrics = wifiMetrics; - mSarManager = sarManager; - mWakeupController = wakeupController; - mClientModeImpl = clientModeImpl; - mStateMachine = new ClientModeStateMachine(looper); - mDeferStopHandler = new DeferStopHandler(TAG, looper); - } - - /** - * Start client mode. - */ - @Override - public void start() { - mTargetRole = ROLE_CLIENT_SCAN_ONLY; - mStateMachine.sendMessage(ClientModeStateMachine.CMD_START); - } - - /** - * Disconnect from any currently connected networks and stop client mode. - */ - @Override - public void stop() { - Log.d(TAG, " currentstate: " + getCurrentStateName()); - mTargetRole = ROLE_UNSPECIFIED; - if (mIfaceIsUp) { - updateConnectModeState(WifiManager.WIFI_STATE_DISABLING, - WifiManager.WIFI_STATE_ENABLED); - } else { - updateConnectModeState(WifiManager.WIFI_STATE_DISABLING, - WifiManager.WIFI_STATE_ENABLING); - } - mDeferStopHandler.start(getWifiOffDeferringTimeMs()); - } - - @Override - public boolean isStopping() { - return mTargetRole == ROLE_UNSPECIFIED && mRole != ROLE_UNSPECIFIED; - } - - private class DeferStopHandler extends WifiHandler { - private boolean mIsDeferring = false; - private ImsMmTelManager mImsMmTelManager = null; - private Looper mLooper = null; - private final Runnable mRunnable = () -> continueToStopWifi(); - private int mMaximumDeferringTimeMillis = 0; - private long mDeferringStartTimeMillis = 0; - private NetworkRequest mImsRequest = null; - private ConnectivityManager mConnectivityManager = null; - - private RegistrationManager.RegistrationCallback mImsRegistrationCallback = - new RegistrationManager.RegistrationCallback() { - @Override - public void onRegistered(int imsRadioTech) { - Log.d(TAG, "on IMS registered on type " + imsRadioTech); - if (!mIsDeferring) return; - - if (imsRadioTech != AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { - continueToStopWifi(); - } - } - - @Override - public void onUnregistered(ImsReasonInfo imsReasonInfo) { - Log.d(TAG, "on IMS unregistered"); - // Wait for onLost in NetworkCallback - } - }; - - private NetworkCallback mImsNetworkCallback = new NetworkCallback() { - private int mRegisteredImsNetworkCount = 0; - @Override - public void onAvailable(Network network) { - synchronized (this) { - Log.d(TAG, "IMS network available: " + network); - mRegisteredImsNetworkCount++; - } - } - - @Override - public void onLost(Network network) { - synchronized (this) { - Log.d(TAG, "IMS network lost: " + network - + " ,isDeferring: " + mIsDeferring - + " ,registered IMS network count: " + mRegisteredImsNetworkCount); - mRegisteredImsNetworkCount--; - if (mIsDeferring && mRegisteredImsNetworkCount <= 0) { - mRegisteredImsNetworkCount = 0; - // Add delay for targets where IMS PDN down at modem takes additional delay. - int delay = mContext.getResources() - .getInteger(R.integer.config_wifiDelayDisconnectOnImsLostMs); - if (delay == 0 || !postDelayed(mRunnable, delay)) { - continueToStopWifi(); - } - } - } - } - }; - - DeferStopHandler(String tag, Looper looper) { - super(tag, looper); - mLooper = looper; - } - - public void start(int delayMs) { - if (mIsDeferring) return; - - mMaximumDeferringTimeMillis = delayMs; - mDeferringStartTimeMillis = mClock.getElapsedSinceBootMillis(); - // Most cases don't need delay, check it first to avoid unnecessary work. - if (delayMs == 0) { - continueToStopWifi(); - return; - } - - mImsMmTelManager = ImsMmTelManager.createForSubscriptionId(mActiveSubId); - if (mImsMmTelManager == null || !postDelayed(mRunnable, delayMs)) { - // if no delay or failed to add runnable, stop Wifi immediately. - continueToStopWifi(); - return; - } - - mIsDeferring = true; - Log.d(TAG, "Start DeferWifiOff handler with deferring time " - + delayMs + " ms for subId: " + mActiveSubId); - try { - mImsMmTelManager.registerImsRegistrationCallback( - new HandlerExecutor(new Handler(mLooper)), - mImsRegistrationCallback); - } catch (RuntimeException | ImsException e) { - Log.e(TAG, "registerImsRegistrationCallback failed", e); - continueToStopWifi(); - return; - } - - mImsRequest = new NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS) - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .build(); - - mConnectivityManager = - (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - - mConnectivityManager.registerNetworkCallback(mImsRequest, mImsNetworkCallback, - new Handler(mLooper)); - } - - private void continueToStopWifi() { - Log.d(TAG, "The target role " + mTargetRole); - - int deferringDurationMillis = - (int) (mClock.getElapsedSinceBootMillis() - mDeferringStartTimeMillis); - boolean isTimedOut = mMaximumDeferringTimeMillis > 0 - && deferringDurationMillis >= mMaximumDeferringTimeMillis; - if (mTargetRole == ROLE_UNSPECIFIED) { - Log.d(TAG, "Continue to stop wifi"); - mStateMachine.quitNow(); - mWifiMetrics.noteWifiOff(mIsDeferring, isTimedOut, deferringDurationMillis); - } else if (mTargetRole == ROLE_CLIENT_SCAN_ONLY) { - if (!mWifiNative.switchClientInterfaceToScanMode(mClientInterfaceName)) { - mModeListener.onStartFailure(); - } else { - mStateMachine.sendMessage( - ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE); - mWifiMetrics.noteWifiOff(mIsDeferring, isTimedOut, deferringDurationMillis); - } - } else { - updateConnectModeState(WifiManager.WIFI_STATE_ENABLED, - WifiManager.WIFI_STATE_DISABLING); - } - - if (!mIsDeferring) return; - - Log.d(TAG, "Stop DeferWifiOff handler."); - removeCallbacks(mRunnable); - if (mImsMmTelManager != null) { - try { - mImsMmTelManager.unregisterImsRegistrationCallback(mImsRegistrationCallback); - } catch (RuntimeException e) { - Log.e(TAG, "unregisterImsRegistrationCallback failed", e); - } - } - - if (mConnectivityManager != null) { - mConnectivityManager.unregisterNetworkCallback(mImsNetworkCallback); - } - - mIsDeferring = false; - } - } - - /** - * Get deferring time before turning off WiFi. - */ - private int getWifiOffDeferringTimeMs() { - SubscriptionManager subscriptionManager = (SubscriptionManager) mContext.getSystemService( - Context.TELEPHONY_SUBSCRIPTION_SERVICE); - if (subscriptionManager == null) { - Log.d(TAG, "SubscriptionManager not found"); - return 0; - } - - List<SubscriptionInfo> subInfoList = subscriptionManager.getActiveSubscriptionInfoList(); - if (subInfoList == null) { - Log.d(TAG, "Active SubscriptionInfo list not found"); - return 0; - } - - // Get the maximum delay for the active subscription latched on IWLAN. - int maxDelay = 0; - for (SubscriptionInfo subInfo : subInfoList) { - int curDelay = getWifiOffDeferringTimeMs(subInfo.getSubscriptionId()); - if (curDelay > maxDelay) { - maxDelay = curDelay; - mActiveSubId = subInfo.getSubscriptionId(); - } - } - return maxDelay; - } - - private int getWifiOffDeferringTimeMs(int subId) { - if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - Log.d(TAG, "Invalid Subscription ID: " + subId); - return 0; - } - - ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(subId); - // If no wifi calling, no delay - if (!imsMmTelManager.isAvailable( - MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, - ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)) { - Log.d(TAG, "IMS not registered over IWLAN for subId: " + subId); - return 0; - } - - CarrierConfigManager configManager = - (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); - PersistableBundle config = configManager.getConfigForSubId(subId); - return (config != null) - ? config.getInt(CarrierConfigManager.Ims.KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT) - : 0; - } - - @Override - public @Role int getRole() { - return mRole; - } - - @Override - public void setRole(@Role int role) { - Preconditions.checkState(CLIENT_ROLES.contains(role)); - if (role == ROLE_CLIENT_SCAN_ONLY) { - mTargetRole = role; - // Switch client mode manager to scan only mode. - mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE); - } else if (CLIENT_CONNECTIVITY_ROLES.contains(role)) { - mTargetRole = role; - // Switch client mode manager to connect mode. - mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE, role); - } - } - - /** - * Dump info about this ClientMode manager. - */ - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("--Dump of ClientModeManager--"); - - pw.println("current StateMachine mode: " + getCurrentStateName()); - pw.println("mRole: " + mRole); - pw.println("mTargetRole: " + mTargetRole); - pw.println("mClientInterfaceName: " + mClientInterfaceName); - pw.println("mIfaceIsUp: " + mIfaceIsUp); - mStateMachine.dump(fd, pw, args); - } - - private String getCurrentStateName() { - IState currentState = mStateMachine.getCurrentState(); - - if (currentState != null) { - return currentState.getName(); - } - - return "StateMachine not active"; - } - - /** - * Update Wifi state and send the broadcast. - * @param newState new Wifi state - * @param currentState current wifi state - */ - private void updateConnectModeState(int newState, int currentState) { - if (newState == WifiManager.WIFI_STATE_UNKNOWN) { - // do not need to broadcast failure to system - return; - } - if (mRole != ROLE_CLIENT_PRIMARY) { - // do not raise public broadcast unless this is the primary client mode manager - return; - } - - mClientModeImpl.setWifiStateForApiCalls(newState); - - final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_WIFI_STATE, newState); - intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, currentState); - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private class ClientModeStateMachine extends StateMachine { - // Commands for the state machine. - public static final int CMD_START = 0; - public static final int CMD_SWITCH_TO_SCAN_ONLY_MODE = 1; - public static final int CMD_SWITCH_TO_CONNECT_MODE = 2; - public static final int CMD_INTERFACE_STATUS_CHANGED = 3; - public static final int CMD_INTERFACE_DESTROYED = 4; - public static final int CMD_INTERFACE_DOWN = 5; - public static final int CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE = 6; - private final State mIdleState = new IdleState(); - private final State mStartedState = new StartedState(); - private final State mScanOnlyModeState = new ScanOnlyModeState(); - private final State mConnectModeState = new ConnectModeState(); - - private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { - @Override - public void onDestroyed(String ifaceName) { - if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { - Log.d(TAG, "STA iface " + ifaceName + " was destroyed, stopping client mode"); - - // we must immediately clean up state in ClientModeImpl to unregister - // all client mode related objects - // Note: onDestroyed is only called from the main Wifi thread - mClientModeImpl.handleIfaceDestroyed(); - - sendMessage(CMD_INTERFACE_DESTROYED); - } - } - - @Override - public void onUp(String ifaceName) { - if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1); - } - } - - @Override - public void onDown(String ifaceName) { - if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); - } - } - }; - - ClientModeStateMachine(Looper looper) { - super(TAG, looper); - - // CHECKSTYLE:OFF IndentationCheck - addState(mIdleState); - addState(mStartedState); - addState(mScanOnlyModeState, mStartedState); - addState(mConnectModeState, mStartedState); - // CHECKSTYLE:ON IndentationCheck - - setInitialState(mIdleState); - start(); - } - - private class IdleState extends State { - @Override - public void enter() { - Log.d(TAG, "entering IdleState"); - mClientInterfaceName = null; - mIfaceIsUp = false; - } - - @Override - public boolean processMessage(Message message) { - switch (message.what) { - case CMD_START: - // Always start in scan mode first. - mClientInterfaceName = - mWifiNative.setupInterfaceForClientInScanMode( - mWifiNativeInterfaceCallback); - if (TextUtils.isEmpty(mClientInterfaceName)) { - Log.e(TAG, "Failed to create ClientInterface. Sit in Idle"); - mModeListener.onStartFailure(); - break; - } - transitionTo(mScanOnlyModeState); - break; - default: - Log.d(TAG, "received an invalid message: " + message); - return NOT_HANDLED; - } - return HANDLED; - } - } - - private class StartedState extends State { - - private void onUpChanged(boolean isUp) { - if (isUp == mIfaceIsUp) { - return; // no change - } - mIfaceIsUp = isUp; - if (!isUp) { - // if the interface goes down we should exit and go back to idle state. - Log.d(TAG, "interface down!"); - mStateMachine.sendMessage(CMD_INTERFACE_DOWN); - } - } - - @Override - public void enter() { - Log.d(TAG, "entering StartedState"); - mIfaceIsUp = false; - onUpChanged(mWifiNative.isInterfaceUp(mClientInterfaceName)); - } - - @Override - public boolean processMessage(Message message) { - switch(message.what) { - case CMD_START: - // Already started, ignore this command. - break; - case CMD_SWITCH_TO_CONNECT_MODE: - mRole = message.arg1; // could be any one of possible connect mode roles. - updateConnectModeState(WifiManager.WIFI_STATE_ENABLING, - WifiManager.WIFI_STATE_DISABLED); - if (!mWifiNative.switchClientInterfaceToConnectivityMode( - mClientInterfaceName)) { - updateConnectModeState(WifiManager.WIFI_STATE_UNKNOWN, - WifiManager.WIFI_STATE_ENABLING); - updateConnectModeState(WifiManager.WIFI_STATE_DISABLED, - WifiManager.WIFI_STATE_UNKNOWN); - mModeListener.onStartFailure(); - break; - } - transitionTo(mConnectModeState); - break; - case CMD_SWITCH_TO_SCAN_ONLY_MODE: - updateConnectModeState(WifiManager.WIFI_STATE_DISABLING, - WifiManager.WIFI_STATE_ENABLED); - mDeferStopHandler.start(getWifiOffDeferringTimeMs()); - break; - case CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE: - transitionTo(mScanOnlyModeState); - break; - case CMD_INTERFACE_DOWN: - Log.e(TAG, "Detected an interface down, reporting failure to " - + "SelfRecovery"); - mClientModeImpl.failureDetected(SelfRecovery.REASON_STA_IFACE_DOWN); - transitionTo(mIdleState); - break; - case CMD_INTERFACE_STATUS_CHANGED: - boolean isUp = message.arg1 == 1; - onUpChanged(isUp); - break; - case CMD_INTERFACE_DESTROYED: - Log.d(TAG, "interface destroyed - client mode stopping"); - mClientInterfaceName = null; - transitionTo(mIdleState); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - /** - * Clean up state, unregister listeners and update wifi state. - */ - @Override - public void exit() { - mClientModeImpl.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - - if (mClientInterfaceName != null) { - mWifiNative.teardownInterface(mClientInterfaceName); - mClientInterfaceName = null; - mIfaceIsUp = false; - } - - // once we leave started, nothing else to do... stop the state machine - mRole = ROLE_UNSPECIFIED; - mStateMachine.quitNow(); - mModeListener.onStopped(); - } - } - - private class ScanOnlyModeState extends State { - @Override - public void enter() { - Log.d(TAG, "entering ScanOnlyModeState"); - mClientModeImpl.setOperationalMode(ClientModeImpl.SCAN_ONLY_MODE, - mClientInterfaceName); - mRole = ROLE_CLIENT_SCAN_ONLY; - mModeListener.onStarted(); - - // Inform sar manager that scan only is being enabled - mSarManager.setScanOnlyWifiState(WifiManager.WIFI_STATE_ENABLED); - mWakeupController.start(); - } - - @Override - public boolean processMessage(Message message) { - switch (message.what) { - case CMD_SWITCH_TO_SCAN_ONLY_MODE: - // Already in scan only mode, ignore this command. - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - @Override - public void exit() { - // Inform sar manager that scan only is being disabled - mSarManager.setScanOnlyWifiState(WifiManager.WIFI_STATE_DISABLED); - mWakeupController.stop(); - } - } - - private class ConnectModeState extends State { - @Override - public void enter() { - Log.d(TAG, "entering ConnectModeState"); - mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE, - mClientInterfaceName); - mModeListener.onStarted(); - updateConnectModeState(WifiManager.WIFI_STATE_ENABLED, - WifiManager.WIFI_STATE_ENABLING); - - // Inform sar manager that wifi is Enabled - mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - } - - @Override - public boolean processMessage(Message message) { - switch (message.what) { - case CMD_SWITCH_TO_CONNECT_MODE: - int newRole = message.arg1; - // Already in connect mode, only switching the connectivity roles. - if (newRole != mRole) { - mRole = newRole; - mModeListener.onStarted(); - } - break; - case CMD_SWITCH_TO_SCAN_ONLY_MODE: - updateConnectModeState(WifiManager.WIFI_STATE_DISABLING, - WifiManager.WIFI_STATE_ENABLED); - return NOT_HANDLED; // Handled in StartedState. - case CMD_INTERFACE_DOWN: - updateConnectModeState(WifiManager.WIFI_STATE_DISABLING, - WifiManager.WIFI_STATE_UNKNOWN); - return NOT_HANDLED; // Handled in StartedState. - case CMD_INTERFACE_STATUS_CHANGED: - boolean isUp = message.arg1 == 1; - if (isUp == mIfaceIsUp) { - break; // no change - } - if (!isUp) { - if (!mClientModeImpl.isConnectedMacRandomizationEnabled()) { - // Handle the error case where our underlying interface went down if - // we do not have mac randomization enabled (b/72459123). - // if the interface goes down we should exit and go back to idle - // state. - updateConnectModeState(WifiManager.WIFI_STATE_UNKNOWN, - WifiManager.WIFI_STATE_ENABLED); - } else { - return HANDLED; // For MAC randomization, ignore... - } - } - return NOT_HANDLED; // Handled in StartedState. - case CMD_INTERFACE_DESTROYED: - updateConnectModeState(WifiManager.WIFI_STATE_DISABLING, - WifiManager.WIFI_STATE_ENABLED); - return NOT_HANDLED; // Handled in StartedState. - default: - return NOT_HANDLED; - } - return HANDLED; - } - - @Override - public void exit() { - updateConnectModeState(WifiManager.WIFI_STATE_DISABLED, - WifiManager.WIFI_STATE_DISABLING); - - // Inform sar manager that wifi is being disabled - mSarManager.setClientWifiState(WifiManager.WIFI_STATE_DISABLED); - } - } - } -} diff --git a/service/java/com/android/server/wifi/Clock.java b/service/java/com/android/server/wifi/Clock.java deleted file mode 100644 index b1d45961b..000000000 --- a/service/java/com/android/server/wifi/Clock.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2016 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.Wifi - */ - -package com.android.server.wifi; - -import android.os.SystemClock; -/** - * Wrapper class for time operations. Allows replacement of clock operations for testing. - */ -public class Clock { - - /** - * Get the current time of the clock in milliseconds. - * - * @return Current time in milliseconds. - */ - public long getWallClockMillis() { - return System.currentTimeMillis(); - } - - /** - * Returns milliseconds since boot, including time spent in sleep. - * - * @return Current time since boot in milliseconds. - */ - public long getElapsedSinceBootMillis() { - return SystemClock.elapsedRealtime(); - } - - /** - * Returns nanoseconds since boot, including time spent in sleep. - * - * @return Current time since boot in nanoseconds. - */ - public long getElapsedSinceBootNanos() { - return SystemClock.elapsedRealtimeNanos(); - } - - /** - * Returns milliseconds since boot, not counting time spent in deep sleep. - * - * @return Milliseconds of non-sleep uptime since boot. - */ - public long getUptimeSinceBootMillis() { - return SystemClock.uptimeMillis(); - } - - /** - * Waits a given number of milliseconds (of uptimeMillis) before returning. - */ - public void sleep(long ms) { - SystemClock.sleep(ms); - } -} diff --git a/service/java/com/android/server/wifi/CompatibilityScorer.java b/service/java/com/android/server/wifi/CompatibilityScorer.java deleted file mode 100644 index 96b5004f5..000000000 --- a/service/java/com/android/server/wifi/CompatibilityScorer.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.net.wifi.ScanResult; - -import com.android.server.wifi.WifiCandidates.Candidate; -import com.android.server.wifi.WifiCandidates.ScoredCandidate; - -import java.util.Collection; - -/** - * A candidate scorer that attempts to match the previous behavior. - */ -final class CompatibilityScorer implements WifiCandidates.CandidateScorer { - - /** - * This should match WifiNetworkSelector.experimentIdFromIdentifier(getIdentifier()) - * when using the default ScoringParams. - */ - public static final int COMPATIBILITY_SCORER_DEFAULT_EXPID = 42504592; - - private final ScoringParams mScoringParams; - - // config_wifi_framework_RSSI_SCORE_OFFSET - public static final int RSSI_SCORE_OFFSET = 85; - - // config_wifi_framework_RSSI_SCORE_SLOPE - public static final int RSSI_SCORE_SLOPE_IS_4 = 4; - - // config_wifi_framework_5GHz_preference_boost_factor - public static final int BAND_5GHZ_AWARD_IS_40 = 40; - - // config_wifiFramework6ghzPreferenceBoostFactor - public static final int BAND_6GHZ_AWARD_IS_40 = 40; - - // config_wifi_framework_SECURITY_AWARD - public static final int SECURITY_AWARD_IS_80 = 80; - - // config_wifi_framework_LAST_SELECTION_AWARD - public static final int LAST_SELECTION_AWARD_IS_480 = 480; - - // config_wifi_framework_current_network_boost - public static final int CURRENT_NETWORK_BOOST_IS_16 = 16; - - // config_wifi_framework_SAME_BSSID_AWARD - public static final int SAME_BSSID_AWARD_IS_24 = 24; - - private static final boolean USE_USER_CONNECT_CHOICE = true; - - CompatibilityScorer(ScoringParams scoringParams) { - mScoringParams = scoringParams; - } - - @Override - public String getIdentifier() { - return "CompatibilityScorer"; - } - - /** - * Calculates an individual candidate's score. - */ - private ScoredCandidate scoreCandidate(Candidate candidate) { - int rssiSaturationThreshold = mScoringParams.getGoodRssi(candidate.getFrequency()); - int rssi = Math.min(candidate.getScanRssi(), rssiSaturationThreshold); - int score = (rssi + RSSI_SCORE_OFFSET) * RSSI_SCORE_SLOPE_IS_4; - - if (ScanResult.is6GHz(candidate.getFrequency())) { - score += BAND_6GHZ_AWARD_IS_40; - } else if (ScanResult.is5GHz(candidate.getFrequency())) { - score += BAND_5GHZ_AWARD_IS_40; - } - score += (int) (candidate.getLastSelectionWeight() * LAST_SELECTION_AWARD_IS_480); - - if (candidate.isCurrentNetwork()) { - // Add both traditional awards, as would be be case with firmware roaming - score += CURRENT_NETWORK_BOOST_IS_16 + SAME_BSSID_AWARD_IS_24; - } - - if (!candidate.isOpenNetwork()) { - score += SECURITY_AWARD_IS_80; - } - - // To simulate the old strict priority rule, subtract a penalty based on - // which nominator added the candidate. - score -= 1000 * candidate.getNominatorId(); - - // The old method breaks ties on the basis of RSSI, which we can - // emulate easily since our score does not need to be an integer. - double tieBreaker = candidate.getScanRssi() / 1000.0; - return new ScoredCandidate(score + tieBreaker, 10, - USE_USER_CONNECT_CHOICE, candidate); - } - - @Override - public ScoredCandidate scoreCandidates(@NonNull Collection<Candidate> candidates) { - ScoredCandidate choice = ScoredCandidate.NONE; - for (Candidate candidate : candidates) { - ScoredCandidate scoredCandidate = scoreCandidate(candidate); - if (scoredCandidate.value > choice.value) { - choice = scoredCandidate; - } - } - // Here we just return the highest scored candidate; we could - // compute a new score, if desired. - return choice; - } - -} diff --git a/service/java/com/android/server/wifi/ConfigurationMap.java b/service/java/com/android/server/wifi/ConfigurationMap.java deleted file mode 100644 index cce895847..000000000 --- a/service/java/com/android/server/wifi/ConfigurationMap.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.os.UserHandle; -import android.os.UserManager; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -public class ConfigurationMap { - private final Map<Integer, WifiConfiguration> mPerID = new HashMap<>(); - - private final Map<Integer, WifiConfiguration> mPerIDForCurrentUser = new HashMap<>(); - private final Map<ScanResultMatchInfo, WifiConfiguration> - mScanResultMatchInfoMapForCurrentUser = new HashMap<>(); - - private final UserManager mUserManager; - - private int mCurrentUserId = UserHandle.SYSTEM.getIdentifier(); - - ConfigurationMap(UserManager userManager) { - mUserManager = userManager; - } - - /** Dump internal state for debugging. */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("mPerId=" + mPerID); - pw.println("mPerIDForCurrentUser=" + mPerIDForCurrentUser); - pw.println("mScanResultMatchInfoMapForCurrentUser=" - + mScanResultMatchInfoMapForCurrentUser); - pw.println("mCurrentUserId=" + mCurrentUserId); - } - - // RW methods: - public WifiConfiguration put(WifiConfiguration config) { - final WifiConfiguration current = mPerID.put(config.networkId, config); - final UserHandle currentUser = UserHandle.of(mCurrentUserId); - final UserHandle creatorUser = UserHandle.getUserHandleForUid(config.creatorUid); - if (config.shared || currentUser.equals(creatorUser) - || mUserManager.isSameProfileGroup(currentUser, creatorUser)) { - mPerIDForCurrentUser.put(config.networkId, config); - // TODO (b/142035508): Add a more generic fix. This cache should only hold saved - // networks. - if (!config.fromWifiNetworkSpecifier) { - mScanResultMatchInfoMapForCurrentUser.put( - ScanResultMatchInfo.fromWifiConfiguration(config), config); - } - } - return current; - } - - public WifiConfiguration remove(int netID) { - WifiConfiguration config = mPerID.remove(netID); - if (config == null) { - return null; - } - - mPerIDForCurrentUser.remove(netID); - - Iterator<Map.Entry<ScanResultMatchInfo, WifiConfiguration>> scanResultMatchInfoEntries = - mScanResultMatchInfoMapForCurrentUser.entrySet().iterator(); - while (scanResultMatchInfoEntries.hasNext()) { - if (scanResultMatchInfoEntries.next().getValue().networkId == netID) { - scanResultMatchInfoEntries.remove(); - break; - } - } - return config; - } - - public void clear() { - mPerID.clear(); - mPerIDForCurrentUser.clear(); - mScanResultMatchInfoMapForCurrentUser.clear(); - } - - /** - * Sets the new foreground user ID. - * - * @param userId the id of the new foreground user - */ - public void setNewUser(int userId) { - mCurrentUserId = userId; - } - - // RO methods: - public WifiConfiguration getForAllUsers(int netid) { - return mPerID.get(netid); - } - - public WifiConfiguration getForCurrentUser(int netid) { - return mPerIDForCurrentUser.get(netid); - } - - public int sizeForAllUsers() { - return mPerID.size(); - } - - public int sizeForCurrentUser() { - return mPerIDForCurrentUser.size(); - } - - public WifiConfiguration getByConfigKeyForCurrentUser(String key) { - if (key == null) { - return null; - } - for (WifiConfiguration config : mPerIDForCurrentUser.values()) { - if (config.getKey().equals(key)) { - return config; - } - } - return null; - } - - /** - * Retrieves the |WifiConfiguration| object matching the provided |scanResult| from the internal - * map. - * Essentially checks if network config and scan result have the same SSID and encryption type. - */ - public WifiConfiguration getByScanResultForCurrentUser(ScanResult scanResult) { - return mScanResultMatchInfoMapForCurrentUser.get( - ScanResultMatchInfo.fromScanResult(scanResult)); - } - - public Collection<WifiConfiguration> valuesForAllUsers() { - return mPerID.values(); - } - - public Collection<WifiConfiguration> valuesForCurrentUser() { - return mPerIDForCurrentUser.values(); - } -} diff --git a/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java b/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java deleted file mode 100644 index 053314dc7..000000000 --- a/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static android.app.Notification.VISIBILITY_SECRET; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Intent; -import android.graphics.drawable.Icon; -import android.net.wifi.ScanResult; -import android.util.Log; - -import com.android.wifi.resources.R; - -/** - * Helper to create notifications for {@link OpenNetworkNotifier}. - */ -public class ConnectToNetworkNotificationBuilder { - - /** Intent when user dismissed the "Connect to Network" notification. */ - public static final String ACTION_USER_DISMISSED_NOTIFICATION = - "com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION"; - - /** Intent when user tapped action button to connect to recommended network. */ - public static final String ACTION_CONNECT_TO_NETWORK = - "com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK"; - - /** Intent when user tapped action button to open Wi-Fi Settings. */ - public static final String ACTION_PICK_WIFI_NETWORK = - "com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK"; - - /** Intent when user tapped "Failed to connect" notification to open Wi-Fi Settings. */ - public static final String ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE = - "com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE"; - - /** Extra data added to the Intent to specify the registering network notifier. */ - public static final String AVAILABLE_NETWORK_NOTIFIER_TAG = - "com.android.server.wifi.ConnectToNetworkNotification.AVAILABLE_NETWORK_NOTIFIER_TAG"; - - private WifiContext mContext; - private WifiInjector mWifiInjector; - private FrameworkFacade mFrameworkFacade; - - public ConnectToNetworkNotificationBuilder( - WifiContext context, - WifiInjector wifiInjector, - FrameworkFacade framework) { - mContext = context; - mWifiInjector = wifiInjector; - mFrameworkFacade = framework; - } - - /** - * Creates the connect to network notification that alerts users of a recommended connectable - * network. - * - * There are two actions - "Options" link to the Wi-Fi picker activity, and "Connect" prompts - * the connection to the recommended network. - * - * @param notifierTag Unique tag of calling network notifier - * @param network The network to be recommended - */ - public Notification createConnectToAvailableNetworkNotification(String notifierTag, - ScanResult network) { - CharSequence title; - switch (notifierTag) { - case OpenNetworkNotifier.TAG: - title = mContext.getText(R.string.wifi_available_title); - break; - default: - Log.wtf("ConnectToNetworkNotificationBuilder", "Unknown network notifier." - + notifierTag); - return null; - } - Notification.Action connectAction = new Notification.Action.Builder(null /* icon */, - mContext.getResources().getText(R.string.wifi_available_action_connect), - getPrivateBroadcast(ACTION_CONNECT_TO_NETWORK, notifierTag)).build(); - Notification.Action allNetworksAction = new Notification.Action.Builder(null /* icon */, - mContext.getResources().getText(R.string.wifi_available_action_all_networks), - getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag)).build(); - return createNotificationBuilder(title, network.SSID, notifierTag) - .setContentIntent(getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag)) - .addAction(connectAction) - .addAction(allNetworksAction) - .setVisibility(VISIBILITY_SECRET) - .build(); - } - - /** - * Creates the notification that indicates the controller is attempting to connect to the - * recommended network. - * - * @param notifierTag Unique tag of the calling network notifier - * @param network The network to be recommended - */ - public Notification createNetworkConnectingNotification(String notifierTag, - ScanResult network) { - return createNotificationBuilder( - mContext.getText(R.string.wifi_available_title_connecting), network.SSID, - notifierTag) - .setProgress(0 /* max */, 0 /* progress */, true /* indeterminate */) - .build(); - } - - /** - * Creates the notification that indicates the controller successfully connected to the - * recommended network. - * - * @param notifierTag Unique tag of the calling network notifier - * @param network The network to be recommended - */ - public Notification createNetworkConnectedNotification(String notifierTag, ScanResult network) { - return createNotificationBuilder( - mContext.getText(R.string.wifi_available_title_connected), network.SSID, - notifierTag) - .build(); - } - - /** - * Creates the notification that indicates the controller failed to connect to the recommended - * network. Tapping this notification opens the wifi picker. - * - * @param notifierTag Unique tag of the calling network notifier - */ - public Notification createNetworkFailedNotification(String notifierTag) { - return createNotificationBuilder( - mContext.getText(R.string.wifi_available_title_failed_to_connect), - mContext.getText(R.string.wifi_available_content_failed_to_connect), notifierTag) - .setContentIntent( - getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE, - notifierTag)) - .setAutoCancel(true) - .build(); - } - - private int getNotifierRequestCode(String notifierTag) { - switch (notifierTag) { - case OpenNetworkNotifier.TAG: - return 1; - } - return 0; - } - - private Notification.Builder createNotificationBuilder( - CharSequence title, CharSequence content, String extraData) { - return mFrameworkFacade.makeNotificationBuilder(mContext, - WifiService.NOTIFICATION_NETWORK_AVAILABLE) - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range)) - .setTicker(title) - .setContentTitle(title) - .setContentText(content) - .setDeleteIntent(getPrivateBroadcast(ACTION_USER_DISMISSED_NOTIFICATION, extraData)) - .setShowWhen(false) - .setLocalOnly(true) - .setColor(mContext.getResources().getColor( - android.R.color.system_notification_accent_color, - mContext.getTheme())); - } - - private PendingIntent getPrivateBroadcast(String action, String extraData) { - Intent intent = new Intent(action) - .setPackage(mWifiInjector.getWifiStackPackageName()); - int requestCode = 0; // Makes the different kinds of notifications distinguishable - if (extraData != null) { - intent.putExtra(AVAILABLE_NETWORK_NOTIFIER_TAG, extraData); - requestCode = getNotifierRequestCode(extraData); - } - return mFrameworkFacade.getBroadcast(mContext, requestCode, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - } -} diff --git a/service/java/com/android/server/wifi/ConnectedScore.java b/service/java/com/android/server/wifi/ConnectedScore.java deleted file mode 100644 index b02db5852..000000000 --- a/service/java/com/android/server/wifi/ConnectedScore.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.net.wifi.WifiInfo; - -/** - * Base class for connection scoring - */ -public abstract class ConnectedScore { - - /** Maximum NetworkAgent score that should be generated by wifi */ - public static final int WIFI_MAX_SCORE = 60; - - /** Score at which wifi is considered poor enough to give up ant try something else */ - public static final int WIFI_TRANSITION_SCORE = WIFI_MAX_SCORE - 10; - - public static final int WIFI_MIN_SCORE = 0; - - final Clock mClock; - - /** This is a typical STD for the connected RSSI for a phone sitting still */ - public double mDefaultRssiStandardDeviation = 2.0; - - /** - * - * @param clock is the time source for getMillis() - */ - public ConnectedScore(Clock clock) { - mClock = clock; - } - - /** - * Returns the current time in milliseconds - * - * This time is to be passed into the update methods. - * The scoring methods generally don't need a particular epoch, depending - * only on deltas. So a different time source may be used, as long as it is consistent. - * - * Note that when there are long intervals between updates, it is unlikely to matter much - * how large the interval is, so a time source that does not update while the processor is - * asleep could be just fine. - * - * @return millisecond-resolution time. - */ - public long getMillis() { - return mClock.getWallClockMillis(); - } - - /** - * Updates scoring state using RSSI alone - * - * @param rssi signal strength (dB). - * @param millis millisecond-resolution time. - */ - public void updateUsingRssi(int rssi, long millis) { - updateUsingRssi(rssi, millis, mDefaultRssiStandardDeviation); - } - - /** - * Updates scoring state using RSSI and noise estimate - * - * This is useful if an RSSI comes from another source (e.g. scan results) and the - * expected noise varies by source. - * - * @param rssi signal strength (dB). - * @param millis millisecond-resolution time. - * @param standardDeviation of the RSSI. - */ - public abstract void updateUsingRssi(int rssi, long millis, double standardDeviation); - - /** - * Updates the score using relevant parts of WifiInfo - * - * @param wifiInfo object holding relevant values. - * @param millis millisecond-resolution time. - */ - public void updateUsingWifiInfo(WifiInfo wifiInfo, long millis) { - updateUsingRssi(wifiInfo.getRssi(), millis); - } - - /** - * Generates a score based on the current state - * - * @return network score - on NetworkAgent scale. - */ - public abstract int generateScore(); - - /** - * Clears out state associated with the connection - */ - public abstract void reset(); -} diff --git a/service/java/com/android/server/wifi/ConnectionFailureNotificationBuilder.java b/service/java/com/android/server/wifi/ConnectionFailureNotificationBuilder.java deleted file mode 100644 index 6f0a487cf..000000000 --- a/service/java/com/android/server/wifi/ConnectionFailureNotificationBuilder.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.app.AlertDialog; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.DialogInterface; -import android.content.Intent; -import android.graphics.drawable.Icon; -import android.net.wifi.WifiConfiguration; -import android.os.Handler; -import android.view.WindowManager; - -import com.android.wifi.resources.R; - -/** - * Helper class for ConnectionFailureNotifier. - */ -public class ConnectionFailureNotificationBuilder { - private static final String TAG = "ConnectionFailureNotifier"; - - public static final String ACTION_SHOW_SET_RANDOMIZATION_DETAILS = - "com.android.server.wifi.ACTION_SHOW_SET_RANDOMIZATION_DETAILS"; - public static final String RANDOMIZATION_SETTINGS_NETWORK_ID = - "com.android.server.wifi.RANDOMIZATION_SETTINGS_NETWORK_ID"; - public static final String RANDOMIZATION_SETTINGS_NETWORK_SSID = - "com.android.server.wifi.RANDOMIZATION_SETTINGS_NETWORK_SSID"; - - private WifiContext mContext; - private String mPackageName; - private FrameworkFacade mFrameworkFacade; - private WifiConnectivityManager mWifiConnectivityManager; - private NotificationManager mNotificationManager; - private Handler mHandler; - - public ConnectionFailureNotificationBuilder(WifiContext context, String packageName, - FrameworkFacade framework) { - mContext = context; - mPackageName = packageName; - mFrameworkFacade = framework; - } - - /** - * Creates a notification that alerts the user that the connection may be failing due to - * MAC randomization. - * @param config - */ - public Notification buildNoMacRandomizationSupportNotification( - @NonNull WifiConfiguration config) { - String ssid = config.SSID; - String ssidAndSecurityType = config.getSsidAndSecurityTypeString(); - String title = mContext.getResources().getString( - R.string.wifi_cannot_connect_with_randomized_mac_title, ssid); - String content = mContext.getResources().getString( - R.string.wifi_cannot_connect_with_randomized_mac_message); - - Intent showDetailIntent = new Intent(ACTION_SHOW_SET_RANDOMIZATION_DETAILS) - .setPackage(mPackageName); - showDetailIntent.putExtra(RANDOMIZATION_SETTINGS_NETWORK_ID, config.networkId); - showDetailIntent.putExtra(RANDOMIZATION_SETTINGS_NETWORK_SSID, ssidAndSecurityType); - PendingIntent pendingShowDetailIntent = mFrameworkFacade.getBroadcast( - mContext, 0, showDetailIntent, PendingIntent.FLAG_UPDATE_CURRENT); - - return mFrameworkFacade.makeNotificationBuilder( - mContext, WifiService.NOTIFICATION_NETWORK_ALERTS) - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range)) - .setTicker(title) - .setContentTitle(title) - .setContentText(content) - .setContentIntent(pendingShowDetailIntent) - .setShowWhen(false) - .setLocalOnly(true) - .setColor(mContext.getResources().getColor( - android.R.color.system_notification_accent_color, mContext.getTheme())) - .setAutoCancel(true) - .build(); - } - - /** - * Creates an AlertDialog that allows the user to disable MAC randomization for a network. - * @param ssid the displayed SSID in the dialog - * @param onUserConfirm - */ - public AlertDialog buildChangeMacRandomizationSettingDialog( - String ssid, DialogInterface.OnClickListener onUserConfirm) { - AlertDialog.Builder builder = mFrameworkFacade.makeAlertDialogBuilder(mContext) - .setTitle(mContext.getResources().getString( - R.string.wifi_disable_mac_randomization_dialog_title)) - .setMessage(mContext.getResources().getString( - R.string.wifi_disable_mac_randomization_dialog_message, ssid)) - .setPositiveButton( - mContext.getResources().getString( - R.string.wifi_disable_mac_randomization_dialog_confirm_text), - onUserConfirm) - // A null listener allows the dialog to be dismissed directly. - .setNegativeButton(android.R.string.no, null); - AlertDialog dialog = builder.create(); - dialog.setCanceledOnTouchOutside(false); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - return dialog; - } -} diff --git a/service/java/com/android/server/wifi/ConnectionFailureNotifier.java b/service/java/com/android/server/wifi/ConnectionFailureNotifier.java deleted file mode 100644 index 6cdbfed15..000000000 --- a/service/java/com/android/server/wifi/ConnectionFailureNotifier.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.app.AlertDialog; -import android.app.Notification; -import android.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.wifi.WifiConfiguration; -import android.os.Handler; -import android.os.Process; -import android.util.Log; - -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.wifi.resources.R; - -/** - * This class may be used to launch notifications when wifi connections fail. - */ -public class ConnectionFailureNotifier { - private static final String TAG = "ConnectionFailureNotifier"; - - private Context mContext; - private WifiInjector mWifiInjector; - private FrameworkFacade mFrameworkFacade; - private WifiConfigManager mWifiConfigManager; - private WifiConnectivityManager mWifiConnectivityManager; - private NotificationManager mNotificationManager; - private Handler mHandler; - private ConnectionFailureNotificationBuilder mConnectionFailureNotificationBuilder; - - public ConnectionFailureNotifier( - Context context, WifiInjector wifiInjector, FrameworkFacade framework, - WifiConfigManager wifiConfigManager, WifiConnectivityManager wifiConnectivityManager, - Handler handler) { - mContext = context; - mWifiInjector = wifiInjector; - mFrameworkFacade = framework; - mWifiConfigManager = wifiConfigManager; - mWifiConnectivityManager = wifiConnectivityManager; - mNotificationManager = mWifiInjector.getNotificationManager(); - mHandler = handler; - mConnectionFailureNotificationBuilder = - mWifiInjector.getConnectionFailureNotificationBuilder(); - - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectionFailureNotificationBuilder - .ACTION_SHOW_SET_RANDOMIZATION_DETAILS); - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(ConnectionFailureNotificationBuilder - .ACTION_SHOW_SET_RANDOMIZATION_DETAILS)) { - int networkId = intent.getIntExtra( - ConnectionFailureNotificationBuilder - .RANDOMIZATION_SETTINGS_NETWORK_ID, - WifiConfiguration.INVALID_NETWORK_ID); - String ssidAndSecurityType = intent.getStringExtra( - ConnectionFailureNotificationBuilder - .RANDOMIZATION_SETTINGS_NETWORK_SSID); - showRandomizationSettingsDialog(networkId, ssidAndSecurityType); - } - } - }, filter); - } - - /** - * Shows a notification which will bring up a dialog which offers the user an option to disable - * MAC randomization on |networkdId|. - * @param networkId - */ - public void showFailedToConnectDueToNoRandomizedMacSupportNotification(int networkId) { - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId); - if (config == null) { - return; - } - Notification notification = mConnectionFailureNotificationBuilder - .buildNoMacRandomizationSupportNotification(config); - mNotificationManager.notify(SystemMessage.NOTE_NETWORK_NO_MAC_RANDOMIZATION_SUPPORT, - notification); - } - - class DisableMacRandomizationListener implements DialogInterface.OnClickListener { - private WifiConfiguration mConfig; - - DisableMacRandomizationListener(WifiConfiguration config) { - mConfig = config; - } - - @Override - public void onClick(DialogInterface dialog, int which) { - mHandler.post(() -> { - mConfig.macRandomizationSetting = - WifiConfiguration.RANDOMIZATION_NONE; - mWifiConfigManager.addOrUpdateNetwork(mConfig, Process.SYSTEM_UID); - WifiConfiguration updatedConfig = - mWifiConfigManager.getConfiguredNetwork(mConfig.networkId); - if (updatedConfig.macRandomizationSetting - == WifiConfiguration.RANDOMIZATION_NONE) { - String message = mContext.getResources().getString( - R.string.wifi_disable_mac_randomization_dialog_success); - mFrameworkFacade.showToast(mContext, message); - mWifiConfigManager.enableNetwork(updatedConfig.networkId, true, - Process.SYSTEM_UID, null); - mWifiConnectivityManager.forceConnectivityScan( - ClientModeImpl.WIFI_WORK_SOURCE); - } else { - // Shouldn't ever fail, but here for completeness - String message = mContext.getResources().getString( - R.string.wifi_disable_mac_randomization_dialog_failure); - mFrameworkFacade.showToast(mContext, message); - Log.e(TAG, "Failed to modify mac randomization setting"); - } - }); - } - } - - /** - * Class to show a AlertDialog which notifies the user of a network not being privacy - * compliant and then suggests an action. - */ - private void showRandomizationSettingsDialog(int networkId, String ssidAndSecurityType) { - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId); - // Make sure the networkId is still pointing to the correct WifiConfiguration since - // there might be a large time gap between when the notification shows and when - // it's tapped. - if (config == null || ssidAndSecurityType == null - || !ssidAndSecurityType.equals(config.getSsidAndSecurityTypeString())) { - String message = mContext.getResources().getString( - R.string.wifi_disable_mac_randomization_dialog_network_not_found); - mFrameworkFacade.showToast(mContext, message); - return; - } - - AlertDialog dialog = mConnectionFailureNotificationBuilder - .buildChangeMacRandomizationSettingDialog(config.SSID, - new DisableMacRandomizationListener(config)); - dialog.show(); - } -} diff --git a/service/java/com/android/server/wifi/DefaultModeManager.java b/service/java/com/android/server/wifi/DefaultModeManager.java deleted file mode 100644 index 00b2117a8..000000000 --- a/service/java/com/android/server/wifi/DefaultModeManager.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.content.Context; - -import com.android.internal.util.Preconditions; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Manager to handle API calls when wifi is disabled (other mode managers could be active, but this - * class triggers calls to the default implementations). - */ -public class DefaultModeManager implements ActiveModeManager { - - private static final String TAG = "WifiDefaultModeManager"; - - private final Context mContext; - - /** - * Start is not used in default mode. - */ - @Override - public void start() { }; - - /** - * Stop is not used in default mode. - */ - @Override - public void stop() { }; - - @Override - public boolean isStopping() { - return false; - } - - /** - * No role specified in default mode. - */ - @Override - public @Role int getRole() { - return ROLE_UNSPECIFIED; - } - - /** - * No role specified in default mode. - */ - @Override - public void setRole(@Role int role) { - Preconditions.checkState(role == ROLE_UNSPECIFIED); - } - - /** - * Dump is not used in default mode. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { } - - DefaultModeManager(Context context) { - mContext = context; - } -} diff --git a/service/java/com/android/server/wifi/DeviceConfigFacade.java b/service/java/com/android/server/wifi/DeviceConfigFacade.java deleted file mode 100644 index a7bcfc764..000000000 --- a/service/java/com/android/server/wifi/DeviceConfigFacade.java +++ /dev/null @@ -1,724 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.CHANNEL_UTILIZATION_SCALE; - -import android.content.Context; -import android.os.Handler; -import android.provider.DeviceConfig; -import android.util.ArraySet; - -import com.android.internal.annotations.VisibleForTesting; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -/** - * This class allows getting all configurable flags from DeviceConfig. - */ -public class DeviceConfigFacade { - private Context mContext; - private final WifiMetrics mWifiMetrics; - - private static final String NAMESPACE = "wifi"; - - // Default values of fields - @VisibleForTesting - protected static final int DEFAULT_ABNORMAL_CONNECTION_DURATION_MS = - (int) TimeUnit.SECONDS.toMillis(30); - // Default duration for evaluating Wifi condition to trigger a data stall - // measured in milliseconds - public static final int DEFAULT_DATA_STALL_DURATION_MS = 1500; - // Default threshold of Tx throughput below which to trigger a data stall measured in Kbps - public static final int DEFAULT_DATA_STALL_TX_TPUT_THR_KBPS = 2000; - // Default threshold of Rx throughput below which to trigger a data stall measured in Kbps - public static final int DEFAULT_DATA_STALL_RX_TPUT_THR_KBPS = 2000; - // Default threshold of Tx packet error rate above which to trigger a data stall in percentage - public static final int DEFAULT_DATA_STALL_TX_PER_THR = 90; - // Default threshold of CCA level above which to trigger a data stall - public static final int DEFAULT_DATA_STALL_CCA_LEVEL_THR = CHANNEL_UTILIZATION_SCALE; - // Default low threshold of L2 sufficient Tx throughput in Kbps - public static final int DEFAULT_TX_TPUT_SUFFICIENT_THR_LOW_KBPS = 1000; - // Default high threshold of L2 sufficient Tx throughput in Kbps - public static final int DEFAULT_TX_TPUT_SUFFICIENT_THR_HIGH_KBPS = 4000; - // Default low threshold of L2 sufficient Rx throughput in Kbps - public static final int DEFAULT_RX_TPUT_SUFFICIENT_THR_LOW_KBPS = 1000; - // Default high threshold of L2 sufficient Rx throughput in Kbps - public static final int DEFAULT_RX_TPUT_SUFFICIENT_THR_HIGH_KBPS = 4000; - // Numerator part of default threshold of L2 throughput over L3 throughput ratio - public static final int DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM = 2; - // Denominator part of default threshold of L2 throughput over L3 throughput ratio - public static final int DEFAULT_TPUT_SUFFICIENT_RATIO_THR_DEN = 1; - // Default threshold of Tx packet per second - public static final int DEFAULT_TX_PACKET_PER_SECOND_THR = 2; - // Default threshold of Rx packet per second - public static final int DEFAULT_RX_PACKET_PER_SECOND_THR = 1; - // Default high threshold values for various connection/disconnection cases - // All of them are in percent with respect to connection attempts - static final int DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT = 40; - static final int DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT = 30; - static final int DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT = 30; - static final int DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT = 30; - static final int DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT = 20; - static final int DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT = 25; - // Default health monitor abnormal count minimum for various cases - static final int DEFAULT_CONNECTION_FAILURE_COUNT_MIN = 6; - static final int DEFAULT_ASSOC_REJECTION_COUNT_MIN = 3; - static final int DEFAULT_ASSOC_TIMEOUT_COUNT_MIN = 3; - static final int DEFAULT_AUTH_FAILURE_COUNT_MIN = 3; - static final int DEFAULT_SHORT_CONNECTION_NONLOCAL_COUNT_MIN = 3; - static final int DEFAULT_DISCONNECTION_NONLOCAL_COUNT_MIN = 3; - // Numerator part of default ratio threshold values for all cases - static final int DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR = 4; - // Denominator part of ratio threshold for all cases - static final int HEALTH_MONITOR_RATIO_THR_DENOMINATOR = 2; - // Minimum RSSI in dBm for connection stats collection - // Connection or disconnection events with RSSI below this threshold are not - // included in connection stats collection. - static final int DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM = -68; - // Default minimum number of connection attempts to qualify daily detection - static final int DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT = 10; - // Default minimum wait time between two bug report captures - static final int DEFAULT_BUG_REPORT_MIN_WINDOW_MS = 3_600_000; - // Default report-high threshold to take-bug-report threshold ratio. - // It should be larger than 1 since the bar to take bugreport should be higher. - static final int DEFAULT_BUG_REPORT_THRESHOLD_EXTRA_RATIO = 2; - // Default overlapping connection duration threshold in ms to trigger bug report - static final int DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS = 75_000; - // At low traffic, Tx link speed values below the following threshold - // are ignored because it could be due to low rate management frames - static final int DEFAULT_TX_LINK_SPEED_LOW_THRESHOLD_MBPS = 9; - // At low traffic, Rx link speed values below the following threshold - // are ignored because it could be due to low rate management frames - static final int DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS = 9; - // Default health monitor short connection duration threshold in ms - static final int DEFAULT_HEALTH_MONITOR_SHORT_CONNECTION_DURATION_THR_MS = 20_000; - - // Default mask for abnormal disconnection reason codes. - // Each bit of mask corresponds to a reason code defined in 802.11 standard section 9.4.1.7 - // For example, b0 for reason code 0, b1 for reason code 1, etc. - // Bits below are abnormal disconnection reasons and thus are set to 1 - // b0: reserved (e.g., STA heartbeat failure) - // b2: invalid auth - // b4: disassociated due to inactivity - // b6 and b7: invalid class 2 and 3 frames - // b34: disassociated due to missing ACKs - static final long DEFAULT_ABNORMAL_DISCONNECTION_REASON_CODE_MASK = 0x4_0000_00d5L; - // Default maximum interval between last RSSI poll and disconnection - static final int DEFAULT_HEALTH_MONITOR_RSSI_POLL_VALID_TIME_MS = 2_100; - // Default maximum interval between scan and connection attempt in non-stationary state - static final int DEFAULT_NONSTATIONARY_SCAN_RSSI_VALID_TIME_MS = 5_000; - // Default maximum interval between scan and connection attempt in stationary state - static final int DEFAULT_STATIONARY_SCAN_RSSI_VALID_TIME_MS = 8_000; - // Default health monitor firmware alert valid time. - // -1 disables firmware alert time check - static final int DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS = -1; - // Default minimum confirmation duration for sending network score to connectivity service - // when score breaches low. The actual confirmation duration is longer in general and it - // depends on the score evaluation period normally controlled by - // 'com.android.wifi.resources.R' config_wifiPollRssiIntervalMilliseconds. - static final int DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS = 5000; - // Default minimum confirmation duration for sending network score to connectivity service - // when score breaches high. The actual confirmation duration is longer in general and it - // depends on the score evaluation period normally controlled by - // 'com.android.wifi.resources.R' config_wifiPollRssiIntervalMilliseconds. - static final int DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS = 0; - // Default RSSI threshold in dBm above which low score is not sent to connectivity service - // when external scorer takes action. - static final int DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM = -67; - // Cached values of fields updated via updateDeviceConfigFlags() - private boolean mIsAbnormalConnectionBugreportEnabled; - private int mAbnormalConnectionDurationMs; - private int mDataStallDurationMs; - private int mDataStallTxTputThrKbps; - private int mDataStallRxTputThrKbps; - private int mDataStallTxPerThr; - private int mDataStallCcaLevelThr; - private int mTxTputSufficientLowThrKbps; - private int mTxTputSufficientHighThrKbps; - private int mRxTputSufficientLowThrKbps; - private int mRxTputSufficientHighThrKbps; - private int mTputSufficientRatioThrNum; - private int mTputSufficientRatioThrDen; - private int mTxPktPerSecondThr; - private int mRxPktPerSecondThr; - private int mConnectionFailureHighThrPercent; - private int mConnectionFailureCountMin; - private int mAssocRejectionHighThrPercent; - private int mAssocRejectionCountMin; - private int mAssocTimeoutHighThrPercent; - private int mAssocTimeoutCountMin; - private int mAuthFailureHighThrPercent; - private int mAuthFailureCountMin; - private int mShortConnectionNonlocalHighThrPercent; - private int mShortConnectionNonlocalCountMin; - private int mDisconnectionNonlocalHighThrPercent; - private int mDisconnectionNonlocalCountMin; - private int mHealthMonitorRatioThrNumerator; - private int mHealthMonitorMinRssiThrDbm; - private Set<String> mRandomizationFlakySsidHotlist; - private Set<String> mAggressiveMacRandomizationSsidAllowlist; - private Set<String> mAggressiveMacRandomizationSsidBlocklist; - private boolean mIsAbnormalConnectionFailureBugreportEnabled; - private boolean mIsAbnormalDisconnectionBugreportEnabled; - private int mHealthMonitorMinNumConnectionAttempt; - private int mBugReportMinWindowMs; - private int mBugReportThresholdExtraRatio; - private boolean mIsOverlappingConnectionBugreportEnabled; - private int mOverlappingConnectionDurationThresholdMs; - private int mTxLinkSpeedLowThresholdMbps; - private int mRxLinkSpeedLowThresholdMbps; - private int mHealthMonitorShortConnectionDurationThrMs; - private long mAbnormalDisconnectionReasonCodeMask; - private int mHealthMonitorRssiPollValidTimeMs; - private int mNonstationaryScanRssiValidTimeMs; - private int mStationaryScanRssiValidTimeMs; - private int mHealthMonitorFwAlertValidTimeMs; - private int mMinConfirmationDurationSendLowScoreMs; - private int mMinConfirmationDurationSendHighScoreMs; - private int mRssiThresholdNotSendLowScoreToCsDbm; - - public DeviceConfigFacade(Context context, Handler handler, WifiMetrics wifiMetrics) { - mContext = context; - mWifiMetrics = wifiMetrics; - - updateDeviceConfigFlags(); - DeviceConfig.addOnPropertiesChangedListener( - NAMESPACE, - command -> handler.post(command), - properties -> { - updateDeviceConfigFlags(); - }); - } - - private void updateDeviceConfigFlags() { - mIsAbnormalConnectionBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE, - "abnormal_connection_bugreport_enabled", false); - mAbnormalConnectionDurationMs = DeviceConfig.getInt(NAMESPACE, - "abnormal_connection_duration_ms", - DEFAULT_ABNORMAL_CONNECTION_DURATION_MS); - - mDataStallDurationMs = DeviceConfig.getInt(NAMESPACE, - "data_stall_duration_ms", DEFAULT_DATA_STALL_DURATION_MS); - mDataStallTxTputThrKbps = DeviceConfig.getInt(NAMESPACE, - "data_stall_tx_tput_thr_kbps", DEFAULT_DATA_STALL_TX_TPUT_THR_KBPS); - mDataStallRxTputThrKbps = DeviceConfig.getInt(NAMESPACE, - "data_stall_rx_tput_thr_kbps", DEFAULT_DATA_STALL_RX_TPUT_THR_KBPS); - mDataStallTxPerThr = DeviceConfig.getInt(NAMESPACE, - "data_stall_tx_per_thr", DEFAULT_DATA_STALL_TX_PER_THR); - mDataStallCcaLevelThr = DeviceConfig.getInt(NAMESPACE, - "data_stall_cca_level_thr", DEFAULT_DATA_STALL_CCA_LEVEL_THR); - mWifiMetrics.setDataStallDurationMs(mDataStallDurationMs); - mWifiMetrics.setDataStallTxTputThrKbps(mDataStallTxTputThrKbps); - mWifiMetrics.setDataStallRxTputThrKbps(mDataStallRxTputThrKbps); - mWifiMetrics.setDataStallTxPerThr(mDataStallTxPerThr); - mWifiMetrics.setDataStallCcaLevelThr(mDataStallCcaLevelThr); - - mTxTputSufficientLowThrKbps = DeviceConfig.getInt(NAMESPACE, - "tput_sufficient_low_thr_kbps", DEFAULT_TX_TPUT_SUFFICIENT_THR_LOW_KBPS); - mTxTputSufficientHighThrKbps = DeviceConfig.getInt(NAMESPACE, - "tput_sufficient_high_thr_kbps", DEFAULT_TX_TPUT_SUFFICIENT_THR_HIGH_KBPS); - mRxTputSufficientLowThrKbps = DeviceConfig.getInt(NAMESPACE, - "rx_tput_sufficient_low_thr_kbps", DEFAULT_RX_TPUT_SUFFICIENT_THR_LOW_KBPS); - mRxTputSufficientHighThrKbps = DeviceConfig.getInt(NAMESPACE, - "rx_tput_sufficient_high_thr_kbps", DEFAULT_RX_TPUT_SUFFICIENT_THR_HIGH_KBPS); - mTputSufficientRatioThrNum = DeviceConfig.getInt(NAMESPACE, - "tput_sufficient_ratio_thr_num", DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM); - mTputSufficientRatioThrDen = DeviceConfig.getInt(NAMESPACE, - "tput_sufficient_ratio_thr_den", DEFAULT_TPUT_SUFFICIENT_RATIO_THR_DEN); - mTxPktPerSecondThr = DeviceConfig.getInt(NAMESPACE, - "tx_pkt_per_second_thr", DEFAULT_TX_PACKET_PER_SECOND_THR); - mRxPktPerSecondThr = DeviceConfig.getInt(NAMESPACE, - "rx_pkt_per_second_thr", DEFAULT_RX_PACKET_PER_SECOND_THR); - - mConnectionFailureHighThrPercent = DeviceConfig.getInt(NAMESPACE, - "connection_failure_high_thr_percent", - DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT); - mConnectionFailureCountMin = DeviceConfig.getInt(NAMESPACE, - "connection_failure_count_min", - DEFAULT_CONNECTION_FAILURE_COUNT_MIN); - mAssocRejectionHighThrPercent = DeviceConfig.getInt(NAMESPACE, - "assoc_rejection_high_thr_percent", - DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT); - mAssocRejectionCountMin = DeviceConfig.getInt(NAMESPACE, - "assoc_rejection_count_min", - DEFAULT_ASSOC_REJECTION_COUNT_MIN); - mAssocTimeoutHighThrPercent = DeviceConfig.getInt(NAMESPACE, - "assoc_timeout_high_thr_percent", - DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT); - mAssocTimeoutCountMin = DeviceConfig.getInt(NAMESPACE, - "assoc_timeout_count_min", - DEFAULT_ASSOC_TIMEOUT_COUNT_MIN); - mAuthFailureHighThrPercent = DeviceConfig.getInt(NAMESPACE, - "auth_failure_high_thr_percent", - DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT); - mAuthFailureCountMin = DeviceConfig.getInt(NAMESPACE, - "auth_failure_count_min", - DEFAULT_AUTH_FAILURE_COUNT_MIN); - mShortConnectionNonlocalHighThrPercent = DeviceConfig.getInt(NAMESPACE, - "short_connection_nonlocal_high_thr_percent", - DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT); - mShortConnectionNonlocalCountMin = DeviceConfig.getInt(NAMESPACE, - "short_connection_nonlocal_count_min", - DEFAULT_SHORT_CONNECTION_NONLOCAL_COUNT_MIN); - mDisconnectionNonlocalHighThrPercent = DeviceConfig.getInt(NAMESPACE, - "disconnection_nonlocal_high_thr_percent", - DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT); - mDisconnectionNonlocalCountMin = DeviceConfig.getInt(NAMESPACE, - "disconnection_nonlocal_count_min", - DEFAULT_DISCONNECTION_NONLOCAL_COUNT_MIN); - mHealthMonitorRatioThrNumerator = DeviceConfig.getInt(NAMESPACE, - "health_monitor_ratio_thr_numerator", - DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR); - mHealthMonitorMinRssiThrDbm = DeviceConfig.getInt(NAMESPACE, - "health_monitor_min_rssi_thr_dbm", - DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM); - - mRandomizationFlakySsidHotlist = - getUnmodifiableSetQuoted("randomization_flaky_ssid_hotlist"); - mAggressiveMacRandomizationSsidAllowlist = - getUnmodifiableSetQuoted("aggressive_randomization_ssid_allowlist"); - mAggressiveMacRandomizationSsidBlocklist = - getUnmodifiableSetQuoted("aggressive_randomization_ssid_blocklist"); - - mIsAbnormalConnectionFailureBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE, - "abnormal_connection_failure_bugreport_enabled", false); - mIsAbnormalDisconnectionBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE, - "abnormal_disconnection_bugreport_enabled", false); - mHealthMonitorMinNumConnectionAttempt = DeviceConfig.getInt(NAMESPACE, - "health_monitor_min_num_connection_attempt", - DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT); - mBugReportMinWindowMs = DeviceConfig.getInt(NAMESPACE, - "bug_report_min_window_ms", - DEFAULT_BUG_REPORT_MIN_WINDOW_MS); - mBugReportThresholdExtraRatio = DeviceConfig.getInt(NAMESPACE, - "report_bug_report_threshold_extra_ratio", - DEFAULT_BUG_REPORT_THRESHOLD_EXTRA_RATIO); - mIsOverlappingConnectionBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE, - "overlapping_connection_bugreport_enabled", false); - mOverlappingConnectionDurationThresholdMs = DeviceConfig.getInt(NAMESPACE, - "overlapping_connection_duration_threshold_ms", - DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS); - mTxLinkSpeedLowThresholdMbps = DeviceConfig.getInt(NAMESPACE, - "tx_link_speed_low_threshold_mbps", - DEFAULT_TX_LINK_SPEED_LOW_THRESHOLD_MBPS); - mRxLinkSpeedLowThresholdMbps = DeviceConfig.getInt(NAMESPACE, - "rx_link_speed_low_threshold_mbps", - DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS); - mHealthMonitorShortConnectionDurationThrMs = DeviceConfig.getInt(NAMESPACE, - "health_monitor_short_connection_duration_thr_ms", - DEFAULT_HEALTH_MONITOR_SHORT_CONNECTION_DURATION_THR_MS); - mAbnormalDisconnectionReasonCodeMask = DeviceConfig.getLong(NAMESPACE, - "abnormal_disconnection_reason_code_mask", - DEFAULT_ABNORMAL_DISCONNECTION_REASON_CODE_MASK); - mHealthMonitorRssiPollValidTimeMs = DeviceConfig.getInt(NAMESPACE, - "health_monitor_rssi_poll_valid_time_ms", - DEFAULT_HEALTH_MONITOR_RSSI_POLL_VALID_TIME_MS); - mNonstationaryScanRssiValidTimeMs = DeviceConfig.getInt(NAMESPACE, - "nonstationary_scan_rssi_valid_time_ms", - DEFAULT_NONSTATIONARY_SCAN_RSSI_VALID_TIME_MS); - mStationaryScanRssiValidTimeMs = DeviceConfig.getInt(NAMESPACE, - "stationary_scan_rssi_valid_time_ms", - DEFAULT_STATIONARY_SCAN_RSSI_VALID_TIME_MS); - mHealthMonitorFwAlertValidTimeMs = DeviceConfig.getInt(NAMESPACE, - "health_monitor_fw_alert_valid_time_ms", - DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS); - mWifiMetrics.setHealthMonitorRssiPollValidTimeMs(mHealthMonitorRssiPollValidTimeMs); - mMinConfirmationDurationSendLowScoreMs = DeviceConfig.getInt(NAMESPACE, - "min_confirmation_duration_send_low_score_ms", - DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS); - mMinConfirmationDurationSendHighScoreMs = DeviceConfig.getInt(NAMESPACE, - "min_confirmation_duration_send_high_score_ms", - DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS); - mRssiThresholdNotSendLowScoreToCsDbm = DeviceConfig.getInt(NAMESPACE, - "rssi_threshold_not_send_low_score_to_cs_dbm", - DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM); - } - - private Set<String> getUnmodifiableSetQuoted(String key) { - String rawList = DeviceConfig.getString(NAMESPACE, key, ""); - Set<String> result = new ArraySet<>(); - String[] list = rawList.split(","); - for (String cur : list) { - if (cur.length() == 0) { - continue; - } - result.add("\"" + cur + "\""); - } - return Collections.unmodifiableSet(result); - } - - /** - * Gets the feature flag for reporting abnormally long connections. - */ - public boolean isAbnormalConnectionBugreportEnabled() { - return mIsAbnormalConnectionBugreportEnabled; - } - - /** - * Gets the threshold for classifying abnormally long connections. - */ - public int getAbnormalConnectionDurationMs() { - return mAbnormalConnectionDurationMs; - } - - /** - * Gets the duration of evaluating Wifi condition to trigger a data stall. - */ - public int getDataStallDurationMs() { - return mDataStallDurationMs; - } - - /** - * Gets the threshold of Tx throughput below which to trigger a data stall. - */ - public int getDataStallTxTputThrKbps() { - return mDataStallTxTputThrKbps; - } - - /** - * Gets the threshold of Rx throughput below which to trigger a data stall. - */ - public int getDataStallRxTputThrKbps() { - return mDataStallRxTputThrKbps; - } - - /** - * Gets the threshold of Tx packet error rate above which to trigger a data stall. - */ - public int getDataStallTxPerThr() { - return mDataStallTxPerThr; - } - - /** - * Gets the threshold of CCA level above which to trigger a data stall. - */ - public int getDataStallCcaLevelThr() { - return mDataStallCcaLevelThr; - } - - /** - * Gets the low threshold of L2 throughput below which L2 throughput is always insufficient - */ - public int getTxTputSufficientLowThrKbps() { - return mTxTputSufficientLowThrKbps; - } - - /** - * Gets the high threshold of L2 throughput above which L2 throughput is always sufficient - */ - public int getTxTputSufficientHighThrKbps() { - return mTxTputSufficientHighThrKbps; - } - - /** - * Gets the low threshold of L2 throughput below which L2 Rx throughput is always insufficient - */ - public int getRxTputSufficientLowThrKbps() { - return mRxTputSufficientLowThrKbps; - } - - /** - * Gets the high threshold of L2 throughput above which L2 Rx throughput is always sufficient - */ - public int getRxTputSufficientHighThrKbps() { - return mRxTputSufficientHighThrKbps; - } - - /** - * Gets the numerator part of L2 throughput over L3 throughput ratio sufficiency threshold - * above which L2 throughput is sufficient - */ - public int getTputSufficientRatioThrNum() { - return mTputSufficientRatioThrNum; - } - - /** - * Gets the denominator part of L2 throughput over L3 throughput ratio sufficiency threshold - * above which L2 throughput is sufficient - */ - public int getTputSufficientRatioThrDen() { - return mTputSufficientRatioThrDen; - } - - /** - * Gets the threshold of Tx packet per second - * below which Tx throughput sufficiency check will always pass - */ - public int getTxPktPerSecondThr() { - return mTxPktPerSecondThr; - } - - /** - * Gets the threshold of Rx packet per second - * below which Rx throughput sufficiency check will always pass - */ - public int getRxPktPerSecondThr() { - return mRxPktPerSecondThr; - } - - /** - * Gets the high threshold of connection failure rate in percent - */ - public int getConnectionFailureHighThrPercent() { - return mConnectionFailureHighThrPercent; - } - - /** - * Gets connection failure min count - */ - public int getConnectionFailureCountMin() { - return mConnectionFailureCountMin; - } - - /** - * Gets the high threshold of association rejection rate in percent - */ - public int getAssocRejectionHighThrPercent() { - return mAssocRejectionHighThrPercent; - } - - /** - * Gets association rejection min count - */ - public int getAssocRejectionCountMin() { - return mAssocRejectionCountMin; - } - - /** - * Gets the high threshold of association timeout rate in percent - */ - public int getAssocTimeoutHighThrPercent() { - return mAssocTimeoutHighThrPercent; - } - - /** - * Gets association timeout min count - */ - public int getAssocTimeoutCountMin() { - return mAssocTimeoutCountMin; - } - - - /** - * Gets the high threshold of authentication failure rate in percent - */ - public int getAuthFailureHighThrPercent() { - return mAuthFailureHighThrPercent; - } - - /** - * Gets authentication failure min count - */ - public int getAuthFailureCountMin() { - return mAuthFailureCountMin; - } - - /** - * Gets the high threshold of nonlocal short connection rate in percent - */ - public int getShortConnectionNonlocalHighThrPercent() { - return mShortConnectionNonlocalHighThrPercent; - } - - /** - * Gets nonlocal short connection min count - */ - public int getShortConnectionNonlocalCountMin() { - return mShortConnectionNonlocalCountMin; - } - - /** - * Gets the high threshold of nonlocal disconnection rate in percent - */ - public int getDisconnectionNonlocalHighThrPercent() { - return mDisconnectionNonlocalHighThrPercent; - } - - /** - * Gets nonlocal disconnection min count - */ - public int getDisconnectionNonlocalCountMin() { - return mDisconnectionNonlocalCountMin; - } - - /** - * Gets health monitor ratio threshold, numerator part - */ - public int getHealthMonitorRatioThrNumerator() { - return mHealthMonitorRatioThrNumerator; - } - - /** - * Gets health monitor min RSSI threshold in dBm - */ - public int getHealthMonitorMinRssiThrDbm() { - return mHealthMonitorMinRssiThrDbm; - } - - /** - * Gets the Set of SSIDs in the flaky SSID hotlist. - */ - public Set<String> getRandomizationFlakySsidHotlist() { - return mRandomizationFlakySsidHotlist; - } - - /** - * Gets the list of SSIDs for aggressive MAC randomization. - */ - public Set<String> getAggressiveMacRandomizationSsidAllowlist() { - return mAggressiveMacRandomizationSsidAllowlist; - } - - /** - * Gets the list of SSIDs that aggressive MAC randomization should not be used for. - */ - public Set<String> getAggressiveMacRandomizationSsidBlocklist() { - return mAggressiveMacRandomizationSsidBlocklist; - } - /** - * Gets the feature flag for reporting abnormal connection failure. - */ - public boolean isAbnormalConnectionFailureBugreportEnabled() { - return mIsAbnormalConnectionFailureBugreportEnabled; - } - - /** - * Gets the feature flag for reporting abnormal disconnection. - */ - public boolean isAbnormalDisconnectionBugreportEnabled() { - return mIsAbnormalDisconnectionBugreportEnabled; - } - - /** - * Gets health monitor min number of connection attempt threshold - */ - public int getHealthMonitorMinNumConnectionAttempt() { - return mHealthMonitorMinNumConnectionAttempt; - } - - /** - * Gets minimum wait time between two bug report captures - */ - public int getBugReportMinWindowMs() { - return mBugReportMinWindowMs; - } - - /** - * Gets the extra ratio of threshold to trigger bug report. - */ - public int getBugReportThresholdExtraRatio() { - return mBugReportThresholdExtraRatio; - } - - /** - * Gets the feature flag for reporting overlapping connection. - */ - public boolean isOverlappingConnectionBugreportEnabled() { - return mIsOverlappingConnectionBugreportEnabled; - } - - /** - * Gets overlapping connection duration threshold in ms - */ - public int getOverlappingConnectionDurationThresholdMs() { - return mOverlappingConnectionDurationThresholdMs; - } - - /** - * Gets the threshold of link speed below which Tx link speed is ignored at low traffic - */ - public int getTxLinkSpeedLowThresholdMbps() { - return mTxLinkSpeedLowThresholdMbps; - } - - /** - * Gets the threshold of link speed below which Rx link speed is ignored at low traffic - */ - public int getRxLinkSpeedLowThresholdMbps() { - return mRxLinkSpeedLowThresholdMbps; - } - - /** - * Gets health monitor short connection duration threshold in ms - */ - public int getHealthMonitorShortConnectionDurationThrMs() { - return mHealthMonitorShortConnectionDurationThrMs; - } - - /** - * Gets abnormal disconnection reason code mask - */ - public long getAbnormalDisconnectionReasonCodeMask() { - return mAbnormalDisconnectionReasonCodeMask; - } - - /** - * Gets health monitor RSSI poll valid time in ms - */ - public int getHealthMonitorRssiPollValidTimeMs() { - return mHealthMonitorRssiPollValidTimeMs; - } - - /** - * Gets scan rssi valid time in ms when device is in non-stationary state - */ - public int getNonstationaryScanRssiValidTimeMs() { - return mNonstationaryScanRssiValidTimeMs; - } - - /** - * Gets scan rssi valid time in ms when device is in stationary state - */ - public int getStationaryScanRssiValidTimeMs() { - return mStationaryScanRssiValidTimeMs; - } - - /** - * Gets health monitor firmware alert valid time in ms, - * -1 disables firmware alert time check - */ - public int getHealthMonitorFwAlertValidTimeMs() { - return mHealthMonitorFwAlertValidTimeMs; - } - - /** - * Gets the minimum confirmation duration for sending network score to connectivity service - * when score breaches low. - */ - public int getMinConfirmationDurationSendLowScoreMs() { - return mMinConfirmationDurationSendLowScoreMs; - } - - /** - * Gets the minimum confirmation duration for sending network score to connectivity service - * when score breaches high. - */ - public int getMinConfirmationDurationSendHighScoreMs() { - return mMinConfirmationDurationSendHighScoreMs; - } - - /** - * Gets the RSSI threshold above which low score is not sent to connectivity service when - * external scorer takes action. - */ - public int getRssiThresholdNotSendLowScoreToCsDbm() { - return mRssiThresholdNotSendLowScoreToCsDbm; - } -} diff --git a/service/java/com/android/server/wifi/DppManager.java b/service/java/com/android/server/wifi/DppManager.java deleted file mode 100644 index 02b11914d..000000000 --- a/service/java/com/android/server/wifi/DppManager.java +++ /dev/null @@ -1,779 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static android.net.wifi.WifiManager.EASY_CONNECT_NETWORK_ROLE_AP; - -import android.content.Context; -import android.hardware.wifi.supplicant.V1_2.DppAkm; -import android.hardware.wifi.supplicant.V1_2.DppNetRole; -import android.hardware.wifi.supplicant.V1_3.DppFailureCode; -import android.hardware.wifi.supplicant.V1_3.DppProgressCode; -import android.hardware.wifi.supplicant.V1_3.DppSuccessCode; -import android.net.wifi.EasyConnectStatusCallback; -import android.net.wifi.IDppCallback; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; -import android.util.SparseArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.WakeupMessage; -import com.android.server.wifi.WifiNative.DppEventCallback; -import com.android.server.wifi.util.ApConfigUtil; - -import java.util.ArrayList; -import java.util.List; -/** - * DPP Manager class - * Implements the DPP Initiator APIs and callbacks - */ -public class DppManager { - private static final String TAG = "DppManager"; - private final Handler mHandler; - - private DppRequestInfo mDppRequestInfo = null; - private final WifiNative mWifiNative; - private String mClientIfaceName; - private boolean mVerboseLoggingEnabled; - WifiConfigManager mWifiConfigManager; - private final Context mContext; - @VisibleForTesting - public WakeupMessage mDppTimeoutMessage = null; - private final Clock mClock; - private static final String DPP_TIMEOUT_TAG = TAG + " Request Timeout"; - private static final int DPP_TIMEOUT_MS = 40_000; // 40 seconds - private final DppMetrics mDppMetrics; - private final ScanRequestProxy mScanRequestProxy; - - private final DppEventCallback mDppEventCallback = new DppEventCallback() { - @Override - public void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration) { - mHandler.post(() -> { - DppManager.this.onSuccessConfigReceived(newWifiConfiguration); - }); - } - - @Override - public void onSuccess(int dppStatusCode) { - mHandler.post(() -> { - DppManager.this.onSuccess(dppStatusCode); - }); - } - - @Override - public void onProgress(int dppStatusCode) { - mHandler.post(() -> { - DppManager.this.onProgress(dppStatusCode); - }); - } - - @Override - public void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList) { - mHandler.post(() -> { - DppManager.this.onFailure(dppStatusCode, ssid, channelList, bandList); - }); - } - }; - - DppManager(Handler handler, WifiNative wifiNative, WifiConfigManager wifiConfigManager, - Context context, DppMetrics dppMetrics, ScanRequestProxy scanRequestProxy) { - mHandler = handler; - mWifiNative = wifiNative; - mWifiConfigManager = wifiConfigManager; - mWifiNative.registerDppEventCallback(mDppEventCallback); - mContext = context; - mClock = new Clock(); - mDppMetrics = dppMetrics; - mScanRequestProxy = scanRequestProxy; - - // Setup timer - mDppTimeoutMessage = new WakeupMessage(mContext, mHandler, - DPP_TIMEOUT_TAG, () -> { - timeoutDppRequest(); - }); - } - - private static String encodeStringToHex(String str) { - if ((str.length() > 1) && (str.charAt(0) == '"') && (str.charAt(str.length() - 1) == '"')) { - // Remove the surrounding quotes - str = str.substring(1, str.length() - 1); - - // Convert to Hex - char[] charsArray = str.toCharArray(); - StringBuffer hexBuffer = new StringBuffer(); - for (int i = 0; i < charsArray.length; i++) { - hexBuffer.append(Integer.toHexString((int) charsArray[i])); - } - return hexBuffer.toString(); - } - return str; - } - - private void timeoutDppRequest() { - logd("DPP timeout"); - - if (mDppRequestInfo == null) { - Log.e(TAG, "DPP timeout with no request info"); - return; - } - - // Clean up supplicant resources - if (!mWifiNative.stopDppInitiator(mClientIfaceName)) { - Log.e(TAG, "Failed to stop DPP Initiator"); - } - - // Clean up resources and let the caller know about the timeout - onFailure(DppFailureCode.TIMEOUT); - } - - /** - * Start DPP request in Configurator-Initiator mode. The goal of this call is to send the - * selected Wi-Fi configuration to a remote peer so it could join that network. - * - * @param uid User ID - * @param binder Binder object - * @param enrolleeUri The Enrollee URI, scanned externally (e.g. via QR code) - * @param selectedNetworkId The selected Wi-Fi network ID to be sent - * @param enrolleeNetworkRole Network role of remote enrollee: STA or AP - * @param callback DPP Callback object - */ - public void startDppAsConfiguratorInitiator(int uid, IBinder binder, - String enrolleeUri, int selectedNetworkId, - @WifiManager.EasyConnectNetworkRole int enrolleeNetworkRole, IDppCallback callback) { - mDppMetrics.updateDppConfiguratorInitiatorRequests(); - if (mDppRequestInfo != null) { - try { - Log.e(TAG, "DPP request already in progress"); - Log.e(TAG, "Ongoing request UID: " + mDppRequestInfo.uid + ", new UID: " - + uid); - - mDppMetrics.updateDppFailure(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_BUSY); - // On going DPP. Call the failure callback directly - callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY, null, - null, new int[0]); - } catch (RemoteException e) { - // Empty - } - return; - } - - mClientIfaceName = mWifiNative.getClientInterfaceName(); - if (mClientIfaceName == null) { - try { - Log.e(TAG, "Wi-Fi client interface does not exist"); - // On going DPP. Call the failure callback directly - mDppMetrics.updateDppFailure(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_GENERIC); - callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC, - null, null, new int[0]); - } catch (RemoteException e) { - // Empty - } - return; - } - - WifiConfiguration selectedNetwork = mWifiConfigManager - .getConfiguredNetworkWithoutMasking(selectedNetworkId); - - if (selectedNetwork == null) { - try { - Log.e(TAG, "Selected network is null"); - // On going DPP. Call the failure callback directly - mDppMetrics.updateDppFailure(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK); - callback.onFailure(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, null, null, new int[0]); - } catch (RemoteException e) { - // Empty - } - return; - } - - String password = null; - String psk = null; - int securityAkm; - - // Currently support either SAE mode or PSK mode - if (selectedNetwork.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { - // SAE - password = selectedNetwork.preSharedKey; - securityAkm = DppAkm.SAE; - } else if (selectedNetwork.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - if (selectedNetwork.preSharedKey.matches(String.format("[0-9A-Fa-f]{%d}", 64))) { - // PSK - psk = selectedNetwork.preSharedKey; - } else { - // Passphrase - password = selectedNetwork.preSharedKey; - } - securityAkm = DppAkm.PSK; - } else { - try { - // Key management must be either PSK or SAE - Log.e(TAG, "Key management must be either PSK or SAE"); - mDppMetrics.updateDppFailure(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK); - callback.onFailure( - EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, null, - null, new int[0]); - } catch (RemoteException e) { - // Empty - } - return; - } - - mDppRequestInfo = new DppRequestInfo(); - mDppRequestInfo.uid = uid; - mDppRequestInfo.binder = binder; - mDppRequestInfo.callback = callback; - - if (!linkToDeath(mDppRequestInfo)) { - // Notify failure and clean up - onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC); - return; - } - - logd("Interface " + mClientIfaceName + ": Initializing URI: " + enrolleeUri); - - mDppRequestInfo.startTime = mClock.getElapsedSinceBootMillis(); - mDppTimeoutMessage.schedule(mDppRequestInfo.startTime + DPP_TIMEOUT_MS); - - // Send Enrollee URI and get a peer ID - int peerId = mWifiNative.addDppPeerUri(mClientIfaceName, enrolleeUri); - - if (peerId < 0) { - Log.e(TAG, "DPP add URI failure"); - - // Notify failure and clean up - onFailure(DppFailureCode.INVALID_URI); - return; - } - mDppRequestInfo.peerId = peerId; - - // Auth init - logd("Authenticating"); - - String ssidEncoded = encodeStringToHex(selectedNetwork.SSID); - String passwordEncoded = null; - - if (password != null) { - passwordEncoded = encodeStringToHex(selectedNetwork.preSharedKey); - } - - if (!mWifiNative.startDppConfiguratorInitiator(mClientIfaceName, - mDppRequestInfo.peerId, 0, ssidEncoded, passwordEncoded, psk, - enrolleeNetworkRole == EASY_CONNECT_NETWORK_ROLE_AP ? DppNetRole.AP - : DppNetRole.STA, - securityAkm)) { - Log.e(TAG, "DPP Start Configurator Initiator failure"); - - // Notify failure and clean up - onFailure(DppFailureCode.FAILURE); - return; - } - - logd("Success: Started DPP Initiator with peer ID " - + mDppRequestInfo.peerId); - } - - /** - * Start DPP request in Enrollee-Initiator mode. The goal of this call is to receive a - * Wi-Fi configuration object from the peer configurator in order to join a network. - * - * @param uid User ID - * @param binder Binder object - * @param configuratorUri The Configurator URI, scanned externally (e.g. via QR code) - * @param callback DPP Callback object - */ - public void startDppAsEnrolleeInitiator(int uid, IBinder binder, - String configuratorUri, IDppCallback callback) { - mDppMetrics.updateDppEnrolleeInitiatorRequests(); - if (mDppRequestInfo != null) { - try { - Log.e(TAG, "DPP request already in progress"); - Log.e(TAG, "Ongoing request UID: " + mDppRequestInfo.uid + ", new UID: " - + uid); - - mDppMetrics.updateDppFailure(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_BUSY); - // On going DPP. Call the failure callback directly - callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY, null, - null, new int[0]); - } catch (RemoteException e) { - // Empty - } - return; - } - - mDppRequestInfo = new DppRequestInfo(); - mDppRequestInfo.uid = uid; - mDppRequestInfo.binder = binder; - mDppRequestInfo.callback = callback; - - if (!linkToDeath(mDppRequestInfo)) { - // Notify failure and clean up - onFailure(DppFailureCode.FAILURE); - return; - } - - mDppRequestInfo.startTime = mClock.getElapsedSinceBootMillis(); - mDppTimeoutMessage.schedule(mDppRequestInfo.startTime + DPP_TIMEOUT_MS); - - mClientIfaceName = mWifiNative.getClientInterfaceName(); - logd("Interface " + mClientIfaceName + ": Initializing URI: " + configuratorUri); - - // Send Configurator URI and get a peer ID - int peerId = mWifiNative.addDppPeerUri(mClientIfaceName, configuratorUri); - - if (peerId < 0) { - Log.e(TAG, "DPP add URI failure"); - onFailure(DppFailureCode.INVALID_URI); - return; - } - mDppRequestInfo.peerId = peerId; - - // Auth init - logd("Authenticating"); - - if (!mWifiNative.startDppEnrolleeInitiator(mClientIfaceName, mDppRequestInfo.peerId, - 0)) { - Log.e(TAG, "DPP Start Enrollee Initiator failure"); - - // Notify failure and clean up - onFailure(DppFailureCode.FAILURE); - return; - } - - logd("Success: Started DPP Initiator with peer ID " - + mDppRequestInfo.peerId); - } - - /** - * Stop a current DPP session - * - * @param uid User ID - */ - public void stopDppSession(int uid) { - if (mDppRequestInfo == null) { - logd("UID " + uid + " called stop DPP session with no active DPP session"); - return; - } - - if (mDppRequestInfo.uid != uid) { - Log.e(TAG, "UID " + uid + " called stop DPP session but UID " + mDppRequestInfo.uid - + " has started it"); - return; - } - - // Clean up supplicant resources - if (!mWifiNative.stopDppInitiator(mClientIfaceName)) { - Log.e(TAG, "Failed to stop DPP Initiator"); - } - - cleanupDppResources(); - - logd("Success: Stopped DPP Initiator"); - } - - private void cleanupDppResources() { - logd("DPP clean up resources"); - if (mDppRequestInfo == null) { - return; - } - - // Cancel pending timeout - mDppTimeoutMessage.cancel(); - - // Remove the URI from the supplicant list - if (!mWifiNative.removeDppUri(mClientIfaceName, mDppRequestInfo.peerId)) { - Log.e(TAG, "Failed to remove DPP URI ID " + mDppRequestInfo.peerId); - } - - mDppRequestInfo.binder.unlinkToDeath(mDppRequestInfo.dr, 0); - - mDppRequestInfo = null; - } - - private static class DppRequestInfo { - public int uid; - public IBinder binder; - public IBinder.DeathRecipient dr; - public int peerId; - public IDppCallback callback; - public long startTime; - - @Override - public String toString() { - return new StringBuilder("DppRequestInfo: uid=").append(uid).append(", binder=").append( - binder).append(", dr=").append(dr) - .append(", callback=").append(callback) - .append(", peerId=").append(peerId).toString(); - } - } - - /** - * Enable vervose logging from DppManager - * - * @param verbose 0 to disable verbose logging, or any other value to enable. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = verbose != 0 ? true : false; - } - - private void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration) { - try { - logd("onSuccessConfigReceived"); - - if (mDppRequestInfo != null) { - long now = mClock.getElapsedSinceBootMillis(); - mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime)); - - NetworkUpdateResult networkUpdateResult = mWifiConfigManager - .addOrUpdateNetwork(newWifiConfiguration, mDppRequestInfo.uid); - - if (networkUpdateResult.isSuccess()) { - mDppMetrics.updateDppEnrolleeSuccess(); - mDppRequestInfo.callback.onSuccessConfigReceived( - networkUpdateResult.getNetworkId()); - } else { - Log.e(TAG, "DPP configuration received, but failed to update network"); - mDppMetrics.updateDppFailure(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION); - mDppRequestInfo.callback.onFailure(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, null, null, new int[0]); - } - } else { - Log.e(TAG, "Unexpected null Wi-Fi configuration object"); - } - } catch (RemoteException e) { - Log.e(TAG, "Callback failure"); - } - - // Success, DPP is complete. Clear the DPP session automatically - cleanupDppResources(); - } - - private void onSuccess(int dppStatusCode) { - try { - if (mDppRequestInfo == null) { - Log.e(TAG, "onSuccess event without a request information object"); - return; - } - - logd("onSuccess: " + dppStatusCode); - long now = mClock.getElapsedSinceBootMillis(); - mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime)); - - int dppSuccessCode; - - // Convert from HAL codes to WifiManager/user codes - switch (dppStatusCode) { - case DppSuccessCode.CONFIGURATION_SENT: - mDppMetrics.updateDppR1CapableEnrolleeResponderDevices(); - dppSuccessCode = EasyConnectStatusCallback - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT; - break; - - case DppSuccessCode.CONFIGURATION_APPLIED: - dppSuccessCode = EasyConnectStatusCallback - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED; - break; - - default: - Log.e(TAG, "onSuccess: unknown code " + dppStatusCode); - // Success, DPP is complete. Clear the DPP session automatically - cleanupDppResources(); - return; - } - - mDppMetrics.updateDppConfiguratorSuccess(dppSuccessCode); - mDppRequestInfo.callback.onSuccess(dppSuccessCode); - - } catch (RemoteException e) { - Log.e(TAG, "Callback failure"); - } - - // Success, DPP is complete. Clear the DPP session automatically - cleanupDppResources(); - } - - private void onProgress(int dppStatusCode) { - try { - if (mDppRequestInfo == null) { - Log.e(TAG, "onProgress event without a request information object"); - return; - } - - logd("onProgress: " + dppStatusCode); - - int dppProgressCode; - - // Convert from HAL codes to WifiManager/user codes - switch (dppStatusCode) { - case DppProgressCode.AUTHENTICATION_SUCCESS: - dppProgressCode = EasyConnectStatusCallback - .EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS; - break; - - case DppProgressCode.RESPONSE_PENDING: - dppProgressCode = EasyConnectStatusCallback - .EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING; - break; - - case DppProgressCode.CONFIGURATION_SENT_WAITING_RESPONSE: - mDppMetrics.updateDppR2CapableEnrolleeResponderDevices(); - dppProgressCode = EasyConnectStatusCallback - .EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE; - break; - - case DppProgressCode.CONFIGURATION_ACCEPTED: - dppProgressCode = EasyConnectStatusCallback - .EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED; - break; - - default: - Log.e(TAG, "onProgress: unknown code " + dppStatusCode); - return; - } - - mDppRequestInfo.callback.onProgress(dppProgressCode); - - } catch (RemoteException e) { - Log.e(TAG, "Callback failure"); - } - } - - private void onFailure(int dppStatusCode) { - onFailure(dppStatusCode, null, null, null); - } - - /** - * - * This function performs the Enrollee compatibility check with the network. - * Compatibilty check is done based on the channel match. - * The logic looks into the scan cache and checks if network's - * operating channel match with one of the channel in enrollee's scanned channel list. - * - * @param ssid Network name. - * @param channelList contains the list of operating class/channels enrollee used to search for - * the network. - * Reference: DPP spec section: DPP Connection Status Object section. - * (eg for channelList: "81/1,2,3,4,5,6,7,8,9,10,11,117/40,115/48") - * @return True On compatibility check failures due to error conditions or - * when AP is not seen in scan cache or when AP is seen in scan cache and - * operating channel is included in enrollee's scanned channel list. - * False when network's operating channel is not included in Enrollee's - * scanned channel list. - * - */ - private boolean isEnrolleeCompatibleWithNetwork(String ssid, String channelList) { - if (ssid == null || channelList == null) { - return true; - } - SparseArray<int[]> dppChannelList = WifiManager.parseDppChannelList(channelList); - - if (dppChannelList.size() == 0) { - Log.d(TAG, "No channels found after parsing channel list string"); - return true; - } - - List<Integer> freqList = new ArrayList<Integer>(); - - /* Convert the received operatingClass/channels to list of frequencies */ - for (int i = 0; i < dppChannelList.size(); i++) { - /* Derive the band corresponding to operating class */ - int operatingClass = dppChannelList.keyAt(i); - int[] channels = dppChannelList.get(operatingClass); - int band = ApConfigUtil.getBandFromOperatingClass(operatingClass); - if (band < 0) { - Log.e(TAG, "Band corresponding to the operating class: " + operatingClass - + " not found in the table"); - continue; - } - /* Derive frequency list from channel and band */ - for (int j = 0; j < channels.length; j++) { - int freq = ApConfigUtil.convertChannelToFrequency(channels[j], band); - if (freq < 0) { - Log.e(TAG, "Invalid frequency after converting channel: " + channels[j] - + " band: " + band); - continue; - } - freqList.add(freq); - } - } - - if (freqList.size() == 0) { - Log.d(TAG, "frequency list is empty"); - return true; - } - - /* Check the scan cache for the network enrollee tried to find */ - boolean isNetworkInScanCache = false; - boolean channelMatch = false; - for (ScanResult scanResult : mScanRequestProxy.getScanResults()) { - if (!ssid.equals(scanResult.SSID)) { - continue; - } - isNetworkInScanCache = true; - if (freqList.contains(scanResult.frequency)) { - channelMatch = true; - break; - } - } - - if (isNetworkInScanCache & !channelMatch) { - Log.d(TAG, "Update the error code to NOT_COMPATIBLE" - + " as enrollee didn't scan network's operating channel"); - mDppMetrics.updateDppR2EnrolleeResponderIncompatibleConfiguration(); - return false; - } - return true; - } - - private void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList) { - try { - if (mDppRequestInfo == null) { - Log.e(TAG, "onFailure event without a request information object"); - return; - } - - logd("OnFailure: " + dppStatusCode); - - long now = mClock.getElapsedSinceBootMillis(); - mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime)); - - int dppFailureCode; - - // Convert from HAL codes to WifiManager/user codes - switch (dppStatusCode) { - case DppFailureCode.INVALID_URI: - dppFailureCode = - EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI; - break; - - case DppFailureCode.AUTHENTICATION: - dppFailureCode = - EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION; - break; - - case DppFailureCode.NOT_COMPATIBLE: - dppFailureCode = - EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; - break; - - case DppFailureCode.CONFIGURATION: - dppFailureCode = - EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION; - break; - - case DppFailureCode.BUSY: - dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY; - break; - - case DppFailureCode.TIMEOUT: - dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT; - break; - - case DppFailureCode.NOT_SUPPORTED: - dppFailureCode = - EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED; - break; - - case DppFailureCode.CANNOT_FIND_NETWORK: - // This is the only case where channel list is populated, according to the - // DPP spec section 6.3.5.2 DPP Connection Status Object - if (isEnrolleeCompatibleWithNetwork(ssid, channelList)) { - dppFailureCode = - EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK; - } else { - dppFailureCode = - EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; - } - break; - - case DppFailureCode.ENROLLEE_AUTHENTICATION: - dppFailureCode = EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION; - break; - - case DppFailureCode.CONFIGURATION_REJECTED: - dppFailureCode = EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION; - break; - - case DppFailureCode.FAILURE: - default: - dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC; - break; - } - - mDppMetrics.updateDppFailure(dppFailureCode); - if (bandList == null) { - bandList = new int[0]; - } - mDppRequestInfo.callback.onFailure(dppFailureCode, ssid, channelList, bandList); - - } catch (RemoteException e) { - Log.e(TAG, "Callback failure"); - } - - // All failures are fatal, clear the DPP session - cleanupDppResources(); - } - - private void logd(String message) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, message); - } - } - - private boolean linkToDeath(DppRequestInfo dppRequestInfo) { - // register for binder death - dppRequestInfo.dr = new IBinder.DeathRecipient() { - @Override - public void binderDied() { - if (dppRequestInfo == null) { - return; - } - - logd("binderDied: uid=" + dppRequestInfo.uid); - - mHandler.post(() -> { - cleanupDppResources(); - }); - } - }; - - try { - dppRequestInfo.binder.linkToDeath(dppRequestInfo.dr, 0); - } catch (RemoteException e) { - Log.e(TAG, "Error on linkToDeath - " + e); - dppRequestInfo.dr = null; - return false; - } - - return true; - } -} diff --git a/service/java/com/android/server/wifi/DppMetrics.java b/service/java/com/android/server/wifi/DppMetrics.java deleted file mode 100644 index bd6231358..000000000 --- a/service/java/com/android/server/wifi/DppMetrics.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT; - -import android.net.wifi.EasyConnectStatusCallback; -import android.util.SparseIntArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.IntHistogram; - -import java.io.PrintWriter; - -/** - * Provides metrics for Wi-Fi Easy Connect (DPP). Metrics include number of initiator requests, - * number of successes, failures and time completion histogram. - */ -public class DppMetrics { - private final WifiMetricsProto.WifiDppLog mWifiDppLogProto = new WifiMetricsProto.WifiDppLog(); - - // Easy-Connect (DPP) Metrics - // Histogram for DPP operation time. Indicates the following 5 buckets (in seconds): - // < 1 - // [1, 10) - // [10, 25) - // [25, 39) - // >= 39 - which means timeout. - @VisibleForTesting - public static final int[] DPP_OPERATION_TIME = {1, 10, 25, 39}; - private IntHistogram mHistogramDppOperationTime = new IntHistogram(DPP_OPERATION_TIME); - - // Failure codes - private SparseIntArray mHistogramDppFailureCode = new SparseIntArray(); - - // Configurator success codes - private SparseIntArray mHistogramDppConfiguratorSuccessCode = new SparseIntArray(); - - private final Object mLock = new Object(); - - /** - * Update DPP Configurator-Initiator requests - */ - public void updateDppConfiguratorInitiatorRequests() { - synchronized (mLock) { - mWifiDppLogProto.numDppConfiguratorInitiatorRequests++; - } - } - - /** - * Update DPP Enrollee-Initiator requests - */ - public void updateDppEnrolleeInitiatorRequests() { - synchronized (mLock) { - mWifiDppLogProto.numDppEnrolleeInitiatorRequests++; - } - } - - /** - * Update DPP Enrollee success counter - */ - public void updateDppEnrolleeSuccess() { - synchronized (mLock) { - mWifiDppLogProto.numDppEnrolleeSuccess++; - } - } - - /** - * Update number of DPP R1 capable enrollee responder devices. - */ - public void updateDppR1CapableEnrolleeResponderDevices() { - synchronized (mLock) { - mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices++; - } - } - - /** - * Update number of DPP R2 capable enrollee responder devices. - */ - public void updateDppR2CapableEnrolleeResponderDevices() { - synchronized (mLock) { - mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices++; - } - } - - /** - * Update number of times DPP R2 compatibility check detected - * that enrollee responder device is incompatible with the - * network. - */ - public void updateDppR2EnrolleeResponderIncompatibleConfiguration() { - synchronized (mLock) { - mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration++; - } - } - - /** - * Update DPP Configurator success counter - */ - public void updateDppConfiguratorSuccess( - @EasyConnectStatusCallback.EasyConnectSuccessStatusCode int code) { - synchronized (mLock) { - switch (code) { - case EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT: - mHistogramDppConfiguratorSuccessCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT, - mHistogramDppConfiguratorSuccessCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT) + 1); - break; - case EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED: - mHistogramDppConfiguratorSuccessCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED, - mHistogramDppConfiguratorSuccessCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED) + 1); - break; - default: - break; - } - } - } - - /** - * Update DPP failure counters - */ - public void updateDppFailure(@EasyConnectStatusCallback.EasyConnectFailureStatusCode int code) { - synchronized (mLock) { - switch (code) { - case EASY_CONNECT_EVENT_FAILURE_INVALID_URI: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_INVALID_URI, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_INVALID_URI) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_CONFIGURATION: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_BUSY: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_BUSY, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_BUSY) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_TIMEOUT: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_TIMEOUT, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_TIMEOUT) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_GENERIC: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_GENERIC, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_GENERIC) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION) + 1); - break; - case EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION: - mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION, - mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION) - + 1); - break; - default: - break; - } - } - } - - /** - * Update DPP operation time - * - * @param timeMs Time it took to complete the operation, in milliseconds - */ - public void updateDppOperationTime(int timeMs) { - synchronized (mLock) { - mHistogramDppOperationTime.increment(timeMs / 1000); - } - } - - /** - * Dump all DPP metrics - * - * @param pw PrintWriter handle - */ - public void dump(PrintWriter pw) { - synchronized (mLock) { - pw.println("---Easy Connect/DPP metrics---"); - pw.println("mWifiDppLogProto.numDppConfiguratorInitiatorRequests=" - + mWifiDppLogProto.numDppConfiguratorInitiatorRequests); - pw.println("mWifiDppLogProto.numDppEnrolleeInitiatorRequests=" - + mWifiDppLogProto.numDppEnrolleeInitiatorRequests); - pw.println("mWifiDppLogProto.numDppEnrolleeSuccess=" - + mWifiDppLogProto.numDppEnrolleeSuccess); - pw.println("mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices=" - + mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices); - pw.println("mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices=" - + mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices); - pw.println("mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration=" - + mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration); - - if (mHistogramDppFailureCode.size() > 0) { - pw.println("mHistogramDppFailureCode="); - pw.println(mHistogramDppFailureCode); - } - - if (mHistogramDppConfiguratorSuccessCode.size() > 0) { - pw.println("mHistogramDppConfiguratorSuccessCode="); - pw.println(mHistogramDppConfiguratorSuccessCode); - } - - if (mHistogramDppOperationTime.numNonEmptyBuckets() > 0) { - pw.println("mHistogramDppOperationTime="); - pw.println(mHistogramDppOperationTime); - } - pw.println("---End of Easy Connect/DPP metrics---"); - } - } - - /** - * Clear all DPP metrics - */ - public void clear() { - synchronized (mLock) { - mWifiDppLogProto.numDppConfiguratorInitiatorRequests = 0; - mWifiDppLogProto.numDppEnrolleeInitiatorRequests = 0; - mWifiDppLogProto.numDppEnrolleeSuccess = 0; - mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices = 0; - mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices = 0; - mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration = 0; - mHistogramDppFailureCode.clear(); - mHistogramDppOperationTime.clear(); - mHistogramDppConfiguratorSuccessCode.clear(); - } - } - - private WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[] consolidateDppFailure( - SparseIntArray data) { - WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[] - dppFailureStatusHistogramBuckets = - new WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[data.size()]; - - for (int i = 0; i < data.size(); i++) { - dppFailureStatusHistogramBuckets[i] = - new WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket(); - dppFailureStatusHistogramBuckets[i].dppStatusType = data.keyAt(i); - dppFailureStatusHistogramBuckets[i].count = data.valueAt(i); - } - - return dppFailureStatusHistogramBuckets; - } - - private WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket[] - consolidateDppSuccess( - SparseIntArray data) { - WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket[] - dppConfiguratorSuccessStatusHistogramBuckets = - new WifiMetricsProto.WifiDppLog - .DppConfiguratorSuccessStatusHistogramBucket[data.size()]; - - for (int i = 0; i < data.size(); i++) { - dppConfiguratorSuccessStatusHistogramBuckets[i] = - new WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket(); - dppConfiguratorSuccessStatusHistogramBuckets[i].dppStatusType = data.keyAt(i); - dppConfiguratorSuccessStatusHistogramBuckets[i].count = data.valueAt(i); - } - - return dppConfiguratorSuccessStatusHistogramBuckets; - } - - /** - * Consolidate all metrics into the proto. - */ - public WifiMetricsProto.WifiDppLog consolidateProto() { - WifiMetricsProto.WifiDppLog log = new WifiMetricsProto.WifiDppLog(); - synchronized (mLock) { - log.numDppConfiguratorInitiatorRequests = - mWifiDppLogProto.numDppConfiguratorInitiatorRequests; - log.numDppEnrolleeInitiatorRequests = mWifiDppLogProto.numDppEnrolleeInitiatorRequests; - log.numDppEnrolleeSuccess = mWifiDppLogProto.numDppEnrolleeSuccess; - log.numDppR1CapableEnrolleeResponderDevices = - mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices; - log.numDppR2CapableEnrolleeResponderDevices = - mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices; - log.numDppR2EnrolleeResponderIncompatibleConfiguration = - mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration; - log.dppFailureCode = consolidateDppFailure(mHistogramDppFailureCode); - log.dppConfiguratorSuccessCode = - consolidateDppSuccess(mHistogramDppConfiguratorSuccessCode); - log.dppOperationTime = mHistogramDppOperationTime.toProto(); - } - return log; - } -} diff --git a/service/java/com/android/server/wifi/DummyLogMessage.java b/service/java/com/android/server/wifi/DummyLogMessage.java deleted file mode 100644 index 7eafcc701..000000000 --- a/service/java/com/android/server/wifi/DummyLogMessage.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -/** LogMessage implementation that does nothing. */ -public class DummyLogMessage implements WifiLog.LogMessage { - @Override - public WifiLog.LogMessage r(String value) { - return this; - } - - @Override - public WifiLog.LogMessage c(String value) { - return this; - } - - @Override - public WifiLog.LogMessage c(long value) { - return this; - } - - @Override - public WifiLog.LogMessage c(char value) { - return this; - } - - @Override - public WifiLog.LogMessage c(boolean value) { - return this; - } - - @Override - public void flush() { - // Nothing to do. - } -} diff --git a/service/java/com/android/server/wifi/EapFailureNotifier.java b/service/java/com/android/server/wifi/EapFailureNotifier.java deleted file mode 100644 index 1d82082a0..000000000 --- a/service/java/com/android/server/wifi/EapFailureNotifier.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.app.ActivityManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.graphics.drawable.Icon; -import android.net.wifi.WifiConfiguration; -import android.os.UserHandle; -import android.provider.Settings; -import android.service.notification.StatusBarNotification; -import android.telephony.SubscriptionManager; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; - -import java.util.List; - -/** - * This class may be used to launch notifications when EAP failure occurs. - */ -public class EapFailureNotifier { - private static final String TAG = "EapFailureNotifier"; - private static final String ERROR_MESSAGE_OVERLAY_PREFIX = "wifi_eap_error_message_code_"; - - private static final long CANCEL_TIMEOUT_MILLISECONDS = 5 * 60 * 1000; - private final WifiContext mContext; - private final NotificationManager mNotificationManager; - private final FrameworkFacade mFrameworkFacade; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - - // Unique ID associated with the notification. - public static final int NOTIFICATION_ID = SystemMessage.NOTE_WIFI_EAP_FAILURE; - private String mCurrentShownSsid; - - public EapFailureNotifier(WifiContext context, FrameworkFacade frameworkFacade, - WifiCarrierInfoManager wifiCarrierInfoManager) { - mContext = context; - mFrameworkFacade = frameworkFacade; - mWifiCarrierInfoManager = wifiCarrierInfoManager; - mNotificationManager = - mContext.getSystemService(NotificationManager.class); - } - - /** - * Invoked when EAP failure occurs. - * - * @param errorCode error code which delivers from supplicant - */ - public void onEapFailure(int errorCode, WifiConfiguration config) { - StatusBarNotification[] activeNotifications = mNotificationManager.getActiveNotifications(); - for (StatusBarNotification activeNotification : activeNotifications) { - if ((activeNotification.getId() == NOTIFICATION_ID) - && TextUtils.equals(config.SSID, mCurrentShownSsid)) { - return; - } - } - Resources res = getResourcesForSubId(mContext, - mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); - if (res == null) return; - int resourceId = res.getIdentifier( - ERROR_MESSAGE_OVERLAY_PREFIX + errorCode, - "string", - // getIdentifier seems to use the Java package name rather than the Android - // application package name. i.e. what you would have used if the resource name was - // statically known: - // import com.android.wifi.resources.R; - // ... - // R.string.wifi_eap_error_message_code_### - mContext.getWifiOverlayJavaPkgName()); - - if (resourceId == 0) return; - String errorMessage = res.getString(resourceId, config.SSID); - if (TextUtils.isEmpty(errorMessage)) return; - showNotification(errorMessage, config.SSID); - } - - private String getSettingsPackageName() { - Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); - List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentActivitiesAsUser( - intent, PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEFAULT_ONLY, - UserHandle.of(ActivityManager.getCurrentUser())); - if (resolveInfos == null || resolveInfos.isEmpty()) { - Log.e(TAG, "Failed to resolve wifi settings activity"); - return null; - } - // Pick the first one if there are more than 1 since the list is ordered from best to worst. - return resolveInfos.get(0).activityInfo.packageName; - } - - /** - * Display eap error notification which defined by carrier. - * - * @param ssid Error Message which defined by carrier - */ - private void showNotification(String errorMessage, String ssid) { - String settingsPackage = getSettingsPackageName(); - if (settingsPackage == null) return; - Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS) - .setPackage(settingsPackage); - Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext, - WifiService.NOTIFICATION_NETWORK_ALERTS) - .setAutoCancel(true) - .setTimeoutAfter(CANCEL_TIMEOUT_MILLISECONDS) - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range)) - .setContentTitle(mContext.getString( - com.android.wifi.resources.R.string.wifi_available_title_failed_to_connect)) - .setContentText(errorMessage) - .setStyle(new Notification.BigTextStyle().bigText(errorMessage)) - .setContentIntent(mFrameworkFacade.getActivity( - mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)) - .setColor(mContext.getResources().getColor( - android.R.color.system_notification_accent_color)); - mNotificationManager.notify(NOTIFICATION_ID, builder.build()); - mCurrentShownSsid = ssid; - } - - /** - * Returns the resources from the given context for the MCC/MNC - * associated with the subscription. - */ - private Resources getResourcesForSubId(WifiContext context, int subId) { - Context resourceContext = null; - try { - resourceContext = context.createPackageContext( - context.getWifiOverlayApkPkgName(), 0); - } catch (PackageManager.NameNotFoundException ex) { - return null; - } - - return SubscriptionManager.getResourcesForSubId(resourceContext, subId); - } - - /** - * Allow tests to modify mCurrentShownSsid - */ - @VisibleForTesting - void setCurrentShownSsid(String currentShownSsid) { - mCurrentShownSsid = currentShownSsid; - } -} diff --git a/service/java/com/android/server/wifi/ExtendedWifiInfo.java b/service/java/com/android/server/wifi/ExtendedWifiInfo.java deleted file mode 100644 index ef0ef0f74..000000000 --- a/service/java/com/android/server/wifi/ExtendedWifiInfo.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.wifi.WifiInfo; - -import com.android.wifi.resources.R; - -/** - * Extends WifiInfo with the methods for computing the averaged packet rates - */ -public class ExtendedWifiInfo extends WifiInfo { - private static final long RESET_TIME_STAMP = Long.MIN_VALUE; - private static final double FILTER_TIME_CONSTANT = 3000.0; - private static final int SOURCE_UNKNOWN = 0; - private static final int SOURCE_TRAFFIC_COUNTERS = 1; - private static final int SOURCE_LLSTATS = 2; - - private final Context mContext; - - private int mLastSource = SOURCE_UNKNOWN; - private long mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP; - - ExtendedWifiInfo(Context context) { - super(); - mContext = context; - } - - @Override - public void reset() { - super.reset(); - mLastSource = SOURCE_UNKNOWN; - mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP; - if (mContext.getResources().getBoolean( - R.bool.config_wifi_connected_mac_randomization_supported)) { - setMacAddress(DEFAULT_MAC_ADDRESS); - } - } - - /** - * Updates the packet rates using link layer stats - * - * @param stats WifiLinkLayerStats - * @param timeStamp time in milliseconds - */ - public void updatePacketRates(@NonNull WifiLinkLayerStats stats, long timeStamp) { - long txgood = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo; - long txretries = stats.retries_be + stats.retries_bk + stats.retries_vi + stats.retries_vo; - long txbad = stats.lostmpdu_be + stats.lostmpdu_bk + stats.lostmpdu_vi + stats.lostmpdu_vo; - long rxgood = stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo; - update(SOURCE_LLSTATS, txgood, txretries, txbad, rxgood, timeStamp); - } - - /** - * This function is less powerful and used if the WifiLinkLayerStats API is not implemented - * at the Wifi HAL - */ - public void updatePacketRates(long txPackets, long rxPackets, long timeStamp) { - update(SOURCE_TRAFFIC_COUNTERS, txPackets, 0, 0, rxPackets, timeStamp); - } - - private void update(int source, long txgood, long txretries, long txbad, long rxgood, - long timeStamp) { - if (source == mLastSource - && mLastPacketCountUpdateTimeStamp != RESET_TIME_STAMP - && mLastPacketCountUpdateTimeStamp < timeStamp - && txBad <= txbad - && txSuccess <= txgood - && rxSuccess <= rxgood - && txRetries <= txretries) { - long timeDelta = timeStamp - mLastPacketCountUpdateTimeStamp; - double lastSampleWeight = Math.exp(-1.0 * timeDelta / FILTER_TIME_CONSTANT); - double currentSampleWeight = 1.0 - lastSampleWeight; - - setLostTxPacketsPerSecond(getLostTxPacketsPerSecond() * lastSampleWeight - + (txbad - txBad) * 1000.0 / timeDelta - * currentSampleWeight); - setSuccessfulTxPacketsPerSecond(getSuccessfulTxPacketsPerSecond() * lastSampleWeight - + (txgood - txSuccess) * 1000.0 / timeDelta - * currentSampleWeight); - setSuccessfulRxPacketsPerSecond(getSuccessfulRxPacketsPerSecond() * lastSampleWeight - + (rxgood - rxSuccess) * 1000.0 / timeDelta - * currentSampleWeight); - setRetriedTxPacketsRate(getRetriedTxPacketsPerSecond() * lastSampleWeight - + (txretries - txRetries) * 1000.0 / timeDelta - * currentSampleWeight); - } else { - setLostTxPacketsPerSecond(0); - setSuccessfulTxPacketsPerSecond(0); - setSuccessfulRxPacketsPerSecond(0); - setRetriedTxPacketsRate(0); - mLastSource = source; - } - txBad = txbad; - txSuccess = txgood; - rxSuccess = rxgood; - txRetries = txretries; - mLastPacketCountUpdateTimeStamp = timeStamp; - } -} diff --git a/service/java/com/android/server/wifi/FakeWifiLog.java b/service/java/com/android/server/wifi/FakeWifiLog.java deleted file mode 100644 index 4c5128114..000000000 --- a/service/java/com/android/server/wifi/FakeWifiLog.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -/** WifiLog implementation that does nothing. */ -public class FakeWifiLog implements WifiLog { - private static final DummyLogMessage sDummyLogMessage = new DummyLogMessage(); - - // New-style methods. - @Override - public LogMessage err(String format) { - return sDummyLogMessage; - } - - @Override - public LogMessage warn(String format) { - return sDummyLogMessage; - } - - @Override - public LogMessage info(String format) { - return sDummyLogMessage; - } - - @Override - public LogMessage trace(String format) { - return sDummyLogMessage; - } - - @Override - public LogMessage trace(String format, int numFramesToIgnore) { - return sDummyLogMessage; - } - - @Override - public LogMessage dump(String format) { - return sDummyLogMessage; - } - - @Override - public void eC(String msg) { - // Do nothing. - } - - @Override - public void wC(String msg) { - // Do nothing. - } - - @Override - public void iC(String msg) { - // Do nothing. - } - - @Override - public void tC(String msg) { - // Do nothing. - } - - // Legacy methods. - @Override - public void e(String msg) { - // Do nothing. - } - - @Override - public void w(String msg) { - // Do nothing. - } - - @Override - public void i(String msg) { - // Do nothing. - } - - @Override - public void d(String msg) { - // Do nothing. - } - - @Override - public void v(String msg) { - // Do nothing. - } -} diff --git a/service/java/com/android/server/wifi/FrameworkFacade.java b/service/java/com/android/server/wifi/FrameworkFacade.java deleted file mode 100644 index 875154e5b..000000000 --- a/service/java/com/android/server/wifi/FrameworkFacade.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; -import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN; - -import android.app.ActivityManager; -import android.app.AlertDialog; -import android.app.Notification; -import android.app.PendingIntent; -import android.app.admin.DevicePolicyManager; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.database.ContentObserver; -import android.net.TrafficStats; -import android.net.Uri; -import android.net.ip.IpClientCallbacks; -import android.net.ip.IpClientUtil; -import android.os.PersistableBundle; -import android.provider.Settings; -import android.telephony.CarrierConfigManager; -import android.util.Log; -import android.widget.Toast; - -import com.android.server.wifi.util.WifiAsyncChannel; - -/** - * This class allows overriding objects with mocks to write unit tests - */ -public class FrameworkFacade { - public static final String TAG = "FrameworkFacade"; - - private ContentResolver mContentResolver = null; - private CarrierConfigManager mCarrierConfigManager = null; - private ActivityManager mActivityManager = null; - - private ContentResolver getContentResolver(Context context) { - if (mContentResolver == null) { - mContentResolver = context.getContentResolver(); - } - return mContentResolver; - } - - private CarrierConfigManager getCarrierConfigManager(Context context) { - if (mCarrierConfigManager == null) { - mCarrierConfigManager = - (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); - } - return mCarrierConfigManager; - } - - private ActivityManager getActivityManager(Context context) { - if (mActivityManager == null) { - mActivityManager = - (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - } - return mActivityManager; - } - - /** - * Mockable setter for Settings.Global - */ - public boolean setIntegerSetting(ContentResolver contentResolver, String name, int value) { - return Settings.Global.putInt(contentResolver, name, value); - } - - /** - * Mockable getter for Settings.Global - */ - public int getIntegerSetting(ContentResolver contentResolver, String name, int def) { - return Settings.Global.getInt(contentResolver, name, def); - } - - public boolean setIntegerSetting(Context context, String name, int def) { - return Settings.Global.putInt(getContentResolver(context), name, def); - } - - public int getIntegerSetting(Context context, String name, int def) { - return Settings.Global.getInt(getContentResolver(context), name, def); - } - - public long getLongSetting(Context context, String name, long def) { - return Settings.Global.getLong(getContentResolver(context), name, def); - } - - public boolean setStringSetting(Context context, String name, String def) { - return Settings.Global.putString(getContentResolver(context), name, def); - } - - public String getStringSetting(Context context, String name) { - return Settings.Global.getString(getContentResolver(context), name); - } - - /** - * Mockable facade to Settings.Secure.getInt(.). - */ - public int getSecureIntegerSetting(Context context, String name, int def) { - return Settings.Secure.getInt(getContentResolver(context), name, def); - } - - /** - * Mockable facade to Settings.Secure.getString(.). - */ - public String getSecureStringSetting(Context context, String name) { - return Settings.Secure.getString(getContentResolver(context), name); - } - - /** - * Returns whether the device is in NIAP mode or not. - */ - public boolean isNiapModeOn(Context context) { - DevicePolicyManager devicePolicyManager = - context.getSystemService(DevicePolicyManager.class); - if (devicePolicyManager == null - && context.getPackageManager().hasSystemFeature(FEATURE_DEVICE_ADMIN)) { - Log.e(TAG, "Error retrieving DPM service"); - } - if (devicePolicyManager == null) return false; - return devicePolicyManager.isCommonCriteriaModeEnabled(null); - } - - /** - * Helper method for classes to register a ContentObserver - * {@see ContentResolver#registerContentObserver(Uri,boolean,ContentObserver)}. - * - * @param context - * @param uri - * @param notifyForDescendants - * @param contentObserver - */ - public void registerContentObserver(Context context, Uri uri, - boolean notifyForDescendants, ContentObserver contentObserver) { - getContentResolver(context).registerContentObserver(uri, notifyForDescendants, - contentObserver); - } - - /** - * Helper method for classes to unregister a ContentObserver - * {@see ContentResolver#unregisterContentObserver(ContentObserver)}. - * - * @param context - * @param contentObserver - */ - public void unregisterContentObserver(Context context, ContentObserver contentObserver) { - getContentResolver(context).unregisterContentObserver(contentObserver); - } - - public PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags) { - return PendingIntent.getBroadcast(context, requestCode, intent, flags); - } - - /** - * Wrapper for {@link PendingIntent#getActivity}. - */ - public PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags) { - return PendingIntent.getActivity(context, requestCode, intent, flags); - } - - public boolean getConfigWiFiDisableInECBM(Context context) { - CarrierConfigManager configManager = getCarrierConfigManager(context); - if (configManager == null) { - return false; - } - PersistableBundle bundle = configManager.getConfig(); - if (bundle == null) { - return false; - } - return bundle.getBoolean(CarrierConfigManager.KEY_CONFIG_WIFI_DISABLE_IN_ECBM); - } - - public long getTxPackets(String iface) { - return TrafficStats.getTxPackets(iface); - } - - public long getRxPackets(String iface) { - return TrafficStats.getRxPackets(iface); - } - - /** - * Request a new IpClient to be created asynchronously. - * @param context Context to use for creation. - * @param iface Interface the client should act on. - * @param callback IpClient event callbacks. - */ - public void makeIpClient(Context context, String iface, IpClientCallbacks callback) { - IpClientUtil.makeIpClient(context, iface, callback); - } - - /** - * Create a new instance of WifiAsyncChannel - * @param tag String corresponding to the service creating the channel - * @return WifiAsyncChannel object created - */ - public WifiAsyncChannel makeWifiAsyncChannel(String tag) { - return new WifiAsyncChannel(tag); - } - - /** - * Check if the provided uid is the app in the foreground. - * @param uid the uid to check - * @return true if the app is in the foreground, false otherwise - */ - public boolean isAppForeground(Context context, int uid) { - ActivityManager activityManager = getActivityManager(context); - if (activityManager == null) return false; - return activityManager.getUidImportance(uid) <= IMPORTANCE_VISIBLE; - } - - /** - * Create a new instance of {@link Notification.Builder}. - * @param context reference to a Context - * @param channelId ID of the notification channel - * @return an instance of Notification.Builder - */ - public Notification.Builder makeNotificationBuilder(Context context, String channelId) { - return new Notification.Builder(context, channelId); - } - - /** - * Starts supplicant - */ - public void startSupplicant() { - SupplicantManager.start(); - } - - /** - * Stops supplicant - */ - public void stopSupplicant() { - SupplicantManager.stop(); - } - - /** - * Create a new instance of {@link AlertDialog.Builder}. - * @param context reference to a Context - * @return an instance of AlertDialog.Builder - */ - public AlertDialog.Builder makeAlertDialogBuilder(Context context) { - return new AlertDialog.Builder(context); - } - - /** - * Show a toast message - * @param context reference to a Context - * @param text the message to display - */ - public void showToast(Context context, String text) { - Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT); - toast.show(); - } - - /** - * Wrapper for {@link TrafficStats#getMobileTxBytes}. - */ - public long getMobileTxBytes() { - return TrafficStats.getMobileTxBytes(); - } - - /** - * Wrapper for {@link TrafficStats#getMobileRxBytes}. - */ - public long getMobileRxBytes() { - return TrafficStats.getMobileRxBytes(); - } - - /** - * Wrapper for {@link TrafficStats#getTotalTxBytes}. - */ - public long getTotalTxBytes() { - return TrafficStats.getTotalTxBytes(); - } - - /** - * Wrapper for {@link TrafficStats#getTotalRxBytes}. - */ - public long getTotalRxBytes() { - return TrafficStats.getTotalRxBytes(); - } -} diff --git a/service/java/com/android/server/wifi/HalDeviceManager.java b/service/java/com/android/server/wifi/HalDeviceManager.java deleted file mode 100644 index 3d0c89c4a..000000000 --- a/service/java/com/android/server/wifi/HalDeviceManager.java +++ /dev/null @@ -1,2368 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.hardware.wifi.V1_0.IWifi; -import android.hardware.wifi.V1_0.IWifiApIface; -import android.hardware.wifi.V1_0.IWifiChip; -import android.hardware.wifi.V1_0.IWifiChipEventCallback; -import android.hardware.wifi.V1_0.IWifiEventCallback; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.IWifiP2pIface; -import android.hardware.wifi.V1_0.IWifiRttController; -import android.hardware.wifi.V1_0.IWifiStaIface; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hidl.manager.V1_0.IServiceNotification; -import android.hidl.manager.V1_2.IServiceManager; -import android.os.Handler; -import android.os.IHwBinder.DeathRecipient; -import android.os.RemoteException; -import android.util.Log; -import android.util.LongSparseArray; -import android.util.MutableBoolean; -import android.util.MutableInt; -import android.util.Pair; -import android.util.SparseArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.GeneralUtil.Mutable; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Handles device management through the HAL (HIDL) interface. - */ -public class HalDeviceManager { - private static final String TAG = "HalDevMgr"; - private static final boolean VDBG = false; - private boolean mDbg = false; - - private static final int START_HAL_RETRY_INTERVAL_MS = 20; - // Number of attempts a start() is re-tried. A value of 0 means no retries after a single - // attempt. - @VisibleForTesting - public static final int START_HAL_RETRY_TIMES = 3; - - private final Clock mClock; - private final Handler mEventHandler; - private WifiDeathRecipient mIWifiDeathRecipient; - private ServiceManagerDeathRecipient mServiceManagerDeathRecipient; - - // cache the value for supporting vendor HAL or not - private boolean mIsVendorHalSupported = false; - - // public API - public HalDeviceManager(Clock clock, Handler handler) { - mClock = clock; - mEventHandler = handler; - mIWifiDeathRecipient = new WifiDeathRecipient(); - mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient(); - - mInterfaceAvailableForRequestListeners.put(IfaceType.STA, new HashMap<>()); - mInterfaceAvailableForRequestListeners.put(IfaceType.AP, new HashMap<>()); - mInterfaceAvailableForRequestListeners.put(IfaceType.P2P, new HashMap<>()); - mInterfaceAvailableForRequestListeners.put(IfaceType.NAN, new HashMap<>()); - } - - /* package */ void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mDbg = true; - } else { - mDbg = false; - } - if (VDBG) { - mDbg = true; // just override - } - } - - /** - * Actually starts the HalDeviceManager: separate from constructor since may want to phase - * at a later time. - * - * TODO: if decide that no need for separating construction from initialization (e.g. both are - * done at injector) then move to constructor. - */ - public void initialize() { - initializeInternal(); - } - - /** - * Register a ManagerStatusListener to get information about the status of the manager. Use the - * isReady() and isStarted() methods to check status immediately after registration and when - * triggered. - * - * It is safe to re-register the same callback object - duplicates are detected and only a - * single copy kept. - * - * @param listener ManagerStatusListener listener object. - * @param handler Handler on which to dispatch listener. Null implies the listener will be - * invoked synchronously from the context of the client which triggered the - * state change. - */ - public void registerStatusListener(@NonNull ManagerStatusListener listener, - @Nullable Handler handler) { - synchronized (mLock) { - if (!mManagerStatusListeners.add(new ManagerStatusListenerProxy(listener, handler))) { - Log.w(TAG, "registerStatusListener: duplicate registration ignored"); - } - } - } - - /** - * Returns whether the vendor HAL is supported on this device or not. - */ - public boolean isSupported() { - return mIsVendorHalSupported; - } - - /** - * Returns the current status of the HalDeviceManager: whether or not it is ready to execute - * commands. A return of 'false' indicates that the HAL service (IWifi) is not available. Use - * the registerStatusListener() to listener for status changes. - */ - public boolean isReady() { - return mIsReady; - } - - /** - * Returns the current status of Wi-Fi: started (true) or stopped (false). - * - * Note: direct call to HIDL. - */ - public boolean isStarted() { - return isWifiStarted(); - } - - /** - * Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or - * the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on - * success. - * - * Note: direct call to HIDL. - */ - public boolean start() { - return startWifi(); - } - - /** - * Stops Wi-Fi. Will also dispatch any registeredManagerStatusCallback.onStop(). - * - * Note: direct call to HIDL - failure is not-expected. - */ - public void stop() { - stopWifi(); - synchronized (mLock) { // prevents race condition - mWifi = null; - } - } - - /** - * HAL device manager status change listener. - */ - public interface ManagerStatusListener { - /** - * Indicates that the status of the HalDeviceManager has changed. Use isReady() and - * isStarted() to obtain status information. - */ - void onStatusChanged(); - } - - /** - * Return the set of supported interface types across all Wi-Fi chips on the device. - * - * @return A set of IfaceTypes constants (possibly empty, e.g. on error). - */ - public Set<Integer> getSupportedIfaceTypes() { - return getSupportedIfaceTypesInternal(null); - } - - /** - * Return the set of supported interface types for the specified Wi-Fi chip. - * - * @return A set of IfaceTypes constants (possibly empty, e.g. on error). - */ - public Set<Integer> getSupportedIfaceTypes(IWifiChip chip) { - return getSupportedIfaceTypesInternal(chip); - } - - // interface-specific behavior - - /** - * Create a STA interface if possible. Changes chip mode and removes conflicting interfaces if - * needed and permitted by priority. - * - * @param destroyedListener Optional (nullable) listener to call when the allocated interface - * is removed. Will only be registered and used if an interface is - * created successfully. - * @param handler Handler on which to dispatch listener. Null implies the listener will be - * invoked synchronously from the context of the client which triggered the - * iface destruction. - * @return A newly created interface - or null if the interface could not be created. - */ - public IWifiStaIface createStaIface( - @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler) { - return (IWifiStaIface) createIface(IfaceType.STA, destroyedListener, handler); - } - - /** - * Create AP interface if possible (see createStaIface doc). - */ - public IWifiApIface createApIface(@Nullable InterfaceDestroyedListener destroyedListener, - @Nullable Handler handler) { - return (IWifiApIface) createIface(IfaceType.AP, destroyedListener, handler); - } - - /** - * Create P2P interface if possible (see createStaIface doc). - */ - public IWifiP2pIface createP2pIface(@Nullable InterfaceDestroyedListener destroyedListener, - @Nullable Handler handler) { - return (IWifiP2pIface) createIface(IfaceType.P2P, destroyedListener, handler); - } - - /** - * Create NAN interface if possible (see createStaIface doc). - */ - public IWifiNanIface createNanIface(@Nullable InterfaceDestroyedListener destroyedListener, - @Nullable Handler handler) { - return (IWifiNanIface) createIface(IfaceType.NAN, destroyedListener, handler); - } - - /** - * Removes (releases/destroys) the given interface. Will trigger any registered - * InterfaceDestroyedListeners and possibly some InterfaceAvailableForRequestListeners if we - * can potentially create some other interfaces as a result of removing this interface. - */ - public boolean removeIface(IWifiIface iface) { - boolean success = removeIfaceInternal(iface); - dispatchAvailableForRequestListeners(); - return success; - } - - /** - * Returns the IWifiChip corresponding to the specified interface (or null on error). - * - * Note: clients must not perform chip mode changes or interface management (create/delete) - * operations on IWifiChip directly. However, they can use the IWifiChip interface to perform - * other functions - e.g. calling the debug/trace methods. - */ - public IWifiChip getChip(IWifiIface iface) { - String name = getName(iface); - int type = getType(iface); - if (VDBG) Log.d(TAG, "getChip: iface(name)=" + name); - - synchronized (mLock) { - InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type)); - if (cacheEntry == null) { - Log.e(TAG, "getChip: no entry for iface(name)=" + name); - return null; - } - - return cacheEntry.chip; - } - } - - /** - * Register an InterfaceDestroyedListener to the specified iface - returns true on success - * and false on failure. This listener is in addition to the one registered when the interface - * was created - allowing non-creators to monitor interface status. - * - * @param destroyedListener Listener to call when the allocated interface is removed. - * Will only be registered and used if an interface is created - * successfully. - * @param handler Handler on which to dispatch listener. Null implies the listener will be - * invoked synchronously from the context of the client which triggered the - * iface destruction. - */ - public boolean registerDestroyedListener(IWifiIface iface, - @NonNull InterfaceDestroyedListener destroyedListener, - @Nullable Handler handler) { - String name = getName(iface); - int type = getType(iface); - if (VDBG) Log.d(TAG, "registerDestroyedListener: iface(name)=" + name); - - synchronized (mLock) { - InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type)); - if (cacheEntry == null) { - Log.e(TAG, "registerDestroyedListener: no entry for iface(name)=" + name); - return false; - } - - return cacheEntry.destroyedListeners.add( - new InterfaceDestroyedListenerProxy(name, destroyedListener, handler)); - } - } - - /** - * Register a listener to be called when an interface of the specified type could be requested. - * No guarantees are provided (some other entity could request it first). The listener is - * active from registration until either - * <li>unregistration (using - * {@link #unregisterInterfaceAvailableForRequestListener(int, - * InterfaceAvailableForRequestListener)})</li> - * <li>HAL stop (using {@link #stop()}.</li> - * - * Only a single instance of a listener will be registered (even if the specified looper is - * different). - * - * Note that if it is possible to create the specified interface type at registration time - * then the callback will be triggered immediately. - * - * @param ifaceType The interface type (IfaceType) to be monitored. - * @param listener Listener to call when an interface of the requested - * type could be created - * @param handler Handler on which to dispatch listener. Null implies the listener will be - * invoked synchronously from the context of the client which triggered the - * mode change. - */ - public void registerInterfaceAvailableForRequestListener(int ifaceType, - @NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler) { - if (VDBG) { - Log.d(TAG, "registerInterfaceAvailableForRequestListener: ifaceType=" + ifaceType - + ", listener=" + listener + ", handler=" + handler); - } - - synchronized (mLock) { - InterfaceAvailableForRequestListenerProxy proxy = - new InterfaceAvailableForRequestListenerProxy(listener, handler); - if (mInterfaceAvailableForRequestListeners.get(ifaceType).containsKey(proxy)) { - if (VDBG) { - Log.d(TAG, - "registerInterfaceAvailableForRequestListener: dup listener skipped: " - + listener); - } - return; - } - mInterfaceAvailableForRequestListeners.get(ifaceType).put(proxy, null); - } - - WifiChipInfo[] chipInfos = getAllChipInfo(); - if (chipInfos == null) { - Log.e(TAG, - "registerInterfaceAvailableForRequestListener: no chip info found - but " - + "possibly registered pre-started - ignoring"); - return; - } - dispatchAvailableForRequestListenersForType(ifaceType, chipInfos); - } - - /** - * Unregisters a listener registered with registerInterfaceAvailableForRequestListener(). - */ - public void unregisterInterfaceAvailableForRequestListener( - int ifaceType, - InterfaceAvailableForRequestListener listener) { - if (VDBG) { - Log.d(TAG, "unregisterInterfaceAvailableForRequestListener: ifaceType=" + ifaceType); - } - - synchronized (mLock) { - mInterfaceAvailableForRequestListeners.get(ifaceType).remove( - new InterfaceAvailableForRequestListenerProxy(listener, null)); - } - } - - /** - * Register a callback object for RTT life-cycle events. The callback object registration - * indicates that an RTT controller should be created whenever possible. The callback object - * will be called with a new RTT controller whenever it is created (or at registration time - * if an RTT controller already exists). The callback object will also be triggered whenever - * an existing RTT controller is destroyed (the previous copies must be discarded by the - * recipient). - * - * @param callback InterfaceRttControllerLifecycleCallback object. - * @param handler Handler on which to dispatch callback - */ - public void registerRttControllerLifecycleCallback( - @NonNull InterfaceRttControllerLifecycleCallback callback, @NonNull Handler handler) { - if (VDBG) { - Log.d(TAG, "registerRttControllerLifecycleCallback: callback=" + callback + ", handler=" - + handler); - } - - if (callback == null || handler == null) { - Log.wtf(TAG, "registerRttControllerLifecycleCallback with nulls!? callback=" + callback - + ", handler=" + handler); - return; - } - - synchronized (mLock) { - InterfaceRttControllerLifecycleCallbackProxy proxy = - new InterfaceRttControllerLifecycleCallbackProxy(callback, handler); - if (!mRttControllerLifecycleCallbacks.add(proxy)) { - Log.d(TAG, - "registerRttControllerLifecycleCallback: registering an existing callback=" - + callback); - return; - } - - if (mIWifiRttController == null) { - mIWifiRttController = createRttControllerIfPossible(); - } - if (mIWifiRttController != null) { - proxy.onNewRttController(mIWifiRttController); - } - } - } - - /** - * Return the name of the input interface or null on error. - */ - public static String getName(IWifiIface iface) { - if (iface == null) { - return "<null>"; - } - - Mutable<String> nameResp = new Mutable<>(); - try { - iface.getName((WifiStatus status, String name) -> { - if (status.code == WifiStatusCode.SUCCESS) { - nameResp.value = name; - } else { - Log.e(TAG, "Error on getName: " + statusString(status)); - } - }); - } catch (RemoteException e) { - Log.e(TAG, "Exception on getName: " + e); - } - - return nameResp.value; - } - - /** - * Called when interface is destroyed. - */ - public interface InterfaceDestroyedListener { - /** - * Called for every interface on which registered when destroyed - whether - * destroyed by releaseIface() or through chip mode change or through Wi-Fi - * going down. - * - * Can be registered when the interface is requested with createXxxIface() - will - * only be valid if the interface creation was successful - i.e. a non-null was returned. - * - * @param ifaceName Name of the interface that was destroyed. - */ - void onDestroyed(@NonNull String ifaceName); - } - - /** - * Called when an interface type availability for creation is changed. - */ - public interface InterfaceAvailableForRequestListener { - /** - * Called when an interface type availability for creation is updated. Registered with - * registerInterfaceAvailableForRequestListener() and unregistered with - * unregisterInterfaceAvailableForRequestListener(). - */ - void onAvailabilityChanged(boolean isAvailable); - } - - /** - * Called on RTT controller lifecycle events. RTT controller is a singleton which will be - * created when possible (after first lifecycle registration) and destroyed if necessary. - * - * Determination of availability is determined by the HAL. Creation attempts (if requested - * by registration of interface) will be done on any mode changes. - */ - public interface InterfaceRttControllerLifecycleCallback { - /** - * Called when an RTT controller was created (or for newly registered listeners - if it - * was already available). The controller provided by this callback may be destroyed by - * the HAL at which point the {@link #onRttControllerDestroyed()} will be called. - * - * Note: this callback can be triggered to replace an existing controller (instead of - * calling the Destroyed callback in between). - * - * @param controller The RTT controller object. - */ - void onNewRttController(@NonNull IWifiRttController controller); - - /** - * Called when the previously provided RTT controller is destroyed. Clients must discard - * their copy. A new copy may be provided later by - * {@link #onNewRttController(IWifiRttController)}. - */ - void onRttControllerDestroyed(); - } - - /** - * Returns whether the provided Iface combo can be supported by the device. - * Note: This only returns an answer based on the iface combination exposed by the HAL. - * The actual iface creation/deletion rules depend on the iface priorities set in - * {@link #allowedToDeleteIfaceTypeForRequestedType(int, int, WifiIfaceInfo[][], int)} - * - * @param ifaceCombo SparseArray keyed in by the iface type to number of ifaces needed. - * @return true if the device supports the provided combo, false otherwise. - */ - public boolean canSupportIfaceCombo(SparseArray<Integer> ifaceCombo) { - if (VDBG) Log.d(TAG, "canSupportIfaceCombo: ifaceCombo=" + ifaceCombo); - - synchronized (mLock) { - int[] ifaceComboArr = new int[IFACE_TYPES_BY_PRIORITY.length]; - for (int type : IFACE_TYPES_BY_PRIORITY) { - ifaceComboArr[type] = ifaceCombo.get(type, 0); - } - WifiChipInfo[] chipInfos = getAllChipInfo(); - if (chipInfos == null) return false; - return isItPossibleToCreateIfaceCombo(chipInfos, ifaceComboArr); - } - } - - // internal state - - /* This "PRIORITY" is not for deciding interface elimination (that is controlled by - * allowedToDeleteIfaceTypeForRequestedType. This priority is used for: - * - Comparing 2 configuration options - * - Order of dispatch of available for request listeners - */ - private static final int[] IFACE_TYPES_BY_PRIORITY = - {IfaceType.AP, IfaceType.STA, IfaceType.P2P, IfaceType.NAN}; - - private final Object mLock = new Object(); - - private IServiceManager mServiceManager; - private IWifi mWifi; - private IWifiRttController mIWifiRttController; - private final WifiEventCallback mWifiEventCallback = new WifiEventCallback(); - private final Set<ManagerStatusListenerProxy> mManagerStatusListeners = new HashSet<>(); - private final Set<InterfaceRttControllerLifecycleCallbackProxy> - mRttControllerLifecycleCallbacks = new HashSet<>(); - private final SparseArray<Map<InterfaceAvailableForRequestListenerProxy, Boolean>> - mInterfaceAvailableForRequestListeners = new SparseArray<>(); - private final SparseArray<IWifiChipEventCallback.Stub> mDebugCallbacks = new SparseArray<>(); - private boolean mIsReady; - - /* - * This is the only place where we cache HIDL information in this manager. Necessary since - * we need to keep a list of registered destroyed listeners. Will be validated regularly - * in getAllChipInfoAndValidateCache(). - */ - private final Map<Pair<String, Integer>, InterfaceCacheEntry> mInterfaceInfoCache = - new HashMap<>(); - private WifiChipInfo[] mDebugChipsInfo = null; - - private class InterfaceCacheEntry { - public IWifiChip chip; - public int chipId; - public String name; - public int type; - public Set<InterfaceDestroyedListenerProxy> destroyedListeners = new HashSet<>(); - public long creationTime; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("{name=").append(name).append(", type=").append(type) - .append(", destroyedListeners.size()=").append(destroyedListeners.size()) - .append(", creationTime=").append(creationTime).append("}"); - return sb.toString(); - } - } - - private class WifiIfaceInfo { - public String name; - public IWifiIface iface; - - @Override - public String toString() { - return "{name=" + name + ", iface=" + iface + "}"; - } - } - - private class WifiChipInfo { - public IWifiChip chip; - public int chipId; - public ArrayList<IWifiChip.ChipMode> availableModes; - public boolean currentModeIdValid; - public int currentModeId; - public WifiIfaceInfo[][] ifaces = new WifiIfaceInfo[IFACE_TYPES_BY_PRIORITY.length][]; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("{chipId=").append(chipId).append(", availableModes=").append(availableModes) - .append(", currentModeIdValid=").append(currentModeIdValid) - .append(", currentModeId=").append(currentModeId); - for (int type: IFACE_TYPES_BY_PRIORITY) { - sb.append(", ifaces[" + type + "].length=").append(ifaces[type].length); - } - sb.append("}"); - return sb.toString(); - } - } - - /** - * Wrapper function to access the HIDL services. Created to be mockable in unit-tests. - */ - protected IWifi getWifiServiceMockable() { - try { - return IWifi.getService(true /* retry */); - } catch (RemoteException e) { - Log.e(TAG, "Exception getting IWifi service: " + e); - return null; - } - } - - protected IServiceManager getServiceManagerMockable() { - try { - return IServiceManager.getService(); - } catch (RemoteException e) { - Log.e(TAG, "Exception getting IServiceManager: " + e); - return null; - } - } - - // internal implementation - - private void initializeInternal() { - initIServiceManagerIfNecessary(); - if (mIsVendorHalSupported) { - initIWifiIfNecessary(); - } - } - - private void teardownInternal() { - managerStatusListenerDispatch(); - dispatchAllDestroyedListeners(); - mInterfaceAvailableForRequestListeners.get(IfaceType.STA).clear(); - mInterfaceAvailableForRequestListeners.get(IfaceType.AP).clear(); - mInterfaceAvailableForRequestListeners.get(IfaceType.P2P).clear(); - mInterfaceAvailableForRequestListeners.get(IfaceType.NAN).clear(); - - mIWifiRttController = null; - dispatchRttControllerLifecycleOnDestroyed(); - mRttControllerLifecycleCallbacks.clear(); - } - - private class ServiceManagerDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - Log.wtf(TAG, "IServiceManager died: cookie=" + cookie); - synchronized (mLock) { - mServiceManager = null; - // theoretically can call initServiceManager again here - but - // there's no point since most likely system is going to reboot - } - }); - } - } - - private final IServiceNotification mServiceNotificationCallback = - new IServiceNotification.Stub() { - @Override - public void onRegistration(String fqName, String name, - boolean preexisting) { - Log.d(TAG, "IWifi registration notification: fqName=" + fqName - + ", name=" + name + ", preexisting=" + preexisting); - synchronized (mLock) { - initIWifiIfNecessary(); - } - } - }; - - /** - * Failures of IServiceManager are most likely system breaking in any case. Behavior here - * will be to WTF and continue. - */ - private void initIServiceManagerIfNecessary() { - if (mDbg) Log.d(TAG, "initIServiceManagerIfNecessary"); - - synchronized (mLock) { - if (mServiceManager != null) { - return; - } - - mServiceManager = getServiceManagerMockable(); - if (mServiceManager == null) { - Log.wtf(TAG, "Failed to get IServiceManager instance"); - } else { - try { - if (!mServiceManager.linkToDeath( - mServiceManagerDeathRecipient, /* don't care */ 0)) { - Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); - mServiceManager = null; - return; - } - - if (!mServiceManager.registerForNotifications(IWifi.kInterfaceName, "", - mServiceNotificationCallback)) { - Log.wtf(TAG, "Failed to register a listener for IWifi service"); - mServiceManager = null; - } - } catch (RemoteException e) { - Log.wtf(TAG, "Exception while operating on IServiceManager: " + e); - mServiceManager = null; - } - - // Cache the result for the supporting vendor hal or not - mIsVendorHalSupported = isSupportedInternal(); - } - } - } - - /** - * Uses the IServiceManager to query if the vendor HAL is present in the VINTF for the device - * or not. - * @return true if supported, false otherwise. - */ - private boolean isSupportedInternal() { - if (VDBG) Log.d(TAG, "isSupportedInternal"); - - synchronized (mLock) { - if (mServiceManager == null) { - Log.e(TAG, "isSupported: called but mServiceManager is null!?"); - return false; - } - try { - List<String> wifiServices = - mServiceManager.listManifestByInterface(IWifi.kInterfaceName); - return !wifiServices.isEmpty(); - } catch (RemoteException e) { - Log.wtf(TAG, "Exception while operating on IServiceManager: " + e); - return false; - } - } - } - - private class WifiDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - Log.e(TAG, "IWifi HAL service died! Have a listener for it ... cookie=" + cookie); - synchronized (mLock) { // prevents race condition with surrounding method - mWifi = null; - mIsReady = false; - teardownInternal(); - // don't restart: wait for registration notification - } - }); - } - } - - /** - * Initialize IWifi and register death listener and event callback. - * - * - It is possible that IWifi is not ready - we have a listener on IServiceManager for it. - * - It is not expected that any of the registrations will fail. Possible indication that - * service died after we obtained a handle to it. - * - * Here and elsewhere we assume that death listener will do the right thing! - */ - private void initIWifiIfNecessary() { - if (mDbg) Log.d(TAG, "initIWifiIfNecessary"); - - synchronized (mLock) { - if (mWifi != null) { - return; - } - - try { - mWifi = getWifiServiceMockable(); - if (mWifi == null) { - Log.e(TAG, "IWifi not (yet) available - but have a listener for it ..."); - return; - } - - if (!mWifi.linkToDeath(mIWifiDeathRecipient, /* don't care */ 0)) { - Log.e(TAG, "Error on linkToDeath on IWifi - will retry later"); - return; - } - - WifiStatus status = mWifi.registerEventCallback(mWifiEventCallback); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "IWifi.registerEventCallback failed: " + statusString(status)); - mWifi = null; - return; - } - // Stopping wifi just in case. This would also trigger the status callback. - stopWifi(); - mIsReady = true; - } catch (RemoteException e) { - Log.e(TAG, "Exception while operating on IWifi: " + e); - } - } - } - - /** - * Registers event listeners on all IWifiChips after a successful start: DEBUG only! - * - * We don't need the listeners since any callbacks are just confirmation of status codes we - * obtain directly from mode changes or interface creation/deletion. - * - * Relies (to the degree we care) on the service removing all listeners when Wi-Fi is stopped. - */ - private void initIWifiChipDebugListeners() { - if (VDBG) Log.d(TAG, "initIWifiChipDebugListeners"); - - if (!VDBG) { - return; - } - - synchronized (mLock) { - try { - MutableBoolean statusOk = new MutableBoolean(false); - Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>(); - - // get all chip IDs - mWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - chipIdsResp.value = chipIds; - } else { - Log.e(TAG, "getChipIds failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return; - } - - Log.d(TAG, "getChipIds=" + chipIdsResp.value); - if (chipIdsResp.value.size() == 0) { - Log.e(TAG, "Should have at least 1 chip!"); - return; - } - - // register a callback for each chip - Mutable<IWifiChip> chipResp = new Mutable<>(); - for (Integer chipId: chipIdsResp.value) { - mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - chipResp.value = chip; - } else { - Log.e(TAG, "getChip failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - continue; // still try next one? - } - - IWifiChipEventCallback.Stub callback = - new IWifiChipEventCallback.Stub() { - @Override - public void onChipReconfigured(int modeId) throws RemoteException { - Log.d(TAG, "onChipReconfigured: modeId=" + modeId); - } - - @Override - public void onChipReconfigureFailure(WifiStatus status) - throws RemoteException { - Log.d(TAG, "onChipReconfigureFailure: status=" + statusString( - status)); - } - - @Override - public void onIfaceAdded(int type, String name) - throws RemoteException { - Log.d(TAG, "onIfaceAdded: type=" + type + ", name=" + name); - } - - @Override - public void onIfaceRemoved(int type, String name) - throws RemoteException { - Log.d(TAG, "onIfaceRemoved: type=" + type + ", name=" + name); - } - - @Override - public void onDebugRingBufferDataAvailable( - WifiDebugRingBufferStatus status, - ArrayList<Byte> data) throws RemoteException { - Log.d(TAG, "onDebugRingBufferDataAvailable"); - } - - @Override - public void onDebugErrorAlert(int errorCode, - ArrayList<Byte> debugData) - throws RemoteException { - Log.d(TAG, "onDebugErrorAlert"); - } - }; - mDebugCallbacks.put(chipId, callback); // store to prevent GC: needed by HIDL - WifiStatus status = chipResp.value.registerEventCallback(callback); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "registerEventCallback failed: " + statusString(status)); - continue; // still try next one? - } - } - } catch (RemoteException e) { - Log.e(TAG, "initIWifiChipDebugListeners: exception: " + e); - return; - } - } - } - - /** - * Get current information about all the chips in the system: modes, current mode (if any), and - * any existing interfaces. - * - * Intended to be called whenever we need to configure the chips - information is NOT cached (to - * reduce the likelihood that we get out-of-sync). - */ - private WifiChipInfo[] getAllChipInfo() { - if (VDBG) Log.d(TAG, "getAllChipInfo"); - - synchronized (mLock) { - if (mWifi == null) { - Log.e(TAG, "getAllChipInfo: called but mWifi is null!?"); - return null; - } - - try { - MutableBoolean statusOk = new MutableBoolean(false); - Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>(); - - // get all chip IDs - mWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - chipIdsResp.value = chipIds; - } else { - Log.e(TAG, "getChipIds failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - - if (VDBG) Log.d(TAG, "getChipIds=" + chipIdsResp.value); - if (chipIdsResp.value.size() == 0) { - Log.e(TAG, "Should have at least 1 chip!"); - return null; - } - - int chipInfoIndex = 0; - WifiChipInfo[] chipsInfo = new WifiChipInfo[chipIdsResp.value.size()]; - - Mutable<IWifiChip> chipResp = new Mutable<>(); - for (Integer chipId: chipIdsResp.value) { - mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - chipResp.value = chip; - } else { - Log.e(TAG, "getChip failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - - Mutable<ArrayList<IWifiChip.ChipMode>> availableModesResp = new Mutable<>(); - chipResp.value.getAvailableModes( - (WifiStatus status, ArrayList<IWifiChip.ChipMode> modes) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - availableModesResp.value = modes; - } else { - Log.e(TAG, "getAvailableModes failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - - MutableBoolean currentModeValidResp = new MutableBoolean(false); - MutableInt currentModeResp = new MutableInt(0); - chipResp.value.getMode((WifiStatus status, int modeId) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - currentModeValidResp.value = true; - currentModeResp.value = modeId; - } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) { - statusOk.value = true; // valid response - } else { - Log.e(TAG, "getMode failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - - Mutable<ArrayList<String>> ifaceNamesResp = new Mutable<>(); - MutableInt ifaceIndex = new MutableInt(0); - - chipResp.value.getStaIfaceNames( - (WifiStatus status, ArrayList<String> ifnames) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - ifaceNamesResp.value = ifnames; - } else { - Log.e(TAG, "getStaIfaceNames failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - - WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; - for (String ifaceName: ifaceNamesResp.value) { - chipResp.value.getStaIface(ifaceName, - (WifiStatus status, IWifiStaIface iface) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.iface = iface; - staIfaces[ifaceIndex.value++] = ifaceInfo; - } else { - Log.e(TAG, "getStaIface failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - } - - ifaceIndex.value = 0; - chipResp.value.getApIfaceNames( - (WifiStatus status, ArrayList<String> ifnames) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - ifaceNamesResp.value = ifnames; - } else { - Log.e(TAG, "getApIfaceNames failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - - WifiIfaceInfo[] apIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; - for (String ifaceName: ifaceNamesResp.value) { - chipResp.value.getApIface(ifaceName, - (WifiStatus status, IWifiApIface iface) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.iface = iface; - apIfaces[ifaceIndex.value++] = ifaceInfo; - } else { - Log.e(TAG, "getApIface failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - } - - ifaceIndex.value = 0; - chipResp.value.getP2pIfaceNames( - (WifiStatus status, ArrayList<String> ifnames) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - ifaceNamesResp.value = ifnames; - } else { - Log.e(TAG, "getP2pIfaceNames failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - - WifiIfaceInfo[] p2pIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; - for (String ifaceName: ifaceNamesResp.value) { - chipResp.value.getP2pIface(ifaceName, - (WifiStatus status, IWifiP2pIface iface) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.iface = iface; - p2pIfaces[ifaceIndex.value++] = ifaceInfo; - } else { - Log.e(TAG, "getP2pIface failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - } - - ifaceIndex.value = 0; - chipResp.value.getNanIfaceNames( - (WifiStatus status, ArrayList<String> ifnames) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - ifaceNamesResp.value = ifnames; - } else { - Log.e(TAG, "getNanIfaceNames failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - - WifiIfaceInfo[] nanIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; - for (String ifaceName: ifaceNamesResp.value) { - chipResp.value.getNanIface(ifaceName, - (WifiStatus status, IWifiNanIface iface) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.iface = iface; - nanIfaces[ifaceIndex.value++] = ifaceInfo; - } else { - Log.e(TAG, "getNanIface failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - } - - WifiChipInfo chipInfo = new WifiChipInfo(); - chipsInfo[chipInfoIndex++] = chipInfo; - - chipInfo.chip = chipResp.value; - chipInfo.chipId = chipId; - chipInfo.availableModes = availableModesResp.value; - chipInfo.currentModeIdValid = currentModeValidResp.value; - chipInfo.currentModeId = currentModeResp.value; - chipInfo.ifaces[IfaceType.STA] = staIfaces; - chipInfo.ifaces[IfaceType.AP] = apIfaces; - chipInfo.ifaces[IfaceType.P2P] = p2pIfaces; - chipInfo.ifaces[IfaceType.NAN] = nanIfaces; - } - - if (mDebugChipsInfo == null) mDebugChipsInfo = chipsInfo; - return chipsInfo; - } catch (RemoteException e) { - Log.e(TAG, "getAllChipInfoAndValidateCache exception: " + e); - } - } - - return null; - } - - /** - * Checks the local state of this object (the cached state) against the input 'chipInfos' - * state (which is a live representation of the Wi-Fi firmware status - read through the HAL). - * Returns 'true' if there are no discrepancies - 'false' otherwise. - * - * A discrepancy is if any local state contains references to a chip or interface which are not - * found on the information read from the chip. - */ - private boolean validateInterfaceCache(WifiChipInfo[] chipInfos) { - if (VDBG) Log.d(TAG, "validateInterfaceCache"); - - synchronized (mLock) { - for (InterfaceCacheEntry entry: mInterfaceInfoCache.values()) { - // search for chip - WifiChipInfo matchingChipInfo = null; - for (WifiChipInfo ci: chipInfos) { - if (ci.chipId == entry.chipId) { - matchingChipInfo = ci; - break; - } - } - if (matchingChipInfo == null) { - Log.e(TAG, "validateInterfaceCache: no chip found for " + entry); - return false; - } - - // search for interface - WifiIfaceInfo[] ifaceInfoList = matchingChipInfo.ifaces[entry.type]; - if (ifaceInfoList == null) { - Log.e(TAG, "validateInterfaceCache: invalid type on entry " + entry); - return false; - } - - boolean matchFound = false; - for (WifiIfaceInfo ifaceInfo: ifaceInfoList) { - if (ifaceInfo.name.equals(entry.name)) { - matchFound = true; - break; - } - } - if (!matchFound) { - Log.e(TAG, "validateInterfaceCache: no interface found for " + entry); - return false; - } - } - } - - return true; - } - - private boolean isWifiStarted() { - if (VDBG) Log.d(TAG, "isWifiStart"); - - synchronized (mLock) { - try { - if (mWifi == null) { - Log.w(TAG, "isWifiStarted called but mWifi is null!?"); - return false; - } else { - return mWifi.isStarted(); - } - } catch (RemoteException e) { - Log.e(TAG, "isWifiStarted exception: " + e); - return false; - } - } - } - - private boolean startWifi() { - if (VDBG) Log.d(TAG, "startWifi"); - initIWifiIfNecessary(); - synchronized (mLock) { - try { - if (mWifi == null) { - Log.w(TAG, "startWifi called but mWifi is null!?"); - return false; - } else { - int triedCount = 0; - while (triedCount <= START_HAL_RETRY_TIMES) { - WifiStatus status = mWifi.start(); - if (status.code == WifiStatusCode.SUCCESS) { - initIWifiChipDebugListeners(); - managerStatusListenerDispatch(); - if (triedCount != 0) { - Log.d(TAG, "start IWifi succeeded after trying " - + triedCount + " times"); - } - return true; - } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) { - // Should retry. Hal might still be stopping. - Log.e(TAG, "Cannot start IWifi: " + statusString(status) - + ", Retrying..."); - try { - Thread.sleep(START_HAL_RETRY_INTERVAL_MS); - } catch (InterruptedException ignore) { - // no-op - } - triedCount++; - } else { - // Should not retry on other failures. - Log.e(TAG, "Cannot start IWifi: " + statusString(status)); - return false; - } - } - Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times"); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "startWifi exception: " + e); - return false; - } - } - } - - private void stopWifi() { - if (VDBG) Log.d(TAG, "stopWifi"); - - synchronized (mLock) { - try { - if (mWifi == null) { - Log.w(TAG, "stopWifi called but mWifi is null!?"); - } else { - WifiStatus status = mWifi.stop(); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "Cannot stop IWifi: " + statusString(status)); - } - - // even on failure since WTF?? - teardownInternal(); - } - } catch (RemoteException e) { - Log.e(TAG, "stopWifi exception: " + e); - } - } - } - - private class WifiEventCallback extends IWifiEventCallback.Stub { - @Override - public void onStart() throws RemoteException { - mEventHandler.post(() -> { - if (VDBG) Log.d(TAG, "IWifiEventCallback.onStart"); - // NOP: only happens in reaction to my calls - will handle directly - }); - } - - @Override - public void onStop() throws RemoteException { - mEventHandler.post(() -> { - if (VDBG) Log.d(TAG, "IWifiEventCallback.onStop"); - // NOP: only happens in reaction to my calls - will handle directly - }); - } - - @Override - public void onFailure(WifiStatus status) throws RemoteException { - mEventHandler.post(() -> { - Log.e(TAG, "IWifiEventCallback.onFailure: " + statusString(status)); - synchronized (mLock) { - teardownInternal(); - } - }); - // No need to do anything else: listeners may (will) re-start Wi-Fi - } - } - - private void managerStatusListenerDispatch() { - synchronized (mLock) { - for (ManagerStatusListenerProxy cb : mManagerStatusListeners) { - cb.trigger(); - } - } - } - - private class ManagerStatusListenerProxy extends - ListenerProxy<ManagerStatusListener> { - ManagerStatusListenerProxy(ManagerStatusListener statusListener, Handler handler) { - super(statusListener, handler, "ManagerStatusListenerProxy"); - } - - @Override - protected void action() { - mListener.onStatusChanged(); - } - } - - Set<Integer> getSupportedIfaceTypesInternal(IWifiChip chip) { - Set<Integer> results = new HashSet<>(); - - WifiChipInfo[] chipInfos = getAllChipInfo(); - if (chipInfos == null) { - Log.e(TAG, "getSupportedIfaceTypesInternal: no chip info found"); - return results; - } - - MutableInt chipIdIfProvided = new MutableInt(0); // NOT using 0 as a magic value - if (chip != null) { - MutableBoolean statusOk = new MutableBoolean(false); - try { - chip.getId((WifiStatus status, int id) -> { - if (status.code == WifiStatusCode.SUCCESS) { - chipIdIfProvided.value = id; - statusOk.value = true; - } else { - Log.e(TAG, "getSupportedIfaceTypesInternal: IWifiChip.getId() error: " - + statusString(status)); - statusOk.value = false; - } - }); - } catch (RemoteException e) { - Log.e(TAG, "getSupportedIfaceTypesInternal IWifiChip.getId() exception: " + e); - return results; - } - if (!statusOk.value) { - return results; - } - } - - for (WifiChipInfo wci: chipInfos) { - if (chip != null && wci.chipId != chipIdIfProvided.value) { - continue; - } - - for (IWifiChip.ChipMode cm: wci.availableModes) { - for (IWifiChip.ChipIfaceCombination cic: cm.availableCombinations) { - for (IWifiChip.ChipIfaceCombinationLimit cicl: cic.limits) { - for (int type: cicl.types) { - results.add(type); - } - } - } - } - } - - return results; - } - - private IWifiIface createIface(int ifaceType, InterfaceDestroyedListener destroyedListener, - Handler handler) { - if (mDbg) { - Log.d(TAG, "createIface: ifaceType=" + ifaceType); - } - - synchronized (mLock) { - WifiChipInfo[] chipInfos = getAllChipInfo(); - if (chipInfos == null) { - Log.e(TAG, "createIface: no chip info found"); - stopWifi(); // major error: shutting down - return null; - } - - if (!validateInterfaceCache(chipInfos)) { - Log.e(TAG, "createIface: local cache is invalid!"); - stopWifi(); // major error: shutting down - return null; - } - - IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, destroyedListener, - handler); - if (iface != null) { // means that some configuration has changed - if (!dispatchAvailableForRequestListeners()) { - return null; // catastrophic failure - shut down - } - } - - return iface; - } - } - - private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType, - InterfaceDestroyedListener destroyedListener, Handler handler) { - if (VDBG) { - Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos) - + ", ifaceType=" + ifaceType); - } - synchronized (mLock) { - IfaceCreationData bestIfaceCreationProposal = null; - for (WifiChipInfo chipInfo: chipInfos) { - for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) { - for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode - .availableCombinations) { - int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo); - if (VDBG) { - Log.d(TAG, chipIfaceCombo + " expands to " - + Arrays.deepToString(expandedIfaceCombos)); - } - - for (int[] expandedIfaceCombo: expandedIfaceCombos) { - IfaceCreationData currentProposal = canIfaceComboSupportRequest( - chipInfo, chipMode, expandedIfaceCombo, ifaceType); - if (compareIfaceCreationData(currentProposal, - bestIfaceCreationProposal)) { - if (VDBG) Log.d(TAG, "new proposal accepted"); - bestIfaceCreationProposal = currentProposal; - } - } - } - } - } - - if (bestIfaceCreationProposal != null) { - IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, ifaceType); - if (iface != null) { - InterfaceCacheEntry cacheEntry = new InterfaceCacheEntry(); - - cacheEntry.chip = bestIfaceCreationProposal.chipInfo.chip; - cacheEntry.chipId = bestIfaceCreationProposal.chipInfo.chipId; - cacheEntry.name = getName(iface); - cacheEntry.type = ifaceType; - if (destroyedListener != null) { - cacheEntry.destroyedListeners.add( - new InterfaceDestroyedListenerProxy( - cacheEntry.name, destroyedListener, handler)); - } - cacheEntry.creationTime = mClock.getUptimeSinceBootMillis(); - - if (mDbg) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry); - mInterfaceInfoCache.put( - Pair.create(cacheEntry.name, cacheEntry.type), cacheEntry); - return iface; - } - } - } - - return null; - } - - // similar to createIfaceIfPossible - but simpler code: not looking for best option just - // for any option (so terminates on first one). - private boolean isItPossibleToCreateIface(WifiChipInfo[] chipInfos, int ifaceType) { - if (VDBG) { - Log.d(TAG, "isItPossibleToCreateIface: chipInfos=" + Arrays.deepToString(chipInfos) - + ", ifaceType=" + ifaceType); - } - - for (WifiChipInfo chipInfo: chipInfos) { - for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) { - for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode - .availableCombinations) { - int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo); - if (VDBG) { - Log.d(TAG, chipIfaceCombo + " expands to " - + Arrays.deepToString(expandedIfaceCombos)); - } - - for (int[] expandedIfaceCombo: expandedIfaceCombos) { - if (canIfaceComboSupportRequest(chipInfo, chipMode, expandedIfaceCombo, - ifaceType) != null) { - return true; - } - } - } - } - } - - return false; - } - - /** - * Expands (or provides an alternative representation) of the ChipIfaceCombination as all - * possible combinations of interface. - * - * Returns [# of combinations][4 (IfaceType)] - * - * Note: there could be duplicates - allow (inefficient but ...). - * TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to - * provide correct hashes. - */ - private int[][] expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo) { - int numOfCombos = 1; - for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) { - for (int i = 0; i < limit.maxIfaces; ++i) { - numOfCombos *= limit.types.size(); - } - } - - int[][] expandedIfaceCombos = new int[numOfCombos][IFACE_TYPES_BY_PRIORITY.length]; - - int span = numOfCombos; // span of an individual type (or sub-tree size) - for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) { - for (int i = 0; i < limit.maxIfaces; ++i) { - span /= limit.types.size(); - for (int k = 0; k < numOfCombos; ++k) { - expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++; - } - } - } - - return expandedIfaceCombos; - } - - private class IfaceCreationData { - public WifiChipInfo chipInfo; - public int chipModeId; - public List<WifiIfaceInfo> interfacesToBeRemovedFirst; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("{chipInfo=").append(chipInfo).append(", chipModeId=").append(chipModeId) - .append(", interfacesToBeRemovedFirst=").append(interfacesToBeRemovedFirst) - .append(")"); - return sb.toString(); - } - } - - /** - * Checks whether the input chip-iface-combo can support the requested interface type: if not - * then returns null, if yes then returns information containing the list of interfaces which - * would have to be removed first before the requested interface can be created. - * - * Note: the list of interfaces to be removed is EMPTY if a chip mode change is required - in - * that case ALL the interfaces on the current chip have to be removed first. - * - * Response determined based on: - * - Mode configuration: i.e. could the mode support the interface type in principle - */ - private IfaceCreationData canIfaceComboSupportRequest(WifiChipInfo chipInfo, - IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType) { - if (VDBG) { - Log.d(TAG, "canIfaceComboSupportRequest: chipInfo=" + chipInfo + ", chipMode=" - + chipMode + ", chipIfaceCombo=" + Arrays.toString(chipIfaceCombo) - + ", ifaceType=" + ifaceType); - } - - // short-circuit: does the chipIfaceCombo even support the requested type? - if (chipIfaceCombo[ifaceType] == 0) { - if (VDBG) Log.d(TAG, "Requested type not supported by combo"); - return null; - } - - boolean isChipModeChangeProposed = - chipInfo.currentModeIdValid && chipInfo.currentModeId != chipMode.id; - - // short-circuit: can't change chip-mode if an existing interface on this chip has a higher - // priority than the requested interface - if (isChipModeChangeProposed) { - for (int type: IFACE_TYPES_BY_PRIORITY) { - if (chipInfo.ifaces[type].length != 0) { - if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType, - chipInfo.ifaces, chipInfo.ifaces[type].length)) { - if (VDBG) { - Log.d(TAG, "Couldn't delete existing type " + type - + " interfaces for requested type"); - } - return null; - } - } - } - - // but if priority allows the mode change then we're good to go - IfaceCreationData ifaceCreationData = new IfaceCreationData(); - ifaceCreationData.chipInfo = chipInfo; - ifaceCreationData.chipModeId = chipMode.id; - - return ifaceCreationData; - } - - // possibly supported - List<WifiIfaceInfo> interfacesToBeRemovedFirst = new ArrayList<>(); - - for (int type: IFACE_TYPES_BY_PRIORITY) { - int tooManyInterfaces = chipInfo.ifaces[type].length - chipIfaceCombo[type]; - - // need to count the requested interface as well - if (type == ifaceType) { - tooManyInterfaces += 1; - } - - if (tooManyInterfaces > 0) { // may need to delete some - if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType, chipInfo.ifaces, - tooManyInterfaces)) { - if (VDBG) { - Log.d(TAG, "Would need to delete some higher priority interfaces"); - } - return null; - } - - // delete the most recently created interfaces - interfacesToBeRemovedFirst.addAll(selectInterfacesToDelete(tooManyInterfaces, - chipInfo.ifaces[type])); - } - } - - IfaceCreationData ifaceCreationData = new IfaceCreationData(); - ifaceCreationData.chipInfo = chipInfo; - ifaceCreationData.chipModeId = chipMode.id; - ifaceCreationData.interfacesToBeRemovedFirst = interfacesToBeRemovedFirst; - - return ifaceCreationData; - } - - /** - * Compares two options to create an interface and determines which is the 'best'. Returns - * true if proposal 1 (val1) is better, other false. - * - * Note: both proposals are 'acceptable' bases on priority criteria. - * - * Criteria: - * - Proposal is better if it means removing fewer high priority interfaces - */ - private boolean compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2) { - if (VDBG) Log.d(TAG, "compareIfaceCreationData: val1=" + val1 + ", val2=" + val2); - - // deal with trivial case of one or the other being null - if (val1 == null) { - return false; - } else if (val2 == null) { - return true; - } - - for (int type: IFACE_TYPES_BY_PRIORITY) { - // # of interfaces to be deleted: the list or all interfaces of the type if mode change - int numIfacesToDelete1 = 0; - if (val1.chipInfo.currentModeIdValid - && val1.chipInfo.currentModeId != val1.chipModeId) { - numIfacesToDelete1 = val1.chipInfo.ifaces[type].length; - } else { - numIfacesToDelete1 = val1.interfacesToBeRemovedFirst.size(); - } - - int numIfacesToDelete2 = 0; - if (val2.chipInfo.currentModeIdValid - && val2.chipInfo.currentModeId != val2.chipModeId) { - numIfacesToDelete2 = val2.chipInfo.ifaces[type].length; - } else { - numIfacesToDelete2 = val2.interfacesToBeRemovedFirst.size(); - } - - if (numIfacesToDelete1 < numIfacesToDelete2) { - if (VDBG) { - Log.d(TAG, "decision based on type=" + type + ": " + numIfacesToDelete1 - + " < " + numIfacesToDelete2); - } - return true; - } - } - - // arbitrary - flip a coin - if (VDBG) Log.d(TAG, "proposals identical - flip a coin"); - return false; - } - - /** - * Returns true if we're allowed to delete the existing interface type for the requested - * interface type. - * - * Rules - applies in order: - * - * General rules: - * 1. No interface will be destroyed for a requested interface of the same type - * 2. No interface will be destroyed if one of the requested interfaces already exists - * 3. If there are >1 interface of an existing type, then it is ok to destroy that type - * interface - * - * Type-specific rules (but note that the general rules are appied first): - * 4. Request for AP or STA will destroy any other interface - * 5. Request for P2P will destroy NAN-only (but will destroy a second STA per #3) - * 6. Request for NAN will destroy P2P-only (but will destroy a second STA per #3) - * - * Note: the 'numNecessaryInterfaces' is used to specify how many interfaces would be needed to - * be deleted. This is used to determine whether there are that many low priority interfaces - * of the requested type to delete. - */ - private boolean allowedToDeleteIfaceTypeForRequestedType(int existingIfaceType, - int requestedIfaceType, WifiIfaceInfo[][] currentIfaces, int numNecessaryInterfaces) { - // rule 1 - if (existingIfaceType == requestedIfaceType) { - return false; - } - - // rule 2 - if (currentIfaces[requestedIfaceType].length != 0) { - return false; - } - - // rule 3 - if (currentIfaces[existingIfaceType].length > 1) { - return true; - } - - // rule 5 - if (requestedIfaceType == IfaceType.P2P) { - return existingIfaceType == IfaceType.NAN; - } - - // rule 6 - if (requestedIfaceType == IfaceType.NAN) { - return existingIfaceType == IfaceType.P2P; - } - - // rule 4, the requestIfaceType is either AP or STA - return true; - } - - /** - * Selects the interfaces to delete. - * - * Rule: select low priority interfaces and then other interfaces in order of creation time. - * - * @param excessInterfaces Number of interfaces which need to be selected. - * @param interfaces Array of interfaces. - */ - private List<WifiIfaceInfo> selectInterfacesToDelete(int excessInterfaces, - WifiIfaceInfo[] interfaces) { - if (VDBG) { - Log.d(TAG, "selectInterfacesToDelete: excessInterfaces=" + excessInterfaces - + ", interfaces=" + Arrays.toString(interfaces)); - } - - boolean lookupError = false; - LongSparseArray<WifiIfaceInfo> orderedList = new LongSparseArray<>(); - for (WifiIfaceInfo info : interfaces) { - InterfaceCacheEntry cacheEntry; - synchronized (mLock) { - cacheEntry = mInterfaceInfoCache.get(Pair.create(info.name, getType(info.iface))); - } - if (cacheEntry == null) { - Log.e(TAG, - "selectInterfacesToDelete: can't find cache entry with name=" + info.name); - lookupError = true; - break; - } - orderedList.append(cacheEntry.creationTime, info); - } - - if (lookupError) { - Log.e(TAG, "selectInterfacesToDelete: falling back to arbitrary selection"); - return Arrays.asList(Arrays.copyOf(interfaces, excessInterfaces)); - } else { - List<WifiIfaceInfo> result = new ArrayList<>(excessInterfaces); - for (int i = 0; i < excessInterfaces; ++i) { - result.add(orderedList.valueAt(orderedList.size() - i - 1)); - } - return result; - } - } - - /** - * Checks whether the input chip-iface-combo can support the requested interface type. - */ - private boolean canIfaceComboSupportRequestedIfaceCombo( - int[] chipIfaceCombo, int[] requestedIfaceCombo) { - if (VDBG) { - Log.d(TAG, "canIfaceComboSupportRequest: chipIfaceCombo=" + chipIfaceCombo - + ", requestedIfaceCombo=" + requestedIfaceCombo); - } - for (int ifaceType : IFACE_TYPES_BY_PRIORITY) { - if (chipIfaceCombo[ifaceType] < requestedIfaceCombo[ifaceType]) { - if (VDBG) Log.d(TAG, "Requested type not supported by combo"); - return false; - } - } - return true; - } - - // Is it possible to create iface combo just looking at the device capabilities. - private boolean isItPossibleToCreateIfaceCombo(WifiChipInfo[] chipInfos, int[] ifaceCombo) { - if (VDBG) { - Log.d(TAG, "isItPossibleToCreateIfaceCombo: chipInfos=" + Arrays.deepToString(chipInfos) - + ", ifaceType=" + ifaceCombo); - } - - for (WifiChipInfo chipInfo: chipInfos) { - for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) { - for (IWifiChip.ChipIfaceCombination chipIfaceCombo - : chipMode.availableCombinations) { - int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo); - if (VDBG) { - Log.d(TAG, chipIfaceCombo + " expands to " - + Arrays.deepToString(expandedIfaceCombos)); - } - - for (int[] expandedIfaceCombo: expandedIfaceCombos) { - if (canIfaceComboSupportRequestedIfaceCombo( - expandedIfaceCombo, ifaceCombo)) { - return true; - } - } - } - } - } - return false; - } - - /** - * Performs chip reconfiguration per the input: - * - Removes the specified interfaces - * - Reconfigures the chip to the new chip mode (if necessary) - * - Creates the new interface - * - * Returns the newly created interface or a null on any error. - */ - private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData, - int ifaceType) { - if (mDbg) { - Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData - + ", ifaceType=" + ifaceType); - } - synchronized (mLock) { - try { - // is this a mode change? - boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid - || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId; - if (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded); - - // first delete interfaces/change modes - if (isModeConfigNeeded) { - // remove all interfaces pre mode-change - // TODO: is this necessary? note that even if we don't want to explicitly - // remove the interfaces we do need to call the onDeleted callbacks - which - // this does - for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) { - for (WifiIfaceInfo ifaceInfo: ifaceInfos) { - removeIfaceInternal(ifaceInfo.iface); // ignore return value - } - } - - WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip( - ifaceCreationData.chipModeId); - updateRttControllerOnModeChange(); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "executeChipReconfiguration: configureChip error: " - + statusString(status)); - return null; - } - } else { - // remove all interfaces on the delete list - for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) { - removeIfaceInternal(ifaceInfo.iface); // ignore return value - } - } - - // create new interface - Mutable<WifiStatus> statusResp = new Mutable<>(); - Mutable<IWifiIface> ifaceResp = new Mutable<>(); - switch (ifaceType) { - case IfaceType.STA: - ifaceCreationData.chipInfo.chip.createStaIface( - (WifiStatus status, IWifiStaIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - break; - case IfaceType.AP: - ifaceCreationData.chipInfo.chip.createApIface( - (WifiStatus status, IWifiApIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - break; - case IfaceType.P2P: - ifaceCreationData.chipInfo.chip.createP2pIface( - (WifiStatus status, IWifiP2pIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - break; - case IfaceType.NAN: - ifaceCreationData.chipInfo.chip.createNanIface( - (WifiStatus status, IWifiNanIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - break; - } - - if (statusResp.value.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "executeChipReconfiguration: failed to create interface ifaceType=" - + ifaceType + ": " + statusString(statusResp.value)); - return null; - } - - return ifaceResp.value; - } catch (RemoteException e) { - Log.e(TAG, "executeChipReconfiguration exception: " + e); - return null; - } - } - } - - private boolean removeIfaceInternal(IWifiIface iface) { - String name = getName(iface); - int type = getType(iface); - if (mDbg) Log.d(TAG, "removeIfaceInternal: iface(name)=" + name + ", type=" + type); - - if (type == -1) { - Log.e(TAG, "removeIfaceInternal: can't get type -- iface(name)=" + name); - return false; - } - - synchronized (mLock) { - if (mWifi == null) { - Log.e(TAG, "removeIfaceInternal: null IWifi -- iface(name)=" + name); - return false; - } - - IWifiChip chip = getChip(iface); - if (chip == null) { - Log.e(TAG, "removeIfaceInternal: null IWifiChip -- iface(name)=" + name); - return false; - } - - if (name == null) { - Log.e(TAG, "removeIfaceInternal: can't get name"); - return false; - } - - WifiStatus status = null; - try { - switch (type) { - case IfaceType.STA: - status = chip.removeStaIface(name); - break; - case IfaceType.AP: - status = chip.removeApIface(name); - break; - case IfaceType.P2P: - status = chip.removeP2pIface(name); - break; - case IfaceType.NAN: - status = chip.removeNanIface(name); - break; - default: - Log.wtf(TAG, "removeIfaceInternal: invalid type=" + type); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "IWifiChip.removeXxxIface exception: " + e); - } - - // dispatch listeners no matter what status - dispatchDestroyedListeners(name, type); - - if (status != null && status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "IWifiChip.removeXxxIface failed: " + statusString(status)); - return false; - } - } - } - - // dispatch all available for request listeners of the specified type AND clean-out the list: - // listeners are called once at most! - private boolean dispatchAvailableForRequestListeners() { - if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListeners"); - - synchronized (mLock) { - WifiChipInfo[] chipInfos = getAllChipInfo(); - if (chipInfos == null) { - Log.e(TAG, "dispatchAvailableForRequestListeners: no chip info found"); - stopWifi(); // major error: shutting down - return false; - } - if (VDBG) { - Log.d(TAG, "dispatchAvailableForRequestListeners: chipInfos=" - + Arrays.deepToString(chipInfos)); - } - - for (int ifaceType : IFACE_TYPES_BY_PRIORITY) { - dispatchAvailableForRequestListenersForType(ifaceType, chipInfos); - } - } - - return true; - } - - - private void dispatchAvailableForRequestListenersForType(int ifaceType, - WifiChipInfo[] chipInfos) { - if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListenersForType: ifaceType=" + ifaceType); - - synchronized (mLock) { - Map<InterfaceAvailableForRequestListenerProxy, Boolean> listeners = - mInterfaceAvailableForRequestListeners.get(ifaceType); - - if (listeners.size() == 0) { - return; - } - - boolean isAvailable = isItPossibleToCreateIface(chipInfos, ifaceType); - - if (VDBG) { - Log.d(TAG, "Interface available for: ifaceType=" + ifaceType + " = " + isAvailable); - } - for (Map.Entry<InterfaceAvailableForRequestListenerProxy, Boolean> listenerEntry : - listeners.entrySet()) { - if (listenerEntry.getValue() == null || listenerEntry.getValue() != isAvailable) { - if (VDBG) { - Log.d(TAG, "Interface available listener dispatched: ifaceType=" + ifaceType - + ", listener=" + listenerEntry.getKey()); - } - listenerEntry.getKey().triggerWithArg(isAvailable); - } - listenerEntry.setValue(isAvailable); - } - } - } - - // dispatch all destroyed listeners registered for the specified interface AND remove the - // cache entry - private void dispatchDestroyedListeners(String name, int type) { - if (VDBG) Log.d(TAG, "dispatchDestroyedListeners: iface(name)=" + name); - - synchronized (mLock) { - InterfaceCacheEntry entry = mInterfaceInfoCache.get(Pair.create(name, type)); - if (entry == null) { - Log.e(TAG, "dispatchDestroyedListeners: no cache entry for iface(name)=" + name); - return; - } - - for (InterfaceDestroyedListenerProxy listener : entry.destroyedListeners) { - listener.trigger(); - } - entry.destroyedListeners.clear(); // for insurance (though cache entry is removed) - mInterfaceInfoCache.remove(Pair.create(name, type)); - } - } - - // dispatch all destroyed listeners registered to all interfaces - private void dispatchAllDestroyedListeners() { - if (VDBG) Log.d(TAG, "dispatchAllDestroyedListeners"); - - List<InterfaceDestroyedListenerProxy> triggerList = new ArrayList<>(); - synchronized (mLock) { - for (InterfaceCacheEntry cacheEntry: mInterfaceInfoCache.values()) { - for (InterfaceDestroyedListenerProxy listener : cacheEntry.destroyedListeners) { - triggerList.add(listener); - } - cacheEntry.destroyedListeners.clear(); // for insurance - } - mInterfaceInfoCache.clear(); - } - - for (InterfaceDestroyedListenerProxy listener : triggerList) { - listener.trigger(); - } - } - - private abstract class ListenerProxy<LISTENER> { - protected LISTENER mListener; - private Handler mHandler; - - // override equals & hash to make sure that the container HashSet is unique with respect to - // the contained listener - @Override - public boolean equals(Object obj) { - return mListener == ((ListenerProxy<LISTENER>) obj).mListener; - } - - @Override - public int hashCode() { - return mListener.hashCode(); - } - - void trigger() { - if (mHandler != null) { - mHandler.post(() -> { - action(); - }); - } else { - action(); - } - } - - void triggerWithArg(boolean arg) { - if (mHandler != null) { - mHandler.post(() -> { - actionWithArg(arg); - }); - } else { - actionWithArg(arg); - } - } - - protected void action() {} - protected void actionWithArg(boolean arg) {} - - ListenerProxy(LISTENER listener, Handler handler, String tag) { - mListener = listener; - mHandler = handler; - } - } - - private class InterfaceDestroyedListenerProxy extends - ListenerProxy<InterfaceDestroyedListener> { - private final String mIfaceName; - InterfaceDestroyedListenerProxy(@NonNull String ifaceName, - InterfaceDestroyedListener destroyedListener, - Handler handler) { - super(destroyedListener, handler, "InterfaceDestroyedListenerProxy"); - mIfaceName = ifaceName; - } - - @Override - protected void action() { - mListener.onDestroyed(mIfaceName); - } - } - - private class InterfaceAvailableForRequestListenerProxy extends - ListenerProxy<InterfaceAvailableForRequestListener> { - InterfaceAvailableForRequestListenerProxy( - InterfaceAvailableForRequestListener destroyedListener, Handler handler) { - super(destroyedListener, handler, "InterfaceAvailableForRequestListenerProxy"); - } - - @Override - protected void actionWithArg(boolean isAvailable) { - mListener.onAvailabilityChanged(isAvailable); - } - } - - private class InterfaceRttControllerLifecycleCallbackProxy implements - InterfaceRttControllerLifecycleCallback { - private InterfaceRttControllerLifecycleCallback mCallback; - private Handler mHandler; - - InterfaceRttControllerLifecycleCallbackProxy( - InterfaceRttControllerLifecycleCallback callback, Handler handler) { - mCallback = callback; - mHandler = handler; - } - - // override equals & hash to make sure that the container HashSet is unique with respect to - // the contained listener - @Override - public boolean equals(Object obj) { - return mCallback == ((InterfaceRttControllerLifecycleCallbackProxy) obj).mCallback; - } - - @Override - public int hashCode() { - return mCallback.hashCode(); - } - - @Override - public void onNewRttController(IWifiRttController controller) { - mHandler.post(() -> mCallback.onNewRttController(controller)); - } - - @Override - public void onRttControllerDestroyed() { - mHandler.post(() -> mCallback.onRttControllerDestroyed()); - } - } - - private void dispatchRttControllerLifecycleOnNew() { - if (VDBG) { - Log.v(TAG, "dispatchRttControllerLifecycleOnNew: # cbs=" - + mRttControllerLifecycleCallbacks.size()); - } - for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { - cbp.onNewRttController(mIWifiRttController); - } - } - - private void dispatchRttControllerLifecycleOnDestroyed() { - for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { - cbp.onRttControllerDestroyed(); - } - } - - - /** - * Updates the RttController when the chip mode is changed: - * - Handles callbacks to registered listeners - * - Handles creation of new RttController - */ - private void updateRttControllerOnModeChange() { - synchronized (mLock) { - boolean controllerDestroyed = mIWifiRttController != null; - mIWifiRttController = null; - if (mRttControllerLifecycleCallbacks.size() == 0) { - Log.d(TAG, "updateRttController: no one is interested in RTT controllers"); - return; - } - - IWifiRttController newRttController = createRttControllerIfPossible(); - if (newRttController == null) { - if (controllerDestroyed) { - dispatchRttControllerLifecycleOnDestroyed(); - } - } else { - mIWifiRttController = newRttController; - dispatchRttControllerLifecycleOnNew(); - } - } - } - - /** - * Try to create a new RttController. - * - * @return The new RttController - or null on failure. - */ - private IWifiRttController createRttControllerIfPossible() { - synchronized (mLock) { - if (!isWifiStarted()) { - Log.d(TAG, "createRttControllerIfPossible: Wifi is not started"); - return null; - } - - WifiChipInfo[] chipInfos = getAllChipInfo(); - if (chipInfos == null) { - Log.d(TAG, "createRttControllerIfPossible: no chip info found - most likely chip " - + "not up yet"); - return null; - } - - for (WifiChipInfo chipInfo : chipInfos) { - if (!chipInfo.currentModeIdValid) { - if (VDBG) { - Log.d(TAG, "createRttControllerIfPossible: chip not configured yet: " - + chipInfo); - } - continue; - } - - Mutable<IWifiRttController> rttResp = new Mutable<>(); - try { - android.hardware.wifi.V1_4.IWifiChip chip14 = - android.hardware.wifi.V1_4.IWifiChip.castFrom(chipInfo.chip); - if (chip14 != null) { - chip14.createRttController_1_4(null, - (WifiStatus status, - android.hardware.wifi.V1_4.IWifiRttController rtt) -> { - if (status.code == WifiStatusCode.SUCCESS) { - rttResp.value = rtt; - } else { - Log.e(TAG, "IWifiChip.createRttController_1_4 failed: " - + statusString(status)); - } - }); - } else { - chipInfo.chip.createRttController(null, - (WifiStatus status, IWifiRttController rtt) -> { - if (status.code == WifiStatusCode.SUCCESS) { - rttResp.value = rtt; - } else { - Log.e(TAG, "IWifiChip.createRttController failed: " - + statusString(status)); - } - }); - } - } catch (RemoteException e) { - Log.e(TAG, "IWifiChip.createRttController exception: " + e); - } - if (rttResp.value != null) { - return rttResp.value; - } - } - } - - Log.w(TAG, "createRttControllerIfPossible: not available from any of the chips"); - return null; - } - - // general utilities - - private static String statusString(WifiStatus status) { - if (status == null) { - return "status=null"; - } - StringBuilder sb = new StringBuilder(); - sb.append(status.code).append(" (").append(status.description).append(")"); - return sb.toString(); - } - - // Will return -1 for invalid results! Otherwise will return one of the 4 valid values. - private static int getType(IWifiIface iface) { - MutableInt typeResp = new MutableInt(-1); - try { - iface.getType((WifiStatus status, int type) -> { - if (status.code == WifiStatusCode.SUCCESS) { - typeResp.value = type; - } else { - Log.e(TAG, "Error on getType: " + statusString(status)); - } - }); - } catch (RemoteException e) { - Log.e(TAG, "Exception on getType: " + e); - } - - return typeResp.value; - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("HalDeviceManager:"); - pw.println(" mServiceManager: " + mServiceManager); - pw.println(" mWifi: " + mWifi); - pw.println(" mManagerStatusListeners: " + mManagerStatusListeners); - pw.println(" mInterfaceAvailableForRequestListeners: " - + mInterfaceAvailableForRequestListeners); - pw.println(" mInterfaceInfoCache: " + mInterfaceInfoCache); - pw.println(" mDebugChipsInfo: " + Arrays.toString(mDebugChipsInfo)); - } -} diff --git a/service/java/com/android/server/wifi/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java deleted file mode 100644 index 1ff8368e3..000000000 --- a/service/java/com/android/server/wifi/HostapdHal.java +++ /dev/null @@ -1,1067 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - - -import android.annotation.NonNull; -import android.content.Context; -import android.hardware.wifi.hostapd.V1_0.HostapdStatus; -import android.hardware.wifi.hostapd.V1_0.HostapdStatusCode; -import android.hardware.wifi.hostapd.V1_0.IHostapd; -import android.hardware.wifi.hostapd.V1_2.DebugLevel; -import android.hardware.wifi.hostapd.V1_2.Ieee80211ReasonCode; -import android.hidl.manager.V1_0.IServiceManager; -import android.hidl.manager.V1_0.IServiceNotification; -import android.net.MacAddress; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApConfiguration.BandType; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.IHwBinder.DeathRecipient; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.WifiNative.HostapdDeathEventHandler; -import com.android.server.wifi.util.ApConfigUtil; -import com.android.server.wifi.util.NativeUtil; -import com.android.wifi.resources.R; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Random; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import javax.annotation.concurrent.ThreadSafe; - -/** - * To maintain thread-safety, the locking protocol is that every non-static method (regardless of - * access level) acquires mLock. - */ -@ThreadSafe -public class HostapdHal { - private static final String TAG = "HostapdHal"; - @VisibleForTesting - public static final String HAL_INSTANCE_NAME = "default"; - @VisibleForTesting - public static final long WAIT_FOR_DEATH_TIMEOUT_MS = 50L; - - private final Object mLock = new Object(); - private boolean mVerboseLoggingEnabled = false; - private final Context mContext; - private final Handler mEventHandler; - private boolean mForceApChannel = false; - private int mForcedApBand; - private int mForcedApChannel; - private String mConfig2gChannelList; - private String mConfig5gChannelList; - private String mConfig6gChannelList; - - // Hostapd HAL interface objects - private IServiceManager mIServiceManager = null; - private IHostapd mIHostapd; - private HashMap<String, Runnable> mSoftApFailureListeners = new HashMap<>(); - private HostapdDeathEventHandler mDeathEventHandler; - private ServiceManagerDeathRecipient mServiceManagerDeathRecipient; - private HostapdDeathRecipient mHostapdDeathRecipient; - // Death recipient cookie registered for current supplicant instance. - private long mDeathRecipientCookie = 0; - - private final IServiceNotification mServiceNotificationCallback = - new IServiceNotification.Stub() { - public void onRegistration(String fqName, String name, boolean preexisting) { - synchronized (mLock) { - if (mVerboseLoggingEnabled) { - Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName - + ", " + name + " preexisting=" + preexisting); - } - if (!initHostapdService()) { - Log.e(TAG, "initalizing IHostapd failed."); - hostapdServiceDiedHandler(mDeathRecipientCookie); - } else { - Log.i(TAG, "Completed initialization of IHostapd."); - } - } - } - }; - private class ServiceManagerDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - synchronized (mLock) { - Log.w(TAG, "IServiceManager died: cookie=" + cookie); - hostapdServiceDiedHandler(mDeathRecipientCookie); - mIServiceManager = null; // Will need to register a new ServiceNotification - } - }); - } - } - private class HostapdDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - synchronized (mLock) { - Log.w(TAG, "IHostapd/IHostapd died: cookie=" + cookie); - hostapdServiceDiedHandler(cookie); - } - }); - } - } - - public HostapdHal(Context context, Handler handler) { - mContext = context; - mEventHandler = handler; - mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient(); - mHostapdDeathRecipient = new HostapdDeathRecipient(); - } - - /** - * Enable/Disable verbose logging. - * - * @param enable true to enable, false to disable. - */ - void enableVerboseLogging(boolean enable) { - synchronized (mLock) { - mVerboseLoggingEnabled = enable; - setLogLevel(); - } - } - - /** - * Uses the IServiceManager to check if the device is running V1_1 of the HAL from the VINTF for - * the device. - * @return true if supported, false otherwise. - */ - private boolean isV1_1() { - return checkHalVersionByInterfaceName( - android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName); - } - - /** - * Uses the IServiceManager to check if the device is running V1_2 of the HAL from the VINTF for - * the device. - * @return true if supported, false otherwise. - */ - private boolean isV1_2() { - return checkHalVersionByInterfaceName( - android.hardware.wifi.hostapd.V1_2.IHostapd.kInterfaceName); - } - - private boolean checkHalVersionByInterfaceName(String interfaceName) { - if (interfaceName == null) { - return false; - } - synchronized (mLock) { - if (mIServiceManager == null) { - Log.e(TAG, "checkHalVersionByInterfaceName called but mServiceManager is null!?"); - return false; - } - try { - return (mIServiceManager.getTransport( - interfaceName, - HAL_INSTANCE_NAME) - != IServiceManager.Transport.EMPTY); - } catch (RemoteException e) { - Log.e(TAG, "Exception while operating on IServiceManager: " + e); - handleRemoteException(e, "getTransport"); - return false; - } - } - } - - /** - * Link to death for IServiceManager object. - * @return true on success, false otherwise. - */ - private boolean linkToServiceManagerDeath() { - synchronized (mLock) { - if (mIServiceManager == null) return false; - try { - if (!mIServiceManager.linkToDeath(mServiceManagerDeathRecipient, 0)) { - Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); - hostapdServiceDiedHandler(mDeathRecipientCookie); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "IServiceManager.linkToDeath exception", e); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - return true; - } - } - - /** - * Registers a service notification for the IHostapd service, which triggers intialization of - * the IHostapd - * @return true if the service notification was successfully registered - */ - public boolean initialize() { - synchronized (mLock) { - if (mVerboseLoggingEnabled) { - Log.i(TAG, "Registering IHostapd service ready callback."); - } - mIHostapd = null; - if (mIServiceManager != null) { - // Already have an IServiceManager and serviceNotification registered, don't - // don't register another. - return true; - } - try { - mIServiceManager = getServiceManagerMockable(); - if (mIServiceManager == null) { - Log.e(TAG, "Failed to get HIDL Service Manager"); - return false; - } - if (!linkToServiceManagerDeath()) { - return false; - } - /* TODO(b/33639391) : Use the new IHostapd.registerForNotifications() once it - exists */ - if (!mIServiceManager.registerForNotifications( - IHostapd.kInterfaceName, "", mServiceNotificationCallback)) { - Log.e(TAG, "Failed to register for notifications to " - + IHostapd.kInterfaceName); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "Exception while trying to register a listener for IHostapd service: " - + e); - hostapdServiceDiedHandler(mDeathRecipientCookie); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - return true; - } - } - - /** - * Link to death for IHostapd object. - * @return true on success, false otherwise. - */ - private boolean linkToHostapdDeath(DeathRecipient deathRecipient, long cookie) { - synchronized (mLock) { - if (mIHostapd == null) return false; - try { - if (!mIHostapd.linkToDeath(deathRecipient, cookie)) { - Log.wtf(TAG, "Error on linkToDeath on IHostapd"); - hostapdServiceDiedHandler(mDeathRecipientCookie); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "IHostapd.linkToDeath exception", e); - return false; - } - return true; - } - } - - private boolean registerCallback( - android.hardware.wifi.hostapd.V1_1.IHostapdCallback callback) { - synchronized (mLock) { - String methodStr = "registerCallback_1_1"; - try { - android.hardware.wifi.hostapd.V1_1.IHostapd iHostapdV1_1 = getHostapdMockableV1_1(); - if (iHostapdV1_1 == null) return false; - HostapdStatus status = iHostapdV1_1.registerCallback(callback); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Initialize the IHostapd object. - * @return true on success, false otherwise. - */ - private boolean initHostapdService() { - synchronized (mLock) { - try { - mIHostapd = getHostapdMockable(); - } catch (RemoteException e) { - Log.e(TAG, "IHostapd.getService exception: " + e); - return false; - } catch (NoSuchElementException e) { - Log.e(TAG, "IHostapd.getService exception: " + e); - return false; - } - if (mIHostapd == null) { - Log.e(TAG, "Got null IHostapd service. Stopping hostapd HIDL startup"); - return false; - } - if (!linkToHostapdDeath(mHostapdDeathRecipient, ++mDeathRecipientCookie)) { - Log.e(TAG, "Fail to link to Hostapd Death, Stopping hostapd HIDL startup"); - mIHostapd = null; - return false; - } - // Register for callbacks for 1.1 hostapd. - if (isV1_1() && !registerCallback(new HostapdCallback())) { - Log.e(TAG, "Fail to regiester Callback, Stopping hostapd HIDL startup"); - mIHostapd = null; - return false; - } - - // Setup log level - setLogLevel(); - } - return true; - } - - /** - * Enable force-soft-AP-channel mode which takes effect when soft AP starts next time - * @param forcedApChannel The forced IEEE channel number - */ - void enableForceSoftApChannel(int forcedApChannel, int forcedApBand) { - mForceApChannel = true; - mForcedApChannel = forcedApChannel; - mForcedApBand = forcedApBand; - } - - /** - * Disable force-soft-AP-channel mode which take effect when soft AP starts next time - */ - void disableForceSoftApChannel() { - mForceApChannel = false; - } - - private boolean isSendFreqRangesNeeded(@BandType int band) { - // Fist we check if one of the selected bands has restrictions in the overlay file. - // Note, - // - We store the config string here for future use, hence we need to check all bands. - // - If there is no OEM restriction, we store the full band - boolean retVal = false; - if ((band & SoftApConfiguration.BAND_2GHZ) != 0) { - mConfig2gChannelList = - mContext.getResources().getString(R.string.config_wifiSoftap2gChannelList); - if (TextUtils.isEmpty(mConfig2gChannelList)) { - mConfig2gChannelList = "1-14"; - } else { - retVal = true; - } - } - - if ((band & SoftApConfiguration.BAND_5GHZ) != 0) { - mConfig5gChannelList = - mContext.getResources().getString(R.string.config_wifiSoftap5gChannelList); - if (TextUtils.isEmpty(mConfig5gChannelList)) { - mConfig5gChannelList = "34-173"; - } else { - retVal = true; - } - } - - if ((band & SoftApConfiguration.BAND_6GHZ) != 0) { - mConfig6gChannelList = - mContext.getResources().getString(R.string.config_wifiSoftap6gChannelList); - if (TextUtils.isEmpty(mConfig6gChannelList)) { - mConfig6gChannelList = "1-254"; - } else { - retVal = true; - } - } - - // If any of the selected band has restriction in the overlay file, we return true. - if (retVal) { - return true; - } - - // Next, if only one of 5G or 6G is selected, then we need freqList to separate them - // Since there is no other way. - if (((band & SoftApConfiguration.BAND_5GHZ) != 0) - && ((band & SoftApConfiguration.BAND_6GHZ) == 0)) { - return true; - } - if (((band & SoftApConfiguration.BAND_5GHZ) == 0) - && ((band & SoftApConfiguration.BAND_6GHZ) != 0)) { - return true; - } - - // In all other cases, we don't need to set the freqList - return false; - } - - /** - * Add and start a new access point. - * - * @param ifaceName Name of the interface. - * @param config Configuration to use for the AP. - * @param onFailureListener A runnable to be triggered on failure. - * @return true on success, false otherwise. - */ - public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config, - @NonNull Runnable onFailureListener) { - synchronized (mLock) { - final String methodStr = "addAccessPoint"; - IHostapd.IfaceParams ifaceParams = new IHostapd.IfaceParams(); - ifaceParams.ifaceName = ifaceName; - ifaceParams.hwModeParams.enable80211N = true; - ifaceParams.hwModeParams.enable80211AC = - mContext.getResources().getBoolean( - R.bool.config_wifi_softap_ieee80211ac_supported); - int band; - boolean enableAcs = ApConfigUtil.isAcsSupported(mContext) && config.getChannel() == 0 - && !mForceApChannel; - if (enableAcs) { - ifaceParams.channelParams.enableAcs = true; - ifaceParams.channelParams.acsShouldExcludeDfs = !mContext.getResources() - .getBoolean(R.bool.config_wifiSoftapAcsIncludeDfs); - } - ifaceParams.channelParams.channel = - mForceApChannel ? mForcedApChannel : config.getChannel(); - band = mForceApChannel ? mForcedApBand : config.getBand(); - - android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams nwParamsV1_2 = - prepareNetworkParams(config); - if (nwParamsV1_2 == null) return false; - if (!checkHostapdAndLogFailure(methodStr)) return false; - try { - HostapdStatus status; - if (!isV1_1() && !isV1_2()) { - ifaceParams.channelParams.band = getHalBand(band); - status = mIHostapd.addAccessPoint(ifaceParams, nwParamsV1_2.V1_0); - if (!checkStatusAndLogFailure(status, methodStr)) { - return false; - } - } else { - android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams ifaceParams1_1 = - new android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams(); - ifaceParams1_1.V1_0 = ifaceParams; - if (!isV1_2()) { - ifaceParams.channelParams.band = getHalBand(band); - - if (ifaceParams.channelParams.enableAcs) { - if ((band & SoftApConfiguration.BAND_2GHZ) != 0) { - ifaceParams1_1.channelParams.acsChannelRanges.addAll( - toAcsChannelRanges(mContext.getResources().getString( - R.string.config_wifiSoftap2gChannelList))); - } - if ((band & SoftApConfiguration.BAND_5GHZ) != 0) { - ifaceParams1_1.channelParams.acsChannelRanges.addAll( - toAcsChannelRanges(mContext.getResources().getString( - R.string.config_wifiSoftap5gChannelList))); - } - } - - android.hardware.wifi.hostapd.V1_1.IHostapd iHostapdV1_1 = - getHostapdMockableV1_1(); - if (iHostapdV1_1 == null) return false; - - status = iHostapdV1_1.addAccessPoint_1_1(ifaceParams1_1, nwParamsV1_2.V1_0); - if (!checkStatusAndLogFailure(status, methodStr)) { - return false; - } - } else { - android.hardware.wifi.hostapd.V1_2.HostapdStatus status12; - android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams ifaceParams1_2 = - new android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams(); - ifaceParams1_2.V1_1 = ifaceParams1_1; - - ifaceParams1_2.hwModeParams.enable80211AX = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapIeee80211axSupported); - ifaceParams1_2.hwModeParams.enable6GhzBand = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftap6ghzSupported); - ifaceParams1_2.hwModeParams.enableHeSingleUserBeamformer = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapHeSuBeamformerSupported); - ifaceParams1_2.hwModeParams.enableHeSingleUserBeamformee = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapHeSuBeamformeeSupported); - ifaceParams1_2.hwModeParams.enableHeMultiUserBeamformer = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapHeMuBeamformerSupported); - ifaceParams1_2.hwModeParams.enableHeTargetWakeTime = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapHeTwtSupported); - ifaceParams1_2.channelParams.bandMask = getHalBandMask(band); - - // Prepare freq ranges/lists if needed - if (ifaceParams.channelParams.enableAcs - && isSendFreqRangesNeeded(band)) { - if ((band & SoftApConfiguration.BAND_2GHZ) != 0) { - ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll( - toAcsFreqRanges(SoftApConfiguration.BAND_2GHZ)); - } - if ((band & SoftApConfiguration.BAND_5GHZ) != 0) { - ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll( - toAcsFreqRanges(SoftApConfiguration.BAND_5GHZ)); - } - if ((band & SoftApConfiguration.BAND_6GHZ) != 0) { - ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll( - toAcsFreqRanges(SoftApConfiguration.BAND_6GHZ)); - } - } - - android.hardware.wifi.hostapd.V1_2.IHostapd iHostapdV1_2 = - getHostapdMockableV1_2(); - if (iHostapdV1_2 == null) return false; - status12 = iHostapdV1_2.addAccessPoint_1_2(ifaceParams1_2, nwParamsV1_2); - if (!checkStatusAndLogFailure12(status12, methodStr)) { - return false; - } - } - } - - mSoftApFailureListeners.put(ifaceName, onFailureListener); - return true; - } catch (IllegalArgumentException e) { - Log.e(TAG, "Unrecognized apBand: " + band); - return false; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Remove a previously started access point. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - public boolean removeAccessPoint(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "removeAccessPoint"; - if (!checkHostapdAndLogFailure(methodStr)) return false; - try { - HostapdStatus status = mIHostapd.removeAccessPoint(ifaceName); - if (!checkStatusAndLogFailure(status, methodStr)) { - return false; - } - mSoftApFailureListeners.remove(ifaceName); - return true; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Remove a previously connected client. - * - * @param ifaceName Name of the interface. - * @param client Mac Address of the client. - * @param reasonCode One of disconnect reason code which defined in {@link WifiManager}. - * @return true on success, false otherwise. - */ - public boolean forceClientDisconnect(@NonNull String ifaceName, - @NonNull MacAddress client, int reasonCode) { - final String methodStr = "forceClientDisconnect"; - if (isV1_2()) { - try { - android.hardware.wifi.hostapd.V1_2.IHostapd iHostapdV1_2 = - getHostapdMockableV1_2(); - if (iHostapdV1_2 == null) return false; - byte[] clientMacByteArray = client.toByteArray(); - short disconnectReason; - switch (reasonCode) { - case WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER: - disconnectReason = Ieee80211ReasonCode.WLAN_REASON_PREV_AUTH_NOT_VALID; - break; - case WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS: - disconnectReason = Ieee80211ReasonCode.WLAN_REASON_DISASSOC_AP_BUSY; - break; - case WifiManager.SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED: - disconnectReason = Ieee80211ReasonCode.WLAN_REASON_UNSPECIFIED; - break; - default: - throw new IllegalArgumentException( - "Unknown disconnect reason code:" + reasonCode); - } - android.hardware.wifi.hostapd.V1_2.HostapdStatus status = - iHostapdV1_2.forceClientDisconnect(ifaceName, - clientMacByteArray, disconnectReason); - if (status.code == HostapdStatusCode.SUCCESS) { - return true; - } - Log.d(TAG, "Error when call forceClientDisconnect, status.code = " + status.code); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - } else { - Log.d(TAG, "HIDL doesn't support forceClientDisconnect"); - } - return false; - } - - /** - * Registers a death notification for hostapd. - * @return Returns true on success. - */ - public boolean registerDeathHandler(@NonNull HostapdDeathEventHandler handler) { - if (mDeathEventHandler != null) { - Log.e(TAG, "Death handler already present"); - } - mDeathEventHandler = handler; - return true; - } - - /** - * Deregisters a death notification for hostapd. - * @return Returns true on success. - */ - public boolean deregisterDeathHandler() { - if (mDeathEventHandler == null) { - Log.e(TAG, "No Death handler present"); - } - mDeathEventHandler = null; - return true; - } - - /** - * Clear internal state. - */ - private void clearState() { - synchronized (mLock) { - mIHostapd = null; - } - } - - /** - * Handle hostapd death. - */ - private void hostapdServiceDiedHandler(long cookie) { - synchronized (mLock) { - if (mDeathRecipientCookie != cookie) { - Log.i(TAG, "Ignoring stale death recipient notification"); - return; - } - clearState(); - if (mDeathEventHandler != null) { - mDeathEventHandler.onDeath(); - } - } - } - - /** - * Signals whether Initialization completed successfully. - */ - public boolean isInitializationStarted() { - synchronized (mLock) { - return mIServiceManager != null; - } - } - - /** - * Signals whether Initialization completed successfully. - */ - public boolean isInitializationComplete() { - synchronized (mLock) { - return mIHostapd != null; - } - } - - /** - * Start the hostapd daemon. - * - * @return true on success, false otherwise. - */ - public boolean startDaemon() { - synchronized (mLock) { - try { - // This should startup hostapd daemon using the lazy start HAL mechanism. - getHostapdMockable(); - } catch (RemoteException e) { - Log.e(TAG, "Exception while trying to start hostapd: " - + e); - hostapdServiceDiedHandler(mDeathRecipientCookie); - return false; - } catch (NoSuchElementException e) { - // We're starting the daemon, so expect |NoSuchElementException|. - Log.d(TAG, "Successfully triggered start of hostapd using HIDL"); - } - return true; - } - } - - /** - * Terminate the hostapd daemon & wait for it's death. - */ - public void terminate() { - synchronized (mLock) { - // Register for a new death listener to block until hostapd is dead. - final long waitForDeathCookie = new Random().nextLong(); - final CountDownLatch waitForDeathLatch = new CountDownLatch(1); - linkToHostapdDeath((cookie) -> { - Log.d(TAG, "IHostapd died: cookie=" + cookie); - if (cookie != waitForDeathCookie) return; - waitForDeathLatch.countDown(); - }, waitForDeathCookie); - - final String methodStr = "terminate"; - if (!checkHostapdAndLogFailure(methodStr)) return; - try { - mIHostapd.terminate(); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - - // Now wait for death listener callback to confirm that it's dead. - try { - if (!waitForDeathLatch.await(WAIT_FOR_DEATH_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { - Log.w(TAG, "Timed out waiting for confirmation of hostapd death"); - } - } catch (InterruptedException e) { - Log.w(TAG, "Failed to wait for hostapd death"); - } - } - } - - /** - * Wrapper functions to access static HAL methods, created to be mockable in unit tests - */ - @VisibleForTesting - protected IServiceManager getServiceManagerMockable() throws RemoteException { - synchronized (mLock) { - return IServiceManager.getService(); - } - } - - @VisibleForTesting - protected IHostapd getHostapdMockable() throws RemoteException { - synchronized (mLock) { - return IHostapd.getService(); - } - } - - @VisibleForTesting - protected android.hardware.wifi.hostapd.V1_1.IHostapd getHostapdMockableV1_1() - throws RemoteException { - synchronized (mLock) { - try { - return android.hardware.wifi.hostapd.V1_1.IHostapd.castFrom(mIHostapd); - } catch (NoSuchElementException e) { - Log.e(TAG, "Failed to get IHostapd", e); - return null; - } - } - } - - @VisibleForTesting - protected android.hardware.wifi.hostapd.V1_2.IHostapd getHostapdMockableV1_2() - throws RemoteException { - synchronized (mLock) { - try { - return android.hardware.wifi.hostapd.V1_2.IHostapd.castFrom(mIHostapd); - } catch (NoSuchElementException e) { - Log.e(TAG, "Failed to get IHostapd", e); - return null; - } - } - } - - private android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams - prepareNetworkParams(SoftApConfiguration config) { - android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams nwParamsV1_2 = - new android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams(); - nwParamsV1_2.V1_0.ssid.addAll(NativeUtil.stringToByteArrayList(config.getSsid())); - nwParamsV1_2.V1_0.isHidden = config.isHiddenSsid(); - int encryptionType = getEncryptionType(config); - nwParamsV1_2.encryptionType = encryptionType; - nwParamsV1_2.passphrase = (config.getPassphrase() != null) - ? config.getPassphrase() : ""; - if (encryptionType - == android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE - || encryptionType == android.hardware.wifi.hostapd.V1_2.IHostapd - .EncryptionType.WPA3_SAE_TRANSITION) { - if (!isV1_2()) { - // It should not happen since we should reject configuration in SoftApManager - Log.e(TAG, "Unsupported Configuration found: " + config); - return null; - } - } else { - // Fill old parameter for old hidl. - nwParamsV1_2.V1_0.encryptionType = encryptionType; - nwParamsV1_2.V1_0.pskPassphrase = (config.getPassphrase() != null) - ? config.getPassphrase() : ""; - } - return nwParamsV1_2; - } - - private static int getEncryptionType(SoftApConfiguration localConfig) { - int encryptionType; - switch (localConfig.getSecurityType()) { - case SoftApConfiguration.SECURITY_TYPE_OPEN: - encryptionType = IHostapd.EncryptionType.NONE; - break; - case SoftApConfiguration.SECURITY_TYPE_WPA2_PSK: - encryptionType = IHostapd.EncryptionType.WPA2; - break; - case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION: - encryptionType = android.hardware.wifi.hostapd.V1_2 - .IHostapd.EncryptionType.WPA3_SAE_TRANSITION; - break; - case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE: - encryptionType = android.hardware.wifi.hostapd.V1_2 - .IHostapd.EncryptionType.WPA3_SAE; - break; - default: - // We really shouldn't default to None, but this was how NetworkManagementService - // used to do this. - encryptionType = IHostapd.EncryptionType.NONE; - break; - } - return encryptionType; - } - - private static int getHalBandMask(int apBand) { - int bandMask = 0; - - if (!ApConfigUtil.isBandValid(apBand)) { - throw new IllegalArgumentException(); - } - - if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_2GHZ)) { - bandMask |= android.hardware.wifi.hostapd.V1_2.IHostapd.BandMask.BAND_2_GHZ; - } - if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_5GHZ)) { - bandMask |= android.hardware.wifi.hostapd.V1_2.IHostapd.BandMask.BAND_5_GHZ; - } - if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_6GHZ)) { - bandMask |= android.hardware.wifi.hostapd.V1_2.IHostapd.BandMask.BAND_6_GHZ; - } - - return bandMask; - } - - private static int getHalBand(int apBand) { - if (!ApConfigUtil.isBandValid(apBand)) { - throw new IllegalArgumentException(); - } - - switch (apBand) { - case SoftApConfiguration.BAND_2GHZ: - return IHostapd.Band.BAND_2_4_GHZ; - case SoftApConfiguration.BAND_5GHZ: - return IHostapd.Band.BAND_5_GHZ; - default: - return IHostapd.Band.BAND_ANY; - } - } - - /** - * Convert channel list string like '1-6,11' to list of AcsChannelRanges - */ - private List<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange> - toAcsChannelRanges(String channelListStr) { - ArrayList<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange> acsChannelRanges = - new ArrayList<>(); - - for (String channelRange : channelListStr.split(",")) { - android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange acsChannelRange = - new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange(); - try { - if (channelRange.contains("-")) { - String[] channels = channelRange.split("-"); - if (channels.length != 2) { - Log.e(TAG, "Unrecognized channel range, length is " + channels.length); - continue; - } - int start = Integer.parseInt(channels[0].trim()); - int end = Integer.parseInt(channels[1].trim()); - if (start > end) { - Log.e(TAG, "Invalid channel range, from " + start + " to " + end); - continue; - } - acsChannelRange.start = start; - acsChannelRange.end = end; - } else { - acsChannelRange.start = Integer.parseInt(channelRange.trim()); - acsChannelRange.end = acsChannelRange.start; - } - } catch (NumberFormatException e) { - // Ignore malformed value - Log.e(TAG, "Malformed channel value detected: " + e); - continue; - } - acsChannelRanges.add(acsChannelRange); - } - return acsChannelRanges; - } - - /** - * Convert channel list string like '1-6,11' to list of AcsFreqRange - */ - private List<android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange> - toAcsFreqRanges(@BandType int band) { - List<android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange> - acsFrequencyRanges = new ArrayList<>(); - - if (!ApConfigUtil.isBandValid(band) || ApConfigUtil.isMultiband(band)) { - Log.e(TAG, "Invalid band : " + band); - return acsFrequencyRanges; - } - - String channelListStr; - switch (band) { - case SoftApConfiguration.BAND_2GHZ: - channelListStr = mConfig2gChannelList; - break; - case SoftApConfiguration.BAND_5GHZ: - channelListStr = mConfig5gChannelList; - break; - case SoftApConfiguration.BAND_6GHZ: - channelListStr = mConfig6gChannelList; - break; - default: - return acsFrequencyRanges; - } - - for (String channelRange : channelListStr.split(",")) { - android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange acsFrequencyRange = - new android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange(); - try { - if (channelRange.contains("-")) { - String[] channels = channelRange.split("-"); - if (channels.length != 2) { - Log.e(TAG, "Unrecognized channel range, length is " + channels.length); - continue; - } - int start = Integer.parseInt(channels[0].trim()); - int end = Integer.parseInt(channels[1].trim()); - if (start > end) { - Log.e(TAG, "Invalid channel range, from " + start + " to " + end); - continue; - } - acsFrequencyRange.start = ApConfigUtil.convertChannelToFrequency(start, band); - acsFrequencyRange.end = ApConfigUtil.convertChannelToFrequency(end, band); - } else { - int channel = Integer.parseInt(channelRange.trim()); - acsFrequencyRange.start = ApConfigUtil.convertChannelToFrequency(channel, band); - acsFrequencyRange.end = acsFrequencyRange.start; - } - } catch (NumberFormatException e) { - // Ignore malformed value - Log.e(TAG, "Malformed channel value detected: " + e); - continue; - } - acsFrequencyRanges.add(acsFrequencyRange); - } - return acsFrequencyRanges; - } - - /** - * Returns false if Hostapd is null, and logs failure to call methodStr - */ - private boolean checkHostapdAndLogFailure(String methodStr) { - synchronized (mLock) { - if (mIHostapd == null) { - Log.e(TAG, "Can't call " + methodStr + ", IHostapd is null"); - return false; - } - return true; - } - } - - /** - * Returns true if provided status code is SUCCESS, logs debug message and returns false - * otherwise - */ - private boolean checkStatusAndLogFailure(HostapdStatus status, - String methodStr) { - synchronized (mLock) { - if (status.code != HostapdStatusCode.SUCCESS) { - Log.e(TAG, "IHostapd." + methodStr + " failed: " + status.code - + ", " + status.debugMessage); - return false; - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "IHostapd." + methodStr + " succeeded"); - } - return true; - } - } - } - - /** - * Returns true if provided status code is SUCCESS, logs debug message and returns false - * otherwise - */ - private boolean checkStatusAndLogFailure12( - android.hardware.wifi.hostapd.V1_2.HostapdStatus status, String methodStr) { - synchronized (mLock) { - if (status.code != HostapdStatusCode.SUCCESS) { - Log.e(TAG, "IHostapd." + methodStr + " failed: " + status.code - + ", " + status.debugMessage); - return false; - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "IHostapd." + methodStr + " succeeded"); - } - return true; - } - } - } - - private void handleRemoteException(RemoteException e, String methodStr) { - synchronized (mLock) { - hostapdServiceDiedHandler(mDeathRecipientCookie); - Log.e(TAG, "IHostapd." + methodStr + " failed with exception", e); - } - } - - private class HostapdCallback extends - android.hardware.wifi.hostapd.V1_1.IHostapdCallback.Stub { - @Override - public void onFailure(String ifaceName) { - Log.w(TAG, "Failure on iface " + ifaceName); - Runnable onFailureListener = mSoftApFailureListeners.get(ifaceName); - if (onFailureListener != null) { - onFailureListener.run(); - } - } - } - - /** - * Set the debug log level for hostapd. - * - * @return true if request is sent successfully, false otherwise. - */ - public boolean setLogLevel() { - synchronized (mLock) { - final String methodStr = "setDebugParams"; - if (!checkHostapdAndLogFailure(methodStr)) return false; - if (isV1_2()) { - try { - android.hardware.wifi.hostapd.V1_2.IHostapd iHostapdV1_2 = - getHostapdMockableV1_2(); - if (iHostapdV1_2 == null) return false; - android.hardware.wifi.hostapd.V1_2.HostapdStatus status = - iHostapdV1_2.setDebugParams(mVerboseLoggingEnabled - ? DebugLevel.DEBUG - : DebugLevel.INFO); - return checkStatusAndLogFailure12(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - } else { - Log.d(TAG, "HIDL doesn't support setDebugParams"); - } - return false; - } - } -} diff --git a/service/java/com/android/server/wifi/IMSIParameter.java b/service/java/com/android/server/wifi/IMSIParameter.java deleted file mode 100644 index 4991bb9a6..000000000 --- a/service/java/com/android/server/wifi/IMSIParameter.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; - -/** - * Class for storing an IMSI (International Mobile Subscriber Identity) parameter. The IMSI - * contains number (up to 15) of numerical digits. When an IMSI ends with a '*', the specified - * IMSI is a prefix. - */ -public class IMSIParameter { - /** - * Per 2.2 of 3GPP TS 23.003 - * MCC (Mobile Country Code) is a 3 digit number and MNC (Mobile Network Code) is a 2 - * or 3 digit number; - * The max length of IMSI is 15; - */ - public static final int MCC_MNC_LENGTH_5 = 5; - public static final int MCC_MNC_LENGTH_6 = 6; - private static final int MAX_IMSI_LENGTH = 15; - - private final String mImsi; - private final boolean mPrefix; - - @VisibleForTesting - public IMSIParameter(String imsi, boolean prefix) { - mImsi = imsi; - mPrefix = prefix; - } - - /** - * Build an IMSIParameter object from the given string. A null will be returned for a - * malformed string. - * - * @param imsi The IMSI string - * @return {@link IMSIParameter} - */ - public static IMSIParameter build(String imsi) { - if (TextUtils.isEmpty(imsi)) { - return null; - } - if (imsi.length() > MAX_IMSI_LENGTH) { - return null; - } - - // Detect the first non-digit character. - int nonDigitIndex; - char stopChar = '\0'; - for (nonDigitIndex = 0; nonDigitIndex < imsi.length(); nonDigitIndex++) { - stopChar = imsi.charAt(nonDigitIndex); - if (stopChar < '0' || stopChar > '9') { - break; - } - } - - if (nonDigitIndex == imsi.length()) { - // Full IMSI. - return new IMSIParameter(imsi, false); - } else if (nonDigitIndex == imsi.length() - 1 && stopChar == '*' - && (nonDigitIndex == MCC_MNC_LENGTH_5 || nonDigitIndex == MCC_MNC_LENGTH_6)) { - // IMSI prefix. - return new IMSIParameter(imsi.substring(0, nonDigitIndex), true); - } - return null; - } - - /** - * Perform matching against the given full IMSI. - * - * @param fullIMSI The full IMSI to match against - * @return true if matched - */ - public boolean matchesImsi(String fullIMSI) { - if (fullIMSI == null) { - return false; - } - - if (mPrefix) { - // Prefix matching. - return mImsi.regionMatches(false, 0, fullIMSI, 0, mImsi.length()); - } else { - // Exact matching. - return mImsi.equals(fullIMSI); - } - } - - /** - * Perform matching against the given MCC-MNC (Mobile Country Code and Mobile Network - * Code) combination. - * - * @param mccMnc The MCC-MNC to match against - * @return true if matched - */ - public boolean matchesMccMnc(String mccMnc) { - if (mccMnc == null) { - return false; - } - if (mccMnc.length() != MCC_MNC_LENGTH_5 && mccMnc.length() != MCC_MNC_LENGTH_6) { - return false; - } - if (mPrefix && mccMnc.length() != mImsi.length()) { - return false; - } - - return mImsi.startsWith(mccMnc); - } - - /** - * If the IMSI is full length. - * - * @return true If the length of IMSI is full, false otherwise. - */ - public boolean isFullImsi() { - return !mPrefix; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof IMSIParameter)) { - return false; - } - - IMSIParameter that = (IMSIParameter) thatObject; - return mPrefix == that.mPrefix && TextUtils.equals(mImsi, that.mImsi); - } - - @Override - public int hashCode() { - int result = mImsi != null ? mImsi.hashCode() : 0; - result = 31 * result + (mPrefix ? 1 : 0); - return result; - } - - @Override - public String toString() { - if (mPrefix) { - return mImsi + '*'; - } - else { - return mImsi; - } - } -} diff --git a/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java b/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java deleted file mode 100644 index a9c99ae54..000000000 --- a/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.util.Log; - -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * This class performs serialization and parsing of XML data block that contain the map of IMSI - * protection exemption user approval info. - */ -public class ImsiPrivacyProtectionExemptionStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "ImsiPrivacyProtectionExemptionStoreData"; - private static final String XML_TAG_SECTION_HEADER_IMSI_PROTECTION_EXEMPTION_CARRIER_MAP = - "ImsiPrivacyProtectionExemptionMap"; - private static final String XML_TAG_CARRIER_EXEMPTION_MAP = "CarrierExemptionMap"; - - /** - * Interface define the data source for the carrier IMSI protection exemption map store data. - */ - public interface DataSource { - /** - * Retrieve the IMSI protection exemption map from the data source to serialize to disk. - * - * @return Map of carrier Id to if allowed. - */ - Map<Integer, Boolean> toSerialize(); - - /** - * Set the IMSI protection exemption map in the data source after serializing them from disk - * - * @param imsiProtectionExemptionMap Map of carrier Id to allowed or not. - */ - void fromDeserialized(Map<Integer, Boolean> imsiProtectionExemptionMap); - - /** - * Clear internal data structure in preparation for user switch or initial store read. - */ - void reset(); - - /** - * Indicates whether there is new data to serialize. - */ - boolean hasNewDataToSerialize(); - } - - private final DataSource mDataSource; - - /** - * Set the data source fot store data. - */ - public ImsiPrivacyProtectionExemptionStoreData(@NonNull DataSource dataSource) { - mDataSource = dataSource; - } - - @Override - public void serializeData(XmlSerializer out, WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - Map<String, Boolean> dataToSerialize = integerMapToStringMap(mDataSource.toSerialize()); - XmlUtil.writeNextValue(out, XML_TAG_CARRIER_EXEMPTION_MAP, dataToSerialize); - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, int version, - WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - // Ignore empty reads. - if (in == null) { - mDataSource.fromDeserialized(Collections.emptyMap()); - return; - } - - mDataSource.fromDeserialized(parseCarrierImsiProtectionExemptionMap(in, outerTagDepth, - version, encryptionUtil)); - - } - - private Map<Integer, Boolean> parseCarrierImsiProtectionExemptionMap(XmlPullParser in, - int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - Map<String, Boolean> protectionExemptionMap = new HashMap<>(); - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_CARRIER_EXEMPTION_MAP: - if (value instanceof Map) { - protectionExemptionMap = (Map<String, Boolean>) value; - } - break; - default: - Log.w(TAG, "Unknown tag under " - + XML_TAG_SECTION_HEADER_IMSI_PROTECTION_EXEMPTION_CARRIER_MAP - + ": " + valueName[0]); - break; - } - } - return stringMapToIntegerMap(protectionExemptionMap); - } - - private Map<String, Boolean> integerMapToStringMap(Map<Integer, Boolean> input) { - Map<String, Boolean> output = new HashMap<>(); - if (input == null) { - return output; - } - for (Map.Entry<Integer, Boolean> entry : input.entrySet()) { - output.put(Integer.toString(entry.getKey()), entry.getValue()); - } - return output; - } - - private Map<Integer, Boolean> stringMapToIntegerMap(Map<String, Boolean> input) { - Map<Integer, Boolean> output = new HashMap<>(); - if (input == null) { - return output; - } - for (Map.Entry<String, Boolean> entry : input.entrySet()) { - try { - output.put(Integer.valueOf(entry.getKey()), entry.getValue()); - } catch (NumberFormatException e) { - Log.e(TAG, "Failed to Integer convert: " + entry.getKey()); - } - } - return output; - } - - - @Override - public void resetData() { - mDataSource.reset(); - } - - @Override - public boolean hasNewDataToSerialize() { - return mDataSource.hasNewDataToSerialize(); - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER_IMSI_PROTECTION_EXEMPTION_CARRIER_MAP; - } - - @Override - public int getStoreFileId() { - // User general store. - return WifiConfigStore.STORE_FILE_USER_GENERAL; - } -} diff --git a/service/java/com/android/server/wifi/LastMileLogger.java b/service/java/com/android/server/wifi/LastMileLogger.java deleted file mode 100644 index 1a43b6f85..000000000 --- a/service/java/com/android/server/wifi/LastMileLogger.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.FileUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Paths; - -/** - * Provides a facility for capturing kernel trace events related to Wifi control and data paths. - */ -public class LastMileLogger { - public LastMileLogger(WifiInjector injector) { - File tracefsEnablePath = new File(WIFI_EVENT_ENABLE_PATH); - if (tracefsEnablePath.exists()) { - initLastMileLogger(injector, WIFI_EVENT_BUFFER_PATH, WIFI_EVENT_ENABLE_PATH, - WIFI_EVENT_RELEASE_PATH); - } else { - initLastMileLogger(injector, WIFI_EVENT_BUFFER_PATH_DEBUGFS, - WIFI_EVENT_ENABLE_PATH_DEBUGFS, WIFI_EVENT_RELEASE_PATH_DEBUGFS); - } - } - - @VisibleForTesting - public LastMileLogger(WifiInjector injector, String bufferPath, String enablePath, - String releasePath) { - initLastMileLogger(injector, bufferPath, enablePath, releasePath); - } - - /** - * Informs LastMileLogger that a connection event has occurred. - * @param event an event defined in BaseWifiDiagnostics - */ - public void reportConnectionEvent(byte event) { - switch (event) { - case BaseWifiDiagnostics.CONNECTION_EVENT_STARTED: - enableTracing(); - return; - case BaseWifiDiagnostics.CONNECTION_EVENT_SUCCEEDED: - disableTracing(); - return; - case BaseWifiDiagnostics.CONNECTION_EVENT_FAILED: - disableTracing(); - mLastMileLogForLastFailure = readTrace(); - return; - case BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT: - disableTracing(); - mLastMileLogForLastFailure = readTrace(); - return; - } - } - - /** - * Dumps the contents of the log. - * @param pw the PrintWriter that will receive the dump - */ - public void dump(PrintWriter pw) { - dumpInternal(pw, "Last failed last-mile log", mLastMileLogForLastFailure); - dumpInternal(pw, "Latest last-mile log", readTrace()); - } - - private static final String TAG = "LastMileLogger"; - private static final String WIFI_EVENT_BUFFER_PATH = - "/sys/kernel/tracing/instances/wifi/trace"; - private static final String WIFI_EVENT_ENABLE_PATH = - "/sys/kernel/tracing/instances/wifi/tracing_on"; - private static final String WIFI_EVENT_RELEASE_PATH = - "/sys/kernel/tracing/instances/wifi/free_buffer"; - private static final String WIFI_EVENT_BUFFER_PATH_DEBUGFS = - "/sys/kernel/debug/tracing/instances/wifi/trace"; - private static final String WIFI_EVENT_ENABLE_PATH_DEBUGFS = - "/sys/kernel/debug/tracing/instances/wifi/tracing_on"; - private static final String WIFI_EVENT_RELEASE_PATH_DEBUGFS = - "/sys/kernel/debug/tracing/instances/wifi/free_buffer"; - - - private String mEventBufferPath; - private String mEventEnablePath; - private String mEventReleasePath; - private WifiLog mLog; - private byte[] mLastMileLogForLastFailure; - private FileInputStream mLastMileTraceHandle; - - private void initLastMileLogger(WifiInjector injector, String bufferPath, String enablePath, - String releasePath) { - mLog = injector.makeLog(TAG); - mEventBufferPath = bufferPath; - mEventEnablePath = enablePath; - mEventReleasePath = releasePath; - } - - private void enableTracing() { - if (!ensureFailSafeIsArmed()) { - mLog.wC("Failed to arm fail-safe."); - return; - } - - try { - FileUtils.stringToFile(mEventEnablePath, "1"); - } catch (IOException e) { - mLog.warn("Failed to start event tracing: %").r(e.getMessage()).flush(); - } - } - - private void disableTracing() { - try { - FileUtils.stringToFile(mEventEnablePath, "0"); - } catch (IOException e) { - mLog.warn("Failed to stop event tracing: %").r(e.getMessage()).flush(); - } - } - - private byte[] readTrace() { - try { - return Files.readAllBytes(Paths.get(mEventBufferPath)); - } catch (IOException e) { - mLog.warn("Failed to read event trace: %").r(e.getMessage()).flush(); - return new byte[0]; - } - } - - private boolean ensureFailSafeIsArmed() { - if (mLastMileTraceHandle != null) { - return true; - } - - try { - // This file provides fail-safe behavior for Last-Mile logging. Given that we: - // 1. Set the disable_on_free option in the trace_options pseudo-file - // (see wifi-events.rc), and - // 2. Hold the WIFI_EVENT_RELEASE_PATH open, - // - // Then, when this process dies, the kernel will automatically disable any - // tracing in the wifi trace instance. - // - // Note that, despite Studio's suggestion that |mLastMileTraceHandle| could be demoted - // to a local variable, we need to stick with a field. Otherwise, the handle could be - // garbage collected. - mLastMileTraceHandle = new FileInputStream(mEventReleasePath); - return true; - } catch (IOException e) { - mLog.warn("Failed to open free_buffer pseudo-file: %").r(e.getMessage()).flush(); - return false; - } - } - - private static void dumpInternal(PrintWriter pw, String description, byte[] lastMileLog) { - if (lastMileLog == null || lastMileLog.length < 1) { - pw.format("No last mile log for \"%s\"\n", description); - return; - } - - pw.format("-------------------------- %s ---------------------------\n", description); - pw.print(new String(lastMileLog)); - pw.println("--------------------------------------------------------------------"); - } -} diff --git a/service/java/com/android/server/wifi/LinkProbeManager.java b/service/java/com/android/server/wifi/LinkProbeManager.java deleted file mode 100644 index 863268811..000000000 --- a/service/java/com/android/server/wifi/LinkProbeManager.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.WifiInfo; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.Handler; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.TimedQuotaManager; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; - -/** - * Tracks state that decides if a link probe should be performed. If so, trigger a link probe to - * evaluate connection quality. - */ -public class LinkProbeManager { - private static final String TAG = "WifiLinkProbeManager"; - - private static final int WIFI_LINK_PROBING_ENABLED_DEFAULT = 1; // 1 = enabled - - // TODO(112029045): Use constants from ScoringParams instead - @VisibleForTesting static final int RSSI_THRESHOLD = -70; - @VisibleForTesting static final int LINK_SPEED_THRESHOLD_MBPS = 15; // in megabits per second - /** Minimum delay before probing after the last probe. */ - @VisibleForTesting static final long DELAY_BETWEEN_PROBES_MS = 6000; - /** Minimum delay before probing after screen turned on. */ - @VisibleForTesting static final long SCREEN_ON_DELAY_MS = 6000; - /** - * Minimum delay before probing after last increase of the Tx success counter (which indicates - * that a data frame (i.e. not counting management frame) was successfully transmitted). - */ - @VisibleForTesting static final long DELAY_AFTER_TX_SUCCESS_MS = 6000; - - @VisibleForTesting static final long MAX_PROBE_COUNT_IN_PERIOD = - WifiMetrics.MAX_LINK_PROBE_STA_EVENTS; - @VisibleForTesting static final long PERIOD_MILLIS = Duration.ofDays(1).toMillis(); - - @VisibleForTesting static final int[] EXPERIMENT_DELAYS_MS = {3000, 6000, 9000, 12000, 15000}; - @VisibleForTesting static final int[] EXPERIMENT_RSSIS = {-65, -70, -75}; - @VisibleForTesting static final int[] EXPERIMENT_LINK_SPEEDS = {10, 15, 20}; - private List<Experiment> mExperiments = new ArrayList<>(); - - private final Clock mClock; - private final WifiNative mWifiNative; - private final WifiMetrics mWifiMetrics; - private final FrameworkFacade mFrameworkFacade; - private final Handler mHandler; - private final Context mContext; - - private Boolean mLinkProbingSupported = null; - - private boolean mVerboseLoggingEnabled = false; - - /** - * Tracks the last timestamp when a link probe was triggered. Link probing only occurs when at - * least {@link #DELAY_BETWEEN_PROBES_MS} has passed since the last link probe. - */ - private long mLastLinkProbeTimestampMs; - /** - * Tracks the last timestamp when {@link WifiInfo#txSuccess} was increased i.e. the last time a - * Tx was successful. Link probing only occurs when at least {@link #DELAY_AFTER_TX_SUCCESS_MS} - * has passed since the last Tx success. - * This is also reset to the current time when {@link #resetOnNewConnection()} is called, so - * that a link probe only occurs at least {@link #DELAY_AFTER_TX_SUCCESS_MS} after a new - * connection is made. - */ - private long mLastTxSuccessIncreaseTimestampMs; - /** - * Stores the last value of {@link WifiInfo#txSuccess}. The current value of - * {@link WifiInfo#txSuccess} is compared against the last value to determine whether there was - * a successful Tx. - */ - private long mLastTxSuccessCount; - /** - * Tracks the last timestamp when the screen turned on. Link probing only occurs when at least - * {@link #SCREEN_ON_DELAY_MS} has passed since the last time the screen was turned on. - */ - private long mLastScreenOnTimestampMs; - private final TimedQuotaManager mTimedQuotaManager; - - public LinkProbeManager(Clock clock, WifiNative wifiNative, WifiMetrics wifiMetrics, - FrameworkFacade frameworkFacade, Handler handler, Context context) { - mClock = clock; - mWifiNative = wifiNative; - mWifiMetrics = wifiMetrics; - mFrameworkFacade = frameworkFacade; - mHandler = handler; - mContext = context; - mTimedQuotaManager = new TimedQuotaManager(clock, MAX_PROBE_COUNT_IN_PERIOD, PERIOD_MILLIS); - - initExperiments(); - } - - private boolean isLinkProbingSupported() { - if (mLinkProbingSupported == null) { - mLinkProbingSupported = mContext.getResources() - .getBoolean(R.bool.config_wifi_link_probing_supported); - if (mLinkProbingSupported) { - resetOnNewConnection(); - resetOnScreenTurnedOn(); - } - } - return mLinkProbingSupported; - } - - /** enables/disables wifi verbose logging */ - public void enableVerboseLogging(boolean enable) { - mVerboseLoggingEnabled = enable; - } - - /** dumps internal state */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of LinkProbeManager"); - pw.println("LinkProbeManager - link probing supported by device: " - + isLinkProbingSupported()); - pw.println("LinkProbeManager - mLastLinkProbeTimestampMs: " + mLastLinkProbeTimestampMs); - pw.println("LinkProbeManager - mLastTxSuccessIncreaseTimestampMs: " - + mLastTxSuccessIncreaseTimestampMs); - pw.println("LinkProbeManager - mLastTxSuccessCount: " + mLastTxSuccessCount); - pw.println("LinkProbeManager - mLastScreenOnTimestampMs: " + mLastScreenOnTimestampMs); - pw.println("LinkProbeManager - mTimedQuotaManager: " + mTimedQuotaManager); - } - - /** - * When connecting to a new network, reset internal state. - */ - public void resetOnNewConnection() { - mExperiments.forEach(Experiment::resetOnNewConnection); - if (!isLinkProbingSupported()) return; - - long now = mClock.getElapsedSinceBootMillis(); - mLastLinkProbeTimestampMs = now; - mLastTxSuccessIncreaseTimestampMs = now; - mLastTxSuccessCount = 0; - } - - /** - * When RSSI poll events are stopped and restarted (usually screen turned off then back on), - * reset internal state. - */ - public void resetOnScreenTurnedOn() { - mExperiments.forEach(Experiment::resetOnScreenTurnedOn); - if (!isLinkProbingSupported()) return; - - mLastScreenOnTimestampMs = mClock.getElapsedSinceBootMillis(); - } - - /** - * Based on network conditions provided by WifiInfo, decides if a link probe should be - * performed. If so, trigger a link probe and report the results to WifiMetrics. - * - * @param wifiInfo the updated WifiInfo - * @param interfaceName the interface that the link probe should be performed on, if applicable. - */ - public void updateConnectionStats(WifiInfo wifiInfo, String interfaceName) { - mExperiments.forEach(e -> e.updateConnectionStats(wifiInfo)); - - if (!isLinkProbingSupported()) return; - - long now = mClock.getElapsedSinceBootMillis(); - - // at least 1 tx succeeded since last update - if (mLastTxSuccessCount < wifiInfo.txSuccess) { - mLastTxSuccessIncreaseTimestampMs = now; - } - mLastTxSuccessCount = wifiInfo.txSuccess; - - // maximum 1 link probe every DELAY_BETWEEN_PROBES_MS - long timeSinceLastLinkProbeMs = now - mLastLinkProbeTimestampMs; - if (timeSinceLastLinkProbeMs < DELAY_BETWEEN_PROBES_MS) { - return; - } - - // if tx succeeded at least once in the last DELAY_AFTER_TX_SUCCESS_MS, don't need to probe - long timeSinceLastTxSuccessIncreaseMs = now - mLastTxSuccessIncreaseTimestampMs; - if (timeSinceLastTxSuccessIncreaseMs < DELAY_AFTER_TX_SUCCESS_MS) { - return; - } - - // if not enough time has passed since the screen last turned on, don't probe - long timeSinceLastScreenOnMs = now - mLastScreenOnTimestampMs; - if (timeSinceLastScreenOnMs < SCREEN_ON_DELAY_MS) { - return; - } - - // can skip probing if RSSI is valid and high and link speed is fast - int rssi = wifiInfo.getRssi(); - int linkSpeed = wifiInfo.getLinkSpeed(); - if (rssi != WifiInfo.INVALID_RSSI && rssi > RSSI_THRESHOLD - && linkSpeed > LINK_SPEED_THRESHOLD_MBPS) { - return; - } - - if (!mTimedQuotaManager.requestQuota()) { - return; - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, String.format( - "link probing triggered with conditions: timeSinceLastLinkProbeMs=%d " - + "timeSinceLastTxSuccessIncreaseMs=%d rssi=%d linkSpeed=%s", - timeSinceLastLinkProbeMs, timeSinceLastTxSuccessIncreaseMs, - rssi, linkSpeed)); - } - - // TODO(b/112029045): also report MCS rate to metrics when supported by driver - mWifiNative.probeLink( - interfaceName, - MacAddress.fromString(wifiInfo.getBSSID()), - new WifiNl80211Manager.SendMgmtFrameCallback() { - @Override - public void onAck(int elapsedTimeMs) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "link probing success, elapsedTimeMs=" - + elapsedTimeMs); - } - mWifiMetrics.logLinkProbeSuccess( - timeSinceLastTxSuccessIncreaseMs, rssi, linkSpeed, - elapsedTimeMs); - } - - @Override - public void onFailure(int reason) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "link probing failure, reason=" + reason); - } - mWifiMetrics.logLinkProbeFailure( - timeSinceLastTxSuccessIncreaseMs, rssi, linkSpeed, reason); - } - }, - -1); // placeholder, lets driver determine MCS rate - mLastLinkProbeTimestampMs = mClock.getElapsedSinceBootMillis(); - } - - private void initExperiments() { - for (int delay : EXPERIMENT_DELAYS_MS) { - for (int rssiThreshold : EXPERIMENT_RSSIS) { - for (int linkSpeedThreshold: EXPERIMENT_LINK_SPEEDS) { - Experiment experiment = new Experiment(mClock, mWifiMetrics, - delay, delay, delay, rssiThreshold, linkSpeedThreshold); - mExperiments.add(experiment); - } - } - } - } - - // TODO(b/131091030): remove once experiment is over - private static class Experiment { - - private final Clock mClock; - private final WifiMetrics mWifiMetrics; - private final int mScreenOnDelayMs; - private final int mNoTxDelayMs; - private final int mDelayBetweenProbesMs; - private final int mRssiThreshold; - private final int mLinkSpeedThreshold; - private final String mExperimentId; - - private long mLastLinkProbeTimestampMs; - private long mLastTxSuccessIncreaseTimestampMs; - private long mLastTxSuccessCount; - private long mLastScreenOnTimestampMs; - - Experiment(Clock clock, WifiMetrics wifiMetrics, - int screenOnDelayMs, int noTxDelayMs, int delayBetweenProbesMs, - int rssiThreshold, int linkSpeedThreshold) { - mClock = clock; - mWifiMetrics = wifiMetrics; - mScreenOnDelayMs = screenOnDelayMs; - mNoTxDelayMs = noTxDelayMs; - mDelayBetweenProbesMs = delayBetweenProbesMs; - mRssiThreshold = rssiThreshold; - mLinkSpeedThreshold = linkSpeedThreshold; - - mExperimentId = getExperimentId(); - - resetOnNewConnection(); - resetOnScreenTurnedOn(); - } - - private String getExperimentId() { - return "[screenOnDelay=" + mScreenOnDelayMs + ',' - + "noTxDelay=" + mNoTxDelayMs + ',' - + "delayBetweenProbes=" + mDelayBetweenProbesMs + ',' - + "rssiThreshold=" + mRssiThreshold + ',' - + "linkSpeedThreshold=" + mLinkSpeedThreshold + ']'; - } - - void resetOnNewConnection() { - long now = mClock.getElapsedSinceBootMillis(); - mLastLinkProbeTimestampMs = now; - mLastTxSuccessIncreaseTimestampMs = now; - mLastTxSuccessCount = 0; - } - - void resetOnScreenTurnedOn() { - mLastScreenOnTimestampMs = mClock.getElapsedSinceBootMillis(); - } - - void updateConnectionStats(WifiInfo wifiInfo) { - long now = mClock.getElapsedSinceBootMillis(); - - if (mLastTxSuccessCount < wifiInfo.txSuccess) { - mLastTxSuccessIncreaseTimestampMs = now; - } - mLastTxSuccessCount = wifiInfo.txSuccess; - - long timeSinceLastLinkProbeMs = now - mLastLinkProbeTimestampMs; - if (timeSinceLastLinkProbeMs < mDelayBetweenProbesMs) { - return; - } - - // if tx succeeded at least once in the last LINK_PROBE_INTERVAL_MS, don't need to probe - long timeSinceLastTxSuccessIncreaseMs = now - mLastTxSuccessIncreaseTimestampMs; - if (timeSinceLastTxSuccessIncreaseMs < mNoTxDelayMs) { - return; - } - - long timeSinceLastScreenOnMs = now - mLastScreenOnTimestampMs; - if (timeSinceLastScreenOnMs < SCREEN_ON_DELAY_MS) { - return; - } - - // can skip probing if RSSI is valid and high and link speed is fast - int rssi = wifiInfo.getRssi(); - int linkSpeed = wifiInfo.getLinkSpeed(); - if (rssi != WifiInfo.INVALID_RSSI && rssi > mRssiThreshold - && linkSpeed > mLinkSpeedThreshold) { - return; - } - - mWifiMetrics.incrementLinkProbeExperimentProbeCount(mExperimentId); - - mLastLinkProbeTimestampMs = mClock.getElapsedSinceBootMillis(); - } - } -} diff --git a/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java b/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java deleted file mode 100644 index 97d5f66f4..000000000 --- a/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.wifi.ILocalOnlyHotspotCallback; -import android.net.wifi.SoftApConfiguration; -import android.os.Binder; -import android.os.IBinder; -import android.os.RemoteException; - -import com.android.internal.util.Preconditions; - -/** - * Tracks information about applications requesting use of the LocalOnlyHotspot. - * - * @hide - */ -class LocalOnlyHotspotRequestInfo implements IBinder.DeathRecipient { - static final int HOTSPOT_NO_ERROR = -1; - - private final int mPid; - private final ILocalOnlyHotspotCallback mCallback; - private final RequestingApplicationDeathCallback mDeathCallback; - private final SoftApConfiguration mCustomConfig; - - /** - * Callback for use with LocalOnlyHotspot to unregister requesting applications upon death. - */ - interface RequestingApplicationDeathCallback { - /** - * Called when requesting app has died. - */ - void onLocalOnlyHotspotRequestorDeath(LocalOnlyHotspotRequestInfo requestor); - } - - LocalOnlyHotspotRequestInfo(@NonNull ILocalOnlyHotspotCallback callback, - @NonNull RequestingApplicationDeathCallback deathCallback, - @Nullable SoftApConfiguration customConfig) { - mPid = Binder.getCallingPid(); - mCallback = Preconditions.checkNotNull(callback); - mDeathCallback = Preconditions.checkNotNull(deathCallback); - mCustomConfig = customConfig; - - try { - mCallback.asBinder().linkToDeath(this, 0); - } catch (RemoteException e) { - binderDied(); - } - } - - /** - * Allow caller to unlink this object from binder death. - */ - public void unlinkDeathRecipient() { - mCallback.asBinder().unlinkToDeath(this, 0); - } - - /** - * Application requesting LocalOnlyHotspot died - */ - @Override - public void binderDied() { - mDeathCallback.onLocalOnlyHotspotRequestorDeath(this); - } - - /** - * Send a HOTSPOT_FAILED message to WifiManager for the calling application with the error code. - * - * @param reasonCode error code for the message - * - * @throws RemoteException - */ - public void sendHotspotFailedMessage(int reasonCode) throws RemoteException { - mCallback.onHotspotFailed(reasonCode); - } - - /** - * Send a HOTSPOT_STARTED message to WifiManager for the calling application with the config. - * - * @param config SoftApConfiguration for the callback - * - * @throws RemoteException - */ - public void sendHotspotStartedMessage(SoftApConfiguration config) throws RemoteException { - mCallback.onHotspotStarted(config); - } - - /** - * Send a HOTSPOT_STOPPED message to WifiManager for the calling application. - * - * @throws RemoteException - */ - public void sendHotspotStoppedMessage() throws RemoteException { - mCallback.onHotspotStopped(); - } - - public int getPid() { - return mPid; - } - - public SoftApConfiguration getCustomConfig() { - return mCustomConfig; - } -} diff --git a/service/java/com/android/server/wifi/LogcatLog.java b/service/java/com/android/server/wifi/LogcatLog.java deleted file mode 100644 index ce296009f..000000000 --- a/service/java/com/android/server/wifi/LogcatLog.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.util.Log; - -import com.android.internal.annotations.Immutable; -import com.android.internal.annotations.VisibleForTesting; - -import javax.annotation.concurrent.ThreadSafe; - -/** - * Provides a WifiLog implementation which uses logd as the - * logging backend. - * - * This class is trivially thread-safe, as instances are immutable. - * Note, however, that LogMessage instances are _not_ thread-safe. - */ -@ThreadSafe -@Immutable -class LogcatLog implements WifiLog { - private final String mTag; - private static volatile boolean sVerboseLogging = false; - private static final DummyLogMessage sDummyLogMessage = new DummyLogMessage(); - - LogcatLog(String tag) { - mTag = tag; - } - - public static void enableVerboseLogging(int verboseMode) { - if (verboseMode > 0) { - sVerboseLogging = true; - } else { - sVerboseLogging = false; - } - } - - /* New-style methods */ - @Override - public LogMessage err(String format) { - return new RealLogMessage(Log.ERROR, mTag, format); - } - - @Override - public LogMessage warn(String format) { - return new RealLogMessage(Log.WARN, mTag, format); - } - - @Override - public LogMessage info(String format) { - return new RealLogMessage(Log.INFO, mTag, format); - } - - @Override - public LogMessage trace(String format) { - if (sVerboseLogging) { - return new RealLogMessage(Log.DEBUG, mTag, format, - getNameOfCallingMethod(0)); - } else { - return sDummyLogMessage; - } - } - - @Override - public LogMessage trace(String format, int numFramesToIgnore) { - if (sVerboseLogging) { - return new RealLogMessage(Log.DEBUG, mTag, format, - getNameOfCallingMethod(numFramesToIgnore)); - } else { - return sDummyLogMessage; - } - } - - @Override - public LogMessage dump(String format) { - if (sVerboseLogging) { - return new RealLogMessage(Log.VERBOSE, mTag, format); - } else { - return sDummyLogMessage; - } - } - - @Override - public void eC(String msg) { - Log.e(mTag, msg); - } - - @Override - public void wC(String msg) { - Log.w(mTag, msg); - } - - @Override - public void iC(String msg) { - Log.i(mTag, msg); - } - - @Override - public void tC(String msg) { - Log.d(mTag, msg); - } - - /* Legacy methods */ - @Override - public void e(String msg) { - Log.e(mTag, msg); - } - - @Override - public void w(String msg) { - Log.w(mTag, msg); - } - - @Override - public void i(String msg) { - Log.i(mTag, msg); - } - - @Override - public void d(String msg) { - Log.d(mTag, msg); - } - - @Override - public void v(String msg) { - Log.v(mTag, msg); - } - - /* Internal details */ - private static class RealLogMessage implements WifiLog.LogMessage { - private final int mLogLevel; - private final String mTag; - private final String mFormat; - private final StringBuilder mStringBuilder; - private int mNextFormatCharPos; - - RealLogMessage(int logLevel, String tag, String format) { - this(logLevel, tag, format, null); - } - - RealLogMessage(int logLevel, String tag, String format, String prefix) { - mLogLevel = logLevel; - mTag = tag; - mFormat = format; - mStringBuilder = new StringBuilder(); - mNextFormatCharPos = 0; - if (prefix != null) { - mStringBuilder.append(prefix).append(" "); - } - } - - @Override - public WifiLog.LogMessage r(String value) { - // Since the logcat back-end is just transitional, we don't attempt to tag sensitive - // information in it. - return c(value); - } - - @Override - public WifiLog.LogMessage c(String value) { - copyUntilPlaceholder(); - if (mNextFormatCharPos < mFormat.length()) { - mStringBuilder.append(value); - ++mNextFormatCharPos; - } - return this; - } - - @Override - public WifiLog.LogMessage c(long value) { - copyUntilPlaceholder(); - if (mNextFormatCharPos < mFormat.length()) { - mStringBuilder.append(value); - ++mNextFormatCharPos; - } - return this; - } - - @Override - public WifiLog.LogMessage c(char value) { - copyUntilPlaceholder(); - if (mNextFormatCharPos < mFormat.length()) { - mStringBuilder.append(value); - ++mNextFormatCharPos; - } - return this; - } - - @Override - public WifiLog.LogMessage c(boolean value) { - copyUntilPlaceholder(); - if (mNextFormatCharPos < mFormat.length()) { - mStringBuilder.append(value); - ++mNextFormatCharPos; - } - return this; - } - - @Override - public void flush() { - if (mNextFormatCharPos < mFormat.length()) { - mStringBuilder.append(mFormat, mNextFormatCharPos, mFormat.length()); - } - Log.println(mLogLevel, mTag, mStringBuilder.toString()); - } - - @VisibleForTesting - public String toString() { - return mStringBuilder.toString(); - } - - private void copyUntilPlaceholder() { - if (mNextFormatCharPos >= mFormat.length()) { - return; - } - - int placeholderPos = mFormat.indexOf(WifiLog.PLACEHOLDER, mNextFormatCharPos); - if (placeholderPos == -1) { - placeholderPos = mFormat.length(); - } - - mStringBuilder.append(mFormat, mNextFormatCharPos, placeholderPos); - mNextFormatCharPos = placeholderPos; - } - } - - private static final String[] TRACE_FRAMES_TO_IGNORE = { - "getNameOfCallingMethod()", "trace()" - }; - private String getNameOfCallingMethod(int callerFramesToIgnore) { - final int frameNumOfInterest = callerFramesToIgnore + TRACE_FRAMES_TO_IGNORE.length; - // In some environments, it's much faster to get a stack trace from a Throwable - // https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6375302. - // - // While Dalvik optimizes the same-thread-stack-trace case, - // Throwable_nativeGetStackTrace() is still simpler than - // VMStack_getThreadStackTrace(). - // - // Some crude benchmarking suggests that the cost of this approach is about - // 50 usec. go/logcatlog-trace-benchmark - StackTraceElement[] stackTrace = (new Throwable()).getStackTrace(); - try { - return stackTrace[frameNumOfInterest].getMethodName(); - } catch (ArrayIndexOutOfBoundsException e) { - return ("<unknown>"); - } - } -} diff --git a/service/java/com/android/server/wifi/MacAddressUtil.java b/service/java/com/android/server/wifi/MacAddressUtil.java deleted file mode 100644 index 3ea265491..000000000 --- a/service/java/com/android/server/wifi/MacAddressUtil.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.net.MacAddress; -import android.security.keystore.AndroidKeyStoreProvider; -import android.security.keystore.KeyGenParameterSpec; -import android.security.keystore.KeyProperties; -import android.util.Log; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.ProviderException; -import java.security.UnrecoverableKeyException; -import java.util.Arrays; - -import javax.crypto.KeyGenerator; -import javax.crypto.Mac; -import javax.crypto.SecretKey; - -/** - * Contains helper methods to support MAC randomization. - */ -public class MacAddressUtil { - private static final String TAG = "MacAddressUtil"; - private static final String MAC_RANDOMIZATION_ALIAS = "MacRandSecret"; - private static final String MAC_RANDOMIZATION_SAP_ALIAS = "MacRandSapSecret"; - private static final long MAC_ADDRESS_VALID_LONG_MASK = (1L << 48) - 1; - private static final long MAC_ADDRESS_LOCALLY_ASSIGNED_MASK = 1L << 41; - private static final long MAC_ADDRESS_MULTICAST_MASK = 1L << 40; - - /** - * Computes the persistent randomized MAC using the given key and hash function. - * @param key the key to compute MAC address for - * @param hashFunction the hash function that will perform the MAC address computation. - * @return The persistent randomized MAC address or null if inputs are invalid. - */ - public MacAddress calculatePersistentMac(String key, Mac hashFunction) { - if (key == null || hashFunction == null) { - return null; - } - byte[] hashedBytes; - try { - hashedBytes = hashFunction.doFinal(key.getBytes(StandardCharsets.UTF_8)); - } catch (ProviderException | IllegalStateException e) { - Log.e(TAG, "Failure in calculatePersistentMac", e); - return null; - } - ByteBuffer bf = ByteBuffer.wrap(hashedBytes); - long longFromSsid = bf.getLong(); - /** - * Masks the generated long so that it represents a valid randomized MAC address. - * Specifically, this sets the locally assigned bit to 1, multicast bit to 0 - */ - longFromSsid &= MAC_ADDRESS_VALID_LONG_MASK; - longFromSsid |= MAC_ADDRESS_LOCALLY_ASSIGNED_MASK; - longFromSsid &= ~MAC_ADDRESS_MULTICAST_MASK; - bf.clear(); - bf.putLong(0, longFromSsid); - - // MacAddress.fromBytes requires input of length 6, which is obtained from the - // last 6 bytes from the generated long. - MacAddress macAddress = MacAddress.fromBytes(Arrays.copyOfRange(bf.array(), 2, 8)); - return macAddress; - } - - private Mac obtainMacRandHashFunctionInternal(int uid, String alias) { - try { - KeyStore keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(uid); - // tries to retrieve the secret, and generate a new one if it's unavailable. - Key key = keyStore.getKey(alias, null); - if (key == null) { - key = generateAndPersistNewMacRandomizationSecret(uid, alias); - } - if (key == null) { - Log.e(TAG, "Failed to generate secret for " + alias); - return null; - } - Mac result = Mac.getInstance("HmacSHA256"); - result.init(key); - return result; - } catch (KeyStoreException | NoSuchAlgorithmException | InvalidKeyException - | UnrecoverableKeyException | NoSuchProviderException e) { - Log.e(TAG, "Failure in obtainMacRandHashFunction", e); - return null; - } - } - - /** - * Retrieves a Hash function that could be used to calculate the persistent randomized MAC - * for a WifiConfiguration for client mode. - * @param uid the UID of the KeyStore to get the secret of the hash function from. - */ - public Mac obtainMacRandHashFunction(int uid) { - return obtainMacRandHashFunctionInternal(uid, MAC_RANDOMIZATION_ALIAS); - } - - /** - * Retrieves a Hash function that could be used to calculate the persistent randomized MAC - * for a WifiConfiguration for Soft AP. - * @param uid the UID of the KeyStore to get the secret of the hash function from. - */ - public Mac obtainMacRandHashFunctionForSap(int uid) { - return obtainMacRandHashFunctionInternal(uid, MAC_RANDOMIZATION_SAP_ALIAS); - } - - /** - * Generates and returns a secret key to use for Mac randomization. - * Will also persist the generated secret inside KeyStore, accessible in the - * future with KeyGenerator#getKey. - */ - private SecretKey generateAndPersistNewMacRandomizationSecret(int uid, String alias) { - try { - KeyGenerator keyGenerator = KeyGenerator.getInstance( - KeyProperties.KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore"); - keyGenerator.init( - new KeyGenParameterSpec.Builder(alias, - KeyProperties.PURPOSE_SIGN) - .setUid(uid) - .build()); - return keyGenerator.generateKey(); - } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException - | NoSuchProviderException | ProviderException e) { - Log.e(TAG, "Failure in generateMacRandomizationSecret", e); - return null; - } - } -} diff --git a/service/java/com/android/server/wifi/MboOceConstants.java b/service/java/com/android/server/wifi/MboOceConstants.java deleted file mode 100644 index 66948b030..000000000 --- a/service/java/com/android/server/wifi/MboOceConstants.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * MBO-OCE related constants - */ -public class MboOceConstants { - - public static final int MBO_OCE_ATTRIBUTE_NOT_PRESENT = -1; - - /** MBO-OCE attribute Ids */ - public static final int MBO_OCE_AID_MBO_AP_CAPABILITY_INDICATION = 0x01; - public static final int MBO_OCE_AID_NON_PREFERRED_CHANNEL_REPORT = 0x02; - public static final int MBO_OCE_AID_CELLULAR_DATA_CAPABILITIES = 0x03; - public static final int MBO_OCE_AID_ASSOCIATION_DISALLOWED = 0x04; - public static final int MBO_OCE_AID_CELLULAR_DATA_CONNECTION_PREFERENCE = 0x05; - public static final int MBO_OCE_AID_TRANSITION_REASON_CODE = 0x06; - public static final int MBO_OCE_AID_TRANSITION_REJECTION_REASON_CODE = 0x07; - public static final int MBO_OCE_AID_ASSOCIATION_RETRY_DELAY = 0x08; - public static final int MBO_OCE_AID_OCE_AP_CAPABILITY_INDICATION = 0x65; - public static final int MBO_OCE_AID_RSSI_BASED_ASSOCIATION_REJECTION = 0x66; - public static final int MBO_OCE_AID_REDUCED_WAN_METRICS = 0x67; - public static final int MBO_OCE_AID_RNR_COMPLETENESS = 0x68; - public static final int MBO_OCE_AID_PROBE_SUPPRESSION_BSSIDS = 0x69; - public static final int MBO_OCE_AID_PROBE_SUPPRESSION_SSIDS = 0x6A; - - @IntDef(prefix = { "MBO_OCE_AID_" }, value = { - MBO_OCE_AID_MBO_AP_CAPABILITY_INDICATION, - MBO_OCE_AID_NON_PREFERRED_CHANNEL_REPORT, - MBO_OCE_AID_CELLULAR_DATA_CAPABILITIES, - MBO_OCE_AID_ASSOCIATION_DISALLOWED, - MBO_OCE_AID_CELLULAR_DATA_CONNECTION_PREFERENCE, - MBO_OCE_AID_TRANSITION_REASON_CODE, - MBO_OCE_AID_TRANSITION_REJECTION_REASON_CODE, - MBO_OCE_AID_ASSOCIATION_RETRY_DELAY, - MBO_OCE_AID_OCE_AP_CAPABILITY_INDICATION, - MBO_OCE_AID_RSSI_BASED_ASSOCIATION_REJECTION, - MBO_OCE_AID_REDUCED_WAN_METRICS, - MBO_OCE_AID_RNR_COMPLETENESS, - MBO_OCE_AID_PROBE_SUPPRESSION_BSSIDS, - MBO_OCE_AID_PROBE_SUPPRESSION_SSIDS - }) - @Retention(RetentionPolicy.SOURCE) - @interface MboOceAid{} - - /** MBO spec v1.2, 4.2.1 Table 7: MBO AP Capability indication - Cellular data aware */ - public static final int MBO_AP_CAP_IND_ATTR_CELL_DATA_AWARE = 0x40; - - /** - * IEEE Std 802.11-2016 - Table 9-357. - * BTM status code filled in BSS transition management response frame. - */ - public static final int BTM_RESPONSE_STATUS_INVALID = -1; - public static final int BTM_RESPONSE_STATUS_ACCEPT = 0; - public static final int BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED = 1; - public static final int BTM_RESPONSE_STATUS_REJECT_INSUFFICIENT_BEACON = 2; - public static final int BTM_RESPONSE_STATUS_REJECT_INSUFFICIENT_CAPABITY = 3; - public static final int BTM_RESPONSE_STATUS_REJECT_BSS_TERMINATION_UNDESIRED = 4; - public static final int BTM_RESPONSE_STATUS_REJECT_BSS_TERMINATION_DELAY_REQUEST = 5; - public static final int BTM_RESPONSE_STATUS_REJECT_STA_CANDIDATE_LIST_PROVIDED = 6; - public static final int BTM_RESPONSE_STATUS_REJECT_NO_SUITABLE_CANDIDATES = 7; - public static final int BTM_RESPONSE_STATUS_REJECT_LEAVING_ESS = 8; - public static final int BTM_RESPONSE_STATUS_REJECT_RESERVED = 254; - - @IntDef(prefix = { "BTM_RESPONSE_STATUS_" }, value = { - BTM_RESPONSE_STATUS_INVALID, - BTM_RESPONSE_STATUS_ACCEPT, - BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED, - BTM_RESPONSE_STATUS_REJECT_INSUFFICIENT_BEACON, - BTM_RESPONSE_STATUS_REJECT_INSUFFICIENT_CAPABITY, - BTM_RESPONSE_STATUS_REJECT_BSS_TERMINATION_UNDESIRED, - BTM_RESPONSE_STATUS_REJECT_BSS_TERMINATION_DELAY_REQUEST, - BTM_RESPONSE_STATUS_REJECT_STA_CANDIDATE_LIST_PROVIDED, - BTM_RESPONSE_STATUS_REJECT_NO_SUITABLE_CANDIDATES, - BTM_RESPONSE_STATUS_REJECT_LEAVING_ESS, - BTM_RESPONSE_STATUS_REJECT_RESERVED - }) - @Retention(RetentionPolicy.SOURCE) - @interface BtmResponseStatus{} - - /** WNM request mode: Preferred candidate list included */ - public static final int BTM_DATA_FLAG_PREFERRED_CANDIDATE_LIST_INCLUDED = 1 << 0; - /** WNM request mode: Abridged */ - public static final int BTM_DATA_FLAG_MODE_ABRIDGED = 1 << 1; - /** WNM request mode: Disassociation Imminent */ - public static final int BTM_DATA_FLAG_DISASSOCIATION_IMMINENT = 1 << 2; - /** WNM request mode: BSS termination included */ - public static final int BTM_DATA_FLAG_BSS_TERMINATION_INCLUDED = 1 << 3; - /** WNM request mode: ESS Disassociation Imminent */ - public static final int BTM_DATA_FLAG_ESS_DISASSOCIATION_IMMINENT = 1 << 4; - /** MBO transition reason code included */ - public static final int BTM_DATA_FLAG_MBO_TRANSITION_REASON_CODE_INCLUDED = 1 << 5; - /** MBO transition reason code included */ - public static final int BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED = 1 << 6; - /** MBO cellular data connection preference value included */ - public static final int BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED = 1 << 7; - - @IntDef(flag = true, prefix = { "BTM_DATA_FLAG_" }, value = { - BTM_DATA_FLAG_PREFERRED_CANDIDATE_LIST_INCLUDED, - BTM_DATA_FLAG_MODE_ABRIDGED, - BTM_DATA_FLAG_DISASSOCIATION_IMMINENT, - BTM_DATA_FLAG_BSS_TERMINATION_INCLUDED, - BTM_DATA_FLAG_ESS_DISASSOCIATION_IMMINENT, - BTM_DATA_FLAG_MBO_TRANSITION_REASON_CODE_INCLUDED, - BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED, - BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED - }) - @Retention(RetentionPolicy.SOURCE) - @interface BtmDataFlag{} - - /** MBO spec v1.2, 4.2.6 Table 18: MBO transition reason attribute */ - public static final int MBO_TRANSITION_REASON_INVALID = -1; - public static final int MBO_TRANSITION_REASON_UNSPECIFIED = 0; - public static final int MBO_TRANSITION_REASON_EXCESSIVE_FRAME_LOSS = 1; - public static final int MBO_TRANSITION_REASON_EXCESSIVE_TRAFFIC_DELAY = 2; - public static final int MBO_TRANSITION_REASON_INSUFFICIENT_BANDWIDTH = 3; - public static final int MBO_TRANSITION_REASON_LOAD_BALANCING = 4; - public static final int MBO_TRANSITION_REASON_LOW_RSSI = 5; - public static final int MBO_TRANSITION_REASON_RX_EXCESSIVE_RETRIES = 6; - public static final int MBO_TRANSITION_REASON_HIGH_INTERFERENCE = 7; - public static final int MBO_TRANSITION_REASON_GRAY_ZONE = 8; - public static final int MBO_TRANSITION_REASON_TRANSITION_TO_PREMIUM_AP = 9; - public static final int MBO_TRANSITION_REASON_RESERVED = 254; - - @IntDef(prefix = { "MBO_TRANSITION_REASON_" }, value = { - MBO_TRANSITION_REASON_INVALID, - MBO_TRANSITION_REASON_UNSPECIFIED, - MBO_TRANSITION_REASON_EXCESSIVE_FRAME_LOSS, - MBO_TRANSITION_REASON_EXCESSIVE_TRAFFIC_DELAY, - MBO_TRANSITION_REASON_INSUFFICIENT_BANDWIDTH, - MBO_TRANSITION_REASON_LOAD_BALANCING, - MBO_TRANSITION_REASON_LOW_RSSI, - MBO_TRANSITION_REASON_RX_EXCESSIVE_RETRIES, - MBO_TRANSITION_REASON_HIGH_INTERFERENCE, - MBO_TRANSITION_REASON_GRAY_ZONE, - MBO_TRANSITION_REASON_TRANSITION_TO_PREMIUM_AP, - MBO_TRANSITION_REASON_RESERVED - }) - @Retention(RetentionPolicy.SOURCE) - @interface MboTransitionReason{} - - /** MBO spec v1.2, 4.2.5 Table 16: MBO Cellular data connection preference attribute values */ - public static final int MBO_CELLULAR_DATA_CONNECTION_INVALID = -1; - public static final int MBO_CELLULAR_DATA_CONNECTION_EXCLUDED = 0; - public static final int MBO_CELLULAR_DATA_CONNECTION_NOT_PREFERRED = 1; - public static final int MBO_CELLULAR_DATA_CONNECTION_RESERVED = 254; - public static final int MBO_CELLULAR_DATA_CONNECTION_PREFERRED = 255; - - @IntDef(prefix = { "MBO_CELLULAR_DATA_CONNECTION_" }, value = { - MBO_CELLULAR_DATA_CONNECTION_INVALID, - MBO_CELLULAR_DATA_CONNECTION_EXCLUDED, - MBO_CELLULAR_DATA_CONNECTION_NOT_PREFERRED, - MBO_CELLULAR_DATA_CONNECTION_RESERVED, - MBO_CELLULAR_DATA_CONNECTION_PREFERRED - }) - @Retention(RetentionPolicy.SOURCE) - @interface MboCellularDataConnectionPreference{} - - /** default Blocklist duration when AP doesn't advertise non zero MBO assoc retry delay */ - public static final long DEFAULT_BLOCKLIST_DURATION_MS = 300_000; // 5 minutes - -} diff --git a/service/java/com/android/server/wifi/MboOceController.java b/service/java/com/android/server/wifi/MboOceController.java deleted file mode 100644 index d71034d81..000000000 --- a/service/java/com/android/server/wifi/MboOceController.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO; -import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE; - -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; -import android.util.Log; - -/** - * MboOceController is responsible for controlling MBO and OCE operations. - */ -public class MboOceController { - private static final String TAG = "MboOceController"; - - /** State of MBO/OCE module. */ - private boolean mEnabled = false; - private boolean mIsMboSupported = false; - private boolean mIsOceSupported = false; - private boolean mVerboseLoggingEnabled = false; - - private final WifiNative mWifiNative; - private final TelephonyManager mTelephonyManager; - - /** - * Create new instance of MboOceController. - */ - public MboOceController(TelephonyManager telephonyManager, - WifiNative wifiNative) { - mTelephonyManager = telephonyManager; - mWifiNative = wifiNative; - } - - /** - * Enable MBO and OCE functionality. - */ - public void enable() { - String iface = mWifiNative.getClientInterfaceName(); - if (iface == null) { - return; - } - mIsMboSupported = (mWifiNative.getSupportedFeatureSet(iface) & WIFI_FEATURE_MBO) != 0; - mIsOceSupported = (mWifiNative.getSupportedFeatureSet(iface) & WIFI_FEATURE_OCE) != 0; - mEnabled = true; - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Enable MBO-OCE MBO support: " + mIsMboSupported - + " OCE support: " + mIsOceSupported); - } - if (mIsMboSupported) { - // Register for data connection state change events (Cellular). - mTelephonyManager.listen(mDataConnectionStateListener, - PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); - } - } - - /** - * Disable MBO and OCE functionality. - */ - public void disable() { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Disable MBO-OCE"); - } - if (mIsMboSupported) { - // Un-register for data connection state change events (Cellular). - mTelephonyManager.listen(mDataConnectionStateListener, PhoneStateListener.LISTEN_NONE); - } - mEnabled = false; - } - - /** - * Enable/Disable verbose logging. - * - * @param verbose true to enable and false to disable. - */ - public void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - } - - /** - * Listen for changes to the data connection state (Cellular). - */ - private PhoneStateListener mDataConnectionStateListener = new PhoneStateListener(){ - public void onDataConnectionStateChanged(int state, int networkType) { - boolean dataAvailable; - - String iface = mWifiNative.getClientInterfaceName(); - if (iface == null) { - return; - } - if (!mEnabled) { - Log.e(TAG, "onDataConnectionStateChanged called when MBO is disabled!!"); - return; - } - if (state == TelephonyManager.DATA_CONNECTED) { - dataAvailable = true; - } else if (state == TelephonyManager.DATA_DISCONNECTED) { - dataAvailable = false; - } else { - Log.e(TAG, "onDataConnectionStateChanged unexpected State: " + state); - return; - } - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Cell Data: " + dataAvailable); - } - mWifiNative.setMboCellularDataStatus(iface, dataAvailable); - } - }; - - /** - * BtmFrameData carries the data retried from received BTM - * request frame handled in supplicant. - */ - public static class BtmFrameData { - public @MboOceConstants.BtmResponseStatus int mStatus = - MboOceConstants.BTM_RESPONSE_STATUS_INVALID; - public int mBssTmDataFlagsMask = 0; - public long mBlockListDurationMs = 0; - public @MboOceConstants.MboTransitionReason int mTransitionReason = - MboOceConstants.MBO_TRANSITION_REASON_INVALID; - public @MboOceConstants.MboCellularDataConnectionPreference int mCellPreference = - MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_INVALID; - - @Override - public String toString() { - return new StringBuilder("BtmFrameData status=").append(mStatus).append( - ", flags=").append(mBssTmDataFlagsMask).append( - ", assocRetryDelay=").append(mBlockListDurationMs).append( - ", transitionReason=").append(mTransitionReason).append( - ", cellPref=").append(mCellPreference).toString(); - } - } -} diff --git a/service/java/com/android/server/wifi/MemoryStoreImpl.java b/service/java/com/android/server/wifi/MemoryStoreImpl.java deleted file mode 100644 index a15ae8106..000000000 --- a/service/java/com/android/server/wifi/MemoryStoreImpl.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.IpMemoryStore; -import android.net.ipmemorystore.Blob; -import android.net.ipmemorystore.NetworkAttributes; -import android.net.ipmemorystore.Status; -import android.util.Log; - -import com.android.internal.util.Preconditions; -import com.android.server.wifi.WifiScoreCard.BlobListener; - -import java.util.Objects; - -/** - * Connects WifiScoreCard to IpMemoryStore. - */ -final class MemoryStoreImpl implements WifiScoreCard.MemoryStore { - private static final String TAG = "WifiMemoryStoreImpl"; - private static final boolean DBG = true; - - // The id of the client that stored this data - public static final String WIFI_FRAMEWORK_IP_MEMORY_STORE_CLIENT_ID = "com.android.server.wifi"; - - @NonNull private final Context mContext; - @NonNull private final WifiScoreCard mWifiScoreCard; - @NonNull private final WifiHealthMonitor mWifiHealthMonitor; - @NonNull private final WifiInjector mWifiInjector; - @Nullable private IpMemoryStore mIpMemoryStore; - - MemoryStoreImpl(Context context, WifiInjector wifiInjector, WifiScoreCard wifiScoreCard, - WifiHealthMonitor wifiHealthMonitor) { - mContext = Preconditions.checkNotNull(context); - mWifiScoreCard = Preconditions.checkNotNull(wifiScoreCard); - mWifiHealthMonitor = Preconditions.checkNotNull(wifiHealthMonitor); - mWifiInjector = Preconditions.checkNotNull(wifiInjector); - mIpMemoryStore = null; - } - - private boolean mBroken = false; - private void handleException(Exception e) { - Log.wtf(TAG, "Exception using IpMemoryStore - disabling WifiScoreReport persistence", e); - mBroken = true; - } - - - @Override - public void read(final String key, final String name, final BlobListener blobListener) { - if (mBroken) return; - try { - mIpMemoryStore.retrieveBlob( - key, - WIFI_FRAMEWORK_IP_MEMORY_STORE_CLIENT_ID, - name, - new CatchAFallingBlob(key, blobListener)); - } catch (RuntimeException e) { - handleException(e); - } - } - - /** - * Listens for a reply to a read request. - * - * Note that onBlobRetrieved() is called on a binder thread, so the - * provided blobListener must be prepared to deal with this. - * - */ - private static class CatchAFallingBlob - implements android.net.ipmemorystore.OnBlobRetrievedListener { - private final String mL2Key; - private final WifiScoreCard.BlobListener mBlobListener; - - CatchAFallingBlob(String l2Key, WifiScoreCard.BlobListener blobListener) { - mL2Key = l2Key; - mBlobListener = blobListener; - } - - @Override - public void onBlobRetrieved(Status status, String l2Key, String name, Blob data) { - if (!Objects.equals(mL2Key, l2Key)) { - throw new IllegalArgumentException("l2Key does not match request"); - } - if (status.isSuccess()) { - if (data == null) { - if (DBG) Log.i(TAG, "Blob is null"); - mBlobListener.onBlobRetrieved(null); - return; - } - mBlobListener.onBlobRetrieved(data.data); - } else { - if (DBG) Log.e(TAG, "android.net.ipmemorystore.Status " + status); - } - } - } - - @Override - public void write(String key, String name, byte[] value) { - if (mBroken) return; - final Blob blob = new Blob(); - blob.data = value; - try { - mIpMemoryStore.storeBlob( - key, - WIFI_FRAMEWORK_IP_MEMORY_STORE_CLIENT_ID, - name, - blob, - null /* no listener for now, just fire and forget */); - } catch (RuntimeException e) { - handleException(e); - } - } - - @Override - public void setCluster(String key, String cluster) { - if (mBroken) return; - try { - NetworkAttributes attributes = new NetworkAttributes.Builder() - .setCluster(cluster) - .build(); - mIpMemoryStore.storeNetworkAttributes(key, attributes, status -> { - Log.d(TAG, "Set cluster " + cluster + " for " + key + ": " + status); - }); - } catch (RuntimeException e) { - handleException(e); - } - } - - @Override - public void removeCluster(String cluster) { - if (mBroken) return; - try { - final boolean needWipe = true; - mIpMemoryStore.deleteCluster(cluster, needWipe, (status, deletedRecords) -> { - Log.d(TAG, "Remove cluster " + cluster + ": " + status - + " deleted: " + deletedRecords); - }); - } catch (RuntimeException e) { - handleException(e); - } - } - - /** - * Starts using IpMemoryStore. - */ - public void start() { - if (mIpMemoryStore != null) { - Log.w(TAG, "Reconnecting to IpMemoryStore service"); - } - mIpMemoryStore = mWifiInjector.getIpMemoryStore(); - if (mIpMemoryStore == null) { - Log.e(TAG, "No IpMemoryStore service!"); - return; - } - mWifiScoreCard.installMemoryStore(this); - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(this); - } - - /** - * Stops using IpMemoryStore after performing any outstanding writes. - */ - public void stop() { - if (mIpMemoryStore == null) return; - mWifiScoreCard.doWrites(); - mWifiHealthMonitor.doWrites(); - // TODO - Should wait for writes to complete (or time out) - Log.i(TAG, "Disconnecting from IpMemoryStore service"); - mIpMemoryStore = null; - } - -} diff --git a/service/java/com/android/server/wifi/NetworkListSharedStoreData.java b/service/java/com/android/server/wifi/NetworkListSharedStoreData.java deleted file mode 100644 index 1b0dc5366..000000000 --- a/service/java/com/android/server/wifi/NetworkListSharedStoreData.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.content.Context; - -/** - * Serialization & Deserialization of shared WiFi network configurations. - */ -public class NetworkListSharedStoreData extends NetworkListStoreData { - - public NetworkListSharedStoreData(Context context) { - super(context); - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - // Shared general store. - return WifiConfigStore.STORE_FILE_SHARED_GENERAL; - } -} - diff --git a/service/java/com/android/server/wifi/NetworkListStoreData.java b/service/java/com/android/server/wifi/NetworkListStoreData.java deleted file mode 100644 index 95c3ba39a..000000000 --- a/service/java/com/android/server/wifi/NetworkListStoreData.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static com.android.server.wifi.WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION; - -import android.annotation.Nullable; -import android.content.Context; -import android.net.IpConfiguration; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; -import android.net.wifi.WifiEnterpriseConfig; -import android.os.Process; -import android.util.Log; -import android.util.Pair; - -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; -import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil; -import com.android.server.wifi.util.XmlUtil.NetworkSelectionStatusXmlUtil; -import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; -import com.android.server.wifi.util.XmlUtil.WifiEnterpriseConfigXmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * This class performs serialization and parsing of XML data block that contain the list of WiFi - * network configurations (XML block data inside <NetworkList> tag). - */ -public abstract class NetworkListStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "NetworkListStoreData"; - - private static final String XML_TAG_SECTION_HEADER_NETWORK_LIST = "NetworkList"; - private static final String XML_TAG_SECTION_HEADER_NETWORK = "Network"; - private static final String XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION = "WifiConfiguration"; - private static final String XML_TAG_SECTION_HEADER_NETWORK_STATUS = "NetworkStatus"; - private static final String XML_TAG_SECTION_HEADER_IP_CONFIGURATION = "IpConfiguration"; - private static final String XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION = - "WifiEnterpriseConfiguration"; - - private final Context mContext; - - /** - * List of saved shared networks visible to all the users to be stored in the store file. - */ - private List<WifiConfiguration> mConfigurations; - - NetworkListStoreData(Context context) { - mContext = context; - } - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - serializeNetworkList(out, mConfigurations, encryptionUtil); - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - // Ignore empty reads. - if (in == null) { - return; - } - mConfigurations = parseNetworkList(in, outerTagDepth, version, encryptionUtil); - } - - @Override - public void resetData() { - mConfigurations = null; - } - - @Override - public boolean hasNewDataToSerialize() { - // always persist. - return true; - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER_NETWORK_LIST; - } - - public void setConfigurations(List<WifiConfiguration> configs) { - mConfigurations = configs; - } - - /** - * An empty list will be returned if no shared configurations. - * - * @return List of {@link WifiConfiguration} - */ - public List<WifiConfiguration> getConfigurations() { - if (mConfigurations == null) { - return new ArrayList<WifiConfiguration>(); - } - return mConfigurations; - } - - /** - * Serialize the list of {@link WifiConfiguration} to an output stream in XML format. - * - * @param out The output stream to serialize the data to - * @param networkList The network list to serialize - * @param encryptionUtil Instance of {@link WifiConfigStoreEncryptionUtil} - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeNetworkList(XmlSerializer out, List<WifiConfiguration> networkList, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - if (networkList == null) { - return; - } - // Sort by SSID - Collections.sort(networkList, Comparator.comparing(a -> a.SSID)); - for (WifiConfiguration network : networkList) { - serializeNetwork(out, network, encryptionUtil); - } - } - - /** - * Serialize a {@link WifiConfiguration} to an output stream in XML format. - * - * @param out The output stream to serialize the data to - * @param config The network config to serialize - * @param encryptionUtil Instance of {@link WifiConfigStoreEncryptionUtil} - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeNetwork(XmlSerializer out, WifiConfiguration config, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK); - - // Serialize WifiConfiguration. - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - WifiConfigurationXmlUtil.writeToXmlForConfigStore(out, config, encryptionUtil); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - - // Serialize network selection status. - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_STATUS); - NetworkSelectionStatusXmlUtil.writeToXml(out, config.getNetworkSelectionStatus()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_STATUS); - - // Serialize IP configuration. - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION); - IpConfigurationXmlUtil.writeToXml(out, config.getIpConfiguration()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION); - - // Serialize enterprise configuration for enterprise networks. - if (config.enterpriseConfig != null - && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) { - XmlUtil.writeNextSectionStart( - out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); - WifiEnterpriseConfigXmlUtil.writeToXml(out, config.enterpriseConfig, encryptionUtil); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); - } - - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK); - } - - /** - * Parse a list of {@link WifiConfiguration} from an input stream in XML format. - * - * @param in The input stream to read from - * @param outerTagDepth The XML tag depth of the outer XML block - * @param version Version of config store file. - * @param encryptionUtil Instance of {@link WifiConfigStoreEncryptionUtil} - * @return List of {@link WifiConfiguration} - * @throws XmlPullParserException - * @throws IOException - */ - private List<WifiConfiguration> parseNetworkList(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - List<WifiConfiguration> networkList = new ArrayList<>(); - while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_NETWORK, - outerTagDepth)) { - // Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are - // fatal and should abort the entire loading process. - try { - WifiConfiguration config = - parseNetwork(in, outerTagDepth + 1, version, encryptionUtil); - networkList.add(config); - } catch (RuntimeException e) { - // Failed to parse this network, skip it. - Log.e(TAG, "Failed to parse network config. Skipping...", e); - } - } - return networkList; - } - - /** - * Parse a {@link WifiConfiguration} from an input stream in XML format. - * - * @param in The input stream to read from - * @param outerTagDepth The XML tag depth of the outer XML block - * @param version Version of config store file. - * @param encryptionUtil Instance of {@link WifiConfigStoreEncryptionUtil} - * @return {@link WifiConfiguration} - * @throws XmlPullParserException - * @throws IOException - */ - private WifiConfiguration parseNetwork(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - Pair<String, WifiConfiguration> parsedConfig = null; - NetworkSelectionStatus status = null; - IpConfiguration ipConfiguration = null; - WifiEnterpriseConfig enterpriseConfig = null; - - String[] headerName = new String[1]; - while (XmlUtil.gotoNextSectionOrEnd(in, headerName, outerTagDepth)) { - switch (headerName[0]) { - case XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION: - if (parsedConfig != null) { - throw new XmlPullParserException("Detected duplicate tag for: " - + XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - } - parsedConfig = WifiConfigurationXmlUtil.parseFromXml(in, outerTagDepth + 1, - version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - encryptionUtil); - break; - case XML_TAG_SECTION_HEADER_NETWORK_STATUS: - if (status != null) { - throw new XmlPullParserException("Detected duplicate tag for: " - + XML_TAG_SECTION_HEADER_NETWORK_STATUS); - } - status = NetworkSelectionStatusXmlUtil.parseFromXml(in, outerTagDepth + 1); - break; - case XML_TAG_SECTION_HEADER_IP_CONFIGURATION: - if (ipConfiguration != null) { - throw new XmlPullParserException("Detected duplicate tag for: " - + XML_TAG_SECTION_HEADER_IP_CONFIGURATION); - } - ipConfiguration = IpConfigurationXmlUtil.parseFromXml(in, outerTagDepth + 1); - break; - case XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION: - if (enterpriseConfig != null) { - throw new XmlPullParserException("Detected duplicate tag for: " - + XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); - } - enterpriseConfig = - WifiEnterpriseConfigXmlUtil.parseFromXml(in, outerTagDepth + 1, - version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - encryptionUtil); - break; - default: - Log.w(TAG, "Ignoring unknown tag under " + XML_TAG_SECTION_HEADER_NETWORK - + ": " + headerName[0]); - break; - } - } - if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) { - throw new XmlPullParserException("XML parsing of wifi configuration failed"); - } - String configKeyParsed = parsedConfig.first; - WifiConfiguration configuration = parsedConfig.second; - - if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { - fixSaeNetworkSecurityBits(configuration); - } - // b/153435438: Added to deal with badly formed WifiConfiguration from apps. - if (configuration.preSharedKey != null && !configuration.needsPreSharedKey()) { - Log.e(TAG, "preSharedKey set with an invalid KeyMgmt, resetting KeyMgmt to WPA_PSK"); - configuration.allowedKeyManagement.clear(); - configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - // Recreate configKey to pass the check below. - configKeyParsed = configuration.getKey(); - } - - String configKeyCalculated = configuration.getKey(); - if (!configKeyParsed.equals(configKeyCalculated)) { - throw new XmlPullParserException( - "Configuration key does not match. Retrieved: " + configKeyParsed - + ", Calculated: " + configKeyCalculated); - } - // Set creatorUid/creatorName for networks which don't have it set to valid value. - String creatorName = mContext.getPackageManager().getNameForUid(configuration.creatorUid); - if (creatorName == null) { - Log.e(TAG, "Invalid creatorUid for saved network " + configuration.getKey() - + ", creatorUid=" + configuration.creatorUid); - configuration.creatorUid = Process.SYSTEM_UID; - configuration.creatorName = - mContext.getPackageManager().getNameForUid(Process.SYSTEM_UID); - } else if (!creatorName.equals(configuration.creatorName)) { - Log.w(TAG, "Invalid creatorName for saved network " + configuration.getKey() - + ", creatorUid=" + configuration.creatorUid - + ", creatorName=" + configuration.creatorName); - configuration.creatorName = creatorName; - } - - configuration.setNetworkSelectionStatus(status); - configuration.setIpConfiguration(ipConfiguration); - if (enterpriseConfig != null) { - configuration.enterpriseConfig = enterpriseConfig; - } - return configuration; - } - - private void fixSaeNetworkSecurityBits(WifiConfiguration saeNetwork) { - // SAE saved networks Auth Algorithm set to OPEN need to be have this field cleared. - if (saeNetwork.allowedAuthAlgorithms.get(WifiConfiguration.AuthAlgorithm.OPEN)) { - saeNetwork.allowedAuthAlgorithms.clear(); - } - // SAE saved networks Pairwise Cipher with TKIP enabled need to be have this bit - // cleared. - if (saeNetwork.allowedPairwiseCiphers.get(WifiConfiguration.PairwiseCipher.TKIP)) { - saeNetwork.allowedPairwiseCiphers.clear(WifiConfiguration.PairwiseCipher.TKIP); - } - // SAE saved networks Protocols with WPA enabled need to be have this bit cleared. - if (saeNetwork.allowedProtocols.get(WifiConfiguration.Protocol.WPA)) { - saeNetwork.allowedProtocols.clear(WifiConfiguration.Protocol.WPA); - } - // SAE saved networks Group Ciphers with legacy ciphers enabled, need to be have these - // bits cleared. - if (saeNetwork.allowedGroupCiphers.get(WifiConfiguration.GroupCipher.WEP40)) { - saeNetwork.allowedGroupCiphers.clear(WifiConfiguration.GroupCipher.WEP40); - } - if (saeNetwork.allowedGroupCiphers.get(WifiConfiguration.GroupCipher.WEP104)) { - saeNetwork.allowedGroupCiphers.clear(WifiConfiguration.GroupCipher.WEP104); - } - if (saeNetwork.allowedGroupCiphers.get(WifiConfiguration.GroupCipher.TKIP)) { - saeNetwork.allowedGroupCiphers.clear(WifiConfiguration.GroupCipher.TKIP); - } - saeNetwork.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - saeNetwork.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - } -} - diff --git a/service/java/com/android/server/wifi/NetworkListUserStoreData.java b/service/java/com/android/server/wifi/NetworkListUserStoreData.java deleted file mode 100644 index c146c18f5..000000000 --- a/service/java/com/android/server/wifi/NetworkListUserStoreData.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.content.Context; - -/** - * Serialization & Deserialization of user specific WiFi network configurations. - */ -public class NetworkListUserStoreData extends NetworkListStoreData { - - public NetworkListUserStoreData(Context context) { - super(context); - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - // Shared general store. - return WifiConfigStore.STORE_FILE_USER_GENERAL; - } -} - diff --git a/service/java/com/android/server/wifi/NetworkRequestStoreData.java b/service/java/com/android/server/wifi/NetworkRequestStoreData.java deleted file mode 100644 index 763f267b9..000000000 --- a/service/java/com/android/server/wifi/NetworkRequestStoreData.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.annotation.Nullable; -import android.net.MacAddress; -import android.util.Log; - -import com.android.server.wifi.WifiNetworkFactory.AccessPoint; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; -import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * This class performs serialization and parsing of XML data block that contain the list of WiFi - * network request approvals. - */ -public class NetworkRequestStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "NetworkRequestStoreData"; - - private static final String XML_TAG_SECTION_HEADER_NETWORK_REQUEST_MAP = - "NetworkRequestMap"; - private static final String XML_TAG_SECTION_HEADER_APPROVED_ACCESS_POINTS_PER_APP = - "ApprovedAccessPointsPerApp"; - private static final String XML_TAG_REQUESTOR_PACKAGE_NAME = "RequestorPackageName"; - private static final String XML_TAG_SECTION_HEADER_ACCESS_POINT = "AccessPoint"; - private static final String XML_TAG_ACCESS_POINT_SSID = WifiConfigurationXmlUtil.XML_TAG_SSID; - private static final String XML_TAG_ACCESS_POINT_BSSID = WifiConfigurationXmlUtil.XML_TAG_BSSID; - private static final String XML_TAG_ACCESS_POINT_NETWORK_TYPE = "NetworkType"; - - /** - * Interface define the data source for the network requests store data. - */ - public interface DataSource { - /** - * Retrieve the approved access points from the data source to serialize them to disk. - * - * @return Map of package name to a set of {@link AccessPoint} - */ - Map<String, Set<AccessPoint>> toSerialize(); - - /** - * Set the approved access points in the data source after serializing them from disk. - * - * @param approvedAccessPoints Map of package name to {@link AccessPoint} - */ - void fromDeserialized(Map<String, Set<AccessPoint>> approvedAccessPoints); - - /** - * Clear internal data structure in preparation for user switch or initial store read. - */ - void reset(); - - /** - * Indicates whether there is new data to serialize. - */ - boolean hasNewDataToSerialize(); - } - - private final DataSource mDataSource; - - public NetworkRequestStoreData(DataSource dataSource) { - mDataSource = dataSource; - } - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - serializeApprovedAccessPointsMap(out, mDataSource.toSerialize()); - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - // Ignore empty reads. - if (in == null) { - return; - } - mDataSource.fromDeserialized(parseApprovedAccessPointsMap(in, outerTagDepth)); - } - - @Override - public void resetData() { - mDataSource.reset(); - } - - @Override - public boolean hasNewDataToSerialize() { - return mDataSource.hasNewDataToSerialize(); - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER_NETWORK_REQUEST_MAP; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - return WifiConfigStore.STORE_FILE_USER_GENERAL; - } - - /** - * Serialize the map of package name to approved access points to an output stream in XML - * format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeApprovedAccessPointsMap( - XmlSerializer out, final Map<String, Set<AccessPoint>> approvedAccessPointsMap) - throws XmlPullParserException, IOException { - if (approvedAccessPointsMap == null) { - return; - } - for (Entry<String, Set<AccessPoint>> entry : approvedAccessPointsMap.entrySet()) { - String packageName = entry.getKey(); - XmlUtil.writeNextSectionStart(out, - XML_TAG_SECTION_HEADER_APPROVED_ACCESS_POINTS_PER_APP); - XmlUtil.writeNextValue(out, XML_TAG_REQUESTOR_PACKAGE_NAME, packageName); - serializeApprovedAccessPoints(out, entry.getValue()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_APPROVED_ACCESS_POINTS_PER_APP); - } - } - - /** - * Serialize the set of approved access points to an output stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeApprovedAccessPoints( - XmlSerializer out, final Set<AccessPoint> approvedAccessPoints) - throws XmlPullParserException, IOException { - for (AccessPoint approvedAccessPoint : approvedAccessPoints) { - serializeApprovedAccessPoint(out, approvedAccessPoint); - } - } - - /** - * Serialize a {@link AccessPoint} to an output stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeApprovedAccessPoint(XmlSerializer out, - AccessPoint approvedAccessPoint) - throws XmlPullParserException, IOException { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_ACCESS_POINT); - XmlUtil.writeNextValue(out, XML_TAG_ACCESS_POINT_SSID, approvedAccessPoint.ssid); - XmlUtil.writeNextValue(out, XML_TAG_ACCESS_POINT_BSSID, - approvedAccessPoint.bssid.toString()); - XmlUtil.writeNextValue(out, XML_TAG_ACCESS_POINT_NETWORK_TYPE, - approvedAccessPoint.networkType); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_ACCESS_POINT); - } - - /** - * Parse a map of package name to approved access point from an input stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private Map<String, Set<AccessPoint>> parseApprovedAccessPointsMap(XmlPullParser in, - int outerTagDepth) - throws XmlPullParserException, IOException { - Map<String, Set<AccessPoint>> approvedAccessPointsMap = new HashMap<>(); - while (XmlUtil.gotoNextSectionWithNameOrEnd( - in, XML_TAG_SECTION_HEADER_APPROVED_ACCESS_POINTS_PER_APP, outerTagDepth)) { - // Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are - // fatal and should abort the entire loading process. - try { - String packageName = - (String) XmlUtil.readNextValueWithName(in, XML_TAG_REQUESTOR_PACKAGE_NAME); - Set<AccessPoint> approvedAccessPoints = - parseApprovedAccessPoints(in, outerTagDepth + 1); - approvedAccessPointsMap.put(packageName, approvedAccessPoints); - } catch (RuntimeException e) { - // Failed to parse this network, skip it. - Log.e(TAG, "Failed to parse network suggestion. Skipping...", e); - } - } - return approvedAccessPointsMap; - } - - /** - * Parse a set of approved access points from an input stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private Set<AccessPoint> parseApprovedAccessPoints(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - Set<AccessPoint> approvedAccessPoints = new LinkedHashSet<>(); - while (XmlUtil.gotoNextSectionWithNameOrEnd( - in, XML_TAG_SECTION_HEADER_ACCESS_POINT, outerTagDepth)) { - // Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are - // fatal and should abort the entire loading process. - try { - AccessPoint approvedAccessPoint = - parseApprovedAccessPoint(in, outerTagDepth + 1); - approvedAccessPoints.add(approvedAccessPoint); - } catch (RuntimeException e) { - // Failed to parse this network, skip it. - Log.e(TAG, "Failed to parse network suggestion. Skipping...", e); - } - } - return approvedAccessPoints; - } - - /** - * Parse a {@link AccessPoint} from an input stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private AccessPoint parseApprovedAccessPoint(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - String ssid = null; - MacAddress bssid = null; - int networkType = -1; - - // Loop through and parse out all the elements from the stream within this section. - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_ACCESS_POINT_SSID: - ssid = (String) value; - break; - case XML_TAG_ACCESS_POINT_BSSID: - bssid = MacAddress.fromString((String) value); - break; - case XML_TAG_ACCESS_POINT_NETWORK_TYPE: - networkType = (int) value; - break; - default: - Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); - break; - } - } - if (ssid == null) { - throw new XmlPullParserException("XML parsing of ssid failed"); - } - if (bssid == null) { - throw new XmlPullParserException("XML parsing of bssid failed"); - } - if (networkType == -1) { - throw new XmlPullParserException("XML parsing of network type failed"); - } - return new AccessPoint(ssid, bssid, networkType); - } -} - diff --git a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java deleted file mode 100644 index 8c901cff9..000000000 --- a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.annotation.NonNull; -import android.net.wifi.WifiConfiguration; -import android.util.LocalLog; -import android.util.Log; -import android.util.Pair; - -import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; -import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.annotation.Nullable; -import javax.annotation.concurrent.NotThreadSafe; - -/** - * Nominator nominate the highest available suggestion candidates. - * Note: - * <li> This class is not thread safe and meant to be used only from {@link WifiNetworkSelector}. - * </li> - * - */ -@NotThreadSafe -public class NetworkSuggestionNominator implements WifiNetworkSelector.NetworkNominator { - private static final String TAG = "NetworkSuggestionNominator"; - - private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private final WifiConfigManager mWifiConfigManager; - private final PasspointNetworkNominateHelper mPasspointNetworkNominateHelper; - private final LocalLog mLocalLog; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - - NetworkSuggestionNominator(WifiNetworkSuggestionsManager networkSuggestionsManager, - WifiConfigManager wifiConfigManager, PasspointNetworkNominateHelper nominateHelper, - LocalLog localLog, WifiCarrierInfoManager wifiCarrierInfoManager) { - mWifiNetworkSuggestionsManager = networkSuggestionsManager; - mWifiConfigManager = wifiConfigManager; - mPasspointNetworkNominateHelper = nominateHelper; - mLocalLog = localLog; - mWifiCarrierInfoManager = wifiCarrierInfoManager; - } - - @Override - public void update(List<ScanDetail> scanDetails) { - // TODO(b/115504887): This could be used to re-evaluate any temporary blacklists. - } - - @Override - public void nominateNetworks(List<ScanDetail> scanDetails, - WifiConfiguration currentNetwork, String currentBssid, boolean connected, - boolean untrustedNetworkAllowed, - @NonNull OnConnectableListener onConnectableListener) { - if (scanDetails.isEmpty()) { - return; - } - MatchMetaInfo matchMetaInfo = new MatchMetaInfo(); - Set<ExtendedWifiNetworkSuggestion> autoJoinDisabledSuggestions = new HashSet<>(); - - findMatchedPasspointSuggestionNetworks(scanDetails, matchMetaInfo, untrustedNetworkAllowed); - findMatchedSuggestionNetworks(scanDetails, matchMetaInfo, - autoJoinDisabledSuggestions, untrustedNetworkAllowed); - - if (matchMetaInfo.isEmpty()) { - mLocalLog.log("did not see any matching auto-join enabled network suggestions."); - } else { - matchMetaInfo.findConnectableNetworksAndHighestPriority(onConnectableListener); - } - - addAutojoinDisabledSuggestionToWifiConfigManager(autoJoinDisabledSuggestions); - } - - private void findMatchedPasspointSuggestionNetworks(List<ScanDetail> scanDetails, - MatchMetaInfo matchMetaInfo, boolean untrustedNetworkAllowed) { - List<Pair<ScanDetail, WifiConfiguration>> candidates = - mPasspointNetworkNominateHelper.getPasspointNetworkCandidates(scanDetails, true); - for (Pair<ScanDetail, WifiConfiguration> candidate : candidates) { - WifiConfiguration config = candidate.second; - Set<ExtendedWifiNetworkSuggestion> matchingPasspointExtSuggestions = - mWifiNetworkSuggestionsManager - .getNetworkSuggestionsForFqdn(config.FQDN); - if (matchingPasspointExtSuggestions == null - || matchingPasspointExtSuggestions.isEmpty()) { - mLocalLog.log("Suggestion is missing for passpoint: " + config.FQDN); - continue; - } - - if (WifiConfiguration.isMetered(config, null) - && mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)) { - continue; - } - if (!isSimBasedNetworkAvailableToAutoConnect(config)) { - continue; - } - // If untrusted network is not allowed, ignore untrusted suggestion. - if (!untrustedNetworkAllowed && !config.trusted) { - continue; - } - Set<ExtendedWifiNetworkSuggestion> autoJoinEnabledExtSuggestions = - matchingPasspointExtSuggestions.stream() - .filter(ewns -> ewns.isAutojoinEnabled) - .collect(Collectors.toSet()); - if (autoJoinEnabledExtSuggestions.isEmpty()) { - continue; - } - - matchMetaInfo.putAll(autoJoinEnabledExtSuggestions, - config, candidate.first); - } - } - - private void findMatchedSuggestionNetworks(List<ScanDetail> scanDetails, - MatchMetaInfo matchMetaInfo, - Set<ExtendedWifiNetworkSuggestion> autoJoinDisabledSuggestions, - boolean untrustedNetworkAllowed) { - for (ScanDetail scanDetail : scanDetails) { - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - if (matchingExtNetworkSuggestions == null || matchingExtNetworkSuggestions.isEmpty()) { - continue; - } - Set<ExtendedWifiNetworkSuggestion> autojoinEnableSuggestions = new HashSet<>(); - for (ExtendedWifiNetworkSuggestion ewns : matchingExtNetworkSuggestions) { - // Ignore insecure enterprise config. - if (ewns.wns.wifiConfiguration.isEnterprise() - && ewns.wns.wifiConfiguration.enterpriseConfig.isInsecure()) { - continue; - } - // If untrusted network is not allowed, ignore untrusted suggestion. - WifiConfiguration config = ewns.wns.wifiConfiguration; - if (!untrustedNetworkAllowed && !config.trusted) { - continue; - } - if (WifiConfiguration.isMetered(config, null) - && mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)) { - continue; - } - if (!ewns.isAutojoinEnabled - || !isSimBasedNetworkAvailableToAutoConnect(config)) { - autoJoinDisabledSuggestions.add(ewns); - continue; - } - if (mWifiConfigManager.isNetworkTemporarilyDisabledByUser(config.SSID)) { - mLocalLog.log("Ignoring user disabled SSID: " - + config.SSID); - autoJoinDisabledSuggestions.add(ewns); - continue; - } - autojoinEnableSuggestions.add(ewns); - } - - if (autojoinEnableSuggestions.isEmpty()) { - continue; - } - // All matching suggestions have the same network credentials type. So, use any one of - // them to lookup/add the credentials to WifiConfigManager. - // Note: Apps could provide different credentials (password, ceritificate) for the same - // network, need to handle that in the future. - String configKey = autojoinEnableSuggestions.stream().findAny().get() - .wns.wifiConfiguration.getKey(); - // Check if we already have a network with the same credentials in WifiConfigManager - // database. - WifiConfiguration wCmConfiguredNetwork = - mWifiConfigManager.getConfiguredNetwork(configKey); - if (wCmConfiguredNetwork != null) { - // If existing network is not from suggestion, ignore. - if (!(wCmConfiguredNetwork.fromWifiNetworkSuggestion - && wCmConfiguredNetwork.allowAutojoin)) { - continue; - } - int creatorUid = wCmConfiguredNetwork.creatorUid; - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestionsFromSamePackage = - autojoinEnableSuggestions.stream() - .filter(ewns -> ewns.perAppInfo.uid == creatorUid) - .collect(Collectors.toSet()); - if (matchingExtNetworkSuggestionsFromSamePackage.isEmpty()) { - continue; - } - // If the network is currently blacklisted, ignore. - if (!wCmConfiguredNetwork.getNetworkSelectionStatus().isNetworkEnabled() - && !mWifiConfigManager.tryEnableNetwork(wCmConfiguredNetwork.networkId)) { - mLocalLog.log("Ignoring blacklisted network: " - + WifiNetworkSelector.toNetworkString(wCmConfiguredNetwork)); - continue; - } - matchingExtNetworkSuggestions = matchingExtNetworkSuggestionsFromSamePackage; - } - matchMetaInfo.putAll(matchingExtNetworkSuggestions, wCmConfiguredNetwork, scanDetail); - } - } - - private boolean isSimBasedNetworkAvailableToAutoConnect(WifiConfiguration config) { - if (config.enterpriseConfig == null - || !config.enterpriseConfig.isAuthenticationSimBased()) { - return true; - } - int subId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config); - if (!mWifiCarrierInfoManager.isSimPresent(subId)) { - mLocalLog.log("SIM is not present for subId: " + subId); - return false; - } - if (mWifiCarrierInfoManager.requiresImsiEncryption(subId)) { - return mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(subId); - } - return true; - } - - // Add auto-join disabled suggestions also to WifiConfigManager if the app allows credential - // sharing.This will surface these networks on the UI, to allow the user manually connect to it. - private void addAutojoinDisabledSuggestionToWifiConfigManager( - Set<ExtendedWifiNetworkSuggestion> autoJoinDisabledSuggestions) { - for (ExtendedWifiNetworkSuggestion ewns : autoJoinDisabledSuggestions) { - if (!ewns.wns.isUserAllowedToManuallyConnect) { - continue; - } - WifiConfiguration config = ewns.createInternalWifiConfiguration(); - WifiConfiguration wCmConfiguredNetwork = - mWifiConfigManager.getConfiguredNetwork(config.getKey()); - NetworkUpdateResult result = mWifiConfigManager.addOrUpdateNetwork( - config, ewns.perAppInfo.uid, ewns.perAppInfo.packageName); - if (!result.isSuccess()) { - mLocalLog.log("Failed to add network suggestion"); - continue; - } - mWifiConfigManager.allowAutojoin(result.getNetworkId(), config.allowAutojoin); - WifiConfiguration currentWCmConfiguredNetwork = - mWifiConfigManager.getConfiguredNetwork(result.netId); - // Try to enable network selection - if (wCmConfiguredNetwork == null) { - if (!mWifiConfigManager.updateNetworkSelectionStatus(result.getNetworkId(), - WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE)) { - mLocalLog.log("Failed to make network suggestion selectable"); - } - } else { - if (!currentWCmConfiguredNetwork.getNetworkSelectionStatus().isNetworkEnabled() - && !mWifiConfigManager.tryEnableNetwork(wCmConfiguredNetwork.networkId)) { - mLocalLog.log("Ignoring blacklisted network: " - + WifiNetworkSelector.toNetworkString(wCmConfiguredNetwork)); - } - } - } - } - - // Add and enable this network to the central database (i.e WifiConfigManager). - // Returns the copy of WifiConfiguration with the allocated network ID filled in. - private WifiConfiguration addCandidateToWifiConfigManager( - @NonNull ExtendedWifiNetworkSuggestion ewns) { - WifiConfiguration wifiConfiguration = ewns.createInternalWifiConfiguration(); - NetworkUpdateResult result = - mWifiConfigManager.addOrUpdateNetwork(wifiConfiguration, ewns.perAppInfo.uid, - ewns.perAppInfo.packageName); - if (!result.isSuccess()) { - mLocalLog.log("Failed to add network suggestion"); - return null; - } - mWifiConfigManager.allowAutojoin(result.getNetworkId(), wifiConfiguration.allowAutojoin); - if (!mWifiConfigManager.updateNetworkSelectionStatus(result.getNetworkId(), - WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE)) { - mLocalLog.log("Failed to make network suggestion selectable"); - return null; - } - int candidateNetworkId = result.getNetworkId(); - return mWifiConfigManager.getConfiguredNetwork(candidateNetworkId); - } - - @Override - public @NominatorId int getId() { - return NOMINATOR_ID_SUGGESTION; - } - - @Override - public String getName() { - return TAG; - } - - // Container classes to handle book-keeping while we're iterating through the scan list. - private class PerNetworkSuggestionMatchMetaInfo { - public final ExtendedWifiNetworkSuggestion extWifiNetworkSuggestion; - public final ScanDetail matchingScanDetail; - public WifiConfiguration wCmConfiguredNetwork; // Added to WifiConfigManager. - - PerNetworkSuggestionMatchMetaInfo( - @NonNull ExtendedWifiNetworkSuggestion extWifiNetworkSuggestion, - @Nullable WifiConfiguration wCmConfiguredNetwork, - @NonNull ScanDetail matchingScanDetail) { - this.extWifiNetworkSuggestion = extWifiNetworkSuggestion; - this.wCmConfiguredNetwork = wCmConfiguredNetwork; - this.matchingScanDetail = matchingScanDetail; - } - } - - private class PerAppMatchMetaInfo { - public final List<PerNetworkSuggestionMatchMetaInfo> networkInfos = new ArrayList<>(); - - /** - * Add the network suggestion & associated info to this package meta info. - */ - public void put(ExtendedWifiNetworkSuggestion wifiNetworkSuggestion, - WifiConfiguration matchingWifiConfiguration, - ScanDetail matchingScanDetail) { - networkInfos.add(new PerNetworkSuggestionMatchMetaInfo( - wifiNetworkSuggestion, matchingWifiConfiguration, matchingScanDetail)); - } - - /** - * Pick the highest priority networks among the current match info candidates for this - * app. - */ - public List<PerNetworkSuggestionMatchMetaInfo> getHighestPriorityNetworks() { - // Partition the list to a map of network suggestions keyed in by the priorities. - // There can be multiple networks with the same priority, hence a list in the value. - Map<Integer, List<PerNetworkSuggestionMatchMetaInfo>> matchedNetworkInfosPerPriority = - networkInfos.stream() - .collect(Collectors.toMap( - e -> e.extWifiNetworkSuggestion.wns.wifiConfiguration.priority, - e -> Arrays.asList(e), - (v1, v2) -> { // concatenate networks with the same priority. - List<PerNetworkSuggestionMatchMetaInfo> concatList = - new ArrayList<>(v1); - concatList.addAll(v2); - return concatList; - })); - if (matchedNetworkInfosPerPriority.isEmpty()) { // should never happen. - Log.wtf(TAG, "Unexepectedly got empty"); - return Collections.EMPTY_LIST; - } - // Return the list associated with the highest priority value. - return matchedNetworkInfosPerPriority.get(Collections.max( - matchedNetworkInfosPerPriority.keySet())); - } - } - - private class MatchMetaInfo { - private Map<String, PerAppMatchMetaInfo> mAppInfos = new HashMap<>(); - - /** - * Add all the network suggestion & associated info. - */ - public void putAll(Set<ExtendedWifiNetworkSuggestion> wifiNetworkSuggestions, - WifiConfiguration wCmConfiguredNetwork, - ScanDetail matchingScanDetail) { - // Separate the suggestions into buckets for each app to allow sorting based on - // priorities set by app. - for (ExtendedWifiNetworkSuggestion wifiNetworkSuggestion : wifiNetworkSuggestions) { - PerAppMatchMetaInfo appInfo = mAppInfos.computeIfAbsent( - wifiNetworkSuggestion.perAppInfo.packageName, - k -> new PerAppMatchMetaInfo()); - appInfo.put(wifiNetworkSuggestion, wCmConfiguredNetwork, matchingScanDetail); - } - } - - /** - * Are there any matched candidates? - */ - public boolean isEmpty() { - return mAppInfos.isEmpty(); - } - - /** - * Run through all connectable suggestions and nominate highest priority networks from each - * app as candidates to {@link WifiNetworkSelector}. - */ - public void findConnectableNetworksAndHighestPriority( - @NonNull OnConnectableListener onConnectableListener) { - for (PerAppMatchMetaInfo appInfo : mAppInfos.values()) { - List<PerNetworkSuggestionMatchMetaInfo> matchedNetworkInfos = - appInfo.getHighestPriorityNetworks(); - for (PerNetworkSuggestionMatchMetaInfo matchedNetworkInfo : matchedNetworkInfos) { - // if the network does not already exist in WifiConfigManager, add now. - if (matchedNetworkInfo.wCmConfiguredNetwork == null) { - matchedNetworkInfo.wCmConfiguredNetwork = addCandidateToWifiConfigManager( - matchedNetworkInfo.extWifiNetworkSuggestion); - if (matchedNetworkInfo.wCmConfiguredNetwork == null) continue; - mLocalLog.log(String.format("network suggestion candidate %s (new)", - WifiNetworkSelector.toNetworkString( - matchedNetworkInfo.wCmConfiguredNetwork))); - } else { - mLocalLog.log(String.format("network suggestion candidate %s (existing)", - WifiNetworkSelector.toNetworkString( - matchedNetworkInfo.wCmConfiguredNetwork))); - } - onConnectableListener.onConnectable( - matchedNetworkInfo.matchingScanDetail, - matchedNetworkInfo.wCmConfiguredNetwork); - } - } - } - } - -} diff --git a/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java b/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java deleted file mode 100644 index 11067f62c..000000000 --- a/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static com.android.server.wifi.WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION; - -import android.annotation.Nullable; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.Process; -import android.telephony.TelephonyManager; -import android.util.Log; -import android.util.Pair; - -import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; -import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo; -import com.android.server.wifi.hotspot2.PasspointXmlUtils; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; -import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * This class performs serialization and parsing of XML data block that contain the list of WiFi - * network suggestions. - */ -public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "NetworkSuggestionStoreData"; - - private static final String XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_MAP = - "NetworkSuggestionMap"; - private static final String XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP = - "NetworkSuggestionPerApp"; - private static final String XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION = "NetworkSuggestion"; - private static final String XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION = "WifiConfiguration"; - private static final String XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION = - "WifiEnterpriseConfiguration"; - private static final String XML_TAG_IS_APP_INTERACTION_REQUIRED = "IsAppInteractionRequired"; - private static final String XML_TAG_IS_USER_INTERACTION_REQUIRED = "IsUserInteractionRequired"; - private static final String XML_TAG_IS_USER_ALLOWED_TO_MANUALLY_CONNECT = - "IsUserAllowedToManuallyConnect"; - private static final String XML_TAG_IS_INITIALIZED_AUTO_JOIN = "InitializedAutoJoinEnabled"; - private static final String XML_TAG_IS_AUTO_JOIN = "AutoJoinEnabled"; - private static final String XML_TAG_SUGGESTOR_UID = "SuggestorUid"; - private static final String XML_TAG_SUGGESTOR_PACKAGE_NAME = "SuggestorPackageName"; - private static final String XML_TAG_SUGGESTOR_FEATURE_ID = "SuggestorFeatureId"; - private static final String XML_TAG_SUGGESTOR_HAS_USER_APPROVED = "SuggestorHasUserApproved"; - private static final String XML_TAG_SUGGESTOR_CARRIER_ID = "SuggestorCarrierId"; - private static final String XML_TAG_SUGGESTOR_MAX_SIZE = "SuggestorMaxSize"; - private static final String XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION = - "PasspointConfiguration"; - - /** - * Interface define the data source for the network suggestions store data. - */ - public interface DataSource { - /** - * Retrieve the network suggestion list from the data source to serialize them to disk. - * - * @return Map of package name to {@link PerAppInfo} - */ - Map<String, PerAppInfo> toSerialize(); - - /** - * Set the network suggestions list in the data source after serializing them from disk. - * - * @param networkSuggestions Map of package name to {@link PerAppInfo} - */ - void fromDeserialized(Map<String, PerAppInfo> networkSuggestions); - - /** - * Clear internal data structure in preparation for user switch or initial store read. - */ - void reset(); - - /** - * Indicates whether there is new data to serialize. - */ - boolean hasNewDataToSerialize(); - } - - private final DataSource mDataSource; - - public NetworkSuggestionStoreData(DataSource dataSource) { - mDataSource = dataSource; - } - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - serializeNetworkSuggestionsMap(out, mDataSource.toSerialize(), encryptionUtil); - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - if (in == null) { - mDataSource.fromDeserialized(Collections.EMPTY_MAP); - return; - } - mDataSource.fromDeserialized( - parseNetworkSuggestionsMap(in, outerTagDepth, version, encryptionUtil)); - } - - @Override - public void resetData() { - mDataSource.reset(); - } - - @Override - public boolean hasNewDataToSerialize() { - return mDataSource.hasNewDataToSerialize(); - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_MAP; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - return WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS; - } - - /** - * Serialize the map of package name to network suggestions to an output stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeNetworkSuggestionsMap( - XmlSerializer out, final Map<String, PerAppInfo> networkSuggestionsMap, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - if (networkSuggestionsMap == null) { - return; - } - for (Entry<String, PerAppInfo> entry : networkSuggestionsMap.entrySet()) { - String packageName = entry.getValue().packageName; - String featureId = entry.getValue().featureId; - boolean hasUserApproved = entry.getValue().hasUserApproved; - int maxSize = entry.getValue().maxSize; - int uid = entry.getValue().uid; - int carrierId = entry.getValue().carrierId; - Set<ExtendedWifiNetworkSuggestion> networkSuggestions = - entry.getValue().extNetworkSuggestions; - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP); - XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_PACKAGE_NAME, packageName); - XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_FEATURE_ID, featureId); - XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_HAS_USER_APPROVED, hasUserApproved); - XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_MAX_SIZE, maxSize); - XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_UID, uid); - XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_CARRIER_ID, carrierId); - serializeExtNetworkSuggestions(out, networkSuggestions, encryptionUtil); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP); - } - } - - /** - * Serialize the set of network suggestions to an output stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeExtNetworkSuggestions( - XmlSerializer out, final Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - for (ExtendedWifiNetworkSuggestion extNetworkSuggestion : extNetworkSuggestions) { - serializeNetworkSuggestion(out, extNetworkSuggestion, encryptionUtil); - } - } - - /** - * Serialize a {@link ExtendedWifiNetworkSuggestion} to an output stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeNetworkSuggestion(XmlSerializer out, - final ExtendedWifiNetworkSuggestion extSuggestion, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - WifiNetworkSuggestion suggestion = extSuggestion.wns; - - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION); - - // Serialize WifiConfiguration. - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - WifiConfigurationXmlUtil.writeToXmlForConfigStore( - out, suggestion.wifiConfiguration, encryptionUtil); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - // Serialize enterprise configuration for enterprise networks. - if (suggestion.wifiConfiguration.enterpriseConfig != null - && suggestion.wifiConfiguration.enterpriseConfig.getEapMethod() - != WifiEnterpriseConfig.Eap.NONE) { - XmlUtil.writeNextSectionStart( - out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); - XmlUtil.WifiEnterpriseConfigXmlUtil.writeToXml( - out, suggestion.wifiConfiguration.enterpriseConfig, encryptionUtil); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); - } - if (suggestion.passpointConfiguration != null) { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION); - PasspointXmlUtils.serializePasspointConfiguration(out, - suggestion.passpointConfiguration); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION); - } - - // Serialize other fields - XmlUtil.writeNextValue(out, XML_TAG_IS_APP_INTERACTION_REQUIRED, - suggestion.isAppInteractionRequired); - XmlUtil.writeNextValue(out, XML_TAG_IS_USER_INTERACTION_REQUIRED, - suggestion.isUserInteractionRequired); - XmlUtil.writeNextValue(out, XML_TAG_IS_USER_ALLOWED_TO_MANUALLY_CONNECT, - suggestion.isUserAllowedToManuallyConnect); - XmlUtil.writeNextValue(out, XML_TAG_IS_INITIALIZED_AUTO_JOIN, - suggestion.isInitialAutoJoinEnabled); - XmlUtil.writeNextValue(out, XML_TAG_IS_AUTO_JOIN, - extSuggestion.isAutojoinEnabled); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION); - } - - /** - * Parse a map of package name to network suggestions from an input stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private Map<String, PerAppInfo> parseNetworkSuggestionsMap(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - Map<String, PerAppInfo> networkSuggestionsMap = new HashMap<>(); - while (XmlUtil.gotoNextSectionWithNameOrEnd( - in, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP, outerTagDepth)) { - // Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are - // fatal and should abort the entire loading process. - try { - PerAppInfo perAppInfo = null; - String packageName = null; - String featureId = null; - boolean hasUserApproved = false; - int maxSize = -1; - int uid = Process.INVALID_UID; - int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; - // Loop through and parse out all the elements from the stream within this section. - while (XmlUtil.nextElementWithin(in, outerTagDepth + 1)) { - if (in.getAttributeValue(null, "name") != null) { - // Value elements. - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - switch (valueName[0]) { - case XML_TAG_SUGGESTOR_PACKAGE_NAME: - packageName = (String) value; - break; - case XML_TAG_SUGGESTOR_FEATURE_ID: - featureId = (String) value; - break; - case XML_TAG_SUGGESTOR_HAS_USER_APPROVED: - hasUserApproved = (boolean) value; - break; - case XML_TAG_SUGGESTOR_MAX_SIZE: - maxSize = (int) value; - break; - case XML_TAG_SUGGESTOR_UID: - uid = (int) value; - break; - case XML_TAG_SUGGESTOR_CARRIER_ID: - carrierId = (int) value; - break; - default: - Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); - break; - } - } else { - String tagName = in.getName(); - if (tagName == null) { - throw new XmlPullParserException("Unexpected null under " - + XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP); - } - // Create the PerAppInfo struct before parsing individual network - // suggestions in the block. - if (perAppInfo == null) { - if (packageName == null) { - throw new XmlPullParserException( - "XML parsing of PerAppInfo failed"); - } - perAppInfo = new PerAppInfo(uid, packageName, featureId); - perAppInfo.hasUserApproved = hasUserApproved; - perAppInfo.maxSize = maxSize; - perAppInfo.carrierId = carrierId; - } - switch (tagName) { - case XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION: - Pair<WifiNetworkSuggestion, Boolean> networkSuggestionData = - parseNetworkSuggestion( - in, outerTagDepth + 2, version, encryptionUtil, - perAppInfo); - perAppInfo.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns( - networkSuggestionData.first, perAppInfo, - networkSuggestionData.second)); - break; - default: - Log.w(TAG, "Ignoring unknown tag under " - + XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP + ": " - + in.getName()); - break; - } - } - } - // If app has no suggestions, create perAppInfo here. - if (perAppInfo == null) { - if (packageName == null) { - throw new XmlPullParserException( - "XML parsing of PerAppInfo failed"); - } - perAppInfo = new PerAppInfo(uid, packageName, featureId); - perAppInfo.hasUserApproved = hasUserApproved; - perAppInfo.maxSize = maxSize; - } - // Store this app info in the map. - networkSuggestionsMap.put(packageName, perAppInfo); - } catch (RuntimeException e) { - // Failed to parse this network, skip it. - Log.e(TAG, "Failed to parse network suggestion. Skipping...", e); - } - } - return networkSuggestionsMap; - } - - /** - * Parse a {@link ExtendedWifiNetworkSuggestion} from an input stream in XML format. - * - * @throws XmlPullParserException - * @throws IOException - */ - private Pair<WifiNetworkSuggestion, Boolean> parseNetworkSuggestion(XmlPullParser in, - int outerTagDepth, @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, PerAppInfo perAppInfo) - throws XmlPullParserException, IOException { - Pair<String, WifiConfiguration> parsedConfig = null; - WifiEnterpriseConfig enterpriseConfig = null; - PasspointConfiguration passpointConfiguration = null; - boolean isAppInteractionRequired = false; - boolean isUserInteractionRequired = false; - boolean isUserAllowedToManuallyConnect = false; // Backward compatibility. - boolean isInitializedAutoJoinEnabled = true; // backward compat - boolean isAutoJoinEnabled = true; // backward compat - boolean isNetworkUntrusted = false; - int suggestorUid = Process.INVALID_UID; - - // Loop through and parse out all the elements from the stream within this section. - while (XmlUtil.nextElementWithin(in, outerTagDepth)) { - if (in.getAttributeValue(null, "name") != null) { - // Value elements. - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - switch (valueName[0]) { - case XML_TAG_IS_APP_INTERACTION_REQUIRED: - isAppInteractionRequired = (boolean) value; - break; - case XML_TAG_IS_USER_INTERACTION_REQUIRED: - isUserInteractionRequired = (boolean) value; - break; - case XML_TAG_IS_USER_ALLOWED_TO_MANUALLY_CONNECT: - isUserAllowedToManuallyConnect = (boolean) value; - break; - case XML_TAG_IS_INITIALIZED_AUTO_JOIN: - isInitializedAutoJoinEnabled = (boolean) value; - break; - case XML_TAG_IS_AUTO_JOIN: - isAutoJoinEnabled = (boolean) value; - break; - case XML_TAG_SUGGESTOR_UID: - // Only needed for migration of data from Q to R. - suggestorUid = (int) value; - break; - default: - Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); - break; - } - } else { - String tagName = in.getName(); - if (tagName == null) { - throw new XmlPullParserException("Unexpected null under " - + XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION); - } - switch (tagName) { - case XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION: - if (parsedConfig != null) { - throw new XmlPullParserException("Detected duplicate tag for: " - + XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - } - parsedConfig = WifiConfigurationXmlUtil.parseFromXml( - in, outerTagDepth + 1, - version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - encryptionUtil); - break; - case XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION: - if (enterpriseConfig != null) { - throw new XmlPullParserException("Detected duplicate tag for: " - + XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); - } - enterpriseConfig = XmlUtil.WifiEnterpriseConfigXmlUtil.parseFromXml( - in, outerTagDepth + 1, - version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - encryptionUtil); - break; - case XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION: - if (passpointConfiguration != null) { - throw new XmlPullParserException("Detected duplicate tag for: " - + XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION); - } - passpointConfiguration = PasspointXmlUtils - .deserializePasspointConfiguration(in, outerTagDepth + 1); - break; - default: - Log.w(TAG, "Ignoring unknown tag under " - + XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION + ": " + in.getName()); - break; - } - } - } - if (parsedConfig == null || parsedConfig.second == null) { - throw new XmlPullParserException("XML parsing of wifi configuration failed"); - } - // Note: In R, we migrated the uid/package name storage from individual - // ExtWifiNetworkSuggestion to the top level PerAppInfo. This block of code helps - // with migration of data for devices upgrading from Q to R. - perAppInfo.setUid(suggestorUid); - WifiConfiguration wifiConfiguration = parsedConfig.second; - if (passpointConfiguration != null) { - wifiConfiguration.setPasspointUniqueId(passpointConfiguration.getUniqueId()); - } - if (enterpriseConfig != null) { - wifiConfiguration.enterpriseConfig = enterpriseConfig; - } - return Pair.create(new WifiNetworkSuggestion(wifiConfiguration, passpointConfiguration, - isAppInteractionRequired, isUserInteractionRequired, isUserAllowedToManuallyConnect, - isInitializedAutoJoinEnabled), isAutoJoinEnabled); - } -} - diff --git a/service/java/com/android/server/wifi/NetworkUpdateResult.java b/service/java/com/android/server/wifi/NetworkUpdateResult.java deleted file mode 100644 index 851b13b11..000000000 --- a/service/java/com/android/server/wifi/NetworkUpdateResult.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID; - -public class NetworkUpdateResult { - int netId; - boolean ipChanged; - boolean proxyChanged; - boolean credentialChanged; - boolean isNewNetwork = false; - - public NetworkUpdateResult(int id) { - netId = id; - ipChanged = false; - proxyChanged = false; - credentialChanged = false; - } - - public NetworkUpdateResult(boolean ip, boolean proxy, boolean credential) { - netId = INVALID_NETWORK_ID; - ipChanged = ip; - proxyChanged = proxy; - credentialChanged = credential; - } - - public void setNetworkId(int id) { - netId = id; - } - - public int getNetworkId() { - return netId; - } - - public boolean hasIpChanged() { - return ipChanged; - } - - public boolean hasProxyChanged() { - return proxyChanged; - } - - public boolean hasCredentialChanged() { - return credentialChanged; - } - - public boolean isNewNetwork() { - return isNewNetwork; - } - - public void setIsNewNetwork(boolean isNew) { - isNewNetwork = isNew; - } - - public boolean isSuccess() { - return netId != INVALID_NETWORK_ID; - } - -} diff --git a/service/java/com/android/server/wifi/OpenNetworkNotifier.java b/service/java/com/android/server/wifi/OpenNetworkNotifier.java deleted file mode 100644 index 5e36f1308..000000000 --- a/service/java/com/android/server/wifi/OpenNetworkNotifier.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.content.Context; -import android.os.Looper; -import android.provider.Settings; - -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.server.wifi.proto.nano.WifiMetricsProto; - -/** - * This class handles the "open wi-fi network available" notification - * - * NOTE: These API's are not thread safe and should only be used from the main Wifi thread. - */ -public class OpenNetworkNotifier extends AvailableNetworkNotifier { - public static final String TAG = "WifiOpenNetworkNotifier"; - private static final String STORE_DATA_IDENTIFIER = "OpenNetworkNotifierBlacklist"; - private static final String TOGGLE_SETTINGS_NAME = - Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON; - - public OpenNetworkNotifier( - Context context, - Looper looper, - FrameworkFacade framework, - Clock clock, - WifiMetrics wifiMetrics, - WifiConfigManager wifiConfigManager, - WifiConfigStore wifiConfigStore, - ClientModeImpl clientModeImpl, - ConnectToNetworkNotificationBuilder connectToNetworkNotificationBuilder) { - super(TAG, STORE_DATA_IDENTIFIER, TOGGLE_SETTINGS_NAME, - SystemMessage.NOTE_NETWORK_AVAILABLE, - WifiMetricsProto.ConnectionEvent.NOMINATOR_OPEN_NETWORK_AVAILABLE, - context, looper, framework, clock, - wifiMetrics, wifiConfigManager, wifiConfigStore, clientModeImpl, - connectToNetworkNotificationBuilder); - } -} diff --git a/service/java/com/android/server/wifi/PropertyService.java b/service/java/com/android/server/wifi/PropertyService.java deleted file mode 100644 index 06ef46d82..000000000 --- a/service/java/com/android/server/wifi/PropertyService.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.annotation.NonNull; - -import com.android.internal.annotations.VisibleForTesting; - -/** Abstraction of android.os.SystemProperties, to enable mocking out its static methods. */ -@VisibleForTesting -public interface PropertyService { - /** - * Get the current value of |key|. - * @return value of |key|, if key exists; |defaultValue| or empty string otherwise - */ - @NonNull - String get(String key, String defaultValue); - - /** - * Get the current value of |key|. - * @return value of |key|, if key exists; |defaultValue| otherwise - */ - boolean getBoolean(String key, boolean defaultValue); - - /** - * Get the current value of |key|. - * @return value of |key|, if key exists; |defaultValue| otherwise - */ - String getString(String key, String defaultValue); -} diff --git a/service/java/com/android/server/wifi/README.txt b/service/java/com/android/server/wifi/README.txt deleted file mode 100644 index 4b4b52074..000000000 --- a/service/java/com/android/server/wifi/README.txt +++ /dev/null @@ -1,49 +0,0 @@ -Path history for this code: - -commit date: 2013-12-18 to 2014-01-07 -commit hash: a07c419913bfae2a896fbc29e8f269ee08c4d910 (add) -commit hash: 4a3f9cf099bbbe52dc0edb2a7e1d1c976bc335a3 (delete) -dst: frameworks/opt/net/wifi/service -src: frameworks/base/services/core/java/com/android/server/wifi - -commit date: 2013-12-19 -commit hash: 9158825f9c41869689d6b1786d7c7aa8bdd524ce (many more files) -commit hash: 19c662b3df3b35756a92282bb6cc767e6407cb8a (a few files) -dst: frameworks/base/services/core/java/com/android/server/wifi -src: frameworks/base/services/java/com/android/server/wifi - -commit date: 2013-12-11 -commit hash: ffadfb9ffdced62db215319d3edc7717802088fb -dst: frameworks/base/services/java/com/android/server/wifi -src: frameworks/base/wifi/java/android/net/wifi - -commit date: 2008-10-21 -commit hash: 54b6cfa9a9e5b861a9930af873580d6dc20f773c -dst: frameworks/base/wifi/java/android/net/wifi -src: initial aosp import? - -//////////////////////////////////////////////////////////////// - -Salient points about Wifi Service implementation - -WifiService: Implements the IWifiManager 3rd party API. The API and the device -state information (screen on/off, battery state, sleep policy) go as input into -the WifiController which tracks high level states as to whether STA or AP mode -is operational and controls wifi to handle bringup and shut down. - -WifiController: Acts as a controller to the ActiveModeWarden based on various inputs (API and device state). Runs on the same thread created in WifiService. - -WifiSettingsStore: Tracks the various settings (wifi toggle, airplane toggle, tethering toggle, scan mode toggle) and provides API to figure if wifi should be turned on or off. - -WifiTrafficPoller: Polls traffic on wifi and notifies apps listening on it. - -WifiNotificationController: Controls whether the open network notification is displayed or not based on the scan results. - -ActiveModeWarden: Tracks the various states on STA and AP connectivity and handles bring up and shut down. - -Feature description: - -Scan-only mode with Wi-Fi turned off: - - Setup wizard opts user into allowing scanning for improved location. We show no further dialogs in setup wizard since the user has just opted into the feature. This is the reason WifiService listens to DEVICE_PROVISIONED setting. - - Once the user has his device provisioned, turning off Wi-Fi from settings or from a third party app will show up a dialog reminding the user that scan mode will be on even though Wi-Fi is being turned off. The user has the choice to turn this notification off. - - In the scan mode, the device continues to allow scanning from any app with Wi-Fi turned off. This is done by disabling all networks and allowing only scans to be passed. diff --git a/service/java/com/android/server/wifi/RandomizedMacStoreData.java b/service/java/com/android/server/wifi/RandomizedMacStoreData.java deleted file mode 100644 index a03be6056..000000000 --- a/service/java/com/android/server/wifi/RandomizedMacStoreData.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.Nullable; -import android.util.Log; - -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * This class performs serialization and parsing of XML data block that contain the mapping - * from configKey to randomized MAC address - * (XML block data inside <MacAddressMappingList> tag). - */ -public class RandomizedMacStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "RandomizedMacStoreData"; - private static final String XML_TAG_SECTION_HEADER_MAC_ADDRESS_MAP = "MacAddressMap"; - private static final String XML_TAG_MAC_MAP = "MacMapEntry"; - - private Map<String, String> mMacMapping; - - RandomizedMacStoreData() {} - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - if (mMacMapping != null) { - XmlUtil.writeNextValue(out, XML_TAG_MAC_MAP, mMacMapping); - } - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - // Ignore empty reads. - if (in == null) { - return; - } - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_MAC_MAP: - mMacMapping = (Map<String, String>) value; - break; - default: - Log.w(TAG, "Ignoring unknown tag under " - + XML_TAG_SECTION_HEADER_MAC_ADDRESS_MAP - + ": " + valueName[0]); - break; - } - } - } - - @Override - public void resetData() { - mMacMapping = null; - } - - @Override - public boolean hasNewDataToSerialize() { - // always persist. - return true; - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER_MAC_ADDRESS_MAP; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - // Shared general store. - return WifiConfigStore.STORE_FILE_SHARED_GENERAL; - } - - /** - * An empty Map will be returned for null MAC address map. - * - * @return Map of mapping from configKey to the randomized MAC address. - */ - public Map<String, String> getMacMapping() { - if (mMacMapping == null) { - return new HashMap<String, String>(); - } - return mMacMapping; - } - - /** - * Sets the data to be stored to file. - * @param macMapping - */ - public void setMacMapping(Map<String, String> macMapping) { - mMacMapping = macMapping; - } -} - diff --git a/service/java/com/android/server/wifi/SarInfo.java b/service/java/com/android/server/wifi/SarInfo.java deleted file mode 100644 index 5a2178d0c..000000000 --- a/service/java/com/android/server/wifi/SarInfo.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * This class represents the list of SAR inputs that will be used to select the proper - * power profile. - * This includes: - * - Is there an ongoing voice call - * - Is SoftAP active - * It also contains info about state of the other Wifi modes - * - Client mode (Sta) - * - ScanOnly mode - * It also keeps history for the reporting of SAR states/scenario to avoid unnecessary reporting - * - keeps track of the last reported states - * - keeps track of the last reported SAR scenario - * - keeps track of if all wifi modes were disabled (no reporting should happen then) - */ -public class SarInfo { - /** - * This value is used as an initial value for the last reported scenario - * It is intended to be different than all valid SAR scenario values (including the - * reset value). - * Using this to initialize the lastReportedScenario results in that the first scenario - * (including reset) would be reported. - */ - public static final int INITIAL_SAR_SCENARIO = -2; - - /** - * This value is used for the reset scenario (no TX Power backoff) - * Valid scenario values only include scenarios with Tx Power backoff, - * so we need this one to represent the "No backoff" case. - */ - public static final int RESET_SAR_SCENARIO = -1; - - /* For Logging */ - private static final String TAG = "WifiSarInfo"; - - /* SAR support configs */ - public boolean sarVoiceCallSupported; - public boolean sarSapSupported; - - public boolean isWifiClientEnabled = false; - public boolean isWifiSapEnabled = false; - public boolean isWifiScanOnlyEnabled = false; - public boolean isVoiceCall = false; - public boolean isEarPieceActive = false; - public int attemptedSarScenario = RESET_SAR_SCENARIO; - - private boolean mAllWifiDisabled = true; - - /* Variables representing the last successfully reported values to hal */ - private boolean mLastReportedIsWifiSapEnabled = false; - private boolean mLastReportedIsVoiceCall = false; - private boolean mLastReportedIsEarPieceActive = false; - private int mLastReportedScenario = INITIAL_SAR_SCENARIO; - private long mLastReportedScenarioTs = 0; - - /** - * shouldReport() - * This method returns false in the following cases: - * 1. If all Wifi modes are disabled. - * 2. Values contributing to the SAR scenario selection have not changed - * since last successful reporting. - * - * Special cases to allow for devices that require setting the SAR scenario value - * when the chip comes up (initial startup, or during operation) - * 1. This method would report true even with unchanged values from last reporting, - * if any wifi mode is just enabled after all wifi modes were disabled. - * 2. This method would report true the first time it is called with any wifi mode enabled. - */ - public boolean shouldReport() { - /* Check if all Wifi modes are disabled */ - if (!isWifiClientEnabled && !isWifiSapEnabled && !isWifiScanOnlyEnabled) { - mAllWifiDisabled = true; - return false; - } - - /* Check if Wifi was all disabled before this call */ - if (mAllWifiDisabled) { - return true; - } - - /* Check if some change happened since last successful reporting */ - return ((isWifiSapEnabled != mLastReportedIsWifiSapEnabled) - || (isVoiceCall != mLastReportedIsVoiceCall) - || (isEarPieceActive != mLastReportedIsEarPieceActive)); - } - - /** - * reportingSuccessful() - * This method is called when reporting SAR scenario is fully successful - * This results in caching the last reported inputs for future comparison. - */ - public void reportingSuccessful() { - mLastReportedIsWifiSapEnabled = isWifiSapEnabled; - mLastReportedIsVoiceCall = isVoiceCall; - mLastReportedIsEarPieceActive = isEarPieceActive; - mLastReportedScenario = attemptedSarScenario; - mLastReportedScenarioTs = System.currentTimeMillis(); - - mAllWifiDisabled = false; - } - - /** - * resetSarScenarioNeeded() - * Returns true if a call towards HAL to reset SAR scenario would be necessary. - * Returns false if the last call to HAL was already a reset, and hence - * another call to reset the SAR scenario would be redundant. - */ - public boolean resetSarScenarioNeeded() { - return setSarScenarioNeeded(RESET_SAR_SCENARIO); - } - - /** - * setSarScenarioNeeded() - * Returns true if a call towards HAL to set SAR scenario to that value would be - * necessary. This happens in the following cases: - * 1. All Wifi modes were disabled, hence we need to init the SAR scenario value. - * 2. The new scenario is different from the last reported one. - * - * Returns false if the last call to HAL was to set the scenario to that value, hence, - * another call to set the SAR scenario to the same value would be redundant. - */ - public boolean setSarScenarioNeeded(int scenario) { - attemptedSarScenario = scenario; - - if (mAllWifiDisabled || (mLastReportedScenario != scenario)) { - return true; - } - return false; - } - - /** - * dump() - * Dumps the state of SarInfo - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of SarInfo"); - pw.println("Current values:"); - pw.println(" Voice Call state is: " + isVoiceCall); - pw.println(" Wifi Client state is: " + isWifiClientEnabled); - pw.println(" Wifi Soft AP state is: " + isWifiSapEnabled); - pw.println(" Wifi ScanOnly state is: " + isWifiScanOnlyEnabled); - pw.println(" Earpiece state is : " + isEarPieceActive); - pw.println("Last reported values:"); - pw.println(" Soft AP state is: " + mLastReportedIsWifiSapEnabled); - pw.println(" Voice Call state is: " + mLastReportedIsVoiceCall); - pw.println(" Earpiece state is: " + mLastReportedIsEarPieceActive); - pw.println("Last reported scenario: " + mLastReportedScenario); - pw.println("Reported " + (System.currentTimeMillis() - mLastReportedScenarioTs) / 1000 - + " seconds ago"); - } -} diff --git a/service/java/com/android/server/wifi/SarManager.java b/service/java/com/android/server/wifi/SarManager.java deleted file mode 100644 index 2d96c38c7..000000000 --- a/service/java/com/android/server/wifi/SarManager.java +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static android.telephony.TelephonyManager.CALL_STATE_IDLE; -import static android.telephony.TelephonyManager.CALL_STATE_OFFHOOK; -import static android.telephony.TelephonyManager.CALL_STATE_RINGING; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.media.AudioAttributes; -import android.media.AudioDeviceAttributes; -import android.media.AudioDeviceInfo; -import android.media.AudioManager; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.Looper; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; -import android.util.Log; - -import com.android.server.wifi.util.WifiHandler; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.List; - -/** - * This class provides the Support for SAR to control WiFi TX power limits. - * It deals with the following: - * - Tracking the STA state through calls from the ClientModeManager. - * - Tracking the SAP state through calls from SoftApManager - * - Tracking the Scan-Only state through ScanOnlyModeManager - * - Tracking the state of the Cellular calls or data. - * - It constructs the sar info and send it towards the HAL - */ -public class SarManager { - // Period for checking on voice steam active (in ms) - private static final int CHECK_VOICE_STREAM_INTERVAL_MS = 5000; - - /** - * @hide constants copied over from {@link AudioManager} - * TODO(b/144250387): Migrate to public API - */ - private static final String STREAM_DEVICES_CHANGED_ACTION = - "android.media.stream_devices_changed_action"; - private static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE"; - private static final String EXTRA_VOLUME_STREAM_DEVICES = - "android.media.EXTRA_VOLUME_STREAM_DEVICES"; - private static final String EXTRA_PREV_VOLUME_STREAM_DEVICES = - "android.media.EXTRA_PREV_VOLUME_STREAM_DEVICES"; - private static final int DEVICE_OUT_EARPIECE = 0x1; - - /* For Logging */ - private static final String TAG = "WifiSarManager"; - private boolean mVerboseLoggingEnabled = true; - - private SarInfo mSarInfo; - - /* Configuration for SAR support */ - private boolean mSupportSarTxPowerLimit; - private boolean mSupportSarVoiceCall; - private boolean mSupportSarSoftAp; - - // Device starts with screen on - private boolean mScreenOn = false; - private boolean mIsVoiceStreamCheckEnabled = false; - - /** - * Other parameters passed in or created in the constructor. - */ - private final Context mContext; - private final TelephonyManager mTelephonyManager; - private final AudioManager mAudioManager; - private final WifiPhoneStateListener mPhoneStateListener; - private final WifiNative mWifiNative; - private final Handler mHandler; - private final Looper mLooper; - - /** - * Create new instance of SarManager. - */ - SarManager(Context context, - TelephonyManager telephonyManager, - Looper looper, - WifiNative wifiNative) { - mContext = context; - mTelephonyManager = telephonyManager; - mWifiNative = wifiNative; - mLooper = looper; - mAudioManager = mContext.getSystemService(AudioManager.class); - mHandler = new WifiHandler(TAG, looper); - mPhoneStateListener = new WifiPhoneStateListener(looper); - } - - /** - * Handle boot completed, read config flags. - */ - public void handleBootCompleted() { - readSarConfigs(); - if (mSupportSarTxPowerLimit) { - mSarInfo = new SarInfo(); - setSarConfigsInInfo(); - registerListeners(); - } - } - - /** - * Notify SarManager of screen status change - */ - public void handleScreenStateChanged(boolean screenOn) { - if (!mSupportSarVoiceCall) { - return; - } - - if (mScreenOn == screenOn) { - return; - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "handleScreenStateChanged: screenOn = " + screenOn); - } - - mScreenOn = screenOn; - - // Only schedule a voice stream check if screen is turning on, and it is currently not - // scheduled - if (mScreenOn && !mIsVoiceStreamCheckEnabled) { - mHandler.post(() -> { - checkAudioDevice(); - }); - - mIsVoiceStreamCheckEnabled = true; - } - } - - private boolean isVoiceCallOnEarpiece() { - final AudioAttributes voiceCallAttr = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) - .build(); - List<AudioDeviceAttributes> devices = mAudioManager.getDevicesForAttributes(voiceCallAttr); - for (AudioDeviceAttributes device : devices) { - if (device.getRole() == AudioDeviceAttributes.ROLE_OUTPUT - && device.getType() == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE) { - return true; - } - } - return false; - } - - private boolean isVoiceCallStreamActive() { - int mode = mAudioManager.getMode(); - return mode == AudioManager.MODE_IN_COMMUNICATION || mode == AudioManager.MODE_IN_CALL; - } - - private void checkAudioDevice() { - // First Check if audio stream is on - boolean voiceStreamActive = isVoiceCallStreamActive(); - boolean earPieceActive; - - if (voiceStreamActive) { - // Check on the audio route - earPieceActive = isVoiceCallOnEarpiece(); - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "EarPiece active = " + earPieceActive); - } - } else { - earPieceActive = false; - } - - // If audio route has changed, update SAR - if (earPieceActive != mSarInfo.isEarPieceActive) { - mSarInfo.isEarPieceActive = earPieceActive; - updateSarScenario(); - } - - // Now should we proceed with the checks - if (!mScreenOn && !voiceStreamActive) { - // No need to continue checking - mIsVoiceStreamCheckEnabled = false; - } else { - // Schedule another check - mHandler.postDelayed(() -> { - checkAudioDevice(); - }, CHECK_VOICE_STREAM_INTERVAL_MS); - } - } - - private void readSarConfigs() { - mSupportSarTxPowerLimit = mContext.getResources().getBoolean( - R.bool.config_wifi_framework_enable_sar_tx_power_limit); - /* In case SAR is disabled, - then all SAR inputs are automatically disabled as well (irrespective of the config) */ - if (!mSupportSarTxPowerLimit) { - mSupportSarVoiceCall = false; - mSupportSarSoftAp = false; - return; - } - - /* Voice calls are supported when SAR is supported */ - mSupportSarVoiceCall = true; - - mSupportSarSoftAp = mContext.getResources().getBoolean( - R.bool.config_wifi_framework_enable_soft_ap_sar_tx_power_limit); - } - - private void setSarConfigsInInfo() { - mSarInfo.sarVoiceCallSupported = mSupportSarVoiceCall; - mSarInfo.sarSapSupported = mSupportSarSoftAp; - } - - private void registerListeners() { - if (mSupportSarVoiceCall) { - /* Listen for Phone State changes */ - registerPhoneStateListener(); - registerVoiceStreamListener(); - } - } - - private void registerVoiceStreamListener() { - Log.i(TAG, "Registering for voice stream status"); - - // Register for listening to transitions of change of voice stream devices - IntentFilter filter = new IntentFilter(); - filter.addAction(STREAM_DEVICES_CHANGED_ACTION); - - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - boolean voiceStreamActive = isVoiceCallStreamActive(); - if (!voiceStreamActive) { - // No need to proceed, there is no voice call ongoing - return; - } - - String action = intent.getAction(); - int streamType = - intent.getIntExtra(EXTRA_VOLUME_STREAM_TYPE, -1); - int device = intent.getIntExtra(EXTRA_VOLUME_STREAM_DEVICES, -1); - int oldDevice = intent.getIntExtra(EXTRA_PREV_VOLUME_STREAM_DEVICES, -1); - - if (streamType == AudioManager.STREAM_VOICE_CALL) { - boolean earPieceActive = mSarInfo.isEarPieceActive; - if (device == DEVICE_OUT_EARPIECE) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Switching to earpiece : HEAD ON"); - Log.d(TAG, "Old device = " + oldDevice); - } - earPieceActive = true; - } else if (oldDevice == DEVICE_OUT_EARPIECE) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Switching from earpiece : HEAD OFF"); - Log.d(TAG, "New device = " + device); - } - earPieceActive = false; - } - - if (earPieceActive != mSarInfo.isEarPieceActive) { - mSarInfo.isEarPieceActive = earPieceActive; - updateSarScenario(); - } - } - } - }, filter, null, mHandler); - } - - /** - * Register the phone state listener. - */ - private void registerPhoneStateListener() { - Log.i(TAG, "Registering for telephony call state changes"); - mTelephonyManager.listen( - mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); - } - - /** - * Update Wifi Client State - */ - public void setClientWifiState(int state) { - boolean newIsEnabled; - /* No action is taken if SAR is not supported */ - if (!mSupportSarTxPowerLimit) { - return; - } - - if (state == WifiManager.WIFI_STATE_DISABLED) { - newIsEnabled = false; - } else if (state == WifiManager.WIFI_STATE_ENABLED) { - newIsEnabled = true; - } else { - /* No change so exiting with no action */ - return; - } - - /* Report change to HAL if needed */ - if (mSarInfo.isWifiClientEnabled != newIsEnabled) { - mSarInfo.isWifiClientEnabled = newIsEnabled; - updateSarScenario(); - } - } - - /** - * Update Wifi SoftAP State - */ - public void setSapWifiState(int state) { - boolean newIsEnabled; - /* No action is taken if SAR is not supported */ - if (!mSupportSarTxPowerLimit) { - return; - } - - if (state == WifiManager.WIFI_AP_STATE_DISABLED) { - newIsEnabled = false; - } else if (state == WifiManager.WIFI_AP_STATE_ENABLED) { - newIsEnabled = true; - } else { - /* No change so exiting with no action */ - return; - } - - /* Report change to HAL if needed */ - if (mSarInfo.isWifiSapEnabled != newIsEnabled) { - mSarInfo.isWifiSapEnabled = newIsEnabled; - updateSarScenario(); - } - } - - /** - * Update Wifi ScanOnly State - */ - public void setScanOnlyWifiState(int state) { - boolean newIsEnabled; - /* No action is taken if SAR is not supported */ - if (!mSupportSarTxPowerLimit) { - return; - } - - if (state == WifiManager.WIFI_STATE_DISABLED) { - newIsEnabled = false; - } else if (state == WifiManager.WIFI_STATE_ENABLED) { - newIsEnabled = true; - } else { - /* No change so exiting with no action */ - return; - } - - /* Report change to HAL if needed */ - if (mSarInfo.isWifiScanOnlyEnabled != newIsEnabled) { - mSarInfo.isWifiScanOnlyEnabled = newIsEnabled; - updateSarScenario(); - } - } - - /** - * Report Cell state event - */ - private void onCellStateChangeEvent(int state) { - boolean newIsVoiceCall; - switch (state) { - case CALL_STATE_OFFHOOK: - case CALL_STATE_RINGING: - newIsVoiceCall = true; - break; - - case CALL_STATE_IDLE: - newIsVoiceCall = false; - break; - - default: - Log.e(TAG, "Invalid Cell State: " + state); - return; - } - - /* Report change to HAL if needed */ - if (mSarInfo.isVoiceCall != newIsVoiceCall) { - mSarInfo.isVoiceCall = newIsVoiceCall; - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Voice Call = " + newIsVoiceCall); - } - updateSarScenario(); - } - } - - /** - * Enable/disable verbose logging. - */ - public void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mVerboseLoggingEnabled = true; - } else { - mVerboseLoggingEnabled = false; - } - } - - /** - * dump() - * Dumps SarManager state (as well as its SarInfo member variable state) - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of SarManager"); - pw.println("isSarSupported: " + mSupportSarTxPowerLimit); - pw.println("isSarVoiceCallSupported: " + mSupportSarVoiceCall); - pw.println("isSarSoftApSupported: " + mSupportSarSoftAp); - pw.println(""); - if (mSarInfo != null) { - mSarInfo.dump(fd, pw, args); - } - } - - /** - * Listen for phone call state events to set/reset TX power limits for SAR requirements. - */ - private class WifiPhoneStateListener extends PhoneStateListener { - WifiPhoneStateListener(Looper looper) { - super(new HandlerExecutor(new Handler(looper))); - } - - /** - * onCallStateChanged() - * This callback is called when a call state event is received - * Note that this runs in the WifiCoreHandlerThread - * since the corresponding Looper was passed to the WifiPhoneStateListener constructor. - */ - @Override - public void onCallStateChanged(int state, String incomingNumber) { - Log.d(TAG, "Received Phone State Change: " + state); - - /* In case of an unsolicited event */ - if (!mSupportSarTxPowerLimit || !mSupportSarVoiceCall) { - return; - } - onCellStateChangeEvent(state); - } - } - - /** - * updateSarScenario() - * Update HAL with the new SAR scenario if needed. - */ - private void updateSarScenario() { - if (!mSarInfo.shouldReport()) { - return; - } - - /* Report info to HAL*/ - if (mWifiNative.selectTxPowerScenario(mSarInfo)) { - mSarInfo.reportingSuccessful(); - } else { - Log.e(TAG, "Failed in WifiNative.selectTxPowerScenario()"); - } - - return; - } -} diff --git a/service/java/com/android/server/wifi/SavedNetworkNominator.java b/service/java/com/android/server/wifi/SavedNetworkNominator.java deleted file mode 100644 index 3c94bed9d..000000000 --- a/service/java/com/android/server/wifi/SavedNetworkNominator.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.annotation.NonNull; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.telephony.TelephonyManager; -import android.util.LocalLog; -import android.util.Pair; - -import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import java.util.List; - -/** - * This class is the WifiNetworkSelector.NetworkNominator implementation for - * saved networks. - */ -public class SavedNetworkNominator implements WifiNetworkSelector.NetworkNominator { - private static final String NAME = "SavedNetworkNominator"; - private final WifiConfigManager mWifiConfigManager; - private final LocalLog mLocalLog; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - private final PasspointNetworkNominateHelper mPasspointNetworkNominateHelper; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - - SavedNetworkNominator(WifiConfigManager configManager, - PasspointNetworkNominateHelper nominateHelper, LocalLog localLog, - WifiCarrierInfoManager wifiCarrierInfoManager, - WifiPermissionsUtil wifiPermissionsUtil, - WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager) { - mWifiConfigManager = configManager; - mPasspointNetworkNominateHelper = nominateHelper; - mLocalLog = localLog; - mWifiCarrierInfoManager = wifiCarrierInfoManager; - mWifiPermissionsUtil = wifiPermissionsUtil; - mWifiNetworkSuggestionsManager = wifiNetworkSuggestionsManager; - } - - private void localLog(String log) { - mLocalLog.log(log); - } - - /** - * Get the Nominator type. - */ - @Override - public @NominatorId int getId() { - return NOMINATOR_ID_SAVED; - } - - /** - * Get the Nominator name. - */ - @Override - public String getName() { - return NAME; - } - - /** - * Update the Nominator. - */ - @Override - public void update(List<ScanDetail> scanDetails) { } - - /** - * Run through all scanDetails and nominate all connectable network as candidates. - * - */ - @Override - public void nominateNetworks(List<ScanDetail> scanDetails, - WifiConfiguration currentNetwork, String currentBssid, boolean connected, - boolean untrustedNetworkAllowed, - @NonNull OnConnectableListener onConnectableListener) { - findMatchedSavedNetworks(scanDetails, onConnectableListener); - findMatchedPasspointNetworks(scanDetails, onConnectableListener); - } - - private void findMatchedSavedNetworks(List<ScanDetail> scanDetails, - OnConnectableListener onConnectableListener) { - for (ScanDetail scanDetail : scanDetails) { - ScanResult scanResult = scanDetail.getScanResult(); - - // One ScanResult can be associated with more than one network, hence we calculate all - // the scores and use the highest one as the ScanResult's score. - WifiConfiguration network = - mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail); - - if (network == null) { - continue; - } - - /** - * Ignore Passpoint and Ephemeral networks. They are configured networks, - * but without being persisted to the storage. They are nominated by - * {@link PasspointNetworkNominator} and {@link ScoredNetworkNominator} - * respectively. - */ - if (network.isPasspoint() || network.isEphemeral()) { - continue; - } - - // Ignore networks that the user has disallowed auto-join for. - if (!network.allowAutojoin) { - localLog("Ignoring auto join disabled SSID: " + network.SSID); - continue; - } - - WifiConfiguration.NetworkSelectionStatus status = - network.getNetworkSelectionStatus(); - status.setSeenInLastQualifiedNetworkSelection(true); - - if (mWifiConfigManager.isNetworkTemporarilyDisabledByUser(network.SSID)) { - localLog("Ignoring user disabled SSID: " + network.SSID); - continue; - } - - if (!status.isNetworkEnabled()) { - localLog("Ignoring network selection disabled SSID: " + network.SSID); - continue; - } - if (network.BSSID != null && !network.BSSID.equals("any") - && !network.BSSID.equals(scanResult.BSSID)) { - // App has specified the only BSSID to connect for this - // configuration. So only the matching ScanResult can be a candidate. - localLog("Network " + WifiNetworkSelector.toNetworkString(network) - + " has specified BSSID " + network.BSSID + ". Skip " - + scanResult.BSSID); - continue; - } - if (isNetworkSimBasedCredential(network) && !isSimBasedNetworkAbleToAutoJoin(network)) { - localLog("Ignoring SIM auto join disabled SSID: " + network.SSID); - continue; - } - - // If the network is marked to use external scores, or is an open network with - // curate saved open networks enabled, do not consider it for network selection. - if (network.useExternalScores) { - localLog("Network " + WifiNetworkSelector.toNetworkString(network) - + " has external score."); - continue; - } - - if (mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network, - scanDetails)) { - localLog("Open Network " + WifiNetworkSelector.toNetworkString(network) - + " has a secure network suggestion from same carrier."); - continue; - } - - onConnectableListener.onConnectable(scanDetail, - mWifiConfigManager.getConfiguredNetwork(network.networkId)); - } - } - - private void findMatchedPasspointNetworks(List<ScanDetail> scanDetails, - OnConnectableListener onConnectableListener) { - List<Pair<ScanDetail, WifiConfiguration>> candidates = - mPasspointNetworkNominateHelper.getPasspointNetworkCandidates(scanDetails, false); - for (Pair<ScanDetail, WifiConfiguration> candidate : candidates) { - WifiConfiguration config = candidate.second; - if (!config.allowAutojoin) { - continue; - } - if (isNetworkSimBasedCredential(config) && !isSimBasedNetworkAbleToAutoJoin(config)) { - continue; - } - onConnectableListener.onConnectable(candidate.first, config); - } - } - - private boolean isSimBasedNetworkAbleToAutoJoin(WifiConfiguration network) { - int carrierId = network.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID - ? mWifiCarrierInfoManager.getDefaultDataSimCarrierId() : network.carrierId; - int subId = mWifiCarrierInfoManager.getMatchingSubId(carrierId); - // Ignore security type is EAP SIM/AKA/AKA' when SIM is not present. - if (!mWifiCarrierInfoManager.isSimPresent(subId)) { - localLog("No SIM card is good for Network " - + WifiNetworkSelector.toNetworkString(network)); - return false; - } - // Ignore IMSI info not available or protection exemption pending network. - if (mWifiCarrierInfoManager.requiresImsiEncryption(subId)) { - if (!mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(subId)) { - localLog("Imsi protection required but not available for Network " - + WifiNetworkSelector.toNetworkString(network)); - return false; - } - } else if (isImsiProtectionApprovalNeeded(network.creatorUid, carrierId)) { - localLog("Imsi protection exemption needed for Network " - + WifiNetworkSelector.toNetworkString(network)); - return false; - } - // Ignore metered network with non-data Sim. - if (WifiConfiguration.isMetered(network, null) - && mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(network)) { - localLog("No default SIM is used for metered Network: " - + WifiNetworkSelector.toNetworkString(network)); - return false; - } - return true; - } - - private boolean isNetworkSimBasedCredential(WifiConfiguration network) { - return network != null && network.enterpriseConfig != null - && network.enterpriseConfig.isAuthenticationSimBased(); - } - - private boolean isImsiProtectionApprovalNeeded(int creatorUid, int carrierId) { - // User saved network got exemption. - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(creatorUid) - || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(creatorUid)) { - return false; - } - if (mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(carrierId)) { - return false; - } - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(carrierId); - return true; - } -} diff --git a/service/java/com/android/server/wifi/ScanDetail.java b/service/java/com/android/server/wifi/ScanDetail.java deleted file mode 100644 index 5be45de8a..000000000 --- a/service/java/com/android/server/wifi/ScanDetail.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import android.net.wifi.AnqpInformationElement; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiSsid; - -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.hotspot2.Utils; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; -import com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement; -import com.android.server.wifi.hotspot2.anqp.RawByteElement; -import com.android.server.wifi.hotspot2.anqp.VenueNameElement; - -import java.util.List; -import java.util.Map; - -/** - * Wifi scan result details. - */ -public class ScanDetail { - private final ScanResult mScanResult; - private volatile NetworkDetail mNetworkDetail; - private long mSeen = 0; - private byte[] mInformationElementRawData; - - public ScanDetail(NetworkDetail networkDetail, WifiSsid wifiSsid, String bssid, - String caps, int level, int frequency, long tsf, - ScanResult.InformationElement[] informationElements, List<String> anqpLines, - byte[] informationElementRawData) { - mNetworkDetail = networkDetail; - mScanResult = new ScanResult(wifiSsid, bssid, networkDetail.getHESSID(), - networkDetail.getAnqpDomainID(), networkDetail.getOsuProviders(), - caps, level, frequency, tsf); - mSeen = System.currentTimeMillis(); - mScanResult.seen = mSeen; - mScanResult.channelWidth = networkDetail.getChannelWidth(); - mScanResult.centerFreq0 = networkDetail.getCenterfreq0(); - mScanResult.centerFreq1 = networkDetail.getCenterfreq1(); - mScanResult.informationElements = informationElements; - mScanResult.anqpLines = anqpLines; - if (networkDetail.is80211McResponderSupport()) { - mScanResult.setFlag(ScanResult.FLAG_80211mc_RESPONDER); - } - if (networkDetail.isInterworking() && networkDetail.getHSRelease() != null) { - mScanResult.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK); - } - mInformationElementRawData = informationElementRawData; - } - - public ScanDetail(WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, - long tsf, long seen) { - mNetworkDetail = null; - mScanResult = new ScanResult(wifiSsid, bssid, 0L, -1, null, caps, level, frequency, tsf); - mSeen = seen; - mScanResult.seen = mSeen; - mScanResult.channelWidth = 0; - mScanResult.centerFreq0 = 0; - mScanResult.centerFreq1 = 0; - mScanResult.flags = 0; - } - - public ScanDetail(ScanResult scanResult, NetworkDetail networkDetail) { - mScanResult = scanResult; - mNetworkDetail = networkDetail; - // Only inherit |mScanResult.seen| if it was previously set. This ensures that |mSeen| - // will always contain a valid timestamp. - mSeen = (mScanResult.seen == 0) ? System.currentTimeMillis() : mScanResult.seen; - } - - /** - * Store ANQ element information - * - * @param anqpElements Map<Constants.ANQPElementType, ANQPElement> - */ - public void propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> anqpElements) { - if (anqpElements.isEmpty()) { - return; - } - mNetworkDetail = mNetworkDetail.complete(anqpElements); - HSFriendlyNameElement fne = (HSFriendlyNameElement) anqpElements.get( - Constants.ANQPElementType.HSFriendlyName); - // !!! Match with language - if (fne != null && !fne.getNames().isEmpty()) { - mScanResult.venueName = fne.getNames().get(0).getText(); - } else { - VenueNameElement vne = - (((VenueNameElement) anqpElements.get( - Constants.ANQPElementType.ANQPVenueName))); - if (vne != null && !vne.getNames().isEmpty()) { - mScanResult.venueName = vne.getNames().get(0).getText(); - } - } - RawByteElement osuProviders = (RawByteElement) anqpElements - .get(Constants.ANQPElementType.HSOSUProviders); - if (osuProviders != null) { - mScanResult.anqpElements = new AnqpInformationElement[1]; - mScanResult.anqpElements[0] = - new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, - AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders.getPayload()); - } - } - - public ScanResult getScanResult() { - return mScanResult; - } - - public NetworkDetail getNetworkDetail() { - return mNetworkDetail; - } - - public String getSSID() { - return mNetworkDetail == null ? mScanResult.SSID : mNetworkDetail.getSSID(); - } - - public String getBSSIDString() { - return mNetworkDetail == null ? mScanResult.BSSID : mNetworkDetail.getBSSIDString(); - } - - /** - * Return the network detail key string. - */ - public String toKeyString() { - NetworkDetail networkDetail = mNetworkDetail; - if (networkDetail != null) { - return networkDetail.toKeyString(); - } else { - return String.format("'%s':%012x", - mScanResult.BSSID, - Utils.parseMac(mScanResult.BSSID)); - } - } - - /** - * Return the time this network was last seen. - */ - public long getSeen() { - return mSeen; - } - - /** - * Update the time this network was last seen to the current system time. - */ - public long setSeen() { - mSeen = System.currentTimeMillis(); - mScanResult.seen = mSeen; - return mSeen; - } - - /** - * Return the network information element raw data. - */ - public byte[] getInformationElementRawData() { - return mInformationElementRawData; - } - - @Override - public String toString() { - try { - return String.format("'%s'/%012x", - mScanResult.SSID, - Utils.parseMac(mScanResult.BSSID)); - } catch (IllegalArgumentException iae) { - return String.format("'%s'/----", mScanResult.BSSID); - } - } -} diff --git a/service/java/com/android/server/wifi/ScanDetailCache.java b/service/java/com/android/server/wifi/ScanDetailCache.java deleted file mode 100644 index c8490a5bc..000000000 --- a/service/java/com/android/server/wifi/ScanDetailCache.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import android.annotation.NonNull; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; - -import com.android.server.wifi.hotspot2.NetworkDetail; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; - -/** - * Maps BSSIDs to their individual ScanDetails for a given WifiConfiguration. - */ -public class ScanDetailCache { - - private static final String TAG = "ScanDetailCache"; - private static final boolean DBG = false; - - private final WifiConfiguration mConfig; - private final int mMaxSize; - private final int mTrimSize; - private final HashMap<String, ScanDetail> mMap; - - /** - * Scan Detail cache associated with each configured network. - * - * The cache size is trimmed down to |trimSize| once it crosses the provided |maxSize|. - * Since this operation is relatively expensive, ensure that |maxSize| and |trimSize| are not - * too close to each other. |trimSize| should always be <= |maxSize|. - * - * @param config WifiConfiguration object corresponding to the network. - * @param maxSize Max size desired for the cache. - * @param trimSize Size to trim the cache down to once it reaches |maxSize|. - */ - ScanDetailCache(WifiConfiguration config, int maxSize, int trimSize) { - mConfig = config; - mMaxSize = maxSize; - mTrimSize = trimSize; - mMap = new HashMap(16, 0.75f); - } - - void put(ScanDetail scanDetail) { - // First check if we have reached |maxSize|. if yes, trim it down to |trimSize|. - if (mMap.size() >= mMaxSize) { - trim(); - } - - mMap.put(scanDetail.getBSSIDString(), scanDetail); - } - - /** - * Get ScanResult object corresponding to the provided BSSID. - * - * @param bssid provided BSSID - * @return {@code null} if no match ScanResult is found. - */ - public ScanResult getScanResult(String bssid) { - ScanDetail scanDetail = getScanDetail(bssid); - return scanDetail == null ? null : scanDetail.getScanResult(); - } - - /** - * Get ScanDetail object corresponding to the provided BSSID. - * - * @param bssid provided BSSID - * @return {@code null} if no match ScanDetail is found. - */ - public ScanDetail getScanDetail(@NonNull String bssid) { - return mMap.get(bssid); - } - - void remove(@NonNull String bssid) { - mMap.remove(bssid); - } - - int size() { - return mMap.size(); - } - - boolean isEmpty() { - return size() == 0; - } - - Collection<String> keySet() { - return mMap.keySet(); - } - - Collection<ScanDetail> values() { - return mMap.values(); - } - - /** - * Method to reduce the cache to |mTrimSize| size by removing the oldest entries. - * TODO: Investigate if this method can be further optimized. - */ - private void trim() { - int currentSize = mMap.size(); - if (currentSize < mTrimSize) { - return; // Nothing to trim - } - ArrayList<ScanDetail> list = new ArrayList<ScanDetail>(mMap.values()); - if (list.size() != 0) { - // Sort by descending timestamp - Collections.sort(list, new Comparator() { - public int compare(Object o1, Object o2) { - ScanDetail a = (ScanDetail) o1; - ScanDetail b = (ScanDetail) o2; - if (a.getSeen() > b.getSeen()) { - return 1; - } - if (a.getSeen() < b.getSeen()) { - return -1; - } - return a.getBSSIDString().compareTo(b.getBSSIDString()); - } - }); - } - for (int i = 0; i < currentSize - mTrimSize; i++) { - // Remove oldest results from scan cache - ScanDetail result = list.get(i); - mMap.remove(result.getBSSIDString()); - } - } - - /* @hide */ - private ArrayList<ScanDetail> sort() { - ArrayList<ScanDetail> list = new ArrayList<ScanDetail>(mMap.values()); - if (list.size() != 0) { - Collections.sort(list, new Comparator() { - public int compare(Object o1, Object o2) { - ScanResult a = ((ScanDetail) o1).getScanResult(); - ScanResult b = ((ScanDetail) o2).getScanResult(); - if (a.seen > b.seen) { - return -1; - } - if (a.seen < b.seen) { - return 1; - } - if (a.level > b.level) { - return -1; - } - if (a.level < b.level) { - return 1; - } - return a.BSSID.compareTo(b.BSSID); - } - }); - } - return list; - } - - @Override - public String toString() { - StringBuilder sbuf = new StringBuilder(); - sbuf.append("Scan Cache: ").append('\n'); - - ArrayList<ScanDetail> list = sort(); - long now_ms = System.currentTimeMillis(); - if (list.size() > 0) { - for (ScanDetail scanDetail : list) { - ScanResult result = scanDetail.getScanResult(); - long milli = now_ms - scanDetail.getSeen(); - long ageSec = 0; - long ageMin = 0; - long ageHour = 0; - long ageMilli = 0; - long ageDay = 0; - if (now_ms > scanDetail.getSeen() && scanDetail.getSeen() > 0) { - ageMilli = milli % 1000; - ageSec = (milli / 1000) % 60; - ageMin = (milli / (60 * 1000)) % 60; - ageHour = (milli / (60 * 60 * 1000)) % 24; - ageDay = (milli / (24 * 60 * 60 * 1000)); - } - sbuf.append("{").append(result.BSSID).append(",").append(result.frequency); - sbuf.append(",").append(String.format("%3d", result.level)); - if (ageSec > 0 || ageMilli > 0) { - sbuf.append(String.format(",%4d.%02d.%02d.%02d.%03dms", ageDay, - ageHour, ageMin, ageSec, ageMilli)); - } - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - if (networkDetail != null && networkDetail.isInterworking()) { - sbuf.append(",Ant=").append(networkDetail.getAnt()).append(",Internet=") - .append(networkDetail.isInternet()); - } - sbuf.append("} "); - } - sbuf.append('\n'); - } - - return sbuf.toString(); - } - -} diff --git a/service/java/com/android/server/wifi/ScanRequestProxy.java b/service/java/com/android/server/wifi/ScanRequestProxy.java deleted file mode 100644 index 622fcdab9..000000000 --- a/service/java/com/android/server/wifi/ScanRequestProxy.java +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_SCAN_THROTTLE_ENABLED; - -import android.annotation.NonNull; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.Intent; -import android.net.wifi.IScanResultsCallback; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiScanner; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.WorkSource; -import android.util.ArrayMap; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import javax.annotation.concurrent.NotThreadSafe; - -/** - * This class manages all scan requests originating from external apps using the - * {@link WifiManager#startScan()}. - * - * This class is responsible for: - * a) Enable/Disable scanning based on the request from {@link ActiveModeWarden}. - * a) Forwarding scan requests from {@link WifiManager#startScan()} to - * {@link WifiScanner#startScan(WifiScanner.ScanSettings, WifiScanner.ScanListener)}. - * Will essentially proxy scan requests from WifiService to WifiScanningService. - * b) Cache the results of these scan requests and return them when - * {@link WifiManager#getScanResults()} is invoked. - * c) Will send out the {@link WifiManager#SCAN_RESULTS_AVAILABLE_ACTION} broadcast when new - * scan results are available. - * d) Throttle scan requests from non-setting apps: - * a) Each foreground app can request a max of - * {@link #SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS} scan every - * {@link #SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS}. - * b) Background apps combined can request 1 scan every - * {@link #SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS}. - * Note: This class is not thread-safe. It needs to be invoked from the main Wifi thread only. - */ -@NotThreadSafe -public class ScanRequestProxy { - private static final String TAG = "WifiScanRequestProxy"; - - @VisibleForTesting - public static final int SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS = 120 * 1000; - @VisibleForTesting - public static final int SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS = 4; - @VisibleForTesting - public static final int SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS = 30 * 60 * 1000; - - private final Context mContext; - private final Handler mHandler; - private final AppOpsManager mAppOps; - private final ActivityManager mActivityManager; - private final WifiInjector mWifiInjector; - private final WifiConfigManager mWifiConfigManager; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final WifiMetrics mWifiMetrics; - private final Clock mClock; - private final WifiSettingsConfigStore mSettingsConfigStore; - private WifiScanner mWifiScanner; - - // Verbose logging flag. - private boolean mVerboseLoggingEnabled = false; - private boolean mThrottleEnabled = true; - // Flag to decide if we need to scan or not. - private boolean mScanningEnabled = false; - // Flag to decide if we need to scan for hidden networks or not. - private boolean mScanningForHiddenNetworksEnabled = false; - // Timestamps for the last scan requested by any background app. - private long mLastScanTimestampForBgApps = 0; - // Timestamps for the list of last few scan requests by each foreground app. - // Keys in the map = Pair<Uid, PackageName> of the app. - // Values in the map = List of the last few scan request timestamps from the app. - private final ArrayMap<Pair<Integer, String>, LinkedList<Long>> mLastScanTimestampsForFgApps = - new ArrayMap(); - // Scan results cached from the last full single scan request. - private final List<ScanResult> mLastScanResults = new ArrayList<>(); - // external ScanResultCallback tracker - private final RemoteCallbackList<IScanResultsCallback> mRegisteredScanResultsCallbacks; - // Global scan listener for listening to all scan requests. - private class GlobalScanListener implements WifiScanner.ScanListener { - @Override - public void onSuccess() { - // Ignore. These will be processed from the scan request listener. - } - - @Override - public void onFailure(int reason, String description) { - // Ignore. These will be processed from the scan request listener. - } - - @Override - public void onResults(WifiScanner.ScanData[] scanDatas) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Scan results received"); - } - // For single scans, the array size should always be 1. - if (scanDatas.length != 1) { - Log.wtf(TAG, "Found more than 1 batch of scan results, Failing..."); - sendScanResultBroadcast(false); - return; - } - WifiScanner.ScanData scanData = scanDatas[0]; - ScanResult[] scanResults = scanData.getResults(); - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Received " + scanResults.length + " scan results"); - } - // Only process full band scan results. - if (WifiScanner.isFullBandScan(scanData.getBandScanned(), false)) { - // Store the last scan results & send out the scan completion broadcast. - mLastScanResults.clear(); - mLastScanResults.addAll(Arrays.asList(scanResults)); - sendScanResultBroadcast(true); - sendScanResultsAvailableToCallbacks(); - } - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - // Ignore for single scans. - } - - @Override - public void onPeriodChanged(int periodInMs) { - // Ignore for single scans. - } - }; - - // Common scan listener for scan requests initiated by this class. - private class ScanRequestProxyScanListener implements WifiScanner.ScanListener { - @Override - public void onSuccess() { - // Scan request succeeded, wait for results to report to external clients. - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Scan request succeeded"); - } - } - - @Override - public void onFailure(int reason, String description) { - Log.e(TAG, "Scan failure received. reason: " + reason + ",description: " + description); - sendScanResultBroadcast(false); - } - - @Override - public void onResults(WifiScanner.ScanData[] scanDatas) { - // Ignore. These will be processed from the global listener. - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - // Ignore for single scans. - } - - @Override - public void onPeriodChanged(int periodInMs) { - // Ignore for single scans. - } - }; - - ScanRequestProxy(Context context, AppOpsManager appOpsManager, ActivityManager activityManager, - WifiInjector wifiInjector, WifiConfigManager configManager, - WifiPermissionsUtil wifiPermissionUtil, WifiMetrics wifiMetrics, Clock clock, - Handler handler, WifiSettingsConfigStore settingsConfigStore) { - mContext = context; - mHandler = handler; - mAppOps = appOpsManager; - mActivityManager = activityManager; - mWifiInjector = wifiInjector; - mWifiConfigManager = configManager; - mWifiPermissionsUtil = wifiPermissionUtil; - mWifiMetrics = wifiMetrics; - mClock = clock; - mSettingsConfigStore = settingsConfigStore; - mRegisteredScanResultsCallbacks = new RemoteCallbackList<>(); - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = (verbose > 0); - } - - /** - * Helper method to populate WifiScanner handle. This is done lazily because - * WifiScanningService is started after WifiService. - */ - private boolean retrieveWifiScannerIfNecessary() { - if (mWifiScanner == null) { - mWifiScanner = mWifiInjector.getWifiScanner(); - // Start listening for throttle settings change after we retrieve scanner instance. - mThrottleEnabled = mSettingsConfigStore.get(WIFI_SCAN_THROTTLE_ENABLED); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Scan throttle enabled " + mThrottleEnabled); - } - // Register the global scan listener. - if (mWifiScanner != null) { - mWifiScanner.registerScanListener( - new HandlerExecutor(mHandler), new GlobalScanListener()); - } - } - return mWifiScanner != null; - } - - /** - * Method that lets public apps know that scans are available. - * - * @param context Context to use for the notification - * @param available boolean indicating if scanning is available - */ - private void sendScanAvailableBroadcast(Context context, boolean available) { - Log.d(TAG, "Sending scan available broadcast: " + available); - final Intent intent = new Intent(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, available); - context.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private void enableScanningInternal(boolean enable) { - if (!retrieveWifiScannerIfNecessary()) { - Log.e(TAG, "Failed to retrieve wifiscanner"); - return; - } - mWifiScanner.setScanningEnabled(enable); - sendScanAvailableBroadcast(mContext, enable); - clearScanResults(); - Log.i(TAG, "Scanning is " + (enable ? "enabled" : "disabled")); - } - - /** - * Enable/disable scanning. - * - * @param enable true to enable, false to disable. - * @param enableScanningForHiddenNetworks true to enable scanning for hidden networks, - * false to disable. - */ - public void enableScanning(boolean enable, boolean enableScanningForHiddenNetworks) { - if (enable) { - enableScanningInternal(true); - mScanningForHiddenNetworksEnabled = enableScanningForHiddenNetworks; - Log.i(TAG, "Scanning for hidden networks is " - + (enableScanningForHiddenNetworks ? "enabled" : "disabled")); - } else { - enableScanningInternal(false); - } - mScanningEnabled = enable; - } - - - /** - * Helper method to send the scan request status broadcast. - */ - private void sendScanResultBroadcast(boolean scanSucceeded) { - Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - /** - * Helper method to send the scan request failure broadcast to specified package. - */ - private void sendScanResultFailureBroadcastToPackage(String packageName) { - Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); - intent.setPackage(packageName); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - private void trimPastScanRequestTimesForForegroundApp( - List<Long> scanRequestTimestamps, long currentTimeMillis) { - Iterator<Long> timestampsIter = scanRequestTimestamps.iterator(); - while (timestampsIter.hasNext()) { - Long scanRequestTimeMillis = timestampsIter.next(); - if ((currentTimeMillis - scanRequestTimeMillis) - > SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS) { - timestampsIter.remove(); - } else { - // This list is sorted by timestamps, so we can skip any more checks - break; - } - } - } - - private LinkedList<Long> getOrCreateScanRequestTimestampsForForegroundApp( - int callingUid, String packageName) { - Pair<Integer, String> uidAndPackageNamePair = Pair.create(callingUid, packageName); - LinkedList<Long> scanRequestTimestamps = - mLastScanTimestampsForFgApps.get(uidAndPackageNamePair); - if (scanRequestTimestamps == null) { - scanRequestTimestamps = new LinkedList<>(); - mLastScanTimestampsForFgApps.put(uidAndPackageNamePair, scanRequestTimestamps); - } - return scanRequestTimestamps; - } - - /** - * Checks if the scan request from the app (specified by packageName) needs - * to be throttled. - * The throttle limit allows a max of {@link #SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS} - * in {@link #SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS} window. - */ - private boolean shouldScanRequestBeThrottledForForegroundApp( - int callingUid, String packageName) { - LinkedList<Long> scanRequestTimestamps = - getOrCreateScanRequestTimestampsForForegroundApp(callingUid, packageName); - long currentTimeMillis = mClock.getElapsedSinceBootMillis(); - // First evict old entries from the list. - trimPastScanRequestTimesForForegroundApp(scanRequestTimestamps, currentTimeMillis); - if (scanRequestTimestamps.size() >= SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS) { - return true; - } - // Proceed with the scan request and record the time. - scanRequestTimestamps.addLast(currentTimeMillis); - return false; - } - - /** - * Checks if the scan request from a background app needs to be throttled. - */ - private boolean shouldScanRequestBeThrottledForBackgroundApp() { - long lastScanMs = mLastScanTimestampForBgApps; - long elapsedRealtime = mClock.getElapsedSinceBootMillis(); - if (lastScanMs != 0 - && (elapsedRealtime - lastScanMs) < SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS) { - return true; - } - // Proceed with the scan request and record the time. - mLastScanTimestampForBgApps = elapsedRealtime; - return false; - } - - /** - * Check if the request comes from background app. - */ - private boolean isRequestFromBackground(int callingUid, String packageName) { - mAppOps.checkPackage(callingUid, packageName); - try { - return mActivityManager.getPackageImportance(packageName) - > ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; - } catch (SecurityException e) { - Log.e(TAG, "Failed to check the app state", e); - return true; - } - } - - /** - * Checks if the scan request from the app (specified by callingUid & packageName) needs - * to be throttled. - */ - private boolean shouldScanRequestBeThrottledForApp(int callingUid, String packageName) { - boolean isThrottled; - if (isRequestFromBackground(callingUid, packageName)) { - isThrottled = shouldScanRequestBeThrottledForBackgroundApp(); - if (isThrottled) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Background scan app request [" + callingUid + ", " - + packageName + "]"); - } - mWifiMetrics.incrementExternalBackgroundAppOneshotScanRequestsThrottledCount(); - } - } else { - isThrottled = shouldScanRequestBeThrottledForForegroundApp(callingUid, packageName); - if (isThrottled) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Foreground scan app request [" + callingUid + ", " - + packageName + "]"); - } - mWifiMetrics.incrementExternalForegroundAppOneshotScanRequestsThrottledCount(); - } - } - mWifiMetrics.incrementExternalAppOneshotScanRequestsCount(); - return isThrottled; - } - - /** - * Initiate a wifi scan. - * - * @param callingUid The uid initiating the wifi scan. Blame will be given to this uid. - * @return true if the scan request was placed or a scan is already ongoing, false otherwise. - */ - public boolean startScan(int callingUid, String packageName) { - if (!mScanningEnabled || !retrieveWifiScannerIfNecessary()) { - Log.e(TAG, "Failed to retrieve wifiscanner"); - sendScanResultFailureBroadcastToPackage(packageName); - return false; - } - boolean fromSettingsOrSetupWizard = - mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid) - || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(callingUid); - // Check and throttle scan request unless, - // a) App has either NETWORK_SETTINGS or NETWORK_SETUP_WIZARD permission. - // b) Throttling has been disabled by user. - if (!fromSettingsOrSetupWizard && mThrottleEnabled - && shouldScanRequestBeThrottledForApp(callingUid, packageName)) { - Log.i(TAG, "Scan request from " + packageName + " throttled"); - sendScanResultFailureBroadcastToPackage(packageName); - return false; - } - // Create a worksource using the caller's UID. - WorkSource workSource = new WorkSource(callingUid, packageName); - - // Create the scan settings. - WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings(); - // Scan requests from apps with network settings will be of high accuracy type. - if (fromSettingsOrSetupWizard) { - settings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - } - // always do full scans - settings.band = WifiScanner.WIFI_BAND_ALL; - settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN - | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; - if (mScanningForHiddenNetworksEnabled) { - settings.hiddenNetworks.clear(); - // retrieve the list of hidden network SSIDs from saved network to scan for, if enabled. - settings.hiddenNetworks.addAll(mWifiConfigManager.retrieveHiddenNetworkList()); - // retrieve the list of hidden network SSIDs from Network suggestion to scan for. - settings.hiddenNetworks.addAll( - mWifiInjector.getWifiNetworkSuggestionsManager().retrieveHiddenNetworkList()); - } - mWifiScanner.startScan(settings, new HandlerExecutor(mHandler), - new ScanRequestProxyScanListener(), workSource); - return true; - } - - /** - * Return the results of the most recent access point scan, in the form of - * a list of {@link ScanResult} objects. - * @return the list of results - */ - public List<ScanResult> getScanResults() { - // return a copy to prevent external modification - return new ArrayList<>(mLastScanResults); - } - - /** - * Clear the stored scan results. - */ - private void clearScanResults() { - mLastScanResults.clear(); - mLastScanTimestampForBgApps = 0; - mLastScanTimestampsForFgApps.clear(); - } - - /** - * Clear any scan timestamps being stored for the app. - * - * @param uid Uid of the package. - * @param packageName Name of the package. - */ - public void clearScanRequestTimestampsForApp(@NonNull String packageName, int uid) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Clearing scan request timestamps for uid=" + uid + ", packageName=" - + packageName); - } - mLastScanTimestampsForFgApps.remove(Pair.create(uid, packageName)); - } - - private void sendScanResultsAvailableToCallbacks() { - int itemCount = mRegisteredScanResultsCallbacks.beginBroadcast(); - for (int i = 0; i < itemCount; i++) { - try { - mRegisteredScanResultsCallbacks.getBroadcastItem(i).onScanResultsAvailable(); - } catch (RemoteException e) { - Log.e(TAG, "onScanResultsAvailable: remote exception -- " + e); - } - } - mRegisteredScanResultsCallbacks.finishBroadcast(); - } - - /** - * Register a callback on scan event - * @param callback IScanResultListener instance to add. - * @return true if succeed otherwise false. - */ - public boolean registerScanResultsCallback(IScanResultsCallback callback) { - return mRegisteredScanResultsCallbacks.register(callback); - } - - /** - * Unregister a callback on scan event - * @param callback IScanResultListener instance to add. - */ - public void unregisterScanResultsCallback(IScanResultsCallback callback) { - mRegisteredScanResultsCallbacks.unregister(callback); - } - - /** - * Enable/disable wifi scan throttling from 3rd party apps. - */ - public void setScanThrottleEnabled(boolean enable) { - mThrottleEnabled = enable; - mSettingsConfigStore.put(WIFI_SCAN_THROTTLE_ENABLED, enable); - Log.i(TAG, "Scan throttle enabled " + mThrottleEnabled); - } - - /** - * Get the persisted Wi-Fi scan throttle state, set by - * {@link #setScanThrottleEnabled(boolean)}. - */ - public boolean isScanThrottleEnabled() { - return mThrottleEnabled; - } -} diff --git a/service/java/com/android/server/wifi/ScanResultMatchInfo.java b/service/java/com/android/server/wifi/ScanResultMatchInfo.java deleted file mode 100644 index cd489536e..000000000 --- a/service/java/com/android/server/wifi/ScanResultMatchInfo.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.annotation.NonNull; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; - -import com.android.server.wifi.util.ScanResultUtil; - -import java.util.Objects; - -/** - * Class to store the info needed to match a scan result to the provided network configuration. - */ -public class ScanResultMatchInfo { - /** - * SSID of the network. - */ - public String networkSsid; - /** - * Security Type of the network. - */ - public @WifiConfiguration.SecurityType int networkType; - /** - * Special flag for PSK-SAE in transition mode - */ - public boolean pskSaeInTransitionMode; - /** - * Special flag for OWE in transition mode - */ - public boolean oweInTransitionMode; - - /** - * True if created from a scan result - */ - private boolean mFromScanResult = false; - /** - * Fetch network type from network configuration. - */ - private static @WifiConfiguration.SecurityType int getNetworkType(WifiConfiguration config) { - if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_SAE; - } else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_PSK; - } else if (WifiConfigurationUtil.isConfigForWapiPskNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_WAPI_PSK; - } else if (WifiConfigurationUtil.isConfigForWapiCertNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_WAPI_CERT; - } else if (WifiConfigurationUtil.isConfigForEapNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_EAP; - } else if (WifiConfigurationUtil.isConfigForEapSuiteBNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B; - } else if (WifiConfigurationUtil.isConfigForWepNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_WEP; - } else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_OWE; - } else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) { - return WifiConfiguration.SECURITY_TYPE_OPEN; - } - throw new IllegalArgumentException("Invalid WifiConfiguration: " + config); - } - - /** - * Get the ScanResultMatchInfo for the given WifiConfiguration - */ - public static ScanResultMatchInfo fromWifiConfiguration(WifiConfiguration config) { - ScanResultMatchInfo info = new ScanResultMatchInfo(); - info.networkSsid = config.SSID; - info.networkType = getNetworkType(config); - return info; - } - - /** - * Fetch network type from scan result. - */ - private static @WifiConfiguration.SecurityType int getNetworkType(ScanResult scanResult) { - if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_SAE; - } else if (ScanResultUtil.isScanResultForWapiPskNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_WAPI_PSK; - } else if (ScanResultUtil.isScanResultForWapiCertNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_WAPI_CERT; - } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_PSK; - } else if (ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B; - } else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_EAP; - } else if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_WEP; - } else if (ScanResultUtil.isScanResultForOweNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_OWE; - } else if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)) { - return WifiConfiguration.SECURITY_TYPE_OPEN; - } else { - throw new IllegalArgumentException("Invalid ScanResult: " + scanResult); - } - } - - /** - * Get the ScanResultMatchInfo for the given ScanResult - */ - public static ScanResultMatchInfo fromScanResult(ScanResult scanResult) { - ScanResultMatchInfo info = new ScanResultMatchInfo(); - // Scan result ssid's are not quoted, hence add quotes. - // TODO: This matching algo works only if the scan result contains a string SSID. - // However, according to our public documentation ths {@link WifiConfiguration#SSID} can - // either have a hex string or quoted ASCII string SSID. - info.networkSsid = ScanResultUtil.createQuotedSSID(scanResult.SSID); - info.networkType = getNetworkType(scanResult); - info.oweInTransitionMode = false; - info.pskSaeInTransitionMode = false; - info.mFromScanResult = true; - if (info.networkType == WifiConfiguration.SECURITY_TYPE_SAE) { - // Note that scan result util will always choose the highest security protocol. - info.pskSaeInTransitionMode = - ScanResultUtil.isScanResultForPskSaeTransitionNetwork(scanResult); - } else if (info.networkType == WifiConfiguration.SECURITY_TYPE_OWE) { - // Note that scan result util will always choose OWE. - info.oweInTransitionMode = - ScanResultUtil.isScanResultForOweTransitionNetwork(scanResult); - } - return info; - } - - /** - * Checks for equality of network type. - */ - public boolean networkTypeEquals(@NonNull ScanResultMatchInfo other, - boolean saeAutoUpgradeEnabled) { - boolean networkTypeEquals; - // Detect <SSID, PSK+SAE> scan result and say it is equal to <SSID, PSK> configuration - if (other.pskSaeInTransitionMode && networkType == WifiConfiguration.SECURITY_TYPE_PSK - || (pskSaeInTransitionMode - && other.networkType == WifiConfiguration.SECURITY_TYPE_PSK)) { - networkTypeEquals = true; - } else if ((networkType == WifiConfiguration.SECURITY_TYPE_OPEN - && other.oweInTransitionMode) || (oweInTransitionMode - && other.networkType == WifiConfiguration.SECURITY_TYPE_OPEN)) { - // Special case we treat Enhanced Open and Open as equals. This is done to support the - // case where a saved network is Open but we found an OWE in transition network. - networkTypeEquals = true; - } else if ((saeAutoUpgradeEnabled) - && ((mFromScanResult && networkType == WifiConfiguration.SECURITY_TYPE_SAE - && other.networkType == WifiConfiguration.SECURITY_TYPE_PSK) - || (other.mFromScanResult - && other.networkType == WifiConfiguration.SECURITY_TYPE_SAE - && networkType == WifiConfiguration.SECURITY_TYPE_PSK))) { - // Allow upgrading WPA2 PSK connections to WPA3 SAE AP - networkTypeEquals = true; - } else { - networkTypeEquals = networkType == other.networkType; - } - return networkTypeEquals; - } - - @Override - public boolean equals(Object otherObj) { - return matchForNetworkSelection(otherObj, false); - } - - /** - * Match two ScanResultMatchInfo objects while considering configuration in overlays - * - * @param otherObj Other object to compare against - * @param saeAutoUpgradeEnabled A boolean that indicates if WPA3 auto upgrade feature is enabled - * @return true if objects are equal for network selection purposes, false otherwise - */ - public boolean matchForNetworkSelection(Object otherObj, boolean saeAutoUpgradeEnabled) { - if (this == otherObj) { - return true; - } else if (!(otherObj instanceof ScanResultMatchInfo)) { - return false; - } - ScanResultMatchInfo other = (ScanResultMatchInfo) otherObj; - if (!Objects.equals(networkSsid, other.networkSsid)) { - return false; - } - return networkTypeEquals(other, saeAutoUpgradeEnabled); - } - - @Override - public int hashCode() { - return Objects.hash(networkSsid); - } - - @Override - public String toString() { - return "ScanResultMatchInfo: SSID: " + networkSsid + ", type: " + networkType - + ", WPA3 in transition mode: " + pskSaeInTransitionMode - + ", OWE in transition mode: " + oweInTransitionMode + ", from scan result: " - + mFromScanResult; - } -} diff --git a/service/java/com/android/server/wifi/ScoreCardBasedScorer.java b/service/java/com/android/server/wifi/ScoreCardBasedScorer.java deleted file mode 100644 index 7363a771b..000000000 --- a/service/java/com/android/server/wifi/ScoreCardBasedScorer.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.net.wifi.ScanResult; - -import com.android.server.wifi.WifiCandidates.Candidate; -import com.android.server.wifi.WifiCandidates.ScoredCandidate; -import com.android.server.wifi.proto.WifiScoreCardProto; -import com.android.server.wifi.proto.WifiScoreCardProto.Event; - -import java.util.Collection; - -/** - * A candidate scorer that uses the scorecard to influence the choice. - */ -final class ScoreCardBasedScorer implements WifiCandidates.CandidateScorer { - - /** - * This should match WifiNetworkSelector.experimentIdFromIdentifier(getIdentifier()) - * when using the default ScoringParams. - */ - public static final int SCORE_CARD_BASED_SCORER_DEFAULT_EXPID = 42902385; - - private final ScoringParams mScoringParams; - - // config_wifi_framework_RSSI_SCORE_OFFSET - public static final int RSSI_SCORE_OFFSET = 85; - - // config_wifi_framework_RSSI_SCORE_SLOPE - public static final int RSSI_SCORE_SLOPE_IS_4 = 4; - - // config_wifi_framework_5GHz_preference_boost_factor - public static final int BAND_5GHZ_AWARD_IS_40 = 40; - - // config_wifiFramework6ghzPreferenceBoostFactor - public static final int BAND_6GHZ_AWARD_IS_40 = 40; - - // config_wifi_framework_SECURITY_AWARD - public static final int SECURITY_AWARD_IS_80 = 80; - - // config_wifi_framework_LAST_SELECTION_AWARD - public static final int LAST_SELECTION_AWARD_IS_480 = 480; - - // config_wifi_framework_current_network_boost - public static final int CURRENT_NETWORK_BOOST_IS_16 = 16; - - // config_wifi_framework_SAME_BSSID_AWARD - public static final int SAME_BSSID_AWARD_IS_24 = 24; - - // Only use scorecard id we have data from this many polls - public static final int MIN_POLLS_FOR_SIGNIFICANCE = 30; - - // Maximum allowable adjustment of the cutoff rssi (dB) - public static final int RSSI_RAIL = 5; - - private static final boolean USE_USER_CONNECT_CHOICE = true; - - ScoreCardBasedScorer(ScoringParams scoringParams) { - mScoringParams = scoringParams; - } - - @Override - public String getIdentifier() { - return "ScoreCardBasedScorer"; - } - - /** - * Calculates an individual candidate's score. - */ - private ScoredCandidate scoreCandidate(Candidate candidate) { - int rssiSaturationThreshold = mScoringParams.getGoodRssi(candidate.getFrequency()); - int rssi = Math.min(candidate.getScanRssi(), rssiSaturationThreshold); - int cutoff = estimatedCutoff(candidate); - int score = (rssi - cutoff) * RSSI_SCORE_SLOPE_IS_4; - - if (ScanResult.is6GHz(candidate.getFrequency())) { - score += BAND_6GHZ_AWARD_IS_40; - } else if (ScanResult.is5GHz(candidate.getFrequency())) { - score += BAND_5GHZ_AWARD_IS_40; - } - score += (int) (candidate.getLastSelectionWeight() * LAST_SELECTION_AWARD_IS_480); - - if (candidate.isCurrentNetwork()) { - score += CURRENT_NETWORK_BOOST_IS_16 + SAME_BSSID_AWARD_IS_24; - } - - if (!candidate.isOpenNetwork()) { - score += SECURITY_AWARD_IS_80; - } - - // To simulate the old strict priority rule, subtract a penalty based on - // which nominator added the candidate. - score -= 1000 * candidate.getNominatorId(); - - return new ScoredCandidate(score, 10, - USE_USER_CONNECT_CHOICE, candidate); - } - - private int estimatedCutoff(Candidate candidate) { - int cutoff = -RSSI_SCORE_OFFSET; - int lowest = cutoff - RSSI_RAIL; - int highest = cutoff + RSSI_RAIL; - WifiScoreCardProto.Signal signal = candidate.getEventStatistics(Event.SIGNAL_POLL); - if (signal == null) return cutoff; - if (!signal.hasRssi()) return cutoff; - if (signal.getRssi().getCount() > MIN_POLLS_FOR_SIGNIFICANCE) { - double mean = signal.getRssi().getSum() / signal.getRssi().getCount(); - double mean_square = signal.getRssi().getSumOfSquares() / signal.getRssi().getCount(); - double variance = mean_square - mean * mean; - double sigma = Math.sqrt(variance); - double value = mean - 2.0 * sigma; - cutoff = (int) Math.min(Math.max(value, lowest), highest); - } - return cutoff; - } - - @Override - public ScoredCandidate scoreCandidates(@NonNull Collection<Candidate> candidates) { - ScoredCandidate choice = ScoredCandidate.NONE; - for (Candidate candidate : candidates) { - ScoredCandidate scoredCandidate = scoreCandidate(candidate); - if (scoredCandidate.value > choice.value) { - choice = scoredCandidate; - } - } - // Here we just return the highest scored candidate; we could - // compute a new score, if desired. - return choice; - } - -} diff --git a/service/java/com/android/server/wifi/ScoredNetworkNominator.java b/service/java/com/android/server/wifi/ScoredNetworkNominator.java deleted file mode 100644 index b2b28c0f5..000000000 --- a/service/java/com/android/server/wifi/ScoredNetworkNominator.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.pm.PackageManager; -import android.database.ContentObserver; -import android.net.NetworkKey; -import android.net.NetworkScoreManager; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.os.Handler; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.LocalLog; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import java.util.ArrayList; -import java.util.List; - -/** - * {@link WifiNetworkSelector.NetworkNominator} implementation that uses scores obtained by - * {@link NetworkScoreManager#requestScores(NetworkKey[])} to make network connection decisions. - */ -public class ScoredNetworkNominator implements WifiNetworkSelector.NetworkNominator { - private static final String TAG = "ScoredNetworkNominator"; - // TODO (b/150977740): Stop using the @hide settings global flag. - @VisibleForTesting - public static final String SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE = - "use_open_wifi_package"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - - private final NetworkScoreManager mNetworkScoreManager; - private final PackageManager mPackageManager; - private final WifiConfigManager mWifiConfigManager; - private final LocalLog mLocalLog; - private final ContentObserver mContentObserver; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private boolean mNetworkRecommendationsEnabled; - private WifiNetworkScoreCache mScoreCache; - - ScoredNetworkNominator(final Context context, Handler handler, - final FrameworkFacade frameworkFacade, NetworkScoreManager networkScoreManager, - PackageManager packageManager, - WifiConfigManager wifiConfigManager, LocalLog localLog, - WifiNetworkScoreCache wifiNetworkScoreCache, - WifiPermissionsUtil wifiPermissionsUtil) { - mScoreCache = wifiNetworkScoreCache; - mWifiPermissionsUtil = wifiPermissionsUtil; - mNetworkScoreManager = networkScoreManager; - mPackageManager = packageManager; - mWifiConfigManager = wifiConfigManager; - mLocalLog = localLog; - mContentObserver = new ContentObserver(handler) { - @Override - public void onChange(boolean selfChange) { - mNetworkRecommendationsEnabled = frameworkFacade.getStringSetting(context, - SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE) != null; - } - }; - frameworkFacade.registerContentObserver(context, - Settings.Global.getUriFor(SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE), - false /* notifyForDescendents */, mContentObserver); - mContentObserver.onChange(false /* unused */); - mLocalLog.log("ScoredNetworkNominator constructed. mNetworkRecommendationsEnabled: " - + mNetworkRecommendationsEnabled); - } - - @Override - public void update(List<ScanDetail> scanDetails) { - if (mNetworkRecommendationsEnabled) { - updateNetworkScoreCache(scanDetails); - } - } - - private void updateNetworkScoreCache(List<ScanDetail> scanDetails) { - ArrayList<NetworkKey> unscoredNetworks = new ArrayList<NetworkKey>(); - for (int i = 0; i < scanDetails.size(); i++) { - ScanResult scanResult = scanDetails.get(i).getScanResult(); - NetworkKey networkKey = NetworkKey.createFromScanResult(scanResult); - if (networkKey != null) { - // Is there a ScoredNetwork for this ScanResult? If not, request a score. - if (mScoreCache.getScoredNetwork(networkKey) == null) { - unscoredNetworks.add(networkKey); - } - } - } - - // Kick the score manager if there are any unscored network. - if (!unscoredNetworks.isEmpty() && activeScorerAllowedtoSeeScanResults()) { - mNetworkScoreManager.requestScores(unscoredNetworks); - } - } - - private Pair<Integer, String> getActiveScorerUidAndPackage() { - String packageName = mNetworkScoreManager.getActiveScorerPackage(); - if (packageName == null) return null; - int uid = -1; - try { - uid = mPackageManager.getApplicationInfo(packageName, 0).uid; - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Failed to retrieve package uid", e); - return null; - } - return Pair.create(uid, packageName); - } - - private boolean activeScorerAllowedtoSeeScanResults() { - Pair<Integer, String> scorerUidAndPackage = getActiveScorerUidAndPackage(); - if (scorerUidAndPackage == null) return false; - try { - // TODO moltmann: Can we set a featureID here instead of null? - mWifiPermissionsUtil.enforceCanAccessScanResults( - scorerUidAndPackage.second, null, scorerUidAndPackage.first, null); - return true; - } catch (SecurityException e) { - return false; - } - } - - @Override - public void nominateNetworks(List<ScanDetail> scanDetails, - WifiConfiguration currentNetwork, String currentBssid, boolean connected, - boolean untrustedNetworkAllowed, - @NonNull OnConnectableListener onConnectableListener) { - if (!mNetworkRecommendationsEnabled) { - mLocalLog.log("Skipping nominateNetworks; Network recommendations disabled."); - return; - } - - final ScoreTracker scoreTracker = new ScoreTracker(); - for (int i = 0; i < scanDetails.size(); i++) { - ScanDetail scanDetail = scanDetails.get(i); - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult == null) continue; - if (mWifiConfigManager.isNetworkTemporarilyDisabledByUser( - ScanResultUtil.createQuotedSSID(scanResult.SSID))) { - debugLog("Ignoring user disabled SSID: " + scanResult.SSID); - continue; - } - final WifiConfiguration configuredNetwork = - mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail); - boolean untrustedScanResult = configuredNetwork == null || !configuredNetwork.trusted; - - if (!untrustedNetworkAllowed && untrustedScanResult) { - continue; - } - - // Track scan results for open wifi networks - if (configuredNetwork == null) { - if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)) { - scoreTracker.trackUntrustedCandidate(scanDetail); - } - continue; - } - - // Ignore trusted and non-externally scored networks - if (configuredNetwork.trusted && !configuredNetwork.useExternalScores) { - continue; - } - - // Ignore externally scored or ephemeral networks that have been disabled for selection - if (!configuredNetwork.getNetworkSelectionStatus().isNetworkEnabled()) { - debugLog("Ignoring disabled SSID: " + configuredNetwork.SSID); - continue; - } - - // TODO(b/37485956): consider applying a boost for networks with only the same SSID - boolean isCurrentNetwork = currentNetwork != null - && currentNetwork.networkId == configuredNetwork.networkId - && TextUtils.equals(currentBssid, scanResult.BSSID); - if (!configuredNetwork.trusted) { - scoreTracker.trackUntrustedCandidate( - scanResult, configuredNetwork, isCurrentNetwork); - } else { - scoreTracker.trackExternallyScoredCandidate( - scanResult, configuredNetwork, isCurrentNetwork); - } - onConnectableListener.onConnectable(scanDetail, configuredNetwork); - } - scoreTracker.getCandidateConfiguration(onConnectableListener); - } - - /** Used to track the network with the highest score. */ - class ScoreTracker { - private static final int EXTERNAL_SCORED_NONE = 0; - private static final int EXTERNAL_SCORED_SAVED_NETWORK = 1; - private static final int EXTERNAL_SCORED_UNTRUSTED_NETWORK = 2; - - private int mBestCandidateType = EXTERNAL_SCORED_NONE; - private int mHighScore = WifiNetworkScoreCache.INVALID_NETWORK_SCORE; - private WifiConfiguration mEphemeralConfig; - private WifiConfiguration mSavedConfig; - private ScanResult mScanResultCandidate; - private ScanDetail mScanDetailCandidate; - - /** - * Returns the available external network score or null if no score is available. - * - * @param scanResult The scan result of the network to score. - * @param isCurrentNetwork Flag which indicates whether this is the current network. - * @return A valid external score if one is available or NULL. - */ - @Nullable - private Integer getNetworkScore(ScanResult scanResult, boolean isCurrentNetwork) { - if (mScoreCache.isScoredNetwork(scanResult)) { - int score = mScoreCache.getNetworkScore(scanResult, isCurrentNetwork); - if (DEBUG) { - mLocalLog.log(WifiNetworkSelector.toScanId(scanResult) + " has score: " - + score + " isCurrentNetwork network: " + isCurrentNetwork); - } - return score; - } - return null; - } - - /** Track an untrusted {@link ScanDetail}. */ - void trackUntrustedCandidate(ScanDetail scanDetail) { - ScanResult scanResult = scanDetail.getScanResult(); - Integer score = getNetworkScore(scanResult, false /* isCurrentNetwork */); - if (score != null && score > mHighScore) { - mHighScore = score; - mScanResultCandidate = scanResult; - mScanDetailCandidate = scanDetail; - mBestCandidateType = EXTERNAL_SCORED_UNTRUSTED_NETWORK; - debugLog(WifiNetworkSelector.toScanId(scanResult) - + " becomes the new untrusted candidate."); - } - } - - /** - * Track an untrusted {@link ScanResult} that already has a corresponding - * ephemeral {@link WifiConfiguration}. - */ - void trackUntrustedCandidate( - ScanResult scanResult, WifiConfiguration config, boolean isCurrentNetwork) { - Integer score = getNetworkScore(scanResult, isCurrentNetwork); - if (score != null && score > mHighScore) { - mHighScore = score; - mScanResultCandidate = scanResult; - mScanDetailCandidate = null; - mBestCandidateType = EXTERNAL_SCORED_UNTRUSTED_NETWORK; - mEphemeralConfig = config; - mWifiConfigManager.setNetworkCandidateScanResult(config.networkId, scanResult, 0); - debugLog(WifiNetworkSelector.toScanId(scanResult) - + " becomes the new untrusted candidate."); - } - } - - /** Tracks a saved network that has been marked with useExternalScores */ - void trackExternallyScoredCandidate( - ScanResult scanResult, WifiConfiguration config, boolean isCurrentNetwork) { - // Always take the highest score. If there's a tie and an untrusted network is currently - // the best then pick the saved network. - Integer score = getNetworkScore(scanResult, isCurrentNetwork); - if (score != null - && (score > mHighScore - || (mBestCandidateType == EXTERNAL_SCORED_UNTRUSTED_NETWORK - && score == mHighScore))) { - mHighScore = score; - mSavedConfig = config; - mScanResultCandidate = scanResult; - mScanDetailCandidate = null; - mBestCandidateType = EXTERNAL_SCORED_SAVED_NETWORK; - mWifiConfigManager.setNetworkCandidateScanResult(config.networkId, scanResult, 0); - debugLog(WifiNetworkSelector.toScanId(scanResult) - + " becomes the new externally scored saved network candidate."); - } - } - - /** Returns the best candidate network tracked by this {@link ScoreTracker}. */ - @Nullable - WifiConfiguration getCandidateConfiguration( - @NonNull OnConnectableListener onConnectableListener) { - int candidateNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - switch (mBestCandidateType) { - case ScoreTracker.EXTERNAL_SCORED_UNTRUSTED_NETWORK: - if (mEphemeralConfig != null) { - candidateNetworkId = mEphemeralConfig.networkId; - mLocalLog.log(String.format("existing ephemeral candidate %s network ID:%d" - + ", meteredHint=%b", - WifiNetworkSelector.toScanId(mScanResultCandidate), - candidateNetworkId, - mEphemeralConfig.meteredHint)); - break; - } - Pair<Integer, String> scorerUidAndPackage = getActiveScorerUidAndPackage(); - if (scorerUidAndPackage == null) { - mLocalLog.log("Can't find active scorer uid and package"); - break; - } - - mEphemeralConfig = - ScanResultUtil.createNetworkFromScanResult(mScanResultCandidate); - // Mark this config as ephemeral so it isn't persisted. - mEphemeralConfig.ephemeral = true; - // Mark this network as untrusted. - mEphemeralConfig.trusted = false; - mEphemeralConfig.meteredHint = mScoreCache.getMeteredHint(mScanResultCandidate); - NetworkUpdateResult result = - mWifiConfigManager.addOrUpdateNetwork(mEphemeralConfig, - scorerUidAndPackage.first, scorerUidAndPackage.second); - if (!result.isSuccess()) { - mLocalLog.log("Failed to add ephemeral network"); - break; - } - if (!mWifiConfigManager.updateNetworkSelectionStatus(result.getNetworkId(), - WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE)) { - mLocalLog.log("Failed to make ephemeral network selectable"); - break; - } - candidateNetworkId = result.getNetworkId(); - if (mScanDetailCandidate == null) { - // This should never happen, but if it does, WNS will log a wtf. - // A message here might help with the diagnosis. - Log.e(TAG, "mScanDetailCandidate is null!"); - } - mWifiConfigManager.setNetworkCandidateScanResult(candidateNetworkId, - mScanResultCandidate, 0); - mLocalLog.log(String.format("new ephemeral candidate %s network ID:%d, " - + "meteredHint=%b", - WifiNetworkSelector.toScanId(mScanResultCandidate), - candidateNetworkId, - mEphemeralConfig.meteredHint)); - break; - case ScoreTracker.EXTERNAL_SCORED_SAVED_NETWORK: - candidateNetworkId = mSavedConfig.networkId; - mLocalLog.log(String.format("new saved network candidate %s network ID:%d", - WifiNetworkSelector.toScanId(mScanResultCandidate), - candidateNetworkId)); - break; - case ScoreTracker.EXTERNAL_SCORED_NONE: - default: - mLocalLog.log("ScoredNetworkNominator did not see any good candidates."); - break; - } - WifiConfiguration ans = mWifiConfigManager.getConfiguredNetwork( - candidateNetworkId); - if (ans != null && mScanDetailCandidate != null) { - // This is a newly created config, so we need to call onConnectable. - onConnectableListener.onConnectable(mScanDetailCandidate, ans); - } - return ans; - } - } - - private void debugLog(String msg) { - if (DEBUG) { - mLocalLog.log(msg); - } - } - - @Override - public @NominatorId int getId() { - return NOMINATOR_ID_SCORED; - } - - @Override - public String getName() { - return TAG; - } -} diff --git a/service/java/com/android/server/wifi/ScoringParams.java b/service/java/com/android/server/wifi/ScoringParams.java deleted file mode 100644 index f2a318261..000000000 --- a/service/java/com/android/server/wifi/ScoringParams.java +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiInfo; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.KeyValueListParser; -import com.android.wifi.resources.R; - -/** - * Holds parameters used for scoring networks. - * - * Doing this in one place means that there's a better chance of consistency between - * connected score and network selection. - * - */ -public class ScoringParams { - private final Context mContext; - - private static final String TAG = "WifiScoringParams"; - private static final int EXIT = 0; - private static final int ENTRY = 1; - private static final int SUFFICIENT = 2; - private static final int GOOD = 3; - - private static final int ACTIVE_TRAFFIC = 1; - private static final int HIGH_TRAFFIC = 2; - /** - * Parameter values are stored in a separate container so that a new collection of values can - * be checked for consistency before activating them. - */ - private class Values { - /** RSSI thresholds for 2.4 GHz band (dBm) */ - public static final String KEY_RSSI2 = "rssi2"; - public final int[] rssi2 = {-83, -80, -73, -60}; - - /** RSSI thresholds for 5 GHz band (dBm) */ - public static final String KEY_RSSI5 = "rssi5"; - public final int[] rssi5 = {-80, -77, -70, -57}; - - /** RSSI thresholds for 6 GHz band (dBm) */ - public static final String KEY_RSSI6 = "rssi6"; - public final int[] rssi6 = {-80, -77, -70, -57}; - - /** Guidelines based on packet rates (packets/sec) */ - public static final String KEY_PPS = "pps"; - public final int[] pps = {0, 1, 100}; - - /** Number of seconds for RSSI forecast */ - public static final String KEY_HORIZON = "horizon"; - public static final int MIN_HORIZON = -9; - public static final int MAX_HORIZON = 60; - public int horizon = 15; - - /** Number 0-10 influencing requests for network unreachability detection */ - public static final String KEY_NUD = "nud"; - public static final int MIN_NUD = 0; - public static final int MAX_NUD = 10; - public int nud = 8; - - /** Experiment identifier */ - public static final String KEY_EXPID = "expid"; - public static final int MIN_EXPID = 0; - public static final int MAX_EXPID = Integer.MAX_VALUE; - public int expid = 0; - - /** CandidateScorer parameters */ - public int throughputBonusNumerator = 120; - public int throughputBonusDenominator = 433; - public int throughputBonusLimit = 200; - public int savedNetworkBonus = 500; - public int unmeteredNetworkBonus = 1000; - public int currentNetworkBonusMin = 20; - public int currentNetworkBonusPercent = 20; - public int secureNetworkBonus = 40; - public int lastSelectionMinutes = 480; - public static final int MIN_MINUTES = 1; - public static final int MAX_MINUTES = Integer.MAX_VALUE / (60 * 1000); - - Values() { - } - - Values(Values source) { - for (int i = 0; i < rssi2.length; i++) { - rssi2[i] = source.rssi2[i]; - } - for (int i = 0; i < rssi5.length; i++) { - rssi5[i] = source.rssi5[i]; - } - for (int i = 0; i < rssi6.length; i++) { - rssi6[i] = source.rssi6[i]; - } - for (int i = 0; i < pps.length; i++) { - pps[i] = source.pps[i]; - } - horizon = source.horizon; - nud = source.nud; - expid = source.expid; - } - - public void validate() throws IllegalArgumentException { - validateRssiArray(rssi2); - validateRssiArray(rssi5); - validateRssiArray(rssi6); - validateOrderedNonNegativeArray(pps); - validateRange(horizon, MIN_HORIZON, MAX_HORIZON); - validateRange(nud, MIN_NUD, MAX_NUD); - validateRange(expid, MIN_EXPID, MAX_EXPID); - validateRange(lastSelectionMinutes, MIN_MINUTES, MAX_MINUTES); - } - - private void validateRssiArray(int[] rssi) throws IllegalArgumentException { - int low = WifiInfo.MIN_RSSI; - int high = Math.min(WifiInfo.MAX_RSSI, -1); // Stricter than Wifiinfo - for (int i = 0; i < rssi.length; i++) { - validateRange(rssi[i], low, high); - low = rssi[i]; - } - } - - private void validateRange(int k, int low, int high) throws IllegalArgumentException { - if (k < low || k > high) { - throw new IllegalArgumentException(); - } - } - - private void validateOrderedNonNegativeArray(int[] a) throws IllegalArgumentException { - int low = 0; - for (int i = 0; i < a.length; i++) { - if (a[i] < low) { - throw new IllegalArgumentException(); - } - low = a[i]; - } - } - - public void parseString(String kvList) throws IllegalArgumentException { - KeyValueListParser parser = new KeyValueListParser(','); - parser.setString(kvList); - if (parser.size() != ("" + kvList).split(",").length) { - throw new IllegalArgumentException("dup keys"); - } - updateIntArray(rssi2, parser, KEY_RSSI2); - updateIntArray(rssi5, parser, KEY_RSSI5); - updateIntArray(rssi6, parser, KEY_RSSI6); - updateIntArray(pps, parser, KEY_PPS); - horizon = updateInt(parser, KEY_HORIZON, horizon); - nud = updateInt(parser, KEY_NUD, nud); - expid = updateInt(parser, KEY_EXPID, expid); - } - - private int updateInt(KeyValueListParser parser, String key, int defaultValue) - throws IllegalArgumentException { - String value = parser.getString(key, null); - if (value == null) return defaultValue; - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(); - } - } - - private void updateIntArray(final int[] dest, KeyValueListParser parser, String key) - throws IllegalArgumentException { - if (parser.getString(key, null) == null) return; - int[] ints = parser.getIntArray(key, null); - if (ints == null) throw new IllegalArgumentException(); - if (ints.length != dest.length) throw new IllegalArgumentException(); - for (int i = 0; i < dest.length; i++) { - dest[i] = ints[i]; - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - appendKey(sb, KEY_RSSI2); - appendInts(sb, rssi2); - appendKey(sb, KEY_RSSI5); - appendInts(sb, rssi5); - appendKey(sb, KEY_RSSI6); - appendInts(sb, rssi6); - appendKey(sb, KEY_PPS); - appendInts(sb, pps); - appendKey(sb, KEY_HORIZON); - sb.append(horizon); - appendKey(sb, KEY_NUD); - sb.append(nud); - appendKey(sb, KEY_EXPID); - sb.append(expid); - return sb.toString(); - } - - private void appendKey(StringBuilder sb, String key) { - if (sb.length() != 0) sb.append(","); - sb.append(key).append("="); - } - - private void appendInts(StringBuilder sb, final int[] a) { - final int n = a.length; - for (int i = 0; i < n; i++) { - if (i > 0) sb.append(":"); - sb.append(a[i]); - } - } - } - - @NonNull private Values mVal = null; - - @VisibleForTesting - public ScoringParams() { - mContext = null; - mVal = new Values(); - } - - public ScoringParams(Context context) { - mContext = context; - } - - private void loadResources(Context context) { - if (mVal != null) return; - mVal = new Values(); - mVal.rssi2[EXIT] = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz); - mVal.rssi2[ENTRY] = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz); - mVal.rssi2[SUFFICIENT] = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); - mVal.rssi2[GOOD] = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz); - mVal.rssi5[EXIT] = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); - mVal.rssi5[ENTRY] = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz); - mVal.rssi5[SUFFICIENT] = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); - mVal.rssi5[GOOD] = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz); - mVal.rssi6[EXIT] = context.getResources().getInteger( - R.integer.config_wifiFrameworkScoreBadRssiThreshold6ghz); - mVal.rssi6[ENTRY] = context.getResources().getInteger( - R.integer.config_wifiFrameworkScoreEntryRssiThreshold6ghz); - mVal.rssi6[SUFFICIENT] = context.getResources().getInteger( - R.integer.config_wifiFrameworkScoreLowRssiThreshold6ghz); - mVal.rssi6[GOOD] = context.getResources().getInteger( - R.integer.config_wifiFrameworkScoreGoodRssiThreshold6ghz); - mVal.throughputBonusNumerator = context.getResources().getInteger( - R.integer.config_wifiFrameworkThroughputBonusNumerator); - mVal.throughputBonusDenominator = context.getResources().getInteger( - R.integer.config_wifiFrameworkThroughputBonusDenominator); - mVal.throughputBonusLimit = context.getResources().getInteger( - R.integer.config_wifiFrameworkThroughputBonusLimit); - mVal.savedNetworkBonus = context.getResources().getInteger( - R.integer.config_wifiFrameworkSavedNetworkBonus); - mVal.unmeteredNetworkBonus = context.getResources().getInteger( - R.integer.config_wifiFrameworkUnmeteredNetworkBonus); - mVal.currentNetworkBonusMin = context.getResources().getInteger( - R.integer.config_wifiFrameworkCurrentNetworkBonusMin); - mVal.currentNetworkBonusPercent = context.getResources().getInteger( - R.integer.config_wifiFrameworkCurrentNetworkBonusPercent); - mVal.secureNetworkBonus = context.getResources().getInteger( - R.integer.config_wifiFrameworkSecureNetworkBonus); - mVal.lastSelectionMinutes = context.getResources().getInteger( - R.integer.config_wifiFrameworkLastSelectionMinutes); - mVal.pps[ACTIVE_TRAFFIC] = context.getResources().getInteger( - R.integer.config_wifiFrameworkMinPacketPerSecondActiveTraffic); - mVal.pps[HIGH_TRAFFIC] = context.getResources().getInteger( - R.integer.config_wifiFrameworkMinPacketPerSecondHighTraffic); - try { - mVal.validate(); - } catch (IllegalArgumentException e) { - Log.wtf(TAG, "Inconsistent config_wifi_framework_ resources: " + this, e); - } - } - - private static final String COMMA_KEY_VAL_STAR = "^(,[A-Za-z_][A-Za-z0-9_]*=[0-9.:+-]+)*$"; - - /** - * Updates the parameters from the given parameter string. - * If any errors are detected, no change is made. - * @param kvList is a comma-separated key=value list. - * @return true for success - */ - @VisibleForTesting - public boolean update(String kvList) { - if (kvList == null || "".equals(kvList)) { - return true; - } - if (!("," + kvList).matches(COMMA_KEY_VAL_STAR)) { - return false; - } - loadResources(mContext); - Values v = new Values(mVal); - try { - v.parseString(kvList); - v.validate(); - mVal = v; - return true; - } catch (IllegalArgumentException e) { - return false; - } - } - - /** - * Sanitize a string to make it safe for printing. - * @param params is the untrusted string - * @return string with questionable characters replaced with question marks - */ - public String sanitize(String params) { - if (params == null) return ""; - String printable = params.replaceAll("[^A-Za-z_0-9=,:.+-]", "?"); - if (printable.length() > 100) { - printable = printable.substring(0, 98) + "..."; - } - return printable; - } - - /** - * Returns the RSSI value at which the connection is deemed to be unusable, - * in the absence of other indications. - */ - public int getExitRssi(int frequencyMegaHertz) { - return getRssiArray(frequencyMegaHertz)[EXIT]; - } - - /** - * Returns the minimum scan RSSI for making a connection attempt. - */ - public int getEntryRssi(int frequencyMegaHertz) { - return getRssiArray(frequencyMegaHertz)[ENTRY]; - } - - /** - * Returns a connected RSSI value that indicates the connection is - * good enough that we needn't scan for alternatives. - */ - public int getSufficientRssi(int frequencyMegaHertz) { - return getRssiArray(frequencyMegaHertz)[SUFFICIENT]; - } - - /** - * Returns a connected RSSI value that indicates a good connection. - */ - public int getGoodRssi(int frequencyMegaHertz) { - return getRssiArray(frequencyMegaHertz)[GOOD]; - } - - /** - * Returns the number of seconds to use for rssi forecast. - */ - public int getHorizonSeconds() { - loadResources(mContext); - return mVal.horizon; - } - - /** - * Returns a packet rate that should be considered acceptable for staying on wifi, - * no matter how bad the RSSI gets (packets per second). - */ - public int getYippeeSkippyPacketsPerSecond() { - loadResources(mContext); - return mVal.pps[HIGH_TRAFFIC]; - } - - /** - * Returns a packet rate that should be considered acceptable to skip scan or network selection - */ - public int getActiveTrafficPacketsPerSecond() { - loadResources(mContext); - return mVal.pps[ACTIVE_TRAFFIC]; - } - - /** - * Returns a number between 0 and 10 inclusive that indicates - * how aggressive to be about asking for IP configuration checks - * (also known as Network Unreachabilty Detection, or NUD). - * - * 0 - no nud checks requested by scorer (framework still checks after roam) - * 1 - check when score becomes very low - * ... - * 10 - check when score first breaches threshold, and again as it gets worse - * - */ - public int getNudKnob() { - loadResources(mContext); - return mVal.nud; - } - - /** - */ - public int getThroughputBonusNumerator() { - return mVal.throughputBonusNumerator; - } - - /** - */ - public int getThroughputBonusDenominator() { - return mVal.throughputBonusDenominator; - } - - /* - * Returns the maximum bonus for the network selection candidate score - * for the contribution of the selected score. - */ - public int getThroughputBonusLimit() { - return mVal.throughputBonusLimit; - } - - /* - * Returns the bonus for the network selection candidate score - * for a saved network (i.e., not a suggestion). - */ - public int getSavedNetworkBonus() { - return mVal.savedNetworkBonus; - } - - /* - * Returns the bonus for the network selection candidate score - * for an unmetered network. - */ - public int getUnmeteredNetworkBonus() { - return mVal.unmeteredNetworkBonus; - } - - /* - * Returns the minimum bonus for the network selection candidate score - * for the currently connected network. - */ - public int getCurrentNetworkBonusMin() { - return mVal.currentNetworkBonusMin; - } - - /* - * Returns the percentage bonus for the network selection candidate score - * for the currently connected network. The percent value is applied to rssi score and - * throughput score; - */ - public int getCurrentNetworkBonusPercent() { - return mVal.currentNetworkBonusPercent; - } - - /* - * Returns the bonus for the network selection candidate score - * for a secure network. - */ - public int getSecureNetworkBonus() { - return mVal.secureNetworkBonus; - } - - /* - * Returns the duration in minutes for a recently selected network - * to be strongly favored. - */ - public int getLastSelectionMinutes() { - return mVal.lastSelectionMinutes; - } - - /** - * Returns the experiment identifier. - * - * This value may be used to tag a set of experimental settings. - */ - public int getExperimentIdentifier() { - loadResources(mContext); - return mVal.expid; - } - - private int[] getRssiArray(int frequency) { - loadResources(mContext); - if (ScanResult.is24GHz(frequency)) { - return mVal.rssi2; - } else if (ScanResult.is5GHz(frequency)) { - return mVal.rssi5; - } else if (ScanResult.is6GHz(frequency)) { - return mVal.rssi6; - } - // Invalid frequency use - Log.e(TAG, "Invalid frequency(" + frequency + "), using 5G as default rssi array"); - return mVal.rssi5; - } - - @Override - public String toString() { - loadResources(mContext); - return mVal.toString(); - } -} diff --git a/service/java/com/android/server/wifi/SelfRecovery.java b/service/java/com/android/server/wifi/SelfRecovery.java deleted file mode 100644 index b7eb72364..000000000 --- a/service/java/com/android/server/wifi/SelfRecovery.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.annotation.IntDef; -import android.content.Context; -import android.util.Log; - -import com.android.wifi.resources.R; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.concurrent.TimeUnit; - -/** - * This class is used to recover the wifi stack from a fatal failure. The recovery mechanism - * involves triggering a stack restart (essentially simulating an airplane mode toggle) using - * {@link ActiveModeWarden}. - * The current triggers for: - * 1. Last resort watchdog bite. - * 2. HAL/wificond crashes during normal operation. - * 3. TBD: supplicant crashes during normal operation. - */ -public class SelfRecovery { - private static final String TAG = "WifiSelfRecovery"; - - /** - * Reason codes for the various recovery triggers. - */ - public static final int REASON_LAST_RESORT_WATCHDOG = 0; - public static final int REASON_WIFINATIVE_FAILURE = 1; - public static final int REASON_STA_IFACE_DOWN = 2; - - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"REASON_"}, value = { - REASON_LAST_RESORT_WATCHDOG, - REASON_WIFINATIVE_FAILURE, - REASON_STA_IFACE_DOWN}) - public @interface RecoveryReason {} - - protected static final String[] REASON_STRINGS = { - "Last Resort Watchdog", // REASON_LAST_RESORT_WATCHDOG - "WifiNative Failure", // REASON_WIFINATIVE_FAILURE - "Sta Interface Down" // REASON_STA_IFACE_DOWN - }; - - private final Context mContext; - private final ActiveModeWarden mActiveModeWarden; - private final Clock mClock; - // Time since boot (in millis) that restart occurred - private final LinkedList<Long> mPastRestartTimes; - public SelfRecovery(Context context, ActiveModeWarden activeModeWarden, Clock clock) { - mContext = context; - mActiveModeWarden = activeModeWarden; - mClock = clock; - mPastRestartTimes = new LinkedList<>(); - } - - /** - * Trigger recovery. - * - * This method does the following: - * 1. Checks reason code used to trigger recovery - * 2. Checks for sta iface down triggers and disables wifi by sending {@link - * ActiveModeWarden#recoveryDisableWifi()} to {@link ActiveModeWarden} to disable wifi. - * 3. Throttles restart calls for underlying native failures - * 4. Sends {@link ActiveModeWarden#recoveryRestartWifi(int)} to {@link ActiveModeWarden} to - * initiate the stack restart. - * @param reason One of the above |REASON_*| codes. - */ - public void trigger(@RecoveryReason int reason) { - if (!(reason == REASON_LAST_RESORT_WATCHDOG || reason == REASON_WIFINATIVE_FAILURE - || reason == REASON_STA_IFACE_DOWN)) { - Log.e(TAG, "Invalid trigger reason. Ignoring..."); - return; - } - if (reason == REASON_STA_IFACE_DOWN) { - Log.e(TAG, "STA interface down, disable wifi"); - mActiveModeWarden.recoveryDisableWifi(); - return; - } - - Log.e(TAG, "Triggering recovery for reason: " + REASON_STRINGS[reason]); - if (reason == REASON_WIFINATIVE_FAILURE) { - int maxRecoveriesPerHour = mContext.getResources().getInteger( - R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour); - if (maxRecoveriesPerHour == 0) { - Log.e(TAG, "Recovery disabled. Disabling wifi"); - mActiveModeWarden.recoveryDisableWifi(); - return; - } - trimPastRestartTimes(); - if (mPastRestartTimes.size() >= maxRecoveriesPerHour) { - Log.e(TAG, "Already restarted wifi " + maxRecoveriesPerHour + " times in" - + " last 1 hour. Disabling wifi"); - mActiveModeWarden.recoveryDisableWifi(); - return; - } - mPastRestartTimes.add(mClock.getElapsedSinceBootMillis()); - } - mActiveModeWarden.recoveryRestartWifi(reason); - } - - /** - * Process the mPastRestartTimes list, removing elements outside the max restarts time window - */ - private void trimPastRestartTimes() { - Iterator<Long> iter = mPastRestartTimes.iterator(); - long now = mClock.getElapsedSinceBootMillis(); - while (iter.hasNext()) { - Long restartTimeMillis = iter.next(); - if (now - restartTimeMillis > TimeUnit.HOURS.toMillis(1)) { - iter.remove(); - } else { - break; - } - } - } -} diff --git a/service/java/com/android/server/wifi/SimRequiredNotifier.java b/service/java/com/android/server/wifi/SimRequiredNotifier.java deleted file mode 100644 index fed7bd8e2..000000000 --- a/service/java/com/android/server/wifi/SimRequiredNotifier.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import android.app.ActivityManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.drawable.Icon; -import android.net.wifi.WifiConfiguration; -import android.os.UserHandle; -import android.provider.Settings; -import android.util.Log; - -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.wifi.resources.R; - -import java.util.List; - -/** - * Helper class to generate SIM required notification - * - */ -public class SimRequiredNotifier { - - private static final String TAG = "SimRequiredNotifier"; - private final WifiContext mContext; - private final FrameworkFacade mFrameworkFacade; - private final NotificationManager mNotificationManager; - - public SimRequiredNotifier(WifiContext context, FrameworkFacade framework) { - mContext = context; - mFrameworkFacade = framework; - mNotificationManager = - mContext.getSystemService(NotificationManager.class); - } - - /** - * Show notification - */ - public void showSimRequiredNotification(WifiConfiguration config, String carrier) { - String name; - if (config.isPasspoint()) { - name = config.providerFriendlyName; - } else { - name = config.SSID; - } - showNotification(name, carrier); - } - - /** - * Dismiss notification - */ - public void dismissSimRequiredNotification() { - mNotificationManager.cancel(null, SystemMessage.NOTE_ID_WIFI_SIM_REQUIRED); - } - - private String getSettingsPackageName() { - Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); - List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentActivitiesAsUser( - intent, PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEFAULT_ONLY, - UserHandle.of(ActivityManager.getCurrentUser())); - if (resolveInfos == null || resolveInfos.isEmpty()) { - Log.e(TAG, "Failed to resolve wifi settings activity"); - return null; - } - // Pick the first one if there are more than 1 since the list is ordered from best to worst. - return resolveInfos.get(0).activityInfo.packageName; - } - - private void showNotification(String ssid, String carrier) { - String settingsPackage = getSettingsPackageName(); - if (settingsPackage == null) return; - Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .setPackage(settingsPackage); - - String title = mContext.getResources().getString( - R.string.wifi_sim_required_title); - String message = mContext.getResources().getString( - R.string.wifi_sim_required_message, - (ssid == null ? "" : ssid), - (carrier == null ? "" : carrier)); - Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext, - WifiService.NOTIFICATION_NETWORK_ALERTS) - .setAutoCancel(true) - .setShowWhen(false) - .setLocalOnly(true) - .setColor(mContext.getResources().getColor( - android.R.color.system_notification_accent_color, mContext.getTheme())) - .setContentTitle(title) - .setTicker(title) - .setContentText(message) - .setStyle(new Notification.BigTextStyle().bigText(message)) - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - R.drawable.stat_notify_wifi_in_range)) - .setContentIntent(mFrameworkFacade.getActivity( - mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); - mNotificationManager.notify(SystemMessage.NOTE_ID_WIFI_SIM_REQUIRED, - builder.build()); - } -} diff --git a/service/java/com/android/server/wifi/SoftApBackupRestore.java b/service/java/com/android/server/wifi/SoftApBackupRestore.java deleted file mode 100644 index 441321cd3..000000000 --- a/service/java/com/android/server/wifi/SoftApBackupRestore.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiMigration; -import android.util.BackupUtils; -import android.util.Log; - -import com.android.server.wifi.util.ApConfigUtil; -import com.android.server.wifi.util.SettingsMigrationDataHolder; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Class used to backup/restore data using the SettingsBackupAgent. - * There are 2 symmetric API's exposed here: - * 1. retrieveBackupDataFromSoftApConfiguration: Retrieve the configuration data to be backed up. - * 2. retrieveSoftApConfigurationFromBackupData: Restore the configuration using the provided data. - * The byte stream to be backed up is versioned to migrate the data easily across - * revisions. - */ -public class SoftApBackupRestore { - private static final String TAG = "SoftApBackupRestore"; - - /** - * Current backup data version. - */ - private static final int CURRENT_SAP_BACKUP_DATA_VERSION = 7; - - private static final int ETHER_ADDR_LEN = 6; // Byte array size of MacAddress - - private final Context mContext; - private final SettingsMigrationDataHolder mSettingsMigrationDataHolder; - - public SoftApBackupRestore(Context context, - SettingsMigrationDataHolder settingsMigrationDataHolder) { - mContext = context; - mSettingsMigrationDataHolder = settingsMigrationDataHolder; - } - - /** - * Retrieve a byte stream representing the data that needs to be backed up from the - * provided softap configuration. - * - * @param config saved soft ap config that needs to be backed up. - * @return Raw byte stream that needs to be backed up. - */ - public byte[] retrieveBackupDataFromSoftApConfiguration(SoftApConfiguration config) { - if (config == null) { - Log.e(TAG, "Invalid configuration received"); - return new byte[0]; - } - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - DataOutputStream out = new DataOutputStream(baos); - - out.writeInt(CURRENT_SAP_BACKUP_DATA_VERSION); - BackupUtils.writeString(out, config.getSsid()); - out.writeInt(config.getBand()); - out.writeInt(config.getChannel()); - BackupUtils.writeString(out, config.getPassphrase()); - out.writeInt(config.getSecurityType()); - out.writeBoolean(config.isHiddenSsid()); - out.writeInt(config.getMaxNumberOfClients()); - out.writeLong(config.getShutdownTimeoutMillis()); - out.writeBoolean(config.isClientControlByUserEnabled()); - writeMacAddressList(out, config.getBlockedClientList()); - writeMacAddressList(out, config.getAllowedClientList()); - out.writeBoolean(config.isAutoShutdownEnabled()); - } catch (IOException io) { - Log.e(TAG, "Invalid configuration received, IOException " + io); - return new byte[0]; - } - return baos.toByteArray(); - } - - /** - * Parse out the configurations from the back up data. - * - * @param data raw byte stream representing the data. - * @return Soft ap config retrieved from the backed up data. - */ - public SoftApConfiguration retrieveSoftApConfigurationFromBackupData(byte[] data) { - if (data == null || data.length == 0) { - Log.e(TAG, "Invalid backup data received"); - return null; - } - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - try { - DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); - int version = in.readInt(); - if (version < 1 || version > CURRENT_SAP_BACKUP_DATA_VERSION) { - throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); - } - - if (version == 1) return null; // Version 1 is a bad dataset. - - configBuilder.setSsid(BackupUtils.readString(in)); - - int band; - if (version < 4) { - band = ApConfigUtil.convertWifiConfigBandToSoftApConfigBand(in.readInt()); - } else { - band = in.readInt(); - } - int channel = in.readInt(); - - if (channel == 0) { - configBuilder.setBand(band); - } else { - configBuilder.setChannel(channel, band); - } - String passphrase = BackupUtils.readString(in); - int securityType = in.readInt(); - if (version < 4 && securityType == WifiConfiguration.KeyMgmt.WPA2_PSK) { - configBuilder.setPassphrase(passphrase, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - } else if (version >= 4 && securityType != SoftApConfiguration.SECURITY_TYPE_OPEN) { - configBuilder.setPassphrase(passphrase, securityType); - } - if (version >= 3) { - configBuilder.setHiddenSsid(in.readBoolean()); - } - if (version >= 5) { - configBuilder.setMaxNumberOfClients(in.readInt()); - if (version >= 7) { - configBuilder.setShutdownTimeoutMillis(in.readLong()); - } else { - configBuilder.setShutdownTimeoutMillis(Long.valueOf(in.readInt())); - } - configBuilder.setClientControlByUserEnabled(in.readBoolean()); - int numberOfBlockedClient = in.readInt(); - List<MacAddress> blockedList = new ArrayList<>( - macAddressListFromByteArray(in, numberOfBlockedClient)); - int numberOfAllowedClient = in.readInt(); - List<MacAddress> allowedList = new ArrayList<>( - macAddressListFromByteArray(in, numberOfAllowedClient)); - configBuilder.setBlockedClientList(blockedList); - configBuilder.setAllowedClientList(allowedList); - } - if (version >= 6) { - configBuilder.setAutoShutdownEnabled(in.readBoolean()); - } else { - // Migrate data out of settings. - WifiMigration.SettingsMigrationData migrationData = - mSettingsMigrationDataHolder.retrieveData(); - if (migrationData == null) { - Log.e(TAG, "No migration data present"); - } else { - configBuilder.setAutoShutdownEnabled(migrationData.isSoftApTimeoutEnabled()); - } - } - } catch (IOException io) { - Log.e(TAG, "Invalid backup data received, IOException: " + io); - return null; - } catch (BackupUtils.BadVersionException badVersion) { - Log.e(TAG, "Invalid backup data received, BadVersionException: " + badVersion); - return null; - } catch (IllegalArgumentException ie) { - Log.e(TAG, "Invalid backup data received, IllegalArgumentException " + ie); - return null; - } - return configBuilder.build(); - } - - private void writeMacAddressList(DataOutputStream out, List<MacAddress> macList) - throws IOException { - out.writeInt(macList.size()); - Iterator<MacAddress> iterator = macList.iterator(); - while (iterator.hasNext()) { - byte[] mac = iterator.next().toByteArray(); - out.write(mac, 0, ETHER_ADDR_LEN); - } - } - - private List<MacAddress> macAddressListFromByteArray(DataInputStream in, int numberOfClients) - throws IOException { - List<MacAddress> macList = new ArrayList<>(); - for (int i = 0; i < numberOfClients; i++) { - byte[] mac = new byte[ETHER_ADDR_LEN]; - in.read(mac, 0, ETHER_ADDR_LEN); - macList.add(MacAddress.fromBytes(mac)); - } - return macList; - } -} diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java deleted file mode 100644 index b321a78a1..000000000 --- a/service/java/com/android/server/wifi/SoftApManager.java +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiManager.SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED; - -import static com.android.server.wifi.util.ApConfigUtil.ERROR_GENERIC; -import static com.android.server.wifi.util.ApConfigUtil.ERROR_NO_CHANNEL; -import static com.android.server.wifi.util.ApConfigUtil.ERROR_UNSUPPORTED_CONFIGURATION; -import static com.android.server.wifi.util.ApConfigUtil.SUCCESS; - -import android.annotation.NonNull; -import android.content.Intent; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApInfo; -import android.net.wifi.WifiAnnotations; -import android.net.wifi.WifiClient; -import android.net.wifi.WifiManager; -import android.net.wifi.nl80211.NativeWifiClient; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.SystemClock; -import android.os.UserHandle; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IState; -import com.android.internal.util.Preconditions; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import com.android.internal.util.WakeupMessage; -import com.android.server.wifi.WifiNative.InterfaceCallback; -import com.android.server.wifi.WifiNative.SoftApListener; -import com.android.server.wifi.util.ApConfigUtil; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Set; - -/** - * Manage WiFi in AP mode. - * The internal state machine runs under the ClientModeImpl handler thread context. - */ -public class SoftApManager implements ActiveModeManager { - private static final String TAG = "SoftApManager"; - - @VisibleForTesting - public static final String SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG = TAG - + " Soft AP Send Message Timeout"; - - private final WifiContext mContext; - private final FrameworkFacade mFrameworkFacade; - private final WifiNative mWifiNative; - - @VisibleForTesting - SoftApNotifier mSoftApNotifier; - - private final String mCountryCode; - - private final SoftApStateMachine mStateMachine; - - private final Listener mModeListener; - private final WifiManager.SoftApCallback mSoftApCallback; - - private String mApInterfaceName; - private boolean mIfaceIsUp; - private boolean mIfaceIsDestroyed; - - private final WifiApConfigStore mWifiApConfigStore; - - private final WifiMetrics mWifiMetrics; - - private boolean mIsRandomizeBssid; - - @NonNull - private SoftApModeConfiguration mApConfig; - - @NonNull - private SoftApInfo mCurrentSoftApInfo = new SoftApInfo(); - - @NonNull - private SoftApCapability mCurrentSoftApCapability; - - private List<WifiClient> mConnectedClients = new ArrayList<>(); - private boolean mTimeoutEnabled = false; - - private final SarManager mSarManager; - - private String mStartTimestamp; - - private long mDefaultShutDownTimeoutMills; - - private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); - - private BaseWifiDiagnostics mWifiDiagnostics; - - private @Role int mRole = ROLE_UNSPECIFIED; - private @Role int mTargetRole = ROLE_UNSPECIFIED; - - private boolean mEverReportMetricsForMaxClient = false; - - @NonNull - private Set<MacAddress> mBlockedClientList = new HashSet<>(); - - @NonNull - private Set<MacAddress> mAllowedClientList = new HashSet<>(); - - /** - * Listener for soft AP events. - */ - private final SoftApListener mSoftApListener = new SoftApListener() { - - @Override - public void onFailure() { - mStateMachine.sendMessage(SoftApStateMachine.CMD_FAILURE); - } - - @Override - public void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) { - if (client != null) { - mStateMachine.sendMessage(SoftApStateMachine.CMD_ASSOCIATED_STATIONS_CHANGED, - isConnected ? 1 : 0, 0, client); - } else { - Log.e(TAG, "onConnectedClientsChanged: Invalid type returned"); - } - } - - @Override - public void onSoftApChannelSwitched(int frequency, - @WifiAnnotations.Bandwidth int bandwidth) { - mStateMachine.sendMessage( - SoftApStateMachine.CMD_SOFT_AP_CHANNEL_SWITCHED, frequency, bandwidth); - } - }; - - public SoftApManager(@NonNull WifiContext context, - @NonNull Looper looper, - @NonNull FrameworkFacade framework, - @NonNull WifiNative wifiNative, - String countryCode, - @NonNull Listener listener, - @NonNull WifiManager.SoftApCallback callback, - @NonNull WifiApConfigStore wifiApConfigStore, - @NonNull SoftApModeConfiguration apConfig, - @NonNull WifiMetrics wifiMetrics, - @NonNull SarManager sarManager, - @NonNull BaseWifiDiagnostics wifiDiagnostics) { - mContext = context; - mFrameworkFacade = framework; - mSoftApNotifier = new SoftApNotifier(mContext, mFrameworkFacade); - mWifiNative = wifiNative; - mCountryCode = countryCode; - mModeListener = listener; - mSoftApCallback = callback; - mWifiApConfigStore = wifiApConfigStore; - SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration(); - mCurrentSoftApCapability = apConfig.getCapability(); - // null is a valid input and means we use the user-configured tethering settings. - if (softApConfig == null) { - softApConfig = mWifiApConfigStore.getApConfiguration(); - // may still be null if we fail to load the default config - } - if (softApConfig != null) { - mIsRandomizeBssid = softApConfig.getBssid() == null; - softApConfig = mWifiApConfigStore.randomizeBssidIfUnset(mContext, softApConfig); - } - mApConfig = new SoftApModeConfiguration(apConfig.getTargetMode(), - softApConfig, mCurrentSoftApCapability); - mWifiMetrics = wifiMetrics; - mSarManager = sarManager; - mWifiDiagnostics = wifiDiagnostics; - mStateMachine = new SoftApStateMachine(looper); - if (softApConfig != null) { - mBlockedClientList = new HashSet<>(softApConfig.getBlockedClientList()); - mAllowedClientList = new HashSet<>(softApConfig.getAllowedClientList()); - mTimeoutEnabled = softApConfig.isAutoShutdownEnabled(); - } - mDefaultShutDownTimeoutMills = mContext.getResources().getInteger( - R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - } - - /** - * Start soft AP, as configured in the constructor. - */ - @Override - public void start() { - mStateMachine.sendMessage(SoftApStateMachine.CMD_START); - } - - /** - * Stop soft AP. - */ - @Override - public void stop() { - Log.d(TAG, " currentstate: " + getCurrentStateName()); - mTargetRole = ROLE_UNSPECIFIED; - mStateMachine.sendMessage(SoftApStateMachine.CMD_STOP); - } - - @Override - public boolean isStopping() { - return mTargetRole == ROLE_UNSPECIFIED && mRole != ROLE_UNSPECIFIED; - } - - @Override - public @Role int getRole() { - return mRole; - } - - @Override - public void setRole(@Role int role) { - // softap does not allow in-place switching of roles. - Preconditions.checkState(mRole == ROLE_UNSPECIFIED); - Preconditions.checkState(SOFTAP_ROLES.contains(role)); - mTargetRole = role; - mRole = role; - } - - /** - * Update AP capability. Called when carrier config or device resouce config changed. - * - * @param capability new AP capability. - */ - public void updateCapability(@NonNull SoftApCapability capability) { - mStateMachine.sendMessage(SoftApStateMachine.CMD_UPDATE_CAPABILITY, capability); - } - - /** - * Update AP configuration. Called when setting update config via - * {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)} - * - * @param config new AP config. - */ - public void updateConfiguration(@NonNull SoftApConfiguration config) { - mStateMachine.sendMessage(SoftApStateMachine.CMD_UPDATE_CONFIG, config); - } - - /** - * Dump info about this softap manager. - */ - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("--Dump of SoftApManager--"); - - pw.println("current StateMachine mode: " + getCurrentStateName()); - pw.println("mRole: " + mRole); - pw.println("mApInterfaceName: " + mApInterfaceName); - pw.println("mIfaceIsUp: " + mIfaceIsUp); - pw.println("mSoftApCountryCode: " + mCountryCode); - pw.println("mApConfig.targetMode: " + mApConfig.getTargetMode()); - SoftApConfiguration softApConfig = mApConfig.getSoftApConfiguration(); - pw.println("mApConfig.SoftApConfiguration.SSID: " + softApConfig.getSsid()); - pw.println("mApConfig.SoftApConfiguration.mBand: " + softApConfig.getBand()); - pw.println("mApConfig.SoftApConfiguration.hiddenSSID: " + softApConfig.isHiddenSsid()); - pw.println("mConnectedClients.size(): " + mConnectedClients.size()); - pw.println("mTimeoutEnabled: " + mTimeoutEnabled); - pw.println("mCurrentSoftApInfo " + mCurrentSoftApInfo); - pw.println("mStartTimestamp: " + mStartTimestamp); - mStateMachine.dump(fd, pw, args); - } - - private String getCurrentStateName() { - IState currentState = mStateMachine.getCurrentState(); - - if (currentState != null) { - return currentState.getName(); - } - - return "StateMachine not active"; - } - - /** - * Update AP state. - * - * @param newState new AP state - * @param currentState current AP state - * @param reason Failure reason if the new AP state is in failure state - */ - private void updateApState(int newState, int currentState, int reason) { - mSoftApCallback.onStateChanged(newState, reason); - - //send the AP state change broadcast - final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, newState); - intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, currentState); - if (newState == WifiManager.WIFI_AP_STATE_FAILED) { - //only set reason number when softAP start failed - intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason); - } - - intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, mApInterfaceName); - intent.putExtra(WifiManager.EXTRA_WIFI_AP_MODE, mApConfig.getTargetMode()); - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private int setMacAddress() { - MacAddress mac = mApConfig.getSoftApConfiguration().getBssid(); - - if (mac == null) { - // If no BSSID is explicitly requested, (re-)configure the factory MAC address. Some - // drivers may not support setting the MAC at all, so fail soft in this case. - mac = mWifiNative.getFactoryMacAddress(mApInterfaceName); - if (mac == null) { - Log.e(TAG, "failed to get factory MAC address"); - return ERROR_GENERIC; - } - - if (!mWifiNative.setMacAddress(mApInterfaceName, mac)) { - Log.w(TAG, "failed to reset to factory MAC address; continuing with current MAC"); - } - return SUCCESS; - } - - - if (mWifiNative.isSetMacAddressSupported(mApInterfaceName)) { - if (!mWifiNative.setMacAddress(mApInterfaceName, mac)) { - Log.e(TAG, "failed to set explicitly requested MAC address"); - return ERROR_GENERIC; - } - } else if (!mIsRandomizeBssid) { - // If hardware does not support MAC address setter, - // only report the error for non randomization. - return ERROR_UNSUPPORTED_CONFIGURATION; - } - return SUCCESS; - } - - private int setCountryCode() { - int band = mApConfig.getSoftApConfiguration().getBand(); - if (TextUtils.isEmpty(mCountryCode)) { - if (band == SoftApConfiguration.BAND_5GHZ) { - // Country code is mandatory for 5GHz band. - Log.e(TAG, "Invalid country code, required for setting up soft ap in 5GHz"); - return ERROR_GENERIC; - } - // Absence of country code is not fatal for 2Ghz & Any band options. - return SUCCESS; - } - - if (!mWifiNative.setCountryCodeHal( - mApInterfaceName, mCountryCode.toUpperCase(Locale.ROOT))) { - if (band == SoftApConfiguration.BAND_5GHZ) { - // Return an error if failed to set country code when AP is configured for - // 5GHz band. - Log.e(TAG, "Failed to set country code, required for setting up soft ap in 5GHz"); - return ERROR_GENERIC; - } - // Failure to set country code is not fatal for other band options. - } - return SUCCESS; - } - - /** - * Start a soft AP instance as configured. - * - * @return integer result code - */ - private int startSoftAp() { - SoftApConfiguration config = mApConfig.getSoftApConfiguration(); - if (config == null || config.getSsid() == null) { - Log.e(TAG, "Unable to start soft AP without valid configuration"); - return ERROR_GENERIC; - } - - Log.d(TAG, "band " + config.getBand() + " iface " - + mApInterfaceName + " country " + mCountryCode); - - int result = setMacAddress(); - if (result != SUCCESS) { - return result; - } - - result = setCountryCode(); - if (result != SUCCESS) { - return result; - } - - // Make a copy of configuration for updating AP band and channel. - SoftApConfiguration.Builder localConfigBuilder = new SoftApConfiguration.Builder(config); - - boolean acsEnabled = mCurrentSoftApCapability.areFeaturesSupported( - SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD); - - result = ApConfigUtil.updateApChannelConfig( - mWifiNative, mContext.getResources(), mCountryCode, localConfigBuilder, config, - acsEnabled); - if (result != SUCCESS) { - Log.e(TAG, "Failed to update AP band and channel"); - return result; - } - - if (config.isHiddenSsid()) { - Log.d(TAG, "SoftAP is a hidden network"); - } - - if (!ApConfigUtil.checkSupportAllConfiguration(config, mCurrentSoftApCapability)) { - Log.d(TAG, "Unsupported Configuration detect! config = " + config); - return ERROR_UNSUPPORTED_CONFIGURATION; - } - - if (!mWifiNative.startSoftAp(mApInterfaceName, - localConfigBuilder.build(), mSoftApListener)) { - Log.e(TAG, "Soft AP start failed"); - return ERROR_GENERIC; - } - - mWifiDiagnostics.startLogging(mApInterfaceName); - mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis())); - Log.d(TAG, "Soft AP is started "); - - return SUCCESS; - } - - /** - * Disconnect all connected clients on active softap interface(s). - * This is usually done just before stopSoftAp(). - */ - private void disconnectAllClients() { - for (WifiClient client : mConnectedClients) { - mWifiNative.forceClientDisconnect(mApInterfaceName, client.getMacAddress(), - SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED); - } - } - - /** - * Teardown soft AP and teardown the interface. - */ - private void stopSoftAp() { - disconnectAllClients(); - mWifiDiagnostics.stopLogging(mApInterfaceName); - mWifiNative.teardownInterface(mApInterfaceName); - Log.d(TAG, "Soft AP is stopped"); - } - - private boolean checkSoftApClient(SoftApConfiguration config, WifiClient newClient) { - if (!mCurrentSoftApCapability.areFeaturesSupported( - SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) { - return true; - } - - if (mBlockedClientList.contains(newClient.getMacAddress())) { - Log.d(TAG, "Force disconnect for client: " + newClient + "in blocked list"); - mWifiNative.forceClientDisconnect( - mApInterfaceName, newClient.getMacAddress(), - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - return false; - } - if (config.isClientControlByUserEnabled() - && !mAllowedClientList.contains(newClient.getMacAddress())) { - mSoftApCallback.onBlockedClientConnecting(newClient, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - Log.d(TAG, "Force disconnect for unauthorized client: " + newClient); - mWifiNative.forceClientDisconnect( - mApInterfaceName, newClient.getMacAddress(), - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - return false; - } - int maxConfig = mCurrentSoftApCapability.getMaxSupportedClients(); - if (config.getMaxNumberOfClients() > 0) { - maxConfig = Math.min(maxConfig, config.getMaxNumberOfClients()); - } - - if (mConnectedClients.size() >= maxConfig) { - Log.i(TAG, "No more room for new client:" + newClient); - mWifiNative.forceClientDisconnect( - mApInterfaceName, newClient.getMacAddress(), - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS); - mSoftApCallback.onBlockedClientConnecting(newClient, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS); - // Avoid report the max client blocked in the same settings. - if (!mEverReportMetricsForMaxClient) { - mWifiMetrics.noteSoftApClientBlocked(maxConfig); - mEverReportMetricsForMaxClient = true; - } - return false; - } - return true; - } - - private class SoftApStateMachine extends StateMachine { - // Commands for the state machine. - public static final int CMD_START = 0; - public static final int CMD_STOP = 1; - public static final int CMD_FAILURE = 2; - public static final int CMD_INTERFACE_STATUS_CHANGED = 3; - public static final int CMD_ASSOCIATED_STATIONS_CHANGED = 4; - public static final int CMD_NO_ASSOCIATED_STATIONS_TIMEOUT = 5; - public static final int CMD_INTERFACE_DESTROYED = 7; - public static final int CMD_INTERFACE_DOWN = 8; - public static final int CMD_SOFT_AP_CHANNEL_SWITCHED = 9; - public static final int CMD_UPDATE_CAPABILITY = 10; - public static final int CMD_UPDATE_CONFIG = 11; - - private final State mIdleState = new IdleState(); - private final State mStartedState = new StartedState(); - - private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { - @Override - public void onDestroyed(String ifaceName) { - if (mApInterfaceName != null && mApInterfaceName.equals(ifaceName)) { - sendMessage(CMD_INTERFACE_DESTROYED); - } - } - - @Override - public void onUp(String ifaceName) { - if (mApInterfaceName != null && mApInterfaceName.equals(ifaceName)) { - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1); - } - } - - @Override - public void onDown(String ifaceName) { - if (mApInterfaceName != null && mApInterfaceName.equals(ifaceName)) { - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); - } - } - }; - - SoftApStateMachine(Looper looper) { - super(TAG, looper); - - addState(mIdleState); - addState(mStartedState); - - setInitialState(mIdleState); - start(); - } - - private class IdleState extends State { - @Override - public void enter() { - mApInterfaceName = null; - mIfaceIsUp = false; - mIfaceIsDestroyed = false; - } - - @Override - public boolean processMessage(Message message) { - switch (message.what) { - case CMD_STOP: - mStateMachine.quitNow(); - break; - case CMD_START: - mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode( - mWifiNativeInterfaceCallback); - if (TextUtils.isEmpty(mApInterfaceName)) { - Log.e(TAG, "setup failure when creating ap interface."); - updateApState(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.WIFI_AP_STATE_DISABLED, - WifiManager.SAP_START_FAILURE_GENERAL); - mWifiMetrics.incrementSoftApStartResult( - false, WifiManager.SAP_START_FAILURE_GENERAL); - mModeListener.onStartFailure(); - break; - } - mSoftApNotifier.dismissSoftApShutDownTimeoutExpiredNotification(); - updateApState(WifiManager.WIFI_AP_STATE_ENABLING, - WifiManager.WIFI_AP_STATE_DISABLED, 0); - int result = startSoftAp(); - if (result != SUCCESS) { - int failureReason = WifiManager.SAP_START_FAILURE_GENERAL; - if (result == ERROR_NO_CHANNEL) { - failureReason = WifiManager.SAP_START_FAILURE_NO_CHANNEL; - } else if (result == ERROR_UNSUPPORTED_CONFIGURATION) { - failureReason = WifiManager - .SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION; - } - updateApState(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.WIFI_AP_STATE_ENABLING, - failureReason); - stopSoftAp(); - mWifiMetrics.incrementSoftApStartResult(false, failureReason); - mModeListener.onStartFailure(); - break; - } - transitionTo(mStartedState); - break; - case CMD_UPDATE_CAPABILITY: - // Capability should only changed by carrier requirement. Only apply to - // Tether Mode - if (mApConfig.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED) { - SoftApCapability capability = (SoftApCapability) message.obj; - mCurrentSoftApCapability = new SoftApCapability(capability); - } - break; - case CMD_UPDATE_CONFIG: - SoftApConfiguration newConfig = (SoftApConfiguration) message.obj; - Log.d(TAG, "Configuration changed to " + newConfig); - mApConfig = new SoftApModeConfiguration(mApConfig.getTargetMode(), - newConfig, mCurrentSoftApCapability); - mBlockedClientList = new HashSet<>(newConfig.getBlockedClientList()); - mAllowedClientList = new HashSet<>(newConfig.getAllowedClientList()); - mTimeoutEnabled = newConfig.isAutoShutdownEnabled(); - break; - default: - // Ignore all other commands. - break; - } - - return HANDLED; - } - } - - private class StartedState extends State { - private WakeupMessage mSoftApTimeoutMessage; - - private void scheduleTimeoutMessage() { - if (!mTimeoutEnabled || mConnectedClients.size() != 0) { - cancelTimeoutMessage(); - return; - } - long timeout = mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis(); - if (timeout == 0) { - timeout = mDefaultShutDownTimeoutMills; - } - mSoftApTimeoutMessage.schedule(SystemClock.elapsedRealtime() - + timeout); - Log.d(TAG, "Timeout message scheduled, delay = " - + timeout); - } - - private void cancelTimeoutMessage() { - mSoftApTimeoutMessage.cancel(); - Log.d(TAG, "Timeout message canceled"); - } - - /** - * When configuration changed, it need to force some clients disconnect to match the - * configuration. - */ - private void updateClientConnection() { - if (!mCurrentSoftApCapability.areFeaturesSupported( - SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) { - return; - } - final int maxAllowedClientsByHardwareAndCarrier = - mCurrentSoftApCapability.getMaxSupportedClients(); - final int userApConfigMaxClientCount = - mApConfig.getSoftApConfiguration().getMaxNumberOfClients(); - int finalMaxClientCount = maxAllowedClientsByHardwareAndCarrier; - if (userApConfigMaxClientCount > 0) { - finalMaxClientCount = Math.min(userApConfigMaxClientCount, - maxAllowedClientsByHardwareAndCarrier); - } - int targetDisconnectClientNumber = mConnectedClients.size() - finalMaxClientCount; - List<WifiClient> allowedConnectedList = new ArrayList<>(); - Iterator<WifiClient> iterator = mConnectedClients.iterator(); - while (iterator.hasNext()) { - WifiClient client = iterator.next(); - if (mBlockedClientList.contains(client.getMacAddress()) - || (mApConfig.getSoftApConfiguration().isClientControlByUserEnabled() - && !mAllowedClientList.contains(client.getMacAddress()))) { - Log.d(TAG, "Force disconnect for not allowed client: " + client); - mWifiNative.forceClientDisconnect( - mApInterfaceName, client.getMacAddress(), - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - targetDisconnectClientNumber--; - } else { - allowedConnectedList.add(client); - } - } - - if (targetDisconnectClientNumber > 0) { - Iterator<WifiClient> allowedClientIterator = allowedConnectedList.iterator(); - while (allowedClientIterator.hasNext()) { - if (targetDisconnectClientNumber == 0) break; - WifiClient allowedClient = allowedClientIterator.next(); - Log.d(TAG, "Force disconnect for client due to no more room: " - + allowedClient); - mWifiNative.forceClientDisconnect( - mApInterfaceName, allowedClient.getMacAddress(), - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS); - targetDisconnectClientNumber--; - } - } - } - - /** - * Set stations associated with this soft AP - * @param client The station for which connection state changed. - * @param isConnected True for the connection changed to connect, otherwise false. - */ - private void updateConnectedClients(WifiClient client, boolean isConnected) { - if (client == null) { - return; - } - - int index = mConnectedClients.indexOf(client); - if ((index != -1) == isConnected) { - Log.e(TAG, "Drop client connection event, client " - + client + "isConnected: " + isConnected - + " , duplicate event or client is blocked"); - return; - } - if (isConnected) { - boolean isAllow = checkSoftApClient( - mApConfig.getSoftApConfiguration(), client); - if (isAllow) { - mConnectedClients.add(client); - } else { - return; - } - } else { - mConnectedClients.remove(index); - } - - Log.d(TAG, "The connected wifi stations have changed with count: " - + mConnectedClients.size() + ": " + mConnectedClients); - - if (mSoftApCallback != null) { - mSoftApCallback.onConnectedClientsChanged(mConnectedClients); - } else { - Log.e(TAG, - "SoftApCallback is null. Dropping ConnectedClientsChanged event." - ); - } - - mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent( - mConnectedClients.size(), mApConfig.getTargetMode()); - - scheduleTimeoutMessage(); - } - - private void setSoftApChannel(int freq, @WifiAnnotations.Bandwidth int apBandwidth) { - Log.d(TAG, "Channel switched. Frequency: " + freq - + " Bandwidth: " + apBandwidth); - - if (freq == mCurrentSoftApInfo.getFrequency() - && apBandwidth == mCurrentSoftApInfo.getBandwidth()) { - return; // no change - } - - mCurrentSoftApInfo.setFrequency(freq); - mCurrentSoftApInfo.setBandwidth(apBandwidth); - mSoftApCallback.onInfoChanged(mCurrentSoftApInfo); - - // ignore invalid freq and softap disable case for metrics - if (freq > 0 && apBandwidth != SoftApInfo.CHANNEL_WIDTH_INVALID) { - mWifiMetrics.addSoftApChannelSwitchedEvent(mCurrentSoftApInfo.getFrequency(), - mCurrentSoftApInfo.getBandwidth(), mApConfig.getTargetMode()); - updateUserBandPreferenceViolationMetricsIfNeeded(); - } - } - - private void onUpChanged(boolean isUp) { - if (isUp == mIfaceIsUp) { - return; // no change - } - - mIfaceIsUp = isUp; - if (isUp) { - Log.d(TAG, "SoftAp is ready for use"); - updateApState(WifiManager.WIFI_AP_STATE_ENABLED, - WifiManager.WIFI_AP_STATE_ENABLING, 0); - mModeListener.onStarted(); - mWifiMetrics.incrementSoftApStartResult(true, 0); - if (mSoftApCallback != null) { - mSoftApCallback.onConnectedClientsChanged(mConnectedClients); - } - } else { - // the interface was up, but goes down - sendMessage(CMD_INTERFACE_DOWN); - } - mWifiMetrics.addSoftApUpChangedEvent(isUp, mApConfig.getTargetMode(), - mDefaultShutDownTimeoutMills); - if (isUp) { - mWifiMetrics.updateSoftApConfiguration(mApConfig.getSoftApConfiguration(), - mApConfig.getTargetMode()); - mWifiMetrics.updateSoftApCapability(mCurrentSoftApCapability, - mApConfig.getTargetMode()); - } - } - - @Override - public void enter() { - mIfaceIsUp = false; - mIfaceIsDestroyed = false; - onUpChanged(mWifiNative.isInterfaceUp(mApInterfaceName)); - - Handler handler = mStateMachine.getHandler(); - mSoftApTimeoutMessage = new WakeupMessage(mContext, handler, - SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG, - SoftApStateMachine.CMD_NO_ASSOCIATED_STATIONS_TIMEOUT); - - mSarManager.setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED); - - Log.d(TAG, "Resetting connected clients on start"); - mConnectedClients.clear(); - mEverReportMetricsForMaxClient = false; - scheduleTimeoutMessage(); - } - - @Override - public void exit() { - if (!mIfaceIsDestroyed) { - stopSoftAp(); - } - - Log.d(TAG, "Resetting num stations on stop"); - if (mConnectedClients.size() != 0) { - mConnectedClients.clear(); - if (mSoftApCallback != null) { - mSoftApCallback.onConnectedClientsChanged(mConnectedClients); - } - mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent( - 0, mApConfig.getTargetMode()); - } - cancelTimeoutMessage(); - - // Need this here since we are exiting |Started| state and won't handle any - // future CMD_INTERFACE_STATUS_CHANGED events after this point - mWifiMetrics.addSoftApUpChangedEvent(false, mApConfig.getTargetMode(), - mDefaultShutDownTimeoutMills); - updateApState(WifiManager.WIFI_AP_STATE_DISABLED, - WifiManager.WIFI_AP_STATE_DISABLING, 0); - - mSarManager.setSapWifiState(WifiManager.WIFI_AP_STATE_DISABLED); - mApInterfaceName = null; - mIfaceIsUp = false; - mIfaceIsDestroyed = false; - mRole = ROLE_UNSPECIFIED; - mStateMachine.quitNow(); - mModeListener.onStopped(); - setSoftApChannel(0, SoftApInfo.CHANNEL_WIDTH_INVALID); - } - - private void updateUserBandPreferenceViolationMetricsIfNeeded() { - int band = mApConfig.getSoftApConfiguration().getBand(); - boolean bandPreferenceViolated = - (ScanResult.is24GHz(mCurrentSoftApInfo.getFrequency()) - && !ApConfigUtil.containsBand(band, - SoftApConfiguration.BAND_2GHZ)) - || (ScanResult.is5GHz(mCurrentSoftApInfo.getFrequency()) - && !ApConfigUtil.containsBand(band, - SoftApConfiguration.BAND_5GHZ)) - || (ScanResult.is6GHz(mCurrentSoftApInfo.getFrequency()) - && !ApConfigUtil.containsBand(band, - SoftApConfiguration.BAND_6GHZ)); - - if (bandPreferenceViolated) { - Log.e(TAG, "Channel does not satisfy user band preference: " - + mCurrentSoftApInfo.getFrequency()); - mWifiMetrics.incrementNumSoftApUserBandPreferenceUnsatisfied(); - } - } - - @Override - public boolean processMessage(Message message) { - switch (message.what) { - case CMD_ASSOCIATED_STATIONS_CHANGED: - if (!(message.obj instanceof NativeWifiClient)) { - Log.e(TAG, "Invalid type returned for" - + " CMD_ASSOCIATED_STATIONS_CHANGED"); - break; - } - NativeWifiClient nativeClient = (NativeWifiClient) message.obj; - boolean isConnected = (message.arg1 == 1); - if (nativeClient != null && nativeClient.getMacAddress() != null) { - WifiClient client = new WifiClient(nativeClient.getMacAddress()); - Log.d(TAG, "CMD_ASSOCIATED_STATIONS_CHANGED, Client: " - + nativeClient.getMacAddress().toString() + " isConnected: " - + isConnected); - updateConnectedClients(client, isConnected); - } - break; - case CMD_SOFT_AP_CHANNEL_SWITCHED: - if (message.arg1 < 0) { - Log.e(TAG, "Invalid ap channel frequency: " + message.arg1); - break; - } - setSoftApChannel(message.arg1, message.arg2); - break; - case CMD_INTERFACE_STATUS_CHANGED: - boolean isUp = message.arg1 == 1; - onUpChanged(isUp); - break; - case CMD_STOP: - if (mIfaceIsUp) { - updateApState(WifiManager.WIFI_AP_STATE_DISABLING, - WifiManager.WIFI_AP_STATE_ENABLED, 0); - } else { - updateApState(WifiManager.WIFI_AP_STATE_DISABLING, - WifiManager.WIFI_AP_STATE_ENABLING, 0); - } - transitionTo(mIdleState); - break; - case CMD_START: - // Already started, ignore this command. - break; - case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT: - if (!mTimeoutEnabled) { - Log.wtf(TAG, "Timeout message received while timeout is disabled." - + " Dropping."); - break; - } - if (mConnectedClients.size() != 0) { - Log.wtf(TAG, "Timeout message received but has clients. Dropping."); - break; - } - mSoftApNotifier.showSoftApShutDownTimeoutExpiredNotification(); - Log.i(TAG, "Timeout message received. Stopping soft AP."); - updateApState(WifiManager.WIFI_AP_STATE_DISABLING, - WifiManager.WIFI_AP_STATE_ENABLED, 0); - transitionTo(mIdleState); - break; - case CMD_INTERFACE_DESTROYED: - Log.d(TAG, "Interface was cleanly destroyed."); - updateApState(WifiManager.WIFI_AP_STATE_DISABLING, - WifiManager.WIFI_AP_STATE_ENABLED, 0); - mIfaceIsDestroyed = true; - transitionTo(mIdleState); - break; - case CMD_FAILURE: - Log.w(TAG, "hostapd failure, stop and report failure"); - /* fall through */ - case CMD_INTERFACE_DOWN: - Log.w(TAG, "interface error, stop and report failure"); - updateApState(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.WIFI_AP_STATE_ENABLED, - WifiManager.SAP_START_FAILURE_GENERAL); - updateApState(WifiManager.WIFI_AP_STATE_DISABLING, - WifiManager.WIFI_AP_STATE_FAILED, 0); - transitionTo(mIdleState); - break; - case CMD_UPDATE_CAPABILITY: - // Capability should only changed by carrier requirement. Only apply to - // Tether Mode - if (mApConfig.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED) { - SoftApCapability capability = (SoftApCapability) message.obj; - mCurrentSoftApCapability = new SoftApCapability(capability); - mWifiMetrics.updateSoftApCapability(mCurrentSoftApCapability, - mApConfig.getTargetMode()); - updateClientConnection(); - } - break; - case CMD_UPDATE_CONFIG: - SoftApConfiguration newConfig = (SoftApConfiguration) message.obj; - SoftApConfiguration currentConfig = mApConfig.getSoftApConfiguration(); - if (mIsRandomizeBssid) { - // Current bssid is ramdon because unset. Set back to null.. - currentConfig = new SoftApConfiguration.Builder(currentConfig) - .setBssid(null) - .build(); - } - if (!ApConfigUtil.checkConfigurationChangeNeedToRestart( - currentConfig, newConfig)) { - Log.d(TAG, "Configuration changed to " + newConfig); - if (mApConfig.getSoftApConfiguration().getMaxNumberOfClients() - != newConfig.getMaxNumberOfClients()) { - Log.d(TAG, "Max Client changed, reset to record the metrics"); - mEverReportMetricsForMaxClient = false; - } - boolean needRescheduleTimer = - mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis() - != newConfig.getShutdownTimeoutMillis() - || mTimeoutEnabled != newConfig.isAutoShutdownEnabled(); - mBlockedClientList = new HashSet<>(newConfig.getBlockedClientList()); - mAllowedClientList = new HashSet<>(newConfig.getAllowedClientList()); - mTimeoutEnabled = newConfig.isAutoShutdownEnabled(); - mApConfig = new SoftApModeConfiguration(mApConfig.getTargetMode(), - newConfig, mCurrentSoftApCapability); - updateClientConnection(); - if (needRescheduleTimer) { - cancelTimeoutMessage(); - scheduleTimeoutMessage(); - } - mWifiMetrics.updateSoftApConfiguration( - mApConfig.getSoftApConfiguration(), - mApConfig.getTargetMode()); - } else { - Log.d(TAG, "Ignore the config: " + newConfig - + " update since it requires restart"); - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - } -} diff --git a/service/java/com/android/server/wifi/SoftApModeConfiguration.java b/service/java/com/android/server/wifi/SoftApModeConfiguration.java deleted file mode 100644 index 213385724..000000000 --- a/service/java/com/android/server/wifi/SoftApModeConfiguration.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiManager; - -import com.android.internal.util.Preconditions; - -import javax.annotation.Nullable; - -/** - * Object holding the parameters needed to start SoftAp mode. - */ -class SoftApModeConfiguration { - /** - * Routing mode. Either {@link android.net.wifi.WifiManager#IFACE_IP_MODE_TETHERED} - * or {@link android.net.wifi.WifiManager#IFACE_IP_MODE_LOCAL_ONLY}. - */ - private final int mTargetMode; - private final SoftApCapability mCapability; - - /** - * SoftApConfiguration for internal use, or null if it hasn't been generated yet. - */ - private final @Nullable SoftApConfiguration mSoftApConfig; - - SoftApModeConfiguration(int targetMode, @Nullable SoftApConfiguration config, - SoftApCapability capability) { - Preconditions.checkArgument( - targetMode == WifiManager.IFACE_IP_MODE_TETHERED - || targetMode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - - mTargetMode = targetMode; - mSoftApConfig = config; - mCapability = capability; - } - - public int getTargetMode() { - return mTargetMode; - } - - public SoftApConfiguration getSoftApConfiguration() { - return mSoftApConfig; - } - - public SoftApCapability getCapability() { - return mCapability; - } -} diff --git a/service/java/com/android/server/wifi/SoftApNotifier.java b/service/java/com/android/server/wifi/SoftApNotifier.java deleted file mode 100644 index 45114a549..000000000 --- a/service/java/com/android/server/wifi/SoftApNotifier.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Intent; -import android.graphics.drawable.Icon; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.wifi.resources.R; - -/** - * Helper class for SoftApManager to generator notification. - */ -public class SoftApNotifier { - private static final String TAG = "SoftApNotifier"; - - @VisibleForTesting - public static final String ACTION_HOTSPOT_PREFERENCES = - "com.android.settings.WIFI_TETHER_SETTINGS"; - - @VisibleForTesting - public static final int NOTIFICATION_ID_SOFTAP_AUTO_DISABLED = - SystemMessage.NOTE_SOFTAP_AUTO_DISABLED; - - private final WifiContext mContext; - private final FrameworkFacade mFrameworkFacade; - private final NotificationManager mNotificationManager; - - public SoftApNotifier(WifiContext context, FrameworkFacade framework) { - mContext = context; - mFrameworkFacade = framework; - mNotificationManager = - mContext.getSystemService(NotificationManager.class); - } - - /** - * Show notification to notify user softap disable because auto shutdown timeout expired. - */ - public void showSoftApShutDownTimeoutExpiredNotification() { - mNotificationManager.notify(NOTIFICATION_ID_SOFTAP_AUTO_DISABLED, - buildSoftApShutDownTimeoutExpiredNotification()); - } - - /** - * Dismiss notification which used to notify user softap disable because auto shutdown - * timeout expired. - */ - public void dismissSoftApShutDownTimeoutExpiredNotification() { - mNotificationManager.cancel(null, NOTIFICATION_ID_SOFTAP_AUTO_DISABLED); - } - - private Notification buildSoftApShutDownTimeoutExpiredNotification() { - String title = mContext.getResources().getString( - R.string.wifi_softap_auto_shutdown_timeout_expired_title); - String contentSummary = mContext.getResources().getString( - R.string.wifi_softap_auto_shutdown_timeout_expired_summary); - - return mFrameworkFacade.makeNotificationBuilder(mContext, - WifiService.NOTIFICATION_NETWORK_STATUS) - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - R.drawable.ic_wifi_settings)) - .setContentTitle(title) - .setContentText(contentSummary) - .setContentIntent(launchWifiTetherSettings()) - .setTicker(title) - .setShowWhen(false) - .setLocalOnly(true) - .setColor(mContext.getResources().getColor( - android.R.color.system_notification_accent_color, mContext.getTheme())) - .setAutoCancel(true) - .build(); - } - - private PendingIntent launchWifiTetherSettings() { - Intent intent = new Intent(ACTION_HOTSPOT_PREFERENCES) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - return mFrameworkFacade.getActivity(mContext, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - } - - -} diff --git a/service/java/com/android/server/wifi/SoftApStoreData.java b/service/java/com/android/server/wifi/SoftApStoreData.java deleted file mode 100644 index ae9a40af9..000000000 --- a/service/java/com/android/server/wifi/SoftApStoreData.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.Nullable; -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiMigration; -import android.text.TextUtils; -import android.util.Log; - -import com.android.server.wifi.util.ApConfigUtil; -import com.android.server.wifi.util.SettingsMigrationDataHolder; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Store data for SoftAp - */ -public class SoftApStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "SoftApStoreData"; - private static final String XML_TAG_SECTION_HEADER_SOFTAP = "SoftAp"; - private static final String XML_TAG_SSID = "SSID"; - private static final String XML_TAG_BSSID = "Bssid"; - private static final String XML_TAG_BAND = "Band"; - private static final String XML_TAG_CHANNEL = "Channel"; - private static final String XML_TAG_HIDDEN_SSID = "HiddenSSID"; - private static final String XML_TAG_SECURITY_TYPE = "SecurityType"; - private static final String XML_TAG_WPA2_PASSPHRASE = "Wpa2Passphrase"; - private static final String XML_TAG_AP_BAND = "ApBand"; - private static final String XML_TAG_PASSPHRASE = "Passphrase"; - private static final String XML_TAG_MAX_NUMBER_OF_CLIENTS = "MaxNumberOfClients"; - private static final String XML_TAG_AUTO_SHUTDOWN_ENABLED = "AutoShutdownEnabled"; - private static final String XML_TAG_SHUTDOWN_TIMEOUT_MILLIS = "ShutdownTimeoutMillis"; - private static final String XML_TAG_CLIENT_CONTROL_BY_USER = "ClientControlByUser"; - private static final String XML_TAG_BLOCKED_CLIENT_LIST = "BlockedClientList"; - private static final String XML_TAG_ALLOWED_CLIENT_LIST = "AllowedClientList"; - - private final Context mContext; - private final SettingsMigrationDataHolder mSettingsMigrationDataHolder; - private final DataSource mDataSource; - - /** - * Interface define the data source for the notifier store data. - */ - public interface DataSource { - /** - * Retrieve the SoftAp configuration from the data source to serialize them to disk. - * - * @return {@link SoftApConfiguration} Instance of SoftApConfiguration. - */ - SoftApConfiguration toSerialize(); - - /** - * Set the SoftAp configuration in the data source after serializing them from disk. - * - * @param config {@link SoftApConfiguration} Instance of SoftApConfiguration. - */ - void fromDeserialized(SoftApConfiguration config); - - /** - * Clear internal data structure in preparation for user switch or initial store read. - */ - void reset(); - - /** - * Indicates whether there is new data to serialize. - */ - boolean hasNewDataToSerialize(); - } - - /** - * Creates the SSID Set store data. - * - * @param dataSource The DataSource that implements the update and retrieval of the SSID set. - */ - SoftApStoreData(Context context, SettingsMigrationDataHolder settingsMigrationDataHolder, - DataSource dataSource) { - mContext = context; - mSettingsMigrationDataHolder = settingsMigrationDataHolder; - mDataSource = dataSource; - } - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - SoftApConfiguration softApConfig = mDataSource.toSerialize(); - if (softApConfig != null) { - XmlUtil.writeNextValue(out, XML_TAG_SSID, softApConfig.getSsid()); - if (softApConfig.getBssid() != null) { - XmlUtil.writeNextValue(out, XML_TAG_BSSID, softApConfig.getBssid().toString()); - } - XmlUtil.writeNextValue(out, XML_TAG_AP_BAND, softApConfig.getBand()); - XmlUtil.writeNextValue(out, XML_TAG_CHANNEL, softApConfig.getChannel()); - XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, softApConfig.isHiddenSsid()); - XmlUtil.writeNextValue(out, XML_TAG_SECURITY_TYPE, softApConfig.getSecurityType()); - if (softApConfig.getSecurityType() != SoftApConfiguration.SECURITY_TYPE_OPEN) { - XmlUtil.writeNextValue(out, XML_TAG_PASSPHRASE, - softApConfig.getPassphrase()); - } - - XmlUtil.writeNextValue(out, XML_TAG_MAX_NUMBER_OF_CLIENTS, - softApConfig.getMaxNumberOfClients()); - XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CONTROL_BY_USER, - softApConfig.isClientControlByUserEnabled()); - XmlUtil.writeNextValue(out, XML_TAG_AUTO_SHUTDOWN_ENABLED, - softApConfig.isAutoShutdownEnabled()); - XmlUtil.writeNextValue(out, XML_TAG_SHUTDOWN_TIMEOUT_MILLIS, - softApConfig.getShutdownTimeoutMillis()); - XmlUtil.writeNextSectionStart(out, XML_TAG_BLOCKED_CLIENT_LIST); - XmlUtil.SoftApConfigurationXmlUtil.writeClientListToXml(out, - softApConfig.getBlockedClientList()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_BLOCKED_CLIENT_LIST); - - XmlUtil.writeNextSectionStart(out, XML_TAG_ALLOWED_CLIENT_LIST); - XmlUtil.SoftApConfigurationXmlUtil.writeClientListToXml(out, - softApConfig.getAllowedClientList()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_ALLOWED_CLIENT_LIST); - } - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - // Ignore empty reads. - if (in == null) { - return; - } - SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder(); - int securityType = SoftApConfiguration.SECURITY_TYPE_OPEN; - String passphrase = null; - String ssid = null; - String bssid = null; - // Note that, during deserializaion, we may read the old band encoding (XML_TAG_BAND) - // or the new band encoding (XML_TAG_AP_BAND) that is used after the introduction of the - // 6GHz band. If the old encoding is found, a conversion is done. - int channel = -1; - int apBand = -1; - List<MacAddress> blockedList = new ArrayList<>(); - List<MacAddress> allowedList = new ArrayList<>(); - boolean autoShutdownEnabledTagPresent = false; - try { - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - if (in.getAttributeValue(null, "name") != null) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (TextUtils.isEmpty(valueName[0])) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_SSID: - ssid = (String) value; - softApConfigBuilder.setSsid((String) value); - break; - case XML_TAG_BSSID: - bssid = (String) value; - softApConfigBuilder.setBssid(MacAddress.fromString(bssid)); - break; - case XML_TAG_BAND: - apBand = ApConfigUtil.convertWifiConfigBandToSoftApConfigBand( - (int) value); - break; - case XML_TAG_AP_BAND: - apBand = (int) value; - break; - case XML_TAG_CHANNEL: - channel = (int) value; - break; - case XML_TAG_HIDDEN_SSID: - softApConfigBuilder.setHiddenSsid((boolean) value); - break; - case XML_TAG_SECURITY_TYPE: - securityType = (int) value; - break; - case XML_TAG_WPA2_PASSPHRASE: - case XML_TAG_PASSPHRASE: - passphrase = (String) value; - break; - case XML_TAG_MAX_NUMBER_OF_CLIENTS: - softApConfigBuilder.setMaxNumberOfClients((int) value); - break; - case XML_TAG_AUTO_SHUTDOWN_ENABLED: - softApConfigBuilder.setAutoShutdownEnabled((boolean) value); - autoShutdownEnabledTagPresent = true; - break; - case XML_TAG_SHUTDOWN_TIMEOUT_MILLIS: - if (value instanceof Integer) { - softApConfigBuilder - .setShutdownTimeoutMillis(Long.valueOf((int) value)); - } else if (value instanceof Long) { - softApConfigBuilder.setShutdownTimeoutMillis((long) value); - } - break; - case XML_TAG_CLIENT_CONTROL_BY_USER: - softApConfigBuilder.setClientControlByUserEnabled((boolean) value); - break; - default: - Log.w(TAG, "Ignoring unknown value name " + valueName[0]); - break; - } - } else { - String tagName = in.getName(); - List<MacAddress> parseredList; - if (tagName == null) { - throw new XmlPullParserException("Unexpected null tag found"); - } - switch (tagName) { - case XML_TAG_BLOCKED_CLIENT_LIST: - parseredList = - XmlUtil.SoftApConfigurationXmlUtil.parseClientListFromXml( - in, outerTagDepth + 1); - if (parseredList != null) blockedList = new ArrayList<>(parseredList); - break; - case XML_TAG_ALLOWED_CLIENT_LIST: - parseredList = - XmlUtil.SoftApConfigurationXmlUtil.parseClientListFromXml( - in, outerTagDepth + 1); - if (parseredList != null) allowedList = new ArrayList<>(parseredList); - break; - default: - Log.w(TAG, "Ignoring unknown tag found: " + tagName); - break; - } - } - } - softApConfigBuilder.setBlockedClientList(blockedList); - softApConfigBuilder.setAllowedClientList(allowedList); - // Set channel and band - if (channel == 0) { - softApConfigBuilder.setBand(apBand); - } else { - softApConfigBuilder.setChannel(channel, apBand); - } - - // We should at-least have SSID restored from store. - if (ssid == null) { - Log.e(TAG, "Failed to parse SSID"); - return; - } - if (securityType != SoftApConfiguration.SECURITY_TYPE_OPEN) { - softApConfigBuilder.setPassphrase(passphrase, securityType); - } - if (!autoShutdownEnabledTagPresent) { - // Migrate data out of settings. - WifiMigration.SettingsMigrationData migrationData = - mSettingsMigrationDataHolder.retrieveData(); - if (migrationData == null) { - Log.e(TAG, "No migration data present"); - } else { - softApConfigBuilder.setAutoShutdownEnabled( - migrationData.isSoftApTimeoutEnabled()); - } - } - } catch (IllegalArgumentException e) { - Log.e(TAG, "Failed to parse configuration" + e); - return; - } - mDataSource.fromDeserialized(softApConfigBuilder.setSsid(ssid).build()); - } - - @Override - public void resetData() { - mDataSource.reset(); - } - - @Override - public boolean hasNewDataToSerialize() { - return mDataSource.hasNewDataToSerialize(); - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER_SOFTAP; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - return WifiConfigStore.STORE_FILE_SHARED_SOFTAP; // Shared softap store. - } -} diff --git a/service/java/com/android/server/wifi/SsidSetStoreData.java b/service/java/com/android/server/wifi/SsidSetStoreData.java deleted file mode 100644 index e3374ddbe..000000000 --- a/service/java/com/android/server/wifi/SsidSetStoreData.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.annotation.Nullable; -import android.text.TextUtils; -import android.util.Log; - -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; - -/** - * Store data for network notifiers. - * - * Below are the current configuration data for each respective store file: - * - * User Store (user specific configurations) - * - Set of blacklisted SSIDs - */ -public class SsidSetStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "SsidSetStoreData"; - private static final String XML_TAG_SECTION_HEADER_SUFFIX = "ConfigData"; - private static final String XML_TAG_SSID_SET = "SSIDSet"; - - private final String mTagName; - private final DataSource mDataSource; - - /** - * Interface define the data source for the notifier store data. - */ - public interface DataSource { - /** - * Retrieve the SSID set from the data source. - * - * @return Set of SSIDs - */ - Set<String> getSsids(); - - /** - * Update the SSID set in the data source. - * - * @param ssidSet The set of SSIDs - */ - void setSsids(Set<String> ssidSet); - } - - /** - * Creates the SSID Set store data. - * - * @param name Identifier of the SSID set. - * @param dataSource The DataSource that implements the update and retrieval of the SSID set. - */ - SsidSetStoreData(String name, DataSource dataSource) { - mTagName = name + XML_TAG_SECTION_HEADER_SUFFIX; - mDataSource = dataSource; - } - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - Set<String> ssidSet = mDataSource.getSsids(); - if (ssidSet != null && !ssidSet.isEmpty()) { - XmlUtil.writeNextValue(out, XML_TAG_SSID_SET, mDataSource.getSsids()); - } - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - // Ignore empty reads. - if (in == null) { - return; - } - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (TextUtils.isEmpty(valueName[0])) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_SSID_SET: - mDataSource.setSsids((Set<String>) value); - break; - default: - Log.w(TAG, "Ignoring unknown tag under " + mTagName + ": " + valueName[0]); - break; - } - } - } - - @Override - public void resetData() { - mDataSource.setSsids(new HashSet<>()); - } - - @Override - public boolean hasNewDataToSerialize() { - // always persist. - return true; - } - - @Override - public String getName() { - return mTagName; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - // Shared general store. - return WifiConfigStore.STORE_FILE_USER_GENERAL; - } -} diff --git a/service/java/com/android/server/wifi/StateChangeResult.java b/service/java/com/android/server/wifi/StateChangeResult.java deleted file mode 100644 index f3d4bd6bf..000000000 --- a/service/java/com/android/server/wifi/StateChangeResult.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2011 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.server.wifi; - -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiSsid; - -/** - * Stores supplicant state change information passed from WifiMonitor to - * a state machine. ClientModeImpl, SupplicantStateTracker and WpsStateMachine - * are example state machines that handle it. - * @hide - */ -public class StateChangeResult { - StateChangeResult(int networkId, WifiSsid wifiSsid, String BSSID, - SupplicantState state) { - this.state = state; - this.wifiSsid= wifiSsid; - this.BSSID = BSSID; - this.networkId = networkId; - } - - int networkId; - WifiSsid wifiSsid; - String BSSID; - SupplicantState state; - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - - sb.append(" SSID: ").append(wifiSsid.toString()); - sb.append(" BSSID: ").append(BSSID); - sb.append(" nid: ").append(networkId); - sb.append(" state: ").append(state); - return sb.toString(); - } -} diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java deleted file mode 100644 index 0e2189ba0..000000000 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQP3GPPNetwork; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPDomName; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPIPAddrAvailability; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPNAIRealm; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPRoamingConsortium; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPVenueName; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSConnCapability; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSFriendlyName; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSOSUProviders; -import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSWANMetrics; - -import android.annotation.NonNull; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.util.Log; - -import com.android.server.wifi.hotspot2.AnqpEvent; -import com.android.server.wifi.hotspot2.IconEvent; -import com.android.server.wifi.hotspot2.WnmData; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.ANQPParser; -import com.android.server.wifi.hotspot2.anqp.Constants; -import com.android.server.wifi.util.NativeUtil; - -import java.io.IOException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -abstract class SupplicantStaIfaceCallbackImpl extends ISupplicantStaIfaceCallback.Stub { - private static final String TAG = SupplicantStaIfaceCallbackImpl.class.getSimpleName(); - private final SupplicantStaIfaceHal mStaIfaceHal; - private final String mIfaceName; - private final Object mLock; - private final WifiMonitor mWifiMonitor; - // Used to help check for PSK password mismatch & EAP connection failure. - private int mStateBeforeDisconnect = State.INACTIVE; - - SupplicantStaIfaceCallbackImpl(@NonNull SupplicantStaIfaceHal staIfaceHal, - @NonNull String ifaceName, - @NonNull Object lock, - @NonNull WifiMonitor wifiMonitor) { - mStaIfaceHal = staIfaceHal; - mIfaceName = ifaceName; - mLock = lock; - mWifiMonitor = wifiMonitor; - } - - /** - * Converts the supplicant state received from HIDL to the equivalent framework state. - */ - protected static SupplicantState supplicantHidlStateToFrameworkState(int state) { - switch (state) { - case ISupplicantStaIfaceCallback.State.DISCONNECTED: - return SupplicantState.DISCONNECTED; - case ISupplicantStaIfaceCallback.State.IFACE_DISABLED: - return SupplicantState.INTERFACE_DISABLED; - case ISupplicantStaIfaceCallback.State.INACTIVE: - return SupplicantState.INACTIVE; - case ISupplicantStaIfaceCallback.State.SCANNING: - return SupplicantState.SCANNING; - case ISupplicantStaIfaceCallback.State.AUTHENTICATING: - return SupplicantState.AUTHENTICATING; - case ISupplicantStaIfaceCallback.State.ASSOCIATING: - return SupplicantState.ASSOCIATING; - case ISupplicantStaIfaceCallback.State.ASSOCIATED: - return SupplicantState.ASSOCIATED; - case ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE: - return SupplicantState.FOUR_WAY_HANDSHAKE; - case ISupplicantStaIfaceCallback.State.GROUP_HANDSHAKE: - return SupplicantState.GROUP_HANDSHAKE; - case ISupplicantStaIfaceCallback.State.COMPLETED: - return SupplicantState.COMPLETED; - default: - throw new IllegalArgumentException("Invalid state: " + state); - } - } - - - /** - * Parses the provided payload into an ANQP element. - * - * @param infoID Element type. - * @param payload Raw payload bytes. - * @return AnqpElement instance on success, null on failure. - */ - private ANQPElement parseAnqpElement(Constants.ANQPElementType infoID, - ArrayList<Byte> payload) { - synchronized (mLock) { - try { - return Constants.getANQPElementID(infoID) != null - ? ANQPParser.parseElement( - infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))) - : ANQPParser.parseHS20Element( - infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))); - } catch (IOException | BufferUnderflowException e) { - Log.e(TAG, "Failed parsing ANQP element payload: " + infoID, e); - return null; - } - } - } - - /** - * Parse the ANQP element data and add to the provided elements map if successful. - * - * @param elementsMap Map to add the parsed out element to. - * @param infoID Element type. - * @param payload Raw payload bytes. - */ - private void addAnqpElementToMap(Map<Constants.ANQPElementType, ANQPElement> elementsMap, - Constants.ANQPElementType infoID, - ArrayList<Byte> payload) { - synchronized (mLock) { - if (payload == null || payload.isEmpty()) return; - ANQPElement element = parseAnqpElement(infoID, payload); - if (element != null) { - elementsMap.put(infoID, element); - } - } - } - - @Override - public void onNetworkAdded(int id) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onNetworkAdded"); - } - } - - @Override - public void onNetworkRemoved(int id) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onNetworkRemoved"); - // Reset state since network has been removed. - mStateBeforeDisconnect = State.INACTIVE; - } - } - - /** - * Added to plumb the new {@code filsHlpSent} param from the V1.3 callback version. - */ - public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid, - boolean filsHlpSent) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onStateChanged"); - SupplicantState newSupplicantState = - supplicantHidlStateToFrameworkState(newState); - WifiSsid wifiSsid = - WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid)); - String bssidStr = NativeUtil.macAddressFromByteArray(bssid); - if (newState != State.DISCONNECTED) { - // onStateChanged(DISCONNECTED) may come before onDisconnected(), so add this - // cache to track the state before the disconnect. - mStateBeforeDisconnect = newState; - } - if (newState == State.COMPLETED) { - mWifiMonitor.broadcastNetworkConnectionEvent( - mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), filsHlpSent, - bssidStr); - } - mWifiMonitor.broadcastSupplicantStateChangeEvent( - mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), wifiSsid, - bssidStr, newSupplicantState); - } - } - - @Override - public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid) { - onStateChanged(newState, bssid, id, ssid, false); - } - - @Override - public void onAnqpQueryDone(byte[/* 6 */] bssid, - ISupplicantStaIfaceCallback.AnqpData data, - ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onAnqpQueryDone"); - Map<Constants.ANQPElementType, ANQPElement> elementsMap = new HashMap<>(); - addAnqpElementToMap(elementsMap, ANQPVenueName, data.venueName); - addAnqpElementToMap(elementsMap, ANQPRoamingConsortium, data.roamingConsortium); - addAnqpElementToMap( - elementsMap, ANQPIPAddrAvailability, data.ipAddrTypeAvailability); - addAnqpElementToMap(elementsMap, ANQPNAIRealm, data.naiRealm); - addAnqpElementToMap(elementsMap, ANQP3GPPNetwork, data.anqp3gppCellularNetwork); - addAnqpElementToMap(elementsMap, ANQPDomName, data.domainName); - addAnqpElementToMap(elementsMap, HSFriendlyName, hs20Data.operatorFriendlyName); - addAnqpElementToMap(elementsMap, HSWANMetrics, hs20Data.wanMetrics); - addAnqpElementToMap(elementsMap, HSConnCapability, hs20Data.connectionCapability); - addAnqpElementToMap(elementsMap, HSOSUProviders, hs20Data.osuProvidersList); - mWifiMonitor.broadcastAnqpDoneEvent( - mIfaceName, new AnqpEvent(NativeUtil.macAddressToLong(bssid), elementsMap)); - } - } - - @Override - public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName, - ArrayList<Byte> data) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onHs20IconQueryDone"); - mWifiMonitor.broadcastIconDoneEvent( - mIfaceName, - new IconEvent(NativeUtil.macAddressToLong(bssid), fileName, data.size(), - NativeUtil.byteArrayFromArrayList(data))); - } - } - - @Override - public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, byte osuMethod, String url) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onHs20SubscriptionRemediation"); - mWifiMonitor.broadcastWnmEvent( - mIfaceName, - new WnmData(NativeUtil.macAddressToLong(bssid), url, osuMethod)); - } - } - - @Override - public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode, - int reAuthDelayInSec, String url) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onHs20DeauthImminentNotice"); - mWifiMonitor.broadcastWnmEvent( - mIfaceName, - new WnmData(NativeUtil.macAddressToLong(bssid), url, - reasonCode == WnmData.ESS, reAuthDelayInSec)); - } - } - - @Override - public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onDisconnected"); - if (mStaIfaceHal.isVerboseLoggingEnabled()) { - Log.e(TAG, "onDisconnected state=" + mStateBeforeDisconnect - + " locallyGenerated=" + locallyGenerated - + " reasonCode=" + reasonCode); - } - WifiConfiguration curConfiguration = - mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName); - if (curConfiguration != null) { - if (mStateBeforeDisconnect == State.FOURWAY_HANDSHAKE - && WifiConfigurationUtil.isConfigForPskNetwork(curConfiguration) - && (!locallyGenerated || reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS)) { - mWifiMonitor.broadcastAuthenticationFailureEvent( - mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1); - } else if (mStateBeforeDisconnect == State.ASSOCIATED - && WifiConfigurationUtil.isConfigForEapNetwork(curConfiguration)) { - mWifiMonitor.broadcastAuthenticationFailureEvent( - mIfaceName, WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, -1); - } - } - mWifiMonitor.broadcastNetworkDisconnectionEvent( - mIfaceName, locallyGenerated ? 1 : 0, reasonCode, - NativeUtil.macAddressFromByteArray(bssid)); - } - } - - @Override - public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode, boolean timedOut) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onAssociationRejected"); - boolean isWrongPwd = false; - WifiConfiguration curConfiguration = - mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName); - if (curConfiguration != null) { - if (!timedOut) { - Log.d(TAG, "flush PMK cache due to association rejection for config id " - + curConfiguration.networkId + "."); - mStaIfaceHal.removePmkCacheEntry(curConfiguration.networkId); - } - // Special handling for WPA3-Personal networks. If the password is - // incorrect, the AP will send association rejection, with status code 1 - // (unspecified failure). In SAE networks, the password authentication - // is not related to the 4-way handshake. In this case, we will send an - // authentication failure event up. - if (statusCode == StatusCode.UNSPECIFIED_FAILURE - && WifiConfigurationUtil.isConfigForSaeNetwork(curConfiguration)) { - mStaIfaceHal.logCallback("SAE incorrect password"); - isWrongPwd = true; - } else if (statusCode == StatusCode.CHALLENGE_FAIL - && WifiConfigurationUtil.isConfigForWepNetwork(curConfiguration)) { - mStaIfaceHal.logCallback("WEP incorrect password"); - isWrongPwd = true; - } - } - - if (isWrongPwd) { - mWifiMonitor.broadcastAuthenticationFailureEvent( - mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1); - } - mWifiMonitor - .broadcastAssociationRejectionEvent( - mIfaceName, statusCode, timedOut, - NativeUtil.macAddressFromByteArray(bssid)); - } - } - - @Override - public void onAuthenticationTimeout(byte[/* 6 */] bssid) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onAuthenticationTimeout"); - mWifiMonitor.broadcastAuthenticationFailureEvent( - mIfaceName, WifiManager.ERROR_AUTH_FAILURE_TIMEOUT, -1); - } - } - - @Override - public void onBssidChanged(byte reason, byte[/* 6 */] bssid) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onBssidChanged"); - if (reason == BssidChangeReason.ASSOC_START) { - mWifiMonitor.broadcastTargetBssidEvent( - mIfaceName, NativeUtil.macAddressFromByteArray(bssid)); - } else if (reason == BssidChangeReason.ASSOC_COMPLETE) { - mWifiMonitor.broadcastAssociatedBssidEvent( - mIfaceName, NativeUtil.macAddressFromByteArray(bssid)); - } - } - } - - @Override - public void onEapFailure() { - synchronized (mLock) { - mStaIfaceHal.logCallback("onEapFailure"); - mWifiMonitor.broadcastAuthenticationFailureEvent( - mIfaceName, WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, -1); - } - } - - @Override - public void onWpsEventSuccess() { - mStaIfaceHal.logCallback("onWpsEventSuccess"); - synchronized (mLock) { - mWifiMonitor.broadcastWpsSuccessEvent(mIfaceName); - } - } - - @Override - public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onWpsEventFail"); - if (configError == WpsConfigError.MSG_TIMEOUT - && errorInd == WpsErrorIndication.NO_ERROR) { - mWifiMonitor.broadcastWpsTimeoutEvent(mIfaceName); - } else { - mWifiMonitor.broadcastWpsFailEvent(mIfaceName, configError, errorInd); - } - } - } - - @Override - public void onWpsEventPbcOverlap() { - synchronized (mLock) { - mStaIfaceHal.logCallback("onWpsEventPbcOverlap"); - mWifiMonitor.broadcastWpsOverlapEvent(mIfaceName); - } - } - - @Override - public void onExtRadioWorkStart(int id) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onExtRadioWorkStart"); - } - } - - @Override - public void onExtRadioWorkTimeout(int id) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onExtRadioWorkTimeout"); - } - } -} diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_1Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_1Impl.java deleted file mode 100644 index c4a3dda16..000000000 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_1Impl.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; -import android.net.wifi.WifiManager; - -import java.util.ArrayList; - -abstract class SupplicantStaIfaceCallbackV1_1Impl extends - android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback.Stub { - private static final String TAG = SupplicantStaIfaceCallbackV1_1Impl.class.getSimpleName(); - private final SupplicantStaIfaceHal mStaIfaceHal; - private final String mIfaceName; - private final Object mLock; - private final WifiMonitor mWifiMonitor; - private final SupplicantStaIfaceHal.SupplicantStaIfaceHalCallback mCallbackV10; - - SupplicantStaIfaceCallbackV1_1Impl(@NonNull SupplicantStaIfaceHal staIfaceHal, - @NonNull String ifaceName, - @NonNull Object lock, - @NonNull WifiMonitor wifiMonitor) { - mStaIfaceHal = staIfaceHal; - mIfaceName = ifaceName; - mLock = lock; - mWifiMonitor = wifiMonitor; - // Create an older callback for function delegation, - // and it would cascadingly create older one. - mCallbackV10 = mStaIfaceHal.new SupplicantStaIfaceHalCallback(mIfaceName); - } - - @Override - public void onNetworkAdded(int id) { - mCallbackV10.onNetworkAdded(id); - } - - @Override - public void onNetworkRemoved(int id) { - mCallbackV10.onNetworkRemoved(id); - } - - /** - * Added to plumb the new {@code filsHlpSent} param from the V1.3 callback version. - */ - public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid, - boolean filsHlpSent) { - mCallbackV10.onStateChanged(newState, bssid, id, ssid, filsHlpSent); - } - - @Override - public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, - ArrayList<Byte> ssid) { - onStateChanged(newState, bssid, id, ssid, false); - } - - @Override - public void onAnqpQueryDone(byte[/* 6 */] bssid, - ISupplicantStaIfaceCallback.AnqpData data, - ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) { - mCallbackV10.onAnqpQueryDone(bssid, data, hs20Data); - } - - @Override - public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName, - ArrayList<Byte> data) { - mCallbackV10.onHs20IconQueryDone(bssid, fileName, data); - } - - @Override - public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, - byte osuMethod, String url) { - mCallbackV10.onHs20SubscriptionRemediation(bssid, osuMethod, url); - } - - @Override - public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode, - int reAuthDelayInSec, String url) { - mCallbackV10.onHs20DeauthImminentNotice(bssid, reasonCode, reAuthDelayInSec, url); - } - - @Override - public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, - int reasonCode) { - mCallbackV10.onDisconnected(bssid, locallyGenerated, reasonCode); - } - - @Override - public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode, - boolean timedOut) { - mCallbackV10.onAssociationRejected(bssid, statusCode, timedOut); - } - - @Override - public void onAuthenticationTimeout(byte[/* 6 */] bssid) { - mCallbackV10.onAuthenticationTimeout(bssid); - } - - @Override - public void onBssidChanged(byte reason, byte[/* 6 */] bssid) { - mCallbackV10.onBssidChanged(reason, bssid); - } - - @Override - public void onEapFailure() { - mCallbackV10.onEapFailure(); - } - - @Override - public void onEapFailure_1_1(int code) { - synchronized (mLock) { - mStaIfaceHal.logCallback("onEapFailure_1_1"); - mWifiMonitor.broadcastAuthenticationFailureEvent( - mIfaceName, WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, code); - } - } - - @Override - public void onWpsEventSuccess() { - mCallbackV10.onWpsEventSuccess(); - } - - @Override - public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) { - mCallbackV10.onWpsEventFail(bssid, configError, errorInd); - } - - @Override - public void onWpsEventPbcOverlap() { - mCallbackV10.onWpsEventPbcOverlap(); - } - - @Override - public void onExtRadioWorkStart(int id) { - mCallbackV10.onExtRadioWorkStart(id); - } - - @Override - public void onExtRadioWorkTimeout(int id) { - mCallbackV10.onExtRadioWorkTimeout(id); - } -} diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_2Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_2Impl.java deleted file mode 100644 index 973e11a4a..000000000 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_2Impl.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.content.Context; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; -import android.hardware.wifi.supplicant.V1_2.DppAkm; -import android.hardware.wifi.supplicant.V1_2.DppFailureCode; -import android.hardware.wifi.supplicant.V1_3.DppSuccessCode; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiSsid; -import android.os.Process; -import android.util.Log; - -import com.android.server.wifi.util.NativeUtil; - -import java.util.ArrayList; - -abstract class SupplicantStaIfaceCallbackV1_2Impl extends - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback.Stub { - private static final String TAG = SupplicantStaIfaceCallbackV1_2Impl.class.getSimpleName(); - private final SupplicantStaIfaceHal mStaIfaceHal; - private final String mIfaceName; - private final Context mContext; - private final SupplicantStaIfaceHal.SupplicantStaIfaceHalCallbackV1_1 mCallbackV11; - - SupplicantStaIfaceCallbackV1_2Impl(@NonNull SupplicantStaIfaceHal staIfaceHal, - @NonNull String ifaceName, - @NonNull Context context) { - mStaIfaceHal = staIfaceHal; - mIfaceName = ifaceName; - mContext = context; - // Create an older callback for function delegation, - // and it would cascadingly create older one. - mCallbackV11 = mStaIfaceHal.new SupplicantStaIfaceHalCallbackV1_1(mIfaceName); - } - - @Override - public void onNetworkAdded(int id) { - mCallbackV11.onNetworkAdded(id); - } - - @Override - public void onNetworkRemoved(int id) { - mCallbackV11.onNetworkRemoved(id); - } - - /** - * Added to plumb the new {@code filsHlpSent} param from the V1.3 callback version. - */ - public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid, - boolean filsHlpSent) { - mCallbackV11.onStateChanged(newState, bssid, id, ssid, filsHlpSent); - } - - @Override - public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, - ArrayList<Byte> ssid) { - onStateChanged(newState, bssid, id, ssid, false); - } - - @Override - public void onAnqpQueryDone(byte[/* 6 */] bssid, - ISupplicantStaIfaceCallback.AnqpData data, - ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) { - mCallbackV11.onAnqpQueryDone(bssid, data, hs20Data); - } - - @Override - public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName, - ArrayList<Byte> data) { - mCallbackV11.onHs20IconQueryDone(bssid, fileName, data); - } - - @Override - public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, - byte osuMethod, String url) { - mCallbackV11.onHs20SubscriptionRemediation(bssid, osuMethod, url); - } - - @Override - public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode, - int reAuthDelayInSec, String url) { - mCallbackV11.onHs20DeauthImminentNotice(bssid, reasonCode, reAuthDelayInSec, url); - } - - @Override - public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, - int reasonCode) { - mCallbackV11.onDisconnected(bssid, locallyGenerated, reasonCode); - } - - @Override - public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode, - boolean timedOut) { - mCallbackV11.onAssociationRejected(bssid, statusCode, timedOut); - } - - @Override - public void onAuthenticationTimeout(byte[/* 6 */] bssid) { - mCallbackV11.onAuthenticationTimeout(bssid); - } - - @Override - public void onBssidChanged(byte reason, byte[/* 6 */] bssid) { - mCallbackV11.onBssidChanged(reason, bssid); - } - - @Override - public void onEapFailure() { - mCallbackV11.onEapFailure(); - } - - @Override - public void onEapFailure_1_1(int code) { - mCallbackV11.onEapFailure_1_1(code); - } - - @Override - public void onWpsEventSuccess() { - mCallbackV11.onWpsEventSuccess(); - } - - @Override - public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) { - mCallbackV11.onWpsEventFail(bssid, configError, errorInd); - } - - @Override - public void onWpsEventPbcOverlap() { - mCallbackV11.onWpsEventPbcOverlap(); - } - - @Override - public void onExtRadioWorkStart(int id) { - mCallbackV11.onExtRadioWorkStart(id); - } - - @Override - public void onExtRadioWorkTimeout(int id) { - mCallbackV11.onExtRadioWorkTimeout(id); - } - - @Override - public void onDppSuccessConfigReceived(ArrayList<Byte> ssid, String password, - byte[] psk, int securityAkm) { - if (mStaIfaceHal.getDppCallback() == null) { - Log.e(TAG, "onDppSuccessConfigReceived callback is null"); - return; - } - - WifiConfiguration newWifiConfiguration = new WifiConfiguration(); - - // Set up SSID - WifiSsid wifiSsid = - WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid)); - - newWifiConfiguration.SSID = "\"" + wifiSsid.toString() + "\""; - - // Set up password or PSK - if (password != null) { - newWifiConfiguration.preSharedKey = "\"" + password + "\""; - } else if (psk != null) { - newWifiConfiguration.preSharedKey = psk.toString(); - } - - // Set up key management: SAE or PSK - if (securityAkm == DppAkm.SAE || securityAkm == DppAkm.PSK_SAE) { - newWifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - newWifiConfiguration.requirePmf = true; - } else if (securityAkm == DppAkm.PSK) { - newWifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - } else { - // No other AKMs are currently supported - onDppFailure(DppFailureCode.NOT_SUPPORTED); - return; - } - - // Set up default values - newWifiConfiguration.creatorName = mContext.getPackageManager() - .getNameForUid(Process.WIFI_UID); - newWifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - newWifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - newWifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); - newWifiConfiguration.status = WifiConfiguration.Status.ENABLED; - - mStaIfaceHal.getDppCallback().onSuccessConfigReceived(newWifiConfiguration); - } - - @Override - public void onDppSuccessConfigSent() { - if (mStaIfaceHal.getDppCallback() != null) { - mStaIfaceHal.getDppCallback().onSuccess(DppSuccessCode.CONFIGURATION_SENT); - } else { - Log.e(TAG, "onSuccessConfigSent callback is null"); - } - } - - @Override - public void onDppProgress(int code) { - if (mStaIfaceHal.getDppCallback() != null) { - mStaIfaceHal.getDppCallback().onProgress(code); - } else { - Log.e(TAG, "onDppProgress callback is null"); - } - } - - @Override - public void onDppFailure(int code) { - if (mStaIfaceHal.getDppCallback() != null) { - mStaIfaceHal.getDppCallback().onFailure(code, null, null, null); - } else { - Log.e(TAG, "onDppFailure callback is null"); - } - } -} diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java deleted file mode 100644 index 154fde40b..000000000 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - - -import android.annotation.NonNull; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.util.Log; - -import java.util.ArrayList; - -abstract class SupplicantStaIfaceCallbackV1_3Impl extends - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback.Stub { - private static final String TAG = SupplicantStaIfaceCallbackV1_3Impl.class.getSimpleName(); - private final SupplicantStaIfaceHal mStaIfaceHal; - private final String mIfaceName; - private final WifiMonitor mWifiMonitor; - private final SupplicantStaIfaceHal.SupplicantStaIfaceHalCallbackV1_2 mCallbackV12; - - SupplicantStaIfaceCallbackV1_3Impl(@NonNull SupplicantStaIfaceHal staIfaceHal, - @NonNull String ifaceName, - @NonNull WifiMonitor wifiMonitor) { - mStaIfaceHal = staIfaceHal; - mIfaceName = ifaceName; - mWifiMonitor = wifiMonitor; - // Create an older callback for function delegation, - // and it would cascadingly create older one. - mCallbackV12 = mStaIfaceHal.new SupplicantStaIfaceHalCallbackV1_2(mIfaceName); - } - - @Override - public void onNetworkAdded(int id) { - mCallbackV12.onNetworkAdded(id); - } - - @Override - public void onNetworkRemoved(int id) { - mCallbackV12.onNetworkRemoved(id); - } - - @Override - public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, - ArrayList<Byte> ssid) { - mCallbackV12.onStateChanged(newState, bssid, id, ssid); - } - - @Override - public void onAnqpQueryDone(byte[/* 6 */] bssid, - ISupplicantStaIfaceCallback.AnqpData data, - ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) { - mCallbackV12.onAnqpQueryDone(bssid, data, hs20Data); - } - - @Override - public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName, - ArrayList<Byte> data) { - mCallbackV12.onHs20IconQueryDone(bssid, fileName, data); - } - - @Override - public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, - byte osuMethod, String url) { - mCallbackV12.onHs20SubscriptionRemediation(bssid, osuMethod, url); - } - - @Override - public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode, - int reAuthDelayInSec, String url) { - mCallbackV12.onHs20DeauthImminentNotice(bssid, reasonCode, reAuthDelayInSec, url); - } - - @Override - public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, - int reasonCode) { - mCallbackV12.onDisconnected(bssid, locallyGenerated, reasonCode); - } - - @Override - public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode, - boolean timedOut) { - mCallbackV12.onAssociationRejected(bssid, statusCode, timedOut); - } - - @Override - public void onAuthenticationTimeout(byte[/* 6 */] bssid) { - mCallbackV12.onAuthenticationTimeout(bssid); - } - - @Override - public void onBssidChanged(byte reason, byte[/* 6 */] bssid) { - mCallbackV12.onBssidChanged(reason, bssid); - } - - @Override - public void onEapFailure() { - mCallbackV12.onEapFailure(); - } - - @Override - public void onEapFailure_1_1(int code) { - mCallbackV12.onEapFailure_1_1(code); - } - - @Override - public void onEapFailure_1_3(int code) { - mWifiMonitor.broadcastAuthenticationFailureEvent( - mIfaceName, WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, code); - } - - @Override - public void onWpsEventSuccess() { - mCallbackV12.onWpsEventSuccess(); - } - - @Override - public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) { - mCallbackV12.onWpsEventFail(bssid, configError, errorInd); - } - - @Override - public void onWpsEventPbcOverlap() { - mCallbackV12.onWpsEventPbcOverlap(); - } - - @Override - public void onExtRadioWorkStart(int id) { - mCallbackV12.onExtRadioWorkStart(id); - } - - @Override - public void onExtRadioWorkTimeout(int id) { - mCallbackV12.onExtRadioWorkTimeout(id); - } - - @Override - public void onDppSuccessConfigReceived(ArrayList<Byte> ssid, String password, - byte[] psk, int securityAkm) { - mCallbackV12.onDppSuccessConfigReceived( - ssid, password, psk, securityAkm); - } - - @Override - public void onDppSuccessConfigSent() { - mCallbackV12.onDppSuccessConfigSent(); - } - - @Override - public void onDppProgress(int code) { - mCallbackV12.onDppProgress(code); - } - - @Override - public void onDppFailure(int code) { - mCallbackV12.onDppFailure(code); - } - - @Override - public void onPmkCacheAdded(long expirationTimeInSec, ArrayList<Byte> serializedEntry) { - WifiConfiguration curConfig = mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName); - - if (curConfig == null) return; - - if (WifiConfigurationUtil.isConfigForPskNetwork(curConfig)) return; - - mStaIfaceHal.addPmkCacheEntry(mIfaceName, - curConfig.networkId, expirationTimeInSec, serializedEntry); - mStaIfaceHal.logCallback( - "onPmkCacheAdded: update pmk cache for config id " - + curConfig.networkId - + " on " - + mIfaceName); - } - - @Override - public void onDppProgress_1_3(int code) { - if (mStaIfaceHal.getDppCallback() != null) { - mStaIfaceHal.getDppCallback().onProgress(code); - } else { - Log.e(TAG, "onDppProgress callback is null"); - } - } - - @Override - public void onDppFailure_1_3(int code, String ssid, String channelList, - ArrayList<Short> bandList) { - if (mStaIfaceHal.getDppCallback() != null) { - int[] bandListArray = null; - - // Convert operating class list to a primitive array - if (bandList != null) { - bandListArray = new int[bandList.size()]; - - for (int i = 0; i < bandList.size(); i++) { - bandListArray[i] = bandList.get(i).intValue(); - } - } - mStaIfaceHal.getDppCallback().onFailure(code, ssid, channelList, bandListArray); - } else { - Log.e(TAG, "onDppFailure callback is null"); - } - } - - @Override - public void onDppSuccess(int code) { - if (mStaIfaceHal.getDppCallback() != null) { - mStaIfaceHal.getDppCallback().onSuccess(code); - } else { - Log.e(TAG, "onDppFailure callback is null"); - } - } - - @Override - public void onBssTmHandlingDone(BssTmData tmData) { - MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData(); - - btmFrmData.mStatus = halToFrameworkBtmResponseStatus(tmData.status); - btmFrmData.mBssTmDataFlagsMask = halToFrameworkBssTmDataFlagsMask(tmData.flags); - btmFrmData.mBlockListDurationMs = tmData.assocRetryDelayMs; - if ((tmData.flags & BssTmDataFlagsMask.MBO_TRANSITION_REASON_CODE_INCLUDED) != 0) { - btmFrmData.mTransitionReason = halToFrameworkMboTransitionReason( - tmData.mboTransitionReason); - } - if ((tmData.flags - & BssTmDataFlagsMask.MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED) != 0) { - btmFrmData.mCellPreference = - halToFrameworkMboCellularDataConnectionPreference(tmData.mboCellPreference); - } - mStaIfaceHal.logCallback( - "onBssTmHandlingDone: Handle BTM handling event"); - mWifiMonitor.broadcastBssTmHandlingDoneEvent(mIfaceName, btmFrmData); - } - - private @MboOceConstants.BtmResponseStatus int halToFrameworkBtmResponseStatus(int status) { - switch (status) { - case BssTmStatusCode.ACCEPT: - return MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT; - case BssTmStatusCode.REJECT_UNSPECIFIED: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED; - case BssTmStatusCode.REJECT_INSUFFICIENT_BEACON: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_INSUFFICIENT_BEACON; - case BssTmStatusCode.REJECT_INSUFFICIENT_CAPABITY: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_INSUFFICIENT_CAPABITY; - case BssTmStatusCode.REJECT_BSS_TERMINATION_UNDESIRED: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_BSS_TERMINATION_UNDESIRED; - case BssTmStatusCode.REJECT_BSS_TERMINATION_DELAY_REQUEST: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_BSS_TERMINATION_DELAY_REQUEST; - case BssTmStatusCode.REJECT_STA_CANDIDATE_LIST_PROVIDED: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_STA_CANDIDATE_LIST_PROVIDED; - case BssTmStatusCode.REJECT_NO_SUITABLE_CANDIDATES: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_NO_SUITABLE_CANDIDATES; - case BssTmStatusCode.REJECT_LEAVING_ESS: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_LEAVING_ESS; - default: - return MboOceConstants.BTM_RESPONSE_STATUS_REJECT_RESERVED; - } - } - - private int halToFrameworkBssTmDataFlagsMask(int flags) { - int tmDataflags = 0; - if ((flags & BssTmDataFlagsMask.WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED) != 0) { - tmDataflags |= MboOceConstants.BTM_DATA_FLAG_PREFERRED_CANDIDATE_LIST_INCLUDED; - } - if ((flags & BssTmDataFlagsMask.WNM_MODE_ABRIDGED) != 0) { - tmDataflags |= MboOceConstants.BTM_DATA_FLAG_MODE_ABRIDGED; - } - if ((flags & BssTmDataFlagsMask.WNM_MODE_DISASSOCIATION_IMMINENT) != 0) { - tmDataflags |= MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT; - } - if ((flags & BssTmDataFlagsMask.WNM_MODE_BSS_TERMINATION_INCLUDED) != 0) { - tmDataflags |= MboOceConstants.BTM_DATA_FLAG_BSS_TERMINATION_INCLUDED; - } - if ((flags & BssTmDataFlagsMask.WNM_MODE_ESS_DISASSOCIATION_IMMINENT) != 0) { - tmDataflags |= MboOceConstants.BTM_DATA_FLAG_ESS_DISASSOCIATION_IMMINENT; - } - if ((flags & BssTmDataFlagsMask.MBO_TRANSITION_REASON_CODE_INCLUDED) != 0) { - tmDataflags |= MboOceConstants.BTM_DATA_FLAG_MBO_TRANSITION_REASON_CODE_INCLUDED; - } - if ((flags & BssTmDataFlagsMask.MBO_ASSOC_RETRY_DELAY_INCLUDED) != 0) { - tmDataflags |= MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED; - } - if ((flags & BssTmDataFlagsMask.MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED) != 0) { - tmDataflags |= - MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED; - } - return tmDataflags; - } - - private @MboOceConstants.MboTransitionReason int halToFrameworkMboTransitionReason( - int reason) { - switch (reason) { - case MboTransitionReasonCode.UNSPECIFIED: - return MboOceConstants.MBO_TRANSITION_REASON_UNSPECIFIED; - case MboTransitionReasonCode.EXCESSIVE_FRAME_LOSS: - return MboOceConstants.MBO_TRANSITION_REASON_EXCESSIVE_FRAME_LOSS; - case MboTransitionReasonCode.EXCESSIVE_TRAFFIC_DELAY: - return MboOceConstants.MBO_TRANSITION_REASON_EXCESSIVE_TRAFFIC_DELAY; - case MboTransitionReasonCode.INSUFFICIENT_BANDWIDTH: - return MboOceConstants.MBO_TRANSITION_REASON_INSUFFICIENT_BANDWIDTH; - case MboTransitionReasonCode.LOAD_BALANCING: - return MboOceConstants.MBO_TRANSITION_REASON_LOAD_BALANCING; - case MboTransitionReasonCode.LOW_RSSI: - return MboOceConstants.MBO_TRANSITION_REASON_LOW_RSSI; - case MboTransitionReasonCode.RX_EXCESSIVE_RETRIES: - return MboOceConstants.MBO_TRANSITION_REASON_RX_EXCESSIVE_RETRIES; - case MboTransitionReasonCode.HIGH_INTERFERENCE: - return MboOceConstants.MBO_TRANSITION_REASON_HIGH_INTERFERENCE; - case MboTransitionReasonCode.GRAY_ZONE: - return MboOceConstants.MBO_TRANSITION_REASON_GRAY_ZONE; - default: - return MboOceConstants.MBO_TRANSITION_REASON_RESERVED; - } - } - - private @MboOceConstants.MboTransitionReason int - halToFrameworkMboCellularDataConnectionPreference(int cellPref) { - switch (cellPref) { - case MboCellularDataConnectionPrefValue.EXCLUDED: - return MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_EXCLUDED; - case MboCellularDataConnectionPrefValue.NOT_PREFERRED: - return MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_NOT_PREFERRED; - case MboCellularDataConnectionPrefValue.PREFERRED: - return MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_PREFERRED; - default: - return MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_RESERVED; - } - } - - @Override - public void onStateChanged_1_3(int newState, byte[/* 6 */] bssid, int id, - ArrayList<Byte> ssid, boolean filsHlpSent) { - mCallbackV12.onStateChanged(newState, bssid, id, ssid, filsHlpSent); - } -} diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java deleted file mode 100644 index b587eed38..000000000 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java +++ /dev/null @@ -1,3315 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP; -import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256; -import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384; -import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO; -import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE; -import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; -import static android.net.wifi.WifiManager.WIFI_FEATURE_WAPI; -import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; -import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; - -import android.annotation.NonNull; -import android.content.Context; -import android.hardware.wifi.V1_0.WifiChannelWidthInMhz; -import android.hardware.wifi.supplicant.V1_0.ISupplicant; -import android.hardware.wifi.supplicant.V1_0.ISupplicantIface; -import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; -import android.hardware.wifi.supplicant.V1_0.IfaceType; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; -import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; -import android.hardware.wifi.supplicant.V1_3.ConnectionCapabilities; -import android.hardware.wifi.supplicant.V1_3.WifiTechnology; -import android.hardware.wifi.supplicant.V1_3.WpaDriverCapabilitiesMask; -import android.hidl.manager.V1_0.IServiceManager; -import android.hidl.manager.V1_0.IServiceNotification; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiAnnotations.WifiStandard; -import android.net.wifi.WifiConfiguration; -import android.os.Handler; -import android.os.IHwBinder.DeathRecipient; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; -import android.util.MutableBoolean; -import android.util.MutableInt; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.WifiNative.DppEventCallback; -import com.android.server.wifi.WifiNative.SupplicantDeathEventHandler; -import com.android.server.wifi.util.GeneralUtil.Mutable; -import com.android.server.wifi.util.NativeUtil; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Random; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.annotation.concurrent.ThreadSafe; - -/** - * Hal calls for bring up/shut down of the supplicant daemon and for - * sending requests to the supplicant daemon - * To maintain thread-safety, the locking protocol is that every non-static method (regardless of - * access level) acquires mLock. - */ -@ThreadSafe -public class SupplicantStaIfaceHal { - private static final String TAG = "SupplicantStaIfaceHal"; - @VisibleForTesting - public static final String HAL_INSTANCE_NAME = "default"; - @VisibleForTesting - public static final long WAIT_FOR_DEATH_TIMEOUT_MS = 50L; - @VisibleForTesting - static final String PMK_CACHE_EXPIRATION_ALARM_TAG = "PMK_CACHE_EXPIRATION_TIMER"; - /** - * Regex pattern for extracting the wps device type bytes. - * Matches a strings like the following: "<categ>-<OUI>-<subcateg>"; - */ - private static final Pattern WPS_DEVICE_TYPE_PATTERN = - Pattern.compile("^(\\d{1,2})-([0-9a-fA-F]{8})-(\\d{1,2})$"); - - private final Object mLock = new Object(); - private boolean mVerboseLoggingEnabled = false; - - // Supplicant HAL interface objects - private IServiceManager mIServiceManager = null; - private ISupplicant mISupplicant; - private HashMap<String, ISupplicantStaIface> mISupplicantStaIfaces = new HashMap<>(); - private HashMap<String, ISupplicantStaIfaceCallback> mISupplicantStaIfaceCallbacks = - new HashMap<>(); - private HashMap<String, SupplicantStaNetworkHal> mCurrentNetworkRemoteHandles = new HashMap<>(); - private HashMap<String, WifiConfiguration> mCurrentNetworkLocalConfigs = new HashMap<>(); - @VisibleForTesting - HashMap<Integer, PmkCacheStoreData> mPmkCacheEntries = new HashMap<>(); - private SupplicantDeathEventHandler mDeathEventHandler; - private ServiceManagerDeathRecipient mServiceManagerDeathRecipient; - private SupplicantDeathRecipient mSupplicantDeathRecipient; - // Death recipient cookie registered for current supplicant instance. - private long mDeathRecipientCookie = 0; - private final Context mContext; - private final WifiMonitor mWifiMonitor; - private final FrameworkFacade mFrameworkFacade; - private final Handler mEventHandler; - private DppEventCallback mDppCallback = null; - private final Clock mClock; - private final WifiMetrics mWifiMetrics; - - private final IServiceNotification mServiceNotificationCallback = - new IServiceNotification.Stub() { - public void onRegistration(String fqName, String name, boolean preexisting) { - synchronized (mLock) { - if (mVerboseLoggingEnabled) { - Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName - + ", " + name + " preexisting=" + preexisting); - } - if (!initSupplicantService()) { - Log.e(TAG, "initalizing ISupplicant failed."); - supplicantServiceDiedHandler(mDeathRecipientCookie); - } else { - Log.i(TAG, "Completed initialization of ISupplicant."); - } - } - } - }; - private class ServiceManagerDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - synchronized (mLock) { - Log.w(TAG, "IServiceManager died: cookie=" + cookie); - supplicantServiceDiedHandler(mDeathRecipientCookie); - mIServiceManager = null; // Will need to register a new ServiceNotification - } - }); - } - } - private class SupplicantDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - synchronized (mLock) { - Log.w(TAG, "ISupplicant died: cookie=" + cookie); - supplicantServiceDiedHandler(cookie); - } - }); - } - } - - @VisibleForTesting - static class PmkCacheStoreData { - public long expirationTimeInSec; - public ArrayList<Byte> data; - public MacAddress macAddress; - - PmkCacheStoreData(long timeInSec, ArrayList<Byte> serializedData, MacAddress macAddress) { - expirationTimeInSec = timeInSec; - data = serializedData; - this.macAddress = macAddress; - } - } - - public SupplicantStaIfaceHal(Context context, WifiMonitor monitor, - FrameworkFacade frameworkFacade, Handler handler, - Clock clock, WifiMetrics wifiMetrics) { - mContext = context; - mWifiMonitor = monitor; - mFrameworkFacade = frameworkFacade; - mEventHandler = handler; - mClock = clock; - mWifiMetrics = wifiMetrics; - - mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient(); - mSupplicantDeathRecipient = new SupplicantDeathRecipient(); - } - - /** - * Enable/Disable verbose logging. - * - * @param enable true to enable, false to disable. - */ - void enableVerboseLogging(boolean enable) { - synchronized (mLock) { - mVerboseLoggingEnabled = enable; - } - } - - protected boolean isVerboseLoggingEnabled() { - return mVerboseLoggingEnabled; - } - - private boolean linkToServiceManagerDeath() { - synchronized (mLock) { - if (mIServiceManager == null) return false; - try { - if (!mIServiceManager.linkToDeath(mServiceManagerDeathRecipient, 0)) { - Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); - supplicantServiceDiedHandler(mDeathRecipientCookie); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "IServiceManager.linkToDeath exception", e); - return false; - } - return true; - } - } - - /** - * Registers a service notification for the ISupplicant service, which triggers initialization - * of the ISupplicantStaIface - * @return true if the service notification was successfully registered - */ - public boolean initialize() { - synchronized (mLock) { - if (mVerboseLoggingEnabled) { - Log.i(TAG, "Registering ISupplicant service ready callback."); - } - mISupplicant = null; - mISupplicantStaIfaces.clear(); - if (mIServiceManager != null) { - // Already have an IServiceManager and serviceNotification registered, don't - // don't register another. - return true; - } - try { - mIServiceManager = getServiceManagerMockable(); - if (mIServiceManager == null) { - Log.e(TAG, "Failed to get HIDL Service Manager"); - return false; - } - if (!linkToServiceManagerDeath()) { - return false; - } - /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it - exists */ - if (!mIServiceManager.registerForNotifications( - ISupplicant.kInterfaceName, "", mServiceNotificationCallback)) { - Log.e(TAG, "Failed to register for notifications to " - + ISupplicant.kInterfaceName); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: " - + e); - supplicantServiceDiedHandler(mDeathRecipientCookie); - } - return true; - } - } - - private boolean linkToSupplicantDeath( - DeathRecipient deathRecipient, long cookie) { - synchronized (mLock) { - if (mISupplicant == null) return false; - try { - if (!mISupplicant.linkToDeath(deathRecipient, cookie)) { - Log.wtf(TAG, "Error on linkToDeath on ISupplicant"); - supplicantServiceDiedHandler(mDeathRecipientCookie); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.linkToDeath exception", e); - return false; - } - return true; - } - } - - private boolean initSupplicantService() { - synchronized (mLock) { - try { - mISupplicant = getSupplicantMockable(); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.getService exception: " + e); - return false; - } catch (NoSuchElementException e) { - Log.e(TAG, "ISupplicant.getService exception: " + e); - return false; - } - if (mISupplicant == null) { - Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup"); - return false; - } - if (!linkToSupplicantDeath(mSupplicantDeathRecipient, ++mDeathRecipientCookie)) { - return false; - } - } - return true; - } - - protected int getCurrentNetworkId(@NonNull String ifaceName) { - synchronized (mLock) { - WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName); - if (currentConfig == null) { - return WifiConfiguration.INVALID_NETWORK_ID; - } - return currentConfig.networkId; - } - } - - private boolean trySetupStaIfaceV1_3(@NonNull String ifaceName, - @NonNull ISupplicantStaIface iface) throws RemoteException { - if (!isV1_3()) return false; - - SupplicantStaIfaceHalCallbackV1_3 callbackV13 = - new SupplicantStaIfaceHalCallbackV1_3(ifaceName); - if (!registerCallbackV1_3(getStaIfaceMockableV1_3(iface), callbackV13)) { - throw new RemoteException("Init StaIface V1_3 failed."); - } - /* keep this in a store to avoid recycling by garbage collector. */ - mISupplicantStaIfaceCallbacks.put(ifaceName, callbackV13); - return true; - } - - private boolean trySetupStaIfaceV1_2(@NonNull String ifaceName, - @NonNull ISupplicantStaIface iface) throws RemoteException { - if (!isV1_2()) return false; - - /* try newer version fist. */ - if (trySetupStaIfaceV1_3(ifaceName, iface)) { - logd("Newer HAL is found, skip V1_2 remaining init flow."); - return true; - } - - SupplicantStaIfaceHalCallbackV1_2 callbackV12 = - new SupplicantStaIfaceHalCallbackV1_2(ifaceName); - if (!registerCallbackV1_2(getStaIfaceMockableV1_2(iface), callbackV12)) { - throw new RemoteException("Init StaIface V1_2 failed."); - } - /* keep this in a store to avoid recycling by garbage collector. */ - mISupplicantStaIfaceCallbacks.put(ifaceName, callbackV12); - return true; - } - - private boolean trySetupStaIfaceV1_1(@NonNull String ifaceName, - @NonNull ISupplicantStaIface iface) throws RemoteException { - if (!isV1_1()) return false; - - /* try newer version fist. */ - if (trySetupStaIfaceV1_2(ifaceName, iface)) { - logd("Newer HAL is found, skip V1_1 remaining init flow."); - return true; - } - - SupplicantStaIfaceHalCallbackV1_1 callbackV11 = - new SupplicantStaIfaceHalCallbackV1_1(ifaceName); - if (!registerCallbackV1_1(getStaIfaceMockableV1_1(iface), callbackV11)) { - throw new RemoteException("Init StaIface V1_1 failed."); - } - /* keep this in a store to avoid recycling by garbage collector. */ - mISupplicantStaIfaceCallbacks.put(ifaceName, callbackV11); - return true; - } - - /** - * Helper function to set up StaIface with different HAL version. - * - * This helper function would try newer version recursively. - * Once the latest version is found, it would register the callback - * of the latest version and skip unnecessary older HAL init flow. - * - * New version callback will be extended from the older one, as a result, - * older callback is always created regardless of the latest version. - * - * Uprev steps: - * 1. add new helper function trySetupStaIfaceV1_Y. - * 2. call newly added function in trySetupStaIfaceV1_X (X should be Y-1). - */ - private ISupplicantStaIface setupStaIface(@NonNull String ifaceName, - @NonNull ISupplicantIface ifaceHwBinder) throws RemoteException { - /* Prepare base type for later cast. */ - ISupplicantStaIface iface = getStaIfaceMockable(ifaceHwBinder); - - /* try newer version first. */ - if (trySetupStaIfaceV1_1(ifaceName, iface)) { - logd("Newer HAL is found, skip V1_0 remaining init flow."); - return iface; - } - - SupplicantStaIfaceHalCallback callback = new SupplicantStaIfaceHalCallback(ifaceName); - if (!registerCallback(iface, callback)) { - throw new RemoteException("Init StaIface V1_0 failed."); - } - /* keep this in a store to avoid recycling by garbage collector. */ - mISupplicantStaIfaceCallbacks.put(ifaceName, callback); - return iface; - } - - /** - * Setup a STA interface for the specified iface name. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - public boolean setupIface(@NonNull String ifaceName) { - final String methodStr = "setupIface"; - if (checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr) != null) return false; - ISupplicantIface ifaceHwBinder; - - if (isV1_1()) { - ifaceHwBinder = addIfaceV1_1(ifaceName); - } else { - ifaceHwBinder = getIfaceV1_0(ifaceName); - } - if (ifaceHwBinder == null) { - Log.e(TAG, "setupIface got null iface"); - return false; - } - - try { - ISupplicantStaIface iface = setupStaIface(ifaceName, ifaceHwBinder); - mISupplicantStaIfaces.put(ifaceName, iface); - } catch (RemoteException e) { - loge("setup StaIface failed: " + e.toString()); - return false; - } - - return true; - } - - /** - * Get a STA interface for the specified iface name. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - private ISupplicantIface getIfaceV1_0(@NonNull String ifaceName) { - synchronized (mLock) { - if (mISupplicant == null) { - return null; - } - - /** List all supplicant Ifaces */ - final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>(); - try { - mISupplicant.listInterfaces((SupplicantStatus status, - ArrayList<ISupplicant.IfaceInfo> ifaces) -> { - if (status.code != SupplicantStatusCode.SUCCESS) { - Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code); - return; - } - supplicantIfaces.addAll(ifaces); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.listInterfaces exception: " + e); - handleRemoteException(e, "listInterfaces"); - return null; - } - if (supplicantIfaces.size() == 0) { - Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup."); - return null; - } - Mutable<ISupplicantIface> supplicantIface = new Mutable<>(); - for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) { - if (ifaceInfo.type == IfaceType.STA && ifaceName.equals(ifaceInfo.name)) { - try { - mISupplicant.getInterface(ifaceInfo, - (SupplicantStatus status, ISupplicantIface iface) -> { - if (status.code != SupplicantStatusCode.SUCCESS) { - Log.e(TAG, "Failed to get ISupplicantIface " + status.code); - return; - } - supplicantIface.value = iface; - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.getInterface exception: " + e); - handleRemoteException(e, "getInterface"); - return null; - } - break; - } - } - return supplicantIface.value; - } - } - - /** - * Create a STA interface for the specified iface name. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - private ISupplicantIface addIfaceV1_1(@NonNull String ifaceName) { - synchronized (mLock) { - ISupplicant.IfaceInfo ifaceInfo = new ISupplicant.IfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.type = IfaceType.STA; - Mutable<ISupplicantIface> supplicantIface = new Mutable<>(); - try { - getSupplicantMockableV1_1().addInterface(ifaceInfo, - (SupplicantStatus status, ISupplicantIface iface) -> { - if (status.code != SupplicantStatusCode.SUCCESS - && status.code != SupplicantStatusCode.FAILURE_IFACE_EXISTS) { - Log.e(TAG, "Failed to create ISupplicantIface " + status.code); - return; - } - supplicantIface.value = iface; - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.addInterface exception: " + e); - handleRemoteException(e, "addInterface"); - return null; - } catch (NoSuchElementException e) { - Log.e(TAG, "ISupplicant.addInterface exception: " + e); - handleNoSuchElementException(e, "addInterface"); - return null; - } catch (IllegalArgumentException e) { - handleIllegalArgumentException(e, "addInterface"); - Log.e(TAG, "ISupplicant.addInterface exception: " + e); - return null; - } - return supplicantIface.value; - } - } - - /** - * Teardown a STA interface for the specified iface name. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - public boolean teardownIface(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "teardownIface"; - if (checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr) == null) return false; - if (isV1_1()) { - if (!removeIfaceV1_1(ifaceName)) { - Log.e(TAG, "Failed to remove iface = " + ifaceName); - return false; - } - } - if (mISupplicantStaIfaces.remove(ifaceName) == null) { - Log.e(TAG, "Trying to teardown unknown inteface"); - return false; - } - mISupplicantStaIfaceCallbacks.remove(ifaceName); - return true; - } - } - - /** - * Remove a STA interface for the specified iface name. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - private boolean removeIfaceV1_1(@NonNull String ifaceName) { - synchronized (mLock) { - try { - ISupplicant.IfaceInfo ifaceInfo = new ISupplicant.IfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.type = IfaceType.STA; - SupplicantStatus status = getSupplicantMockableV1_1().removeInterface(ifaceInfo); - if (status.code != SupplicantStatusCode.SUCCESS) { - Log.e(TAG, "Failed to remove iface " + status.code); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.removeInterface exception: " + e); - handleRemoteException(e, "removeInterface"); - return false; - } catch (NoSuchElementException e) { - Log.e(TAG, "ISupplicant.removeInterface exception: " + e); - handleNoSuchElementException(e, "removeInterface"); - return false; - } - return true; - } - } - - /** - * Registers a death notification for supplicant. - * @return Returns true on success. - */ - public boolean registerDeathHandler(@NonNull SupplicantDeathEventHandler handler) { - if (mDeathEventHandler != null) { - Log.e(TAG, "Death handler already present"); - } - mDeathEventHandler = handler; - return true; - } - - /** - * Deregisters a death notification for supplicant. - * @return Returns true on success. - */ - public boolean deregisterDeathHandler() { - if (mDeathEventHandler == null) { - Log.e(TAG, "No Death handler present"); - } - mDeathEventHandler = null; - return true; - } - - - private void clearState() { - synchronized (mLock) { - mISupplicant = null; - mISupplicantStaIfaces.clear(); - mCurrentNetworkLocalConfigs.clear(); - mCurrentNetworkRemoteHandles.clear(); - } - } - - private void supplicantServiceDiedHandler(long cookie) { - synchronized (mLock) { - if (mDeathRecipientCookie != cookie) { - Log.i(TAG, "Ignoring stale death recipient notification"); - return; - } - for (String ifaceName : mISupplicantStaIfaces.keySet()) { - mWifiMonitor.broadcastSupplicantDisconnectionEvent(ifaceName); - } - clearState(); - if (mDeathEventHandler != null) { - mDeathEventHandler.onDeath(); - } - } - } - - /** - * Signals whether Initialization completed successfully. - */ - public boolean isInitializationStarted() { - synchronized (mLock) { - return mIServiceManager != null; - } - } - - /** - * Signals whether Initialization completed successfully. - */ - public boolean isInitializationComplete() { - synchronized (mLock) { - return mISupplicant != null; - } - } - - - /** - * Start the supplicant daemon for V1_1 service. - * - * @return true on success, false otherwise. - */ - private boolean startDaemon_V1_1() { - synchronized (mLock) { - try { - // This should startup supplicant daemon using the lazy start HAL mechanism. - getSupplicantMockableV1_1(); - } catch (RemoteException e) { - Log.e(TAG, "Exception while trying to start supplicant: " - + e); - supplicantServiceDiedHandler(mDeathRecipientCookie); - return false; - } catch (NoSuchElementException e) { - // We're starting the daemon, so expect |NoSuchElementException|. - Log.d(TAG, "Successfully triggered start of supplicant using HIDL"); - } - return true; - } - } - - /** - * Start the supplicant daemon. - * - * @return true on success, false otherwise. - */ - public boolean startDaemon() { - synchronized (mLock) { - if (isV1_1()) { - Log.i(TAG, "Starting supplicant using HIDL"); - return startDaemon_V1_1(); - } else { - Log.i(TAG, "Starting supplicant using init"); - mFrameworkFacade.startSupplicant(); - return true; - } - } - } - - /** - * Terminate the supplicant daemon for V1_1 service. - */ - private void terminate_V1_1() { - synchronized (mLock) { - final String methodStr = "terminate"; - if (!checkSupplicantAndLogFailure(methodStr)) return; - try { - getSupplicantMockableV1_1().terminate(); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } catch (NoSuchElementException e) { - handleNoSuchElementException(e, methodStr); - } - } - } - - /** - * Terminate the supplicant daemon & wait for it's death. - */ - public void terminate() { - synchronized (mLock) { - // Register for a new death listener to block until supplicant is dead. - final long waitForDeathCookie = new Random().nextLong(); - final CountDownLatch waitForDeathLatch = new CountDownLatch(1); - linkToSupplicantDeath((cookie) -> { - Log.d(TAG, "ISupplicant died: cookie=" + cookie); - if (cookie != waitForDeathCookie) return; - waitForDeathLatch.countDown(); - }, waitForDeathCookie); - - if (isV1_1()) { - Log.i(TAG, "Terminating supplicant using HIDL"); - terminate_V1_1(); - } else { - Log.i(TAG, "Terminating supplicant using init"); - mFrameworkFacade.stopSupplicant(); - } - - // Now wait for death listener callback to confirm that it's dead. - try { - if (!waitForDeathLatch.await(WAIT_FOR_DEATH_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { - Log.w(TAG, "Timed out waiting for confirmation of supplicant death"); - } - } catch (InterruptedException e) { - Log.w(TAG, "Failed to wait for supplicant death"); - } - } - } - - /** - * Wrapper functions to access static HAL methods, created to be mockable in unit tests - */ - protected IServiceManager getServiceManagerMockable() throws RemoteException { - synchronized (mLock) { - return IServiceManager.getService(); - } - } - - protected ISupplicant getSupplicantMockable() throws RemoteException, NoSuchElementException { - synchronized (mLock) { - ISupplicant iSupplicant = ISupplicant.getService(); - if (iSupplicant == null) { - throw new NoSuchElementException("Cannot get root service."); - } - return iSupplicant; - } - } - - protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1() - throws RemoteException, NoSuchElementException { - synchronized (mLock) { - android.hardware.wifi.supplicant.V1_1.ISupplicant iSupplicantDerived = - android.hardware.wifi.supplicant.V1_1.ISupplicant.castFrom( - getSupplicantMockable()); - if (iSupplicantDerived == null) { - throw new NoSuchElementException("Cannot cast to V1.1 service."); - } - return iSupplicantDerived; - } - } - - protected android.hardware.wifi.supplicant.V1_2.ISupplicant getSupplicantMockableV1_2() - throws RemoteException, NoSuchElementException { - synchronized (mLock) { - android.hardware.wifi.supplicant.V1_2.ISupplicant iSupplicantDerived = - android.hardware.wifi.supplicant.V1_2.ISupplicant.castFrom( - getSupplicantMockable()); - if (iSupplicantDerived == null) { - throw new NoSuchElementException("Cannot cast to V1.1 service."); - } - return iSupplicantDerived; - } - } - - protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) { - synchronized (mLock) { - return ISupplicantStaIface.asInterface(iface.asBinder()); - } - } - - protected android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface - getStaIfaceMockableV1_1(ISupplicantIface iface) { - synchronized (mLock) { - return android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface - .asInterface(iface.asBinder()); - } - } - - protected android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - getStaIfaceMockableV1_2(ISupplicantIface iface) { - synchronized (mLock) { - return android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - .asInterface(iface.asBinder()); - } - } - - protected android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - getStaIfaceMockableV1_3(ISupplicantIface iface) { - synchronized (mLock) { - return android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .asInterface(iface.asBinder()); - } - } - - /** - * Uses the IServiceManager to check if the device is running V1_1 of the HAL from the VINTF for - * the device. - * @return true if supported, false otherwise. - */ - private boolean isV1_1() { - return checkHalVersionByInterfaceName( - android.hardware.wifi.supplicant.V1_1.ISupplicant.kInterfaceName); - } - - /** - * Uses the IServiceManager to check if the device is running V1_2 of the HAL from the VINTF for - * the device. - * @return true if supported, false otherwise. - */ - private boolean isV1_2() { - return checkHalVersionByInterfaceName( - android.hardware.wifi.supplicant.V1_2.ISupplicant.kInterfaceName); - } - - /** - * Uses the IServiceManager to check if the device is running V1_3 of the HAL from the VINTF for - * the device. - * @return true if supported, false otherwise. - */ - private boolean isV1_3() { - return checkHalVersionByInterfaceName( - android.hardware.wifi.supplicant.V1_3.ISupplicant.kInterfaceName); - } - - private boolean checkHalVersionByInterfaceName(String interfaceName) { - if (interfaceName == null) { - return false; - } - synchronized (mLock) { - if (mIServiceManager == null) { - Log.e(TAG, "checkHalVersionByInterfaceName: called but mServiceManager is null"); - return false; - } - try { - return (mIServiceManager.getTransport( - interfaceName, - HAL_INSTANCE_NAME) - != IServiceManager.Transport.EMPTY); - } catch (RemoteException e) { - Log.e(TAG, "Exception while operating on IServiceManager: " + e); - handleRemoteException(e, "getTransport"); - return false; - } - } - } - - /** - * Helper method to look up the network object for the specified iface. - */ - private ISupplicantStaIface getStaIface(@NonNull String ifaceName) { - return mISupplicantStaIfaces.get(ifaceName); - } - - /** - * Helper method to look up the network object for the specified iface. - */ - private SupplicantStaNetworkHal getCurrentNetworkRemoteHandle(@NonNull String ifaceName) { - return mCurrentNetworkRemoteHandles.get(ifaceName); - } - - /** - * Helper method to look up the network config or the specified iface. - */ - protected WifiConfiguration getCurrentNetworkLocalConfig(@NonNull String ifaceName) { - return mCurrentNetworkLocalConfigs.get(ifaceName); - } - - /** - * Add a network configuration to wpa_supplicant. - * - * @param config Config corresponding to the network. - * @return a Pair object including SupplicantStaNetworkHal and WifiConfiguration objects - * for the current network. - */ - private Pair<SupplicantStaNetworkHal, WifiConfiguration> - addNetworkAndSaveConfig(@NonNull String ifaceName, WifiConfiguration config) { - synchronized (mLock) { - logi("addSupplicantStaNetwork via HIDL"); - if (config == null) { - loge("Cannot add NULL network!"); - return null; - } - SupplicantStaNetworkHal network = addNetwork(ifaceName); - if (network == null) { - loge("Failed to add a network!"); - return null; - } - boolean saveSuccess = false; - try { - saveSuccess = network.saveWifiConfiguration(config); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Exception while saving config params: " + config, e); - } - if (!saveSuccess) { - loge("Failed to save variables for: " + config.getKey()); - if (!removeAllNetworks(ifaceName)) { - loge("Failed to remove all networks on failure."); - } - return null; - } - return new Pair(network, new WifiConfiguration(config)); - } - } - - /** - * Add the provided network configuration to wpa_supplicant and initiate connection to it. - * This method does the following: - * 1. If |config| is different to the current supplicant network, removes all supplicant - * networks and saves |config|. - * 2. Select the new network in wpa_supplicant. - * - * @param ifaceName Name of the interface. - * @param config WifiConfiguration parameters for the provided network. - * @return {@code true} if it succeeds, {@code false} otherwise - */ - public boolean connectToNetwork(@NonNull String ifaceName, @NonNull WifiConfiguration config) { - synchronized (mLock) { - logd("connectToNetwork " + config.getKey()); - WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName); - if (WifiConfigurationUtil.isSameNetwork(config, currentConfig)) { - String networkSelectionBSSID = config.getNetworkSelectionStatus() - .getNetworkSelectionBSSID(); - String networkSelectionBSSIDCurrent = - currentConfig.getNetworkSelectionStatus().getNetworkSelectionBSSID(); - if (Objects.equals(networkSelectionBSSID, networkSelectionBSSIDCurrent)) { - logd("Network is already saved, will not trigger remove and add operation."); - } else { - logd("Network is already saved, but need to update BSSID."); - if (!setCurrentNetworkBssid( - ifaceName, - config.getNetworkSelectionStatus().getNetworkSelectionBSSID())) { - loge("Failed to set current network BSSID."); - return false; - } - mCurrentNetworkLocalConfigs.put(ifaceName, new WifiConfiguration(config)); - } - } else { - mCurrentNetworkRemoteHandles.remove(ifaceName); - mCurrentNetworkLocalConfigs.remove(ifaceName); - if (!removeAllNetworks(ifaceName)) { - loge("Failed to remove existing networks"); - return false; - } - Pair<SupplicantStaNetworkHal, WifiConfiguration> pair = - addNetworkAndSaveConfig(ifaceName, config); - if (pair == null) { - loge("Failed to add/save network configuration: " + config.getKey()); - return false; - } - mCurrentNetworkRemoteHandles.put(ifaceName, pair.first); - mCurrentNetworkLocalConfigs.put(ifaceName, pair.second); - } - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure(ifaceName, "connectToNetwork"); - if (networkHandle == null) { - loge("No valid remote network handle for network configuration: " - + config.getKey()); - return false; - } - - PmkCacheStoreData pmkData = mPmkCacheEntries.get(config.networkId); - if (pmkData != null - && !WifiConfigurationUtil.isConfigForPskNetwork(config) - && pmkData.expirationTimeInSec > mClock.getElapsedSinceBootMillis() / 1000) { - logi("Set PMK cache for config id " + config.networkId); - if (networkHandle.setPmkCache(pmkData.data)) { - mWifiMetrics.setConnectionPmkCache(true); - } - } - - if (!networkHandle.select()) { - loge("Failed to select network configuration: " + config.getKey()); - return false; - } - return true; - } - } - - /** - * Initiates roaming to the already configured network in wpa_supplicant. If the network - * configuration provided does not match the already configured network, then this triggers - * a new connection attempt (instead of roam). - * 1. First check if we're attempting to connect to the same network as we currently have - * configured. - * 2. Set the new bssid for the network in wpa_supplicant. - * 3. Trigger reassociate command to wpa_supplicant. - * - * @param ifaceName Name of the interface. - * @param config WifiConfiguration parameters for the provided network. - * @return {@code true} if it succeeds, {@code false} otherwise - */ - public boolean roamToNetwork(@NonNull String ifaceName, WifiConfiguration config) { - synchronized (mLock) { - if (getCurrentNetworkId(ifaceName) != config.networkId) { - Log.w(TAG, "Cannot roam to a different network, initiate new connection. " - + "Current network ID: " + getCurrentNetworkId(ifaceName)); - return connectToNetwork(ifaceName, config); - } - String bssid = config.getNetworkSelectionStatus().getNetworkSelectionBSSID(); - logd("roamToNetwork" + config.getKey() + " (bssid " + bssid + ")"); - - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure(ifaceName, "roamToNetwork"); - if (networkHandle == null || !networkHandle.setBssid(bssid)) { - loge("Failed to set new bssid on network: " + config.getKey()); - return false; - } - if (!reassociate(ifaceName)) { - loge("Failed to trigger reassociate"); - return false; - } - return true; - } - } - - /** - * Clean HAL cached data for |networkId| in the framework. - * - * @param networkId network id of the network to be removed from supplicant. - */ - public void removeNetworkCachedData(int networkId) { - synchronized (mLock) { - logd("Remove cached HAL data for config id " + networkId); - removePmkCacheEntry(networkId); - } - } - - /** - * Clear HAL cached data if MAC address is changed. - * - * @param networkId network id of the network to be checked. - * @param curMacAddress current MAC address - */ - public void removeNetworkCachedDataIfNeeded(int networkId, MacAddress curMacAddress) { - synchronized (mLock) { - PmkCacheStoreData pmkData = mPmkCacheEntries.get(networkId); - - if (pmkData == null) return; - - if (curMacAddress.equals(pmkData.macAddress)) return; - - removeNetworkCachedData(networkId); - } - } - - /** - * Remove all networks from supplicant - * - * @param ifaceName Name of the interface. - */ - public boolean removeAllNetworks(@NonNull String ifaceName) { - synchronized (mLock) { - ArrayList<Integer> networks = listNetworks(ifaceName); - if (networks == null) { - Log.e(TAG, "removeAllNetworks failed, got null networks"); - return false; - } - for (int id : networks) { - if (!removeNetwork(ifaceName, id)) { - Log.e(TAG, "removeAllNetworks failed to remove network: " + id); - return false; - } - } - // Reset current network info. Probably not needed once we add support to remove/reset - // current network on receiving disconnection event from supplicant (b/32898136). - mCurrentNetworkRemoteHandles.remove(ifaceName); - mCurrentNetworkLocalConfigs.remove(ifaceName); - return true; - } - } - - /** - * Set the currently configured network's bssid. - * - * @param ifaceName Name of the interface. - * @param bssidStr Bssid to set in the form of "XX:XX:XX:XX:XX:XX" - * @return true if succeeds, false otherwise. - */ - public boolean setCurrentNetworkBssid(@NonNull String ifaceName, String bssidStr) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure(ifaceName, "setCurrentNetworkBssid"); - if (networkHandle == null) return false; - return networkHandle.setBssid(bssidStr); - } - } - - /** - * Get the currently configured network's WPS NFC token. - * - * @param ifaceName Name of the interface. - * @return Hex string corresponding to the WPS NFC token. - */ - public String getCurrentNetworkWpsNfcConfigurationToken(@NonNull String ifaceName) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure( - ifaceName, "getCurrentNetworkWpsNfcConfigurationToken"); - if (networkHandle == null) return null; - return networkHandle.getWpsNfcConfigurationToken(); - } - } - - /** - * Get the eap anonymous identity for the currently configured network. - * - * @param ifaceName Name of the interface. - * @return anonymous identity string if succeeds, null otherwise. - */ - public String getCurrentNetworkEapAnonymousIdentity(@NonNull String ifaceName) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure( - ifaceName, "getCurrentNetworkEapAnonymousIdentity"); - if (networkHandle == null) return null; - return networkHandle.fetchEapAnonymousIdentity(); - } - } - - /** - * Send the eap identity response for the currently configured network. - * - * @param ifaceName Name of the interface. - * @param identity identity used for EAP-Identity - * @param encryptedIdentity encrypted identity used for EAP-AKA/EAP-SIM - * @return true if succeeds, false otherwise. - */ - public boolean sendCurrentNetworkEapIdentityResponse( - @NonNull String ifaceName, @NonNull String identity, String encryptedIdentity) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure( - ifaceName, "sendCurrentNetworkEapIdentityResponse"); - if (networkHandle == null) return false; - return networkHandle.sendNetworkEapIdentityResponse(identity, encryptedIdentity); - } - } - - /** - * Send the eap sim gsm auth response for the currently configured network. - * - * @param ifaceName Name of the interface. - * @param paramsStr String to send. - * @return true if succeeds, false otherwise. - */ - public boolean sendCurrentNetworkEapSimGsmAuthResponse( - @NonNull String ifaceName, String paramsStr) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure( - ifaceName, "sendCurrentNetworkEapSimGsmAuthResponse"); - if (networkHandle == null) return false; - return networkHandle.sendNetworkEapSimGsmAuthResponse(paramsStr); - } - } - - /** - * Send the eap sim gsm auth failure for the currently configured network. - * - * @param ifaceName Name of the interface. - * @return true if succeeds, false otherwise. - */ - public boolean sendCurrentNetworkEapSimGsmAuthFailure(@NonNull String ifaceName) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure( - ifaceName, "sendCurrentNetworkEapSimGsmAuthFailure"); - if (networkHandle == null) return false; - return networkHandle.sendNetworkEapSimGsmAuthFailure(); - } - } - - /** - * Send the eap sim umts auth response for the currently configured network. - * - * @param ifaceName Name of the interface. - * @param paramsStr String to send. - * @return true if succeeds, false otherwise. - */ - public boolean sendCurrentNetworkEapSimUmtsAuthResponse( - @NonNull String ifaceName, String paramsStr) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure( - ifaceName, "sendCurrentNetworkEapSimUmtsAuthResponse"); - if (networkHandle == null) return false; - return networkHandle.sendNetworkEapSimUmtsAuthResponse(paramsStr); - } - } - - /** - * Send the eap sim umts auts response for the currently configured network. - * - * @param ifaceName Name of the interface. - * @param paramsStr String to send. - * @return true if succeeds, false otherwise. - */ - public boolean sendCurrentNetworkEapSimUmtsAutsResponse( - @NonNull String ifaceName, String paramsStr) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure( - ifaceName, "sendCurrentNetworkEapSimUmtsAutsResponse"); - if (networkHandle == null) return false; - return networkHandle.sendNetworkEapSimUmtsAutsResponse(paramsStr); - } - } - - /** - * Send the eap sim umts auth failure for the currently configured network. - * - * @param ifaceName Name of the interface. - * @return true if succeeds, false otherwise. - */ - public boolean sendCurrentNetworkEapSimUmtsAuthFailure(@NonNull String ifaceName) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHandle = - checkSupplicantStaNetworkAndLogFailure( - ifaceName, "sendCurrentNetworkEapSimUmtsAuthFailure"); - if (networkHandle == null) return false; - return networkHandle.sendNetworkEapSimUmtsAuthFailure(); - } - } - - /** - * Adds a new network. - * - * @return The ISupplicantNetwork object for the new network, or null if the call fails - */ - private SupplicantStaNetworkHal addNetwork(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "addNetwork"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return null; - Mutable<ISupplicantNetwork> newNetwork = new Mutable<>(); - try { - iface.addNetwork((SupplicantStatus status, - ISupplicantNetwork network) -> { - if (checkStatusAndLogFailure(status, methodStr)) { - newNetwork.value = network; - } - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - if (newNetwork.value != null) { - return getStaNetworkMockable( - ifaceName, - ISupplicantStaNetwork.asInterface(newNetwork.value.asBinder())); - } else { - return null; - } - } - } - - /** - * Remove network from supplicant with network Id - * - * @return true if request is sent successfully, false otherwise. - */ - private boolean removeNetwork(@NonNull String ifaceName, int id) { - synchronized (mLock) { - final String methodStr = "removeNetwork"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.removeNetwork(id); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Use this to mock the creation of SupplicantStaNetworkHal instance. - * - * @param ifaceName Name of the interface. - * @param iSupplicantStaNetwork ISupplicantStaNetwork instance retrieved from HIDL. - * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if - * the call fails - */ - protected SupplicantStaNetworkHal getStaNetworkMockable( - @NonNull String ifaceName, ISupplicantStaNetwork iSupplicantStaNetwork) { - synchronized (mLock) { - SupplicantStaNetworkHal network = - new SupplicantStaNetworkHal(iSupplicantStaNetwork, ifaceName, mContext, - mWifiMonitor); - if (network != null) { - network.enableVerboseLogging(mVerboseLoggingEnabled); - } - return network; - } - } - - /** - * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if - * the call fails - */ - private SupplicantStaNetworkHal getNetwork(@NonNull String ifaceName, int id) { - synchronized (mLock) { - final String methodStr = "getNetwork"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return null; - Mutable<ISupplicantNetwork> gotNetwork = new Mutable<>(); - try { - iface.getNetwork(id, (SupplicantStatus status, ISupplicantNetwork network) -> { - if (checkStatusAndLogFailure(status, methodStr)) { - gotNetwork.value = network; - } - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - if (gotNetwork.value != null) { - return getStaNetworkMockable( - ifaceName, - ISupplicantStaNetwork.asInterface(gotNetwork.value.asBinder())); - } else { - return null; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean registerCallback( - ISupplicantStaIface iface, ISupplicantStaIfaceCallback callback) { - synchronized (mLock) { - final String methodStr = "registerCallback"; - if (iface == null) return false; - try { - SupplicantStatus status = iface.registerCallback(callback); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - private boolean registerCallbackV1_1( - android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface iface, - android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback callback) { - synchronized (mLock) { - String methodStr = "registerCallback_1_1"; - - if (iface == null) return false; - try { - SupplicantStatus status = iface.registerCallback_1_1(callback); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - private boolean registerCallbackV1_2( - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface iface, - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback callback) { - synchronized (mLock) { - String methodStr = "registerCallback_1_2"; - - if (iface == null) return false; - try { - SupplicantStatus status = iface.registerCallback_1_2(callback); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - private boolean registerCallbackV1_3( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface iface, - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback callback) { - synchronized (mLock) { - String methodStr = "registerCallback_1_3"; - - if (iface == null) return false; - try { - SupplicantStatus status = iface.registerCallback_1_3(callback); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns - * null if the call fails - */ - private java.util.ArrayList<Integer> listNetworks(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "listNetworks"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return null; - Mutable<ArrayList<Integer>> networkIdList = new Mutable<>(); - try { - iface.listNetworks((SupplicantStatus status, ArrayList<Integer> networkIds) -> { - if (checkStatusAndLogFailure(status, methodStr)) { - networkIdList.value = networkIds; - } - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - return networkIdList.value; - } - } - - /** - * Set WPS device name. - * - * @param ifaceName Name of the interface. - * @param name String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsDeviceName(@NonNull String ifaceName, String name) { - synchronized (mLock) { - final String methodStr = "setWpsDeviceName"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setWpsDeviceName(name); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set WPS device type. - * - * @param ifaceName Name of the interface. - * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg> - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsDeviceType(@NonNull String ifaceName, String typeStr) { - synchronized (mLock) { - try { - Matcher match = WPS_DEVICE_TYPE_PATTERN.matcher(typeStr); - if (!match.find() || match.groupCount() != 3) { - Log.e(TAG, "Malformed WPS device type " + typeStr); - return false; - } - short categ = Short.parseShort(match.group(1)); - byte[] oui = NativeUtil.hexStringToByteArray(match.group(2)); - short subCateg = Short.parseShort(match.group(3)); - - byte[] bytes = new byte[8]; - ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); - byteBuffer.putShort(categ); - byteBuffer.put(oui); - byteBuffer.putShort(subCateg); - return setWpsDeviceType(ifaceName, bytes); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + typeStr, e); - return false; - } - } - } - - private boolean setWpsDeviceType(@NonNull String ifaceName, byte[/* 8 */] type) { - synchronized (mLock) { - final String methodStr = "setWpsDeviceType"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setWpsDeviceType(type); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set WPS manufacturer. - * - * @param ifaceName Name of the interface. - * @param manufacturer String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsManufacturer(@NonNull String ifaceName, String manufacturer) { - synchronized (mLock) { - final String methodStr = "setWpsManufacturer"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setWpsManufacturer(manufacturer); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set WPS model name. - * - * @param ifaceName Name of the interface. - * @param modelName String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsModelName(@NonNull String ifaceName, String modelName) { - synchronized (mLock) { - final String methodStr = "setWpsModelName"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setWpsModelName(modelName); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set WPS model number. - * - * @param ifaceName Name of the interface. - * @param modelNumber String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsModelNumber(@NonNull String ifaceName, String modelNumber) { - synchronized (mLock) { - final String methodStr = "setWpsModelNumber"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setWpsModelNumber(modelNumber); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set WPS serial number. - * - * @param ifaceName Name of the interface. - * @param serialNumber String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsSerialNumber(@NonNull String ifaceName, String serialNumber) { - synchronized (mLock) { - final String methodStr = "setWpsSerialNumber"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setWpsSerialNumber(serialNumber); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set WPS config methods - * - * @param ifaceName Name of the interface. - * @param configMethodsStr List of config methods. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsConfigMethods(@NonNull String ifaceName, String configMethodsStr) { - synchronized (mLock) { - short configMethodsMask = 0; - String[] configMethodsStrArr = configMethodsStr.split("\\s+"); - for (int i = 0; i < configMethodsStrArr.length; i++) { - configMethodsMask |= stringToWpsConfigMethod(configMethodsStrArr[i]); - } - return setWpsConfigMethods(ifaceName, configMethodsMask); - } - } - - private boolean setWpsConfigMethods(@NonNull String ifaceName, short configMethods) { - synchronized (mLock) { - final String methodStr = "setWpsConfigMethods"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setWpsConfigMethods(configMethods); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Trigger a reassociation even if the iface is currently connected. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean reassociate(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "reassociate"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.reassociate(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Trigger a reconnection if the iface is disconnected. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean reconnect(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "reconnect"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.reconnect(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Trigger a disconnection from the currently connected network. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean disconnect(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "disconnect"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.disconnect(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Enable or disable power save mode. - * - * @param ifaceName Name of the interface. - * @param enable true to enable, false to disable. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setPowerSave(@NonNull String ifaceName, boolean enable) { - synchronized (mLock) { - final String methodStr = "setPowerSave"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setPowerSave(enable); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Initiate TDLS discover with the specified AP. - * - * @param ifaceName Name of the interface. - * @param macAddress MAC Address of the AP. - * @return true if request is sent successfully, false otherwise. - */ - public boolean initiateTdlsDiscover(@NonNull String ifaceName, String macAddress) { - synchronized (mLock) { - try { - return initiateTdlsDiscover( - ifaceName, NativeUtil.macAddressToByteArray(macAddress)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + macAddress, e); - return false; - } - } - } - /** See ISupplicantStaIface.hal for documentation */ - private boolean initiateTdlsDiscover(@NonNull String ifaceName, byte[/* 6 */] macAddress) { - synchronized (mLock) { - final String methodStr = "initiateTdlsDiscover"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.initiateTdlsDiscover(macAddress); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Initiate TDLS setup with the specified AP. - * - * @param ifaceName Name of the interface. - * @param macAddress MAC Address of the AP. - * @return true if request is sent successfully, false otherwise. - */ - public boolean initiateTdlsSetup(@NonNull String ifaceName, String macAddress) { - synchronized (mLock) { - try { - return initiateTdlsSetup(ifaceName, NativeUtil.macAddressToByteArray(macAddress)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + macAddress, e); - return false; - } - } - } - /** See ISupplicantStaIface.hal for documentation */ - private boolean initiateTdlsSetup(@NonNull String ifaceName, byte[/* 6 */] macAddress) { - synchronized (mLock) { - final String methodStr = "initiateTdlsSetup"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.initiateTdlsSetup(macAddress); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Initiate TDLS teardown with the specified AP. - * @param ifaceName Name of the interface. - * @param macAddress MAC Address of the AP. - * @return true if request is sent successfully, false otherwise. - */ - public boolean initiateTdlsTeardown(@NonNull String ifaceName, String macAddress) { - synchronized (mLock) { - try { - return initiateTdlsTeardown( - ifaceName, NativeUtil.macAddressToByteArray(macAddress)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + macAddress, e); - return false; - } - } - } - - /** See ISupplicantStaIface.hal for documentation */ - private boolean initiateTdlsTeardown(@NonNull String ifaceName, byte[/* 6 */] macAddress) { - synchronized (mLock) { - final String methodStr = "initiateTdlsTeardown"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.initiateTdlsTeardown(macAddress); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Request the specified ANQP elements |elements| from the specified AP |bssid|. - * - * @param ifaceName Name of the interface. - * @param bssid BSSID of the AP - * @param infoElements ANQP elements to be queried. Refer to ISupplicantStaIface.AnqpInfoId. - * @param hs20SubTypes HS subtypes to be queried. Refer to ISupplicantStaIface.Hs20AnqpSubTypes. - * @return true if request is sent successfully, false otherwise. - */ - public boolean initiateAnqpQuery(@NonNull String ifaceName, String bssid, - ArrayList<Short> infoElements, - ArrayList<Integer> hs20SubTypes) { - synchronized (mLock) { - try { - return initiateAnqpQuery( - ifaceName, - NativeUtil.macAddressToByteArray(bssid), infoElements, hs20SubTypes); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + bssid, e); - return false; - } - } - } - - /** See ISupplicantStaIface.hal for documentation */ - private boolean initiateAnqpQuery(@NonNull String ifaceName, byte[/* 6 */] macAddress, - java.util.ArrayList<Short> infoElements, java.util.ArrayList<Integer> subTypes) { - synchronized (mLock) { - final String methodStr = "initiateAnqpQuery"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.initiateAnqpQuery( - macAddress, infoElements, subTypes); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Request the specified ANQP ICON from the specified AP |bssid|. - * - * @param ifaceName Name of the interface. - * @param bssid BSSID of the AP - * @param fileName Name of the file to request. - * @return true if request is sent successfully, false otherwise. - */ - public boolean initiateHs20IconQuery(@NonNull String ifaceName, String bssid, String fileName) { - synchronized (mLock) { - try { - return initiateHs20IconQuery( - ifaceName, NativeUtil.macAddressToByteArray(bssid), fileName); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + bssid, e); - return false; - } - } - } - - /** See ISupplicantStaIface.hal for documentation */ - private boolean initiateHs20IconQuery(@NonNull String ifaceName, - byte[/* 6 */] macAddress, String fileName) { - synchronized (mLock) { - final String methodStr = "initiateHs20IconQuery"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.initiateHs20IconQuery(macAddress, fileName); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Makes a callback to HIDL to getMacAddress from supplicant - * - * @param ifaceName Name of the interface. - * @return string containing the MAC address, or null on a failed call - */ - public String getMacAddress(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "getMacAddress"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return null; - Mutable<String> gotMac = new Mutable<>(); - try { - iface.getMacAddress((SupplicantStatus status, - byte[/* 6 */] macAddr) -> { - if (checkStatusAndLogFailure(status, methodStr)) { - gotMac.value = NativeUtil.macAddressFromByteArray(macAddr); - } - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - return gotMac.value; - } - } - - /** - * Start using the added RX filters. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean startRxFilter(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "startRxFilter"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.startRxFilter(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Stop using the added RX filters. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean stopRxFilter(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "stopRxFilter"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.stopRxFilter(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Add an RX filter. - * - * @param ifaceName Name of the interface. - * @param type one of {@link WifiNative#RX_FILTER_TYPE_V4_MULTICAST} - * {@link WifiNative#RX_FILTER_TYPE_V6_MULTICAST} values. - * @return true if request is sent successfully, false otherwise. - */ - public boolean addRxFilter(@NonNull String ifaceName, int type) { - synchronized (mLock) { - byte halType; - switch (type) { - case WifiNative.RX_FILTER_TYPE_V4_MULTICAST: - halType = ISupplicantStaIface.RxFilterType.V4_MULTICAST; - break; - case WifiNative.RX_FILTER_TYPE_V6_MULTICAST: - halType = ISupplicantStaIface.RxFilterType.V6_MULTICAST; - break; - default: - Log.e(TAG, "Invalid Rx Filter type: " + type); - return false; - } - return addRxFilter(ifaceName, halType); - } - } - - private boolean addRxFilter(@NonNull String ifaceName, byte type) { - synchronized (mLock) { - final String methodStr = "addRxFilter"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.addRxFilter(type); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Remove an RX filter. - * - * @param ifaceName Name of the interface. - * @param type one of {@link WifiNative#RX_FILTER_TYPE_V4_MULTICAST} - * {@link WifiNative#RX_FILTER_TYPE_V6_MULTICAST} values. - * @return true if request is sent successfully, false otherwise. - */ - public boolean removeRxFilter(@NonNull String ifaceName, int type) { - synchronized (mLock) { - byte halType; - switch (type) { - case WifiNative.RX_FILTER_TYPE_V4_MULTICAST: - halType = ISupplicantStaIface.RxFilterType.V4_MULTICAST; - break; - case WifiNative.RX_FILTER_TYPE_V6_MULTICAST: - halType = ISupplicantStaIface.RxFilterType.V6_MULTICAST; - break; - default: - Log.e(TAG, "Invalid Rx Filter type: " + type); - return false; - } - return removeRxFilter(ifaceName, halType); - } - } - - private boolean removeRxFilter(@NonNull String ifaceName, byte type) { - synchronized (mLock) { - final String methodStr = "removeRxFilter"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.removeRxFilter(type); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set Bt co existense mode. - * - * @param ifaceName Name of the interface. - * @param mode one of the above {@link WifiNative#BLUETOOTH_COEXISTENCE_MODE_DISABLED}, - * {@link WifiNative#BLUETOOTH_COEXISTENCE_MODE_ENABLED} or - * {@link WifiNative#BLUETOOTH_COEXISTENCE_MODE_SENSE}. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setBtCoexistenceMode(@NonNull String ifaceName, int mode) { - synchronized (mLock) { - byte halMode; - switch (mode) { - case WifiNative.BLUETOOTH_COEXISTENCE_MODE_ENABLED: - halMode = ISupplicantStaIface.BtCoexistenceMode.ENABLED; - break; - case WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED: - halMode = ISupplicantStaIface.BtCoexistenceMode.DISABLED; - break; - case WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE: - halMode = ISupplicantStaIface.BtCoexistenceMode.SENSE; - break; - default: - Log.e(TAG, "Invalid Bt Coex mode: " + mode); - return false; - } - return setBtCoexistenceMode(ifaceName, halMode); - } - } - - private boolean setBtCoexistenceMode(@NonNull String ifaceName, byte mode) { - synchronized (mLock) { - final String methodStr = "setBtCoexistenceMode"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setBtCoexistenceMode(mode); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** Enable or disable BT coexistence mode. - * - * @param ifaceName Name of the interface. - * @param enable true to enable, false to disable. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setBtCoexistenceScanModeEnabled(@NonNull String ifaceName, boolean enable) { - synchronized (mLock) { - final String methodStr = "setBtCoexistenceScanModeEnabled"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = - iface.setBtCoexistenceScanModeEnabled(enable); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Enable or disable suspend mode optimizations. - * - * @param ifaceName Name of the interface. - * @param enable true to enable, false otherwise. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setSuspendModeEnabled(@NonNull String ifaceName, boolean enable) { - synchronized (mLock) { - final String methodStr = "setSuspendModeEnabled"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setSuspendModeEnabled(enable); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set country code. - * - * @param ifaceName Name of the interface. - * @param codeStr 2 byte ASCII string. For ex: US, CA. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setCountryCode(@NonNull String ifaceName, String codeStr) { - synchronized (mLock) { - if (TextUtils.isEmpty(codeStr)) return false; - byte[] countryCodeBytes = NativeUtil.stringToByteArray(codeStr); - if (countryCodeBytes.length != 2) return false; - return setCountryCode(ifaceName, countryCodeBytes); - } - } - - /** See ISupplicantStaIface.hal for documentation */ - private boolean setCountryCode(@NonNull String ifaceName, byte[/* 2 */] code) { - synchronized (mLock) { - final String methodStr = "setCountryCode"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setCountryCode(code); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Flush all previously configured HLPs. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean flushAllHlp(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "filsHlpFlushRequest"; - if (isV1_3()) { - ISupplicantStaIface iface = - checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return false; - } - - // Get a v1.3 supplicant STA Interface - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 = - getStaIfaceMockableV1_3(iface); - - if (staIfaceV13 == null) { - Log.e(TAG, methodStr - + ": ISupplicantStaIface is null, cannot flushAllHlp"); - return false; - } - try { - SupplicantStatus status = staIfaceV13.filsHlpFlushRequest(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } else { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return false; - } - } - } - - /** - * Set FILS HLP packet. - * - * @param ifaceName Name of the interface. - * @param dst Destination MAC address. - * @param hlpPacket Hlp Packet data in hex. - * @return true if request is sent successfully, false otherwise. - */ - public boolean addHlpReq(@NonNull String ifaceName, byte [] dst, byte [] hlpPacket) { - synchronized (mLock) { - final String methodStr = "filsHlpAddRequest"; - if (isV1_3()) { - ISupplicantStaIface iface = - checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return false; - } - - // Get a v1.3 supplicant STA Interface - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 = - getStaIfaceMockableV1_3(iface); - - if (staIfaceV13 == null) { - Log.e(TAG, methodStr - + ": ISupplicantStaIface is null, cannot addHlpReq"); - return false; - } - try { - ArrayList<Byte> payload = NativeUtil.byteArrayToArrayList(hlpPacket); - SupplicantStatus status = staIfaceV13.filsHlpAddRequest(dst, payload); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } else { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return false; - } - } - } - - - /** - * Start WPS pin registrar operation with the specified peer and pin. - * - * @param ifaceName Name of the interface. - * @param bssidStr BSSID of the peer. - * @param pin Pin to be used. - * @return true if request is sent successfully, false otherwise. - */ - public boolean startWpsRegistrar(@NonNull String ifaceName, String bssidStr, String pin) { - synchronized (mLock) { - if (TextUtils.isEmpty(bssidStr) || TextUtils.isEmpty(pin)) return false; - try { - return startWpsRegistrar( - ifaceName, NativeUtil.macAddressToByteArray(bssidStr), pin); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + bssidStr, e); - return false; - } - } - } - - /** See ISupplicantStaIface.hal for documentation */ - private boolean startWpsRegistrar(@NonNull String ifaceName, byte[/* 6 */] bssid, String pin) { - synchronized (mLock) { - final String methodStr = "startWpsRegistrar"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.startWpsRegistrar(bssid, pin); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Start WPS pin display operation with the specified peer. - * - * @param ifaceName Name of the interface. - * @param bssidStr BSSID of the peer. Use empty bssid to indicate wildcard. - * @return true if request is sent successfully, false otherwise. - */ - public boolean startWpsPbc(@NonNull String ifaceName, String bssidStr) { - synchronized (mLock) { - try { - return startWpsPbc(ifaceName, NativeUtil.macAddressToByteArray(bssidStr)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + bssidStr, e); - return false; - } - } - } - - /** See ISupplicantStaIface.hal for documentation */ - private boolean startWpsPbc(@NonNull String ifaceName, byte[/* 6 */] bssid) { - synchronized (mLock) { - final String methodStr = "startWpsPbc"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.startWpsPbc(bssid); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Start WPS pin keypad operation with the specified pin. - * - * @param ifaceName Name of the interface. - * @param pin Pin to be used. - * @return true if request is sent successfully, false otherwise. - */ - public boolean startWpsPinKeypad(@NonNull String ifaceName, String pin) { - if (TextUtils.isEmpty(pin)) return false; - synchronized (mLock) { - final String methodStr = "startWpsPinKeypad"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.startWpsPinKeypad(pin); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Start WPS pin display operation with the specified peer. - * - * @param ifaceName Name of the interface. - * @param bssidStr BSSID of the peer. Use empty bssid to indicate wildcard. - * @return new pin generated on success, null otherwise. - */ - public String startWpsPinDisplay(@NonNull String ifaceName, String bssidStr) { - synchronized (mLock) { - try { - return startWpsPinDisplay(ifaceName, NativeUtil.macAddressToByteArray(bssidStr)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + bssidStr, e); - return null; - } - } - } - - /** See ISupplicantStaIface.hal for documentation */ - private String startWpsPinDisplay(@NonNull String ifaceName, byte[/* 6 */] bssid) { - synchronized (mLock) { - final String methodStr = "startWpsPinDisplay"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return null; - final Mutable<String> gotPin = new Mutable<>(); - try { - iface.startWpsPinDisplay(bssid, - (SupplicantStatus status, String pin) -> { - if (checkStatusAndLogFailure(status, methodStr)) { - gotPin.value = pin; - } - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - return gotPin.value; - } - } - - /** - * Cancels any ongoing WPS requests. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean cancelWps(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "cancelWps"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.cancelWps(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Sets whether to use external sim for SIM/USIM processing. - * - * @param ifaceName Name of the interface. - * @param useExternalSim true to enable, false otherwise. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setExternalSim(@NonNull String ifaceName, boolean useExternalSim) { - synchronized (mLock) { - final String methodStr = "setExternalSim"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.setExternalSim(useExternalSim); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicant.hal for documentation */ - public boolean enableAutoReconnect(@NonNull String ifaceName, boolean enable) { - synchronized (mLock) { - final String methodStr = "enableAutoReconnect"; - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) return false; - try { - SupplicantStatus status = iface.enableAutoReconnect(enable); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set the debug log level for wpa_supplicant - * - * @param turnOnVerbose Whether to turn on verbose logging or not. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setLogLevel(boolean turnOnVerbose) { - synchronized (mLock) { - int logLevel = turnOnVerbose - ? ISupplicant.DebugLevel.DEBUG - : ISupplicant.DebugLevel.INFO; - return setDebugParams(logLevel, false, false); - } - } - - /** See ISupplicant.hal for documentation */ - private boolean setDebugParams(int level, boolean showTimestamp, boolean showKeys) { - synchronized (mLock) { - final String methodStr = "setDebugParams"; - if (!checkSupplicantAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = - mISupplicant.setDebugParams(level, showTimestamp, showKeys); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set concurrency priority between P2P & STA operations. - * - * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, - * false otherwise. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setConcurrencyPriority(boolean isStaHigherPriority) { - synchronized (mLock) { - if (isStaHigherPriority) { - return setConcurrencyPriority(IfaceType.STA); - } else { - return setConcurrencyPriority(IfaceType.P2P); - } - } - } - - /** See ISupplicant.hal for documentation */ - private boolean setConcurrencyPriority(int type) { - synchronized (mLock) { - final String methodStr = "setConcurrencyPriority"; - if (!checkSupplicantAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicant.setConcurrencyPriority(type); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Returns false if Supplicant is null, and logs failure to call methodStr - */ - private boolean checkSupplicantAndLogFailure(final String methodStr) { - synchronized (mLock) { - if (mISupplicant == null) { - Log.e(TAG, "Can't call " + methodStr + ", ISupplicant is null"); - return false; - } - return true; - } - } - - /** - * Returns false if SupplicantStaIface is null, and logs failure to call methodStr - */ - private ISupplicantStaIface checkSupplicantStaIfaceAndLogFailure( - @NonNull String ifaceName, final String methodStr) { - synchronized (mLock) { - ISupplicantStaIface iface = getStaIface(ifaceName); - if (iface == null) { - Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaIface is null"); - return null; - } - return iface; - } - } - - /** - * Returns false if SupplicantStaNetwork is null, and logs failure to call methodStr - */ - private SupplicantStaNetworkHal checkSupplicantStaNetworkAndLogFailure( - @NonNull String ifaceName, final String methodStr) { - synchronized (mLock) { - SupplicantStaNetworkHal networkHal = getCurrentNetworkRemoteHandle(ifaceName); - if (networkHal == null) { - Log.e(TAG, "Can't call " + methodStr + ", SupplicantStaNetwork is null"); - return null; - } - return networkHal; - } - } - - /** - * Returns true if provided status code is SUCCESS, logs debug message and returns false - * otherwise - */ - private boolean checkStatusAndLogFailure(SupplicantStatus status, - final String methodStr) { - synchronized (mLock) { - if (status == null || status.code != SupplicantStatusCode.SUCCESS) { - Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed: " + status); - return false; - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "ISupplicantStaIface." + methodStr + " succeeded"); - } - return true; - } - } - } - - /** - * Helper function to log callbacks. - */ - protected void logCallback(final String methodStr) { - synchronized (mLock) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "ISupplicantStaIfaceCallback." + methodStr + " received"); - } - } - } - - private void handleNoSuchElementException(NoSuchElementException e, String methodStr) { - synchronized (mLock) { - clearState(); - Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e); - } - } - - private void handleRemoteException(RemoteException e, String methodStr) { - synchronized (mLock) { - clearState(); - Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e); - } - } - - private void handleIllegalArgumentException(IllegalArgumentException e, String methodStr) { - synchronized (mLock) { - clearState(); - Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e); - } - } - - /** - * Converts the Wps config method string to the equivalent enum value. - */ - private static short stringToWpsConfigMethod(String configMethod) { - switch (configMethod) { - case "usba": - return WpsConfigMethods.USBA; - case "ethernet": - return WpsConfigMethods.ETHERNET; - case "label": - return WpsConfigMethods.LABEL; - case "display": - return WpsConfigMethods.DISPLAY; - case "int_nfc_token": - return WpsConfigMethods.INT_NFC_TOKEN; - case "ext_nfc_token": - return WpsConfigMethods.EXT_NFC_TOKEN; - case "nfc_interface": - return WpsConfigMethods.NFC_INTERFACE; - case "push_button": - return WpsConfigMethods.PUSHBUTTON; - case "keypad": - return WpsConfigMethods.KEYPAD; - case "virtual_push_button": - return WpsConfigMethods.VIRT_PUSHBUTTON; - case "physical_push_button": - return WpsConfigMethods.PHY_PUSHBUTTON; - case "p2ps": - return WpsConfigMethods.P2PS; - case "virtual_display": - return WpsConfigMethods.VIRT_DISPLAY; - case "physical_display": - return WpsConfigMethods.PHY_DISPLAY; - default: - throw new IllegalArgumentException( - "Invalid WPS config method: " + configMethod); - } - } - - protected class SupplicantStaIfaceHalCallback extends SupplicantStaIfaceCallbackImpl { - SupplicantStaIfaceHalCallback(@NonNull String ifaceName) { - super(SupplicantStaIfaceHal.this, ifaceName, mLock, mWifiMonitor); - } - } - - protected class SupplicantStaIfaceHalCallbackV1_1 extends SupplicantStaIfaceCallbackV1_1Impl { - SupplicantStaIfaceHalCallbackV1_1(@NonNull String ifaceName) { - super(SupplicantStaIfaceHal.this, ifaceName, mLock, mWifiMonitor); - } - } - - protected class SupplicantStaIfaceHalCallbackV1_2 extends SupplicantStaIfaceCallbackV1_2Impl { - SupplicantStaIfaceHalCallbackV1_2(@NonNull String ifaceName) { - super(SupplicantStaIfaceHal.this, ifaceName, mContext); - } - } - - protected class SupplicantStaIfaceHalCallbackV1_3 extends SupplicantStaIfaceCallbackV1_3Impl { - SupplicantStaIfaceHalCallbackV1_3(@NonNull String ifaceName) { - super(SupplicantStaIfaceHal.this, ifaceName, mWifiMonitor); - } - } - - protected void addPmkCacheEntry( - String ifaceName, - int networkId, long expirationTimeInSec, ArrayList<Byte> serializedEntry) { - String macAddressStr = getMacAddress(ifaceName); - if (macAddressStr == null) { - Log.w(TAG, "Omit PMK cache due to no valid MAC address on " + ifaceName); - return; - } - try { - MacAddress macAddress = MacAddress.fromString(macAddressStr); - mPmkCacheEntries.put(networkId, - new PmkCacheStoreData(expirationTimeInSec, serializedEntry, macAddress)); - updatePmkCacheExpiration(); - } catch (IllegalArgumentException ex) { - Log.w(TAG, "Invalid MAC address string " + macAddressStr); - } - } - - protected void removePmkCacheEntry(int networkId) { - if (mPmkCacheEntries.remove(networkId) != null) { - updatePmkCacheExpiration(); - } - } - - private void updatePmkCacheExpiration() { - synchronized (mLock) { - mEventHandler.removeCallbacksAndMessages(PMK_CACHE_EXPIRATION_ALARM_TAG); - - long elapseTimeInSecond = mClock.getElapsedSinceBootMillis() / 1000; - long nextUpdateTimeInSecond = Long.MAX_VALUE; - logd("Update PMK cache expiration at " + elapseTimeInSecond); - - Iterator<Map.Entry<Integer, PmkCacheStoreData>> iter = - mPmkCacheEntries.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry<Integer, PmkCacheStoreData> entry = iter.next(); - if (entry.getValue().expirationTimeInSec <= elapseTimeInSecond) { - logd("Config " + entry.getKey() + " PMK is expired."); - iter.remove(); - } else if (entry.getValue().expirationTimeInSec <= 0) { - logd("Config " + entry.getKey() + " PMK expiration time is invalid."); - iter.remove(); - } else if (nextUpdateTimeInSecond > entry.getValue().expirationTimeInSec) { - nextUpdateTimeInSecond = entry.getValue().expirationTimeInSec; - } - } - - // No need to arrange next update since there is no valid PMK in the cache. - if (nextUpdateTimeInSecond == Long.MAX_VALUE) { - return; - } - - logd("PMK cache next expiration time: " + nextUpdateTimeInSecond); - long delayedTimeInMs = (nextUpdateTimeInSecond - elapseTimeInSecond) * 1000; - mEventHandler.postDelayed( - () -> { - updatePmkCacheExpiration(); - }, - PMK_CACHE_EXPIRATION_ALARM_TAG, - (delayedTimeInMs > 0) ? delayedTimeInMs : 0); - } - } - - private static void logd(String s) { - Log.d(TAG, s); - } - - private static void logi(String s) { - Log.i(TAG, s); - } - - private static void loge(String s) { - Log.e(TAG, s); - } - - /** - * Returns a bitmask of advanced key management capabilities: WPA3 SAE/SUITE B and OWE - * Bitmask used is: - * - WIFI_FEATURE_WPA3_SAE - * - WIFI_FEATURE_WPA3_SUITE_B - * - WIFI_FEATURE_OWE - * - * This is a v1.2+ HAL feature. - * On error, or if these features are not supported, 0 is returned. - */ - public long getAdvancedKeyMgmtCapabilities(@NonNull String ifaceName) { - final String methodStr = "getAdvancedKeyMgmtCapabilities"; - - long advancedCapabilities = 0; - int keyMgmtCapabilities = getKeyMgmtCapabilities(ifaceName); - - if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .KeyMgmtMask.SAE) != 0) { - advancedCapabilities |= WIFI_FEATURE_WPA3_SAE; - - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": SAE supported"); - } - } - - if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .KeyMgmtMask.SUITE_B_192) != 0) { - advancedCapabilities |= WIFI_FEATURE_WPA3_SUITE_B; - - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": SUITE_B supported"); - } - } - - if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .KeyMgmtMask.OWE) != 0) { - advancedCapabilities |= WIFI_FEATURE_OWE; - - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": OWE supported"); - } - } - - if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .KeyMgmtMask.DPP) != 0) { - advancedCapabilities |= WIFI_FEATURE_DPP; - - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": DPP supported"); - } - } - - if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .KeyMgmtMask.WAPI_PSK) != 0) { - advancedCapabilities |= WIFI_FEATURE_WAPI; - - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": WAPI supported"); - } - } - - if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .KeyMgmtMask.FILS_SHA256) != 0) { - advancedCapabilities |= WIFI_FEATURE_FILS_SHA256; - - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": FILS_SHA256 supported"); - } - } - if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .KeyMgmtMask.FILS_SHA384) != 0) { - advancedCapabilities |= WIFI_FEATURE_FILS_SHA384; - - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": FILS_SHA384 supported"); - } - } - - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": Capability flags = " + keyMgmtCapabilities); - } - - return advancedCapabilities; - } - - private int getKeyMgmtCapabilities_1_3(@NonNull String ifaceName) { - final String methodStr = "getKeyMgmtCapabilities_1_3"; - MutableInt keyMgmtMask = new MutableInt(0); - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return 0; - } - - // Get a v1.3 supplicant STA Interface - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 = - getStaIfaceMockableV1_3(iface); - if (staIfaceV13 == null) { - Log.e(TAG, methodStr - + ": ISupplicantStaIface V1.3 is null, cannot get advanced capabilities"); - return 0; - } - - try { - // Support for new key management types; WAPI_PSK, WAPI_CERT - // Requires HAL v1.3 or higher - staIfaceV13.getKeyMgmtCapabilities_1_3( - (SupplicantStatus statusInternal, int keyMgmtMaskInternal) -> { - if (statusInternal.code == SupplicantStatusCode.SUCCESS) { - keyMgmtMask.value = keyMgmtMaskInternal; - } - checkStatusAndLogFailure(statusInternal, methodStr); - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - return keyMgmtMask.value; - } - - private int getKeyMgmtCapabilities(@NonNull String ifaceName) { - final String methodStr = "getKeyMgmtCapabilities"; - MutableBoolean status = new MutableBoolean(false); - MutableInt keyMgmtMask = new MutableInt(0); - - if (isV1_3()) { - keyMgmtMask.value = getKeyMgmtCapabilities_1_3(ifaceName); - } else if (isV1_2()) { - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return 0; - } - - // Get a v1.2 supplicant STA Interface - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 = - getStaIfaceMockableV1_2(iface); - - if (staIfaceV12 == null) { - Log.e(TAG, methodStr - + ": ISupplicantStaIface is null, cannot get advanced capabilities"); - return 0; - } - - try { - // Support for new key management types; SAE, SUITE_B, OWE - // Requires HAL v1.2 or higher - staIfaceV12.getKeyMgmtCapabilities( - (SupplicantStatus statusInternal, int keyMgmtMaskInternal) -> { - status.value = statusInternal.code == SupplicantStatusCode.SUCCESS; - if (status.value) { - keyMgmtMask.value = keyMgmtMaskInternal; - } - checkStatusAndLogFailure(statusInternal, methodStr); - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - } else { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - } - - // 0 is returned in case of an error - return keyMgmtMask.value; - } - - /** - * Get the driver supported features through supplicant. - * - * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_*. - */ - public long getWpaDriverFeatureSet(@NonNull String ifaceName) { - final String methodStr = "getWpaDriverFeatureSet"; - MutableInt drvCapabilitiesMask = new MutableInt(0); - long featureSet = 0; - - if (isV1_3()) { - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return 0; - } - // Get a v1.3 supplicant STA Interface - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 = - getStaIfaceMockableV1_3(iface); - if (staIfaceV13 == null) { - Log.e(TAG, methodStr - + ": SupplicantStaIface is null, cannot get wpa driver features"); - return 0; - } - - try { - staIfaceV13.getWpaDriverCapabilities( - (SupplicantStatus statusInternal, int drvCapabilities) -> { - if (statusInternal.code == SupplicantStatusCode.SUCCESS) { - drvCapabilitiesMask.value = drvCapabilities; - } - checkStatusAndLogFailure(statusInternal, methodStr); - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - } else { - Log.i(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return 0; - } - - if ((drvCapabilitiesMask.value & WpaDriverCapabilitiesMask.MBO) != 0) { - featureSet |= WIFI_FEATURE_MBO; - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": MBO supported"); - } - if ((drvCapabilitiesMask.value - & WpaDriverCapabilitiesMask.OCE) != 0) { - featureSet |= WIFI_FEATURE_OCE; - if (mVerboseLoggingEnabled) { - Log.v(TAG, methodStr + ": OCE supported"); - } - } - } - - return featureSet; - } - - private @WifiStandard int getWifiStandardFromCap(ConnectionCapabilities capa) { - switch(capa.technology) { - case WifiTechnology.HE: - return ScanResult.WIFI_STANDARD_11AX; - case WifiTechnology.VHT: - return ScanResult.WIFI_STANDARD_11AC; - case WifiTechnology.HT: - return ScanResult.WIFI_STANDARD_11N; - case WifiTechnology.LEGACY: - return ScanResult.WIFI_STANDARD_LEGACY; - default: - return ScanResult.WIFI_STANDARD_UNKNOWN; - } - } - - private int getChannelBandwidthFromCap(ConnectionCapabilities cap) { - switch(cap.channelBandwidth) { - case WifiChannelWidthInMhz.WIDTH_20: - return ScanResult.CHANNEL_WIDTH_20MHZ; - case WifiChannelWidthInMhz.WIDTH_40: - return ScanResult.CHANNEL_WIDTH_40MHZ; - case WifiChannelWidthInMhz.WIDTH_80: - return ScanResult.CHANNEL_WIDTH_80MHZ; - case WifiChannelWidthInMhz.WIDTH_160: - return ScanResult.CHANNEL_WIDTH_160MHZ; - case WifiChannelWidthInMhz.WIDTH_80P80: - return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; - default: - return ScanResult.CHANNEL_WIDTH_20MHZ; - } - } - - /** - * Returns connection capabilities of the current network - * - * This is a v1.3+ HAL feature. - * @param ifaceName Name of the interface. - * @return connection capabilities of the current network - */ - public WifiNative.ConnectionCapabilities getConnectionCapabilities(@NonNull String ifaceName) { - final String methodStr = "getConnectionCapabilities"; - WifiNative.ConnectionCapabilities capOut = new WifiNative.ConnectionCapabilities(); - if (isV1_3()) { - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return capOut; - } - - // Get a v1.3 supplicant STA Interface - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 = - getStaIfaceMockableV1_3(iface); - - if (staIfaceV13 == null) { - Log.e(TAG, methodStr - + ": SupplicantStaIface is null, cannot get Connection Capabilities"); - return capOut; - } - - try { - staIfaceV13.getConnectionCapabilities( - (SupplicantStatus statusInternal, ConnectionCapabilities cap) -> { - if (statusInternal.code == SupplicantStatusCode.SUCCESS) { - capOut.wifiStandard = getWifiStandardFromCap(cap); - capOut.channelBandwidth = getChannelBandwidthFromCap(cap); - capOut.maxNumberTxSpatialStreams = cap.maxNumberTxSpatialStreams; - capOut.maxNumberRxSpatialStreams = cap.maxNumberRxSpatialStreams; - } - checkStatusAndLogFailure(statusInternal, methodStr); - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - } else { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - } - return capOut; - } - - /** - * Adds a DPP peer URI to the URI list. - * - * This is a v1.2+ HAL feature. - * Returns an ID to be used later to refer to this URI (>0). - * On error, or if these features are not supported, -1 is returned. - */ - public int addDppPeerUri(@NonNull String ifaceName, @NonNull String uri) { - final String methodStr = "addDppPeerUri"; - MutableBoolean status = new MutableBoolean(false); - MutableInt bootstrapId = new MutableInt(-1); - - if (!isV1_2()) { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return -1; - } - - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return -1; - } - - // Get a v1.2 supplicant STA Interface - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 = - getStaIfaceMockableV1_2(iface); - - if (staIfaceV12 == null) { - Log.e(TAG, methodStr + ": ISupplicantStaIface is null"); - return -1; - } - - try { - // Support for DPP (Easy connect) - // Requires HAL v1.2 or higher - staIfaceV12.addDppPeerUri(uri, - (SupplicantStatus statusInternal, int bootstrapIdInternal) -> { - status.value = statusInternal.code == SupplicantStatusCode.SUCCESS; - if (status.value) { - bootstrapId.value = bootstrapIdInternal; - } - checkStatusAndLogFailure(statusInternal, methodStr); - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return -1; - } - - return bootstrapId.value; - } - - /** - * Removes a DPP URI to the URI list given an ID. - * - * This is a v1.2+ HAL feature. - * Returns true when operation is successful - * On error, or if these features are not supported, false is returned. - */ - public boolean removeDppUri(@NonNull String ifaceName, int bootstrapId) { - final String methodStr = "removeDppUri"; - - if (!isV1_2()) { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return false; - } - - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return false; - } - - // Get a v1.2 supplicant STA Interface - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 = - getStaIfaceMockableV1_2(iface); - - if (staIfaceV12 == null) { - Log.e(TAG, methodStr + ": ISupplicantStaIface is null"); - return false; - } - - try { - // Support for DPP (Easy connect) - // Requires HAL v1.2 or higher - SupplicantStatus status = staIfaceV12.removeDppUri(bootstrapId); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - - return false; - } - - /** - * Stops/aborts DPP Initiator request - * - * This is a v1.2+ HAL feature. - * Returns true when operation is successful - * On error, or if these features are not supported, false is returned. - */ - public boolean stopDppInitiator(@NonNull String ifaceName) { - final String methodStr = "stopDppInitiator"; - - if (!isV1_2()) { - return false; - } - - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return false; - } - - // Get a v1.2 supplicant STA Interface - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 = - getStaIfaceMockableV1_2(iface); - - if (staIfaceV12 == null) { - Log.e(TAG, methodStr + ": ISupplicantStaIface is null"); - return false; - } - - try { - // Support for DPP (Easy connect) - // Requires HAL v1.2 or higher - SupplicantStatus status = staIfaceV12.stopDppInitiator(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - - return false; - } - - /** - * Starts DPP Configurator-Initiator request - * - * This is a v1.2+ HAL feature. - * Returns true when operation is successful - * On error, or if these features are not supported, false is returned. - */ - public boolean startDppConfiguratorInitiator(@NonNull String ifaceName, int peerBootstrapId, - int ownBootstrapId, @NonNull String ssid, String password, String psk, - int netRole, int securityAkm) { - final String methodStr = "startDppConfiguratorInitiator"; - - if (!isV1_2()) { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return false; - } - - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return false; - } - - // Get a v1.2 supplicant STA Interface - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 = - getStaIfaceMockableV1_2(iface); - - if (staIfaceV12 == null) { - Log.e(TAG, methodStr + ": ISupplicantStaIface is null"); - return false; - } - - try { - // Support for DPP (Easy connect) - // Requires HAL v1.2 or higher - SupplicantStatus status = staIfaceV12.startDppConfiguratorInitiator(peerBootstrapId, - ownBootstrapId, ssid, password != null ? password : "", psk != null ? psk : "", - netRole, securityAkm); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - - return false; - } - - /** - * Starts DPP Enrollee-Initiator request - * - * This is a v1.2+ HAL feature. - * Returns true when operation is successful - * On error, or if these features are not supported, false is returned. - */ - public boolean startDppEnrolleeInitiator(@NonNull String ifaceName, int peerBootstrapId, - int ownBootstrapId) { - final String methodStr = "startDppEnrolleeInitiator"; - - if (!isV1_2()) { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return false; - } - - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return false; - } - - // Get a v1.2 supplicant STA Interface - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 = - getStaIfaceMockableV1_2(iface); - - if (staIfaceV12 == null) { - Log.e(TAG, methodStr + ": ISupplicantStaIface is null"); - return false; - } - - try { - // Support for DPP (Easy connect) - // Requires HAL v1.2 or higher - SupplicantStatus status = staIfaceV12.startDppEnrolleeInitiator(peerBootstrapId, - ownBootstrapId); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - - return false; - } - - /** - * Register callbacks for DPP events. - * - * @param dppCallback DPP callback object. - */ - public void registerDppCallback(DppEventCallback dppCallback) { - mDppCallback = dppCallback; - } - - protected DppEventCallback getDppCallback() { - return mDppCallback; - } - - /** - * Set MBO cellular data availability. - * - * @param ifaceName Name of the interface. - * @param available true means cellular data available, false otherwise. - * @return None. - */ - public boolean setMboCellularDataStatus(@NonNull String ifaceName, boolean available) { - final String methodStr = "setMboCellularDataStatus"; - - if (isV1_3()) { - ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr); - if (iface == null) { - return false; - } - - // Get a v1.3 supplicant STA Interface - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 = - getStaIfaceMockableV1_3(iface); - if (staIfaceV13 == null) { - Log.e(TAG, methodStr - + ": SupplicantStaIface is null, cannot update cell status"); - return false; - } - - try { - SupplicantStatus status = staIfaceV13.setMboCellularDataStatus(available); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - } else { - Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return false; - } - - return false; - } - -} diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java deleted file mode 100644 index 68623fb7e..000000000 --- a/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java +++ /dev/null @@ -1,3587 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.content.Context; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiEnterpriseConfig.Ocsp; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; -import android.util.MutableBoolean; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.ArrayUtils; -import com.android.server.wifi.util.GeneralUtil.Mutable; -import com.android.server.wifi.util.NativeUtil; -import com.android.wifi.resources.R; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.annotation.concurrent.ThreadSafe; - - -/** - * Wrapper class for ISupplicantStaNetwork HAL calls. Gets and sets supplicant sta network variables - * and interacts with networks. - * Public fields should be treated as invalid until their 'get' method is called, which will set the - * value if it returns true - * To maintain thread-safety, the locking protocol is that every non-static method (regardless of - * access level) acquires mLock. - */ -@ThreadSafe -public class SupplicantStaNetworkHal { - private static final String TAG = "SupplicantStaNetworkHal"; - @VisibleForTesting - public static final String ID_STRING_KEY_FQDN = "fqdn"; - @VisibleForTesting - public static final String ID_STRING_KEY_CREATOR_UID = "creatorUid"; - @VisibleForTesting - public static final String ID_STRING_KEY_CONFIG_KEY = "configKey"; - - /** - * Regex pattern for extracting the GSM sim authentication response params from a string. - * Matches a strings like the following: "[:<kc_value>:<sres_value>]"; - */ - private static final Pattern GSM_AUTH_RESPONSE_PARAMS_PATTERN = - Pattern.compile(":([0-9a-fA-F]+):([0-9a-fA-F]+)"); - /** - * Regex pattern for extracting the UMTS sim authentication response params from a string. - * Matches a strings like the following: ":<ik_value>:<ck_value>:<res_value>"; - */ - private static final Pattern UMTS_AUTH_RESPONSE_PARAMS_PATTERN = - Pattern.compile("^:([0-9a-fA-F]+):([0-9a-fA-F]+):([0-9a-fA-F]+)$"); - /** - * Regex pattern for extracting the UMTS sim auts response params from a string. - * Matches a strings like the following: ":<auts_value>"; - */ - private static final Pattern UMTS_AUTS_RESPONSE_PARAMS_PATTERN = - Pattern.compile("^:([0-9a-fA-F]+)$"); - - private final Object mLock = new Object(); - private final Context mContext; - private final String mIfaceName; - private final WifiMonitor mWifiMonitor; - private ISupplicantStaNetwork mISupplicantStaNetwork; - private ISupplicantStaNetworkCallback mISupplicantStaNetworkCallback; - - private boolean mVerboseLoggingEnabled = false; - // Network variables read from wpa_supplicant. - private int mNetworkId; - private ArrayList<Byte> mSsid; - private byte[/* 6 */] mBssid; - private boolean mScanSsid; - private int mKeyMgmtMask; - private int mProtoMask; - private int mAuthAlgMask; - private int mGroupCipherMask; - private int mPairwiseCipherMask; - private int mGroupMgmtCipherMask; - private String mPskPassphrase; - private String mSaePassword; - private String mSaePasswordId; - private byte[] mPsk; - private ArrayList<Byte> mWepKey; - private int mWepTxKeyIdx; - private boolean mRequirePmf; - private String mIdStr; - private int mEapMethod; - private int mEapPhase2Method; - private ArrayList<Byte> mEapIdentity; - private ArrayList<Byte> mEapAnonymousIdentity; - private ArrayList<Byte> mEapPassword; - private String mEapCACert; - private String mEapCAPath; - private String mEapClientCert; - private String mEapPrivateKeyId; - private String mEapSubjectMatch; - private String mEapAltSubjectMatch; - private boolean mEapEngine; - private String mEapEngineID; - private String mEapDomainSuffixMatch; - private @Ocsp int mOcsp; - private String mWapiCertSuite; - - SupplicantStaNetworkHal(ISupplicantStaNetwork iSupplicantStaNetwork, String ifaceName, - Context context, WifiMonitor monitor) { - mISupplicantStaNetwork = iSupplicantStaNetwork; - mContext = context; - mIfaceName = ifaceName; - mWifiMonitor = monitor; - } - - /** - * Enable/Disable verbose logging. - * - * @param enable true to enable, false to disable. - */ - void enableVerboseLogging(boolean enable) { - synchronized (mLock) { - mVerboseLoggingEnabled = enable; - } - } - - /** - * Read network variables from wpa_supplicant into the provided WifiConfiguration object. - * - * @param config WifiConfiguration object to be populated. - * @param networkExtras Map of network extras parsed from wpa_supplicant. - * @return true if succeeds, false otherwise. - * @throws IllegalArgumentException on malformed configuration params. - */ - @VisibleForTesting - public boolean loadWifiConfiguration(WifiConfiguration config, - Map<String, String> networkExtras) { - synchronized (mLock) { - if (config == null) return false; - /** SSID */ - config.SSID = null; - if (getSsid() && !ArrayUtils.isEmpty(mSsid)) { - config.SSID = NativeUtil.encodeSsid(mSsid); - } else { - Log.e(TAG, "failed to read ssid"); - return false; - } - /** Network Id */ - config.networkId = -1; - if (getId()) { - config.networkId = mNetworkId; - } else { - Log.e(TAG, "getId failed"); - return false; - } - /** BSSID */ - config.getNetworkSelectionStatus().setNetworkSelectionBSSID(null); - if (getBssid() && !ArrayUtils.isEmpty(mBssid)) { - config.getNetworkSelectionStatus().setNetworkSelectionBSSID( - NativeUtil.macAddressFromByteArray(mBssid)); - } - /** Scan SSID (Is Hidden Network?) */ - config.hiddenSSID = false; - if (getScanSsid()) { - config.hiddenSSID = mScanSsid; - } - /** Require PMF*/ - config.requirePmf = false; - if (getRequirePmf()) { - config.requirePmf = mRequirePmf; - } - /** WEP keys **/ - config.wepTxKeyIndex = -1; - if (getWepTxKeyIdx()) { - config.wepTxKeyIndex = mWepTxKeyIdx; - } - for (int i = 0; i < 4; i++) { - config.wepKeys[i] = null; - if (getWepKey(i) && !ArrayUtils.isEmpty(mWepKey)) { - config.wepKeys[i] = NativeUtil.bytesToHexOrQuotedString(mWepKey); - } - } - - /** allowedKeyManagement */ - if (getKeyMgmt()) { - BitSet keyMgmtMask = supplicantToWifiConfigurationKeyMgmtMask(mKeyMgmtMask); - config.allowedKeyManagement = removeFastTransitionFlags(keyMgmtMask); - config.allowedKeyManagement = removeSha256KeyMgmtFlags(config.allowedKeyManagement); - } - /** allowedProtocols */ - if (getProto()) { - config.allowedProtocols = - supplicantToWifiConfigurationProtoMask(mProtoMask); - } - /** allowedAuthAlgorithms */ - if (getAuthAlg()) { - config.allowedAuthAlgorithms = - supplicantToWifiConfigurationAuthAlgMask(mAuthAlgMask); - } - /** allowedGroupCiphers */ - if (getGroupCipher()) { - config.allowedGroupCiphers = - supplicantToWifiConfigurationGroupCipherMask(mGroupCipherMask); - } - /** allowedPairwiseCiphers */ - if (getPairwiseCipher()) { - config.allowedPairwiseCiphers = - supplicantToWifiConfigurationPairwiseCipherMask(mPairwiseCipherMask); - } - /** allowedPairwiseCiphers */ - if (getGroupMgmtCipher()) { - config.allowedGroupManagementCiphers = - supplicantToWifiConfigurationGroupMgmtCipherMask(mGroupMgmtCipherMask); - } - - /** PSK pass phrase */ - config.preSharedKey = null; - if (getPskPassphrase() && !TextUtils.isEmpty(mPskPassphrase)) { - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK)) { - config.preSharedKey = mPskPassphrase; - } else { - config.preSharedKey = NativeUtil.addEnclosingQuotes(mPskPassphrase); - } - } else if (getPsk() && !ArrayUtils.isEmpty(mPsk)) { - config.preSharedKey = NativeUtil.hexStringFromByteArray(mPsk); - } /* Do not read SAE password */ - - /** metadata: idstr */ - if (getIdStr() && !TextUtils.isEmpty(mIdStr)) { - Map<String, String> metadata = parseNetworkExtra(mIdStr); - networkExtras.putAll(metadata); - } else { - Log.w(TAG, "getIdStr failed or empty"); - } - - /** WAPI Cert Suite */ - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_CERT)) { - if (config.enterpriseConfig == null) { - return false; - } - config.enterpriseConfig.setEapMethod( - WifiEnterpriseConfig.Eap.WAPI_CERT); - /** WAPI Certificate Suite. */ - if (getWapiCertSuite() && !TextUtils.isEmpty(mWapiCertSuite)) { - config.enterpriseConfig.setWapiCertSuite(mWapiCertSuite); - } - return true; - } - return loadWifiEnterpriseConfig(config.SSID, config.enterpriseConfig); - } - } - - /** - * Save an entire WifiConfiguration to wpa_supplicant via HIDL. - * - * @param config WifiConfiguration object to be saved. - * @return true if succeeds, false otherwise. - * @throws IllegalArgumentException on malformed configuration params. - */ - public boolean saveWifiConfiguration(WifiConfiguration config) { - synchronized (mLock) { - if (config == null) return false; - /** SSID */ - if (config.SSID != null) { - if (!setSsid(NativeUtil.decodeSsid(config.SSID))) { - Log.e(TAG, "failed to set SSID: " + config.SSID); - return false; - } - } - /** BSSID */ - String bssidStr = config.getNetworkSelectionStatus().getNetworkSelectionBSSID(); - if (bssidStr != null) { - byte[] bssid = NativeUtil.macAddressToByteArray(bssidStr); - if (!setBssid(bssid)) { - Log.e(TAG, "failed to set BSSID: " + bssidStr); - return false; - } - } - /** HiddenSSID */ - if (!setScanSsid(config.hiddenSSID)) { - Log.e(TAG, config.SSID + ": failed to set hiddenSSID: " + config.hiddenSSID); - return false; - } - - /** RequirePMF */ - if (!setRequirePmf(config.requirePmf)) { - Log.e(TAG, config.SSID + ": failed to set requirePMF: " + config.requirePmf); - return false; - } - /** Key Management Scheme */ - if (config.allowedKeyManagement.cardinality() != 0) { - // Add FT flags if supported. - BitSet keyMgmtMask = addFastTransitionFlags(config.allowedKeyManagement); - // Add SHA256 key management flags. - keyMgmtMask = addSha256KeyMgmtFlags(keyMgmtMask); - if (!setKeyMgmt(wifiConfigurationToSupplicantKeyMgmtMask(keyMgmtMask))) { - Log.e(TAG, "failed to set Key Management"); - return false; - } - // Check and set SuiteB configurations. - if (keyMgmtMask.get(WifiConfiguration.KeyMgmt.SUITE_B_192) - && !saveSuiteBConfig(config)) { - Log.e(TAG, "Failed to set Suite-B-192 configuration"); - return false; - } - } - /** Security Protocol */ - if (config.allowedProtocols.cardinality() != 0 - && !setProto(wifiConfigurationToSupplicantProtoMask(config.allowedProtocols))) { - Log.e(TAG, "failed to set Security Protocol"); - return false; - } - /** Auth Algorithm */ - if (config.allowedAuthAlgorithms.cardinality() != 0 - && !setAuthAlg(wifiConfigurationToSupplicantAuthAlgMask( - config.allowedAuthAlgorithms))) { - Log.e(TAG, "failed to set AuthAlgorithm"); - return false; - } - /** Group Cipher */ - if (config.allowedGroupCiphers.cardinality() != 0 - && (!setGroupCipher(wifiConfigurationToSupplicantGroupCipherMask( - config.allowedGroupCiphers)))) { - Log.e(TAG, "failed to set Group Cipher"); - return false; - } - /** Pairwise Cipher*/ - if (config.allowedPairwiseCiphers.cardinality() != 0 - && !setPairwiseCipher(wifiConfigurationToSupplicantPairwiseCipherMask( - config.allowedPairwiseCiphers))) { - Log.e(TAG, "failed to set PairwiseCipher"); - return false; - } - /** Pre Shared Key */ - // For PSK, this can either be quoted ASCII passphrase or hex string for raw psk. - // For SAE, password must be a quoted ASCII string - if (config.preSharedKey != null) { - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK)) { - if (!setPskPassphrase(config.preSharedKey)) { - Log.e(TAG, "failed to set wapi psk passphrase"); - return false; - } - } else if (config.preSharedKey.startsWith("\"")) { - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { - /* WPA3 case, field is SAE Password */ - if (!setSaePassword( - NativeUtil.removeEnclosingQuotes(config.preSharedKey))) { - Log.e(TAG, "failed to set sae password"); - return false; - } - } else { - if (!setPskPassphrase( - NativeUtil.removeEnclosingQuotes(config.preSharedKey))) { - Log.e(TAG, "failed to set psk passphrase"); - return false; - } - } - } else { - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { - return false; - } - if (!setPsk(NativeUtil.hexStringToByteArray(config.preSharedKey))) { - Log.e(TAG, "failed to set psk"); - return false; - } - } - } - /** Wep Keys */ - boolean hasSetKey = false; - if (config.wepKeys != null) { - for (int i = 0; i < config.wepKeys.length; i++) { - if (config.wepKeys[i] != null) { - if (!setWepKey( - i, NativeUtil.hexOrQuotedStringToBytes(config.wepKeys[i]))) { - Log.e(TAG, "failed to set wep_key " + i); - return false; - } - hasSetKey = true; - } - } - } - /** Wep Tx Key Idx */ - if (hasSetKey) { - if (!setWepTxKeyIdx(config.wepTxKeyIndex)) { - Log.e(TAG, "failed to set wep_tx_keyidx: " + config.wepTxKeyIndex); - return false; - } - } - /** metadata: FQDN + ConfigKey + CreatorUid */ - final Map<String, String> metadata = new HashMap<String, String>(); - if (config.isPasspoint()) { - metadata.put(ID_STRING_KEY_FQDN, config.FQDN); - } - metadata.put(ID_STRING_KEY_CONFIG_KEY, config.getKey()); - metadata.put(ID_STRING_KEY_CREATOR_UID, Integer.toString(config.creatorUid)); - if (!setIdStr(createNetworkExtra(metadata))) { - Log.e(TAG, "failed to set id string"); - return false; - } - /** UpdateIdentifier */ - if (config.updateIdentifier != null - && !setUpdateIdentifier(Integer.parseInt(config.updateIdentifier))) { - Log.e(TAG, "failed to set update identifier"); - return false; - } - // Finish here if no EAP config to set - if (config.enterpriseConfig != null - && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) { - if (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.WAPI_CERT) { - /** WAPI certificate suite name*/ - String param = config.enterpriseConfig - .getFieldValue(WifiEnterpriseConfig.WAPI_CERT_SUITE_KEY); - if (!TextUtils.isEmpty(param) && !setWapiCertSuite(param)) { - Log.e(TAG, config.SSID + ": failed to set WAPI certificate suite: " - + param); - return false; - } - return true; - } else if (!saveWifiEnterpriseConfig(config.SSID, config.enterpriseConfig)) { - return false; - } - } - - // Now that the network is configured fully, start listening for callback events. - mISupplicantStaNetworkCallback = - new SupplicantStaNetworkHalCallback(config.networkId, config.SSID); - if (!registerCallback(mISupplicantStaNetworkCallback)) { - Log.e(TAG, "Failed to register callback"); - return false; - } - return true; - } - } - - /** - * Read network variables from wpa_supplicant into the provided WifiEnterpriseConfig object. - * - * @param ssid SSID of the network. (Used for logging purposes only) - * @param eapConfig WifiEnterpriseConfig object to be populated. - * @return true if succeeds, false otherwise. - */ - private boolean loadWifiEnterpriseConfig(String ssid, WifiEnterpriseConfig eapConfig) { - synchronized (mLock) { - if (eapConfig == null) return false; - /** EAP method */ - if (getEapMethod()) { - eapConfig.setEapMethod(supplicantToWifiConfigurationEapMethod(mEapMethod)); - } else { - // Invalid eap method could be because it's not an enterprise config. - Log.e(TAG, "failed to get eap method. Assumimg not an enterprise network"); - return true; - } - /** EAP Phase 2 method */ - if (getEapPhase2Method()) { - eapConfig.setPhase2Method( - supplicantToWifiConfigurationEapPhase2Method(mEapPhase2Method)); - } else { - // We cannot have an invalid eap phase 2 method. Return failure. - Log.e(TAG, "failed to get eap phase2 method"); - return false; - } - /** EAP Identity */ - if (getEapIdentity() && !ArrayUtils.isEmpty(mEapIdentity)) { - eapConfig.setFieldValue( - WifiEnterpriseConfig.IDENTITY_KEY, - NativeUtil.stringFromByteArrayList(mEapIdentity)); - } - /** EAP Anonymous Identity */ - if (getEapAnonymousIdentity() && !ArrayUtils.isEmpty(mEapAnonymousIdentity)) { - eapConfig.setFieldValue( - WifiEnterpriseConfig.ANON_IDENTITY_KEY, - NativeUtil.stringFromByteArrayList(mEapAnonymousIdentity)); - } - /** EAP Password */ - if (getEapPassword() && !ArrayUtils.isEmpty(mEapPassword)) { - eapConfig.setFieldValue( - WifiEnterpriseConfig.PASSWORD_KEY, - NativeUtil.stringFromByteArrayList(mEapPassword)); - } - /** EAP Client Cert */ - if (getEapClientCert() && !TextUtils.isEmpty(mEapClientCert)) { - eapConfig.setFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY, mEapClientCert); - } - /** EAP CA Cert */ - if (getEapCACert() && !TextUtils.isEmpty(mEapCACert)) { - eapConfig.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, mEapCACert); - } - /** EAP OCSP type */ - if (getOcsp()) { - eapConfig.setOcsp(mOcsp); - } - /** EAP Subject Match */ - if (getEapSubjectMatch() && !TextUtils.isEmpty(mEapSubjectMatch)) { - eapConfig.setFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY, mEapSubjectMatch); - } - /** EAP Engine ID */ - if (getEapEngineID() && !TextUtils.isEmpty(mEapEngineID)) { - eapConfig.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, mEapEngineID); - } - /** EAP Engine. Set this only if the engine id is non null. */ - if (getEapEngine() && !TextUtils.isEmpty(mEapEngineID)) { - eapConfig.setFieldValue( - WifiEnterpriseConfig.ENGINE_KEY, - mEapEngine - ? WifiEnterpriseConfig.ENGINE_ENABLE - : WifiEnterpriseConfig.ENGINE_DISABLE); - } - /** EAP Private Key */ - if (getEapPrivateKeyId() && !TextUtils.isEmpty(mEapPrivateKeyId)) { - eapConfig.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, mEapPrivateKeyId); - } - /** EAP Alt Subject Match */ - if (getEapAltSubjectMatch() && !TextUtils.isEmpty(mEapAltSubjectMatch)) { - eapConfig.setFieldValue( - WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, mEapAltSubjectMatch); - } - /** EAP Domain Suffix Match */ - if (getEapDomainSuffixMatch() && !TextUtils.isEmpty(mEapDomainSuffixMatch)) { - eapConfig.setFieldValue( - WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, mEapDomainSuffixMatch); - } - /** EAP CA Path*/ - if (getEapCAPath() && !TextUtils.isEmpty(mEapCAPath)) { - eapConfig.setFieldValue(WifiEnterpriseConfig.CA_PATH_KEY, mEapCAPath); - } - return true; - } - } - - /** - * Save network variables from the provided SuiteB configuration to wpa_supplicant. - * - * @param config WifiConfiguration object to be saved - * @return true if succeeds, false otherwise. - */ - private boolean saveSuiteBConfig(WifiConfiguration config) { - /** Group Cipher **/ - if (config.allowedGroupCiphers.cardinality() != 0 - && !setGroupCipher(wifiConfigurationToSupplicantGroupCipherMask( - config.allowedGroupCiphers))) { - Log.e(TAG, "failed to set Group Cipher"); - return false; - } - /** Pairwise Cipher*/ - if (config.allowedPairwiseCiphers.cardinality() != 0 - && !setPairwiseCipher(wifiConfigurationToSupplicantPairwiseCipherMask( - config.allowedPairwiseCiphers))) { - Log.e(TAG, "failed to set PairwiseCipher"); - return false; - } - /** GroupMgmt Cipher */ - if (config.allowedGroupManagementCiphers.cardinality() != 0 - && !setGroupMgmtCipher(wifiConfigurationToSupplicantGroupMgmtCipherMask( - config.allowedGroupManagementCiphers))) { - Log.e(TAG, "failed to set GroupMgmtCipher"); - return false; - } - - if (config.allowedSuiteBCiphers.get(WifiConfiguration.SuiteBCipher.ECDHE_RSA)) { - if (!enableTlsSuiteBEapPhase1Param(true)) { - Log.e(TAG, "failed to set TLSSuiteB"); - return false; - } - } else if (config.allowedSuiteBCiphers.get(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA)) { - if (!enableSuiteBEapOpenSslCiphers()) { - Log.e(TAG, "failed to set OpensslCipher"); - return false; - } - } - - return true; - } - - /** - * Save network variables from the provided WifiEnterpriseConfig object to wpa_supplicant. - * - * @param ssid SSID of the network. (Used for logging purposes only) - * @param eapConfig WifiEnterpriseConfig object to be saved. - * @return true if succeeds, false otherwise. - */ - private boolean saveWifiEnterpriseConfig(String ssid, WifiEnterpriseConfig eapConfig) { - synchronized (mLock) { - if (eapConfig == null) return false; - /** EAP method */ - if (!setEapMethod(wifiConfigurationToSupplicantEapMethod(eapConfig.getEapMethod()))) { - Log.e(TAG, ssid + ": failed to set eap method: " + eapConfig.getEapMethod()); - return false; - } - /** EAP Phase 2 method */ - if (!setEapPhase2Method(wifiConfigurationToSupplicantEapPhase2Method( - eapConfig.getPhase2Method()))) { - Log.e(TAG, ssid + ": failed to set eap phase 2 method: " - + eapConfig.getPhase2Method()); - return false; - } - String eapParam = null; - /** EAP Identity */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY); - if (!TextUtils.isEmpty(eapParam) - && !setEapIdentity(NativeUtil.stringToByteArrayList(eapParam))) { - Log.e(TAG, ssid + ": failed to set eap identity: " + eapParam); - return false; - } - /** EAP Anonymous Identity */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY); - if (!TextUtils.isEmpty(eapParam) - && !setEapAnonymousIdentity(NativeUtil.stringToByteArrayList(eapParam))) { - Log.e(TAG, ssid + ": failed to set eap anonymous identity: " + eapParam); - return false; - } - /** EAP Password */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY); - if (!TextUtils.isEmpty(eapParam) - && !setEapPassword(NativeUtil.stringToByteArrayList(eapParam))) { - Log.e(TAG, ssid + ": failed to set eap password"); - return false; - } - /** EAP Client Cert */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapClientCert(eapParam)) { - Log.e(TAG, ssid + ": failed to set eap client cert: " + eapParam); - return false; - } - /** EAP CA Cert */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapCACert(eapParam)) { - Log.e(TAG, ssid + ": failed to set eap ca cert: " + eapParam); - return false; - } - /** EAP Subject Match */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapSubjectMatch(eapParam)) { - Log.e(TAG, ssid + ": failed to set eap subject match: " + eapParam); - return false; - } - /** EAP Engine ID */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapEngineID(eapParam)) { - Log.e(TAG, ssid + ": failed to set eap engine id: " + eapParam); - return false; - } - /** EAP Engine */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapEngine( - eapParam.equals(WifiEnterpriseConfig.ENGINE_ENABLE) ? true : false)) { - Log.e(TAG, ssid + ": failed to set eap engine: " + eapParam); - return false; - } - /** EAP Private Key */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapPrivateKeyId(eapParam)) { - Log.e(TAG, ssid + ": failed to set eap private key: " + eapParam); - return false; - } - /** EAP Alt Subject Match */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapAltSubjectMatch(eapParam)) { - Log.e(TAG, ssid + ": failed to set eap alt subject match: " + eapParam); - return false; - } - /** EAP Domain Suffix Match */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapDomainSuffixMatch(eapParam)) { - Log.e(TAG, ssid + ": failed to set eap domain suffix match: " + eapParam); - return false; - } - /** EAP CA Path*/ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY); - if (!TextUtils.isEmpty(eapParam) && !setEapCAPath(eapParam)) { - Log.e(TAG, ssid + ": failed to set eap ca path: " + eapParam); - return false; - } - - /** EAP Proactive Key Caching */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.OPP_KEY_CACHING); - if (!TextUtils.isEmpty(eapParam) - && !setEapProactiveKeyCaching(eapParam.equals("1") ? true : false)) { - Log.e(TAG, ssid + ": failed to set proactive key caching: " + eapParam); - return false; - } - - /** - * OCSP (Online Certificate Status Protocol) - * For older HAL compatibility, omit this step to avoid breaking - * connection flow. - */ - if (getV1_3StaNetwork() != null && !setOcsp(eapConfig.getOcsp())) { - Log.e(TAG, "failed to set ocsp"); - return false; - } - /** EAP ERP */ - eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.EAP_ERP); - if (!TextUtils.isEmpty(eapParam) && eapParam.equals("1")) { - if (!setEapErp(true)) { - Log.e(TAG, ssid + ": failed to set eap erp"); - return false; - } - } - - - return true; - } - } - - private android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork getV1_2StaNetwork() { - synchronized (mLock) { - return getSupplicantStaNetworkForV1_2Mockable(); - } - } - - private android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork getV1_3StaNetwork() { - synchronized (mLock) { - return getSupplicantStaNetworkForV1_3Mockable(); - } - } - - /** - * Maps WifiConfiguration Key Management BitSet to Supplicant HIDL bitmask int - * TODO(b/32571829): Update mapping when fast transition keys are added - * - * @return bitmask int describing the allowed Key Management schemes, readable by the Supplicant - * HIDL hal - */ - private static int wifiConfigurationToSupplicantKeyMgmtMask(BitSet keyMgmt) { - int mask = 0; - for (int bit = keyMgmt.nextSetBit(0); bit != -1; - bit = keyMgmt.nextSetBit(bit + 1)) { - switch (bit) { - case WifiConfiguration.KeyMgmt.NONE: - mask |= ISupplicantStaNetwork.KeyMgmtMask.NONE; - break; - case WifiConfiguration.KeyMgmt.WPA_PSK: - mask |= ISupplicantStaNetwork.KeyMgmtMask.WPA_PSK; - break; - case WifiConfiguration.KeyMgmt.WPA_EAP: - mask |= ISupplicantStaNetwork.KeyMgmtMask.WPA_EAP; - break; - case WifiConfiguration.KeyMgmt.IEEE8021X: - mask |= ISupplicantStaNetwork.KeyMgmtMask.IEEE8021X; - break; - case WifiConfiguration.KeyMgmt.OSEN: - mask |= ISupplicantStaNetwork.KeyMgmtMask.OSEN; - break; - case WifiConfiguration.KeyMgmt.FT_PSK: - mask |= ISupplicantStaNetwork.KeyMgmtMask.FT_PSK; - break; - case WifiConfiguration.KeyMgmt.FT_EAP: - mask |= ISupplicantStaNetwork.KeyMgmtMask.FT_EAP; - break; - case WifiConfiguration.KeyMgmt.OWE: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .OWE; - break; - case WifiConfiguration.KeyMgmt.SAE: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .SAE; - break; - case WifiConfiguration.KeyMgmt.SUITE_B_192: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .SUITE_B_192; - break; - case WifiConfiguration.KeyMgmt.WPA_PSK_SHA256: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .WPA_PSK_SHA256; - break; - case WifiConfiguration.KeyMgmt.WPA_EAP_SHA256: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .WPA_EAP_SHA256; - break; - case WifiConfiguration.KeyMgmt.WAPI_PSK: - mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask - .WAPI_PSK; - break; - case WifiConfiguration.KeyMgmt.WAPI_CERT: - mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask - .WAPI_CERT; - break; - case WifiConfiguration.KeyMgmt.FILS_SHA256: - mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask - .FILS_SHA256; - break; - case WifiConfiguration.KeyMgmt.FILS_SHA384: - mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask - .FILS_SHA384; - break; - case WifiConfiguration.KeyMgmt.WPA2_PSK: // This should never happen - default: - throw new IllegalArgumentException( - "Invalid protoMask bit in keyMgmt: " + bit); - } - } - return mask; - } - - private static int wifiConfigurationToSupplicantProtoMask(BitSet protoMask) { - int mask = 0; - for (int bit = protoMask.nextSetBit(0); bit != -1; - bit = protoMask.nextSetBit(bit + 1)) { - switch (bit) { - case WifiConfiguration.Protocol.WPA: - mask |= ISupplicantStaNetwork.ProtoMask.WPA; - break; - case WifiConfiguration.Protocol.RSN: - mask |= ISupplicantStaNetwork.ProtoMask.RSN; - break; - case WifiConfiguration.Protocol.OSEN: - mask |= ISupplicantStaNetwork.ProtoMask.OSEN; - break; - case WifiConfiguration.Protocol.WAPI: - mask |= android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.ProtoMask.WAPI; - break; - default: - throw new IllegalArgumentException( - "Invalid protoMask bit in wificonfig: " + bit); - } - } - return mask; - } - - private static int wifiConfigurationToSupplicantAuthAlgMask(BitSet authAlgMask) { - int mask = 0; - for (int bit = authAlgMask.nextSetBit(0); bit != -1; - bit = authAlgMask.nextSetBit(bit + 1)) { - switch (bit) { - case WifiConfiguration.AuthAlgorithm.OPEN: - mask |= ISupplicantStaNetwork.AuthAlgMask.OPEN; - break; - case WifiConfiguration.AuthAlgorithm.SHARED: - mask |= ISupplicantStaNetwork.AuthAlgMask.SHARED; - break; - case WifiConfiguration.AuthAlgorithm.LEAP: - mask |= ISupplicantStaNetwork.AuthAlgMask.LEAP; - break; - case WifiConfiguration.AuthAlgorithm.SAE: - mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.AuthAlgMask - .SAE; - break; - default: - throw new IllegalArgumentException( - "Invalid authAlgMask bit in wificonfig: " + bit); - } - } - return mask; - } - - private static int wifiConfigurationToSupplicantGroupCipherMask(BitSet groupCipherMask) { - int mask = 0; - for (int bit = groupCipherMask.nextSetBit(0); bit != -1; bit = - groupCipherMask.nextSetBit(bit + 1)) { - switch (bit) { - case WifiConfiguration.GroupCipher.WEP40: - mask |= ISupplicantStaNetwork.GroupCipherMask.WEP40; - break; - case WifiConfiguration.GroupCipher.WEP104: - mask |= ISupplicantStaNetwork.GroupCipherMask.WEP104; - break; - case WifiConfiguration.GroupCipher.TKIP: - mask |= ISupplicantStaNetwork.GroupCipherMask.TKIP; - break; - case WifiConfiguration.GroupCipher.CCMP: - mask |= ISupplicantStaNetwork.GroupCipherMask.CCMP; - break; - case WifiConfiguration.GroupCipher.GTK_NOT_USED: - mask |= ISupplicantStaNetwork.GroupCipherMask.GTK_NOT_USED; - break; - case WifiConfiguration.GroupCipher.GCMP_256: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupCipherMask.GCMP_256; - break; - case WifiConfiguration.GroupCipher.SMS4: - mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .GroupCipherMask.SMS4; - break; - default: - throw new IllegalArgumentException( - "Invalid GroupCipherMask bit in wificonfig: " + bit); - } - } - return mask; - } - - private static int wifiConfigurationToSupplicantGroupMgmtCipherMask(BitSet - groupMgmtCipherMask) { - int mask = 0; - - for (int bit = groupMgmtCipherMask.nextSetBit(0); bit != -1; bit = - groupMgmtCipherMask.nextSetBit(bit + 1)) { - switch (bit) { - case WifiConfiguration.GroupMgmtCipher.BIP_CMAC_256: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupMgmtCipherMask.BIP_CMAC_256; - break; - case WifiConfiguration.GroupMgmtCipher.BIP_GMAC_128: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupMgmtCipherMask.BIP_GMAC_128; - break; - case WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupMgmtCipherMask.BIP_GMAC_256; - break; - default: - throw new IllegalArgumentException( - "Invalid GroupMgmtCipherMask bit in wificonfig: " + bit); - } - } - return mask; - } - - private static int wifiConfigurationToSupplicantPairwiseCipherMask(BitSet pairwiseCipherMask) { - int mask = 0; - for (int bit = pairwiseCipherMask.nextSetBit(0); bit != -1; - bit = pairwiseCipherMask.nextSetBit(bit + 1)) { - switch (bit) { - case WifiConfiguration.PairwiseCipher.NONE: - mask |= ISupplicantStaNetwork.PairwiseCipherMask.NONE; - break; - case WifiConfiguration.PairwiseCipher.TKIP: - mask |= ISupplicantStaNetwork.PairwiseCipherMask.TKIP; - break; - case WifiConfiguration.PairwiseCipher.CCMP: - mask |= ISupplicantStaNetwork.PairwiseCipherMask.CCMP; - break; - case WifiConfiguration.PairwiseCipher.GCMP_256: - mask |= android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .PairwiseCipherMask.GCMP_256; - break; - case WifiConfiguration.PairwiseCipher.SMS4: - mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .PairwiseCipherMask.SMS4; - break; - default: - throw new IllegalArgumentException( - "Invalid pairwiseCipherMask bit in wificonfig: " + bit); - } - } - return mask; - } - - private static int supplicantToWifiConfigurationEapMethod(int value) { - switch (value) { - case ISupplicantStaNetwork.EapMethod.PEAP: - return WifiEnterpriseConfig.Eap.PEAP; - case ISupplicantStaNetwork.EapMethod.TLS: - return WifiEnterpriseConfig.Eap.TLS; - case ISupplicantStaNetwork.EapMethod.TTLS: - return WifiEnterpriseConfig.Eap.TTLS; - case ISupplicantStaNetwork.EapMethod.PWD: - return WifiEnterpriseConfig.Eap.PWD; - case ISupplicantStaNetwork.EapMethod.SIM: - return WifiEnterpriseConfig.Eap.SIM; - case ISupplicantStaNetwork.EapMethod.AKA: - return WifiEnterpriseConfig.Eap.AKA; - case ISupplicantStaNetwork.EapMethod.AKA_PRIME: - return WifiEnterpriseConfig.Eap.AKA_PRIME; - case ISupplicantStaNetwork.EapMethod.WFA_UNAUTH_TLS: - return WifiEnterpriseConfig.Eap.UNAUTH_TLS; - // WifiEnterpriseConfig.Eap.NONE: - default: - Log.e(TAG, "invalid eap method value from supplicant: " + value); - return -1; - } - } - - private static int supplicantToWifiConfigurationEapPhase2Method(int value) { - switch (value) { - case ISupplicantStaNetwork.EapPhase2Method.NONE: - return WifiEnterpriseConfig.Phase2.NONE; - case ISupplicantStaNetwork.EapPhase2Method.PAP: - return WifiEnterpriseConfig.Phase2.PAP; - case ISupplicantStaNetwork.EapPhase2Method.MSPAP: - return WifiEnterpriseConfig.Phase2.MSCHAP; - case ISupplicantStaNetwork.EapPhase2Method.MSPAPV2: - return WifiEnterpriseConfig.Phase2.MSCHAPV2; - case ISupplicantStaNetwork.EapPhase2Method.GTC: - return WifiEnterpriseConfig.Phase2.GTC; - case ISupplicantStaNetwork.EapPhase2Method.SIM: - return WifiEnterpriseConfig.Phase2.SIM; - case ISupplicantStaNetwork.EapPhase2Method.AKA: - return WifiEnterpriseConfig.Phase2.AKA; - case ISupplicantStaNetwork.EapPhase2Method.AKA_PRIME: - return WifiEnterpriseConfig.Phase2.AKA_PRIME; - default: - Log.e(TAG, "invalid eap phase2 method value from supplicant: " + value); - return -1; - } - } - - private static int supplicantMaskValueToWifiConfigurationBitSet(int supplicantMask, - int supplicantValue, BitSet bitset, - int bitSetPosition) { - bitset.set(bitSetPosition, (supplicantMask & supplicantValue) == supplicantValue); - int modifiedSupplicantMask = supplicantMask & ~supplicantValue; - return modifiedSupplicantMask; - } - - private static BitSet supplicantToWifiConfigurationKeyMgmtMask(int mask) { - BitSet bitset = new BitSet(); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.KeyMgmtMask.NONE, bitset, - WifiConfiguration.KeyMgmt.NONE); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.KeyMgmtMask.WPA_PSK, bitset, - WifiConfiguration.KeyMgmt.WPA_PSK); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.KeyMgmtMask.WPA_EAP, bitset, - WifiConfiguration.KeyMgmt.WPA_EAP); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.KeyMgmtMask.IEEE8021X, bitset, - WifiConfiguration.KeyMgmt.IEEE8021X); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.KeyMgmtMask.OSEN, bitset, - WifiConfiguration.KeyMgmt.OSEN); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.KeyMgmtMask.FT_PSK, bitset, - WifiConfiguration.KeyMgmt.FT_PSK); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.KeyMgmtMask.FT_EAP, bitset, - WifiConfiguration.KeyMgmt.FT_EAP); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask.SAE, - bitset, WifiConfiguration.KeyMgmt.SAE); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask.OWE, - bitset, WifiConfiguration.KeyMgmt.OWE); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .SUITE_B_192, bitset, WifiConfiguration.KeyMgmt.SUITE_B_192); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .WPA_PSK_SHA256, bitset, WifiConfiguration.KeyMgmt.WPA_PSK_SHA256); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .WPA_EAP_SHA256, bitset, WifiConfiguration.KeyMgmt.WPA_EAP_SHA256); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask - .WAPI_PSK, bitset, WifiConfiguration.KeyMgmt.WAPI_PSK); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask - .WAPI_CERT, bitset, WifiConfiguration.KeyMgmt.WAPI_CERT); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask - .FILS_SHA256, bitset, WifiConfiguration.KeyMgmt.FILS_SHA256); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask - .FILS_SHA384, bitset, WifiConfiguration.KeyMgmt.FILS_SHA384); - if (mask != 0) { - throw new IllegalArgumentException( - "invalid key mgmt mask from supplicant: " + mask); - } - return bitset; - } - - private static BitSet supplicantToWifiConfigurationProtoMask(int mask) { - BitSet bitset = new BitSet(); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.ProtoMask.WPA, bitset, - WifiConfiguration.Protocol.WPA); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.ProtoMask.RSN, bitset, - WifiConfiguration.Protocol.RSN); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.ProtoMask.OSEN, bitset, - WifiConfiguration.Protocol.OSEN); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.ProtoMask.WAPI, - bitset, WifiConfiguration.Protocol.WAPI); - if (mask != 0) { - throw new IllegalArgumentException( - "invalid proto mask from supplicant: " + mask); - } - return bitset; - } - - private static BitSet supplicantToWifiConfigurationAuthAlgMask(int mask) { - BitSet bitset = new BitSet(); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.AuthAlgMask.OPEN, bitset, - WifiConfiguration.AuthAlgorithm.OPEN); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.AuthAlgMask.SHARED, bitset, - WifiConfiguration.AuthAlgorithm.SHARED); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.AuthAlgMask.LEAP, bitset, - WifiConfiguration.AuthAlgorithm.LEAP); - mask = supplicantMaskValueToWifiConfigurationBitSet(mask, - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.AuthAlgMask - .SAE, bitset, WifiConfiguration.AuthAlgorithm.SAE); - if (mask != 0) { - throw new IllegalArgumentException( - "invalid auth alg mask from supplicant: " + mask); - } - return bitset; - } - - private static BitSet supplicantToWifiConfigurationGroupCipherMask(int mask) { - BitSet bitset = new BitSet(); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.GroupCipherMask.WEP40, bitset, - WifiConfiguration.GroupCipher.WEP40); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.GroupCipherMask.WEP104, bitset, - WifiConfiguration.GroupCipher.WEP104); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.GroupCipherMask.TKIP, bitset, - WifiConfiguration.GroupCipher.TKIP); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.GroupCipherMask.CCMP, bitset, - WifiConfiguration.GroupCipher.CCMP); - mask = supplicantMaskValueToWifiConfigurationBitSet(mask, - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupCipherMask.GCMP_256, bitset, WifiConfiguration.GroupCipher.GCMP_256); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.GroupCipherMask.GTK_NOT_USED, bitset, - WifiConfiguration.GroupCipher.GTK_NOT_USED); - mask = supplicantMaskValueToWifiConfigurationBitSet(mask, - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.GroupCipherMask - .SMS4, bitset, WifiConfiguration.GroupCipher.SMS4); - if (mask != 0) { - throw new IllegalArgumentException( - "invalid group cipher mask from supplicant: " + mask); - } - return bitset; - } - - private static BitSet supplicantToWifiConfigurationGroupMgmtCipherMask(int mask) { - BitSet bitset = new BitSet(); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupMgmtCipherMask.BIP_GMAC_128, bitset, - WifiConfiguration.GroupMgmtCipher.BIP_GMAC_128); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupMgmtCipherMask.BIP_GMAC_256, bitset, - WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupMgmtCipherMask.BIP_CMAC_256, bitset, - WifiConfiguration.GroupMgmtCipher.BIP_CMAC_256); - if (mask != 0) { - throw new IllegalArgumentException( - "invalid group mgmt cipher mask from supplicant: " + mask); - } - return bitset; - } - - private static BitSet supplicantToWifiConfigurationPairwiseCipherMask(int mask) { - BitSet bitset = new BitSet(); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.PairwiseCipherMask.NONE, bitset, - WifiConfiguration.PairwiseCipher.NONE); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.PairwiseCipherMask.TKIP, bitset, - WifiConfiguration.PairwiseCipher.TKIP); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, ISupplicantStaNetwork.PairwiseCipherMask.CCMP, bitset, - WifiConfiguration.PairwiseCipher.CCMP); - mask = supplicantMaskValueToWifiConfigurationBitSet(mask, - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.PairwiseCipherMask - .GCMP_256, bitset, - WifiConfiguration.PairwiseCipher.GCMP_256); - mask = supplicantMaskValueToWifiConfigurationBitSet(mask, - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.PairwiseCipherMask - .SMS4, bitset, - WifiConfiguration.PairwiseCipher.SMS4); - if (mask != 0) { - throw new IllegalArgumentException( - "invalid pairwise cipher mask from supplicant: " + mask); - } - return bitset; - } - - private static int wifiConfigurationToSupplicantEapMethod(int value) { - switch (value) { - case WifiEnterpriseConfig.Eap.PEAP: - return ISupplicantStaNetwork.EapMethod.PEAP; - case WifiEnterpriseConfig.Eap.TLS: - return ISupplicantStaNetwork.EapMethod.TLS; - case WifiEnterpriseConfig.Eap.TTLS: - return ISupplicantStaNetwork.EapMethod.TTLS; - case WifiEnterpriseConfig.Eap.PWD: - return ISupplicantStaNetwork.EapMethod.PWD; - case WifiEnterpriseConfig.Eap.SIM: - return ISupplicantStaNetwork.EapMethod.SIM; - case WifiEnterpriseConfig.Eap.AKA: - return ISupplicantStaNetwork.EapMethod.AKA; - case WifiEnterpriseConfig.Eap.AKA_PRIME: - return ISupplicantStaNetwork.EapMethod.AKA_PRIME; - case WifiEnterpriseConfig.Eap.UNAUTH_TLS: - return ISupplicantStaNetwork.EapMethod.WFA_UNAUTH_TLS; - // WifiEnterpriseConfig.Eap.NONE: - default: - Log.e(TAG, "invalid eap method value from WifiConfiguration: " + value); - return -1; - } - } - - private static int wifiConfigurationToSupplicantEapPhase2Method(int value) { - switch (value) { - case WifiEnterpriseConfig.Phase2.NONE: - return ISupplicantStaNetwork.EapPhase2Method.NONE; - case WifiEnterpriseConfig.Phase2.PAP: - return ISupplicantStaNetwork.EapPhase2Method.PAP; - case WifiEnterpriseConfig.Phase2.MSCHAP: - return ISupplicantStaNetwork.EapPhase2Method.MSPAP; - case WifiEnterpriseConfig.Phase2.MSCHAPV2: - return ISupplicantStaNetwork.EapPhase2Method.MSPAPV2; - case WifiEnterpriseConfig.Phase2.GTC: - return ISupplicantStaNetwork.EapPhase2Method.GTC; - case WifiEnterpriseConfig.Phase2.SIM: - return ISupplicantStaNetwork.EapPhase2Method.SIM; - case WifiEnterpriseConfig.Phase2.AKA: - return ISupplicantStaNetwork.EapPhase2Method.AKA; - case WifiEnterpriseConfig.Phase2.AKA_PRIME: - return ISupplicantStaNetwork.EapPhase2Method.AKA_PRIME; - default: - Log.e(TAG, "invalid eap phase2 method value from WifiConfiguration: " + value); - return -1; - } - } - - /** See ISupplicantNetwork.hal for documentation */ - private boolean getId() { - synchronized (mLock) { - final String methodStr = "getId"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getId((SupplicantStatus status, int idValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mNetworkId = idValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean registerCallback(ISupplicantStaNetworkCallback callback) { - synchronized (mLock) { - final String methodStr = "registerCallback"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.registerCallback(callback); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setSsid(java.util.ArrayList<Byte> ssid) { - synchronized (mLock) { - final String methodStr = "setSsid"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setSsid(ssid); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Set the BSSID for this network. - * - * @param bssidStr MAC address in "XX:XX:XX:XX:XX:XX" form or "any" to reset the mac address. - * @return true if it succeeds, false otherwise. - */ - public boolean setBssid(String bssidStr) { - synchronized (mLock) { - try { - return setBssid(NativeUtil.macAddressToByteArray(bssidStr)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + bssidStr, e); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setBssid(byte[/* 6 */] bssid) { - synchronized (mLock) { - final String methodStr = "setBssid"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setBssid(bssid); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setScanSsid(boolean enable) { - synchronized (mLock) { - final String methodStr = "setScanSsid"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setScanSsid(enable); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setKeyMgmt(int keyMgmtMask) { - synchronized (mLock) { - final String methodStr = "setKeyMgmt"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status; - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - - if (getV1_3StaNetwork() != null) { - /* Support for new key management types: - * WAPI_PSK, WAPI_CERT - * Requires HAL v1.3 or higher */ - status = getV1_3StaNetwork().setKeyMgmt_1_3(keyMgmtMask); - } else if (iSupplicantStaNetworkV12 != null) { - /* Support for new key management types; - * SAE, OWE, WPA_PSK_SHA256, WPA_EAP_SHA256 - * Requires HAL v1.2 or higher */ - status = iSupplicantStaNetworkV12.setKeyMgmt_1_2(keyMgmtMask); - } else { - status = mISupplicantStaNetwork.setKeyMgmt(keyMgmtMask); - } - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setProto(int protoMask) { - synchronized (mLock) { - final String methodStr = "setProto"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status; - if (null != getV1_3StaNetwork()) { - /* Support for new proto types: WAPI - * Requires HAL v1.3 or higher - */ - status = getV1_3StaNetwork().setProto_1_3(protoMask); - } else { - status = mISupplicantStaNetwork.setProto(protoMask); - } - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setAuthAlg(int authAlgMask) { - synchronized (mLock) { - final String methodStr = "setAuthAlg"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status; - if (null != getV1_3StaNetwork()) { - /* Support for SAE Authentication algorithm requires HAL v1.3 or higher */ - status = getV1_3StaNetwork().setAuthAlg_1_3(authAlgMask); - } else { - status = mISupplicantStaNetwork.setAuthAlg(authAlgMask); - } - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setGroupCipher(int groupCipherMask) { - synchronized (mLock) { - final String methodStr = "setGroupCipher"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status; - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (null != getV1_3StaNetwork()) { - /* Support for new key group cipher types for SMS4 - * Requires HAL v1.3 or higher */ - status = getV1_3StaNetwork().setGroupCipher_1_3(groupCipherMask); - } else if (iSupplicantStaNetworkV12 != null) { - /* Support for new key group cipher types for SuiteB - * Requires HAL v1.2 or higher */ - status = iSupplicantStaNetworkV12.setGroupCipher_1_2(groupCipherMask); - } else { - // Clear GCMP_256 group cipher which is not supported before v1.2 - groupCipherMask &= ~android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupCipherMask.GCMP_256; - status = mISupplicantStaNetwork.setGroupCipher( - groupCipherMask); - } - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean enableTlsSuiteBEapPhase1Param(boolean enable) { - synchronized (mLock) { - final String methodStr = "setEapPhase1Params"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (iSupplicantStaNetworkV12 != null) { - /* Support for for SuiteB - * Requires HAL v1.2 or higher */ - SupplicantStatus status = iSupplicantStaNetworkV12 - .enableTlsSuiteBEapPhase1Param(enable); - return checkStatusAndLogFailure(status, methodStr); - } else { - Log.e(TAG, "Supplicant HAL version does not support " + methodStr); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean enableSuiteBEapOpenSslCiphers() { - synchronized (mLock) { - final String methodStr = "setEapOpenSslCiphers"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (iSupplicantStaNetworkV12 != null) { - /* Support for for SuiteB - * Requires HAL v1.2 or higher */ - SupplicantStatus status = iSupplicantStaNetworkV12 - .enableSuiteBEapOpenSslCiphers(); - return checkStatusAndLogFailure(status, methodStr); - } else { - Log.e(TAG, "Supplicant HAL version does not support " + methodStr); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setPairwiseCipher(int pairwiseCipherMask) { - synchronized (mLock) { - final String methodStr = "setPairwiseCipher"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status; - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (null != getV1_3StaNetwork()) { - /* Support for new key pairwise cipher types for SMS4 - * Requires HAL v1.3 or higher */ - status = getV1_3StaNetwork().setPairwiseCipher_1_3(pairwiseCipherMask); - } else if (iSupplicantStaNetworkV12 != null) { - /* Support for new key pairwise cipher types for SuiteB - * Requires HAL v1.2 or higher */ - status = iSupplicantStaNetworkV12.setPairwiseCipher_1_2(pairwiseCipherMask); - } else { - // Clear GCMP_256 pairwise cipher which is not supported before v1.2 - pairwiseCipherMask &= ~android.hardware.wifi.supplicant.V1_2 - .ISupplicantStaNetwork.PairwiseCipherMask.GCMP_256; - status = - mISupplicantStaNetwork.setPairwiseCipher(pairwiseCipherMask); - } - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setGroupMgmtCipher(int groupMgmtCipherMask) { - synchronized (mLock) { - final String methodStr = "setGroupMgmtCipher"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (iSupplicantStaNetworkV12 != null) { - /* Support for new key pairwise cipher types for SuiteB - * Requires HAL v1.2 or higher */ - SupplicantStatus status = iSupplicantStaNetworkV12 - .setGroupMgmtCipher(groupMgmtCipherMask); - return checkStatusAndLogFailure(status, methodStr); - } else { - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setPskPassphrase(String psk) { - synchronized (mLock) { - final String methodStr = "setPskPassphrase"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setPskPassphrase(psk); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setPsk(byte[] psk) { - synchronized (mLock) { - final String methodStr = "setPsk"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setPsk(psk); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } catch (ArrayIndexOutOfBoundsException e) { - Log.e(TAG, "ISupplicantStaNetwork." + methodStr + " failed: " + e); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setWepKey(int keyIdx, java.util.ArrayList<Byte> wepKey) { - synchronized (mLock) { - final String methodStr = "setWepKey"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setWepKey(keyIdx, wepKey); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setWepTxKeyIdx(int keyIdx) { - synchronized (mLock) { - final String methodStr = "setWepTxKeyIdx"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setWepTxKeyIdx(keyIdx); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setRequirePmf(boolean enable) { - synchronized (mLock) { - final String methodStr = "setRequirePmf"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setRequirePmf(enable); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setUpdateIdentifier(int identifier) { - synchronized (mLock) { - final String methodStr = "setUpdateIdentifier"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setUpdateIdentifier(identifier); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setWapiCertSuite(String certSuite) { - synchronized (mLock) { - final String methodStr = "setWapiCertSuite"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - if (null != getV1_3StaNetwork()) { - /* Requires HAL v1.3 or higher */ - SupplicantStatus status = getV1_3StaNetwork().setWapiCertSuite(certSuite); - return checkStatusAndLogFailure(status, methodStr); - } else { - Log.e(TAG, "Cannot get ISupplicantStaNetwork V1.3"); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapMethod(int method) { - synchronized (mLock) { - final String methodStr = "setEapMethod"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapMethod(method); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapPhase2Method(int method) { - synchronized (mLock) { - final String methodStr = "setEapPhase2Method"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapPhase2Method(method); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapIdentity(java.util.ArrayList<Byte> identity) { - synchronized (mLock) { - final String methodStr = "setEapIdentity"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapIdentity(identity); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapAnonymousIdentity(java.util.ArrayList<Byte> identity) { - synchronized (mLock) { - final String methodStr = "setEapAnonymousIdentity"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapAnonymousIdentity(identity); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapPassword(java.util.ArrayList<Byte> password) { - synchronized (mLock) { - final String methodStr = "setEapPassword"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapPassword(password); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapCACert(String path) { - synchronized (mLock) { - final String methodStr = "setEapCACert"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapCACert(path); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapCAPath(String path) { - synchronized (mLock) { - final String methodStr = "setEapCAPath"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapCAPath(path); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapClientCert(String path) { - synchronized (mLock) { - final String methodStr = "setEapClientCert"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapClientCert(path); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapPrivateKeyId(String id) { - synchronized (mLock) { - final String methodStr = "setEapPrivateKeyId"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapPrivateKeyId(id); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapSubjectMatch(String match) { - synchronized (mLock) { - final String methodStr = "setEapSubjectMatch"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapSubjectMatch(match); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapAltSubjectMatch(String match) { - synchronized (mLock) { - final String methodStr = "setEapAltSubjectMatch"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapAltSubjectMatch(match); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapEngine(boolean enable) { - synchronized (mLock) { - final String methodStr = "setEapEngine"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapEngine(enable); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapEngineID(String id) { - synchronized (mLock) { - final String methodStr = "setEapEngineID"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapEngineID(id); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapDomainSuffixMatch(String match) { - synchronized (mLock) { - final String methodStr = "setEapDomainSuffixMatch"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setEapDomainSuffixMatch(match); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapProactiveKeyCaching(boolean enable) { - synchronized (mLock) { - final String methodStr = "setEapProactiveKeyCaching"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setProactiveKeyCaching(enable); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setIdStr(String idString) { - synchronized (mLock) { - final String methodStr = "setIdStr"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.setIdStr(idString); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setSaePassword(String saePassword) { - synchronized (mLock) { - final String methodStr = "setSaePassword"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (iSupplicantStaNetworkV12 != null) { - /* Support for SAE Requires HAL v1.2 or higher */ - SupplicantStatus status = iSupplicantStaNetworkV12.setSaePassword(saePassword); - return checkStatusAndLogFailure(status, methodStr); - } else { - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setEapErp(boolean enable) { - synchronized (mLock) { - final String methodStr = "setEapErp"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - iSupplicantStaNetworkV13; - - iSupplicantStaNetworkV13 = getV1_3StaNetwork(); - if (iSupplicantStaNetworkV13 != null) { - /* Support for set ERP Requires HAL v1.3 or higher */ - SupplicantStatus status = iSupplicantStaNetworkV13.setEapErp(enable); - return checkStatusAndLogFailure(status, methodStr); - } else { - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getSsid() { - synchronized (mLock) { - final String methodStr = "getSsid"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getSsid((SupplicantStatus status, - java.util.ArrayList<Byte> ssidValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mSsid = ssidValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getBssid() { - synchronized (mLock) { - final String methodStr = "getBssid"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getBssid((SupplicantStatus status, - byte[/* 6 */] bssidValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mBssid = bssidValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getScanSsid() { - synchronized (mLock) { - final String methodStr = "getScanSsid"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getScanSsid((SupplicantStatus status, - boolean enabledValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mScanSsid = enabledValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getKeyMgmt() { - synchronized (mLock) { - final String methodStr = "getKeyMgmt"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - if (getV1_3StaNetwork() != null) { - return getKeyMgmt_1_3(); - } else { - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getKeyMgmt((SupplicantStatus status, - int keyMgmtMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mKeyMgmtMask = keyMgmtMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - } - - private boolean getKeyMgmt_1_3() { - synchronized (mLock) { - final String methodStr = "getKeyMgmt_1_3"; - try { - MutableBoolean statusOk = new MutableBoolean(false); - getV1_3StaNetwork().getKeyMgmt_1_3((SupplicantStatus status, - int keyMgmtMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mKeyMgmtMask = keyMgmtMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getProto() { - synchronized (mLock) { - final String methodStr = "getProto"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - if (getV1_3StaNetwork() != null) { - return getProto_1_3(); - } else { - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getProto( - (SupplicantStatus status, int protoMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mProtoMask = protoMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - } - - private boolean getProto_1_3() { - synchronized (mLock) { - final String methodStr = "getProto_1_3"; - try { - MutableBoolean statusOk = new MutableBoolean(false); - getV1_3StaNetwork().getProto((SupplicantStatus status, int protoMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mProtoMask = protoMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getAuthAlg() { - synchronized (mLock) { - final String methodStr = "getAuthAlg"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - if (getV1_3StaNetwork() != null) { - return getAuthAlg_1_3(); - } - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getAuthAlg((SupplicantStatus status, - int authAlgMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mAuthAlgMask = authAlgMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - private boolean getAuthAlg_1_3() { - final String methodStr = "getAuthAlg_1_3"; - try { - MutableBoolean statusOk = new MutableBoolean(false); - getV1_3StaNetwork().getAuthAlg_1_3((SupplicantStatus status, - int authAlgMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mAuthAlgMask = authAlgMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getGroupCipher() { - synchronized (mLock) { - final String methodStr = "getGroupCipher"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - if (getV1_3StaNetwork() != null) { - return getGroupCipher_1_3(); - } else { - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getGroupCipher((SupplicantStatus status, - int groupCipherMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mGroupCipherMask = groupCipherMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - } - - private boolean getGroupCipher_1_3() { - synchronized (mLock) { - final String methodStr = "getGroupCipher_1_3"; - try { - MutableBoolean statusOk = new MutableBoolean(false); - getV1_3StaNetwork().getGroupCipher((SupplicantStatus status, - int groupCipherMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mGroupCipherMask = groupCipherMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getPairwiseCipher() { - synchronized (mLock) { - final String methodStr = "getPairwiseCipher"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - if (getV1_3StaNetwork() != null) { - return getPairwiseCipher_1_3(); - } else { - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getPairwiseCipher((SupplicantStatus status, - int pairwiseCipherMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mPairwiseCipherMask = pairwiseCipherMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - } - - private boolean getPairwiseCipher_1_3() { - synchronized (mLock) { - final String methodStr = "getPairwiseCipher_1_3"; - try { - MutableBoolean statusOk = new MutableBoolean(false); - getV1_3StaNetwork().getPairwiseCipher((SupplicantStatus status, - int pairwiseCipherMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mPairwiseCipherMask = pairwiseCipherMaskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getGroupMgmtCipher() { - synchronized (mLock) { - final String methodStr = "getGroupMgmtCipher"; - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (iSupplicantStaNetworkV12 != null) { - MutableBoolean statusOk = new MutableBoolean(false); - iSupplicantStaNetworkV12.getGroupMgmtCipher((SupplicantStatus status, - int groupMgmtCipherMaskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mGroupMgmtCipherMask = groupMgmtCipherMaskValue; - } - checkStatusAndLogFailure(status, methodStr); - }); - return statusOk.value; - } else { - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getPskPassphrase() { - synchronized (mLock) { - final String methodStr = "getPskPassphrase"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getPskPassphrase((SupplicantStatus status, - String pskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mPskPassphrase = pskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getSaePassword() { - synchronized (mLock) { - final String methodStr = "getSaePassword"; - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (iSupplicantStaNetworkV12 != null) { - MutableBoolean statusOk = new MutableBoolean(false); - iSupplicantStaNetworkV12.getSaePassword((SupplicantStatus status, - String saePassword) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mSaePassword = saePassword; - } - checkStatusAndLogFailure(status, methodStr); - }); - return statusOk.value; - } else { - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getPsk() { - synchronized (mLock) { - final String methodStr = "getPsk"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getPsk((SupplicantStatus status, byte[] pskValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mPsk = pskValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getWepKey(int keyIdx) { - synchronized (mLock) { - final String methodStr = "keyIdx"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getWepKey(keyIdx, (SupplicantStatus status, - java.util.ArrayList<Byte> wepKeyValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mWepKey = wepKeyValue; - } else { - Log.e(TAG, methodStr + ", failed: " + status.debugMessage); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getWepTxKeyIdx() { - synchronized (mLock) { - final String methodStr = "getWepTxKeyIdx"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getWepTxKeyIdx((SupplicantStatus status, - int keyIdxValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mWepTxKeyIdx = keyIdxValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getRequirePmf() { - synchronized (mLock) { - final String methodStr = "getRequirePmf"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getRequirePmf((SupplicantStatus status, - boolean enabledValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mRequirePmf = enabledValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getWapiCertSuite() { - synchronized (mLock) { - final String methodStr = "getWapiCertSuite"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - iSupplicantStaNetworkV13; - iSupplicantStaNetworkV13 = getV1_3StaNetwork(); - if (iSupplicantStaNetworkV13 != null) { - MutableBoolean statusOk = new MutableBoolean(false); - iSupplicantStaNetworkV13.getWapiCertSuite((SupplicantStatus status, - String suiteValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - mWapiCertSuite = suiteValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } else { - Log.e(TAG, "Cannot get ISupplicantStaNetwork V1.3"); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapMethod() { - synchronized (mLock) { - final String methodStr = "getEapMethod"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapMethod((SupplicantStatus status, - int methodValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapMethod = methodValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapPhase2Method() { - synchronized (mLock) { - final String methodStr = "getEapPhase2Method"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapPhase2Method((SupplicantStatus status, - int methodValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapPhase2Method = methodValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapIdentity() { - synchronized (mLock) { - final String methodStr = "getEapIdentity"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapIdentity((SupplicantStatus status, - ArrayList<Byte> identityValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapIdentity = identityValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapAnonymousIdentity() { - synchronized (mLock) { - final String methodStr = "getEapAnonymousIdentity"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapAnonymousIdentity((SupplicantStatus status, - ArrayList<Byte> identityValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapAnonymousIdentity = identityValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * A wrapping method for getEapAnonymousIdentity(). - * This get anonymous identity from supplicant and returns it as a string. - * - * @return anonymous identity string if succeeds, null otherwise. - */ - public String fetchEapAnonymousIdentity() { - synchronized (mLock) { - if (!getEapAnonymousIdentity()) { - return null; - } - return NativeUtil.stringFromByteArrayList(mEapAnonymousIdentity); - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapPassword() { - synchronized (mLock) { - final String methodStr = "getEapPassword"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapPassword((SupplicantStatus status, - ArrayList<Byte> passwordValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapPassword = passwordValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapCACert() { - synchronized (mLock) { - final String methodStr = "getEapCACert"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapCACert((SupplicantStatus status, String pathValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapCACert = pathValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapCAPath() { - synchronized (mLock) { - final String methodStr = "getEapCAPath"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapCAPath((SupplicantStatus status, String pathValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapCAPath = pathValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapClientCert() { - synchronized (mLock) { - final String methodStr = "getEapClientCert"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapClientCert((SupplicantStatus status, - String pathValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapClientCert = pathValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapPrivateKeyId() { - synchronized (mLock) { - final String methodStr = "getEapPrivateKeyId"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapPrivateKeyId((SupplicantStatus status, - String idValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapPrivateKeyId = idValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapSubjectMatch() { - synchronized (mLock) { - final String methodStr = "getEapSubjectMatch"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapSubjectMatch((SupplicantStatus status, - String matchValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapSubjectMatch = matchValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapAltSubjectMatch() { - synchronized (mLock) { - final String methodStr = "getEapAltSubjectMatch"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapAltSubjectMatch((SupplicantStatus status, - String matchValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapAltSubjectMatch = matchValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapEngine() { - synchronized (mLock) { - final String methodStr = "getEapEngine"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapEngine((SupplicantStatus status, - boolean enabledValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapEngine = enabledValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapEngineID() { - synchronized (mLock) { - final String methodStr = "getEapEngineID"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapEngineID((SupplicantStatus status, String idValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapEngineID = idValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getEapDomainSuffixMatch() { - synchronized (mLock) { - final String methodStr = "getEapDomainSuffixMatch"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getEapDomainSuffixMatch((SupplicantStatus status, - String matchValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mEapDomainSuffixMatch = matchValue; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getIdStr() { - synchronized (mLock) { - final String methodStr = "getIdStr"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - MutableBoolean statusOk = new MutableBoolean(false); - mISupplicantStaNetwork.getIdStr((SupplicantStatus status, String idString) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - this.mIdStr = idString; - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean enable(boolean noConnect) { - synchronized (mLock) { - final String methodStr = "enable"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.enable(noConnect); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean disable() { - synchronized (mLock) { - final String methodStr = "disable"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.disable(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Trigger a connection to this network. - * - * @return true if it succeeds, false otherwise. - */ - public boolean select() { - synchronized (mLock) { - final String methodStr = "select"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.select(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Send GSM auth response. - * - * @param paramsStr Response params as a string. - * @return true if succeeds, false otherwise. - */ - public boolean sendNetworkEapSimGsmAuthResponse(String paramsStr) { - synchronized (mLock) { - try { - Matcher match = GSM_AUTH_RESPONSE_PARAMS_PATTERN.matcher(paramsStr); - ArrayList<ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams> params = - new ArrayList<>(); - while (match.find()) { - if (match.groupCount() != 2) { - Log.e(TAG, "Malformed gsm auth response params: " + paramsStr); - return false; - } - ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams param = - new ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams(); - byte[] kc = NativeUtil.hexStringToByteArray(match.group(1)); - if (kc == null || kc.length != param.kc.length) { - Log.e(TAG, "Invalid kc value: " + match.group(1)); - return false; - } - byte[] sres = NativeUtil.hexStringToByteArray(match.group(2)); - if (sres == null || sres.length != param.sres.length) { - Log.e(TAG, "Invalid sres value: " + match.group(2)); - return false; - } - System.arraycopy(kc, 0, param.kc, 0, param.kc.length); - System.arraycopy(sres, 0, param.sres, 0, param.sres.length); - params.add(param); - } - // The number of kc/sres pairs can either be 2 or 3 depending on the request. - if (params.size() > 3 || params.size() < 2) { - Log.e(TAG, "Malformed gsm auth response params: " + paramsStr); - return false; - } - return sendNetworkEapSimGsmAuthResponse(params); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + paramsStr, e); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean sendNetworkEapSimGsmAuthResponse( - ArrayList<ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams> params) { - synchronized (mLock) { - final String methodStr = "sendNetworkEapSimGsmAuthResponse"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = - mISupplicantStaNetwork.sendNetworkEapSimGsmAuthResponse(params); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - public boolean sendNetworkEapSimGsmAuthFailure() { - synchronized (mLock) { - final String methodStr = "sendNetworkEapSimGsmAuthFailure"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.sendNetworkEapSimGsmAuthFailure(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Send UMTS auth response. - * - * @param paramsStr Response params as a string. - * @return true if succeeds, false otherwise. - */ - public boolean sendNetworkEapSimUmtsAuthResponse(String paramsStr) { - synchronized (mLock) { - try { - Matcher match = UMTS_AUTH_RESPONSE_PARAMS_PATTERN.matcher(paramsStr); - if (!match.find() || match.groupCount() != 3) { - Log.e(TAG, "Malformed umts auth response params: " + paramsStr); - return false; - } - ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams params = - new ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams(); - byte[] ik = NativeUtil.hexStringToByteArray(match.group(1)); - if (ik == null || ik.length != params.ik.length) { - Log.e(TAG, "Invalid ik value: " + match.group(1)); - return false; - } - byte[] ck = NativeUtil.hexStringToByteArray(match.group(2)); - if (ck == null || ck.length != params.ck.length) { - Log.e(TAG, "Invalid ck value: " + match.group(2)); - return false; - } - byte[] res = NativeUtil.hexStringToByteArray(match.group(3)); - if (res == null || res.length == 0) { - Log.e(TAG, "Invalid res value: " + match.group(3)); - return false; - } - System.arraycopy(ik, 0, params.ik, 0, params.ik.length); - System.arraycopy(ck, 0, params.ck, 0, params.ck.length); - for (byte b : res) { - params.res.add(b); - } - return sendNetworkEapSimUmtsAuthResponse(params); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + paramsStr, e); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean sendNetworkEapSimUmtsAuthResponse( - ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams params) { - synchronized (mLock) { - final String methodStr = "sendNetworkEapSimUmtsAuthResponse"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = - mISupplicantStaNetwork.sendNetworkEapSimUmtsAuthResponse(params); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Send UMTS auts response. - * - * @param paramsStr Response params as a string. - * @return true if succeeds, false otherwise. - */ - public boolean sendNetworkEapSimUmtsAutsResponse(String paramsStr) { - synchronized (mLock) { - try { - Matcher match = UMTS_AUTS_RESPONSE_PARAMS_PATTERN.matcher(paramsStr); - if (!match.find() || match.groupCount() != 1) { - Log.e(TAG, "Malformed umts auts response params: " + paramsStr); - return false; - } - byte[] auts = NativeUtil.hexStringToByteArray(match.group(1)); - if (auts == null || auts.length != 14) { - Log.e(TAG, "Invalid auts value: " + match.group(1)); - return false; - } - return sendNetworkEapSimUmtsAutsResponse(auts); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + paramsStr, e); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean sendNetworkEapSimUmtsAutsResponse(byte[/* 14 */] auts) { - synchronized (mLock) { - final String methodStr = "sendNetworkEapSimUmtsAutsResponse"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = - mISupplicantStaNetwork.sendNetworkEapSimUmtsAutsResponse(auts); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - public boolean sendNetworkEapSimUmtsAuthFailure() { - synchronized (mLock) { - final String methodStr = "sendNetworkEapSimUmtsAuthFailure"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status = mISupplicantStaNetwork.sendNetworkEapSimUmtsAuthFailure(); - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Method to mock out the V1_1 ISupplicantStaNetwork retrieval in unit tests. - * - * @return 1.1 ISupplicantStaNetwork object if the device is running the 1.1 supplicant hal - * service, null otherwise. - */ - protected android.hardware.wifi.supplicant.V1_1.ISupplicantStaNetwork - getSupplicantStaNetworkForV1_1Mockable() { - if (mISupplicantStaNetwork == null) return null; - return android.hardware.wifi.supplicant.V1_1.ISupplicantStaNetwork.castFrom( - mISupplicantStaNetwork); - } - - /** - * Method to mock out the V1_2 ISupplicantStaNetwork retrieval in unit tests. - * - * @return 1.2 ISupplicantStaNetwork object if the device is running the 1.2 supplicant hal - * service, null otherwise. - */ - protected android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - getSupplicantStaNetworkForV1_2Mockable() { - if (mISupplicantStaNetwork == null) return null; - return android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.castFrom( - mISupplicantStaNetwork); - } - - /** - * Method to mock out the V1_3 ISupplicantStaNetwork retrieval in unit tests. - * - * @return 1.3 ISupplicantStaNetwork object if the device is running the 1.3 supplicant hal - * service, null otherwise. - */ - protected android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - getSupplicantStaNetworkForV1_3Mockable() { - if (mISupplicantStaNetwork == null) return null; - return android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.castFrom( - mISupplicantStaNetwork); - } - - /** - * Send eap identity response. - * - * @param identityStr identity used for EAP-Identity - * @param encryptedIdentityStr encrypted identity used for EAP-AKA/EAP-SIM - * @return true if succeeds, false otherwise. - */ - public boolean sendNetworkEapIdentityResponse(String identityStr, - String encryptedIdentityStr) { - synchronized (mLock) { - try { - ArrayList<Byte> unencryptedIdentity = - NativeUtil.stringToByteArrayList(identityStr); - ArrayList<Byte> encryptedIdentity = null; - if (!TextUtils.isEmpty(encryptedIdentityStr)) { - encryptedIdentity = NativeUtil.stringToByteArrayList(encryptedIdentityStr); - } - return sendNetworkEapIdentityResponse(unencryptedIdentity, encryptedIdentity); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + identityStr + "," + encryptedIdentityStr, e); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean sendNetworkEapIdentityResponse(ArrayList<Byte> unencryptedIdentity, - ArrayList<Byte> encryptedIdentity) { - synchronized (mLock) { - final String methodStr = "sendNetworkEapIdentityResponse"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - try { - SupplicantStatus status; - android.hardware.wifi.supplicant.V1_1.ISupplicantStaNetwork - iSupplicantStaNetworkV11 = - getSupplicantStaNetworkForV1_1Mockable(); - - if (iSupplicantStaNetworkV11 != null && encryptedIdentity != null) { - status = iSupplicantStaNetworkV11.sendNetworkEapIdentityResponse_1_1( - unencryptedIdentity, encryptedIdentity); - } else { - status = mISupplicantStaNetwork.sendNetworkEapIdentityResponse( - unencryptedIdentity); - } - - return checkStatusAndLogFailure(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean setOcsp(@Ocsp int ocsp) { - synchronized (mLock) { - final String methodStr = "setOcsp"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - - int halOcspValue = android.hardware.wifi.supplicant.V1_3.OcspType.NONE; - switch (ocsp) { - case WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS: - halOcspValue = android.hardware.wifi.supplicant.V1_3 - .OcspType.REQUEST_CERT_STATUS; - break; - case WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS: - halOcspValue = android.hardware.wifi.supplicant.V1_3 - .OcspType.REQUIRE_CERT_STATUS; - break; - case WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS: - halOcspValue = android.hardware.wifi.supplicant.V1_3 - .OcspType.REQUIRE_ALL_CERTS_STATUS; - break; - } - try { - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - iSupplicantStaNetworkV13; - - iSupplicantStaNetworkV13 = getV1_3StaNetwork(); - if (iSupplicantStaNetworkV13 != null) { - /* Support for OCSP Requires HAL v1.3 or higher */ - SupplicantStatus status = iSupplicantStaNetworkV13 - .setOcsp(halOcspValue); - return checkStatusAndLogFailure(status, methodStr); - } else { - Log.e(TAG, "Cannot get ISupplicantStaNetwork V1.3"); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private boolean getOcsp() { - synchronized (mLock) { - final String methodStr = "getOcsp"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - - try { - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - iSupplicantStaNetworkV13; - iSupplicantStaNetworkV13 = getV1_3StaNetwork(); - if (iSupplicantStaNetworkV13 != null) { - MutableBoolean statusOk = new MutableBoolean(false); - iSupplicantStaNetworkV13.getOcsp((SupplicantStatus status, - int halOcspValue) -> { - statusOk.value = status.code == SupplicantStatusCode.SUCCESS; - if (statusOk.value) { - mOcsp = WifiEnterpriseConfig.OCSP_NONE; - switch (halOcspValue) { - case android.hardware.wifi.supplicant.V1_3 - .OcspType.REQUEST_CERT_STATUS: - mOcsp = WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS; - break; - case android.hardware.wifi.supplicant.V1_3 - .OcspType.REQUIRE_CERT_STATUS: - mOcsp = WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS; - break; - case android.hardware.wifi.supplicant.V1_3 - .OcspType.REQUIRE_ALL_CERTS_STATUS: - mOcsp = WifiEnterpriseConfig - .OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS; - break; - default: - Log.e(TAG, "Invalid HAL OCSP value " + halOcspValue); - break; - } - } else { - checkStatusAndLogFailure(status, methodStr); - } - }); - return statusOk.value; - } else { - Log.e(TAG, "Cannot get ISupplicantStaNetwork V1.3"); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - public boolean setPmkCache(ArrayList<Byte> serializedEntry) { - synchronized (mLock) { - final String methodStr = "setPmkCache"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; - - try { - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - iSupplicantStaNetworkV13; - - iSupplicantStaNetworkV13 = getV1_3StaNetwork(); - if (iSupplicantStaNetworkV13 != null) { - SupplicantStatus status = iSupplicantStaNetworkV13 - .setPmkCache(serializedEntry); - return checkStatusAndLogFailure(status, methodStr); - } else { - Log.e(TAG, "Cannot get ISupplicantStaNetwork V1.3"); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Retrieve the NFC token for this network. - * - * @return Hex string corresponding to the NFC token or null for failure. - */ - public String getWpsNfcConfigurationToken() { - synchronized (mLock) { - ArrayList<Byte> token = getWpsNfcConfigurationTokenInternal(); - if (token == null) { - return null; - } - return NativeUtil.hexStringFromByteArray(NativeUtil.byteArrayFromArrayList(token)); - } - } - - /** See ISupplicantStaNetwork.hal for documentation */ - private ArrayList<Byte> getWpsNfcConfigurationTokenInternal() { - synchronized (mLock) { - final String methodStr = "getWpsNfcConfigurationToken"; - if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return null; - final Mutable<ArrayList<Byte>> gotToken = new Mutable<>(); - try { - mISupplicantStaNetwork.getWpsNfcConfigurationToken( - (SupplicantStatus status, ArrayList<Byte> token) -> { - if (checkStatusAndLogFailure(status, methodStr)) { - gotToken.value = token; - } - }); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - return gotToken.value; - } - } - - /** - * Returns true if provided status code is SUCCESS, logs debug message and returns false - * otherwise - */ - private boolean checkStatusAndLogFailure(SupplicantStatus status, final String methodStr) { - synchronized (mLock) { - if (status.code != SupplicantStatusCode.SUCCESS) { - Log.e(TAG, "ISupplicantStaNetwork." + methodStr + " failed: " + status); - return false; - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "ISupplicantStaNetwork." + methodStr + " succeeded"); - } - return true; - } - } - } - - /** - * Helper function to log callbacks. - */ - private void logCallback(final String methodStr) { - synchronized (mLock) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "ISupplicantStaNetworkCallback." + methodStr + " received"); - } - } - } - - /** - * Returns false if ISupplicantStaNetwork is null, and logs failure of methodStr - */ - private boolean checkISupplicantStaNetworkAndLogFailure(final String methodStr) { - synchronized (mLock) { - if (mISupplicantStaNetwork == null) { - Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaNetwork is null"); - return false; - } - return true; - } - } - - private void handleRemoteException(RemoteException e, String methodStr) { - synchronized (mLock) { - mISupplicantStaNetwork = null; - Log.e(TAG, "ISupplicantStaNetwork." + methodStr + " failed with exception", e); - } - } - - /** - * Adds FT flags for networks if the device supports it. - */ - private BitSet addFastTransitionFlags(BitSet keyManagementFlags) { - synchronized (mLock) { - if (!mContext.getResources().getBoolean( - R.bool.config_wifi_fast_bss_transition_enabled)) { - return keyManagementFlags; - } - BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); - if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - modifiedFlags.set(WifiConfiguration.KeyMgmt.FT_PSK); - } - if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { - modifiedFlags.set(WifiConfiguration.KeyMgmt.FT_EAP); - } - return modifiedFlags; - } - } - - /** - * Removes FT flags for networks if the device supports it. - */ - private BitSet removeFastTransitionFlags(BitSet keyManagementFlags) { - synchronized (mLock) { - BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); - modifiedFlags.clear(WifiConfiguration.KeyMgmt.FT_PSK); - modifiedFlags.clear(WifiConfiguration.KeyMgmt.FT_EAP); - return modifiedFlags; - } - } - - /** - * Adds SHA256 key management flags for networks. - */ - private BitSet addSha256KeyMgmtFlags(BitSet keyManagementFlags) { - synchronized (mLock) { - BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); - android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - iSupplicantStaNetworkV12; - iSupplicantStaNetworkV12 = getV1_2StaNetwork(); - if (iSupplicantStaNetworkV12 == null) { - // SHA256 key management requires HALv1.2 or higher - return modifiedFlags; - } - - if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - modifiedFlags.set(WifiConfiguration.KeyMgmt.WPA_PSK_SHA256); - } - if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { - modifiedFlags.set(WifiConfiguration.KeyMgmt.WPA_EAP_SHA256); - } - return modifiedFlags; - } - } - - /** - * Removes SHA256 key management flags for networks. - */ - private BitSet removeSha256KeyMgmtFlags(BitSet keyManagementFlags) { - synchronized (mLock) { - BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); - modifiedFlags.clear(WifiConfiguration.KeyMgmt.WPA_PSK_SHA256); - modifiedFlags.clear(WifiConfiguration.KeyMgmt.WPA_EAP_SHA256); - return modifiedFlags; - } - } - - /** - * Creates the JSON encoded network extra using the map of string key, value pairs. - */ - public static String createNetworkExtra(Map<String, String> values) { - final String encoded; - try { - encoded = URLEncoder.encode(new JSONObject(values).toString(), "UTF-8"); - } catch (NullPointerException e) { - Log.e(TAG, "Unable to serialize networkExtra: " + e.toString()); - return null; - } catch (UnsupportedEncodingException e) { - Log.e(TAG, "Unable to serialize networkExtra: " + e.toString()); - return null; - } - return encoded; - } - - /** - * Parse the network extra JSON encoded string to a map of string key, value pairs. - */ - public static Map<String, String> parseNetworkExtra(String encoded) { - if (TextUtils.isEmpty(encoded)) { - return null; - } - try { - // This method reads a JSON dictionary that was written by setNetworkExtra(). However, - // on devices that upgraded from Marshmallow, it may encounter a legacy value instead - - // an FQDN stored as a plain string. If such a value is encountered, the JSONObject - // constructor will thrown a JSONException and the method will return null. - final JSONObject json = new JSONObject(URLDecoder.decode(encoded, "UTF-8")); - final Map<String, String> values = new HashMap<>(); - final Iterator<?> it = json.keys(); - while (it.hasNext()) { - final String key = (String) it.next(); - final Object value = json.get(key); - if (value instanceof String) { - values.put(key, (String) value); - } - } - return values; - } catch (UnsupportedEncodingException e) { - Log.e(TAG, "Unable to deserialize networkExtra: " + e.toString()); - return null; - } catch (JSONException e) { - // This is not necessarily an error. This exception will also occur if we encounter a - // legacy FQDN stored as a plain string. We want to return null in this case as no JSON - // dictionary of extras was found. - return null; - } - } - - private class SupplicantStaNetworkHalCallback extends ISupplicantStaNetworkCallback.Stub { - /** - * Current configured network's framework network id. - */ - private final int mFramewokNetworkId; - /** - * Current configured network's ssid. - */ - private final String mSsid; - - SupplicantStaNetworkHalCallback(int framewokNetworkId, String ssid) { - mFramewokNetworkId = framewokNetworkId; - mSsid = ssid; - } - - @Override - public void onNetworkEapSimGsmAuthRequest( - ISupplicantStaNetworkCallback.NetworkRequestEapSimGsmAuthParams params) { - synchronized (mLock) { - logCallback("onNetworkEapSimGsmAuthRequest"); - String[] data = new String[params.rands.size()]; - int i = 0; - for (byte[] rand : params.rands) { - data[i++] = NativeUtil.hexStringFromByteArray(rand); - } - mWifiMonitor.broadcastNetworkGsmAuthRequestEvent( - mIfaceName, mFramewokNetworkId, mSsid, data); - } - } - - @Override - public void onNetworkEapSimUmtsAuthRequest( - ISupplicantStaNetworkCallback.NetworkRequestEapSimUmtsAuthParams params) { - synchronized (mLock) { - logCallback("onNetworkEapSimUmtsAuthRequest"); - String randHex = NativeUtil.hexStringFromByteArray(params.rand); - String autnHex = NativeUtil.hexStringFromByteArray(params.autn); - String[] data = {randHex, autnHex}; - mWifiMonitor.broadcastNetworkUmtsAuthRequestEvent( - mIfaceName, mFramewokNetworkId, mSsid, data); - } - } - - @Override - public void onNetworkEapIdentityRequest() { - synchronized (mLock) { - logCallback("onNetworkEapIdentityRequest"); - mWifiMonitor.broadcastNetworkIdentityRequestEvent( - mIfaceName, mFramewokNetworkId, mSsid); - } - } - } -} diff --git a/service/java/com/android/server/wifi/SupplicantStateTracker.java b/service/java/com/android/server/wifi/SupplicantStateTracker.java deleted file mode 100644 index 19540d426..000000000 --- a/service/java/com/android/server/wifi/SupplicantStateTracker.java +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import android.content.Context; -import android.content.Intent; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.os.BatteryStatsManager; -import android.os.Handler; -import android.os.Message; -import android.os.Parcelable; -import android.os.UserHandle; -import android.util.Log; - -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Tracks the state changes in supplicant and provides functionality - * that is based on these state changes: - * - detect a failed WPA handshake that loops indefinitely - * - authentication failure handling - */ -public class SupplicantStateTracker extends StateMachine { - - private static final String TAG = "SupplicantStateTracker"; - private static boolean DBG = false; - private final WifiConfigManager mWifiConfigManager; - private FrameworkFacade mFacade; - private final BatteryStatsManager mBatteryStatsManager; - /* Indicates authentication failure in supplicant broadcast. - * TODO: enhance auth failure reporting to include notification - * for all type of failures: EAP, WPS & WPA networks */ - private boolean mAuthFailureInSupplicantBroadcast = false; - - /* Authentication failure reason - * see {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_NONE}, - * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_TIMEOUT}, - * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_WRONG_PSWD}, - * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_EAP_FAILURE} - */ - private int mAuthFailureReason; - - /* Maximum retries on a authentication failure notification */ - private static final int MAX_RETRIES_ON_AUTHENTICATION_FAILURE = 2; - - /* Maximum retries on assoc rejection events */ - private static final int MAX_RETRIES_ON_ASSOCIATION_REJECT = 16; - - private final Context mContext; - - private final State mUninitializedState = new UninitializedState(); - private final State mDefaultState = new DefaultState(); - private final State mInactiveState = new InactiveState(); - private final State mDisconnectState = new DisconnectedState(); - private final State mScanState = new ScanState(); - private final State mConnectionActiveState = new ConnectionActiveState(); - private final State mHandshakeState = new HandshakeState(); - private final State mCompletedState = new CompletedState(); - private final State mDormantState = new DormantState(); - - void enableVerboseLogging(int verbose) { - if (verbose > 0) { - DBG = true; - } else { - DBG = false; - } - } - - public String getSupplicantStateName() { - return getCurrentState().getName(); - } - - public SupplicantStateTracker(Context c, WifiConfigManager wcs, - BatteryStatsManager batteryStatsManager, Handler t) { - super(TAG, t.getLooper()); - - mContext = c; - mWifiConfigManager = wcs; - mBatteryStatsManager = batteryStatsManager; - // CHECKSTYLE:OFF IndentationCheck - addState(mDefaultState); - addState(mUninitializedState, mDefaultState); - addState(mInactiveState, mDefaultState); - addState(mDisconnectState, mDefaultState); - addState(mConnectionActiveState, mDefaultState); - addState(mScanState, mConnectionActiveState); - addState(mHandshakeState, mConnectionActiveState); - addState(mCompletedState, mConnectionActiveState); - addState(mDormantState, mConnectionActiveState); - // CHECKSTYLE:ON IndentationCheck - - setInitialState(mUninitializedState); - setLogRecSize(50); - setLogOnlyTransitions(true); - //start the state machine - start(); - } - - private void handleNetworkConnectionFailure(int netId, int disableReason) { - if (DBG) { - Log.d(TAG, "handleNetworkConnectionFailure netId=" + Integer.toString(netId) - + " reason " + Integer.toString(disableReason)); - } - - /* update network status */ - mWifiConfigManager.updateNetworkSelectionStatus(netId, disableReason); - } - - private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) { - SupplicantState supState = (SupplicantState) stateChangeResult.state; - - if (DBG) Log.d(TAG, "Supplicant state: " + supState.toString() + "\n"); - - switch (supState) { - case DISCONNECTED: - transitionTo(mDisconnectState); - break; - case INTERFACE_DISABLED: - //we should have received a disconnection already, do nothing - break; - case SCANNING: - transitionTo(mScanState); - break; - case AUTHENTICATING: - case ASSOCIATING: - case ASSOCIATED: - case FOUR_WAY_HANDSHAKE: - case GROUP_HANDSHAKE: - transitionTo(mHandshakeState); - break; - case COMPLETED: - transitionTo(mCompletedState); - break; - case DORMANT: - transitionTo(mDormantState); - break; - case INACTIVE: - transitionTo(mInactiveState); - break; - case UNINITIALIZED: - case INVALID: - transitionTo(mUninitializedState); - break; - default: - Log.e(TAG, "Unknown supplicant state " + supState); - break; - } - } - - private void sendSupplicantStateChangedBroadcast(SupplicantState state, boolean failedAuth) { - sendSupplicantStateChangedBroadcast(state, failedAuth, WifiManager.ERROR_AUTH_FAILURE_NONE); - } - - private void sendSupplicantStateChangedBroadcast(SupplicantState state, boolean failedAuth, - int reasonCode) { - int supplState; - switch (state) { - case DISCONNECTED: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_DISCONNECTED; - break; - case INTERFACE_DISABLED: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_INTERFACE_DISABLED; - break; - case INACTIVE: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_INACTIVE; - break; - case SCANNING: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_SCANNING; - break; - case AUTHENTICATING: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_AUTHENTICATING; - break; - case ASSOCIATING: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_ASSOCIATING; - break; - case ASSOCIATED: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_ASSOCIATED; - break; - case FOUR_WAY_HANDSHAKE: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_FOUR_WAY_HANDSHAKE; - break; - case GROUP_HANDSHAKE: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_GROUP_HANDSHAKE; - break; - case COMPLETED: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_COMPLETED; - break; - case DORMANT: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_DORMANT; - break; - case UNINITIALIZED: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_UNINITIALIZED; - break; - case INVALID: - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_INVALID; - break; - default: - Log.w(TAG, "Unknown supplicant state " + state); - supplState = BatteryStatsManager.WIFI_SUPPL_STATE_INVALID; - break; - } - mBatteryStatsManager.reportWifiSupplicantStateChanged(supplState, failedAuth); - Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable) state); - if (failedAuth) { - intent.putExtra( - WifiManager.EXTRA_SUPPLICANT_ERROR, - WifiManager.ERROR_AUTHENTICATING); - intent.putExtra( - WifiManager.EXTRA_SUPPLICANT_ERROR_REASON, - reasonCode); - } - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - /******************************************************** - * HSM states - *******************************************************/ - - class DefaultState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - @Override - public boolean processMessage(Message message) { - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: - mAuthFailureInSupplicantBroadcast = true; - mAuthFailureReason = message.arg1; - break; - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - SupplicantState state = stateChangeResult.state; - sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast, - mAuthFailureReason); - mAuthFailureInSupplicantBroadcast = false; - mAuthFailureReason = WifiManager.ERROR_AUTH_FAILURE_NONE; - transitionOnSupplicantStateChange(stateChangeResult); - break; - case ClientModeImpl.CMD_RESET_SUPPLICANT_STATE: - transitionTo(mUninitializedState); - break; - case WifiMonitor.ASSOCIATION_REJECTION_EVENT: - default: - Log.e(TAG, "Ignoring " + message); - break; - } - return HANDLED; - } - } - - /* - * This indicates that the supplicant state as seen - * by the framework is not initialized yet. We are - * in this state right after establishing a control - * channel connection before any supplicant events - * or after we have lost the control channel - * connection to the supplicant - */ - class UninitializedState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - } - - class InactiveState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - } - - class DisconnectedState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - } - - class ScanState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - } - - /* Meta-state that processes supplicant disconnections and broadcasts this event. */ - class ConnectionActiveState extends State { - @Override - public boolean processMessage(Message message) { - if (message.what == ClientModeImpl.CMD_RESET_SUPPLICANT_STATE) { - sendSupplicantStateChangedBroadcast(SupplicantState.DISCONNECTED, false); - } - - /* Let parent states handle the state possible transition. */ - return NOT_HANDLED; - } - } - - class HandshakeState extends State { - /** - * The max number of the WPA supplicant loop iterations before we - * decide that the loop should be terminated: - */ - private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4; - private int mLoopDetectIndex; - private int mLoopDetectCount; - - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - mLoopDetectIndex = 0; - mLoopDetectCount = 0; - } - @Override - public boolean processMessage(Message message) { - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - SupplicantState state = stateChangeResult.state; - if (SupplicantState.isHandshakeState(state)) { - if (mLoopDetectIndex > state.ordinal()) { - mLoopDetectCount++; - } - if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) { - Log.d(TAG, "Supplicant loop detected, disabling network " + - stateChangeResult.networkId); - handleNetworkConnectionFailure(stateChangeResult.networkId, - WifiConfiguration.NetworkSelectionStatus - .DISABLED_AUTHENTICATION_FAILURE); - } - mLoopDetectIndex = state.ordinal(); - sendSupplicantStateChangedBroadcast(state, - mAuthFailureInSupplicantBroadcast, mAuthFailureReason); - } else { - //Have the DefaultState handle the transition - return NOT_HANDLED; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class CompletedState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - @Override - public boolean processMessage(Message message) { - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch(message.what) { - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - SupplicantState state = stateChangeResult.state; - sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast, - mAuthFailureReason); - /* Ignore any connecting state in completed state. Group re-keying - * events and other auth events that do not affect connectivity are - * ignored - */ - if (SupplicantState.isConnecting(state)) { - break; - } - transitionOnSupplicantStateChange(stateChangeResult); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - //TODO: remove after getting rid of the state in supplicant - class DormantState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - super.dump(fd, pw, args); - pw.println("mAuthFailureInSupplicantBroadcast " + mAuthFailureInSupplicantBroadcast); - pw.println("mAuthFailureReason " + mAuthFailureReason); - pw.println(); - } -} diff --git a/service/java/com/android/server/wifi/SystemBuildProperties.java b/service/java/com/android/server/wifi/SystemBuildProperties.java deleted file mode 100644 index df79afdd2..000000000 --- a/service/java/com/android/server/wifi/SystemBuildProperties.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.os.Build; - -class SystemBuildProperties implements BuildProperties { - @Override - public boolean isEngBuild() { - return Build.TYPE.equals("eng"); - } - - @Override - public boolean isUserdebugBuild() { - return Build.TYPE.equals("userdebug"); - } - - @Override - public boolean isUserBuild() { - return Build.TYPE.equals("user"); - } -} diff --git a/service/java/com/android/server/wifi/SystemPropertyService.java b/service/java/com/android/server/wifi/SystemPropertyService.java deleted file mode 100644 index 98c547cbb..000000000 --- a/service/java/com/android/server/wifi/SystemPropertyService.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -/** PropertyService implementation which uses the real Android property store */ -class SystemPropertyService implements PropertyService { - @Override - public String get(String key, String defaultValue) { - return android.os.SystemProperties.get(key, defaultValue); - } - - @Override - public boolean getBoolean(String key, boolean defaultValue) { - return android.os.SystemProperties.getBoolean(key, defaultValue); - } - - @Override - public String getString(String key, String defaultValue) { - return android.os.SystemProperties.get(key, defaultValue); - } -} diff --git a/service/java/com/android/server/wifi/ThroughputPredictor.java b/service/java/com/android/server/wifi/ThroughputPredictor.java deleted file mode 100644 index 5cd8a5ce9..000000000 --- a/service/java/com/android/server/wifi/ThroughputPredictor.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.INVALID; -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.MAX_CHANNEL_UTILIZATION; -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.MIN_CHANNEL_UTILIZATION; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiAnnotations.WifiStandard; -import android.net.wifi.WifiInfo; -import android.net.wifi.nl80211.DeviceWiphyCapabilities; -import android.util.Log; - -import com.android.wifi.resources.R; - -/** - * A class that predicts network throughput based on RSSI, channel utilization, channel width, - * WiFi standard (PHY/MAC mode), Nss and other radio information. - */ -public class ThroughputPredictor { - private static final String TAG = "WifiThroughputPredictor"; - private boolean mVerboseLoggingEnabled = false; - - // Default value of channel utilization at 2G when channel utilization is not available from - // BssLoad IE or from link layer stats - public static final int CHANNEL_UTILIZATION_DEFAULT_2G = MAX_CHANNEL_UTILIZATION * 6 / 16; - // Default value of channel utilization at 5G when channel utilization is not available from - // BssLoad IE or from link layer stats - public static final int CHANNEL_UTILIZATION_DEFAULT_ABOVE_2G = MAX_CHANNEL_UTILIZATION / 16; - // Channel utilization boost when bluetooth is in the connected mode - public static final int CHANNEL_UTILIZATION_BOOST_BT_CONNECTED_2G = MAX_CHANNEL_UTILIZATION / 4; - //TODO: b/145133625 Need to consider 6GHz - - // Number of data tones per OFDM symbol - private static final int NUM_TONE_PER_SYM_LEGACY = 48; - private static final int NUM_TONE_PER_SYM_11N_20MHZ = 52; - private static final int NUM_TONE_PER_SYM_11N_40MHZ = 108; - private static final int NUM_TONE_PER_SYM_11AC_20MHZ = 52; - private static final int NUM_TONE_PER_SYM_11AC_40MHZ = 108; - private static final int NUM_TONE_PER_SYM_11AC_80MHZ = 234; - private static final int NUM_TONE_PER_SYM_11AC_160MHZ = 468; - private static final int NUM_TONE_PER_SYM_11AX_20MHZ = 234; - private static final int NUM_TONE_PER_SYM_11AX_40MHZ = 468; - private static final int NUM_TONE_PER_SYM_11AX_80MHZ = 980; - private static final int NUM_TONE_PER_SYM_11AX_160MHZ = 1960; - - // 11ag OFDM symbol duration in ns - private static final int SYM_DURATION_LEGACY_NS = 4000; - // 11n OFDM symbol duration in ns with 0.4us guard interval - private static final int SYM_DURATION_11N_NS = 3600; - // 11ac OFDM symbol duration in ns with 0.4us guard interval - private static final int SYM_DURATION_11AC_NS = 3600; - // 11ax OFDM symbol duration in ns with 0.8us guard interval - private static final int SYM_DURATION_11AX_NS = 13600; - private static final int MICRO_TO_NANO_RATIO = 1000; - - // The scaling factor for integer representation of bitPerTone and MAX_BITS_PER_TONE_XXX - private static final int BIT_PER_TONE_SCALE = 1000; - private static final int MAX_BITS_PER_TONE_LEGACY = - (int) Math.round((6 * 3.0 * BIT_PER_TONE_SCALE) / 4.0); - private static final int MAX_BITS_PER_TONE_11N = - (int) Math.round((6 * 5.0 * BIT_PER_TONE_SCALE) / 6.0); - private static final int MAX_BITS_PER_TONE_11AC = - (int) Math.round((8 * 5.0 * BIT_PER_TONE_SCALE) / 6.0); - private static final int MAX_BITS_PER_TONE_11AX = - (int) Math.round((10 * 5.0 * BIT_PER_TONE_SCALE) / 6.0); - - // snrDb-to-bitPerTone lookup table (LUT) used at low SNR - // snr = Math.pow(10.0, snrDb / 10.0); - // bitPerTone = (int) (Math.log10(1 + snr) / Math.log10(2.0) * BIT_PER_TONE_SCALE) - private static final int TWO_IN_DB = 3; - private static final int SNR_DB_TO_BIT_PER_TONE_HIGH_SNR_SCALE = BIT_PER_TONE_SCALE / TWO_IN_DB; - private static final int SNR_DB_TO_BIT_PER_TONE_LUT_MIN = -10; // minimum snrDb supported by LUT - private static final int SNR_DB_TO_BIT_PER_TONE_LUT_MAX = 9; // maximum snrDb supported by LUT - private static final int[] SNR_DB_TO_BIT_PER_TONE_LUT = {0, 171, 212, 262, 323, 396, 484, 586, - 706, 844, 1000, 1176, 1370, 1583, 1812, 2058, 2317, 2588, 2870, 3161}; - // Thermal noise floor power in dBm integrated over 20MHz with 5.5dB noise figure at 25C - private static final int NOISE_FLOOR_20MHZ_DBM = -96; - // A fudge factor to represent HW implementation margin in dB. - // Predicted throughput matches pretty well with OTA throughput with this fudge factor. - private static final int SNR_MARGIN_DB = 16; - private static final int MAX_NUM_SPATIAL_STREAM_11AX = 8; - private static final int MAX_NUM_SPATIAL_STREAM_11AC = 8; - private static final int MAX_NUM_SPATIAL_STREAM_11N = 4; - private static final int MAX_NUM_SPATIAL_STREAM_LEGACY = 1; - - private final Context mContext; - - ThroughputPredictor(Context context) { - mContext = context; - } - - /** - * Enable/Disable verbose logging. - * - * @param verbose true to enable and false to disable. - */ - public void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - } - - /** - * Predict maximum Tx throughput supported by connected network at the highest RSSI - * with the lowest channel utilization - * @return predicted maximum Tx throughput in Mbps - */ - public int predictMaxTxThroughput(@NonNull WifiNative.ConnectionCapabilities capabilities) { - return predictThroughputInternal(capabilities.wifiStandard, capabilities.channelBandwidth, - WifiInfo.MAX_RSSI, capabilities.maxNumberTxSpatialStreams, MIN_CHANNEL_UTILIZATION); - } - - /** - * Predict maximum Rx throughput supported by connected network at the highest RSSI - * with the lowest channel utilization - * @return predicted maximum Rx throughput in Mbps - */ - public int predictMaxRxThroughput(@NonNull WifiNative.ConnectionCapabilities capabilities) { - return predictThroughputInternal(capabilities.wifiStandard, capabilities.channelBandwidth, - WifiInfo.MAX_RSSI, capabilities.maxNumberRxSpatialStreams, MIN_CHANNEL_UTILIZATION); - } - - /** - * Predict Tx throughput with current connection capabilities, RSSI and channel utilization - * @return predicted Tx throughput in Mbps - */ - public int predictTxThroughput(@NonNull WifiNative.ConnectionCapabilities capabilities, - int rssiDbm, int frequency, int channelUtilization) { - int channelUtilizationFinal = getValidChannelUtilization(frequency, - INVALID, channelUtilization, false); - return predictThroughputInternal(capabilities.wifiStandard, capabilities.channelBandwidth, - rssiDbm, capabilities.maxNumberTxSpatialStreams, channelUtilizationFinal); - } - - /** - * Predict Rx throughput with current connection capabilities, RSSI and channel utilization - * @return predicted Rx throughput in Mbps - */ - public int predictRxThroughput(@NonNull WifiNative.ConnectionCapabilities capabilities, - int rssiDbm, int frequency, int channelUtilization) { - int channelUtilizationFinal = getValidChannelUtilization(frequency, - INVALID, channelUtilization, false); - return predictThroughputInternal(capabilities.wifiStandard, capabilities.channelBandwidth, - rssiDbm, capabilities.maxNumberRxSpatialStreams, channelUtilizationFinal); - } - - /** - * Predict network throughput given by the current channel condition and RSSI - * @param deviceCapabilities Phy Capabilities of the device - * @param wifiStandardAp the highest wifi standard supported by AP - * @param channelWidthAp the channel bandwidth of AP - * @param rssiDbm the scan RSSI in dBm - * @param frequency the center frequency of primary 20MHz channel - * @param maxNumSpatialStreamAp the maximum number of spatial streams supported by AP - * @param channelUtilizationBssLoad the channel utilization ratio indicated from BssLoad IE - * @param channelUtilizationLinkLayerStats the channel utilization ratio detected from scan - * @param isBluetoothConnected whether the bluetooth adaptor is in connected mode - * @return predicted throughput in Mbps - */ - public int predictThroughput(DeviceWiphyCapabilities deviceCapabilities, - @WifiStandard int wifiStandardAp, - int channelWidthAp, int rssiDbm, int frequency, int maxNumSpatialStreamAp, - int channelUtilizationBssLoad, int channelUtilizationLinkLayerStats, - boolean isBluetoothConnected) { - - if (deviceCapabilities == null) { - Log.e(TAG, "Null device capabilities passed to throughput predictor"); - return 0; - } - - int maxNumSpatialStreamDevice = Math.min(deviceCapabilities.getMaxNumberTxSpatialStreams(), - deviceCapabilities.getMaxNumberRxSpatialStreams()); - - if (mContext.getResources().getBoolean( - R.bool.config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideEnable)) { - maxNumSpatialStreamDevice = mContext.getResources().getInteger( - R.integer.config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideValue); - } - - int maxNumSpatialStream = Math.min(maxNumSpatialStreamDevice, maxNumSpatialStreamAp); - - // Get minimum standard support between device and AP - int wifiStandard; - switch (wifiStandardAp) { - case ScanResult.WIFI_STANDARD_11AX: - if (deviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX)) { - wifiStandard = ScanResult.WIFI_STANDARD_11AX; - break; - } - //FALL THROUGH - case ScanResult.WIFI_STANDARD_11AC: - if (deviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC)) { - wifiStandard = ScanResult.WIFI_STANDARD_11AC; - break; - } - //FALL THROUGH - case ScanResult.WIFI_STANDARD_11N: - if (deviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N)) { - wifiStandard = ScanResult.WIFI_STANDARD_11N; - break; - } - //FALL THROUGH - default: - wifiStandard = ScanResult.WIFI_STANDARD_LEGACY; - } - - // Calculate channel width - int channelWidth; - switch (channelWidthAp) { - case ScanResult.CHANNEL_WIDTH_160MHZ: - if (deviceCapabilities.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_160MHZ)) { - channelWidth = ScanResult.CHANNEL_WIDTH_160MHZ; - break; - } - // FALL THROUGH - case ScanResult.CHANNEL_WIDTH_80MHZ: - if (deviceCapabilities.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)) { - channelWidth = ScanResult.CHANNEL_WIDTH_80MHZ; - break; - } - // FALL THROUGH - case ScanResult.CHANNEL_WIDTH_40MHZ: - if (deviceCapabilities.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)) { - channelWidth = ScanResult.CHANNEL_WIDTH_40MHZ; - break; - } - // FALL THROUGH - default: - channelWidth = ScanResult.CHANNEL_WIDTH_20MHZ; - } - - if (mVerboseLoggingEnabled) { - StringBuilder sb = new StringBuilder(); - Log.d(TAG, sb.append("AP Nss: ").append(maxNumSpatialStreamAp) - .append(", Device Nss: ").append(maxNumSpatialStreamDevice) - .append(", freq: ").append(frequency) - .toString()); - } - - int channelUtilization = getValidChannelUtilization(frequency, - channelUtilizationBssLoad, - channelUtilizationLinkLayerStats, - isBluetoothConnected); - - return predictThroughputInternal(wifiStandard, channelWidth, rssiDbm, maxNumSpatialStream, - channelUtilization); - } - - private int predictThroughputInternal(@WifiStandard int wifiStandard, - int channelWidth, int rssiDbm, int maxNumSpatialStream, int channelUtilization) { - - // channel bandwidth in MHz = 20MHz * (2 ^ channelWidthFactor); - int channelWidthFactor; - int numTonePerSym; - int symDurationNs; - int maxBitsPerTone; - if (maxNumSpatialStream < 1) { - Log.e(TAG, "maxNumSpatialStream < 1 due to wrong implementation. Overridden to 1"); - maxNumSpatialStream = 1; - } - if (wifiStandard == ScanResult.WIFI_STANDARD_UNKNOWN) { - return WifiInfo.LINK_SPEED_UNKNOWN; - } else if (wifiStandard == ScanResult.WIFI_STANDARD_LEGACY) { - numTonePerSym = NUM_TONE_PER_SYM_LEGACY; - channelWidthFactor = 0; - maxNumSpatialStream = MAX_NUM_SPATIAL_STREAM_LEGACY; - maxBitsPerTone = MAX_BITS_PER_TONE_LEGACY; - symDurationNs = SYM_DURATION_LEGACY_NS; - } else if (wifiStandard == ScanResult.WIFI_STANDARD_11N) { - if (channelWidth == ScanResult.CHANNEL_WIDTH_20MHZ) { - numTonePerSym = NUM_TONE_PER_SYM_11N_20MHZ; - channelWidthFactor = 0; - } else { - numTonePerSym = NUM_TONE_PER_SYM_11N_40MHZ; - channelWidthFactor = 1; - } - maxNumSpatialStream = Math.min(maxNumSpatialStream, MAX_NUM_SPATIAL_STREAM_11N); - maxBitsPerTone = MAX_BITS_PER_TONE_11N; - symDurationNs = SYM_DURATION_11N_NS; - } else if (wifiStandard == ScanResult.WIFI_STANDARD_11AC) { - if (channelWidth == ScanResult.CHANNEL_WIDTH_20MHZ) { - numTonePerSym = NUM_TONE_PER_SYM_11AC_20MHZ; - channelWidthFactor = 0; - } else if (channelWidth == ScanResult.CHANNEL_WIDTH_40MHZ) { - numTonePerSym = NUM_TONE_PER_SYM_11AC_40MHZ; - channelWidthFactor = 1; - } else if (channelWidth == ScanResult.CHANNEL_WIDTH_80MHZ) { - numTonePerSym = NUM_TONE_PER_SYM_11AC_80MHZ; - channelWidthFactor = 2; - } else { - numTonePerSym = NUM_TONE_PER_SYM_11AC_160MHZ; - channelWidthFactor = 3; - } - maxNumSpatialStream = Math.min(maxNumSpatialStream, MAX_NUM_SPATIAL_STREAM_11AC); - maxBitsPerTone = MAX_BITS_PER_TONE_11AC; - symDurationNs = SYM_DURATION_11AC_NS; - } else { // ScanResult.WIFI_STANDARD_11AX - if (channelWidth == ScanResult.CHANNEL_WIDTH_20MHZ) { - numTonePerSym = NUM_TONE_PER_SYM_11AX_20MHZ; - channelWidthFactor = 0; - } else if (channelWidth == ScanResult.CHANNEL_WIDTH_40MHZ) { - numTonePerSym = NUM_TONE_PER_SYM_11AX_40MHZ; - channelWidthFactor = 1; - } else if (channelWidth == ScanResult.CHANNEL_WIDTH_80MHZ) { - numTonePerSym = NUM_TONE_PER_SYM_11AX_80MHZ; - channelWidthFactor = 2; - } else { - numTonePerSym = NUM_TONE_PER_SYM_11AX_160MHZ; - channelWidthFactor = 3; - } - maxNumSpatialStream = Math.min(maxNumSpatialStream, MAX_NUM_SPATIAL_STREAM_11AX); - maxBitsPerTone = MAX_BITS_PER_TONE_11AX; - symDurationNs = SYM_DURATION_11AX_NS; - } - // noiseFloorDbBoost = 10 * log10 * (2 ^ channelWidthFactor) - int noiseFloorDbBoost = TWO_IN_DB * channelWidthFactor; - int noiseFloorDbm = NOISE_FLOOR_20MHZ_DBM + noiseFloorDbBoost + SNR_MARGIN_DB; - int snrDb = rssiDbm - noiseFloorDbm; - - int bitPerTone = calculateBitPerTone(snrDb); - bitPerTone = Math.min(bitPerTone, maxBitsPerTone); - - long bitPerToneTotal = bitPerTone * maxNumSpatialStream; - long numBitPerSym = bitPerToneTotal * numTonePerSym; - int phyRateMbps = (int) ((numBitPerSym * MICRO_TO_NANO_RATIO) - / (symDurationNs * BIT_PER_TONE_SCALE)); - - int airTimeFraction = calculateAirTimeFraction(channelUtilization, channelWidthFactor); - - int throughputMbps = (phyRateMbps * airTimeFraction) / MAX_CHANNEL_UTILIZATION; - - if (mVerboseLoggingEnabled) { - StringBuilder sb = new StringBuilder(); - Log.d(TAG, sb.append(" BW: ").append(channelWidth) - .append(" RSSI: ").append(rssiDbm) - .append(" Nss: ").append(maxNumSpatialStream) - .append(" Mode: ").append(wifiStandard) - .append(" symDur: ").append(symDurationNs) - .append(" snrDb ").append(snrDb) - .append(" bitPerTone: ").append(bitPerTone) - .append(" rate: ").append(phyRateMbps) - .append(" throughput: ").append(throughputMbps) - .toString()); - } - return throughputMbps; - } - - // Calculate the number of bits per tone based on the input of SNR in dB - // The output is scaled up by BIT_PER_TONE_SCALE for integer representation - private static int calculateBitPerTone(int snrDb) { - int bitPerTone; - if (snrDb <= SNR_DB_TO_BIT_PER_TONE_LUT_MAX) { - int lut_in_idx = Math.max(snrDb, SNR_DB_TO_BIT_PER_TONE_LUT_MIN) - - SNR_DB_TO_BIT_PER_TONE_LUT_MIN; - lut_in_idx = Math.min(lut_in_idx, SNR_DB_TO_BIT_PER_TONE_LUT.length - 1); - bitPerTone = SNR_DB_TO_BIT_PER_TONE_LUT[lut_in_idx]; - } else { - // bitPerTone = Math.log10(1+snr)/Math.log10(2) can be approximated as - // Math.log10(snr) / 0.3 = log10(10^(snrDb/10)) / 0.3 = snrDb / 3 - // SNR_DB_TO_BIT_PER_TONE_HIGH_SNR_SCALE = BIT_PER_TONE_SCALE / 3 - bitPerTone = snrDb * SNR_DB_TO_BIT_PER_TONE_HIGH_SNR_SCALE; - } - return bitPerTone; - } - - private int getValidChannelUtilization(int frequency, int channelUtilizationBssLoad, - int channelUtilizationLinkLayerStats, boolean isBluetoothConnected) { - int channelUtilization; - boolean is2G = ScanResult.is24GHz(frequency); - if (isValidUtilizationRatio(channelUtilizationBssLoad)) { - channelUtilization = channelUtilizationBssLoad; - } else if (isValidUtilizationRatio(channelUtilizationLinkLayerStats)) { - channelUtilization = channelUtilizationLinkLayerStats; - } else { - channelUtilization = is2G ? CHANNEL_UTILIZATION_DEFAULT_2G : - CHANNEL_UTILIZATION_DEFAULT_ABOVE_2G; - } - - if (is2G && isBluetoothConnected) { - channelUtilization += CHANNEL_UTILIZATION_BOOST_BT_CONNECTED_2G; - channelUtilization = Math.min(channelUtilization, MAX_CHANNEL_UTILIZATION); - } - if (mVerboseLoggingEnabled) { - StringBuilder sb = new StringBuilder(); - Log.d(TAG, sb.append(" utilization (BssLoad) ").append(channelUtilizationBssLoad) - .append(" utilization (LLStats) ").append(channelUtilizationLinkLayerStats) - .append(" isBluetoothConnected: ").append(isBluetoothConnected) - .append(" final utilization: ").append(channelUtilization) - .toString()); - } - return channelUtilization; - } - - /** - * Check if the channel utilization ratio is valid - */ - private static boolean isValidUtilizationRatio(int utilizationRatio) { - return (utilizationRatio <= MAX_CHANNEL_UTILIZATION - && utilizationRatio >= MIN_CHANNEL_UTILIZATION); - } - - // Calculate the available airtime fraction value which is multiplied by - // MAX_CHANNEL_UTILIZATION for integer representation. It is calculated as - // (1 - channelUtilization / MAX_CHANNEL_UTILIZATION) * MAX_CHANNEL_UTILIZATION - private int calculateAirTimeFraction(int channelUtilization, int channelWidthFactor) { - int airTimeFraction20MHz = MAX_CHANNEL_UTILIZATION - channelUtilization; - int airTimeFraction = airTimeFraction20MHz; - // For the cases of 40MHz or above, need to take - // (1 - channelUtilization / MAX_CHANNEL_UTILIZATION) ^ (2 ^ channelWidthFactor) - // because channelUtilization is defined for primary 20MHz channel - for (int i = 1; i <= channelWidthFactor; ++i) { - airTimeFraction *= airTimeFraction; - airTimeFraction /= MAX_CHANNEL_UTILIZATION; - } - if (mVerboseLoggingEnabled) { - Log.d(TAG, " airTime20: " + airTimeFraction20MHz + " airTime: " + airTimeFraction); - } - return airTimeFraction; - } -} diff --git a/service/java/com/android/server/wifi/ThroughputScorer.java b/service/java/com/android/server/wifi/ThroughputScorer.java deleted file mode 100644 index ed0d0da73..000000000 --- a/service/java/com/android/server/wifi/ThroughputScorer.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import static com.android.server.wifi.WifiNetworkSelector.NetworkNominator.NOMINATOR_ID_SCORED; - -import android.annotation.NonNull; -import android.util.Log; - -import com.android.server.wifi.WifiCandidates.Candidate; -import com.android.server.wifi.WifiCandidates.ScoredCandidate; - -import java.util.Collection; - -/** - * A candidate scorer that combines RSSI base score and network throughput score. - */ -final class ThroughputScorer implements WifiCandidates.CandidateScorer { - private static final String TAG = "ThroughputScorer"; - private static final boolean DBG = false; - /** - * This should match WifiNetworkSelector.experimentIdFromIdentifier(getIdentifier()) - * when using the default ScoringParams. - */ - public static final int THROUGHPUT_SCORER_DEFAULT_EXPID = 42330058; - - /** - * Base score that is large enough to override all of the other categories. - * This is applied to the last-select network for a limited duration. - */ - public static final int TOP_TIER_BASE_SCORE = 1_000_000; - - private final ScoringParams mScoringParams; - - // config_wifi_framework_RSSI_SCORE_OFFSET - public static final int RSSI_SCORE_OFFSET = 85; - - // config_wifi_framework_RSSI_SCORE_SLOPE - public static final int RSSI_SCORE_SLOPE_IS_4 = 4; - - public static final int TRUSTED_AWARD = 1000; - public static final int HALF_TRUSTED_AWARD = 1000 / 2; - - private static final boolean USE_USER_CONNECT_CHOICE = true; - - ThroughputScorer(ScoringParams scoringParams) { - mScoringParams = scoringParams; - } - - @Override - public String getIdentifier() { - return "ThroughputScorer"; - } - - /** - * Calculates an individual candidate's score. - */ - private ScoredCandidate scoreCandidate(Candidate candidate) { - int rssiSaturationThreshold = mScoringParams.getSufficientRssi(candidate.getFrequency()); - int rssi = Math.min(candidate.getScanRssi(), rssiSaturationThreshold); - int rssiBaseScore = (rssi + RSSI_SCORE_OFFSET) * RSSI_SCORE_SLOPE_IS_4; - - int throughputBonusScore = calculateThroughputBonusScore(candidate); - - int rssiAndThroughputScore = rssiBaseScore + throughputBonusScore; - - boolean unExpectedNoInternet = candidate.hasNoInternetAccess() - && !candidate.isNoInternetAccessExpected(); - int currentNetworkBonusMin = mScoringParams.getCurrentNetworkBonusMin(); - int currentNetworkBonus = Math.max(currentNetworkBonusMin, rssiAndThroughputScore - * mScoringParams.getCurrentNetworkBonusPercent() / 100); - int currentNetworkBoost = (candidate.isCurrentNetwork() && !unExpectedNoInternet) - ? currentNetworkBonus : 0; - - int securityAward = candidate.isOpenNetwork() - ? 0 - : mScoringParams.getSecureNetworkBonus(); - - int unmeteredAward = candidate.isMetered() - ? 0 - : mScoringParams.getUnmeteredNetworkBonus(); - - int savedNetworkAward = candidate.isEphemeral() ? 0 : mScoringParams.getSavedNetworkBonus(); - - int trustedAward = TRUSTED_AWARD; - - if (!candidate.isTrusted()) { - savedNetworkAward = 0; // Saved networks are not untrusted, but clear anyway - unmeteredAward = 0; // Ignore metered for untrusted networks - if (candidate.isCarrierOrPrivileged()) { - trustedAward = HALF_TRUSTED_AWARD; - } else if (candidate.getNominatorId() == NOMINATOR_ID_SCORED) { - Log.e(TAG, "ScoredNetworkNominator is not carrier or privileged!"); - trustedAward = 0; - } else { - trustedAward = 0; - } - } - - int score = rssiBaseScore + throughputBonusScore - + currentNetworkBoost + securityAward + unmeteredAward + savedNetworkAward - + trustedAward; - - if (candidate.getLastSelectionWeight() > 0.0) { - // Put a recently-selected network in a tier above everything else, - // but include rssi and throughput contributions for BSSID selection. - score = TOP_TIER_BASE_SCORE + rssiBaseScore + throughputBonusScore; - } - - if (DBG) { - Log.d(TAG, " rssiScore: " + rssiBaseScore - + " throughputScore: " + throughputBonusScore - + " currentNetworkBoost: " + currentNetworkBoost - + " securityAward: " + securityAward - + " unmeteredAward: " + unmeteredAward - + " savedNetworkAward: " + savedNetworkAward - + " trustedAward: " + trustedAward - + " final score: " + score); - } - - // The old method breaks ties on the basis of RSSI, which we can - // emulate easily since our score does not need to be an integer. - double tieBreaker = candidate.getScanRssi() / 1000.0; - return new ScoredCandidate(score + tieBreaker, 10, - USE_USER_CONNECT_CHOICE, candidate); - } - - private int calculateThroughputBonusScore(Candidate candidate) { - int throughputScoreRaw = candidate.getPredictedThroughputMbps() - * mScoringParams.getThroughputBonusNumerator() - / mScoringParams.getThroughputBonusDenominator(); - return Math.min(throughputScoreRaw, mScoringParams.getThroughputBonusLimit()); - } - - @Override - public ScoredCandidate scoreCandidates(@NonNull Collection<Candidate> candidates) { - ScoredCandidate choice = ScoredCandidate.NONE; - for (Candidate candidate : candidates) { - ScoredCandidate scoredCandidate = scoreCandidate(candidate); - if (scoredCandidate.value > choice.value) { - choice = scoredCandidate; - } - } - // Here we just return the highest scored candidate; we could - // compute a new score, if desired. - return choice; - } - -} diff --git a/service/java/com/android/server/wifi/UntrustedWifiNetworkFactory.java b/service/java/com/android/server/wifi/UntrustedWifiNetworkFactory.java deleted file mode 100644 index b6b60ffb6..000000000 --- a/service/java/com/android/server/wifi/UntrustedWifiNetworkFactory.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.content.Context; -import android.net.NetworkCapabilities; -import android.net.NetworkFactory; -import android.net.NetworkRequest; -import android.os.Looper; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Network factory to handle untrusted (used for {@link ScoredNetworkNominator}) wifi network - * requests. - */ -public class UntrustedWifiNetworkFactory extends NetworkFactory { - private static final String TAG = "UntrustedWifiNetworkFactory"; - private static final int SCORE_FILTER = Integer.MAX_VALUE; - - private final WifiConnectivityManager mWifiConnectivityManager; - private int mConnectionReqCount = 0; - - public UntrustedWifiNetworkFactory(Looper l, Context c, NetworkCapabilities f, - WifiConnectivityManager connectivityManager) { - super(l, c, TAG, f); - mWifiConnectivityManager = connectivityManager; - - setScoreFilter(SCORE_FILTER); - } - - @Override - protected void needNetworkFor(NetworkRequest networkRequest, int score) { - if (!networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { - if (++mConnectionReqCount == 1) { - mWifiConnectivityManager.setUntrustedConnectionAllowed(true); - } - } - } - - @Override - protected void releaseNetworkFor(NetworkRequest networkRequest) { - if (!networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { - if (mConnectionReqCount == 0) { - Log.e(TAG, "No valid network request to release"); - return; - } - if (--mConnectionReqCount == 0) { - mWifiConnectivityManager.setUntrustedConnectionAllowed(false); - } - } - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - super.dump(fd, pw, args); - pw.println(TAG + ": mConnectionReqCount " + mConnectionReqCount); - } - - /** - * Check if there is at-least one connection request. - */ - public boolean hasConnectionRequests() { - return mConnectionReqCount > 0; - } -} - diff --git a/service/java/com/android/server/wifi/VelocityBasedConnectedScore.java b/service/java/com/android/server/wifi/VelocityBasedConnectedScore.java deleted file mode 100644 index b931689a2..000000000 --- a/service/java/com/android/server/wifi/VelocityBasedConnectedScore.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.net.wifi.ScanResult; -import android.net.wifi.WifiInfo; - -import com.android.server.wifi.util.KalmanFilter; -import com.android.server.wifi.util.Matrix; - -/** - * Class used to calculate scores for connected wifi networks and report it to the associated - * network agent. - */ -public class VelocityBasedConnectedScore extends ConnectedScore { - - private final ScoringParams mScoringParams; - - private int mFrequency = ScanResult.BAND_5_GHZ_START_FREQ_MHZ; - private double mThresholdAdjustment; - private final KalmanFilter mFilter; - private long mLastMillis; - - public VelocityBasedConnectedScore(ScoringParams scoringParams, Clock clock) { - super(clock); - mScoringParams = scoringParams; - mFilter = new KalmanFilter(); - mFilter.mH = new Matrix(2, new double[]{1.0, 0.0}); - mFilter.mR = new Matrix(1, new double[]{1.0}); - } - - /** - * Set the Kalman filter's state transition matrix F and process noise covariance Q given - * a time step. - * - * @param dt delta time, in seconds - */ - private void setDeltaTimeSeconds(double dt) { - mFilter.mF = new Matrix(2, new double[]{1.0, dt, 0.0, 1.0}); - Matrix tG = new Matrix(1, new double[]{0.5 * dt * dt, dt}); - double stda = 0.02; // standard deviation of modelled acceleration - mFilter.mQ = tG.dotTranspose(tG).dot(new Matrix(2, new double[]{ - stda * stda, 0.0, - 0.0, stda * stda})); - } - /** - * Reset the filter state. - */ - @Override - public void reset() { - mLastMillis = 0; - mThresholdAdjustment = 0; - mFilter.mx = null; - } - - /** - * Updates scoring state using RSSI and measurement noise estimate - * <p> - * This is useful if an RSSI comes from another source (e.g. scan results) and the - * expected noise varies by source. - * - * @param rssi signal strength (dB). - * @param millis millisecond-resolution time. - * @param standardDeviation of the RSSI. - */ - @Override - public void updateUsingRssi(int rssi, long millis, double standardDeviation) { - if (millis <= 0) return; - if (mLastMillis <= 0 || millis < mLastMillis || mFilter.mx == null) { - double initialVariance = 9.0 * standardDeviation * standardDeviation; - mFilter.mx = new Matrix(1, new double[]{rssi, 0.0}); - mFilter.mP = new Matrix(2, new double[]{initialVariance, 0.0, 0.0, 0.0}); - } else { - double dt = (millis - mLastMillis) * 0.001; - mFilter.mR.put(0, 0, standardDeviation * standardDeviation); - setDeltaTimeSeconds(dt); - mFilter.predict(); - mFilter.update(new Matrix(1, new double[]{rssi})); - } - mLastMillis = millis; - mFilteredRssi = mFilter.mx.get(0, 0); - mEstimatedRateOfRssiChange = mFilter.mx.get(1, 0); - } - - /** - * Updates the state. - */ - @Override - public void updateUsingWifiInfo(WifiInfo wifiInfo, long millis) { - int frequency = wifiInfo.getFrequency(); - if (frequency != mFrequency) { - mLastMillis = 0; // Probably roamed; reset filter but retain threshold adjustment - // Consider resetting or partially resetting threshold adjustment - // Consider checking bssid - mFrequency = frequency; - } - updateUsingRssi(wifiInfo.getRssi(), millis, mDefaultRssiStandardDeviation); - adjustThreshold(wifiInfo); - } - - private double mFilteredRssi; - private double mEstimatedRateOfRssiChange; - - /** - * Returns the most recently computed extimate of the RSSI. - */ - public double getFilteredRssi() { - return mFilteredRssi; - } - - /** - * Returns the estimated rate of change of RSSI, in dB/second - */ - public double getEstimatedRateOfRssiChange() { - return mEstimatedRateOfRssiChange; - } - - /** - * Returns the adjusted RSSI threshold - */ - public double getAdjustedRssiThreshold() { - return mScoringParams.getExitRssi(mFrequency) + mThresholdAdjustment; - } - - private double mMinimumPpsForMeasuringSuccess = 2.0; - - /** - * Adjusts the threshold if appropriate - * <p> - * If the (filtered) rssi is near or below the current effective threshold, and the - * rate of rssi change is small, and there is traffic, and the error rate is looking - * reasonable, then decrease the effective threshold to keep from dropping a perfectly good - * connection. - * - */ - private void adjustThreshold(WifiInfo wifiInfo) { - if (mThresholdAdjustment < -7) return; - if (mFilteredRssi >= getAdjustedRssiThreshold() + 2.0) return; - if (Math.abs(mEstimatedRateOfRssiChange) >= 0.2) return; - double txSuccessPps = wifiInfo.getSuccessfulTxPacketsPerSecond(); - double rxSuccessPps = wifiInfo.getSuccessfulRxPacketsPerSecond(); - if (txSuccessPps < mMinimumPpsForMeasuringSuccess) return; - if (rxSuccessPps < mMinimumPpsForMeasuringSuccess) return; - double txBadPps = wifiInfo.getLostTxPacketsPerSecond(); - double txRetriesPps = wifiInfo.getRetriedTxPacketsPerSecond(); - double probabilityOfSuccessfulTx = txSuccessPps / (txSuccessPps + txBadPps + txRetriesPps); - if (probabilityOfSuccessfulTx > 0.2) { - // May want this amount to vary with how close to threshold we are - mThresholdAdjustment -= 0.5; - } - } - - /** - * Velocity scorer - predict the rssi a few seconds from now - */ - @Override - public int generateScore() { - if (mFilter.mx == null) return WIFI_TRANSITION_SCORE + 1; - double badRssi = getAdjustedRssiThreshold(); - double horizonSeconds = mScoringParams.getHorizonSeconds(); - Matrix x = new Matrix(mFilter.mx); - double filteredRssi = x.get(0, 0); - setDeltaTimeSeconds(horizonSeconds); - x = mFilter.mF.dot(x); - double forecastRssi = x.get(0, 0); - if (forecastRssi > filteredRssi) { - forecastRssi = filteredRssi; // Be pessimistic about predicting an actual increase - } - int score = (int) (Math.round(forecastRssi) - badRssi) + WIFI_TRANSITION_SCORE; - return score; - } -} diff --git a/service/java/com/android/server/wifi/WakeupConfigStoreData.java b/service/java/com/android/server/wifi/WakeupConfigStoreData.java deleted file mode 100644 index 074393b81..000000000 --- a/service/java/com/android/server/wifi/WakeupConfigStoreData.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import android.annotation.Nullable; -import android.util.ArraySet; -import android.util.Log; - -import com.android.server.wifi.WifiConfigStore.StoreData; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.Collections; -import java.util.Set; - -/** - * Config store data for Wifi Wake. - */ -public class WakeupConfigStoreData implements StoreData { - private static final String TAG = "WakeupConfigStoreData"; - - private static final String XML_TAG_FEATURE_STATE_SECTION = "FeatureState"; - private static final String XML_TAG_IS_ACTIVE = "IsActive"; - private static final String XML_TAG_IS_ONBOARDED = "IsOnboarded"; - private static final String XML_TAG_NOTIFICATIONS_SHOWN = "NotificationsShown"; - private static final String XML_TAG_NETWORK_SECTION = "Network"; - private static final String XML_TAG_SSID = "SSID"; - private static final String XML_TAG_SECURITY = "Security"; - - private final DataSource<Boolean> mIsActiveDataSource; - private final DataSource<Boolean> mIsOnboardedDataSource; - private final DataSource<Integer> mNotificationsDataSource; - private final DataSource<Set<ScanResultMatchInfo>> mNetworkDataSource; - private boolean mHasBeenRead = false; - - /** - * Interface defining a data source for the store data. - * - * @param <T> Type of data source - */ - public interface DataSource<T> { - /** - * Returns the data from the data source. - */ - T getData(); - - /** - * Updates the data in the data source. - * - * @param data Data retrieved from the store - */ - void setData(T data); - } - - /** - * Creates the config store data with its data sources. - * - * @param isActiveDataSource Data source for isActive - * @param networkDataSource Data source for the locked network list - */ - public WakeupConfigStoreData( - DataSource<Boolean> isActiveDataSource, - DataSource<Boolean> isOnboardedDataSource, - DataSource<Integer> notificationsDataSource, - DataSource<Set<ScanResultMatchInfo>> networkDataSource) { - mIsActiveDataSource = isActiveDataSource; - mIsOnboardedDataSource = isOnboardedDataSource; - mNotificationsDataSource = notificationsDataSource; - mNetworkDataSource = networkDataSource; - } - - /** - * Returns whether the user store has been read. - */ - public boolean hasBeenRead() { - return mHasBeenRead; - } - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - writeFeatureState(out); - - for (ScanResultMatchInfo scanResultMatchInfo : mNetworkDataSource.getData()) { - writeNetwork(out, scanResultMatchInfo); - } - } - - /** - * Writes the current state of Wifi Wake to an XML output stream. - * - * @param out XML output stream - * @throws XmlPullParserException - * @throws IOException - */ - private void writeFeatureState(XmlSerializer out) - throws IOException, XmlPullParserException { - XmlUtil.writeNextSectionStart(out, XML_TAG_FEATURE_STATE_SECTION); - - XmlUtil.writeNextValue(out, XML_TAG_IS_ACTIVE, mIsActiveDataSource.getData()); - XmlUtil.writeNextValue(out, XML_TAG_IS_ONBOARDED, mIsOnboardedDataSource.getData()); - XmlUtil.writeNextValue(out, XML_TAG_NOTIFICATIONS_SHOWN, - mNotificationsDataSource.getData()); - - XmlUtil.writeNextSectionEnd(out, XML_TAG_FEATURE_STATE_SECTION); - } - - /** - * Writes a {@link ScanResultMatchInfo} to an XML output stream. - * - * @param out XML output stream - * @param scanResultMatchInfo The ScanResultMatchInfo to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private void writeNetwork(XmlSerializer out, ScanResultMatchInfo scanResultMatchInfo) - throws XmlPullParserException, IOException { - XmlUtil.writeNextSectionStart(out, XML_TAG_NETWORK_SECTION); - - XmlUtil.writeNextValue(out, XML_TAG_SSID, scanResultMatchInfo.networkSsid); - XmlUtil.writeNextValue(out, XML_TAG_SECURITY, scanResultMatchInfo.networkType); - - XmlUtil.writeNextSectionEnd(out, XML_TAG_NETWORK_SECTION); - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - if (!mHasBeenRead) { - Log.d(TAG, "WifiWake user data has been read"); - mHasBeenRead = true; - } - // Ignore empty reads. - if (in == null) { - return; - } - - Set<ScanResultMatchInfo> networks = new ArraySet<>(); - - String[] headerName = new String[1]; - while (XmlUtil.gotoNextSectionOrEnd(in, headerName, outerTagDepth)) { - switch (headerName[0]) { - case XML_TAG_FEATURE_STATE_SECTION: - parseFeatureState(in, outerTagDepth + 1); - break; - case XML_TAG_NETWORK_SECTION: - networks.add(parseNetwork(in, outerTagDepth + 1)); - break; - } - } - - mNetworkDataSource.setData(networks); - } - - /** - * Parses the state of Wifi Wake from an XML input stream and sets the respective data sources. - * - * @param in XML input stream - * @param outerTagDepth XML tag depth of the containing section - * @throws IOException - * @throws XmlPullParserException - */ - private void parseFeatureState(XmlPullParser in, int outerTagDepth) - throws IOException, XmlPullParserException { - boolean isActive = false; - boolean isOnboarded = false; - int notificationsShown = 0; - - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_IS_ACTIVE: - isActive = (Boolean) value; - break; - case XML_TAG_IS_ONBOARDED: - isOnboarded = (Boolean) value; - break; - case XML_TAG_NOTIFICATIONS_SHOWN: - notificationsShown = (Integer) value; - break; - default: - Log.w(TAG, "Unknown value found: " + valueName[0]); - break; - } - } - - mIsActiveDataSource.setData(isActive); - mIsOnboardedDataSource.setData(isOnboarded); - mNotificationsDataSource.setData(notificationsShown); - } - - /** - * Parses a {@link ScanResultMatchInfo} from an XML input stream. - * - * @param in XML input stream - * @param outerTagDepth XML tag depth of the containing section - * @return The {@link ScanResultMatchInfo} - * @throws IOException - * @throws XmlPullParserException - */ - private ScanResultMatchInfo parseNetwork(XmlPullParser in, int outerTagDepth) - throws IOException, XmlPullParserException { - ScanResultMatchInfo scanResultMatchInfo = new ScanResultMatchInfo(); - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_SSID: - scanResultMatchInfo.networkSsid = (String) value; - break; - case XML_TAG_SECURITY: - scanResultMatchInfo.networkType = (int) value; - break; - default: - Log.w(TAG, "Ignoring unknown tag under " + TAG + ": " + valueName[0]); - break; - } - } - - return scanResultMatchInfo; - } - - @Override - public void resetData() { - mNetworkDataSource.setData(Collections.emptySet()); - mIsActiveDataSource.setData(false); - mIsOnboardedDataSource.setData(false); - mNotificationsDataSource.setData(0); - } - - @Override - public boolean hasNewDataToSerialize() { - // always persist. - return true; - } - - @Override - public String getName() { - return TAG; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - // Shared general store. - return WifiConfigStore.STORE_FILE_USER_GENERAL; - } -} diff --git a/service/java/com/android/server/wifi/WakeupController.java b/service/java/com/android/server/wifi/WakeupController.java deleted file mode 100644 index a92bdf7f1..000000000 --- a/service/java/com/android/server/wifi/WakeupController.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import android.content.Context; -import android.database.ContentObserver; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.Process; -import android.provider.Settings; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - - -/** - * WakeupController is responsible managing Auto Wifi. - * - * <p>It determines if and when to re-enable wifi after it has been turned off by the user. - */ -public class WakeupController { - - private static final String TAG = "WakeupController"; - - private static final boolean USE_PLATFORM_WIFI_WAKE = true; - - private final Context mContext; - private final Handler mHandler; - private final FrameworkFacade mFrameworkFacade; - private final ContentObserver mContentObserver; - private final WakeupLock mWakeupLock; - private final WakeupEvaluator mWakeupEvaluator; - private final WakeupOnboarding mWakeupOnboarding; - private final WifiConfigManager mWifiConfigManager; - private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private final WifiInjector mWifiInjector; - private final WakeupConfigStoreData mWakeupConfigStoreData; - private final WifiWakeMetrics mWifiWakeMetrics; - private final Clock mClock; - - private final WifiScanner.ScanListener mScanListener = new WifiScanner.ScanListener() { - @Override - public void onPeriodChanged(int periodInMs) { - // no-op - } - - @Override - public void onResults(WifiScanner.ScanData[] results) { - // We treat any full band scans (with DFS or not) as "full". - if (results.length == 1 - && WifiScanner.isFullBandScan(results[0].getBandScanned(), true)) { - handleScanResults(filterDfsScanResults(Arrays.asList(results[0].getResults()))); - } - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - // no-op - } - - @Override - public void onSuccess() { - // no-op - } - - @Override - public void onFailure(int reason, String description) { - Log.e(TAG, "ScanListener onFailure: " + reason + ": " + description); - } - }; - - /** Whether this feature is enabled in Settings. */ - private boolean mWifiWakeupEnabled; - - /** Whether the WakeupController is currently active. */ - private boolean mIsActive = false; - - /** The number of scans that have been handled by the controller since last {@link #reset()}. */ - private int mNumScansHandled = 0; - - /** Whether Wifi verbose logging is enabled. */ - private boolean mVerboseLoggingEnabled; - - /** - * The timestamp of when the Wifi network was last disconnected (either device disconnected - * from the network or Wifi was turned off entirely). - * Note: mLastDisconnectTimestampMillis and mLastDisconnectInfo must always be updated together. - */ - private long mLastDisconnectTimestampMillis; - - /** - * The SSID of the last Wifi network the device was connected to (either device disconnected - * from the network or Wifi was turned off entirely). - * Note: mLastDisconnectTimestampMillis and mLastDisconnectInfo must always be updated together. - */ - private ScanResultMatchInfo mLastDisconnectInfo; - - public WakeupController( - Context context, - Handler handler, - WakeupLock wakeupLock, - WakeupEvaluator wakeupEvaluator, - WakeupOnboarding wakeupOnboarding, - WifiConfigManager wifiConfigManager, - WifiConfigStore wifiConfigStore, - WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager, - WifiWakeMetrics wifiWakeMetrics, - WifiInjector wifiInjector, - FrameworkFacade frameworkFacade, - Clock clock) { - mContext = context; - mHandler = handler; - mWakeupLock = wakeupLock; - mWakeupEvaluator = wakeupEvaluator; - mWakeupOnboarding = wakeupOnboarding; - mWifiConfigManager = wifiConfigManager; - mWifiNetworkSuggestionsManager = wifiNetworkSuggestionsManager; - mWifiWakeMetrics = wifiWakeMetrics; - mFrameworkFacade = frameworkFacade; - mWifiInjector = wifiInjector; - mContentObserver = new ContentObserver(mHandler) { - @Override - public void onChange(boolean selfChange) { - readWifiWakeupEnabledFromSettings(); - mWakeupOnboarding.setOnboarded(); - } - }; - mFrameworkFacade.registerContentObserver(mContext, Settings.Global.getUriFor( - Settings.Global.WIFI_WAKEUP_ENABLED), true, mContentObserver); - readWifiWakeupEnabledFromSettings(); - - // registering the store data here has the effect of reading the persisted value of the - // data sources after system boot finishes - mWakeupConfigStoreData = new WakeupConfigStoreData( - new IsActiveDataSource(), - mWakeupOnboarding.getIsOnboadedDataSource(), - mWakeupOnboarding.getNotificationsDataSource(), - mWakeupLock.getDataSource()); - wifiConfigStore.registerStoreData(mWakeupConfigStoreData); - mClock = clock; - mLastDisconnectTimestampMillis = 0; - mLastDisconnectInfo = null; - } - - private void readWifiWakeupEnabledFromSettings() { - mWifiWakeupEnabled = mFrameworkFacade.getIntegerSetting( - mContext, Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1; - Log.d(TAG, "WifiWake " + (mWifiWakeupEnabled ? "enabled" : "disabled")); - } - - private void setActive(boolean isActive) { - if (mIsActive != isActive) { - Log.d(TAG, "Setting active to " + isActive); - mIsActive = isActive; - mWifiConfigManager.saveToStore(false /* forceWrite */); - } - } - - /** - * Enable/Disable the feature. - */ - public void setEnabled(boolean enable) { - mFrameworkFacade.setIntegerSetting( - mContext, Settings.Global.WIFI_WAKEUP_ENABLED, enable ? 1 : 0); - } - - /** - * Whether the feature is currently enabled. - */ - public boolean isEnabled() { - return mWifiWakeupEnabled; - } - - /** - * Saves the SSID of the last Wifi network that was disconnected. Should only be called before - * WakeupController is active. - */ - public void setLastDisconnectInfo(ScanResultMatchInfo scanResultMatchInfo) { - if (mIsActive) { - Log.e(TAG, "Unexpected setLastDisconnectInfo when WakeupController is active!"); - return; - } - if (scanResultMatchInfo == null) { - Log.e(TAG, "Unexpected setLastDisconnectInfo(null)"); - return; - } - mLastDisconnectTimestampMillis = mClock.getElapsedSinceBootMillis(); - mLastDisconnectInfo = scanResultMatchInfo; - if (mVerboseLoggingEnabled) { - Log.d(TAG, "mLastDisconnectInfo set to " + scanResultMatchInfo); - } - } - - /** - * If Wifi was disabled within LAST_DISCONNECT_TIMEOUT_MILLIS of losing a Wifi connection, - * add that Wifi connection to the Wakeup Lock as if Wifi was disabled while connected to that - * connection. - * Often times, networks with poor signal intermittently connect and disconnect, causing the - * user to manually turn off Wifi. If the Wifi was turned off during the disconnected phase of - * the intermittent connection, then that connection normally would not be added to the Wakeup - * Lock. This constant defines the timeout after disconnecting, in milliseconds, within which - * if Wifi was disabled, the network would still be added to the wakeup lock. - */ - @VisibleForTesting - static final long LAST_DISCONNECT_TIMEOUT_MILLIS = 5 * 1000; - - /** - * Starts listening for incoming scans. - * - * <p>Should only be called upon entering ScanMode. WakeupController registers its listener with - * the WifiScanner. If the WakeupController is already active, then it returns early. Otherwise - * it performs its initialization steps and sets {@link #mIsActive} to true. - */ - public void start() { - Log.d(TAG, "start()"); - if (getGoodSavedNetworksAndSuggestions().isEmpty()) { - Log.i(TAG, "Ignore wakeup start since there are no good networks."); - return; - } - mWifiInjector.getWifiScanner().registerScanListener( - new HandlerExecutor(mHandler), mScanListener); - - // If already active, we don't want to restart the session, so return early. - if (mIsActive) { - mWifiWakeMetrics.recordIgnoredStart(); - return; - } - setActive(true); - - // ensure feature is enabled and store data has been read before performing work - if (isEnabledAndReady()) { - mWakeupOnboarding.maybeShowNotification(); - - List<ScanResult> scanResults = - filterDfsScanResults(mWifiInjector.getWifiScanner().getSingleScanResults()); - Set<ScanResultMatchInfo> matchInfos = toMatchInfos(scanResults); - matchInfos.retainAll(getGoodSavedNetworksAndSuggestions()); - - // ensure that the last disconnected network is added to the wakeup lock, since we don't - // want to automatically reconnect to the same network that the user manually - // disconnected from - long now = mClock.getElapsedSinceBootMillis(); - if (mLastDisconnectInfo != null && ((now - mLastDisconnectTimestampMillis) - <= LAST_DISCONNECT_TIMEOUT_MILLIS)) { - matchInfos.add(mLastDisconnectInfo); - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Added last connected network to lock: " + mLastDisconnectInfo); - } - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Saved networks in most recent scan:" + matchInfos); - } - - mWifiWakeMetrics.recordStartEvent(matchInfos.size()); - mWakeupLock.setLock(matchInfos); - // TODO(b/77291248): request low latency scan here - } - } - - /** - * Stops listening for scans. - * - * <p>Should only be called upon leaving ScanMode. It deregisters the listener from - * WifiScanner. - */ - public void stop() { - Log.d(TAG, "stop()"); - mLastDisconnectTimestampMillis = 0; - mLastDisconnectInfo = null; - mWifiInjector.getWifiScanner().unregisterScanListener(mScanListener); - mWakeupOnboarding.onStop(); - } - - /** Resets the WakeupController, setting {@link #mIsActive} to false. */ - public void reset() { - Log.d(TAG, "reset()"); - mWifiWakeMetrics.recordResetEvent(mNumScansHandled); - mNumScansHandled = 0; - setActive(false); - } - - /** Sets verbose logging flag based on verbose level. */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = verbose > 0; - mWakeupLock.enableVerboseLogging(mVerboseLoggingEnabled); - } - - /** Returns a list of ScanResults with DFS channels removed. */ - private List<ScanResult> filterDfsScanResults(Collection<ScanResult> scanResults) { - int[] dfsChannels = mWifiInjector.getWifiNative() - .getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY); - if (dfsChannels == null) { - dfsChannels = new int[0]; - } - - final Set<Integer> dfsChannelSet = Arrays.stream(dfsChannels).boxed() - .collect(Collectors.toSet()); - - return scanResults.stream() - .filter(scanResult -> !dfsChannelSet.contains(scanResult.frequency)) - .collect(Collectors.toList()); - } - - /** Returns a filtered set of saved networks from WifiConfigManager & suggestions - * from WifiNetworkSuggestionsManager. */ - private Set<ScanResultMatchInfo> getGoodSavedNetworksAndSuggestions() { - List<WifiConfiguration> savedNetworks = mWifiConfigManager.getSavedNetworks( - Process.WIFI_UID); - - Set<ScanResultMatchInfo> goodNetworks = new HashSet<>(savedNetworks.size()); - for (WifiConfiguration config : savedNetworks) { - if (isWideAreaNetwork(config) - || config.hasNoInternetAccess() - || config.noInternetAccessExpected - || !config.getNetworkSelectionStatus().hasEverConnected()) { - continue; - } - goodNetworks.add(ScanResultMatchInfo.fromWifiConfiguration(config)); - } - - Set<WifiNetworkSuggestion> networkSuggestions = - mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions(); - for (WifiNetworkSuggestion suggestion : networkSuggestions) { - // TODO(b/127799111): Do we need to filter the list similar to saved networks above? - goodNetworks.add( - ScanResultMatchInfo.fromWifiConfiguration(suggestion.wifiConfiguration)); - } - return goodNetworks; - } - - //TODO(b/69271702) implement WAN filtering - private static boolean isWideAreaNetwork(WifiConfiguration config) { - return false; - } - - /** - * Handles incoming scan results. - * - * <p>The controller updates the WakeupLock with the incoming scan results. If WakeupLock is not - * yet fully initialized, it adds the current scanResults to the lock and returns. If WakeupLock - * is initialized but not empty, the controller updates the lock with the current scan. If it is - * both initialized and empty, it evaluates scan results for a match with saved networks. If a - * match exists, it enables wifi. - * - * <p>The feature must be enabled and the store data must be loaded in order for the controller - * to handle scan results. - * - * @param scanResults The scan results with which to update the controller - */ - private void handleScanResults(Collection<ScanResult> scanResults) { - if (!isEnabledAndReady()) { - Log.d(TAG, "Attempted to handleScanResults while not enabled"); - return; - } - - // only count scan as handled if isEnabledAndReady - mNumScansHandled++; - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Incoming scan #" + mNumScansHandled); - } - - // need to show notification here in case user turns phone on while wifi is off - mWakeupOnboarding.maybeShowNotification(); - - // filter out unknown networks - Set<ScanResultMatchInfo> goodNetworks = getGoodSavedNetworksAndSuggestions(); - Set<ScanResultMatchInfo> matchInfos = toMatchInfos(scanResults); - matchInfos.retainAll(goodNetworks); - - mWakeupLock.update(matchInfos); - if (!mWakeupLock.isUnlocked()) { - return; - } - - ScanResult network = mWakeupEvaluator.findViableNetwork(scanResults, goodNetworks); - - if (network != null) { - Log.d(TAG, "Enabling wifi for network: " + network.SSID); - enableWifi(); - } - } - - /** - * Converts ScanResults to ScanResultMatchInfos. - */ - private static Set<ScanResultMatchInfo> toMatchInfos(Collection<ScanResult> scanResults) { - return scanResults.stream() - .map(ScanResultMatchInfo::fromScanResult) - .collect(Collectors.toSet()); - } - - /** - * Enables wifi. - * - * <p>This method ignores all checks and assumes that {@link ActiveModeWarden} is currently - * in ScanModeState. - */ - private void enableWifi() { - if (USE_PLATFORM_WIFI_WAKE) { - // TODO(b/72180295): ensure that there is no race condition with WifiServiceImpl here - if (mWifiInjector.getWifiSettingsStore().handleWifiToggled(true /* wifiEnabled */)) { - mWifiInjector.getActiveModeWarden().wifiToggled(); - mWifiWakeMetrics.recordWakeupEvent(mNumScansHandled); - } - } - } - - /** - * Whether the feature is currently enabled. - * - * <p>This method checks both the Settings value and the store data to ensure that it has been - * read. - */ - @VisibleForTesting - boolean isEnabledAndReady() { - return mWifiWakeupEnabled && mWakeupConfigStoreData.hasBeenRead(); - } - - /** Dumps wakeup controller state. */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WakeupController"); - pw.println("USE_PLATFORM_WIFI_WAKE: " + USE_PLATFORM_WIFI_WAKE); - pw.println("mWifiWakeupEnabled: " + mWifiWakeupEnabled); - pw.println("isOnboarded: " + mWakeupOnboarding.isOnboarded()); - pw.println("configStore hasBeenRead: " + mWakeupConfigStoreData.hasBeenRead()); - pw.println("mIsActive: " + mIsActive); - pw.println("mNumScansHandled: " + mNumScansHandled); - - mWakeupLock.dump(fd, pw, args); - } - - private class IsActiveDataSource implements WakeupConfigStoreData.DataSource<Boolean> { - - @Override - public Boolean getData() { - return mIsActive; - } - - @Override - public void setData(Boolean data) { - mIsActive = data; - } - } -} diff --git a/service/java/com/android/server/wifi/WakeupEvaluator.java b/service/java/com/android/server/wifi/WakeupEvaluator.java deleted file mode 100644 index ceee8af79..000000000 --- a/service/java/com/android/server/wifi/WakeupEvaluator.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import android.net.wifi.ScanResult; - -import java.util.Collection; - -/** - * Evaluates ScanResults for Wifi Wake. - */ -public class WakeupEvaluator { - - private final ScoringParams mScoringParams; - - WakeupEvaluator(ScoringParams scoringParams) { - mScoringParams = scoringParams; - } - - /** - * Searches ScanResults to find a connectable network. - * - * <p>This method searches the given ScanResults for one that is present in the given - * ScanResultMatchInfos and has a sufficiently high RSSI. If there is no such ScanResult, it - * returns null. If there are multiple, it returns the one with the highest RSSI. - * - * @param scanResults ScanResults to search - * @param networks Network list to compare against - * @return The {@link ScanResult} representing an in-range connectable network, or {@code null} - * signifying there is no viable network - */ - public ScanResult findViableNetwork(Collection<ScanResult> scanResults, - Collection<ScanResultMatchInfo> networks) { - ScanResult selectedScanResult = null; - - for (ScanResult scanResult : scanResults) { - if (isBelowThreshold(scanResult)) { - continue; - } - if (networks.contains(ScanResultMatchInfo.fromScanResult(scanResult))) { - if (selectedScanResult == null || selectedScanResult.level < scanResult.level) { - selectedScanResult = scanResult; - } - } - } - - return selectedScanResult; - } - - /** - * Returns whether the given ScanResult's signal strength is below the selection threshold. - */ - public boolean isBelowThreshold(ScanResult scanResult) { - return scanResult.level < mScoringParams.getEntryRssi(scanResult.frequency); - } -} diff --git a/service/java/com/android/server/wifi/WakeupLock.java b/service/java/com/android/server/wifi/WakeupLock.java deleted file mode 100644 index 3a1d097fc..000000000 --- a/service/java/com/android/server/wifi/WakeupLock.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import android.text.format.DateUtils; -import android.util.ArrayMap; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -/** - * A lock to determine whether Wifi Wake can re-enable Wifi. - * - * <p>Wakeuplock manages a list of networks to determine whether the device's location has changed. - */ -public class WakeupLock { - - private static final String TAG = WakeupLock.class.getSimpleName(); - - @VisibleForTesting - static final int CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT = 5; - @VisibleForTesting - static final long MAX_LOCK_TIME_MILLIS = 10 * DateUtils.MINUTE_IN_MILLIS; - - private final WifiConfigManager mWifiConfigManager; - private final Map<ScanResultMatchInfo, Integer> mLockedNetworks = new ArrayMap<>(); - private final WifiWakeMetrics mWifiWakeMetrics; - private final Clock mClock; - - private boolean mVerboseLoggingEnabled; - private long mLockTimestamp; - private boolean mIsInitialized; - private int mNumScans; - - public WakeupLock(WifiConfigManager wifiConfigManager, WifiWakeMetrics wifiWakeMetrics, - Clock clock) { - mWifiConfigManager = wifiConfigManager; - mWifiWakeMetrics = wifiWakeMetrics; - mClock = clock; - } - - /** - * Sets the WakeupLock with the given {@link ScanResultMatchInfo} list. - * - * <p>This saves the wakeup lock to the store and begins the initialization process. - * - * @param scanResultList list of ScanResultMatchInfos to start the lock with - */ - public void setLock(Collection<ScanResultMatchInfo> scanResultList) { - mLockTimestamp = mClock.getElapsedSinceBootMillis(); - mIsInitialized = false; - mNumScans = 0; - - mLockedNetworks.clear(); - for (ScanResultMatchInfo scanResultMatchInfo : scanResultList) { - mLockedNetworks.put(scanResultMatchInfo, CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT); - } - - Log.d(TAG, "Lock set. Number of networks: " + mLockedNetworks.size()); - - mWifiConfigManager.saveToStore(false /* forceWrite */); - } - - /** - * Maybe sets the WakeupLock as initialized based on total scans handled. - * - * @param numScans total number of elapsed scans in the current WifiWake session - */ - private void maybeSetInitializedByScans(int numScans) { - if (mIsInitialized) { - return; - } - boolean shouldBeInitialized = numScans >= CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT; - if (shouldBeInitialized) { - mIsInitialized = true; - - Log.d(TAG, "Lock initialized by handled scans. Scans: " + numScans); - if (mVerboseLoggingEnabled) { - Log.d(TAG, "State of lock: " + mLockedNetworks); - } - - // log initialize event - mWifiWakeMetrics.recordInitializeEvent(mNumScans, mLockedNetworks.size()); - } - } - - /** - * Maybe sets the WakeupLock as initialized based on elapsed time. - * - * @param timestampMillis current timestamp - */ - private void maybeSetInitializedByTimeout(long timestampMillis) { - if (mIsInitialized) { - return; - } - long elapsedTime = timestampMillis - mLockTimestamp; - boolean shouldBeInitialized = elapsedTime > MAX_LOCK_TIME_MILLIS; - - if (shouldBeInitialized) { - mIsInitialized = true; - - Log.d(TAG, "Lock initialized by timeout. Elapsed time: " + elapsedTime); - if (mNumScans == 0) { - Log.w(TAG, "Lock initialized with 0 handled scans!"); - } - if (mVerboseLoggingEnabled) { - Log.d(TAG, "State of lock: " + mLockedNetworks); - } - - // log initialize event - mWifiWakeMetrics.recordInitializeEvent(mNumScans, mLockedNetworks.size()); - } - } - - /** Returns whether the lock has been fully initialized. */ - public boolean isInitialized() { - return mIsInitialized; - } - - /** - * Adds the given networks to the lock. - * - * <p>This is called during the initialization step. - * - * @param networkList The list of networks to be added - */ - private void addToLock(Collection<ScanResultMatchInfo> networkList) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Initializing lock with networks: " + networkList); - } - - boolean hasChanged = false; - - for (ScanResultMatchInfo network : networkList) { - if (!mLockedNetworks.containsKey(network)) { - mLockedNetworks.put(network, CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT); - hasChanged = true; - } - } - - if (hasChanged) { - mWifiConfigManager.saveToStore(false /* forceWrite */); - } - - // Set initialized if the lock has handled enough scans, and log the event - maybeSetInitializedByScans(mNumScans); - } - - /** - * Removes networks from the lock if not present in the given {@link ScanResultMatchInfo} list. - * - * <p>If a network in the lock is not present in the list, reduce the number of scans - * required to evict by one. Remove any entries in the list with 0 scans required to evict. If - * any entries in the lock are removed, the store is updated. - * - * @param networkList list of present ScanResultMatchInfos to update the lock with - */ - private void removeFromLock(Collection<ScanResultMatchInfo> networkList) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Filtering lock with networks: " + networkList); - } - - boolean hasChanged = false; - Iterator<Map.Entry<ScanResultMatchInfo, Integer>> it = - mLockedNetworks.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<ScanResultMatchInfo, Integer> entry = it.next(); - - // if present in scan list, reset to max - if (networkList.contains(entry.getKey())) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Found network in lock: " + entry.getKey().networkSsid); - } - entry.setValue(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT); - continue; - } - - // decrement and remove if necessary - entry.setValue(entry.getValue() - 1); - if (entry.getValue() <= 0) { - Log.d(TAG, "Removed network from lock: " + entry.getKey().networkSsid); - it.remove(); - hasChanged = true; - } - } - - if (hasChanged) { - mWifiConfigManager.saveToStore(false /* forceWrite */); - } - - if (isUnlocked()) { - Log.d(TAG, "Lock emptied. Recording unlock event."); - mWifiWakeMetrics.recordUnlockEvent(mNumScans); - } - } - - /** - * Updates the lock with the given {@link ScanResultMatchInfo} list. - * - * <p>Based on the current initialization state of the lock, either adds or removes networks - * from the lock. - * - * <p>The lock is initialized after {@link #CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT} - * scans have been handled, or after {@link #MAX_LOCK_TIME_MILLIS} milliseconds have elapsed - * since {@link #setLock(Collection)}. - * - * @param networkList list of present ScanResultMatchInfos to update the lock with - */ - public void update(Collection<ScanResultMatchInfo> networkList) { - // update is no-op if already unlocked - if (isUnlocked()) { - return; - } - // Before checking handling the scan, we check to see whether we've exceeded the maximum - // time allowed for initialization. If so, we set initialized and treat this scan as a - // "removeFromLock()" instead of an "addToLock()". - maybeSetInitializedByTimeout(mClock.getElapsedSinceBootMillis()); - - mNumScans++; - - // add or remove networks based on initialized status - if (mIsInitialized) { - removeFromLock(networkList); - } else { - addToLock(networkList); - } - } - - /** Returns whether the WakeupLock is unlocked */ - public boolean isUnlocked() { - return mIsInitialized && mLockedNetworks.isEmpty(); - } - - /** Returns the data source for the WakeupLock config store data. */ - public WakeupConfigStoreData.DataSource<Set<ScanResultMatchInfo>> getDataSource() { - return new WakeupLockDataSource(); - } - - /** Dumps wakeup lock contents. */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("WakeupLock: "); - pw.println("mNumScans: " + mNumScans); - pw.println("mIsInitialized: " + mIsInitialized); - pw.println("Locked networks: " + mLockedNetworks.size()); - for (Map.Entry<ScanResultMatchInfo, Integer> entry : mLockedNetworks.entrySet()) { - pw.println(entry.getKey() + ", scans to evict: " + entry.getValue()); - } - } - - /** Set whether verbose logging is enabled. */ - public void enableVerboseLogging(boolean enabled) { - mVerboseLoggingEnabled = enabled; - } - - private class WakeupLockDataSource - implements WakeupConfigStoreData.DataSource<Set<ScanResultMatchInfo>> { - - @Override - public Set<ScanResultMatchInfo> getData() { - return mLockedNetworks.keySet(); - } - - @Override - public void setData(Set<ScanResultMatchInfo> data) { - mLockedNetworks.clear(); - for (ScanResultMatchInfo network : data) { - mLockedNetworks.put(network, CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT); - } - // lock is considered initialized if loaded from store - mIsInitialized = true; - } - } -} diff --git a/service/java/com/android/server/wifi/WakeupNotificationFactory.java b/service/java/com/android/server/wifi/WakeupNotificationFactory.java deleted file mode 100644 index 9eb69b70c..000000000 --- a/service/java/com/android/server/wifi/WakeupNotificationFactory.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Intent; -import android.graphics.drawable.Icon; - -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.wifi.resources.R; - - -/** Factory for Wifi Wake notifications. */ -public class WakeupNotificationFactory { - - public static final String ACTION_DISMISS_NOTIFICATION = - "com.android.server.wifi.wakeup.DISMISS_NOTIFICATION"; - public static final String ACTION_OPEN_WIFI_PREFERENCES = - "com.android.server.wifi.wakeup.OPEN_WIFI_PREFERENCES"; - public static final String ACTION_OPEN_WIFI_SETTINGS = - "com.android.server.wifi.wakeup.OPEN_WIFI_SETTINGS"; - public static final String ACTION_TURN_OFF_WIFI_WAKE = - "com.android.server.wifi.wakeup.TURN_OFF_WIFI_WAKE"; - - /** Notification channel ID for onboarding messages. */ - public static final int ONBOARD_ID = SystemMessage.NOTE_WIFI_WAKE_ONBOARD; - - private final WifiContext mContext; - private final WifiInjector mWifiInjector; - private final FrameworkFacade mFrameworkFacade; - - WakeupNotificationFactory(WifiContext context, WifiInjector wifiInjector, - FrameworkFacade frameworkFacade) { - mContext = context; - mWifiInjector = wifiInjector; - mFrameworkFacade = frameworkFacade; - } - - /** - * Creates a Wifi Wake onboarding notification. - */ - public Notification createOnboardingNotification() { - CharSequence title = mContext.getText(R.string.wifi_wakeup_onboarding_title); - CharSequence content = mContext.getText(R.string.wifi_wakeup_onboarding_subtext); - CharSequence disableText = mContext.getText(R.string.wifi_wakeup_onboarding_action_disable); - int color = mContext.getResources() - .getColor(android.R.color.system_notification_accent_color, mContext.getTheme()); - - final Notification.Action disableAction = new Notification.Action.Builder( - null /* icon */, disableText, getPrivateBroadcast(ACTION_TURN_OFF_WIFI_WAKE)) - .build(); - - return mFrameworkFacade.makeNotificationBuilder(mContext, - WifiService.NOTIFICATION_NETWORK_STATUS) - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - R.drawable.ic_wifi_settings)) - .setTicker(title) - .setContentTitle(title) - .setContentText(content) - .setContentIntent(getPrivateBroadcast(ACTION_OPEN_WIFI_PREFERENCES)) - .setDeleteIntent(getPrivateBroadcast(ACTION_DISMISS_NOTIFICATION)) - .addAction(disableAction) - .setShowWhen(false) - .setLocalOnly(true) - .setColor(color) - .build(); - } - - - private PendingIntent getPrivateBroadcast(String action) { - Intent intent = new Intent(action) - .setPackage(mWifiInjector.getWifiStackPackageName()); - return mFrameworkFacade.getBroadcast( - mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } -} diff --git a/service/java/com/android/server/wifi/WakeupOnboarding.java b/service/java/com/android/server/wifi/WakeupOnboarding.java deleted file mode 100644 index 93540e00a..000000000 --- a/service/java/com/android/server/wifi/WakeupOnboarding.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import static com.android.server.wifi.WakeupNotificationFactory.ACTION_DISMISS_NOTIFICATION; -import static com.android.server.wifi.WakeupNotificationFactory.ACTION_OPEN_WIFI_PREFERENCES; -import static com.android.server.wifi.WakeupNotificationFactory.ACTION_TURN_OFF_WIFI_WAKE; - -import android.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Handler; -import android.os.SystemClock; -import android.provider.Settings; -import android.text.format.DateUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -/** - * Manages the WiFi Wake onboarding notification. - * - * <p>If a user disables wifi with Wifi Wake enabled, this notification is shown to explain that - * wifi may turn back on automatically. It will be displayed up to 3 times, or until the - * user either interacts with the onboarding notification in some way (e.g. dismiss, tap) or - * manually enables/disables the feature in WifiSettings. - */ -public class WakeupOnboarding { - - private static final String TAG = "WakeupOnboarding"; - - @VisibleForTesting - static final int NOTIFICATIONS_UNTIL_ONBOARDED = 3; - @VisibleForTesting - static final long REQUIRED_NOTIFICATION_DELAY = DateUtils.DAY_IN_MILLIS; - private static final long NOT_SHOWN_TIMESTAMP = -1; - - private final Context mContext; - private final WakeupNotificationFactory mWakeupNotificationFactory; - private NotificationManager mNotificationManager; - private final Handler mHandler; - private final WifiConfigManager mWifiConfigManager; - private final IntentFilter mIntentFilter; - private final FrameworkFacade mFrameworkFacade; - - private boolean mIsOnboarded; - private int mTotalNotificationsShown; - private long mLastShownTimestamp = NOT_SHOWN_TIMESTAMP; - private boolean mIsNotificationShowing; - - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - switch (intent.getAction()) { - case ACTION_TURN_OFF_WIFI_WAKE: - mFrameworkFacade.setIntegerSetting(mContext, - Settings.Global.WIFI_WAKEUP_ENABLED, 0); - dismissNotification(true /* shouldOnboard */); - break; - case ACTION_OPEN_WIFI_PREFERENCES: - // Close notification drawer before opening preferences. - mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); - mContext.startActivity(new Intent(Settings.ACTION_WIFI_IP_SETTINGS) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - dismissNotification(true /* shouldOnboard */); - break; - case ACTION_DISMISS_NOTIFICATION: - dismissNotification(true /* shouldOnboard */); - break; - default: - Log.e(TAG, "Unknown action " + intent.getAction()); - } - } - }; - - public WakeupOnboarding( - Context context, - WifiConfigManager wifiConfigManager, - Handler handler, - FrameworkFacade frameworkFacade, - WakeupNotificationFactory wakeupNotificationFactory) { - mContext = context; - mWifiConfigManager = wifiConfigManager; - mHandler = handler; - mFrameworkFacade = frameworkFacade; - mWakeupNotificationFactory = wakeupNotificationFactory; - - mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(ACTION_TURN_OFF_WIFI_WAKE); - mIntentFilter.addAction(ACTION_DISMISS_NOTIFICATION); - mIntentFilter.addAction(ACTION_OPEN_WIFI_PREFERENCES); - } - - /** Returns whether the user is onboarded. */ - public boolean isOnboarded() { - return mIsOnboarded; - } - - /** Shows the onboarding notification if applicable. */ - public void maybeShowNotification() { - maybeShowNotification(SystemClock.elapsedRealtime()); - } - - @VisibleForTesting - void maybeShowNotification(long timestamp) { - if (!shouldShowNotification(timestamp)) { - return; - } - Log.d(TAG, "Showing onboarding notification."); - - incrementTotalNotificationsShown(); - mIsNotificationShowing = true; - mLastShownTimestamp = timestamp; - - mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, - null /* broadcastPermission */, mHandler); - getNotificationManager().notify(WakeupNotificationFactory.ONBOARD_ID, - mWakeupNotificationFactory.createOnboardingNotification()); - } - - /** - * Increment the total number of shown notifications and onboard the user if reached the - * required amount. - */ - private void incrementTotalNotificationsShown() { - mTotalNotificationsShown++; - if (mTotalNotificationsShown >= NOTIFICATIONS_UNTIL_ONBOARDED) { - setOnboarded(); - } else { - mWifiConfigManager.saveToStore(false /* forceWrite */); - } - } - - private boolean shouldShowNotification(long timestamp) { - if (isOnboarded() || mIsNotificationShowing) { - return false; - } - - return mLastShownTimestamp == NOT_SHOWN_TIMESTAMP - || (timestamp - mLastShownTimestamp) > REQUIRED_NOTIFICATION_DELAY; - } - - /** Handles onboarding cleanup on stop. */ - public void onStop() { - dismissNotification(false /* shouldOnboard */); - } - - private void dismissNotification(boolean shouldOnboard) { - if (!mIsNotificationShowing) { - return; - } - - if (shouldOnboard) { - setOnboarded(); - } - - mContext.unregisterReceiver(mBroadcastReceiver); - getNotificationManager().cancel(WakeupNotificationFactory.ONBOARD_ID); - mIsNotificationShowing = false; - } - - /** Sets the user as onboarded and persists to store. */ - public void setOnboarded() { - if (mIsOnboarded) { - return; - } - Log.d(TAG, "Setting user as onboarded."); - mIsOnboarded = true; - mWifiConfigManager.saveToStore(false /* forceWrite */); - } - - private NotificationManager getNotificationManager() { - if (mNotificationManager == null) { - mNotificationManager = (NotificationManager) - mContext.getSystemService(Context.NOTIFICATION_SERVICE); - } - return mNotificationManager; - } - - /** Returns the {@link WakeupConfigStoreData.DataSource} for the onboarded status. */ - public WakeupConfigStoreData.DataSource<Boolean> getIsOnboadedDataSource() { - return new IsOnboardedDataSource(); - } - - /** Returns the {@link WakeupConfigStoreData.DataSource} for the notification status. */ - public WakeupConfigStoreData.DataSource<Integer> getNotificationsDataSource() { - return new NotificationsDataSource(); - } - - private class IsOnboardedDataSource implements WakeupConfigStoreData.DataSource<Boolean> { - - @Override - public Boolean getData() { - return mIsOnboarded; - } - - @Override - public void setData(Boolean data) { - mIsOnboarded = data; - } - } - - private class NotificationsDataSource implements WakeupConfigStoreData.DataSource<Integer> { - - @Override - public Integer getData() { - return mTotalNotificationsShown; - } - - @Override - public void setData(Integer data) { - mTotalNotificationsShown = data; - } - } -} diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java deleted file mode 100644 index 3de99711b..000000000 --- a/service/java/com/android/server/wifi/WifiApConfigStore.java +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import android.annotation.NonNull; -import android.content.Context; -import android.content.IntentFilter; -import android.net.MacAddress; -import android.net.util.MacAddressUtils; -import android.net.wifi.SoftApConfiguration; -import android.os.Handler; -import android.os.Process; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.ApConfigUtil; -import com.android.wifi.resources.R; - -import java.nio.charset.StandardCharsets; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Random; - -import javax.annotation.Nullable; - -/** - * Provides API for reading/writing soft access point configuration. - */ -public class WifiApConfigStore { - - // Intent when user has interacted with the softap settings change notification - public static final String ACTION_HOTSPOT_CONFIG_USER_TAPPED_CONTENT = - "com.android.server.wifi.WifiApConfigStoreUtil.HOTSPOT_CONFIG_USER_TAPPED_CONTENT"; - - private static final String TAG = "WifiApConfigStore"; - - private static final int RAND_SSID_INT_MIN = 1000; - private static final int RAND_SSID_INT_MAX = 9999; - - @VisibleForTesting - static final int SSID_MIN_LEN = 1; - @VisibleForTesting - static final int SSID_MAX_LEN = 32; - @VisibleForTesting - static final int PSK_MIN_LEN = 8; - @VisibleForTesting - static final int PSK_MAX_LEN = 63; - - private SoftApConfiguration mPersistentWifiApConfig = null; - - private final Context mContext; - private final Handler mHandler; - private final WifiMetrics mWifiMetrics; - private final BackupManagerProxy mBackupManagerProxy; - private final MacAddressUtil mMacAddressUtil; - private final WifiConfigManager mWifiConfigManager; - private final ActiveModeWarden mActiveModeWarden; - private boolean mHasNewDataToSerialize = false; - - /** - * Module to interact with the wifi config store. - */ - private class SoftApStoreDataSource implements SoftApStoreData.DataSource { - - public SoftApConfiguration toSerialize() { - mHasNewDataToSerialize = false; - return mPersistentWifiApConfig; - } - - public void fromDeserialized(SoftApConfiguration config) { - mPersistentWifiApConfig = new SoftApConfiguration.Builder(config).build(); - } - - public void reset() { - mPersistentWifiApConfig = null; - } - - public boolean hasNewDataToSerialize() { - return mHasNewDataToSerialize; - } - } - - WifiApConfigStore(Context context, - WifiInjector wifiInjector, - Handler handler, - BackupManagerProxy backupManagerProxy, - WifiConfigStore wifiConfigStore, - WifiConfigManager wifiConfigManager, - ActiveModeWarden activeModeWarden, - WifiMetrics wifiMetrics) { - mContext = context; - mHandler = handler; - mBackupManagerProxy = backupManagerProxy; - mWifiConfigManager = wifiConfigManager; - mActiveModeWarden = activeModeWarden; - mWifiMetrics = wifiMetrics; - - // Register store data listener - wifiConfigStore.registerStoreData( - wifiInjector.makeSoftApStoreData(new SoftApStoreDataSource())); - - IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_HOTSPOT_CONFIG_USER_TAPPED_CONTENT); - mMacAddressUtil = wifiInjector.getMacAddressUtil(); - } - - /** - * Return the current soft access point configuration. - */ - public synchronized SoftApConfiguration getApConfiguration() { - if (mPersistentWifiApConfig == null) { - /* Use default configuration. */ - Log.d(TAG, "Fallback to use default AP configuration"); - persistConfigAndTriggerBackupManagerProxy(getDefaultApConfiguration()); - } - SoftApConfiguration sanitizedPersistentconfig = - sanitizePersistentApConfig(mPersistentWifiApConfig); - if (mPersistentWifiApConfig != sanitizedPersistentconfig) { - Log.d(TAG, "persisted config was converted, need to resave it"); - persistConfigAndTriggerBackupManagerProxy(sanitizedPersistentconfig); - } - return mPersistentWifiApConfig; - } - - /** - * Update the current soft access point configuration. - * Restore to default AP configuration if null is provided. - * This can be invoked under context of binder threads (WifiManager.setWifiApConfiguration) - * and the main Wifi thread (CMD_START_AP). - */ - public synchronized void setApConfiguration(SoftApConfiguration config) { - if (config == null) { - config = getDefaultApConfiguration(); - } else { - config = sanitizePersistentApConfig(config); - } - persistConfigAndTriggerBackupManagerProxy(config); - } - - /** - * Returns SoftApConfiguration in which some parameters might be reset to supported default - * config since it depends on UI or HW. - * - * MaxNumberOfClients and isClientControlByUserEnabled will need HAL support client force - * disconnect, and Band setting (5g/6g) need HW support. - * - * HiddenSsid, Channel, ShutdownTimeoutMillis and AutoShutdownEnabled are features - * which need UI(Setting) support. - * - * SAE/SAE-Transition need hardware support, reset to secured WPA2 security type when device - * doesn't support it. - */ - public SoftApConfiguration resetToDefaultForUnsupportedConfig( - @NonNull SoftApConfiguration config) { - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config); - if ((!ApConfigUtil.isClientForceDisconnectSupported(mContext) - || mContext.getResources().getBoolean( - R.bool.config_wifiSoftapResetUserControlConfig)) - && (config.isClientControlByUserEnabled() - || config.getBlockedClientList().size() != 0)) { - configBuilder.setClientControlByUserEnabled(false); - configBuilder.setBlockedClientList(new ArrayList<>()); - Log.i(TAG, "Reset ClientControlByUser to false due to device doesn't support"); - } - - if ((!ApConfigUtil.isClientForceDisconnectSupported(mContext) - || mContext.getResources().getBoolean( - R.bool.config_wifiSoftapResetMaxClientSettingConfig)) - && config.getMaxNumberOfClients() != 0) { - configBuilder.setMaxNumberOfClients(0); - Log.i(TAG, "Reset MaxNumberOfClients to 0 due to device doesn't support"); - } - - if (!ApConfigUtil.isWpa3SaeSupported(mContext) && (config.getSecurityType() - == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE - || config.getSecurityType() - == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)) { - configBuilder.setPassphrase(generatePassword(), - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - Log.i(TAG, "Device doesn't support WPA3-SAE, reset config to WPA2"); - } - - if (mContext.getResources().getBoolean(R.bool.config_wifiSoftapResetChannelConfig) - && config.getChannel() != 0) { - // The device might not support customize channel or forced channel might not - // work in some countries. Need to reset it. - // Add 2.4G by default - configBuilder.setBand(config.getBand() | SoftApConfiguration.BAND_2GHZ); - Log.i(TAG, "Reset SAP channel configuration"); - } - - int newBand = config.getBand(); - if (!mContext.getResources().getBoolean(R.bool.config_wifi6ghzSupport) - && (newBand & SoftApConfiguration.BAND_6GHZ) != 0) { - newBand &= ~SoftApConfiguration.BAND_6GHZ; - Log.i(TAG, "Device doesn't support 6g, remove 6G band from band setting"); - } - - if (!mContext.getResources().getBoolean(R.bool.config_wifi5ghzSupport) - && (newBand & SoftApConfiguration.BAND_5GHZ) != 0) { - newBand &= ~SoftApConfiguration.BAND_5GHZ; - Log.i(TAG, "Device doesn't support 5g, remove 5G band from band setting"); - } - - if (newBand != config.getBand()) { - // Always added 2.4G by default when reset the band. - Log.i(TAG, "Reset band from " + config.getBand() + " to " - + (newBand | SoftApConfiguration.BAND_2GHZ)); - configBuilder.setBand(newBand | SoftApConfiguration.BAND_2GHZ); - } - - if (mContext.getResources().getBoolean(R.bool.config_wifiSoftapResetHiddenConfig) - && config.isHiddenSsid()) { - configBuilder.setHiddenSsid(false); - Log.i(TAG, "Reset SAP Hidden Network configuration"); - } - - if (mContext.getResources().getBoolean( - R.bool.config_wifiSoftapResetAutoShutdownTimerConfig) - && config.getShutdownTimeoutMillis() != 0) { - configBuilder.setShutdownTimeoutMillis(0); - Log.i(TAG, "Reset SAP auto shutdown configuration"); - } - - mWifiMetrics.noteSoftApConfigReset(config, configBuilder.build()); - return configBuilder.build(); - } - - private SoftApConfiguration sanitizePersistentApConfig(SoftApConfiguration config) { - SoftApConfiguration.Builder convertedConfigBuilder = null; - - // some countries are unable to support 5GHz only operation, always allow for 2GHz when - // config doesn't force channel - if (config.getChannel() == 0 && (config.getBand() & SoftApConfiguration.BAND_2GHZ) == 0) { - Log.w(TAG, "Supplied ap config band without 2.4G, add allowing for 2.4GHz"); - if (convertedConfigBuilder == null) { - convertedConfigBuilder = new SoftApConfiguration.Builder(config); - } - convertedConfigBuilder.setBand(config.getBand() | SoftApConfiguration.BAND_2GHZ); - } - return convertedConfigBuilder == null ? config : convertedConfigBuilder.build(); - } - - private void persistConfigAndTriggerBackupManagerProxy(SoftApConfiguration config) { - mPersistentWifiApConfig = config; - mHasNewDataToSerialize = true; - mWifiConfigManager.saveToStore(true); - mBackupManagerProxy.notifyDataChanged(); - } - - /** - * Generate a default WPA3 SAE transition (if supported) or WPA2 based - * configuration with a random password. - * We are changing the Wifi Ap configuration storage from secure settings to a - * flat file accessible only by the system. A WPA2 based default configuration - * will keep the device secure after the update. - */ - private SoftApConfiguration getDefaultApConfiguration() { - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(mContext.getResources().getString( - R.string.wifi_tether_configure_ssid_default) + "_" + getRandomIntForDefaultSsid()); - if (ApConfigUtil.isWpa3SaeSupported(mContext)) { - configBuilder.setPassphrase(generatePassword(), - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); - } else { - configBuilder.setPassphrase(generatePassword(), - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - } - return configBuilder.build(); - } - - private static int getRandomIntForDefaultSsid() { - Random random = new Random(); - return random.nextInt((RAND_SSID_INT_MAX - RAND_SSID_INT_MIN) + 1) + RAND_SSID_INT_MIN; - } - - private static String generateLohsSsid(Context context) { - return context.getResources().getString( - R.string.wifi_localhotspot_configure_ssid_default) + "_" - + getRandomIntForDefaultSsid(); - } - - /** - * Generate a temporary WPA2 based configuration for use by the local only hotspot. - * This config is not persisted and will not be stored by the WifiApConfigStore. - */ - public static SoftApConfiguration generateLocalOnlyHotspotConfig(Context context, int apBand, - @Nullable SoftApConfiguration customConfig) { - SoftApConfiguration.Builder configBuilder; - if (customConfig != null) { - configBuilder = new SoftApConfiguration.Builder(customConfig); - } else { - configBuilder = new SoftApConfiguration.Builder(); - // Default to disable the auto shutdown - configBuilder.setAutoShutdownEnabled(false); - } - - configBuilder.setBand(apBand); - - if (customConfig == null || customConfig.getSsid() == null) { - configBuilder.setSsid(generateLohsSsid(context)); - } - if (customConfig == null) { - if (ApConfigUtil.isWpa3SaeSupported(context)) { - configBuilder.setPassphrase(generatePassword(), - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); - } else { - configBuilder.setPassphrase(generatePassword(), - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - } - } - - return configBuilder.build(); - } - - /** - * @return a copy of the given SoftApConfig with the BSSID randomized, unless a custom BSSID is - * already set. - */ - SoftApConfiguration randomizeBssidIfUnset(Context context, SoftApConfiguration config) { - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config); - if (config.getBssid() == null && context.getResources().getBoolean( - R.bool.config_wifi_ap_mac_randomization_supported)) { - MacAddress macAddress = mMacAddressUtil.calculatePersistentMac(config.getSsid(), - mMacAddressUtil.obtainMacRandHashFunctionForSap(Process.WIFI_UID)); - if (macAddress == null) { - Log.e(TAG, "Failed to calculate MAC from SSID. " - + "Generating new random MAC instead."); - macAddress = MacAddressUtils.createRandomUnicastAddress(); - } - configBuilder.setBssid(macAddress); - } - return configBuilder.build(); - } - - /** - * Verify provided SSID for existence, length and conversion to bytes - * - * @param ssid String ssid name - * @return boolean indicating ssid met requirements - */ - private static boolean validateApConfigSsid(String ssid) { - if (TextUtils.isEmpty(ssid)) { - Log.d(TAG, "SSID for softap configuration must be set."); - return false; - } - - try { - byte[] ssid_bytes = ssid.getBytes(StandardCharsets.UTF_8); - - if (ssid_bytes.length < SSID_MIN_LEN || ssid_bytes.length > SSID_MAX_LEN) { - Log.d(TAG, "softap SSID is defined as UTF-8 and it must be at least " - + SSID_MIN_LEN + " byte and not more than " + SSID_MAX_LEN + " bytes"); - return false; - } - } catch (IllegalArgumentException e) { - Log.e(TAG, "softap config SSID verification failed: malformed string " + ssid); - return false; - } - return true; - } - - /** - * Verify provided preSharedKey in ap config for WPA2_PSK network meets requirements. - */ - private static boolean validateApConfigPreSharedKey(String preSharedKey) { - if (preSharedKey.length() < PSK_MIN_LEN || preSharedKey.length() > PSK_MAX_LEN) { - Log.d(TAG, "softap network password string size must be at least " + PSK_MIN_LEN - + " and no more than " + PSK_MAX_LEN); - return false; - } - - try { - preSharedKey.getBytes(StandardCharsets.UTF_8); - } catch (IllegalArgumentException e) { - Log.e(TAG, "softap network password verification failed: malformed string"); - return false; - } - return true; - } - - /** - * Validate a SoftApConfiguration is properly configured for use by SoftApManager. - * - * This method checks the length of the SSID and for sanity between security settings (if it - * requires a password, was one provided?). - * - * @param apConfig {@link SoftApConfiguration} to use for softap mode - * @param isPrivileged indicate the caller can pass some fields check or not - * @return boolean true if the provided config meets the minimum set of details, false - * otherwise. - */ - static boolean validateApWifiConfiguration(@NonNull SoftApConfiguration apConfig, - boolean isPrivileged) { - // first check the SSID - if (!validateApConfigSsid(apConfig.getSsid())) { - // failed SSID verificiation checks - return false; - } - - // BSSID can be set if caller own permission:android.Manifest.permission.NETWORK_SETTINGS. - if (apConfig.getBssid() != null && !isPrivileged) { - Log.e(TAG, "Config BSSID needs NETWORK_SETTINGS permission"); - return false; - } - - String preSharedKey = apConfig.getPassphrase(); - boolean hasPreSharedKey = !TextUtils.isEmpty(preSharedKey); - int authType; - - try { - authType = apConfig.getSecurityType(); - } catch (IllegalStateException e) { - Log.d(TAG, "Unable to get AuthType for softap config: " + e.getMessage()); - return false; - } - - if (authType == SoftApConfiguration.SECURITY_TYPE_OPEN) { - // open networks should not have a password - if (hasPreSharedKey) { - Log.d(TAG, "open softap network should not have a password"); - return false; - } - } else if (authType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK - || authType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION - || authType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) { - // this is a config that should have a password - check that first - if (!hasPreSharedKey) { - Log.d(TAG, "softap network password must be set"); - return false; - } - if (authType != SoftApConfiguration.SECURITY_TYPE_WPA3_SAE - && !validateApConfigPreSharedKey(preSharedKey)) { - // failed preSharedKey checks for WPA2 and WPA3 SAE Transition mode. - return false; - } - } else { - // this is not a supported security type - Log.d(TAG, "softap configs must either be open or WPA2 PSK networks"); - return false; - } - - return true; - } - - private static String generatePassword() { - // Characters that will be used for password generation. Some characters commonly known to - // be confusing like 0 and O excluded from this list. - final String allowed = "23456789abcdefghijkmnpqrstuvwxyz"; - final int passLength = 15; - - StringBuilder sb = new StringBuilder(passLength); - SecureRandom random = new SecureRandom(); - for (int i = 0; i < passLength; i++) { - sb.append(allowed.charAt(random.nextInt(allowed.length()))); - } - return sb.toString(); - } -} diff --git a/service/java/com/android/server/wifi/WifiBackupDataParser.java b/service/java/com/android/server/wifi/WifiBackupDataParser.java deleted file mode 100644 index e61cab213..000000000 --- a/service/java/com/android/server/wifi/WifiBackupDataParser.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.net.wifi.WifiConfiguration; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.List; - -/** - * Interface describing parser of WiFi backup data for each major version. - * Note that implementations of this interface should be returned - * from {@link WifiBackupRestore#getWifiBackupDataParser()} method based on major version they - * belong to. - */ -interface WifiBackupDataParser { - - /** - * Parses the list of configurations from the provided XML stream. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @param minorVersion minor version number parsed from incoming data. - * @return List<WifiConfiguration> object if parsing is successful, null otherwise. - */ - List<WifiConfiguration> parseNetworkConfigurationsFromXml(XmlPullParser in, int outerTagDepth, - int minorVersion) throws XmlPullParserException, IOException; - - /** - * Get the highest supported minor version for this major version. - * This is used for generating the version code when serializing the data. - * @return Indicating the max supported minor version by this major version parser. - */ - int getHighestSupportedMinorVersion(); -} diff --git a/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java b/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java deleted file mode 100644 index 89ab9a9a3..000000000 --- a/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.annotation.Nullable; -import android.net.InetAddresses; -import android.net.IpConfiguration; -import android.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; -import android.net.LinkAddress; -import android.net.ProxyInfo; -import android.net.RouteInfo; -import android.net.StaticIpConfiguration; -import android.net.Uri; -import android.net.wifi.WifiConfiguration; -import android.util.Log; -import android.util.Pair; - -import com.android.server.wifi.util.XmlUtil; -import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil; -import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; - -/** - * Parser for major version 1 of WiFi backup data. - * Contains whitelists of tags for WifiConfiguration and IpConfiguration sections for each of - * the minor versions. - * - * Overall structure of the major version 1 XML schema: - * <?xml version='1.0' encoding='utf-8' standalone='yes' ?> - * <WifiConfigStore> - * <float name="Version" value="1.0" /> - * <NetworkList> - * <Network> - * <WifiConfiguration> - * <string name="ConfigKey">value</string> - * <string name="SSID">value</string> - * <string name="PreSharedKey" />value</string> - * <string-array name="WEPKeys" num="4"> - * <item value="WifiConfigStoreWep1" /> - * <item value="WifiConfigStoreWep2" /> - * <item value="WifiConfigStoreWep3" /> - * <item value="WifiConfigStoreWep3" /> - * </string-array> - * ... (other supported tag names in minor version 1: "WEPTxKeyIndex", "HiddenSSID", - * "RequirePMF", "AllowedKeyMgmt", "AllowedProtocols", "AllowedAuthAlgos", - * "AllowedGroupCiphers", "AllowedPairwiseCiphers", "Shared") - * </WifiConfiguration> - * <IpConfiguration> - * <string name="IpAssignment">value</string> - * <string name="ProxySettings">value</string> - * ... (other supported tag names in minor version 1: "LinkAddress", "LinkPrefixLength", - * "GatewayAddress", "DNSServers", "ProxyHost", "ProxyPort", "ProxyPac", - * "ProxyExclusionList") - * </IpConfiguration> - * </Network> - * <Network> - * ... (format as above) - * </Network> - * </NetworkList> - * </WifiConfigStore> - */ -class WifiBackupDataV1Parser implements WifiBackupDataParser { - - private static final String TAG = "WifiBackupDataV1Parser"; - - private static final int HIGHEST_SUPPORTED_MINOR_VERSION = 2; - - // List of tags supported for <WifiConfiguration> section in minor version 0 - private static final Set<String> WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS = - new HashSet<String>(Arrays.asList(new String[] { - WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY, - WifiConfigurationXmlUtil.XML_TAG_SSID, - WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY, - WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS, - WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX, - WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID, - WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS, - WifiConfigurationXmlUtil.XML_TAG_SHARED, - })); - - // List of tags supported for <WifiConfiguration> section in minor version 1 - private static final Set<String> WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS = - new HashSet<String>() {{ - addAll(WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS); - add(WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE); - }}; - - // List of tags supported for <WifiConfiguration> section in minor version 2 - private static final Set<String> WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS = - new HashSet<String>() {{ - addAll(WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS); - add(WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN); - }}; - - // List of tags supported for <IpConfiguration> section in minor version 0 to 2 - private static final Set<String> IP_CONFIGURATION_MINOR_V0_V1_V2_SUPPORTED_TAGS = - new HashSet<String>(Arrays.asList(new String[] { - IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT, - IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS, - IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH, - IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS, - IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES, - IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS, - IpConfigurationXmlUtil.XML_TAG_PROXY_HOST, - IpConfigurationXmlUtil.XML_TAG_PROXY_PORT, - IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST, - IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE, - })); - - @Override - public List<WifiConfiguration> parseNetworkConfigurationsFromXml(XmlPullParser in, - int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { - // clamp down the minorVersion to the highest one that this parser version supports - if (minorVersion > HIGHEST_SUPPORTED_MINOR_VERSION) { - minorVersion = HIGHEST_SUPPORTED_MINOR_VERSION; - } - // Find the configuration list section. - XmlUtil.gotoNextSectionWithName(in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK_LIST, - outerTagDepth); - // Find all the configurations within the configuration list section. - int networkListTagDepth = outerTagDepth + 1; - List<WifiConfiguration> configurations = new ArrayList<>(); - while (XmlUtil.gotoNextSectionWithNameOrEnd( - in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK, networkListTagDepth)) { - WifiConfiguration configuration = - parseNetworkConfigurationFromXml(in, minorVersion, networkListTagDepth); - if (configuration != null) { - Log.v(TAG, "Parsed Configuration: " + configuration.getKey()); - configurations.add(configuration); - } - } - return configurations; - } - - @Override - public int getHighestSupportedMinorVersion() { - return HIGHEST_SUPPORTED_MINOR_VERSION; - } - - /** - * Parses the configuration data elements from the provided XML stream to a Configuration. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param minorVersion minor version number parsed from incoming data. - * @param outerTagDepth depth of the outer tag in the XML document. - * @return WifiConfiguration object if parsing is successful, null otherwise. - */ - private WifiConfiguration parseNetworkConfigurationFromXml(XmlPullParser in, int minorVersion, - int outerTagDepth) throws XmlPullParserException, IOException { - WifiConfiguration configuration = null; - int networkTagDepth = outerTagDepth + 1; - // Retrieve WifiConfiguration object first. - XmlUtil.gotoNextSectionWithName( - in, WifiBackupRestore.XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION, - networkTagDepth); - int configTagDepth = networkTagDepth + 1; - configuration = parseWifiConfigurationFromXml(in, configTagDepth, minorVersion); - if (configuration == null) { - return null; - } - // Now retrieve any IP configuration info. - XmlUtil.gotoNextSectionWithName( - in, WifiBackupRestore.XML_TAG_SECTION_HEADER_IP_CONFIGURATION, networkTagDepth); - IpConfiguration ipConfiguration = parseIpConfigurationFromXml(in, configTagDepth, - minorVersion); - configuration.setIpConfiguration(ipConfiguration); - return configuration; - } - - /** - * Helper method to parse the WifiConfiguration object. - */ - private WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in, - int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { - Pair<String, WifiConfiguration> parsedConfig = - parseWifiConfigurationFromXmlInternal(in, outerTagDepth, minorVersion); - if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) { - return null; - } - String configKeyParsed = parsedConfig.first; - WifiConfiguration configuration = parsedConfig.second; - String configKeyCalculated = configuration.getKey(); - if (!configKeyParsed.equals(configKeyCalculated)) { - // configKey is not part of the SDK. So, we can't expect this to be the same - // across OEM's. Just log a warning & continue. - Log.w(TAG, "Configuration key does not match. Retrieved: " + configKeyParsed - + ", Calculated: " + configKeyCalculated); - } - return configuration; - } - - /** - * Helper method to mask out any invalid data in parsed WifiConfiguration. - * - * This is a compatibility layer added to the parsing logic to try and weed out any known - * issues in the backup data format from other OEM's. - */ - private static void clearAnyKnownIssuesInParsedConfiguration(WifiConfiguration config) { - /** - * Fix for b/73987207. Clear any invalid bits in the bitsets. - */ - // |allowedKeyManagement| - if (config.allowedKeyManagement.length() - > WifiConfiguration.KeyMgmt.strings.length) { - config.allowedKeyManagement.clear( - WifiConfiguration.KeyMgmt.strings.length, - config.allowedKeyManagement.length()); - } - // |allowedProtocols| - if (config.allowedProtocols.length() - > WifiConfiguration.Protocol.strings.length) { - config.allowedProtocols.clear( - WifiConfiguration.Protocol.strings.length, - config.allowedProtocols.length()); - } - // |allowedAuthAlgorithms| - if (config.allowedAuthAlgorithms.length() - > WifiConfiguration.AuthAlgorithm.strings.length) { - config.allowedAuthAlgorithms.clear( - WifiConfiguration.AuthAlgorithm.strings.length, - config.allowedAuthAlgorithms.length()); - } - // |allowedGroupCiphers| - if (config.allowedGroupCiphers.length() - > WifiConfiguration.GroupCipher.strings.length) { - config.allowedGroupCiphers.clear( - WifiConfiguration.GroupCipher.strings.length, - config.allowedGroupCiphers.length()); - } - // |allowedPairwiseCiphers| - if (config.allowedPairwiseCiphers.length() - > WifiConfiguration.PairwiseCipher.strings.length) { - config.allowedPairwiseCiphers.clear( - WifiConfiguration.PairwiseCipher.strings.length, - config.allowedPairwiseCiphers.length()); - } - // Add any other fixable issues discovered from other OEM's here. - } - - /** - * Parses the configuration data elements from the provided XML stream to a - * WifiConfiguration object. - * Looping through the tags makes it easy to add elements in the future minor versions if - * needed. Unsupported elements will be ignored. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @param minorVersion minor version number parsed from incoming data. - * @return Pair<Config key, WifiConfiguration object> if parsing is successful, null otherwise. - */ - private static Pair<String, WifiConfiguration> parseWifiConfigurationFromXmlInternal( - XmlPullParser in, int outerTagDepth, int minorVersion) - throws XmlPullParserException, IOException { - WifiConfiguration configuration = new WifiConfiguration(); - String configKeyInData = null; - Set<String> supportedTags = getSupportedWifiConfigurationTags(minorVersion); - - // Loop through and parse out all the elements from the stream within this section. - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - String tagName = valueName[0]; - if (tagName == null) { - throw new XmlPullParserException("Missing value name"); - } - - // ignore the tags that are not supported up until the current minor version - if (!supportedTags.contains(tagName)) { - Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <WifiConfiguration>" - + " section, ignoring."); - continue; - } - - // note: the below switch case list should contain all tags supported up until the - // highest minor version supported by this parser - switch (tagName) { - case WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY: - configKeyInData = (String) value; - break; - case WifiConfigurationXmlUtil.XML_TAG_SSID: - configuration.SSID = (String) value; - break; - case WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY: - configuration.preSharedKey = (String) value; - break; - case WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS: - populateWepKeysFromXmlValue(value, configuration.wepKeys); - break; - case WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX: - configuration.wepTxKeyIndex = (int) value; - break; - case WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID: - configuration.hiddenSSID = (boolean) value; - break; - case WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF: - configuration.requirePmf = (boolean) value; - break; - case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT: - byte[] allowedKeyMgmt = (byte[]) value; - configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); - break; - case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS: - byte[] allowedProtocols = (byte[]) value; - configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); - break; - case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS: - byte[] allowedAuthAlgorithms = (byte[]) value; - configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); - break; - case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS: - byte[] allowedGroupCiphers = (byte[]) value; - configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers); - break; - case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS: - byte[] allowedPairwiseCiphers = (byte[]) value; - configuration.allowedPairwiseCiphers = - BitSet.valueOf(allowedPairwiseCiphers); - break; - case WifiConfigurationXmlUtil.XML_TAG_SHARED: - configuration.shared = (boolean) value; - break; - case WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE: - configuration.meteredOverride = (int) value; - break; - case WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN: - configuration.allowAutojoin = (boolean) value; - break; - default: - // should never happen, since other tags are filtered out earlier - throw new XmlPullParserException( - "Unknown value name found: " + valueName[0]); - } - } - clearAnyKnownIssuesInParsedConfiguration(configuration); - return Pair.create(configKeyInData, configuration); - } - - /** - * Returns a set of supported tags of <WifiConfiguration> element for all minor versions of - * this major version up to and including the specified minorVersion (only adding tags is - * supported in minor versions, removal or changing the meaning of tags requires bumping - * the major version and reseting the minor to 0). - * - * @param minorVersion minor version number parsed from incoming data. - */ - private static Set<String> getSupportedWifiConfigurationTags(int minorVersion) { - switch (minorVersion) { - case 0: - return WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS; - case 1: - return WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS; - case 2: - return WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS; - default: - Log.e(TAG, "Invalid minorVersion: " + minorVersion); - return Collections.<String>emptySet(); - } - } - - /** - * Populate wepKeys array elements only if they were non-empty in the backup data. - * - * @throws XmlPullParserException if parsing errors occur. - */ - private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) - throws XmlPullParserException, IOException { - String[] wepKeysInData = (String[]) value; - if (wepKeysInData == null) { - return; - } - if (wepKeysInData.length != wepKeys.length) { - throw new XmlPullParserException( - "Invalid Wep Keys length: " + wepKeysInData.length); - } - for (int i = 0; i < wepKeys.length; i++) { - if (wepKeysInData[i].isEmpty()) { - wepKeys[i] = null; - } else { - wepKeys[i] = wepKeysInData[i]; - } - } - } - - private static List<String> parseProxyExclusionListString( - @Nullable String exclusionListString) { - if (exclusionListString == null) { - return Collections.emptyList(); - } else { - return Arrays.asList(exclusionListString.toLowerCase(Locale.ROOT).split(",")); - } - } - - /** - * Parses the IP configuration data elements from the provided XML stream to an - * IpConfiguration object. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @param minorVersion minor version number parsed from incoming data. - * @return IpConfiguration object if parsing is successful, null otherwise. - */ - private static IpConfiguration parseIpConfigurationFromXml(XmlPullParser in, - int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { - // First parse *all* of the tags in <IpConfiguration> section - Set<String> supportedTags = getSupportedIpConfigurationTags(minorVersion); - - String ipAssignmentString = null; - String linkAddressString = null; - Integer linkPrefixLength = null; - String gatewayAddressString = null; - String[] dnsServerAddressesString = null; - String proxySettingsString = null; - String proxyHost = null; - int proxyPort = -1; - String proxyExclusionList = null; - String proxyPacFile = null; - - // Loop through and parse out all the elements from the stream within this section. - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - String tagName = valueName[0]; - if (tagName == null) { - throw new XmlPullParserException("Missing value name"); - } - - // ignore the tags that are not supported up until the current minor version - if (!supportedTags.contains(tagName)) { - Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <IpConfiguration>" - + " section, ignoring."); - continue; - } - - // note: the below switch case list should contain all tags supported up until the - // highest minor version supported by this parser - // should any tags be added in next minor versions, conditional processing of them - // also needs to be added in the below code (processing into IpConfiguration object) - switch (tagName) { - case IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT: - ipAssignmentString = (String) value; - break; - case IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS: - linkAddressString = (String) value; - break; - case IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH: - linkPrefixLength = (Integer) value; - break; - case IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS: - gatewayAddressString = (String) value; - break; - case IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES: - dnsServerAddressesString = (String[]) value; - break; - case IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS: - proxySettingsString = (String) value; - break; - case IpConfigurationXmlUtil.XML_TAG_PROXY_HOST: - proxyHost = (String) value; - break; - case IpConfigurationXmlUtil.XML_TAG_PROXY_PORT: - proxyPort = (int) value; - break; - case IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST: - proxyExclusionList = (String) value; - break; - case IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE: - proxyPacFile = (String) value; - break; - default: - // should never happen, since other tags are filtered out earlier - throw new XmlPullParserException( - "Unknown value name found: " + valueName[0]); - } - } - - // Now process the values into IpConfiguration object - IpConfiguration ipConfiguration = new IpConfiguration(); - if (ipAssignmentString == null) { - throw new XmlPullParserException("IpAssignment was missing in IpConfiguration section"); - } - IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); - ipConfiguration.setIpAssignment(ipAssignment); - switch (ipAssignment) { - case STATIC: - StaticIpConfiguration.Builder builder = new StaticIpConfiguration.Builder(); - if (linkAddressString != null && linkPrefixLength != null) { - LinkAddress linkAddress = new LinkAddress( - InetAddresses.parseNumericAddress(linkAddressString), linkPrefixLength); - if (linkAddress.getAddress() instanceof Inet4Address) { - builder.setIpAddress(linkAddress); - } else { - Log.w(TAG, "Non-IPv4 address: " + linkAddress); - } - } - if (gatewayAddressString != null) { - InetAddress gateway = InetAddresses.parseNumericAddress(gatewayAddressString); - RouteInfo route = new RouteInfo(null, gateway, null, RouteInfo.RTN_UNICAST); - if (route.isDefaultRoute() - && route.getDestination().getAddress() instanceof Inet4Address) { - builder.setGateway(gateway); - } else { - Log.w(TAG, "Non-IPv4 default route: " + route); - } - } - if (dnsServerAddressesString != null) { - List<InetAddress> dnsServerAddresses = new ArrayList<>(); - for (String dnsServerAddressString : dnsServerAddressesString) { - InetAddress dnsServerAddress = - InetAddresses.parseNumericAddress(dnsServerAddressString); - dnsServerAddresses.add(dnsServerAddress); - } - builder.setDnsServers(dnsServerAddresses); - } - ipConfiguration.setStaticIpConfiguration(builder.build()); - break; - case DHCP: - case UNASSIGNED: - break; - default: - throw new XmlPullParserException("Unknown ip assignment type: " + ipAssignment); - } - - // Process the proxy settings next - if (proxySettingsString == null) { - throw new XmlPullParserException("ProxySettings was missing in" - + " IpConfiguration section"); - } - ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); - ipConfiguration.setProxySettings(proxySettings); - switch (proxySettings) { - case STATIC: - if (proxyHost == null) { - throw new XmlPullParserException("ProxyHost was missing in" - + " IpConfiguration section"); - } - if (proxyPort == -1) { - throw new XmlPullParserException("ProxyPort was missing in" - + " IpConfiguration section"); - } - if (proxyExclusionList == null) { - throw new XmlPullParserException("ProxyExclusionList was missing in" - + " IpConfiguration section"); - } - ipConfiguration.setHttpProxy( - ProxyInfo.buildDirectProxy( - proxyHost, proxyPort, - parseProxyExclusionListString(proxyExclusionList))); - break; - case PAC: - if (proxyPacFile == null) { - throw new XmlPullParserException("ProxyPac was missing in" - + " IpConfiguration section"); - } - ipConfiguration.setHttpProxy( - ProxyInfo.buildPacProxy(Uri.parse(proxyPacFile))); - break; - case NONE: - case UNASSIGNED: - break; - default: - throw new XmlPullParserException( - "Unknown proxy settings type: " + proxySettings); - } - - return ipConfiguration; - } - - /** - * Returns a set of supported tags of <IpConfiguration> element for all minor versions of - * this major version up to and including the specified minorVersion (only adding tags is - * supported in minor versions, removal or changing the meaning of tags requires bumping - * the major version and reseting the minor to 0). - * - * @param minorVersion minor version number parsed from incoming data. - */ - private static Set<String> getSupportedIpConfigurationTags(int minorVersion) { - switch (minorVersion) { - case 0: - case 1: - case 2: - return IP_CONFIGURATION_MINOR_V0_V1_V2_SUPPORTED_TAGS; - default: - Log.e(TAG, "Invalid minorVersion: " + minorVersion); - return Collections.<String>emptySet(); - } - } -} diff --git a/service/java/com/android/server/wifi/WifiBackupRestore.java b/service/java/com/android/server/wifi/WifiBackupRestore.java deleted file mode 100644 index ab46bb62f..000000000 --- a/service/java/com/android/server/wifi/WifiBackupRestore.java +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.net.IpConfiguration; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.os.Process; -import android.util.Log; -import android.util.SparseArray; -import android.util.Xml; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.util.IpConfigStore; -import com.android.server.wifi.util.NativeUtil; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.XmlUtil; -import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil; -import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.CharArrayReader; -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Class used to backup/restore data using the SettingsBackupAgent. - * There are 2 symmetric API's exposed here: - * 1. retrieveBackupDataFromConfigurations: Retrieve the configuration data to be backed up. - * 2. retrieveConfigurationsFromBackupData: Restore the configuration using the provided data. - * The byte stream to be backed up is XML encoded and versioned to migrate the data easily across - * revisions. - */ -public class WifiBackupRestore { - private static final String TAG = "WifiBackupRestore"; - - /** - * Current backup data version. - * Note: before Android P this used to be an {@code int}, however support for minor versions - * has been added in Android P. Currently this field is a {@code float} representing - * "majorVersion.minorVersion" of the backed up data. MinorVersion starts with 0 and should - * be incremented when necessary. MajorVersion starts with 1 and bumping it up requires - * also resetting minorVersion to 0. - * - * MajorVersion will be incremented for modifications of the XML schema, excluding additive - * modifications in <WifiConfiguration> and/or <IpConfiguration> tags. - * Should the major version be bumped up, a new {@link WifiBackupDataParser} parser needs to - * be added and returned from {@link #getWifiBackupDataParser(int)} ()}. - * Note that bumping up the major version will result in inability to restore the backup - * set to those lower versions of SDK_INT that don't support the version. - * - * MinorVersion will only be incremented for addition of <WifiConfiguration> and/or - * <IpConfiguration> tags. Any other modifications to the schema should result in bumping up - * the major version and resetting the minor version to 0. - * Note that bumping up only the minor version will still allow restoring the backup set to - * lower versions of SDK_INT. - */ - private static final int CURRENT_BACKUP_DATA_MAJOR_VERSION = 1; - - /** This list of older versions will be used to restore data from older backups. */ - /** - * First version of the backup data format. - */ - private static final int INITIAL_BACKUP_DATA_VERSION = 1; - - /** - * List of XML section header tags in the backed up data - */ - private static final String XML_TAG_DOCUMENT_HEADER = "WifiBackupData"; - private static final String XML_TAG_VERSION = "Version"; - - static final String XML_TAG_SECTION_HEADER_NETWORK_LIST = "NetworkList"; - static final String XML_TAG_SECTION_HEADER_NETWORK = "Network"; - static final String XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION = "WifiConfiguration"; - static final String XML_TAG_SECTION_HEADER_IP_CONFIGURATION = "IpConfiguration"; - - /** - * Regex to mask out passwords in backup data dump. - */ - private static final String PSK_MASK_LINE_MATCH_PATTERN = - "<.*" + WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY + ".*>.*<.*>"; - private static final String PSK_MASK_SEARCH_PATTERN = - "(<.*" + WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY + ".*>)(.*)(<.*>)"; - private static final String PSK_MASK_REPLACE_PATTERN = "$1*$3"; - - private static final String WEP_KEYS_MASK_LINE_START_MATCH_PATTERN = - "<string-array.*" + WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS + ".*num=\"[0-9]\">"; - private static final String WEP_KEYS_MASK_LINE_END_MATCH_PATTERN = "</string-array>"; - private static final String WEP_KEYS_MASK_SEARCH_PATTERN = "(<.*=)(.*)(/>)"; - private static final String WEP_KEYS_MASK_REPLACE_PATTERN = "$1*$3"; - - private final WifiPermissionsUtil mWifiPermissionsUtil; - /** - * Verbose logging flag. - */ - private boolean mVerboseLoggingEnabled = false; - - /** - * Store the dump of the backup/restore data for debugging. This is only stored when verbose - * logging is enabled in developer options. - */ - private byte[] mDebugLastBackupDataRetrieved; - private byte[] mDebugLastBackupDataRestored; - private byte[] mDebugLastSupplicantBackupDataRestored; - private byte[] mDebugLastIpConfigBackupDataRestored; - - public WifiBackupRestore(WifiPermissionsUtil wifiPermissionsUtil) { - mWifiPermissionsUtil = wifiPermissionsUtil; - } - - /** - * Retrieve the version for serialization. - */ - private Float getVersion() { - WifiBackupDataParser parser = - getWifiBackupDataParser(CURRENT_BACKUP_DATA_MAJOR_VERSION); - if (parser == null) { - Log.e(TAG, "Major version of backup data is unknown to this Android" - + " version; not backing up"); - return null; - } - int minorVersion = parser.getHighestSupportedMinorVersion(); - Float version; - try { - version = Float.valueOf( - CURRENT_BACKUP_DATA_MAJOR_VERSION + "." + minorVersion); - } catch (NumberFormatException e) { - Log.e(TAG, "Failed to generate version", e); - return null; - } - return version; - } - - /** - * Retrieve an XML byte stream representing the data that needs to be backed up from the - * provided configurations. - * - * @param configurations list of currently saved networks that needs to be backed up. - * @return Raw byte stream of XML that needs to be backed up. - */ - public byte[] retrieveBackupDataFromConfigurations(List<WifiConfiguration> configurations) { - if (configurations == null) { - Log.e(TAG, "Invalid configuration list received"); - return new byte[0]; - } - - try { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - - // Start writing the XML stream. - XmlUtil.writeDocumentStart(out, XML_TAG_DOCUMENT_HEADER); - - Float version = getVersion(); - if (version == null) return null; - XmlUtil.writeNextValue(out, XML_TAG_VERSION, version.floatValue()); - - writeNetworkConfigurationsToXml(out, configurations); - - XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER); - - byte[] data = outputStream.toByteArray(); - - if (mVerboseLoggingEnabled) { - mDebugLastBackupDataRetrieved = data; - } - - return data; - } catch (XmlPullParserException e) { - Log.e(TAG, "Error retrieving the backup data: " + e); - } catch (IOException e) { - Log.e(TAG, "Error retrieving the backup data: " + e); - } - return new byte[0]; - } - - /** - * Write the list of configurations to the XML stream. - */ - private void writeNetworkConfigurationsToXml( - XmlSerializer out, List<WifiConfiguration> configurations) - throws XmlPullParserException, IOException { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_LIST); - for (WifiConfiguration configuration : configurations) { - // We don't want to backup/restore enterprise/passpoint configurations. - if (configuration.isEnterprise() || configuration.isPasspoint()) { - continue; - } - if (!mWifiPermissionsUtil.checkConfigOverridePermission(configuration.creatorUid)) { - Log.d(TAG, "Ignoring network from an app with no config override permission: " - + configuration.getKey()); - continue; - } - // Write this configuration data now. - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK); - writeNetworkConfigurationToXml(out, configuration); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK); - } - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_LIST); - } - - /** - * Write the configuration data elements from the provided Configuration to the XML stream. - * Uses XmlUtils to write the values of each element. - */ - private void writeNetworkConfigurationToXml(XmlSerializer out, WifiConfiguration configuration) - throws XmlPullParserException, IOException { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - WifiConfigurationXmlUtil.writeToXmlForBackup(out, configuration); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION); - IpConfigurationXmlUtil.writeToXml(out, configuration.getIpConfiguration()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION); - } - - /** - * Parse out the configurations from the back up data. - * - * @param data raw byte stream representing the XML data. - * @return list of networks retrieved from the backed up data. - */ - public List<WifiConfiguration> retrieveConfigurationsFromBackupData(byte[] data) { - if (data == null || data.length == 0) { - Log.e(TAG, "Invalid backup data received"); - return null; - } - try { - if (mVerboseLoggingEnabled) { - mDebugLastBackupDataRestored = data; - } - - final XmlPullParser in = Xml.newPullParser(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - - // Start parsing the XML stream. - XmlUtil.gotoDocumentStart(in, XML_TAG_DOCUMENT_HEADER); - int rootTagDepth = in.getDepth(); - - int majorVersion = -1; - int minorVersion = -1; - try { - float version = (float) XmlUtil.readNextValueWithName(in, XML_TAG_VERSION); - - // parse out major and minor versions - String versionStr = new Float(version).toString(); - int separatorPos = versionStr.indexOf('.'); - if (separatorPos == -1) { - majorVersion = Integer.parseInt(versionStr); - minorVersion = 0; - } else { - majorVersion = Integer.parseInt(versionStr.substring(0, separatorPos)); - minorVersion = Integer.parseInt(versionStr.substring(separatorPos + 1)); - } - } catch (ClassCastException cce) { - // Integer cannot be cast to Float for data coming from before Android P - majorVersion = 1; - minorVersion = 0; - } - Log.d(TAG, "Version of backup data - major: " + majorVersion - + "; minor: " + minorVersion); - - WifiBackupDataParser parser = getWifiBackupDataParser(majorVersion); - if (parser == null) { - Log.w(TAG, "Major version of backup data is unknown to this Android" - + " version; not restoring"); - return null; - } else { - return parser.parseNetworkConfigurationsFromXml(in, rootTagDepth, minorVersion); - } - } catch (XmlPullParserException | IOException | ClassCastException - | IllegalArgumentException e) { - Log.e(TAG, "Error parsing the backup data: " + e); - } - return null; - } - - private WifiBackupDataParser getWifiBackupDataParser(int majorVersion) { - switch (majorVersion) { - case INITIAL_BACKUP_DATA_VERSION: - return new WifiBackupDataV1Parser(); - default: - Log.e(TAG, "Unrecognized majorVersion of backup data: " + majorVersion); - return null; - } - } - - /** - * Create log dump of the backup data in XML format with the preShared & WEP key masked. - * - * PSK keys are written in the following format in XML: - * <string name="PreSharedKey">WifiBackupRestorePsk</string> - * - * WEP Keys are written in following format in XML: - * <string-array name="WEPKeys" num="4"> - * <item value="WifiBackupRestoreWep1" /> - * <item value="WifiBackupRestoreWep2" /> - * <item value="WifiBackupRestoreWep3" /> - * <item value="WifiBackupRestoreWep3" /> - * </string-array> - */ - private String createLogFromBackupData(byte[] data) { - StringBuilder sb = new StringBuilder(); - try { - String xmlString = new String(data, StandardCharsets.UTF_8.name()); - boolean wepKeysLine = false; - for (String line : xmlString.split("\n")) { - if (line.matches(PSK_MASK_LINE_MATCH_PATTERN)) { - line = line.replaceAll(PSK_MASK_SEARCH_PATTERN, PSK_MASK_REPLACE_PATTERN); - } - if (line.matches(WEP_KEYS_MASK_LINE_START_MATCH_PATTERN)) { - wepKeysLine = true; - } else if (line.matches(WEP_KEYS_MASK_LINE_END_MATCH_PATTERN)) { - wepKeysLine = false; - } else if (wepKeysLine) { - line = line.replaceAll( - WEP_KEYS_MASK_SEARCH_PATTERN, WEP_KEYS_MASK_REPLACE_PATTERN); - } - sb.append(line).append("\n"); - } - } catch (UnsupportedEncodingException e) { - return ""; - } - return sb.toString(); - } - - /** - * Restore state from the older supplicant back up data. - * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file. - * - * @param supplicantData Raw byte stream of wpa_supplicant.conf - * @param ipConfigData Raw byte stream of ipconfig.txt - * @return list of networks retrieved from the backed up data. - */ - public List<WifiConfiguration> retrieveConfigurationsFromSupplicantBackupData( - byte[] supplicantData, byte[] ipConfigData) { - if (supplicantData == null || supplicantData.length == 0) { - Log.e(TAG, "Invalid supplicant backup data received"); - return null; - } - - if (mVerboseLoggingEnabled) { - mDebugLastSupplicantBackupDataRestored = supplicantData; - mDebugLastIpConfigBackupDataRestored = ipConfigData; - } - - SupplicantBackupMigration.SupplicantNetworks supplicantNetworks = - new SupplicantBackupMigration.SupplicantNetworks(); - // Incorporate the networks present in the backup data. - char[] restoredAsChars = new char[supplicantData.length]; - for (int i = 0; i < supplicantData.length; i++) { - restoredAsChars[i] = (char) supplicantData[i]; - } - - BufferedReader in = new BufferedReader(new CharArrayReader(restoredAsChars)); - supplicantNetworks.readNetworksFromStream(in); - - // Retrieve corresponding WifiConfiguration objects. - List<WifiConfiguration> configurations = supplicantNetworks.retrieveWifiConfigurations(); - - // Now retrieve all the IpConfiguration objects and set in the corresponding - // WifiConfiguration objects if ipconfig data is present. - if (ipConfigData != null && ipConfigData.length != 0) { - SparseArray<IpConfiguration> networks = - IpConfigStore.readIpAndProxyConfigurations( - new ByteArrayInputStream(ipConfigData)); - if (networks != null) { - for (int i = 0; i < networks.size(); i++) { - int id = networks.keyAt(i); - for (WifiConfiguration configuration : configurations) { - // This is a dangerous lookup, but that's how it is currently written. - if (configuration.getKey().hashCode() == id) { - configuration.setIpConfiguration(networks.valueAt(i)); - } - } - } - } else { - Log.e(TAG, "Failed to parse ipconfig data"); - } - } else { - Log.e(TAG, "Invalid ipconfig backup data received"); - } - return configurations; - } - - /** - * Enable verbose logging. - * - * @param verbose verbosity level. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = (verbose > 0); - if (!mVerboseLoggingEnabled) { - mDebugLastBackupDataRetrieved = null; - mDebugLastBackupDataRestored = null; - mDebugLastSupplicantBackupDataRestored = null; - mDebugLastIpConfigBackupDataRestored = null; - } - } - - /** - * Dump out the last backup/restore data if verbose logging is enabled. - * - * @param fd unused - * @param pw PrintWriter for writing dump to - * @param args unused - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WifiBackupRestore"); - if (mDebugLastBackupDataRetrieved != null) { - pw.println("Last backup data retrieved: " - + createLogFromBackupData(mDebugLastBackupDataRetrieved)); - } - if (mDebugLastBackupDataRestored != null) { - pw.println("Last backup data restored: " - + createLogFromBackupData(mDebugLastBackupDataRestored)); - } - if (mDebugLastSupplicantBackupDataRestored != null) { - pw.println("Last old supplicant backup data restored: " - + SupplicantBackupMigration.createLogFromBackupData( - mDebugLastSupplicantBackupDataRestored)); - } - if (mDebugLastIpConfigBackupDataRestored != null) { - pw.println("Last old ipconfig backup data restored: " - + mDebugLastIpConfigBackupDataRestored); - } - } - - /** - * These sub classes contain the logic to parse older backups and restore wifi state from it. - * Most of the code here has been migrated over from BackupSettingsAgent. - * This is kind of ugly text parsing, but it is needed to support the migration of this data. - */ - public static class SupplicantBackupMigration { - /** - * List of keys to look out for in wpa_supplicant.conf parsing. - * These key values are declared in different parts of the wifi codebase today. - */ - public static final String SUPPLICANT_KEY_SSID = WifiConfiguration.ssidVarName; - public static final String SUPPLICANT_KEY_HIDDEN = WifiConfiguration.hiddenSSIDVarName; - public static final String SUPPLICANT_KEY_KEY_MGMT = WifiConfiguration.KeyMgmt.varName; - public static final String SUPPLICANT_KEY_AUTH_ALG = - WifiConfiguration.AuthAlgorithm.varName; - public static final String SUPPLICANT_KEY_CLIENT_CERT = - WifiEnterpriseConfig.CLIENT_CERT_KEY; - public static final String SUPPLICANT_KEY_CA_CERT = WifiEnterpriseConfig.CA_CERT_KEY; - public static final String SUPPLICANT_KEY_CA_PATH = WifiEnterpriseConfig.CA_PATH_KEY; - public static final String SUPPLICANT_KEY_EAP = WifiEnterpriseConfig.EAP_KEY; - public static final String SUPPLICANT_KEY_PSK = WifiConfiguration.pskVarName; - public static final String SUPPLICANT_KEY_WEP_KEY0 = WifiConfiguration.wepKeyVarNames[0]; - public static final String SUPPLICANT_KEY_WEP_KEY1 = WifiConfiguration.wepKeyVarNames[1]; - public static final String SUPPLICANT_KEY_WEP_KEY2 = WifiConfiguration.wepKeyVarNames[2]; - public static final String SUPPLICANT_KEY_WEP_KEY3 = WifiConfiguration.wepKeyVarNames[3]; - public static final String SUPPLICANT_KEY_WEP_KEY_IDX = - WifiConfiguration.wepTxKeyIdxVarName; - public static final String SUPPLICANT_KEY_ID_STR = "id_str"; - - /** - * Regex to mask out passwords in backup data dump. - */ - private static final String PSK_MASK_LINE_MATCH_PATTERN = - ".*" + SUPPLICANT_KEY_PSK + ".*=.*"; - private static final String PSK_MASK_SEARCH_PATTERN = - "(.*" + SUPPLICANT_KEY_PSK + ".*=)(.*)"; - private static final String PSK_MASK_REPLACE_PATTERN = "$1*"; - - private static final String WEP_KEYS_MASK_LINE_MATCH_PATTERN = - ".*" + SUPPLICANT_KEY_WEP_KEY0.replace("0", "") + ".*=.*"; - private static final String WEP_KEYS_MASK_SEARCH_PATTERN = - "(.*" + SUPPLICANT_KEY_WEP_KEY0.replace("0", "") + ".*=)(.*)"; - private static final String WEP_KEYS_MASK_REPLACE_PATTERN = "$1*"; - - /** - * Create log dump of the backup data in wpa_supplicant.conf format with the preShared & - * WEP key masked. - * - * PSK keys are written in the following format in wpa_supplicant.conf: - * psk=WifiBackupRestorePsk - * - * WEP Keys are written in following format in wpa_supplicant.conf: - * wep_keys0=WifiBackupRestoreWep0 - * wep_keys1=WifiBackupRestoreWep1 - * wep_keys2=WifiBackupRestoreWep2 - * wep_keys3=WifiBackupRestoreWep3 - */ - public static String createLogFromBackupData(byte[] data) { - StringBuilder sb = new StringBuilder(); - try { - String supplicantConfString = new String(data, StandardCharsets.UTF_8.name()); - for (String line : supplicantConfString.split("\n")) { - if (line.matches(PSK_MASK_LINE_MATCH_PATTERN)) { - line = line.replaceAll(PSK_MASK_SEARCH_PATTERN, PSK_MASK_REPLACE_PATTERN); - } - if (line.matches(WEP_KEYS_MASK_LINE_MATCH_PATTERN)) { - line = line.replaceAll( - WEP_KEYS_MASK_SEARCH_PATTERN, WEP_KEYS_MASK_REPLACE_PATTERN); - } - sb.append(line).append("\n"); - } - } catch (UnsupportedEncodingException e) { - return ""; - } - return sb.toString(); - } - - /** - * Class for capturing a network definition from the wifi supplicant config file. - */ - static class SupplicantNetwork { - private String mParsedSSIDLine; - private String mParsedHiddenLine; - private String mParsedKeyMgmtLine; - private String mParsedAuthAlgLine; - private String mParsedPskLine; - private String[] mParsedWepKeyLines = new String[4]; - private String mParsedWepTxKeyIdxLine; - private String mParsedIdStrLine; - public boolean certUsed = false; - public boolean isEap = false; - - /** - * Read lines from wpa_supplicant.conf stream for this network. - */ - public static SupplicantNetwork readNetworkFromStream(BufferedReader in) { - final SupplicantNetwork n = new SupplicantNetwork(); - String line; - try { - while (in.ready()) { - line = in.readLine(); - if (line == null || line.startsWith("}")) { - break; - } - n.parseLine(line); - } - } catch (IOException e) { - return null; - } - return n; - } - - /** - * Parse a line from wpa_supplicant.conf stream for this network. - */ - void parseLine(String line) { - // Can't rely on particular whitespace patterns so strip leading/trailing. - line = line.trim(); - if (line.isEmpty()) return; // only whitespace; drop the line. - - // Now parse the network block within wpa_supplicant.conf and store the important - // lines for processing later. - if (line.startsWith(SUPPLICANT_KEY_SSID + "=")) { - mParsedSSIDLine = line; - } else if (line.startsWith(SUPPLICANT_KEY_HIDDEN + "=")) { - mParsedHiddenLine = line; - } else if (line.startsWith(SUPPLICANT_KEY_KEY_MGMT + "=")) { - mParsedKeyMgmtLine = line; - if (line.contains("EAP")) { - isEap = true; - } - } else if (line.startsWith(SUPPLICANT_KEY_AUTH_ALG + "=")) { - mParsedAuthAlgLine = line; - } else if (line.startsWith(SUPPLICANT_KEY_CLIENT_CERT + "=")) { - certUsed = true; - } else if (line.startsWith(SUPPLICANT_KEY_CA_CERT + "=")) { - certUsed = true; - } else if (line.startsWith(SUPPLICANT_KEY_CA_PATH + "=")) { - certUsed = true; - } else if (line.startsWith(SUPPLICANT_KEY_EAP + "=")) { - isEap = true; - } else if (line.startsWith(SUPPLICANT_KEY_PSK + "=")) { - mParsedPskLine = line; - } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY0 + "=")) { - mParsedWepKeyLines[0] = line; - } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY1 + "=")) { - mParsedWepKeyLines[1] = line; - } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY2 + "=")) { - mParsedWepKeyLines[2] = line; - } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY3 + "=")) { - mParsedWepKeyLines[3] = line; - } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY_IDX + "=")) { - mParsedWepTxKeyIdxLine = line; - } else if (line.startsWith(SUPPLICANT_KEY_ID_STR + "=")) { - mParsedIdStrLine = line; - } - } - - /** - * Create WifiConfiguration object from the parsed data for this network. - */ - public WifiConfiguration createWifiConfiguration() { - if (mParsedSSIDLine == null) { - // No SSID => malformed network definition - return null; - } - WifiConfiguration configuration = new WifiConfiguration(); - configuration.SSID = mParsedSSIDLine.substring(mParsedSSIDLine.indexOf('=') + 1); - - if (mParsedHiddenLine != null) { - // Can't use Boolean.valueOf() because it works only for true/false. - configuration.hiddenSSID = - Integer.parseInt(mParsedHiddenLine.substring( - mParsedHiddenLine.indexOf('=') + 1)) != 0; - } - if (mParsedKeyMgmtLine == null) { - // no key_mgmt line specified; this is defined as equivalent to - // "WPA-PSK WPA-EAP". - configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - } else { - // Need to parse the mParsedKeyMgmtLine line - final String bareKeyMgmt = - mParsedKeyMgmtLine.substring(mParsedKeyMgmtLine.indexOf('=') + 1); - String[] typeStrings = bareKeyMgmt.split("\\s+"); - - // Parse out all the key management regimes permitted for this network. - // The literal strings here are the standard values permitted in - // wpa_supplicant.conf. - for (int i = 0; i < typeStrings.length; i++) { - final String ktype = typeStrings[i]; - if (ktype.equals("NONE")) { - configuration.allowedKeyManagement.set( - WifiConfiguration.KeyMgmt.NONE); - } else if (ktype.equals("WPA-PSK")) { - configuration.allowedKeyManagement.set( - WifiConfiguration.KeyMgmt.WPA_PSK); - } else if (ktype.equals("WPA-EAP")) { - configuration.allowedKeyManagement.set( - WifiConfiguration.KeyMgmt.WPA_EAP); - } else if (ktype.equals("IEEE8021X")) { - configuration.allowedKeyManagement.set( - WifiConfiguration.KeyMgmt.IEEE8021X); - } else if (ktype.equals("WAPI-PSK")) { - configuration.allowedKeyManagement.set( - WifiConfiguration.KeyMgmt.WAPI_PSK); - } else if (ktype.equals("WAPI-CERT")) { - configuration.allowedKeyManagement.set( - WifiConfiguration.KeyMgmt.WAPI_CERT); - } - } - } - if (mParsedAuthAlgLine != null) { - if (mParsedAuthAlgLine.contains("OPEN")) { - configuration.allowedAuthAlgorithms.set( - WifiConfiguration.AuthAlgorithm.OPEN); - } - if (mParsedAuthAlgLine.contains("SHARED")) { - configuration.allowedAuthAlgorithms.set( - WifiConfiguration.AuthAlgorithm.SHARED); - } - } - if (mParsedPskLine != null) { - configuration.preSharedKey = - mParsedPskLine.substring(mParsedPskLine.indexOf('=') + 1); - } - if (mParsedWepKeyLines[0] != null) { - configuration.wepKeys[0] = - mParsedWepKeyLines[0].substring(mParsedWepKeyLines[0].indexOf('=') + 1); - } - if (mParsedWepKeyLines[1] != null) { - configuration.wepKeys[1] = - mParsedWepKeyLines[1].substring(mParsedWepKeyLines[1].indexOf('=') + 1); - } - if (mParsedWepKeyLines[2] != null) { - configuration.wepKeys[2] = - mParsedWepKeyLines[2].substring(mParsedWepKeyLines[2].indexOf('=') + 1); - } - if (mParsedWepKeyLines[3] != null) { - configuration.wepKeys[3] = - mParsedWepKeyLines[3].substring(mParsedWepKeyLines[3].indexOf('=') + 1); - } - if (mParsedWepTxKeyIdxLine != null) { - configuration.wepTxKeyIndex = - Integer.valueOf(mParsedWepTxKeyIdxLine.substring( - mParsedWepTxKeyIdxLine.indexOf('=') + 1)); - } - if (mParsedIdStrLine != null) { - String idString = - mParsedIdStrLine.substring(mParsedIdStrLine.indexOf('=') + 1); - if (idString != null) { - Map<String, String> extras = - SupplicantStaNetworkHal.parseNetworkExtra( - NativeUtil.removeEnclosingQuotes(idString)); - if (extras == null) { - Log.e(TAG, "Error parsing network extras, ignoring network."); - return null; - } - String configKey = extras.get( - SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY); - // No ConfigKey was passed but we need it for validating the parsed - // network so we stop the restore. - if (configKey == null) { - Log.e(TAG, "Configuration key was not passed, ignoring network."); - return null; - } - if (!configKey.equals(configuration.getKey())) { - // ConfigKey mismatches are expected for private networks because the - // UID is not preserved across backup/restore. - Log.w(TAG, "Configuration key does not match. Retrieved: " + configKey - + ", Calculated: " + configuration.getKey()); - } - // For wpa_supplicant backup data, parse out the creatorUid to ensure that - // these networks were created by system apps. - int creatorUid = - Integer.parseInt(extras.get( - SupplicantStaNetworkHal.ID_STRING_KEY_CREATOR_UID)); - if (creatorUid >= Process.FIRST_APPLICATION_UID) { - Log.d(TAG, "Ignoring network from non-system app: " - + configuration.getKey()); - return null; - } - } - } - return configuration; - } - } - - /** - * Ingest multiple wifi config fragments from wpa_supplicant.conf, looking for network={} - * blocks and eliminating duplicates - */ - static class SupplicantNetworks { - final ArrayList<SupplicantNetwork> mNetworks = new ArrayList<>(8); - - /** - * Parse the wpa_supplicant.conf file stream and add networks. - */ - public void readNetworksFromStream(BufferedReader in) { - try { - String line; - while (in.ready()) { - line = in.readLine(); - if (line != null) { - if (line.startsWith("network")) { - SupplicantNetwork net = SupplicantNetwork.readNetworkFromStream(in); - - // An IOException occurred while trying to read the network. - if (net == null) { - Log.e(TAG, "Error while parsing the network."); - continue; - } - - // Networks that use certificates for authentication can't be - // restored because the certificates they need don't get restored - // (because they are stored in keystore, and can't be restored). - // Similarly, omit EAP network definitions to avoid propagating - // controlled enterprise network definitions. - if (net.isEap || net.certUsed) { - Log.d(TAG, "Skipping enterprise network for restore: " - + net.mParsedSSIDLine + " / " + net.mParsedKeyMgmtLine); - continue; - } - mNetworks.add(net); - } - } - } - } catch (IOException e) { - // whatever happened, we're done now - } - } - - /** - * Retrieve a list of WifiConfiguration objects parsed from wpa_supplicant.conf - */ - public List<WifiConfiguration> retrieveWifiConfigurations() { - ArrayList<WifiConfiguration> wifiConfigurations = new ArrayList<>(); - for (SupplicantNetwork net : mNetworks) { - try { - WifiConfiguration wifiConfiguration = net.createWifiConfiguration(); - if (wifiConfiguration != null) { - Log.v(TAG, "Parsed Configuration: " + wifiConfiguration.getKey()); - wifiConfigurations.add(wifiConfiguration); - } - } catch (NumberFormatException e) { - // Occurs if we are unable to parse the hidden SSID, WEP Key index or - // creator UID. - Log.e(TAG, "Error parsing wifi configuration: " + e); - return null; - } - } - return wifiConfigurations; - } - } - } -} diff --git a/service/java/com/android/server/wifi/WifiCandidates.java b/service/java/com/android/server/wifi/WifiCandidates.java deleted file mode 100644 index 0513e5c1e..000000000 --- a/service/java/com/android/server/wifi/WifiCandidates.java +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.util.ArrayMap; - -import com.android.internal.util.Preconditions; -import com.android.server.wifi.proto.WifiScoreCardProto; -import com.android.wifi.resources.R; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.StringJoiner; -import java.util.stream.Collectors; - -/** - * Candidates for network selection - */ -public class WifiCandidates { - private static final String TAG = "WifiCandidates"; - - public WifiCandidates(@NonNull WifiScoreCard wifiScoreCard, @NonNull Context context) { - this(wifiScoreCard, context, Collections.EMPTY_LIST); - } - - public WifiCandidates(@NonNull WifiScoreCard wifiScoreCard, @NonNull Context context, - @NonNull List<Candidate> candidates) { - mWifiScoreCard = Preconditions.checkNotNull(wifiScoreCard); - mContext = context; - for (Candidate c : candidates) { - mCandidates.put(c.getKey(), c); - } - } - - private final WifiScoreCard mWifiScoreCard; - private final Context mContext; - - /** - * Represents a connectable candidate. - */ - public interface Candidate { - /** - * Gets the Key, which contains the SSID, BSSID, security type, and config id. - * - * Generally, a CandidateScorer should not need to use this. - */ - @Nullable Key getKey(); - - /** - * Gets the config id. - */ - int getNetworkConfigId(); - /** - * Returns true for an open network. - */ - boolean isOpenNetwork(); - /** - * Returns true for a passpoint network. - */ - boolean isPasspoint(); - /** - * Returns true for an ephemeral network. - */ - boolean isEphemeral(); - /** - * Returns true for a trusted network. - */ - boolean isTrusted(); - /** - * Returns true if suggestion came from a carrier or privileged app. - */ - boolean isCarrierOrPrivileged(); - /** - * Returns true for a metered network. - */ - boolean isMetered(); - - /** - * Returns true if network doesn't have internet access during last connection - */ - boolean hasNoInternetAccess(); - - /** - * Returns true if network is expected not to have Internet access - * (e.g., a wireless printer, a Chromecast hotspot, etc.). - */ - boolean isNoInternetAccessExpected(); - - /** - * Returns the ID of the nominator that provided the candidate. - */ - @WifiNetworkSelector.NetworkNominator.NominatorId - int getNominatorId(); - - /** - * Returns true if the candidate is in the same network as the - * current connection. - */ - boolean isCurrentNetwork(); - /** - * Return true if the candidate is currently connected. - */ - boolean isCurrentBssid(); - /** - * Returns a value between 0 and 1. - * - * 1.0 means the network was recently selected by the user or an app. - * 0.0 means not recently selected by user or app. - */ - double getLastSelectionWeight(); - /** - * Gets the scan RSSI. - */ - int getScanRssi(); - /** - * Gets the scan frequency. - */ - int getFrequency(); - /** - * Gets the predicted throughput in Mbps. - */ - int getPredictedThroughputMbps(); - /** - * Estimated probability of getting internet access (percent 0-100). - */ - int getEstimatedPercentInternetAvailability(); - /** - * Gets statistics from the scorecard. - */ - @Nullable WifiScoreCardProto.Signal getEventStatistics(WifiScoreCardProto.Event event); - } - - /** - * Represents a connectable candidate - */ - private static class CandidateImpl implements Candidate { - private final Key mKey; // SSID/sectype/BSSID/configId - private final @WifiNetworkSelector.NetworkNominator.NominatorId int mNominatorId; - private final int mScanRssi; - private final int mFrequency; - private final double mLastSelectionWeight; - private final WifiScoreCard.PerBssid mPerBssid; // For accessing the scorecard entry - private final boolean mIsCurrentNetwork; - private final boolean mIsCurrentBssid; - private final boolean mIsMetered; - private final boolean mHasNoInternetAccess; - private final boolean mIsNoInternetAccessExpected; - private final boolean mIsOpenNetwork; - private final boolean mPasspoint; - private final boolean mEphemeral; - private final boolean mTrusted; - private final boolean mCarrierOrPrivileged; - private final int mPredictedThroughputMbps; - private final int mEstimatedPercentInternetAvailability; - - CandidateImpl(Key key, WifiConfiguration config, - WifiScoreCard.PerBssid perBssid, - @WifiNetworkSelector.NetworkNominator.NominatorId int nominatorId, - int scanRssi, - int frequency, - double lastSelectionWeight, - boolean isCurrentNetwork, - boolean isCurrentBssid, - boolean isMetered, - boolean isCarrierOrPrivileged, - int predictedThroughputMbps) { - this.mKey = key; - this.mNominatorId = nominatorId; - this.mScanRssi = scanRssi; - this.mFrequency = frequency; - this.mPerBssid = perBssid; - this.mLastSelectionWeight = lastSelectionWeight; - this.mIsCurrentNetwork = isCurrentNetwork; - this.mIsCurrentBssid = isCurrentBssid; - this.mIsMetered = isMetered; - this.mHasNoInternetAccess = config.hasNoInternetAccess(); - this.mIsNoInternetAccessExpected = config.isNoInternetAccessExpected(); - this.mIsOpenNetwork = WifiConfigurationUtil.isConfigForOpenNetwork(config); - this.mPasspoint = config.isPasspoint(); - this.mEphemeral = config.isEphemeral(); - this.mTrusted = config.trusted; - this.mCarrierOrPrivileged = isCarrierOrPrivileged; - this.mPredictedThroughputMbps = predictedThroughputMbps; - this.mEstimatedPercentInternetAvailability = perBssid == null ? 50 : - perBssid.estimatePercentInternetAvailability(); - } - - @Override - public Key getKey() { - return mKey; - } - - @Override - public int getNetworkConfigId() { - return mKey.networkId; - } - - @Override - public boolean isOpenNetwork() { - return mIsOpenNetwork; - } - - @Override - public boolean isPasspoint() { - return mPasspoint; - } - - @Override - public boolean isEphemeral() { - return mEphemeral; - } - - @Override - public boolean isTrusted() { - return mTrusted; - } - - @Override - public boolean isCarrierOrPrivileged() { - return mCarrierOrPrivileged; - } - - @Override - public boolean isMetered() { - return mIsMetered; - } - - @Override - public boolean hasNoInternetAccess() { - return mHasNoInternetAccess; - } - - @Override - public boolean isNoInternetAccessExpected() { - return mIsNoInternetAccessExpected; - } - - @Override - public @WifiNetworkSelector.NetworkNominator.NominatorId int getNominatorId() { - return mNominatorId; - } - - @Override - public double getLastSelectionWeight() { - return mLastSelectionWeight; - } - - @Override - public boolean isCurrentNetwork() { - return mIsCurrentNetwork; - } - - @Override - public boolean isCurrentBssid() { - return mIsCurrentBssid; - } - - @Override - public int getScanRssi() { - return mScanRssi; - } - - @Override - public int getFrequency() { - return mFrequency; - } - - @Override - public int getPredictedThroughputMbps() { - return mPredictedThroughputMbps; - } - - @Override - public int getEstimatedPercentInternetAvailability() { - return mEstimatedPercentInternetAvailability; - } - - /** - * Accesses statistical information from the score card - */ - @Override - public WifiScoreCardProto.Signal getEventStatistics(WifiScoreCardProto.Event event) { - if (mPerBssid == null) return null; - WifiScoreCard.PerSignal perSignal = mPerBssid.lookupSignal(event, getFrequency()); - if (perSignal == null) return null; - return perSignal.toSignal(); - } - - @Override - public String toString() { - Key key = getKey(); - String lastSelectionWeightString = ""; - if (getLastSelectionWeight() != 0.0) { - // Round this to 3 places - lastSelectionWeightString = "lastSelectionWeight = " - + Math.round(getLastSelectionWeight() * 1000.0) / 1000.0 - + ", "; - } - return "Candidate { " - + "config = " + getNetworkConfigId() + ", " - + "bssid = " + key.bssid + ", " - + "freq = " + getFrequency() + ", " - + "rssi = " + getScanRssi() + ", " - + "Mbps = " + getPredictedThroughputMbps() + ", " - + "nominator = " + getNominatorId() + ", " - + "pInternet = " + getEstimatedPercentInternetAvailability() + ", " - + lastSelectionWeightString - + (isCurrentBssid() ? "connected, " : "") - + (isCurrentNetwork() ? "current, " : "") - + (isEphemeral() ? "ephemeral" : "saved") + ", " - + (isTrusted() ? "trusted, " : "") - + (isCarrierOrPrivileged() ? "priv, " : "") - + (isMetered() ? "metered, " : "") - + (hasNoInternetAccess() ? "noInternet, " : "") - + (isNoInternetAccessExpected() ? "noInternetExpected, " : "") - + (isPasspoint() ? "passpoint, " : "") - + (isOpenNetwork() ? "open" : "secure") + " }"; - } - } - - /** - * Represents a scoring function - */ - public interface CandidateScorer { - /** - * The scorer's name, and perhaps important parameterization/version. - */ - String getIdentifier(); - - /** - * Calculates the best score for a collection of candidates. - */ - @Nullable ScoredCandidate scoreCandidates(@NonNull Collection<Candidate> candidates); - - } - - /** - * Represents a candidate with a real-valued score, along with an error estimate. - * - * Larger values reflect more desirable candidates. The range is arbitrary, - * because scores generated by different sources are not compared with each - * other. - * - * The error estimate is on the same scale as the value, and should - * always be strictly positive. For instance, it might be the standard deviation. - */ - public static class ScoredCandidate { - public final double value; - public final double err; - public final Key candidateKey; - public final boolean userConnectChoiceOverride; - public ScoredCandidate(double value, double err, boolean userConnectChoiceOverride, - Candidate candidate) { - this.value = value; - this.err = err; - this.candidateKey = (candidate == null) ? null : candidate.getKey(); - this.userConnectChoiceOverride = userConnectChoiceOverride; - } - /** - * Represents no score - */ - public static final ScoredCandidate NONE = - new ScoredCandidate(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, - false, null); - } - - /** - * The key used for tracking candidates, consisting of SSID, security type, BSSID, and network - * configuration id. - */ - // TODO (b/123014687) unify with similar classes in the framework - public static class Key { - public final ScanResultMatchInfo matchInfo; // Contains the SSID and security type - public final MacAddress bssid; - public final int networkId; // network configuration id - - public Key(ScanResultMatchInfo matchInfo, - MacAddress bssid, - int networkId) { - this.matchInfo = matchInfo; - this.bssid = bssid; - this.networkId = networkId; - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof Key)) return false; - Key that = (Key) other; - return (this.matchInfo.equals(that.matchInfo) - && this.bssid.equals(that.bssid) - && this.networkId == that.networkId); - } - - @Override - public int hashCode() { - return Objects.hash(matchInfo, bssid, networkId); - } - } - - private final Map<Key, Candidate> mCandidates = new ArrayMap<>(); - - private int mCurrentNetworkId = -1; - @Nullable private MacAddress mCurrentBssid = null; - - /** - * Sets up information about the currently-connected network. - */ - public void setCurrent(int currentNetworkId, String currentBssid) { - mCurrentNetworkId = currentNetworkId; - mCurrentBssid = null; - if (currentBssid == null) return; - try { - mCurrentBssid = MacAddress.fromString(currentBssid); - } catch (RuntimeException e) { - failWithException(e); - } - } - - /** - * Adds a new candidate - * - * @return true if added or replaced, false otherwise - */ - public boolean add(ScanDetail scanDetail, - WifiConfiguration config, - @WifiNetworkSelector.NetworkNominator.NominatorId int nominatorId, - double lastSelectionWeightBetweenZeroAndOne, - boolean isMetered, - int predictedThroughputMbps) { - Key key = keyFromScanDetailAndConfig(scanDetail, config); - if (key == null) return false; - return add(key, config, nominatorId, - scanDetail.getScanResult().level, - scanDetail.getScanResult().frequency, - lastSelectionWeightBetweenZeroAndOne, - isMetered, - false, - predictedThroughputMbps); - } - - /** - * Makes a Key from a ScanDetail and WifiConfiguration (null if error). - */ - public @Nullable Key keyFromScanDetailAndConfig(ScanDetail scanDetail, - WifiConfiguration config) { - if (!validConfigAndScanDetail(config, scanDetail)) return null; - ScanResult scanResult = scanDetail.getScanResult(); - MacAddress bssid = MacAddress.fromString(scanResult.BSSID); - return new Key(ScanResultMatchInfo.fromScanResult(scanResult), bssid, config.networkId); - } - - /** - * Adds a new candidate - * - * @return true if added or replaced, false otherwise - */ - public boolean add(@NonNull Key key, - WifiConfiguration config, - @WifiNetworkSelector.NetworkNominator.NominatorId int nominatorId, - int scanRssi, - int frequency, - double lastSelectionWeightBetweenZeroAndOne, - boolean isMetered, - boolean isCarrierOrPrivileged, - int predictedThroughputMbps) { - Candidate old = mCandidates.get(key); - if (old != null) { - // check if we want to replace this old candidate - if (nominatorId > old.getNominatorId()) return false; - remove(old); - } - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.lookupBssid( - key.matchInfo.networkSsid, - key.bssid.toString()); - perBssid.setSecurityType( - WifiScoreCardProto.SecurityType.forNumber(key.matchInfo.networkType)); - perBssid.setNetworkConfigId(config.networkId); - CandidateImpl candidate = new CandidateImpl(key, config, perBssid, nominatorId, - scanRssi, - frequency, - Math.min(Math.max(lastSelectionWeightBetweenZeroAndOne, 0.0), 1.0), - config.networkId == mCurrentNetworkId, - key.bssid.equals(mCurrentBssid), - isMetered, - isCarrierOrPrivileged, - predictedThroughputMbps); - mCandidates.put(key, candidate); - return true; - } - - /** - * Checks that the supplied config and scan detail are valid (for the parts - * we care about) and consistent with each other. - * - * @param config to be validated - * @param scanDetail to be validated - * @return true if the config and scanDetail are consistent with each other - */ - private boolean validConfigAndScanDetail(WifiConfiguration config, ScanDetail scanDetail) { - if (config == null) return failure(); - if (scanDetail == null) return failure(); - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult == null) return failure(); - MacAddress bssid; - try { - bssid = MacAddress.fromString(scanResult.BSSID); - } catch (RuntimeException e) { - return failWithException(e); - } - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromScanResult(scanResult); - if (!config.isPasspoint()) { - ScanResultMatchInfo key2 = ScanResultMatchInfo.fromWifiConfiguration(config); - if (!key1.matchForNetworkSelection(key2, mContext.getResources() - .getBoolean(R.bool.config_wifiSaeUpgradeEnabled))) { - return failure(key1, key2); - } - } - return true; - } - - /** - * Removes a candidate - * @return true if the candidate was successfully removed - */ - public boolean remove(Candidate candidate) { - if (!(candidate instanceof CandidateImpl)) return failure(); - return mCandidates.remove(candidate.getKey(), candidate); - } - - /** - * Returns the number of candidates (at the BSSID level) - */ - public int size() { - return mCandidates.size(); - } - - /** - * Returns the candidates, grouped by network. - */ - public Collection<Collection<Candidate>> getGroupedCandidates() { - Map<Integer, Collection<Candidate>> candidatesForNetworkId = new ArrayMap<>(); - for (Candidate candidate : mCandidates.values()) { - Collection<Candidate> cc = candidatesForNetworkId.get(candidate.getNetworkConfigId()); - if (cc == null) { - cc = new ArrayList<>(2); // Guess 2 bssids per network - candidatesForNetworkId.put(candidate.getNetworkConfigId(), cc); - } - cc.add(candidate); - } - return candidatesForNetworkId.values(); - } - - /** - * Return a copy of the Candidates. - */ - public List<Candidate> getCandidates() { - return mCandidates.entrySet().stream().map(entry -> entry.getValue()) - .collect(Collectors.toList()); - } - - /** - * Make a choice from among the candidates, using the provided scorer. - * - * @return the chosen scored candidate, or ScoredCandidate.NONE. - */ - public @NonNull ScoredCandidate choose(@NonNull CandidateScorer candidateScorer) { - Preconditions.checkNotNull(candidateScorer); - Collection<Candidate> candidates = new ArrayList<>(mCandidates.values()); - ScoredCandidate choice = candidateScorer.scoreCandidates(candidates); - return choice == null ? ScoredCandidate.NONE : choice; - } - - /** - * After a failure indication is returned, this may be used to get details. - */ - public RuntimeException getLastFault() { - return mLastFault; - } - - /** - * Returns the number of faults we have seen - */ - public int getFaultCount() { - return mFaultCount; - } - - /** - * Clears any recorded faults - */ - public void clearFaults() { - mLastFault = null; - mFaultCount = 0; - } - - /** - * Controls whether to immediately raise an exception on a failure - */ - public WifiCandidates setPicky(boolean picky) { - mPicky = picky; - return this; - } - - /** - * Records details about a failure - * - * This captures a stack trace, so don't bother to construct a string message, just - * supply any culprits (convertible to strings) that might aid diagnosis. - * - * @return false - * @throws RuntimeException (if in picky mode) - */ - private boolean failure(Object... culprits) { - StringJoiner joiner = new StringJoiner(","); - for (Object c : culprits) { - joiner.add("" + c); - } - return failWithException(new IllegalArgumentException(joiner.toString())); - } - - /** - * As above, if we already have an exception. - */ - private boolean failWithException(RuntimeException e) { - mLastFault = e; - mFaultCount++; - if (mPicky) { - throw e; - } - return false; - } - - private boolean mPicky = false; - private RuntimeException mLastFault = null; - private int mFaultCount = 0; -} diff --git a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java deleted file mode 100644 index 047f9139d..000000000 --- a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java +++ /dev/null @@ -1,1561 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.Manifest.permission.NETWORK_SETTINGS; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.app.AlertDialog; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.graphics.drawable.Icon; -import android.net.Uri; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.os.Handler; -import android.os.PersistableBundle; -import android.telephony.CarrierConfigManager; -import android.telephony.ImsiEncryptionInfo; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Base64; -import android.util.Log; -import android.util.Pair; -import android.util.SparseBooleanArray; -import android.view.WindowManager; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.messages.nano.SystemMessageProto; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.annotation.Nullable; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; - -/** - * This class provide APIs to get carrier info from telephony service. - * TODO(b/132188983): Refactor into TelephonyFacade which owns all instances of - * TelephonyManager/SubscriptionManager in Wifi - */ -public class WifiCarrierInfoManager { - public static final String TAG = "WifiCarrierInfoManager"; - public static final String DEFAULT_EAP_PREFIX = "\0"; - - public static final int CARRIER_INVALID_TYPE = -1; - public static final int CARRIER_MNO_TYPE = 0; // Mobile Network Operator - public static final int CARRIER_MVNO_TYPE = 1; // Mobile Virtual Network Operator - public static final String ANONYMOUS_IDENTITY = "anonymous"; - public static final String THREE_GPP_NAI_REALM_FORMAT = "wlan.mnc%s.mcc%s.3gppnetwork.org"; - /** Intent when user tapped action button to allow the app. */ - @VisibleForTesting - public static final String NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION = - "com.android.server.wifi.action.CarrierNetwork.USER_ALLOWED_CARRIER"; - /** Intent when user tapped action button to disallow the app. */ - @VisibleForTesting - public static final String NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION = - "com.android.server.wifi.action.CarrierNetwork.USER_DISALLOWED_CARRIER"; - /** Intent when user dismissed the notification. */ - @VisibleForTesting - public static final String NOTIFICATION_USER_DISMISSED_INTENT_ACTION = - "com.android.server.wifi.action.CarrierNetwork.USER_DISMISSED"; - /** Intent when user clicked on the notification. */ - @VisibleForTesting - public static final String NOTIFICATION_USER_CLICKED_INTENT_ACTION = - "com.android.server.wifi.action.CarrierNetwork.USER_CLICKED"; - @VisibleForTesting - public static final String EXTRA_CARRIER_NAME = - "com.android.server.wifi.extra.CarrierNetwork.CARRIER_NAME"; - @VisibleForTesting - public static final String EXTRA_CARRIER_ID = - "com.android.server.wifi.extra.CarrierNetwork.CARRIER_ID"; - - // IMSI encryption method: RSA-OAEP with SHA-256 hash function - private static final String IMSI_CIPHER_TRANSFORMATION = - "RSA/ECB/OAEPwithSHA-256andMGF1Padding"; - - private static final HashMap<Integer, String> EAP_METHOD_PREFIX = new HashMap<>(); - static { - EAP_METHOD_PREFIX.put(WifiEnterpriseConfig.Eap.AKA, "0"); - EAP_METHOD_PREFIX.put(WifiEnterpriseConfig.Eap.SIM, "1"); - EAP_METHOD_PREFIX.put(WifiEnterpriseConfig.Eap.AKA_PRIME, "6"); - } - - public static final int ACTION_USER_ALLOWED_CARRIER = 1; - public static final int ACTION_USER_DISALLOWED_CARRIER = 2; - public static final int ACTION_USER_DISMISS = 3; - - @IntDef(prefix = { "ACTION_USER_" }, value = { - ACTION_USER_ALLOWED_CARRIER, - ACTION_USER_DISALLOWED_CARRIER, - ACTION_USER_DISMISS - }) - @Retention(RetentionPolicy.SOURCE) - public @interface UserActionCode { } - - /** - * 3GPP TS 11.11 2G_authentication command/response - * Input: [RAND] - * Output: [SRES][Cipher Key Kc] - */ - private static final int START_SRES_POS = 0; // MUST be 0 - private static final int SRES_LEN = 4; - private static final int START_KC_POS = START_SRES_POS + SRES_LEN; - private static final int KC_LEN = 8; - - private static final Uri CONTENT_URI = Uri.parse("content://carrier_information/carrier"); - - private final WifiContext mContext; - private final Handler mHandler; - private final WifiInjector mWifiInjector; - private final Resources mResources; - private final TelephonyManager mTelephonyManager; - private final SubscriptionManager mSubscriptionManager; - private final NotificationManager mNotificationManager; - private final WifiMetrics mWifiMetrics; - - /** - * Intent filter for processing notification actions. - */ - private final IntentFilter mIntentFilter; - private final FrameworkFacade mFrameworkFacade; - - private boolean mVerboseLogEnabled = false; - private SparseBooleanArray mImsiEncryptionRequired = new SparseBooleanArray(); - private SparseBooleanArray mImsiEncryptionInfoAvailable = new SparseBooleanArray(); - private SparseBooleanArray mEapMethodPrefixEnable = new SparseBooleanArray(); - private final Map<Integer, Boolean> mImsiPrivacyProtectionExemptionMap = new HashMap<>(); - private final List<OnUserApproveCarrierListener> - mOnUserApproveCarrierListeners = - new ArrayList<>(); - - private boolean mUserApprovalUiActive = false; - private boolean mHasNewDataToSerialize = false; - private boolean mUserDataLoaded = false; - private boolean mIsLastUserApprovalUiDialog = false; - - /** - * Interface for other modules to listen to the user approve IMSI protection exemption. - */ - public interface OnUserApproveCarrierListener { - - /** - * Invoke when user approve the IMSI protection exemption. - */ - void onUserAllowed(int carrierId); - } - - /** - * Module to interact with the wifi config store. - */ - private class ImsiProtectionExemptionDataSource implements - ImsiPrivacyProtectionExemptionStoreData.DataSource { - @Override - public Map<Integer, Boolean> toSerialize() { - // Clear the flag after writing to disk. - // TODO(b/115504887): Don't reset the flag on write failure. - mHasNewDataToSerialize = false; - return mImsiPrivacyProtectionExemptionMap; - } - - @Override - public void fromDeserialized(Map<Integer, Boolean> imsiProtectionExemptionMap) { - mImsiPrivacyProtectionExemptionMap.clear(); - mImsiPrivacyProtectionExemptionMap.putAll(imsiProtectionExemptionMap); - mUserDataLoaded = true; - } - - @Override - public void reset() { - mUserDataLoaded = false; - mImsiPrivacyProtectionExemptionMap.clear(); - } - - @Override - public boolean hasNewDataToSerialize() { - return mHasNewDataToSerialize; - } - } - - private final BroadcastReceiver mBroadcastReceiver = - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String carrierName = intent.getStringExtra(EXTRA_CARRIER_NAME); - int carrierId = intent.getIntExtra(EXTRA_CARRIER_ID, -1); - if (carrierName == null || carrierId == -1) { - Log.e(TAG, "No carrier name or carrier id found in intent"); - return; - } - - switch (intent.getAction()) { - case NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION: - handleUserAllowCarrierExemptionAction(carrierName, carrierId); - break; - case NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION: - handleUserDisallowCarrierExemptionAction(carrierName, carrierId); - break; - case NOTIFICATION_USER_CLICKED_INTENT_ACTION: - sendImsiPrivacyConfirmationDialog(carrierName, carrierId); - // Collapse the notification bar - mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); - break; - case NOTIFICATION_USER_DISMISSED_INTENT_ACTION: - handleUserDismissAction(); - return; // no need to cancel a dismissed notification, return. - default: - Log.e(TAG, "Unknown action " + intent.getAction()); - return; - } - // Clear notification once the user interacts with it. - mNotificationManager.cancel(SystemMessageProto - .SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - } - }; - private void handleUserDismissAction() { - Log.i(TAG, "User dismissed the notification"); - mUserApprovalUiActive = false; - mWifiMetrics.addUserApprovalCarrierUiReaction(ACTION_USER_DISMISS, - mIsLastUserApprovalUiDialog); - } - - private void handleUserAllowCarrierExemptionAction(String carrierName, int carrierId) { - Log.i(TAG, "User clicked to allow carrier:" + carrierName); - setHasUserApprovedImsiPrivacyExemptionForCarrier(true, carrierId); - mUserApprovalUiActive = false; - mWifiMetrics.addUserApprovalCarrierUiReaction(ACTION_USER_ALLOWED_CARRIER, - mIsLastUserApprovalUiDialog); - - } - - private void handleUserDisallowCarrierExemptionAction(String carrierName, int carrierId) { - Log.i(TAG, "User clicked to disallow carrier:" + carrierName); - setHasUserApprovedImsiPrivacyExemptionForCarrier(false, carrierId); - mUserApprovalUiActive = false; - mWifiMetrics.addUserApprovalCarrierUiReaction( - ACTION_USER_DISALLOWED_CARRIER, mIsLastUserApprovalUiDialog); - } - - /** - * Gets the instance of WifiCarrierInfoManager. - * @param telephonyManager Instance of {@link TelephonyManager} - * @param subscriptionManager Instance of {@link SubscriptionManager} - * @param WifiInjector Instance of {@link WifiInjector} - * @return The instance of WifiCarrierInfoManager - */ - public WifiCarrierInfoManager(@NonNull TelephonyManager telephonyManager, - @NonNull SubscriptionManager subscriptionManager, - @NonNull WifiInjector wifiInjector, - @NonNull FrameworkFacade frameworkFacade, - @NonNull WifiContext context, - @NonNull WifiConfigStore configStore, - @NonNull Handler handler, - @NonNull WifiMetrics wifiMetrics) { - mTelephonyManager = telephonyManager; - mContext = context; - mResources = mContext.getResources(); - mWifiInjector = wifiInjector; - mHandler = handler; - mSubscriptionManager = subscriptionManager; - mFrameworkFacade = frameworkFacade; - mWifiMetrics = wifiMetrics; - mNotificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - // Register broadcast receiver for UI interactions. - mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(NOTIFICATION_USER_DISMISSED_INTENT_ACTION); - mIntentFilter.addAction(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION); - mIntentFilter.addAction(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION); - mIntentFilter.addAction(NOTIFICATION_USER_CLICKED_INTENT_ACTION); - - mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, NETWORK_SETTINGS, handler); - configStore.registerStoreData(wifiInjector.makeImsiProtectionExemptionStoreData( - new ImsiProtectionExemptionDataSource())); - - updateImsiEncryptionInfo(context); - - // Monitor for carrier config changes. - IntentFilter filter = new IntentFilter(); - filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); - context.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED - .equals(intent.getAction())) { - updateImsiEncryptionInfo(context); - } - } - }, filter); - - frameworkFacade.registerContentObserver(context, CONTENT_URI, false, - new ContentObserver(handler) { - @Override - public void onChange(boolean selfChange) { - updateImsiEncryptionInfo(context); - } - }); - } - - /** - * Enable/disable verbose logging. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLogEnabled = verbose > 0; - } - - /** - * Updates the IMSI encryption information. - */ - private void updateImsiEncryptionInfo(Context context) { - CarrierConfigManager carrierConfigManager = - (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); - if (carrierConfigManager == null) { - return; - } - - mImsiEncryptionRequired.clear(); - mImsiEncryptionInfoAvailable.clear(); - mEapMethodPrefixEnable.clear(); - List<SubscriptionInfo> activeSubInfos = - mSubscriptionManager.getActiveSubscriptionInfoList(); - if (activeSubInfos == null) { - return; - } - for (SubscriptionInfo subInfo : activeSubInfos) { - int subId = subInfo.getSubscriptionId(); - PersistableBundle bundle = carrierConfigManager.getConfigForSubId(subId); - if (bundle != null) { - if ((bundle.getInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT) - & TelephonyManager.KEY_TYPE_WLAN) != 0) { - vlogd("IMSI encryption is required for " + subId); - mImsiEncryptionRequired.put(subId, true); - } - if (bundle.getBoolean(CarrierConfigManager.ENABLE_EAP_METHOD_PREFIX_BOOL)) { - vlogd("EAP Prefix is required for " + subId); - mEapMethodPrefixEnable.put(subId, true); - } - } else { - Log.e(TAG, "Carrier config is missing for: " + subId); - } - - try { - if (mImsiEncryptionRequired.get(subId) - && mTelephonyManager.createForSubscriptionId(subId) - .getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN) != null) { - vlogd("IMSI encryption info is available for " + subId); - mImsiEncryptionInfoAvailable.put(subId, true); - } - } catch (IllegalArgumentException e) { - vlogd("IMSI encryption info is not available."); - } - } - } - - /** - * Check if the IMSI encryption is required for the SIM card. - * - * @param subId The subscription ID of SIM card. - * @return true if the IMSI encryption is required, otherwise false. - */ - public boolean requiresImsiEncryption(int subId) { - return mImsiEncryptionRequired.get(subId); - } - - /** - * Check if the IMSI encryption is downloaded(available) for the SIM card. - * - * @param subId The subscription ID of SIM card. - * @return true if the IMSI encryption is available, otherwise false. - */ - public boolean isImsiEncryptionInfoAvailable(int subId) { - return mImsiEncryptionInfoAvailable.get(subId); - } - - /** - * Gets the SubscriptionId of SIM card which is from the carrier specified in config. - * - * @param config the instance of {@link WifiConfiguration} - * @return the best match SubscriptionId - */ - public int getBestMatchSubscriptionId(@NonNull WifiConfiguration config) { - if (config.isPasspoint()) { - return getMatchingSubId(config.carrierId); - } else { - return getBestMatchSubscriptionIdForEnterprise(config); - } - } - - /** - * Gets the SubscriptionId of SIM card for given carrier Id - * - * @param carrierId carrier id for target carrier - * @return the matched SubscriptionId - */ - public int getMatchingSubId(int carrierId) { - List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); - if (subInfoList == null || subInfoList.isEmpty()) { - return SubscriptionManager.INVALID_SUBSCRIPTION_ID; - } - - int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); - int matchSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - for (SubscriptionInfo subInfo : subInfoList) { - if (subInfo.getCarrierId() == carrierId) { - matchSubId = subInfo.getSubscriptionId(); - if (matchSubId == dataSubId) { - // Priority of Data sub is higher than non data sub. - break; - } - } - } - vlogd("matching subId is " + matchSubId); - return matchSubId; - } - - private int getBestMatchSubscriptionIdForEnterprise(WifiConfiguration config) { - if (config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { - return getMatchingSubId(config.carrierId); - } - // Legacy WifiConfiguration without carrier ID - if (config.enterpriseConfig == null - || !config.enterpriseConfig.isAuthenticationSimBased()) { - Log.w(TAG, "The legacy config is not using EAP-SIM."); - return SubscriptionManager.INVALID_SUBSCRIPTION_ID; - } - int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); - if (isSimPresent(dataSubId)) { - vlogd("carrierId is not assigned, using the default data sub."); - return dataSubId; - } - vlogd("data sim is not present."); - return SubscriptionManager.INVALID_SUBSCRIPTION_ID; - } - - /** - * Check if the specified SIM card is in the device. - * - * @param subId subscription ID of SIM card in the device. - * @return true if the subId is active, otherwise false. - */ - public boolean isSimPresent(int subId) { - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return false; - } - List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); - if (subInfoList == null || subInfoList.isEmpty()) { - return false; - } - return subInfoList.stream() - .anyMatch(info -> info.getSubscriptionId() == subId - && isSimStateReady(info)); - } - - /** - * Check if SIM card for SubscriptionInfo is ready. - */ - private boolean isSimStateReady(SubscriptionInfo info) { - int simSlotIndex = info.getSimSlotIndex(); - return mTelephonyManager.getSimState(simSlotIndex) == TelephonyManager.SIM_STATE_READY; - } - - /** - * Get the identity for the current SIM or null if the SIM is not available - * - * @param config WifiConfiguration that indicates what sort of authentication is necessary - * @return Pair<identify, encrypted identity> or null if the SIM is not available - * or config is invalid - */ - public Pair<String, String> getSimIdentity(WifiConfiguration config) { - int subId = getBestMatchSubscriptionId(config); - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return null; - } - - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - String imsi = specifiedTm.getSubscriberId(); - String mccMnc = ""; - - if (specifiedTm.getSimState() == TelephonyManager.SIM_STATE_READY) { - mccMnc = specifiedTm.getSimOperator(); - } - - String identity = buildIdentity(getSimMethodForConfig(config), imsi, mccMnc, false); - if (identity == null) { - Log.e(TAG, "Failed to build the identity"); - return null; - } - - ImsiEncryptionInfo imsiEncryptionInfo; - try { - imsiEncryptionInfo = specifiedTm.getCarrierInfoForImsiEncryption( - TelephonyManager.KEY_TYPE_WLAN); - } catch (RuntimeException e) { - Log.e(TAG, "Failed to get imsi encryption info: " + e.getMessage()); - return null; - } - if (imsiEncryptionInfo == null) { - // Does not support encrypted identity. - return Pair.create(identity, ""); - } - - String encryptedIdentity = buildEncryptedIdentity(identity, - imsiEncryptionInfo); - - // In case of failure for encryption, abort current EAP authentication. - if (encryptedIdentity == null) { - Log.e(TAG, "failed to encrypt the identity"); - return null; - } - return Pair.create(identity, encryptedIdentity); - } - - /** - * Gets Anonymous identity for current active SIM. - * - * @param config the instance of WifiConfiguration. - * @return anonymous identity@realm which is based on current MCC/MNC, {@code null} if SIM is - * not ready or absent. - */ - public String getAnonymousIdentityWith3GppRealm(@NonNull WifiConfiguration config) { - int subId = getBestMatchSubscriptionId(config); - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - if (specifiedTm.getSimState() != TelephonyManager.SIM_STATE_READY) { - return null; - } - String mccMnc = specifiedTm.getSimOperator(); - if (mccMnc == null || mccMnc.isEmpty()) { - return null; - } - - // Extract mcc & mnc from mccMnc - String mcc = mccMnc.substring(0, 3); - String mnc = mccMnc.substring(3); - - if (mnc.length() == 2) { - mnc = "0" + mnc; - } - - String realm = String.format(THREE_GPP_NAI_REALM_FORMAT, mnc, mcc); - StringBuilder sb = new StringBuilder(); - if (mEapMethodPrefixEnable.get(subId)) { - // Set the EAP method as a prefix - String eapMethod = EAP_METHOD_PREFIX.get(config.enterpriseConfig.getEapMethod()); - if (!TextUtils.isEmpty(eapMethod)) { - sb.append(eapMethod); - } - } - return sb.append(ANONYMOUS_IDENTITY).append("@").append(realm).toString(); - } - - /** - * Encrypt the given data with the given public key. The encrypted data will be returned as - * a Base64 encoded string. - * - * @param key The public key to use for encryption - * @param data The data need to be encrypted - * @param encodingFlag base64 encoding flag - * @return Base64 encoded string, or null if encryption failed - */ - @VisibleForTesting - public static String encryptDataUsingPublicKey(PublicKey key, byte[] data, int encodingFlag) { - try { - Cipher cipher = Cipher.getInstance(IMSI_CIPHER_TRANSFORMATION); - cipher.init(Cipher.ENCRYPT_MODE, key); - byte[] encryptedBytes = cipher.doFinal(data); - - return Base64.encodeToString(encryptedBytes, 0, encryptedBytes.length, encodingFlag); - } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException - | IllegalBlockSizeException | BadPaddingException e) { - Log.e(TAG, "Encryption failed: " + e.getMessage()); - return null; - } - } - - /** - * Create the encrypted identity. - * - * Prefix value: - * "0" - EAP-AKA Identity - * "1" - EAP-SIM Identity - * "6" - EAP-AKA' Identity - * Encrypted identity format: prefix|IMSI@<NAIRealm> - * @param identity permanent identity with format based on section 4.1.1.6 of RFC 4187 - * and 4.2.1.6 of RFC 4186. - * @param imsiEncryptionInfo The IMSI encryption info retrieved from the SIM - * @return "\0" + encryptedIdentity + "{, Key Identifier AVP}" - */ - private static String buildEncryptedIdentity(String identity, - ImsiEncryptionInfo imsiEncryptionInfo) { - if (imsiEncryptionInfo == null) { - Log.e(TAG, "imsiEncryptionInfo is not valid"); - return null; - } - if (identity == null) { - Log.e(TAG, "identity is not valid"); - return null; - } - - // Build and return the encrypted identity. - String encryptedIdentity = encryptDataUsingPublicKey( - imsiEncryptionInfo.getPublicKey(), identity.getBytes(), Base64.NO_WRAP); - if (encryptedIdentity == null) { - Log.e(TAG, "Failed to encrypt IMSI"); - return null; - } - encryptedIdentity = DEFAULT_EAP_PREFIX + encryptedIdentity; - if (imsiEncryptionInfo.getKeyIdentifier() != null) { - // Include key identifier AVP (Attribute Value Pair). - encryptedIdentity = encryptedIdentity + "," + imsiEncryptionInfo.getKeyIdentifier(); - } - return encryptedIdentity; - } - - /** - * Create an identity used for SIM-based EAP authentication. The identity will be based on - * the info retrieved from the SIM card, such as IMSI and IMSI encryption info. The IMSI - * contained in the identity will be encrypted if IMSI encryption info is provided. - * - * See rfc4186 & rfc4187 & rfc5448: - * - * Identity format: - * Prefix | [IMSI || Encrypted IMSI] | @realm | {, Key Identifier AVP} - * where "|" denotes concatenation, "||" denotes exclusive value, "{}" - * denotes optional value, and realm is the 3GPP network domain name derived from the given - * MCC/MNC according to the 3GGP spec(TS23.003). - * - * Prefix value: - * "\0" - Encrypted Identity - * "0" - EAP-AKA Identity - * "1" - EAP-SIM Identity - * "6" - EAP-AKA' Identity - * - * Encrypted IMSI: - * Base64{RSA_Public_Key_Encryption{eapPrefix | IMSI}} - * where "|" denotes concatenation, - * - * @param eapMethod EAP authentication method: EAP-SIM, EAP-AKA, EAP-AKA' - * @param imsi The IMSI retrieved from the SIM - * @param mccMnc The MCC MNC identifier retrieved from the SIM - * @param isEncrypted Whether the imsi is encrypted or not. - * @return the eap identity, built using either the encrypted or un-encrypted IMSI. - */ - private static String buildIdentity(int eapMethod, String imsi, String mccMnc, - boolean isEncrypted) { - if (imsi == null || imsi.isEmpty()) { - Log.e(TAG, "No IMSI or IMSI is null"); - return null; - } - - String prefix = isEncrypted ? DEFAULT_EAP_PREFIX : EAP_METHOD_PREFIX.get(eapMethod); - if (prefix == null) { - return null; - } - - /* extract mcc & mnc from mccMnc */ - String mcc; - String mnc; - if (mccMnc != null && !mccMnc.isEmpty()) { - mcc = mccMnc.substring(0, 3); - mnc = mccMnc.substring(3); - if (mnc.length() == 2) { - mnc = "0" + mnc; - } - } else { - // extract mcc & mnc from IMSI, assume mnc size is 3 - mcc = imsi.substring(0, 3); - mnc = imsi.substring(3, 6); - } - - String naiRealm = String.format(THREE_GPP_NAI_REALM_FORMAT, mnc, mcc); - return prefix + imsi + "@" + naiRealm; - } - - /** - * Return the associated SIM method for the configuration. - * - * @param config WifiConfiguration corresponding to the network. - * @return the outer EAP method associated with this SIM configuration. - */ - private static int getSimMethodForConfig(WifiConfiguration config) { - if (config == null || config.enterpriseConfig == null - || !config.enterpriseConfig.isAuthenticationSimBased()) { - return WifiEnterpriseConfig.Eap.NONE; - } - int eapMethod = config.enterpriseConfig.getEapMethod(); - if (eapMethod == WifiEnterpriseConfig.Eap.PEAP) { - // Translate known inner eap methods into an equivalent outer eap method. - switch (config.enterpriseConfig.getPhase2Method()) { - case WifiEnterpriseConfig.Phase2.SIM: - eapMethod = WifiEnterpriseConfig.Eap.SIM; - break; - case WifiEnterpriseConfig.Phase2.AKA: - eapMethod = WifiEnterpriseConfig.Eap.AKA; - break; - case WifiEnterpriseConfig.Phase2.AKA_PRIME: - eapMethod = WifiEnterpriseConfig.Eap.AKA_PRIME; - break; - } - } - - return eapMethod; - } - - /** - * Returns true if {@code identity} contains an anonymous@realm identity, false otherwise. - */ - public static boolean isAnonymousAtRealmIdentity(String identity) { - if (TextUtils.isEmpty(identity)) return false; - final String anonymousId = WifiCarrierInfoManager.ANONYMOUS_IDENTITY + "@"; - return identity.startsWith(anonymousId) - || identity.substring(1).startsWith(anonymousId); - } - - // TODO replace some of this code with Byte.parseByte - private static int parseHex(char ch) { - if ('0' <= ch && ch <= '9') { - return ch - '0'; - } else if ('a' <= ch && ch <= 'f') { - return ch - 'a' + 10; - } else if ('A' <= ch && ch <= 'F') { - return ch - 'A' + 10; - } else { - throw new NumberFormatException("" + ch + " is not a valid hex digit"); - } - } - - private static byte[] parseHex(String hex) { - /* This only works for good input; don't throw bad data at it */ - if (hex == null) { - return new byte[0]; - } - - if (hex.length() % 2 != 0) { - throw new NumberFormatException(hex + " is not a valid hex string"); - } - - byte[] result = new byte[(hex.length()) / 2 + 1]; - result[0] = (byte) ((hex.length()) / 2); - for (int i = 0, j = 1; i < hex.length(); i += 2, j++) { - int val = parseHex(hex.charAt(i)) * 16 + parseHex(hex.charAt(i + 1)); - byte b = (byte) (val & 0xFF); - result[j] = b; - } - - return result; - } - - private static byte[] parseHexWithoutLength(String hex) { - byte[] tmpRes = parseHex(hex); - if (tmpRes.length == 0) { - return tmpRes; - } - - byte[] result = new byte[tmpRes.length - 1]; - System.arraycopy(tmpRes, 1, result, 0, tmpRes.length - 1); - - return result; - } - - private static String makeHex(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - sb.append(String.format("%02x", b)); - } - return sb.toString(); - } - - private static String makeHex(byte[] bytes, int from, int len) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < len; i++) { - sb.append(String.format("%02x", bytes[from + i])); - } - return sb.toString(); - } - - private static byte[] concatHex(byte[] array1, byte[] array2) { - - int len = array1.length + array2.length; - - byte[] result = new byte[len]; - - int index = 0; - if (array1.length != 0) { - for (byte b : array1) { - result[index] = b; - index++; - } - } - - if (array2.length != 0) { - for (byte b : array2) { - result[index] = b; - index++; - } - } - - return result; - } - - /** - * Calculate SRES and KC as 3G authentication. - * - * Standard Cellular_auth Type Command - * - * 3GPP TS 31.102 3G_authentication [Length][RAND][Length][AUTN] - * [Length][RES][Length][CK][Length][IK] and more - * - * @param requestData RAND data from server. - * @param config The instance of WifiConfiguration. - * @return the response data processed by SIM. If all request data is malformed, then returns - * empty string. If request data is invalid, then returns null. - */ - public String getGsmSimAuthResponse(String[] requestData, WifiConfiguration config) { - return getGsmAuthResponseWithLength(requestData, config, TelephonyManager.APPTYPE_USIM); - } - - /** - * Calculate SRES and KC as 2G authentication. - * - * Standard Cellular_auth Type Command - * - * 3GPP TS 31.102 2G_authentication [Length][RAND] - * [Length][SRES][Length][Cipher Key Kc] - * - * @param requestData RAND data from server. - * @param config The instance of WifiConfiguration. - * @return the response data processed by SIM. If all request data is malformed, then returns - * empty string. If request data is invalid, then returns null. - */ - public String getGsmSimpleSimAuthResponse(String[] requestData, - WifiConfiguration config) { - return getGsmAuthResponseWithLength(requestData, config, TelephonyManager.APPTYPE_SIM); - } - - private String getGsmAuthResponseWithLength(String[] requestData, - WifiConfiguration config, int appType) { - int subId = getBestMatchSubscriptionId(config); - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return null; - } - - StringBuilder sb = new StringBuilder(); - for (String challenge : requestData) { - if (challenge == null || challenge.isEmpty()) { - continue; - } - Log.d(TAG, "RAND = " + challenge); - - byte[] rand = null; - try { - rand = parseHex(challenge); - } catch (NumberFormatException e) { - Log.e(TAG, "malformed challenge"); - continue; - } - - String base64Challenge = Base64.encodeToString(rand, Base64.NO_WRAP); - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - String tmResponse = specifiedTm.getIccAuthentication( - appType, TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge); - Log.v(TAG, "Raw Response - " + tmResponse); - - if (tmResponse == null || tmResponse.length() <= 4) { - Log.e(TAG, "bad response - " + tmResponse); - return null; - } - - byte[] result = Base64.decode(tmResponse, Base64.DEFAULT); - Log.v(TAG, "Hex Response -" + makeHex(result)); - int sresLen = result[0]; - if (sresLen < 0 || sresLen >= result.length) { - Log.e(TAG, "malformed response - " + tmResponse); - return null; - } - String sres = makeHex(result, 1, sresLen); - int kcOffset = 1 + sresLen; - if (kcOffset >= result.length) { - Log.e(TAG, "malformed response - " + tmResponse); - return null; - } - int kcLen = result[kcOffset]; - if (kcLen < 0 || kcOffset + kcLen > result.length) { - Log.e(TAG, "malformed response - " + tmResponse); - return null; - } - String kc = makeHex(result, 1 + kcOffset, kcLen); - sb.append(":" + kc + ":" + sres); - Log.v(TAG, "kc:" + kc + " sres:" + sres); - } - - return sb.toString(); - } - - /** - * Calculate SRES and KC as 2G authentication. - * - * Standard Cellular_auth Type Command - * - * 3GPP TS 11.11 2G_authentication [RAND] - * [SRES][Cipher Key Kc] - * - * @param requestData RAND data from server. - * @param config the instance of WifiConfiguration. - * @return the response data processed by SIM. If all request data is malformed, then returns - * empty string. If request data is invalid, then returns null. - */ - public String getGsmSimpleSimNoLengthAuthResponse(String[] requestData, - @NonNull WifiConfiguration config) { - - int subId = getBestMatchSubscriptionId(config); - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return null; - } - - StringBuilder sb = new StringBuilder(); - for (String challenge : requestData) { - if (challenge == null || challenge.isEmpty()) { - continue; - } - Log.d(TAG, "RAND = " + challenge); - - byte[] rand = null; - try { - rand = parseHexWithoutLength(challenge); - } catch (NumberFormatException e) { - Log.e(TAG, "malformed challenge"); - continue; - } - - String base64Challenge = Base64.encodeToString(rand, Base64.NO_WRAP); - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - String tmResponse = specifiedTm.getIccAuthentication(TelephonyManager.APPTYPE_SIM, - TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge); - Log.v(TAG, "Raw Response - " + tmResponse); - - if (tmResponse == null || tmResponse.length() <= 4) { - Log.e(TAG, "bad response - " + tmResponse); - return null; - } - - byte[] result = Base64.decode(tmResponse, Base64.DEFAULT); - if (SRES_LEN + KC_LEN != result.length) { - Log.e(TAG, "malformed response - " + tmResponse); - return null; - } - Log.v(TAG, "Hex Response -" + makeHex(result)); - String sres = makeHex(result, START_SRES_POS, SRES_LEN); - String kc = makeHex(result, START_KC_POS, KC_LEN); - sb.append(":" + kc + ":" + sres); - Log.v(TAG, "kc:" + kc + " sres:" + sres); - } - - return sb.toString(); - } - - /** - * Data supplied when making a SIM Auth Request - */ - public static class SimAuthRequestData { - public SimAuthRequestData() {} - public SimAuthRequestData(int networkId, int protocol, String ssid, String[] data) { - this.networkId = networkId; - this.protocol = protocol; - this.ssid = ssid; - this.data = data; - } - - public int networkId; - public int protocol; - public String ssid; - // EAP-SIM: data[] contains the 3 rand, one for each of the 3 challenges - // EAP-AKA/AKA': data[] contains rand & authn couple for the single challenge - public String[] data; - } - - /** - * The response to a SIM Auth request if successful - */ - public static class SimAuthResponseData { - public SimAuthResponseData(String type, String response) { - this.type = type; - this.response = response; - } - - public String type; - public String response; - } - - /** - * Get the response data for 3G authentication. - * - * @param requestData authentication request data from server. - * @param config the instance of WifiConfiguration. - * @return the response data processed by SIM. If request data is invalid, then returns null. - */ - public SimAuthResponseData get3GAuthResponse(SimAuthRequestData requestData, - WifiConfiguration config) { - StringBuilder sb = new StringBuilder(); - byte[] rand = null; - byte[] authn = null; - String resType = WifiNative.SIM_AUTH_RESP_TYPE_UMTS_AUTH; - - if (requestData.data.length == 2) { - try { - rand = parseHex(requestData.data[0]); - authn = parseHex(requestData.data[1]); - } catch (NumberFormatException e) { - Log.e(TAG, "malformed challenge"); - } - } else { - Log.e(TAG, "malformed challenge"); - } - - String tmResponse = ""; - if (rand != null && authn != null) { - String base64Challenge = Base64.encodeToString(concatHex(rand, authn), Base64.NO_WRAP); - int subId = getBestMatchSubscriptionId(config); - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return null; - } - tmResponse = mTelephonyManager - .createForSubscriptionId(subId) - .getIccAuthentication(TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_AKA, base64Challenge); - Log.v(TAG, "Raw Response - " + tmResponse); - } - - boolean goodReponse = false; - if (tmResponse != null && tmResponse.length() > 4) { - byte[] result = Base64.decode(tmResponse, Base64.DEFAULT); - Log.e(TAG, "Hex Response - " + makeHex(result)); - byte tag = result[0]; - if (tag == (byte) 0xdb) { - Log.v(TAG, "successful 3G authentication "); - int resLen = result[1]; - String res = makeHex(result, 2, resLen); - int ckLen = result[resLen + 2]; - String ck = makeHex(result, resLen + 3, ckLen); - int ikLen = result[resLen + ckLen + 3]; - String ik = makeHex(result, resLen + ckLen + 4, ikLen); - sb.append(":" + ik + ":" + ck + ":" + res); - Log.v(TAG, "ik:" + ik + "ck:" + ck + " res:" + res); - goodReponse = true; - } else if (tag == (byte) 0xdc) { - Log.e(TAG, "synchronisation failure"); - int autsLen = result[1]; - String auts = makeHex(result, 2, autsLen); - resType = WifiNative.SIM_AUTH_RESP_TYPE_UMTS_AUTS; - sb.append(":" + auts); - Log.v(TAG, "auts:" + auts); - goodReponse = true; - } else { - Log.e(TAG, "bad response - unknown tag = " + tag); - } - } else { - Log.e(TAG, "bad response - " + tmResponse); - } - - if (goodReponse) { - String response = sb.toString(); - Log.v(TAG, "Supplicant Response -" + response); - return new SimAuthResponseData(resType, response); - } else { - return null; - } - } - - /** - * Get the carrier type of current SIM. - * - * @param subId the subscription ID of SIM card. - * @return carrier type of current active sim, {{@link #CARRIER_INVALID_TYPE}} if sim is not - * ready. - */ - private int getCarrierType(int subId) { - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return CARRIER_INVALID_TYPE; - } - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - - if (specifiedTm.getSimState() != TelephonyManager.SIM_STATE_READY) { - return CARRIER_INVALID_TYPE; - } - - // If two APIs return the same carrier ID, then is considered as MNO, otherwise MVNO - if (specifiedTm.getCarrierIdFromSimMccMnc() == specifiedTm.getSimCarrierId()) { - return CARRIER_MNO_TYPE; - } - return CARRIER_MVNO_TYPE; - } - - /** - * Decorates a pseudonym with the NAI realm, in case it wasn't provided by the server - * - * @param config The instance of WifiConfiguration - * @param pseudonym The pseudonym (temporary identity) provided by the server - * @return pseudonym@realm which is based on current MCC/MNC, {@code null} if SIM is - * not ready or absent. - */ - public String decoratePseudonymWith3GppRealm(@NonNull WifiConfiguration config, - String pseudonym) { - if (TextUtils.isEmpty(pseudonym)) { - return null; - } - if (pseudonym.contains("@")) { - // Pseudonym is already decorated - return pseudonym; - } - int subId = getBestMatchSubscriptionId(config); - - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - if (specifiedTm.getSimState() != TelephonyManager.SIM_STATE_READY) { - return null; - } - String mccMnc = specifiedTm.getSimOperator(); - if (mccMnc == null || mccMnc.isEmpty()) { - return null; - } - - // Extract mcc & mnc from mccMnc - String mcc = mccMnc.substring(0, 3); - String mnc = mccMnc.substring(3); - - if (mnc.length() == 2) { - mnc = "0" + mnc; - } - - String realm = String.format(THREE_GPP_NAI_REALM_FORMAT, mnc, mcc); - return String.format("%s@%s", pseudonym, realm); - } - - /** - * Reset the downloaded IMSI encryption key. - * @param config Instance of WifiConfiguration - */ - public void resetCarrierKeysForImsiEncryption(@NonNull WifiConfiguration config) { - int subId = getBestMatchSubscriptionId(config); - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - return; - } - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - specifiedTm.resetCarrierKeysForImsiEncryption(); - } - - /** - * Updates the carrier ID for passpoint configuration with SIM credential. - * - * @param config The instance of PasspointConfiguration. - * @return true if the carrier ID is updated, false otherwise - */ - public boolean tryUpdateCarrierIdForPasspoint(PasspointConfiguration config) { - if (config.getCarrierId() != TelephonyManager.UNKNOWN_CARRIER_ID) { - return false; - } - - Credential.SimCredential simCredential = config.getCredential().getSimCredential(); - if (simCredential == null) { - // carrier ID is not required. - return false; - } - - IMSIParameter imsiParameter = IMSIParameter.build(simCredential.getImsi()); - // If the IMSI is not full, the carrier ID can not be matched for sure, so it should - // be ignored. - if (imsiParameter == null || !imsiParameter.isFullImsi()) { - vlogd("IMSI is not available or not full"); - return false; - } - List<SubscriptionInfo> infos = mSubscriptionManager.getActiveSubscriptionInfoList(); - if (infos == null) { - return false; - } - // Find the active matching SIM card with the full IMSI from passpoint profile. - for (SubscriptionInfo subInfo : infos) { - String imsi = mTelephonyManager - .createForSubscriptionId(subInfo.getSubscriptionId()).getSubscriberId(); - if (imsiParameter.matchesImsi(imsi)) { - config.setCarrierId(subInfo.getCarrierId()); - return true; - } - } - - return false; - } - - /** - * Get the IMSI and carrier ID of the SIM card which is matched with the given carrier ID. - * - * @param carrierId The carrier ID see {@link TelephonyManager.getSimCarrierId} - * @return null if there is no matching SIM card, otherwise the IMSI and carrier ID of the - * matching SIM card - */ - public @Nullable String getMatchingImsi(int carrierId) { - int subId = getMatchingSubId(carrierId); - if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - if (requiresImsiEncryption(subId) && !isImsiEncryptionInfoAvailable(subId)) { - vlogd("required IMSI encryption information is not available."); - return null; - } - return mTelephonyManager.createForSubscriptionId(subId).getSubscriberId(); - } - vlogd("no active SIM card to match the carrier ID."); - return null; - } - - /** - * Get the IMSI and carrier ID of the SIM card which is matched with the given IMSI - * (only prefix of IMSI - mccmnc*) from passpoint profile. - * - * @param imsiPrefix The IMSI parameter from passpoint profile. - * @return null if there is no matching SIM card, otherwise the IMSI and carrier ID of the - * matching SIM card - */ - public @Nullable Pair<String, Integer> getMatchingImsiCarrierId( - String imsiPrefix) { - IMSIParameter imsiParameter = IMSIParameter.build(imsiPrefix); - if (imsiParameter == null) { - return null; - } - List<SubscriptionInfo> infos = mSubscriptionManager.getActiveSubscriptionInfoList(); - if (infos == null) { - return null; - } - int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); - //Pair<IMSI, carrier ID> the IMSI and carrier ID of matched SIM card - Pair<String, Integer> matchedPair = null; - // matchedDataPair check if the data SIM is matched. - Pair<String, Integer> matchedDataPair = null; - // matchedMnoPair check if any matched SIM card is MNO. - Pair<String, Integer> matchedMnoPair = null; - - // Find the active matched SIM card with the priority order of Data MNO SIM, - // Nondata MNO SIM, Data MVNO SIM, Nondata MVNO SIM. - for (SubscriptionInfo subInfo : infos) { - int subId = subInfo.getSubscriptionId(); - if (requiresImsiEncryption(subId) && !isImsiEncryptionInfoAvailable(subId)) { - vlogd("required IMSI encryption information is not available."); - continue; - } - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - String operatorNumeric = specifiedTm.getSimOperator(); - if (operatorNumeric != null && imsiParameter.matchesMccMnc(operatorNumeric)) { - String curImsi = specifiedTm.getSubscriberId(); - if (TextUtils.isEmpty(curImsi)) { - continue; - } - matchedPair = new Pair<>(curImsi, subInfo.getCarrierId()); - if (subId == dataSubId) { - matchedDataPair = matchedPair; - if (getCarrierType(subId) == CARRIER_MNO_TYPE) { - vlogd("MNO data is matched via IMSI."); - return matchedDataPair; - } - } - if (getCarrierType(subId) == CARRIER_MNO_TYPE) { - matchedMnoPair = matchedPair; - } - } - } - - if (matchedMnoPair != null) { - vlogd("MNO sub is matched via IMSI."); - return matchedMnoPair; - } - - if (matchedDataPair != null) { - vlogd("MVNO data sub is matched via IMSI."); - return matchedDataPair; - } - - return matchedPair; - } - - private void vlogd(String msg) { - if (!mVerboseLogEnabled) { - return; - } - - Log.d(TAG, msg); - } - - /** Dump state. */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(TAG + ": "); - pw.println("mImsiEncryptionRequired=" + mImsiEncryptionRequired); - pw.println("mImsiEncryptionInfoAvailable=" + mImsiEncryptionInfoAvailable); - } - - /** - * Get the carrier ID {@link TelephonyManager#getSimCarrierId()} of the carrier which give - * target package carrier privileges. - * - * @param packageName target package to check if grant privileges by any carrier. - * @return Carrier ID who give privilege to this package. If package isn't granted privilege - * by any available carrier, will return UNKNOWN_CARRIER_ID. - */ - public int getCarrierIdForPackageWithCarrierPrivileges(String packageName) { - List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); - if (subInfoList == null || subInfoList.isEmpty()) { - if (mVerboseLogEnabled) Log.v(TAG, "No subs for carrier privilege check"); - return TelephonyManager.UNKNOWN_CARRIER_ID; - } - for (SubscriptionInfo info : subInfoList) { - TelephonyManager specifiedTm = - mTelephonyManager.createForSubscriptionId(info.getSubscriptionId()); - if (specifiedTm.checkCarrierPrivilegesForPackage(packageName) - == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { - return info.getCarrierId(); - } - } - return TelephonyManager.UNKNOWN_CARRIER_ID; - } - - /** - * Get the carrier name for target subscription id. - * @param subId Subscription id - * @return String of carrier name. - */ - public String getCarrierNameforSubId(int subId) { - TelephonyManager specifiedTm = - mTelephonyManager.createForSubscriptionId(subId); - - CharSequence name = specifiedTm.getSimCarrierIdName(); - if (name == null) { - return null; - } - return name.toString(); - } - - /** - * Check if a config is carrier network and from the non default data SIM. - * @return True if it is carrier network and from non default data SIM,otherwise return false. - */ - public boolean isCarrierNetworkFromNonDefaultDataSim(WifiConfiguration config) { - if (config.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { - return false; - } - int subId = getMatchingSubId(config.carrierId); - return subId != SubscriptionManager.getDefaultDataSubscriptionId(); - } - - /** - * Get the carrier Id of the default data sim. - */ - public int getDefaultDataSimCarrierId() { - int subId = SubscriptionManager.getDefaultDataSubscriptionId(); - TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId); - return specifiedTm.getSimCarrierId(); - } - - /** - * Add a listener to monitor user approval IMSI protection exemption. - */ - public void addImsiExemptionUserApprovalListener( - OnUserApproveCarrierListener listener) { - mOnUserApproveCarrierListeners.add(listener); - } - - /** - * Clear the Imsi Privacy Exemption user approval info the target carrier. - */ - public void clearImsiPrivacyExemptionForCarrier(int carrierId) { - mImsiPrivacyProtectionExemptionMap.remove(carrierId); - saveToStore(); - } - - /** - * Check if carrier have user approved exemption for IMSI protection - */ - public boolean hasUserApprovedImsiPrivacyExemptionForCarrier(int carrierId) { - return mImsiPrivacyProtectionExemptionMap.getOrDefault(carrierId, false); - } - - /** - * Enable or disable exemption on IMSI protection. - */ - public void setHasUserApprovedImsiPrivacyExemptionForCarrier(boolean approved, int carrierId) { - if (mVerboseLogEnabled) { - Log.v(TAG, "Setting Imsi privacy exemption for carrier " + carrierId - + (approved ? " approved" : " not approved")); - } - mImsiPrivacyProtectionExemptionMap.put(carrierId, approved); - // If user approved the exemption restore to initial auto join configure. - if (approved) { - for (OnUserApproveCarrierListener listener : mOnUserApproveCarrierListeners) { - listener.onUserAllowed(carrierId); - } - } - saveToStore(); - } - - private void sendImsiPrivacyNotification(int carrierId) { - String carrierName = getCarrierNameforSubId(getMatchingSubId(carrierId)); - Notification.Action userAllowAppNotificationAction = - new Notification.Action.Builder(null, - mResources.getText(R.string - .wifi_suggestion_action_allow_imsi_privacy_exemption_carrier), - getPrivateBroadcast(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION, - Pair.create(EXTRA_CARRIER_NAME, carrierName), - Pair.create(EXTRA_CARRIER_ID, carrierId))) - .build(); - Notification.Action userDisallowAppNotificationAction = - new Notification.Action.Builder(null, - mResources.getText(R.string - .wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier), - getPrivateBroadcast(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION, - Pair.create(EXTRA_CARRIER_NAME, carrierName), - Pair.create(EXTRA_CARRIER_ID, carrierId))) - .build(); - - Notification notification = mFrameworkFacade.makeNotificationBuilder( - mContext, WifiService.NOTIFICATION_NETWORK_STATUS) - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range)) - .setTicker(mResources.getString( - R.string.wifi_suggestion_imsi_privacy_title, carrierName)) - .setContentTitle(mResources.getString( - R.string.wifi_suggestion_imsi_privacy_title, carrierName)) - .setStyle(new Notification.BigTextStyle() - .bigText(mResources.getString( - R.string.wifi_suggestion_imsi_privacy_content))) - .setContentIntent(getPrivateBroadcast(NOTIFICATION_USER_CLICKED_INTENT_ACTION, - Pair.create(EXTRA_CARRIER_NAME, carrierName), - Pair.create(EXTRA_CARRIER_ID, carrierId))) - .setDeleteIntent(getPrivateBroadcast(NOTIFICATION_USER_DISMISSED_INTENT_ACTION, - Pair.create(EXTRA_CARRIER_NAME, carrierName), - Pair.create(EXTRA_CARRIER_ID, carrierId))) - .setShowWhen(false) - .setLocalOnly(true) - .setColor(mResources.getColor(android.R.color.system_notification_accent_color, - mContext.getTheme())) - .addAction(userDisallowAppNotificationAction) - .addAction(userAllowAppNotificationAction) - .build(); - - // Post the notification. - mNotificationManager.notify( - SystemMessageProto.SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE, notification); - mUserApprovalUiActive = true; - mIsLastUserApprovalUiDialog = false; - } - - private void sendImsiPrivacyConfirmationDialog(@NonNull String carrierName, int carrierId) { - mWifiMetrics.addUserApprovalCarrierUiReaction(ACTION_USER_ALLOWED_CARRIER, - mIsLastUserApprovalUiDialog); - AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) - .setTitle(mResources.getString( - R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_title)) - .setMessage(mResources.getString( - R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_content, - carrierName)) - .setPositiveButton(mResources.getText( - R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation), - (d, which) -> mHandler.post( - () -> handleUserAllowCarrierExemptionAction( - carrierName, carrierId))) - .setNegativeButton(mResources.getText( - R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation), - (d, which) -> mHandler.post( - () -> handleUserDisallowCarrierExemptionAction( - carrierName, carrierId))) - .setOnDismissListener( - (d) -> mHandler.post(this::handleUserDismissAction)) - .setOnCancelListener( - (d) -> mHandler.post(this::handleUserDismissAction)) - .create(); - dialog.setCanceledOnTouchOutside(false); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - dialog.getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); - dialog.show(); - mUserApprovalUiActive = true; - mIsLastUserApprovalUiDialog = true; - } - - /** - * Send notification for exemption of IMSI protection if user never made choice before. - */ - public void sendImsiProtectionExemptionNotificationIfRequired(int carrierId) { - int subId = getMatchingSubId(carrierId); - // If user data isn't loaded, don't send notification. - if (!mUserDataLoaded) { - return; - } - if (requiresImsiEncryption(subId)) { - return; - } - if (mImsiPrivacyProtectionExemptionMap.containsKey(carrierId)) { - return; - } - if (mUserApprovalUiActive) { - return; - } - Log.i(TAG, "Sending IMSI protection notification for " + carrierId); - sendImsiPrivacyNotification(carrierId); - } - - private PendingIntent getPrivateBroadcast(@NonNull String action, - @NonNull Pair<String, String> extra1, @NonNull Pair<String, Integer> extra2) { - Intent intent = new Intent(action) - .setPackage(mWifiInjector.getWifiStackPackageName()) - .putExtra(extra1.first, extra1.second) - .putExtra(extra2.first, extra2.second); - return mFrameworkFacade.getBroadcast(mContext, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - } - - private void saveToStore() { - // Set the flag to let WifiConfigStore that we have new data to write. - mHasNewDataToSerialize = true; - if (!mWifiInjector.getWifiConfigManager().saveToStore(true)) { - Log.w(TAG, "Failed to save to store"); - } - } - - /** - * Helper method for user factory reset network setting. - */ - public void clear() { - mImsiPrivacyProtectionExemptionMap.clear(); - saveToStore(); - } -} diff --git a/service/java/com/android/server/wifi/WifiChannelUtilization.java b/service/java/com/android/server/wifi/WifiChannelUtilization.java deleted file mode 100644 index 5e8cde61d..000000000 --- a/service/java/com/android/server/wifi/WifiChannelUtilization.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_STATIONARY; -import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN; - -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager.DeviceMobilityState; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.WifiLinkLayerStats.ChannelStats; -import com.android.server.wifi.util.InformationElementUtil.BssLoad; -import com.android.wifi.resources.R; - -import java.util.ArrayDeque; -import java.util.Iterator; - -/** - * This class collects channel stats over a Wifi Interface - * and calculates channel utilization using the latest and cached channel stats. - * Cache saves previous readings of channel stats in a FIFO. - * The cache is updated when a new stats arrives and it has been a long while since the last update. - * To get more statistically sound channel utilization, for these devices which support - * mobility state report, the cache update is stopped when the device stays in the stationary state. - */ -public class WifiChannelUtilization { - private static final String TAG = "WifiChannelUtilization"; - private static boolean sVerboseLoggingEnabled = false; - public static final int UNKNOWN_FREQ = -1; - // Invalidate the utilization value if it is larger than the following value. - // This is to detect and mitigate the incorrect HW reports of ccaBusy/OnTime. - // It is reasonable to assume that utilization ratio in the real life is never beyond this value - // given by all the inter-frame-spacings (IFS) - static final int UTILIZATION_RATIO_MAX = BssLoad.MAX_CHANNEL_UTILIZATION * 94 / 100; - // Minimum time interval in ms between two cache updates. - @VisibleForTesting - static final int DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS = 10 * 60 * 1000; - // To get valid channel utilization, the time difference between the reference chanStat's - // radioOnTime and current chanStat's radioOntime should be no less than the following value - @VisibleForTesting - static final int RADIO_ON_TIME_DIFF_MIN_MS = 250; - // The number of chanStatsMap readings saved in cache - // where each reading corresponds to one link layer stats update. - @VisibleForTesting - static final int CHANNEL_STATS_CACHE_SIZE = 5; - private final Clock mClock; - private final Context mContext; - private @DeviceMobilityState int mDeviceMobilityState = DEVICE_MOBILITY_STATE_UNKNOWN; - private int mCacheUpdateIntervalMinMs = DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - - // Map frequency (key) to utilization ratio (value) with the valid range of - // [BssLoad.MIN_CHANNEL_UTILIZATION, BssLoad.MAX_CHANNEL_UTILIZATION], - // where MIN_CHANNEL_UTILIZATION corresponds to ratio 0% - // and MAX_CHANNEL_UTILIZATION corresponds to ratio 100% - private SparseIntArray mChannelUtilizationMap = new SparseIntArray(); - private ArrayDeque<SparseArray<ChannelStats>> mChannelStatsMapCache = new ArrayDeque<>(); - private long mLastChannelStatsMapTimeStamp; - private int mLastChannelStatsMapMobilityState; - - WifiChannelUtilization(Clock clock, Context context) { - mContext = context; - mClock = clock; - } - - /** - * Enable/Disable verbose logging. - * @param verbose true to enable and false to disable. - */ - public void enableVerboseLogging(boolean verbose) { - sVerboseLoggingEnabled = verbose; - } - - /** - * (Re)initialize internal variables and status - * @param wifiLinkLayerStats The latest wifi link layer stats - */ - public void init(WifiLinkLayerStats wifiLinkLayerStats) { - mChannelUtilizationMap.clear(); - mChannelStatsMapCache.clear(); - mDeviceMobilityState = DEVICE_MOBILITY_STATE_UNKNOWN; - mLastChannelStatsMapMobilityState = DEVICE_MOBILITY_STATE_UNKNOWN; - for (int i = 0; i < (CHANNEL_STATS_CACHE_SIZE - 1); ++i) { - mChannelStatsMapCache.addFirst(new SparseArray<>()); - } - if (wifiLinkLayerStats != null) { - mChannelStatsMapCache.addFirst(wifiLinkLayerStats.channelStatsMap); - } else { - mChannelStatsMapCache.addFirst(new SparseArray<>()); - } - mLastChannelStatsMapTimeStamp = mClock.getElapsedSinceBootMillis(); - if (sVerboseLoggingEnabled) { - Log.d(TAG, "initializing"); - } - } - - /** - * Set channel stats cache update minimum interval - */ - public void setCacheUpdateIntervalMs(int cacheUpdateIntervalMinMs) { - mCacheUpdateIntervalMinMs = cacheUpdateIntervalMinMs; - } - - /** - * Get channel utilization ratio for a given frequency - * @param frequency The center frequency of 20MHz WLAN channel - * @return Utilization ratio value if it is available; BssLoad.INVALID otherwise - */ - public int getUtilizationRatio(int frequency) { - if (mContext.getResources().getBoolean( - R.bool.config_wifiChannelUtilizationOverrideEnabled)) { - if (ScanResult.is24GHz(frequency)) { - return mContext.getResources().getInteger( - R.integer.config_wifiChannelUtilizationOverride2g); - } - if (ScanResult.is5GHz(frequency)) { - return mContext.getResources().getInteger( - R.integer.config_wifiChannelUtilizationOverride5g); - } - return mContext.getResources().getInteger( - R.integer.config_wifiChannelUtilizationOverride6g); - } - return mChannelUtilizationMap.get(frequency, BssLoad.INVALID); - } - - /** - * Update device mobility state - * @param newState the new device mobility state - */ - public void setDeviceMobilityState(@DeviceMobilityState int newState) { - mDeviceMobilityState = newState; - if (sVerboseLoggingEnabled) { - Log.d(TAG, " update device mobility state to " + newState); - } - } - - /** - * Set channel utilization ratio for a given frequency - * @param frequency The center frequency of 20MHz channel - * @param utilizationRatio The utilization ratio of 20MHz channel - */ - public void setUtilizationRatio(int frequency, int utilizationRatio) { - mChannelUtilizationMap.put(frequency, utilizationRatio); - } - - /** - * Update channel utilization with the latest link layer stats and the cached channel stats - * and then update channel stats cache - * If the given frequency is UNKNOWN_FREQ, calculate channel utilization of all frequencies - * Otherwise, calculate the channel utilization of the given frequency - * @param wifiLinkLayerStats The latest wifi link layer stats - * @param frequency Current frequency of network. - */ - public void refreshChannelStatsAndChannelUtilization(WifiLinkLayerStats wifiLinkLayerStats, - int frequency) { - if (mContext.getResources().getBoolean( - R.bool.config_wifiChannelUtilizationOverrideEnabled)) { - return; - } - - if (wifiLinkLayerStats == null) { - return; - } - SparseArray<ChannelStats> channelStatsMap = wifiLinkLayerStats.channelStatsMap; - if (channelStatsMap == null) { - return; - } - if (frequency != UNKNOWN_FREQ) { - ChannelStats channelStats = channelStatsMap.get(frequency, null); - if (channelStats != null) calculateChannelUtilization(channelStats); - } else { - for (int i = 0; i < channelStatsMap.size(); i++) { - ChannelStats channelStats = channelStatsMap.valueAt(i); - calculateChannelUtilization(channelStats); - } - } - updateChannelStatsCache(channelStatsMap, frequency); - } - - private void calculateChannelUtilization(ChannelStats channelStats) { - int freq = channelStats.frequency; - int ccaBusyTimeMs = channelStats.ccaBusyTimeMs; - int radioOnTimeMs = channelStats.radioOnTimeMs; - - ChannelStats channelStatsRef = findChanStatsReference(freq, radioOnTimeMs); - int busyTimeDiff = ccaBusyTimeMs - channelStatsRef.ccaBusyTimeMs; - int radioOnTimeDiff = radioOnTimeMs - channelStatsRef.radioOnTimeMs; - int utilizationRatio = BssLoad.INVALID; - if (radioOnTimeDiff >= RADIO_ON_TIME_DIFF_MIN_MS && busyTimeDiff >= 0) { - utilizationRatio = calculateUtilizationRatio(radioOnTimeDiff, busyTimeDiff); - } - mChannelUtilizationMap.put(freq, utilizationRatio); - - if (sVerboseLoggingEnabled) { - int utilizationRatioT0 = calculateUtilizationRatio(radioOnTimeMs, ccaBusyTimeMs); - StringBuilder sb = new StringBuilder(); - Log.d(TAG, sb.append(" freq: ").append(freq) - .append(" onTime: ").append(radioOnTimeMs) - .append(" busyTime: ").append(ccaBusyTimeMs) - .append(" onTimeDiff: ").append(radioOnTimeDiff) - .append(" busyTimeDiff: ").append(busyTimeDiff) - .append(" utilization: ").append(utilizationRatio) - .append(" utilization t0: ").append(utilizationRatioT0) - .toString()); - } - } - /** - * Find a proper channelStats reference from channelStatsMap cache. - * The search continues until it finds a channelStat at the given frequency with radioOnTime - * sufficiently smaller than current radioOnTime, or there is no channelStats for the given - * frequency or it reaches the end of cache. - * @param freq Frequency of current channel - * @param radioOnTimeMs The latest radioOnTime of current channel - * @return the found channelStat reference if search succeeds, or a dummy channelStats with time - * zero if channelStats is not found for the given frequency, or a dummy channelStats with the - * latest radioOnTimeMs if it reaches the end of cache. - */ - private ChannelStats findChanStatsReference(int freq, int radioOnTimeMs) { - // A dummy channelStats with the latest radioOnTimeMs. - ChannelStats channelStatsCurrRadioOnTime = new ChannelStats(); - channelStatsCurrRadioOnTime.radioOnTimeMs = radioOnTimeMs; - Iterator iterator = mChannelStatsMapCache.iterator(); - while (iterator.hasNext()) { - SparseArray<ChannelStats> channelStatsMap = (SparseArray<ChannelStats>) iterator.next(); - // If the freq can't be found in current channelStatsMap, stop search because it won't - // appear in older ones either due to the fact that channelStatsMap are accumulated - // in HW and thus a recent reading should have channels no less than old readings. - // Return a dummy channelStats with zero radioOnTimeMs - if (channelStatsMap == null || channelStatsMap.get(freq) == null) { - return new ChannelStats(); - } - ChannelStats channelStats = channelStatsMap.get(freq); - int radioOnTimeDiff = radioOnTimeMs - channelStats.radioOnTimeMs; - if (radioOnTimeDiff >= RADIO_ON_TIME_DIFF_MIN_MS) { - return channelStats; - } - } - return channelStatsCurrRadioOnTime; - } - - private int calculateUtilizationRatio(int radioOnTimeDiff, int busyTimeDiff) { - if (radioOnTimeDiff > 0) { - int utilizationRatio = busyTimeDiff * BssLoad.MAX_CHANNEL_UTILIZATION / radioOnTimeDiff; - return (utilizationRatio > UTILIZATION_RATIO_MAX) ? BssLoad.INVALID : utilizationRatio; - } else { - return BssLoad.INVALID; - } - } - - private void updateChannelStatsCache(SparseArray<ChannelStats> channelStatsMap, int freq) { - // Update cache if it hits one of following conditions - // 1) it has been a long while since the last update and device doesn't remain stationary - // 2) cache is empty - boolean remainStationary = - mLastChannelStatsMapMobilityState == DEVICE_MOBILITY_STATE_STATIONARY - && mDeviceMobilityState == DEVICE_MOBILITY_STATE_STATIONARY; - long currTimeStamp = mClock.getElapsedSinceBootMillis(); - boolean isLongTimeSinceLastUpdate = - (currTimeStamp - mLastChannelStatsMapTimeStamp) >= mCacheUpdateIntervalMinMs; - if ((isLongTimeSinceLastUpdate && !remainStationary) || isChannelStatsMapCacheEmpty(freq)) { - mChannelStatsMapCache.addFirst(channelStatsMap); - mChannelStatsMapCache.removeLast(); - mLastChannelStatsMapTimeStamp = currTimeStamp; - mLastChannelStatsMapMobilityState = mDeviceMobilityState; - } - } - - private boolean isChannelStatsMapCacheEmpty(int freq) { - SparseArray<ChannelStats> channelStatsMap = mChannelStatsMapCache.peekFirst(); - if (channelStatsMap == null || channelStatsMap.size() == 0) return true; - if (freq != UNKNOWN_FREQ && channelStatsMap.get(freq) == null) return true; - return false; - } -} diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java deleted file mode 100644 index 8fc91cb09..000000000 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ /dev/null @@ -1,3303 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLE_REASON_INFOS; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.net.IpConfiguration; -import android.net.MacAddress; -import android.net.ProxyInfo; -import android.net.StaticIpConfiguration; -import android.net.util.MacAddressUtils; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DisableReasonInfo; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NetworkSelectionDisableReason; -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.Process; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.LocalLog; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; -import com.android.server.wifi.util.LruConnectionTracker; -import com.android.server.wifi.util.MissingCounterTimerLockList; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; -import com.android.wifi.resources.R; - -import org.xmlpull.v1.XmlPullParserException; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * This class provides the APIs to manage configured Wi-Fi networks. - * It deals with the following: - * - Maintaining a list of configured networks for quick access. - * - Persisting the configurations to store when required. - * - Supporting WifiManager Public API calls: - * > addOrUpdateNetwork() - * > removeNetwork() - * > enableNetwork() - * > disableNetwork() - * - Handle user switching on multi-user devices. - * - * All network configurations retrieved from this class are copies of the original configuration - * stored in the internal database. So, any updates to the retrieved configuration object are - * meaningless and will not be reflected in the original database. - * This is done on purpose to ensure that only WifiConfigManager can modify configurations stored - * in the internal database. Any configuration updates should be triggered with appropriate helper - * methods of this class using the configuration's unique networkId. - * - * NOTE: These API's are not thread safe and should only be used from the main Wifi thread. - */ -public class WifiConfigManager { - /** - * String used to mask passwords to public interface. - */ - @VisibleForTesting - public static final String PASSWORD_MASK = "*"; - - /** - * Interface for other modules to listen to the network updated events. - * Note: Credentials are masked to avoid accidentally sending credentials outside the stack. - * Use WifiConfigManager#getConfiguredNetworkWithPassword() to retrieve credentials. - */ - public interface OnNetworkUpdateListener { - /** - * Invoked on network being added. - */ - void onNetworkAdded(@NonNull WifiConfiguration config); - /** - * Invoked on network being enabled. - */ - void onNetworkEnabled(@NonNull WifiConfiguration config); - /** - * Invoked on network being permanently disabled. - */ - void onNetworkPermanentlyDisabled(@NonNull WifiConfiguration config, int disableReason); - /** - * Invoked on network being removed. - */ - void onNetworkRemoved(@NonNull WifiConfiguration config); - /** - * Invoked on network being temporarily disabled. - */ - void onNetworkTemporarilyDisabled(@NonNull WifiConfiguration config, int disableReason); - /** - * Invoked on network being updated. - * - * @param newConfig Updated WifiConfiguration object. - * @param oldConfig Prev WifiConfiguration object. - */ - void onNetworkUpdated( - @NonNull WifiConfiguration newConfig, @NonNull WifiConfiguration oldConfig); - } - /** - * Max size of scan details to cache in {@link #mScanDetailCaches}. - */ - @VisibleForTesting - public static final int SCAN_CACHE_ENTRIES_MAX_SIZE = 192; - /** - * Once the size of the scan details in the cache {@link #mScanDetailCaches} exceeds - * {@link #SCAN_CACHE_ENTRIES_MAX_SIZE}, trim it down to this value so that we have some - * buffer time before the next eviction. - */ - @VisibleForTesting - public static final int SCAN_CACHE_ENTRIES_TRIM_SIZE = 128; - /** - * Link networks only if they have less than this number of scan cache entries. - */ - @VisibleForTesting - public static final int LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES = 6; - /** - * Link networks only if the bssid in scan results for the networks match in the first - * 16 ASCII chars in the bssid string. For example = "af:de:56;34:15:7" - */ - @VisibleForTesting - public static final int LINK_CONFIGURATION_BSSID_MATCH_LENGTH = 16; - /** - * Log tag for this class. - */ - private static final String TAG = "WifiConfigManager"; - /** - * Maximum age of scan results that can be used for averaging out RSSI value. - */ - private static final int SCAN_RESULT_MAXIMUM_AGE_MS = 40000; - - /** - * Maximum number of blocked BSSIDs per SSID used for calcualting the duration of temporarily - * disabling a network. - */ - private static final int MAX_BLOCKED_BSSID_PER_NETWORK = 10; - - /** - * Enforce a minimum time to wait after the last disconnect to generate a new randomized MAC, - * since IPv6 networks don't provide the DHCP lease duration. - * 4 hours. - */ - @VisibleForTesting - protected static final long AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS = 4 * 60 * 60 * 1000; - @VisibleForTesting - protected static final long AGGRESSIVE_MAC_REFRESH_MS_MIN = 30 * 60 * 1000; // 30 minutes - @VisibleForTesting - protected static final long AGGRESSIVE_MAC_REFRESH_MS_MAX = 24 * 60 * 60 * 1000; // 24 hours - - private static final MacAddress DEFAULT_MAC_ADDRESS = - MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); - - /** - * Expiration timeout for user disconnect network. (1 hour) - */ - @VisibleForTesting - public static final long USER_DISCONNECT_NETWORK_BLOCK_EXPIRY_MS = (long) 1000 * 60 * 60; - - @VisibleForTesting - public static final int SCAN_RESULT_MISSING_COUNT_THRESHOLD = 1; - @VisibleForTesting - protected static final String ENHANCED_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG = - "enhanced_mac_randomization_force_enabled"; - - /** - * General sorting algorithm of all networks for scanning purposes: - * Place the configurations in ascending order of their AgeIndex. AgeIndex is based on most - * recently connected order. The lower the more recently connected. - * If networks have the same AgeIndex, place the configurations with - * |lastSeenInQualifiedNetworkSelection| set first. - */ - private final WifiConfigurationUtil.WifiConfigurationComparator mScanListComparator = - new WifiConfigurationUtil.WifiConfigurationComparator() { - @Override - public int compareNetworksWithSameStatus(WifiConfiguration a, WifiConfiguration b) { - int indexA = mLruConnectionTracker.getAgeIndexOfNetwork(a); - int indexB = mLruConnectionTracker.getAgeIndexOfNetwork(b); - if (indexA != indexB) { - return Integer.compare(indexA, indexB); - } else { - boolean isConfigALastSeen = - a.getNetworkSelectionStatus() - .getSeenInLastQualifiedNetworkSelection(); - boolean isConfigBLastSeen = - b.getNetworkSelectionStatus() - .getSeenInLastQualifiedNetworkSelection(); - return Boolean.compare(isConfigBLastSeen, isConfigALastSeen); - } - } - }; - - /** - * List of external dependencies for WifiConfigManager. - */ - private final Context mContext; - private final Clock mClock; - private final UserManager mUserManager; - private final BackupManagerProxy mBackupManagerProxy; - private final WifiKeyStore mWifiKeyStore; - private final WifiConfigStore mWifiConfigStore; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final WifiPermissionsWrapper mWifiPermissionsWrapper; - private final WifiInjector mWifiInjector; - private final MacAddressUtil mMacAddressUtil; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - private final WifiScoreCard mWifiScoreCard; - // Keep order of network connection. - private final LruConnectionTracker mLruConnectionTracker; - - /** - * Local log used for debugging any WifiConfigManager issues. - */ - private final LocalLog mLocalLog; - /** - * Map of configured networks with network id as the key. - */ - private final ConfigurationMap mConfiguredNetworks; - /** - * Stores a map of NetworkId to ScanDetailCache. - */ - private final Map<Integer, ScanDetailCache> mScanDetailCaches; - /** - * Framework keeps a list of networks that where temporarily disabled by user, - * framework knows not to autoconnect again even if the app/scorer recommends it. - * Network will be based on FQDN for passpoint and SSID for non-passpoint. - * List will be deleted when Wifi turn off, device restart or network settings reset. - * Also when user manfully select to connect network will unblock that network. - */ - private final MissingCounterTimerLockList<String> mUserTemporarilyDisabledList; - - /** - * Framework keeps a mapping from configKey to the randomized MAC address so that - * when a user forgets a network and thne adds it back, the same randomized MAC address - * will get used. - */ - private final Map<String, String> mRandomizedMacAddressMapping; - - /** - * Store the network update listeners. - */ - private final List<OnNetworkUpdateListener> mListeners; - - private final FrameworkFacade mFrameworkFacade; - private final DeviceConfigFacade mDeviceConfigFacade; - - /** - * Verbose logging flag. Toggled by developer options. - */ - private boolean mVerboseLoggingEnabled = false; - /** - * Current logged in user ID. - */ - private int mCurrentUserId = UserHandle.SYSTEM.getIdentifier(); - /** - * Flag to indicate that the new user's store has not yet been read since user switch. - * Initialize this flag to |true| to trigger a read on the first user unlock after - * bootup. - */ - private boolean mPendingUnlockStoreRead = true; - /** - * Flag to indicate if we have performed a read from store at all. This is used to gate - * any user unlock/switch operations until we read the store (Will happen if wifi is disabled - * when user updates from N to O). - */ - private boolean mPendingStoreRead = true; - /** - * Flag to indicate if the user unlock was deferred until the store load occurs. - */ - private boolean mDeferredUserUnlockRead = false; - /** - * This is keeping track of the next network ID to be assigned. Any new networks will be - * assigned |mNextNetworkId| as network ID. - */ - private int mNextNetworkId = 0; - /** - * This is used to remember which network was selected successfully last by an app. This is set - * when an app invokes {@link #enableNetwork(int, boolean, int)} with |disableOthers| flag set. - * This is the only way for an app to request connection to a specific network using the - * {@link WifiManager} API's. - */ - private int mLastSelectedNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - private long mLastSelectedTimeStamp = - WifiConfiguration.NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; - - // Store data for network list and deleted ephemeral SSID list. Used for serializing - // parsing data to/from the config store. - private final NetworkListSharedStoreData mNetworkListSharedStoreData; - private final NetworkListUserStoreData mNetworkListUserStoreData; - private final RandomizedMacStoreData mRandomizedMacStoreData; - - /** - * Create new instance of WifiConfigManager. - */ - WifiConfigManager( - Context context, Clock clock, UserManager userManager, - WifiCarrierInfoManager wifiCarrierInfoManager, WifiKeyStore wifiKeyStore, - WifiConfigStore wifiConfigStore, - WifiPermissionsUtil wifiPermissionsUtil, - WifiPermissionsWrapper wifiPermissionsWrapper, - WifiInjector wifiInjector, - NetworkListSharedStoreData networkListSharedStoreData, - NetworkListUserStoreData networkListUserStoreData, - RandomizedMacStoreData randomizedMacStoreData, - FrameworkFacade frameworkFacade, Handler handler, - DeviceConfigFacade deviceConfigFacade, WifiScoreCard wifiScoreCard, - LruConnectionTracker lruConnectionTracker) { - mContext = context; - mClock = clock; - mUserManager = userManager; - mBackupManagerProxy = new BackupManagerProxy(); - mWifiCarrierInfoManager = wifiCarrierInfoManager; - mWifiKeyStore = wifiKeyStore; - mWifiConfigStore = wifiConfigStore; - mWifiPermissionsUtil = wifiPermissionsUtil; - mWifiPermissionsWrapper = wifiPermissionsWrapper; - mWifiInjector = wifiInjector; - mWifiScoreCard = wifiScoreCard; - - mConfiguredNetworks = new ConfigurationMap(userManager); - mScanDetailCaches = new HashMap<>(16, 0.75f); - mUserTemporarilyDisabledList = - new MissingCounterTimerLockList<>(SCAN_RESULT_MISSING_COUNT_THRESHOLD, mClock); - mRandomizedMacAddressMapping = new HashMap<>(); - mListeners = new ArrayList<>(); - - // Register store data for network list and deleted ephemeral SSIDs. - mNetworkListSharedStoreData = networkListSharedStoreData; - mNetworkListUserStoreData = networkListUserStoreData; - mRandomizedMacStoreData = randomizedMacStoreData; - mWifiConfigStore.registerStoreData(mNetworkListSharedStoreData); - mWifiConfigStore.registerStoreData(mNetworkListUserStoreData); - mWifiConfigStore.registerStoreData(mRandomizedMacStoreData); - - mFrameworkFacade = frameworkFacade; - mDeviceConfigFacade = deviceConfigFacade; - - mLocalLog = new LocalLog( - context.getSystemService(ActivityManager.class).isLowRamDevice() ? 128 : 256); - mMacAddressUtil = mWifiInjector.getMacAddressUtil(); - mLruConnectionTracker = lruConnectionTracker; - } - - /** - * Network Selection disable reason thresholds. These numbers are used to debounce network - * failures before we disable them. - * - * @param reason int reason code - * @return the disable threshold, or -1 if not found. - */ - @VisibleForTesting - public static int getNetworkSelectionDisableThreshold( - @NetworkSelectionDisableReason int reason) { - DisableReasonInfo info = DISABLE_REASON_INFOS.get(reason); - if (info == null) { - Log.e(TAG, "Unrecognized network disable reason code for disable threshold: " + reason); - return -1; - } else { - return info.mDisableThreshold; - } - } - - /** - * Network Selection disable timeout for each kind of error. After the timeout in milliseconds, - * enable the network again. - */ - @VisibleForTesting - public static int getNetworkSelectionDisableTimeoutMillis( - @NetworkSelectionDisableReason int reason) { - DisableReasonInfo info = DISABLE_REASON_INFOS.get(reason); - if (info == null) { - Log.e(TAG, "Unrecognized network disable reason code for disable timeout: " + reason); - return -1; - } else { - return info.mDisableTimeoutMillis; - } - } - - /** - * Determine if the framework should perform "aggressive" MAC randomization when connecting - * to the SSID or FQDN in the input WifiConfiguration. - * @param config - * @return - */ - public boolean shouldUseAggressiveRandomization(WifiConfiguration config) { - if (!isMacRandomizationSupported() - || config.macRandomizationSetting != WifiConfiguration.RANDOMIZATION_PERSISTENT) { - return false; - } - if (mFrameworkFacade.getIntegerSetting(mContext, - ENHANCED_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG, 0) == 1) { - return true; - } - if (config.getIpConfiguration().getIpAssignment() == IpConfiguration.IpAssignment.STATIC) { - return false; - } - if (config.isPasspoint()) { - return isNetworkOptInForAggressiveRandomization(config.FQDN); - } else { - return isNetworkOptInForAggressiveRandomization(config.SSID); - } - } - - private boolean isNetworkOptInForAggressiveRandomization(String ssidOrFqdn) { - Set<String> perDeviceSsidBlocklist = new ArraySet<>(mContext.getResources().getStringArray( - R.array.config_wifi_aggressive_randomization_ssid_blocklist)); - if (mDeviceConfigFacade.getAggressiveMacRandomizationSsidBlocklist().contains(ssidOrFqdn) - || perDeviceSsidBlocklist.contains(ssidOrFqdn)) { - return false; - } - Set<String> perDeviceSsidAllowlist = new ArraySet<>(mContext.getResources().getStringArray( - R.array.config_wifi_aggressive_randomization_ssid_allowlist)); - return mDeviceConfigFacade.getAggressiveMacRandomizationSsidAllowlist().contains(ssidOrFqdn) - || perDeviceSsidAllowlist.contains(ssidOrFqdn); - } - - @VisibleForTesting - protected int getRandomizedMacAddressMappingSize() { - return mRandomizedMacAddressMapping.size(); - } - - /** - * The persistent randomized MAC address is locally generated for each SSID and does not - * change until factory reset of the device. In the initial Q release the per-SSID randomized - * MAC is saved on the device, but in an update the storing of randomized MAC is removed. - * Instead, the randomized MAC is calculated directly from the SSID and a on device secret. - * For backward compatibility, this method first checks the device storage for saved - * randomized MAC. If it is not found or the saved MAC is invalid then it will calculate the - * randomized MAC directly. - * - * In the future as devices launched on Q no longer get supported, this method should get - * simplified to return the calculated MAC address directly. - * @param config the WifiConfiguration to obtain MAC address for. - * @return persistent MAC address for this WifiConfiguration - */ - private MacAddress getPersistentMacAddress(WifiConfiguration config) { - // mRandomizedMacAddressMapping had been the location to save randomized MAC addresses. - String persistentMacString = mRandomizedMacAddressMapping.get( - config.getKey()); - // Use the MAC address stored in the storage if it exists and is valid. Otherwise - // use the MAC address calculated from a hash function as the persistent MAC. - if (persistentMacString != null) { - try { - return MacAddress.fromString(persistentMacString); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Error creating randomized MAC address from stored value."); - mRandomizedMacAddressMapping.remove(config.getKey()); - } - } - MacAddress result = mMacAddressUtil.calculatePersistentMac(config.getKey(), - mMacAddressUtil.obtainMacRandHashFunction(Process.WIFI_UID)); - if (result == null) { - result = mMacAddressUtil.calculatePersistentMac(config.getKey(), - mMacAddressUtil.obtainMacRandHashFunction(Process.WIFI_UID)); - } - if (result == null) { - Log.wtf(TAG, "Failed to generate MAC address from KeyStore even after retrying. " - + "Using locally generated MAC address instead."); - result = config.getRandomizedMacAddress(); - if (DEFAULT_MAC_ADDRESS.equals(result)) { - result = MacAddressUtils.createRandomUnicastAddress(); - } - } - return result; - } - - /** - * Sets the randomized MAC expiration time based on the DHCP lease duration. - * This should be called every time DHCP lease information is obtained. - */ - public void updateRandomizedMacExpireTime(WifiConfiguration config, long dhcpLeaseSeconds) { - WifiConfiguration internalConfig = getInternalConfiguredNetwork(config.networkId); - if (internalConfig == null) { - return; - } - long expireDurationMs = (dhcpLeaseSeconds & 0xffffffffL) * 1000; - expireDurationMs = Math.max(AGGRESSIVE_MAC_REFRESH_MS_MIN, expireDurationMs); - expireDurationMs = Math.min(AGGRESSIVE_MAC_REFRESH_MS_MAX, expireDurationMs); - internalConfig.randomizedMacExpirationTimeMs = mClock.getWallClockMillis() - + expireDurationMs; - } - - /** - * Obtain the persistent MAC address by first reading from an internal database. If non exists - * then calculate the persistent MAC using HMAC-SHA256. - * Finally set the randomized MAC of the configuration to the randomized MAC obtained. - * @param config the WifiConfiguration to make the update - * @return the persistent MacAddress or null if the operation is unsuccessful - */ - private MacAddress setRandomizedMacToPersistentMac(WifiConfiguration config) { - MacAddress persistentMac = getPersistentMacAddress(config); - if (persistentMac == null || persistentMac.equals(config.getRandomizedMacAddress())) { - return persistentMac; - } - WifiConfiguration internalConfig = getInternalConfiguredNetwork(config.networkId); - internalConfig.setRandomizedMacAddress(persistentMac); - return persistentMac; - } - - /** - * This method is called before connecting to a network that has "aggressive randomization" - * enabled, and will re-randomize the MAC address if needed. - * @param config the WifiConfiguration to make the update - * @return the updated MacAddress - */ - private MacAddress updateRandomizedMacIfNeeded(WifiConfiguration config) { - boolean shouldUpdateMac = config.randomizedMacExpirationTimeMs - < mClock.getWallClockMillis(); - if (!shouldUpdateMac) { - return config.getRandomizedMacAddress(); - } - WifiConfiguration internalConfig = getInternalConfiguredNetwork(config.networkId); - internalConfig.setRandomizedMacAddress(MacAddressUtils.createRandomUnicastAddress()); - return internalConfig.getRandomizedMacAddress(); - } - - /** - * Returns the randomized MAC address that should be used for this WifiConfiguration. - * This API may return a randomized MAC different from the persistent randomized MAC if - * the WifiConfiguration is configured for aggressive MAC randomization. - * @param config - * @return MacAddress - */ - public MacAddress getRandomizedMacAndUpdateIfNeeded(WifiConfiguration config) { - MacAddress mac = shouldUseAggressiveRandomization(config) - ? updateRandomizedMacIfNeeded(config) - : setRandomizedMacToPersistentMac(config); - return mac; - } - - /** - * Enable/disable verbose logging in WifiConfigManager & its helper classes. - */ - public void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mVerboseLoggingEnabled = true; - } else { - mVerboseLoggingEnabled = false; - } - mWifiConfigStore.enableVerboseLogging(mVerboseLoggingEnabled); - mWifiKeyStore.enableVerboseLogging(mVerboseLoggingEnabled); - } - - /** - * Helper method to mask all passwords/keys from the provided WifiConfiguration object. This - * is needed when the network configurations are being requested via the public WifiManager - * API's. - * This currently masks the following elements: psk, wepKeys & enterprise config password. - */ - private void maskPasswordsInWifiConfiguration(WifiConfiguration configuration) { - if (!TextUtils.isEmpty(configuration.preSharedKey)) { - configuration.preSharedKey = PASSWORD_MASK; - } - if (configuration.wepKeys != null) { - for (int i = 0; i < configuration.wepKeys.length; i++) { - if (!TextUtils.isEmpty(configuration.wepKeys[i])) { - configuration.wepKeys[i] = PASSWORD_MASK; - } - } - } - if (configuration.enterpriseConfig != null && !TextUtils.isEmpty( - configuration.enterpriseConfig.getPassword())) { - configuration.enterpriseConfig.setPassword(PASSWORD_MASK); - } - } - - /** - * Helper method to mask randomized MAC address from the provided WifiConfiguration Object. - * This is needed when the network configurations are being requested via the public - * WifiManager API's. This method puts "02:00:00:00:00:00" as the MAC address. - * @param configuration WifiConfiguration to hide the MAC address - */ - private void maskRandomizedMacAddressInWifiConfiguration(WifiConfiguration configuration) { - configuration.setRandomizedMacAddress(DEFAULT_MAC_ADDRESS); - } - - /** - * Helper method to create a copy of the provided internal WifiConfiguration object to be - * passed to external modules. - * - * @param configuration provided WifiConfiguration object. - * @param maskPasswords Mask passwords or not. - * @param targetUid Target UID for MAC address reading: -1 = mask all, 0 = mask none, >0 = - * mask all but the targetUid (carrier app). - * @return Copy of the WifiConfiguration object. - */ - private WifiConfiguration createExternalWifiConfiguration( - WifiConfiguration configuration, boolean maskPasswords, int targetUid) { - WifiConfiguration network = new WifiConfiguration(configuration); - if (maskPasswords) { - maskPasswordsInWifiConfiguration(network); - } - if (targetUid != Process.WIFI_UID && targetUid != Process.SYSTEM_UID - && targetUid != configuration.creatorUid) { - maskRandomizedMacAddressInWifiConfiguration(network); - } - if (!isMacRandomizationSupported()) { - network.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - } - return network; - } - - /** - * Returns whether MAC randomization is supported on this device. - * @param config - * @return - */ - private boolean isMacRandomizationSupported() { - return mContext.getResources().getBoolean( - R.bool.config_wifi_connected_mac_randomization_supported); - } - - /** - * Fetch the list of currently configured networks maintained in WifiConfigManager. - * - * This retrieves a copy of the internal configurations maintained by WifiConfigManager and - * should be used for any public interfaces. - * - * @param savedOnly Retrieve only saved networks. - * @param maskPasswords Mask passwords or not. - * @param targetUid Target UID for MAC address reading: -1 (Invalid UID) = mask all, - * WIFI||SYSTEM = mask none, <other> = mask all but the targetUid (carrier - * app). - * @return List of WifiConfiguration objects representing the networks. - */ - private List<WifiConfiguration> getConfiguredNetworks( - boolean savedOnly, boolean maskPasswords, int targetUid) { - List<WifiConfiguration> networks = new ArrayList<>(); - for (WifiConfiguration config : getInternalConfiguredNetworks()) { - if (savedOnly && (config.ephemeral || config.isPasspoint())) { - continue; - } - networks.add(createExternalWifiConfiguration(config, maskPasswords, targetUid)); - } - return networks; - } - - /** - * Retrieves the list of all configured networks with passwords masked. - * - * @return List of WifiConfiguration objects representing the networks. - */ - public List<WifiConfiguration> getConfiguredNetworks() { - return getConfiguredNetworks(false, true, Process.WIFI_UID); - } - - /** - * Retrieves the list of all configured networks with the passwords in plaintext. - * - * WARNING: Don't use this to pass network configurations to external apps. Should only be - * sent to system apps/wifi stack, when there is a need for passwords in plaintext. - * TODO: Need to understand the current use case of this API. - * - * @return List of WifiConfiguration objects representing the networks. - */ - public List<WifiConfiguration> getConfiguredNetworksWithPasswords() { - return getConfiguredNetworks(false, false, Process.WIFI_UID); - } - - /** - * Retrieves the list of all configured networks with the passwords masked. - * - * @return List of WifiConfiguration objects representing the networks. - */ - public List<WifiConfiguration> getSavedNetworks(int targetUid) { - return getConfiguredNetworks(true, true, targetUid); - } - - /** - * Retrieves the configured network corresponding to the provided networkId with password - * masked. - * - * @param networkId networkId of the requested network. - * @return WifiConfiguration object if found, null otherwise. - */ - public WifiConfiguration getConfiguredNetwork(int networkId) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return null; - } - // Create a new configuration object with the passwords masked to send out to the external - // world. - return createExternalWifiConfiguration(config, true, Process.WIFI_UID); - } - - /** - * Retrieves the configured network corresponding to the provided config key with password - * masked. - * - * @param configKey configKey of the requested network. - * @return WifiConfiguration object if found, null otherwise. - */ - public WifiConfiguration getConfiguredNetwork(String configKey) { - WifiConfiguration config = getInternalConfiguredNetwork(configKey); - if (config == null) { - return null; - } - // Create a new configuration object with the passwords masked to send out to the external - // world. - return createExternalWifiConfiguration(config, true, Process.WIFI_UID); - } - - /** - * Retrieves the configured network corresponding to the provided networkId with password - * in plaintext. - * - * WARNING: Don't use this to pass network configurations to external apps. Should only be - * sent to system apps/wifi stack, when there is a need for passwords in plaintext. - * - * @param networkId networkId of the requested network. - * @return WifiConfiguration object if found, null otherwise. - */ - public WifiConfiguration getConfiguredNetworkWithPassword(int networkId) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return null; - } - // Create a new configuration object without the passwords masked to send out to the - // external world. - return createExternalWifiConfiguration(config, false, Process.WIFI_UID); - } - - /** - * Retrieves the configured network corresponding to the provided networkId - * without any masking. - * - * WARNING: Don't use this to pass network configurations except in the wifi stack, when - * there is a need for passwords and randomized MAC address. - * - * @param networkId networkId of the requested network. - * @return Copy of WifiConfiguration object if found, null otherwise. - */ - public WifiConfiguration getConfiguredNetworkWithoutMasking(int networkId) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return null; - } - return new WifiConfiguration(config); - } - - /** - * Helper method to retrieve all the internal WifiConfiguration objects corresponding to all - * the networks in our database. - */ - private Collection<WifiConfiguration> getInternalConfiguredNetworks() { - return mConfiguredNetworks.valuesForCurrentUser(); - } - - /** - * Helper method to retrieve the internal WifiConfiguration object corresponding to the - * provided configuration in our database. - * This first attempts to find the network using the provided network ID in configuration, - * else it attempts to find a matching configuration using the configKey. - */ - private WifiConfiguration getInternalConfiguredNetwork(WifiConfiguration config) { - WifiConfiguration internalConfig = mConfiguredNetworks.getForCurrentUser(config.networkId); - if (internalConfig != null) { - return internalConfig; - } - internalConfig = mConfiguredNetworks.getByConfigKeyForCurrentUser(config.getKey()); - if (internalConfig == null) { - Log.e(TAG, "Cannot find network with networkId " + config.networkId - + " or configKey " + config.getKey()); - } - return internalConfig; - } - - /** - * Helper method to retrieve the internal WifiConfiguration object corresponding to the - * provided network ID in our database. - */ - private WifiConfiguration getInternalConfiguredNetwork(int networkId) { - if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { - return null; - } - WifiConfiguration internalConfig = mConfiguredNetworks.getForCurrentUser(networkId); - if (internalConfig == null) { - Log.e(TAG, "Cannot find network with networkId " + networkId); - } - return internalConfig; - } - - /** - * Helper method to retrieve the internal WifiConfiguration object corresponding to the - * provided configKey in our database. - */ - private WifiConfiguration getInternalConfiguredNetwork(String configKey) { - WifiConfiguration internalConfig = - mConfiguredNetworks.getByConfigKeyForCurrentUser(configKey); - if (internalConfig == null) { - Log.e(TAG, "Cannot find network with configKey " + configKey); - } - return internalConfig; - } - - /** - * Method to send out the configured networks change broadcast when network configurations - * changed. - * - * In Android R we stopped sending out WifiConfiguration due to user privacy concerns. - * Thus, no matter how many networks changed, - * {@link WifiManager#EXTRA_MULTIPLE_NETWORKS_CHANGED} is always set to true, and - * {@link WifiManager#EXTRA_WIFI_CONFIGURATION} is always null. - * - * @param reason The reason for the change, should be one of WifiManager.CHANGE_REASON_ADDED, - * WifiManager.CHANGE_REASON_REMOVED, or WifiManager.CHANGE_REASON_CHANGE. - */ - private void sendConfiguredNetworkChangedBroadcast(int reason) { - Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true); - intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, Manifest.permission.ACCESS_WIFI_STATE); - } - - /** - * Checks if |uid| has permission to modify the provided configuration. - * - * @param config WifiConfiguration object corresponding to the network to be modified. - * @param uid UID of the app requesting the modification. - * @param packageName Package name of the app requesting the modification. - */ - private boolean canModifyNetwork(WifiConfiguration config, int uid, - @Nullable String packageName) { - // System internals can always update networks; they're typically only - // making meteredHint or meteredOverride changes - if (uid == Process.SYSTEM_UID) { - return true; - } - - // Passpoint configurations are generated and managed by PasspointManager. They can be - // added by either PasspointNetworkNominator (for auto connection) or Settings app - // (for manual connection), and need to be removed once the connection is completed. - // Since it is "owned" by us, so always allow us to modify them. - if (config.isPasspoint() && uid == Process.WIFI_UID) { - return true; - } - - // EAP-SIM/AKA/AKA' network needs framework to update the anonymous identity provided - // by authenticator back to the WifiConfiguration object. - // Since it is "owned" by us, so always allow us to modify them. - if (config.enterpriseConfig != null - && uid == Process.WIFI_UID - && config.enterpriseConfig.isAuthenticationSimBased()) { - return true; - } - - final boolean isDeviceOwner = mWifiPermissionsUtil.isDeviceOwner(uid, packageName); - - // If |uid| corresponds to the device owner, allow all modifications. - if (isDeviceOwner) { - return true; - } - - final boolean isCreator = (config.creatorUid == uid); - - // WiFi config lockdown related logic. At this point we know uid is NOT a Device Owner. - final boolean isConfigEligibleForLockdown = - mWifiPermissionsUtil.isDeviceOwner(config.creatorUid, config.creatorName); - if (!isConfigEligibleForLockdown) { - // App that created the network or settings app (i.e user) has permission to - // modify the network. - return isCreator || mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); - } - - final ContentResolver resolver = mContext.getContentResolver(); - final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver, - Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0; - return !isLockdownFeatureEnabled - // If not locked down, settings app (i.e user) has permission to modify the network. - && mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); - } - - /** - * Copy over public elements from an external WifiConfiguration object to the internal - * configuration object if element has been set in the provided external WifiConfiguration. - * The only exception is the hidden |IpConfiguration| parameters, these need to be copied over - * for every update. - * - * This method updates all elements that are common to both network addition & update. - * The following fields of {@link WifiConfiguration} are not copied from external configs: - * > networkId - These are allocated by Wi-Fi stack internally for any new configurations. - * > status - The status needs to be explicitly updated using - * {@link WifiManager#enableNetwork(int, boolean)} or - * {@link WifiManager#disableNetwork(int)}. - * - * @param internalConfig WifiConfiguration object in our internal map. - * @param externalConfig WifiConfiguration object provided from the external API. - */ - private void mergeWithInternalWifiConfiguration( - WifiConfiguration internalConfig, WifiConfiguration externalConfig) { - if (externalConfig.SSID != null) { - internalConfig.SSID = externalConfig.SSID; - } - if (externalConfig.BSSID != null) { - internalConfig.BSSID = externalConfig.BSSID.toLowerCase(); - } - internalConfig.hiddenSSID = externalConfig.hiddenSSID; - internalConfig.requirePmf = externalConfig.requirePmf; - - if (externalConfig.preSharedKey != null - && !externalConfig.preSharedKey.equals(PASSWORD_MASK)) { - internalConfig.preSharedKey = externalConfig.preSharedKey; - } - // Modify only wep keys are present in the provided configuration. This is a little tricky - // because there is no easy way to tell if the app is actually trying to null out the - // existing keys or not. - if (externalConfig.wepKeys != null) { - boolean hasWepKey = false; - for (int i = 0; i < internalConfig.wepKeys.length; i++) { - if (externalConfig.wepKeys[i] != null - && !externalConfig.wepKeys[i].equals(PASSWORD_MASK)) { - internalConfig.wepKeys[i] = externalConfig.wepKeys[i]; - hasWepKey = true; - } - } - if (hasWepKey) { - internalConfig.wepTxKeyIndex = externalConfig.wepTxKeyIndex; - } - } - if (externalConfig.FQDN != null) { - internalConfig.FQDN = externalConfig.FQDN; - } - if (externalConfig.providerFriendlyName != null) { - internalConfig.providerFriendlyName = externalConfig.providerFriendlyName; - } - if (externalConfig.roamingConsortiumIds != null) { - internalConfig.roamingConsortiumIds = externalConfig.roamingConsortiumIds.clone(); - } - - // Copy over all the auth/protocol/key mgmt parameters if set. - if (externalConfig.allowedAuthAlgorithms != null - && !externalConfig.allowedAuthAlgorithms.isEmpty()) { - internalConfig.allowedAuthAlgorithms = - (BitSet) externalConfig.allowedAuthAlgorithms.clone(); - } - if (externalConfig.allowedProtocols != null - && !externalConfig.allowedProtocols.isEmpty()) { - internalConfig.allowedProtocols = (BitSet) externalConfig.allowedProtocols.clone(); - } - if (externalConfig.allowedKeyManagement != null - && !externalConfig.allowedKeyManagement.isEmpty()) { - internalConfig.allowedKeyManagement = - (BitSet) externalConfig.allowedKeyManagement.clone(); - } - if (externalConfig.allowedPairwiseCiphers != null - && !externalConfig.allowedPairwiseCiphers.isEmpty()) { - internalConfig.allowedPairwiseCiphers = - (BitSet) externalConfig.allowedPairwiseCiphers.clone(); - } - if (externalConfig.allowedGroupCiphers != null - && !externalConfig.allowedGroupCiphers.isEmpty()) { - internalConfig.allowedGroupCiphers = - (BitSet) externalConfig.allowedGroupCiphers.clone(); - } - if (externalConfig.allowedGroupManagementCiphers != null - && !externalConfig.allowedGroupManagementCiphers.isEmpty()) { - internalConfig.allowedGroupManagementCiphers = - (BitSet) externalConfig.allowedGroupManagementCiphers.clone(); - } - // allowedSuiteBCiphers is set internally according to the certificate type - - // Copy over the |IpConfiguration| parameters if set. - if (externalConfig.getIpConfiguration() != null) { - IpConfiguration.IpAssignment ipAssignment = externalConfig.getIpAssignment(); - if (ipAssignment != IpConfiguration.IpAssignment.UNASSIGNED) { - internalConfig.setIpAssignment(ipAssignment); - if (ipAssignment == IpConfiguration.IpAssignment.STATIC) { - internalConfig.setStaticIpConfiguration( - new StaticIpConfiguration(externalConfig.getStaticIpConfiguration())); - } - } - IpConfiguration.ProxySettings proxySettings = externalConfig.getProxySettings(); - if (proxySettings != IpConfiguration.ProxySettings.UNASSIGNED) { - internalConfig.setProxySettings(proxySettings); - if (proxySettings == IpConfiguration.ProxySettings.PAC - || proxySettings == IpConfiguration.ProxySettings.STATIC) { - internalConfig.setHttpProxy(new ProxyInfo(externalConfig.getHttpProxy())); - } - } - } - - // Copy over the |WifiEnterpriseConfig| parameters if set. - if (externalConfig.enterpriseConfig != null) { - internalConfig.enterpriseConfig.copyFromExternal( - externalConfig.enterpriseConfig, PASSWORD_MASK); - } - - // Copy over any metered information. - internalConfig.meteredHint = externalConfig.meteredHint; - internalConfig.meteredOverride = externalConfig.meteredOverride; - - // Copy trusted bit - internalConfig.trusted = externalConfig.trusted; - - // Copy over macRandomizationSetting - internalConfig.macRandomizationSetting = externalConfig.macRandomizationSetting; - internalConfig.carrierId = externalConfig.carrierId; - internalConfig.isHomeProviderNetwork = externalConfig.isHomeProviderNetwork; - } - - /** - * Set all the exposed defaults in the newly created WifiConfiguration object. - * These fields have a default value advertised in our public documentation. The only exception - * is the hidden |IpConfiguration| parameters, these have a default value even though they're - * hidden. - * - * @param configuration provided WifiConfiguration object. - */ - private void setDefaultsInWifiConfiguration(WifiConfiguration configuration) { - configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); - configuration.allowedProtocols.set(WifiConfiguration.Protocol.WPA); - - configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - - configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); - - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); - - configuration.allowedGroupManagementCiphers - .set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); - - configuration.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - configuration.setProxySettings(IpConfiguration.ProxySettings.NONE); - - configuration.status = WifiConfiguration.Status.DISABLED; - configuration.getNetworkSelectionStatus().setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); - configuration.getNetworkSelectionStatus().setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER); - } - - /** - * Create a new internal WifiConfiguration object by copying over parameters from the provided - * external configuration and set defaults for the appropriate parameters. - * - * @param externalConfig WifiConfiguration object provided from the external API. - * @return New WifiConfiguration object with parameters merged from the provided external - * configuration. - */ - private WifiConfiguration createNewInternalWifiConfigurationFromExternal( - WifiConfiguration externalConfig, int uid, @Nullable String packageName) { - WifiConfiguration newInternalConfig = new WifiConfiguration(); - - // First allocate a new network ID for the configuration. - newInternalConfig.networkId = mNextNetworkId++; - - // First set defaults in the new configuration created. - setDefaultsInWifiConfiguration(newInternalConfig); - - // Copy over all the public elements from the provided configuration. - mergeWithInternalWifiConfiguration(newInternalConfig, externalConfig); - - // Copy over the hidden configuration parameters. These are the only parameters used by - // system apps to indicate some property about the network being added. - // These are only copied over for network additions and ignored for network updates. - newInternalConfig.requirePmf = externalConfig.requirePmf; - newInternalConfig.noInternetAccessExpected = externalConfig.noInternetAccessExpected; - newInternalConfig.ephemeral = externalConfig.ephemeral; - newInternalConfig.osu = externalConfig.osu; - newInternalConfig.fromWifiNetworkSuggestion = externalConfig.fromWifiNetworkSuggestion; - newInternalConfig.fromWifiNetworkSpecifier = externalConfig.fromWifiNetworkSpecifier; - newInternalConfig.useExternalScores = externalConfig.useExternalScores; - newInternalConfig.shared = externalConfig.shared; - newInternalConfig.updateIdentifier = externalConfig.updateIdentifier; - newInternalConfig.setPasspointUniqueId(externalConfig.getPasspointUniqueId()); - - // Add debug information for network addition. - newInternalConfig.creatorUid = newInternalConfig.lastUpdateUid = uid; - newInternalConfig.creatorName = newInternalConfig.lastUpdateName = - packageName != null ? packageName : mContext.getPackageManager().getNameForUid(uid); - initRandomizedMacForInternalConfig(newInternalConfig); - return newInternalConfig; - } - - /** - * Create a new internal WifiConfiguration object by copying over parameters from the provided - * external configuration to a copy of the existing internal WifiConfiguration object. - * - * @param internalConfig WifiConfiguration object in our internal map. - * @param externalConfig WifiConfiguration object provided from the external API. - * @return Copy of existing WifiConfiguration object with parameters merged from the provided - * configuration. - */ - private WifiConfiguration updateExistingInternalWifiConfigurationFromExternal( - WifiConfiguration internalConfig, WifiConfiguration externalConfig, int uid, - @Nullable String packageName) { - WifiConfiguration newInternalConfig = new WifiConfiguration(internalConfig); - - // Copy over all the public elements from the provided configuration. - mergeWithInternalWifiConfiguration(newInternalConfig, externalConfig); - - // Add debug information for network update. - newInternalConfig.lastUpdateUid = uid; - newInternalConfig.lastUpdateName = - packageName != null ? packageName : mContext.getPackageManager().getNameForUid(uid); - - return newInternalConfig; - } - - private void logUserActionEvents(WifiConfiguration before, WifiConfiguration after) { - // Logs changes in meteredOverride. - if (before.meteredOverride != after.meteredOverride) { - mWifiInjector.getWifiMetrics().logUserActionEvent( - WifiMetrics.convertMeteredOverrideEnumToUserActionEventType( - after.meteredOverride), - after.networkId); - } - - // Logs changes in macRandomizationSetting. - if (before.macRandomizationSetting != after.macRandomizationSetting) { - mWifiInjector.getWifiMetrics().logUserActionEvent( - after.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_NONE - ? UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF - : UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_ON, - after.networkId); - } - } - - /** - * Add a network or update a network configuration to our database. - * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty - * network configuration. Otherwise, the networkId should refer to an existing configuration. - * - * @param config provided WifiConfiguration object. - * @param uid UID of the app requesting the network addition/modification. - * @param packageName Package name of the app requesting the network addition/modification. - * @return NetworkUpdateResult object representing status of the update. - */ - private NetworkUpdateResult addOrUpdateNetworkInternal(WifiConfiguration config, int uid, - @Nullable String packageName) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Adding/Updating network " + config.getPrintableSsid()); - } - WifiConfiguration newInternalConfig = null; - - // First check if we already have a network with the provided network id or configKey. - WifiConfiguration existingInternalConfig = getInternalConfiguredNetwork(config); - // No existing network found. So, potentially a network add. - if (existingInternalConfig == null) { - if (!WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)) { - Log.e(TAG, "Cannot add network with invalid config"); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - newInternalConfig = - createNewInternalWifiConfigurationFromExternal(config, uid, packageName); - // Since the original config provided may have had an empty - // {@link WifiConfiguration#allowedKeyMgmt} field, check again if we already have a - // network with the the same configkey. - existingInternalConfig = getInternalConfiguredNetwork(newInternalConfig.getKey()); - } - // Existing network found. So, a network update. - if (existingInternalConfig != null) { - if (!WifiConfigurationUtil.validate( - config, WifiConfigurationUtil.VALIDATE_FOR_UPDATE)) { - Log.e(TAG, "Cannot update network with invalid config"); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - // Check for the app's permission before we let it update this network. - if (!canModifyNetwork(existingInternalConfig, uid, packageName)) { - Log.e(TAG, "UID " + uid + " does not have permission to update configuration " - + config.getKey()); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) - && !config.isPasspoint()) { - logUserActionEvents(existingInternalConfig, config); - } - newInternalConfig = - updateExistingInternalWifiConfigurationFromExternal( - existingInternalConfig, config, uid, packageName); - } - - // Only add networks with proxy settings if the user has permission to - if (WifiConfigurationUtil.hasProxyChanged(existingInternalConfig, newInternalConfig) - && !canModifyProxySettings(uid, packageName)) { - Log.e(TAG, "UID " + uid + " does not have permission to modify proxy Settings " - + config.getKey() + ". Must have NETWORK_SETTINGS," - + " or be device or profile owner."); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - - if (WifiConfigurationUtil.hasMacRandomizationSettingsChanged(existingInternalConfig, - newInternalConfig) && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) - && !mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid) - && !(newInternalConfig.isPasspoint() && uid == newInternalConfig.creatorUid)) { - Log.e(TAG, "UID " + uid + " does not have permission to modify MAC randomization " - + "Settings " + config.getKey() + ". Must have " - + "NETWORK_SETTINGS or NETWORK_SETUP_WIZARD or be the creator adding or " - + "updating a passpoint network."); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - - // Update the keys for saved enterprise networks. For Passpoint, the certificates - // and keys are installed at the time the provider is installed. For suggestion enterprise - // network the certificates and keys are installed at the time the suggestion is added - if (!config.isPasspoint() && !config.fromWifiNetworkSuggestion && config.isEnterprise()) { - if (!(mWifiKeyStore.updateNetworkKeys(newInternalConfig, existingInternalConfig))) { - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - } - - boolean newNetwork = (existingInternalConfig == null); - // This is needed to inform IpClient about any IP configuration changes. - boolean hasIpChanged = - newNetwork || WifiConfigurationUtil.hasIpChanged( - existingInternalConfig, newInternalConfig); - boolean hasProxyChanged = - newNetwork || WifiConfigurationUtil.hasProxyChanged( - existingInternalConfig, newInternalConfig); - // Reset the |hasEverConnected| flag if the credential parameters changed in this update. - boolean hasCredentialChanged = - newNetwork || WifiConfigurationUtil.hasCredentialChanged( - existingInternalConfig, newInternalConfig); - if (hasCredentialChanged) { - newInternalConfig.getNetworkSelectionStatus().setHasEverConnected(false); - } - - // Add it to our internal map. This will replace any existing network configuration for - // updates. - try { - mConfiguredNetworks.put(newInternalConfig); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Failed to add network to config map", e); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - // Only re-enable network: 1. add or update user saved network; 2. add or update a user - // saved passpoint network framework consider it is a new network. - if (!newInternalConfig.fromWifiNetworkSuggestion - && (!newInternalConfig.isPasspoint() || newNetwork)) { - userEnabledNetwork(newInternalConfig.networkId); - } - - // Stage the backup of the SettingsProvider package which backs this up. - mBackupManagerProxy.notifyDataChanged(); - - NetworkUpdateResult result = - new NetworkUpdateResult(hasIpChanged, hasProxyChanged, hasCredentialChanged); - result.setIsNewNetwork(newNetwork); - result.setNetworkId(newInternalConfig.networkId); - - localLog("addOrUpdateNetworkInternal: added/updated config." - + " netId=" + newInternalConfig.networkId - + " configKey=" + newInternalConfig.getKey() - + " uid=" + Integer.toString(newInternalConfig.creatorUid) - + " name=" + newInternalConfig.creatorName); - return result; - } - - /** - * Add a network or update a network configuration to our database. - * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty - * network configuration. Otherwise, the networkId should refer to an existing configuration. - * - * @param config provided WifiConfiguration object. - * @param uid UID of the app requesting the network addition/modification. - * @param packageName Package name of the app requesting the network addition/modification. - * @return NetworkUpdateResult object representing status of the update. - */ - public NetworkUpdateResult addOrUpdateNetwork(WifiConfiguration config, int uid, - @Nullable String packageName) { - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - if (config == null) { - Log.e(TAG, "Cannot add/update network with null config"); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - if (mPendingStoreRead) { - Log.e(TAG, "Cannot add/update network before store is read!"); - return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); - } - WifiConfiguration existingConfig = getInternalConfiguredNetwork(config); - if (!config.isEphemeral()) { - // Removes the existing ephemeral network if it exists to add this configuration. - if (existingConfig != null && existingConfig.isEphemeral()) { - // In this case, new connection for this config won't happen because same - // network is already registered as an ephemeral network. - // Clear the Ephemeral Network to address the situation. - removeNetwork( - existingConfig.networkId, existingConfig.creatorUid, config.creatorName); - } - } - - NetworkUpdateResult result = addOrUpdateNetworkInternal(config, uid, packageName); - if (!result.isSuccess()) { - Log.e(TAG, "Failed to add/update network " + config.getPrintableSsid()); - return result; - } - WifiConfiguration newConfig = getInternalConfiguredNetwork(result.getNetworkId()); - sendConfiguredNetworkChangedBroadcast( - result.isNewNetwork() - ? WifiManager.CHANGE_REASON_ADDED - : WifiManager.CHANGE_REASON_CONFIG_CHANGE); - // Unless the added network is ephemeral or Passpoint, persist the network update/addition. - if (!config.ephemeral && !config.isPasspoint()) { - saveToStore(true); - } - - for (OnNetworkUpdateListener listener : mListeners) { - if (result.isNewNetwork()) { - listener.onNetworkAdded( - createExternalWifiConfiguration(newConfig, true, Process.WIFI_UID)); - } else { - listener.onNetworkUpdated( - createExternalWifiConfiguration(newConfig, true, Process.WIFI_UID), - createExternalWifiConfiguration(existingConfig, true, Process.WIFI_UID)); - } - } - return result; - } - - /** - * Add a network or update a network configuration to our database. - * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty - * network configuration. Otherwise, the networkId should refer to an existing configuration. - * - * @param config provided WifiConfiguration object. - * @param uid UID of the app requesting the network addition/modification. - * @return NetworkUpdateResult object representing status of the update. - */ - public NetworkUpdateResult addOrUpdateNetwork(WifiConfiguration config, int uid) { - return addOrUpdateNetwork(config, uid, null); - } - - /** - * Removes the specified network configuration from our database. - * - * @param config provided WifiConfiguration object. - * @param uid UID of the app requesting the network deletion. - * @return true if successful, false otherwise. - */ - private boolean removeNetworkInternal(WifiConfiguration config, int uid) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Removing network " + config.getPrintableSsid()); - } - // Remove any associated enterprise keys for saved enterprise networks. Passpoint network - // will remove the enterprise keys when provider is uninstalled. Suggestion enterprise - // networks will remove the enterprise keys when suggestion is removed. - if (!config.fromWifiNetworkSuggestion && !config.isPasspoint() && config.isEnterprise()) { - mWifiKeyStore.removeKeys(config.enterpriseConfig); - } - - removeConnectChoiceFromAllNetworks(config.getKey()); - mConfiguredNetworks.remove(config.networkId); - mScanDetailCaches.remove(config.networkId); - // Stage the backup of the SettingsProvider package which backs this up. - mBackupManagerProxy.notifyDataChanged(); - mWifiInjector.getBssidBlocklistMonitor().handleNetworkRemoved(config.SSID); - - localLog("removeNetworkInternal: removed config." - + " netId=" + config.networkId - + " configKey=" + config.getKey() - + " uid=" + Integer.toString(uid) - + " name=" + mContext.getPackageManager().getNameForUid(uid)); - return true; - } - - /** - * Removes the specified network configuration from our database. - * - * @param networkId network ID of the provided network. - * @param uid UID of the app requesting the network deletion. - * @return true if successful, false otherwise. - */ - public boolean removeNetwork(int networkId, int uid, String packageName) { - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return false; - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - if (!canModifyNetwork(config, uid, packageName)) { - Log.e(TAG, "UID " + uid + " does not have permission to delete configuration " - + config.getKey()); - return false; - } - if (!removeNetworkInternal(config, uid)) { - Log.e(TAG, "Failed to remove network " + config.getPrintableSsid()); - return false; - } - if (networkId == mLastSelectedNetworkId) { - clearLastSelectedNetwork(); - } - if (!config.ephemeral && !config.isPasspoint()) { - mLruConnectionTracker.removeNetwork(config); - } - sendConfiguredNetworkChangedBroadcast(WifiManager.CHANGE_REASON_REMOVED); - // Unless the removed network is ephemeral or Passpoint, persist the network removal. - if (!config.ephemeral && !config.isPasspoint()) { - saveToStore(true); - } - for (OnNetworkUpdateListener listener : mListeners) { - listener.onNetworkRemoved( - createExternalWifiConfiguration(config, true, Process.WIFI_UID)); - } - return true; - } - - private String getCreatorPackageName(WifiConfiguration config) { - String creatorName = config.creatorName; - // getNameForUid (Stored in WifiConfiguration.creatorName) returns a concatenation of name - // and uid for shared UIDs ("name:uid"). - if (!creatorName.contains(":")) { - return creatorName; // regular app not using shared UID. - } - // Separate the package name from the string for app using shared UID. - return creatorName.substring(0, creatorName.indexOf(":")); - } - - /** - * Remove all networks associated with an application. - * - * @param app Application info of the package of networks to remove. - * @return the {@link Set} of networks that were removed by this call. Networks which matched - * but failed to remove are omitted from this set. - */ - public Set<Integer> removeNetworksForApp(ApplicationInfo app) { - if (app == null || app.packageName == null) { - return Collections.<Integer>emptySet(); - } - Log.d(TAG, "Remove all networks for app " + app); - Set<Integer> removedNetworks = new ArraySet<>(); - WifiConfiguration[] copiedConfigs = - mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]); - for (WifiConfiguration config : copiedConfigs) { - if (app.uid != config.creatorUid - || !app.packageName.equals(getCreatorPackageName(config))) { - continue; - } - localLog("Removing network " + config.SSID - + ", application \"" + app.packageName + "\" uninstalled" - + " from user " + UserHandle.getUserHandleForUid(app.uid)); - if (removeNetwork(config.networkId, config.creatorUid, config.creatorName)) { - removedNetworks.add(config.networkId); - } - } - return removedNetworks; - } - - /** - * Remove all networks associated with a user. - * - * @param userId The identifier of the user which is being removed. - * @return the {@link Set} of networks that were removed by this call. Networks which matched - * but failed to remove are omitted from this set. - */ - Set<Integer> removeNetworksForUser(int userId) { - Log.d(TAG, "Remove all networks for user " + userId); - Set<Integer> removedNetworks = new ArraySet<>(); - WifiConfiguration[] copiedConfigs = - mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]); - for (WifiConfiguration config : copiedConfigs) { - if (userId != UserHandle.getUserHandleForUid(config.creatorUid).getIdentifier()) { - continue; - } - localLog("Removing network " + config.SSID + ", user " + userId + " removed"); - if (removeNetwork(config.networkId, config.creatorUid, config.creatorName)) { - removedNetworks.add(config.networkId); - } - } - return removedNetworks; - } - - /** - * Iterates through the internal list of configured networks and removes any ephemeral or - * passpoint network configurations which are transient in nature. - * - * @return true if a network was removed, false otherwise. - */ - public boolean removeAllEphemeralOrPasspointConfiguredNetworks() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Removing all passpoint or ephemeral configured networks"); - } - boolean didRemove = false; - WifiConfiguration[] copiedConfigs = - mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]); - for (WifiConfiguration config : copiedConfigs) { - if (config.isPasspoint()) { - Log.d(TAG, "Removing passpoint network config " + config.getKey()); - removeNetwork(config.networkId, config.creatorUid, config.creatorName); - didRemove = true; - } else if (config.ephemeral) { - Log.d(TAG, "Removing ephemeral network config " + config.getKey()); - removeNetwork(config.networkId, config.creatorUid, config.creatorName); - didRemove = true; - } - } - return didRemove; - } - - /** - * Removes the suggestion network configuration matched with {@code configKey} provided. - * - * @param configKey Config Key for the corresponding network suggestion. - * @return true if a network was removed, false otherwise. - */ - public boolean removeSuggestionConfiguredNetwork(@NonNull String configKey) { - WifiConfiguration config = getInternalConfiguredNetwork(configKey); - if (config != null && config.ephemeral && config.fromWifiNetworkSuggestion) { - Log.d(TAG, "Removing suggestion network config " + config.getKey()); - return removeNetwork(config.networkId, config.creatorUid, config.creatorName); - } - return false; - } - - /** - * Removes the passpoint network configuration matched with {@code configKey} provided. - * - * @param configKey Config Key for the corresponding passpoint. - * @return true if a network was removed, false otherwise. - */ - public boolean removePasspointConfiguredNetwork(@NonNull String configKey) { - WifiConfiguration config = getInternalConfiguredNetwork(configKey); - if (config != null && config.isPasspoint()) { - Log.d(TAG, "Removing passpoint network config " + config.getKey()); - return removeNetwork(config.networkId, config.creatorUid, config.creatorName); - } - return false; - } - - /** - * Check whether a network belong to a known list of networks that may not support randomized - * MAC. - * @param networkId - * @return true if the network is in the hotlist and MAC randomization is enabled. - */ - public boolean isInFlakyRandomizationSsidHotlist(int networkId) { - WifiConfiguration config = getConfiguredNetwork(networkId); - return config != null - && config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT - && mDeviceConfigFacade.getRandomizationFlakySsidHotlist().contains(config.SSID); - } - - /** - * Helper method to mark a network enabled for network selection. - */ - private void setNetworkSelectionEnabled(WifiConfiguration config) { - NetworkSelectionStatus status = config.getNetworkSelectionStatus(); - if (status.getNetworkSelectionStatus() - != NetworkSelectionStatus.NETWORK_SELECTION_ENABLED) { - localLog("setNetworkSelectionEnabled: configKey=" + config.getKey() - + " old networkStatus=" + status.getNetworkStatusString() - + " disableReason=" + status.getNetworkSelectionDisableReasonString()); - } - status.setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); - status.setDisableTime( - NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); - status.setNetworkSelectionDisableReason(NetworkSelectionStatus.DISABLED_NONE); - - // Clear out all the disable reason counters. - status.clearDisableReasonCounter(); - for (OnNetworkUpdateListener listener : mListeners) { - listener.onNetworkEnabled( - createExternalWifiConfiguration(config, true, Process.WIFI_UID)); - } - } - - /** - * Helper method to mark a network temporarily disabled for network selection. - */ - private void setNetworkSelectionTemporarilyDisabled( - WifiConfiguration config, int disableReason) { - NetworkSelectionStatus status = config.getNetworkSelectionStatus(); - status.setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - // Only need a valid time filled in for temporarily disabled networks. - status.setDisableTime(mClock.getElapsedSinceBootMillis()); - status.setNetworkSelectionDisableReason(disableReason); - for (OnNetworkUpdateListener listener : mListeners) { - listener.onNetworkTemporarilyDisabled( - createExternalWifiConfiguration(config, true, Process.WIFI_UID), disableReason); - } - } - - /** - * Helper method to mark a network permanently disabled for network selection. - */ - private void setNetworkSelectionPermanentlyDisabled( - WifiConfiguration config, int disableReason) { - NetworkSelectionStatus status = config.getNetworkSelectionStatus(); - status.setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); - status.setDisableTime( - NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); - status.setNetworkSelectionDisableReason(disableReason); - for (OnNetworkUpdateListener listener : mListeners) { - WifiConfiguration configForListener = new WifiConfiguration(config); - listener.onNetworkPermanentlyDisabled( - createExternalWifiConfiguration(config, true, Process.WIFI_UID), disableReason); - } - } - - /** - * Helper method to set the publicly exposed status for the network and send out the network - * status change broadcast. - */ - private void setNetworkStatus(WifiConfiguration config, int status) { - config.status = status; - sendConfiguredNetworkChangedBroadcast(WifiManager.CHANGE_REASON_CONFIG_CHANGE); - } - - /** - * Sets a network's status (both internal and public) according to the update reason and - * its current state. - * - * This updates the network's {@link WifiConfiguration#mNetworkSelectionStatus} field and the - * public {@link WifiConfiguration#status} field if the network is either enabled or - * permanently disabled. - * - * @param config network to be updated. - * @param reason reason code for update. - * @return true if the input configuration has been updated, false otherwise. - */ - private boolean setNetworkSelectionStatus(WifiConfiguration config, int reason) { - NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus(); - if (reason < 0 || reason >= NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX) { - Log.e(TAG, "Invalid Network disable reason " + reason); - return false; - } - if (reason == NetworkSelectionStatus.DISABLED_NONE) { - setNetworkSelectionEnabled(config); - setNetworkStatus(config, WifiConfiguration.Status.ENABLED); - } else if (reason < NetworkSelectionStatus.PERMANENTLY_DISABLED_STARTING_INDEX) { - setNetworkSelectionTemporarilyDisabled(config, reason); - } else { - setNetworkSelectionPermanentlyDisabled(config, reason); - setNetworkStatus(config, WifiConfiguration.Status.DISABLED); - } - localLog("setNetworkSelectionStatus: configKey=" + config.getKey() - + " networkStatus=" + networkStatus.getNetworkStatusString() + " disableReason=" - + networkStatus.getNetworkSelectionDisableReasonString()); - saveToStore(false); - return true; - } - - /** - * Update a network's status (both internal and public) according to the update reason and - * its current state. - * - * @param config network to be updated. - * @param reason reason code for update. - * @return true if the input configuration has been updated, false otherwise. - */ - private boolean updateNetworkSelectionStatus(WifiConfiguration config, int reason) { - NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus(); - if (reason != NetworkSelectionStatus.DISABLED_NONE) { - - // Do not update SSID blacklist with information if this is the only - // SSID be observed. By ignoring it we will cause additional failures - // which will trigger Watchdog. - if (reason == NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION - || reason == NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE - || reason == NetworkSelectionStatus.DISABLED_DHCP_FAILURE) { - if (mWifiInjector.getWifiLastResortWatchdog().shouldIgnoreSsidUpdate()) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Ignore update network selection status " - + "since Watchdog trigger is activated"); - } - return false; - } - } - - networkStatus.incrementDisableReasonCounter(reason); - // For network disable reasons, we should only update the status if we cross the - // threshold. - int disableReasonCounter = networkStatus.getDisableReasonCounter(reason); - int disableReasonThreshold = getNetworkSelectionDisableThreshold(reason); - if (disableReasonCounter < disableReasonThreshold) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Disable counter for network " + config.getPrintableSsid() - + " for reason " - + NetworkSelectionStatus.getNetworkSelectionDisableReasonString(reason) - + " is " + networkStatus.getDisableReasonCounter(reason) - + " and threshold is " + disableReasonThreshold); - } - return true; - } - } - return setNetworkSelectionStatus(config, reason); - } - - /** - * Update a network's status (both internal and public) according to the update reason and - * its current state. - * - * Each network has 2 status: - * 1. NetworkSelectionStatus: This is internal selection status of the network. This is used - * for temporarily disabling a network for Network Selector. - * 2. Status: This is the exposed status for a network. This is mostly set by - * the public API's {@link WifiManager#enableNetwork(int, boolean)} & - * {@link WifiManager#disableNetwork(int)}. - * - * @param networkId network ID of the network that needs the update. - * @param reason reason to update the network. - * @return true if the input configuration has been updated, false otherwise. - */ - public boolean updateNetworkSelectionStatus(int networkId, int reason) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - return updateNetworkSelectionStatus(config, reason); - } - - /** - * Attempt to re-enable a network for network selection, if this network was either: - * a) Previously temporarily disabled, but its disable timeout has expired, or - * b) Previously disabled because of a user switch, but is now visible to the current - * user. - * - * @param config configuration for the network to be re-enabled for network selection. The - * network corresponding to the config must be visible to the current user. - * @return true if the network identified by {@param config} was re-enabled for qualified - * network selection, false otherwise. - */ - private boolean tryEnableNetwork(WifiConfiguration config) { - NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus(); - if (networkStatus.isNetworkTemporaryDisabled()) { - long timeDifferenceMs = - mClock.getElapsedSinceBootMillis() - networkStatus.getDisableTime(); - int disableReason = networkStatus.getNetworkSelectionDisableReason(); - int blockedBssids = Math.min(MAX_BLOCKED_BSSID_PER_NETWORK, - mWifiInjector.getBssidBlocklistMonitor() - .updateAndGetNumBlockedBssidsForSsid(config.SSID)); - // if no BSSIDs are blocked then we should keep trying to connect to something - long disableTimeoutMs = 0; - if (blockedBssids > 0) { - double multiplier = Math.pow(2.0, blockedBssids - 1.0); - disableTimeoutMs = (long) (getNetworkSelectionDisableTimeoutMillis(disableReason) - * multiplier); - } - if (timeDifferenceMs >= disableTimeoutMs) { - return updateNetworkSelectionStatus( - config, NetworkSelectionStatus.DISABLED_NONE); - } - } - return false; - } - - /** - * Attempt to re-enable a network for network selection, if this network was either: - * a) Previously temporarily disabled, but its disable timeout has expired, or - * b) Previously disabled because of a user switch, but is now visible to the current - * user. - * - * @param networkId the id of the network to be checked for possible unblock (due to timeout) - * @return true if the network identified by {@param networkId} was re-enabled for qualified - * network selection, false otherwise. - */ - public boolean tryEnableNetwork(int networkId) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - return tryEnableNetwork(config); - } - - /** - * Enable a network using the public {@link WifiManager#enableNetwork(int, boolean)} API. - * - * @param networkId network ID of the network that needs the update. - * @param disableOthers Whether to disable all other networks or not. This is used to indicate - * that the app requested connection to a specific network. - * @param uid uid of the app requesting the update. - * @return true if it succeeds, false otherwise - */ - public boolean enableNetwork(int networkId, boolean disableOthers, int uid, - String packageName) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Enabling network " + networkId + " (disableOthers " + disableOthers + ")"); - } - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return false; - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - // Set the "last selected" flag even if the app does not have permissions to modify this - // network config. Apps are allowed to connect to networks even if they don't have - // permission to modify it. - if (disableOthers) { - setLastSelectedNetwork(networkId); - } - if (!canModifyNetwork(config, uid, packageName)) { - Log.e(TAG, "UID " + uid + " does not have permission to update configuration " - + config.getKey()); - return false; - } - if (!updateNetworkSelectionStatus( - networkId, WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE)) { - return false; - } - saveToStore(true); - return true; - } - - /** - * Disable a network using the public {@link WifiManager#disableNetwork(int)} API. - * - * @param networkId network ID of the network that needs the update. - * @param uid uid of the app requesting the update. - * @return true if it succeeds, false otherwise - */ - public boolean disableNetwork(int networkId, int uid, String packageName) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Disabling network " + networkId); - } - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return false; - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - // Reset the "last selected" flag even if the app does not have permissions to modify this - // network config. - if (networkId == mLastSelectedNetworkId) { - clearLastSelectedNetwork(); - } - if (!canModifyNetwork(config, uid, packageName)) { - Log.e(TAG, "UID " + uid + " does not have permission to update configuration " - + config.getKey()); - return false; - } - if (!updateNetworkSelectionStatus( - networkId, NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) { - return false; - } - saveToStore(true); - return true; - } - - /** - * Changes the user's choice to allow auto-join using the - * {@link WifiManager#allowAutojoin(int, boolean)} API. - * - * @param networkId network ID of the network that needs the update. - * @param choice the choice to allow auto-join or not - * @return true if it succeeds, false otherwise - */ - public boolean allowAutojoin(int networkId, boolean choice) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Setting allowAutojoin to " + choice + " for netId " + networkId); - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - Log.e(TAG, "allowAutojoin: Supplied networkId " + networkId - + " has no matching config"); - return false; - } - - config.allowAutojoin = choice; - if (!choice) { - removeConnectChoiceFromAllNetworks(config.getKey()); - clearNetworkConnectChoice(config.networkId); - } - sendConfiguredNetworkChangedBroadcast(WifiManager.CHANGE_REASON_CONFIG_CHANGE); - if (!config.ephemeral) { - saveToStore(true); - } - return true; - } - - /** - * Updates the last connected UID for the provided configuration. - * - * @param networkId network ID corresponding to the network. - * @param uid uid of the app requesting the connection. - * @return true if the network was found, false otherwise. - */ - public boolean updateLastConnectUid(int networkId, int uid) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Update network last connect UID for " + networkId); - } - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return false; - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.lastConnectUid = uid; - return true; - } - - /** - * Updates a network configuration after a successful connection to it. - * - * This method updates the following WifiConfiguration elements: - * 1. Set the |lastConnected| timestamp. - * 2. Increment |numAssociation| counter. - * 3. Clear the disable reason counters in the associated |NetworkSelectionStatus|. - * 4. Set the hasEverConnected| flag in the associated |NetworkSelectionStatus|. - * 5. Sets the status of network as |CURRENT|. - * - * @param networkId network ID corresponding to the network. - * @return true if the network was found, false otherwise. - */ - public boolean updateNetworkAfterConnect(int networkId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Update network after connect for " + networkId); - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - - // Only record connection order for non-passpoint from user saved or suggestion. - if (!config.isPasspoint() && (config.fromWifiNetworkSuggestion || !config.ephemeral)) { - mLruConnectionTracker.addNetwork(config); - } - config.lastConnected = mClock.getWallClockMillis(); - config.numAssociation++; - config.getNetworkSelectionStatus().clearDisableReasonCounter(); - config.getNetworkSelectionStatus().setHasEverConnected(true); - setNetworkStatus(config, WifiConfiguration.Status.CURRENT); - saveToStore(false); - return true; - } - - /** - * Updates a network configuration after disconnection from it. - * - * This method updates the following WifiConfiguration elements: - * 1. Set the |lastDisConnected| timestamp. - * 2. Sets the status of network back to |ENABLED|. - * - * @param networkId network ID corresponding to the network. - * @return true if the network was found, false otherwise. - */ - public boolean updateNetworkAfterDisconnect(int networkId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Update network after disconnect for " + networkId); - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.lastDisconnected = mClock.getWallClockMillis(); - config.randomizedMacExpirationTimeMs = Math.max(config.randomizedMacExpirationTimeMs, - config.lastDisconnected + AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS); - // If the network hasn't been disabled, mark it back as - // enabled after disconnection. - if (config.status == WifiConfiguration.Status.CURRENT) { - setNetworkStatus(config, WifiConfiguration.Status.ENABLED); - } - saveToStore(false); - return true; - } - - /** - * Set default GW MAC address for the provided network. - * - * @param networkId network ID corresponding to the network. - * @param macAddress MAC address of the gateway to be set. - * @return true if the network was found, false otherwise. - */ - public boolean setNetworkDefaultGwMacAddress(int networkId, String macAddress) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.defaultGwMacAddress = macAddress; - return true; - } - - /** - * Clear the {@link NetworkSelectionStatus#mCandidate}, - * {@link NetworkSelectionStatus#mCandidateScore} & - * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network. - * - * This is invoked by Network Selector at the start of every selection procedure to clear all - * configured networks' scan-result-candidates. - * - * @param networkId network ID corresponding to the network. - * @return true if the network was found, false otherwise. - */ - public boolean clearNetworkCandidateScanResult(int networkId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Clear network candidate scan result for " + networkId); - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.getNetworkSelectionStatus().setCandidate(null); - config.getNetworkSelectionStatus().setCandidateScore(Integer.MIN_VALUE); - config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(false); - return true; - } - - /** - * Set the {@link NetworkSelectionStatus#mCandidate}, - * {@link NetworkSelectionStatus#mCandidateScore} & - * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network. - * - * This is invoked by Network Selector when it sees a network during network selection procedure - * to set the scan result candidate. - * - * @param networkId network ID corresponding to the network. - * @param scanResult Candidate ScanResult associated with this network. - * @param score Score assigned to the candidate. - * @return true if the network was found, false otherwise. - */ - public boolean setNetworkCandidateScanResult(int networkId, ScanResult scanResult, int score) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Set network candidate scan result " + scanResult + " for " + networkId); - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - Log.e(TAG, "Cannot find network for " + networkId); - return false; - } - config.getNetworkSelectionStatus().setCandidate(scanResult); - config.getNetworkSelectionStatus().setCandidateScore(score); - config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(true); - return true; - } - - /** - * Iterate through all the saved networks and remove the provided configuration from the - * {@link NetworkSelectionStatus#mConnectChoice} from them. - * - * This is invoked when a network is removed from our records. - * - * @param connectChoiceConfigKey ConfigKey corresponding to the network that is being removed. - */ - private void removeConnectChoiceFromAllNetworks(String connectChoiceConfigKey) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Removing connect choice from all networks " + connectChoiceConfigKey); - } - if (connectChoiceConfigKey == null) { - return; - } - for (WifiConfiguration config : getInternalConfiguredNetworks()) { - WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus(); - String connectChoice = status.getConnectChoice(); - if (TextUtils.equals(connectChoice, connectChoiceConfigKey)) { - Log.d(TAG, "remove connect choice:" + connectChoice + " from " + config.SSID - + " : " + config.networkId); - clearNetworkConnectChoice(config.networkId); - } - } - } - - /** - * Clear the {@link NetworkSelectionStatus#mConnectChoice} for the provided network. - * - * @param networkId network ID corresponding to the network. - * @return true if the network was found, false otherwise. - */ - public boolean clearNetworkConnectChoice(int networkId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Clear network connect choice for " + networkId); - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.getNetworkSelectionStatus().setConnectChoice(null); - saveToStore(false); - return true; - } - - /** - * Set the {@link NetworkSelectionStatus#mConnectChoice} for the provided network. - * - * This is invoked by Network Selector when the user overrides the currently connected network - * choice. - * - * @param networkId network ID corresponding to the network. - * @param connectChoiceConfigKey ConfigKey corresponding to the network which was chosen over - * this network. - * @param timestamp timestamp at which the choice was made. - * @return true if the network was found, false otherwise. - */ - public boolean setNetworkConnectChoice( - int networkId, String connectChoiceConfigKey) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Set network connect choice " + connectChoiceConfigKey + " for " + networkId); - } - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.getNetworkSelectionStatus().setConnectChoice(connectChoiceConfigKey); - saveToStore(false); - return true; - } - - /** - * Increments the number of no internet access reports in the provided network. - * - * @param networkId network ID corresponding to the network. - * @return true if the network was found, false otherwise. - */ - public boolean incrementNetworkNoInternetAccessReports(int networkId) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.numNoInternetAccessReports++; - return true; - } - - /** - * Sets the internet access is validated or not in the provided network. - * - * @param networkId network ID corresponding to the network. - * @param validated Whether access is validated or not. - * @return true if the network was found, false otherwise. - */ - public boolean setNetworkValidatedInternetAccess(int networkId, boolean validated) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.validatedInternetAccess = validated; - config.numNoInternetAccessReports = 0; - saveToStore(false); - return true; - } - - /** - * Sets whether the internet access is expected or not in the provided network. - * - * @param networkId network ID corresponding to the network. - * @param expected Whether access is expected or not. - * @return true if the network was found, false otherwise. - */ - public boolean setNetworkNoInternetAccessExpected(int networkId, boolean expected) { - WifiConfiguration config = getInternalConfiguredNetwork(networkId); - if (config == null) { - return false; - } - config.noInternetAccessExpected = expected; - return true; - } - - /** - * Helper method to clear out the {@link #mNextNetworkId} user/app network selection. This - * is done when either the corresponding network is either removed or disabled. - */ - public void clearLastSelectedNetwork() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Clearing last selected network"); - } - mLastSelectedNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - mLastSelectedTimeStamp = NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; - } - - /** - * Helper method to mark a network as the last selected one by an app/user. This is set - * when an app invokes {@link #enableNetwork(int, boolean, int)} with |disableOthers| flag set. - * This is used by network selector to assign a special bonus during network selection. - */ - private void setLastSelectedNetwork(int networkId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Setting last selected network to " + networkId); - } - mLastSelectedNetworkId = networkId; - mLastSelectedTimeStamp = mClock.getElapsedSinceBootMillis(); - } - - /** - * Retrieve the network Id corresponding to the last network that was explicitly selected by - * an app/user. - * - * @return network Id corresponding to the last selected network. - */ - public int getLastSelectedNetwork() { - return mLastSelectedNetworkId; - } - - /** - * Retrieve the configKey corresponding to the last network that was explicitly selected by - * an app/user. - * - * @return network Id corresponding to the last selected network. - */ - public String getLastSelectedNetworkConfigKey() { - if (mLastSelectedNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { - return ""; - } - WifiConfiguration config = getInternalConfiguredNetwork(mLastSelectedNetworkId); - if (config == null) { - return ""; - } - return config.getKey(); - } - - /** - * Retrieve the time stamp at which a network was explicitly selected by an app/user. - * - * @return timestamp in milliseconds from boot when this was set. - */ - public long getLastSelectedTimeStamp() { - return mLastSelectedTimeStamp; - } - - /** - * Helper method to get the scan detail cache entry {@link #mScanDetailCaches} for the provided - * network. - * - * @param networkId network ID corresponding to the network. - * @return existing {@link ScanDetailCache} entry if one exists or null. - */ - public ScanDetailCache getScanDetailCacheForNetwork(int networkId) { - return mScanDetailCaches.get(networkId); - } - - /** - * Helper method to get or create a scan detail cache entry {@link #mScanDetailCaches} for - * the provided network. - * - * @param config configuration corresponding to the the network. - * @return existing {@link ScanDetailCache} entry if one exists or a new instance created for - * this network. - */ - private ScanDetailCache getOrCreateScanDetailCacheForNetwork(WifiConfiguration config) { - if (config == null) return null; - ScanDetailCache cache = getScanDetailCacheForNetwork(config.networkId); - if (cache == null && config.networkId != WifiConfiguration.INVALID_NETWORK_ID) { - cache = new ScanDetailCache( - config, SCAN_CACHE_ENTRIES_MAX_SIZE, SCAN_CACHE_ENTRIES_TRIM_SIZE); - mScanDetailCaches.put(config.networkId, cache); - } - return cache; - } - - /** - * Saves the provided ScanDetail into the corresponding scan detail cache entry - * {@link #mScanDetailCaches} for the provided network. - * - * @param config configuration corresponding to the the network. - * @param scanDetail new scan detail instance to be saved into the cache. - */ - private void saveToScanDetailCacheForNetwork( - WifiConfiguration config, ScanDetail scanDetail) { - ScanResult scanResult = scanDetail.getScanResult(); - - WifiScoreCard.PerNetwork network = mWifiScoreCard.lookupNetwork(config.SSID); - network.addFrequency(scanResult.frequency); - ScanDetailCache scanDetailCache = getOrCreateScanDetailCacheForNetwork(config); - if (scanDetailCache == null) { - Log.e(TAG, "Could not allocate scan cache for " + config.getPrintableSsid()); - return; - } - - // Adding a new BSSID - if (config.ephemeral) { - // For an ephemeral Wi-Fi config, the ScanResult should be considered - // untrusted. - scanResult.untrusted = true; - } - - // Add the scan detail to this network's scan detail cache. - scanDetailCache.put(scanDetail); - - // Since we added a scan result to this configuration, re-attempt linking. - // TODO: Do we really need to do this after every scan result? - attemptNetworkLinking(config); - } - - /** - * Retrieves a configured network corresponding to the provided scan detail if one exists. - * - * @param scanDetail ScanDetail instance to use for looking up the network. - * @return WifiConfiguration object representing the network corresponding to the scanDetail, - * null if none exists. - * - * TODO (b/142035508): This should only return saved networks (and rename to - * getSavedNetworkForScanDetail()). - */ - public WifiConfiguration getConfiguredNetworkForScanDetail(ScanDetail scanDetail) { - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult == null) { - Log.e(TAG, "No scan result found in scan detail"); - return null; - } - WifiConfiguration config = null; - try { - config = mConfiguredNetworks.getByScanResultForCurrentUser(scanResult); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Failed to lookup network from config map", e); - } - if (config != null) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "getSavedNetworkFromScanDetail Found " + config.getKey() - + " for " + scanResult.SSID + "[" + scanResult.capabilities + "]"); - } - } - return config; - } - - /** - * Caches the provided |scanDetail| into the corresponding scan detail cache entry - * {@link #mScanDetailCaches} for the retrieved network. - * - * @param scanDetail input a scanDetail from the scan result - * TODO (b/142035508): This should only return saved networks (and rename to - * updateScanDetailCacheFromScanDetail()). - */ - public void updateScanDetailCacheFromScanDetail(ScanDetail scanDetail) { - WifiConfiguration network = getConfiguredNetworkForScanDetail(scanDetail); - if (network == null) { - return; - } - saveToScanDetailCacheForNetwork(network, scanDetail); - } - /** - * Retrieves a configured network corresponding to the provided scan detail if one exists and - * caches the provided |scanDetail| into the corresponding scan detail cache entry - * {@link #mScanDetailCaches} for the retrieved network. - * - * @param scanDetail input a scanDetail from the scan result - * @return WifiConfiguration object representing the network corresponding to the scanDetail, - * null if none exists. - * TODO (b/142035508): This should only return saved networks (and rename to - * getSavedNetworkForScanDetailAndCache()). - */ - public WifiConfiguration getConfiguredNetworkForScanDetailAndCache(ScanDetail scanDetail) { - WifiConfiguration network = getConfiguredNetworkForScanDetail(scanDetail); - if (network == null) { - return null; - } - saveToScanDetailCacheForNetwork(network, scanDetail); - // Cache DTIM values parsed from the beacon frame Traffic Indication Map (TIM) - // Information Element (IE), into the associated WifiConfigurations. Most of the - // time there is no TIM IE in the scan result (Probe Response instead of Beacon - // Frame), these scanResult DTIM's are negative and ignored. - // Used for metrics collection. - if (scanDetail.getNetworkDetail() != null - && scanDetail.getNetworkDetail().getDtimInterval() > 0) { - network.dtimInterval = scanDetail.getNetworkDetail().getDtimInterval(); - } - return createExternalWifiConfiguration(network, true, Process.WIFI_UID); - } - - /** - * Update the scan detail cache associated with current connected network with latest - * RSSI value in the provided WifiInfo. - * This is invoked when we get an RSSI poll update after connection. - * - * @param info WifiInfo instance pointing to the current connected network. - */ - public void updateScanDetailCacheFromWifiInfo(WifiInfo info) { - WifiConfiguration config = getInternalConfiguredNetwork(info.getNetworkId()); - ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(info.getNetworkId()); - if (config != null && scanDetailCache != null) { - ScanDetail scanDetail = scanDetailCache.getScanDetail(info.getBSSID()); - if (scanDetail != null) { - ScanResult result = scanDetail.getScanResult(); - long previousSeen = result.seen; - int previousRssi = result.level; - // Update the scan result - scanDetail.setSeen(); - result.level = info.getRssi(); - // Average the RSSI value - long maxAge = SCAN_RESULT_MAXIMUM_AGE_MS; - long age = result.seen - previousSeen; - if (previousSeen > 0 && age > 0 && age < maxAge / 2) { - // Average the RSSI with previously seen instances of this scan result - double alpha = 0.5 - (double) age / (double) maxAge; - result.level = (int) ((double) result.level * (1 - alpha) - + (double) previousRssi * alpha); - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Updating scan detail cache freq=" + result.frequency - + " BSSID=" + result.BSSID - + " RSSI=" + result.level - + " for " + config.getKey()); - } - } - } - } - - /** - * Save the ScanDetail to the ScanDetailCache of the given network. This is used - * by {@link PasspointNetworkNominator} for caching - * ScanDetail for newly created {@link WifiConfiguration} for Passpoint network. - * - * @param networkId The ID of the network to save ScanDetail to - * @param scanDetail The ScanDetail to cache - */ - public void updateScanDetailForNetwork(int networkId, ScanDetail scanDetail) { - WifiConfiguration network = getInternalConfiguredNetwork(networkId); - if (network == null) { - return; - } - saveToScanDetailCacheForNetwork(network, scanDetail); - } - - /** - * Helper method to check if the 2 provided networks can be linked or not. - * Networks are considered for linking if: - * 1. Share the same GW MAC address. - * 2. Scan results for the networks have AP's with MAC address which differ only in the last - * nibble. - * - * @param network1 WifiConfiguration corresponding to network 1. - * @param network2 WifiConfiguration corresponding to network 2. - * @param scanDetailCache1 ScanDetailCache entry for network 1. - * @param scanDetailCache1 ScanDetailCache entry for network 2. - * @return true if the networks should be linked, false if the networks should be unlinked. - */ - private boolean shouldNetworksBeLinked( - WifiConfiguration network1, WifiConfiguration network2, - ScanDetailCache scanDetailCache1, ScanDetailCache scanDetailCache2) { - // TODO (b/30706406): Link networks only with same passwords if the - // |mOnlyLinkSameCredentialConfigurations| flag is set. - if (mContext.getResources().getBoolean( - R.bool.config_wifi_only_link_same_credential_configurations)) { - if (!TextUtils.equals(network1.preSharedKey, network2.preSharedKey)) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "shouldNetworksBeLinked unlink due to password mismatch"); - } - return false; - } - } - if (network1.defaultGwMacAddress != null && network2.defaultGwMacAddress != null) { - // If both default GW are known, link only if they are equal - if (network1.defaultGwMacAddress.equals(network2.defaultGwMacAddress)) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "shouldNetworksBeLinked link due to same gw " + network2.SSID - + " and " + network1.SSID + " GW " + network1.defaultGwMacAddress); - } - return true; - } - } else { - // We do not know BOTH default gateways hence we will try to link - // hoping that WifiConfigurations are indeed behind the same gateway. - // once both WifiConfiguration have been tried and thus once both default gateways - // are known we will revisit the choice of linking them. - if (scanDetailCache1 != null && scanDetailCache2 != null) { - for (String abssid : scanDetailCache1.keySet()) { - for (String bbssid : scanDetailCache2.keySet()) { - if (abssid.regionMatches( - true, 0, bbssid, 0, LINK_CONFIGURATION_BSSID_MATCH_LENGTH)) { - // If first 16 ASCII characters of BSSID matches, - // we assume this is a DBDC. - if (mVerboseLoggingEnabled) { - Log.v(TAG, "shouldNetworksBeLinked link due to DBDC BSSID match " - + network2.SSID + " and " + network1.SSID - + " bssida " + abssid + " bssidb " + bbssid); - } - return true; - } - } - } - } - } - return false; - } - - /** - * Helper methods to link 2 networks together. - * - * @param network1 WifiConfiguration corresponding to network 1. - * @param network2 WifiConfiguration corresponding to network 2. - */ - private void linkNetworks(WifiConfiguration network1, WifiConfiguration network2) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "linkNetworks will link " + network2.getKey() - + " and " + network1.getKey()); - } - if (network2.linkedConfigurations == null) { - network2.linkedConfigurations = new HashMap<>(); - } - if (network1.linkedConfigurations == null) { - network1.linkedConfigurations = new HashMap<>(); - } - // TODO (b/30638473): This needs to become a set instead of map, but it will need - // public interface changes and need some migration of existing store data. - network2.linkedConfigurations.put(network1.getKey(), 1); - network1.linkedConfigurations.put(network2.getKey(), 1); - } - - /** - * Helper methods to unlink 2 networks from each other. - * - * @param network1 WifiConfiguration corresponding to network 1. - * @param network2 WifiConfiguration corresponding to network 2. - */ - private void unlinkNetworks(WifiConfiguration network1, WifiConfiguration network2) { - if (network2.linkedConfigurations != null - && (network2.linkedConfigurations.get(network1.getKey()) != null)) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "unlinkNetworks un-link " + network1.getKey() - + " from " + network2.getKey()); - } - network2.linkedConfigurations.remove(network1.getKey()); - } - if (network1.linkedConfigurations != null - && (network1.linkedConfigurations.get(network2.getKey()) != null)) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "unlinkNetworks un-link " + network2.getKey() - + " from " + network1.getKey()); - } - network1.linkedConfigurations.remove(network2.getKey()); - } - } - - /** - * This method runs through all the saved networks and checks if the provided network can be - * linked with any of them. - * - * @param config WifiConfiguration object corresponding to the network that needs to be - * checked for potential links. - */ - private void attemptNetworkLinking(WifiConfiguration config) { - // Only link WPA_PSK config. - if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - return; - } - ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(config.networkId); - // Ignore configurations with large number of BSSIDs. - if (scanDetailCache != null - && scanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) { - return; - } - for (WifiConfiguration linkConfig : getInternalConfiguredNetworks()) { - if (linkConfig.getKey().equals(config.getKey())) { - continue; - } - if (linkConfig.ephemeral) { - continue; - } - // Network Selector will be allowed to dynamically jump from a linked configuration - // to another, hence only link configurations that have WPA_PSK security type. - if (!linkConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - continue; - } - ScanDetailCache linkScanDetailCache = - getScanDetailCacheForNetwork(linkConfig.networkId); - // Ignore configurations with large number of BSSIDs. - if (linkScanDetailCache != null - && linkScanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) { - continue; - } - // Check if the networks should be linked/unlinked. - if (shouldNetworksBeLinked( - config, linkConfig, scanDetailCache, linkScanDetailCache)) { - linkNetworks(config, linkConfig); - } else { - unlinkNetworks(config, linkConfig); - } - } - } - - /** - * Retrieves a list of all the saved hidden networks for scans - * - * Hidden network list sent to the firmware has limited size. If there are a lot of saved - * networks, this list will be truncated and we might end up not sending the networks - * with the highest chance of connecting to the firmware. - * So, re-sort the network list based on the frequency of connection to those networks - * and whether it was last seen in the scan results. - * - * @return list of networks in the order of priority. - */ - public List<WifiScanner.ScanSettings.HiddenNetwork> retrieveHiddenNetworkList() { - List<WifiScanner.ScanSettings.HiddenNetwork> hiddenList = new ArrayList<>(); - List<WifiConfiguration> networks = getConfiguredNetworks(); - // Remove any non hidden networks. - networks.removeIf(config -> !config.hiddenSSID); - networks.sort(mScanListComparator); - // The most frequently connected network has the highest priority now. - for (WifiConfiguration config : networks) { - hiddenList.add(new WifiScanner.ScanSettings.HiddenNetwork(config.SSID)); - } - return hiddenList; - } - - /** - * Check if the provided network was temporarily disabled by the user and still blocked. - * - * @param network Input can be SSID or FQDN. And caller must ensure that the SSID passed thru - * this API matched the WifiConfiguration.SSID rules, and thus be surrounded by - * quotes. - * @return true if network is blocking, otherwise false. - */ - public boolean isNetworkTemporarilyDisabledByUser(String network) { - if (mUserTemporarilyDisabledList.isLocked(network)) { - return true; - } - mUserTemporarilyDisabledList.remove(network); - return false; - } - - /** - * User temporarily disable a network and will be block to auto-join when network is still - * nearby. - * - * The network will be re-enabled when: - * a) User select to connect the network. - * b) The network is not in range for {@link #USER_DISCONNECT_NETWORK_BLOCK_EXPIRY_MS} - * c) Toggle wifi off, reset network settings or device reboot. - * - * @param network Input can be SSID or FQDN. And caller must ensure that the SSID passed thru - * this API matched the WifiConfiguration.SSID rules, and thus be surrounded by - * quotes. - * uid UID of the calling process. - */ - public void userTemporarilyDisabledNetwork(String network, int uid) { - mUserTemporarilyDisabledList.add(network, USER_DISCONNECT_NETWORK_BLOCK_EXPIRY_MS); - Log.d(TAG, "Temporarily disable network: " + network + " uid=" + uid + " num=" - + mUserTemporarilyDisabledList.size()); - removeUserChoiceFromDisabledNetwork(network, uid); - } - - /** - * Update the user temporarily disabled network list with networks in range. - * @param networks networks in range in String format, FQDN or SSID. And caller must ensure - * that the SSID passed thru this API matched the WifiConfiguration.SSID rules, - * and thus be surrounded by quotes. - */ - public void updateUserDisabledList(List<String> networks) { - mUserTemporarilyDisabledList.update(new HashSet<>(networks)); - } - - private void removeUserChoiceFromDisabledNetwork( - @NonNull String network, int uid) { - for (WifiConfiguration config : getInternalConfiguredNetworks()) { - if (TextUtils.equals(config.SSID, network) || TextUtils.equals(config.FQDN, network)) { - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { - mWifiInjector.getWifiMetrics().logUserActionEvent( - UserActionEvent.EVENT_DISCONNECT_WIFI, config.networkId); - } - removeConnectChoiceFromAllNetworks(config.getKey()); - } - } - } - - /** - * User enabled network manually, maybe trigger by user select to connect network. - * @param networkId enabled network id. - */ - public void userEnabledNetwork(int networkId) { - WifiConfiguration configuration = getInternalConfiguredNetwork(networkId); - if (configuration == null) { - return; - } - String network; - if (configuration.isPasspoint()) { - network = configuration.FQDN; - } else { - network = configuration.SSID; - } - mUserTemporarilyDisabledList.remove(network); - mWifiInjector.getBssidBlocklistMonitor().clearBssidBlocklistForSsid(configuration.SSID); - Log.d(TAG, "Enable disabled network: " + network + " num=" - + mUserTemporarilyDisabledList.size()); - } - - /** - * Clear all user temporarily disabled networks. - */ - public void clearUserTemporarilyDisabledList() { - mUserTemporarilyDisabledList.clear(); - } - - /** - * Resets all sim networks state. - */ - public void resetSimNetworks() { - if (mVerboseLoggingEnabled) localLog("resetSimNetworks"); - for (WifiConfiguration config : getInternalConfiguredNetworks()) { - if (config.enterpriseConfig == null - || !config.enterpriseConfig.isAuthenticationSimBased()) { - continue; - } - if (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) { - Pair<String, String> currentIdentity = - mWifiCarrierInfoManager.getSimIdentity(config); - if (mVerboseLoggingEnabled) { - Log.d(TAG, "New identity for config " + config + ": " + currentIdentity); - } - // Update the loaded config - if (currentIdentity == null) { - Log.d(TAG, "Identity is null"); - } else { - config.enterpriseConfig.setIdentity(currentIdentity.first); - } - // do not reset anonymous identity since it may be dependent on user-entry - // (i.e. cannot re-request on every reboot/SIM re-entry) - } else { - // reset identity as well: supplicant will ask us for it - config.enterpriseConfig.setIdentity(""); - if (!WifiCarrierInfoManager.isAnonymousAtRealmIdentity( - config.enterpriseConfig.getAnonymousIdentity())) { - config.enterpriseConfig.setAnonymousIdentity(""); - } - } - } - } - - /** - * Helper method to perform the following operations during user switch/unlock: - * - Remove private networks of the old user. - * - Load from the new user store file. - * - Save the store files again to migrate any user specific networks from the shared store - * to user store. - * This method assumes the user store is visible (i.e CE storage is unlocked). So, the caller - * should ensure that the stores are accessible before invocation. - * - * @param userId The identifier of the new foreground user, after the unlock or switch. - */ - private void handleUserUnlockOrSwitch(int userId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Loading from store after user switch/unlock for " + userId); - } - // Switch out the user store file. - if (loadFromUserStoreAfterUnlockOrSwitch(userId)) { - saveToStore(true); - mPendingUnlockStoreRead = false; - } - } - - /** - * Handles the switch to a different foreground user: - * - Flush the current state to the old user's store file. - * - Switch the user specific store file. - * - Reload the networks from the store files (shared & user). - * - Write the store files to move any user specific private networks from shared store to user - * store. - * - * Need to be called when {@link com.android.server.SystemService#onSwitchUser(int)} is invoked. - * - * @param userId The identifier of the new foreground user, after the switch. - * @return List of network ID's of all the private networks of the old user which will be - * removed from memory. - */ - public Set<Integer> handleUserSwitch(int userId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Handling user switch for " + userId); - } - if (userId == mCurrentUserId) { - Log.w(TAG, "User already in foreground " + userId); - return new HashSet<>(); - } - if (mPendingStoreRead) { - Log.w(TAG, "User switch before store is read!"); - mConfiguredNetworks.setNewUser(userId); - mCurrentUserId = userId; - // Reset any state from previous user unlock. - mDeferredUserUnlockRead = false; - // Cannot read data from new user's CE store file before they log-in. - mPendingUnlockStoreRead = true; - return new HashSet<>(); - } - if (mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(mCurrentUserId))) { - saveToStore(true); - } - // Remove any private networks of the old user before switching the userId. - Set<Integer> removedNetworkIds = clearInternalDataForCurrentUser(); - mConfiguredNetworks.setNewUser(userId); - mCurrentUserId = userId; - - if (mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(mCurrentUserId))) { - handleUserUnlockOrSwitch(mCurrentUserId); - } else { - // Cannot read data from new user's CE store file before they log-in. - mPendingUnlockStoreRead = true; - Log.i(TAG, "Waiting for user unlock to load from store"); - } - return removedNetworkIds; - } - - /** - * Handles the unlock of foreground user. This maybe needed to read the store file if the user's - * CE storage is not visible when {@link #handleUserSwitch(int)} is invoked. - * - * Need to be called when {@link com.android.server.SystemService#onUnlockUser(int)} is invoked. - * - * @param userId The identifier of the user that unlocked. - */ - public void handleUserUnlock(int userId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Handling user unlock for " + userId); - } - if (userId != mCurrentUserId) { - Log.e(TAG, "Ignore user unlock for non current user " + userId); - return; - } - if (mPendingStoreRead) { - Log.w(TAG, "Ignore user unlock until store is read!"); - mDeferredUserUnlockRead = true; - return; - } - if (mPendingUnlockStoreRead) { - handleUserUnlockOrSwitch(mCurrentUserId); - } - } - - /** - * Handles the stop of foreground user. This is needed to write the store file to flush - * out any pending data before the user's CE store storage is unavailable. - * - * Need to be called when {@link com.android.server.SystemService#onStopUser(int)} is invoked. - * - * @param userId The identifier of the user that stopped. - */ - public void handleUserStop(int userId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Handling user stop for " + userId); - } - if (userId == mCurrentUserId - && mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(mCurrentUserId))) { - saveToStore(true); - clearInternalDataForCurrentUser(); - } - } - - /** - * Helper method to clear internal databases. - * This method clears the: - * - List of configured networks. - * - Map of scan detail caches. - * - List of deleted ephemeral networks. - */ - private void clearInternalData() { - localLog("clearInternalData: Clearing all internal data"); - mConfiguredNetworks.clear(); - mUserTemporarilyDisabledList.clear(); - mRandomizedMacAddressMapping.clear(); - mScanDetailCaches.clear(); - clearLastSelectedNetwork(); - } - - /** - * Helper method to clear internal databases of the specified user. - * This method clears the: - * - Private configured configured networks of the specified user. - * - Map of scan detail caches. - * - List of deleted ephemeral networks. - * - * @return List of network ID's of all the private networks of the old user which will be - * removed from memory. - */ - private Set<Integer> clearInternalDataForCurrentUser() { - localLog("clearInternalUserData: Clearing user internal data for " + mCurrentUserId); - Set<Integer> removedNetworkIds = new HashSet<>(); - // Remove any private networks of the old user before switching the userId. - for (WifiConfiguration config : getConfiguredNetworks()) { - if ((!config.shared && !mWifiPermissionsUtil - .doesUidBelongToCurrentUser(config.creatorUid)) - || config.ephemeral) { - removedNetworkIds.add(config.networkId); - localLog("clearInternalUserData: removed config." - + " netId=" + config.networkId - + " configKey=" + config.getKey()); - mConfiguredNetworks.remove(config.networkId); - for (OnNetworkUpdateListener listener : mListeners) { - listener.onNetworkRemoved( - createExternalWifiConfiguration(config, true, Process.WIFI_UID)); - } - } - } - if (!removedNetworkIds.isEmpty()) { - sendConfiguredNetworkChangedBroadcast(WifiManager.CHANGE_REASON_REMOVED); - } - mUserTemporarilyDisabledList.clear(); - mScanDetailCaches.clear(); - clearLastSelectedNetwork(); - return removedNetworkIds; - } - - /** - * Helper function to populate the internal (in-memory) data from the retrieved shared store - * (file) data. - * - * @param configurations list of configurations retrieved from store. - */ - private void loadInternalDataFromSharedStore( - List<WifiConfiguration> configurations, - Map<String, String> macAddressMapping) { - for (WifiConfiguration configuration : configurations) { - configuration.networkId = mNextNetworkId++; - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Adding network from shared store " + configuration.getKey()); - } - try { - mConfiguredNetworks.put(configuration); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Failed to add network to config map", e); - } - } - mRandomizedMacAddressMapping.putAll(macAddressMapping); - } - - /** - * Helper function to populate the internal (in-memory) data from the retrieved user store - * (file) data. - * - * @param configurations list of configurations retrieved from store. - */ - private void loadInternalDataFromUserStore(List<WifiConfiguration> configurations) { - for (WifiConfiguration configuration : configurations) { - configuration.networkId = mNextNetworkId++; - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Adding network from user store " + configuration.getKey()); - } - try { - mConfiguredNetworks.put(configuration); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Failed to add network to config map", e); - } - - if (configuration.isMostRecentlyConnected) { - mLruConnectionTracker.addNetwork(configuration); - } - } - } - - /** - * Initializes the randomized MAC address for an internal WifiConfiguration depending on - * whether it should use aggressive randomization. - * @param config - */ - private void initRandomizedMacForInternalConfig(WifiConfiguration internalConfig) { - MacAddress randomizedMac = shouldUseAggressiveRandomization(internalConfig) - ? MacAddressUtils.createRandomUnicastAddress() - : getPersistentMacAddress(internalConfig); - if (randomizedMac != null) { - internalConfig.setRandomizedMacAddress(randomizedMac); - } - } - - /** - * Assign randomized MAC addresses for configured networks. - * This is needed to generate persistent randomized MAC address for existing networks when - * a device updates to Q+ for the first time since we are not calling addOrUpdateNetwork when - * we load configuration at boot. - */ - private void generateRandomizedMacAddresses() { - for (WifiConfiguration config : getInternalConfiguredNetworks()) { - if (DEFAULT_MAC_ADDRESS.equals(config.getRandomizedMacAddress())) { - initRandomizedMacForInternalConfig(config); - } - } - } - - /** - * Helper function to populate the internal (in-memory) data from the retrieved stores (file) - * data. - * This method: - * 1. Clears all existing internal data. - * 2. Sends out the networks changed broadcast after loading all the data. - * - * @param sharedConfigurations list of network configurations retrieved from shared store. - * @param userConfigurations list of network configurations retrieved from user store. - * @param macAddressMapping - */ - private void loadInternalData( - List<WifiConfiguration> sharedConfigurations, - List<WifiConfiguration> userConfigurations, - Map<String, String> macAddressMapping) { - // Clear out all the existing in-memory lists and load the lists from what was retrieved - // from the config store. - clearInternalData(); - loadInternalDataFromSharedStore(sharedConfigurations, macAddressMapping); - loadInternalDataFromUserStore(userConfigurations); - generateRandomizedMacAddresses(); - if (mConfiguredNetworks.sizeForAllUsers() == 0) { - Log.w(TAG, "No stored networks found."); - } - // reset identity & anonymous identity for networks using SIM-based authentication - // on load (i.e. boot) so that if the user changed SIMs while the device was powered off, - // we do not reuse stale credentials that would lead to authentication failure. - resetSimNetworks(); - sendConfiguredNetworkChangedBroadcast(WifiManager.CHANGE_REASON_ADDED); - mPendingStoreRead = false; - } - - /** - * Read the config store and load the in-memory lists from the store data retrieved and sends - * out the networks changed broadcast. - * - * This reads all the network configurations from: - * 1. Shared WifiConfigStore.xml - * 2. User WifiConfigStore.xml - * - * @return true on success or not needed (fresh install), false otherwise. - */ - public boolean loadFromStore() { - // If the user unlock comes in before we load from store, which means the user store have - // not been setup yet for the current user. Setup the user store before the read so that - // configurations for the current user will also being loaded. - if (mDeferredUserUnlockRead) { - Log.i(TAG, "Handling user unlock before loading from store."); - List<WifiConfigStore.StoreFile> userStoreFiles = - WifiConfigStore.createUserFiles( - mCurrentUserId, mFrameworkFacade.isNiapModeOn(mContext)); - if (userStoreFiles == null) { - Log.wtf(TAG, "Failed to create user store files"); - return false; - } - mWifiConfigStore.setUserStores(userStoreFiles); - mDeferredUserUnlockRead = false; - } - try { - mWifiConfigStore.read(); - } catch (IOException | IllegalStateException e) { - Log.wtf(TAG, "Reading from new store failed. All saved networks are lost!", e); - return false; - } catch (XmlPullParserException e) { - Log.wtf(TAG, "XML deserialization of store failed. All saved networks are lost!", e); - return false; - } - loadInternalData(mNetworkListSharedStoreData.getConfigurations(), - mNetworkListUserStoreData.getConfigurations(), - mRandomizedMacStoreData.getMacMapping()); - return true; - } - - /** - * Read the user config store and load the in-memory lists from the store data retrieved and - * sends out the networks changed broadcast. - * This should be used for all user switches/unlocks to only load networks from the user - * specific store and avoid reloading the shared networks. - * - * This reads all the network configurations from: - * 1. User WifiConfigStore.xml - * - * @param userId The identifier of the foreground user. - * @return true on success, false otherwise. - */ - private boolean loadFromUserStoreAfterUnlockOrSwitch(int userId) { - try { - List<WifiConfigStore.StoreFile> userStoreFiles = - WifiConfigStore.createUserFiles( - userId, mFrameworkFacade.isNiapModeOn(mContext)); - if (userStoreFiles == null) { - Log.e(TAG, "Failed to create user store files"); - return false; - } - mWifiConfigStore.switchUserStoresAndRead(userStoreFiles); - } catch (IOException | IllegalStateException e) { - Log.wtf(TAG, "Reading from new store failed. All saved private networks are lost!", e); - return false; - } catch (XmlPullParserException e) { - Log.wtf(TAG, "XML deserialization of store failed. All saved private networks are " - + "lost!", e); - return false; - } - loadInternalDataFromUserStore(mNetworkListUserStoreData.getConfigurations()); - return true; - } - - /** - * Save the current snapshot of the in-memory lists to the config store. - * - * @param forceWrite Whether the write needs to be forced or not. - * @return Whether the write was successful or not, this is applicable only for force writes. - */ - public boolean saveToStore(boolean forceWrite) { - if (mPendingStoreRead) { - Log.e(TAG, "Cannot save to store before store is read!"); - return false; - } - ArrayList<WifiConfiguration> sharedConfigurations = new ArrayList<>(); - ArrayList<WifiConfiguration> userConfigurations = new ArrayList<>(); - // List of network IDs for legacy Passpoint configuration to be removed. - List<Integer> legacyPasspointNetId = new ArrayList<>(); - for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { - // Ignore ephemeral networks and non-legacy Passpoint configurations. - if (config.ephemeral || (config.isPasspoint() && !config.isLegacyPasspointConfig)) { - continue; - } - - // Migrate the legacy Passpoint configurations owned by the current user to - // {@link PasspointManager}. - if (config.isLegacyPasspointConfig && !mWifiPermissionsUtil - .doesUidBelongToCurrentUser(config.creatorUid)) { - legacyPasspointNetId.add(config.networkId); - // Migrate the legacy Passpoint configuration and add it to PasspointManager. - if (!PasspointManager.addLegacyPasspointConfig(config)) { - Log.e(TAG, "Failed to migrate legacy Passpoint config: " + config.FQDN); - } - // This will prevent adding |config| to the |sharedConfigurations|. - continue; - } - - config.isMostRecentlyConnected = - mLruConnectionTracker.isMostRecentlyConnected(config); - - // We push all shared networks & private networks not belonging to the current - // user to the shared store. Ideally, private networks for other users should - // not even be in memory, - // But, this logic is in place to deal with store migration from N to O - // because all networks were previously stored in a central file. We cannot - // write these private networks to the user specific store until the corresponding - // user logs in. - if (config.shared || !mWifiPermissionsUtil - .doesUidBelongToCurrentUser(config.creatorUid)) { - sharedConfigurations.add(config); - } else { - userConfigurations.add(config); - } - } - - // Remove the configurations for migrated Passpoint configurations. - for (int networkId : legacyPasspointNetId) { - mConfiguredNetworks.remove(networkId); - } - - // Setup store data for write. - mNetworkListSharedStoreData.setConfigurations(sharedConfigurations); - mNetworkListUserStoreData.setConfigurations(userConfigurations); - mRandomizedMacStoreData.setMacMapping(mRandomizedMacAddressMapping); - - try { - mWifiConfigStore.write(forceWrite); - } catch (IOException | IllegalStateException e) { - Log.wtf(TAG, "Writing to store failed. Saved networks maybe lost!", e); - return false; - } catch (XmlPullParserException e) { - Log.wtf(TAG, "XML serialization for store failed. Saved networks maybe lost!", e); - return false; - } - return true; - } - - /** - * Helper method for logging into local log buffer. - */ - private void localLog(String s) { - if (mLocalLog != null) { - mLocalLog.log(s); - } - } - - /** - * Dump the local log buffer and other internal state of WifiConfigManager. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WifiConfigManager"); - pw.println("WifiConfigManager - Log Begin ----"); - mLocalLog.dump(fd, pw, args); - pw.println("WifiConfigManager - Log End ----"); - pw.println("WifiConfigManager - Configured networks Begin ----"); - for (WifiConfiguration network : getInternalConfiguredNetworks()) { - pw.println(network); - } - pw.println("WifiConfigManager - Configured networks End ----"); - pw.println("WifiConfigManager - ConfigurationMap Begin ----"); - mConfiguredNetworks.dump(fd, pw, args); - pw.println("WifiConfigManager - ConfigurationMap End ----"); - pw.println("WifiConfigManager - Next network ID to be allocated " + mNextNetworkId); - pw.println("WifiConfigManager - Last selected network ID " + mLastSelectedNetworkId); - pw.println("WifiConfigManager - PNO scan frequency culling enabled = " - + mContext.getResources().getBoolean(R.bool.config_wifiPnoFrequencyCullingEnabled)); - pw.println("WifiConfigManager - PNO scan recency sorting enabled = " - + mContext.getResources().getBoolean(R.bool.config_wifiPnoRecencySortingEnabled)); - mWifiConfigStore.dump(fd, pw, args); - mWifiCarrierInfoManager.dump(fd, pw, args); - } - - /** - * Returns true if the given uid has permission to add, update or remove proxy settings - */ - private boolean canModifyProxySettings(int uid, String packageName) { - final boolean isDeviceOwner = mWifiPermissionsUtil.isDeviceOwner(uid, packageName); - final boolean isProfileOwner = mWifiPermissionsUtil.isProfileOwner(uid, packageName); - final boolean hasNetworkSettingsPermission = - mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); - final boolean hasNetworkSetupWizardPermission = - mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid); - final boolean hasNetworkManagedProvisioningPermission = - mWifiPermissionsUtil.checkNetworkManagedProvisioningPermission(uid); - // If |uid| corresponds to the device owner, allow all modifications. - if (isProfileOwner || isDeviceOwner || hasNetworkSettingsPermission - || hasNetworkSetupWizardPermission || hasNetworkManagedProvisioningPermission) { - return true; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "UID: " + uid + " cannot modify WifiConfiguration proxy settings." - + " hasNetworkSettings=" + hasNetworkSettingsPermission - + " hasNetworkSetupWizard=" + hasNetworkSetupWizardPermission - + " DeviceOwner=" + isDeviceOwner - + " ProfileOwner=" + isProfileOwner); - } - return false; - } - - /** - * Add the network update event listener - */ - public void addOnNetworkUpdateListener(OnNetworkUpdateListener listener) { - mListeners.add(listener); - } - - /** - * Set extra failure reason for given config. Used to surface extra failure details to the UI - * @param netId The network ID of the config to set the extra failure reason for - * @param reason the WifiConfiguration.ExtraFailureReason failure code representing the most - * recent failure reason - */ - public void setRecentFailureAssociationStatus(int netId, int reason) { - WifiConfiguration config = getInternalConfiguredNetwork(netId); - if (config == null) { - return; - } - config.recentFailure.setAssociationStatus(reason); - } - - /** - * @param netId The network ID of the config to clear the extra failure reason from - */ - public void clearRecentFailureReason(int netId) { - WifiConfiguration config = getInternalConfiguredNetwork(netId); - if (config == null) { - return; - } - config.recentFailure.clear(); - } - - /** - * Find the highest RSSI among all valid scanDetails in current network's scanDetail cache. - * If scanDetail is too old, it is not considered to be valid. - * @param netId The network ID of the config to find scan RSSI - * @params scanRssiValidTimeMs The valid time for scan RSSI - * @return The highest RSSI in dBm found with current network's scanDetail cache. - */ - public int findScanRssi(int netId, int scanRssiValidTimeMs) { - int scanMaxRssi = WifiInfo.INVALID_RSSI; - ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(netId); - if (scanDetailCache == null || scanDetailCache.size() == 0) return scanMaxRssi; - long nowInMillis = mClock.getWallClockMillis(); - for (ScanDetail scanDetail : scanDetailCache.values()) { - ScanResult result = scanDetail.getScanResult(); - if (result == null) continue; - boolean valid = (nowInMillis - result.seen) < scanRssiValidTimeMs; - - if (valid) { - scanMaxRssi = Math.max(scanMaxRssi, result.level); - } - } - return scanMaxRssi; - } - - public Comparator<WifiConfiguration> getScanListComparator() { - return mScanListComparator; - } -} diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java deleted file mode 100644 index 2853bbac5..000000000 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ /dev/null @@ -1,1026 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static java.lang.Math.toIntExact; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.AlarmManager; -import android.content.Context; -import android.net.wifi.WifiMigration; -import android.os.Handler; -import android.os.UserHandle; -import android.util.AtomicFile; -import android.util.Log; -import android.util.SparseArray; -import android.util.Xml; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.FastXmlSerializer; -import com.android.internal.util.Preconditions; -import com.android.server.wifi.util.EncryptedData; -import com.android.server.wifi.util.Environment; -import com.android.server.wifi.util.FileUtils; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * This class provides a mechanism to save data to persistent store files {@link StoreFile}. - * Modules can register a {@link StoreData} instance indicating the {@StoreFile} into which they - * want to save their data to. - * - * NOTE: - * <li>Modules can register their {@StoreData} using - * {@link WifiConfigStore#registerStoreData(StoreData)} directly, but should - * use {@link WifiConfigManager#saveToStore(boolean)} for any writes.</li> - * <li>{@link WifiConfigManager} controls {@link WifiConfigStore} and initiates read at bootup and - * store file changes on user switch.</li> - * <li>Not thread safe!</li> - */ -public class WifiConfigStore { - /** - * Config store file for general shared store file. - */ - public static final int STORE_FILE_SHARED_GENERAL = 0; - /** - * Config store file for softap shared store file. - */ - public static final int STORE_FILE_SHARED_SOFTAP = 1; - /** - * Config store file for general user store file. - */ - public static final int STORE_FILE_USER_GENERAL = 2; - /** - * Config store file for network suggestions user store file. - */ - public static final int STORE_FILE_USER_NETWORK_SUGGESTIONS = 3; - - @IntDef(prefix = { "STORE_FILE_" }, value = { - STORE_FILE_SHARED_GENERAL, - STORE_FILE_SHARED_SOFTAP, - STORE_FILE_USER_GENERAL, - STORE_FILE_USER_NETWORK_SUGGESTIONS - }) - @Retention(RetentionPolicy.SOURCE) - public @interface StoreFileId { } - - private static final String XML_TAG_DOCUMENT_HEADER = "WifiConfigStoreData"; - private static final String XML_TAG_VERSION = "Version"; - private static final String XML_TAG_HEADER_INTEGRITY = "Integrity"; - /** - * Current config store data version. This will be incremented for any additions. - */ - private static final int CURRENT_CONFIG_STORE_DATA_VERSION = 3; - /** This list of older versions will be used to restore data from older config store. */ - /** - * First version of the config store data format. - */ - public static final int INITIAL_CONFIG_STORE_DATA_VERSION = 1; - /** - * Second version of the config store data format, introduced: - * - Integrity info. - */ - public static final int INTEGRITY_CONFIG_STORE_DATA_VERSION = 2; - /** - * Third version of the config store data format, - * introduced: - * - Encryption of credentials - * removed: - * - Integrity info. - */ - public static final int ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION = 3; - - @IntDef(suffix = { "_VERSION" }, value = { - INITIAL_CONFIG_STORE_DATA_VERSION, - INTEGRITY_CONFIG_STORE_DATA_VERSION, - ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION - }) - @Retention(RetentionPolicy.SOURCE) - public @interface Version { } - - /** - * Alarm tag to use for starting alarms for buffering file writes. - */ - @VisibleForTesting - public static final String BUFFERED_WRITE_ALARM_TAG = "WriteBufferAlarm"; - /** - * Log tag. - */ - private static final String TAG = "WifiConfigStore"; - /** - * Time interval for buffering file writes for non-forced writes - */ - private static final int BUFFERED_WRITE_ALARM_INTERVAL_MS = 10 * 1000; - /** - * Config store file name for general shared store file. - */ - private static final String STORE_FILE_NAME_SHARED_GENERAL = "WifiConfigStore.xml"; - /** - * Config store file name for SoftAp shared store file. - */ - private static final String STORE_FILE_NAME_SHARED_SOFTAP = "WifiConfigStoreSoftAp.xml"; - /** - * Config store file name for general user store file. - */ - private static final String STORE_FILE_NAME_USER_GENERAL = "WifiConfigStore.xml"; - /** - * Config store file name for network suggestions user store file. - */ - private static final String STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS = - "WifiConfigStoreNetworkSuggestions.xml"; - /** - * Mapping of Store file Id to Store file names. - */ - private static final SparseArray<String> STORE_ID_TO_FILE_NAME = - new SparseArray<String>() {{ - put(STORE_FILE_SHARED_GENERAL, STORE_FILE_NAME_SHARED_GENERAL); - put(STORE_FILE_SHARED_SOFTAP, STORE_FILE_NAME_SHARED_SOFTAP); - put(STORE_FILE_USER_GENERAL, STORE_FILE_NAME_USER_GENERAL); - put(STORE_FILE_USER_NETWORK_SUGGESTIONS, STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS); - }}; - /** - * Handler instance to post alarm timeouts to - */ - private final Handler mEventHandler; - /** - * Alarm manager instance to start buffer timeout alarms. - */ - private final AlarmManager mAlarmManager; - /** - * Clock instance to retrieve timestamps for alarms. - */ - private final Clock mClock; - private final WifiMetrics mWifiMetrics; - /** - * Shared config store file instance. There are 2 shared store files: - * {@link #STORE_FILE_NAME_SHARED_GENERAL} & {@link #STORE_FILE_NAME_SHARED_SOFTAP}. - */ - private final List<StoreFile> mSharedStores; - /** - * User specific store file instances. There are 2 user store files: - * {@link #STORE_FILE_NAME_USER_GENERAL} & {@link #STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS}. - */ - private List<StoreFile> mUserStores; - /** - * Verbose logging flag. - */ - private boolean mVerboseLoggingEnabled = false; - /** - * Flag to indicate if there is a buffered write pending. - */ - private boolean mBufferedWritePending = false; - /** - * Alarm listener for flushing out any buffered writes. - */ - private final AlarmManager.OnAlarmListener mBufferedWriteListener = - new AlarmManager.OnAlarmListener() { - public void onAlarm() { - try { - writeBufferedData(); - } catch (IOException e) { - Log.wtf(TAG, "Buffered write failed", e); - } - } - }; - - /** - * List of data containers. - */ - private final List<StoreData> mStoreDataList; - - /** - * Create a new instance of WifiConfigStore. - * Note: The store file instances have been made inputs to this class to ease unit-testing. - * - * @param context context to use for retrieving the alarm manager. - * @param handler handler instance to post alarm timeouts to. - * @param clock clock instance to retrieve timestamps for alarms. - * @param wifiMetrics Metrics instance. - * @param sharedStores List of {@link StoreFile} instances pointing to the shared store files. - * This should be retrieved using {@link #createSharedFiles(boolean)} - * method. - */ - public WifiConfigStore(Context context, Handler handler, Clock clock, WifiMetrics wifiMetrics, - List<StoreFile> sharedStores) { - - mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - mEventHandler = handler; - mClock = clock; - mWifiMetrics = wifiMetrics; - mStoreDataList = new ArrayList<>(); - - // Initialize the store files. - mSharedStores = sharedStores; - // The user store is initialized to null, this will be set when the user unlocks and - // CE storage is accessible via |switchUserStoresAndRead|. - mUserStores = null; - } - - /** - * Set the user store files. - * (Useful for mocking in unit tests). - * @param userStores List of {@link StoreFile} created using - * {@link #createUserFiles(int, boolean)}. - */ - public void setUserStores(@NonNull List<StoreFile> userStores) { - Preconditions.checkNotNull(userStores); - mUserStores = userStores; - } - - /** - * Register a {@link StoreData} to read/write data from/to a store. A {@link StoreData} is - * responsible for a block of data in the store file, and provides serialization/deserialization - * functions for those data. - * - * @param storeData The store data to be registered to the config store - * @return true if registered successfully, false if the store file name is not valid. - */ - public boolean registerStoreData(@NonNull StoreData storeData) { - if (storeData == null) { - Log.e(TAG, "Unable to register null store data"); - return false; - } - int storeFileId = storeData.getStoreFileId(); - if (STORE_ID_TO_FILE_NAME.get(storeFileId) == null) { - Log.e(TAG, "Invalid shared store file specified" + storeFileId); - return false; - } - mStoreDataList.add(storeData); - return true; - } - - /** - * Helper method to create a store file instance for either the shared store or user store. - * Note: The method creates the store directory if not already present. This may be needed for - * user store files. - * - * @param storeDir Base directory under which the store file is to be stored. The store file - * will be at <storeDir>/WifiConfigStore.xml. - * @param fileId Identifier for the file. See {@link StoreFileId}. - * @param userHandle User handle. Meaningful only for user specific store files. - * @param shouldEncryptCredentials Whether to encrypt credentials or not. - * @return new instance of the store file or null if the directory cannot be created. - */ - private static @Nullable StoreFile createFile(@NonNull File storeDir, - @StoreFileId int fileId, UserHandle userHandle, boolean shouldEncryptCredentials) { - if (!storeDir.exists()) { - if (!storeDir.mkdir()) { - Log.w(TAG, "Could not create store directory " + storeDir); - return null; - } - } - File file = new File(storeDir, STORE_ID_TO_FILE_NAME.get(fileId)); - WifiConfigStoreEncryptionUtil encryptionUtil = null; - if (shouldEncryptCredentials) { - encryptionUtil = new WifiConfigStoreEncryptionUtil(file.getName()); - } - return new StoreFile(file, fileId, userHandle, encryptionUtil); - } - - private static @Nullable List<StoreFile> createFiles(File storeDir, List<Integer> storeFileIds, - UserHandle userHandle, boolean shouldEncryptCredentials) { - List<StoreFile> storeFiles = new ArrayList<>(); - for (int fileId : storeFileIds) { - StoreFile storeFile = - createFile(storeDir, fileId, userHandle, shouldEncryptCredentials); - if (storeFile == null) { - return null; - } - storeFiles.add(storeFile); - } - return storeFiles; - } - - /** - * Create a new instance of the shared store file. - * - * @param shouldEncryptCredentials Whether to encrypt credentials or not. - * @return new instance of the store file or null if the directory cannot be created. - */ - public static @NonNull List<StoreFile> createSharedFiles(boolean shouldEncryptCredentials) { - return createFiles( - Environment.getWifiSharedDirectory(), - Arrays.asList(STORE_FILE_SHARED_GENERAL, STORE_FILE_SHARED_SOFTAP), - UserHandle.ALL, - shouldEncryptCredentials); - } - - /** - * Create new instances of the user specific store files. - * The user store file is inside the user's encrypted data directory. - * - * @param userId userId corresponding to the currently logged-in user. - * @param shouldEncryptCredentials Whether to encrypt credentials or not. - * @return List of new instances of the store files created or null if the directory cannot be - * created. - */ - public static @Nullable List<StoreFile> createUserFiles(int userId, - boolean shouldEncryptCredentials) { - UserHandle userHandle = UserHandle.of(userId); - return createFiles( - Environment.getWifiUserDirectory(userId), - Arrays.asList(STORE_FILE_USER_GENERAL, STORE_FILE_USER_NETWORK_SUGGESTIONS), - userHandle, - shouldEncryptCredentials); - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - } - - /** - * Retrieve the list of {@link StoreData} instances registered for the provided - * {@link StoreFile}. - */ - private List<StoreData> retrieveStoreDataListForStoreFile(@NonNull StoreFile storeFile) { - return mStoreDataList - .stream() - .filter(s -> s.getStoreFileId() == storeFile.getFileId()) - .collect(Collectors.toList()); - } - - /** - * Check if any of the provided list of {@link StoreData} instances registered - * for the provided {@link StoreFile }have indicated that they have new data to serialize. - */ - private boolean hasNewDataToSerialize(@NonNull StoreFile storeFile) { - List<StoreData> storeDataList = retrieveStoreDataListForStoreFile(storeFile); - return storeDataList.stream().anyMatch(s -> s.hasNewDataToSerialize()); - } - - /** - * API to write the data provided by registered store data to config stores. - * The method writes the user specific configurations to user specific config store and the - * shared configurations to shared config store. - * - * @param forceSync boolean to force write the config stores now. if false, the writes are - * buffered and written after the configured interval. - */ - public void write(boolean forceSync) - throws XmlPullParserException, IOException { - boolean hasAnyNewData = false; - // Serialize the provided data and send it to the respective stores. The actual write will - // be performed later depending on the |forceSync| flag . - for (StoreFile sharedStoreFile : mSharedStores) { - if (hasNewDataToSerialize(sharedStoreFile)) { - byte[] sharedDataBytes = serializeData(sharedStoreFile); - sharedStoreFile.storeRawDataToWrite(sharedDataBytes); - hasAnyNewData = true; - } - } - if (mUserStores != null) { - for (StoreFile userStoreFile : mUserStores) { - if (hasNewDataToSerialize(userStoreFile)) { - byte[] userDataBytes = serializeData(userStoreFile); - userStoreFile.storeRawDataToWrite(userDataBytes); - hasAnyNewData = true; - } - } - } - - if (hasAnyNewData) { - // Every write provides a new snapshot to be persisted, so |forceSync| flag overrides - // any pending buffer writes. - if (forceSync) { - writeBufferedData(); - } else { - startBufferedWriteAlarm(); - } - } else if (forceSync && mBufferedWritePending) { - // no new data to write, but there is a pending buffered write. So, |forceSync| should - // flush that out. - writeBufferedData(); - } - } - - /** - * Serialize all the data from all the {@link StoreData} clients registered for the provided - * {@link StoreFile}. - * - * This method also computes the integrity of the data being written and serializes the computed - * {@link EncryptedData} to the output. - * - * @param storeFile StoreFile that we want to write to. - * @return byte[] of serialized bytes - * @throws XmlPullParserException - * @throws IOException - */ - private byte[] serializeData(@NonNull StoreFile storeFile) - throws XmlPullParserException, IOException { - List<StoreData> storeDataList = retrieveStoreDataListForStoreFile(storeFile); - - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - - // First XML header. - XmlUtil.writeDocumentStart(out, XML_TAG_DOCUMENT_HEADER); - // Next version. - XmlUtil.writeNextValue(out, XML_TAG_VERSION, CURRENT_CONFIG_STORE_DATA_VERSION); - for (StoreData storeData : storeDataList) { - String tag = storeData.getName(); - XmlUtil.writeNextSectionStart(out, tag); - storeData.serializeData(out, storeFile.getEncryptionUtil()); - XmlUtil.writeNextSectionEnd(out, tag); - } - XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER); - return outputStream.toByteArray(); - } - - /** - * Helper method to start a buffered write alarm if one doesn't already exist. - */ - private void startBufferedWriteAlarm() { - if (!mBufferedWritePending) { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + BUFFERED_WRITE_ALARM_INTERVAL_MS, - BUFFERED_WRITE_ALARM_TAG, mBufferedWriteListener, mEventHandler); - mBufferedWritePending = true; - } - } - - /** - * Helper method to stop a buffered write alarm if one exists. - */ - private void stopBufferedWriteAlarm() { - if (mBufferedWritePending) { - mAlarmManager.cancel(mBufferedWriteListener); - mBufferedWritePending = false; - } - } - - /** - * Helper method to actually perform the writes to the file. This flushes out any write data - * being buffered in the respective stores and cancels any pending buffer write alarms. - */ - private void writeBufferedData() throws IOException { - stopBufferedWriteAlarm(); - - long writeStartTime = mClock.getElapsedSinceBootMillis(); - for (StoreFile sharedStoreFile : mSharedStores) { - sharedStoreFile.writeBufferedRawData(); - } - if (mUserStores != null) { - for (StoreFile userStoreFile : mUserStores) { - userStoreFile.writeBufferedRawData(); - } - } - long writeTime = mClock.getElapsedSinceBootMillis() - writeStartTime; - try { - mWifiMetrics.noteWifiConfigStoreWriteDuration(toIntExact(writeTime)); - } catch (ArithmeticException e) { - // Silently ignore on any overflow errors. - } - Log.d(TAG, "Writing to stores completed in " + writeTime + " ms."); - } - - /** - * Note: This is a copy of {@link AtomicFile#readFully()} modified to use the passed in - * {@link InputStream} which was returned using {@link AtomicFile#openRead()}. - */ - private static byte[] readAtomicFileFully(InputStream stream) throws IOException { - try { - int pos = 0; - int avail = stream.available(); - byte[] data = new byte[avail]; - while (true) { - int amt = stream.read(data, pos, data.length - pos); - if (amt <= 0) { - return data; - } - pos += amt; - avail = stream.available(); - if (avail > data.length - pos) { - byte[] newData = new byte[pos + avail]; - System.arraycopy(data, 0, newData, 0, pos); - data = newData; - } - } - } finally { - stream.close(); - } - } - - /** - * Conversion for file id's to use in WifiMigration API surface. - */ - private static Integer getMigrationStoreFileId(@StoreFileId int fileId) { - switch (fileId) { - case STORE_FILE_SHARED_GENERAL: - return WifiMigration.STORE_FILE_SHARED_GENERAL; - case STORE_FILE_SHARED_SOFTAP: - return WifiMigration.STORE_FILE_SHARED_SOFTAP; - case STORE_FILE_USER_GENERAL: - return WifiMigration.STORE_FILE_USER_GENERAL; - case STORE_FILE_USER_NETWORK_SUGGESTIONS: - return WifiMigration.STORE_FILE_USER_NETWORK_SUGGESTIONS; - default: - return null; - } - } - - private static byte[] readDataFromMigrationSharedStoreFile(@StoreFileId int fileId) - throws IOException { - Integer migrationStoreFileId = getMigrationStoreFileId(fileId); - if (migrationStoreFileId == null) return null; - InputStream migrationIs = - WifiMigration.convertAndRetrieveSharedConfigStoreFile(migrationStoreFileId); - if (migrationIs == null) return null; - return readAtomicFileFully(migrationIs); - } - - private static byte[] readDataFromMigrationUserStoreFile(@StoreFileId int fileId, - UserHandle userHandle) throws IOException { - Integer migrationStoreFileId = getMigrationStoreFileId(fileId); - if (migrationStoreFileId == null) return null; - InputStream migrationIs = - WifiMigration.convertAndRetrieveUserConfigStoreFile( - migrationStoreFileId, userHandle); - if (migrationIs == null) return null; - return readAtomicFileFully(migrationIs); - } - - /** - * Helper method to read from the shared store files. - * @throws XmlPullParserException - * @throws IOException - */ - private void readFromSharedStoreFiles() throws XmlPullParserException, IOException { - for (StoreFile sharedStoreFile : mSharedStores) { - byte[] sharedDataBytes = - readDataFromMigrationSharedStoreFile(sharedStoreFile.getFileId()); - if (sharedDataBytes == null) { - // nothing to migrate, do normal read. - sharedDataBytes = sharedStoreFile.readRawData(); - } else { - Log.i(TAG, "Read data out of shared migration store file: " - + sharedStoreFile.getName()); - // Save the migrated file contents to the regular store file and delete the - // migrated stored file. - sharedStoreFile.storeRawDataToWrite(sharedDataBytes); - sharedStoreFile.writeBufferedRawData(); - // Note: If the migrated store file is at the same location as the store file, - // then the OEM implementation should ignore this remove. - WifiMigration.removeSharedConfigStoreFile( - getMigrationStoreFileId(sharedStoreFile.getFileId())); - } - deserializeData(sharedDataBytes, sharedStoreFile); - } - } - - /** - * Helper method to read from the user store files. - * @throws XmlPullParserException - * @throws IOException - */ - private void readFromUserStoreFiles() throws XmlPullParserException, IOException { - for (StoreFile userStoreFile : mUserStores) { - byte[] userDataBytes = readDataFromMigrationUserStoreFile( - userStoreFile.getFileId(), userStoreFile.mUserHandle); - if (userDataBytes == null) { - // nothing to migrate, do normal read. - userDataBytes = userStoreFile.readRawData(); - } else { - Log.i(TAG, "Read data out of user migration store file: " - + userStoreFile.getName()); - // Save the migrated file contents to the regular store file and delete the - // migrated stored file. - userStoreFile.storeRawDataToWrite(userDataBytes); - userStoreFile.writeBufferedRawData(); - // Note: If the migrated store file is at the same location as the store file, - // then the OEM implementation should ignore this remove. - WifiMigration.removeUserConfigStoreFile( - getMigrationStoreFileId(userStoreFile.getFileId()), - userStoreFile.mUserHandle); - } - deserializeData(userDataBytes, userStoreFile); - } - } - - /** - * API to read the store data from the config stores. - * The method reads the user specific configurations from user specific config store and the - * shared configurations from the shared config store. - */ - public void read() throws XmlPullParserException, IOException { - // Reset both share and user store data. - for (StoreFile sharedStoreFile : mSharedStores) { - resetStoreData(sharedStoreFile); - } - if (mUserStores != null) { - for (StoreFile userStoreFile : mUserStores) { - resetStoreData(userStoreFile); - } - } - long readStartTime = mClock.getElapsedSinceBootMillis(); - readFromSharedStoreFiles(); - if (mUserStores != null) { - readFromUserStoreFiles(); - } - long readTime = mClock.getElapsedSinceBootMillis() - readStartTime; - try { - mWifiMetrics.noteWifiConfigStoreReadDuration(toIntExact(readTime)); - } catch (ArithmeticException e) { - // Silently ignore on any overflow errors. - } - Log.d(TAG, "Reading from all stores completed in " + readTime + " ms."); - } - - /** - * Handles a user switch. This method changes the user specific store files and reads from the - * new user's store files. - * - * @param userStores List of {@link StoreFile} created using {@link #createUserFiles(int)}. - */ - public void switchUserStoresAndRead(@NonNull List<StoreFile> userStores) - throws XmlPullParserException, IOException { - Preconditions.checkNotNull(userStores); - // Reset user store data. - if (mUserStores != null) { - for (StoreFile userStoreFile : mUserStores) { - resetStoreData(userStoreFile); - } - } - - // Stop any pending buffered writes, if any. - stopBufferedWriteAlarm(); - mUserStores = userStores; - - // Now read from the user store files. - long readStartTime = mClock.getElapsedSinceBootMillis(); - readFromUserStoreFiles(); - long readTime = mClock.getElapsedSinceBootMillis() - readStartTime; - mWifiMetrics.noteWifiConfigStoreReadDuration(toIntExact(readTime)); - Log.d(TAG, "Reading from user stores completed in " + readTime + " ms."); - } - - /** - * Reset data for all {@link StoreData} instances registered for this {@link StoreFile}. - */ - private void resetStoreData(@NonNull StoreFile storeFile) { - for (StoreData storeData: retrieveStoreDataListForStoreFile(storeFile)) { - storeData.resetData(); - } - } - - // Inform all the provided store data clients that there is nothing in the store for them. - private void indicateNoDataForStoreDatas(Collection<StoreData> storeDataSet, - @Version int version, @NonNull WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - for (StoreData storeData : storeDataSet) { - storeData.deserializeData(null, 0, version, encryptionUtil); - } - } - - /** - * Deserialize data from a {@link StoreFile} for all {@link StoreData} instances registered. - * - * This method also computes the integrity of the incoming |dataBytes| and compare with - * {@link EncryptedData} parsed from |dataBytes|. If the integrity check fails, the data - * is discarded. - * - * @param dataBytes The data to parse - * @param storeFile StoreFile that we read from. Will be used to retrieve the list of clients - * who have data to deserialize from this file. - * - * @throws XmlPullParserException - * @throws IOException - */ - private void deserializeData(@NonNull byte[] dataBytes, @NonNull StoreFile storeFile) - throws XmlPullParserException, IOException { - List<StoreData> storeDataList = retrieveStoreDataListForStoreFile(storeFile); - if (dataBytes == null) { - indicateNoDataForStoreDatas(storeDataList, -1 /* unknown */, - storeFile.getEncryptionUtil()); - return; - } - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(dataBytes); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - - // Start parsing the XML stream. - int rootTagDepth = in.getDepth() + 1; - XmlUtil.gotoDocumentStart(in, XML_TAG_DOCUMENT_HEADER); - - @Version int version = parseVersionFromXml(in); - // Version 2 contains the now unused integrity data, parse & then discard the information. - if (version == INTEGRITY_CONFIG_STORE_DATA_VERSION) { - parseAndDiscardIntegrityDataFromXml(in, rootTagDepth); - } - - String[] headerName = new String[1]; - Set<StoreData> storeDatasInvoked = new HashSet<>(); - while (XmlUtil.gotoNextSectionOrEnd(in, headerName, rootTagDepth)) { - // There can only be 1 store data matching the tag, O indicates a previous StoreData - // module that no longer exists (ignore this XML section). - StoreData storeData = storeDataList.stream() - .filter(s -> s.getName().equals(headerName[0])) - .findAny() - .orElse(null); - if (storeData == null) { - Log.e(TAG, "Unknown store data: " + headerName[0] + ". List of store data: " - + storeDataList); - continue; - } - storeData.deserializeData(in, rootTagDepth + 1, version, - storeFile.getEncryptionUtil()); - storeDatasInvoked.add(storeData); - } - // Inform all the other registered store data clients that there is nothing in the store - // for them. - Set<StoreData> storeDatasNotInvoked = new HashSet<>(storeDataList); - storeDatasNotInvoked.removeAll(storeDatasInvoked); - indicateNoDataForStoreDatas(storeDatasNotInvoked, version, storeFile.getEncryptionUtil()); - } - - /** - * Parse the version from the XML stream. - * This is used for both the shared and user config store data. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @return version number retrieved from the Xml stream. - */ - private static @Version int parseVersionFromXml(XmlPullParser in) - throws XmlPullParserException, IOException { - int version = (int) XmlUtil.readNextValueWithName(in, XML_TAG_VERSION); - if (version < INITIAL_CONFIG_STORE_DATA_VERSION - || version > CURRENT_CONFIG_STORE_DATA_VERSION) { - throw new XmlPullParserException("Invalid version of data: " + version); - } - return version; - } - - /** - * Parse the integrity data structure from the XML stream and discard it. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth Outer tag depth. - */ - private static void parseAndDiscardIntegrityDataFromXml(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - XmlUtil.gotoNextSectionWithName(in, XML_TAG_HEADER_INTEGRITY, outerTagDepth); - XmlUtil.EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); - } - - /** - * Dump the local log buffer and other internal state of WifiConfigManager. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WifiConfigStore"); - pw.println("WifiConfigStore - Store File Begin ----"); - Stream.of(mSharedStores, mUserStores) - .flatMap(List::stream) - .forEach((storeFile) -> { - pw.print("Name: " + storeFile.mFileName); - pw.print(", File Id: " + storeFile.mFileId); - pw.println(", Credentials encrypted: " - + (storeFile.getEncryptionUtil() != null)); - }); - pw.println("WifiConfigStore - Store Data Begin ----"); - for (StoreData storeData : mStoreDataList) { - pw.print("StoreData =>"); - pw.print(" "); - pw.print("Name: " + storeData.getName()); - pw.print(", "); - pw.print("File Id: " + storeData.getStoreFileId()); - pw.print(", "); - pw.println("File Name: " + STORE_ID_TO_FILE_NAME.get(storeData.getStoreFileId())); - } - pw.println("WifiConfigStore - Store Data End ----"); - } - - /** - * Class to encapsulate all file writes. This is a wrapper over {@link AtomicFile} to write/read - * raw data from the persistent file with integrity. This class provides helper methods to - * read/write the entire file into a byte array. - * This helps to separate out the processing, parsing, and integrity checking from the actual - * file writing. - */ - public static class StoreFile { - /** - * File permissions to lock down the file. - */ - private static final int FILE_MODE = 0600; - /** - * The store file to be written to. - */ - private final AtomicFile mAtomicFile; - /** - * This is an intermediate buffer to store the data to be written. - */ - private byte[] mWriteData; - /** - * Store the file name for setting the file permissions/logging purposes. - */ - private final String mFileName; - /** - * {@link StoreFileId} Type of store file. - */ - private final @StoreFileId int mFileId; - /** - * User handle. Meaningful only for user specific store files. - */ - private final UserHandle mUserHandle; - /** - * Integrity checking for the store file. - */ - private final WifiConfigStoreEncryptionUtil mEncryptionUtil; - - public StoreFile(File file, @StoreFileId int fileId, - @NonNull UserHandle userHandle, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) { - mAtomicFile = new AtomicFile(file); - mFileName = file.getAbsolutePath(); - mFileId = fileId; - mUserHandle = userHandle; - mEncryptionUtil = encryptionUtil; - } - - public String getName() { - return mAtomicFile.getBaseFile().getName(); - } - - public @StoreFileId int getFileId() { - return mFileId; - } - - /** - * @return Returns the encryption util used for this store file. - */ - public @Nullable WifiConfigStoreEncryptionUtil getEncryptionUtil() { - return mEncryptionUtil; - } - - /** - * Read the entire raw data from the store file and return in a byte array. - * - * @return raw data read from the file or null if the file is not found or the data has - * been altered. - * @throws IOException if an error occurs. The input stream is always closed by the method - * even when an exception is encountered. - */ - public byte[] readRawData() throws IOException { - byte[] bytes = null; - try { - bytes = mAtomicFile.readFully(); - } catch (FileNotFoundException e) { - return null; - } - return bytes; - } - - /** - * Store the provided byte array to be written when {@link #writeBufferedRawData()} method - * is invoked. - * This intermediate step is needed to help in buffering file writes. - * - * @param data raw data to be written to the file. - */ - public void storeRawDataToWrite(byte[] data) { - mWriteData = data; - } - - /** - * Write the stored raw data to the store file. - * After the write to file, the mWriteData member is reset. - * @throws IOException if an error occurs. The output stream is always closed by the method - * even when an exception is encountered. - */ - public void writeBufferedRawData() throws IOException { - if (mWriteData == null) return; // No data to write for this file. - // Write the data to the atomic file. - FileOutputStream out = null; - try { - out = mAtomicFile.startWrite(); - FileUtils.chmod(mFileName, FILE_MODE); - out.write(mWriteData); - mAtomicFile.finishWrite(out); - } catch (IOException e) { - if (out != null) { - mAtomicFile.failWrite(out); - } - throw e; - } - // Reset the pending write data after write. - mWriteData = null; - } - } - - /** - * Interface to be implemented by a module that contained data in the config store file. - * - * The module will be responsible for serializing/deserializing their own data. - * Whenever {@link WifiConfigStore#read()} is invoked, all registered StoreData instances will - * be notified that a read was performed via {@link StoreData#deserializeData( - * XmlPullParser, int)} regardless of whether there is any data for them or not in the - * store file. - * - * Note: StoreData clients that need a config store read to kick-off operations should wait - * for the {@link StoreData#deserializeData(XmlPullParser, int)} invocation. - */ - public interface StoreData { - /** - * Serialize a XML data block to the output stream. - * - * @param out The output stream to serialize the data to - * @param encryptionUtil Utility to help encrypt any credential data. - */ - void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException; - - /** - * Deserialize a XML data block from the input stream. - * - * @param in The input stream to read the data from. This could be null if there is - * nothing in the store. - * @param outerTagDepth The depth of the outer tag in the XML document - * @param version Version of config store file. - * @param encryptionUtil Utility to help decrypt any credential data. - * - * Note: This will be invoked every time a store file is read, even if there is nothing - * in the store for them. - */ - void deserializeData(@Nullable XmlPullParser in, int outerTagDepth, @Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException; - - /** - * Reset configuration data. - */ - void resetData(); - - /** - * Check if there is any new data to persist from the last write. - * - * @return true if the module has new data to persist, false otherwise. - */ - boolean hasNewDataToSerialize(); - - /** - * Return the name of this store data. The data will be enclosed under this tag in - * the XML block. - * - * @return The name of the store data - */ - String getName(); - - /** - * File Id where this data needs to be written to. - * This should be one of {@link #STORE_FILE_SHARED_GENERAL}, - * {@link #STORE_FILE_USER_GENERAL} or - * {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}. - * - * Note: For most uses, the shared or user general store is sufficient. Creating and - * managing store files are expensive. Only use specific store files if you have a large - * amount of data which may not need to be persisted frequently (or at least not as - * frequently as the general store). - * @return Id of the file where this data needs to be persisted. - */ - @StoreFileId int getStoreFileId(); - } -} diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java deleted file mode 100644 index 336d97810..000000000 --- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java +++ /dev/null @@ -1,894 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiManager.ALL_ZEROS_MAC_ADDRESS; - -import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes; - -import android.net.IpConfiguration; -import android.net.MacAddress; -import android.net.StaticIpConfiguration; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiNetworkSpecifier; -import android.net.wifi.WifiScanner; -import android.os.PatternMatcher; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.NativeUtil; - -import java.nio.charset.StandardCharsets; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Comparator; -import java.util.Objects; - -/** - * WifiConfiguration utility for any {@link android.net.wifi.WifiConfiguration} related operations. - * Currently contains: - * > Helper method to check if the WifiConfiguration object is visible to the provided users. - * > Helper methods to identify the encryption of a WifiConfiguration object. - */ -public class WifiConfigurationUtil { - private static final String TAG = "WifiConfigurationUtil"; - - /** - * Constants used for validating external config objects. - */ - private static final int ENCLOSING_QUOTES_LEN = 2; - private static final int SSID_UTF_8_MIN_LEN = 1 + ENCLOSING_QUOTES_LEN; - private static final int SSID_UTF_8_MAX_LEN = 32 + ENCLOSING_QUOTES_LEN; - private static final int SSID_HEX_MIN_LEN = 2; - private static final int SSID_HEX_MAX_LEN = 64; - private static final int PSK_ASCII_MIN_LEN = 8 + ENCLOSING_QUOTES_LEN; - private static final int SAE_ASCII_MIN_LEN = 1 + ENCLOSING_QUOTES_LEN; - private static final int PSK_SAE_ASCII_MAX_LEN = 63 + ENCLOSING_QUOTES_LEN; - private static final int PSK_SAE_HEX_LEN = 64; - - @VisibleForTesting - public static final String PASSWORD_MASK = "*"; - private static final String MATCH_EMPTY_SSID_PATTERN_PATH = ""; - private static final Pair<MacAddress, MacAddress> MATCH_NONE_BSSID_PATTERN = - new Pair<>(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS); - private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN = - new Pair<>(ALL_ZEROS_MAC_ADDRESS, ALL_ZEROS_MAC_ADDRESS); - - /** - * Checks if the provided |wepKeys| array contains any non-null value; - */ - public static boolean hasAnyValidWepKey(String[] wepKeys) { - for (int i = 0; i < wepKeys.length; i++) { - if (wepKeys[i] != null) { - return true; - } - } - return false; - } - - /** - * Helper method to check if the provided |config| corresponds to a PSK network or not. - */ - public static boolean isConfigForPskNetwork(WifiConfiguration config) { - return config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK); - } - - /** - * Helper method to check if the provided |config| corresponds to a WAPI PSK network or not. - */ - public static boolean isConfigForWapiPskNetwork(WifiConfiguration config) { - return config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK); - } - - /** - * Helper method to check if the provided |config| corresponds to a WAPI CERT network or not. - */ - public static boolean isConfigForWapiCertNetwork(WifiConfiguration config) { - return config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_CERT); - } - - /** - * Helper method to check if the provided |config| corresponds to an SAE network or not. - */ - public static boolean isConfigForSaeNetwork(WifiConfiguration config) { - return config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE); - } - - /** - * Helper method to check if the provided |config| corresponds to an OWE network or not. - */ - public static boolean isConfigForOweNetwork(WifiConfiguration config) { - return config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE); - } - - /** - * Helper method to check if the provided |config| corresponds to a EAP network or not. - */ - public static boolean isConfigForEapNetwork(WifiConfiguration config) { - return (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) - || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)); - } - - /** - * Helper method to check if the provided |config| corresponds to a EAP Suite-B network or not. - */ - public static boolean isConfigForEapSuiteBNetwork(WifiConfiguration config) { - return config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192); - } - - /** - * Helper method to check if the provided |config| corresponds to a WEP network or not. - */ - public static boolean isConfigForWepNetwork(WifiConfiguration config) { - return (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE) - && hasAnyValidWepKey(config.wepKeys)); - } - - /** - * Helper method to check if the provided |config| corresponds to an open or enhanced - * open network, or not. - */ - public static boolean isConfigForOpenNetwork(WifiConfiguration config) { - return (!(isConfigForWepNetwork(config) || isConfigForPskNetwork(config) - || isConfigForEapNetwork(config) || isConfigForSaeNetwork(config) - || isConfigForEapSuiteBNetwork(config))); - } - - /** - * Compare existing and new WifiConfiguration objects after a network update and return if - * IP parameters have changed or not. - * - * @param existingConfig Existing WifiConfiguration object corresponding to the network. - * @param newConfig New WifiConfiguration object corresponding to the network. - * @return true if IP parameters have changed, false otherwise. - */ - public static boolean hasIpChanged(WifiConfiguration existingConfig, - WifiConfiguration newConfig) { - if (existingConfig.getIpAssignment() != newConfig.getIpAssignment()) { - return true; - } - if (newConfig.getIpAssignment() == IpConfiguration.IpAssignment.STATIC) { - return !Objects.equals(existingConfig.getStaticIpConfiguration(), - newConfig.getStaticIpConfiguration()); - } - return false; - } - - /** - * Compare existing and new WifiConfiguration objects after a network update and return if - * proxy parameters have changed or not. - * - * @param existingConfig Existing WifiConfiguration object corresponding to the network. - * @param newConfig New WifiConfiguration object corresponding to the network. - * @return true if proxy parameters have changed, false if no existing config and proxy settings - * are NONE, false otherwise. - */ - public static boolean hasProxyChanged(WifiConfiguration existingConfig, - WifiConfiguration newConfig) { - if (existingConfig == null) { - return newConfig.getProxySettings() != IpConfiguration.ProxySettings.NONE; - } - if (newConfig.getProxySettings() != existingConfig.getProxySettings()) { - return true; - } - return !Objects.equals(existingConfig.getHttpProxy(), newConfig.getHttpProxy()); - } - - /** - * Compare existing and new WifiConfiguration objects after a network update and return if - * MAC randomization setting has changed or not. - * @param existingConfig Existing WifiConfiguration object corresponding to the network. - * @param newConfig New WifiConfiguration object corresponding to the network. - * @return true if MAC randomization setting setting changed or the existing confiuration is - * null and the newConfig is setting macRandomizationSetting to the default value. - */ - public static boolean hasMacRandomizationSettingsChanged(WifiConfiguration existingConfig, - WifiConfiguration newConfig) { - if (existingConfig == null) { - return newConfig.macRandomizationSetting != WifiConfiguration.RANDOMIZATION_PERSISTENT; - } - return newConfig.macRandomizationSetting != existingConfig.macRandomizationSetting; - } - - /** - * Compare existing and new WifiEnterpriseConfig objects after a network update and return if - * credential parameters have changed or not. - * - * @param existingEnterpriseConfig Existing WifiConfiguration object corresponding to the - * network. - * @param newEnterpriseConfig New WifiConfiguration object corresponding to the network. - * @return true if credentials have changed, false otherwise. - */ - @VisibleForTesting - public static boolean hasEnterpriseConfigChanged(WifiEnterpriseConfig existingEnterpriseConfig, - WifiEnterpriseConfig newEnterpriseConfig) { - if (existingEnterpriseConfig != null && newEnterpriseConfig != null) { - if (existingEnterpriseConfig.getEapMethod() != newEnterpriseConfig.getEapMethod()) { - return true; - } - if (existingEnterpriseConfig.isAuthenticationSimBased()) { - // No other credential changes for SIM based methods. - // The SIM card is the credential. - return false; - } - if (existingEnterpriseConfig.getPhase2Method() - != newEnterpriseConfig.getPhase2Method()) { - return true; - } - if (!TextUtils.equals(existingEnterpriseConfig.getIdentity(), - newEnterpriseConfig.getIdentity())) { - return true; - } - if (!TextUtils.equals(existingEnterpriseConfig.getAnonymousIdentity(), - newEnterpriseConfig.getAnonymousIdentity())) { - return true; - } - if (!TextUtils.equals(existingEnterpriseConfig.getPassword(), - newEnterpriseConfig.getPassword())) { - return true; - } - X509Certificate[] existingCaCerts = existingEnterpriseConfig.getCaCertificates(); - X509Certificate[] newCaCerts = newEnterpriseConfig.getCaCertificates(); - if (!Arrays.equals(existingCaCerts, newCaCerts)) { - return true; - } - if (!Arrays.equals(newEnterpriseConfig.getCaCertificateAliases(), - existingEnterpriseConfig.getCaCertificateAliases())) { - return true; - } - if (!TextUtils.equals(newEnterpriseConfig.getClientCertificateAlias(), - existingEnterpriseConfig.getClientCertificateAlias())) { - return true; - } - if (!TextUtils.equals(newEnterpriseConfig.getAltSubjectMatch(), - existingEnterpriseConfig.getAltSubjectMatch())) { - return true; - } - if (newEnterpriseConfig.getOcsp() != existingEnterpriseConfig.getOcsp()) { - return true; - } - } else { - // One of the configs may have an enterpriseConfig - if (existingEnterpriseConfig != null || newEnterpriseConfig != null) { - return true; - } - } - return false; - } - - /** - * Compare existing and new WifiConfiguration objects after a network update and return if - * credential parameters have changed or not. - * - * @param existingConfig Existing WifiConfiguration object corresponding to the network. - * @param newConfig New WifiConfiguration object corresponding to the network. - * @return true if credentials have changed, false otherwise. - */ - public static boolean hasCredentialChanged(WifiConfiguration existingConfig, - WifiConfiguration newConfig) { - if (!Objects.equals(existingConfig.allowedKeyManagement, - newConfig.allowedKeyManagement)) { - return true; - } - if (!Objects.equals(existingConfig.allowedProtocols, newConfig.allowedProtocols)) { - return true; - } - if (!Objects.equals(existingConfig.allowedAuthAlgorithms, - newConfig.allowedAuthAlgorithms)) { - return true; - } - if (!Objects.equals(existingConfig.allowedPairwiseCiphers, - newConfig.allowedPairwiseCiphers)) { - return true; - } - if (!Objects.equals(existingConfig.allowedGroupCiphers, - newConfig.allowedGroupCiphers)) { - return true; - } - if (!Objects.equals(existingConfig.allowedGroupManagementCiphers, - newConfig.allowedGroupManagementCiphers)) { - return true; - } - if (!Objects.equals(existingConfig.allowedSuiteBCiphers, - newConfig.allowedSuiteBCiphers)) { - return true; - } - if (!Objects.equals(existingConfig.preSharedKey, newConfig.preSharedKey)) { - return true; - } - if (!Arrays.equals(existingConfig.wepKeys, newConfig.wepKeys)) { - return true; - } - if (existingConfig.wepTxKeyIndex != newConfig.wepTxKeyIndex) { - return true; - } - if (existingConfig.hiddenSSID != newConfig.hiddenSSID) { - return true; - } - if (existingConfig.requirePmf != newConfig.requirePmf) { - return true; - } - if (existingConfig.carrierId != newConfig.carrierId) { - return true; - } - if (hasEnterpriseConfigChanged(existingConfig.enterpriseConfig, - newConfig.enterpriseConfig)) { - return true; - } - return false; - } - - private static boolean validateSsid(String ssid, boolean isAdd) { - if (isAdd) { - if (ssid == null) { - Log.e(TAG, "validateSsid : null string"); - return false; - } - } else { - if (ssid == null) { - // This is an update, so the SSID can be null if that is not being changed. - return true; - } - } - if (ssid.isEmpty()) { - Log.e(TAG, "validateSsid failed: empty string"); - return false; - } - if (ssid.startsWith("\"")) { - // UTF-8 SSID string - byte[] ssidBytes = ssid.getBytes(StandardCharsets.UTF_8); - if (ssidBytes.length < SSID_UTF_8_MIN_LEN) { - Log.e(TAG, "validateSsid failed: utf-8 ssid string size too small: " - + ssidBytes.length); - return false; - } - if (ssidBytes.length > SSID_UTF_8_MAX_LEN) { - Log.e(TAG, "validateSsid failed: utf-8 ssid string size too large: " - + ssidBytes.length); - return false; - } - } else { - // HEX SSID string - if (ssid.length() < SSID_HEX_MIN_LEN) { - Log.e(TAG, "validateSsid failed: hex string size too small: " + ssid.length()); - return false; - } - if (ssid.length() > SSID_HEX_MAX_LEN) { - Log.e(TAG, "validateSsid failed: hex string size too large: " + ssid.length()); - return false; - } - } - try { - NativeUtil.decodeSsid(ssid); - } catch (IllegalArgumentException e) { - Log.e(TAG, "validateSsid failed: malformed string: " + ssid); - return false; - } - return true; - } - - private static boolean validateBssid(MacAddress bssid) { - if (bssid == null) return true; - if (bssid.getAddressType() != MacAddress.TYPE_UNICAST) { - Log.e(TAG, "validateBssid failed: invalid bssid"); - return false; - } - return true; - } - - private static boolean validateBssid(String bssid) { - if (bssid == null) return true; - if (bssid.isEmpty()) { - Log.e(TAG, "validateBssid failed: empty string"); - return false; - } - MacAddress bssidMacAddress; - try { - bssidMacAddress = MacAddress.fromString(bssid); - } catch (IllegalArgumentException e) { - Log.e(TAG, "validateBssid failed: malformed string: " + bssid); - return false; - } - if (!validateBssid(bssidMacAddress)) { - return false; - } - return true; - } - - private static boolean validatePassword(String password, boolean isAdd, boolean isSae) { - if (isAdd) { - if (password == null) { - Log.e(TAG, "validatePassword: null string"); - return false; - } - } else { - if (password == null) { - // This is an update, so the psk can be null if that is not being changed. - return true; - } else if (password.equals(PASSWORD_MASK)) { - // This is an update, so the app might have returned back the masked password, let - // it thru. WifiConfigManager will handle it. - return true; - } - } - if (password.isEmpty()) { - Log.e(TAG, "validatePassword failed: empty string"); - return false; - } - if (password.startsWith("\"")) { - // ASCII PSK string - byte[] passwordBytes = password.getBytes(StandardCharsets.US_ASCII); - int targetMinLength; - - if (isSae) { - targetMinLength = SAE_ASCII_MIN_LEN; - } else { - targetMinLength = PSK_ASCII_MIN_LEN; - } - if (passwordBytes.length < targetMinLength) { - Log.e(TAG, "validatePassword failed: ASCII string size too small: " - + passwordBytes.length); - return false; - } - if (passwordBytes.length > PSK_SAE_ASCII_MAX_LEN) { - Log.e(TAG, "validatePassword failed: ASCII string size too large: " - + passwordBytes.length); - return false; - } - } else { - // HEX PSK string - if (password.length() != PSK_SAE_HEX_LEN) { - Log.e(TAG, "validatePassword failed: hex string size mismatch: " - + password.length()); - return false; - } - } - try { - NativeUtil.hexOrQuotedStringToBytes(password); - } catch (IllegalArgumentException e) { - Log.e(TAG, "validatePassword failed: malformed string: " + password); - return false; - } - return true; - } - - private static boolean validateBitSet(BitSet bitSet, int validValuesLength) { - if (bitSet == null) return false; - BitSet clonedBitset = (BitSet) bitSet.clone(); - clonedBitset.clear(0, validValuesLength); - return clonedBitset.isEmpty(); - } - - private static boolean validateBitSets(WifiConfiguration config) { - // 1. Check |allowedKeyManagement|. - if (!validateBitSet(config.allowedKeyManagement, - WifiConfiguration.KeyMgmt.strings.length)) { - Log.e(TAG, "validateBitsets failed: invalid allowedKeyManagement bitset " - + config.allowedKeyManagement); - return false; - } - // 2. Check |allowedProtocols|. - if (!validateBitSet(config.allowedProtocols, - WifiConfiguration.Protocol.strings.length)) { - Log.e(TAG, "validateBitsets failed: invalid allowedProtocols bitset " - + config.allowedProtocols); - return false; - } - // 3. Check |allowedAuthAlgorithms|. - if (!validateBitSet(config.allowedAuthAlgorithms, - WifiConfiguration.AuthAlgorithm.strings.length)) { - Log.e(TAG, "validateBitsets failed: invalid allowedAuthAlgorithms bitset " - + config.allowedAuthAlgorithms); - return false; - } - // 4. Check |allowedGroupCiphers|. - if (!validateBitSet(config.allowedGroupCiphers, - WifiConfiguration.GroupCipher.strings.length)) { - Log.e(TAG, "validateBitsets failed: invalid allowedGroupCiphers bitset " - + config.allowedGroupCiphers); - return false; - } - // 5. Check |allowedPairwiseCiphers|. - if (!validateBitSet(config.allowedPairwiseCiphers, - WifiConfiguration.PairwiseCipher.strings.length)) { - Log.e(TAG, "validateBitsets failed: invalid allowedPairwiseCiphers bitset " - + config.allowedPairwiseCiphers); - return false; - } - return true; - } - - private static boolean validateKeyMgmt(BitSet keyMgmnt) { - if (keyMgmnt.cardinality() > 1) { - if (keyMgmnt.cardinality() > 3) { - Log.e(TAG, "validateKeyMgmt failed: cardinality > 3"); - return false; - } - if (!keyMgmnt.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { - Log.e(TAG, "validateKeyMgmt failed: not WPA_EAP"); - return false; - } - if (!keyMgmnt.get(WifiConfiguration.KeyMgmt.IEEE8021X) - && !keyMgmnt.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - Log.e(TAG, "validateKeyMgmt failed: not PSK or 8021X"); - return false; - } - if (keyMgmnt.cardinality() == 3 - && !keyMgmnt.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) { - Log.e(TAG, "validateKeyMgmt failed: not SUITE_B_192"); - return false; - } - } - return true; - } - - private static boolean validateIpConfiguration(IpConfiguration ipConfig) { - if (ipConfig == null) { - Log.e(TAG, "validateIpConfiguration failed: null IpConfiguration"); - return false; - } - if (ipConfig.getIpAssignment() == IpConfiguration.IpAssignment.STATIC) { - StaticIpConfiguration staticIpConfig = ipConfig.getStaticIpConfiguration(); - if (staticIpConfig == null) { - Log.e(TAG, "validateIpConfiguration failed: null StaticIpConfiguration"); - return false; - } - if (staticIpConfig.getIpAddress() == null) { - Log.e(TAG, "validateIpConfiguration failed: null static ip Address"); - return false; - } - } - return true; - } - - /** - * Enums to specify if the provided config is being validated for add or update. - */ - public static final boolean VALIDATE_FOR_ADD = true; - public static final boolean VALIDATE_FOR_UPDATE = false; - - /** - * Validate the configuration received from an external application. - * - * This method checks for the following parameters: - * 1. {@link WifiConfiguration#SSID} - * 2. {@link WifiConfiguration#BSSID} - * 3. {@link WifiConfiguration#preSharedKey} - * 4. {@link WifiConfiguration#allowedKeyManagement} - * 5. {@link WifiConfiguration#allowedProtocols} - * 6. {@link WifiConfiguration#allowedAuthAlgorithms} - * 7. {@link WifiConfiguration#allowedGroupCiphers} - * 8. {@link WifiConfiguration#allowedPairwiseCiphers} - * 9. {@link WifiConfiguration#getIpConfiguration()} - * - * @param config {@link WifiConfiguration} received from an external application. - * @param isAdd {@link #VALIDATE_FOR_ADD} to indicate a network config received for an add, - * {@link #VALIDATE_FOR_UPDATE} for a network config received for an update. - * These 2 cases need to be handled differently because the config received for an - * update could contain only the fields that are being changed. - * @return true if the parameters are valid, false otherwise. - */ - public static boolean validate(WifiConfiguration config, boolean isAdd) { - if (!validateSsid(config.SSID, isAdd)) { - return false; - } - if (!validateBssid(config.BSSID)) { - return false; - } - if (!validateBitSets(config)) { - return false; - } - if (!validateKeyMgmt(config.allowedKeyManagement)) { - return false; - } - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) - && !validatePassword(config.preSharedKey, isAdd, false)) { - return false; - } - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) { - // PMF mandatory for OWE networks - if (!config.requirePmf) { - Log.e(TAG, "PMF must be enabled for OWE networks"); - return false; - } - } - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { - // PMF mandatory for WPA3-Personal networks - if (!config.requirePmf) { - Log.e(TAG, "PMF must be enabled for SAE networks"); - return false; - } - if (!validatePassword(config.preSharedKey, isAdd, true)) { - return false; - } - } - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) { - // PMF mandatory for WPA3-Enterprise networks - if (!config.requirePmf) { - Log.e(TAG, "PMF must be enabled for Suite-B 192-bit networks"); - return false; - } - } - // b/153435438: Added to deal with badly formed WifiConfiguration from apps. - if (config.preSharedKey != null && !config.needsPreSharedKey()) { - Log.e(TAG, "preSharedKey set with an invalid KeyMgmt, resetting KeyMgmt to WPA_PSK"); - config.allowedKeyManagement.clear(); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - } - if (!validateIpConfiguration(config.getIpConfiguration())) { - return false; - } - // TBD: Validate some enterprise params as well in the future here. - return true; - } - - private static boolean validateBssidPattern( - Pair<MacAddress, MacAddress> bssidPatternMatcher) { - if (bssidPatternMatcher == null) return true; - MacAddress baseAddress = bssidPatternMatcher.first; - MacAddress mask = bssidPatternMatcher.second; - if (baseAddress.getAddressType() != MacAddress.TYPE_UNICAST) { - Log.e(TAG, "validateBssidPatternMatcher failed : invalid base address: " + baseAddress); - return false; - } - if (mask.equals(ALL_ZEROS_MAC_ADDRESS) - && !baseAddress.equals(ALL_ZEROS_MAC_ADDRESS)) { - Log.e(TAG, "validateBssidPatternMatcher failed : invalid mask/base: " + mask + "/" - + baseAddress); - return false; - } - // TBD: Can we do any more sanity checks? - return true; - } - - // TODO(b/113878056): Some of this is duplicated in {@link WifiNetworkConfigBuilder}. - // Merge them somehow?. - private static boolean isValidNetworkSpecifier(WifiNetworkSpecifier specifier) { - PatternMatcher ssidPatternMatcher = specifier.ssidPatternMatcher; - Pair<MacAddress, MacAddress> bssidPatternMatcher = specifier.bssidPatternMatcher; - if (ssidPatternMatcher == null || bssidPatternMatcher == null) { - return false; - } - if (ssidPatternMatcher.getPath() == null || bssidPatternMatcher.first == null - || bssidPatternMatcher.second == null) { - return false; - } - return true; - } - - private static boolean isMatchNoneNetworkSpecifier(WifiNetworkSpecifier specifier) { - PatternMatcher ssidPatternMatcher = specifier.ssidPatternMatcher; - Pair<MacAddress, MacAddress> bssidPatternMatcher = specifier.bssidPatternMatcher; - if (ssidPatternMatcher.getType() != PatternMatcher.PATTERN_PREFIX - && ssidPatternMatcher.getPath().equals(MATCH_EMPTY_SSID_PATTERN_PATH)) { - return true; - } - if (bssidPatternMatcher.equals(MATCH_NONE_BSSID_PATTERN)) { - return true; - } - return false; - } - - private static boolean isMatchAllNetworkSpecifier(WifiNetworkSpecifier specifier) { - PatternMatcher ssidPatternMatcher = specifier.ssidPatternMatcher; - Pair<MacAddress, MacAddress> bssidPatternMatcher = specifier.bssidPatternMatcher; - if (ssidPatternMatcher.match(MATCH_EMPTY_SSID_PATTERN_PATH) - && bssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN)) { - return true; - } - return false; - } - - /** - * Validate the configuration received from an external application inside - * {@link WifiNetworkSpecifier}. - * - * This method checks for the following parameters: - * 1. {@link WifiNetworkSpecifier#ssidPatternMatcher} - * 2. {@link WifiNetworkSpecifier#bssidPatternMatcher} - * 3. {@link WifiConfiguration#SSID} - * 4. {@link WifiConfiguration#BSSID} - * 5. {@link WifiConfiguration#preSharedKey} - * 6. {@link WifiConfiguration#allowedKeyManagement} - * 7. {@link WifiConfiguration#allowedProtocols} - * 8. {@link WifiConfiguration#allowedAuthAlgorithms} - * 9. {@link WifiConfiguration#allowedGroupCiphers} - * 10. {@link WifiConfiguration#allowedPairwiseCiphers} - * 11. {@link WifiConfiguration#getIpConfiguration()} - * - * @param specifier Instance of {@link WifiNetworkSpecifier}. - * @return true if the parameters are valid, false otherwise. - */ - public static boolean validateNetworkSpecifier(WifiNetworkSpecifier specifier) { - if (!isValidNetworkSpecifier(specifier)) { - Log.e(TAG, "validateNetworkSpecifier failed : invalid network specifier"); - return false; - } - if (isMatchNoneNetworkSpecifier(specifier)) { - Log.e(TAG, "validateNetworkSpecifier failed : match-none specifier"); - return false; - } - if (isMatchAllNetworkSpecifier(specifier)) { - Log.e(TAG, "validateNetworkSpecifier failed : match-all specifier"); - return false; - } - WifiConfiguration config = specifier.wifiConfiguration; - if (specifier.ssidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) { - // For literal SSID matches, the value should satisfy SSID requirements. - // WifiConfiguration.SSID needs quotes around ASCII SSID. - if (!validateSsid(addEnclosingQuotes(specifier.ssidPatternMatcher.getPath()), true)) { - return false; - } - } else { - if (config.hiddenSSID) { - Log.e(TAG, "validateNetworkSpecifier failed : ssid pattern not supported " - + "for hidden networks"); - return false; - } - } - if (Objects.equals(specifier.bssidPatternMatcher.second, MacAddress.BROADCAST_ADDRESS)) { - // For literal BSSID matches, the value should satisfy MAC address requirements. - if (!validateBssid(specifier.bssidPatternMatcher.first)) { - return false; - } - } else { - if (!validateBssidPattern(specifier.bssidPatternMatcher)) { - return false; - } - } - if (!validateBitSets(config)) { - return false; - } - if (!validateKeyMgmt(config.allowedKeyManagement)) { - return false; - } - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) - && !validatePassword(config.preSharedKey, true, false)) { - return false; - } - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) { - // PMF mandatory for OWE networks - if (!config.requirePmf) { - return false; - } - } - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { - // PMF mandatory for WPA3-Personal networks - if (!config.requirePmf) { - return false; - } - if (!validatePassword(config.preSharedKey, true, true)) { - return false; - } - } - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) { - // PMF mandatory for WPA3-Enterprise networks - if (!config.requirePmf) { - return false; - } - } - // TBD: Validate some enterprise params as well in the future here. - return true; - } - - /** - * Check if the provided two networks are the same. - * Note: This does not check if network selection BSSID's are the same. - * - * @param config Configuration corresponding to a network. - * @param config1 Configuration corresponding to another network. - * - * @return true if |config| and |config1| are the same network. - * false otherwise. - */ - public static boolean isSameNetwork(WifiConfiguration config, WifiConfiguration config1) { - if (config == null && config1 == null) { - return true; - } - if (config == null || config1 == null) { - return false; - } - if (config.networkId != config1.networkId) { - return false; - } - if (!Objects.equals(config.SSID, config1.SSID)) { - return false; - } - if (WifiConfigurationUtil.hasCredentialChanged(config, config1)) { - return false; - } - return true; - } - - /** - * Create a PnoNetwork object from the provided WifiConfiguration. - * - * @param config Configuration corresponding to the network. - * @return PnoNetwork object corresponding to the network. - */ - public static WifiScanner.PnoSettings.PnoNetwork createPnoNetwork( - WifiConfiguration config) { - WifiScanner.PnoSettings.PnoNetwork pnoNetwork = - new WifiScanner.PnoSettings.PnoNetwork(config.SSID); - if (config.hiddenSSID) { - pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN; - } - pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND; - pnoNetwork.flags |= WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND; - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_PSK; - } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) - || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) { - pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_EAPOL; - } else { - pnoNetwork.authBitField |= WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_OPEN; - } - return pnoNetwork; - } - - - /** - * General WifiConfiguration list sorting algorithm: - * 1, Place the fully enabled networks first. - * 2. Next place all the temporarily disabled networks. - * 3. Place the permanently disabled networks last (Permanently disabled networks are removed - * before WifiConfigManager uses this comparator today!). - * - * Among the networks with the same status, sort them in the order determined by the return of - * {@link #compareNetworksWithSameStatus(WifiConfiguration, WifiConfiguration)} method - * implementation. - */ - public abstract static class WifiConfigurationComparator implements - Comparator<WifiConfiguration> { - private static final int ENABLED_NETWORK_SCORE = 3; - private static final int TEMPORARY_DISABLED_NETWORK_SCORE = 2; - private static final int PERMANENTLY_DISABLED_NETWORK_SCORE = 1; - - @Override - public int compare(WifiConfiguration a, WifiConfiguration b) { - int configAScore = getNetworkStatusScore(a); - int configBScore = getNetworkStatusScore(b); - if (configAScore == configBScore) { - return compareNetworksWithSameStatus(a, b); - } else { - return Integer.compare(configBScore, configAScore); - } - } - - // This needs to be implemented by the connected/disconnected PNO list comparator. - abstract int compareNetworksWithSameStatus(WifiConfiguration a, WifiConfiguration b); - - /** - * Returns an integer representing a score for each configuration. The scores are assigned - * based on the status of the configuration. The scores are assigned according to the order: - * Fully enabled network > Temporarily disabled network > Permanently disabled network. - */ - private int getNetworkStatusScore(WifiConfiguration config) { - if (config.getNetworkSelectionStatus().isNetworkEnabled()) { - return ENABLED_NETWORK_SCORE; - } else if (config.getNetworkSelectionStatus().isNetworkTemporaryDisabled()) { - return TEMPORARY_DISABLED_NETWORK_SCORE; - } else { - return PERMANENTLY_DISABLED_NETWORK_SCORE; - } - } - } -} diff --git a/service/java/com/android/server/wifi/WifiConnectivityHelper.java b/service/java/com/android/server/wifi/WifiConnectivityHelper.java deleted file mode 100644 index 248877f3b..000000000 --- a/service/java/com/android/server/wifi/WifiConnectivityHelper.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static android.net.wifi.WifiManager.WIFI_FEATURE_CONTROL_ROAMING; - -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.util.ArrayList; - -/** - * This class provides helper functions for Wifi connectivity related modules to - * access WifiNative. It starts with firmware roaming. TODO(b/34819513): Move operations - * such as connection to network and legacy framework roaming here. - * - * NOTE: This class is not thread safe and should only be used from the main Wifi thread. - */ -public class WifiConnectivityHelper { - private static final String TAG = "WifiConnectivityHelper"; - @VisibleForTesting - public static int INVALID_LIST_SIZE = -1; - private final WifiNative mWifiNative; - private boolean mFirmwareRoamingSupported = false; - private int mMaxNumBlacklistBssid = INVALID_LIST_SIZE; - private int mMaxNumWhitelistSsid = INVALID_LIST_SIZE; - - WifiConnectivityHelper(WifiNative wifiNative) { - mWifiNative = wifiNative; - } - - /** - * Query firmware if it supports - * {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING}. If yes, get the firmware - * roaming capabilities. If firmware roaming is supported but we fail to get the roaming - * capabilities or the returned capability values are invalid, we fall back to framework - * roaming. - * - * @return true if succeed, false if firmware roaming is supported but fail to get valid - * roaming capabilities. - */ - public boolean getFirmwareRoamingInfo() { - mFirmwareRoamingSupported = false; - mMaxNumBlacklistBssid = INVALID_LIST_SIZE; - mMaxNumWhitelistSsid = INVALID_LIST_SIZE; - - long fwFeatureSet = - mWifiNative.getSupportedFeatureSet(mWifiNative.getClientInterfaceName()); - Log.d(TAG, "Firmware supported feature set: " + Long.toHexString(fwFeatureSet)); - - if ((fwFeatureSet & WIFI_FEATURE_CONTROL_ROAMING) == 0) { - Log.d(TAG, "Firmware roaming is not supported"); - return true; - } - - WifiNative.RoamingCapabilities roamingCap = new WifiNative.RoamingCapabilities(); - if (mWifiNative.getRoamingCapabilities(mWifiNative.getClientInterfaceName(), roamingCap)) { - if (roamingCap.maxBlacklistSize < 0 || roamingCap.maxWhitelistSize < 0) { - Log.e(TAG, "Invalid firmware roaming capabilities: max num blacklist bssid=" - + roamingCap.maxBlacklistSize + " max num whitelist ssid=" - + roamingCap.maxWhitelistSize); - } else { - mFirmwareRoamingSupported = true; - mMaxNumBlacklistBssid = roamingCap.maxBlacklistSize; - mMaxNumWhitelistSsid = roamingCap.maxWhitelistSize; - Log.d(TAG, "Firmware roaming supported with capabilities: max num blacklist bssid=" - + mMaxNumBlacklistBssid + " max num whitelist ssid=" - + mMaxNumWhitelistSsid); - return true; - } - } else { - Log.e(TAG, "Failed to get firmware roaming capabilities"); - } - - return false; - } - - /** - * Return if firmware roaming is supported. - */ - public boolean isFirmwareRoamingSupported() { - return mFirmwareRoamingSupported; - } - - /** - * Get the maximum size of BSSID blacklist firmware supports. - * - * @return INVALID_LIST_SIZE if firmware roaming is not supported, or - * maximum size of the BSSID blacklist firmware supports. - */ - public int getMaxNumBlacklistBssid() { - if (mFirmwareRoamingSupported) { - return mMaxNumBlacklistBssid; - } else { - Log.e(TAG, "getMaxNumBlacklistBssid: Firmware roaming is not supported"); - return INVALID_LIST_SIZE; - } - } - - /** - * Get the maximum size of SSID whitelist firmware supports. - * - * @return INVALID_LIST_SIZE if firmware roaming is not supported, or - * maximum size of the SSID whitelist firmware supports. - */ - public int getMaxNumWhitelistSsid() { - if (mFirmwareRoamingSupported) { - return mMaxNumWhitelistSsid; - } else { - Log.e(TAG, "getMaxNumWhitelistSsid: Firmware roaming is not supported"); - return INVALID_LIST_SIZE; - } - } - - /** - * Write firmware roaming configuration to firmware. - * - * @param blacklistBssids BSSIDs to be blacklisted - * @param whitelistSsids SSIDs to be whitelisted - * @return true if succeeded, false otherwise. - */ - public boolean setFirmwareRoamingConfiguration(ArrayList<String> blacklistBssids, - ArrayList<String> whitelistSsids) { - if (!mFirmwareRoamingSupported) { - Log.e(TAG, "Firmware roaming is not supported"); - return false; - } - - if (blacklistBssids == null || whitelistSsids == null) { - Log.e(TAG, "Invalid firmware roaming configuration settings"); - return false; - } - - int blacklistSize = blacklistBssids.size(); - int whitelistSize = whitelistSsids.size(); - - if (blacklistSize > mMaxNumBlacklistBssid || whitelistSize > mMaxNumWhitelistSsid) { - Log.e(TAG, "Invalid BSSID blacklist size " + blacklistSize + " SSID whitelist size " - + whitelistSize + ". Max blacklist size: " + mMaxNumBlacklistBssid - + ", max whitelist size: " + mMaxNumWhitelistSsid); - return false; - } - - WifiNative.RoamingConfig roamConfig = new WifiNative.RoamingConfig(); - roamConfig.blacklistBssids = blacklistBssids; - roamConfig.whitelistSsids = whitelistSsids; - - return mWifiNative.configureRoaming(mWifiNative.getClientInterfaceName(), roamConfig); - } -} diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java deleted file mode 100644 index 77af65400..000000000 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ /dev/null @@ -1,1976 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static com.android.internal.util.Preconditions.checkNotNull; -import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE; - -import android.annotation.NonNull; -import android.app.AlarmManager; -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.DeviceMobilityState; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.PnoSettings; -import android.net.wifi.WifiScanner.ScanSettings; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.Process; -import android.os.WorkSource; -import android.util.ArrayMap; -import android.util.LocalLog; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * This class manages all the connectivity related scanning activities. - * - * When the screen is turned on or off, WiFi is connected or disconnected, - * or on-demand, a scan is initiatiated and the scan results are passed - * to WifiNetworkSelector for it to make a recommendation on which network - * to connect to. - */ -public class WifiConnectivityManager { - public static final String WATCHDOG_TIMER_TAG = - "WifiConnectivityManager Schedule Watchdog Timer"; - public static final String PERIODIC_SCAN_TIMER_TAG = - "WifiConnectivityManager Schedule Periodic Scan Timer"; - public static final String RESTART_SINGLE_SCAN_TIMER_TAG = - "WifiConnectivityManager Restart Single Scan"; - public static final String RESTART_CONNECTIVITY_SCAN_TIMER_TAG = - "WifiConnectivityManager Restart Scan"; - public static final String DELAYED_PARTIAL_SCAN_TIMER_TAG = - "WifiConnectivityManager Schedule Delayed Partial Scan Timer"; - - private static final long RESET_TIME_STAMP = Long.MIN_VALUE; - // Constants to indicate whether a scan should start immediately or - // it should comply to the minimum scan interval rule. - private static final boolean SCAN_IMMEDIATELY = true; - private static final boolean SCAN_ON_SCHEDULE = false; - - // PNO scan interval in milli-seconds. This is the scan - // performed when screen is off and connected. - private static final int CONNECTED_PNO_SCAN_INTERVAL_MS = 160 * 1000; // 160 seconds - // When a network is found by PNO scan but gets rejected by Wifi Network Selector due - // to its low RSSI value, scan will be reschduled in an exponential back off manner. - private static final int LOW_RSSI_NETWORK_RETRY_START_DELAY_MS = 20 * 1000; // 20 seconds - private static final int LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS = 80 * 1000; // 80 seconds - // Maximum number of retries when starting a scan failed - @VisibleForTesting - public static final int MAX_SCAN_RESTART_ALLOWED = 5; - // Number of milli-seconds to delay before retry starting - // a previously failed scan - private static final int RESTART_SCAN_DELAY_MS = 2 * 1000; // 2 seconds - // When in disconnected mode, a watchdog timer will be fired - // every WATCHDOG_INTERVAL_MS to start a single scan. This is - // to prevent caveat from things like PNO scan. - private static final int WATCHDOG_INTERVAL_MS = 20 * 60 * 1000; // 20 minutes - // Restricted channel list age out value. - private static final long CHANNEL_LIST_AGE_MS = 60 * 60 * 1000; // 1 hour - // This is the time interval for the connection attempt rate calculation. Connection attempt - // timestamps beyond this interval is evicted from the list. - public static final int MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS = 4 * 60 * 1000; // 4 mins - // Max number of connection attempts in the above time interval. - public static final int MAX_CONNECTION_ATTEMPTS_RATE = 6; - private static final int TEMP_BSSID_BLOCK_DURATION = 10 * 1000; // 10 seconds - // Maximum age of frequencies last seen to be included in pno scans. (30 days) - private static final long MAX_PNO_SCAN_FREQUENCY_AGE_MS = (long) 1000 * 3600 * 24 * 30; - // ClientModeImpl has a bunch of states. From the - // WifiConnectivityManager's perspective it only cares - // if it is in Connected state, Disconnected state or in - // transition between these two states. - public static final int WIFI_STATE_UNKNOWN = 0; - public static final int WIFI_STATE_CONNECTED = 1; - public static final int WIFI_STATE_DISCONNECTED = 2; - public static final int WIFI_STATE_TRANSITIONING = 3; - - // Initial scan state, used to manage performing partial scans in initial scans - // Initial scans are the first scan after enabling Wifi or turning on screen when disconnected - private static final int INITIAL_SCAN_STATE_START = 0; - private static final int INITIAL_SCAN_STATE_AWAITING_RESPONSE = 1; - private static final int INITIAL_SCAN_STATE_COMPLETE = 2; - - // Log tag for this class - private static final String TAG = "WifiConnectivityManager"; - private static final String ALL_SINGLE_SCAN_LISTENER = "AllSingleScanListener"; - private static final String PNO_SCAN_LISTENER = "PnoScanListener"; - - private final Context mContext; - private final ClientModeImpl mStateMachine; - private final WifiInjector mWifiInjector; - private final WifiConfigManager mConfigManager; - private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private final WifiInfo mWifiInfo; - private final WifiConnectivityHelper mConnectivityHelper; - private final WifiNetworkSelector mNetworkSelector; - private final WifiLastResortWatchdog mWifiLastResortWatchdog; - private final OpenNetworkNotifier mOpenNetworkNotifier; - private final WifiMetrics mWifiMetrics; - private final AlarmManager mAlarmManager; - private final Handler mEventHandler; - private final Clock mClock; - private final ScoringParams mScoringParams; - private final LocalLog mLocalLog; - private final LinkedList<Long> mConnectionAttemptTimeStamps; - private final BssidBlocklistMonitor mBssidBlocklistMonitor; - private WifiScanner mScanner; - private WifiScoreCard mWifiScoreCard; - - private boolean mDbg = false; - private boolean mVerboseLoggingEnabled = false; - private boolean mWifiEnabled = false; - private boolean mAutoJoinEnabled = false; // disabled by default, enabled by external triggers - private boolean mRunning = false; - private boolean mScreenOn = false; - private int mWifiState = WIFI_STATE_UNKNOWN; - private int mInitialScanState = INITIAL_SCAN_STATE_COMPLETE; - private boolean mAutoJoinEnabledExternal = true; // enabled by default - private boolean mUntrustedConnectionAllowed = false; - private boolean mTrustedConnectionAllowed = false; - private boolean mSpecificNetworkRequestInProgress = false; - private int mScanRestartCount = 0; - private int mSingleScanRestartCount = 0; - private int mTotalConnectivityAttemptsRateLimited = 0; - private String mLastConnectionAttemptBssid = null; - private long mLastPeriodicSingleScanTimeStamp = RESET_TIME_STAMP; - private long mLastNetworkSelectionTimeStamp = RESET_TIME_STAMP; - private boolean mPnoScanStarted = false; - private boolean mPeriodicScanTimerSet = false; - private boolean mDelayedPartialScanTimerSet = false; - - // Used for Initial Scan metrics - private boolean mFailedInitialPartialScan = false; - private int mInitialPartialScanChannelCount; - - // Device configs - private boolean mWaitForFullBandScanResults = false; - - // Scanning Schedules - // Default schedule used in case of invalid configuration - private static final int[] DEFAULT_SCANNING_SCHEDULE_SEC = {20, 40, 80, 160}; - private int[] mConnectedSingleScanScheduleSec; - private int[] mDisconnectedSingleScanScheduleSec; - private int[] mConnectedSingleSavedNetworkSingleScanScheduleSec; - private List<WifiCandidates.Candidate> mLatestCandidates = null; - private long mLatestCandidatesTimestampMs = 0; - - private final Object mLock = new Object(); - - @GuardedBy("mLock") - private int[] mCurrentSingleScanScheduleSec; - - private int mCurrentSingleScanScheduleIndex; - private WifiChannelUtilization mWifiChannelUtilization; - // Cached WifiCandidates used in high mobility state to avoid connecting to APs that are - // moving relative to the user. - private CachedWifiCandidates mCachedWifiCandidates = null; - private @DeviceMobilityState int mDeviceMobilityState = - WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN; - - // A helper to log debugging information in the local log buffer, which can - // be retrieved in bugreport. - private void localLog(String log) { - mLocalLog.log(log); - if (mVerboseLoggingEnabled) Log.v(TAG, log); - } - - /** - * Enable verbose logging for WifiConnectivityManager. - */ - public void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - } - - // A periodic/PNO scan will be rescheduled up to MAX_SCAN_RESTART_ALLOWED times - // if the start scan command failed. A timer is used here to make it a deferred retry. - private final AlarmManager.OnAlarmListener mRestartScanListener = - new AlarmManager.OnAlarmListener() { - public void onAlarm() { - startConnectivityScan(SCAN_IMMEDIATELY); - } - }; - - // A single scan will be rescheduled up to MAX_SCAN_RESTART_ALLOWED times - // if the start scan command failed. An timer is used here to make it a deferred retry. - private class RestartSingleScanListener implements AlarmManager.OnAlarmListener { - private final boolean mIsFullBandScan; - - RestartSingleScanListener(boolean isFullBandScan) { - mIsFullBandScan = isFullBandScan; - } - - @Override - public void onAlarm() { - startSingleScan(mIsFullBandScan, WIFI_WORK_SOURCE); - } - } - - // As a watchdog mechanism, a single scan will be scheduled every WATCHDOG_INTERVAL_MS - // if it is in the WIFI_STATE_DISCONNECTED state. - private final AlarmManager.OnAlarmListener mWatchdogListener = - new AlarmManager.OnAlarmListener() { - public void onAlarm() { - watchdogHandler(); - } - }; - - // Due to b/28020168, timer based single scan will be scheduled - // to provide periodic scan in an exponential backoff fashion. - private final AlarmManager.OnAlarmListener mPeriodicScanTimerListener = - new AlarmManager.OnAlarmListener() { - public void onAlarm() { - periodicScanTimerHandler(); - } - }; - - private final AlarmManager.OnAlarmListener mDelayedPartialScanTimerListener = - new AlarmManager.OnAlarmListener() { - public void onAlarm() { - if (mCachedWifiCandidates == null - || mCachedWifiCandidates.frequencies == null - || mCachedWifiCandidates.frequencies.size() == 0) { - return; - } - ScanSettings settings = new ScanSettings(); - settings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - settings.band = getScanBand(false); - settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - settings.numBssidsPerScan = 0; - int index = 0; - settings.channels = - new WifiScanner.ChannelSpec[mCachedWifiCandidates.frequencies.size()]; - for (Integer freq : mCachedWifiCandidates.frequencies) { - settings.channels[index++] = new WifiScanner.ChannelSpec(freq); - } - SingleScanListener singleScanListener = new SingleScanListener(false); - mScanner.startScan(settings, new HandlerExecutor(mEventHandler), - singleScanListener, WIFI_WORK_SOURCE); - mWifiMetrics.incrementConnectivityOneshotScanCount(); - } - }; - - /** - * Handles 'onResult' callbacks for the Periodic, Single & Pno ScanListener. - * Executes selection of potential network candidates, initiation of connection attempt to that - * network. - * - * @return true - if a candidate is selected by WifiNetworkSelector - * false - if no candidate is selected by WifiNetworkSelector - */ - private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName, - boolean isFullScan) { - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization( - mStateMachine.getWifiLinkLayerStats(), WifiChannelUtilization.UNKNOWN_FREQ); - - updateUserDisabledList(scanDetails); - - // Check if any blocklisted BSSIDs can be freed. - mBssidBlocklistMonitor.tryEnablingBlockedBssids(scanDetails); - Set<String> bssidBlocklist = mBssidBlocklistMonitor.updateAndGetBssidBlocklistForSsid( - mWifiInfo.getSSID()); - - if (mStateMachine.isSupplicantTransientState()) { - localLog(listenerName - + " onResults: No network selection because supplicantTransientState is " - + mStateMachine.isSupplicantTransientState()); - return false; - } - - localLog(listenerName + " onResults: start network selection"); - - List<WifiCandidates.Candidate> candidates = mNetworkSelector.getCandidatesFromScan( - scanDetails, bssidBlocklist, mWifiInfo, mStateMachine.isConnected(), - mStateMachine.isDisconnected(), mUntrustedConnectionAllowed); - mLatestCandidates = candidates; - mLatestCandidatesTimestampMs = mClock.getElapsedSinceBootMillis(); - - if (mDeviceMobilityState == WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT - && mContext.getResources().getBoolean( - R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled)) { - candidates = filterCandidatesHighMovement(candidates, listenerName, isFullScan); - } - - WifiConfiguration candidate = mNetworkSelector.selectNetwork(candidates); - mLastNetworkSelectionTimeStamp = mClock.getElapsedSinceBootMillis(); - mWifiLastResortWatchdog.updateAvailableNetworks( - mNetworkSelector.getConnectableScanDetails()); - mWifiMetrics.countScanResults(scanDetails); - if (candidate != null) { - localLog(listenerName + ": WNS candidate-" + candidate.SSID); - connectToNetwork(candidate); - return true; - } else { - if (mWifiState == WIFI_STATE_DISCONNECTED) { - mOpenNetworkNotifier.handleScanResults( - mNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks()); - } - return false; - } - } - - private List<WifiCandidates.Candidate> filterCandidatesHighMovement( - List<WifiCandidates.Candidate> candidates, String listenerName, boolean isFullScan) { - boolean isNotPartialScan = isFullScan || listenerName.equals(PNO_SCAN_LISTENER); - if (candidates == null || candidates.isEmpty()) { - // No connectable networks nearby or network selection is unnecessary - if (isNotPartialScan) { - mCachedWifiCandidates = new CachedWifiCandidates(mClock.getElapsedSinceBootMillis(), - null); - } - return null; - } - - long minimumTimeBetweenScansMs = mContext.getResources().getInteger( - R.integer.config_wifiHighMovementNetworkSelectionOptimizationScanDelayMs); - if (mCachedWifiCandidates != null && mCachedWifiCandidates.candidateRssiMap != null) { - // cached candidates are too recent, wait for next scan - if (mClock.getElapsedSinceBootMillis() - mCachedWifiCandidates.timeSinceBootMs - < minimumTimeBetweenScansMs) { - mWifiMetrics.incrementNumHighMovementConnectionSkipped(); - return null; - } - - int rssiDelta = mContext.getResources().getInteger(R.integer - .config_wifiHighMovementNetworkSelectionOptimizationRssiDelta); - List<WifiCandidates.Candidate> filteredCandidates = candidates.stream().filter( - item -> mCachedWifiCandidates.candidateRssiMap.containsKey(item.getKey()) - && Math.abs(mCachedWifiCandidates.candidateRssiMap.get(item.getKey()) - - item.getScanRssi()) < rssiDelta) - .collect(Collectors.toList()); - - if (!filteredCandidates.isEmpty()) { - if (isNotPartialScan) { - mCachedWifiCandidates = - new CachedWifiCandidates(mClock.getElapsedSinceBootMillis(), - candidates); - } - mWifiMetrics.incrementNumHighMovementConnectionStarted(); - return filteredCandidates; - } - } - - // Either no cached candidates, or all candidates got filtered out. - // Update the cached candidates here and schedule a delayed partial scan. - if (isNotPartialScan) { - mCachedWifiCandidates = new CachedWifiCandidates(mClock.getElapsedSinceBootMillis(), - candidates); - localLog("Found " + candidates.size() + " candidates at high mobility state. " - + "Re-doing scan to confirm network quality."); - scheduleDelayedPartialScan(minimumTimeBetweenScansMs); - } - mWifiMetrics.incrementNumHighMovementConnectionSkipped(); - return null; - } - - private void updateUserDisabledList(List<ScanDetail> scanDetails) { - List<String> results = new ArrayList<>(); - List<ScanResult> passpointAp = new ArrayList<>(); - for (ScanDetail scanDetail : scanDetails) { - results.add(ScanResultUtil.createQuotedSSID(scanDetail.getScanResult().SSID)); - if (!scanDetail.getScanResult().isPasspointNetwork()) { - continue; - } - passpointAp.add(scanDetail.getScanResult()); - } - if (!passpointAp.isEmpty()) { - results.addAll(new ArrayList<>(mWifiInjector.getPasspointManager() - .getAllMatchingPasspointProfilesForScanResults(passpointAp).keySet())); - } - mConfigManager.updateUserDisabledList(results); - } - - /** - * Set whether bluetooth is in the connected state - */ - public void setBluetoothConnected(boolean isBluetoothConnected) { - mNetworkSelector.setBluetoothConnected(isBluetoothConnected); - } - - private class CachedWifiCandidates { - public final long timeSinceBootMs; - public final Map<WifiCandidates.Key, Integer> candidateRssiMap; - public final Set<Integer> frequencies; - - CachedWifiCandidates(long timeSinceBootMs, List<WifiCandidates.Candidate> candidates) { - this.timeSinceBootMs = timeSinceBootMs; - if (candidates == null) { - this.candidateRssiMap = null; - this.frequencies = null; - } else { - this.candidateRssiMap = new ArrayMap<WifiCandidates.Key, Integer>(); - this.frequencies = new HashSet<Integer>(); - for (WifiCandidates.Candidate c : candidates) { - candidateRssiMap.put(c.getKey(), c.getScanRssi()); - frequencies.add(c.getFrequency()); - } - } - } - } - - // All single scan results listener. - // - // Note: This is the listener for all the available single scan results, - // including the ones initiated by WifiConnectivityManager and - // other modules. - private class AllSingleScanListener implements WifiScanner.ScanListener { - private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); - private int mNumScanResultsIgnoredDueToSingleRadioChain = 0; - - public void clearScanDetails() { - mScanDetails.clear(); - mNumScanResultsIgnoredDueToSingleRadioChain = 0; - } - - @Override - public void onSuccess() { - } - - @Override - public void onFailure(int reason, String description) { - localLog("registerScanListener onFailure:" - + " reason: " + reason + " description: " + description); - } - - @Override - public void onPeriodChanged(int periodInMs) { - } - - @Override - public void onResults(WifiScanner.ScanData[] results) { - if (!mWifiEnabled || !mAutoJoinEnabled) { - clearScanDetails(); - mWaitForFullBandScanResults = false; - return; - } - - // We treat any full band scans (with DFS or not) as "full". - boolean isFullBandScanResults = false; - if (results != null && results.length > 0) { - isFullBandScanResults = - WifiScanner.isFullBandScan(results[0].getBandScanned(), true); - } - // Full band scan results only. - if (mWaitForFullBandScanResults) { - if (!isFullBandScanResults) { - localLog("AllSingleScanListener waiting for full band scan results."); - clearScanDetails(); - return; - } else { - mWaitForFullBandScanResults = false; - } - } - if (results != null && results.length > 0) { - mWifiMetrics.incrementAvailableNetworksHistograms(mScanDetails, - isFullBandScanResults); - } - if (mNumScanResultsIgnoredDueToSingleRadioChain > 0) { - Log.i(TAG, "Number of scan results ignored due to single radio chain scan: " - + mNumScanResultsIgnoredDueToSingleRadioChain); - } - boolean wasConnectAttempted = handleScanResults(mScanDetails, - ALL_SINGLE_SCAN_LISTENER, isFullBandScanResults); - clearScanDetails(); - - // Update metrics to see if a single scan detected a valid network - // while PNO scan didn't. - // Note: We don't update the background scan metrics any more as it is - // not in use. - if (mPnoScanStarted) { - if (wasConnectAttempted) { - mWifiMetrics.incrementNumConnectivityWatchdogPnoBad(); - } else { - mWifiMetrics.incrementNumConnectivityWatchdogPnoGood(); - } - } - - // Check if we are in the middle of initial partial scan - if (mInitialScanState == INITIAL_SCAN_STATE_AWAITING_RESPONSE) { - // Done with initial scan - setInitialScanState(INITIAL_SCAN_STATE_COMPLETE); - - if (wasConnectAttempted) { - Log.i(TAG, "Connection attempted with the reduced initial scans"); - schedulePeriodicScanTimer( - getScheduledSingleScanIntervalMs(mCurrentSingleScanScheduleIndex)); - mWifiMetrics.reportInitialPartialScan(mInitialPartialScanChannelCount, true); - mInitialPartialScanChannelCount = 0; - } else { - Log.i(TAG, "Connection was not attempted, issuing a full scan"); - startConnectivityScan(SCAN_IMMEDIATELY); - mFailedInitialPartialScan = true; - } - } else if (mInitialScanState == INITIAL_SCAN_STATE_COMPLETE) { - if (mFailedInitialPartialScan && wasConnectAttempted) { - // Initial scan failed, but following full scan succeeded - mWifiMetrics.reportInitialPartialScan(mInitialPartialScanChannelCount, false); - } - mFailedInitialPartialScan = false; - mInitialPartialScanChannelCount = 0; - } - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - if (!mWifiEnabled || !mAutoJoinEnabled) { - return; - } - - if (mDbg) { - localLog("AllSingleScanListener onFullResult: " + fullScanResult.SSID - + " capabilities " + fullScanResult.capabilities); - } - - // When the scan result has radio chain info, ensure we throw away scan results - // not received with both radio chains (if |mUseSingleRadioChainScanResults| is false). - if (!mContext.getResources().getBoolean( - R.bool.config_wifi_framework_use_single_radio_chain_scan_results_network_selection) - && fullScanResult.radioChainInfos != null - && fullScanResult.radioChainInfos.length == 1) { - // Keep track of the number of dropped scan results for logging. - mNumScanResultsIgnoredDueToSingleRadioChain++; - return; - } - - mScanDetails.add(ScanResultUtil.toScanDetail(fullScanResult)); - } - } - - private final AllSingleScanListener mAllSingleScanListener = new AllSingleScanListener(); - - // Single scan results listener. A single scan is initiated when - // DisconnectedPNO scan found a valid network and woke up - // the system, or by the watchdog timer, or to form the timer based - // periodic scan. - // - // Note: This is the listener for the single scans initiated by the - // WifiConnectivityManager. - private class SingleScanListener implements WifiScanner.ScanListener { - private final boolean mIsFullBandScan; - - SingleScanListener(boolean isFullBandScan) { - mIsFullBandScan = isFullBandScan; - } - - @Override - public void onSuccess() { - } - - @Override - public void onFailure(int reason, String description) { - localLog("SingleScanListener onFailure:" - + " reason: " + reason + " description: " + description); - - // reschedule the scan - if (mSingleScanRestartCount++ < MAX_SCAN_RESTART_ALLOWED) { - scheduleDelayedSingleScan(mIsFullBandScan); - } else { - mSingleScanRestartCount = 0; - localLog("Failed to successfully start single scan for " - + MAX_SCAN_RESTART_ALLOWED + " times"); - } - } - - @Override - public void onPeriodChanged(int periodInMs) { - localLog("SingleScanListener onPeriodChanged: " - + "actual scan period " + periodInMs + "ms"); - } - - @Override - public void onResults(WifiScanner.ScanData[] results) { - mSingleScanRestartCount = 0; - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - } - } - - // PNO scan results listener for both disconnected and connected PNO scanning. - // A PNO scan is initiated when screen is off. - private class PnoScanListener implements WifiScanner.PnoScanListener { - private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); - private int mLowRssiNetworkRetryDelay = - LOW_RSSI_NETWORK_RETRY_START_DELAY_MS; - - public void clearScanDetails() { - mScanDetails.clear(); - } - - // Reset to the start value when either a non-PNO scan is started or - // WifiNetworkSelector selects a candidate from the PNO scan results. - public void resetLowRssiNetworkRetryDelay() { - mLowRssiNetworkRetryDelay = LOW_RSSI_NETWORK_RETRY_START_DELAY_MS; - } - - @VisibleForTesting - public int getLowRssiNetworkRetryDelay() { - return mLowRssiNetworkRetryDelay; - } - - @Override - public void onSuccess() { - } - - @Override - public void onFailure(int reason, String description) { - localLog("PnoScanListener onFailure:" - + " reason: " + reason + " description: " + description); - - // reschedule the scan - if (mScanRestartCount++ < MAX_SCAN_RESTART_ALLOWED) { - scheduleDelayedConnectivityScan(RESTART_SCAN_DELAY_MS); - } else { - mScanRestartCount = 0; - localLog("Failed to successfully start PNO scan for " - + MAX_SCAN_RESTART_ALLOWED + " times"); - } - } - - @Override - public void onPeriodChanged(int periodInMs) { - localLog("PnoScanListener onPeriodChanged: " - + "actual scan period " + periodInMs + "ms"); - } - - // Currently the PNO scan results doesn't include IE, - // which contains information required by WifiNetworkSelector. Ignore them - // for now. - @Override - public void onResults(WifiScanner.ScanData[] results) { - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - } - - @Override - public void onPnoNetworkFound(ScanResult[] results) { - for (ScanResult result: results) { - if (result.informationElements == null) { - localLog("Skipping scan result with null information elements"); - continue; - } - mScanDetails.add(ScanResultUtil.toScanDetail(result)); - } - - boolean wasConnectAttempted; - wasConnectAttempted = handleScanResults(mScanDetails, PNO_SCAN_LISTENER, false); - clearScanDetails(); - mScanRestartCount = 0; - - if (!wasConnectAttempted) { - // The scan results were rejected by WifiNetworkSelector due to low RSSI values - if (mLowRssiNetworkRetryDelay > LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS) { - mLowRssiNetworkRetryDelay = LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS; - } - scheduleDelayedConnectivityScan(mLowRssiNetworkRetryDelay); - - // Set up the delay value for next retry. - mLowRssiNetworkRetryDelay *= 2; - } else { - resetLowRssiNetworkRetryDelay(); - } - } - } - - private final PnoScanListener mPnoScanListener = new PnoScanListener(); - - private class OnNetworkUpdateListener implements - WifiConfigManager.OnNetworkUpdateListener { - @Override - public void onNetworkAdded(WifiConfiguration config) { - triggerScanOnNetworkChanges(); - } - @Override - public void onNetworkEnabled(WifiConfiguration config) { - triggerScanOnNetworkChanges(); - } - @Override - public void onNetworkRemoved(WifiConfiguration config) { - triggerScanOnNetworkChanges(); - } - @Override - public void onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig) { - triggerScanOnNetworkChanges(); - } - @Override - public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) { } - - @Override - public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) { - triggerScanOnNetworkChanges(); - } - } - - private class OnSuggestionUpdateListener implements - WifiNetworkSuggestionsManager.OnSuggestionUpdateListener { - @Override - public void onSuggestionsAddedOrUpdated(List<WifiNetworkSuggestion> suggestions) { - triggerScanOnNetworkChanges(); - } - - @Override - public void onSuggestionsRemoved(List<WifiNetworkSuggestion> suggestions) { - triggerScanOnNetworkChanges(); - } - } - - /** - * WifiConnectivityManager constructor - */ - WifiConnectivityManager(Context context, ScoringParams scoringParams, - ClientModeImpl stateMachine, - WifiInjector injector, WifiConfigManager configManager, - WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager, WifiInfo wifiInfo, - WifiNetworkSelector networkSelector, WifiConnectivityHelper connectivityHelper, - WifiLastResortWatchdog wifiLastResortWatchdog, OpenNetworkNotifier openNetworkNotifier, - WifiMetrics wifiMetrics, Handler handler, - Clock clock, LocalLog localLog, WifiScoreCard scoreCard) { - mContext = context; - mStateMachine = stateMachine; - mWifiInjector = injector; - mConfigManager = configManager; - mWifiNetworkSuggestionsManager = wifiNetworkSuggestionsManager; - mWifiInfo = wifiInfo; - mNetworkSelector = networkSelector; - mConnectivityHelper = connectivityHelper; - mLocalLog = localLog; - mWifiLastResortWatchdog = wifiLastResortWatchdog; - mOpenNetworkNotifier = openNetworkNotifier; - mWifiMetrics = wifiMetrics; - mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - mEventHandler = handler; - mClock = clock; - mScoringParams = scoringParams; - mConnectionAttemptTimeStamps = new LinkedList<>(); - - // Listen to WifiConfigManager network update events - mConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener()); - // Listen to WifiNetworkSuggestionsManager suggestion update events - mWifiNetworkSuggestionsManager.addOnSuggestionUpdateListener( - new OnSuggestionUpdateListener()); - mBssidBlocklistMonitor = mWifiInjector.getBssidBlocklistMonitor(); - mWifiChannelUtilization = mWifiInjector.getWifiChannelUtilizationScan(); - mNetworkSelector.setWifiChannelUtilization(mWifiChannelUtilization); - mWifiScoreCard = scoreCard; - } - - /** Initialize single scanning schedules, and validate them */ - private int[] initializeScanningSchedule(int state) { - int[] scheduleSec; - - if (state == WIFI_STATE_CONNECTED) { - scheduleSec = mContext.getResources().getIntArray( - R.array.config_wifiConnectedScanIntervalScheduleSec); - } else if (state == WIFI_STATE_DISCONNECTED) { - scheduleSec = mContext.getResources().getIntArray( - R.array.config_wifiDisconnectedScanIntervalScheduleSec); - } else { - scheduleSec = null; - } - - boolean invalidConfig = false; - if (scheduleSec == null || scheduleSec.length == 0) { - invalidConfig = true; - } else { - for (int val : scheduleSec) { - if (val <= 0) { - invalidConfig = true; - break; - } - } - } - if (!invalidConfig) { - return scheduleSec; - } - - Log.e(TAG, "Configuration for wifi scanning schedule is mis-configured," - + "using default schedule"); - return DEFAULT_SCANNING_SCHEDULE_SEC; - } - - /** - * This checks the connection attempt rate and recommends whether the connection attempt - * should be skipped or not. This attempts to rate limit the rate of connections to - * prevent us from flapping between networks and draining battery rapidly. - */ - private boolean shouldSkipConnectionAttempt(Long timeMillis) { - Iterator<Long> attemptIter = mConnectionAttemptTimeStamps.iterator(); - // First evict old entries from the queue. - while (attemptIter.hasNext()) { - Long connectionAttemptTimeMillis = attemptIter.next(); - if ((timeMillis - connectionAttemptTimeMillis) - > MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS) { - attemptIter.remove(); - } else { - // This list is sorted by timestamps, so we can skip any more checks - break; - } - } - // If we've reached the max connection attempt rate, skip this connection attempt - return (mConnectionAttemptTimeStamps.size() >= MAX_CONNECTION_ATTEMPTS_RATE); - } - - /** - * Add the current connection attempt timestamp to our queue of connection attempts. - */ - private void noteConnectionAttempt(Long timeMillis) { - mConnectionAttemptTimeStamps.addLast(timeMillis); - } - - /** - * This is used to clear the connection attempt rate limiter. This is done when the user - * explicitly tries to connect to a specified network. - */ - private void clearConnectionAttemptTimeStamps() { - mConnectionAttemptTimeStamps.clear(); - } - - /** - * Attempt to connect to a network candidate. - * - * Based on the currently connected network, this menthod determines whether we should - * connect or roam to the network candidate recommended by WifiNetworkSelector. - */ - private void connectToNetwork(WifiConfiguration candidate) { - ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate(); - if (scanResultCandidate == null) { - localLog("connectToNetwork: bad candidate - " + candidate - + " scanResult: " + scanResultCandidate); - return; - } - - String targetBssid = scanResultCandidate.BSSID; - String targetAssociationId = candidate.SSID + " : " + targetBssid; - - // Check if we are already connected or in the process of connecting to the target - // BSSID. mWifiInfo.mBSSID tracks the currently connected BSSID. This is checked just - // in case the firmware automatically roamed to a BSSID different from what - // WifiNetworkSelector selected. - if (targetBssid != null - && (targetBssid.equals(mLastConnectionAttemptBssid) - || targetBssid.equals(mWifiInfo.getBSSID())) - && SupplicantState.isConnecting(mWifiInfo.getSupplicantState())) { - localLog("connectToNetwork: Either already connected " - + "or is connecting to " + targetAssociationId); - return; - } - - if (candidate.BSSID != null - && !candidate.BSSID.equals(ClientModeImpl.SUPPLICANT_BSSID_ANY) - && !candidate.BSSID.equals(targetBssid)) { - localLog("connecToNetwork: target BSSID " + targetBssid + " does not match the " - + "config specified BSSID " + candidate.BSSID + ". Drop it!"); - return; - } - - long elapsedTimeMillis = mClock.getElapsedSinceBootMillis(); - if (!mScreenOn && shouldSkipConnectionAttempt(elapsedTimeMillis)) { - localLog("connectToNetwork: Too many connection attempts. Skipping this attempt!"); - mTotalConnectivityAttemptsRateLimited++; - return; - } - noteConnectionAttempt(elapsedTimeMillis); - - mLastConnectionAttemptBssid = targetBssid; - - WifiConfiguration currentConnectedNetwork = mConfigManager - .getConfiguredNetwork(mWifiInfo.getNetworkId()); - String currentAssociationId = (currentConnectedNetwork == null) ? "Disconnected" : - (mWifiInfo.getSSID() + " : " + mWifiInfo.getBSSID()); - - if (currentConnectedNetwork != null - && (currentConnectedNetwork.networkId == candidate.networkId - //TODO(b/36788683): re-enable linked configuration check - /* || currentConnectedNetwork.isLinked(candidate) */)) { - // Framework initiates roaming only if firmware doesn't support - // {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING}. - if (mConnectivityHelper.isFirmwareRoamingSupported()) { - // Keep this logging here for now to validate the firmware roaming behavior. - localLog("connectToNetwork: Roaming candidate - " + targetAssociationId + "." - + " The actual roaming target is up to the firmware."); - } else { - localLog("connectToNetwork: Roaming to " + targetAssociationId + " from " - + currentAssociationId); - mStateMachine.startRoamToNetwork(candidate.networkId, scanResultCandidate); - } - } else { - // Framework specifies the connection target BSSID if firmware doesn't support - // {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING} or the - // candidate configuration contains a specified BSSID. - if (mConnectivityHelper.isFirmwareRoamingSupported() && (candidate.BSSID == null - || candidate.BSSID.equals(ClientModeImpl.SUPPLICANT_BSSID_ANY))) { - targetBssid = ClientModeImpl.SUPPLICANT_BSSID_ANY; - localLog("connectToNetwork: Connect to " + candidate.SSID + ":" + targetBssid - + " from " + currentAssociationId); - } else { - localLog("connectToNetwork: Connect to " + targetAssociationId + " from " - + currentAssociationId); - } - mStateMachine.startConnectToNetwork(candidate.networkId, Process.WIFI_UID, targetBssid); - } - } - - // Helper for selecting the band for connectivity scan - private int getScanBand() { - return getScanBand(true); - } - - private int getScanBand(boolean isFullBandScan) { - if (isFullBandScan) { - return WifiScanner.WIFI_BAND_ALL; - } else { - // Use channel list instead. - return WifiScanner.WIFI_BAND_UNSPECIFIED; - } - } - - // Helper for setting the channels for connectivity scan when band is unspecified. Returns - // false if we can't retrieve the info. - // If connected, return channels used for the connected network - // If disconnected, return channels used for any network. - private boolean setScanChannels(ScanSettings settings) { - Set<Integer> freqs; - - WifiConfiguration config = mStateMachine.getCurrentWifiConfiguration(); - if (config == null) { - long ageInMillis = 1000 * 60 * mContext.getResources().getInteger( - R.integer.config_wifiInitialPartialScanChannelCacheAgeMins); - int maxCount = mContext.getResources().getInteger( - R.integer.config_wifiInitialPartialScanChannelMaxCount); - freqs = fetchChannelSetForPartialScan(maxCount, ageInMillis); - } else { - freqs = fetchChannelSetForNetworkForPartialScan(config.networkId); - } - - if (freqs != null && freqs.size() != 0) { - int index = 0; - settings.channels = new WifiScanner.ChannelSpec[freqs.size()]; - for (Integer freq : freqs) { - settings.channels[index++] = new WifiScanner.ChannelSpec(freq); - } - return true; - } else { - localLog("No history scan channels found, Perform full band scan"); - return false; - } - } - - /** - * Add the channels into the channel set with a size limit. - * If maxCount equals to 0, will add all available channels into the set. - * @param channelSet Target set for adding channel to. - * @param config Network for query channel from WifiScoreCard - * @param maxCount Size limit of the set. If equals to 0, means no limit. - * @param ageInMillis Only consider channel info whose timestamps are younger than this value. - * @return True if all available channels for this network are added, otherwise false. - */ - private boolean addChannelFromWifiScoreCard(@NonNull Set<Integer> channelSet, - @NonNull WifiConfiguration config, int maxCount, long ageInMillis) { - WifiScoreCard.PerNetwork network = mWifiScoreCard.lookupNetwork(config.SSID); - for (Integer channel : network.getFrequencies(ageInMillis)) { - if (maxCount > 0 && channelSet.size() >= maxCount) { - localLog("addChannelFromWifiScoreCard: size limit reached for network:" - + config.SSID); - return false; - } - channelSet.add(channel); - } - return true; - } - - /** - * Fetch channel set for target network. - */ - @VisibleForTesting - public Set<Integer> fetchChannelSetForNetworkForPartialScan(int networkId) { - WifiConfiguration config = mConfigManager.getConfiguredNetwork(networkId); - if (config == null) { - return null; - } - final int maxNumActiveChannelsForPartialScans = mContext.getResources().getInteger( - R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels); - Set<Integer> channelSet = new HashSet<>(); - // First add the currently connected network channel. - if (mWifiInfo.getFrequency() > 0) { - channelSet.add(mWifiInfo.getFrequency()); - } - // Then get channels for the network. - addChannelFromWifiScoreCard(channelSet, config, maxNumActiveChannelsForPartialScans, - CHANNEL_LIST_AGE_MS); - return channelSet; - } - - /** - * Fetch channel set for all saved and suggestion non-passpoint network for partial scan. - */ - @VisibleForTesting - public Set<Integer> fetchChannelSetForPartialScan(int maxCount, long ageInMillis) { - List<WifiConfiguration> networks = getAllScanOptimizationNetworks(); - if (networks.isEmpty()) { - return null; - } - - // Sort the networks with the most frequent ones at the front of the network list. - Collections.sort(networks, mConfigManager.getScanListComparator()); - - Set<Integer> channelSet = new HashSet<>(); - - for (WifiConfiguration config : networks) { - if (!addChannelFromWifiScoreCard(channelSet, config, maxCount, ageInMillis)) { - return channelSet; - } - } - - return channelSet; - } - - // Watchdog timer handler - private void watchdogHandler() { - // Schedule the next timer and start a single scan if we are in disconnected state. - // Otherwise, the watchdog timer will be scheduled when entering disconnected - // state. - if (mWifiState == WIFI_STATE_DISCONNECTED) { - localLog("start a single scan from watchdogHandler"); - - scheduleWatchdogTimer(); - startSingleScan(true, WIFI_WORK_SOURCE); - } - } - - private void triggerScanOnNetworkChanges() { - if (mScreenOn) { - // Update scanning schedule if needed - if (updateSingleScanningSchedule()) { - localLog("Saved networks / suggestions updated impacting single scan schedule"); - startConnectivityScan(false); - } - } else { - // Update the PNO scan network list when screen is off. Here we - // rely on startConnectivityScan() to perform all the checks and clean up. - localLog("Saved networks / suggestions updated impacting pno scan"); - startConnectivityScan(false); - } - } - - // Start a single scan and set up the interval for next single scan. - private void startPeriodicSingleScan() { - // Reaching here with scanning schedule is null means this is a false timer alarm - if (getSingleScanningSchedule() == null) { - return; - } - - long currentTimeStamp = mClock.getElapsedSinceBootMillis(); - - if (mLastPeriodicSingleScanTimeStamp != RESET_TIME_STAMP) { - long msSinceLastScan = currentTimeStamp - mLastPeriodicSingleScanTimeStamp; - if (msSinceLastScan < getScheduledSingleScanIntervalMs(0)) { - localLog("Last periodic single scan started " + msSinceLastScan - + "ms ago, defer this new scan request."); - schedulePeriodicScanTimer( - getScheduledSingleScanIntervalMs(0) - (int) msSinceLastScan); - return; - } - } - - boolean isScanNeeded = true; - boolean isFullBandScan = true; - - boolean isShortTimeSinceLastNetworkSelection = - ((currentTimeStamp - mLastNetworkSelectionTimeStamp) - <= 1000 * mContext.getResources().getInteger( - R.integer.config_wifiConnectedHighRssiScanMinimumWindowSizeSec)); - - boolean isGoodLinkAndAcceptableInternetAndShortTimeSinceLastNetworkSelection = - mNetworkSelector.hasSufficientLinkQuality(mWifiInfo) - && mNetworkSelector.hasInternetOrExpectNoInternet(mWifiInfo) - && isShortTimeSinceLastNetworkSelection; - // Check it is one of following conditions to skip scan (with firmware roaming) - // or do partial scan only (without firmware roaming). - // 1) Network is sufficient - // 2) link is good, internet status is acceptable - // and it is a short time since last network selection - // 3) There is active stream such that scan will be likely disruptive - if (mWifiState == WIFI_STATE_CONNECTED - && (mNetworkSelector.isNetworkSufficient(mWifiInfo) - || isGoodLinkAndAcceptableInternetAndShortTimeSinceLastNetworkSelection - || mNetworkSelector.hasActiveStream(mWifiInfo))) { - // If only partial scan is proposed and firmware roaming control is supported, - // we will not issue any scan because firmware roaming will take care of - // intra-SSID roam. - if (mConnectivityHelper.isFirmwareRoamingSupported()) { - localLog("No partial scan because firmware roaming is supported."); - isScanNeeded = false; - } else { - localLog("No full band scan because current network is sufficient"); - isFullBandScan = false; - } - } - - if (isScanNeeded) { - mLastPeriodicSingleScanTimeStamp = currentTimeStamp; - - if (mWifiState == WIFI_STATE_DISCONNECTED - && mInitialScanState == INITIAL_SCAN_STATE_START) { - startSingleScan(false, WIFI_WORK_SOURCE); - - // Note, initial partial scan may fail due to lack of channel history - // Hence, we verify state before changing to AWIATING_RESPONSE - if (mInitialScanState == INITIAL_SCAN_STATE_START) { - setInitialScanState(INITIAL_SCAN_STATE_AWAITING_RESPONSE); - mWifiMetrics.incrementInitialPartialScanCount(); - } - // No scheduling for another scan (until we get the results) - return; - } - - startSingleScan(isFullBandScan, WIFI_WORK_SOURCE); - schedulePeriodicScanTimer( - getScheduledSingleScanIntervalMs(mCurrentSingleScanScheduleIndex)); - - // Set up the next scan interval in an exponential backoff fashion. - mCurrentSingleScanScheduleIndex++; - } else { - // Since we already skipped this scan, keep the same scan interval for next scan. - schedulePeriodicScanTimer( - getScheduledSingleScanIntervalMs(mCurrentSingleScanScheduleIndex)); - } - } - - // Retrieve a value from single scanning schedule in ms - private int getScheduledSingleScanIntervalMs(int index) { - synchronized (mLock) { - if (mCurrentSingleScanScheduleSec == null) { - Log.e(TAG, "Invalid attempt to get schedule interval, Schedule array is null "); - - // Use a default value - return DEFAULT_SCANNING_SCHEDULE_SEC[0] * 1000; - } - - if (index >= mCurrentSingleScanScheduleSec.length) { - index = mCurrentSingleScanScheduleSec.length - 1; - } - - return mCurrentSingleScanScheduleSec[index] * 1000; - } - } - - // Set the single scanning schedule - private void setSingleScanningSchedule(int[] scheduleSec) { - synchronized (mLock) { - mCurrentSingleScanScheduleSec = scheduleSec; - } - } - - // Get the single scanning schedule - private int[] getSingleScanningSchedule() { - synchronized (mLock) { - return mCurrentSingleScanScheduleSec; - } - } - - // Update the single scanning schedule if needed, and return true if update occurs - private boolean updateSingleScanningSchedule() { - if (mWifiState != WIFI_STATE_CONNECTED) { - // No need to update the scanning schedule - return false; - } - - boolean shouldUseSingleSavedNetworkSchedule = useSingleSavedNetworkSchedule(); - - if (mCurrentSingleScanScheduleSec == mConnectedSingleScanScheduleSec - && shouldUseSingleSavedNetworkSchedule) { - mCurrentSingleScanScheduleSec = mConnectedSingleSavedNetworkSingleScanScheduleSec; - return true; - } - if (mCurrentSingleScanScheduleSec == mConnectedSingleSavedNetworkSingleScanScheduleSec - && !shouldUseSingleSavedNetworkSchedule) { - mCurrentSingleScanScheduleSec = mConnectedSingleScanScheduleSec; - return true; - } - return false; - } - - // Set initial scan state - private void setInitialScanState(int state) { - Log.i(TAG, "SetInitialScanState to : " + state); - mInitialScanState = state; - } - - // Reset the last periodic single scan time stamp so that the next periodic single - // scan can start immediately. - private void resetLastPeriodicSingleScanTimeStamp() { - mLastPeriodicSingleScanTimeStamp = RESET_TIME_STAMP; - } - - // Periodic scan timer handler - private void periodicScanTimerHandler() { - localLog("periodicScanTimerHandler"); - - // Schedule the next timer and start a single scan if screen is on. - if (mScreenOn) { - startPeriodicSingleScan(); - } - } - - // Start a single scan - private void startForcedSingleScan(boolean isFullBandScan, WorkSource workSource) { - mPnoScanListener.resetLowRssiNetworkRetryDelay(); - - ScanSettings settings = new ScanSettings(); - if (!isFullBandScan) { - if (!setScanChannels(settings)) { - isFullBandScan = true; - // Skip the initial scan since no channel history available - setInitialScanState(INITIAL_SCAN_STATE_COMPLETE); - } else { - mInitialPartialScanChannelCount = settings.channels.length; - } - } - settings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; // always do high accuracy scans. - settings.band = getScanBand(isFullBandScan); - settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - settings.numBssidsPerScan = 0; - settings.hiddenNetworks.clear(); - // retrieve the list of hidden network SSIDs from saved network to scan for - settings.hiddenNetworks.addAll(mConfigManager.retrieveHiddenNetworkList()); - // retrieve the list of hidden network SSIDs from Network suggestion to scan for - settings.hiddenNetworks.addAll(mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList()); - - SingleScanListener singleScanListener = - new SingleScanListener(isFullBandScan); - mScanner.startScan( - settings, new HandlerExecutor(mEventHandler), singleScanListener, workSource); - mWifiMetrics.incrementConnectivityOneshotScanCount(); - } - - private void startSingleScan(boolean isFullBandScan, WorkSource workSource) { - if (!mWifiEnabled || !mAutoJoinEnabled) { - return; - } - startForcedSingleScan(isFullBandScan, workSource); - } - - // Start a periodic scan when screen is on - private void startPeriodicScan(boolean scanImmediately) { - mPnoScanListener.resetLowRssiNetworkRetryDelay(); - - // No connectivity scan if auto roaming is disabled. - if (mWifiState == WIFI_STATE_CONNECTED && !mContext.getResources().getBoolean( - R.bool.config_wifi_framework_enable_associated_network_selection)) { - return; - } - - // Due to b/28020168, timer based single scan will be scheduled - // to provide periodic scan in an exponential backoff fashion. - if (scanImmediately) { - resetLastPeriodicSingleScanTimeStamp(); - } - mCurrentSingleScanScheduleIndex = 0; - startPeriodicSingleScan(); - } - - private int deviceMobilityStateToPnoScanIntervalMs(@DeviceMobilityState int state) { - switch (state) { - case WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN: - case WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT: - case WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT: - return mContext.getResources() - .getInteger(R.integer.config_wifiMovingPnoScanIntervalMillis); - case WifiManager.DEVICE_MOBILITY_STATE_STATIONARY: - return mContext.getResources() - .getInteger(R.integer.config_wifiStationaryPnoScanIntervalMillis); - default: - return -1; - } - } - - /** - * Pass device mobility state to WifiChannelUtilization and - * alter the PNO scan interval based on the current device mobility state. - * If the device is stationary, it will likely not find many new Wifi networks. Thus, increase - * the interval between scans. Decrease the interval between scans if the device begins to move - * again. - * @param newState the new device mobility state - */ - public void setDeviceMobilityState(@DeviceMobilityState int newState) { - int oldDeviceMobilityState = mDeviceMobilityState; - localLog("Device mobility state changed. state=" + newState); - int newPnoScanIntervalMs = deviceMobilityStateToPnoScanIntervalMs(newState); - if (newPnoScanIntervalMs < 0) { - Log.e(TAG, "Invalid device mobility state: " + newState); - return; - } - mDeviceMobilityState = newState; - mWifiChannelUtilization.setDeviceMobilityState(newState); - - int oldPnoScanIntervalMs = deviceMobilityStateToPnoScanIntervalMs(oldDeviceMobilityState); - if (newPnoScanIntervalMs == oldPnoScanIntervalMs) { - if (mPnoScanStarted) { - mWifiMetrics.logPnoScanStop(); - mWifiMetrics.enterDeviceMobilityState(newState); - mWifiMetrics.logPnoScanStart(); - } else { - mWifiMetrics.enterDeviceMobilityState(newState); - } - } else { - Log.d(TAG, "PNO Scan Interval changed to " + newPnoScanIntervalMs + " ms."); - - if (mPnoScanStarted) { - Log.d(TAG, "Restarting PNO Scan with new scan interval"); - stopPnoScan(); - mWifiMetrics.enterDeviceMobilityState(newState); - startDisconnectedPnoScan(); - } else { - mWifiMetrics.enterDeviceMobilityState(newState); - } - } - } - - // Start a DisconnectedPNO scan when screen is off and Wifi is disconnected - private void startDisconnectedPnoScan() { - // Initialize PNO settings - PnoSettings pnoSettings = new PnoSettings(); - List<PnoSettings.PnoNetwork> pnoNetworkList = retrievePnoNetworkList(); - int listSize = pnoNetworkList.size(); - - if (listSize == 0) { - // No saved network - localLog("No saved network for starting disconnected PNO."); - return; - } - - pnoSettings.networkList = new PnoSettings.PnoNetwork[listSize]; - pnoSettings.networkList = pnoNetworkList.toArray(pnoSettings.networkList); - pnoSettings.min6GHzRssi = mScoringParams.getEntryRssi(ScanResult.BAND_6_GHZ_START_FREQ_MHZ); - pnoSettings.min5GHzRssi = mScoringParams.getEntryRssi(ScanResult.BAND_5_GHZ_START_FREQ_MHZ); - pnoSettings.min24GHzRssi = mScoringParams.getEntryRssi( - ScanResult.BAND_24_GHZ_START_FREQ_MHZ); - - // Initialize scan settings - ScanSettings scanSettings = new ScanSettings(); - scanSettings.band = getScanBand(); - scanSettings.reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; - scanSettings.numBssidsPerScan = 0; - scanSettings.periodInMs = deviceMobilityStateToPnoScanIntervalMs(mDeviceMobilityState); - - mPnoScanListener.clearScanDetails(); - - mScanner.startDisconnectedPnoScan( - scanSettings, pnoSettings, new HandlerExecutor(mEventHandler), mPnoScanListener); - mPnoScanStarted = true; - mWifiMetrics.logPnoScanStart(); - } - - private @NonNull List<WifiConfiguration> getAllScanOptimizationNetworks() { - List<WifiConfiguration> networks = mConfigManager.getSavedNetworks(-1); - networks.addAll(mWifiNetworkSuggestionsManager.getAllScanOptimizationSuggestionNetworks()); - // remove all auto-join disabled or network selection disabled network. - networks.removeIf(config -> !config.allowAutojoin - || !config.getNetworkSelectionStatus().isNetworkEnabled()); - return networks; - } - - /** - * Retrieve the PnoNetworks from Saved and suggestion non-passpoint network. - */ - @VisibleForTesting - public List<PnoSettings.PnoNetwork> retrievePnoNetworkList() { - List<WifiConfiguration> networks = getAllScanOptimizationNetworks(); - - if (networks.isEmpty()) { - return Collections.EMPTY_LIST; - } - Collections.sort(networks, mConfigManager.getScanListComparator()); - boolean pnoFrequencyCullingEnabled = mContext.getResources() - .getBoolean(R.bool.config_wifiPnoFrequencyCullingEnabled); - - List<PnoSettings.PnoNetwork> pnoList = new ArrayList<>(); - Set<WifiScanner.PnoSettings.PnoNetwork> pnoSet = new HashSet<>(); - for (WifiConfiguration config : networks) { - WifiScanner.PnoSettings.PnoNetwork pnoNetwork = - WifiConfigurationUtil.createPnoNetwork(config); - if (pnoSet.contains(pnoNetwork)) { - continue; - } - pnoList.add(pnoNetwork); - pnoSet.add(pnoNetwork); - if (!pnoFrequencyCullingEnabled) { - continue; - } - Set<Integer> channelList = new HashSet<>(); - addChannelFromWifiScoreCard(channelList, config, 0, - MAX_PNO_SCAN_FREQUENCY_AGE_MS); - pnoNetwork.frequencies = channelList.stream().mapToInt(Integer::intValue).toArray(); - localLog("retrievePnoNetworkList " + pnoNetwork.ssid + ":" - + Arrays.toString(pnoNetwork.frequencies)); - } - return pnoList; - } - - // Stop PNO scan. - private void stopPnoScan() { - if (!mPnoScanStarted) return; - - mScanner.stopPnoScan(mPnoScanListener); - mPnoScanStarted = false; - mWifiMetrics.logPnoScanStop(); - } - - // Set up watchdog timer - private void scheduleWatchdogTimer() { - localLog("scheduleWatchdogTimer"); - - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + WATCHDOG_INTERVAL_MS, - WATCHDOG_TIMER_TAG, - mWatchdogListener, mEventHandler); - } - - // Schedules a delayed partial scan, which will scan the frequencies in mCachedWifiCandidates. - private void scheduleDelayedPartialScan(long delayMillis) { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + delayMillis, DELAYED_PARTIAL_SCAN_TIMER_TAG, - mDelayedPartialScanTimerListener, mEventHandler); - mDelayedPartialScanTimerSet = true; - } - - // Cancel the delayed partial scan timer. - private void cancelDelayedPartialScan() { - if (mDelayedPartialScanTimerSet) { - mAlarmManager.cancel(mDelayedPartialScanTimerListener); - mDelayedPartialScanTimerSet = false; - } - } - - // Set up periodic scan timer - private void schedulePeriodicScanTimer(int intervalMs) { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + intervalMs, - PERIODIC_SCAN_TIMER_TAG, - mPeriodicScanTimerListener, mEventHandler); - mPeriodicScanTimerSet = true; - } - - // Cancel periodic scan timer - private void cancelPeriodicScanTimer() { - if (mPeriodicScanTimerSet) { - mAlarmManager.cancel(mPeriodicScanTimerListener); - mPeriodicScanTimerSet = false; - } - } - - // Set up timer to start a delayed single scan after RESTART_SCAN_DELAY_MS - private void scheduleDelayedSingleScan(boolean isFullBandScan) { - localLog("scheduleDelayedSingleScan"); - - RestartSingleScanListener restartSingleScanListener = - new RestartSingleScanListener(isFullBandScan); - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + RESTART_SCAN_DELAY_MS, - RESTART_SINGLE_SCAN_TIMER_TAG, - restartSingleScanListener, mEventHandler); - } - - // Set up timer to start a delayed scan after msFromNow milli-seconds - private void scheduleDelayedConnectivityScan(int msFromNow) { - localLog("scheduleDelayedConnectivityScan"); - - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + msFromNow, - RESTART_CONNECTIVITY_SCAN_TIMER_TAG, - mRestartScanListener, mEventHandler); - - } - - // Start a connectivity scan. The scan method is chosen according to - // the current screen state and WiFi state. - private void startConnectivityScan(boolean scanImmediately) { - localLog("startConnectivityScan: screenOn=" + mScreenOn - + " wifiState=" + stateToString(mWifiState) - + " scanImmediately=" + scanImmediately - + " wifiEnabled=" + mWifiEnabled - + " wifiConnectivityManagerEnabled=" - + mAutoJoinEnabled); - - if (!mWifiEnabled || !mAutoJoinEnabled) { - return; - } - - // Always stop outstanding connecivity scan if there is any - stopConnectivityScan(); - - // Don't start a connectivity scan while Wifi is in the transition - // between connected and disconnected states. - if ((mWifiState != WIFI_STATE_CONNECTED && mWifiState != WIFI_STATE_DISCONNECTED) - || (getSingleScanningSchedule() == null)) { - return; - } - - if (mScreenOn) { - startPeriodicScan(scanImmediately); - } else { - if (mWifiState == WIFI_STATE_DISCONNECTED && !mPnoScanStarted) { - startDisconnectedPnoScan(); - } - } - - } - - // Stop connectivity scan if there is any. - private void stopConnectivityScan() { - // Due to b/28020168, timer based single scan will be scheduled - // to provide periodic scan in an exponential backoff fashion. - cancelPeriodicScanTimer(); - cancelDelayedPartialScan(); - stopPnoScan(); - } - - /** - * Handler for screen state (on/off) changes - */ - public void handleScreenStateChanged(boolean screenOn) { - localLog("handleScreenStateChanged: screenOn=" + screenOn); - - mScreenOn = screenOn; - - if (mWifiState == WIFI_STATE_DISCONNECTED - && mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan)) { - setInitialScanState(INITIAL_SCAN_STATE_START); - } - - mOpenNetworkNotifier.handleScreenStateChanged(screenOn); - - startConnectivityScan(SCAN_ON_SCHEDULE); - } - - /** - * Helper function that converts the WIFI_STATE_XXX constants to string - */ - private static String stateToString(int state) { - switch (state) { - case WIFI_STATE_CONNECTED: - return "connected"; - case WIFI_STATE_DISCONNECTED: - return "disconnected"; - case WIFI_STATE_TRANSITIONING: - return "transitioning"; - default: - return "unknown"; - } - } - - /** - * Check if Single saved network schedule should be used - * This is true if the one of the following is satisfied: - * 1. Device has a total of 1 network whether saved, passpoint, or suggestion. - * 2. The device is connected to that network. - */ - private boolean useSingleSavedNetworkSchedule() { - WifiConfiguration currentNetwork = mStateMachine.getCurrentWifiConfiguration(); - if (currentNetwork == null) { - localLog("Current network is missing, may caused by remove network and disconnecting "); - return false; - } - List<WifiConfiguration> savedNetworks = - mConfigManager.getSavedNetworks(Process.WIFI_UID); - // If we have multiple saved networks, then no need to proceed - if (savedNetworks.size() > 1) { - return false; - } - - List<PasspointConfiguration> passpointNetworks = - mWifiInjector.getPasspointManager().getProviderConfigs(Process.WIFI_UID, true); - // If we have multiple networks (saved + passpoint), then no need to proceed - if (passpointNetworks.size() + savedNetworks.size() > 1) { - return false; - } - - Set<WifiNetworkSuggestion> suggestionsNetworks = - mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions(); - // If total size not equal to 1, then no need to proceed - if (passpointNetworks.size() + savedNetworks.size() + suggestionsNetworks.size() != 1) { - return false; - } - - // Next verify that this network is the one device is connected to - int currentNetworkId = currentNetwork.networkId; - - // If we have a single saved network, and we are connected to it, return true. - if (savedNetworks.size() == 1) { - return (savedNetworks.get(0).networkId == currentNetworkId); - } - - // If we have a single passpoint network, and we are connected to it, return true. - if (passpointNetworks.size() == 1) { - String passpointKey = passpointNetworks.get(0).getUniqueId(); - WifiConfiguration config = mConfigManager.getConfiguredNetwork(passpointKey); - return (config != null && config.networkId == currentNetworkId); - } - - // If we have a single suggestion network, and we are connected to it, return true. - WifiNetworkSuggestion network = suggestionsNetworks.iterator().next(); - String suggestionKey = network.getWifiConfiguration().getKey(); - WifiConfiguration config = mConfigManager.getConfiguredNetwork(suggestionKey); - return (config != null && config.networkId == currentNetworkId); - } - - private int[] initSingleSavedNetworkSchedule() { - int[] schedule = mContext.getResources().getIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec); - if (schedule == null || schedule.length == 0) { - return null; - } - - for (int val : schedule) { - if (val <= 0) { - return null; - } - } - return schedule; - } - - /** - * Handler for WiFi state (connected/disconnected) changes - */ - public void handleConnectionStateChanged(int state) { - localLog("handleConnectionStateChanged: state=" + stateToString(state)); - - if (mConnectedSingleScanScheduleSec == null) { - mConnectedSingleScanScheduleSec = initializeScanningSchedule(WIFI_STATE_CONNECTED); - } - if (mDisconnectedSingleScanScheduleSec == null) { - mDisconnectedSingleScanScheduleSec = - initializeScanningSchedule(WIFI_STATE_DISCONNECTED); - } - if (mConnectedSingleSavedNetworkSingleScanScheduleSec == null) { - mConnectedSingleSavedNetworkSingleScanScheduleSec = - initSingleSavedNetworkSchedule(); - if (mConnectedSingleSavedNetworkSingleScanScheduleSec == null) { - mConnectedSingleSavedNetworkSingleScanScheduleSec = mConnectedSingleScanScheduleSec; - } - } - - mWifiState = state; - - // Reset BSSID of last connection attempt and kick off - // the watchdog timer if entering disconnected state. - if (mWifiState == WIFI_STATE_DISCONNECTED) { - mLastConnectionAttemptBssid = null; - scheduleWatchdogTimer(); - // Switch to the disconnected scanning schedule - setSingleScanningSchedule(mDisconnectedSingleScanScheduleSec); - startConnectivityScan(SCAN_IMMEDIATELY); - } else if (mWifiState == WIFI_STATE_CONNECTED) { - if (useSingleSavedNetworkSchedule()) { - // Switch to Single-Saved-Network connected schedule - setSingleScanningSchedule(mConnectedSingleSavedNetworkSingleScanScheduleSec); - } else { - // Switch to connected single scanning schedule - setSingleScanningSchedule(mConnectedSingleScanScheduleSec); - } - startConnectivityScan(SCAN_ON_SCHEDULE); - } else { - // Intermediate state, no applicable single scanning schedule - setSingleScanningSchedule(null); - startConnectivityScan(SCAN_ON_SCHEDULE); - } - } - - /** - * Handler when a WiFi connection attempt ended. - * - * @param failureCode {@link WifiMetrics.ConnectionEvent} failure code. - * @param bssid the failed network. - * @param ssid identifies the failed network. - */ - public void handleConnectionAttemptEnded(int failureCode, @NonNull String bssid, - @NonNull String ssid) { - if (failureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) { - String ssidUnquoted = (mWifiInfo.getWifiSsid() == null) - ? null - : mWifiInfo.getWifiSsid().toString(); - mOpenNetworkNotifier.handleWifiConnected(ssidUnquoted); - } else { - mOpenNetworkNotifier.handleConnectionFailure(); - retryConnectionOnLatestCandidates(bssid, ssid); - } - } - - private void retryConnectionOnLatestCandidates(String bssid, String ssid) { - try { - if (mLatestCandidates == null || mLatestCandidates.size() == 0 - || mClock.getElapsedSinceBootMillis() - mLatestCandidatesTimestampMs - > TEMP_BSSID_BLOCK_DURATION) { - mLatestCandidates = null; - return; - } - MacAddress macAddress = MacAddress.fromString(bssid); - int prevNumCandidates = mLatestCandidates.size(); - mLatestCandidates = mLatestCandidates.stream() - .filter(candidate -> !macAddress.equals(candidate.getKey().bssid)) - .collect(Collectors.toList()); - if (prevNumCandidates == mLatestCandidates.size()) { - return; - } - WifiConfiguration candidate = mNetworkSelector.selectNetwork(mLatestCandidates); - if (candidate != null) { - localLog("Automatic retry on the next best WNS candidate-" + candidate.SSID); - // Make sure that the failed BSSID is blocked for at least TEMP_BSSID_BLOCK_DURATION - // to prevent the supplicant from trying it again. - mBssidBlocklistMonitor.blockBssidForDurationMs(bssid, ssid, - TEMP_BSSID_BLOCK_DURATION, - BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT, 0); - connectToNetwork(candidate); - } - } catch (IllegalArgumentException e) { - localLog("retryConnectionOnLatestCandidates: failed to create MacAddress from bssid=" - + bssid); - mLatestCandidates = null; - return; - } - } - - // Enable auto-join if WifiConnectivityManager is enabled & we have any pending generic network - // request (trusted or untrusted) and no specific network request in progress. - private void checkAllStatesAndEnableAutoJoin() { - // if auto-join was disabled externally, don't re-enable for any triggers. - // External triggers to disable always trumps any internal state. - setAutoJoinEnabled(mAutoJoinEnabledExternal - && (mUntrustedConnectionAllowed || mTrustedConnectionAllowed) - && !mSpecificNetworkRequestInProgress); - startConnectivityScan(SCAN_IMMEDIATELY); - } - - /** - * Triggered when {@link WifiNetworkFactory} has a pending general network request. - */ - public void setTrustedConnectionAllowed(boolean allowed) { - localLog("setTrustedConnectionAllowed: allowed=" + allowed); - - if (mTrustedConnectionAllowed != allowed) { - mTrustedConnectionAllowed = allowed; - checkAllStatesAndEnableAutoJoin(); - } - } - - - /** - * Triggered when {@link UntrustedWifiNetworkFactory} has a pending ephemeral network request. - */ - public void setUntrustedConnectionAllowed(boolean allowed) { - localLog("setUntrustedConnectionAllowed: allowed=" + allowed); - - if (mUntrustedConnectionAllowed != allowed) { - mUntrustedConnectionAllowed = allowed; - checkAllStatesAndEnableAutoJoin(); - } - } - - /** - * Triggered when {@link WifiNetworkFactory} is processing a specific network request. - */ - public void setSpecificNetworkRequestInProgress(boolean inProgress) { - localLog("setsetSpecificNetworkRequestInProgress : inProgress=" + inProgress); - - if (mSpecificNetworkRequestInProgress != inProgress) { - mSpecificNetworkRequestInProgress = inProgress; - checkAllStatesAndEnableAutoJoin(); - } - } - - /** - * Handler when user specifies a particular network to connect to - */ - public void setUserConnectChoice(int netId) { - localLog("setUserConnectChoice: netId=" + netId); - - mNetworkSelector.setUserConnectChoice(netId); - } - - /** - * Handler to prepare for connection to a user or app specified network - */ - public void prepareForForcedConnection(int netId) { - WifiConfiguration config = mConfigManager.getConfiguredNetwork(netId); - if (config == null) { - return; - } - localLog("prepareForForcedConnection: SSID=" + config.SSID); - - clearConnectionAttemptTimeStamps(); - mBssidBlocklistMonitor.clearBssidBlocklistForSsid(config.SSID); - } - - /** - * Handler for on-demand connectivity scan - */ - public void forceConnectivityScan(WorkSource workSource) { - if (!mWifiEnabled) return; - localLog("forceConnectivityScan in request of " + workSource); - - clearConnectionAttemptTimeStamps(); - mWaitForFullBandScanResults = true; - startForcedSingleScan(true, workSource); - } - - /** - * Helper method to populate WifiScanner handle. This is done lazily because - * WifiScanningService is started after WifiService. - */ - private void retrieveWifiScanner() { - if (mScanner != null) return; - mScanner = mWifiInjector.getWifiScanner(); - checkNotNull(mScanner); - // Register for all single scan results - mScanner.registerScanListener(new HandlerExecutor(mEventHandler), mAllSingleScanListener); - } - - /** - * Start WifiConnectivityManager - */ - private void start() { - if (mRunning) return; - retrieveWifiScanner(); - mConnectivityHelper.getFirmwareRoamingInfo(); - mBssidBlocklistMonitor.clearBssidBlocklist(); - mWifiChannelUtilization.init(mStateMachine.getWifiLinkLayerStats()); - - if (mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan)) { - setInitialScanState(INITIAL_SCAN_STATE_START); - } - - mRunning = true; - mLatestCandidates = null; - mLatestCandidatesTimestampMs = 0; - } - - /** - * Stop and reset WifiConnectivityManager - */ - private void stop() { - if (!mRunning) return; - mRunning = false; - stopConnectivityScan(); - resetLastPeriodicSingleScanTimeStamp(); - mOpenNetworkNotifier.clearPendingNotification(true /* resetRepeatDelay */); - mLastConnectionAttemptBssid = null; - mWaitForFullBandScanResults = false; - mLatestCandidates = null; - mLatestCandidatesTimestampMs = 0; - mScanRestartCount = 0; - } - - /** - * Update WifiConnectivityManager running state - * - * Start WifiConnectivityManager only if both Wifi and WifiConnectivityManager - * are enabled, otherwise stop it. - */ - private void updateRunningState() { - if (mWifiEnabled && mAutoJoinEnabled) { - localLog("Starting up WifiConnectivityManager"); - start(); - } else { - localLog("Stopping WifiConnectivityManager"); - stop(); - } - } - - /** - * Inform WiFi is enabled for connection or not - */ - public void setWifiEnabled(boolean enable) { - localLog("Set WiFi " + (enable ? "enabled" : "disabled")); - - if (mWifiEnabled && !enable) { - mNetworkSelector.resetOnDisable(); - mBssidBlocklistMonitor.clearBssidBlocklist(); - } - mWifiEnabled = enable; - updateRunningState(); - } - - /** - * Turn on/off the WifiConnectivityManager at runtime - */ - private void setAutoJoinEnabled(boolean enable) { - mAutoJoinEnabled = enable; - updateRunningState(); - } - - /** - * Turn on/off the auto join at runtime - */ - public void setAutoJoinEnabledExternal(boolean enable) { - localLog("Set auto join " + (enable ? "enabled" : "disabled")); - - if (mAutoJoinEnabledExternal != enable) { - mAutoJoinEnabledExternal = enable; - checkAllStatesAndEnableAutoJoin(); - } - } - - @VisibleForTesting - int getLowRssiNetworkRetryDelay() { - return mPnoScanListener.getLowRssiNetworkRetryDelay(); - } - - @VisibleForTesting - long getLastPeriodicSingleScanTimeStamp() { - return mLastPeriodicSingleScanTimeStamp; - } - - /** - * Dump the local logs. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WifiConnectivityManager"); - pw.println("WifiConnectivityManager - Log Begin ----"); - mLocalLog.dump(fd, pw, args); - pw.println("WifiConnectivityManager - Log End ----"); - mOpenNetworkNotifier.dump(fd, pw, args); - mBssidBlocklistMonitor.dump(fd, pw, args); - } -} diff --git a/service/java/com/android/server/wifi/WifiContext.java b/service/java/com/android/server/wifi/WifiContext.java deleted file mode 100644 index bbcb9d8a7..000000000 --- a/service/java/com/android/server/wifi/WifiContext.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.AssetManager; -import android.content.res.Resources; -import android.util.Log; - -import com.android.server.wifi.util.Environment; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * Wrapper for context to override getResources method. Resources for wifi mainline jar needs to be - * fetched from the resources APK. - */ -public class WifiContext extends ContextWrapper { - private static final String TAG = "WifiContext"; - /** Intent action that is used to identify ServiceWifiResources.apk */ - private static final String ACTION_RESOURCES_APK = - "com.android.server.wifi.intent.action.SERVICE_WIFI_RESOURCES_APK"; - private static final String WIFI_OVERLAY_JAVA_PKG_NAME = "com.android.wifi.resources"; - - private String mWifiOverlayApkPkgName; - - // Cached resources from the resources APK. - private AssetManager mWifiAssetsFromApk; - private Resources mWifiResourcesFromApk; - private Resources.Theme mWifiThemeFromApk; - - public WifiContext(@NonNull Context contextBase) { - super(contextBase); - } - - /** - * Get the Java package name of the resources in ServiceWifiResources.apk - * - * i.e. the package name of the Wifi Resources R class: - * {@code import com.android.wifi.resources.R;}, which is "com.android.wifi.resources" - */ - public String getWifiOverlayJavaPkgName() { - return WIFI_OVERLAY_JAVA_PKG_NAME; - } - - /** Get the Android application package name of ServiceWifiResources.apk */ - public String getWifiOverlayApkPkgName() { - if (mWifiOverlayApkPkgName != null) { - return mWifiOverlayApkPkgName; - } - - List<ResolveInfo> resolveInfos = getPackageManager().queryIntentActivities( - new Intent(ACTION_RESOURCES_APK), - PackageManager.MATCH_SYSTEM_ONLY); - - // remove apps that don't live in the Wifi apex - resolveInfos.removeIf(info -> - !Environment.isAppInWifiApex(info.activityInfo.applicationInfo)); - - if (resolveInfos.isEmpty()) { - // Resource APK not loaded yet, print a stack trace to see where this is called from - Log.e(TAG, "Attempted to fetch resources before Wifi Resources APK is loaded!", - new IllegalStateException()); - return null; - } - - if (resolveInfos.size() > 1) { - // multiple apps found, log a warning, but continue - Log.w(TAG, "Found > 1 APK that can resolve Wifi Resources APK intent: " - + resolveInfos.stream() - .map(info -> info.activityInfo.applicationInfo.packageName) - .collect(Collectors.joining(", "))); - } - - // Assume the first ResolveInfo is the one we're looking for - ResolveInfo info = resolveInfos.get(0); - mWifiOverlayApkPkgName = info.activityInfo.applicationInfo.packageName; - Log.i(TAG, "Found Wifi Resources APK at: " + mWifiOverlayApkPkgName); - return mWifiOverlayApkPkgName; - } - - private Context getResourcesApkContext() { - try { - return createPackageContext(getWifiOverlayApkPkgName(), 0); - } catch (PackageManager.NameNotFoundException e) { - Log.wtf(TAG, "Failed to load resources", e); - } - return null; - } - - /** - * Retrieve assets held in the wifi resources APK. - */ - @Override - public AssetManager getAssets() { - if (mWifiAssetsFromApk == null) { - Context resourcesApkContext = getResourcesApkContext(); - if (resourcesApkContext != null) { - mWifiAssetsFromApk = resourcesApkContext.getAssets(); - } - } - return mWifiAssetsFromApk; - } - - /** - * Retrieve resources held in the wifi resources APK. - */ - @Override - public Resources getResources() { - if (mWifiResourcesFromApk == null) { - Context resourcesApkContext = getResourcesApkContext(); - if (resourcesApkContext != null) { - mWifiResourcesFromApk = resourcesApkContext.getResources(); - } - } - return mWifiResourcesFromApk; - } - - /** - * Retrieve theme held in the wifi resources APK. - */ - @Override - public Resources.Theme getTheme() { - if (mWifiThemeFromApk == null) { - Context resourcesApkContext = getResourcesApkContext(); - if (resourcesApkContext != null) { - mWifiThemeFromApk = resourcesApkContext.getTheme(); - } - } - return mWifiThemeFromApk; - } -} diff --git a/service/java/com/android/server/wifi/WifiCountryCode.java b/service/java/com/android/server/wifi/WifiCountryCode.java deleted file mode 100644 index 3d05571d7..000000000 --- a/service/java/com/android/server/wifi/WifiCountryCode.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Handler; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -/** - * Provide functions for making changes to WiFi country code. - * This Country Code is from MCC or phone default setting. This class sends Country Code - * to driver through wpa_supplicant when ClientModeImpl marks current state as ready - * using setReadyForChange(true). - */ -public class WifiCountryCode { - private static final String TAG = "WifiCountryCode"; - private final Context mContext; - private final TelephonyManager mTelephonyManager; - private final WifiNative mWifiNative; - private boolean DBG = false; - private boolean mReady = false; - private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); - - private String mDefaultCountryCode = null; - private String mTelephonyCountryCode = null; - private String mDriverCountryCode = null; - private String mTelephonyCountryTimestamp = null; - private String mDriverCountryTimestamp = null; - private String mReadyTimestamp = null; - private boolean mForceCountryCode = false; - - public WifiCountryCode( - Context context, - Handler handler, - WifiNative wifiNative, - String oemDefaultCountryCode) { - mContext = context; - mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - mWifiNative = wifiNative; - - if (!TextUtils.isEmpty(oemDefaultCountryCode)) { - mDefaultCountryCode = oemDefaultCountryCode.toUpperCase(Locale.US); - } - context.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String countryCode = intent.getStringExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY); - Log.d(TAG, "Country code changed"); - setCountryCodeAndUpdate(countryCode); - }}, new IntentFilter(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED), null, handler); - - Log.d(TAG, "mDefaultCountryCode " + mDefaultCountryCode); - } - - /** - * Enable verbose logging for WifiCountryCode. - */ - public void enableVerboseLogging(int verbose) { - if (verbose > 0) { - DBG = true; - } else { - DBG = false; - } - } - - private void initializeTelephonyCountryCodeIfNeeded() { - // If we don't have telephony country code set yet, poll it. - if (mTelephonyCountryCode == null) { - Log.d(TAG, "Reading country code from telephony"); - setCountryCode(mTelephonyManager.getNetworkCountryIso()); - } - } - - /** - * Change the state to indicates if wpa_supplicant is ready to handle country code changing - * request or not. - * We call native code to request country code changes only when wpa_supplicant is - * started but not yet L2 connected. - */ - public synchronized void setReadyForChange(boolean ready) { - mReady = ready; - mReadyTimestamp = FORMATTER.format(new Date(System.currentTimeMillis())); - // We are ready to set country code now. - // We need to post pending country code request. - if (mReady) { - updateCountryCode(); - } - } - - /** - * Enable force-country-code mode - * This is for forcing a country using cmd wifi from adb shell - * This is for test purpose only and we should disallow any update from - * telephony in this mode - * @param countryCode The forced two-letter country code - */ - synchronized void enableForceCountryCode(String countryCode) { - if (TextUtils.isEmpty(countryCode)) { - Log.d(TAG, "Fail to force country code because the received country code is empty"); - return; - } - mForceCountryCode = true; - mTelephonyCountryCode = countryCode.toUpperCase(Locale.US); - - // If wpa_supplicant is ready we set the country code now, otherwise it will be - // set once wpa_supplicant is ready. - if (mReady) { - updateCountryCode(); - } else { - Log.d(TAG, "skip update supplicant not ready yet"); - } - } - - /** - * Disable force-country-code mode - */ - synchronized void disableForceCountryCode() { - mForceCountryCode = false; - mTelephonyCountryCode = null; - - // If wpa_supplicant is ready we set the country code now, otherwise it will be - // set once wpa_supplicant is ready. - if (mReady) { - updateCountryCode(); - } else { - Log.d(TAG, "skip update supplicant not ready yet"); - } - } - - private boolean setCountryCode(String countryCode) { - if (mForceCountryCode) { - Log.d(TAG, "Telephony Country code ignored due to force-country-code mode"); - return false; - } - Log.d(TAG, "Set telephony country code to: " + countryCode); - mTelephonyCountryTimestamp = FORMATTER.format(new Date(System.currentTimeMillis())); - - // Empty country code. - if (TextUtils.isEmpty(countryCode)) { - if (mContext.getResources() - .getBoolean(R.bool.config_wifi_revert_country_code_on_cellular_loss)) { - Log.d(TAG, "Received empty country code, reset to default country code"); - mTelephonyCountryCode = null; - } - } else { - mTelephonyCountryCode = countryCode.toUpperCase(Locale.US); - } - return true; - } - - /** - * Handle country code change request. - * @param countryCode The country code intended to set. - * This is supposed to be from Telephony service. - * otherwise we think it is from other applications. - * @return Returns true if the country code passed in is acceptable. - */ - private boolean setCountryCodeAndUpdate(String countryCode) { - if (!setCountryCode(countryCode)) return false; - // If wpa_supplicant is ready we set the country code now, otherwise it will be - // set once wpa_supplicant is ready. - if (mReady) { - updateCountryCode(); - } else { - Log.d(TAG, "skip update supplicant not ready yet"); - } - - return true; - } - - /** - * Method to get the Country Code that was sent to wpa_supplicant. - * - * @return Returns the local copy of the Country Code that was sent to the driver upon - * setReadyForChange(true). - * If wpa_supplicant was never started, this may be null even if a SIM reported a valid - * country code. - * Returns null if no Country Code was sent to driver. - */ - @VisibleForTesting - public synchronized String getCountryCodeSentToDriver() { - return mDriverCountryCode; - } - - /** - * Method to return the currently reported Country Code from the SIM or phone default setting. - * - * @return The currently reported Country Code from the SIM. If there is no Country Code - * reported from SIM, a phone default Country Code will be returned. - * Returns null when there is no Country Code available. - */ - public synchronized String getCountryCode() { - return pickCountryCode(); - } - - /** - * Method to dump the current state of this WifiCounrtyCode object. - */ - public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("mRevertCountryCodeOnCellularLoss: " - + mContext.getResources().getBoolean( - R.bool.config_wifi_revert_country_code_on_cellular_loss)); - pw.println("mDefaultCountryCode: " + mDefaultCountryCode); - pw.println("mDriverCountryCode: " + mDriverCountryCode); - pw.println("mTelephonyCountryCode: " + mTelephonyCountryCode); - pw.println("mTelephonyCountryTimestamp: " + mTelephonyCountryTimestamp); - pw.println("mDriverCountryTimestamp: " + mDriverCountryTimestamp); - pw.println("mReadyTimestamp: " + mReadyTimestamp); - pw.println("mReady: " + mReady); - } - - private void updateCountryCode() { - String country = pickCountryCode(); - Log.d(TAG, "updateCountryCode to " + country); - - // We do not check if the country code equals the current one. - // There are two reasons: - // 1. Wpa supplicant may silently modify the country code. - // 2. If Wifi restarted therefoere wpa_supplicant also restarted, - // the country code counld be reset to '00' by wpa_supplicant. - if (country != null) { - setCountryCodeNative(country); - } - // We do not set country code if there is no candidate. This is reasonable - // because wpa_supplicant usually starts with an international safe country - // code setting: '00'. - } - - private String pickCountryCode() { - - initializeTelephonyCountryCodeIfNeeded(); - - if (mTelephonyCountryCode != null) { - return mTelephonyCountryCode; - } - if (mDefaultCountryCode != null) { - return mDefaultCountryCode; - } - // If there is no candidate country code we will return null. - return null; - } - - private boolean setCountryCodeNative(String country) { - mDriverCountryTimestamp = FORMATTER.format(new Date(System.currentTimeMillis())); - if (mWifiNative.setCountryCode(mWifiNative.getClientInterfaceName(), country)) { - Log.d(TAG, "Succeeded to set country code to: " + country); - mDriverCountryCode = country; - return true; - } - Log.d(TAG, "Failed to set country code to: " + country); - return false; - } -} - diff --git a/service/java/com/android/server/wifi/WifiDataStall.java b/service/java/com/android/server/wifi/WifiDataStall.java deleted file mode 100644 index ebc184773..000000000 --- a/service/java/com/android/server/wifi/WifiDataStall.java +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.CHANNEL_UTILIZATION_SCALE; - -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager.DeviceMobilityState; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; -import android.util.Log; - -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; -import com.android.server.wifi.scanner.KnownBandsChannelHelper; -import com.android.server.wifi.util.InformationElementUtil.BssLoad; -import com.android.wifi.resources.R; - -/** - * Looks for Wifi data stalls - */ -public class WifiDataStall { - private static final String TAG = "WifiDataStall"; - private boolean mVerboseLoggingEnabled = false; - public static final int INVALID_THROUGHPUT = -1; - // Maximum time gap between two WifiLinkLayerStats to trigger a data stall - public static final int MAX_MS_DELTA_FOR_DATA_STALL = 60 * 1000; // 1 minute - // Maximum time that a data stall start time stays valid. - public static final long VALIDITY_PERIOD_OF_DATA_STALL_START_MS = 30 * 1000; // 0.5 minutes - // Default Tx packet error rate when there is no Tx attempt - public static final int DEFAULT_TX_PACKET_ERROR_RATE = 5; - // Default CCA level when CCA stats are not available - public static final int DEFAULT_CCA_LEVEL_2G = CHANNEL_UTILIZATION_SCALE * 16 / 100; - public static final int DEFAULT_CCA_LEVEL_ABOVE_2G = CHANNEL_UTILIZATION_SCALE * 6 / 100; - // Minimum time interval in ms between two link layer stats cache updates - private static final int LLSTATS_CACHE_UPDATE_INTERVAL_MIN_MS = 30_000; - // Maximum time margin between two link layer stats for connection duration update - public static final int MAX_TIME_MARGIN_LAST_TWO_POLLS_MS = 200; - - private final FrameworkFacade mFacade; - private final DeviceConfigFacade mDeviceConfigFacade; - private final WifiMetrics mWifiMetrics; - private final Context mContext; - private final WifiChannelUtilization mWifiChannelUtilization; - private TelephonyManager mTelephonyManager; - private final ThroughputPredictor mThroughputPredictor; - private WifiNative.ConnectionCapabilities mConnectionCapabilities; - - private int mLastFrequency = -1; - private String mLastBssid; - private long mDataStallStartTimeMs = -1; - private Clock mClock; - private boolean mDataStallTx = false; - private boolean mDataStallRx = false; - private long mLastTxBytes; - private long mLastRxBytes; - private boolean mIsThroughputSufficient = true; - private boolean mIsCellularDataAvailable = false; - private final PhoneStateListener mPhoneStateListener; - private boolean mPhoneStateListenerEnabled = false; - private int mTxTputKbps = INVALID_THROUGHPUT; - private int mRxTputKbps = INVALID_THROUGHPUT; - - public WifiDataStall(FrameworkFacade facade, WifiMetrics wifiMetrics, Context context, - DeviceConfigFacade deviceConfigFacade, WifiChannelUtilization wifiChannelUtilization, - Clock clock, Handler handler, ThroughputPredictor throughputPredictor) { - mFacade = facade; - mDeviceConfigFacade = deviceConfigFacade; - mWifiMetrics = wifiMetrics; - mContext = context; - mClock = clock; - mWifiChannelUtilization = wifiChannelUtilization; - mWifiChannelUtilization.setCacheUpdateIntervalMs(LLSTATS_CACHE_UPDATE_INTERVAL_MIN_MS); - mThroughputPredictor = throughputPredictor; - mPhoneStateListener = new PhoneStateListener(new HandlerExecutor(handler)) { - @Override - public void onDataConnectionStateChanged(int state, int networkType) { - if (state == TelephonyManager.DATA_CONNECTED) { - mIsCellularDataAvailable = true; - } else if (state == TelephonyManager.DATA_DISCONNECTED) { - mIsCellularDataAvailable = false; - } else { - Log.e(TAG, "onDataConnectionStateChanged unexpected State: " + state); - return; - } - logd("Cellular Data: " + mIsCellularDataAvailable); - } - }; - } - - /** - * initialization after wifi is enabled - */ - public void init() { - mWifiChannelUtilization.init(null); - reset(); - } - - /** - * Reset internal variables - */ - public void reset() { - mLastTxBytes = 0; - mLastRxBytes = 0; - mLastFrequency = -1; - mLastBssid = null; - mDataStallStartTimeMs = -1; - mDataStallTx = false; - mDataStallRx = false; - mIsThroughputSufficient = true; - mTxTputKbps = INVALID_THROUGHPUT; - mRxTputKbps = INVALID_THROUGHPUT; - } - - /** - * Set ConnectionCapabilities after each association and roaming - */ - public void setConnectionCapabilities(WifiNative.ConnectionCapabilities capabilities) { - mConnectionCapabilities = capabilities; - } - /** - * Enable phone state listener - */ - public void enablePhoneStateListener() { - if (mTelephonyManager == null) { - mTelephonyManager = (TelephonyManager) mContext - .getSystemService(Context.TELEPHONY_SERVICE); - } - if (mTelephonyManager != null && !mPhoneStateListenerEnabled) { - mPhoneStateListenerEnabled = true; - mTelephonyManager.listen(mPhoneStateListener, - PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); - } - } - - /** - * Disable phone state listener - */ - public void disablePhoneStateListener() { - if (mTelephonyManager != null && mPhoneStateListenerEnabled) { - mPhoneStateListenerEnabled = false; - mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); - } - } - - /** - * Enable/Disable verbose logging. - * @param verbose true to enable and false to disable. - */ - public void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - mWifiChannelUtilization.enableVerboseLogging(verbose); - } - - /** - * Update device mobility state - * @param newState the new device mobility state - */ - public void setDeviceMobilityState(@DeviceMobilityState int newState) { - mWifiChannelUtilization.setDeviceMobilityState(newState); - } - - /** - * Check if current link layer throughput is sufficient. - * This should be called after checkDataStallAndThroughputSufficiency(). - * @return true if it is sufficient or false if it is insufficient - */ - public boolean isThroughputSufficient() { - return mIsThroughputSufficient; - } - - /** - * Check if cellular data is available - * @return true if it is available and false otherwise - */ - public boolean isCellularDataAvailable() { - return mIsCellularDataAvailable; - } - - /** - * Get the latest Tx throughput based on Tx link speed, PER and channel utilization - * @return the latest estimated Tx throughput in Kbps if it is available - * or INVALID_THROUGHPUT if it is not available - */ - public int getTxThroughputKbps() { - logd("tx tput in kbps: " + mTxTputKbps); - return mTxTputKbps; - } - - /** - * Get the latest Rx throughput based on Rx link speed and channel utilization - * @return the latest estimated Rx throughput in Kbps if it is available - * or INVALID_THROUGHPUT if it is not available - */ - public int getRxThroughputKbps() { - logd("rx tput in kbps: " + mRxTputKbps); - return mRxTputKbps; - } - - /** - * Update data stall detection, check throughput sufficiency and report wifi health stat - * with the latest link layer stats - * @param oldStats second most recent WifiLinkLayerStats - * @param newStats most recent WifiLinkLayerStats - * @param wifiInfo WifiInfo for current connection - * @return trigger type of WifiIsUnusableEvent - */ - public int checkDataStallAndThroughputSufficiency(WifiLinkLayerStats oldStats, - WifiLinkLayerStats newStats, WifiInfo wifiInfo) { - int currFrequency = wifiInfo.getFrequency(); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(newStats, currFrequency); - int ccaLevel = mWifiChannelUtilization.getUtilizationRatio(currFrequency); - mWifiMetrics.incrementChannelUtilizationCount(ccaLevel, currFrequency); - - if (oldStats == null || newStats == null) { - // First poll after new association - // Update throughput with prediction - if (wifiInfo.getRssi() != WifiInfo.INVALID_RSSI && mConnectionCapabilities != null) { - mTxTputKbps = mThroughputPredictor.predictTxThroughput(mConnectionCapabilities, - wifiInfo.getRssi(), currFrequency, ccaLevel) * 1000; - mRxTputKbps = mThroughputPredictor.predictRxThroughput(mConnectionCapabilities, - wifiInfo.getRssi(), currFrequency, ccaLevel) * 1000; - } - mIsThroughputSufficient = true; - mWifiMetrics.resetWifiIsUnusableLinkLayerStats(); - mWifiMetrics.incrementThroughputKbpsCount(mTxTputKbps, mRxTputKbps, currFrequency); - return WifiIsUnusableEvent.TYPE_UNKNOWN; - } - - long txSuccessDelta = (newStats.txmpdu_be + newStats.txmpdu_bk - + newStats.txmpdu_vi + newStats.txmpdu_vo) - - (oldStats.txmpdu_be + oldStats.txmpdu_bk - + oldStats.txmpdu_vi + oldStats.txmpdu_vo); - long txRetriesDelta = (newStats.retries_be + newStats.retries_bk - + newStats.retries_vi + newStats.retries_vo) - - (oldStats.retries_be + oldStats.retries_bk - + oldStats.retries_vi + oldStats.retries_vo); - long txBadDelta = (newStats.lostmpdu_be + newStats.lostmpdu_bk - + newStats.lostmpdu_vi + newStats.lostmpdu_vo) - - (oldStats.lostmpdu_be + oldStats.lostmpdu_bk - + oldStats.lostmpdu_vi + oldStats.lostmpdu_vo); - long rxSuccessDelta = (newStats.rxmpdu_be + newStats.rxmpdu_bk - + newStats.rxmpdu_vi + newStats.rxmpdu_vo) - - (oldStats.rxmpdu_be + oldStats.rxmpdu_bk - + oldStats.rxmpdu_vi + oldStats.rxmpdu_vo); - int timeDeltaLastTwoPollsMs = (int) (newStats.timeStampInMs - oldStats.timeStampInMs); - - long totalTxDelta = txSuccessDelta + txRetriesDelta; - boolean isTxTrafficHigh = (totalTxDelta * 1000) - > (mDeviceConfigFacade.getTxPktPerSecondThr() * timeDeltaLastTwoPollsMs); - boolean isRxTrafficHigh = (rxSuccessDelta * 1000) - > (mDeviceConfigFacade.getRxPktPerSecondThr() * timeDeltaLastTwoPollsMs); - if (timeDeltaLastTwoPollsMs < 0 - || txSuccessDelta < 0 - || txRetriesDelta < 0 - || txBadDelta < 0 - || rxSuccessDelta < 0) { - mIsThroughputSufficient = true; - // There was a reset in WifiLinkLayerStats - mWifiMetrics.resetWifiIsUnusableLinkLayerStats(); - return WifiIsUnusableEvent.TYPE_UNKNOWN; - } - - mWifiMetrics.updateWifiIsUnusableLinkLayerStats(txSuccessDelta, txRetriesDelta, - txBadDelta, rxSuccessDelta, timeDeltaLastTwoPollsMs); - - int txLinkSpeedMbps = wifiInfo.getLinkSpeed(); - int rxLinkSpeedMbps = wifiInfo.getRxLinkSpeedMbps(); - boolean isSameBssidAndFreq = mLastBssid == null || mLastFrequency == -1 - || (mLastBssid.equals(wifiInfo.getBSSID()) - && mLastFrequency == currFrequency); - mLastFrequency = currFrequency; - mLastBssid = wifiInfo.getBSSID(); - - if (ccaLevel == BssLoad.INVALID) { - ccaLevel = wifiInfo.is24GHz() ? DEFAULT_CCA_LEVEL_2G : DEFAULT_CCA_LEVEL_ABOVE_2G; - logd(" use default cca Level"); - } - logd(" ccaLevel = " + ccaLevel); - - int txPer = updateTxPer(txSuccessDelta, txRetriesDelta, isSameBssidAndFreq, - isTxTrafficHigh); - - boolean isTxTputLow = false; - boolean isRxTputLow = false; - - if (txLinkSpeedMbps > 0) { - // Exclude update with low rate management frames - if (isTxTrafficHigh - || txLinkSpeedMbps > mDeviceConfigFacade.getTxLinkSpeedLowThresholdMbps()) { - mTxTputKbps = (int) ((long) txLinkSpeedMbps * 1000 * (100 - txPer) / 100 - * (CHANNEL_UTILIZATION_SCALE - ccaLevel) / CHANNEL_UTILIZATION_SCALE); - } - isTxTputLow = mTxTputKbps < mDeviceConfigFacade.getDataStallTxTputThrKbps(); - } else { - mTxTputKbps = INVALID_THROUGHPUT; - } - - if (rxLinkSpeedMbps > 0) { - // Exclude update with low rate management frames - if (isRxTrafficHigh - || rxLinkSpeedMbps > mDeviceConfigFacade.getRxLinkSpeedLowThresholdMbps()) { - mRxTputKbps = (int) ((long) rxLinkSpeedMbps * 1000 - * (CHANNEL_UTILIZATION_SCALE - ccaLevel) / CHANNEL_UTILIZATION_SCALE); - } - isRxTputLow = mRxTputKbps < mDeviceConfigFacade.getDataStallRxTputThrKbps(); - } else { - mRxTputKbps = INVALID_THROUGHPUT; - } - mWifiMetrics.incrementThroughputKbpsCount(mTxTputKbps, mRxTputKbps, currFrequency); - - mIsThroughputSufficient = isThroughputSufficientInternal(mTxTputKbps, mRxTputKbps, - isTxTrafficHigh, isRxTrafficHigh, timeDeltaLastTwoPollsMs); - - int maxTimeDeltaMs = mContext.getResources().getInteger( - R.integer.config_wifiPollRssiIntervalMilliseconds) - + MAX_TIME_MARGIN_LAST_TWO_POLLS_MS; - if (timeDeltaLastTwoPollsMs > 0 && timeDeltaLastTwoPollsMs <= maxTimeDeltaMs) { - mWifiMetrics.incrementConnectionDuration(timeDeltaLastTwoPollsMs, - mIsThroughputSufficient, mIsCellularDataAvailable); - reportWifiHealthStat(currFrequency, timeDeltaLastTwoPollsMs, mIsThroughputSufficient, - mIsCellularDataAvailable); - } - - boolean possibleDataStallTx = isTxTputLow - || ccaLevel >= mDeviceConfigFacade.getDataStallCcaLevelThr() - || txPer >= mDeviceConfigFacade.getDataStallTxPerThr(); - boolean possibleDataStallRx = isRxTputLow - || ccaLevel >= mDeviceConfigFacade.getDataStallCcaLevelThr(); - - boolean dataStallTx = isTxTrafficHigh ? possibleDataStallTx : mDataStallTx; - boolean dataStallRx = isRxTrafficHigh ? possibleDataStallRx : mDataStallRx; - - return detectConsecutiveTwoDataStalls(timeDeltaLastTwoPollsMs, dataStallTx, dataStallRx); - } - - // Data stall event is triggered if there are consecutive Tx and/or Rx data stalls - // 1st data stall should be preceded by no data stall - // Reset mDataStallStartTimeMs to -1 if currently there is no Tx or Rx data stall - private int detectConsecutiveTwoDataStalls(int timeDeltaLastTwoPollsMs, - boolean dataStallTx, boolean dataStallRx) { - if (timeDeltaLastTwoPollsMs >= MAX_MS_DELTA_FOR_DATA_STALL) { - return WifiIsUnusableEvent.TYPE_UNKNOWN; - } - - if (dataStallTx || dataStallRx) { - mDataStallTx = mDataStallTx || dataStallTx; - mDataStallRx = mDataStallRx || dataStallRx; - if (mDataStallStartTimeMs == -1) { - mDataStallStartTimeMs = mClock.getElapsedSinceBootMillis(); - if (mDeviceConfigFacade.getDataStallDurationMs() == 0) { - mDataStallStartTimeMs = -1; - int result = calculateUsabilityEventType(mDataStallTx, mDataStallRx); - mDataStallRx = false; - mDataStallTx = false; - return result; - } - } else { - long elapsedTime = mClock.getElapsedSinceBootMillis() - mDataStallStartTimeMs; - if (elapsedTime >= mDeviceConfigFacade.getDataStallDurationMs()) { - mDataStallStartTimeMs = -1; - if (elapsedTime <= VALIDITY_PERIOD_OF_DATA_STALL_START_MS) { - int result = calculateUsabilityEventType(mDataStallTx, mDataStallRx); - mDataStallRx = false; - mDataStallTx = false; - return result; - } else { - mDataStallTx = false; - mDataStallRx = false; - } - } else { - // No need to do anything. - } - } - } else { - mDataStallStartTimeMs = -1; - mDataStallTx = false; - mDataStallRx = false; - } - return WifiIsUnusableEvent.TYPE_UNKNOWN; - } - - private int updateTxPer(long txSuccessDelta, long txRetriesDelta, boolean isSameBssidAndFreq, - boolean isTxTrafficHigh) { - if (!isSameBssidAndFreq) { - return DEFAULT_TX_PACKET_ERROR_RATE; - } - long txAttempts = txSuccessDelta + txRetriesDelta; - if (txAttempts <= 0 || !isTxTrafficHigh) { - return DEFAULT_TX_PACKET_ERROR_RATE; - } - return (int) (txRetriesDelta * 100 / txAttempts); - } - private int calculateUsabilityEventType(boolean dataStallTx, boolean dataStallRx) { - int result = WifiIsUnusableEvent.TYPE_UNKNOWN; - if (dataStallTx && dataStallRx) { - result = WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH; - } else if (dataStallTx) { - result = WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX; - } else if (dataStallRx) { - result = WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX; - } - mWifiMetrics.logWifiIsUnusableEvent(result); - return result; - } - - private boolean isThroughputSufficientInternal(int l2TxTputKbps, int l2RxTputKbps, - boolean isTxTrafficHigh, boolean isRxTrafficHigh, int timeDeltaLastTwoPollsMs) { - long txBytes = mFacade.getTotalTxBytes() - mFacade.getMobileTxBytes(); - long rxBytes = mFacade.getTotalRxBytes() - mFacade.getMobileRxBytes(); - if (timeDeltaLastTwoPollsMs > MAX_MS_DELTA_FOR_DATA_STALL - || mLastTxBytes == 0 || mLastRxBytes == 0) { - mLastTxBytes = txBytes; - mLastRxBytes = rxBytes; - return true; - } - - int l3TxTputKbps = (int) ((txBytes - mLastTxBytes) * 8 / timeDeltaLastTwoPollsMs); - int l3RxTputKbps = (int) ((rxBytes - mLastRxBytes) * 8 / timeDeltaLastTwoPollsMs); - - mLastTxBytes = txBytes; - mLastRxBytes = rxBytes; - - boolean isTxTputSufficient = isL2ThroughputSufficient(l2TxTputKbps, l3TxTputKbps, false); - boolean isRxTputSufficient = isL2ThroughputSufficient(l2RxTputKbps, l3RxTputKbps, true); - isTxTputSufficient = detectAndOverrideFalseInSufficient( - isTxTputSufficient, isTxTrafficHigh, mIsThroughputSufficient); - isRxTputSufficient = detectAndOverrideFalseInSufficient( - isRxTputSufficient, isRxTrafficHigh, mIsThroughputSufficient); - - boolean isThroughputSufficient = isTxTputSufficient && isRxTputSufficient; - - StringBuilder sb = new StringBuilder(); - logd(sb.append("L2 txTputKbps: ").append(l2TxTputKbps) - .append(", rxTputKbps: ").append(l2RxTputKbps) - .append(", L3 txTputKbps: ").append(l3TxTputKbps) - .append(", rxTputKbps: ").append(l3RxTputKbps) - .append(", TxTrafficHigh: ").append(isTxTrafficHigh) - .append(", RxTrafficHigh: ").append(isRxTrafficHigh) - .append(", Throughput Sufficient: ").append(isThroughputSufficient) - .toString()); - return isThroughputSufficient; - } - - /** - * L2 tput is sufficient when one of the following conditions is met - * 1) L3 tput is low and L2 tput is above its low threshold - * 2) L3 tput is not low and L2 tput over L3 tput ratio is above sufficientRatioThr - * 3) L3 tput is not low and L2 tput is above its high threshold - * 4) L2 tput is invalid - */ - private boolean isL2ThroughputSufficient(int l2TputKbps, int l3TputKbps, boolean isForRxTput) { - if (l2TputKbps == INVALID_THROUGHPUT) return true; - int tputSufficientLowThrKbps = mDeviceConfigFacade.getTxTputSufficientLowThrKbps(); - int tputSufficientHighThrKbps = mDeviceConfigFacade.getTxTputSufficientHighThrKbps(); - if (isForRxTput) { - tputSufficientLowThrKbps = mDeviceConfigFacade.getRxTputSufficientLowThrKbps(); - tputSufficientHighThrKbps = mDeviceConfigFacade.getRxTputSufficientHighThrKbps(); - } - boolean isL3TputLow = (l3TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrDen()) - < (tputSufficientLowThrKbps * mDeviceConfigFacade.getTputSufficientRatioThrNum()); - boolean isL2TputAboveLowThr = l2TputKbps >= tputSufficientLowThrKbps; - if (isL3TputLow) return isL2TputAboveLowThr; - - boolean isL2TputAboveHighThr = l2TputKbps >= tputSufficientHighThrKbps; - boolean isL2L3TputRatioAboveThr = - (l2TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrDen()) - >= (l3TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrNum()); - return isL2TputAboveHighThr || isL2L3TputRatioAboveThr; - } - - private boolean detectAndOverrideFalseInSufficient(boolean isTputSufficient, - boolean isTrafficHigh, boolean lastIsTputSufficient) { - boolean possibleFalseInsufficient = (!isTrafficHigh && !isTputSufficient); - return possibleFalseInsufficient ? lastIsTputSufficient : isTputSufficient; - } - - /** - * Report the latest Wifi connection health to statsd - */ - private void reportWifiHealthStat(int frequency, int timeDeltaLastTwoPollsMs, - boolean isThroughputSufficient, - boolean isCellularDataAvailable) { - int band = getBand(frequency); - WifiStatsLog.write(WifiStatsLog.WIFI_HEALTH_STAT_REPORTED, timeDeltaLastTwoPollsMs, - isThroughputSufficient, isCellularDataAvailable, band); - } - - private int getBand(int frequency) { - int band; - if (ScanResult.is24GHz(frequency)) { - band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_2G; - } else if (ScanResult.is5GHz(frequency)) { - if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_LOW_END_FREQ) { - band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_5G_LOW; - } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_MID_END_FREQ) { - band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_5G_MIDDLE; - } else { - band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_5G_HIGH; - } - } else if (ScanResult.is6GHz(frequency)) { - if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_LOW_END_FREQ) { - band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_6G_LOW; - } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_MID_END_FREQ) { - band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_6G_MIDDLE; - } else { - band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_6G_HIGH; - } - } else { - band = WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__UNKNOWN; - } - return band; - } - - private void logd(String string) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, string); - } - } -} diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java deleted file mode 100644 index 38045625e..000000000 --- a/service/java/com/android/server/wifi/WifiDiagnostics.java +++ /dev/null @@ -1,837 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import android.annotation.NonNull; -import android.content.Context; -import android.os.BugreportManager; -import android.os.BugreportParams; -import android.util.ArraySet; -import android.util.Base64; -import android.util.Log; -import android.util.SparseLongArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.util.ByteArrayRingBuffer; -import com.android.server.wifi.util.StringUtil; -import com.android.wifi.resources.R; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.zip.Deflater; - -/** - * Tracks various logs for framework. - */ -class WifiDiagnostics extends BaseWifiDiagnostics { - /** - * Thread-safety: - * 1) All non-private methods are |synchronized|. - * 2) Callbacks into WifiDiagnostics use non-private (and hence, synchronized) methods. See, e.g, - * onRingBufferData(), onWifiAlert(). - */ - - private static final String TAG = "WifiDiags"; - private static final boolean DBG = false; - - /** log level flags; keep these consistent with wifi_logger.h */ - - /** No logs whatsoever */ - public static final int VERBOSE_NO_LOG = 0; - /** No logs whatsoever */ - public static final int VERBOSE_NORMAL_LOG = 1; - /** Be careful since this one can affect performance and power */ - public static final int VERBOSE_LOG_WITH_WAKEUP = 2; - /** Be careful since this one can affect performance and power and memory */ - public static final int VERBOSE_DETAILED_LOG_WITH_WAKEUP = 3; - - /** ring buffer flags; keep these consistent with wifi_logger.h */ - public static final int RING_BUFFER_FLAG_HAS_BINARY_ENTRIES = 0x00000001; - public static final int RING_BUFFER_FLAG_HAS_ASCII_ENTRIES = 0x00000002; - public static final int RING_BUFFER_FLAG_HAS_PER_PACKET_ENTRIES = 0x00000004; - - /** various reason codes */ - public static final int REPORT_REASON_NONE = 0; - public static final int REPORT_REASON_ASSOC_FAILURE = 1; - public static final int REPORT_REASON_AUTH_FAILURE = 2; - public static final int REPORT_REASON_AUTOROAM_FAILURE = 3; - public static final int REPORT_REASON_DHCP_FAILURE = 4; - public static final int REPORT_REASON_UNEXPECTED_DISCONNECT = 5; - public static final int REPORT_REASON_SCAN_FAILURE = 6; - public static final int REPORT_REASON_USER_ACTION = 7; - public static final int REPORT_REASON_WIFINATIVE_FAILURE = 8; - public static final int REPORT_REASON_REACHABILITY_LOST = 9; - public static final int REPORT_REASON_FATAL_FW_ALERT = 10; - - /** number of bug reports to hold */ - public static final int MAX_BUG_REPORTS = 4; - - /** number of alerts to hold */ - public static final int MAX_ALERT_REPORTS = 1; - - /** minimum wakeup interval for each of the log levels */ - private static final int MinWakeupIntervals[] = new int[] { 0, 3600, 60, 10 }; - /** minimum buffer size for each of the log levels */ - private static final int MinBufferSizes[] = new int[] { 0, 16384, 16384, 65536 }; - - /** Map from dump reason to elapsed time millis */ - private final SparseLongArray mLastDumpTime = new SparseLongArray(); - - /** Minimum dump period with same error code */ - public static final long MIN_DUMP_TIME_WINDOW_MILLIS = 10 * 60 * 1000; // 10 mins - - // Timeout for logcat process termination - private static final long LOGCAT_PROC_TIMEOUT_MILLIS = 50; - // Timeout for logcat read from input/error stream each. - @VisibleForTesting - public static final long LOGCAT_READ_TIMEOUT_MILLIS = 50; - - private long mLastBugReportTime; - - @VisibleForTesting public static final String FIRMWARE_DUMP_SECTION_HEADER = - "FW Memory dump"; - @VisibleForTesting public static final String DRIVER_DUMP_SECTION_HEADER = - "Driver state dump"; - - private int mLogLevel = VERBOSE_NO_LOG; - private boolean mIsLoggingEventHandlerRegistered; - private WifiNative.RingBufferStatus[] mRingBuffers; - private WifiNative.RingBufferStatus mPerPacketRingBuffer; - private final Context mContext; - private final BuildProperties mBuildProperties; - private final WifiLog mLog; - private final LastMileLogger mLastMileLogger; - private final Runtime mJavaRuntime; - private final WifiMetrics mWifiMetrics; - private int mMaxRingBufferSizeBytes; - private WifiInjector mWifiInjector; - private Clock mClock; - - /** Interfaces started logging */ - private final Set<String> mActiveInterfaces = new ArraySet<>(); - - public WifiDiagnostics(Context context, WifiInjector wifiInjector, - WifiNative wifiNative, BuildProperties buildProperties, - LastMileLogger lastMileLogger, Clock clock) { - super(wifiNative); - - mContext = context; - mBuildProperties = buildProperties; - mIsLoggingEventHandlerRegistered = false; - mLog = wifiInjector.makeLog(TAG); - mLastMileLogger = lastMileLogger; - mJavaRuntime = wifiInjector.getJavaRuntime(); - mWifiMetrics = wifiInjector.getWifiMetrics(); - mWifiInjector = wifiInjector; - mClock = clock; - } - - /** - * Start wifi HAL dependent logging features. - * This method should be called only after the interface has - * been set up. - * - * @param ifaceName the interface requesting to start logging. - */ - @Override - public synchronized void startLogging(@NonNull String ifaceName) { - if (mActiveInterfaces.contains(ifaceName)) { - Log.w(TAG, "Interface: " + ifaceName + " had already started logging"); - return; - } - if (mActiveInterfaces.isEmpty()) { - mFirmwareVersion = mWifiNative.getFirmwareVersion(); - mDriverVersion = mWifiNative.getDriverVersion(); - mSupportedFeatureSet = mWifiNative.getSupportedLoggerFeatureSet(); - - if (!mIsLoggingEventHandlerRegistered) { - mIsLoggingEventHandlerRegistered = mWifiNative.setLoggingEventHandler(mHandler); - } - - startLoggingRingBuffers(); - } - - mActiveInterfaces.add(ifaceName); - - Log.d(TAG, "startLogging() iface list is " + mActiveInterfaces - + " after adding " + ifaceName); - } - - @Override - public synchronized void startPacketLog() { - if (mPerPacketRingBuffer != null) { - startLoggingRingBuffer(mPerPacketRingBuffer); - } else { - if (DBG) mLog.tC("There is no per packet ring buffer"); - } - } - - @Override - public synchronized void stopPacketLog() { - if (mPerPacketRingBuffer != null) { - stopLoggingRingBuffer(mPerPacketRingBuffer); - } else { - if (DBG) mLog.tC("There is no per packet ring buffer"); - } - } - - /** - * Stop wifi HAL dependent logging features. - * This method should be called before the interface has been - * torn down. - * - * @param ifaceName the interface requesting to stop logging. - */ - @Override - public synchronized void stopLogging(@NonNull String ifaceName) { - if (!mActiveInterfaces.contains(ifaceName)) { - Log.w(TAG, "ifaceName: " + ifaceName + " is not in the start log user list"); - return; - } - - mActiveInterfaces.remove(ifaceName); - - Log.d(TAG, "stopLogging() iface list is " + mActiveInterfaces - + " after removing " + ifaceName); - - if (!mActiveInterfaces.isEmpty()) { - return; - } - if (mLogLevel != VERBOSE_NO_LOG) { - stopLoggingAllBuffers(); - mRingBuffers = null; - } - if (mIsLoggingEventHandlerRegistered) { - if (!mWifiNative.resetLogHandler()) { - mLog.wC("Fail to reset log handler"); - } else { - if (DBG) mLog.tC("Reset log handler"); - } - // Clear mIsLoggingEventHandlerRegistered even if resetLogHandler() failed, because - // the log handler is in an indeterminate state. - mIsLoggingEventHandlerRegistered = false; - } - } - - @Override - public synchronized void reportConnectionEvent(byte event) { - mLastMileLogger.reportConnectionEvent(event); - if (event == CONNECTION_EVENT_FAILED || event == CONNECTION_EVENT_TIMEOUT) { - mPacketFatesForLastFailure = fetchPacketFates(); - } - } - - @Override - public synchronized void captureBugReportData(int reason) { - BugReport report = captureBugreport(reason, isVerboseLoggingEnabled()); - mLastBugReports.addLast(report); - flushDump(reason); - } - - @Override - public synchronized void captureAlertData(int errorCode, byte[] alertData) { - BugReport report = captureBugreport(errorCode, isVerboseLoggingEnabled()); - report.alertData = alertData; - mLastAlerts.addLast(report); - /* Flush HAL ring buffer when detecting data stall */ - if (Arrays.stream(mContext.getResources().getIntArray( - R.array.config_wifi_fatal_firmware_alert_error_code_list)) - .boxed().collect(Collectors.toList()).contains(errorCode)) { - flushDump(REPORT_REASON_FATAL_FW_ALERT); - } - } - - @Override - public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - super.dump(pw); - - for (int i = 0; i < mLastAlerts.size(); i++) { - pw.println("--------------------------------------------------------------------"); - pw.println("Alert dump " + i); - pw.print(mLastAlerts.get(i)); - pw.println("--------------------------------------------------------------------"); - } - - for (int i = 0; i < mLastBugReports.size(); i++) { - pw.println("--------------------------------------------------------------------"); - pw.println("Bug dump " + i); - pw.print(mLastBugReports.get(i)); - pw.println("--------------------------------------------------------------------"); - } - - pw.println("Last Flush Time: " + mLastDumpTime.toString()); - pw.println("--------------------------------------------------------------------"); - - dumpPacketFates(pw); - mLastMileLogger.dump(pw); - - pw.println("--------------------------------------------------------------------"); - } - - /** - * Initiates a system-level bug report if there is no bug report taken recently. - * This is done in a non-blocking fashion. - */ - @Override - public void takeBugReport(String bugTitle, String bugDetail) { - if (mBuildProperties.isUserBuild() - || !mContext.getResources().getBoolean( - R.bool.config_wifi_diagnostics_bugreport_enabled)) { - return; - } - long currentTime = mClock.getWallClockMillis(); - if ((currentTime - mLastBugReportTime) - < mWifiInjector.getDeviceConfigFacade().getBugReportMinWindowMs() - && mLastBugReportTime > 0) { - return; - } - mLastBugReportTime = currentTime; - BugreportManager bugreportManager = mContext.getSystemService(BugreportManager.class); - BugreportParams params = new BugreportParams(BugreportParams.BUGREPORT_MODE_FULL); - try { - bugreportManager.requestBugreport(params, bugTitle, bugDetail); - } catch (RuntimeException e) { - mLog.err("error taking bugreport: %").c(e.getClass().getName()).flush(); - } - } - - /* private methods and data */ - class BugReport { - long systemTimeMs; - long kernelTimeNanos; - int errorCode; - HashMap<String, byte[][]> ringBuffers = new HashMap(); - byte[] fwMemoryDump; - byte[] mDriverStateDump; - byte[] alertData; - ArrayList<String> kernelLogLines; - ArrayList<String> logcatLines; - - void clearVerboseLogs() { - fwMemoryDump = null; - mDriverStateDump = null; - } - - public String toString() { - StringBuilder builder = new StringBuilder(); - - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(systemTimeMs); - builder.append("system time = ").append( - String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)).append("\n"); - - long kernelTimeMs = kernelTimeNanos/(1000*1000); - builder.append("kernel time = ").append(kernelTimeMs/1000).append(".").append - (kernelTimeMs%1000).append("\n"); - - if (alertData == null) - builder.append("reason = ").append(errorCode).append("\n"); - else { - builder.append("errorCode = ").append(errorCode); - builder.append("data \n"); - builder.append(compressToBase64(alertData)).append("\n"); - } - - if (kernelLogLines != null) { - builder.append("kernel log: \n"); - for (int i = 0; i < kernelLogLines.size(); i++) { - builder.append(kernelLogLines.get(i)).append("\n"); - } - builder.append("\n"); - } - - if (logcatLines != null) { - builder.append("system log: \n"); - for (int i = 0; i < logcatLines.size(); i++) { - builder.append(logcatLines.get(i)).append("\n"); - } - builder.append("\n"); - } - - for (HashMap.Entry<String, byte[][]> e : ringBuffers.entrySet()) { - String ringName = e.getKey(); - byte[][] buffers = e.getValue(); - builder.append("ring-buffer = ").append(ringName).append("\n"); - - int size = 0; - for (int i = 0; i < buffers.length; i++) { - size += buffers[i].length; - } - - byte[] buffer = new byte[size]; - int index = 0; - for (int i = 0; i < buffers.length; i++) { - System.arraycopy(buffers[i], 0, buffer, index, buffers[i].length); - index += buffers[i].length; - } - - builder.append(compressToBase64(buffer)); - builder.append("\n"); - } - - if (fwMemoryDump != null) { - builder.append(FIRMWARE_DUMP_SECTION_HEADER); - builder.append("\n"); - builder.append(compressToBase64(fwMemoryDump)); - builder.append("\n"); - } - - if (mDriverStateDump != null) { - builder.append(DRIVER_DUMP_SECTION_HEADER); - if (StringUtil.isAsciiPrintable(mDriverStateDump)) { - builder.append(" (ascii)\n"); - builder.append(new String(mDriverStateDump, Charset.forName("US-ASCII"))); - builder.append("\n"); - } else { - builder.append(" (base64)\n"); - builder.append(compressToBase64(mDriverStateDump)); - } - } - - return builder.toString(); - } - } - - class LimitedCircularArray<E> { - private ArrayList<E> mArrayList; - private int mMax; - LimitedCircularArray(int max) { - mArrayList = new ArrayList<E>(max); - mMax = max; - } - - public final void addLast(E e) { - if (mArrayList.size() >= mMax) - mArrayList.remove(0); - mArrayList.add(e); - } - - public final int size() { - return mArrayList.size(); - } - - public final E get(int i) { - return mArrayList.get(i); - } - } - - private final LimitedCircularArray<BugReport> mLastAlerts = - new LimitedCircularArray<BugReport>(MAX_ALERT_REPORTS); - private final LimitedCircularArray<BugReport> mLastBugReports = - new LimitedCircularArray<BugReport>(MAX_BUG_REPORTS); - private final HashMap<String, ByteArrayRingBuffer> mRingBufferData = new HashMap(); - - private final WifiNative.WifiLoggerEventHandler mHandler = - new WifiNative.WifiLoggerEventHandler() { - @Override - public void onRingBufferData(WifiNative.RingBufferStatus status, byte[] buffer) { - WifiDiagnostics.this.onRingBufferData(status, buffer); - } - - @Override - public void onWifiAlert(int errorCode, byte[] buffer) { - WifiDiagnostics.this.onWifiAlert(errorCode, buffer); - } - }; - - synchronized void onRingBufferData(WifiNative.RingBufferStatus status, byte[] buffer) { - ByteArrayRingBuffer ring = mRingBufferData.get(status.name); - if (ring != null) { - ring.appendBuffer(buffer); - } - } - - synchronized void onWifiAlert(int errorCode, @NonNull byte[] buffer) { - captureAlertData(errorCode, buffer); - mWifiMetrics.logFirmwareAlert(errorCode); - mWifiInjector.getWifiScoreCard().noteFirmwareAlert(errorCode); - } - - /** - * Enables or disables verbose logging - * - * @param verbose - with the obvious interpretation - */ - @Override - public synchronized void enableVerboseLogging(boolean verboseEnabled) { - final int ringBufferByteLimitSmall = mContext.getResources().getInteger( - R.integer.config_wifi_logger_ring_buffer_default_size_limit_kb) * 1024; - final int ringBufferByteLimitLarge = mContext.getResources().getInteger( - R.integer.config_wifi_logger_ring_buffer_verbose_size_limit_kb) * 1024; - if (verboseEnabled) { - mLogLevel = VERBOSE_LOG_WITH_WAKEUP; - mMaxRingBufferSizeBytes = ringBufferByteLimitLarge; - } else { - mLogLevel = VERBOSE_NORMAL_LOG; - mMaxRingBufferSizeBytes = enableVerboseLoggingForDogfood() - ? ringBufferByteLimitLarge : ringBufferByteLimitSmall; - } - - if (!mActiveInterfaces.isEmpty()) { - mLog.wC("verbosity changed: restart logging"); - startLoggingRingBuffers(); - } - } - - private boolean isVerboseLoggingEnabled() { - return mLogLevel > VERBOSE_NORMAL_LOG; - } - - private void clearVerboseLogs() { - - for (int i = 0; i < mLastAlerts.size(); i++) { - mLastAlerts.get(i).clearVerboseLogs(); - } - - for (int i = 0; i < mLastBugReports.size(); i++) { - mLastBugReports.get(i).clearVerboseLogs(); - } - } - - private boolean fetchRingBuffers() { - if (mRingBuffers != null) return true; - - mRingBuffers = mWifiNative.getRingBufferStatus(); - if (mRingBuffers != null) { - for (WifiNative.RingBufferStatus buffer : mRingBuffers) { - if (DBG) mLog.trace("RingBufferStatus is: %").c(buffer.name).flush(); - if (mRingBufferData.containsKey(buffer.name) == false) { - mRingBufferData.put(buffer.name, - new ByteArrayRingBuffer(mMaxRingBufferSizeBytes)); - } - if ((buffer.flag & RING_BUFFER_FLAG_HAS_PER_PACKET_ENTRIES) != 0) { - mPerPacketRingBuffer = buffer; - } - } - } else { - mLog.wC("no ring buffers found"); - } - - return mRingBuffers != null; - } - - private void resizeRingBuffers() { - for (ByteArrayRingBuffer byteArrayRingBuffer : mRingBufferData.values()) { - byteArrayRingBuffer.resize(mMaxRingBufferSizeBytes); - } - } - - private void startLoggingRingBuffers() { - if (!isVerboseLoggingEnabled()) { - clearVerboseLogs(); - } - if (mRingBuffers == null) { - fetchRingBuffers(); - } - if (mRingBuffers != null) { - // Log level may have changed, so restart logging with new levels. - stopLoggingAllBuffers(); - resizeRingBuffers(); - startLoggingAllExceptPerPacketBuffers(); - } - } - - private boolean startLoggingAllExceptPerPacketBuffers() { - - if (mRingBuffers == null) { - if (DBG) mLog.tC("No ring buffers to log anything!"); - return false; - } - - for (WifiNative.RingBufferStatus buffer : mRingBuffers){ - - if ((buffer.flag & RING_BUFFER_FLAG_HAS_PER_PACKET_ENTRIES) != 0) { - /* skip per-packet-buffer */ - if (DBG) mLog.trace("skipped per packet logging ring %").c(buffer.name).flush(); - continue; - } - - startLoggingRingBuffer(buffer); - } - - return true; - } - - private boolean startLoggingRingBuffer(WifiNative.RingBufferStatus buffer) { - - int minInterval = MinWakeupIntervals[mLogLevel]; - int minDataSize = MinBufferSizes[mLogLevel]; - - if (mWifiNative.startLoggingRingBuffer( - mLogLevel, 0, minInterval, minDataSize, buffer.name) == false) { - if (DBG) mLog.warn("Could not start logging ring %").c(buffer.name).flush(); - return false; - } - - return true; - } - - private boolean stopLoggingRingBuffer(WifiNative.RingBufferStatus buffer) { - if (mWifiNative.startLoggingRingBuffer(0, 0, 0, 0, buffer.name) == false) { - if (DBG) mLog.warn("Could not stop logging ring %").c(buffer.name).flush(); - } - return true; - } - - private boolean stopLoggingAllBuffers() { - if (mRingBuffers != null) { - for (WifiNative.RingBufferStatus buffer : mRingBuffers) { - stopLoggingRingBuffer(buffer); - } - } - return true; - } - - private boolean enableVerboseLoggingForDogfood() { - return true; - - } - - private boolean flushDump(int errorCode) { - if (errorCode == REPORT_REASON_USER_ACTION) return false; - - long currentTime = mClock.getWallClockMillis(); - int index = mLastDumpTime.indexOfKey(errorCode); - if (index >= 0) { - if (currentTime - mLastDumpTime.valueAt(index) < MIN_DUMP_TIME_WINDOW_MILLIS) { - return false; - } - } - if (!mWifiNative.flushRingBufferData()) { - mLog.wC("could not flush ringbuffer"); - return false; - } - mLastDumpTime.put(errorCode, currentTime); - return true; - } - - private BugReport captureBugreport(int errorCode, boolean captureFWDump) { - BugReport report = new BugReport(); - report.errorCode = errorCode; - report.systemTimeMs = System.currentTimeMillis(); - report.kernelTimeNanos = System.nanoTime(); - - if (mRingBuffers != null) { - for (WifiNative.RingBufferStatus buffer : mRingBuffers) { - /* this will push data in mRingBuffers */ - mWifiNative.getRingBufferData(buffer.name); - ByteArrayRingBuffer data = mRingBufferData.get(buffer.name); - byte[][] buffers = new byte[data.getNumBuffers()][]; - for (int i = 0; i < data.getNumBuffers(); i++) { - buffers[i] = data.getBuffer(i).clone(); - } - report.ringBuffers.put(buffer.name, buffers); - } - } - - report.logcatLines = getLogcatSystem(127); - report.kernelLogLines = getLogcatKernel(127); - - if (captureFWDump) { - report.fwMemoryDump = mWifiNative.getFwMemoryDump(); - report.mDriverStateDump = mWifiNative.getDriverStateDump(); - } - return report; - } - - @VisibleForTesting - LimitedCircularArray<BugReport> getBugReports() { - return mLastBugReports; - } - - @VisibleForTesting - LimitedCircularArray<BugReport> getAlertReports() { - return mLastAlerts; - } - - private String compressToBase64(byte[] input) { - String result; - //compress - Deflater compressor = new Deflater(); - compressor.setLevel(Deflater.BEST_SPEED); - compressor.setInput(input); - compressor.finish(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length); - final byte[] buf = new byte[1024]; - - while (!compressor.finished()) { - int count = compressor.deflate(buf); - bos.write(buf, 0, count); - } - - try { - compressor.end(); - bos.close(); - } catch (IOException e) { - mLog.wC("ByteArrayOutputStream close error"); - result = android.util.Base64.encodeToString(input, Base64.DEFAULT); - return result; - } - - byte[] compressed = bos.toByteArray(); - if (DBG) { - mLog.dump("length is: %").c(compressed == null ? 0 : compressed.length).flush(); - } - - //encode - result = android.util.Base64.encodeToString( - compressed.length < input.length ? compressed : input , Base64.DEFAULT); - - if (DBG) { - mLog.dump("FwMemoryDump length is: %").c(result.length()).flush(); - } - - return result; - } - - private void readLogcatStreamLinesWithTimeout( - BufferedReader inReader, List<String> outLinesList) throws IOException { - long startTimeMs = mClock.getElapsedSinceBootMillis(); - while (mClock.getElapsedSinceBootMillis() < startTimeMs + LOGCAT_READ_TIMEOUT_MILLIS) { - // If there is a burst of data, continue reading without checking for timeout. - while (inReader.ready()) { - String line = inReader.readLine(); - if (line == null) return; // end of stream. - outLinesList.add(line); - } - mClock.sleep(LOGCAT_READ_TIMEOUT_MILLIS / 10); - } - } - - private ArrayList<String> getLogcat(String logcatSections, int maxLines) { - ArrayList<String> lines = new ArrayList<>(maxLines); - try { - Process process = mJavaRuntime.exec( - String.format("logcat -b %s -t %d", logcatSections, maxLines)); - readLogcatStreamLinesWithTimeout( - new BufferedReader(new InputStreamReader(process.getInputStream())), lines); - readLogcatStreamLinesWithTimeout( - new BufferedReader(new InputStreamReader(process.getErrorStream())), lines); - process.waitFor(LOGCAT_PROC_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); - } catch (InterruptedException|IOException e) { - mLog.dump("Exception while capturing logcat: %").c(e.toString()).flush(); - } - return lines; - - } - - private ArrayList<String> getLogcatSystem(int maxLines) { - return getLogcat("main,system,crash", maxLines); - } - - private ArrayList<String> getLogcatKernel(int maxLines) { - return getLogcat("kernel", maxLines); - } - - /** Packet fate reporting */ - private ArrayList<WifiNative.FateReport> mPacketFatesForLastFailure; - - private ArrayList<WifiNative.FateReport> fetchPacketFates() { - ArrayList<WifiNative.FateReport> mergedFates = new ArrayList<WifiNative.FateReport>(); - WifiNative.TxFateReport[] txFates = - new WifiNative.TxFateReport[WifiLoggerHal.MAX_FATE_LOG_LEN]; - if (mWifiNative.getTxPktFates(mWifiNative.getClientInterfaceName(), txFates)) { - for (int i = 0; i < txFates.length && txFates[i] != null; i++) { - mergedFates.add(txFates[i]); - } - } - - WifiNative.RxFateReport[] rxFates = - new WifiNative.RxFateReport[WifiLoggerHal.MAX_FATE_LOG_LEN]; - if (mWifiNative.getRxPktFates(mWifiNative.getClientInterfaceName(), rxFates)) { - for (int i = 0; i < rxFates.length && rxFates[i] != null; i++) { - mergedFates.add(rxFates[i]); - } - } - - Collections.sort(mergedFates, new Comparator<WifiNative.FateReport>() { - @Override - public int compare(WifiNative.FateReport lhs, WifiNative.FateReport rhs) { - return Long.compare(lhs.mDriverTimestampUSec, rhs.mDriverTimestampUSec); - } - }); - - return mergedFates; - } - - private void dumpPacketFates(PrintWriter pw) { - dumpPacketFatesInternal(pw, "Last failed connection fates", mPacketFatesForLastFailure, - isVerboseLoggingEnabled()); - dumpPacketFatesInternal(pw, "Latest fates", fetchPacketFates(), isVerboseLoggingEnabled()); - } - - private static void dumpPacketFatesInternal(PrintWriter pw, String description, - ArrayList<WifiNative.FateReport> fates, boolean verbose) { - if (fates == null) { - pw.format("No fates fetched for \"%s\"\n", description); - return; - } - - if (fates.size() == 0) { - pw.format("HAL provided zero fates for \"%s\"\n", description); - return; - } - - pw.format("--------------------- %s ----------------------\n", description); - - StringBuilder verboseOutput = new StringBuilder(); - pw.print(WifiNative.FateReport.getTableHeader()); - for (WifiNative.FateReport fate : fates) { - pw.print(fate.toTableRowString()); - if (verbose) { - // Important: only print Personally Identifiable Information (PII) if verbose - // logging is turned on. - verboseOutput.append(fate.toVerboseStringWithPiiAllowed()); - verboseOutput.append("\n"); - } - } - - if (verbose) { - pw.format("\n>>> VERBOSE PACKET FATE DUMP <<<\n\n"); - pw.print(verboseOutput.toString()); - } - - pw.println("--------------------------------------------------------------------"); - } - - /** - * Enable packet fate monitoring. - * - * @param ifaceName Name of the interface. - */ - @Override - public void startPktFateMonitoring(@NonNull String ifaceName) { - if (!mWifiNative.startPktFateMonitoring(ifaceName)) { - mLog.wC("Failed to start packet fate monitoring"); - } - } -} diff --git a/service/java/com/android/server/wifi/WifiHealthMonitor.java b/service/java/com/android/server/wifi/WifiHealthMonitor.java deleted file mode 100644 index b21ea516d..000000000 --- a/service/java/com/android/server/wifi/WifiHealthMonitor.java +++ /dev/null @@ -1,1081 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS; - -import static com.android.server.wifi.WifiScoreCard.TS_NONE; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.app.AlarmManager; -import android.content.Context; -import android.content.pm.ModuleInfo; -import android.content.pm.PackageManager; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.DeviceMobilityState; -import android.net.wifi.WifiScanner; -import android.os.Build; -import android.os.Handler; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.WifiScoreCard.MemoryStore; -import com.android.server.wifi.WifiScoreCard.MemoryStoreAccessBase; -import com.android.server.wifi.WifiScoreCard.PerNetwork; -import com.android.server.wifi.proto.WifiScoreCardProto.SoftwareBuildInfo; -import com.android.server.wifi.proto.WifiScoreCardProto.SystemInfoStats; -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorFailureStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics; -import com.android.server.wifi.util.ScanResultUtil; - -import com.google.protobuf.InvalidProtocolBufferException; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -import javax.annotation.concurrent.NotThreadSafe; - -/** - * Monitor and detect potential WiFi health issue when RSSI is sufficiently high. - * There are two detections, daily detection and post-boot detection. - * Post-boot detection is to detect abnormal scan/connection behavior change after device reboot - * and/or SW build change. - * Daily detection is to detect connection and other behavior changes especially after SW change. - */ - -@NotThreadSafe -public class WifiHealthMonitor { - private static final String TAG = "WifiHealthMonitor"; - private boolean mVerboseLoggingEnabled = false; - public static final String DAILY_DETECTION_TIMER_TAG = - "WifiHealthMonitor Schedule Daily Detection Timer"; - public static final String POST_BOOT_DETECTION_TIMER_TAG = - "WifiHealthMonitor Schedule Post-Boot Detection Timer"; - // Package name of WiFi mainline module found from the following adb command - // adb shell pm list packages --apex-only| grep wifi - private static final String WIFI_APEX_NAME = "com.android.wifi"; - private static final String SYSTEM_INFO_DATA_NAME = "systemInfoData"; - // The time that device waits after device boot before triggering post-boot detection. - // This needs be long enough so that memory read can complete before post-boot detection. - private static final int POST_BOOT_DETECTION_WAIT_TIME_MS = 25_000; - // The time interval between two daily detections - private static final long DAILY_DETECTION_INTERVAL_MS = 24 * 3600_000; - public static final int DAILY_DETECTION_HOUR = 23; - private static final int DAILY_DETECTION_MIN = 00; - private static final long MIN_WAIT_TIME_BEFORE_FIRST_DETECTION_MS = 100_000; - // Max interval between pre-boot scan and post-boot scan to qualify post-boot scan detection - private static final long MAX_INTERVAL_BETWEEN_TWO_SCAN_MS = 60_000; - // The minimum number of BSSIDs that should be found during a normal scan to trigger detection - // of an abnormal scan which happens either before or after the normal scan within a short time. - // Minimum number of BSSIDs found at 2G with a normal scan - private static final int MIN_NUM_BSSID_SCAN_2G = 2; - // Minimum number of BSSIDs found above 2G with a normal scan - private static final int MIN_NUM_BSSID_SCAN_ABOVE_2G = 2; - // Minimum Tx speed in Mbps for disconnection stats collection - static final int HEALTH_MONITOR_COUNT_TX_SPEED_MIN_MBPS = 54; - // Minimum Tx packet per seconds for disconnection stats collection - static final int HEALTH_MONITOR_MIN_TX_PACKET_PER_SEC = 4; - - private final Context mContext; - private final WifiConfigManager mWifiConfigManager; - private final WifiScoreCard mWifiScoreCard; - private final Clock mClock; - private final AlarmManager mAlarmManager; - private final Handler mHandler; - private final WifiNative mWifiNative; - private final WifiInjector mWifiInjector; - private final DeviceConfigFacade mDeviceConfigFacade; - private WifiScanner mScanner; - private MemoryStore mMemoryStore; - private boolean mWifiEnabled; - private WifiSystemInfoStats mWifiSystemInfoStats; - private ScanStats mFirstScanStats = new ScanStats(); - // Detected significant increase of failure stats between daily data and historical data - private FailureStats mFailureStatsIncrease = new FailureStats(); - // Detected significant decrease of failure stats between daily data and historical data - private FailureStats mFailureStatsDecrease = new FailureStats(); - // Detected high failure stats from daily data without historical data - private FailureStats mFailureStatsHigh = new FailureStats(); - private int mNumNetworkSufficientRecentStatsOnly = 0; - private int mNumNetworkSufficientRecentPrevStats = 0; - private boolean mHasNewDataForWifiMetrics = false; - private int mDeviceMobilityState = WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN; - - WifiHealthMonitor(Context context, WifiInjector wifiInjector, Clock clock, - WifiConfigManager wifiConfigManager, WifiScoreCard wifiScoreCard, Handler handler, - WifiNative wifiNative, String l2KeySeed, DeviceConfigFacade deviceConfigFacade) { - mContext = context; - mWifiInjector = wifiInjector; - mClock = clock; - mWifiConfigManager = wifiConfigManager; - mWifiScoreCard = wifiScoreCard; - mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); - mHandler = handler; - mWifiNative = wifiNative; - mDeviceConfigFacade = deviceConfigFacade; - mWifiEnabled = false; - mWifiSystemInfoStats = new WifiSystemInfoStats(l2KeySeed); - mWifiConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener()); - } - - /** - * Enable/Disable verbose logging. - * - * @param verbose true to enable and false to disable. - */ - public void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - } - - private final AlarmManager.OnAlarmListener mDailyDetectionListener = - new AlarmManager.OnAlarmListener() { - public void onAlarm() { - dailyDetectionHandler(); - } - }; - - private final AlarmManager.OnAlarmListener mPostBootDetectionListener = - new AlarmManager.OnAlarmListener() { - public void onAlarm() { - postBootDetectionHandler(); - } - }; - - /** - * Installs a memory store, request read for post-boot detection and set up detection alarms. - */ - public void installMemoryStoreSetUpDetectionAlarm(@NonNull MemoryStore memoryStore) { - if (mMemoryStore == null) { - mMemoryStore = memoryStore; - Log.i(TAG, "Installing MemoryStore"); - } else { - mMemoryStore = memoryStore; - Log.e(TAG, "Reinstalling MemoryStore"); - } - requestReadForPostBootDetection(); - setFirstHealthDetectionAlarm(); - setPostBootDetectionAlarm(); - } - - /** - * Set WiFi enable state. - * During the off->on transition, retrieve scanner. - * During the on->off transition, issue MemoryStore write to save data. - */ - public void setWifiEnabled(boolean enable) { - mWifiEnabled = enable; - logd("Set WiFi " + (enable ? "enabled" : "disabled")); - if (enable) { - retrieveWifiScanner(); - } else { - doWrites(); - } - } - - /** - * Issue MemoryStore write. This should be called from time to time - * to save the state to persistent storage. - */ - public void doWrites() { - mWifiSystemInfoStats.writeToMemory(); - } - - /** - * Set device mobility state to assist abnormal scan failure detection - */ - public void setDeviceMobilityState(@DeviceMobilityState int newState) { - logd("Device mobility state: " + newState); - mDeviceMobilityState = newState; - mWifiSystemInfoStats.setMobilityState(newState); - } - - /** - * Get the maximum scan RSSI valid time for scan RSSI search which is done by finding - * the maximum RSSI found among all valid scan detail entries of each network's scanDetailCache - * If a scanDetail was older than the returned value, it will not be considered valid. - */ - public int getScanRssiValidTimeMs() { - return (mDeviceMobilityState == WifiManager.DEVICE_MOBILITY_STATE_STATIONARY) - ? mDeviceConfigFacade.getStationaryScanRssiValidTimeMs() : - mDeviceConfigFacade.getNonstationaryScanRssiValidTimeMs(); - } - - /** - * Issue read request to prepare for post-boot detection. - */ - private void requestReadForPostBootDetection() { - mWifiSystemInfoStats.readFromMemory(); - // Potential SW change detection may require to update all networks. - // Thus read all networks. - requestReadAllNetworks(); - } - - /** - * Helper method to populate WifiScanner handle. This is done lazily because - * WifiScanningService is started after WifiService. - */ - private void retrieveWifiScanner() { - if (mScanner != null) return; - mScanner = mWifiInjector.getWifiScanner(); - if (mScanner == null) return; - // Register for all single scan results - mScanner.registerScanListener(new ScanListener()); - } - - /** - * Handle scan results when scan results come back from WiFi scanner. - */ - private void handleScanResults(List<ScanDetail> scanDetails) { - ScanStats scanStats = mWifiSystemInfoStats.getCurrScanStats(); - scanStats.clear(); - scanStats.setLastScanTimeMs(mClock.getWallClockMillis()); - for (ScanDetail scanDetail : scanDetails) { - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult.is24GHz()) { - scanStats.incrementNumBssidLastScan2g(); - } else { - scanStats.incrementNumBssidLastScanAbove2g(); - } - } - if (mFirstScanStats.getLastScanTimeMs() == TS_NONE) { - mFirstScanStats.copy(scanStats); - } - mWifiSystemInfoStats.setChanged(true); - logd(" 2G scanResult count: " + scanStats.getNumBssidLastScan2g() - + ", Above2g scanResult count: " + scanStats.getNumBssidLastScanAbove2g()); - } - - private void setFirstHealthDetectionAlarm() { - long currTimeMs = mClock.getWallClockMillis(); - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(currTimeMs); - calendar.set(Calendar.HOUR_OF_DAY, DAILY_DETECTION_HOUR); - calendar.set(Calendar.MINUTE, DAILY_DETECTION_MIN); - long targetTimeMs = calendar.getTimeInMillis(); - long waitTimeMs = targetTimeMs - currTimeMs; - if (waitTimeMs < MIN_WAIT_TIME_BEFORE_FIRST_DETECTION_MS) { - waitTimeMs += DAILY_DETECTION_INTERVAL_MS; - } - scheduleDailyDetectionAlarm(waitTimeMs); - } - - private void scheduleDailyDetectionAlarm(long waitTimeMs) { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, - mClock.getElapsedSinceBootMillis() + waitTimeMs, - DAILY_DETECTION_TIMER_TAG, - mDailyDetectionListener, mHandler); - } - - private void setPostBootDetectionAlarm() { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + POST_BOOT_DETECTION_WAIT_TIME_MS, - POST_BOOT_DETECTION_TIMER_TAG, - mPostBootDetectionListener, mHandler); - } - - /** - * Dump the internal state of WifiHealthMonitor. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WifiHealthMonitor"); - pw.println("WifiHealthMonitor - Log Begin ----"); - pw.println("System Info Stats"); - pw.println(mWifiSystemInfoStats); - pw.println("configured network connection stats"); - List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : configuredNetworks) { - if (isInvalidConfiguredNetwork(network)) continue; - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(network.SSID); - int cntName = WifiScoreCard.CNT_CONNECTION_ATTEMPT; - if (perNetwork.getStatsCurrBuild().getCount(cntName) > 0 - || perNetwork.getRecentStats().getCount(cntName) > 0) { - pw.println(mWifiScoreCard.lookupNetwork(network.SSID)); - } - } - pw.println("networks with failure increase: "); - pw.println(mFailureStatsIncrease); - pw.println("networks with failure drop: "); - pw.println(mFailureStatsDecrease); - pw.println("networks with high failure without previous stats: "); - pw.println(mFailureStatsHigh); - pw.println("WifiHealthMonitor - Log End ----"); - } - - /** - * Get current wifi mainline module long version code - * @Return a non-zero value if version code is available, 0 otherwise. - */ - public long getWifiStackVersion() { - PackageManager packageManager = mContext.getPackageManager(); - long wifiStackVersion = 0; - try { - ModuleInfo wifiModule = packageManager.getModuleInfo( - WIFI_APEX_NAME, PackageManager.MODULE_APEX_NAME); - String wifiPackageName = wifiModule.getPackageName(); - if (wifiPackageName != null) { - wifiStackVersion = packageManager.getPackageInfo( - wifiPackageName, PackageManager.MATCH_APEX).getLongVersionCode(); - } - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, " Hit PackageManager exception", e); - } - return wifiStackVersion; - } - - private synchronized void dailyDetectionHandler() { - logd("Run daily detection"); - // Clear daily detection result - mFailureStatsDecrease.clear(); - mFailureStatsIncrease.clear(); - mFailureStatsHigh.clear(); - mNumNetworkSufficientRecentStatsOnly = 0; - mNumNetworkSufficientRecentPrevStats = 0; - mHasNewDataForWifiMetrics = true; - int connectionDurationSec = 0; - // Set the alarm for the next day - scheduleDailyDetectionAlarm(DAILY_DETECTION_INTERVAL_MS); - List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : configuredNetworks) { - if (isInvalidConfiguredNetwork(network)) { - continue; - } - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(network.SSID); - - int detectionFlag = perNetwork.dailyDetection(mFailureStatsDecrease, - mFailureStatsIncrease, mFailureStatsHigh); - if (detectionFlag == WifiScoreCard.SUFFICIENT_RECENT_STATS_ONLY) { - mNumNetworkSufficientRecentStatsOnly++; - } - if (detectionFlag == WifiScoreCard.SUFFICIENT_RECENT_PREV_STATS) { - mNumNetworkSufficientRecentPrevStats++; - } - - connectionDurationSec += perNetwork.getRecentStats().getCount( - WifiScoreCard.CNT_CONNECTION_DURATION_SEC); - - logd("before daily update: " + perNetwork); - // Update historical stats with dailyStats and clear dailyStats - perNetwork.updateAfterDailyDetection(); - logd("after daily update: " + perNetwork); - } - logd("total connection duration: " + connectionDurationSec); - logd("#networks w/ sufficient recent stats: " + mNumNetworkSufficientRecentStatsOnly); - logd("#networks w/ sufficient recent and prev stats: " - + mNumNetworkSufficientRecentPrevStats); - // Write metrics to statsd - writeToWifiStatsLog(); - doWrites(); - mWifiScoreCard.doWrites(); - } - - private void writeToWifiStatsLog() { - writeToWifiStatsLogPerStats(mFailureStatsIncrease, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__ABNORMALITY_TYPE__SIGNIFICANT_INCREASE); - writeToWifiStatsLogPerStats(mFailureStatsDecrease, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__ABNORMALITY_TYPE__SIGNIFICANT_DECREASE); - writeToWifiStatsLogPerStats(mFailureStatsHigh, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__ABNORMALITY_TYPE__SIMPLY_HIGH); - } - - private void writeToWifiStatsLogPerStats(FailureStats failureStats, int abnormalityType) { - int cntAssocRejection = failureStats.getCount(REASON_ASSOC_REJECTION); - if (cntAssocRejection > 0) { - WifiStatsLog.write(WifiStatsLog.WIFI_FAILURE_STAT_REPORTED, abnormalityType, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__FAILURE_TYPE__FAILURE_ASSOCIATION_REJECTION, - cntAssocRejection); - } - int cntAssocTimeout = failureStats.getCount(REASON_ASSOC_TIMEOUT); - if (cntAssocTimeout > 0) { - WifiStatsLog.write(WifiStatsLog.WIFI_FAILURE_STAT_REPORTED, abnormalityType, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__FAILURE_TYPE__FAILURE_ASSOCIATION_TIMEOUT, - cntAssocTimeout); - } - int cntAuthFailure = failureStats.getCount(REASON_AUTH_FAILURE); - if (cntAuthFailure > 0) { - WifiStatsLog.write(WifiStatsLog.WIFI_FAILURE_STAT_REPORTED, abnormalityType, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__FAILURE_TYPE__FAILURE_AUTHENTICATION, - cntAuthFailure); - } - int cntConnectionFailure = failureStats.getCount(REASON_CONNECTION_FAILURE); - if (cntConnectionFailure > 0) { - WifiStatsLog.write(WifiStatsLog.WIFI_FAILURE_STAT_REPORTED, abnormalityType, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__FAILURE_TYPE__FAILURE_CONNECTION, - cntConnectionFailure); - } - int cntDisconnectionNonlocal = failureStats.getCount(REASON_DISCONNECTION_NONLOCAL); - if (cntDisconnectionNonlocal > 0) { - WifiStatsLog.write(WifiStatsLog.WIFI_FAILURE_STAT_REPORTED, abnormalityType, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__FAILURE_TYPE__FAILURE_NON_LOCAL_DISCONNECTION, - cntDisconnectionNonlocal); - } - int cntShortConnectionNonlocal = failureStats.getCount(REASON_SHORT_CONNECTION_NONLOCAL); - if (cntShortConnectionNonlocal > 0) { - WifiStatsLog.write(WifiStatsLog.WIFI_FAILURE_STAT_REPORTED, abnormalityType, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__FAILURE_TYPE__FAILURE_SHORT_CONNECTION_DUE_TO_NON_LOCAL_DISCONNECTION, - cntShortConnectionNonlocal); - } - } - - /** - * Build HealthMonitor proto for WifiMetrics - * @return counts of networks with significant connection failure stats if there is a new - * detection, or a empty proto with default values if there is no new detection - */ - public synchronized HealthMonitorMetrics buildProto() { - if (!mHasNewDataForWifiMetrics) return null; - HealthMonitorMetrics metrics = new HealthMonitorMetrics(); - metrics.failureStatsIncrease = failureStatsToProto(mFailureStatsIncrease); - metrics.failureStatsDecrease = failureStatsToProto(mFailureStatsDecrease); - metrics.failureStatsHigh = failureStatsToProto(mFailureStatsHigh); - - metrics.numNetworkSufficientRecentStatsOnly = mNumNetworkSufficientRecentStatsOnly; - metrics.numNetworkSufficientRecentPrevStats = mNumNetworkSufficientRecentPrevStats; - mHasNewDataForWifiMetrics = false; - return metrics; - } - - private HealthMonitorFailureStats failureStatsToProto(FailureStats failureStats) { - HealthMonitorFailureStats stats = new HealthMonitorFailureStats(); - stats.cntAssocRejection = failureStats.getCount(REASON_ASSOC_REJECTION); - stats.cntAssocTimeout = failureStats.getCount(REASON_ASSOC_TIMEOUT); - stats.cntAuthFailure = failureStats.getCount(REASON_AUTH_FAILURE); - stats.cntConnectionFailure = failureStats.getCount(REASON_CONNECTION_FAILURE); - stats.cntDisconnectionNonlocal = - failureStats.getCount(REASON_DISCONNECTION_NONLOCAL); - stats.cntShortConnectionNonlocal = - failureStats.getCount(REASON_SHORT_CONNECTION_NONLOCAL); - return stats; - } - - private boolean isInvalidConfiguredNetwork(WifiConfiguration config) { - return (config == null || WifiManager.UNKNOWN_SSID.equals(config.SSID) - || config.SSID == null); - } - - private void postBootDetectionHandler() { - logd("Run post-boot detection"); - postBootSwBuildCheck(); - mWifiSystemInfoStats.postBootAbnormalScanDetection(mFirstScanStats); - logd(" postBootAbnormalScanDetection: " + mWifiSystemInfoStats.getScanFailure()); - // TODO: Check if scan is not empty but all high RSSI connection attempts failed - // while connection attempt with the same network succeeded before boot. - doWrites(); - } - - private void postBootSwBuildCheck() { - WifiSoftwareBuildInfo currSoftwareBuildInfo = extractCurrentSoftwareBuildInfo(); - if (currSoftwareBuildInfo == null) return; - logd(currSoftwareBuildInfo.toString()); - - mWifiSystemInfoStats.finishPendingRead(); - if (mWifiSystemInfoStats.getCurrSoftwareBuildInfo() == null) { - logd("Miss current software build info from memory"); - mWifiSystemInfoStats.setCurrSoftwareBuildInfo(currSoftwareBuildInfo); - return; - } - if (mWifiSystemInfoStats.detectSwBuildChange(currSoftwareBuildInfo)) { - logd("Detect SW build change"); - updateAllNetworkAfterSwBuildChange(); - mWifiSystemInfoStats.updateBuildInfoAfterSwBuildChange(currSoftwareBuildInfo); - } else { - logd("Detect no SW build change"); - } - } - - /** - * Issue NetworkStats read request for all configured networks. - */ - private void requestReadAllNetworks() { - List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : configuredNetworks) { - if (isInvalidConfiguredNetwork(network)) { - continue; - } - logd(network.SSID); - WifiScoreCard.PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(network.SSID); - if (perNetwork == null) { - // This network is not in cache. Move it to cache and read it out from MemoryStore. - mWifiScoreCard.lookupNetwork(network.SSID); - } else { - // This network is already in cache before memoryStore is stalled. - mWifiScoreCard.requestReadNetwork(perNetwork); - } - } - } - - /** - * Update NetworkStats of all configured networks after a SW build change is detected - */ - private void updateAllNetworkAfterSwBuildChange() { - List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : configuredNetworks) { - if (isInvalidConfiguredNetwork(network)) { - continue; - } - logd(network.SSID); - WifiScoreCard.PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(network.SSID); - - logd("before SW build update: " + perNetwork); - perNetwork.updateAfterSwBuildChange(); - logd("after SW build update: " + perNetwork); - } - } - - /** - * Extract current software build information from the running software. - */ - private WifiSoftwareBuildInfo extractCurrentSoftwareBuildInfo() { - if (!mWifiEnabled) { - return null; - } - long wifiStackVersion = getWifiStackVersion(); - String osBuildVersion = replaceNullByEmptyString(Build.DISPLAY); - if (mWifiNative == null) { - return null; - } - String driverVersion = replaceNullByEmptyString(mWifiNative.getDriverVersion()); - String firmwareVersion = replaceNullByEmptyString(mWifiNative.getFirmwareVersion()); - return (new WifiSoftwareBuildInfo(osBuildVersion, - wifiStackVersion, driverVersion, firmwareVersion)); - } - - private String replaceNullByEmptyString(String str) { - return str == null ? "" : str; - } - - /** - * Clears the internal state. - * This is called in response to a factoryReset call from Settings. - */ - public void clear() { - mWifiSystemInfoStats.clearAll(); - } - - public static final int REASON_NO_FAILURE = -1; - public static final int REASON_ASSOC_REJECTION = 0; - public static final int REASON_ASSOC_TIMEOUT = 1; - public static final int REASON_AUTH_FAILURE = 2; - public static final int REASON_CONNECTION_FAILURE = 3; - public static final int REASON_DISCONNECTION_NONLOCAL = 4; - public static final int REASON_SHORT_CONNECTION_NONLOCAL = 5; - public static final int NUMBER_FAILURE_REASON_CODE = 6; - public static final String[] FAILURE_REASON_NAME = { - "association rejection failure", - "association timeout failure", - "authentication failure", - "connection failure", - "disconnection", - "short connection" - }; - @IntDef(prefix = { "REASON_" }, value = { - REASON_NO_FAILURE, - REASON_ASSOC_REJECTION, - REASON_ASSOC_TIMEOUT, - REASON_AUTH_FAILURE, - REASON_CONNECTION_FAILURE, - REASON_DISCONNECTION_NONLOCAL, - REASON_SHORT_CONNECTION_NONLOCAL - }) - @Retention(RetentionPolicy.SOURCE) - public @interface FailureReasonCode {} - - /** - * A class maintaining the number of networks with high failure rate or - * with a significant change of failure rate - */ - public static class FailureStats { - private final int[] mCount = new int[NUMBER_FAILURE_REASON_CODE]; - void clear() { - for (int i = 0; i < NUMBER_FAILURE_REASON_CODE; i++) { - mCount[i] = 0; - } - } - - int getCount(@FailureReasonCode int reasonCode) { - return mCount[reasonCode]; - } - - void setCount(@FailureReasonCode int reasonCode, int cnt) { - mCount[reasonCode] = cnt; - } - - void incrementCount(@FailureReasonCode int reasonCode) { - mCount[reasonCode]++; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < NUMBER_FAILURE_REASON_CODE; i++) { - if (mCount[i] == 0) continue; - sb.append(FAILURE_REASON_NAME[i]).append(": ").append(mCount[i]).append(" "); - } - return sb.toString(); - } - } - /** - * A class maintaining current OS, Wifi APK, Wifi driver and firmware build version information. - */ - final class WifiSoftwareBuildInfo { - private String mOsBuildVersion; - private long mWifiStackVersion; - private String mWifiDriverVersion; - private String mWifiFirmwareVersion; - WifiSoftwareBuildInfo(@NonNull String osBuildVersion, long wifiStackVersion, - @NonNull String wifiDriverVersion, @NonNull String wifiFirmwareVersion) { - mOsBuildVersion = osBuildVersion; - mWifiStackVersion = wifiStackVersion; - mWifiDriverVersion = wifiDriverVersion; - mWifiFirmwareVersion = wifiFirmwareVersion; - } - WifiSoftwareBuildInfo(@NonNull WifiSoftwareBuildInfo wifiSoftwareBuildInfo) { - mOsBuildVersion = wifiSoftwareBuildInfo.getOsBuildVersion(); - mWifiStackVersion = wifiSoftwareBuildInfo.getWifiStackVersion(); - mWifiDriverVersion = wifiSoftwareBuildInfo.getWifiDriverVersion(); - mWifiFirmwareVersion = wifiSoftwareBuildInfo.getWifiFirmwareVersion(); - } - String getOsBuildVersion() { - return mOsBuildVersion; - } - long getWifiStackVersion() { - return mWifiStackVersion; - } - String getWifiDriverVersion() { - return mWifiDriverVersion; - } - String getWifiFirmwareVersion() { - return mWifiFirmwareVersion; - } - @Override - public boolean equals(Object otherObj) { - if (this == otherObj) { - return true; - } - if (!(otherObj instanceof WifiSoftwareBuildInfo)) { - return false; - } - if (otherObj == null) { - return false; - } - WifiSoftwareBuildInfo other = (WifiSoftwareBuildInfo) otherObj; - return mOsBuildVersion.equals(other.getOsBuildVersion()) - && mWifiStackVersion == other.getWifiStackVersion() - && mWifiDriverVersion.equals(other.getWifiDriverVersion()) - && mWifiFirmwareVersion.equals(other.getWifiFirmwareVersion()); - } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("OS build version: "); - sb.append(mOsBuildVersion); - sb.append(" Wifi stack version: "); - sb.append(mWifiStackVersion); - sb.append(" Wifi driver version: "); - sb.append(mWifiDriverVersion); - sb.append(" Wifi firmware version: "); - sb.append(mWifiFirmwareVersion); - return sb.toString(); - } - } - - /** - * A class maintaining various WiFi system information and statistics. - */ - final class WifiSystemInfoStats extends MemoryStoreAccessBase { - private WifiSoftwareBuildInfo mCurrSoftwareBuildInfo; - private WifiSoftwareBuildInfo mPrevSoftwareBuildInfo; - private ScanStats mCurrScanStats = new ScanStats(); - private ScanStats mPrevScanStats = new ScanStats(); - private int mScanFailure; - private @DeviceMobilityState int mMobilityState; - private boolean mChanged = false; - WifiSystemInfoStats(String l2KeySeed) { - super(WifiScoreCard.computeHashLong( - "", MacAddress.fromString(DEFAULT_MAC_ADDRESS), l2KeySeed)); - } - - ScanStats getCurrScanStats() { - return mCurrScanStats; - } - - void setChanged(boolean changed) { - mChanged = changed; - } - - void setCurrSoftwareBuildInfo(WifiSoftwareBuildInfo currSoftwareBuildInfo) { - mCurrSoftwareBuildInfo = currSoftwareBuildInfo; - mChanged = true; - } - - void setMobilityState(@DeviceMobilityState int mobilityState) { - mMobilityState = mobilityState; - } - - WifiSoftwareBuildInfo getCurrSoftwareBuildInfo() { - return mCurrSoftwareBuildInfo; - } - - WifiSoftwareBuildInfo getPrevSoftwareBuildInfo() { - return mPrevSoftwareBuildInfo; - } - - void clearAll() { - mCurrSoftwareBuildInfo = null; - mPrevSoftwareBuildInfo = null; - mCurrScanStats.clear(); - mPrevScanStats.clear(); - mChanged = true; - } - - /** - * Detect if there is a SW build change by comparing current SW build version vs. SW build - * version previously saved in MemoryStore. - * @param currSoftwareBuildInfo is current SW build info derived from running SW - * @return true if a SW build change is detected, false if no change is detected. - */ - boolean detectSwBuildChange(@NonNull WifiSoftwareBuildInfo currSoftwareBuildInfo) { - if (mCurrSoftwareBuildInfo == null) { - return false; - } - - logd(" from Memory: " + mCurrSoftwareBuildInfo); - logd(" from SW: " + currSoftwareBuildInfo); - return (!mCurrSoftwareBuildInfo.equals(currSoftwareBuildInfo)); - } - - void updateBuildInfoAfterSwBuildChange(@NonNull WifiSoftwareBuildInfo currBuildInfo) { - mPrevSoftwareBuildInfo = new WifiSoftwareBuildInfo(mCurrSoftwareBuildInfo); - mCurrSoftwareBuildInfo = new WifiSoftwareBuildInfo(currBuildInfo); - mChanged = true; - } - - void readFromMemory() { - if (mMemoryStore != null) { - mMemoryStore.read(getL2Key(), SYSTEM_INFO_DATA_NAME, - (value) -> readBackListener(value)); - } - } - - // Read may not be completed in theory when finishPendingRead() is called. - // Currently it relies on the fact that memory read is issued right after boot complete - // while finishPendingRead() is called only POST_BOOT_DETECTION_WAIT_TIME_MS after that. - private void finishPendingRead() { - final byte[] serialized = finishPendingReadBytes(); - if (serialized == null) { - logd("Fail to read systemInfoStats from memory"); - return; - } - SystemInfoStats systemInfoStats; - try { - systemInfoStats = SystemInfoStats.parseFrom(serialized); - } catch (InvalidProtocolBufferException e) { - Log.e(TAG, "Failed to deserialize", e); - return; - } - readFromMemory(systemInfoStats); - } - - private void readFromMemory(@NonNull SystemInfoStats systemInfoStats) { - if (systemInfoStats.hasCurrSoftwareBuildInfo()) { - mCurrSoftwareBuildInfo = fromSoftwareBuildInfo( - systemInfoStats.getCurrSoftwareBuildInfo()); - } - if (systemInfoStats.hasPrevSoftwareBuildInfo()) { - mPrevSoftwareBuildInfo = fromSoftwareBuildInfo( - systemInfoStats.getPrevSoftwareBuildInfo()); - } - if (systemInfoStats.hasNumBssidLastScan2G()) { - mPrevScanStats.setNumBssidLastScan2g(systemInfoStats.getNumBssidLastScan2G()); - } - if (systemInfoStats.hasNumBssidLastScanAbove2G()) { - mPrevScanStats.setNumBssidLastScanAbove2g(systemInfoStats - .getNumBssidLastScanAbove2G()); - } - if (systemInfoStats.hasLastScanTimeMs()) { - mPrevScanStats.setLastScanTimeMs(systemInfoStats.getLastScanTimeMs()); - } - } - - void writeToMemory() { - if (mMemoryStore == null || !mChanged) return; - byte[] serialized = toSystemInfoStats().toByteArray(); - mMemoryStore.write(getL2Key(), SYSTEM_INFO_DATA_NAME, serialized); - mChanged = false; - } - - SystemInfoStats toSystemInfoStats() { - SystemInfoStats.Builder builder = SystemInfoStats.newBuilder(); - if (mCurrSoftwareBuildInfo != null) { - builder.setCurrSoftwareBuildInfo(toSoftwareBuildInfo(mCurrSoftwareBuildInfo)); - } - if (mPrevSoftwareBuildInfo != null) { - builder.setPrevSoftwareBuildInfo(toSoftwareBuildInfo(mPrevSoftwareBuildInfo)); - } - builder.setLastScanTimeMs(mCurrScanStats.getLastScanTimeMs()); - builder.setNumBssidLastScan2G(mCurrScanStats.getNumBssidLastScan2g()); - builder.setNumBssidLastScanAbove2G(mCurrScanStats.getNumBssidLastScanAbove2g()); - return builder.build(); - } - - private SoftwareBuildInfo toSoftwareBuildInfo( - @NonNull WifiSoftwareBuildInfo softwareBuildInfo) { - SoftwareBuildInfo.Builder builder = SoftwareBuildInfo.newBuilder(); - builder.setOsBuildVersion(softwareBuildInfo.getOsBuildVersion()); - builder.setWifiStackVersion(softwareBuildInfo.getWifiStackVersion()); - builder.setWifiDriverVersion(softwareBuildInfo.getWifiDriverVersion()); - builder.setWifiFirmwareVersion(softwareBuildInfo.getWifiFirmwareVersion()); - return builder.build(); - } - - WifiSoftwareBuildInfo fromSoftwareBuildInfo( - @NonNull SoftwareBuildInfo softwareBuildInfo) { - String osBuildVersion = softwareBuildInfo.hasOsBuildVersion() - ? softwareBuildInfo.getOsBuildVersion() : "NA"; - long stackVersion = softwareBuildInfo.hasWifiStackVersion() - ? softwareBuildInfo.getWifiStackVersion() : 0; - String driverVersion = softwareBuildInfo.hasWifiDriverVersion() - ? softwareBuildInfo.getWifiDriverVersion() : "NA"; - String firmwareVersion = softwareBuildInfo.hasWifiFirmwareVersion() - ? softwareBuildInfo.getWifiFirmwareVersion() : "NA"; - return new WifiSoftwareBuildInfo(osBuildVersion, stackVersion, - driverVersion, firmwareVersion); - } - /** - * Detect pre-boot or post-boot detection failure. - * @return 0 if no failure is found or a positive integer if failure is found where - * b0 for pre-boot 2G scan failure - * b1 for pre-boot Above2g scan failure - * b2 for post-boot 2G scan failure - * b3 for post-boot Above2g scan failure - */ - void postBootAbnormalScanDetection(ScanStats firstScanStats) { - long preBootScanTimeMs = mPrevScanStats.getLastScanTimeMs(); - long postBootScanTimeMs = firstScanStats.getLastScanTimeMs(); - logd(" preBootScanTimeMs: " + preBootScanTimeMs); - logd(" postBootScanTimeMs: " + postBootScanTimeMs); - int preBootNumBssid2g = mPrevScanStats.getNumBssidLastScan2g(); - int preBootNumBssidAbove2g = mPrevScanStats.getNumBssidLastScanAbove2g(); - int postBootNumBssid2g = firstScanStats.getNumBssidLastScan2g(); - int postBootNumBssidAbove2g = firstScanStats.getNumBssidLastScanAbove2g(); - logd(" preBootScan 2G count: " + preBootNumBssid2g - + ", Above2G count: " + preBootNumBssidAbove2g); - logd(" postBootScan 2G count: " + postBootNumBssid2g - + ", Above2G count: " + postBootNumBssidAbove2g); - mScanFailure = 0; - if (postBootScanTimeMs == TS_NONE || preBootScanTimeMs == TS_NONE) return; - if ((postBootScanTimeMs - preBootScanTimeMs) > MAX_INTERVAL_BETWEEN_TWO_SCAN_MS) { - return; - } - if (preBootNumBssid2g == 0 && postBootNumBssid2g >= MIN_NUM_BSSID_SCAN_2G) { - mScanFailure += 1; - } - if (preBootNumBssidAbove2g == 0 && postBootNumBssidAbove2g - >= MIN_NUM_BSSID_SCAN_ABOVE_2G) { - mScanFailure += 2; - } - if (postBootNumBssid2g == 0 && preBootNumBssid2g >= MIN_NUM_BSSID_SCAN_2G) { - mScanFailure += 4; - } - if (postBootNumBssidAbove2g == 0 && preBootNumBssidAbove2g - >= MIN_NUM_BSSID_SCAN_ABOVE_2G) { - mScanFailure += 8; - } - } - - int getScanFailure() { - return mScanFailure; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - if (mCurrSoftwareBuildInfo != null) { - sb.append("current SW build: "); - sb.append(mCurrSoftwareBuildInfo); - } - if (mPrevSoftwareBuildInfo != null) { - sb.append("\n"); - sb.append("previous SW build: "); - sb.append(mPrevSoftwareBuildInfo); - } - sb.append("\n"); - sb.append("currScanStats: "); - sb.append(mCurrScanStats); - sb.append("\n"); - sb.append("prevScanStats: "); - sb.append(mPrevScanStats); - return sb.toString(); - } - } - - final class ScanStats { - private long mLastScanTimeMs = TS_NONE; - private int mNumBssidLastScan2g; - private int mNumBssidLastScanAbove2g; - void copy(ScanStats source) { - mLastScanTimeMs = source.mLastScanTimeMs; - mNumBssidLastScan2g = source.mNumBssidLastScan2g; - mNumBssidLastScanAbove2g = source.mNumBssidLastScanAbove2g; - } - void setLastScanTimeMs(long lastScanTimeMs) { - mLastScanTimeMs = lastScanTimeMs; - } - void setNumBssidLastScan2g(int numBssidLastScan2g) { - mNumBssidLastScan2g = numBssidLastScan2g; - } - void setNumBssidLastScanAbove2g(int numBssidLastScanAbove2g) { - mNumBssidLastScanAbove2g = numBssidLastScanAbove2g; - } - long getLastScanTimeMs() { - return mLastScanTimeMs; - } - int getNumBssidLastScan2g() { - return mNumBssidLastScan2g; - } - int getNumBssidLastScanAbove2g() { - return mNumBssidLastScanAbove2g; - } - void incrementNumBssidLastScan2g() { - mNumBssidLastScan2g++; - } - void incrementNumBssidLastScanAbove2g() { - mNumBssidLastScanAbove2g++; - } - void clear() { - mLastScanTimeMs = TS_NONE; - mNumBssidLastScan2g = 0; - mNumBssidLastScanAbove2g = 0; - } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("last scan time: "); - sb.append(mLastScanTimeMs); - sb.append(" APs found at 2G: "); - sb.append(mNumBssidLastScan2g); - sb.append(" APs found above 2g: "); - sb.append(mNumBssidLastScanAbove2g); - return sb.toString(); - } - } - - @VisibleForTesting - WifiSystemInfoStats getWifiSystemInfoStats() { - return mWifiSystemInfoStats; - } - - private void logd(String string) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, string); - } - } - - /** - * Listener for config manager network config related events. - */ - private class OnNetworkUpdateListener implements - WifiConfigManager.OnNetworkUpdateListener { - - @Override - public void onNetworkAdded(WifiConfiguration config) { - if (config == null) return; - mWifiScoreCard.lookupNetwork(config.SSID); - } - - @Override - public void onNetworkEnabled(WifiConfiguration config) { - } - - @Override - public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) { - } - - @Override - public void onNetworkRemoved(WifiConfiguration config) { - if (config == null || (config.fromWifiNetworkSuggestion && !config.isPasspoint())) { - // If a suggestion non-passpoint network is removed from wifiConfigManager do not - // remove the ScoreCard. That will be removed when suggestion is removed. - return; - } - mWifiScoreCard.removeNetwork(config.SSID); - } - - @Override - public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) { - } - - @Override - public void onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig) { - } - } - - /** - * Scan listener for any full band scan. - */ - private class ScanListener implements WifiScanner.ScanListener { - private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); - - public void clearScanDetails() { - mScanDetails.clear(); - } - - @Override - public void onSuccess() { - } - - @Override - public void onFailure(int reason, String description) { - logd("registerScanListener onFailure:" - + " reason: " + reason + " description: " + description); - } - - @Override - public void onPeriodChanged(int periodInMs) { - } - - @Override - public void onResults(WifiScanner.ScanData[] results) { - if (!mWifiEnabled || results == null || results.length == 0) { - clearScanDetails(); - return; - } - - if (WifiScanner.isFullBandScan(results[0].getBandScanned(), true)) { - handleScanResults(mScanDetails); - } - clearScanDetails(); - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - if (!mWifiEnabled) { - return; - } - mScanDetails.add(ScanResultUtil.toScanDetail(fullScanResult)); - } - } -} diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java deleted file mode 100644 index 48f1b3f2e..000000000 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.annotation.NonNull; -import android.app.ActivityManager; -import android.app.AlarmManager; -import android.app.AppOpsManager; -import android.app.NotificationManager; -import android.content.Context; -import android.net.IpMemoryStore; -import android.net.NetworkCapabilities; -import android.net.NetworkKey; -import android.net.NetworkScoreManager; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiScanner; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.BatteryStatsManager; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Process; -import android.os.SystemProperties; -import android.os.UserManager; -import android.provider.Settings.Secure; -import android.security.keystore.AndroidKeyStoreProvider; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.util.LocalLog; -import android.util.Log; - -import com.android.server.wifi.aware.WifiAwareMetrics; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper; -import com.android.server.wifi.hotspot2.PasspointObjectFactory; -import com.android.server.wifi.p2p.SupplicantP2pIfaceHal; -import com.android.server.wifi.p2p.WifiP2pMetrics; -import com.android.server.wifi.p2p.WifiP2pMonitor; -import com.android.server.wifi.p2p.WifiP2pNative; -import com.android.server.wifi.rtt.RttMetrics; -import com.android.server.wifi.util.LruConnectionTracker; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.SettingsMigrationDataHolder; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; - -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchProviderException; -import java.util.Random; - -/** - * WiFi dependency injector. To be used for accessing various WiFi class instances and as a - * handle for mock injection. - * - * Some WiFi class instances currently depend on having a Looper from a HandlerThread that has - * been started. To accommodate this, we have a two-phased approach to initialize and retrieve - * an instance of the WifiInjector. - */ -public class WifiInjector { - private static final String TAG = "WifiInjector"; - private static final String BOOT_DEFAULT_WIFI_COUNTRY_CODE = "ro.boot.wificountrycode"; - /** - * Maximum number in-memory store network connection order; - */ - private static final int MAX_RECENTLY_CONNECTED_NETWORK = 100; - - static WifiInjector sWifiInjector = null; - - private final WifiContext mContext; - private final BatteryStatsManager mBatteryStats; - private final FrameworkFacade mFrameworkFacade; - private final DeviceConfigFacade mDeviceConfigFacade; - private final UserManager mUserManager; - private final HandlerThread mAsyncChannelHandlerThread; - private final HandlerThread mWifiHandlerThread; - private final HandlerThread mWifiP2pServiceHandlerThread; - private final HandlerThread mPasspointProvisionerHandlerThread; - private final WifiTrafficPoller mWifiTrafficPoller; - private final WifiCountryCode mCountryCode; - private final BackupManagerProxy mBackupManagerProxy = new BackupManagerProxy(); - private final WifiApConfigStore mWifiApConfigStore; - private final WifiNative mWifiNative; - private final WifiMonitor mWifiMonitor; - private final WifiP2pNative mWifiP2pNative; - private final WifiP2pMonitor mWifiP2pMonitor; - private final SupplicantStaIfaceHal mSupplicantStaIfaceHal; - private final SupplicantP2pIfaceHal mSupplicantP2pIfaceHal; - private final HostapdHal mHostapdHal; - private final WifiVendorHal mWifiVendorHal; - private final ScoringParams mScoringParams; - private final ClientModeImpl mClientModeImpl; - private final ActiveModeWarden mActiveModeWarden; - private final WifiSettingsStore mSettingsStore; - private OpenNetworkNotifier mOpenNetworkNotifier; - private final WifiLockManager mLockManager; - private final WifiNl80211Manager mWifiCondManager; - private final Clock mClock = new Clock(); - private final WifiMetrics mWifiMetrics; - private final WifiP2pMetrics mWifiP2pMetrics; - private WifiLastResortWatchdog mWifiLastResortWatchdog; - private final PropertyService mPropertyService = new SystemPropertyService(); - private final BuildProperties mBuildProperties = new SystemBuildProperties(); - private final WifiBackupRestore mWifiBackupRestore; - private final SoftApBackupRestore mSoftApBackupRestore; - private final WifiMulticastLockManager mWifiMulticastLockManager; - private final WifiConfigStore mWifiConfigStore; - private final WifiKeyStore mWifiKeyStore; - private final WifiConfigManager mWifiConfigManager; - private final WifiConnectivityHelper mWifiConnectivityHelper; - private final LocalLog mConnectivityLocalLog; - private final WifiNetworkSelector mWifiNetworkSelector; - private final SavedNetworkNominator mSavedNetworkNominator; - private final NetworkSuggestionNominator mNetworkSuggestionNominator; - private final ScoredNetworkNominator mScoredNetworkNominator; - private final WifiNetworkScoreCache mWifiNetworkScoreCache; - private final NetworkScoreManager mNetworkScoreManager; - private WifiScanner mWifiScanner; - private final WifiPermissionsWrapper mWifiPermissionsWrapper; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final PasspointManager mPasspointManager; - private HandlerThread mWifiAwareHandlerThread; - private HandlerThread mRttHandlerThread; - private HalDeviceManager mHalDeviceManager; - private final WifiStateTracker mWifiStateTracker; - private final SelfRecovery mSelfRecovery; - private final WakeupController mWakeupController; - private final ScanRequestProxy mScanRequestProxy; - private final SarManager mSarManager; - private final BaseWifiDiagnostics mWifiDiagnostics; - private final WifiDataStall mWifiDataStall; - private final WifiScoreCard mWifiScoreCard; - private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private final DppMetrics mDppMetrics; - private final DppManager mDppManager; - private final LinkProbeManager mLinkProbeManager; - private IpMemoryStore mIpMemoryStore; - private final WifiThreadRunner mWifiThreadRunner; - private BssidBlocklistMonitor mBssidBlocklistMonitor; - private final MacAddressUtil mMacAddressUtil; - private final MboOceController mMboOceController; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - private WifiChannelUtilization mWifiChannelUtilizationScan; - private WifiChannelUtilization mWifiChannelUtilizationConnected; - private final KeyStore mKeyStore; - private final ConnectionFailureNotificationBuilder mConnectionFailureNotificationBuilder; - private final ThroughputPredictor mThroughputPredictor; - private NetdWrapper mNetdWrapper; - private final WifiHealthMonitor mWifiHealthMonitor; - private final WifiSettingsConfigStore mSettingsConfigStore; - private final WifiScanAlwaysAvailableSettingsCompatibility - mWifiScanAlwaysAvailableSettingsCompatibility; - private final SettingsMigrationDataHolder mSettingsMigrationDataHolder; - private final LruConnectionTracker mLruConnectionTracker; - - public WifiInjector(WifiContext context) { - if (context == null) { - throw new IllegalStateException( - "WifiInjector should not be initialized with a null Context."); - } - - if (sWifiInjector != null) { - throw new IllegalStateException( - "WifiInjector was already created, use getInstance instead."); - } - - sWifiInjector = this; - - // Now create and start handler threads - mAsyncChannelHandlerThread = new HandlerThread("AsyncChannelHandlerThread"); - mAsyncChannelHandlerThread.start(); - mWifiHandlerThread = new HandlerThread("WifiHandlerThread"); - mWifiHandlerThread.start(); - Looper wifiLooper = mWifiHandlerThread.getLooper(); - Handler wifiHandler = new Handler(wifiLooper); - - mFrameworkFacade = new FrameworkFacade(); - mMacAddressUtil = new MacAddressUtil(); - mContext = context; - mScoringParams = new ScoringParams(mContext); - mSettingsMigrationDataHolder = new SettingsMigrationDataHolder(mContext); - mConnectionFailureNotificationBuilder = new ConnectionFailureNotificationBuilder( - mContext, getWifiStackPackageName(), mFrameworkFacade); - mBatteryStats = context.getSystemService(BatteryStatsManager.class); - mWifiPermissionsWrapper = new WifiPermissionsWrapper(mContext); - mNetworkScoreManager = mContext.getSystemService(NetworkScoreManager.class); - mWifiNetworkScoreCache = new WifiNetworkScoreCache(mContext); - mNetworkScoreManager.registerNetworkScoreCallback(NetworkKey.TYPE_WIFI, - NetworkScoreManager.SCORE_FILTER_NONE, - new HandlerExecutor(wifiHandler), mWifiNetworkScoreCache); - mUserManager = mContext.getSystemService(UserManager.class); - mWifiPermissionsUtil = new WifiPermissionsUtil(mWifiPermissionsWrapper, mContext, - mUserManager, this); - mWifiBackupRestore = new WifiBackupRestore(mWifiPermissionsUtil); - mSoftApBackupRestore = new SoftApBackupRestore(mContext, mSettingsMigrationDataHolder); - mWifiStateTracker = new WifiStateTracker(mBatteryStats); - mWifiThreadRunner = new WifiThreadRunner(wifiHandler); - mWifiP2pServiceHandlerThread = new HandlerThread("WifiP2pService"); - mWifiP2pServiceHandlerThread.start(); - mPasspointProvisionerHandlerThread = - new HandlerThread("PasspointProvisionerHandlerThread"); - mPasspointProvisionerHandlerThread.start(); - WifiAwareMetrics awareMetrics = new WifiAwareMetrics(mClock); - RttMetrics rttMetrics = new RttMetrics(mClock); - mWifiP2pMetrics = new WifiP2pMetrics(mClock); - mDppMetrics = new DppMetrics(); - mWifiMetrics = new WifiMetrics(mContext, mFrameworkFacade, mClock, wifiLooper, - awareMetrics, rttMetrics, new WifiPowerMetrics(mBatteryStats), mWifiP2pMetrics, - mDppMetrics); - mDeviceConfigFacade = new DeviceConfigFacade(mContext, wifiHandler, mWifiMetrics); - // Modules interacting with Native. - mWifiMonitor = new WifiMonitor(this); - mHalDeviceManager = new HalDeviceManager(mClock, wifiHandler); - mWifiVendorHal = new WifiVendorHal(mHalDeviceManager, wifiHandler); - mSupplicantStaIfaceHal = new SupplicantStaIfaceHal( - mContext, mWifiMonitor, mFrameworkFacade, wifiHandler, mClock, mWifiMetrics); - mHostapdHal = new HostapdHal(mContext, wifiHandler); - mWifiCondManager = (WifiNl80211Manager) mContext.getSystemService( - Context.WIFI_NL80211_SERVICE); - mWifiNative = new WifiNative( - mWifiVendorHal, mSupplicantStaIfaceHal, mHostapdHal, mWifiCondManager, - mWifiMonitor, mPropertyService, mWifiMetrics, - wifiHandler, new Random(), this); - mWifiP2pMonitor = new WifiP2pMonitor(this); - mSupplicantP2pIfaceHal = new SupplicantP2pIfaceHal(mWifiP2pMonitor); - mWifiP2pNative = new WifiP2pNative(this, - mWifiVendorHal, mSupplicantP2pIfaceHal, mHalDeviceManager, - mPropertyService); - - // Now get instances of all the objects that depend on the HandlerThreads - mWifiTrafficPoller = new WifiTrafficPoller(wifiHandler); - mCountryCode = new WifiCountryCode(mContext, wifiHandler, mWifiNative, - SystemProperties.get(BOOT_DEFAULT_WIFI_COUNTRY_CODE)); - // WifiConfigManager/Store objects and their dependencies. - KeyStore keyStore = null; - try { - keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(Process.WIFI_UID); - } catch (KeyStoreException | NoSuchProviderException e) { - Log.wtf(TAG, "Failed to load keystore", e); - } - mKeyStore = keyStore; - mWifiKeyStore = new WifiKeyStore(mKeyStore); - // New config store - mWifiConfigStore = new WifiConfigStore(mContext, wifiHandler, mClock, mWifiMetrics, - WifiConfigStore.createSharedFiles(mFrameworkFacade.isNiapModeOn(mContext))); - SubscriptionManager subscriptionManager = - mContext.getSystemService(SubscriptionManager.class); - mWifiCarrierInfoManager = new WifiCarrierInfoManager(makeTelephonyManager(), - subscriptionManager, this, mFrameworkFacade, mContext, - mWifiConfigStore, wifiHandler, mWifiMetrics); - String l2KeySeed = Secure.getString(mContext.getContentResolver(), Secure.ANDROID_ID); - mWifiScoreCard = new WifiScoreCard(mClock, l2KeySeed, mDeviceConfigFacade); - mWifiMetrics.setWifiScoreCard(mWifiScoreCard); - mLruConnectionTracker = new LruConnectionTracker(MAX_RECENTLY_CONNECTED_NETWORK, - mContext); - // Config Manager - mWifiConfigManager = new WifiConfigManager(mContext, mClock, - mUserManager, mWifiCarrierInfoManager, - mWifiKeyStore, mWifiConfigStore, mWifiPermissionsUtil, - mWifiPermissionsWrapper, this, - new NetworkListSharedStoreData(mContext), - new NetworkListUserStoreData(mContext), - new RandomizedMacStoreData(), mFrameworkFacade, wifiHandler, mDeviceConfigFacade, - mWifiScoreCard, mLruConnectionTracker); - mSettingsConfigStore = new WifiSettingsConfigStore(context, wifiHandler, - mSettingsMigrationDataHolder, mWifiConfigManager, mWifiConfigStore); - mSettingsStore = new WifiSettingsStore(mContext, mSettingsConfigStore); - mWifiMetrics.setWifiConfigManager(mWifiConfigManager); - - mWifiConnectivityHelper = new WifiConnectivityHelper(mWifiNative); - mConnectivityLocalLog = new LocalLog( - mContext.getSystemService(ActivityManager.class).isLowRamDevice() ? 256 : 512); - mWifiMetrics.setScoringParams(mScoringParams); - mThroughputPredictor = new ThroughputPredictor(mContext); - mWifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiScoreCard, mScoringParams, - mWifiConfigManager, mClock, mConnectivityLocalLog, mWifiMetrics, mWifiNative, - mThroughputPredictor); - CompatibilityScorer compatibilityScorer = new CompatibilityScorer(mScoringParams); - mWifiNetworkSelector.registerCandidateScorer(compatibilityScorer); - ScoreCardBasedScorer scoreCardBasedScorer = new ScoreCardBasedScorer(mScoringParams); - mWifiNetworkSelector.registerCandidateScorer(scoreCardBasedScorer); - BubbleFunScorer bubbleFunScorer = new BubbleFunScorer(mScoringParams); - mWifiNetworkSelector.registerCandidateScorer(bubbleFunScorer); - ThroughputScorer throughputScorer = new ThroughputScorer(mScoringParams); - mWifiNetworkSelector.registerCandidateScorer(throughputScorer); - mWifiMetrics.setWifiNetworkSelector(mWifiNetworkSelector); - mWifiNetworkSuggestionsManager = new WifiNetworkSuggestionsManager(mContext, wifiHandler, - this, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore, mWifiMetrics, - mWifiCarrierInfoManager, mWifiKeyStore, mLruConnectionTracker); - mPasspointManager = new PasspointManager(mContext, this, - wifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(), - mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, - mMacAddressUtil, mWifiPermissionsUtil); - PasspointNetworkNominateHelper nominateHelper = - new PasspointNetworkNominateHelper(mPasspointManager, mWifiConfigManager, - mConnectivityLocalLog); - mSavedNetworkNominator = new SavedNetworkNominator( - mWifiConfigManager, nominateHelper, mConnectivityLocalLog, mWifiCarrierInfoManager, - mWifiPermissionsUtil, mWifiNetworkSuggestionsManager); - mNetworkSuggestionNominator = new NetworkSuggestionNominator(mWifiNetworkSuggestionsManager, - mWifiConfigManager, nominateHelper, mConnectivityLocalLog, mWifiCarrierInfoManager); - mScoredNetworkNominator = new ScoredNetworkNominator(mContext, wifiHandler, - mFrameworkFacade, mNetworkScoreManager, mContext.getPackageManager(), - mWifiConfigManager, mConnectivityLocalLog, - mWifiNetworkScoreCache, mWifiPermissionsUtil); - - mWifiMetrics.setPasspointManager(mPasspointManager); - mScanRequestProxy = new ScanRequestProxy(mContext, - (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE), - (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE), - this, mWifiConfigManager, - mWifiPermissionsUtil, mWifiMetrics, mClock, wifiHandler, mSettingsConfigStore); - mSarManager = new SarManager(mContext, makeTelephonyManager(), wifiLooper, - mWifiNative); - mWifiDiagnostics = new WifiDiagnostics( - mContext, this, mWifiNative, mBuildProperties, - new LastMileLogger(this), mClock); - mWifiChannelUtilizationConnected = new WifiChannelUtilization(mClock, mContext); - mWifiDataStall = new WifiDataStall(mFrameworkFacade, mWifiMetrics, mContext, - mDeviceConfigFacade, mWifiChannelUtilizationConnected, mClock, wifiHandler, - mThroughputPredictor); - mWifiMetrics.setWifiDataStall(mWifiDataStall); - mLinkProbeManager = new LinkProbeManager(mClock, mWifiNative, mWifiMetrics, - mFrameworkFacade, wifiHandler, mContext); - SupplicantStateTracker supplicantStateTracker = new SupplicantStateTracker( - mContext, mWifiConfigManager, mBatteryStats, wifiHandler); - mMboOceController = new MboOceController(makeTelephonyManager(), mWifiNative); - mWifiHealthMonitor = new WifiHealthMonitor(mContext, this, mClock, mWifiConfigManager, - mWifiScoreCard, wifiHandler, mWifiNative, l2KeySeed, mDeviceConfigFacade); - mWifiMetrics.setWifiHealthMonitor(mWifiHealthMonitor); - mClientModeImpl = new ClientModeImpl(mContext, mFrameworkFacade, - wifiLooper, mUserManager, - this, mBackupManagerProxy, mCountryCode, mWifiNative, - new WrongPasswordNotifier(mContext, mFrameworkFacade), - mSarManager, mWifiTrafficPoller, mLinkProbeManager, mBatteryStats, - supplicantStateTracker, mMboOceController, mWifiCarrierInfoManager, - new EapFailureNotifier(mContext, mFrameworkFacade, mWifiCarrierInfoManager), - new SimRequiredNotifier(mContext, mFrameworkFacade)); - mActiveModeWarden = new ActiveModeWarden(this, wifiLooper, - mWifiNative, new DefaultModeManager(mContext), mBatteryStats, mWifiDiagnostics, - mContext, mClientModeImpl, mSettingsStore, mFrameworkFacade, mWifiPermissionsUtil); - mWifiScanAlwaysAvailableSettingsCompatibility = - new WifiScanAlwaysAvailableSettingsCompatibility(mContext, wifiHandler, - mSettingsStore, mActiveModeWarden, mFrameworkFacade); - mWifiApConfigStore = new WifiApConfigStore( - mContext, this, wifiHandler, mBackupManagerProxy, - mWifiConfigStore, mWifiConfigManager, mActiveModeWarden, mWifiMetrics); - WakeupNotificationFactory wakeupNotificationFactory = - new WakeupNotificationFactory(mContext, this, mFrameworkFacade); - WakeupOnboarding wakeupOnboarding = new WakeupOnboarding(mContext, mWifiConfigManager, - wifiHandler, mFrameworkFacade, wakeupNotificationFactory); - mWakeupController = new WakeupController(mContext, wifiHandler, - new WakeupLock(mWifiConfigManager, mWifiMetrics.getWakeupMetrics(), mClock), - new WakeupEvaluator(mScoringParams), wakeupOnboarding, mWifiConfigManager, - mWifiConfigStore, mWifiNetworkSuggestionsManager, mWifiMetrics.getWakeupMetrics(), - this, mFrameworkFacade, mClock); - mLockManager = new WifiLockManager(mContext, mBatteryStats, - mClientModeImpl, mFrameworkFacade, wifiHandler, mWifiNative, mClock, mWifiMetrics); - mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock); - mWifiMulticastLockManager = new WifiMulticastLockManager( - mClientModeImpl.getMcastLockManagerFilterController(), mBatteryStats); - mDppManager = new DppManager(wifiHandler, mWifiNative, - mWifiConfigManager, mContext, mDppMetrics, mScanRequestProxy); - - // Register the various network Nominators with the network selector. - mWifiNetworkSelector.registerNetworkNominator(mSavedNetworkNominator); - mWifiNetworkSelector.registerNetworkNominator(mNetworkSuggestionNominator); - mWifiNetworkSelector.registerNetworkNominator(mScoredNetworkNominator); - - mClientModeImpl.start(); - } - - /** - * Obtain an instance of the WifiInjector class. - * - * This is the generic method to get an instance of the class. The first instance should be - * retrieved using the getInstanceWithContext method. - */ - public static WifiInjector getInstance() { - if (sWifiInjector == null) { - throw new IllegalStateException( - "Attempted to retrieve a WifiInjector instance before constructor was called."); - } - return sWifiInjector; - } - - /** - * Enable verbose logging in Injector objects. Called from the WifiServiceImpl (based on - * binder call). - */ - public void enableVerboseLogging(int verbose) { - mWifiLastResortWatchdog.enableVerboseLogging(verbose); - mWifiBackupRestore.enableVerboseLogging(verbose); - mHalDeviceManager.enableVerboseLogging(verbose); - mScanRequestProxy.enableVerboseLogging(verbose); - mWakeupController.enableVerboseLogging(verbose); - mWifiNetworkSuggestionsManager.enableVerboseLogging(verbose); - LogcatLog.enableVerboseLogging(verbose); - mDppManager.enableVerboseLogging(verbose); - mWifiCarrierInfoManager.enableVerboseLogging(verbose); - } - - public UserManager getUserManager() { - return mUserManager; - } - - public WifiMetrics getWifiMetrics() { - return mWifiMetrics; - } - - public WifiP2pMetrics getWifiP2pMetrics() { - return mWifiP2pMetrics; - } - - public SupplicantStaIfaceHal getSupplicantStaIfaceHal() { - return mSupplicantStaIfaceHal; - } - - public BackupManagerProxy getBackupManagerProxy() { - return mBackupManagerProxy; - } - - public FrameworkFacade getFrameworkFacade() { - return mFrameworkFacade; - } - - public HandlerThread getAsyncChannelHandlerThread() { - return mAsyncChannelHandlerThread; - } - - public HandlerThread getWifiP2pServiceHandlerThread() { - return mWifiP2pServiceHandlerThread; - } - - public HandlerThread getPasspointProvisionerHandlerThread() { - return mPasspointProvisionerHandlerThread; - } - - public HandlerThread getWifiHandlerThread() { - return mWifiHandlerThread; - } - - public WifiTrafficPoller getWifiTrafficPoller() { - return mWifiTrafficPoller; - } - - public WifiCountryCode getWifiCountryCode() { - return mCountryCode; - } - - public WifiApConfigStore getWifiApConfigStore() { - return mWifiApConfigStore; - } - - public SarManager getSarManager() { - return mSarManager; - } - - public ClientModeImpl getClientModeImpl() { - return mClientModeImpl; - } - - public ActiveModeWarden getActiveModeWarden() { - return mActiveModeWarden; - } - - public WifiSettingsStore getWifiSettingsStore() { - return mSettingsStore; - } - - public WifiLockManager getWifiLockManager() { - return mLockManager; - } - - public WifiLastResortWatchdog getWifiLastResortWatchdog() { - return mWifiLastResortWatchdog; - } - - public Clock getClock() { - return mClock; - } - - public PropertyService getPropertyService() { - return mPropertyService; - } - - public BuildProperties getBuildProperties() { - return mBuildProperties; - } - - public WifiBackupRestore getWifiBackupRestore() { - return mWifiBackupRestore; - } - - public SoftApBackupRestore getSoftApBackupRestore() { - return mSoftApBackupRestore; - } - - public WifiMulticastLockManager getWifiMulticastLockManager() { - return mWifiMulticastLockManager; - } - - public WifiConfigManager getWifiConfigManager() { - return mWifiConfigManager; - } - - public PasspointManager getPasspointManager() { - return mPasspointManager; - } - - public WakeupController getWakeupController() { - return mWakeupController; - } - - public ScoringParams getScoringParams() { - return mScoringParams; - } - - public WifiScoreCard getWifiScoreCard() { - return mWifiScoreCard; - } - - public TelephonyManager makeTelephonyManager() { - return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); - } - - public WifiCarrierInfoManager getWifiCarrierInfoManager() { - return mWifiCarrierInfoManager; - } - - public WifiStateTracker getWifiStateTracker() { - return mWifiStateTracker; - } - - public DppManager getDppManager() { - return mDppManager; - } - - /** - * Create a SoftApManager. - * @param config SoftApModeConfiguration object holding the config and mode - * @return an instance of SoftApManager - */ - public SoftApManager makeSoftApManager(@NonNull ActiveModeManager.Listener listener, - @NonNull WifiManager.SoftApCallback callback, - @NonNull SoftApModeConfiguration config) { - return new SoftApManager(mContext, mWifiHandlerThread.getLooper(), - mFrameworkFacade, mWifiNative, mCountryCode.getCountryCode(), listener, callback, - mWifiApConfigStore, config, mWifiMetrics, mSarManager, mWifiDiagnostics); - } - - /** - * Create a ClientModeManager - * - * @param listener listener for ClientModeManager state changes - * @return a new instance of ClientModeManager - */ - public ClientModeManager makeClientModeManager(ClientModeManager.Listener listener) { - return new ClientModeManager(mContext, mWifiHandlerThread.getLooper(), mClock, - mWifiNative, listener, mWifiMetrics, mSarManager, mWakeupController, - mClientModeImpl); - } - - /** - * Create a WifiLog instance. - * @param tag module name to include in all log messages - */ - public WifiLog makeLog(String tag) { - return new LogcatLog(tag); - } - - public BaseWifiDiagnostics getWifiDiagnostics() { - return mWifiDiagnostics; - } - - /** - * Obtain an instance of WifiScanner. - * If it was not already created, then obtain an instance. Note, this must be done lazily since - * WifiScannerService is separate and created later. - */ - public synchronized WifiScanner getWifiScanner() { - if (mWifiScanner == null) { - mWifiScanner = mContext.getSystemService(WifiScanner.class); - } - return mWifiScanner; - } - - /** - * Construct a new instance of WifiConnectivityManager & its dependencies. - * - * Create and return a new WifiConnectivityManager. - * @param clientModeImpl Instance of client mode impl. - * TODO(b/116233964): Remove cyclic dependency between WifiConnectivityManager & ClientModeImpl. - */ - public WifiConnectivityManager makeWifiConnectivityManager(ClientModeImpl clientModeImpl) { - mOpenNetworkNotifier = new OpenNetworkNotifier(mContext, - mWifiHandlerThread.getLooper(), mFrameworkFacade, mClock, mWifiMetrics, - mWifiConfigManager, mWifiConfigStore, clientModeImpl, - new ConnectToNetworkNotificationBuilder(mContext, this, mFrameworkFacade)); - mWifiLastResortWatchdog = new WifiLastResortWatchdog(this, mContext, mClock, - mWifiMetrics, clientModeImpl, mWifiHandlerThread.getLooper(), mDeviceConfigFacade, - mWifiThreadRunner); - mBssidBlocklistMonitor = new BssidBlocklistMonitor(mContext, mWifiConnectivityHelper, - mWifiLastResortWatchdog, mClock, mConnectivityLocalLog, mWifiScoreCard, - mScoringParams); - mWifiMetrics.setBssidBlocklistMonitor(mBssidBlocklistMonitor); - mWifiChannelUtilizationScan = new WifiChannelUtilization(mClock, mContext); - return new WifiConnectivityManager(mContext, getScoringParams(), - clientModeImpl, this, - mWifiConfigManager, mWifiNetworkSuggestionsManager, clientModeImpl.getWifiInfo(), - mWifiNetworkSelector, mWifiConnectivityHelper, - mWifiLastResortWatchdog, mOpenNetworkNotifier, - mWifiMetrics, new Handler(mWifiHandlerThread.getLooper()), - mClock, mConnectivityLocalLog, mWifiScoreCard); - } - - /** - * Construct a new instance of ConnectionFailureNotifier. - * @param wifiConnectivityManager - * @return the created instance - */ - public ConnectionFailureNotifier makeConnectionFailureNotifier( - WifiConnectivityManager wifiConnectivityManager) { - return new ConnectionFailureNotifier(mContext, this, mFrameworkFacade, mWifiConfigManager, - wifiConnectivityManager, new Handler(mWifiHandlerThread.getLooper())); - } - - /** - * Construct a new instance of {@link WifiNetworkFactory}. - * TODO(b/116233964): Remove cyclic dependency between WifiConnectivityManager & ClientModeImpl. - */ - public WifiNetworkFactory makeWifiNetworkFactory( - NetworkCapabilities nc, WifiConnectivityManager wifiConnectivityManager) { - return new WifiNetworkFactory( - mWifiHandlerThread.getLooper(), mContext, nc, - (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE), - (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE), - (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE), - mClock, this, wifiConnectivityManager, mWifiConfigManager, - mWifiConfigStore, mWifiPermissionsUtil, mWifiMetrics); - } - - /** - * Construct an instance of {@link NetworkRequestStoreData}. - */ - public NetworkRequestStoreData makeNetworkRequestStoreData( - NetworkRequestStoreData.DataSource dataSource) { - return new NetworkRequestStoreData(dataSource); - } - - /** - * Construct a new instance of {@link UntrustedWifiNetworkFactory}. - * TODO(b/116233964): Remove cyclic dependency between WifiConnectivityManager & ClientModeImpl. - */ - public UntrustedWifiNetworkFactory makeUntrustedWifiNetworkFactory( - NetworkCapabilities nc, WifiConnectivityManager wifiConnectivityManager) { - return new UntrustedWifiNetworkFactory( - mWifiHandlerThread.getLooper(), mContext, nc, wifiConnectivityManager); - } - - /** - * Construct an instance of {@link NetworkSuggestionStoreData}. - */ - public NetworkSuggestionStoreData makeNetworkSuggestionStoreData( - NetworkSuggestionStoreData.DataSource dataSource) { - return new NetworkSuggestionStoreData(dataSource); - } - - /** - * - */ - public ImsiPrivacyProtectionExemptionStoreData makeImsiProtectionExemptionStoreData( - ImsiPrivacyProtectionExemptionStoreData.DataSource dataSource) { - return new ImsiPrivacyProtectionExemptionStoreData(dataSource); - } - - /** - * Construct an instance of {@link SoftApStoreData}. - */ - public SoftApStoreData makeSoftApStoreData( - SoftApStoreData.DataSource dataSource) { - return new SoftApStoreData(mContext, mSettingsMigrationDataHolder, dataSource); - } - - public WifiPermissionsUtil getWifiPermissionsUtil() { - return mWifiPermissionsUtil; - } - - public WifiPermissionsWrapper getWifiPermissionsWrapper() { - return mWifiPermissionsWrapper; - } - - /** - * Returns a singleton instance of a HandlerThread for injection. Uses lazy initialization. - * - * TODO: share worker thread with other Wi-Fi handlers (b/27924886) - */ - public HandlerThread getWifiAwareHandlerThread() { - if (mWifiAwareHandlerThread == null) { // lazy initialization - mWifiAwareHandlerThread = new HandlerThread("wifiAwareService"); - mWifiAwareHandlerThread.start(); - } - return mWifiAwareHandlerThread; - } - - /** - * Returns a singleton instance of a HandlerThread for injection. Uses lazy initialization. - * - * TODO: share worker thread with other Wi-Fi handlers (b/27924886) - */ - public HandlerThread getRttHandlerThread() { - if (mRttHandlerThread == null) { // lazy initialization - mRttHandlerThread = new HandlerThread("wifiRttService"); - mRttHandlerThread.start(); - } - return mRttHandlerThread; - } - - public MacAddressUtil getMacAddressUtil() { - return mMacAddressUtil; - } - - public NotificationManager getNotificationManager() { - return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); - } - - public ConnectionFailureNotificationBuilder getConnectionFailureNotificationBuilder() { - return mConnectionFailureNotificationBuilder; - } - - /** - * Returns a single instance of HalDeviceManager for injection. - */ - public HalDeviceManager getHalDeviceManager() { - return mHalDeviceManager; - } - - public WifiNative getWifiNative() { - return mWifiNative; - } - - public WifiMonitor getWifiMonitor() { - return mWifiMonitor; - } - - public WifiP2pNative getWifiP2pNative() { - return mWifiP2pNative; - } - - public WifiP2pMonitor getWifiP2pMonitor() { - return mWifiP2pMonitor; - } - - public SelfRecovery getSelfRecovery() { - return mSelfRecovery; - } - - public ScanRequestProxy getScanRequestProxy() { - return mScanRequestProxy; - } - - public Runtime getJavaRuntime() { - return Runtime.getRuntime(); - } - - public WifiDataStall getWifiDataStall() { - return mWifiDataStall; - } - - public WifiNetworkSuggestionsManager getWifiNetworkSuggestionsManager() { - return mWifiNetworkSuggestionsManager; - } - - public IpMemoryStore getIpMemoryStore() { - if (mIpMemoryStore == null) { - mIpMemoryStore = IpMemoryStore.getMemoryStore(mContext); - } - return mIpMemoryStore; - } - - public BssidBlocklistMonitor getBssidBlocklistMonitor() { - return mBssidBlocklistMonitor; - } - - public HostapdHal getHostapdHal() { - return mHostapdHal; - } - - public String getWifiStackPackageName() { - return mContext.getPackageName(); - } - - public WifiThreadRunner getWifiThreadRunner() { - return mWifiThreadRunner; - } - - public WifiChannelUtilization getWifiChannelUtilizationScan() { - return mWifiChannelUtilizationScan; - } - - public WifiNetworkScoreCache getWifiNetworkScoreCache() { - return mWifiNetworkScoreCache; - } - - public NetdWrapper makeNetdWrapper() { - if (mNetdWrapper == null) { - mNetdWrapper = new NetdWrapper(mContext, new Handler(mWifiHandlerThread.getLooper())); - } - return mNetdWrapper; - } - - public WifiNl80211Manager getWifiCondManager() { - return mWifiCondManager; - } - - public WifiHealthMonitor getWifiHealthMonitor() { - return mWifiHealthMonitor; - } - - public ThroughputPredictor getThroughputPredictor() { - return mThroughputPredictor; - } - - public WifiSettingsConfigStore getSettingsConfigStore() { - return mSettingsConfigStore; - } - - public WifiScanAlwaysAvailableSettingsCompatibility - getWifiScanAlwaysAvailableSettingsCompatibility() { - return mWifiScanAlwaysAvailableSettingsCompatibility; - } - - public DeviceConfigFacade getDeviceConfigFacade() { - return mDeviceConfigFacade; - } -} diff --git a/service/java/com/android/server/wifi/WifiKeyStore.java b/service/java/com/android/server/wifi/WifiKeyStore.java deleted file mode 100644 index c248d2269..000000000 --- a/service/java/com/android/server/wifi/WifiKeyStore.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.annotation.Nullable; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.security.KeyChain; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.Log; - -import com.android.internal.util.Preconditions; -import com.android.server.wifi.util.ArrayUtils; - -import java.security.Key; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.Principal; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -/** - * This class provides the methods to access keystore for certificate management. - * - * NOTE: This class should only be used from WifiConfigManager! - */ -public class WifiKeyStore { - private static final String TAG = "WifiKeyStore"; - - private boolean mVerboseLoggingEnabled = false; - - @Nullable private final KeyStore mKeyStore; - - WifiKeyStore(@Nullable KeyStore keyStore) { - mKeyStore = keyStore; - if (mKeyStore == null) { - Log.e(TAG, "Unable to retrieve keystore, all key operations will fail"); - } - } - - /** - * Enable verbose logging. - */ - void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - } - - // Certificate and private key management for EnterpriseConfig - private static boolean needsKeyStore(WifiEnterpriseConfig config) { - return (config.getClientCertificate() != null || config.getCaCertificate() != null - || config.getCaCertificateAlias() != null - || config.getClientCertificateAlias() != null); - } - - private static boolean isHardwareBackedKey(Key key) { - return KeyChain.isBoundKeyAlgorithm(key.getAlgorithm()); - } - - private static boolean hasHardwareBackedKey(Certificate certificate) { - return isHardwareBackedKey(certificate.getPublicKey()); - } - - /** - * Install keys for given enterprise network. - * - * @param existingConfig Existing config corresponding to the network already stored in our - * database. This maybe null if it's a new network. - * @param config Config corresponding to the network. - * @param existingAlias Alias for all the existing key store data stored. - * @param alias Alias for all the key store data to store. - * @return true if successful, false otherwise. - */ - private boolean installKeys(WifiEnterpriseConfig existingConfig, WifiEnterpriseConfig config, - String existingAlias, String alias) { - Preconditions.checkNotNull(mKeyStore); - Certificate[] clientCertificateChain = config.getClientCertificateChain(); - if (!ArrayUtils.isEmpty(clientCertificateChain)) { - if (!putUserPrivKeyAndCertsInKeyStore(alias, config.getClientPrivateKey(), - clientCertificateChain)) { - return false; - } - } - X509Certificate[] caCertificates = config.getCaCertificates(); - Set<String> oldCaCertificatesToRemove = new ArraySet<>(); - if (existingConfig != null && existingConfig.getCaCertificateAliases() != null) { - oldCaCertificatesToRemove.addAll( - Arrays.asList(existingConfig.getCaCertificateAliases())); - } - List<String> caCertificateAliases = null; - if (caCertificates != null) { - caCertificateAliases = new ArrayList<>(); - for (int i = 0; i < caCertificates.length; i++) { - String caAlias = String.format("%s_%d", alias, i); - - oldCaCertificatesToRemove.remove(caAlias); - if (!putCaCertInKeyStore(caAlias, caCertificates[i])) { - // cleanup everything on failure. - removeEntryFromKeyStore(alias); - for (String addedAlias : caCertificateAliases) { - removeEntryFromKeyStore(addedAlias); - } - return false; - } - caCertificateAliases.add(caAlias); - } - } - // If alias changed, remove the old one. - if (!alias.equals(existingAlias)) { - // Remove old private keys. - removeEntryFromKeyStore(existingAlias); - } - // Remove any old CA certs. - for (String oldAlias : oldCaCertificatesToRemove) { - removeEntryFromKeyStore(oldAlias); - } - // Set alias names - if (config.getClientCertificate() != null) { - config.setClientCertificateAlias(alias); - config.resetClientKeyEntry(); - } - - if (caCertificates != null) { - config.setCaCertificateAliases( - caCertificateAliases.toArray(new String[caCertificateAliases.size()])); - config.resetCaCertificate(); - } - return true; - } - - /** - * Install a CA certificate into the keystore. - * - * @param alias The alias name of the CA certificate to be installed - * @param cert The CA certificate to be installed - * @return true on success - */ - public boolean putCaCertInKeyStore(String alias, Certificate cert) { - try { - mKeyStore.setCertificateEntry(alias, cert); - return true; - } catch (KeyStoreException e) { - Log.e(TAG, "Failed to put CA certificate in keystore: " + e.getMessage()); - return false; - } - } - - /** - * Install a private key + user certificate into the keystore. - * - * @param alias The alias name of the key to be installed - * @param key The private key to be installed - * @param certs User Certificate chain. - * @return true on success - */ - public boolean putUserPrivKeyAndCertsInKeyStore(String alias, Key key, Certificate[] certs) { - try { - mKeyStore.setKeyEntry(alias, key, null, certs); - return true; - } catch (KeyStoreException e) { - Log.e(TAG, "Failed to put private key or certificate in keystore: " + e.getMessage()); - return false; - } - } - - /** - * Remove a certificate or key entry specified by the alias name from the keystore. - * - * @param alias The alias name of the entry to be removed - * @return true on success - */ - public boolean removeEntryFromKeyStore(String alias) { - Preconditions.checkNotNull(mKeyStore); - try { - mKeyStore.deleteEntry(alias); - return true; - } catch (KeyStoreException e) { - return false; - } - } - - /** - * Remove enterprise keys from the network config. - * - * @param config Config corresponding to the network. - */ - public void removeKeys(WifiEnterpriseConfig config) { - Preconditions.checkNotNull(mKeyStore); - // Do not remove keys that were manually installed by the user - if (config.isAppInstalledDeviceKeyAndCert()) { - String client = config.getClientCertificateAlias(); - // a valid client certificate is configured - if (!TextUtils.isEmpty(client)) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "removing client private key, user cert and CA cert)"); - } - // if there is only a single CA certificate, then that is also stored with - // the same alias, hence will be removed here. - removeEntryFromKeyStore(client); - } - } - - // Do not remove CA certs that were manually installed by the user - if (config.isAppInstalledCaCert()) { - String[] aliases = config.getCaCertificateAliases(); - if (aliases == null || aliases.length == 0) { - return; - } - // Remove all CA certificate. - for (String ca : aliases) { - if (!TextUtils.isEmpty(ca)) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "removing CA cert: " + ca); - } - removeEntryFromKeyStore(ca); - } - } - } - } - - /** - * Update/Install keys for given enterprise network. - * - * @param config Config corresponding to the network. - * @param existingConfig Existing config corresponding to the network already stored in our - * database. This maybe null if it's a new network. - * @return true if successful, false otherwise. - */ - public boolean updateNetworkKeys(WifiConfiguration config, WifiConfiguration existingConfig) { - Preconditions.checkNotNull(mKeyStore); - Preconditions.checkNotNull(config.enterpriseConfig); - WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; - /* config passed may include only fields being updated. - * In order to generate the key id, fetch uninitialized - * fields from the currently tracked configuration - */ - String keyId = config.getKeyIdForCredentials(existingConfig); - WifiEnterpriseConfig existingEnterpriseConfig = null; - String existingKeyId = null; - if (existingConfig != null) { - Preconditions.checkNotNull(existingConfig.enterpriseConfig); - existingEnterpriseConfig = existingConfig.enterpriseConfig; - existingKeyId = existingConfig.getKeyIdForCredentials(existingConfig); - } - if (!needsKeyStore(enterpriseConfig)) { - return true; - } - - try { - if (!installKeys(existingEnterpriseConfig, enterpriseConfig, existingKeyId, keyId)) { - Log.e(TAG, config.SSID + ": failed to install keys"); - return false; - } - } catch (IllegalStateException e) { - Log.e(TAG, config.SSID + " invalid config for key installation: " + e.getMessage()); - return false; - } - - // For WPA3-Enterprise 192-bit networks, set the SuiteBCipher field based on the - // CA certificate type. Suite-B requires SHA384, reject other certs. - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) { - // Read the CA certificates, and initialize - String[] caAliases = config.enterpriseConfig.getCaCertificateAliases(); - - if (caAliases == null || caAliases.length == 0) { - Log.e(TAG, "No CA aliases in profile"); - return false; - } - - int caCertType = -1; - int prevCaCertType = -1; - for (String caAlias : caAliases) { - Certificate caCert = null; - try { - caCert = mKeyStore.getCertificate(caAlias); - } catch (KeyStoreException e) { - Log.e(TAG, "Failed to get Suite-B certificate", e); - } - if (caCert == null || !(caCert instanceof X509Certificate)) { - Log.e(TAG, "Failed reading CA certificate for Suite-B"); - return false; - } - - // Confirm that the CA certificate is compatible with Suite-B requirements - caCertType = getSuiteBCipherFromCert((X509Certificate) caCert); - if (caCertType < 0) { - return false; - } - if (prevCaCertType != -1) { - if (prevCaCertType != caCertType) { - Log.e(TAG, "Incompatible CA certificates"); - return false; - } - } - prevCaCertType = caCertType; - } - - Certificate clientCert = null; - try { - clientCert = mKeyStore.getCertificate(config.enterpriseConfig - .getClientCertificateAlias()); - } catch (KeyStoreException e) { - Log.e(TAG, "Failed to get Suite-B client certificate", e); - } - if (clientCert == null || !(clientCert instanceof X509Certificate)) { - Log.e(TAG, "Failed reading client certificate for Suite-B"); - return false; - } - - int clientCertType = getSuiteBCipherFromCert((X509Certificate) clientCert); - if (clientCertType < 0) { - return false; - } - - if (clientCertType == caCertType) { - config.allowedSuiteBCiphers.clear(); - config.allowedSuiteBCiphers.set(clientCertType); - } else { - Log.e(TAG, "Client certificate for Suite-B is incompatible with the CA " - + "certificate"); - return false; - } - } - return true; - } - - /** - * Get the Suite-B cipher from the certificate - * - * @param x509Certificate Certificate to process - * @return WifiConfiguration.SuiteBCipher.ECDHE_RSA if the certificate OID matches the Suite-B - * requirements for RSA certificates, WifiConfiguration.SuiteBCipher.ECDHE_ECDSA if the - * certificate OID matches the Suite-B requirements for ECDSA certificates, or -1 otherwise. - */ - private int getSuiteBCipherFromCert(X509Certificate x509Certificate) { - String sigAlgOid = x509Certificate.getSigAlgOID(); - if (mVerboseLoggingEnabled) { - Principal p = x509Certificate.getSubjectX500Principal(); - if (p != null && !TextUtils.isEmpty(p.getName())) { - Log.d(TAG, "Checking cert " + p.getName()); - } - } - - // Wi-Fi alliance requires the use of both ECDSA secp384r1 and RSA 3072 certificates - // in WPA3-Enterprise 192-bit security networks, which are also known as Suite-B-192 - // networks, even though NSA Suite-B-192 mandates ECDSA only. The use of the term - // Suite-B was already coined in the IEEE 802.11-2016 specification for - // AKM 00-0F-AC but the test plan for WPA3-Enterprise 192-bit for APs mandates - // support for both RSA and ECDSA, and for STAs it mandates ECDSA and optionally - // RSA. In order to be compatible with all WPA3-Enterprise 192-bit deployments, - // we are supporting both types here. - if (sigAlgOid.equals("1.2.840.113549.1.1.12")) { - // sha384WithRSAEncryption - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Found Suite-B RSA certificate"); - } - return WifiConfiguration.SuiteBCipher.ECDHE_RSA; - } else if (sigAlgOid.equals("1.2.840.10045.4.3.3")) { - // ecdsa-with-SHA384 - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Found Suite-B ECDSA certificate"); - } - return WifiConfiguration.SuiteBCipher.ECDHE_ECDSA; - } - Log.e(TAG, "Invalid certificate type for Suite-B: " + sigAlgOid); - return -1; - } -} diff --git a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java deleted file mode 100644 index 9846747f6..000000000 --- a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java +++ /dev/null @@ -1,831 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.text.TextUtils; -import android.util.LocalLog; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * This Class is a Work-In-Progress, intended behavior is as follows: - * Essentially this class automates a user toggling 'Airplane Mode' when WiFi "won't work". - * IF each available saved network has failed connecting more times than the FAILURE_THRESHOLD - * THEN Watchdog will restart Supplicant, wifi driver and return ClientModeImpl to InitialState. - */ -public class WifiLastResortWatchdog { - private static final String TAG = "WifiLastResortWatchdog"; - private boolean mVerboseLoggingEnabled = false; - /** - * Association Failure code - */ - public static final int FAILURE_CODE_ASSOCIATION = 1; - /** - * Authentication Failure code - */ - public static final int FAILURE_CODE_AUTHENTICATION = 2; - /** - * Dhcp Failure code - */ - public static final int FAILURE_CODE_DHCP = 3; - /** - * Maximum number of scan results received since we last saw a BSSID. - * If it is not seen before this limit is reached, the network is culled - */ - public static final int MAX_BSSID_AGE = 10; - /** - * BSSID used to increment failure counts against ALL bssids associated with a particular SSID - */ - public static final String BSSID_ANY = "any"; - /** - * Failure count that each available networks must meet to possibly trigger the Watchdog - */ - public static final int FAILURE_THRESHOLD = 7; - public static final String BUGREPORT_TITLE = "Wifi watchdog triggered"; - public static final double PROB_TAKE_BUGREPORT_DEFAULT = 1; - - // Number of milliseconds to wait before re-enable Watchdog triger - @VisibleForTesting - public static final long LAST_TRIGGER_TIMEOUT_MILLIS = 2 * 3600 * 1000; // 2 hours - - - /** - * Cached WifiConfigurations of available networks seen within MAX_BSSID_AGE scan results - * Key:BSSID, Value:Counters of failure types - */ - private Map<String, AvailableNetworkFailureCount> mRecentAvailableNetworks = new HashMap<>(); - - /** - * Map of SSID to <FailureCount, AP count>, used to count failures & number of access points - * belonging to an SSID. - */ - private Map<String, Pair<AvailableNetworkFailureCount, Integer>> mSsidFailureCount = - new HashMap<>(); - - /* List of failure BSSID */ - private Set<String> mBssidFailureList = new HashSet<>(); - - // Tracks: if ClientModeImpl is in ConnectedState - private boolean mWifiIsConnected = false; - // Is Watchdog allowed to trigger now? Set to false after triggering. Set to true after - // successfully connecting or a new network (SSID) becomes available to connect to. - private boolean mWatchdogAllowedToTrigger = true; - private long mTimeLastTrigger = 0; - private String mSsidLastTrigger = null; - - private WifiInjector mWifiInjector; - private WifiMetrics mWifiMetrics; - private ClientModeImpl mClientModeImpl; - private Looper mClientModeImplLooper; - private double mBugReportProbability = PROB_TAKE_BUGREPORT_DEFAULT; - private Clock mClock; - private Context mContext; - private DeviceConfigFacade mDeviceConfigFacade; - // If any connection failure happened after watchdog triggering restart then assume watchdog - // did not fix the problem - private boolean mWatchdogFixedWifi = true; - private long mLastStartConnectTime = 0; - private final Handler mHandler; - private final WifiThreadRunner mWifiThreadRunner; - - private Boolean mWatchdogFeatureEnabled = null; - - /** - * Local log used for debugging any WifiLastResortWatchdog issues. - */ - private final LocalLog mLocalLog = new LocalLog(100); - - WifiLastResortWatchdog(WifiInjector wifiInjector, Context context, Clock clock, - WifiMetrics wifiMetrics, ClientModeImpl clientModeImpl, Looper clientModeImplLooper, - DeviceConfigFacade deviceConfigFacade, WifiThreadRunner wifiThreadRunner) { - mWifiInjector = wifiInjector; - mClock = clock; - mWifiMetrics = wifiMetrics; - mClientModeImpl = clientModeImpl; - mClientModeImplLooper = clientModeImplLooper; - mContext = context; - mDeviceConfigFacade = deviceConfigFacade; - mWifiThreadRunner = wifiThreadRunner; - mHandler = new Handler(clientModeImplLooper) { - public void handleMessage(Message msg) { - processMessage(msg); - } - }; - } - - /** - * Returns handler for L2 events from supplicant. - * @return Handler - */ - public Handler getHandler() { - return mHandler; - } - - /** - * Refreshes when the last CMD_START_CONNECT is triggered. - */ - public void noteStartConnectTime() { - mHandler.post(() -> { - mLastStartConnectTime = mClock.getElapsedSinceBootMillis(); - }); - } - - private void processMessage(Message msg) { - switch (msg.what) { - case WifiMonitor.NETWORK_CONNECTION_EVENT: - // Trigger bugreport for successful connections that take abnormally long - if (mDeviceConfigFacade.isAbnormalConnectionBugreportEnabled() - && mLastStartConnectTime > 0) { - long durationMs = mClock.getElapsedSinceBootMillis() - mLastStartConnectTime; - long abnormalConnectionDurationMs = - mDeviceConfigFacade.getAbnormalConnectionDurationMs(); - if (durationMs > abnormalConnectionDurationMs) { - final String bugTitle = "Wi-Fi Bugreport: Abnormal connection time"; - final String bugDetail = "Expected connection to take less than " - + abnormalConnectionDurationMs + " milliseconds. " - + "Actually took " + durationMs + " milliseconds."; - logv("Triggering bug report for abnormal connection time."); - mWifiThreadRunner.post(() -> - mClientModeImpl.takeBugReport(bugTitle, bugDetail)); - } - } - // Should reset last connection time after each connection regardless if bugreport - // is enabled or not. - mLastStartConnectTime = 0; - break; - default: - return; - } - } - - /** - * Refreshes recentAvailableNetworks with the latest available networks - * Adds new networks, removes old ones that have timed out. Should be called after Wifi - * framework decides what networks it is potentially connecting to. - * @param availableNetworks ScanDetail & Config list of potential connection - * candidates - */ - public void updateAvailableNetworks( - List<Pair<ScanDetail, WifiConfiguration>> availableNetworks) { - // Add new networks to mRecentAvailableNetworks - if (availableNetworks != null) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "updateAvailableNetworks: size = " + availableNetworks.size()); - } - for (Pair<ScanDetail, WifiConfiguration> pair : availableNetworks) { - final ScanDetail scanDetail = pair.first; - final WifiConfiguration config = pair.second; - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult == null) continue; - String bssid = scanResult.BSSID; - String ssid = "\"" + scanDetail.getSSID() + "\""; - if (mVerboseLoggingEnabled) { - Log.v(TAG, " " + bssid + ": " + scanDetail.getSSID()); - } - // Cache the scanResult & WifiConfig - AvailableNetworkFailureCount availableNetworkFailureCount = - mRecentAvailableNetworks.get(bssid); - if (availableNetworkFailureCount == null) { - // New network is available - availableNetworkFailureCount = new AvailableNetworkFailureCount(config); - availableNetworkFailureCount.ssid = ssid; - - // Count AP for this SSID - Pair<AvailableNetworkFailureCount, Integer> ssidFailsAndApCount = - mSsidFailureCount.get(ssid); - if (ssidFailsAndApCount == null) { - // This is a new SSID, create new FailureCount for it and set AP count to 1 - ssidFailsAndApCount = Pair.create(new AvailableNetworkFailureCount(config), - 1); - // Do not re-enable Watchdog in LAST_TRIGGER_TIMEOUT_MILLIS - // after last time Watchdog be triggered - if (!mWatchdogAllowedToTrigger && (mTimeLastTrigger == 0 - || (mClock.getElapsedSinceBootMillis() - mTimeLastTrigger) - >= LAST_TRIGGER_TIMEOUT_MILLIS)) { - localLog("updateAvailableNetworks: setWatchdogTriggerEnabled to true"); - setWatchdogTriggerEnabled(true); - } - } else { - final Integer numberOfAps = ssidFailsAndApCount.second; - // This is not a new SSID, increment the AP count for it - ssidFailsAndApCount = Pair.create(ssidFailsAndApCount.first, - numberOfAps + 1); - } - mSsidFailureCount.put(ssid, ssidFailsAndApCount); - } - // refresh config if it is not null - if (config != null) { - availableNetworkFailureCount.config = config; - } - // If we saw a network, set its Age to -1 here, aging iteration will set it to 0 - availableNetworkFailureCount.age = -1; - mRecentAvailableNetworks.put(bssid, availableNetworkFailureCount); - } - } - - // Iterate through available networks updating timeout counts & removing networks. - Iterator<Map.Entry<String, AvailableNetworkFailureCount>> it = - mRecentAvailableNetworks.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<String, AvailableNetworkFailureCount> entry = it.next(); - if (entry.getValue().age < MAX_BSSID_AGE - 1) { - entry.getValue().age++; - } else { - // Decrement this SSID : AP count - String ssid = entry.getValue().ssid; - Pair<AvailableNetworkFailureCount, Integer> ssidFails = - mSsidFailureCount.get(ssid); - if (ssidFails != null) { - Integer apCount = ssidFails.second - 1; - if (apCount > 0) { - ssidFails = Pair.create(ssidFails.first, apCount); - mSsidFailureCount.put(ssid, ssidFails); - } else { - mSsidFailureCount.remove(ssid); - } - } else { - Log.d(TAG, "updateAvailableNetworks: SSID to AP count mismatch for " + ssid); - } - it.remove(); - } - } - if (mVerboseLoggingEnabled) Log.v(TAG, toString()); - } - - /** - * Increments the failure reason count for the given bssid. Performs a check to see if we have - * exceeded a failure threshold for all available networks, and executes the last resort restart - * @param bssid of the network that has failed connection, can be "any" - * @param reason Message id from ClientModeImpl for this failure - * @return true if watchdog triggers, returned for test visibility - */ - public boolean noteConnectionFailureAndTriggerIfNeeded(String ssid, String bssid, int reason) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "noteConnectionFailureAndTriggerIfNeeded: [" + ssid + ", " + bssid + ", " - + reason + "]"); - } - - // Update failure count for the failing network - updateFailureCountForNetwork(ssid, bssid, reason); - - // If watchdog is not allowed to trigger it means a wifi restart is already triggered - if (!mWatchdogAllowedToTrigger) { - mWifiMetrics.incrementWatchdogTotalConnectionFailureCountAfterTrigger(); - mWatchdogFixedWifi = false; - } - // Have we met conditions to trigger the Watchdog Wifi restart? - boolean isRestartNeeded = checkTriggerCondition(); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "isRestartNeeded = " + isRestartNeeded); - } - if (isRestartNeeded) { - if (getWifiWatchdogFeature()) { - // Stop the watchdog from triggering until re-enabled - localLog("Trigger recovery: setWatchdogTriggerEnabled to false"); - setWatchdogTriggerEnabled(false); - mWatchdogFixedWifi = true; - loge("Watchdog triggering recovery"); - mSsidLastTrigger = ssid; - mTimeLastTrigger = mClock.getElapsedSinceBootMillis(); - localLog(toString()); - mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - incrementWifiMetricsTriggerCounts(); - } else { - // auto bugreport if issue happens - loge("bugreport notification"); - setWatchdogTriggerEnabled(false); - takeBugReportWithCurrentProbability("Wifi Watchdog bite"); - } - } - return isRestartNeeded; - } - - /** - * Handles transitions entering and exiting ClientModeImpl ConnectedState - * Used to track wifistate, and perform watchdog count resetting - * @param isEntering true if called from ConnectedState.enter(), false for exit() - */ - public void connectedStateTransition(boolean isEntering) { - logv("connectedStateTransition: isEntering = " + isEntering); - - mWifiIsConnected = isEntering; - if (!isEntering) { - return; - } - if (!mWatchdogAllowedToTrigger && mWatchdogFixedWifi - && getWifiWatchdogFeature() - && checkIfAtleastOneNetworkHasEverConnected() - && checkIfConnectedBackToSameSsid() - && checkIfConnectedBssidHasEverFailed()) { - takeBugReportWithCurrentProbability("Wifi fixed after restart"); - // WiFi has connected after a Watchdog trigger, without any new networks becoming - // available, log a Watchdog success in wifi metrics - mWifiMetrics.incrementNumLastResortWatchdogSuccesses(); - long durationMs = mClock.getElapsedSinceBootMillis() - mTimeLastTrigger; - mWifiMetrics.setWatchdogSuccessTimeDurationMs(durationMs); - } - // If the watchdog trigger was disabled (it triggered), connecting means we did - // something right, re-enable it so it can fire again. - localLog("connectedStateTransition: setWatchdogTriggerEnabled to true"); - setWatchdogTriggerEnabled(true); - } - - /** - * Helper function to check if device connected to BSSID - * which is in BSSID failure list after watchdog trigger. - */ - private boolean checkIfConnectedBssidHasEverFailed() { - return mBssidFailureList.contains(mClientModeImpl.getWifiInfo().getBSSID()); - } - - /** - * Helper function to check if device connect back to same - * SSID after watchdog trigger - */ - private boolean checkIfConnectedBackToSameSsid() { - if (TextUtils.equals(mSsidLastTrigger, mClientModeImpl.getWifiInfo().getSSID())) { - return true; - } - localLog("checkIfConnectedBackToSameSsid: different SSID be connected"); - return false; - } - - /** - * Triggers a wifi specific bugreport with a based on the current trigger probability. - * @param bugDetail description of the bug - */ - private void takeBugReportWithCurrentProbability(String bugDetail) { - if (mBugReportProbability <= Math.random()) { - return; - } - (new Handler(mClientModeImplLooper)).post(() -> { - mClientModeImpl.takeBugReport(BUGREPORT_TITLE, bugDetail); - }); - } - - /** - * Increments the failure reason count for the given network, in 'mSsidFailureCount' - * Failures are counted per SSID, either; by using the ssid string when the bssid is "any" - * or by looking up the ssid attached to a specific bssid - * An unused set of counts is also kept which is bssid specific, in 'mRecentAvailableNetworks' - * @param ssid of the network that has failed connection - * @param bssid of the network that has failed connection, can be "any" - * @param reason Message id from ClientModeImpl for this failure - */ - private void updateFailureCountForNetwork(String ssid, String bssid, int reason) { - logv("updateFailureCountForNetwork: [" + ssid + ", " + bssid + ", " - + reason + "]"); - if (BSSID_ANY.equals(bssid)) { - incrementSsidFailureCount(ssid, reason); - } else { - // Bssid count is actually unused except for logging purposes - // SSID count is incremented within the BSSID counting method - incrementBssidFailureCount(ssid, bssid, reason); - mBssidFailureList.add(bssid); - } - } - - /** - * Update the per-SSID failure count - * @param ssid the ssid to increment failure count for - * @param reason the failure type to increment count for - */ - private void incrementSsidFailureCount(String ssid, int reason) { - Pair<AvailableNetworkFailureCount, Integer> ssidFails = mSsidFailureCount.get(ssid); - if (ssidFails == null) { - Log.d(TAG, "updateFailureCountForNetwork: No networks for ssid = " + ssid); - return; - } - AvailableNetworkFailureCount failureCount = ssidFails.first; - failureCount.incrementFailureCount(reason); - } - - /** - * Update the per-BSSID failure count - * @param bssid the bssid to increment failure count for - * @param reason the failure type to increment count for - */ - private void incrementBssidFailureCount(String ssid, String bssid, int reason) { - AvailableNetworkFailureCount availableNetworkFailureCount = - mRecentAvailableNetworks.get(bssid); - if (availableNetworkFailureCount == null) { - Log.d(TAG, "updateFailureCountForNetwork: Unable to find Network [" + ssid - + ", " + bssid + "]"); - return; - } - if (!availableNetworkFailureCount.ssid.equals(ssid)) { - Log.d(TAG, "updateFailureCountForNetwork: Failed connection attempt has" - + " wrong ssid. Failed [" + ssid + ", " + bssid + "], buffered [" - + availableNetworkFailureCount.ssid + ", " + bssid + "]"); - return; - } - if (availableNetworkFailureCount.config == null) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "updateFailureCountForNetwork: network has no config [" - + ssid + ", " + bssid + "]"); - } - } - availableNetworkFailureCount.incrementFailureCount(reason); - incrementSsidFailureCount(ssid, reason); - } - - /** - * Helper function to check if we should ignore BSSID update. - * @param bssid BSSID of the access point - * @return true if we should ignore BSSID update - */ - public boolean shouldIgnoreBssidUpdate(String bssid) { - return mWatchdogAllowedToTrigger - && isBssidOnlyApOfSsid(bssid) - && isSingleSsidRecorded() - && checkIfAtleastOneNetworkHasEverConnected(); - } - - /** - * Helper function to check if we should ignore SSID update. - * @return true if should ignore SSID update - */ - public boolean shouldIgnoreSsidUpdate() { - return mWatchdogAllowedToTrigger - && isSingleSsidRecorded() - && checkIfAtleastOneNetworkHasEverConnected(); - } - - /** - * Check the specified BSSID is the only BSSID for its corresponding SSID. - * @param bssid BSSID of the access point - * @return true if only BSSID for its corresponding SSID be observed - */ - private boolean isBssidOnlyApOfSsid(String bssid) { - AvailableNetworkFailureCount availableNetworkFailureCount = - mRecentAvailableNetworks.get(bssid); - if (availableNetworkFailureCount == null) { - return false; - } - String ssid = availableNetworkFailureCount.ssid; - Pair<AvailableNetworkFailureCount, Integer> ssidFails = mSsidFailureCount.get(ssid); - if (ssidFails == null) { - Log.d(TAG, "isOnlyBssidAvailable: Could not find SSID count for " + ssid); - return false; - } - if (ssidFails.second != 1) { - return false; - } - return true; - } - - /** - * Check there is only single SSID be observed. - * @return true if only single SSID be observed. - */ - private boolean isSingleSsidRecorded() { - return (mSsidFailureCount.size() == 1); - } - - /** - * Check trigger condition: For all available networks, have we met a failure threshold for each - * of them, and have previously connected to at-least one of the available networks - * @return is the trigger condition true - */ - private boolean checkTriggerCondition() { - if (mVerboseLoggingEnabled) Log.v(TAG, "checkTriggerCondition."); - // Don't check Watchdog trigger if wifi is in a connected state - // (This should not occur, but we want to protect against any race conditions) - if (mWifiIsConnected) return false; - // Don't check Watchdog trigger if trigger is not enabled - if (!mWatchdogAllowedToTrigger) return false; - - for (Map.Entry<String, AvailableNetworkFailureCount> entry - : mRecentAvailableNetworks.entrySet()) { - if (!isOverFailureThreshold(entry.getKey())) { - // This available network is not over failure threshold, meaning we still have a - // network to try connecting to - return false; - } - } - // We have met the failure count for every available network. - // Trigger restart if there exists at-least one network that we have previously connected. - boolean atleastOneNetworkHasEverConnected = checkIfAtleastOneNetworkHasEverConnected(); - logv("checkTriggerCondition: return = " + atleastOneNetworkHasEverConnected); - return checkIfAtleastOneNetworkHasEverConnected(); - } - - private boolean checkIfAtleastOneNetworkHasEverConnected() { - for (Map.Entry<String, AvailableNetworkFailureCount> entry - : mRecentAvailableNetworks.entrySet()) { - if (entry.getValue().config != null - && entry.getValue().config.getNetworkSelectionStatus().hasEverConnected()) { - return true; - } - } - return false; - } - - /** - * Update WifiMetrics with various Watchdog stats (trigger counts, failed network counts) - */ - private void incrementWifiMetricsTriggerCounts() { - if (mVerboseLoggingEnabled) Log.v(TAG, "incrementWifiMetricsTriggerCounts."); - mWifiMetrics.incrementNumLastResortWatchdogTriggers(); - mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal( - mSsidFailureCount.size()); - // Number of networks over each failure type threshold, present at trigger time - int badAuth = 0; - int badAssoc = 0; - int badDhcp = 0; - int badSum = 0; - for (Map.Entry<String, Pair<AvailableNetworkFailureCount, Integer>> entry - : mSsidFailureCount.entrySet()) { - badSum = entry.getValue().first.associationRejection - + entry.getValue().first.authenticationFailure - + entry.getValue().first.dhcpFailure; - // count as contributor if over half of badSum. - if (badSum >= FAILURE_THRESHOLD) { - badAssoc += (entry.getValue().first.associationRejection >= badSum / 2) ? 1 : 0; - badAuth += (entry.getValue().first.authenticationFailure >= badSum / 2) ? 1 : 0; - badDhcp += (entry.getValue().first.dhcpFailure >= badSum / 2) ? 1 : 0; - } - } - if (badAuth > 0) { - mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(badAuth); - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication(); - } - if (badAssoc > 0) { - mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal(badAssoc); - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation(); - } - if (badDhcp > 0) { - mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal(badDhcp); - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp(); - } - } - - /** - * Clear all failure counts - */ - public void clearAllFailureCounts() { - if (mVerboseLoggingEnabled) Log.v(TAG, "clearAllFailureCounts."); - for (Map.Entry<String, AvailableNetworkFailureCount> entry - : mRecentAvailableNetworks.entrySet()) { - final AvailableNetworkFailureCount failureCount = entry.getValue(); - failureCount.resetCounts(); - } - for (Map.Entry<String, Pair<AvailableNetworkFailureCount, Integer>> entry - : mSsidFailureCount.entrySet()) { - final AvailableNetworkFailureCount failureCount = entry.getValue().first; - failureCount.resetCounts(); - } - mBssidFailureList.clear(); - } - /** - * Gets the buffer of recently available networks - */ - Map<String, AvailableNetworkFailureCount> getRecentAvailableNetworks() { - return mRecentAvailableNetworks; - } - - /** - * Activates or deactivates the Watchdog trigger. Counting and network buffering still occurs - * @param enable true to enable the Watchdog trigger, false to disable it - */ - private void setWatchdogTriggerEnabled(boolean enable) { - if (mVerboseLoggingEnabled) Log.v(TAG, "setWatchdogTriggerEnabled: enable = " + enable); - // Reset failure counts before actives watchdog - if (enable) { - clearAllFailureCounts(); - } - mWatchdogAllowedToTrigger = enable; - } - - /** - * Prints all networks & counts within mRecentAvailableNetworks to string - */ - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("mWatchdogFeatureEnabled: ").append(getWifiWatchdogFeature()); - sb.append("\nmWatchdogAllowedToTrigger: ").append(mWatchdogAllowedToTrigger); - sb.append("\nmWifiIsConnected: ").append(mWifiIsConnected); - sb.append("\nmRecentAvailableNetworks: ").append(mRecentAvailableNetworks.size()); - for (Map.Entry<String, AvailableNetworkFailureCount> entry - : mRecentAvailableNetworks.entrySet()) { - sb.append("\n ").append(entry.getKey()).append(": ").append(entry.getValue()) - .append(", Age: ").append(entry.getValue().age); - } - sb.append("\nmSsidFailureCount:"); - for (Map.Entry<String, Pair<AvailableNetworkFailureCount, Integer>> entry : - mSsidFailureCount.entrySet()) { - final AvailableNetworkFailureCount failureCount = entry.getValue().first; - final Integer apCount = entry.getValue().second; - sb.append("\n").append(entry.getKey()).append(": ").append(apCount).append(",") - .append(failureCount.toString()); - } - return sb.toString(); - } - - /** - * @param bssid bssid to check the failures for - * @return true if sum of failure count is over FAILURE_THRESHOLD - */ - public boolean isOverFailureThreshold(String bssid) { - return (getFailureCount(bssid, FAILURE_CODE_ASSOCIATION) - + getFailureCount(bssid, FAILURE_CODE_AUTHENTICATION) - + getFailureCount(bssid, FAILURE_CODE_DHCP)) >= FAILURE_THRESHOLD; - } - - /** - * Get the failure count for a specific bssid. This actually checks the ssid attached to the - * BSSID and returns the SSID count - * @param reason failure reason to get count for - */ - public int getFailureCount(String bssid, int reason) { - AvailableNetworkFailureCount availableNetworkFailureCount = - mRecentAvailableNetworks.get(bssid); - if (availableNetworkFailureCount == null) { - return 0; - } - String ssid = availableNetworkFailureCount.ssid; - Pair<AvailableNetworkFailureCount, Integer> ssidFails = mSsidFailureCount.get(ssid); - if (ssidFails == null) { - Log.d(TAG, "getFailureCount: Could not find SSID count for " + ssid); - return 0; - } - final AvailableNetworkFailureCount failCount = ssidFails.first; - switch (reason) { - case FAILURE_CODE_ASSOCIATION: - return failCount.associationRejection; - case FAILURE_CODE_AUTHENTICATION: - return failCount.authenticationFailure; - case FAILURE_CODE_DHCP: - return failCount.dhcpFailure; - default: - return 0; - } - } - - /** - * Sets whether wifi watchdog should trigger recovery - */ - public void setWifiWatchdogFeature(boolean enable) { - logv("setWifiWatchdogFeature: " + enable); - mWatchdogFeatureEnabled = enable; - // for debugging purpose, reset mWatchdogAllowedToTrigger as well - setWatchdogTriggerEnabled(true); - } - - /** - * Returns whether wifi watchdog should trigger recovery. - */ - public boolean getWifiWatchdogFeature() { - if (mWatchdogFeatureEnabled == null) { - mWatchdogFeatureEnabled = mContext.getResources().getBoolean( - R.bool.config_wifi_watchdog_enabled); - } - return mWatchdogFeatureEnabled; - } - - protected void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mVerboseLoggingEnabled = true; - } else { - mVerboseLoggingEnabled = false; - } - } - - @VisibleForTesting - protected void setBugReportProbability(double newProbability) { - mBugReportProbability = newProbability; - } - - /** - * This class holds the failure counts for an 'available network' (one of the potential - * candidates for connection, as determined by framework). - */ - public static class AvailableNetworkFailureCount { - /** - * WifiConfiguration associated with this network. Can be null for Ephemeral networks - */ - public WifiConfiguration config; - /** - * SSID of the network (from ScanDetail) - */ - public String ssid = ""; - /** - * Number of times network has failed due to Association Rejection - */ - public int associationRejection = 0; - /** - * Number of times network has failed due to Authentication Failure or SSID_TEMP_DISABLED - */ - public int authenticationFailure = 0; - /** - * Number of times network has failed due to DHCP failure - */ - public int dhcpFailure = 0; - /** - * Number of scanResults since this network was last seen - */ - public int age = 0; - - AvailableNetworkFailureCount(WifiConfiguration configParam) { - this.config = configParam; - } - - /** - * @param reason failure reason to increment count for - */ - public void incrementFailureCount(int reason) { - switch (reason) { - case FAILURE_CODE_ASSOCIATION: - associationRejection++; - break; - case FAILURE_CODE_AUTHENTICATION: - authenticationFailure++; - break; - case FAILURE_CODE_DHCP: - dhcpFailure++; - break; - default: //do nothing - } - } - - /** - * Set all failure counts for this network to 0 - */ - void resetCounts() { - associationRejection = 0; - authenticationFailure = 0; - dhcpFailure = 0; - } - - public String toString() { - return ssid + " HasEverConnected: " + ((config != null) - ? config.getNetworkSelectionStatus().hasEverConnected() : "null_config") - + ", Failures: {" - + "Assoc: " + associationRejection - + ", Auth: " + authenticationFailure - + ", Dhcp: " + dhcpFailure - + "}"; - } - } - - /** - * Helper function for logging into local log buffer. - */ - private void localLog(String s) { - mLocalLog.log(s); - } - - private void logv(String s) { - mLocalLog.log(s); - if (mVerboseLoggingEnabled) { - Log.v(TAG, s); - } - } - - private void loge(String s) { - mLocalLog.log(s); - Log.e(TAG, s); - } - - /** - * Dump the local log buffer and other internal state of WifiLastResortWatchdog. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WifiLastResortWatchdog"); - pw.println("WifiLastResortWatchdog - Log Begin ----"); - mLocalLog.dump(fd, pw, args); - pw.println("WifiLastResortWatchdog - Log End ----"); - } -} diff --git a/service/java/com/android/server/wifi/WifiLinkLayerStats.java b/service/java/com/android/server/wifi/WifiLinkLayerStats.java deleted file mode 100644 index 898b1313d..000000000 --- a/service/java/com/android/server/wifi/WifiLinkLayerStats.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2014 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.server.wifi; - -import android.util.SparseArray; - -import java.util.Arrays; - -/** - * A class representing link layer statistics collected over a Wifi Interface. - */ - -/** - * {@hide} - */ -public class WifiLinkLayerStats { - public static final String V1_0 = "V1_0"; - public static final String V1_3 = "V1_3"; - - /** The version of hal StaLinkLayerStats **/ - public String version; - - /** Number of beacons received from our own AP */ - public int beacon_rx; - - /** RSSI of management frames */ - public int rssi_mgmt; - - /* Packet counters */ - - /** WME Best Effort Access Category received mpdu */ - public long rxmpdu_be; - /** WME Best Effort Access Category transmitted mpdu */ - public long txmpdu_be; - /** WME Best Effort Access Category lost mpdu */ - public long lostmpdu_be; - /** WME Best Effort Access Category number of transmission retries */ - public long retries_be; - - /** WME Background Access Category received mpdu */ - public long rxmpdu_bk; - /** WME Background Access Category transmitted mpdu */ - public long txmpdu_bk; - /** WME Background Access Category lost mpdu */ - public long lostmpdu_bk; - /** WME Background Access Category number of transmission retries */ - public long retries_bk; - - /** WME Video Access Category received mpdu */ - public long rxmpdu_vi; - /** WME Video Access Category transmitted mpdu */ - public long txmpdu_vi; - /** WME Video Access Category lost mpdu */ - public long lostmpdu_vi; - /** WME Video Access Category number of transmission retries */ - public long retries_vi; - - /** WME Voice Access Category received mpdu */ - public long rxmpdu_vo; - /** WME Voice Access Category transmitted mpdu */ - public long txmpdu_vo; - /** WME Voice Access Category lost mpdu */ - public long lostmpdu_vo; - /** WME Voice Access Category number of transmission retries */ - public long retries_vo; - - /** - * Cumulative milliseconds when radio is awake - */ - public int on_time; - /** - * Cumulative milliseconds of active transmission - */ - public int tx_time; - /** - * Cumulative milliseconds per level of active transmission - */ - public int[] tx_time_per_level; - /** - * Cumulative milliseconds of active receive - */ - public int rx_time; - /** - * Cumulative milliseconds when radio is awake due to scan - */ - public int on_time_scan; - /** - * Cumulative milliseconds when radio is awake due to nan scan - */ - public int on_time_nan_scan = -1; - /** - * Cumulative milliseconds when radio is awake due to background scan - */ - public int on_time_background_scan = -1; - /** - * Cumulative milliseconds when radio is awake due to roam scan - */ - public int on_time_roam_scan = -1; - /** - * Cumulative milliseconds when radio is awake due to pno scan - */ - public int on_time_pno_scan = -1; - /** - * Cumulative milliseconds when radio is awake due to hotspot 2.0 scan amd GAS exchange - */ - public int on_time_hs20_scan = -1; - /** - * channel stats - */ - public static class ChannelStats { - /** - * Channel frequency in MHz; - */ - public int frequency; - /** - * Cumulative milliseconds radio is awake on this channel - */ - public int radioOnTimeMs; - /** - * Cumulative milliseconds CCA is held busy on this channel - */ - public int ccaBusyTimeMs; - } - /** - * Channel stats list - */ - public final SparseArray<ChannelStats> channelStatsMap = new SparseArray<>(); - - /** - * TimeStamp - absolute milliseconds from boot when these stats were sampled. - */ - public long timeStampInMs; - - @Override - public String toString() { - StringBuilder sbuf = new StringBuilder(); - sbuf.append(" WifiLinkLayerStats: ").append('\n'); - - sbuf.append(" version of StaLinkLayerStats: ").append(version).append('\n'); - sbuf.append(" my bss beacon rx: ").append(Integer.toString(this.beacon_rx)).append('\n'); - sbuf.append(" RSSI mgmt: ").append(Integer.toString(this.rssi_mgmt)).append('\n'); - sbuf.append(" BE : ").append(" rx=").append(Long.toString(this.rxmpdu_be)) - .append(" tx=").append(Long.toString(this.txmpdu_be)) - .append(" lost=").append(Long.toString(this.lostmpdu_be)) - .append(" retries=").append(Long.toString(this.retries_be)).append('\n'); - sbuf.append(" BK : ").append(" rx=").append(Long.toString(this.rxmpdu_bk)) - .append(" tx=").append(Long.toString(this.txmpdu_bk)) - .append(" lost=").append(Long.toString(this.lostmpdu_bk)) - .append(" retries=").append(Long.toString(this.retries_bk)).append('\n'); - sbuf.append(" VI : ").append(" rx=").append(Long.toString(this.rxmpdu_vi)) - .append(" tx=").append(Long.toString(this.txmpdu_vi)) - .append(" lost=").append(Long.toString(this.lostmpdu_vi)) - .append(" retries=").append(Long.toString(this.retries_vi)).append('\n'); - sbuf.append(" VO : ").append(" rx=").append(Long.toString(this.rxmpdu_vo)) - .append(" tx=").append(Long.toString(this.txmpdu_vo)) - .append(" lost=").append(Long.toString(this.lostmpdu_vo)) - .append(" retries=").append(Long.toString(this.retries_vo)).append('\n'); - sbuf.append(" on_time : ").append(Integer.toString(this.on_time)) - .append(" tx_time=").append(Integer.toString(this.tx_time)) - .append(" rx_time=").append(Integer.toString(this.rx_time)) - .append(" scan_time=").append(Integer.toString(this.on_time_scan)).append('\n') - .append(" nan_scan_time=") - .append(Integer.toString(this.on_time_nan_scan)).append('\n') - .append(" g_scan_time=") - .append(Integer.toString(this.on_time_background_scan)).append('\n') - .append(" roam_scan_time=") - .append(Integer.toString(this.on_time_roam_scan)).append('\n') - .append(" pno_scan_time=") - .append(Integer.toString(this.on_time_pno_scan)).append('\n') - .append(" hs2.0_scan_time=") - .append(Integer.toString(this.on_time_hs20_scan)).append('\n') - .append(" tx_time_per_level=" + Arrays.toString(tx_time_per_level)).append('\n'); - int numChanStats = this.channelStatsMap.size(); - sbuf.append(" Number of channel stats=").append(numChanStats).append('\n'); - for (int i = 0; i < numChanStats; ++i) { - ChannelStats channelStatsEntry = this.channelStatsMap.valueAt(i); - sbuf.append(" Frequency=").append(channelStatsEntry.frequency) - .append(" radioOnTimeMs=").append(channelStatsEntry.radioOnTimeMs) - .append(" ccaBusyTimeMs=").append(channelStatsEntry.ccaBusyTimeMs).append('\n'); - } - sbuf.append(" ts=" + timeStampInMs); - return sbuf.toString(); - } - -} diff --git a/service/java/com/android/server/wifi/WifiLockManager.java b/service/java/com/android/server/wifi/WifiLockManager.java deleted file mode 100644 index 7cbeea0d3..000000000 --- a/service/java/com/android/server/wifi/WifiLockManager.java +++ /dev/null @@ -1,857 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.app.ActivityManager; -import android.content.Context; -import android.net.wifi.WifiManager; -import android.os.BatteryStatsManager; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.WorkSource; -import android.os.WorkSource.WorkChain; -import android.util.Log; -import android.util.Pair; -import android.util.SparseArray; - -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.util.WorkSourceUtil; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * WifiLockManager maintains the list of wake locks held by different applications. - */ -public class WifiLockManager { - private static final String TAG = "WifiLockManager"; - - private static final int LOW_LATENCY_SUPPORT_UNDEFINED = -1; - private static final int LOW_LATENCY_NOT_SUPPORTED = 0; - private static final int LOW_LATENCY_SUPPORTED = 1; - - private static final int IGNORE_SCREEN_STATE_MASK = 0x01; - private static final int IGNORE_WIFI_STATE_MASK = 0x02; - - private int mLatencyModeSupport = LOW_LATENCY_SUPPORT_UNDEFINED; - - private boolean mVerboseLoggingEnabled = false; - - private final Clock mClock; - private final Context mContext; - private final BatteryStatsManager mBatteryStats; - private final FrameworkFacade mFrameworkFacade; - private final ClientModeImpl mClientModeImpl; - private final ActivityManager mActivityManager; - private final Handler mHandler; - private final WifiMetrics mWifiMetrics; - private final WifiNative mWifiNative; - - private final List<WifiLock> mWifiLocks = new ArrayList<>(); - // map UIDs to their corresponding records (for low-latency locks) - private final SparseArray<UidRec> mLowLatencyUidWatchList = new SparseArray<>(); - private int mCurrentOpMode; - private boolean mScreenOn = false; - private boolean mWifiConnected = false; - - // For shell command support - private boolean mForceHiPerfMode = false; - private boolean mForceLowLatencyMode = false; - - // some wifi lock statistics - private int mFullHighPerfLocksAcquired; - private int mFullHighPerfLocksReleased; - private int mFullLowLatencyLocksAcquired; - private int mFullLowLatencyLocksReleased; - private long mCurrentSessionStartTimeMs; - - WifiLockManager(Context context, BatteryStatsManager batteryStats, - ClientModeImpl clientModeImpl, FrameworkFacade frameworkFacade, Handler handler, - WifiNative wifiNative, Clock clock, WifiMetrics wifiMetrics) { - mContext = context; - mBatteryStats = batteryStats; - mClientModeImpl = clientModeImpl; - mFrameworkFacade = frameworkFacade; - mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - mCurrentOpMode = WifiManager.WIFI_MODE_NO_LOCKS_HELD; - mWifiNative = wifiNative; - mHandler = handler; - mClock = clock; - mWifiMetrics = wifiMetrics; - - // Register for UID fg/bg transitions - registerUidImportanceTransitions(); - } - - // Check for conditions to activate high-perf lock - private boolean canActivateHighPerfLock(int ignoreMask) { - boolean check = true; - - // Only condition is when Wifi is connected - if ((ignoreMask & IGNORE_WIFI_STATE_MASK) == 0) { - check = check && mWifiConnected; - } - - return check; - } - - private boolean canActivateHighPerfLock() { - return canActivateHighPerfLock(0); - } - - // Check for conditions to activate low-latency lock - private boolean canActivateLowLatencyLock(int ignoreMask, UidRec uidRec) { - boolean check = true; - - if ((ignoreMask & IGNORE_WIFI_STATE_MASK) == 0) { - check = check && mWifiConnected; - } - if ((ignoreMask & IGNORE_SCREEN_STATE_MASK) == 0) { - check = check && mScreenOn; - } - if (uidRec != null) { - check = check && uidRec.mIsFg; - } - - return check; - } - - private boolean canActivateLowLatencyLock(int ignoreMask) { - return canActivateLowLatencyLock(ignoreMask, null); - } - - private boolean canActivateLowLatencyLock() { - return canActivateLowLatencyLock(0, null); - } - - // Detect UIDs going foreground/background - private void registerUidImportanceTransitions() { - mActivityManager.addOnUidImportanceListener(new ActivityManager.OnUidImportanceListener() { - @Override - public void onUidImportance(final int uid, final int importance) { - mHandler.post(() -> { - UidRec uidRec = mLowLatencyUidWatchList.get(uid); - if (uidRec == null) { - // Not a uid in the watch list - return; - } - - boolean newModeIsFg = (importance - == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); - if (uidRec.mIsFg == newModeIsFg) { - return; // already at correct state - } - - uidRec.mIsFg = newModeIsFg; - updateOpMode(); - - // If conditions for lock activation are met, - // then UID either share the blame, or removed from sharing - // whether to start or stop the blame based on UID fg/bg state - if (canActivateLowLatencyLock()) { - setBlameLowLatencyUid(uid, uidRec.mIsFg); - } - }); - } - }, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE); - } - - /** - * Method allowing a calling app to acquire a Wifi WakeLock in the supplied mode. - * - * This method checks that the lock mode is a valid WifiLock mode. - * @param lockMode int representation of the Wifi WakeLock type. - * @param tag String passed to WifiManager.WifiLock - * @param binder IBinder for the calling app - * @param ws WorkSource of the calling app - * - * @return true if the lock was successfully acquired, false if the lockMode was invalid. - */ - public boolean acquireWifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) { - // Make a copy of the WorkSource before adding it to the WakeLock - // This is to make sure worksource value can not be changed by caller - // after function returns. - WorkSource newWorkSource = new WorkSource(ws); - return addLock(new WifiLock(lockMode, tag, binder, newWorkSource)); - } - - /** - * Method used by applications to release a WiFi Wake lock. - * - * @param binder IBinder for the calling app. - * @return true if the lock was released, false if the caller did not hold any locks - */ - public boolean releaseWifiLock(IBinder binder) { - return releaseLock(binder); - } - - /** - * Method used to get the strongest lock type currently held by the WifiLockManager. - * - * If no locks are held, WifiManager.WIFI_MODE_NO_LOCKS_HELD is returned. - * - * @return int representing the currently held (highest power consumption) lock. - */ - public synchronized int getStrongestLockMode() { - // If Wifi Client is not connected, then all locks are not effective - if (!mWifiConnected) { - return WifiManager.WIFI_MODE_NO_LOCKS_HELD; - } - - // Check if mode is forced to hi-perf - if (mForceHiPerfMode) { - return WifiManager.WIFI_MODE_FULL_HIGH_PERF; - } - - // Check if mode is forced to low-latency - if (mForceLowLatencyMode) { - return WifiManager.WIFI_MODE_FULL_LOW_LATENCY; - } - - if (mScreenOn && countFgLowLatencyUids() > 0) { - return WifiManager.WIFI_MODE_FULL_LOW_LATENCY; - } - - if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) { - return WifiManager.WIFI_MODE_FULL_HIGH_PERF; - } - - return WifiManager.WIFI_MODE_NO_LOCKS_HELD; - } - - /** - * Method to create a WorkSource containing all active WifiLock WorkSources. - */ - public synchronized WorkSource createMergedWorkSource() { - WorkSource mergedWS = new WorkSource(); - for (WifiLock lock : mWifiLocks) { - mergedWS.add(lock.getWorkSource()); - } - return mergedWS; - } - - /** - * Method used to update WifiLocks with a new WorkSouce. - * - * @param binder IBinder for the calling application. - * @param ws WorkSource to add to the existing WifiLock(s). - */ - public synchronized void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { - - // Now check if there is an active lock - WifiLock wl = findLockByBinder(binder); - if (wl == null) { - throw new IllegalArgumentException("Wifi lock not active"); - } - - // Make a copy of the WorkSource before adding it to the WakeLock - // This is to make sure worksource value can not be changed by caller - // after function returns. - WorkSource newWorkSource = new WorkSource(ws); - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "updateWifiLockWakeSource: " + wl + ", newWorkSource=" + newWorkSource); - } - - // Note: - // Log the acquire before the release to avoid "holes" in the collected data due to - // an acquire event immediately after a release in the case where newWorkSource and - // wl.mWorkSource share one or more attribution UIDs. Both batteryStats and statsd - // can correctly match "nested" acquire / release pairs. - switch(wl.mMode) { - case WifiManager.WIFI_MODE_FULL_HIGH_PERF: - // Shift blame to new worksource if needed - if (canActivateHighPerfLock()) { - setBlameHiPerfWs(newWorkSource, true); - setBlameHiPerfWs(wl.mWorkSource, false); - } - break; - case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: - addWsToLlWatchList(newWorkSource); - removeWsFromLlWatchList(wl.mWorkSource); - updateOpMode(); - break; - default: - // Do nothing - break; - } - - wl.mWorkSource = newWorkSource; - } - - /** - * Method Used for shell command support - * - * @param isEnabled True to force hi-perf mode, false to leave it up to acquired wifiLocks. - * @return True for success, false for failure (failure turns forcing mode off) - */ - public boolean forceHiPerfMode(boolean isEnabled) { - mForceHiPerfMode = isEnabled; - mForceLowLatencyMode = false; - if (!updateOpMode()) { - Log.e(TAG, "Failed to force hi-perf mode, returning to normal mode"); - mForceHiPerfMode = false; - return false; - } - return true; - } - - /** - * Method Used for shell command support - * - * @param isEnabled True to force low-latency mode, false to leave it up to acquired wifiLocks. - * @return True for success, false for failure (failure turns forcing mode off) - */ - public boolean forceLowLatencyMode(boolean isEnabled) { - mForceLowLatencyMode = isEnabled; - mForceHiPerfMode = false; - if (!updateOpMode()) { - Log.e(TAG, "Failed to force low-latency mode, returning to normal mode"); - mForceLowLatencyMode = false; - return false; - } - return true; - } - - /** - * Handler for screen state (on/off) changes - */ - public void handleScreenStateChanged(boolean screenOn) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "handleScreenStateChanged: screenOn = " + screenOn); - } - - mScreenOn = screenOn; - - if (canActivateLowLatencyLock(IGNORE_SCREEN_STATE_MASK)) { - // Update the running mode - updateOpMode(); - // Adjust blaming for UIDs in foreground - setBlameLowLatencyWatchList(screenOn); - } - } - - /** - * Handler for Wifi Client mode state changes - */ - public void updateWifiClientConnected(boolean isConnected) { - if (mWifiConnected == isConnected) { - // No need to take action - return; - } - mWifiConnected = isConnected; - - // Adjust blaming for UIDs in foreground carrying low latency locks - if (canActivateLowLatencyLock(IGNORE_WIFI_STATE_MASK)) { - setBlameLowLatencyWatchList(mWifiConnected); - } - - // Adjust blaming for UIDs carrying high perf locks - // Note that blaming is adjusted only if needed, - // since calling this API is reference counted - if (canActivateHighPerfLock(IGNORE_WIFI_STATE_MASK)) { - setBlameHiPerfLocks(mWifiConnected); - } - - updateOpMode(); - } - - private void setBlameHiPerfLocks(boolean shouldBlame) { - for (WifiLock lock : mWifiLocks) { - if (lock.mMode == WifiManager.WIFI_MODE_FULL_HIGH_PERF) { - setBlameHiPerfWs(lock.getWorkSource(), shouldBlame); - } - } - } - - /** - * Validate that the lock mode is valid - i.e. one of the supported enumerations. - * - * @param lockMode The lock mode to verify. - * @return true for valid lock modes, false otherwise. - */ - public static boolean isValidLockMode(int lockMode) { - if (lockMode != WifiManager.WIFI_MODE_FULL - && lockMode != WifiManager.WIFI_MODE_SCAN_ONLY - && lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF - && lockMode != WifiManager.WIFI_MODE_FULL_LOW_LATENCY) { - return false; - } - return true; - } - - private void addUidToLlWatchList(int uid) { - UidRec uidRec = mLowLatencyUidWatchList.get(uid); - if (uidRec != null) { - uidRec.mLockCount++; - } else { - uidRec = new UidRec(uid); - uidRec.mLockCount = 1; - mLowLatencyUidWatchList.put(uid, uidRec); - - // Now check if the uid is running in foreground - if (mFrameworkFacade.isAppForeground(mContext, uid)) { - uidRec.mIsFg = true; - } - - if (canActivateLowLatencyLock(0, uidRec)) { - // Share the blame for this uid - setBlameLowLatencyUid(uid, true); - } - } - } - - private void removeUidFromLlWatchList(int uid) { - UidRec uidRec = mLowLatencyUidWatchList.get(uid); - if (uidRec == null) { - Log.e(TAG, "Failed to find uid in low-latency watch list"); - return; - } - - if (uidRec.mLockCount > 0) { - uidRec.mLockCount--; - } else { - Log.e(TAG, "Error, uid record conatains no locks"); - } - if (uidRec.mLockCount == 0) { - mLowLatencyUidWatchList.remove(uid); - - // Remove blame for this UID if it was alerady set - // Note that blame needs to be stopped only if it was started before - // to avoid calling the API unnecessarily, since it is reference counted - if (canActivateLowLatencyLock(0, uidRec)) { - setBlameLowLatencyUid(uid, false); - } - } - } - - private void addWsToLlWatchList(WorkSource ws) { - int wsSize = ws.size(); - for (int i = 0; i < wsSize; i++) { - final int uid = ws.getUid(i); - addUidToLlWatchList(uid); - } - - final List<WorkChain> workChains = ws.getWorkChains(); - if (workChains != null) { - for (int i = 0; i < workChains.size(); ++i) { - final WorkChain workChain = workChains.get(i); - final int uid = workChain.getAttributionUid(); - addUidToLlWatchList(uid); - } - } - } - - private void removeWsFromLlWatchList(WorkSource ws) { - int wsSize = ws.size(); - for (int i = 0; i < wsSize; i++) { - final int uid = ws.getUid(i); - removeUidFromLlWatchList(uid); - } - - final List<WorkChain> workChains = ws.getWorkChains(); - if (workChains != null) { - for (int i = 0; i < workChains.size(); ++i) { - final WorkChain workChain = workChains.get(i); - final int uid = workChain.getAttributionUid(); - removeUidFromLlWatchList(uid); - } - } - } - - private synchronized boolean addLock(WifiLock lock) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "addLock: " + lock); - } - - if (findLockByBinder(lock.getBinder()) != null) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "attempted to add a lock when already holding one"); - } - return false; - } - - mWifiLocks.add(lock); - - switch(lock.mMode) { - case WifiManager.WIFI_MODE_FULL_HIGH_PERF: - ++mFullHighPerfLocksAcquired; - // Start blaming this worksource if conditions are met - if (canActivateHighPerfLock()) { - setBlameHiPerfWs(lock.mWorkSource, true); - } - break; - case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: - addWsToLlWatchList(lock.getWorkSource()); - ++mFullLowLatencyLocksAcquired; - break; - default: - // Do nothing - break; - } - - // Recalculate the operating mode - updateOpMode(); - - return true; - } - - private synchronized WifiLock removeLock(IBinder binder) { - WifiLock lock = findLockByBinder(binder); - if (lock != null) { - mWifiLocks.remove(lock); - lock.unlinkDeathRecipient(); - } - return lock; - } - - private synchronized boolean releaseLock(IBinder binder) { - WifiLock wifiLock = removeLock(binder); - if (wifiLock == null) { - // attempting to release a lock that does not exist. - return false; - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "releaseLock: " + wifiLock); - } - - switch(wifiLock.mMode) { - case WifiManager.WIFI_MODE_FULL_HIGH_PERF: - ++mFullHighPerfLocksReleased; - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mClock.getElapsedSinceBootMillis() - wifiLock.getAcqTimestamp()); - // Stop blaming only if blaming was set before (conditions are met). - // This is to avoid calling the api unncessarily, since this API is - // reference counted in batteryStats and statsd - if (canActivateHighPerfLock()) { - setBlameHiPerfWs(wifiLock.mWorkSource, false); - } - break; - case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: - removeWsFromLlWatchList(wifiLock.getWorkSource()); - ++mFullLowLatencyLocksReleased; - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mClock.getElapsedSinceBootMillis() - wifiLock.getAcqTimestamp()); - break; - default: - // Do nothing - break; - } - - // Recalculate the operating mode - updateOpMode(); - - return true; - } - - private synchronized boolean updateOpMode() { - final int newLockMode = getStrongestLockMode(); - - if (newLockMode == mCurrentOpMode) { - // No action is needed - return true; - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Current opMode: " + mCurrentOpMode + " New LockMode: " + newLockMode); - } - - // Otherwise, we need to change current mode, first reset it to normal - switch (mCurrentOpMode) { - case WifiManager.WIFI_MODE_FULL_HIGH_PERF: - if (!mClientModeImpl.setPowerSave(true)) { - Log.e(TAG, "Failed to reset the OpMode from hi-perf to Normal"); - return false; - } - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mClock.getElapsedSinceBootMillis() - mCurrentSessionStartTimeMs); - break; - - case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: - if (!setLowLatencyMode(false)) { - Log.e(TAG, "Failed to reset the OpMode from low-latency to Normal"); - return false; - } - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mClock.getElapsedSinceBootMillis() - mCurrentSessionStartTimeMs); - break; - - case WifiManager.WIFI_MODE_NO_LOCKS_HELD: - default: - // No action - break; - } - - // Set the current mode, before we attempt to set the new mode - mCurrentOpMode = WifiManager.WIFI_MODE_NO_LOCKS_HELD; - - // Now switch to the new opMode - switch (newLockMode) { - case WifiManager.WIFI_MODE_FULL_HIGH_PERF: - if (!mClientModeImpl.setPowerSave(false)) { - Log.e(TAG, "Failed to set the OpMode to hi-perf"); - return false; - } - mCurrentSessionStartTimeMs = mClock.getElapsedSinceBootMillis(); - break; - - case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: - if (!setLowLatencyMode(true)) { - Log.e(TAG, "Failed to set the OpMode to low-latency"); - return false; - } - mCurrentSessionStartTimeMs = mClock.getElapsedSinceBootMillis(); - break; - - case WifiManager.WIFI_MODE_NO_LOCKS_HELD: - // No action - break; - - default: - // Invalid mode, don't change currentOpMode , and exit with error - Log.e(TAG, "Invalid new opMode: " + newLockMode); - return false; - } - - // Now set the mode to the new value - mCurrentOpMode = newLockMode; - return true; - } - - private int getLowLatencyModeSupport() { - if (mLatencyModeSupport == LOW_LATENCY_SUPPORT_UNDEFINED) { - String ifaceName = mWifiNative.getClientInterfaceName(); - if (ifaceName == null) { - return LOW_LATENCY_SUPPORT_UNDEFINED; - } - - long supportedFeatures = mWifiNative.getSupportedFeatureSet(ifaceName); - if (supportedFeatures != 0) { - if ((supportedFeatures & WifiManager.WIFI_FEATURE_LOW_LATENCY) != 0) { - mLatencyModeSupport = LOW_LATENCY_SUPPORTED; - } else { - mLatencyModeSupport = LOW_LATENCY_NOT_SUPPORTED; - } - } - } - - return mLatencyModeSupport; - } - - private boolean setLowLatencyMode(boolean enabled) { - int lowLatencySupport = getLowLatencyModeSupport(); - - if (lowLatencySupport == LOW_LATENCY_SUPPORT_UNDEFINED) { - // Support undefined, no action is taken - return false; - } - - if (lowLatencySupport == LOW_LATENCY_SUPPORTED) { - if (!mClientModeImpl.setLowLatencyMode(enabled)) { - Log.e(TAG, "Failed to set low latency mode"); - return false; - } - - if (!mClientModeImpl.setPowerSave(!enabled)) { - Log.e(TAG, "Failed to set power save mode"); - // Revert the low latency mode - mClientModeImpl.setLowLatencyMode(!enabled); - return false; - } - } else if (lowLatencySupport == LOW_LATENCY_NOT_SUPPORTED) { - // Only set power save mode - if (!mClientModeImpl.setPowerSave(!enabled)) { - Log.e(TAG, "Failed to set power save mode"); - return false; - } - } - - return true; - } - - private synchronized WifiLock findLockByBinder(IBinder binder) { - for (WifiLock lock : mWifiLocks) { - if (lock.getBinder() == binder) { - return lock; - } - } - return null; - } - - private int countFgLowLatencyUids() { - int uidCount = 0; - int listSize = mLowLatencyUidWatchList.size(); - for (int idx = 0; idx < listSize; idx++) { - UidRec uidRec = mLowLatencyUidWatchList.valueAt(idx); - if (uidRec.mIsFg) { - uidCount++; - } - } - return uidCount; - } - - private void setBlameHiPerfWs(WorkSource ws, boolean shouldBlame) { - long ident = Binder.clearCallingIdentity(); - Pair<int[], String[]> uidsAndTags = WorkSourceUtil.getUidsAndTagsForWs(ws); - try { - if (shouldBlame) { - mBatteryStats.reportFullWifiLockAcquiredFromSource(ws); - WifiStatsLog.write(WifiStatsLog.WIFI_LOCK_STATE_CHANGED, - uidsAndTags.first, uidsAndTags.second, - WifiStatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON, - WifiStatsLog.WIFI_LOCK_STATE_CHANGED__MODE__WIFI_MODE_FULL_HIGH_PERF); - } else { - mBatteryStats.reportFullWifiLockReleasedFromSource(ws); - WifiStatsLog.write(WifiStatsLog.WIFI_LOCK_STATE_CHANGED, - uidsAndTags.first, uidsAndTags.second, - WifiStatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF, - WifiStatsLog.WIFI_LOCK_STATE_CHANGED__MODE__WIFI_MODE_FULL_HIGH_PERF); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private void setBlameLowLatencyUid(int uid, boolean shouldBlame) { - long ident = Binder.clearCallingIdentity(); - try { - if (shouldBlame) { - mBatteryStats.reportFullWifiLockAcquiredFromSource(new WorkSource(uid)); - WifiStatsLog.write_non_chained(WifiStatsLog.WIFI_LOCK_STATE_CHANGED, uid, null, - WifiStatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON, - WifiStatsLog.WIFI_LOCK_STATE_CHANGED__MODE__WIFI_MODE_FULL_LOW_LATENCY); - } else { - mBatteryStats.reportFullWifiLockReleasedFromSource(new WorkSource(uid)); - WifiStatsLog.write_non_chained(WifiStatsLog.WIFI_LOCK_STATE_CHANGED, uid, null, - WifiStatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF, - WifiStatsLog.WIFI_LOCK_STATE_CHANGED__MODE__WIFI_MODE_FULL_LOW_LATENCY); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private void setBlameLowLatencyWatchList(boolean shouldBlame) { - for (int idx = 0; idx < mLowLatencyUidWatchList.size(); idx++) { - UidRec uidRec = mLowLatencyUidWatchList.valueAt(idx); - // Affect the blame for only UIDs running in foreground - // UIDs running in the background are already not blamed, - // and they should remain in that state. - if (uidRec.mIsFg) { - setBlameLowLatencyUid(uidRec.mUid, shouldBlame); - } - } - } - - protected void dump(PrintWriter pw) { - pw.println("Locks acquired: " - + mFullHighPerfLocksAcquired + " full high perf, " - + mFullLowLatencyLocksAcquired + " full low latency"); - pw.println("Locks released: " - + mFullHighPerfLocksReleased + " full high perf, " - + mFullLowLatencyLocksReleased + " full low latency"); - - pw.println(); - pw.println("Locks held:"); - for (WifiLock lock : mWifiLocks) { - pw.print(" "); - pw.println(lock); - } - } - - protected void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mVerboseLoggingEnabled = true; - } else { - mVerboseLoggingEnabled = false; - } - } - - private class WifiLock implements IBinder.DeathRecipient { - String mTag; - int mUid; - IBinder mBinder; - int mMode; - WorkSource mWorkSource; - long mAcqTimestamp; - - WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) { - mTag = tag; - mBinder = binder; - mUid = Binder.getCallingUid(); - mMode = lockMode; - mWorkSource = ws; - mAcqTimestamp = mClock.getElapsedSinceBootMillis(); - try { - mBinder.linkToDeath(this, 0); - } catch (RemoteException e) { - Log.e(TAG, "mBinder.linkToDeath failed: " + e.getMessage()); - binderDied(); - } - } - - protected WorkSource getWorkSource() { - return mWorkSource; - } - - protected int getUid() { - return mUid; - } - - protected IBinder getBinder() { - return mBinder; - } - - protected long getAcqTimestamp() { - return mAcqTimestamp; - } - - public void binderDied() { - releaseLock(mBinder); - } - - public void unlinkDeathRecipient() { - try { - mBinder.unlinkToDeath(this, 0); - } catch (NoSuchElementException e) { - Log.e(TAG, "mBinder.unlinkToDeath failed: " + e.getMessage()); - } - } - - public String toString() { - return "WifiLock{" + this.mTag + " type=" + this.mMode + " uid=" + mUid - + " workSource=" + mWorkSource + "}"; - } - } - - private class UidRec { - final int mUid; - // Count of locks owned or co-owned by this UID - int mLockCount; - // Is this UID running in foreground - boolean mIsFg; - - UidRec(int uid) { - mUid = uid; - } - } -} diff --git a/service/java/com/android/server/wifi/WifiLog.java b/service/java/com/android/server/wifi/WifiLog.java deleted file mode 100644 index 8d345d648..000000000 --- a/service/java/com/android/server/wifi/WifiLog.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.annotation.NonNull; - -import com.google.errorprone.annotations.CompileTimeConstant; - -import javax.annotation.CheckReturnValue; - -/** - * Provides an abstraction of logging back-ends. - * - * The abstraction is designed to - * a) minimize the cost of disabled log messages, - * b) allow callers to tag message parameters as containing sensitive - * information, - * c) avoid the use of format codes, and - * d) easily support additional data types. - * - * Implementations of WifiLog may or may not be thread-safe. - * Implementations of LogMessage are expected _not_ to be thread-safe, - * as LogMessage instances are not expected to be shared between threads. - */ -@SuppressWarnings("NonFinalCompileTimeConstant") // See below. -public interface WifiLog { - // Explanation of SuppressWarnings above: - // - // We use @CompileTimeConstant to verify that our callers do not stringify - // arguments into the |format| parameter. And, by default, error-prone - // requires that CompileTimeConstant parameters are declared final. - // - // However, declaring an interface parameter as final has no effect, since - // classes implementing the interface are free to declare their parameters - // as non-final. Moreover, to avoid such confusing situations (interface says - // final, implementation does not), checkstyle rejects |final| qualification - // of method parameters in interface methods. - // - // To avoid making empty promises. we override error-prone's default behavior, - // and allow the CompileTimeConstant parameters to be non-final. - - char PLACEHOLDER = '%'; - - // New-style API. - /** - * Allocate an error-level log message, which the caller will fill with - * additional parameters according to |format|. After filling the message - * with parameters, the caller must call flush(), to actually log the message. - * - * Error-level messages should be used when a malfunction has occurred, - * and the malfunction is likely to cause an externally visible problem. - * For example: we failed to initialize the Wifi interface. - * - * Typical usage is as follows: - * WifiDevice() { - * mLog = new LogcatLog("ModuleName"); - * } - * - * void start() { - * // ... - * mLog.err("error % while starting interface %").c(errNum).c(ifaceName).flush(); - * } - * - * void stop() { - * // ... - * mLog.err("error % while stopping interface %").c(errNum).c(ifaceName).flush(); - * } - */ - @CheckReturnValue - @NonNull - LogMessage err(@CompileTimeConstant @NonNull String format); - - /** - * Like {@link #err(String) err()}, except that a warning-level message is - * allocated. - * - * Warning-level messages should be used when a malfunction has occurred, - * but the malfunction is _unlikely_ to cause an externally visible problem - * on its own. For example: if we fail to start the debugging subsystem. - */ - @CheckReturnValue - @NonNull - LogMessage warn(@CompileTimeConstant @NonNull String format); - - /** - * Like {@link #err(String) err()}, except that a info-level message is - * allocated. - * - * Info-level messages should be used to report progress or status messages - * that help understand the program's external behavior. For example: we - * might log an info message before initiating a Wifi association. - */ - @CheckReturnValue - @NonNull - LogMessage info(@CompileTimeConstant @NonNull String format); - - /** - * Like {@link #err(String) err()}, except: - * - a trace-level message is allocated - * - the log message is prefixed with the caller's name - * - * Trace-level messages should be used to report progress or status messages - * that help understand the program's internal behavior. For example: - * "invoked with verbose=%". - */ - @CheckReturnValue - @NonNull - LogMessage trace(@CompileTimeConstant @NonNull String format); - - /** - * Like {@link #trace(String) trace(String)}, except that, rather than logging - * the immediate caller, the |numFramesToIgnore + 1|-th caller will be logged. - * - * E.g. if numFramesToIgnore == 1, then the caller's caller will be logged. - * - * Trace-level messages should be used to report progress or status messages - * that help understand the program's internal behavior. For example: - * "invoked with verbose=%". - */ - @CheckReturnValue - @NonNull - LogMessage trace(@NonNull String format, int numFramesToIgnore); - - /** - * Like {@link #err(String) err()}, except that a dump-level message is - * allocated. - * - * Dump-level messages should be used to report detailed internal state. - */ - @CheckReturnValue - @NonNull - LogMessage dump(@CompileTimeConstant @NonNull String format); - - /** - * Log a warning using the default tag for this WifiLog instance. Mark - * the message as 'clean' (i.e. _not_ containing any sensitive data). - * - * NOTE: this method should only be used for literal strings. For messages with - * parameters, use err(). - * - * @param msg the message to be logged - */ - void eC(@CompileTimeConstant String msg); - - /** - * Like {@link #eC(String)} eC()}, except that a warning-level message - * is logged. - */ - void wC(@CompileTimeConstant String msg); - - /** - * Like {@link #eC(String)} eC()}, except that an info-level message - * is logged. - */ - void iC(@CompileTimeConstant String msg); - - /** - * Like {@link #eC(String)} eC()}, except that a trace-level message - * is logged. - */ - void tC(@CompileTimeConstant String msg); - - /** - * Note: dC() is deliberately omitted, as "dumping" is inherently at - * odds with the intention that the caller pass in a literal string. - */ - - /** - * Represents a single log message. - * - * Implementations are expected _not_ to be thread-safe. - */ - interface LogMessage { - /** - * Replace the first available placeholder in this LogMessage's format - * with the specified value. Mark the value as 'raw', to inform the - * logging daemon that the value may contain sensitive data. - * - * @return |this|, to allow chaining of calls - */ - @CheckReturnValue - @NonNull - LogMessage r(String value); - - /** - * Like {@link #r(String) r()}, except that the value is marked - * as 'clean', to inform the logging daemon that the value does _not_ - * contain sensitive data. - */ - @CheckReturnValue - @NonNull - LogMessage c(String value); - - /** - * Like {@link #c(String) c(String)}, except that the value is a long. - */ - @CheckReturnValue - @NonNull - LogMessage c(long value); - - /** - * Like {@link #c(String) c(String)}, except that the value is a char. - */ - @CheckReturnValue - @NonNull - LogMessage c(char value); - - /** - * Like {@link #c(String) c(String)}, except that the value is a boolean. - */ - @CheckReturnValue - @NonNull - LogMessage c(boolean value); - - /** - * Write this LogMessage to the logging daemon. Writing the - * message is best effort. More specifically: - * 1) The operation is non-blocking. If we’re unable to write - * the log message to the IPC channel, the message is - * dropped silently. - * 2) If the number of |value|s provided exceeds the number of - * placeholders in the |format|, then extraneous |value|s - * are silently dropped. - * 3) If the number of placeholders in the |format| exceeds - * the number of |value|s provided, the message is sent to - * the logging daemon without generating an Exception. - * 4) If the total message length exceeds the logging - * protocol’s maximum message length, the message is - * silently truncated. - */ - void flush(); - } - - // Legacy API. - /** - * Log an error using the default tag for this WifiLog instance. - * @param msg the message to be logged - * TODO(b/30736737): Remove this method, once all code has migrated to alternatives. - */ - void e(String msg); - - /** - * Log a warning using the default tag for this WifiLog instance. - * @param msg the message to be logged - * TODO(b/30736737): Remove this method, once all code has migrated to alternatives. - */ - void w(String msg); - - /** - * Log an informational message using the default tag for this WifiLog instance. - * @param msg the message to be logged - * TODO(b/30736737): Remove this method, once all code has migrated to alternatives. - */ - void i(String msg); - - /** - * Log a debug message using the default tag for this WifiLog instance. - * @param msg the message to be logged - * TODO(b/30736737): Remove this method, once all code has migrated to alternatives. - */ - void d(String msg); - - /** - * Log a verbose message using the default tag for this WifiLog instance. - * @param msg the message to be logged - * TODO(b/30736737): Remove this method, once all code has migrated to alternatives. - */ - void v(String msg); -} diff --git a/service/java/com/android/server/wifi/WifiLoggerHal.java b/service/java/com/android/server/wifi/WifiLoggerHal.java deleted file mode 100644 index 5e2635f13..000000000 --- a/service/java/com/android/server/wifi/WifiLoggerHal.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -public class WifiLoggerHal { - // Must match wifi_logger.h - public static final int MAX_FATE_LOG_LEN = 32; - - public static final byte FRAME_TYPE_UNKNOWN = 0; - public static final byte FRAME_TYPE_ETHERNET_II = 1; - public static final byte FRAME_TYPE_80211_MGMT = 2; - - public static final byte TX_PKT_FATE_ACKED = 0; - public static final byte TX_PKT_FATE_SENT = 1; - public static final byte TX_PKT_FATE_FW_QUEUED = 2; - public static final byte TX_PKT_FATE_FW_DROP_INVALID = 3; - public static final byte TX_PKT_FATE_FW_DROP_NOBUFS = 4; - public static final byte TX_PKT_FATE_FW_DROP_OTHER = 5; - public static final byte TX_PKT_FATE_DRV_QUEUED = 6; - public static final byte TX_PKT_FATE_DRV_DROP_INVALID = 7; - public static final byte TX_PKT_FATE_DRV_DROP_NOBUFS = 8; - public static final byte TX_PKT_FATE_DRV_DROP_OTHER = 9; - - public static final byte RX_PKT_FATE_SUCCESS = 0; - public static final byte RX_PKT_FATE_FW_QUEUED = 1; - public static final byte RX_PKT_FATE_FW_DROP_FILTER = 2; - public static final byte RX_PKT_FATE_FW_DROP_INVALID = 3; - public static final byte RX_PKT_FATE_FW_DROP_NOBUFS = 4; - public static final byte RX_PKT_FATE_FW_DROP_OTHER = 5; - public static final byte RX_PKT_FATE_DRV_QUEUED = 6; - public static final byte RX_PKT_FATE_DRV_DROP_FILTER = 7; - public static final byte RX_PKT_FATE_DRV_DROP_INVALID = 8; - public static final byte RX_PKT_FATE_DRV_DROP_NOBUFS = 9; - public static final byte RX_PKT_FATE_DRV_DROP_OTHER = 10; - - /** These aren't formally part of the HAL. But they probably should be, eventually. */ - public static final int WIFI_ALERT_REASON_RESERVED = 0; - public static final int WIFI_ALERT_REASON_MIN = 0; - public static final int WIFI_ALERT_REASON_MAX = 1024; -} diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java deleted file mode 100644 index 75d53fc95..000000000 --- a/service/java/com/android/server/wifi/WifiMetrics.java +++ /dev/null @@ -1,6737 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiConfiguration.MeteredOverride; - -import static java.lang.StrictMath.toIntExact; - -import android.content.Context; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; -import android.net.wifi.EAPConstants; -import android.net.wifi.IOnWifiUsabilityStatsListener; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SupplicantState; -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.WifiManager.DeviceMobilityState; -import android.net.wifi.WifiUsabilityStatsEntry.ProbeStatus; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.ProvisioningCallback; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.os.SystemProperties; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Base64; -import android.util.Log; -import android.util.Pair; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.aware.WifiAwareMetrics; -import com.android.server.wifi.hotspot2.ANQPNetworkKey; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.hotspot2.PasspointMatch; -import com.android.server.wifi.hotspot2.PasspointProvider; -import com.android.server.wifi.hotspot2.Utils; -import com.android.server.wifi.p2p.WifiP2pMetrics; -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.proto.nano.WifiMetricsProto.CarrierWifiMetrics; -import com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.ExperimentValues; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics; -import com.android.server.wifi.proto.nano.WifiMetricsProto.InitPartialScanStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkSpeedCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.MeteredNetworkStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason; -import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions; -import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats.ProvisionFailureCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.PnoScanMetrics; -import com.android.server.wifi.proto.nano.WifiMetricsProto.SoftApConnectedClientsEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.ConfigInfo; -import com.android.server.wifi.proto.nano.WifiMetricsProto.TargetNetworkInfo; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserReactionToApprovalUiEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserReactionToApprovalUiEvent.UserReaction; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiLinkLayerUsageStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiLockStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkRequestApiLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog.SuggestionAppCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiStatus; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToggleStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry; -import com.android.server.wifi.rtt.RttMetrics; -import com.android.server.wifi.scanner.KnownBandsChannelHelper; -import com.android.server.wifi.util.ExternalCallbackTracker; -import com.android.server.wifi.util.InformationElementUtil; -import com.android.server.wifi.util.IntCounter; -import com.android.server.wifi.util.IntHistogram; -import com.android.server.wifi.util.MetricsUtils; -import com.android.server.wifi.util.ObjectCounter; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.wifi.resources.R; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Calendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; - -/** - * Provides storage for wireless connectivity metrics, as they are generated. - * Metrics logged by this class include: - * Aggregated connection stats (num of connections, num of failures, ...) - * Discrete connection event stats (time, duration, failure codes, ...) - * Router details (technology type, authentication type, ...) - * Scan stats - */ -public class WifiMetrics { - private static final String TAG = "WifiMetrics"; - private static final boolean DBG = false; - /** - * Clamp the RSSI poll counts to values between [MIN,MAX]_RSSI_POLL - */ - private static final int MAX_RSSI_POLL = 0; - private static final int MIN_RSSI_POLL = -127; - public static final int MAX_RSSI_DELTA = 127; - public static final int MIN_RSSI_DELTA = -127; - /** Minimum link speed (Mbps) to count for link_speed_counts */ - public static final int MIN_LINK_SPEED_MBPS = 0; - /** Maximum time period between ScanResult and RSSI poll to generate rssi delta datapoint */ - public static final long TIMEOUT_RSSI_DELTA_MILLIS = 3000; - private static final int MIN_WIFI_SCORE = 0; - private static final int MAX_WIFI_SCORE = ConnectedScore.WIFI_MAX_SCORE; - private static final int MIN_WIFI_USABILITY_SCORE = 0; // inclusive - private static final int MAX_WIFI_USABILITY_SCORE = 100; // inclusive - @VisibleForTesting - static final int LOW_WIFI_SCORE = 50; // Mobile data score - @VisibleForTesting - static final int LOW_WIFI_USABILITY_SCORE = 50; // Mobile data score - private final Object mLock = new Object(); - private static final int MAX_CONNECTION_EVENTS = 256; - // Largest bucket in the NumConnectableNetworkCount histogram, - // anything large will be stored in this bucket - public static final int MAX_CONNECTABLE_SSID_NETWORK_BUCKET = 20; - public static final int MAX_CONNECTABLE_BSSID_NETWORK_BUCKET = 50; - public static final int MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET = 100; - public static final int MAX_TOTAL_SCAN_RESULTS_BUCKET = 250; - public static final int MAX_TOTAL_PASSPOINT_APS_BUCKET = 50; - public static final int MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET = 20; - public static final int MAX_PASSPOINT_APS_PER_UNIQUE_ESS_BUCKET = 50; - public static final int MAX_TOTAL_80211MC_APS_BUCKET = 20; - private static final int CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER = 1000; - // Max limit for number of soft AP related events, extra events will be dropped. - private static final int MAX_NUM_SOFT_AP_EVENTS = 256; - // Maximum number of WifiIsUnusableEvent - public static final int MAX_UNUSABLE_EVENTS = 20; - // Minimum time wait before generating next WifiIsUnusableEvent from data stall - public static final int MIN_DATA_STALL_WAIT_MS = 120 * 1000; // 2 minutes - // Max number of WifiUsabilityStatsEntry elements to store in the ringbuffer. - public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE = 40; - // Max number of WifiUsabilityStats elements to store for each type. - public static final int MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE = 10; - // Max number of WifiUsabilityStats per labeled type to upload to server - public static final int MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD = 2; - public static final int NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD = 100; - public static final int MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS = 1000 * 3600; // 1 hour - // Histogram for WifiConfigStore IO duration times. Indicates the following 5 buckets (in ms): - // < 50 - // [50, 100) - // [100, 150) - // [150, 200) - // [200, 300) - // >= 300 - private static final int[] WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS = - {50, 100, 150, 200, 300}; - // Minimum time wait before generating a LABEL_GOOD stats after score breaching low. - public static final int MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS = 60 * 1000; // 1 minute - // Maximum time that a score breaching low event stays valid. - public static final int VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS = 90 * 1000; // 1.5 minutes - - private Clock mClock; - private boolean mScreenOn; - private int mWifiState; - private WifiAwareMetrics mWifiAwareMetrics; - private RttMetrics mRttMetrics; - private final PnoScanMetrics mPnoScanMetrics = new PnoScanMetrics(); - private final WifiLinkLayerUsageStats mWifiLinkLayerUsageStats = new WifiLinkLayerUsageStats(); - private final ExperimentValues mExperimentValues = new ExperimentValues(); - private Handler mHandler; - private ScoringParams mScoringParams; - private WifiConfigManager mWifiConfigManager; - private BssidBlocklistMonitor mBssidBlocklistMonitor; - private WifiNetworkSelector mWifiNetworkSelector; - private PasspointManager mPasspointManager; - private Context mContext; - private FrameworkFacade mFacade; - private WifiDataStall mWifiDataStall; - private WifiLinkLayerStats mLastLinkLayerStats; - private WifiHealthMonitor mWifiHealthMonitor; - private WifiScoreCard mWifiScoreCard; - private String mLastBssid; - private int mLastFrequency = -1; - private int mSeqNumInsideFramework = 0; - private int mLastWifiUsabilityScore = -1; - private int mLastWifiUsabilityScoreNoReset = -1; - private int mLastPredictionHorizonSec = -1; - private int mLastPredictionHorizonSecNoReset = -1; - private int mSeqNumToFramework = -1; - @ProbeStatus private int mProbeStatusSinceLastUpdate = - android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE; - private int mProbeElapsedTimeSinceLastUpdateMs = -1; - private int mProbeMcsRateSinceLastUpdate = -1; - private long mScoreBreachLowTimeMillis = -1; - - public static final int MAX_STA_EVENTS = 768; - @VisibleForTesting static final int MAX_USER_ACTION_EVENTS = 200; - private LinkedList<StaEventWithTime> mStaEventList = new LinkedList<>(); - private LinkedList<UserActionEventWithTime> mUserActionEventList = new LinkedList<>(); - private WifiStatusBuilder mWifiStatusBuilder = new WifiStatusBuilder(); - private int mLastPollRssi = -127; - private int mLastPollLinkSpeed = -1; - private int mLastPollRxLinkSpeed = -1; - private int mLastPollFreq = -1; - private int mLastScore = -1; - private boolean mAdaptiveConnectivityEnabled = true; - - /** - * Metrics are stored within an instance of the WifiLog proto during runtime, - * The ConnectionEvent, SystemStateEntries & ScanReturnEntries metrics are stored during - * runtime in member lists of this WifiMetrics class, with the final WifiLog proto being pieced - * together at dump-time - */ - private final WifiMetricsProto.WifiLog mWifiLogProto = new WifiMetricsProto.WifiLog(); - /** - * Session information that gets logged for every Wifi connection attempt. - */ - private final List<ConnectionEvent> mConnectionEventList = new ArrayList<>(); - /** - * The latest started (but un-ended) connection attempt - */ - private ConnectionEvent mCurrentConnectionEvent; - /** - * Count of number of times each scan return code, indexed by WifiLog.ScanReturnCode - */ - private final SparseIntArray mScanReturnEntries = new SparseIntArray(); - /** - * Mapping of system state to the counts of scans requested in that wifi state * screenOn - * combination. Indexed by WifiLog.WifiState * (1 + screenOn) - */ - private final SparseIntArray mWifiSystemStateEntries = new SparseIntArray(); - /** Mapping of channel frequency to its RSSI distribution histogram **/ - private final Map<Integer, SparseIntArray> mRssiPollCountsMap = new HashMap<>(); - /** Mapping of RSSI scan-poll delta values to counts. */ - private final SparseIntArray mRssiDeltaCounts = new SparseIntArray(); - /** Mapping of link speed values to LinkSpeedCount objects. */ - private final SparseArray<LinkSpeedCount> mLinkSpeedCounts = new SparseArray<>(); - - private final IntCounter mTxLinkSpeedCount2g = new IntCounter(); - private final IntCounter mTxLinkSpeedCount5gLow = new IntCounter(); - private final IntCounter mTxLinkSpeedCount5gMid = new IntCounter(); - private final IntCounter mTxLinkSpeedCount5gHigh = new IntCounter(); - private final IntCounter mTxLinkSpeedCount6gLow = new IntCounter(); - private final IntCounter mTxLinkSpeedCount6gMid = new IntCounter(); - private final IntCounter mTxLinkSpeedCount6gHigh = new IntCounter(); - - private final IntCounter mRxLinkSpeedCount2g = new IntCounter(); - private final IntCounter mRxLinkSpeedCount5gLow = new IntCounter(); - private final IntCounter mRxLinkSpeedCount5gMid = new IntCounter(); - private final IntCounter mRxLinkSpeedCount5gHigh = new IntCounter(); - private final IntCounter mRxLinkSpeedCount6gLow = new IntCounter(); - private final IntCounter mRxLinkSpeedCount6gMid = new IntCounter(); - private final IntCounter mRxLinkSpeedCount6gHigh = new IntCounter(); - - /** RSSI of the scan result for the last connection event*/ - private int mScanResultRssi = 0; - /** Boot-relative timestamp when the last candidate scanresult was received, used to calculate - RSSI deltas. -1 designates no candidate scanResult being tracked */ - private long mScanResultRssiTimestampMillis = -1; - /** Mapping of alert reason to the respective alert count. */ - private final SparseIntArray mWifiAlertReasonCounts = new SparseIntArray(); - /** - * Records the getElapsedSinceBootMillis (in seconds) that represents the beginning of data - * capture for for this WifiMetricsProto - */ - private long mRecordStartTimeSec; - /** Mapping of Wifi Scores to counts */ - private final SparseIntArray mWifiScoreCounts = new SparseIntArray(); - /** Mapping of Wifi Usability Scores to counts */ - private final SparseIntArray mWifiUsabilityScoreCounts = new SparseIntArray(); - /** Mapping of SoftApManager start SoftAp return codes to counts */ - private final SparseIntArray mSoftApManagerReturnCodeCounts = new SparseIntArray(); - - private final SparseIntArray mTotalSsidsInScanHistogram = new SparseIntArray(); - private final SparseIntArray mTotalBssidsInScanHistogram = new SparseIntArray(); - private final SparseIntArray mAvailableOpenSsidsInScanHistogram = new SparseIntArray(); - private final SparseIntArray mAvailableOpenBssidsInScanHistogram = new SparseIntArray(); - private final SparseIntArray mAvailableSavedSsidsInScanHistogram = new SparseIntArray(); - private final SparseIntArray mAvailableSavedBssidsInScanHistogram = new SparseIntArray(); - private final SparseIntArray mAvailableOpenOrSavedSsidsInScanHistogram = new SparseIntArray(); - private final SparseIntArray mAvailableOpenOrSavedBssidsInScanHistogram = new SparseIntArray(); - private final SparseIntArray mAvailableSavedPasspointProviderProfilesInScanHistogram = - new SparseIntArray(); - private final SparseIntArray mAvailableSavedPasspointProviderBssidsInScanHistogram = - new SparseIntArray(); - - private final IntCounter mInstalledPasspointProfileTypeForR1 = new IntCounter(); - private final IntCounter mInstalledPasspointProfileTypeForR2 = new IntCounter(); - - /** Mapping of "Connect to Network" notifications to counts. */ - private final SparseIntArray mConnectToNetworkNotificationCount = new SparseIntArray(); - /** Mapping of "Connect to Network" notification user actions to counts. */ - private final SparseIntArray mConnectToNetworkNotificationActionCount = new SparseIntArray(); - private int mOpenNetworkRecommenderBlacklistSize = 0; - private boolean mIsWifiNetworksAvailableNotificationOn = false; - private int mNumOpenNetworkConnectMessageFailedToSend = 0; - private int mNumOpenNetworkRecommendationUpdates = 0; - /** List of soft AP events related to number of connected clients in tethered mode */ - private final List<SoftApConnectedClientsEvent> mSoftApEventListTethered = new ArrayList<>(); - /** List of soft AP events related to number of connected clients in local only mode */ - private final List<SoftApConnectedClientsEvent> mSoftApEventListLocalOnly = new ArrayList<>(); - - private final SparseIntArray mObservedHotspotR1ApInScanHistogram = new SparseIntArray(); - private final SparseIntArray mObservedHotspotR2ApInScanHistogram = new SparseIntArray(); - private final SparseIntArray mObservedHotspotR3ApInScanHistogram = new SparseIntArray(); - private final SparseIntArray mObservedHotspotR1EssInScanHistogram = new SparseIntArray(); - private final SparseIntArray mObservedHotspotR2EssInScanHistogram = new SparseIntArray(); - private final SparseIntArray mObservedHotspotR3EssInScanHistogram = new SparseIntArray(); - private final SparseIntArray mObservedHotspotR1ApsPerEssInScanHistogram = new SparseIntArray(); - private final SparseIntArray mObservedHotspotR2ApsPerEssInScanHistogram = new SparseIntArray(); - private final SparseIntArray mObservedHotspotR3ApsPerEssInScanHistogram = new SparseIntArray(); - - private final SparseIntArray mObserved80211mcApInScanHistogram = new SparseIntArray(); - - // link probing stats - private final IntCounter mLinkProbeSuccessRssiCounts = new IntCounter(-85, -65); - private final IntCounter mLinkProbeFailureRssiCounts = new IntCounter(-85, -65); - private final IntCounter mLinkProbeSuccessLinkSpeedCounts = new IntCounter(); - private final IntCounter mLinkProbeFailureLinkSpeedCounts = new IntCounter(); - - private static final int[] LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS = - {5, 15, 45, 135}; - private final IntHistogram mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram = - new IntHistogram(LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS); - private final IntHistogram mLinkProbeFailureSecondsSinceLastTxSuccessHistogram = - new IntHistogram(LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS); - - private static final int[] LINK_PROBE_ELAPSED_TIME_MS_HISTOGRAM_BUCKETS = - {5, 10, 15, 20, 25, 50, 100, 200, 400, 800}; - private final IntHistogram mLinkProbeSuccessElapsedTimeMsHistogram = new IntHistogram( - LINK_PROBE_ELAPSED_TIME_MS_HISTOGRAM_BUCKETS); - private final IntCounter mLinkProbeFailureReasonCounts = new IntCounter(); - private final MeteredNetworkStatsBuilder mMeteredNetworkStatsBuilder = - new MeteredNetworkStatsBuilder(); - - /** - * Maps a String link probe experiment ID to the number of link probes that were sent for this - * experiment. - */ - private final ObjectCounter<String> mLinkProbeExperimentProbeCounts = new ObjectCounter<>(); - private int mLinkProbeStaEventCount = 0; - @VisibleForTesting static final int MAX_LINK_PROBE_STA_EVENTS = MAX_STA_EVENTS / 4; - - private final LinkedList<WifiUsabilityStatsEntry> mWifiUsabilityStatsEntriesList = - new LinkedList<>(); - private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListBad = new LinkedList<>(); - private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListGood = new LinkedList<>(); - private int mWifiUsabilityStatsCounter = 0; - private final Random mRand = new Random(); - private final ExternalCallbackTracker<IOnWifiUsabilityStatsListener> mOnWifiUsabilityListeners; - - private final SparseArray<DeviceMobilityStatePnoScanStats> mMobilityStatePnoStatsMap = - new SparseArray<>(); - private int mCurrentDeviceMobilityState; - /** - * The timestamp of the start of the current device mobility state. - */ - private long mCurrentDeviceMobilityStateStartMs; - /** - * The timestamp of when the PNO scan started in the current device mobility state. - */ - private long mCurrentDeviceMobilityStatePnoScanStartMs; - - /** Wifi power metrics*/ - private WifiPowerMetrics mWifiPowerMetrics; - - /** Wifi Wake metrics */ - private final WifiWakeMetrics mWifiWakeMetrics = new WifiWakeMetrics(); - - /** Wifi P2p metrics */ - private final WifiP2pMetrics mWifiP2pMetrics; - - /** DPP */ - private final DppMetrics mDppMetrics; - - /** WifiConfigStore read duration histogram. */ - private SparseIntArray mWifiConfigStoreReadDurationHistogram = new SparseIntArray(); - - /** WifiConfigStore write duration histogram. */ - private SparseIntArray mWifiConfigStoreWriteDurationHistogram = new SparseIntArray(); - - /** New API surface metrics */ - private final WifiNetworkRequestApiLog mWifiNetworkRequestApiLog = - new WifiNetworkRequestApiLog(); - private static final int[] NETWORK_REQUEST_API_MATCH_SIZE_HISTOGRAM_BUCKETS = - {0, 1, 5, 10}; - private final IntHistogram mWifiNetworkRequestApiMatchSizeHistogram = - new IntHistogram(NETWORK_REQUEST_API_MATCH_SIZE_HISTOGRAM_BUCKETS); - - private final WifiNetworkSuggestionApiLog mWifiNetworkSuggestionApiLog = - new WifiNetworkSuggestionApiLog(); - private static final int[] NETWORK_SUGGESTION_API_LIST_SIZE_HISTOGRAM_BUCKETS = - {5, 20, 50, 100, 500}; - private final IntHistogram mWifiNetworkSuggestionApiListSizeHistogram = - new IntHistogram(NETWORK_SUGGESTION_API_LIST_SIZE_HISTOGRAM_BUCKETS); - private final IntCounter mWifiNetworkSuggestionApiAppTypeCounter = new IntCounter(); - private final List<UserReaction> mUserApprovalSuggestionAppUiReactionList = - new ArrayList<>(); - private final List<UserReaction> mUserApprovalCarrierUiReactionList = - new ArrayList<>(); - - private final WifiLockStats mWifiLockStats = new WifiLockStats(); - private static final int[] WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS = - {1, 10, 60, 600, 3600}; - private final WifiToggleStats mWifiToggleStats = new WifiToggleStats(); - private BssidBlocklistStats mBssidBlocklistStats = new BssidBlocklistStats(); - - private final IntHistogram mWifiLockHighPerfAcqDurationSecHistogram = - new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS); - private final IntHistogram mWifiLockLowLatencyAcqDurationSecHistogram = - new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS); - - private final IntHistogram mWifiLockHighPerfActiveSessionDurationSecHistogram = - new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS); - private final IntHistogram mWifiLockLowLatencyActiveSessionDurationSecHistogram = - new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS); - - /** - * (experiment1Id, experiment2Id) => - * (sameSelectionNumChoicesCounter, differentSelectionNumChoicesCounter) - */ - private Map<Pair<Integer, Integer>, NetworkSelectionExperimentResults> - mNetworkSelectionExperimentPairNumChoicesCounts = new ArrayMap<>(); - - private int mNetworkSelectorExperimentId; - - /** - * Tracks the nominator for each network (i.e. which entity made the suggestion to connect). - * This object should not be cleared. - */ - private final SparseIntArray mNetworkIdToNominatorId = new SparseIntArray(); - - /** passpoint provision success count */ - private int mNumProvisionSuccess = 0; - - /** Mapping of failure code to the respective passpoint provision failure count. */ - private final IntCounter mPasspointProvisionFailureCounts = new IntCounter(); - - // Connection duration stats collected while link layer stats reports are on - private final ConnectionDurationStats mConnectionDurationStats = new ConnectionDurationStats(); - - private static final int[] CHANNEL_UTILIZATION_BUCKETS = - {25, 50, 75, 100, 125, 150, 175, 200, 225}; - - private final IntHistogram mChannelUtilizationHistogram2G = - new IntHistogram(CHANNEL_UTILIZATION_BUCKETS); - - private final IntHistogram mChannelUtilizationHistogramAbove2G = - new IntHistogram(CHANNEL_UTILIZATION_BUCKETS); - - private static final int[] THROUGHPUT_MBPS_BUCKETS = - {1, 5, 10, 15, 25, 50, 100, 150, 200, 300, 450, 600, 800, 1200, 1600}; - private final IntHistogram mTxThroughputMbpsHistogram2G = - new IntHistogram(THROUGHPUT_MBPS_BUCKETS); - private final IntHistogram mRxThroughputMbpsHistogram2G = - new IntHistogram(THROUGHPUT_MBPS_BUCKETS); - private final IntHistogram mTxThroughputMbpsHistogramAbove2G = - new IntHistogram(THROUGHPUT_MBPS_BUCKETS); - private final IntHistogram mRxThroughputMbpsHistogramAbove2G = - new IntHistogram(THROUGHPUT_MBPS_BUCKETS); - - // Init partial scan metrics - private int mInitPartialScanTotalCount; - private int mInitPartialScanSuccessCount; - private int mInitPartialScanFailureCount; - private static final int[] INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS = - {1, 3, 5, 10}; - private final IntHistogram mInitPartialScanSuccessHistogram = - new IntHistogram(INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS); - private final IntHistogram mInitPartialScanFailureHistogram = - new IntHistogram(INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS); - - // Wi-Fi off metrics - private final WifiOffMetrics mWifiOffMetrics = new WifiOffMetrics(); - - private final SoftApConfigLimitationMetrics mSoftApConfigLimitationMetrics = - new SoftApConfigLimitationMetrics(); - - private final CarrierWifiMetrics mCarrierWifiMetrics = - new CarrierWifiMetrics(); - - @VisibleForTesting - static class NetworkSelectionExperimentResults { - public static final int MAX_CHOICES = 10; - - public IntCounter sameSelectionNumChoicesCounter = new IntCounter(0, MAX_CHOICES); - public IntCounter differentSelectionNumChoicesCounter = new IntCounter(0, MAX_CHOICES); - - @Override - public String toString() { - return "NetworkSelectionExperimentResults{" - + "sameSelectionNumChoicesCounter=" - + sameSelectionNumChoicesCounter - + ", differentSelectionNumChoicesCounter=" - + differentSelectionNumChoicesCounter - + '}'; - } - } - - class RouterFingerPrint { - private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto; - RouterFingerPrint() { - mRouterFingerPrintProto = new WifiMetricsProto.RouterFingerPrint(); - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - synchronized (mLock) { - sb.append("mConnectionEvent.roamType=" + mRouterFingerPrintProto.roamType); - sb.append(", mChannelInfo=" + mRouterFingerPrintProto.channelInfo); - sb.append(", mDtim=" + mRouterFingerPrintProto.dtim); - sb.append(", mAuthentication=" + mRouterFingerPrintProto.authentication); - sb.append(", mHidden=" + mRouterFingerPrintProto.hidden); - sb.append(", mRouterTechnology=" + mRouterFingerPrintProto.routerTechnology); - sb.append(", mSupportsIpv6=" + mRouterFingerPrintProto.supportsIpv6); - sb.append(", mEapMethod=" + mRouterFingerPrintProto.eapMethod); - sb.append(", mAuthPhase2Method=" + mRouterFingerPrintProto.authPhase2Method); - sb.append(", mOcspType=" + mRouterFingerPrintProto.ocspType); - sb.append(", mPmkCache=" + mRouterFingerPrintProto.pmkCacheEnabled); - sb.append(", mMaxSupportedTxLinkSpeedMbps=" + mRouterFingerPrintProto - .maxSupportedTxLinkSpeedMbps); - sb.append(", mMaxSupportedRxLinkSpeedMbps=" + mRouterFingerPrintProto - .maxSupportedRxLinkSpeedMbps); - } - return sb.toString(); - } - public void updateFromWifiConfiguration(WifiConfiguration config) { - synchronized (mLock) { - if (config != null) { - // Is this a hidden network - mRouterFingerPrintProto.hidden = config.hiddenSSID; - // Config may not have a valid dtimInterval set yet, in which case dtim will be zero - // (These are only populated from beacon frame scan results, which are returned as - // scan results from the chip far less frequently than Probe-responses) - if (config.dtimInterval > 0) { - mRouterFingerPrintProto.dtim = config.dtimInterval; - } - mCurrentConnectionEvent.mConfigSsid = config.SSID; - // Get AuthType information from config (We do this again from ScanResult after - // associating with BSSID) - if (config.allowedKeyManagement != null - && config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_OPEN; - } else if (config.isEnterprise()) { - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE; - } else { - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; - } - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .passpoint = config.isPasspoint(); - // If there's a ScanResult candidate associated with this config already, get it and - // log (more accurate) metrics from it - ScanResult candidate = config.getNetworkSelectionStatus().getCandidate(); - if (candidate != null) { - updateMetricsFromScanResult(candidate); - } - if (mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .authentication == WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE - && config.enterpriseConfig != null) { - int eapMethod = config.enterpriseConfig.getEapMethod(); - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .eapMethod = getEapMethodProto(eapMethod); - int phase2Method = config.enterpriseConfig.getPhase2Method(); - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .authPhase2Method = getAuthPhase2MethodProto(phase2Method); - int ocspType = config.enterpriseConfig.getOcsp(); - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .ocspType = getOcspTypeProto(ocspType); - } - } - } - } - - public void setPmkCache(boolean isEnabled) { - synchronized (mLock) { - mRouterFingerPrintProto.pmkCacheEnabled = isEnabled; - } - } - - public void setMaxSupportedLinkSpeedMbps(int maxSupportedTxLinkSpeedMbps, - int maxSupportedRxLinkSpeedMbps) { - synchronized (mLock) { - mRouterFingerPrintProto.maxSupportedTxLinkSpeedMbps = maxSupportedTxLinkSpeedMbps; - mRouterFingerPrintProto.maxSupportedRxLinkSpeedMbps = maxSupportedRxLinkSpeedMbps; - } - } - } - private int getEapMethodProto(int eapMethod) { - switch (eapMethod) { - case WifiEnterpriseConfig.Eap.WAPI_CERT: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_WAPI_CERT; - case WifiEnterpriseConfig.Eap.TLS: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TLS; - case WifiEnterpriseConfig.Eap.UNAUTH_TLS: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNAUTH_TLS; - case WifiEnterpriseConfig.Eap.PEAP: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_PEAP; - case WifiEnterpriseConfig.Eap.PWD: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_PWD; - case WifiEnterpriseConfig.Eap.TTLS: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TTLS; - case WifiEnterpriseConfig.Eap.SIM: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_SIM; - case WifiEnterpriseConfig.Eap.AKA: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_AKA; - case WifiEnterpriseConfig.Eap.AKA_PRIME: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_AKA_PRIME; - default: - return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNKNOWN; - } - } - private int getAuthPhase2MethodProto(int phase2Method) { - switch (phase2Method) { - case WifiEnterpriseConfig.Phase2.PAP: - return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_PAP; - case WifiEnterpriseConfig.Phase2.MSCHAP: - return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAP; - case WifiEnterpriseConfig.Phase2.MSCHAPV2: - return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAPV2; - case WifiEnterpriseConfig.Phase2.GTC: - return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_GTC; - case WifiEnterpriseConfig.Phase2.SIM: - return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_SIM; - case WifiEnterpriseConfig.Phase2.AKA: - return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_AKA; - case WifiEnterpriseConfig.Phase2.AKA_PRIME: - return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_AKA_PRIME; - default: - return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_NONE; - } - } - - private int getOcspTypeProto(int ocspType) { - switch (ocspType) { - case WifiEnterpriseConfig.OCSP_NONE: - return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE; - case WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS: - return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUEST_CERT_STATUS; - case WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS: - return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUIRE_CERT_STATUS; - case WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS: - return WifiMetricsProto.RouterFingerPrint - .TYPE_OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS; - default: - return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE; - } - } - - class BssidBlocklistStats { - public IntCounter networkSelectionFilteredBssidCount = new IntCounter(); - public int numHighMovementConnectionSkipped = 0; - public int numHighMovementConnectionStarted = 0; - - public WifiMetricsProto.BssidBlocklistStats toProto() { - WifiMetricsProto.BssidBlocklistStats proto = new WifiMetricsProto.BssidBlocklistStats(); - proto.networkSelectionFilteredBssidCount = networkSelectionFilteredBssidCount.toProto(); - proto.highMovementMultipleScansFeatureEnabled = mContext.getResources().getBoolean( - R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled); - proto.numHighMovementConnectionSkipped = numHighMovementConnectionSkipped; - proto.numHighMovementConnectionStarted = numHighMovementConnectionStarted; - return proto; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("networkSelectionFilteredBssidCount=" + networkSelectionFilteredBssidCount); - sb.append(", highMovementMultipleScansFeatureEnabled=" - + mContext.getResources().getBoolean( - R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled)); - sb.append(", numHighMovementConnectionSkipped=" + numHighMovementConnectionSkipped); - sb.append(", numHighMovementConnectionStarted=" + numHighMovementConnectionStarted); - return sb.toString(); - } - } - - class ConnectionDurationStats { - private int mConnectionDurationCellularDataOffMs; - private int mConnectionDurationSufficientThroughputMs; - private int mConnectionDurationInSufficientThroughputMs; - - public WifiMetricsProto.ConnectionDurationStats toProto() { - WifiMetricsProto.ConnectionDurationStats proto = - new WifiMetricsProto.ConnectionDurationStats(); - proto.totalTimeSufficientThroughputMs = mConnectionDurationSufficientThroughputMs; - proto.totalTimeInsufficientThroughputMs = mConnectionDurationInSufficientThroughputMs; - proto.totalTimeCellularDataOffMs = mConnectionDurationCellularDataOffMs; - return proto; - } - public void clear() { - mConnectionDurationCellularDataOffMs = 0; - mConnectionDurationSufficientThroughputMs = 0; - mConnectionDurationInSufficientThroughputMs = 0; - } - public void incrementDurationCount(int timeDeltaLastTwoPollsMs, - boolean isThroughputSufficient, boolean isCellularDataAvailable) { - if (!isCellularDataAvailable) { - mConnectionDurationCellularDataOffMs += timeDeltaLastTwoPollsMs; - } else { - if (isThroughputSufficient) { - mConnectionDurationSufficientThroughputMs += timeDeltaLastTwoPollsMs; - } else { - mConnectionDurationInSufficientThroughputMs += timeDeltaLastTwoPollsMs; - } - } - } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("connectionDurationSufficientThroughputMs=") - .append(mConnectionDurationSufficientThroughputMs) - .append(", connectionDurationInSufficientThroughputMs=") - .append(mConnectionDurationInSufficientThroughputMs) - .append(", connectionDurationCellularDataOffMs=") - .append(mConnectionDurationCellularDataOffMs); - return sb.toString(); - } - } - - class WifiStatusBuilder { - private int mNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - private boolean mConnected; - private boolean mValidated; - private int mRssi; - private int mEstimatedTxKbps; - private int mEstimatedRxKbps; - private boolean mIsStuckDueToUserChoice; - - public void setNetworkId(int networkId) { - mNetworkId = networkId; - } - - public int getNetworkId() { - return mNetworkId; - } - - public void setConnected(boolean connected) { - mConnected = connected; - } - - public void setValidated(boolean validated) { - mValidated = validated; - } - - public void setRssi(int rssi) { - mRssi = rssi; - } - - public void setEstimatedTxKbps(int estimatedTxKbps) { - mEstimatedTxKbps = estimatedTxKbps; - } - - public void setEstimatedRxKbps(int estimatedRxKbps) { - mEstimatedRxKbps = estimatedRxKbps; - } - - public void setUserChoice(boolean userChoice) { - mIsStuckDueToUserChoice = userChoice; - } - - public WifiStatus toProto() { - WifiStatus result = new WifiStatus(); - result.isConnected = mConnected; - result.isValidated = mValidated; - result.lastRssi = mRssi; - result.estimatedTxKbps = mEstimatedTxKbps; - result.estimatedRxKbps = mEstimatedRxKbps; - result.isStuckDueToUserConnectChoice = mIsStuckDueToUserChoice; - return result; - } - } - - private NetworkDisableReason convertToNetworkDisableReason( - WifiConfiguration config, Set<Integer> bssidBlocklistReasons) { - NetworkSelectionStatus status = config.getNetworkSelectionStatus(); - NetworkDisableReason result = new NetworkDisableReason(); - if (config.allowAutojoin) { - if (!status.isNetworkEnabled()) { - result.disableReason = - MetricsUtils.convertNetworkSelectionDisableReasonToWifiProtoEnum( - status.getNetworkSelectionDisableReason()); - if (status.isNetworkPermanentlyDisabled()) { - result.configPermanentlyDisabled = true; - } else { - result.configTemporarilyDisabled = true; - } - } - } else { - result.disableReason = NetworkDisableReason.REASON_AUTO_JOIN_DISABLED; - result.configPermanentlyDisabled = true; - } - - int[] convertedBssidBlockReasons = bssidBlocklistReasons.stream() - .mapToInt(i -> MetricsUtils.convertBssidBlocklistReasonToWifiProtoEnum(i)) - .toArray(); - if (convertedBssidBlockReasons.length > 0) { - result.bssidDisableReasons = convertedBssidBlockReasons; - } - return result; - } - - class UserActionEventWithTime { - private UserActionEvent mUserActionEvent; - private long mWallClockTimeMs = 0; // wall clock time for debugging only - - UserActionEventWithTime(int eventType, TargetNetworkInfo targetNetworkInfo) { - mUserActionEvent = new UserActionEvent(); - mUserActionEvent.eventType = eventType; - mUserActionEvent.startTimeMillis = mClock.getElapsedSinceBootMillis(); - mWallClockTimeMs = mClock.getWallClockMillis(); - mUserActionEvent.targetNetworkInfo = targetNetworkInfo; - mUserActionEvent.wifiStatus = mWifiStatusBuilder.toProto(); - } - - UserActionEventWithTime(int eventType, int targetNetId) { - this(eventType, null); - if (targetNetId >= 0) { - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(targetNetId); - if (config != null) { - TargetNetworkInfo networkInfo = new TargetNetworkInfo(); - networkInfo.isEphemeral = config.isEphemeral(); - networkInfo.isPasspoint = config.isPasspoint(); - mUserActionEvent.targetNetworkInfo = networkInfo; - mUserActionEvent.networkDisableReason = convertToNetworkDisableReason( - config, mBssidBlocklistMonitor.getFailureReasonsForSsid(config.SSID)); - } - } - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(mWallClockTimeMs); - sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); - String eventType = "UNKNOWN"; - switch (mUserActionEvent.eventType) { - case UserActionEvent.EVENT_FORGET_WIFI: - eventType = "EVENT_FORGET_WIFI"; - break; - case UserActionEvent.EVENT_DISCONNECT_WIFI: - eventType = "EVENT_DISCONNECT_WIFI"; - break; - case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_METERED: - eventType = "EVENT_CONFIGURE_METERED_STATUS_METERED"; - break; - case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_UNMETERED: - eventType = "EVENT_CONFIGURE_METERED_STATUS_UNMETERED"; - break; - case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_AUTO: - eventType = "EVENT_CONFIGURE_METERED_STATUS_AUTO"; - break; - case UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_ON: - eventType = "EVENT_CONFIGURE_MAC_RANDOMIZATION_ON"; - break; - case UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF: - eventType = "EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF"; - break; - case UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON: - eventType = "EVENT_CONFIGURE_AUTO_CONNECT_ON"; - break; - case UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF: - eventType = "EVENT_CONFIGURE_AUTO_CONNECT_OFF"; - break; - case UserActionEvent.EVENT_TOGGLE_WIFI_ON: - eventType = "EVENT_TOGGLE_WIFI_ON"; - break; - case UserActionEvent.EVENT_TOGGLE_WIFI_OFF: - eventType = "EVENT_TOGGLE_WIFI_OFF"; - break; - case UserActionEvent.EVENT_MANUAL_CONNECT: - eventType = "EVENT_MANUAL_CONNECT"; - break; - case UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK: - eventType = "EVENT_ADD_OR_UPDATE_NETWORK"; - break; - } - sb.append(" eventType=").append(eventType); - sb.append(" startTimeMillis=").append(mUserActionEvent.startTimeMillis); - TargetNetworkInfo networkInfo = mUserActionEvent.targetNetworkInfo; - if (networkInfo != null) { - sb.append(" isEphemeral=").append(networkInfo.isEphemeral); - sb.append(" isPasspoint=").append(networkInfo.isPasspoint); - } - WifiStatus wifiStatus = mUserActionEvent.wifiStatus; - if (wifiStatus != null) { - sb.append("\nWifiStatus: isConnected=").append(wifiStatus.isConnected); - sb.append(" isValidated=").append(wifiStatus.isValidated); - sb.append(" lastRssi=").append(wifiStatus.lastRssi); - sb.append(" estimatedTxKbps=").append(wifiStatus.estimatedTxKbps); - sb.append(" estimatedRxKbps=").append(wifiStatus.estimatedRxKbps); - sb.append(" isStuckDueToUserConnectChoice=") - .append(wifiStatus.isStuckDueToUserConnectChoice); - } - NetworkDisableReason disableReason = mUserActionEvent.networkDisableReason; - if (disableReason != null) { - sb.append("\nNetworkDisableReason: DisableReason=") - .append(disableReason.disableReason); - sb.append(" configTemporarilyDisabled=") - .append(disableReason.configTemporarilyDisabled); - sb.append(" configPermanentlyDisabled=") - .append(disableReason.configPermanentlyDisabled); - sb.append(" bssidDisableReasons=") - .append(Arrays.toString(disableReason.bssidDisableReasons)); - } - return sb.toString(); - } - - public UserActionEvent toProto() { - return mUserActionEvent; - } - } - - /** - * Log event, tracking the start time, end time and result of a wireless connection attempt. - */ - class ConnectionEvent { - WifiMetricsProto.ConnectionEvent mConnectionEvent; - //<TODO> Move these constants into a wifi.proto Enum, and create a new Failure Type field - //covering more than just l2 failures. see b/27652362 - /** - * Failure codes, used for the 'level_2_failure_code' Connection event field (covers a lot - * more failures than just l2 though, since the proto does not have a place to log - * framework failures) - */ - // Failure is unknown - public static final int FAILURE_UNKNOWN = 0; - // NONE - public static final int FAILURE_NONE = 1; - // ASSOCIATION_REJECTION_EVENT - public static final int FAILURE_ASSOCIATION_REJECTION = 2; - // AUTHENTICATION_FAILURE_EVENT - public static final int FAILURE_AUTHENTICATION_FAILURE = 3; - // SSID_TEMP_DISABLED (Also Auth failure) - public static final int FAILURE_SSID_TEMP_DISABLED = 4; - // reconnect() or reassociate() call to WifiNative failed - public static final int FAILURE_CONNECT_NETWORK_FAILED = 5; - // NETWORK_DISCONNECTION_EVENT - public static final int FAILURE_NETWORK_DISCONNECTION = 6; - // NEW_CONNECTION_ATTEMPT before previous finished - public static final int FAILURE_NEW_CONNECTION_ATTEMPT = 7; - // New connection attempt to the same network & bssid - public static final int FAILURE_REDUNDANT_CONNECTION_ATTEMPT = 8; - // Roam Watchdog timer triggered (Roaming timed out) - public static final int FAILURE_ROAM_TIMEOUT = 9; - // DHCP failure - public static final int FAILURE_DHCP = 10; - // ASSOCIATION_TIMED_OUT - public static final int FAILURE_ASSOCIATION_TIMED_OUT = 11; - - RouterFingerPrint mRouterFingerPrint; - private long mRealStartTime; - private long mRealEndTime; - private String mConfigSsid; - private String mConfigBssid; - private int mWifiState; - private boolean mScreenOn; - - private ConnectionEvent() { - mConnectionEvent = new WifiMetricsProto.ConnectionEvent(); - mRealEndTime = 0; - mRealStartTime = 0; - mRouterFingerPrint = new RouterFingerPrint(); - mConnectionEvent.routerFingerprint = mRouterFingerPrint.mRouterFingerPrintProto; - mConfigSsid = "<NULL>"; - mConfigBssid = "<NULL>"; - mWifiState = WifiMetricsProto.WifiLog.WIFI_UNKNOWN; - mScreenOn = false; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("startTime="); - Calendar c = Calendar.getInstance(); - synchronized (mLock) { - c.setTimeInMillis(mConnectionEvent.startTimeMillis); - sb.append(mConnectionEvent.startTimeMillis == 0 ? " <null>" : - String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); - sb.append(", SSID="); - sb.append(mConfigSsid); - sb.append(", BSSID="); - sb.append(mConfigBssid); - sb.append(", durationMillis="); - sb.append(mConnectionEvent.durationTakenToConnectMillis); - sb.append(", roamType="); - switch(mConnectionEvent.roamType) { - case 1: - sb.append("ROAM_NONE"); - break; - case 2: - sb.append("ROAM_DBDC"); - break; - case 3: - sb.append("ROAM_ENTERPRISE"); - break; - case 4: - sb.append("ROAM_USER_SELECTED"); - break; - case 5: - sb.append("ROAM_UNRELATED"); - break; - default: - sb.append("ROAM_UNKNOWN"); - } - sb.append(", connectionResult="); - sb.append(mConnectionEvent.connectionResult); - sb.append(", level2FailureCode="); - switch(mConnectionEvent.level2FailureCode) { - case FAILURE_NONE: - sb.append("NONE"); - break; - case FAILURE_ASSOCIATION_REJECTION: - sb.append("ASSOCIATION_REJECTION"); - break; - case FAILURE_AUTHENTICATION_FAILURE: - sb.append("AUTHENTICATION_FAILURE"); - break; - case FAILURE_SSID_TEMP_DISABLED: - sb.append("SSID_TEMP_DISABLED"); - break; - case FAILURE_CONNECT_NETWORK_FAILED: - sb.append("CONNECT_NETWORK_FAILED"); - break; - case FAILURE_NETWORK_DISCONNECTION: - sb.append("NETWORK_DISCONNECTION"); - break; - case FAILURE_NEW_CONNECTION_ATTEMPT: - sb.append("NEW_CONNECTION_ATTEMPT"); - break; - case FAILURE_REDUNDANT_CONNECTION_ATTEMPT: - sb.append("REDUNDANT_CONNECTION_ATTEMPT"); - break; - case FAILURE_ROAM_TIMEOUT: - sb.append("ROAM_TIMEOUT"); - break; - case FAILURE_DHCP: - sb.append("DHCP"); - break; - case FAILURE_ASSOCIATION_TIMED_OUT: - sb.append("ASSOCIATION_TIMED_OUT"); - break; - default: - sb.append("UNKNOWN"); - break; - } - sb.append(", connectivityLevelFailureCode="); - switch(mConnectionEvent.connectivityLevelFailureCode) { - case WifiMetricsProto.ConnectionEvent.HLF_NONE: - sb.append("NONE"); - break; - case WifiMetricsProto.ConnectionEvent.HLF_DHCP: - sb.append("DHCP"); - break; - case WifiMetricsProto.ConnectionEvent.HLF_NO_INTERNET: - sb.append("NO_INTERNET"); - break; - case WifiMetricsProto.ConnectionEvent.HLF_UNWANTED: - sb.append("UNWANTED"); - break; - default: - sb.append("UNKNOWN"); - break; - } - sb.append(", signalStrength="); - sb.append(mConnectionEvent.signalStrength); - sb.append(", wifiState="); - switch(mWifiState) { - case WifiMetricsProto.WifiLog.WIFI_DISABLED: - sb.append("WIFI_DISABLED"); - break; - case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED: - sb.append("WIFI_DISCONNECTED"); - break; - case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED: - sb.append("WIFI_ASSOCIATED"); - break; - default: - sb.append("WIFI_UNKNOWN"); - break; - } - sb.append(", screenOn="); - sb.append(mScreenOn); - sb.append(", mRouterFingerprint="); - sb.append(mRouterFingerPrint.toString()); - sb.append(", useRandomizedMac="); - sb.append(mConnectionEvent.useRandomizedMac); - sb.append(", useAggressiveMac=" + mConnectionEvent.useAggressiveMac); - sb.append(", connectionNominator="); - switch (mConnectionEvent.connectionNominator) { - case WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN: - sb.append("NOMINATOR_UNKNOWN"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL: - sb.append("NOMINATOR_MANUAL"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED: - sb.append("NOMINATOR_SAVED"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_SUGGESTION: - sb.append("NOMINATOR_SUGGESTION"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_PASSPOINT: - sb.append("NOMINATOR_PASSPOINT"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER: - sb.append("NOMINATOR_CARRIER"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED: - sb.append("NOMINATOR_EXTERNAL_SCORED"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER: - sb.append("NOMINATOR_SPECIFIER"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE: - sb.append("NOMINATOR_SAVED_USER_CONNECT_CHOICE"); - break; - case WifiMetricsProto.ConnectionEvent.NOMINATOR_OPEN_NETWORK_AVAILABLE: - sb.append("NOMINATOR_OPEN_NETWORK_AVAILABLE"); - break; - default: - sb.append(String.format("UnrecognizedNominator(%d)", - mConnectionEvent.connectionNominator)); - } - sb.append(", networkSelectorExperimentId="); - sb.append(mConnectionEvent.networkSelectorExperimentId); - sb.append(", numBssidInBlocklist=" + mConnectionEvent.numBssidInBlocklist); - sb.append(", level2FailureReason="); - switch(mConnectionEvent.level2FailureReason) { - case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE: - sb.append("AUTH_FAILURE_NONE"); - break; - case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT: - sb.append("AUTH_FAILURE_TIMEOUT"); - break; - case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD: - sb.append("AUTH_FAILURE_WRONG_PSWD"); - break; - case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE: - sb.append("AUTH_FAILURE_EAP_FAILURE"); - break; - default: - sb.append("FAILURE_REASON_UNKNOWN"); - break; - } - sb.append(", networkType="); - switch(mConnectionEvent.networkType) { - case WifiMetricsProto.ConnectionEvent.TYPE_UNKNOWN: - sb.append("TYPE_UNKNOWN"); - break; - case WifiMetricsProto.ConnectionEvent.TYPE_WPA2: - sb.append("TYPE_WPA2"); - break; - case WifiMetricsProto.ConnectionEvent.TYPE_WPA3: - sb.append("TYPE_WPA3"); - break; - case WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT: - sb.append("TYPE_PASSPOINT"); - break; - case WifiMetricsProto.ConnectionEvent.TYPE_EAP: - sb.append("TYPE_EAP"); - break; - case WifiMetricsProto.ConnectionEvent.TYPE_OWE: - sb.append("TYPE_OWE"); - break; - case WifiMetricsProto.ConnectionEvent.TYPE_OPEN: - sb.append("TYPE_OPEN"); - break; - case WifiMetricsProto.ConnectionEvent.TYPE_WAPI: - sb.append("TYPE_WAPI"); - break; - } - sb.append(", networkCreator="); - switch (mConnectionEvent.networkCreator) { - case WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN: - sb.append("CREATOR_UNKNOWN"); - break; - case WifiMetricsProto.ConnectionEvent.CREATOR_USER: - sb.append("CREATOR_USER"); - break; - case WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER: - sb.append("CREATOR_CARRIER"); - break; - } - sb.append(", numConsecutiveConnectionFailure=" - + mConnectionEvent.numConsecutiveConnectionFailure); - sb.append(", isOsuProvisioned=" + mConnectionEvent.isOsuProvisioned); - } - return sb.toString(); - } - } - - class WifiOffMetrics { - public int numWifiOff = 0; - public int numWifiOffDeferring = 0; - public int numWifiOffDeferringTimeout = 0; - public final IntCounter wifiOffDeferringTimeHistogram = new IntCounter(); - - public WifiMetricsProto.WifiOffMetrics toProto() { - WifiMetricsProto.WifiOffMetrics proto = - new WifiMetricsProto.WifiOffMetrics(); - proto.numWifiOff = numWifiOff; - proto.numWifiOffDeferring = numWifiOffDeferring; - proto.numWifiOffDeferringTimeout = numWifiOffDeferringTimeout; - proto.wifiOffDeferringTimeHistogram = wifiOffDeferringTimeHistogram.toProto(); - return proto; - } - - public void clear() { - numWifiOff = 0; - numWifiOffDeferring = 0; - numWifiOffDeferringTimeout = 0; - wifiOffDeferringTimeHistogram.clear(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("numWifiOff=") - .append(numWifiOff) - .append(", numWifiOffDeferring=") - .append(numWifiOffDeferring) - .append(", numWifiOffDeferringTimeout=") - .append(numWifiOffDeferringTimeout) - .append(", wifiOffDeferringTimeHistogram=") - .append(wifiOffDeferringTimeHistogram); - return sb.toString(); - } - } - - class SoftApConfigLimitationMetrics { - // Collect the number of softap security setting reset to default during the restore - public int numSecurityTypeResetToDefault = 0; - // Collect the number of softap max client setting reset to default during the restore - public int numMaxClientSettingResetToDefault = 0; - // Collect the number of softap client control setting reset to default during the restore - public int numClientControlByUserResetToDefault = 0; - // Collect the max client setting when reach it cause client is blocked - public final IntCounter maxClientSettingWhenReachHistogram = new IntCounter(); - - public WifiMetricsProto.SoftApConfigLimitationMetrics toProto() { - WifiMetricsProto.SoftApConfigLimitationMetrics proto = - new WifiMetricsProto.SoftApConfigLimitationMetrics(); - proto.numSecurityTypeResetToDefault = numSecurityTypeResetToDefault; - proto.numMaxClientSettingResetToDefault = numMaxClientSettingResetToDefault; - proto.numClientControlByUserResetToDefault = numClientControlByUserResetToDefault; - proto.maxClientSettingWhenReachHistogram = maxClientSettingWhenReachHistogram.toProto(); - return proto; - } - - public void clear() { - numSecurityTypeResetToDefault = 0; - numMaxClientSettingResetToDefault = 0; - numClientControlByUserResetToDefault = 0; - maxClientSettingWhenReachHistogram.clear(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("numSecurityTypeResetToDefault=") - .append(numSecurityTypeResetToDefault) - .append(", numMaxClientSettingResetToDefault=") - .append(numMaxClientSettingResetToDefault) - .append(", numClientControlByUserResetToDefault=") - .append(numClientControlByUserResetToDefault) - .append(", maxClientSettingWhenReachHistogram=") - .append(maxClientSettingWhenReachHistogram); - return sb.toString(); - } - } - - class CarrierWifiMetrics { - public int numConnectionSuccess = 0; - public int numConnectionAuthFailure = 0; - public int numConnectionNonAuthFailure = 0; - - public WifiMetricsProto.CarrierWifiMetrics toProto() { - WifiMetricsProto.CarrierWifiMetrics proto = - new WifiMetricsProto.CarrierWifiMetrics(); - proto.numConnectionSuccess = numConnectionSuccess; - proto.numConnectionAuthFailure = numConnectionAuthFailure; - proto.numConnectionNonAuthFailure = numConnectionNonAuthFailure; - return proto; - } - - public void clear() { - numConnectionSuccess = 0; - numConnectionAuthFailure = 0; - numConnectionNonAuthFailure = 0; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("numConnectionSuccess=") - .append(numConnectionSuccess) - .append(", numConnectionAuthFailure=") - .append(numConnectionAuthFailure) - .append(", numConnectionNonAuthFailure") - .append(numConnectionNonAuthFailure); - return sb.toString(); - } - } - - public WifiMetrics(Context context, FrameworkFacade facade, Clock clock, Looper looper, - WifiAwareMetrics awareMetrics, RttMetrics rttMetrics, - WifiPowerMetrics wifiPowerMetrics, WifiP2pMetrics wifiP2pMetrics, - DppMetrics dppMetrics) { - mContext = context; - mFacade = facade; - mClock = clock; - mCurrentConnectionEvent = null; - mScreenOn = true; - mWifiState = WifiMetricsProto.WifiLog.WIFI_DISABLED; - mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000; - mWifiAwareMetrics = awareMetrics; - mRttMetrics = rttMetrics; - mWifiPowerMetrics = wifiPowerMetrics; - mWifiP2pMetrics = wifiP2pMetrics; - mDppMetrics = dppMetrics; - mHandler = new Handler(looper) { - public void handleMessage(Message msg) { - synchronized (mLock) { - processMessage(msg); - } - } - }; - - mCurrentDeviceMobilityState = WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN; - DeviceMobilityStatePnoScanStats unknownStateStats = - getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState); - unknownStateStats.numTimesEnteredState++; - mCurrentDeviceMobilityStateStartMs = mClock.getElapsedSinceBootMillis(); - mCurrentDeviceMobilityStatePnoScanStartMs = -1; - mOnWifiUsabilityListeners = - new ExternalCallbackTracker<IOnWifiUsabilityStatsListener>(mHandler); - } - - /** Sets internal ScoringParams member */ - public void setScoringParams(ScoringParams scoringParams) { - mScoringParams = scoringParams; - } - - /** Sets internal WifiConfigManager member */ - public void setWifiConfigManager(WifiConfigManager wifiConfigManager) { - mWifiConfigManager = wifiConfigManager; - } - - /** Sets internal WifiNetworkSelector member */ - public void setWifiNetworkSelector(WifiNetworkSelector wifiNetworkSelector) { - mWifiNetworkSelector = wifiNetworkSelector; - } - - /** Sets internal PasspointManager member */ - public void setPasspointManager(PasspointManager passpointManager) { - mPasspointManager = passpointManager; - } - - /** Sets internal WifiDataStall member */ - public void setWifiDataStall(WifiDataStall wifiDataStall) { - mWifiDataStall = wifiDataStall; - } - - /** Sets internal BssidBlocklistMonitor member */ - public void setBssidBlocklistMonitor(BssidBlocklistMonitor bssidBlocklistMonitor) { - mBssidBlocklistMonitor = bssidBlocklistMonitor; - } - - /** Sets internal WifiHealthMonitor member */ - public void setWifiHealthMonitor(WifiHealthMonitor wifiHealthMonitor) { - mWifiHealthMonitor = wifiHealthMonitor; - } - - /** Sets internal WifiScoreCard member */ - public void setWifiScoreCard(WifiScoreCard wifiScoreCard) { - mWifiScoreCard = wifiScoreCard; - } - - /** - * Increment cumulative counters for link layer stats. - * @param newStats - */ - public void incrementWifiLinkLayerUsageStats(WifiLinkLayerStats newStats) { - if (newStats == null) { - return; - } - if (mLastLinkLayerStats == null) { - mLastLinkLayerStats = newStats; - return; - } - if (!newLinkLayerStatsIsValid(mLastLinkLayerStats, newStats)) { - // This could mean the radio chip is reset or the data is incorrectly reported. - // Don't increment any counts and discard the possibly corrupt |newStats| completely. - mLastLinkLayerStats = null; - return; - } - mWifiLinkLayerUsageStats.loggingDurationMs += - (newStats.timeStampInMs - mLastLinkLayerStats.timeStampInMs); - mWifiLinkLayerUsageStats.radioOnTimeMs += (newStats.on_time - mLastLinkLayerStats.on_time); - mWifiLinkLayerUsageStats.radioTxTimeMs += (newStats.tx_time - mLastLinkLayerStats.tx_time); - mWifiLinkLayerUsageStats.radioRxTimeMs += (newStats.rx_time - mLastLinkLayerStats.rx_time); - mWifiLinkLayerUsageStats.radioScanTimeMs += - (newStats.on_time_scan - mLastLinkLayerStats.on_time_scan); - mWifiLinkLayerUsageStats.radioNanScanTimeMs += - (newStats.on_time_nan_scan - mLastLinkLayerStats.on_time_nan_scan); - mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs += - (newStats.on_time_background_scan - mLastLinkLayerStats.on_time_background_scan); - mWifiLinkLayerUsageStats.radioRoamScanTimeMs += - (newStats.on_time_roam_scan - mLastLinkLayerStats.on_time_roam_scan); - mWifiLinkLayerUsageStats.radioPnoScanTimeMs += - (newStats.on_time_pno_scan - mLastLinkLayerStats.on_time_pno_scan); - mWifiLinkLayerUsageStats.radioHs20ScanTimeMs += - (newStats.on_time_hs20_scan - mLastLinkLayerStats.on_time_hs20_scan); - mLastLinkLayerStats = newStats; - } - - private boolean newLinkLayerStatsIsValid(WifiLinkLayerStats oldStats, - WifiLinkLayerStats newStats) { - if (newStats.on_time < oldStats.on_time - || newStats.tx_time < oldStats.tx_time - || newStats.rx_time < oldStats.rx_time - || newStats.on_time_scan < oldStats.on_time_scan) { - return false; - } - return true; - } - - /** - * Increment total number of attempts to start a pno scan - */ - public void incrementPnoScanStartAttemptCount() { - synchronized (mLock) { - mPnoScanMetrics.numPnoScanAttempts++; - } - } - - /** - * Increment total number of attempts with pno scan failed - */ - public void incrementPnoScanFailedCount() { - synchronized (mLock) { - mPnoScanMetrics.numPnoScanFailed++; - } - } - - /** - * Increment number of times pno scan found a result - */ - public void incrementPnoFoundNetworkEventCount() { - synchronized (mLock) { - mPnoScanMetrics.numPnoFoundNetworkEvents++; - } - } - - // Values used for indexing SystemStateEntries - private static final int SCREEN_ON = 1; - private static final int SCREEN_OFF = 0; - - /** - * Create a new connection event and check if the new one overlaps with previous one. - * Call when wifi attempts to make a new network connection - * If there is a current 'un-ended' connection event, it will be ended with UNKNOWN connectivity - * failure code. - * Gathers and sets the RouterFingerPrint data as well - * - * @param config WifiConfiguration of the config used for the current connection attempt - * @param roamType Roam type that caused connection attempt, see WifiMetricsProto.WifiLog.ROAM_X - * @return The duration in ms since the last unfinished connection attempt, - * or 0 if there is no unfinished connection - */ - public int startConnectionEvent( - WifiConfiguration config, String targetBSSID, int roamType) { - synchronized (mLock) { - int overlapWithLastConnectionMs = 0; - if (mCurrentConnectionEvent != null) { - overlapWithLastConnectionMs = (int) (mClock.getElapsedSinceBootMillis() - - mCurrentConnectionEvent.mRealStartTime); - //Is this new Connection Event the same as the current one - if (mCurrentConnectionEvent.mConfigSsid != null - && mCurrentConnectionEvent.mConfigBssid != null - && config != null - && mCurrentConnectionEvent.mConfigSsid.equals(config.SSID) - && (mCurrentConnectionEvent.mConfigBssid.equals("any") - || mCurrentConnectionEvent.mConfigBssid.equals(targetBSSID))) { - mCurrentConnectionEvent.mConfigBssid = targetBSSID; - // End Connection Event due to new connection attempt to the same network - endConnectionEvent(ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - } else { - // End Connection Event due to new connection attempt to different network - endConnectionEvent(ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - } - } - //If past maximum connection events, start removing the oldest - while(mConnectionEventList.size() >= MAX_CONNECTION_EVENTS) { - mConnectionEventList.remove(0); - } - mCurrentConnectionEvent = new ConnectionEvent(); - mCurrentConnectionEvent.mConnectionEvent.startTimeMillis = - mClock.getWallClockMillis(); - mCurrentConnectionEvent.mConfigBssid = targetBSSID; - mCurrentConnectionEvent.mConnectionEvent.roamType = roamType; - mCurrentConnectionEvent.mConnectionEvent.networkSelectorExperimentId = - mNetworkSelectorExperimentId; - mCurrentConnectionEvent.mRouterFingerPrint.updateFromWifiConfiguration(config); - mCurrentConnectionEvent.mConfigBssid = "any"; - mCurrentConnectionEvent.mRealStartTime = mClock.getElapsedSinceBootMillis(); - mCurrentConnectionEvent.mWifiState = mWifiState; - mCurrentConnectionEvent.mScreenOn = mScreenOn; - mConnectionEventList.add(mCurrentConnectionEvent); - mScanResultRssiTimestampMillis = -1; - if (config != null) { - mCurrentConnectionEvent.mConnectionEvent.useRandomizedMac = - config.macRandomizationSetting - == WifiConfiguration.RANDOMIZATION_PERSISTENT; - mCurrentConnectionEvent.mConnectionEvent.useAggressiveMac = - mWifiConfigManager.shouldUseAggressiveRandomization(config); - mCurrentConnectionEvent.mConnectionEvent.connectionNominator = - mNetworkIdToNominatorId.get(config.networkId, - WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN); - ScanResult candidate = config.getNetworkSelectionStatus().getCandidate(); - if (candidate != null) { - // Cache the RSSI of the candidate, as the connection event level is updated - // from other sources (polls, bssid_associations) and delta requires the - // scanResult rssi - mScanResultRssi = candidate.level; - mScanResultRssiTimestampMillis = mClock.getElapsedSinceBootMillis(); - } - mCurrentConnectionEvent.mConnectionEvent.numBssidInBlocklist = - mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(config.SSID); - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_UNKNOWN; - mCurrentConnectionEvent.mConnectionEvent.isOsuProvisioned = false; - if (config.isPasspoint()) { - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT; - mCurrentConnectionEvent.mConnectionEvent.isOsuProvisioned = - !TextUtils.isEmpty(config.updateIdentifier); - } else if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) { - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_WPA3; - } else if (WifiConfigurationUtil.isConfigForWapiPskNetwork(config)) { - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_WAPI; - } else if (WifiConfigurationUtil.isConfigForWapiCertNetwork(config)) { - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_WAPI; - } else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) { - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_WPA2; - } else if (WifiConfigurationUtil.isConfigForEapNetwork(config)) { - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_EAP; - } else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) { - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_OWE; - } else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) { - mCurrentConnectionEvent.mConnectionEvent.networkType = - WifiMetricsProto.ConnectionEvent.TYPE_OPEN; - } - - if (!config.fromWifiNetworkSuggestion) { - mCurrentConnectionEvent.mConnectionEvent.networkCreator = - WifiMetricsProto.ConnectionEvent.CREATOR_USER; - } else if (config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { - mCurrentConnectionEvent.mConnectionEvent.networkCreator = - WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER; - } else { - mCurrentConnectionEvent.mConnectionEvent.networkCreator = - WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN; - } - - mCurrentConnectionEvent.mConnectionEvent.screenOn = mScreenOn; - if (mCurrentConnectionEvent.mConfigSsid != null) { - WifiScoreCard.NetworkConnectionStats recentStats = mWifiScoreCard.lookupNetwork( - mCurrentConnectionEvent.mConfigSsid).getRecentStats(); - mCurrentConnectionEvent.mConnectionEvent.numConsecutiveConnectionFailure = - recentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE); - } - } - return overlapWithLastConnectionMs; - } - } - - /** - * set the RoamType of the current ConnectionEvent (if any) - */ - public void setConnectionEventRoamType(int roamType) { - synchronized (mLock) { - if (mCurrentConnectionEvent != null) { - mCurrentConnectionEvent.mConnectionEvent.roamType = roamType; - } - } - } - - /** - * Set AP related metrics from ScanDetail - */ - public void setConnectionScanDetail(ScanDetail scanDetail) { - synchronized (mLock) { - if (mCurrentConnectionEvent != null && scanDetail != null) { - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - ScanResult scanResult = scanDetail.getScanResult(); - //Ensure that we have a networkDetail, and that it corresponds to the currently - //tracked connection attempt - if (networkDetail != null && scanResult != null - && mCurrentConnectionEvent.mConfigSsid != null - && mCurrentConnectionEvent.mConfigSsid - .equals("\"" + networkDetail.getSSID() + "\"")) { - updateMetricsFromNetworkDetail(networkDetail); - updateMetricsFromScanResult(scanResult); - } - } - } - } - - /** - * Set PMK cache status for a connection event - */ - public void setConnectionPmkCache(boolean isEnabled) { - synchronized (mLock) { - if (mCurrentConnectionEvent != null) { - mCurrentConnectionEvent.mRouterFingerPrint.setPmkCache(isEnabled); - } - } - } - - /** - * Set the max link speed supported by current network - */ - public void setConnectionMaxSupportedLinkSpeedMbps(int maxSupportedTxLinkSpeedMbps, - int maxSupportedRxLinkSpeedMbps) { - synchronized (mLock) { - if (mCurrentConnectionEvent != null) { - mCurrentConnectionEvent.mRouterFingerPrint.setMaxSupportedLinkSpeedMbps( - maxSupportedTxLinkSpeedMbps, maxSupportedRxLinkSpeedMbps); - } - } - } - - /** - * End a Connection event record. Call when wifi connection attempt succeeds or fails. - * If a Connection event has not been started and is active when .end is called, then this - * method will do nothing. - * - * @param level2FailureCode Level 2 failure code returned by supplicant - * @param connectivityFailureCode WifiMetricsProto.ConnectionEvent.HLF_X - * @param level2FailureReason Breakdown of level2FailureCode with more detailed reason - */ - public void endConnectionEvent(int level2FailureCode, int connectivityFailureCode, - int level2FailureReason) { - synchronized (mLock) { - if (mCurrentConnectionEvent != null) { - boolean result = (level2FailureCode == 1) - && (connectivityFailureCode == WifiMetricsProto.ConnectionEvent.HLF_NONE); - mCurrentConnectionEvent.mConnectionEvent.connectionResult = result ? 1 : 0; - mCurrentConnectionEvent.mRealEndTime = mClock.getElapsedSinceBootMillis(); - mCurrentConnectionEvent.mConnectionEvent.durationTakenToConnectMillis = (int) - (mCurrentConnectionEvent.mRealEndTime - - mCurrentConnectionEvent.mRealStartTime); - mCurrentConnectionEvent.mConnectionEvent.level2FailureCode = level2FailureCode; - mCurrentConnectionEvent.mConnectionEvent.connectivityLevelFailureCode = - connectivityFailureCode; - mCurrentConnectionEvent.mConnectionEvent.level2FailureReason = level2FailureReason; - - // Write metrics to statsd - int wwFailureCode = getConnectionResultFailureCode(level2FailureCode, - level2FailureReason); - if (wwFailureCode != -1) { - WifiStatsLog.write(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED, result, - wwFailureCode, mCurrentConnectionEvent.mConnectionEvent.signalStrength); - } - // ConnectionEvent already added to ConnectionEvents List. Safe to null current here - mCurrentConnectionEvent = null; - if (!result) { - mScanResultRssiTimestampMillis = -1; - } - mWifiStatusBuilder.setConnected(result); - } - } - } - - private int getConnectionResultFailureCode(int level2FailureCode, int level2FailureReason) { - switch (level2FailureCode) { - case ConnectionEvent.FAILURE_NONE: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_UNKNOWN; - case ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ASSOCIATION_TIMEOUT; - case ConnectionEvent.FAILURE_ASSOCIATION_REJECTION: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ASSOCIATION_REJECTION; - case ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE: - switch (level2FailureReason) { - case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_EAP; - case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD: - return -1; - default: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_GENERAL; - } - case ConnectionEvent.FAILURE_DHCP: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_DHCP; - case ConnectionEvent.FAILURE_NETWORK_DISCONNECTION: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_NETWORK_DISCONNECTION; - case ConnectionEvent.FAILURE_ROAM_TIMEOUT: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ROAM_TIMEOUT; - case ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT: - case ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT: - return -1; - default: - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_UNKNOWN; - } - } - - /** - * Set ConnectionEvent DTIM Interval (if set), and 802.11 Connection mode, from NetworkDetail - */ - private void updateMetricsFromNetworkDetail(NetworkDetail networkDetail) { - int dtimInterval = networkDetail.getDtimInterval(); - if (dtimInterval > 0) { - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.dtim = - dtimInterval; - } - int connectionWifiMode; - switch (networkDetail.getWifiMode()) { - case InformationElementUtil.WifiMode.MODE_UNDEFINED: - connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_UNKNOWN; - break; - case InformationElementUtil.WifiMode.MODE_11A: - connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_A; - break; - case InformationElementUtil.WifiMode.MODE_11B: - connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_B; - break; - case InformationElementUtil.WifiMode.MODE_11G: - connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_G; - break; - case InformationElementUtil.WifiMode.MODE_11N: - connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_N; - break; - case InformationElementUtil.WifiMode.MODE_11AC : - connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AC; - break; - case InformationElementUtil.WifiMode.MODE_11AX : - connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AX; - break; - default: - connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_OTHER; - break; - } - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto - .routerTechnology = connectionWifiMode; - - if (networkDetail.isMboSupported()) { - mWifiLogProto.numConnectToNetworkSupportingMbo++; - if (networkDetail.isOceSupported()) { - mWifiLogProto.numConnectToNetworkSupportingOce++; - } - } - } - - /** - * Set ConnectionEvent RSSI and authentication type from ScanResult - */ - private void updateMetricsFromScanResult(ScanResult scanResult) { - mCurrentConnectionEvent.mConnectionEvent.signalStrength = scanResult.level; - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = - WifiMetricsProto.RouterFingerPrint.AUTH_OPEN; - mCurrentConnectionEvent.mConfigBssid = scanResult.BSSID; - if (scanResult.capabilities != null) { - if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) { - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = - WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; - } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult) - || ScanResultUtil.isScanResultForSaeNetwork(scanResult)) { - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = - WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; - } else if (ScanResultUtil.isScanResultForEapNetwork(scanResult) - || ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) { - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = - WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE; - } - } - mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.channelInfo = - scanResult.frequency; - } - - void setIsLocationEnabled(boolean enabled) { - synchronized (mLock) { - mWifiLogProto.isLocationEnabled = enabled; - } - } - - void setIsScanningAlwaysEnabled(boolean enabled) { - synchronized (mLock) { - mWifiLogProto.isScanningAlwaysEnabled = enabled; - } - } - - /** - * Developer options toggle value for verbose logging. - */ - public void setVerboseLoggingEnabled(boolean enabled) { - synchronized (mLock) { - mWifiLogProto.isVerboseLoggingEnabled = enabled; - } - } - - /** - * Developer options toggle value for enhanced MAC randomization. - */ - public void setEnhancedMacRandomizationForceEnabled(boolean enabled) { - synchronized (mLock) { - mWifiLogProto.isEnhancedMacRandomizationForceEnabled = enabled; - } - } - - /** - * Wifi wake feature toggle. - */ - public void setWifiWakeEnabled(boolean enabled) { - synchronized (mLock) { - mWifiLogProto.isWifiWakeEnabled = enabled; - } - } - - /** - * Increment Non Empty Scan Results count - */ - public void incrementNonEmptyScanResultCount() { - if (DBG) Log.v(TAG, "incrementNonEmptyScanResultCount"); - synchronized (mLock) { - mWifiLogProto.numNonEmptyScanResults++; - } - } - - /** - * Increment Empty Scan Results count - */ - public void incrementEmptyScanResultCount() { - if (DBG) Log.v(TAG, "incrementEmptyScanResultCount"); - synchronized (mLock) { - mWifiLogProto.numEmptyScanResults++; - } - } - - /** - * Increment background scan count - */ - public void incrementBackgroundScanCount() { - if (DBG) Log.v(TAG, "incrementBackgroundScanCount"); - synchronized (mLock) { - mWifiLogProto.numBackgroundScans++; - } - } - - /** - * Get Background scan count - */ - public int getBackgroundScanCount() { - synchronized (mLock) { - return mWifiLogProto.numBackgroundScans; - } - } - - /** - * Increment oneshot scan count, and the associated WifiSystemScanStateCount entry - */ - public void incrementOneshotScanCount() { - synchronized (mLock) { - mWifiLogProto.numOneshotScans++; - } - incrementWifiSystemScanStateCount(mWifiState, mScreenOn); - } - - /** - * Increment the count of oneshot scans that include DFS channels. - */ - public void incrementOneshotScanWithDfsCount() { - synchronized (mLock) { - mWifiLogProto.numOneshotHasDfsChannelScans++; - } - } - - /** - * Increment connectivity oneshot scan count. - */ - public void incrementConnectivityOneshotScanCount() { - synchronized (mLock) { - mWifiLogProto.numConnectivityOneshotScans++; - } - } - - /** - * Get oneshot scan count - */ - public int getOneshotScanCount() { - synchronized (mLock) { - return mWifiLogProto.numOneshotScans; - } - } - - /** - * Get connectivity oneshot scan count - */ - public int getConnectivityOneshotScanCount() { - synchronized (mLock) { - return mWifiLogProto.numConnectivityOneshotScans; - } - } - - /** - * Get the count of oneshot scan requests that included DFS channels. - */ - public int getOneshotScanWithDfsCount() { - synchronized (mLock) { - return mWifiLogProto.numOneshotHasDfsChannelScans; - } - } - - /** - * Increment oneshot scan count for external apps. - */ - public void incrementExternalAppOneshotScanRequestsCount() { - synchronized (mLock) { - mWifiLogProto.numExternalAppOneshotScanRequests++; - } - } - /** - * Increment oneshot scan throttle count for external foreground apps. - */ - public void incrementExternalForegroundAppOneshotScanRequestsThrottledCount() { - synchronized (mLock) { - mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled++; - } - } - - /** - * Increment oneshot scan throttle count for external background apps. - */ - public void incrementExternalBackgroundAppOneshotScanRequestsThrottledCount() { - synchronized (mLock) { - mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled++; - } - } - - private String returnCodeToString(int scanReturnCode) { - switch(scanReturnCode){ - case WifiMetricsProto.WifiLog.SCAN_UNKNOWN: - return "SCAN_UNKNOWN"; - case WifiMetricsProto.WifiLog.SCAN_SUCCESS: - return "SCAN_SUCCESS"; - case WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED: - return "SCAN_FAILURE_INTERRUPTED"; - case WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION: - return "SCAN_FAILURE_INVALID_CONFIGURATION"; - case WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED: - return "FAILURE_WIFI_DISABLED"; - default: - return "<UNKNOWN>"; - } - } - - /** - * Increment count of scan return code occurrence - * - * @param scanReturnCode Return code from scan attempt WifiMetricsProto.WifiLog.SCAN_X - */ - public void incrementScanReturnEntry(int scanReturnCode, int countToAdd) { - synchronized (mLock) { - if (DBG) Log.v(TAG, "incrementScanReturnEntry " + returnCodeToString(scanReturnCode)); - int entry = mScanReturnEntries.get(scanReturnCode); - entry += countToAdd; - mScanReturnEntries.put(scanReturnCode, entry); - } - } - /** - * Get the count of this scanReturnCode - * @param scanReturnCode that we are getting the count for - */ - public int getScanReturnEntry(int scanReturnCode) { - synchronized (mLock) { - return mScanReturnEntries.get(scanReturnCode); - } - } - - private String wifiSystemStateToString(int state) { - switch(state){ - case WifiMetricsProto.WifiLog.WIFI_UNKNOWN: - return "WIFI_UNKNOWN"; - case WifiMetricsProto.WifiLog.WIFI_DISABLED: - return "WIFI_DISABLED"; - case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED: - return "WIFI_DISCONNECTED"; - case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED: - return "WIFI_ASSOCIATED"; - default: - return "default"; - } - } - - /** - * Increments the count of scans initiated by each wifi state, accounts for screenOn/Off - * - * @param state State of the system when scan was initiated, see WifiMetricsProto.WifiLog.WIFI_X - * @param screenOn Is the screen on - */ - public void incrementWifiSystemScanStateCount(int state, boolean screenOn) { - synchronized (mLock) { - if (DBG) { - Log.v(TAG, "incrementWifiSystemScanStateCount " + wifiSystemStateToString(state) - + " " + screenOn); - } - int index = (state * 2) + (screenOn ? SCREEN_ON : SCREEN_OFF); - int entry = mWifiSystemStateEntries.get(index); - entry++; - mWifiSystemStateEntries.put(index, entry); - } - } - - /** - * Get the count of this system State Entry - */ - public int getSystemStateCount(int state, boolean screenOn) { - synchronized (mLock) { - int index = state * 2 + (screenOn ? SCREEN_ON : SCREEN_OFF); - return mWifiSystemStateEntries.get(index); - } - } - - /** - * Increment number of times the Watchdog of Last Resort triggered, resetting the wifi stack - */ - public void incrementNumLastResortWatchdogTriggers() { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogTriggers++; - } - } - /** - * @param count number of networks over bad association threshold when watchdog triggered - */ - public void addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count) { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal += count; - } - } - /** - * @param count number of networks over bad authentication threshold when watchdog triggered - */ - public void addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count) { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal += count; - } - } - /** - * @param count number of networks over bad dhcp threshold when watchdog triggered - */ - public void addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count) { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal += count; - } - } - /** - * @param count number of networks over bad other threshold when watchdog triggered - */ - public void addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count) { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal += count; - } - } - /** - * @param count number of networks seen when watchdog triggered - */ - public void addCountToNumLastResortWatchdogAvailableNetworksTotal(int count) { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal += count; - } - } - /** - * Increment count of triggers with atleast one bad association network - */ - public void incrementNumLastResortWatchdogTriggersWithBadAssociation() { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation++; - } - } - /** - * Increment count of triggers with atleast one bad authentication network - */ - public void incrementNumLastResortWatchdogTriggersWithBadAuthentication() { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication++; - } - } - /** - * Increment count of triggers with atleast one bad dhcp network - */ - public void incrementNumLastResortWatchdogTriggersWithBadDhcp() { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp++; - } - } - /** - * Increment count of triggers with atleast one bad other network - */ - public void incrementNumLastResortWatchdogTriggersWithBadOther() { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogTriggersWithBadOther++; - } - } - - /** - * Increment number of times connectivity watchdog confirmed pno is working - */ - public void incrementNumConnectivityWatchdogPnoGood() { - synchronized (mLock) { - mWifiLogProto.numConnectivityWatchdogPnoGood++; - } - } - /** - * Increment number of times connectivity watchdog found pno not working - */ - public void incrementNumConnectivityWatchdogPnoBad() { - synchronized (mLock) { - mWifiLogProto.numConnectivityWatchdogPnoBad++; - } - } - /** - * Increment number of times connectivity watchdog confirmed background scan is working - */ - public void incrementNumConnectivityWatchdogBackgroundGood() { - synchronized (mLock) { - mWifiLogProto.numConnectivityWatchdogBackgroundGood++; - } - } - /** - * Increment number of times connectivity watchdog found background scan not working - */ - public void incrementNumConnectivityWatchdogBackgroundBad() { - synchronized (mLock) { - mWifiLogProto.numConnectivityWatchdogBackgroundBad++; - } - } - - /** - * Increment various poll related metrics, and cache performance data for StaEvent logging - */ - public void handlePollResult(WifiInfo wifiInfo) { - mLastPollRssi = wifiInfo.getRssi(); - mLastPollLinkSpeed = wifiInfo.getLinkSpeed(); - mLastPollFreq = wifiInfo.getFrequency(); - incrementRssiPollRssiCount(mLastPollFreq, mLastPollRssi); - incrementLinkSpeedCount(mLastPollLinkSpeed, mLastPollRssi); - mLastPollRxLinkSpeed = wifiInfo.getRxLinkSpeedMbps(); - incrementTxLinkSpeedBandCount(mLastPollLinkSpeed, mLastPollFreq); - incrementRxLinkSpeedBandCount(mLastPollRxLinkSpeed, mLastPollFreq); - mWifiStatusBuilder.setRssi(mLastPollRssi); - mWifiStatusBuilder.setNetworkId(wifiInfo.getNetworkId()); - } - - /** - * Increment occurence count of RSSI level from RSSI poll for the given frequency. - * @param frequency (MHz) - * @param rssi - */ - @VisibleForTesting - public void incrementRssiPollRssiCount(int frequency, int rssi) { - if (!(rssi >= MIN_RSSI_POLL && rssi <= MAX_RSSI_POLL)) { - return; - } - synchronized (mLock) { - if (!mRssiPollCountsMap.containsKey(frequency)) { - mRssiPollCountsMap.put(frequency, new SparseIntArray()); - } - SparseIntArray sparseIntArray = mRssiPollCountsMap.get(frequency); - int count = sparseIntArray.get(rssi); - sparseIntArray.put(rssi, count + 1); - maybeIncrementRssiDeltaCount(rssi - mScanResultRssi); - } - } - - /** - * Increment occurence count of difference between scan result RSSI and the first RSSI poll. - * Ignores rssi values outside the bounds of [MIN_RSSI_DELTA, MAX_RSSI_DELTA] - * mLock must be held when calling this method. - */ - private void maybeIncrementRssiDeltaCount(int rssi) { - // Check if this RSSI poll is close enough to a scan result RSSI to log a delta value - if (mScanResultRssiTimestampMillis >= 0) { - long timeDelta = mClock.getElapsedSinceBootMillis() - mScanResultRssiTimestampMillis; - if (timeDelta <= TIMEOUT_RSSI_DELTA_MILLIS) { - if (rssi >= MIN_RSSI_DELTA && rssi <= MAX_RSSI_DELTA) { - int count = mRssiDeltaCounts.get(rssi); - mRssiDeltaCounts.put(rssi, count + 1); - } - } - mScanResultRssiTimestampMillis = -1; - } - } - - /** - * Increment occurrence count of link speed. - * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS - * and rssi values outside the bounds of [MIN_RSSI_POLL, MAX_RSSI_POLL] - */ - @VisibleForTesting - public void incrementLinkSpeedCount(int linkSpeed, int rssi) { - if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled) - && linkSpeed >= MIN_LINK_SPEED_MBPS - && rssi >= MIN_RSSI_POLL - && rssi <= MAX_RSSI_POLL)) { - return; - } - synchronized (mLock) { - LinkSpeedCount linkSpeedCount = mLinkSpeedCounts.get(linkSpeed); - if (linkSpeedCount == null) { - linkSpeedCount = new LinkSpeedCount(); - linkSpeedCount.linkSpeedMbps = linkSpeed; - mLinkSpeedCounts.put(linkSpeed, linkSpeedCount); - } - linkSpeedCount.count++; - linkSpeedCount.rssiSumDbm += Math.abs(rssi); - linkSpeedCount.rssiSumOfSquaresDbmSq += rssi * rssi; - } - } - - /** - * Increment occurrence count of Tx link speed for operating sub-band - * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS - * @param txLinkSpeed PHY layer Tx link speed in Mbps - * @param frequency Channel frequency of beacon frames in MHz - */ - @VisibleForTesting - public void incrementTxLinkSpeedBandCount(int txLinkSpeed, int frequency) { - if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled) - && txLinkSpeed >= MIN_LINK_SPEED_MBPS)) { - return; - } - synchronized (mLock) { - if (ScanResult.is24GHz(frequency)) { - mTxLinkSpeedCount2g.increment(txLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_LOW_END_FREQ) { - mTxLinkSpeedCount5gLow.increment(txLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_MID_END_FREQ) { - mTxLinkSpeedCount5gMid.increment(txLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_HIGH_END_FREQ) { - mTxLinkSpeedCount5gHigh.increment(txLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_LOW_END_FREQ) { - mTxLinkSpeedCount6gLow.increment(txLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_MID_END_FREQ) { - mTxLinkSpeedCount6gMid.increment(txLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_HIGH_END_FREQ) { - mTxLinkSpeedCount6gHigh.increment(txLinkSpeed); - } - } - } - - /** - * Increment occurrence count of Rx link speed for operating sub-band - * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS - * @param rxLinkSpeed PHY layer Tx link speed in Mbps - * @param frequency Channel frequency of beacon frames in MHz - */ - @VisibleForTesting - public void incrementRxLinkSpeedBandCount(int rxLinkSpeed, int frequency) { - if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled) - && rxLinkSpeed >= MIN_LINK_SPEED_MBPS)) { - return; - } - synchronized (mLock) { - if (ScanResult.is24GHz(frequency)) { - mRxLinkSpeedCount2g.increment(rxLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_LOW_END_FREQ) { - mRxLinkSpeedCount5gLow.increment(rxLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_MID_END_FREQ) { - mRxLinkSpeedCount5gMid.increment(rxLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_HIGH_END_FREQ) { - mRxLinkSpeedCount5gHigh.increment(rxLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_LOW_END_FREQ) { - mRxLinkSpeedCount6gLow.increment(rxLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_MID_END_FREQ) { - mRxLinkSpeedCount6gMid.increment(rxLinkSpeed); - } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_HIGH_END_FREQ) { - mRxLinkSpeedCount6gHigh.increment(rxLinkSpeed); - } - } - } - - /** - * Increment occurrence count of channel utilization - * @param channelUtilization Channel utilization of current network - * @param frequency Channel frequency of current network - */ - @VisibleForTesting - public void incrementChannelUtilizationCount(int channelUtilization, int frequency) { - if (channelUtilization < InformationElementUtil.BssLoad.MIN_CHANNEL_UTILIZATION - || channelUtilization > InformationElementUtil.BssLoad.MAX_CHANNEL_UTILIZATION) { - return; - } - synchronized (mLock) { - if (ScanResult.is24GHz(frequency)) { - mChannelUtilizationHistogram2G.increment(channelUtilization); - } else { - mChannelUtilizationHistogramAbove2G.increment(channelUtilization); - } - } - } - - /** - * Increment occurrence count of Tx and Rx throughput - * @param txThroughputKbps Tx throughput of current network in Kbps - * @param rxThroughputKbps Rx throughput of current network in Kbps - * @param frequency Channel frequency of current network in MHz - */ - @VisibleForTesting - public void incrementThroughputKbpsCount(int txThroughputKbps, int rxThroughputKbps, - int frequency) { - synchronized (mLock) { - if (ScanResult.is24GHz(frequency)) { - if (txThroughputKbps >= 0) { - mTxThroughputMbpsHistogram2G.increment(txThroughputKbps / 1000); - } - if (rxThroughputKbps >= 0) { - mRxThroughputMbpsHistogram2G.increment(rxThroughputKbps / 1000); - } - } else { - if (txThroughputKbps >= 0) { - mTxThroughputMbpsHistogramAbove2G.increment(txThroughputKbps / 1000); - } - if (rxThroughputKbps >= 0) { - mRxThroughputMbpsHistogramAbove2G.increment(rxThroughputKbps / 1000); - } - } - mWifiStatusBuilder.setEstimatedTxKbps(txThroughputKbps); - mWifiStatusBuilder.setEstimatedRxKbps(rxThroughputKbps); - } - } - - /** - * Increment count of Watchdog successes. - */ - public void incrementNumLastResortWatchdogSuccesses() { - synchronized (mLock) { - mWifiLogProto.numLastResortWatchdogSuccesses++; - } - } - - /** - * Increment the count of network connection failures that happened after watchdog has been - * triggered. - */ - public void incrementWatchdogTotalConnectionFailureCountAfterTrigger() { - synchronized (mLock) { - mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger++; - } - } - - /** - * Sets the time taken for wifi to connect after a watchdog triggers a restart. - * @param milliseconds - */ - public void setWatchdogSuccessTimeDurationMs(long ms) { - synchronized (mLock) { - mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs = ms; - } - } - - /** - * Increments the count of alerts by alert reason. - * - * @param reason The cause of the alert. The reason values are driver-specific. - */ - private void incrementAlertReasonCount(int reason) { - if (reason > WifiLoggerHal.WIFI_ALERT_REASON_MAX - || reason < WifiLoggerHal.WIFI_ALERT_REASON_MIN) { - reason = WifiLoggerHal.WIFI_ALERT_REASON_RESERVED; - } - synchronized (mLock) { - int alertCount = mWifiAlertReasonCounts.get(reason); - mWifiAlertReasonCounts.put(reason, alertCount + 1); - } - } - - /** - * Counts all the different types of networks seen in a set of scan results - */ - public void countScanResults(List<ScanDetail> scanDetails) { - if (scanDetails == null) { - return; - } - int totalResults = 0; - int openNetworks = 0; - int personalNetworks = 0; - int enterpriseNetworks = 0; - int hiddenNetworks = 0; - int hotspot2r1Networks = 0; - int hotspot2r2Networks = 0; - int hotspot2r3Networks = 0; - int enhacedOpenNetworks = 0; - int wpa3PersonalNetworks = 0; - int wpa3EnterpriseNetworks = 0; - int wapiPersonalNetworks = 0; - int wapiEnterpriseNetworks = 0; - int mboSupportedNetworks = 0; - int mboCellularDataAwareNetworks = 0; - int oceSupportedNetworks = 0; - int filsSupportedNetworks = 0; - int band6gNetworks = 0; - int standard11axNetworks = 0; - - for (ScanDetail scanDetail : scanDetails) { - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - ScanResult scanResult = scanDetail.getScanResult(); - totalResults++; - if (networkDetail != null) { - if (networkDetail.isHiddenBeaconFrame()) { - hiddenNetworks++; - } - if (networkDetail.getHSRelease() != null) { - if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) { - hotspot2r1Networks++; - } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) { - hotspot2r2Networks++; - } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) { - hotspot2r3Networks++; - } - } - if (networkDetail.isMboSupported()) { - mboSupportedNetworks++; - if (networkDetail.isMboCellularDataAware()) { - mboCellularDataAwareNetworks++; - } - if (networkDetail.isOceSupported()) { - oceSupportedNetworks++; - } - } - if (networkDetail.getWifiMode() == InformationElementUtil.WifiMode.MODE_11AX) { - standard11axNetworks++; - } - } - if (scanResult != null && scanResult.capabilities != null) { - if (ScanResultUtil.isScanResultForFilsSha256Network(scanResult) - || ScanResultUtil.isScanResultForFilsSha384Network(scanResult)) { - filsSupportedNetworks++; - } - if (scanResult.is6GHz()) { - band6gNetworks++; - } - if (ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) { - wpa3EnterpriseNetworks++; - } else if (ScanResultUtil.isScanResultForWapiPskNetwork(scanResult)) { - wapiPersonalNetworks++; - } else if (ScanResultUtil.isScanResultForWapiCertNetwork(scanResult)) { - wapiEnterpriseNetworks++; - } else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) { - enterpriseNetworks++; - } else if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)) { - wpa3PersonalNetworks++; - } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult) - || ScanResultUtil.isScanResultForWepNetwork(scanResult)) { - personalNetworks++; - } else if (ScanResultUtil.isScanResultForOweNetwork(scanResult)) { - enhacedOpenNetworks++; - } else { - openNetworks++; - } - } - } - synchronized (mLock) { - mWifiLogProto.numTotalScanResults += totalResults; - mWifiLogProto.numOpenNetworkScanResults += openNetworks; - mWifiLogProto.numLegacyPersonalNetworkScanResults += personalNetworks; - mWifiLogProto.numLegacyEnterpriseNetworkScanResults += enterpriseNetworks; - mWifiLogProto.numEnhancedOpenNetworkScanResults += enhacedOpenNetworks; - mWifiLogProto.numWpa3PersonalNetworkScanResults += wpa3PersonalNetworks; - mWifiLogProto.numWpa3EnterpriseNetworkScanResults += wpa3EnterpriseNetworks; - mWifiLogProto.numWapiPersonalNetworkScanResults += wapiPersonalNetworks; - mWifiLogProto.numWapiEnterpriseNetworkScanResults += wapiEnterpriseNetworks; - mWifiLogProto.numHiddenNetworkScanResults += hiddenNetworks; - mWifiLogProto.numHotspot2R1NetworkScanResults += hotspot2r1Networks; - mWifiLogProto.numHotspot2R2NetworkScanResults += hotspot2r2Networks; - mWifiLogProto.numHotspot2R3NetworkScanResults += hotspot2r3Networks; - mWifiLogProto.numMboSupportedNetworkScanResults += mboSupportedNetworks; - mWifiLogProto.numMboCellularDataAwareNetworkScanResults += mboCellularDataAwareNetworks; - mWifiLogProto.numOceSupportedNetworkScanResults += oceSupportedNetworks; - mWifiLogProto.numFilsSupportedNetworkScanResults += filsSupportedNetworks; - mWifiLogProto.num11AxNetworkScanResults += standard11axNetworks; - mWifiLogProto.num6GNetworkScanResults += band6gNetworks; - mWifiLogProto.numScans++; - } - } - - private boolean mWifiWins = false; // Based on scores, use wifi instead of mobile data? - // Based on Wifi usability scores. use wifi instead of mobile data? - private boolean mWifiWinsUsabilityScore = false; - - /** - * Increments occurence of a particular wifi score calculated - * in WifiScoreReport by current connected network. Scores are bounded - * within [MIN_WIFI_SCORE, MAX_WIFI_SCORE] to limit size of SparseArray. - * - * Also records events when the current score breaches significant thresholds. - */ - public void incrementWifiScoreCount(int score) { - if (score < MIN_WIFI_SCORE || score > MAX_WIFI_SCORE) { - return; - } - synchronized (mLock) { - int count = mWifiScoreCounts.get(score); - mWifiScoreCounts.put(score, count + 1); - - boolean wifiWins = mWifiWins; - if (mWifiWins && score < LOW_WIFI_SCORE) { - wifiWins = false; - } else if (!mWifiWins && score > LOW_WIFI_SCORE) { - wifiWins = true; - } - mLastScore = score; - mLastScoreNoReset = score; - if (wifiWins != mWifiWins) { - mWifiWins = wifiWins; - StaEvent event = new StaEvent(); - event.type = StaEvent.TYPE_SCORE_BREACH; - addStaEvent(event); - // Only record the first score breach by checking whether mScoreBreachLowTimeMillis - // has been set to -1 - if (!wifiWins && mScoreBreachLowTimeMillis == -1) { - mScoreBreachLowTimeMillis = mClock.getElapsedSinceBootMillis(); - } - } - } - } - - /** - * Increments occurence of the results from attempting to start SoftAp. - * Maps the |result| and WifiManager |failureCode| constant to proto defined SoftApStartResult - * codes. - */ - public void incrementSoftApStartResult(boolean result, int failureCode) { - synchronized (mLock) { - if (result) { - int count = mSoftApManagerReturnCodeCounts.get( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY); - mSoftApManagerReturnCodeCounts.put( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY, - count + 1); - return; - } - - // now increment failure modes - if not explicitly handled, dump into the general - // error bucket. - if (failureCode == WifiManager.SAP_START_FAILURE_NO_CHANNEL) { - int count = mSoftApManagerReturnCodeCounts.get( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL); - mSoftApManagerReturnCodeCounts.put( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL, - count + 1); - } else if (failureCode == WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION) { - int count = mSoftApManagerReturnCodeCounts.get( - WifiMetricsProto.SoftApReturnCodeCount - .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION); - mSoftApManagerReturnCodeCounts.put( - WifiMetricsProto.SoftApReturnCodeCount - .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION, - count + 1); - } else { - // failure mode not tracked at this time... count as a general error for now. - int count = mSoftApManagerReturnCodeCounts.get( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR); - mSoftApManagerReturnCodeCounts.put( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR, - count + 1); - } - } - } - - /** - * Adds a record indicating the current up state of soft AP - */ - public void addSoftApUpChangedEvent(boolean isUp, int mode, long defaultShutdownTimeoutMillis) { - SoftApConnectedClientsEvent event = new SoftApConnectedClientsEvent(); - event.eventType = isUp ? SoftApConnectedClientsEvent.SOFT_AP_UP : - SoftApConnectedClientsEvent.SOFT_AP_DOWN; - event.numConnectedClients = 0; - event.defaultShutdownTimeoutSetting = defaultShutdownTimeoutMillis; - addSoftApConnectedClientsEvent(event, mode); - } - - /** - * Adds a record for current number of associated stations to soft AP - */ - public void addSoftApNumAssociatedStationsChangedEvent(int numStations, int mode) { - SoftApConnectedClientsEvent event = new SoftApConnectedClientsEvent(); - event.eventType = SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED; - event.numConnectedClients = numStations; - addSoftApConnectedClientsEvent(event, mode); - } - - /** - * Adds a record to the corresponding event list based on mode param - */ - private void addSoftApConnectedClientsEvent(SoftApConnectedClientsEvent event, int mode) { - synchronized (mLock) { - List<SoftApConnectedClientsEvent> softApEventList; - switch (mode) { - case WifiManager.IFACE_IP_MODE_TETHERED: - softApEventList = mSoftApEventListTethered; - break; - case WifiManager.IFACE_IP_MODE_LOCAL_ONLY: - softApEventList = mSoftApEventListLocalOnly; - break; - default: - return; - } - - if (softApEventList.size() > MAX_NUM_SOFT_AP_EVENTS) { - return; - } - - event.timeStampMillis = mClock.getElapsedSinceBootMillis(); - softApEventList.add(event); - } - } - - /** - * Updates current soft AP events with channel info - */ - public void addSoftApChannelSwitchedEvent(int frequency, int bandwidth, int mode) { - synchronized (mLock) { - List<SoftApConnectedClientsEvent> softApEventList; - switch (mode) { - case WifiManager.IFACE_IP_MODE_TETHERED: - softApEventList = mSoftApEventListTethered; - break; - case WifiManager.IFACE_IP_MODE_LOCAL_ONLY: - softApEventList = mSoftApEventListLocalOnly; - break; - default: - return; - } - - for (int index = softApEventList.size() - 1; index >= 0; index--) { - SoftApConnectedClientsEvent event = softApEventList.get(index); - - if (event != null && event.eventType == SoftApConnectedClientsEvent.SOFT_AP_UP) { - event.channelFrequency = frequency; - event.channelBandwidth = bandwidth; - break; - } - } - } - } - - /** - * Updates current soft AP events with softap configuration - */ - public void updateSoftApConfiguration(SoftApConfiguration config, int mode) { - synchronized (mLock) { - List<SoftApConnectedClientsEvent> softApEventList; - switch (mode) { - case WifiManager.IFACE_IP_MODE_TETHERED: - softApEventList = mSoftApEventListTethered; - break; - case WifiManager.IFACE_IP_MODE_LOCAL_ONLY: - softApEventList = mSoftApEventListLocalOnly; - break; - default: - return; - } - - for (int index = softApEventList.size() - 1; index >= 0; index--) { - SoftApConnectedClientsEvent event = softApEventList.get(index); - - if (event != null && event.eventType == SoftApConnectedClientsEvent.SOFT_AP_UP) { - event.maxNumClientsSettingInSoftapConfiguration = - config.getMaxNumberOfClients(); - event.shutdownTimeoutSettingInSoftapConfiguration = - config.getShutdownTimeoutMillis(); - event.clientControlIsEnabled = config.isClientControlByUserEnabled(); - break; - } - } - } - } - - /** - * Updates current soft AP events with softap capability - */ - public void updateSoftApCapability(SoftApCapability capability, int mode) { - synchronized (mLock) { - List<SoftApConnectedClientsEvent> softApEventList; - switch (mode) { - case WifiManager.IFACE_IP_MODE_TETHERED: - softApEventList = mSoftApEventListTethered; - break; - case WifiManager.IFACE_IP_MODE_LOCAL_ONLY: - softApEventList = mSoftApEventListLocalOnly; - break; - default: - return; - } - - for (int index = softApEventList.size() - 1; index >= 0; index--) { - SoftApConnectedClientsEvent event = softApEventList.get(index); - if (event != null && event.eventType == SoftApConnectedClientsEvent.SOFT_AP_UP) { - event.maxNumClientsSettingInSoftapCapability = - capability.getMaxSupportedClients(); - break; - } - } - } - } - - /** - * Increment number of times the HAL crashed. - */ - public void incrementNumHalCrashes() { - synchronized (mLock) { - mWifiLogProto.numHalCrashes++; - } - } - - /** - * Increment number of times the Wificond crashed. - */ - public void incrementNumWificondCrashes() { - synchronized (mLock) { - mWifiLogProto.numWificondCrashes++; - } - } - - /** - * Increment number of times the supplicant crashed. - */ - public void incrementNumSupplicantCrashes() { - synchronized (mLock) { - mWifiLogProto.numSupplicantCrashes++; - } - } - - /** - * Increment number of times the hostapd crashed. - */ - public void incrementNumHostapdCrashes() { - synchronized (mLock) { - mWifiLogProto.numHostapdCrashes++; - } - } - - /** - * Increment number of times the wifi on failed due to an error in HAL. - */ - public void incrementNumSetupClientInterfaceFailureDueToHal() { - synchronized (mLock) { - mWifiLogProto.numSetupClientInterfaceFailureDueToHal++; - } - } - - /** - * Increment number of times the wifi on failed due to an error in wificond. - */ - public void incrementNumSetupClientInterfaceFailureDueToWificond() { - synchronized (mLock) { - mWifiLogProto.numSetupClientInterfaceFailureDueToWificond++; - } - } - - /** - * Increment number of times the wifi on failed due to an error in supplicant. - */ - public void incrementNumSetupClientInterfaceFailureDueToSupplicant() { - synchronized (mLock) { - mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant++; - } - } - - /** - * Increment number of times the SoftAp on failed due to an error in HAL. - */ - public void incrementNumSetupSoftApInterfaceFailureDueToHal() { - synchronized (mLock) { - mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal++; - } - } - - /** - * Increment number of times the SoftAp on failed due to an error in wificond. - */ - public void incrementNumSetupSoftApInterfaceFailureDueToWificond() { - synchronized (mLock) { - mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond++; - } - } - - /** - * Increment number of times the SoftAp on failed due to an error in hostapd. - */ - public void incrementNumSetupSoftApInterfaceFailureDueToHostapd() { - synchronized (mLock) { - mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd++; - } - } - - /** - * Increment number of times we got client interface down. - */ - public void incrementNumClientInterfaceDown() { - synchronized (mLock) { - mWifiLogProto.numClientInterfaceDown++; - } - } - - /** - * Increment number of times we got client interface down. - */ - public void incrementNumSoftApInterfaceDown() { - synchronized (mLock) { - mWifiLogProto.numSoftApInterfaceDown++; - } - } - - /** - * Increment number of times Passpoint provider being installed. - */ - public void incrementNumPasspointProviderInstallation() { - synchronized (mLock) { - mWifiLogProto.numPasspointProviderInstallation++; - } - } - - /** - * Increment number of times Passpoint provider is installed successfully. - */ - public void incrementNumPasspointProviderInstallSuccess() { - synchronized (mLock) { - mWifiLogProto.numPasspointProviderInstallSuccess++; - } - } - - /** - * Increment number of times Passpoint provider being uninstalled. - */ - public void incrementNumPasspointProviderUninstallation() { - synchronized (mLock) { - mWifiLogProto.numPasspointProviderUninstallation++; - } - } - - /** - * Increment number of times Passpoint provider is uninstalled successfully. - */ - public void incrementNumPasspointProviderUninstallSuccess() { - synchronized (mLock) { - mWifiLogProto.numPasspointProviderUninstallSuccess++; - } - } - - /** - * Increment number of Passpoint providers with no Root CA in their profile. - */ - public void incrementNumPasspointProviderWithNoRootCa() { - synchronized (mLock) { - mWifiLogProto.numPasspointProviderWithNoRootCa++; - } - } - - /** - * Increment number of Passpoint providers with a self-signed Root CA in their profile. - */ - public void incrementNumPasspointProviderWithSelfSignedRootCa() { - synchronized (mLock) { - mWifiLogProto.numPasspointProviderWithSelfSignedRootCa++; - } - } - - /** - * Increment number of Passpoint providers with subscription expiration date in their profile. - */ - public void incrementNumPasspointProviderWithSubscriptionExpiration() { - synchronized (mLock) { - mWifiLogProto.numPasspointProviderWithSubscriptionExpiration++; - } - } - - /** - * Increment number of times we detected a radio mode change to MCC. - */ - public void incrementNumRadioModeChangeToMcc() { - synchronized (mLock) { - mWifiLogProto.numRadioModeChangeToMcc++; - } - } - - /** - * Increment number of times we detected a radio mode change to SCC. - */ - public void incrementNumRadioModeChangeToScc() { - synchronized (mLock) { - mWifiLogProto.numRadioModeChangeToScc++; - } - } - - /** - * Increment number of times we detected a radio mode change to SBS. - */ - public void incrementNumRadioModeChangeToSbs() { - synchronized (mLock) { - mWifiLogProto.numRadioModeChangeToSbs++; - } - } - - /** - * Increment number of times we detected a radio mode change to DBS. - */ - public void incrementNumRadioModeChangeToDbs() { - synchronized (mLock) { - mWifiLogProto.numRadioModeChangeToDbs++; - } - } - - /** - * Increment number of times we detected a channel did not satisfy user band preference. - */ - public void incrementNumSoftApUserBandPreferenceUnsatisfied() { - synchronized (mLock) { - mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied++; - } - } - - /** - * Increment N-Way network selection decision histograms: - * Counts the size of various sets of scanDetails within a scan, and increment the occurrence - * of that size for the associated histogram. There are ten histograms generated for each - * combination of: {SSID, BSSID} *{Total, Saved, Open, Saved_or_Open, Passpoint} - * Only performs this count if isFullBand is true, otherwise, increments the partial scan count - */ - public void incrementAvailableNetworksHistograms(List<ScanDetail> scanDetails, - boolean isFullBand) { - synchronized (mLock) { - if (mWifiConfigManager == null || mWifiNetworkSelector == null - || mPasspointManager == null) { - return; - } - if (!isFullBand) { - mWifiLogProto.partialAllSingleScanListenerResults++; - return; - } - Set<ScanResultMatchInfo> ssids = new HashSet<ScanResultMatchInfo>(); - int bssids = 0; - Set<ScanResultMatchInfo> openSsids = new HashSet<ScanResultMatchInfo>(); - int openBssids = 0; - Set<ScanResultMatchInfo> savedSsids = new HashSet<ScanResultMatchInfo>(); - int savedBssids = 0; - // openOrSavedSsids calculated from union of savedSsids & openSsids - int openOrSavedBssids = 0; - Set<PasspointProvider> savedPasspointProviderProfiles = - new HashSet<PasspointProvider>(); - int savedPasspointProviderBssids = 0; - int passpointR1Aps = 0; - int passpointR2Aps = 0; - int passpointR3Aps = 0; - Map<ANQPNetworkKey, Integer> passpointR1UniqueEss = new HashMap<>(); - Map<ANQPNetworkKey, Integer> passpointR2UniqueEss = new HashMap<>(); - Map<ANQPNetworkKey, Integer> passpointR3UniqueEss = new HashMap<>(); - int supporting80211mcAps = 0; - for (ScanDetail scanDetail : scanDetails) { - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - ScanResult scanResult = scanDetail.getScanResult(); - - // statistics to be collected for ALL APs (irrespective of signal power) - if (networkDetail.is80211McResponderSupport()) { - supporting80211mcAps++; - } - - ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(scanResult); - List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = null; - if (networkDetail.isInterworking()) { - // Try to match provider, but do not allow new ANQP messages. Use cached data. - matchedProviders = mPasspointManager.matchProvider(scanResult, false); - if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) { - passpointR1Aps++; - } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) { - passpointR2Aps++; - } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) { - passpointR3Aps++; - } - - long bssid = 0; - boolean validBssid = false; - try { - bssid = Utils.parseMac(scanResult.BSSID); - validBssid = true; - } catch (IllegalArgumentException e) { - Log.e(TAG, - "Invalid BSSID provided in the scan result: " + scanResult.BSSID); - } - if (validBssid) { - ANQPNetworkKey uniqueEss = ANQPNetworkKey.buildKey(scanResult.SSID, bssid, - scanResult.hessid, networkDetail.getAnqpDomainID()); - if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) { - Integer countObj = passpointR1UniqueEss.get(uniqueEss); - int count = countObj == null ? 0 : countObj; - passpointR1UniqueEss.put(uniqueEss, count + 1); - } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) { - Integer countObj = passpointR2UniqueEss.get(uniqueEss); - int count = countObj == null ? 0 : countObj; - passpointR2UniqueEss.put(uniqueEss, count + 1); - } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) { - Integer countObj = passpointR3UniqueEss.get(uniqueEss); - int count = countObj == null ? 0 : countObj; - passpointR3UniqueEss.put(uniqueEss, count + 1); - } - } - } - - if (mWifiNetworkSelector.isSignalTooWeak(scanResult)) { - continue; - } - - // statistics to be collected ONLY for those APs with sufficient signal power - - ssids.add(matchInfo); - bssids++; - boolean isOpen = matchInfo.networkType == WifiConfiguration.SECURITY_TYPE_OPEN; - WifiConfiguration config = - mWifiConfigManager.getConfiguredNetworkForScanDetail(scanDetail); - boolean isSaved = (config != null) && !config.isEphemeral() - && !config.isPasspoint(); - if (isOpen) { - openSsids.add(matchInfo); - openBssids++; - } - if (isSaved) { - savedSsids.add(matchInfo); - savedBssids++; - } - if (isOpen || isSaved) { - openOrSavedBssids++; - // Calculate openOrSavedSsids union later - } - if (matchedProviders != null && !matchedProviders.isEmpty()) { - for (Pair<PasspointProvider, PasspointMatch> passpointProvider : - matchedProviders) { - savedPasspointProviderProfiles.add(passpointProvider.first); - } - savedPasspointProviderBssids++; - } - } - mWifiLogProto.fullBandAllSingleScanListenerResults++; - incrementTotalScanSsids(mTotalSsidsInScanHistogram, ssids.size()); - incrementTotalScanResults(mTotalBssidsInScanHistogram, bssids); - incrementSsid(mAvailableOpenSsidsInScanHistogram, openSsids.size()); - incrementBssid(mAvailableOpenBssidsInScanHistogram, openBssids); - incrementSsid(mAvailableSavedSsidsInScanHistogram, savedSsids.size()); - incrementBssid(mAvailableSavedBssidsInScanHistogram, savedBssids); - openSsids.addAll(savedSsids); // openSsids = Union(openSsids, savedSsids) - incrementSsid(mAvailableOpenOrSavedSsidsInScanHistogram, openSsids.size()); - incrementBssid(mAvailableOpenOrSavedBssidsInScanHistogram, openOrSavedBssids); - incrementSsid(mAvailableSavedPasspointProviderProfilesInScanHistogram, - savedPasspointProviderProfiles.size()); - incrementBssid(mAvailableSavedPasspointProviderBssidsInScanHistogram, - savedPasspointProviderBssids); - incrementTotalPasspointAps(mObservedHotspotR1ApInScanHistogram, passpointR1Aps); - incrementTotalPasspointAps(mObservedHotspotR2ApInScanHistogram, passpointR2Aps); - incrementTotalPasspointAps(mObservedHotspotR3ApInScanHistogram, passpointR3Aps); - incrementTotalUniquePasspointEss(mObservedHotspotR1EssInScanHistogram, - passpointR1UniqueEss.size()); - incrementTotalUniquePasspointEss(mObservedHotspotR2EssInScanHistogram, - passpointR2UniqueEss.size()); - incrementTotalUniquePasspointEss(mObservedHotspotR3EssInScanHistogram, - passpointR3UniqueEss.size()); - for (Integer count : passpointR1UniqueEss.values()) { - incrementPasspointPerUniqueEss(mObservedHotspotR1ApsPerEssInScanHistogram, count); - } - for (Integer count : passpointR2UniqueEss.values()) { - incrementPasspointPerUniqueEss(mObservedHotspotR2ApsPerEssInScanHistogram, count); - } - for (Integer count : passpointR3UniqueEss.values()) { - incrementPasspointPerUniqueEss(mObservedHotspotR3ApsPerEssInScanHistogram, count); - } - increment80211mcAps(mObserved80211mcApInScanHistogram, supporting80211mcAps); - } - } - - /** Increments the occurence of a "Connect to Network" notification. */ - public void incrementConnectToNetworkNotification(String notifierTag, int notificationType) { - synchronized (mLock) { - int count = mConnectToNetworkNotificationCount.get(notificationType); - mConnectToNetworkNotificationCount.put(notificationType, count + 1); - } - } - - /** Increments the occurence of an "Connect to Network" notification user action. */ - public void incrementConnectToNetworkNotificationAction(String notifierTag, - int notificationType, int actionType) { - synchronized (mLock) { - int key = notificationType * CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER - + actionType; - int count = mConnectToNetworkNotificationActionCount.get(key); - mConnectToNetworkNotificationActionCount.put(key, count + 1); - } - } - - /** - * Sets the number of SSIDs blacklisted from recommendation by the open network notification - * recommender. - */ - public void setNetworkRecommenderBlacklistSize(String notifierTag, int size) { - synchronized (mLock) { - mOpenNetworkRecommenderBlacklistSize = size; - } - } - - /** Sets if the available network notification feature is enabled. */ - public void setIsWifiNetworksAvailableNotificationEnabled(String notifierTag, boolean enabled) { - synchronized (mLock) { - mIsWifiNetworksAvailableNotificationOn = enabled; - } - } - - /** Increments the occurence of connection attempts that were initiated unsuccessfully */ - public void incrementNumNetworkRecommendationUpdates(String notifierTag) { - synchronized (mLock) { - mNumOpenNetworkRecommendationUpdates++; - } - } - - /** Increments the occurence of connection attempts that were initiated unsuccessfully */ - public void incrementNumNetworkConnectMessageFailedToSend(String notifierTag) { - synchronized (mLock) { - mNumOpenNetworkConnectMessageFailedToSend++; - } - } - - /** Log firmware alert related metrics */ - public void logFirmwareAlert(int errorCode) { - incrementAlertReasonCount(errorCode); - logWifiIsUnusableEvent(WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, errorCode); - addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_FIRMWARE_ALERT, errorCode); - } - - public static final String PROTO_DUMP_ARG = "wifiMetricsProto"; - public static final String CLEAN_DUMP_ARG = "clean"; - - /** - * Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager - * at this time. - * - * @param fd unused - * @param pw PrintWriter for writing dump to - * @param args [wifiMetricsProto [clean]] - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - synchronized (mLock) { - consolidateScoringParams(); - if (args != null && args.length > 0 && PROTO_DUMP_ARG.equals(args[0])) { - // Dump serialized WifiLog proto - consolidateProto(); - - byte[] wifiMetricsProto = WifiMetricsProto.WifiLog.toByteArray(mWifiLogProto); - String metricsProtoDump = Base64.encodeToString(wifiMetricsProto, Base64.DEFAULT); - if (args.length > 1 && CLEAN_DUMP_ARG.equals(args[1])) { - // Output metrics proto bytes (base64) and nothing else - pw.print(metricsProtoDump); - } else { - // Tag the start and end of the metrics proto bytes - pw.println("WifiMetrics:"); - pw.println(metricsProtoDump); - pw.println("EndWifiMetrics"); - } - clear(); - } else { - pw.println("WifiMetrics:"); - pw.println("mConnectionEvents:"); - for (ConnectionEvent event : mConnectionEventList) { - String eventLine = event.toString(); - if (event == mCurrentConnectionEvent) { - eventLine += " CURRENTLY OPEN EVENT"; - } - pw.println(eventLine); - } - pw.println("mWifiLogProto.numSavedNetworks=" + mWifiLogProto.numSavedNetworks); - pw.println("mWifiLogProto.numSavedNetworksWithMacRandomization=" - + mWifiLogProto.numSavedNetworksWithMacRandomization); - pw.println("mWifiLogProto.numOpenNetworks=" + mWifiLogProto.numOpenNetworks); - pw.println("mWifiLogProto.numLegacyPersonalNetworks=" - + mWifiLogProto.numLegacyPersonalNetworks); - pw.println("mWifiLogProto.numLegacyEnterpriseNetworks=" - + mWifiLogProto.numLegacyEnterpriseNetworks); - pw.println("mWifiLogProto.numEnhancedOpenNetworks=" - + mWifiLogProto.numEnhancedOpenNetworks); - pw.println("mWifiLogProto.numWpa3PersonalNetworks=" - + mWifiLogProto.numWpa3PersonalNetworks); - pw.println("mWifiLogProto.numWpa3EnterpriseNetworks=" - + mWifiLogProto.numWpa3EnterpriseNetworks); - pw.println("mWifiLogProto.numWapiPersonalNetworks=" - + mWifiLogProto.numWapiPersonalNetworks); - pw.println("mWifiLogProto.numWapiEnterpriseNetworks=" - + mWifiLogProto.numWapiEnterpriseNetworks); - pw.println("mWifiLogProto.numHiddenNetworks=" + mWifiLogProto.numHiddenNetworks); - pw.println("mWifiLogProto.numPasspointNetworks=" - + mWifiLogProto.numPasspointNetworks); - pw.println("mWifiLogProto.isLocationEnabled=" + mWifiLogProto.isLocationEnabled); - pw.println("mWifiLogProto.isScanningAlwaysEnabled=" - + mWifiLogProto.isScanningAlwaysEnabled); - pw.println("mWifiLogProto.isVerboseLoggingEnabled=" - + mWifiLogProto.isVerboseLoggingEnabled); - pw.println("mWifiLogProto.isEnhancedMacRandomizationForceEnabled=" - + mWifiLogProto.isEnhancedMacRandomizationForceEnabled); - pw.println("mWifiLogProto.isWifiWakeEnabled=" + mWifiLogProto.isWifiWakeEnabled); - pw.println("mWifiLogProto.numNetworksAddedByUser=" - + mWifiLogProto.numNetworksAddedByUser); - pw.println("mWifiLogProto.numNetworksAddedByApps=" - + mWifiLogProto.numNetworksAddedByApps); - pw.println("mWifiLogProto.numNonEmptyScanResults=" - + mWifiLogProto.numNonEmptyScanResults); - pw.println("mWifiLogProto.numEmptyScanResults=" - + mWifiLogProto.numEmptyScanResults); - pw.println("mWifiLogProto.numConnecitvityOneshotScans=" - + mWifiLogProto.numConnectivityOneshotScans); - pw.println("mWifiLogProto.numOneshotScans=" - + mWifiLogProto.numOneshotScans); - pw.println("mWifiLogProto.numOneshotHasDfsChannelScans=" - + mWifiLogProto.numOneshotHasDfsChannelScans); - pw.println("mWifiLogProto.numBackgroundScans=" - + mWifiLogProto.numBackgroundScans); - pw.println("mWifiLogProto.numExternalAppOneshotScanRequests=" - + mWifiLogProto.numExternalAppOneshotScanRequests); - pw.println("mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled=" - + mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled); - pw.println("mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled=" - + mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled); - pw.println("mWifiLogProto.meteredNetworkStatsSaved="); - pw.println(mMeteredNetworkStatsBuilder.toProto(false)); - pw.println("mWifiLogProto.meteredNetworkStatsSuggestion="); - pw.println(mMeteredNetworkStatsBuilder.toProto(true)); - pw.println("mScanReturnEntries:"); - pw.println(" SCAN_UNKNOWN: " + getScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_UNKNOWN)); - pw.println(" SCAN_SUCCESS: " + getScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_SUCCESS)); - pw.println(" SCAN_FAILURE_INTERRUPTED: " + getScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED)); - pw.println(" SCAN_FAILURE_INVALID_CONFIGURATION: " + getScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION)); - pw.println(" FAILURE_WIFI_DISABLED: " + getScanReturnEntry( - WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED)); - - pw.println("mSystemStateEntries: <state><screenOn> : <scansInitiated>"); - pw.println(" WIFI_UNKNOWN ON: " - + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true)); - pw.println(" WIFI_DISABLED ON: " - + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, true)); - pw.println(" WIFI_DISCONNECTED ON: " - + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, true)); - pw.println(" WIFI_ASSOCIATED ON: " - + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true)); - pw.println(" WIFI_UNKNOWN OFF: " - + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false)); - pw.println(" WIFI_DISABLED OFF: " - + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, false)); - pw.println(" WIFI_DISCONNECTED OFF: " - + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, false)); - pw.println(" WIFI_ASSOCIATED OFF: " - + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false)); - pw.println("mWifiLogProto.numConnectivityWatchdogPnoGood=" - + mWifiLogProto.numConnectivityWatchdogPnoGood); - pw.println("mWifiLogProto.numConnectivityWatchdogPnoBad=" - + mWifiLogProto.numConnectivityWatchdogPnoBad); - pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundGood=" - + mWifiLogProto.numConnectivityWatchdogBackgroundGood); - pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundBad=" - + mWifiLogProto.numConnectivityWatchdogBackgroundBad); - pw.println("mWifiLogProto.numLastResortWatchdogTriggers=" - + mWifiLogProto.numLastResortWatchdogTriggers); - pw.println("mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal=" - + mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal); - pw.println("mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal=" - + mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal); - pw.println("mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal=" - + mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal); - pw.println("mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal=" - + mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal); - pw.println("mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal=" - + mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal); - pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation=" - + mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation); - pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication=" - + mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication); - pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp=" - + mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp); - pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadOther=" - + mWifiLogProto.numLastResortWatchdogTriggersWithBadOther); - pw.println("mWifiLogProto.numLastResortWatchdogSuccesses=" - + mWifiLogProto.numLastResortWatchdogSuccesses); - pw.println("mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger=" - + mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger); - pw.println("mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs=" - + mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs); - pw.println("mWifiLogProto.recordDurationSec=" - + ((mClock.getElapsedSinceBootMillis() / 1000) - mRecordStartTimeSec)); - - try { - JSONObject rssiMap = new JSONObject(); - for (Map.Entry<Integer, SparseIntArray> entry : mRssiPollCountsMap.entrySet()) { - int frequency = entry.getKey(); - final SparseIntArray histogram = entry.getValue(); - JSONArray histogramElements = new JSONArray(); - for (int i = MIN_RSSI_POLL; i <= MAX_RSSI_POLL; i++) { - int count = histogram.get(i); - if (count == 0) { - continue; - } - JSONObject histogramElement = new JSONObject(); - histogramElement.put(Integer.toString(i), count); - histogramElements.put(histogramElement); - } - rssiMap.put(Integer.toString(frequency), histogramElements); - } - pw.println("mWifiLogProto.rssiPollCount: " + rssiMap.toString()); - } catch (JSONException e) { - pw.println("JSONException occurred: " + e.getMessage()); - } - - pw.println("mWifiLogProto.rssiPollDeltaCount: Printing counts for [" - + MIN_RSSI_DELTA + ", " + MAX_RSSI_DELTA + "]"); - StringBuilder sb = new StringBuilder(); - for (int i = MIN_RSSI_DELTA; i <= MAX_RSSI_DELTA; i++) { - sb.append(mRssiDeltaCounts.get(i) + " "); - } - pw.println(" " + sb.toString()); - pw.println("mWifiLogProto.linkSpeedCounts: "); - sb.setLength(0); - for (int i = 0; i < mLinkSpeedCounts.size(); i++) { - LinkSpeedCount linkSpeedCount = mLinkSpeedCounts.valueAt(i); - sb.append(linkSpeedCount.linkSpeedMbps).append(":{") - .append(linkSpeedCount.count).append(", ") - .append(linkSpeedCount.rssiSumDbm).append(", ") - .append(linkSpeedCount.rssiSumOfSquaresDbmSq).append("} "); - } - if (sb.length() > 0) { - pw.println(sb.toString()); - } - pw.print("mWifiLogProto.alertReasonCounts="); - sb.setLength(0); - for (int i = WifiLoggerHal.WIFI_ALERT_REASON_MIN; - i <= WifiLoggerHal.WIFI_ALERT_REASON_MAX; i++) { - int count = mWifiAlertReasonCounts.get(i); - if (count > 0) { - sb.append("(" + i + "," + count + "),"); - } - } - if (sb.length() > 1) { - sb.setLength(sb.length() - 1); // strip trailing comma - pw.println(sb.toString()); - } else { - pw.println("()"); - } - pw.println("mWifiLogProto.numTotalScanResults=" - + mWifiLogProto.numTotalScanResults); - pw.println("mWifiLogProto.numOpenNetworkScanResults=" - + mWifiLogProto.numOpenNetworkScanResults); - pw.println("mWifiLogProto.numLegacyPersonalNetworkScanResults=" - + mWifiLogProto.numLegacyPersonalNetworkScanResults); - pw.println("mWifiLogProto.numLegacyEnterpriseNetworkScanResults=" - + mWifiLogProto.numLegacyEnterpriseNetworkScanResults); - pw.println("mWifiLogProto.numEnhancedOpenNetworkScanResults=" - + mWifiLogProto.numEnhancedOpenNetworkScanResults); - pw.println("mWifiLogProto.numWpa3PersonalNetworkScanResults=" - + mWifiLogProto.numWpa3PersonalNetworkScanResults); - pw.println("mWifiLogProto.numWpa3EnterpriseNetworkScanResults=" - + mWifiLogProto.numWpa3EnterpriseNetworkScanResults); - pw.println("mWifiLogProto.numWapiPersonalNetworkScanResults=" - + mWifiLogProto.numWapiPersonalNetworkScanResults); - pw.println("mWifiLogProto.numWapiEnterpriseNetworkScanResults=" - + mWifiLogProto.numWapiEnterpriseNetworkScanResults); - pw.println("mWifiLogProto.numHiddenNetworkScanResults=" - + mWifiLogProto.numHiddenNetworkScanResults); - pw.println("mWifiLogProto.numHotspot2R1NetworkScanResults=" - + mWifiLogProto.numHotspot2R1NetworkScanResults); - pw.println("mWifiLogProto.numHotspot2R2NetworkScanResults=" - + mWifiLogProto.numHotspot2R2NetworkScanResults); - pw.println("mWifiLogProto.numHotspot2R3NetworkScanResults=" - + mWifiLogProto.numHotspot2R3NetworkScanResults); - pw.println("mWifiLogProto.numMboSupportedNetworkScanResults=" - + mWifiLogProto.numMboSupportedNetworkScanResults); - pw.println("mWifiLogProto.numMboCellularDataAwareNetworkScanResults=" - + mWifiLogProto.numMboCellularDataAwareNetworkScanResults); - pw.println("mWifiLogProto.numOceSupportedNetworkScanResults=" - + mWifiLogProto.numOceSupportedNetworkScanResults); - pw.println("mWifiLogProto.numFilsSupportedNetworkScanResults=" - + mWifiLogProto.numFilsSupportedNetworkScanResults); - pw.println("mWifiLogProto.num11AxNetworkScanResults=" - + mWifiLogProto.num11AxNetworkScanResults); - pw.println("mWifiLogProto.num6GNetworkScanResults" - + mWifiLogProto.num6GNetworkScanResults); - pw.println("mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd=" - + mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd); - pw.println("mWifiLogProto.numConnectToNetworkSupportingMbo=" - + mWifiLogProto.numConnectToNetworkSupportingMbo); - pw.println("mWifiLogProto.numConnectToNetworkSupportingOce=" - + mWifiLogProto.numConnectToNetworkSupportingOce); - pw.println("mWifiLogProto.numForceScanDueToSteeringRequest=" - + mWifiLogProto.numForceScanDueToSteeringRequest); - pw.println("mWifiLogProto.numMboCellularSwitchRequest=" - + mWifiLogProto.numMboCellularSwitchRequest); - pw.println("mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay=" - + mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay); - pw.println("mWifiLogProto.numConnectRequestWithFilsAkm=" - + mWifiLogProto.numConnectRequestWithFilsAkm); - pw.println("mWifiLogProto.numL2ConnectionThroughFilsAuthentication=" - + mWifiLogProto.numL2ConnectionThroughFilsAuthentication); - - pw.println("mWifiLogProto.numScans=" + mWifiLogProto.numScans); - pw.println("mWifiLogProto.WifiScoreCount: [" + MIN_WIFI_SCORE + ", " - + MAX_WIFI_SCORE + "]"); - for (int i = 0; i <= MAX_WIFI_SCORE; i++) { - pw.print(mWifiScoreCounts.get(i) + " "); - } - pw.println(); // add a line after wifi scores - pw.println("mWifiLogProto.WifiUsabilityScoreCount: [" + MIN_WIFI_USABILITY_SCORE - + ", " + MAX_WIFI_USABILITY_SCORE + "]"); - for (int i = MIN_WIFI_USABILITY_SCORE; i <= MAX_WIFI_USABILITY_SCORE; i++) { - pw.print(mWifiUsabilityScoreCounts.get(i) + " "); - } - pw.println(); // add a line after wifi usability scores - pw.println("mWifiLogProto.SoftApManagerReturnCodeCounts:"); - pw.println(" SUCCESS: " + mSoftApManagerReturnCodeCounts.get( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY)); - pw.println(" FAILED_GENERAL_ERROR: " + mSoftApManagerReturnCodeCounts.get( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR)); - pw.println(" FAILED_NO_CHANNEL: " + mSoftApManagerReturnCodeCounts.get( - WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL)); - pw.println(" FAILED_UNSUPPORTED_CONFIGURATION: " - + mSoftApManagerReturnCodeCounts.get( - WifiMetricsProto.SoftApReturnCodeCount - .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION)); - pw.print("\n"); - pw.println("mWifiLogProto.numHalCrashes=" - + mWifiLogProto.numHalCrashes); - pw.println("mWifiLogProto.numWificondCrashes=" - + mWifiLogProto.numWificondCrashes); - pw.println("mWifiLogProto.numSupplicantCrashes=" - + mWifiLogProto.numSupplicantCrashes); - pw.println("mWifiLogProto.numHostapdCrashes=" - + mWifiLogProto.numHostapdCrashes); - pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToHal=" - + mWifiLogProto.numSetupClientInterfaceFailureDueToHal); - pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToWificond=" - + mWifiLogProto.numSetupClientInterfaceFailureDueToWificond); - pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant=" - + mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant); - pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal=" - + mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal); - pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond=" - + mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond); - pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd=" - + mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd); - pw.println("StaEventList:"); - for (StaEventWithTime event : mStaEventList) { - pw.println(event); - } - pw.println("UserActionEvents:"); - for (UserActionEventWithTime event : mUserActionEventList) { - pw.println(event); - } - - pw.println("mWifiLogProto.numPasspointProviders=" - + mWifiLogProto.numPasspointProviders); - pw.println("mWifiLogProto.numPasspointProviderInstallation=" - + mWifiLogProto.numPasspointProviderInstallation); - pw.println("mWifiLogProto.numPasspointProviderInstallSuccess=" - + mWifiLogProto.numPasspointProviderInstallSuccess); - pw.println("mWifiLogProto.numPasspointProviderUninstallation=" - + mWifiLogProto.numPasspointProviderUninstallation); - pw.println("mWifiLogProto.numPasspointProviderUninstallSuccess=" - + mWifiLogProto.numPasspointProviderUninstallSuccess); - pw.println("mWifiLogProto.numPasspointProvidersSuccessfullyConnected=" - + mWifiLogProto.numPasspointProvidersSuccessfullyConnected); - - pw.println("mWifiLogProto.installedPasspointProfileTypeForR1:" - + mInstalledPasspointProfileTypeForR1); - pw.println("mWifiLogProto.installedPasspointProfileTypeForR2:" - + mInstalledPasspointProfileTypeForR2); - - pw.println("mWifiLogProto.passpointProvisionStats.numProvisionSuccess=" - + mNumProvisionSuccess); - pw.println("mWifiLogProto.passpointProvisionStats.provisionFailureCount:" - + mPasspointProvisionFailureCounts); - - pw.println("mWifiLogProto.numRadioModeChangeToMcc=" - + mWifiLogProto.numRadioModeChangeToMcc); - pw.println("mWifiLogProto.numRadioModeChangeToScc=" - + mWifiLogProto.numRadioModeChangeToScc); - pw.println("mWifiLogProto.numRadioModeChangeToSbs=" - + mWifiLogProto.numRadioModeChangeToSbs); - pw.println("mWifiLogProto.numRadioModeChangeToDbs=" - + mWifiLogProto.numRadioModeChangeToDbs); - pw.println("mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied=" - + mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied); - pw.println("mTotalSsidsInScanHistogram:" - + mTotalSsidsInScanHistogram.toString()); - pw.println("mTotalBssidsInScanHistogram:" - + mTotalBssidsInScanHistogram.toString()); - pw.println("mAvailableOpenSsidsInScanHistogram:" - + mAvailableOpenSsidsInScanHistogram.toString()); - pw.println("mAvailableOpenBssidsInScanHistogram:" - + mAvailableOpenBssidsInScanHistogram.toString()); - pw.println("mAvailableSavedSsidsInScanHistogram:" - + mAvailableSavedSsidsInScanHistogram.toString()); - pw.println("mAvailableSavedBssidsInScanHistogram:" - + mAvailableSavedBssidsInScanHistogram.toString()); - pw.println("mAvailableOpenOrSavedSsidsInScanHistogram:" - + mAvailableOpenOrSavedSsidsInScanHistogram.toString()); - pw.println("mAvailableOpenOrSavedBssidsInScanHistogram:" - + mAvailableOpenOrSavedBssidsInScanHistogram.toString()); - pw.println("mAvailableSavedPasspointProviderProfilesInScanHistogram:" - + mAvailableSavedPasspointProviderProfilesInScanHistogram.toString()); - pw.println("mAvailableSavedPasspointProviderBssidsInScanHistogram:" - + mAvailableSavedPasspointProviderBssidsInScanHistogram.toString()); - pw.println("mWifiLogProto.partialAllSingleScanListenerResults=" - + mWifiLogProto.partialAllSingleScanListenerResults); - pw.println("mWifiLogProto.fullBandAllSingleScanListenerResults=" - + mWifiLogProto.fullBandAllSingleScanListenerResults); - pw.println("mWifiAwareMetrics:"); - mWifiAwareMetrics.dump(fd, pw, args); - pw.println("mRttMetrics:"); - mRttMetrics.dump(fd, pw, args); - - pw.println("mPnoScanMetrics.numPnoScanAttempts=" - + mPnoScanMetrics.numPnoScanAttempts); - pw.println("mPnoScanMetrics.numPnoScanFailed=" - + mPnoScanMetrics.numPnoScanFailed); - pw.println("mPnoScanMetrics.numPnoScanStartedOverOffload=" - + mPnoScanMetrics.numPnoScanStartedOverOffload); - pw.println("mPnoScanMetrics.numPnoScanFailedOverOffload=" - + mPnoScanMetrics.numPnoScanFailedOverOffload); - pw.println("mPnoScanMetrics.numPnoFoundNetworkEvents=" - + mPnoScanMetrics.numPnoFoundNetworkEvents); - - pw.println("mWifiLinkLayerUsageStats.loggingDurationMs=" - + mWifiLinkLayerUsageStats.loggingDurationMs); - pw.println("mWifiLinkLayerUsageStats.radioOnTimeMs=" - + mWifiLinkLayerUsageStats.radioOnTimeMs); - pw.println("mWifiLinkLayerUsageStats.radioTxTimeMs=" - + mWifiLinkLayerUsageStats.radioTxTimeMs); - pw.println("mWifiLinkLayerUsageStats.radioRxTimeMs=" - + mWifiLinkLayerUsageStats.radioRxTimeMs); - pw.println("mWifiLinkLayerUsageStats.radioScanTimeMs=" - + mWifiLinkLayerUsageStats.radioScanTimeMs); - pw.println("mWifiLinkLayerUsageStats.radioNanScanTimeMs=" - + mWifiLinkLayerUsageStats.radioNanScanTimeMs); - pw.println("mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs=" - + mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs); - pw.println("mWifiLinkLayerUsageStats.radioRoamScanTimeMs=" - + mWifiLinkLayerUsageStats.radioRoamScanTimeMs); - pw.println("mWifiLinkLayerUsageStats.radioPnoScanTimeMs=" - + mWifiLinkLayerUsageStats.radioPnoScanTimeMs); - pw.println("mWifiLinkLayerUsageStats.radioHs20ScanTimeMs=" - + mWifiLinkLayerUsageStats.radioHs20ScanTimeMs); - - pw.println("mWifiLogProto.connectToNetworkNotificationCount=" - + mConnectToNetworkNotificationCount.toString()); - pw.println("mWifiLogProto.connectToNetworkNotificationActionCount=" - + mConnectToNetworkNotificationActionCount.toString()); - pw.println("mWifiLogProto.openNetworkRecommenderBlacklistSize=" - + mOpenNetworkRecommenderBlacklistSize); - pw.println("mWifiLogProto.isWifiNetworksAvailableNotificationOn=" - + mIsWifiNetworksAvailableNotificationOn); - pw.println("mWifiLogProto.numOpenNetworkRecommendationUpdates=" - + mNumOpenNetworkRecommendationUpdates); - pw.println("mWifiLogProto.numOpenNetworkConnectMessageFailedToSend=" - + mNumOpenNetworkConnectMessageFailedToSend); - - pw.println("mWifiLogProto.observedHotspotR1ApInScanHistogram=" - + mObservedHotspotR1ApInScanHistogram); - pw.println("mWifiLogProto.observedHotspotR2ApInScanHistogram=" - + mObservedHotspotR2ApInScanHistogram); - pw.println("mWifiLogProto.observedHotspotR3ApInScanHistogram=" - + mObservedHotspotR3ApInScanHistogram); - pw.println("mWifiLogProto.observedHotspotR1EssInScanHistogram=" - + mObservedHotspotR1EssInScanHistogram); - pw.println("mWifiLogProto.observedHotspotR2EssInScanHistogram=" - + mObservedHotspotR2EssInScanHistogram); - pw.println("mWifiLogProto.observedHotspotR3EssInScanHistogram=" - + mObservedHotspotR3EssInScanHistogram); - pw.println("mWifiLogProto.observedHotspotR1ApsPerEssInScanHistogram=" - + mObservedHotspotR1ApsPerEssInScanHistogram); - pw.println("mWifiLogProto.observedHotspotR2ApsPerEssInScanHistogram=" - + mObservedHotspotR2ApsPerEssInScanHistogram); - pw.println("mWifiLogProto.observedHotspotR3ApsPerEssInScanHistogram=" - + mObservedHotspotR3ApsPerEssInScanHistogram); - - pw.println("mWifiLogProto.observed80211mcSupportingApsInScanHistogram" - + mObserved80211mcApInScanHistogram); - pw.println("mWifiLogProto.bssidBlocklistStats:"); - pw.println(mBssidBlocklistStats.toString()); - - pw.println("mSoftApTetheredEvents:"); - for (SoftApConnectedClientsEvent event : mSoftApEventListTethered) { - StringBuilder eventLine = new StringBuilder(); - eventLine.append("event_type=" + event.eventType); - eventLine.append(",time_stamp_millis=" + event.timeStampMillis); - eventLine.append(",num_connected_clients=" + event.numConnectedClients); - eventLine.append(",channel_frequency=" + event.channelFrequency); - eventLine.append(",channel_bandwidth=" + event.channelBandwidth); - eventLine.append(",max_num_clients_setting_in_softap_configuration=" - + event.maxNumClientsSettingInSoftapConfiguration); - eventLine.append(",max_num_clients_setting_in_softap_capability=" - + event.maxNumClientsSettingInSoftapCapability); - eventLine.append(",shutdown_timeout_setting_in_softap_configuration=" - + event.shutdownTimeoutSettingInSoftapConfiguration); - eventLine.append(",default_shutdown_timeout_setting=" - + event.defaultShutdownTimeoutSetting); - eventLine.append(",client_control_is_enabled=" + event.clientControlIsEnabled); - pw.println(eventLine.toString()); - } - pw.println("mSoftApLocalOnlyEvents:"); - for (SoftApConnectedClientsEvent event : mSoftApEventListLocalOnly) { - StringBuilder eventLine = new StringBuilder(); - eventLine.append("event_type=" + event.eventType); - eventLine.append(",time_stamp_millis=" + event.timeStampMillis); - eventLine.append(",num_connected_clients=" + event.numConnectedClients); - eventLine.append(",channel_frequency=" + event.channelFrequency); - eventLine.append(",channel_bandwidth=" + event.channelBandwidth); - eventLine.append(",max_num_clients_setting_in_softap_configuration=" - + event.maxNumClientsSettingInSoftapConfiguration); - eventLine.append(",max_num_clients_setting_in_softap_capability=" - + event.maxNumClientsSettingInSoftapCapability); - eventLine.append(",shutdown_timeout_setting_in_softap_configuration=" - + event.shutdownTimeoutSettingInSoftapConfiguration); - eventLine.append(",default_shutdown_timeout_setting=" - + event.defaultShutdownTimeoutSetting); - eventLine.append(",client_control_is_enabled=" + event.clientControlIsEnabled); - pw.println(eventLine.toString()); - } - - mWifiPowerMetrics.dump(pw); - mWifiWakeMetrics.dump(pw); - - pw.println("mWifiLogProto.isMacRandomizationOn=" - + mContext.getResources().getBoolean( - R.bool.config_wifi_connected_mac_randomization_supported)); - pw.println("mWifiLogProto.scoreExperimentId=" + mWifiLogProto.scoreExperimentId); - pw.println("mExperimentValues.wifiIsUnusableLoggingEnabled=" - + mContext.getResources().getBoolean( - R.bool.config_wifiIsUnusableEventMetricsEnabled)); - pw.println("mExperimentValues.wifiDataStallMinTxBad=" - + mContext.getResources().getInteger( - R.integer.config_wifiDataStallMinTxBad)); - pw.println("mExperimentValues.wifiDataStallMinTxSuccessWithoutRx=" - + mContext.getResources().getInteger( - R.integer.config_wifiDataStallMinTxSuccessWithoutRx)); - pw.println("mExperimentValues.linkSpeedCountsLoggingEnabled=" - + mContext.getResources().getBoolean( - R.bool.config_wifiLinkSpeedMetricsEnabled)); - pw.println("mExperimentValues.dataStallDurationMs=" - + mExperimentValues.dataStallDurationMs); - pw.println("mExperimentValues.dataStallTxTputThrKbps=" - + mExperimentValues.dataStallTxTputThrKbps); - pw.println("mExperimentValues.dataStallRxTputThrKbps=" - + mExperimentValues.dataStallRxTputThrKbps); - pw.println("mExperimentValues.dataStallTxPerThr=" - + mExperimentValues.dataStallTxPerThr); - pw.println("mExperimentValues.dataStallCcaLevelThr=" - + mExperimentValues.dataStallCcaLevelThr); - pw.println("WifiIsUnusableEventList: "); - for (WifiIsUnusableWithTime event : mWifiIsUnusableList) { - pw.println(event); - } - pw.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", "")); - - pw.println("mWifiUsabilityStatsEntriesList:"); - for (WifiUsabilityStatsEntry stats : mWifiUsabilityStatsEntriesList) { - printWifiUsabilityStatsEntry(pw, stats); - } - pw.println("mWifiUsabilityStatsList:"); - for (WifiUsabilityStats stats : mWifiUsabilityStatsListGood) { - pw.println("\nlabel=" + stats.label); - pw.println("\ntrigger_type=" + stats.triggerType); - pw.println("\ntime_stamp_ms=" + stats.timeStampMs); - for (WifiUsabilityStatsEntry entry : stats.stats) { - printWifiUsabilityStatsEntry(pw, entry); - } - } - for (WifiUsabilityStats stats : mWifiUsabilityStatsListBad) { - pw.println("\nlabel=" + stats.label); - pw.println("\ntrigger_type=" + stats.triggerType); - pw.println("\ntime_stamp_ms=" + stats.timeStampMs); - for (WifiUsabilityStatsEntry entry : stats.stats) { - printWifiUsabilityStatsEntry(pw, entry); - } - } - - pw.println("mMobilityStatePnoStatsMap:"); - for (int i = 0; i < mMobilityStatePnoStatsMap.size(); i++) { - printDeviceMobilityStatePnoScanStats(pw, mMobilityStatePnoStatsMap.valueAt(i)); - } - - mWifiP2pMetrics.dump(pw); - pw.println("mDppMetrics:"); - mDppMetrics.dump(pw); - - pw.println("mWifiConfigStoreReadDurationHistogram:" - + mWifiConfigStoreReadDurationHistogram.toString()); - pw.println("mWifiConfigStoreWriteDurationHistogram:" - + mWifiConfigStoreWriteDurationHistogram.toString()); - - pw.println("mLinkProbeSuccessRssiCounts:" + mLinkProbeSuccessRssiCounts); - pw.println("mLinkProbeFailureRssiCounts:" + mLinkProbeFailureRssiCounts); - pw.println("mLinkProbeSuccessLinkSpeedCounts:" + mLinkProbeSuccessLinkSpeedCounts); - pw.println("mLinkProbeFailureLinkSpeedCounts:" + mLinkProbeFailureLinkSpeedCounts); - pw.println("mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram:" - + mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram); - pw.println("mLinkProbeFailureSecondsSinceLastTxSuccessHistogram:" - + mLinkProbeFailureSecondsSinceLastTxSuccessHistogram); - pw.println("mLinkProbeSuccessElapsedTimeMsHistogram:" - + mLinkProbeSuccessElapsedTimeMsHistogram); - pw.println("mLinkProbeFailureReasonCounts:" + mLinkProbeFailureReasonCounts); - pw.println("mLinkProbeExperimentProbeCounts:" + mLinkProbeExperimentProbeCounts); - - pw.println("mNetworkSelectionExperimentPairNumChoicesCounts:" - + mNetworkSelectionExperimentPairNumChoicesCounts); - pw.println("mLinkProbeStaEventCount:" + mLinkProbeStaEventCount); - - pw.println("mWifiNetworkRequestApiLog:\n" + mWifiNetworkRequestApiLog); - pw.println("mWifiNetworkRequestApiMatchSizeHistogram:\n" - + mWifiNetworkRequestApiMatchSizeHistogram); - pw.println("mWifiNetworkSuggestionApiLog:\n" + mWifiNetworkSuggestionApiLog); - pw.println("mWifiNetworkSuggestionApiMatchSizeHistogram:\n" - + mWifiNetworkSuggestionApiListSizeHistogram); - pw.println("mWifiNetworkSuggestionApiAppTypeCounter:\n" - + mWifiNetworkSuggestionApiAppTypeCounter); - printUserApprovalSuggestionAppReaction(pw); - printUserApprovalCarrierReaction(pw); - pw.println("mNetworkIdToNominatorId:\n" + mNetworkIdToNominatorId); - pw.println("mWifiLockStats:\n" + mWifiLockStats); - pw.println("mWifiLockHighPerfAcqDurationSecHistogram:\n" - + mWifiLockHighPerfAcqDurationSecHistogram); - pw.println("mWifiLockLowLatencyAcqDurationSecHistogram:\n" - + mWifiLockLowLatencyAcqDurationSecHistogram); - pw.println("mWifiLockHighPerfActiveSessionDurationSecHistogram:\n" - + mWifiLockHighPerfActiveSessionDurationSecHistogram); - pw.println("mWifiLockLowLatencyActiveSessionDurationSecHistogram:\n" - + mWifiLockLowLatencyActiveSessionDurationSecHistogram); - pw.println("mWifiToggleStats:\n" + mWifiToggleStats); - pw.println("mWifiLogProto.numAddOrUpdateNetworkCalls=" - + mWifiLogProto.numAddOrUpdateNetworkCalls); - pw.println("mWifiLogProto.numEnableNetworkCalls=" - + mWifiLogProto.numEnableNetworkCalls); - - pw.println("mWifiLogProto.txLinkSpeedCount2g=" + mTxLinkSpeedCount2g); - pw.println("mWifiLogProto.txLinkSpeedCount5gLow=" + mTxLinkSpeedCount5gLow); - pw.println("mWifiLogProto.txLinkSpeedCount5gMid=" + mTxLinkSpeedCount5gMid); - pw.println("mWifiLogProto.txLinkSpeedCount5gHigh=" + mTxLinkSpeedCount5gHigh); - pw.println("mWifiLogProto.txLinkSpeedCount6gLow=" + mTxLinkSpeedCount6gLow); - pw.println("mWifiLogProto.txLinkSpeedCount6gMid=" + mTxLinkSpeedCount6gMid); - pw.println("mWifiLogProto.txLinkSpeedCount6gHigh=" + mTxLinkSpeedCount6gHigh); - - pw.println("mWifiLogProto.rxLinkSpeedCount2g=" + mRxLinkSpeedCount2g); - pw.println("mWifiLogProto.rxLinkSpeedCount5gLow=" + mRxLinkSpeedCount5gLow); - pw.println("mWifiLogProto.rxLinkSpeedCount5gMid=" + mRxLinkSpeedCount5gMid); - pw.println("mWifiLogProto.rxLinkSpeedCount5gHigh=" + mRxLinkSpeedCount5gHigh); - pw.println("mWifiLogProto.rxLinkSpeedCount6gLow=" + mRxLinkSpeedCount6gLow); - pw.println("mWifiLogProto.rxLinkSpeedCount6gMid=" + mRxLinkSpeedCount6gMid); - pw.println("mWifiLogProto.rxLinkSpeedCount6gHigh=" + mRxLinkSpeedCount6gHigh); - - pw.println("mWifiLogProto.numIpRenewalFailure=" - + mWifiLogProto.numIpRenewalFailure); - pw.println("mWifiLogProto.connectionDurationStats=" - + mConnectionDurationStats.toString()); - pw.println("mWifiLogProto.isExternalWifiScorerOn=" - + mWifiLogProto.isExternalWifiScorerOn); - pw.println("mWifiLogProto.wifiOffMetrics=" - + mWifiOffMetrics.toString()); - pw.println("mWifiLogProto.softApConfigLimitationMetrics=" - + mSoftApConfigLimitationMetrics.toString()); - pw.println("mChannelUtilizationHistogram2G:\n" - + mChannelUtilizationHistogram2G); - pw.println("mChannelUtilizationHistogramAbove2G:\n" - + mChannelUtilizationHistogramAbove2G); - pw.println("mTxThroughputMbpsHistogram2G:\n" - + mTxThroughputMbpsHistogram2G); - pw.println("mRxThroughputMbpsHistogram2G:\n" - + mRxThroughputMbpsHistogram2G); - pw.println("mTxThroughputMbpsHistogramAbove2G:\n" - + mTxThroughputMbpsHistogramAbove2G); - pw.println("mRxThroughputMbpsHistogramAbove2G:\n" - + mRxThroughputMbpsHistogramAbove2G); - pw.println("mCarrierWifiMetrics:\n" - + mCarrierWifiMetrics); - - dumpInitPartialScanMetrics(pw); - } - } - } - - private void dumpInitPartialScanMetrics(PrintWriter pw) { - pw.println("mInitPartialScanTotalCount:\n" + mInitPartialScanTotalCount); - pw.println("mInitPartialScanSuccessCount:\n" + mInitPartialScanSuccessCount); - pw.println("mInitPartialScanFailureCount:\n" + mInitPartialScanFailureCount); - pw.println("mInitPartialScanSuccessHistogram:\n" + mInitPartialScanSuccessHistogram); - pw.println("mInitPartialScanFailureHistogram:\n" + mInitPartialScanFailureHistogram); - } - - private void printWifiUsabilityStatsEntry(PrintWriter pw, WifiUsabilityStatsEntry entry) { - StringBuilder line = new StringBuilder(); - line.append("timestamp_ms=" + entry.timeStampMs); - line.append(",rssi=" + entry.rssi); - line.append(",link_speed_mbps=" + entry.linkSpeedMbps); - line.append(",total_tx_success=" + entry.totalTxSuccess); - line.append(",total_tx_retries=" + entry.totalTxRetries); - line.append(",total_tx_bad=" + entry.totalTxBad); - line.append(",total_rx_success=" + entry.totalRxSuccess); - line.append(",total_radio_on_time_ms=" + entry.totalRadioOnTimeMs); - line.append(",total_radio_tx_time_ms=" + entry.totalRadioTxTimeMs); - line.append(",total_radio_rx_time_ms=" + entry.totalRadioRxTimeMs); - line.append(",total_scan_time_ms=" + entry.totalScanTimeMs); - line.append(",total_nan_scan_time_ms=" + entry.totalNanScanTimeMs); - line.append(",total_background_scan_time_ms=" + entry.totalBackgroundScanTimeMs); - line.append(",total_roam_scan_time_ms=" + entry.totalRoamScanTimeMs); - line.append(",total_pno_scan_time_ms=" + entry.totalPnoScanTimeMs); - line.append(",total_hotspot_2_scan_time_ms=" + entry.totalHotspot2ScanTimeMs); - line.append(",wifi_score=" + entry.wifiScore); - line.append(",wifi_usability_score=" + entry.wifiUsabilityScore); - line.append(",seq_num_to_framework=" + entry.seqNumToFramework); - line.append(",prediction_horizon_sec=" + entry.predictionHorizonSec); - line.append(",total_cca_busy_freq_time_ms=" + entry.totalCcaBusyFreqTimeMs); - line.append(",total_radio_on_freq_time_ms=" + entry.totalRadioOnFreqTimeMs); - line.append(",total_beacon_rx=" + entry.totalBeaconRx); - line.append(",probe_status_since_last_update=" + entry.probeStatusSinceLastUpdate); - line.append(",probe_elapsed_time_ms_since_last_update=" - + entry.probeElapsedTimeSinceLastUpdateMs); - line.append(",probe_mcs_rate_since_last_update=" + entry.probeMcsRateSinceLastUpdate); - line.append(",rx_link_speed_mbps=" + entry.rxLinkSpeedMbps); - line.append(",seq_num_inside_framework=" + entry.seqNumInsideFramework); - line.append(",is_same_bssid_and_freq=" + entry.isSameBssidAndFreq); - line.append(",device_mobility_state=" + entry.deviceMobilityState); - pw.println(line.toString()); - } - - private void printDeviceMobilityStatePnoScanStats(PrintWriter pw, - DeviceMobilityStatePnoScanStats stats) { - StringBuilder line = new StringBuilder(); - line.append("device_mobility_state=" + stats.deviceMobilityState); - line.append(",num_times_entered_state=" + stats.numTimesEnteredState); - line.append(",total_duration_ms=" + stats.totalDurationMs); - line.append(",pno_duration_ms=" + stats.pnoDurationMs); - pw.println(line.toString()); - } - - private void printUserApprovalSuggestionAppReaction(PrintWriter pw) { - pw.println("mUserApprovalSuggestionAppUiUserReaction:"); - for (UserReaction event : mUserApprovalSuggestionAppUiReactionList) { - pw.println(event); - } - } - - private void printUserApprovalCarrierReaction(PrintWriter pw) { - pw.println("mUserApprovalCarrierUiUserReaction:"); - for (UserReaction event : mUserApprovalCarrierUiReactionList) { - pw.println(event); - } - } - - /** - * Update various counts of saved network types - * @param networks List of WifiConfigurations representing all saved networks, must not be null - */ - public void updateSavedNetworks(List<WifiConfiguration> networks) { - synchronized (mLock) { - mWifiLogProto.numSavedNetworks = networks.size(); - mWifiLogProto.numSavedNetworksWithMacRandomization = 0; - mWifiLogProto.numOpenNetworks = 0; - mWifiLogProto.numLegacyPersonalNetworks = 0; - mWifiLogProto.numLegacyEnterpriseNetworks = 0; - mWifiLogProto.numEnhancedOpenNetworks = 0; - mWifiLogProto.numWpa3PersonalNetworks = 0; - mWifiLogProto.numWpa3EnterpriseNetworks = 0; - mWifiLogProto.numWapiPersonalNetworks = 0; - mWifiLogProto.numWapiEnterpriseNetworks = 0; - mWifiLogProto.numNetworksAddedByUser = 0; - mWifiLogProto.numNetworksAddedByApps = 0; - mWifiLogProto.numHiddenNetworks = 0; - mWifiLogProto.numPasspointNetworks = 0; - - for (WifiConfiguration config : networks) { - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { - mWifiLogProto.numOpenNetworks++; - } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) { - mWifiLogProto.numEnhancedOpenNetworks++; - } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK)) { - mWifiLogProto.numWapiPersonalNetworks++; - } else if (config.isEnterprise()) { - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) { - mWifiLogProto.numWpa3EnterpriseNetworks++; - } else if (config.allowedKeyManagement.get( - WifiConfiguration.KeyMgmt.WAPI_CERT)) { - mWifiLogProto.numWapiEnterpriseNetworks++; - } else { - mWifiLogProto.numLegacyEnterpriseNetworks++; - } - } else { - if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { - mWifiLogProto.numWpa3PersonalNetworks++; - } else { - mWifiLogProto.numLegacyPersonalNetworks++; - } - } - mWifiLogProto.numNetworksAddedByApps++; - if (config.hiddenSSID) { - mWifiLogProto.numHiddenNetworks++; - } - if (config.isPasspoint()) { - mWifiLogProto.numPasspointNetworks++; - } - if (config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) { - mWifiLogProto.numSavedNetworksWithMacRandomization++; - } - } - } - } - - /** - * Update metrics for saved Passpoint profiles. - * - * @param numSavedProfiles The number of saved Passpoint profiles - * @param numConnectedProfiles The number of saved Passpoint profiles that have ever resulted - * in a successful network connection - */ - public void updateSavedPasspointProfiles(int numSavedProfiles, int numConnectedProfiles) { - synchronized (mLock) { - mWifiLogProto.numPasspointProviders = numSavedProfiles; - mWifiLogProto.numPasspointProvidersSuccessfullyConnected = numConnectedProfiles; - } - } - - /** - * Update number of times for type of saved Passpoint profile. - * - * @param providers Passpoint providers installed on the device. - */ - public void updateSavedPasspointProfilesInfo( - Map<String, PasspointProvider> providers) { - int passpointType; - int eapType; - PasspointConfiguration config; - synchronized (mLock) { - mInstalledPasspointProfileTypeForR1.clear(); - mInstalledPasspointProfileTypeForR2.clear(); - for (Map.Entry<String, PasspointProvider> entry : providers.entrySet()) { - config = entry.getValue().getConfig(); - if (config.getCredential().getUserCredential() != null) { - eapType = EAPConstants.EAP_TTLS; - } else if (config.getCredential().getCertCredential() != null) { - eapType = EAPConstants.EAP_TLS; - } else if (config.getCredential().getSimCredential() != null) { - eapType = config.getCredential().getSimCredential().getEapType(); - } else { - eapType = -1; - } - switch (eapType) { - case EAPConstants.EAP_TLS: - passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_TLS; - break; - case EAPConstants.EAP_TTLS: - passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_TTLS; - break; - case EAPConstants.EAP_SIM: - passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_SIM; - break; - case EAPConstants.EAP_AKA: - passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_AKA; - break; - case EAPConstants.EAP_AKA_PRIME: - passpointType = - WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_AKA_PRIME; - break; - default: - passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_UNKNOWN; - - } - if (config.validateForR2()) { - mInstalledPasspointProfileTypeForR2.increment(passpointType); - } else { - mInstalledPasspointProfileTypeForR1.increment(passpointType); - } - } - } - } - - /** - * Increment initial partial scan count - */ - public void incrementInitialPartialScanCount() { - synchronized (mLock) { - mInitPartialScanTotalCount++; - } - } - - /** - * Report of initial partial scan - * @param channelCount number of channels used in this scan - * @param status true if scan resulted in a network connection attempt, false otherwise - */ - public void reportInitialPartialScan(int channelCount, boolean status) { - synchronized (mLock) { - if (status) { - mInitPartialScanSuccessCount++; - mInitPartialScanSuccessHistogram.increment(channelCount); - } else { - mInitPartialScanFailureCount++; - mInitPartialScanFailureHistogram.increment(channelCount); - } - } - } - - /** - * Put all metrics that were being tracked separately into mWifiLogProto - */ - private void consolidateProto() { - List<WifiMetricsProto.RssiPollCount> rssis = new ArrayList<>(); - synchronized (mLock) { - int connectionEventCount = mConnectionEventList.size(); - // Exclude the current active un-ended connection event - if (mCurrentConnectionEvent != null) { - connectionEventCount--; - } - mWifiLogProto.connectionEvent = - new WifiMetricsProto.ConnectionEvent[connectionEventCount]; - for (int i = 0; i < connectionEventCount; i++) { - mWifiLogProto.connectionEvent[i] = mConnectionEventList.get(i).mConnectionEvent; - } - - //Convert the SparseIntArray of scanReturnEntry integers into ScanReturnEntry proto list - mWifiLogProto.scanReturnEntries = - new WifiMetricsProto.WifiLog.ScanReturnEntry[mScanReturnEntries.size()]; - for (int i = 0; i < mScanReturnEntries.size(); i++) { - mWifiLogProto.scanReturnEntries[i] = new WifiMetricsProto.WifiLog.ScanReturnEntry(); - mWifiLogProto.scanReturnEntries[i].scanReturnCode = mScanReturnEntries.keyAt(i); - mWifiLogProto.scanReturnEntries[i].scanResultsCount = mScanReturnEntries.valueAt(i); - } - - // Convert the SparseIntArray of systemStateEntry into WifiSystemStateEntry proto list - // This one is slightly more complex, as the Sparse are indexed with: - // key: wifiState * 2 + isScreenOn, value: wifiStateCount - mWifiLogProto.wifiSystemStateEntries = - new WifiMetricsProto.WifiLog - .WifiSystemStateEntry[mWifiSystemStateEntries.size()]; - for (int i = 0; i < mWifiSystemStateEntries.size(); i++) { - mWifiLogProto.wifiSystemStateEntries[i] = - new WifiMetricsProto.WifiLog.WifiSystemStateEntry(); - mWifiLogProto.wifiSystemStateEntries[i].wifiState = - mWifiSystemStateEntries.keyAt(i) / 2; - mWifiLogProto.wifiSystemStateEntries[i].wifiStateCount = - mWifiSystemStateEntries.valueAt(i); - mWifiLogProto.wifiSystemStateEntries[i].isScreenOn = - (mWifiSystemStateEntries.keyAt(i) % 2) > 0; - } - mWifiLogProto.recordDurationSec = (int) ((mClock.getElapsedSinceBootMillis() / 1000) - - mRecordStartTimeSec); - - /** - * Convert the SparseIntArrays of RSSI poll rssi, counts, and frequency to the - * proto's repeated IntKeyVal array. - */ - for (Map.Entry<Integer, SparseIntArray> entry : mRssiPollCountsMap.entrySet()) { - int frequency = entry.getKey(); - SparseIntArray histogram = entry.getValue(); - for (int i = 0; i < histogram.size(); i++) { - WifiMetricsProto.RssiPollCount keyVal = new WifiMetricsProto.RssiPollCount(); - keyVal.rssi = histogram.keyAt(i); - keyVal.count = histogram.valueAt(i); - keyVal.frequency = frequency; - rssis.add(keyVal); - } - } - mWifiLogProto.rssiPollRssiCount = rssis.toArray(mWifiLogProto.rssiPollRssiCount); - - /** - * Convert the SparseIntArray of RSSI delta rssi's and counts to the proto's repeated - * IntKeyVal array. - */ - mWifiLogProto.rssiPollDeltaCount = - new WifiMetricsProto.RssiPollCount[mRssiDeltaCounts.size()]; - for (int i = 0; i < mRssiDeltaCounts.size(); i++) { - mWifiLogProto.rssiPollDeltaCount[i] = new WifiMetricsProto.RssiPollCount(); - mWifiLogProto.rssiPollDeltaCount[i].rssi = mRssiDeltaCounts.keyAt(i); - mWifiLogProto.rssiPollDeltaCount[i].count = mRssiDeltaCounts.valueAt(i); - } - - /** - * Add LinkSpeedCount objects from mLinkSpeedCounts to proto. - */ - mWifiLogProto.linkSpeedCounts = - new WifiMetricsProto.LinkSpeedCount[mLinkSpeedCounts.size()]; - for (int i = 0; i < mLinkSpeedCounts.size(); i++) { - mWifiLogProto.linkSpeedCounts[i] = mLinkSpeedCounts.valueAt(i); - } - - /** - * Convert the SparseIntArray of alert reasons and counts to the proto's repeated - * IntKeyVal array. - */ - mWifiLogProto.alertReasonCount = - new WifiMetricsProto.AlertReasonCount[mWifiAlertReasonCounts.size()]; - for (int i = 0; i < mWifiAlertReasonCounts.size(); i++) { - mWifiLogProto.alertReasonCount[i] = new WifiMetricsProto.AlertReasonCount(); - mWifiLogProto.alertReasonCount[i].reason = mWifiAlertReasonCounts.keyAt(i); - mWifiLogProto.alertReasonCount[i].count = mWifiAlertReasonCounts.valueAt(i); - } - - /** - * Convert the SparseIntArray of Wifi Score and counts to proto's repeated - * IntKeyVal array. - */ - mWifiLogProto.wifiScoreCount = - new WifiMetricsProto.WifiScoreCount[mWifiScoreCounts.size()]; - for (int score = 0; score < mWifiScoreCounts.size(); score++) { - mWifiLogProto.wifiScoreCount[score] = new WifiMetricsProto.WifiScoreCount(); - mWifiLogProto.wifiScoreCount[score].score = mWifiScoreCounts.keyAt(score); - mWifiLogProto.wifiScoreCount[score].count = mWifiScoreCounts.valueAt(score); - } - - /** - * Convert the SparseIntArray of Wifi Usability Score and counts to proto's repeated - * IntKeyVal array. - */ - mWifiLogProto.wifiUsabilityScoreCount = - new WifiMetricsProto.WifiUsabilityScoreCount[mWifiUsabilityScoreCounts.size()]; - for (int scoreIdx = 0; scoreIdx < mWifiUsabilityScoreCounts.size(); scoreIdx++) { - mWifiLogProto.wifiUsabilityScoreCount[scoreIdx] = - new WifiMetricsProto.WifiUsabilityScoreCount(); - mWifiLogProto.wifiUsabilityScoreCount[scoreIdx].score = - mWifiUsabilityScoreCounts.keyAt(scoreIdx); - mWifiLogProto.wifiUsabilityScoreCount[scoreIdx].count = - mWifiUsabilityScoreCounts.valueAt(scoreIdx); - } - - /** - * Convert the SparseIntArray of SoftAp Return codes and counts to proto's repeated - * IntKeyVal array. - */ - int codeCounts = mSoftApManagerReturnCodeCounts.size(); - mWifiLogProto.softApReturnCode = new WifiMetricsProto.SoftApReturnCodeCount[codeCounts]; - for (int sapCode = 0; sapCode < codeCounts; sapCode++) { - mWifiLogProto.softApReturnCode[sapCode] = - new WifiMetricsProto.SoftApReturnCodeCount(); - mWifiLogProto.softApReturnCode[sapCode].startResult = - mSoftApManagerReturnCodeCounts.keyAt(sapCode); - mWifiLogProto.softApReturnCode[sapCode].count = - mSoftApManagerReturnCodeCounts.valueAt(sapCode); - } - - /** - * Convert StaEventList to array of StaEvents - */ - mWifiLogProto.staEventList = new StaEvent[mStaEventList.size()]; - for (int i = 0; i < mStaEventList.size(); i++) { - mWifiLogProto.staEventList[i] = mStaEventList.get(i).staEvent; - } - mWifiLogProto.userActionEvents = new UserActionEvent[mUserActionEventList.size()]; - for (int i = 0; i < mUserActionEventList.size(); i++) { - mWifiLogProto.userActionEvents[i] = mUserActionEventList.get(i).toProto(); - } - mWifiLogProto.totalSsidsInScanHistogram = - makeNumConnectableNetworksBucketArray(mTotalSsidsInScanHistogram); - mWifiLogProto.totalBssidsInScanHistogram = - makeNumConnectableNetworksBucketArray(mTotalBssidsInScanHistogram); - mWifiLogProto.availableOpenSsidsInScanHistogram = - makeNumConnectableNetworksBucketArray(mAvailableOpenSsidsInScanHistogram); - mWifiLogProto.availableOpenBssidsInScanHistogram = - makeNumConnectableNetworksBucketArray(mAvailableOpenBssidsInScanHistogram); - mWifiLogProto.availableSavedSsidsInScanHistogram = - makeNumConnectableNetworksBucketArray(mAvailableSavedSsidsInScanHistogram); - mWifiLogProto.availableSavedBssidsInScanHistogram = - makeNumConnectableNetworksBucketArray(mAvailableSavedBssidsInScanHistogram); - mWifiLogProto.availableOpenOrSavedSsidsInScanHistogram = - makeNumConnectableNetworksBucketArray( - mAvailableOpenOrSavedSsidsInScanHistogram); - mWifiLogProto.availableOpenOrSavedBssidsInScanHistogram = - makeNumConnectableNetworksBucketArray( - mAvailableOpenOrSavedBssidsInScanHistogram); - mWifiLogProto.availableSavedPasspointProviderProfilesInScanHistogram = - makeNumConnectableNetworksBucketArray( - mAvailableSavedPasspointProviderProfilesInScanHistogram); - mWifiLogProto.availableSavedPasspointProviderBssidsInScanHistogram = - makeNumConnectableNetworksBucketArray( - mAvailableSavedPasspointProviderBssidsInScanHistogram); - mWifiLogProto.wifiAwareLog = mWifiAwareMetrics.consolidateProto(); - mWifiLogProto.wifiRttLog = mRttMetrics.consolidateProto(); - - mWifiLogProto.pnoScanMetrics = mPnoScanMetrics; - mWifiLogProto.wifiLinkLayerUsageStats = mWifiLinkLayerUsageStats; - - /** - * Convert the SparseIntArray of "Connect to Network" notification types and counts to - * proto's repeated IntKeyVal array. - */ - ConnectToNetworkNotificationAndActionCount[] notificationCountArray = - new ConnectToNetworkNotificationAndActionCount[ - mConnectToNetworkNotificationCount.size()]; - for (int i = 0; i < mConnectToNetworkNotificationCount.size(); i++) { - ConnectToNetworkNotificationAndActionCount keyVal = - new ConnectToNetworkNotificationAndActionCount(); - keyVal.notification = mConnectToNetworkNotificationCount.keyAt(i); - keyVal.recommender = - ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN; - keyVal.count = mConnectToNetworkNotificationCount.valueAt(i); - notificationCountArray[i] = keyVal; - } - mWifiLogProto.connectToNetworkNotificationCount = notificationCountArray; - - /** - * Convert the SparseIntArray of "Connect to Network" notification types and counts to - * proto's repeated IntKeyVal array. - */ - ConnectToNetworkNotificationAndActionCount[] notificationActionCountArray = - new ConnectToNetworkNotificationAndActionCount[ - mConnectToNetworkNotificationActionCount.size()]; - for (int i = 0; i < mConnectToNetworkNotificationActionCount.size(); i++) { - ConnectToNetworkNotificationAndActionCount keyVal = - new ConnectToNetworkNotificationAndActionCount(); - int k = mConnectToNetworkNotificationActionCount.keyAt(i); - keyVal.notification = k / CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER; - keyVal.action = k % CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER; - keyVal.recommender = - ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN; - keyVal.count = mConnectToNetworkNotificationActionCount.valueAt(i); - notificationActionCountArray[i] = keyVal; - } - - mWifiLogProto.installedPasspointProfileTypeForR1 = - convertPasspointProfilesToProto(mInstalledPasspointProfileTypeForR1); - mWifiLogProto.installedPasspointProfileTypeForR2 = - convertPasspointProfilesToProto(mInstalledPasspointProfileTypeForR2); - - mWifiLogProto.connectToNetworkNotificationActionCount = notificationActionCountArray; - - mWifiLogProto.openNetworkRecommenderBlacklistSize = - mOpenNetworkRecommenderBlacklistSize; - mWifiLogProto.isWifiNetworksAvailableNotificationOn = - mIsWifiNetworksAvailableNotificationOn; - mWifiLogProto.numOpenNetworkRecommendationUpdates = - mNumOpenNetworkRecommendationUpdates; - mWifiLogProto.numOpenNetworkConnectMessageFailedToSend = - mNumOpenNetworkConnectMessageFailedToSend; - - mWifiLogProto.observedHotspotR1ApsInScanHistogram = - makeNumConnectableNetworksBucketArray(mObservedHotspotR1ApInScanHistogram); - mWifiLogProto.observedHotspotR2ApsInScanHistogram = - makeNumConnectableNetworksBucketArray(mObservedHotspotR2ApInScanHistogram); - mWifiLogProto.observedHotspotR3ApsInScanHistogram = - makeNumConnectableNetworksBucketArray(mObservedHotspotR3ApInScanHistogram); - mWifiLogProto.observedHotspotR1EssInScanHistogram = - makeNumConnectableNetworksBucketArray(mObservedHotspotR1EssInScanHistogram); - mWifiLogProto.observedHotspotR2EssInScanHistogram = - makeNumConnectableNetworksBucketArray(mObservedHotspotR2EssInScanHistogram); - mWifiLogProto.observedHotspotR3EssInScanHistogram = - makeNumConnectableNetworksBucketArray(mObservedHotspotR3EssInScanHistogram); - mWifiLogProto.observedHotspotR1ApsPerEssInScanHistogram = - makeNumConnectableNetworksBucketArray( - mObservedHotspotR1ApsPerEssInScanHistogram); - mWifiLogProto.observedHotspotR2ApsPerEssInScanHistogram = - makeNumConnectableNetworksBucketArray( - mObservedHotspotR2ApsPerEssInScanHistogram); - mWifiLogProto.observedHotspotR3ApsPerEssInScanHistogram = - makeNumConnectableNetworksBucketArray( - mObservedHotspotR3ApsPerEssInScanHistogram); - - mWifiLogProto.observed80211McSupportingApsInScanHistogram = - makeNumConnectableNetworksBucketArray(mObserved80211mcApInScanHistogram); - - if (mSoftApEventListTethered.size() > 0) { - mWifiLogProto.softApConnectedClientsEventsTethered = - mSoftApEventListTethered.toArray( - mWifiLogProto.softApConnectedClientsEventsTethered); - } - if (mSoftApEventListLocalOnly.size() > 0) { - mWifiLogProto.softApConnectedClientsEventsLocalOnly = - mSoftApEventListLocalOnly.toArray( - mWifiLogProto.softApConnectedClientsEventsLocalOnly); - } - - mWifiLogProto.wifiPowerStats = mWifiPowerMetrics.buildProto(); - mWifiLogProto.wifiRadioUsage = mWifiPowerMetrics.buildWifiRadioUsageProto(); - mWifiLogProto.wifiWakeStats = mWifiWakeMetrics.buildProto(); - mWifiLogProto.isMacRandomizationOn = mContext.getResources().getBoolean( - R.bool.config_wifi_connected_mac_randomization_supported); - mExperimentValues.wifiIsUnusableLoggingEnabled = mContext.getResources().getBoolean( - R.bool.config_wifiIsUnusableEventMetricsEnabled); - mExperimentValues.linkSpeedCountsLoggingEnabled = mContext.getResources().getBoolean( - R.bool.config_wifiLinkSpeedMetricsEnabled); - mExperimentValues.wifiDataStallMinTxBad = mContext.getResources().getInteger( - R.integer.config_wifiDataStallMinTxBad); - mExperimentValues.wifiDataStallMinTxSuccessWithoutRx = - mContext.getResources().getInteger( - R.integer.config_wifiDataStallMinTxSuccessWithoutRx); - mWifiLogProto.experimentValues = mExperimentValues; - mWifiLogProto.wifiIsUnusableEventList = - new WifiIsUnusableEvent[mWifiIsUnusableList.size()]; - for (int i = 0; i < mWifiIsUnusableList.size(); i++) { - mWifiLogProto.wifiIsUnusableEventList[i] = mWifiIsUnusableList.get(i).event; - } - mWifiLogProto.hardwareRevision = SystemProperties.get("ro.boot.revision", ""); - - // Postprocessing on WifiUsabilityStats to upload an equal number of LABEL_GOOD and - // LABEL_BAD WifiUsabilityStats - final int numUsabilityStats = Math.min( - Math.min(mWifiUsabilityStatsListBad.size(), - mWifiUsabilityStatsListGood.size()), - MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD); - LinkedList<WifiUsabilityStats> usabilityStatsGoodCopy = - new LinkedList<>(mWifiUsabilityStatsListGood); - LinkedList<WifiUsabilityStats> usabilityStatsBadCopy = - new LinkedList<>(mWifiUsabilityStatsListBad); - mWifiLogProto.wifiUsabilityStatsList = new WifiUsabilityStats[numUsabilityStats * 2]; - for (int i = 0; i < numUsabilityStats; i++) { - mWifiLogProto.wifiUsabilityStatsList[2 * i] = usabilityStatsGoodCopy.remove( - mRand.nextInt(usabilityStatsGoodCopy.size())); - mWifiLogProto.wifiUsabilityStatsList[2 * i + 1] = usabilityStatsBadCopy.remove( - mRand.nextInt(usabilityStatsBadCopy.size())); - } - mWifiLogProto.mobilityStatePnoStatsList = - new DeviceMobilityStatePnoScanStats[mMobilityStatePnoStatsMap.size()]; - for (int i = 0; i < mMobilityStatePnoStatsMap.size(); i++) { - mWifiLogProto.mobilityStatePnoStatsList[i] = mMobilityStatePnoStatsMap.valueAt(i); - } - mWifiLogProto.wifiP2PStats = mWifiP2pMetrics.consolidateProto(); - mWifiLogProto.wifiDppLog = mDppMetrics.consolidateProto(); - mWifiLogProto.wifiConfigStoreIo = new WifiMetricsProto.WifiConfigStoreIO(); - mWifiLogProto.wifiConfigStoreIo.readDurations = - makeWifiConfigStoreIODurationBucketArray(mWifiConfigStoreReadDurationHistogram); - mWifiLogProto.wifiConfigStoreIo.writeDurations = - makeWifiConfigStoreIODurationBucketArray( - mWifiConfigStoreWriteDurationHistogram); - - LinkProbeStats linkProbeStats = new LinkProbeStats(); - linkProbeStats.successRssiCounts = mLinkProbeSuccessRssiCounts.toProto(); - linkProbeStats.failureRssiCounts = mLinkProbeFailureRssiCounts.toProto(); - linkProbeStats.successLinkSpeedCounts = mLinkProbeSuccessLinkSpeedCounts.toProto(); - linkProbeStats.failureLinkSpeedCounts = mLinkProbeFailureLinkSpeedCounts.toProto(); - linkProbeStats.successSecondsSinceLastTxSuccessHistogram = - mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.toProto(); - linkProbeStats.failureSecondsSinceLastTxSuccessHistogram = - mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.toProto(); - linkProbeStats.successElapsedTimeMsHistogram = - mLinkProbeSuccessElapsedTimeMsHistogram.toProto(); - linkProbeStats.failureReasonCounts = mLinkProbeFailureReasonCounts.toProto( - LinkProbeFailureReasonCount.class, - (reason, count) -> { - LinkProbeFailureReasonCount c = new LinkProbeFailureReasonCount(); - c.failureReason = linkProbeFailureReasonToProto(reason); - c.count = count; - return c; - }); - linkProbeStats.experimentProbeCounts = mLinkProbeExperimentProbeCounts.toProto( - ExperimentProbeCounts.class, - (experimentId, probeCount) -> { - ExperimentProbeCounts c = new ExperimentProbeCounts(); - c.experimentId = experimentId; - c.probeCount = probeCount; - return c; - }); - mWifiLogProto.linkProbeStats = linkProbeStats; - - mWifiLogProto.networkSelectionExperimentDecisionsList = - makeNetworkSelectionExperimentDecisionsList(); - - mWifiNetworkRequestApiLog.networkMatchSizeHistogram = - mWifiNetworkRequestApiMatchSizeHistogram.toProto(); - mWifiLogProto.wifiNetworkRequestApiLog = mWifiNetworkRequestApiLog; - - mWifiNetworkSuggestionApiLog.networkListSizeHistogram = - mWifiNetworkSuggestionApiListSizeHistogram.toProto(); - mWifiNetworkSuggestionApiLog.appCountPerType = - mWifiNetworkSuggestionApiAppTypeCounter.toProto(SuggestionAppCount.class, - (key, count) -> { - SuggestionAppCount entry = new SuggestionAppCount(); - entry.appType = key; - entry.count = count; - return entry; - }); - mWifiLogProto.wifiNetworkSuggestionApiLog = mWifiNetworkSuggestionApiLog; - - UserReactionToApprovalUiEvent events = new UserReactionToApprovalUiEvent(); - events.userApprovalAppUiReaction = mUserApprovalSuggestionAppUiReactionList - .toArray(new UserReaction[0]); - events.userApprovalCarrierUiReaction = mUserApprovalCarrierUiReactionList - .toArray(new UserReaction[0]); - mWifiLogProto.userReactionToApprovalUiEvent = events; - - mWifiLockStats.highPerfLockAcqDurationSecHistogram = - mWifiLockHighPerfAcqDurationSecHistogram.toProto(); - - mWifiLockStats.lowLatencyLockAcqDurationSecHistogram = - mWifiLockLowLatencyAcqDurationSecHistogram.toProto(); - - mWifiLockStats.highPerfActiveSessionDurationSecHistogram = - mWifiLockHighPerfActiveSessionDurationSecHistogram.toProto(); - - mWifiLockStats.lowLatencyActiveSessionDurationSecHistogram = - mWifiLockLowLatencyActiveSessionDurationSecHistogram.toProto(); - - mWifiLogProto.wifiLockStats = mWifiLockStats; - mWifiLogProto.wifiToggleStats = mWifiToggleStats; - - /** - * Convert the SparseIntArray of passpoint provision failure code - * and counts to the proto's repeated IntKeyVal array. - */ - mWifiLogProto.passpointProvisionStats = new PasspointProvisionStats(); - mWifiLogProto.passpointProvisionStats.numProvisionSuccess = mNumProvisionSuccess; - mWifiLogProto.passpointProvisionStats.provisionFailureCount = - mPasspointProvisionFailureCounts.toProto(ProvisionFailureCount.class, - (key, count) -> { - ProvisionFailureCount entry = new ProvisionFailureCount(); - entry.failureCode = key; - entry.count = count; - return entry; - }); - // 'G' is due to that 1st Letter after _ becomes capital during protobuff compilation - mWifiLogProto.txLinkSpeedCount2G = mTxLinkSpeedCount2g.toProto(); - mWifiLogProto.txLinkSpeedCount5GLow = mTxLinkSpeedCount5gLow.toProto(); - mWifiLogProto.txLinkSpeedCount5GMid = mTxLinkSpeedCount5gMid.toProto(); - mWifiLogProto.txLinkSpeedCount5GHigh = mTxLinkSpeedCount5gHigh.toProto(); - mWifiLogProto.txLinkSpeedCount6GLow = mTxLinkSpeedCount6gLow.toProto(); - mWifiLogProto.txLinkSpeedCount6GMid = mTxLinkSpeedCount6gMid.toProto(); - mWifiLogProto.txLinkSpeedCount6GHigh = mTxLinkSpeedCount6gHigh.toProto(); - - mWifiLogProto.rxLinkSpeedCount2G = mRxLinkSpeedCount2g.toProto(); - mWifiLogProto.rxLinkSpeedCount5GLow = mRxLinkSpeedCount5gLow.toProto(); - mWifiLogProto.rxLinkSpeedCount5GMid = mRxLinkSpeedCount5gMid.toProto(); - mWifiLogProto.rxLinkSpeedCount5GHigh = mRxLinkSpeedCount5gHigh.toProto(); - mWifiLogProto.rxLinkSpeedCount6GLow = mRxLinkSpeedCount6gLow.toProto(); - mWifiLogProto.rxLinkSpeedCount6GMid = mRxLinkSpeedCount6gMid.toProto(); - mWifiLogProto.rxLinkSpeedCount6GHigh = mRxLinkSpeedCount6gHigh.toProto(); - - HealthMonitorMetrics healthMonitorMetrics = mWifiHealthMonitor.buildProto(); - if (healthMonitorMetrics != null) { - mWifiLogProto.healthMonitorMetrics = healthMonitorMetrics; - } - mWifiLogProto.bssidBlocklistStats = mBssidBlocklistStats.toProto(); - mWifiLogProto.connectionDurationStats = mConnectionDurationStats.toProto(); - mWifiLogProto.wifiOffMetrics = mWifiOffMetrics.toProto(); - mWifiLogProto.softApConfigLimitationMetrics = mSoftApConfigLimitationMetrics.toProto(); - mWifiLogProto.channelUtilizationHistogram = - new WifiMetricsProto.ChannelUtilizationHistogram(); - mWifiLogProto.channelUtilizationHistogram.utilization2G = - mChannelUtilizationHistogram2G.toProto(); - mWifiLogProto.channelUtilizationHistogram.utilizationAbove2G = - mChannelUtilizationHistogramAbove2G.toProto(); - mWifiLogProto.throughputMbpsHistogram = - new WifiMetricsProto.ThroughputMbpsHistogram(); - mWifiLogProto.throughputMbpsHistogram.tx2G = - mTxThroughputMbpsHistogram2G.toProto(); - mWifiLogProto.throughputMbpsHistogram.txAbove2G = - mTxThroughputMbpsHistogramAbove2G.toProto(); - mWifiLogProto.throughputMbpsHistogram.rx2G = - mRxThroughputMbpsHistogram2G.toProto(); - mWifiLogProto.throughputMbpsHistogram.rxAbove2G = - mRxThroughputMbpsHistogramAbove2G.toProto(); - mWifiLogProto.meteredNetworkStatsSaved = mMeteredNetworkStatsBuilder.toProto(false); - mWifiLogProto.meteredNetworkStatsSuggestion = mMeteredNetworkStatsBuilder.toProto(true); - - InitPartialScanStats initialPartialScanStats = new InitPartialScanStats(); - initialPartialScanStats.numScans = mInitPartialScanTotalCount; - initialPartialScanStats.numSuccessScans = mInitPartialScanSuccessCount; - initialPartialScanStats.numFailureScans = mInitPartialScanFailureCount; - initialPartialScanStats.successfulScanChannelCountHistogram = - mInitPartialScanSuccessHistogram.toProto(); - initialPartialScanStats.failedScanChannelCountHistogram = - mInitPartialScanFailureHistogram.toProto(); - mWifiLogProto.initPartialScanStats = initialPartialScanStats; - mWifiLogProto.carrierWifiMetrics = mCarrierWifiMetrics.toProto(); - mWifiLogProto.mainlineModuleVersion = mWifiHealthMonitor.getWifiStackVersion(); - - } - } - - private static int linkProbeFailureReasonToProto(int reason) { - switch (reason) { - case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED: - return LinkProbeStats.LINK_PROBE_FAILURE_REASON_MCS_UNSUPPORTED; - case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK: - return LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK; - case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_TIMEOUT: - return LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT; - case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_ALREADY_STARTED: - return LinkProbeStats.LINK_PROBE_FAILURE_REASON_ALREADY_STARTED; - default: - return LinkProbeStats.LINK_PROBE_FAILURE_REASON_UNKNOWN; - } - } - - private NetworkSelectionExperimentDecisions[] makeNetworkSelectionExperimentDecisionsList() { - NetworkSelectionExperimentDecisions[] results = new NetworkSelectionExperimentDecisions[ - mNetworkSelectionExperimentPairNumChoicesCounts.size()]; - int i = 0; - for (Map.Entry<Pair<Integer, Integer>, NetworkSelectionExperimentResults> entry : - mNetworkSelectionExperimentPairNumChoicesCounts.entrySet()) { - NetworkSelectionExperimentDecisions result = new NetworkSelectionExperimentDecisions(); - result.experiment1Id = entry.getKey().first; - result.experiment2Id = entry.getKey().second; - result.sameSelectionNumChoicesCounter = - entry.getValue().sameSelectionNumChoicesCounter.toProto(); - result.differentSelectionNumChoicesCounter = - entry.getValue().differentSelectionNumChoicesCounter.toProto(); - results[i] = result; - i++; - } - return results; - } - - /** Sets the scoring experiment id to current value */ - private void consolidateScoringParams() { - synchronized (mLock) { - if (mScoringParams != null) { - int experimentIdentifier = mScoringParams.getExperimentIdentifier(); - if (experimentIdentifier == 0) { - mWifiLogProto.scoreExperimentId = ""; - } else { - mWifiLogProto.scoreExperimentId = "x" + experimentIdentifier; - } - } - } - } - - private WifiMetricsProto.NumConnectableNetworksBucket[] makeNumConnectableNetworksBucketArray( - SparseIntArray sia) { - WifiMetricsProto.NumConnectableNetworksBucket[] array = - new WifiMetricsProto.NumConnectableNetworksBucket[sia.size()]; - for (int i = 0; i < sia.size(); i++) { - WifiMetricsProto.NumConnectableNetworksBucket keyVal = - new WifiMetricsProto.NumConnectableNetworksBucket(); - keyVal.numConnectableNetworks = sia.keyAt(i); - keyVal.count = sia.valueAt(i); - array[i] = keyVal; - } - return array; - } - - private WifiMetricsProto.WifiConfigStoreIO.DurationBucket[] - makeWifiConfigStoreIODurationBucketArray(SparseIntArray sia) { - MetricsUtils.GenericBucket[] genericBuckets = - MetricsUtils.linearHistogramToGenericBuckets(sia, - WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS); - WifiMetricsProto.WifiConfigStoreIO.DurationBucket[] array = - new WifiMetricsProto.WifiConfigStoreIO.DurationBucket[genericBuckets.length]; - try { - for (int i = 0; i < genericBuckets.length; i++) { - array[i] = new WifiMetricsProto.WifiConfigStoreIO.DurationBucket(); - array[i].rangeStartMs = toIntExact(genericBuckets[i].start); - array[i].rangeEndMs = toIntExact(genericBuckets[i].end); - array[i].count = genericBuckets[i].count; - } - } catch (ArithmeticException e) { - // Return empty array on any overflow errors. - array = new WifiMetricsProto.WifiConfigStoreIO.DurationBucket[0]; - } - return array; - } - - /** - * Clear all WifiMetrics, except for currentConnectionEvent and Open Network Notification - * feature enabled state, blacklist size. - */ - private void clear() { - synchronized (mLock) { - mConnectionEventList.clear(); - if (mCurrentConnectionEvent != null) { - mConnectionEventList.add(mCurrentConnectionEvent); - } - mScanReturnEntries.clear(); - mWifiSystemStateEntries.clear(); - mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000; - mRssiPollCountsMap.clear(); - mRssiDeltaCounts.clear(); - mLinkSpeedCounts.clear(); - mTxLinkSpeedCount2g.clear(); - mTxLinkSpeedCount5gLow.clear(); - mTxLinkSpeedCount5gMid.clear(); - mTxLinkSpeedCount5gHigh.clear(); - mTxLinkSpeedCount6gLow.clear(); - mTxLinkSpeedCount6gMid.clear(); - mTxLinkSpeedCount6gHigh.clear(); - mRxLinkSpeedCount2g.clear(); - mRxLinkSpeedCount5gLow.clear(); - mRxLinkSpeedCount5gMid.clear(); - mRxLinkSpeedCount5gHigh.clear(); - mRxLinkSpeedCount6gLow.clear(); - mRxLinkSpeedCount6gMid.clear(); - mRxLinkSpeedCount6gHigh.clear(); - mWifiAlertReasonCounts.clear(); - mWifiScoreCounts.clear(); - mWifiUsabilityScoreCounts.clear(); - mWifiLogProto.clear(); - mScanResultRssiTimestampMillis = -1; - mSoftApManagerReturnCodeCounts.clear(); - mStaEventList.clear(); - mUserActionEventList.clear(); - mWifiAwareMetrics.clear(); - mRttMetrics.clear(); - mTotalSsidsInScanHistogram.clear(); - mTotalBssidsInScanHistogram.clear(); - mAvailableOpenSsidsInScanHistogram.clear(); - mAvailableOpenBssidsInScanHistogram.clear(); - mAvailableSavedSsidsInScanHistogram.clear(); - mAvailableSavedBssidsInScanHistogram.clear(); - mAvailableOpenOrSavedSsidsInScanHistogram.clear(); - mAvailableOpenOrSavedBssidsInScanHistogram.clear(); - mAvailableSavedPasspointProviderProfilesInScanHistogram.clear(); - mAvailableSavedPasspointProviderBssidsInScanHistogram.clear(); - mPnoScanMetrics.clear(); - mWifiLinkLayerUsageStats.clear(); - mConnectToNetworkNotificationCount.clear(); - mConnectToNetworkNotificationActionCount.clear(); - mNumOpenNetworkRecommendationUpdates = 0; - mNumOpenNetworkConnectMessageFailedToSend = 0; - mObservedHotspotR1ApInScanHistogram.clear(); - mObservedHotspotR2ApInScanHistogram.clear(); - mObservedHotspotR3ApInScanHistogram.clear(); - mObservedHotspotR1EssInScanHistogram.clear(); - mObservedHotspotR2EssInScanHistogram.clear(); - mObservedHotspotR3EssInScanHistogram.clear(); - mObservedHotspotR1ApsPerEssInScanHistogram.clear(); - mObservedHotspotR2ApsPerEssInScanHistogram.clear(); - mObservedHotspotR3ApsPerEssInScanHistogram.clear(); - mSoftApEventListTethered.clear(); - mSoftApEventListLocalOnly.clear(); - mWifiWakeMetrics.clear(); - mObserved80211mcApInScanHistogram.clear(); - mWifiIsUnusableList.clear(); - mInstalledPasspointProfileTypeForR1.clear(); - mInstalledPasspointProfileTypeForR2.clear(); - mWifiUsabilityStatsListGood.clear(); - mWifiUsabilityStatsListBad.clear(); - mWifiUsabilityStatsEntriesList.clear(); - mMobilityStatePnoStatsMap.clear(); - mWifiP2pMetrics.clear(); - mDppMetrics.clear(); - mWifiUsabilityStatsCounter = 0; - mLastBssid = null; - mLastFrequency = -1; - mSeqNumInsideFramework = 0; - mLastWifiUsabilityScore = -1; - mLastWifiUsabilityScoreNoReset = -1; - mLastPredictionHorizonSec = -1; - mLastPredictionHorizonSecNoReset = -1; - mSeqNumToFramework = -1; - mProbeStatusSinceLastUpdate = - android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE; - mProbeElapsedTimeSinceLastUpdateMs = -1; - mProbeMcsRateSinceLastUpdate = -1; - mScoreBreachLowTimeMillis = -1; - mMeteredNetworkStatsBuilder.clear(); - mWifiConfigStoreReadDurationHistogram.clear(); - mWifiConfigStoreWriteDurationHistogram.clear(); - mLinkProbeSuccessRssiCounts.clear(); - mLinkProbeFailureRssiCounts.clear(); - mLinkProbeSuccessLinkSpeedCounts.clear(); - mLinkProbeFailureLinkSpeedCounts.clear(); - mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.clear(); - mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.clear(); - mLinkProbeSuccessElapsedTimeMsHistogram.clear(); - mLinkProbeFailureReasonCounts.clear(); - mLinkProbeExperimentProbeCounts.clear(); - mLinkProbeStaEventCount = 0; - mNetworkSelectionExperimentPairNumChoicesCounts.clear(); - mWifiNetworkSuggestionApiLog.clear(); - mWifiNetworkRequestApiMatchSizeHistogram.clear(); - mWifiNetworkSuggestionApiListSizeHistogram.clear(); - mWifiNetworkSuggestionApiAppTypeCounter.clear(); - mUserApprovalSuggestionAppUiReactionList.clear(); - mUserApprovalCarrierUiReactionList.clear(); - mWifiLockHighPerfAcqDurationSecHistogram.clear(); - mWifiLockLowLatencyAcqDurationSecHistogram.clear(); - mWifiLockHighPerfActiveSessionDurationSecHistogram.clear(); - mWifiLockLowLatencyActiveSessionDurationSecHistogram.clear(); - mWifiLockStats.clear(); - mWifiToggleStats.clear(); - mChannelUtilizationHistogram2G.clear(); - mChannelUtilizationHistogramAbove2G.clear(); - mTxThroughputMbpsHistogram2G.clear(); - mRxThroughputMbpsHistogram2G.clear(); - mTxThroughputMbpsHistogramAbove2G.clear(); - mRxThroughputMbpsHistogramAbove2G.clear(); - mPasspointProvisionFailureCounts.clear(); - mNumProvisionSuccess = 0; - mBssidBlocklistStats = new BssidBlocklistStats(); - mConnectionDurationStats.clear(); - mWifiLogProto.isExternalWifiScorerOn = false; - mWifiOffMetrics.clear(); - mSoftApConfigLimitationMetrics.clear(); - //Initial partial scan metrics - mInitPartialScanTotalCount = 0; - mInitPartialScanSuccessCount = 0; - mInitPartialScanFailureCount = 0; - mInitPartialScanSuccessHistogram.clear(); - mInitPartialScanFailureHistogram.clear(); - mCarrierWifiMetrics.clear(); - } - } - - /** - * Set screen state (On/Off) - */ - public void setScreenState(boolean screenOn) { - synchronized (mLock) { - mScreenOn = screenOn; - } - } - - /** - * Set wifi state (WIFI_UNKNOWN, WIFI_DISABLED, WIFI_DISCONNECTED, WIFI_ASSOCIATED) - */ - public void setWifiState(int wifiState) { - synchronized (mLock) { - mWifiState = wifiState; - mWifiWins = (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); - mWifiWinsUsabilityScore = (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); - if (wifiState == WifiMetricsProto.WifiLog.WIFI_DISCONNECTED - || wifiState == WifiMetricsProto.WifiLog.WIFI_DISABLED) { - mWifiStatusBuilder = new WifiStatusBuilder(); - } - } - } - - /** - * Message handler for interesting WifiMonitor messages. Generates StaEvents - */ - private void processMessage(Message msg) { - StaEvent event = new StaEvent(); - boolean logEvent = true; - switch (msg.what) { - case WifiMonitor.ASSOCIATION_REJECTION_EVENT: - event.type = StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT; - event.associationTimedOut = msg.arg1 > 0 ? true : false; - event.status = msg.arg2; - break; - case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: - event.type = StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT; - switch (msg.arg1) { - case WifiManager.ERROR_AUTH_FAILURE_NONE: - event.authFailureReason = StaEvent.AUTH_FAILURE_NONE; - break; - case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT: - event.authFailureReason = StaEvent.AUTH_FAILURE_TIMEOUT; - break; - case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD: - event.authFailureReason = StaEvent.AUTH_FAILURE_WRONG_PSWD; - break; - case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE: - event.authFailureReason = StaEvent.AUTH_FAILURE_EAP_FAILURE; - break; - default: - break; - } - break; - case WifiMonitor.NETWORK_CONNECTION_EVENT: - event.type = StaEvent.TYPE_NETWORK_CONNECTION_EVENT; - break; - case WifiMonitor.NETWORK_DISCONNECTION_EVENT: - event.type = StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT; - event.reason = msg.arg2; - event.localGen = msg.arg1 == 0 ? false : true; - break; - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - logEvent = false; - StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; - mSupplicantStateChangeBitmask |= supplicantStateToBit(stateChangeResult.state); - break; - case WifiMonitor.ASSOCIATED_BSSID_EVENT: - event.type = StaEvent.TYPE_CMD_ASSOCIATED_BSSID; - break; - case WifiMonitor.TARGET_BSSID_EVENT: - event.type = StaEvent.TYPE_CMD_TARGET_BSSID; - break; - default: - return; - } - if (logEvent) { - addStaEvent(event); - } - } - /** - * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant - * generated event types, which are logged through 'sendMessage' - * @param type StaEvent.EventType describing the event - */ - public void logStaEvent(int type) { - logStaEvent(type, StaEvent.DISCONNECT_UNKNOWN, null); - } - /** - * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant - * generated event types, which are logged through 'sendMessage' - * @param type StaEvent.EventType describing the event - * @param config WifiConfiguration for a framework initiated connection attempt - */ - public void logStaEvent(int type, WifiConfiguration config) { - logStaEvent(type, StaEvent.DISCONNECT_UNKNOWN, config); - } - /** - * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant - * generated event types, which are logged through 'sendMessage' - * @param type StaEvent.EventType describing the event - * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework - * initiated a FRAMEWORK_DISCONNECT - */ - public void logStaEvent(int type, int frameworkDisconnectReason) { - logStaEvent(type, frameworkDisconnectReason, null); - } - /** - * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant - * generated event types, which are logged through 'sendMessage' - * @param type StaEvent.EventType describing the event - * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework - * initiated a FRAMEWORK_DISCONNECT - * @param config WifiConfiguration for a framework initiated connection attempt - */ - public void logStaEvent(int type, int frameworkDisconnectReason, WifiConfiguration config) { - switch (type) { - case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL: - case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST: - case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST: - case StaEvent.TYPE_CMD_START_CONNECT: - case StaEvent.TYPE_CMD_START_ROAM: - case StaEvent.TYPE_CONNECT_NETWORK: - case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK: - mWifiStatusBuilder.setValidated(true); - case StaEvent.TYPE_FRAMEWORK_DISCONNECT: - case StaEvent.TYPE_SCORE_BREACH: - case StaEvent.TYPE_MAC_CHANGE: - case StaEvent.TYPE_WIFI_ENABLED: - case StaEvent.TYPE_WIFI_DISABLED: - case StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH: - break; - default: - Log.e(TAG, "Unknown StaEvent:" + type); - return; - } - StaEvent event = new StaEvent(); - event.type = type; - if (frameworkDisconnectReason != StaEvent.DISCONNECT_UNKNOWN) { - event.frameworkDisconnectReason = frameworkDisconnectReason; - } - event.configInfo = createConfigInfo(config); - addStaEvent(event); - } - - private void addStaEvent(StaEvent staEvent) { - staEvent.startTimeMillis = mClock.getElapsedSinceBootMillis(); - staEvent.lastRssi = mLastPollRssi; - staEvent.lastFreq = mLastPollFreq; - staEvent.lastLinkSpeed = mLastPollLinkSpeed; - staEvent.supplicantStateChangesBitmask = mSupplicantStateChangeBitmask; - staEvent.lastScore = mLastScore; - staEvent.lastWifiUsabilityScore = mLastWifiUsabilityScore; - staEvent.lastPredictionHorizonSec = mLastPredictionHorizonSec; - staEvent.mobileTxBytes = mFacade.getMobileTxBytes(); - staEvent.mobileRxBytes = mFacade.getMobileRxBytes(); - staEvent.totalTxBytes = mFacade.getTotalTxBytes(); - staEvent.totalRxBytes = mFacade.getTotalRxBytes(); - staEvent.screenOn = mScreenOn; - if (mWifiDataStall != null) { - staEvent.isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable(); - } - staEvent.isAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabled; - mSupplicantStateChangeBitmask = 0; - mLastPollRssi = -127; - mLastPollFreq = -1; - mLastPollLinkSpeed = -1; - mLastPollRxLinkSpeed = -1; - mLastScore = -1; - mLastWifiUsabilityScore = -1; - mLastPredictionHorizonSec = -1; - synchronized (mLock) { - mStaEventList.add(new StaEventWithTime(staEvent, mClock.getWallClockMillis())); - // Prune StaEventList if it gets too long - if (mStaEventList.size() > MAX_STA_EVENTS) mStaEventList.remove(); - } - } - - private ConfigInfo createConfigInfo(WifiConfiguration config) { - if (config == null) return null; - ConfigInfo info = new ConfigInfo(); - info.allowedKeyManagement = bitSetToInt(config.allowedKeyManagement); - info.allowedProtocols = bitSetToInt(config.allowedProtocols); - info.allowedAuthAlgorithms = bitSetToInt(config.allowedAuthAlgorithms); - info.allowedPairwiseCiphers = bitSetToInt(config.allowedPairwiseCiphers); - info.allowedGroupCiphers = bitSetToInt(config.allowedGroupCiphers); - info.hiddenSsid = config.hiddenSSID; - info.isPasspoint = config.isPasspoint(); - info.isEphemeral = config.isEphemeral(); - info.hasEverConnected = config.getNetworkSelectionStatus().hasEverConnected(); - ScanResult candidate = config.getNetworkSelectionStatus().getCandidate(); - if (candidate != null) { - info.scanRssi = candidate.level; - info.scanFreq = candidate.frequency; - } - return info; - } - - public Handler getHandler() { - return mHandler; - } - - public WifiAwareMetrics getWifiAwareMetrics() { - return mWifiAwareMetrics; - } - - public WifiWakeMetrics getWakeupMetrics() { - return mWifiWakeMetrics; - } - - public RttMetrics getRttMetrics() { - return mRttMetrics; - } - - // Rather than generate a StaEvent for each SUPPLICANT_STATE_CHANGE, cache these in a bitmask - // and attach it to the next event which is generated. - private int mSupplicantStateChangeBitmask = 0; - - /** - * Converts a SupplicantState value to a single bit, with position defined by - * {@code StaEvent.SupplicantState} - */ - public static int supplicantStateToBit(SupplicantState state) { - switch(state) { - case DISCONNECTED: - return 1 << StaEvent.STATE_DISCONNECTED; - case INTERFACE_DISABLED: - return 1 << StaEvent.STATE_INTERFACE_DISABLED; - case INACTIVE: - return 1 << StaEvent.STATE_INACTIVE; - case SCANNING: - return 1 << StaEvent.STATE_SCANNING; - case AUTHENTICATING: - return 1 << StaEvent.STATE_AUTHENTICATING; - case ASSOCIATING: - return 1 << StaEvent.STATE_ASSOCIATING; - case ASSOCIATED: - return 1 << StaEvent.STATE_ASSOCIATED; - case FOUR_WAY_HANDSHAKE: - return 1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE; - case GROUP_HANDSHAKE: - return 1 << StaEvent.STATE_GROUP_HANDSHAKE; - case COMPLETED: - return 1 << StaEvent.STATE_COMPLETED; - case DORMANT: - return 1 << StaEvent.STATE_DORMANT; - case UNINITIALIZED: - return 1 << StaEvent.STATE_UNINITIALIZED; - case INVALID: - return 1 << StaEvent.STATE_INVALID; - default: - Log.wtf(TAG, "Got unknown supplicant state: " + state.ordinal()); - return 0; - } - } - - private static String supplicantStateChangesBitmaskToString(int mask) { - StringBuilder sb = new StringBuilder(); - sb.append("supplicantStateChangeEvents: {"); - if ((mask & (1 << StaEvent.STATE_DISCONNECTED)) > 0) sb.append(" DISCONNECTED"); - if ((mask & (1 << StaEvent.STATE_INTERFACE_DISABLED)) > 0) sb.append(" INTERFACE_DISABLED"); - if ((mask & (1 << StaEvent.STATE_INACTIVE)) > 0) sb.append(" INACTIVE"); - if ((mask & (1 << StaEvent.STATE_SCANNING)) > 0) sb.append(" SCANNING"); - if ((mask & (1 << StaEvent.STATE_AUTHENTICATING)) > 0) sb.append(" AUTHENTICATING"); - if ((mask & (1 << StaEvent.STATE_ASSOCIATING)) > 0) sb.append(" ASSOCIATING"); - if ((mask & (1 << StaEvent.STATE_ASSOCIATED)) > 0) sb.append(" ASSOCIATED"); - if ((mask & (1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE)) > 0) sb.append(" FOUR_WAY_HANDSHAKE"); - if ((mask & (1 << StaEvent.STATE_GROUP_HANDSHAKE)) > 0) sb.append(" GROUP_HANDSHAKE"); - if ((mask & (1 << StaEvent.STATE_COMPLETED)) > 0) sb.append(" COMPLETED"); - if ((mask & (1 << StaEvent.STATE_DORMANT)) > 0) sb.append(" DORMANT"); - if ((mask & (1 << StaEvent.STATE_UNINITIALIZED)) > 0) sb.append(" UNINITIALIZED"); - if ((mask & (1 << StaEvent.STATE_INVALID)) > 0) sb.append(" INVALID"); - sb.append(" }"); - return sb.toString(); - } - - /** - * Returns a human readable string from a Sta Event. Only adds information relevant to the event - * type. - */ - public static String staEventToString(StaEvent event) { - if (event == null) return "<NULL>"; - StringBuilder sb = new StringBuilder(); - switch (event.type) { - case StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT: - sb.append("ASSOCIATION_REJECTION_EVENT") - .append(" timedOut=").append(event.associationTimedOut) - .append(" status=").append(event.status).append(":") - .append(ISupplicantStaIfaceCallback.StatusCode.toString(event.status)); - break; - case StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT: - sb.append("AUTHENTICATION_FAILURE_EVENT reason=").append(event.authFailureReason) - .append(":").append(authFailureReasonToString(event.authFailureReason)); - break; - case StaEvent.TYPE_NETWORK_CONNECTION_EVENT: - sb.append("NETWORK_CONNECTION_EVENT"); - break; - case StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT: - sb.append("NETWORK_DISCONNECTION_EVENT") - .append(" local_gen=").append(event.localGen) - .append(" reason=").append(event.reason).append(":") - .append(ISupplicantStaIfaceCallback.ReasonCode.toString( - (event.reason >= 0 ? event.reason : -1 * event.reason))); - break; - case StaEvent.TYPE_CMD_ASSOCIATED_BSSID: - sb.append("CMD_ASSOCIATED_BSSID"); - break; - case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL: - sb.append("CMD_IP_CONFIGURATION_SUCCESSFUL"); - break; - case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST: - sb.append("CMD_IP_CONFIGURATION_LOST"); - break; - case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST: - sb.append("CMD_IP_REACHABILITY_LOST"); - break; - case StaEvent.TYPE_CMD_TARGET_BSSID: - sb.append("CMD_TARGET_BSSID"); - break; - case StaEvent.TYPE_CMD_START_CONNECT: - sb.append("CMD_START_CONNECT"); - break; - case StaEvent.TYPE_CMD_START_ROAM: - sb.append("CMD_START_ROAM"); - break; - case StaEvent.TYPE_CONNECT_NETWORK: - sb.append("CONNECT_NETWORK"); - break; - case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK: - sb.append("NETWORK_AGENT_VALID_NETWORK"); - break; - case StaEvent.TYPE_FRAMEWORK_DISCONNECT: - sb.append("FRAMEWORK_DISCONNECT") - .append(" reason=") - .append(frameworkDisconnectReasonToString(event.frameworkDisconnectReason)); - break; - case StaEvent.TYPE_SCORE_BREACH: - sb.append("SCORE_BREACH"); - break; - case StaEvent.TYPE_MAC_CHANGE: - sb.append("MAC_CHANGE"); - break; - case StaEvent.TYPE_WIFI_ENABLED: - sb.append("WIFI_ENABLED"); - break; - case StaEvent.TYPE_WIFI_DISABLED: - sb.append("WIFI_DISABLED"); - break; - case StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH: - sb.append("WIFI_USABILITY_SCORE_BREACH"); - break; - case StaEvent.TYPE_LINK_PROBE: - sb.append("LINK_PROBE"); - sb.append(" linkProbeWasSuccess=").append(event.linkProbeWasSuccess); - if (event.linkProbeWasSuccess) { - sb.append(" linkProbeSuccessElapsedTimeMs=") - .append(event.linkProbeSuccessElapsedTimeMs); - } else { - sb.append(" linkProbeFailureReason=").append(event.linkProbeFailureReason); - } - break; - default: - sb.append("UNKNOWN " + event.type + ":"); - break; - } - if (event.lastRssi != -127) sb.append(" lastRssi=").append(event.lastRssi); - if (event.lastFreq != -1) sb.append(" lastFreq=").append(event.lastFreq); - if (event.lastLinkSpeed != -1) sb.append(" lastLinkSpeed=").append(event.lastLinkSpeed); - if (event.lastScore != -1) sb.append(" lastScore=").append(event.lastScore); - if (event.lastWifiUsabilityScore != -1) { - sb.append(" lastWifiUsabilityScore=").append(event.lastWifiUsabilityScore); - sb.append(" lastPredictionHorizonSec=").append(event.lastPredictionHorizonSec); - } - if (event.mobileTxBytes > 0) sb.append(" mobileTxBytes=").append(event.mobileTxBytes); - if (event.mobileRxBytes > 0) sb.append(" mobileRxBytes=").append(event.mobileRxBytes); - if (event.totalTxBytes > 0) sb.append(" totalTxBytes=").append(event.totalTxBytes); - if (event.totalRxBytes > 0) sb.append(" totalRxBytes=").append(event.totalRxBytes); - sb.append(" screenOn=").append(event.screenOn); - sb.append(" cellularData=").append(event.isCellularDataAvailable); - sb.append(" adaptiveConnectivity=").append(event.isAdaptiveConnectivityEnabled); - if (event.supplicantStateChangesBitmask != 0) { - sb.append(", ").append(supplicantStateChangesBitmaskToString( - event.supplicantStateChangesBitmask)); - } - if (event.configInfo != null) { - sb.append(", ").append(configInfoToString(event.configInfo)); - } - - return sb.toString(); - } - - private static String authFailureReasonToString(int authFailureReason) { - switch (authFailureReason) { - case StaEvent.AUTH_FAILURE_NONE: - return "ERROR_AUTH_FAILURE_NONE"; - case StaEvent.AUTH_FAILURE_TIMEOUT: - return "ERROR_AUTH_FAILURE_TIMEOUT"; - case StaEvent.AUTH_FAILURE_WRONG_PSWD: - return "ERROR_AUTH_FAILURE_WRONG_PSWD"; - case StaEvent.AUTH_FAILURE_EAP_FAILURE: - return "ERROR_AUTH_FAILURE_EAP_FAILURE"; - default: - return ""; - } - } - - private static String frameworkDisconnectReasonToString(int frameworkDisconnectReason) { - switch (frameworkDisconnectReason) { - case StaEvent.DISCONNECT_API: - return "DISCONNECT_API"; - case StaEvent.DISCONNECT_GENERIC: - return "DISCONNECT_GENERIC"; - case StaEvent.DISCONNECT_UNWANTED: - return "DISCONNECT_UNWANTED"; - case StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER: - return "DISCONNECT_ROAM_WATCHDOG_TIMER"; - case StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST: - return "DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST"; - case StaEvent.DISCONNECT_RESET_SIM_NETWORKS: - return "DISCONNECT_RESET_SIM_NETWORKS"; - default: - return "DISCONNECT_UNKNOWN=" + frameworkDisconnectReason; - } - } - - private static String configInfoToString(ConfigInfo info) { - StringBuilder sb = new StringBuilder(); - sb.append("ConfigInfo:") - .append(" allowed_key_management=").append(info.allowedKeyManagement) - .append(" allowed_protocols=").append(info.allowedProtocols) - .append(" allowed_auth_algorithms=").append(info.allowedAuthAlgorithms) - .append(" allowed_pairwise_ciphers=").append(info.allowedPairwiseCiphers) - .append(" allowed_group_ciphers=").append(info.allowedGroupCiphers) - .append(" hidden_ssid=").append(info.hiddenSsid) - .append(" is_passpoint=").append(info.isPasspoint) - .append(" is_ephemeral=").append(info.isEphemeral) - .append(" has_ever_connected=").append(info.hasEverConnected) - .append(" scan_rssi=").append(info.scanRssi) - .append(" scan_freq=").append(info.scanFreq); - return sb.toString(); - } - - /** - * Converts the first 31 bits of a BitSet to a little endian int - */ - private static int bitSetToInt(BitSet bits) { - int value = 0; - int nBits = bits.length() < 31 ? bits.length() : 31; - for (int i = 0; i < nBits; i++) { - value += bits.get(i) ? (1 << i) : 0; - } - return value; - } - private void incrementSsid(SparseIntArray sia, int element) { - increment(sia, Math.min(element, MAX_CONNECTABLE_SSID_NETWORK_BUCKET)); - } - private void incrementBssid(SparseIntArray sia, int element) { - increment(sia, Math.min(element, MAX_CONNECTABLE_BSSID_NETWORK_BUCKET)); - } - private void incrementTotalScanResults(SparseIntArray sia, int element) { - increment(sia, Math.min(element, MAX_TOTAL_SCAN_RESULTS_BUCKET)); - } - private void incrementTotalScanSsids(SparseIntArray sia, int element) { - increment(sia, Math.min(element, MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET)); - } - private void incrementTotalPasspointAps(SparseIntArray sia, int element) { - increment(sia, Math.min(element, MAX_TOTAL_PASSPOINT_APS_BUCKET)); - } - private void incrementTotalUniquePasspointEss(SparseIntArray sia, int element) { - increment(sia, Math.min(element, MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET)); - } - private void incrementPasspointPerUniqueEss(SparseIntArray sia, int element) { - increment(sia, Math.min(element, MAX_PASSPOINT_APS_PER_UNIQUE_ESS_BUCKET)); - } - private void increment80211mcAps(SparseIntArray sia, int element) { - increment(sia, Math.min(element, MAX_TOTAL_80211MC_APS_BUCKET)); - } - private void increment(SparseIntArray sia, int element) { - int count = sia.get(element); - sia.put(element, count + 1); - } - - private static class StaEventWithTime { - public StaEvent staEvent; - public long wallClockMillis; - - StaEventWithTime(StaEvent event, long wallClockMillis) { - staEvent = event; - this.wallClockMillis = wallClockMillis; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(wallClockMillis); - if (wallClockMillis != 0) { - sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); - } else { - sb.append(" "); - } - sb.append(" ").append(staEventToString(staEvent)); - return sb.toString(); - } - } - - private LinkedList<WifiIsUnusableWithTime> mWifiIsUnusableList = - new LinkedList<WifiIsUnusableWithTime>(); - private long mTxScucessDelta = 0; - private long mTxRetriesDelta = 0; - private long mTxBadDelta = 0; - private long mRxSuccessDelta = 0; - private long mLlStatsUpdateTimeDelta = 0; - private long mLlStatsLastUpdateTime = 0; - private int mLastScoreNoReset = -1; - private long mLastDataStallTime = Long.MIN_VALUE; - - private static class WifiIsUnusableWithTime { - public WifiIsUnusableEvent event; - public long wallClockMillis; - - WifiIsUnusableWithTime(WifiIsUnusableEvent event, long wallClockMillis) { - this.event = event; - this.wallClockMillis = wallClockMillis; - } - - public String toString() { - if (event == null) return "<NULL>"; - StringBuilder sb = new StringBuilder(); - if (wallClockMillis != 0) { - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(wallClockMillis); - sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); - } else { - sb.append(" "); - } - sb.append(" "); - - switch(event.type) { - case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX: - sb.append("DATA_STALL_BAD_TX"); - break; - case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX: - sb.append("DATA_STALL_TX_WITHOUT_RX"); - break; - case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH: - sb.append("DATA_STALL_BOTH"); - break; - case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT: - sb.append("FIRMWARE_ALERT"); - break; - case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST: - sb.append("IP_REACHABILITY_LOST"); - break; - default: - sb.append("UNKNOWN " + event.type); - break; - } - - sb.append(" lastScore=").append(event.lastScore); - sb.append(" txSuccessDelta=").append(event.txSuccessDelta); - sb.append(" txRetriesDelta=").append(event.txRetriesDelta); - sb.append(" txBadDelta=").append(event.txBadDelta); - sb.append(" rxSuccessDelta=").append(event.rxSuccessDelta); - sb.append(" packetUpdateTimeDelta=").append(event.packetUpdateTimeDelta) - .append("ms"); - if (event.firmwareAlertCode != -1) { - sb.append(" firmwareAlertCode=").append(event.firmwareAlertCode); - } - sb.append(" lastWifiUsabilityScore=").append(event.lastWifiUsabilityScore); - sb.append(" lastPredictionHorizonSec=").append(event.lastPredictionHorizonSec); - sb.append(" screenOn=").append(event.screenOn); - sb.append(" mobileTxBytes=").append(event.mobileTxBytes); - sb.append(" mobileRxBytes=").append(event.mobileRxBytes); - sb.append(" totalTxBytes=").append(event.totalTxBytes); - sb.append(" totalRxBytes=").append(event.totalRxBytes); - return sb.toString(); - } - } - - /** - * Converts MeteredOverride enum to UserActionEvent type. - * @param value - */ - public static int convertMeteredOverrideEnumToUserActionEventType(@MeteredOverride int value) { - int result = UserActionEvent.EVENT_UNKNOWN; - switch(value) { - case WifiConfiguration.METERED_OVERRIDE_NONE: - result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_AUTO; - break; - case WifiConfiguration.METERED_OVERRIDE_METERED: - result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_METERED; - break; - case WifiConfiguration.METERED_OVERRIDE_NOT_METERED: - result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_UNMETERED; - break; - } - return result; - } - - /** - * Converts Adaptive Connectivity state to UserActionEvent type. - * @param value - */ - public static int convertAdaptiveConnectivityStateToUserActionEventType(boolean value) { - return value ? UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_ON - : UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_OFF; - } - - static class MeteredNetworkStatsBuilder { - // A map from network identifier to MeteredDetail - Map<String, MeteredDetail> mNetworkMap = new ArrayMap<>(); - - void put(WifiConfiguration config, boolean detectedAsMetered) { - MeteredDetail meteredDetail = new MeteredDetail(); - boolean isMetered = detectedAsMetered; - if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) { - isMetered = true; - } else if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) { - isMetered = false; - } - meteredDetail.isMetered = isMetered; - meteredDetail.isMeteredOverrideSet = config.meteredOverride - != WifiConfiguration.METERED_OVERRIDE_NONE; - meteredDetail.isFromSuggestion = config.fromWifiNetworkSuggestion; - mNetworkMap.put(config.getKey(), meteredDetail); - } - - void clear() { - mNetworkMap.clear(); - } - - MeteredNetworkStats toProto(boolean isFromSuggestion) { - MeteredNetworkStats result = new MeteredNetworkStats(); - for (MeteredDetail meteredDetail : mNetworkMap.values()) { - if (meteredDetail.isFromSuggestion != isFromSuggestion) { - continue; - } - if (meteredDetail.isMetered) { - result.numMetered++; - } else { - result.numUnmetered++; - } - if (meteredDetail.isMeteredOverrideSet) { - if (meteredDetail.isMetered) { - result.numOverrideMetered++; - } else { - result.numOverrideUnmetered++; - } - } - } - return result; - } - - static class MeteredDetail { - public boolean isMetered; - public boolean isMeteredOverrideSet; - public boolean isFromSuggestion; - } - } - - /** - * Add metered information of this network. - * @param config WifiConfiguration representing the netework. - * @param detectedAsMetered is the network detected as metered. - */ - public void addMeteredStat(WifiConfiguration config, boolean detectedAsMetered) { - synchronized (mLock) { - if (config == null) { - return; - } - mMeteredNetworkStatsBuilder.put(config, detectedAsMetered); - } - } - /** - * Logs a UserActionEvent without a target network. - * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType) - */ - public void logUserActionEvent(int eventType) { - logUserActionEvent(eventType, -1); - } - - /** - * Logs a UserActionEvent which has a target network. - * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType) - * @param networkId networkId of the target network. - */ - public void logUserActionEvent(int eventType, int networkId) { - synchronized (mLock) { - mUserActionEventList.add(new UserActionEventWithTime(eventType, networkId)); - if (mUserActionEventList.size() > MAX_USER_ACTION_EVENTS) { - mUserActionEventList.remove(); - } - } - } - - /** - * Logs a UserActionEvent, directly specifying the target network's properties. - * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType) - * @param isEphemeral true if the target network is ephemeral. - * @param isPasspoint true if the target network is passpoint. - */ - public void logUserActionEvent(int eventType, boolean isEphemeral, boolean isPasspoint) { - synchronized (mLock) { - TargetNetworkInfo networkInfo = new TargetNetworkInfo(); - networkInfo.isEphemeral = isEphemeral; - networkInfo.isPasspoint = isPasspoint; - mUserActionEventList.add(new UserActionEventWithTime(eventType, networkInfo)); - if (mUserActionEventList.size() > MAX_USER_ACTION_EVENTS) { - mUserActionEventList.remove(); - } - } - } - - /** - * Update the difference between the last two WifiLinkLayerStats for WifiIsUnusableEvent - */ - public void updateWifiIsUnusableLinkLayerStats(long txSuccessDelta, long txRetriesDelta, - long txBadDelta, long rxSuccessDelta, long updateTimeDelta) { - mTxScucessDelta = txSuccessDelta; - mTxRetriesDelta = txRetriesDelta; - mTxBadDelta = txBadDelta; - mRxSuccessDelta = rxSuccessDelta; - mLlStatsUpdateTimeDelta = updateTimeDelta; - mLlStatsLastUpdateTime = mClock.getElapsedSinceBootMillis(); - } - - /** - * Clear the saved difference between the last two WifiLinkLayerStats - */ - public void resetWifiIsUnusableLinkLayerStats() { - mTxScucessDelta = 0; - mTxRetriesDelta = 0; - mTxBadDelta = 0; - mRxSuccessDelta = 0; - mLlStatsUpdateTimeDelta = 0; - mLlStatsLastUpdateTime = 0; - mLastDataStallTime = Long.MIN_VALUE; - } - - /** - * Log a WifiIsUnusableEvent - * @param triggerType WifiIsUnusableEvent.type describing the event - */ - public void logWifiIsUnusableEvent(int triggerType) { - logWifiIsUnusableEvent(triggerType, -1); - } - - /** - * Log a WifiIsUnusableEvent - * @param triggerType WifiIsUnusableEvent.type describing the event - * @param firmwareAlertCode WifiIsUnusableEvent.firmwareAlertCode for firmware alert code - */ - public void logWifiIsUnusableEvent(int triggerType, int firmwareAlertCode) { - mScoreBreachLowTimeMillis = -1; - if (!mContext.getResources().getBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled)) { - return; - } - - long currentBootTime = mClock.getElapsedSinceBootMillis(); - switch (triggerType) { - case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX: - case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX: - case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH: - // Have a time-based throttle for generating WifiIsUnusableEvent from data stalls - if (currentBootTime < mLastDataStallTime + MIN_DATA_STALL_WAIT_MS) { - return; - } - mLastDataStallTime = currentBootTime; - break; - case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT: - break; - case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST: - break; - default: - Log.e(TAG, "Unknown WifiIsUnusableEvent: " + triggerType); - return; - } - - WifiIsUnusableEvent event = new WifiIsUnusableEvent(); - event.type = triggerType; - if (triggerType == WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT) { - event.firmwareAlertCode = firmwareAlertCode; - } - event.startTimeMillis = currentBootTime; - event.lastScore = mLastScoreNoReset; - event.lastWifiUsabilityScore = mLastWifiUsabilityScoreNoReset; - event.lastPredictionHorizonSec = mLastPredictionHorizonSecNoReset; - event.txSuccessDelta = mTxScucessDelta; - event.txRetriesDelta = mTxRetriesDelta; - event.txBadDelta = mTxBadDelta; - event.rxSuccessDelta = mRxSuccessDelta; - event.packetUpdateTimeDelta = mLlStatsUpdateTimeDelta; - event.lastLinkLayerStatsUpdateTime = mLlStatsLastUpdateTime; - event.screenOn = mScreenOn; - event.mobileTxBytes = mFacade.getMobileTxBytes(); - event.mobileRxBytes = mFacade.getMobileRxBytes(); - event.totalTxBytes = mFacade.getTotalTxBytes(); - event.totalRxBytes = mFacade.getTotalRxBytes(); - - mWifiIsUnusableList.add(new WifiIsUnusableWithTime(event, mClock.getWallClockMillis())); - if (mWifiIsUnusableList.size() > MAX_UNUSABLE_EVENTS) { - mWifiIsUnusableList.removeFirst(); - } - } - - /** - * Extract data from |info| and |stats| to build a WifiUsabilityStatsEntry and then adds it - * into an internal ring buffer. - * @param info - * @param stats - */ - public void updateWifiUsabilityStatsEntries(WifiInfo info, WifiLinkLayerStats stats) { - synchronized (mLock) { - if (info == null) { - return; - } - if (stats == null) { - // For devices lacking vendor hal, fill in the parts that we can - stats = new WifiLinkLayerStats(); - stats.timeStampInMs = mClock.getElapsedSinceBootMillis(); - stats.txmpdu_be = info.txSuccess; - stats.retries_be = info.txRetries; - stats.lostmpdu_be = info.txBad; - stats.rxmpdu_be = info.rxSuccess; - } - WifiUsabilityStatsEntry wifiUsabilityStatsEntry = - mWifiUsabilityStatsEntriesList.size() - < MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - ? new WifiUsabilityStatsEntry() : mWifiUsabilityStatsEntriesList.remove(); - wifiUsabilityStatsEntry.timeStampMs = stats.timeStampInMs; - wifiUsabilityStatsEntry.totalTxSuccess = stats.txmpdu_be + stats.txmpdu_bk - + stats.txmpdu_vi + stats.txmpdu_vo; - wifiUsabilityStatsEntry.totalTxRetries = stats.retries_be + stats.retries_bk - + stats.retries_vi + stats.retries_vo; - wifiUsabilityStatsEntry.totalTxBad = stats.lostmpdu_be + stats.lostmpdu_bk - + stats.lostmpdu_vi + stats.lostmpdu_vo; - wifiUsabilityStatsEntry.totalRxSuccess = stats.rxmpdu_be + stats.rxmpdu_bk - + stats.rxmpdu_vi + stats.rxmpdu_vo; - wifiUsabilityStatsEntry.totalRadioOnTimeMs = stats.on_time; - wifiUsabilityStatsEntry.totalRadioTxTimeMs = stats.tx_time; - wifiUsabilityStatsEntry.totalRadioRxTimeMs = stats.rx_time; - wifiUsabilityStatsEntry.totalScanTimeMs = stats.on_time_scan; - wifiUsabilityStatsEntry.totalNanScanTimeMs = stats.on_time_nan_scan; - wifiUsabilityStatsEntry.totalBackgroundScanTimeMs = stats.on_time_background_scan; - wifiUsabilityStatsEntry.totalRoamScanTimeMs = stats.on_time_roam_scan; - wifiUsabilityStatsEntry.totalPnoScanTimeMs = stats.on_time_pno_scan; - wifiUsabilityStatsEntry.totalHotspot2ScanTimeMs = stats.on_time_hs20_scan; - wifiUsabilityStatsEntry.rssi = info.getRssi(); - wifiUsabilityStatsEntry.linkSpeedMbps = info.getLinkSpeed(); - WifiLinkLayerStats.ChannelStats statsMap = - stats.channelStatsMap.get(info.getFrequency()); - if (statsMap != null) { - wifiUsabilityStatsEntry.totalRadioOnFreqTimeMs = statsMap.radioOnTimeMs; - wifiUsabilityStatsEntry.totalCcaBusyFreqTimeMs = statsMap.ccaBusyTimeMs; - } - wifiUsabilityStatsEntry.totalBeaconRx = stats.beacon_rx; - - boolean isSameBssidAndFreq = mLastBssid == null || mLastFrequency == -1 - || (mLastBssid.equals(info.getBSSID()) - && mLastFrequency == info.getFrequency()); - mLastBssid = info.getBSSID(); - mLastFrequency = info.getFrequency(); - wifiUsabilityStatsEntry.wifiScore = mLastScoreNoReset; - wifiUsabilityStatsEntry.wifiUsabilityScore = mLastWifiUsabilityScoreNoReset; - wifiUsabilityStatsEntry.seqNumToFramework = mSeqNumToFramework; - wifiUsabilityStatsEntry.predictionHorizonSec = mLastPredictionHorizonSecNoReset; - switch (mProbeStatusSinceLastUpdate) { - case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE: - wifiUsabilityStatsEntry.probeStatusSinceLastUpdate = - WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE; - break; - case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS: - wifiUsabilityStatsEntry.probeStatusSinceLastUpdate = - WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS; - break; - case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE: - wifiUsabilityStatsEntry.probeStatusSinceLastUpdate = - WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE; - break; - default: - wifiUsabilityStatsEntry.probeStatusSinceLastUpdate = - WifiUsabilityStatsEntry.PROBE_STATUS_UNKNOWN; - Log.e(TAG, "Unknown link probe status: " + mProbeStatusSinceLastUpdate); - } - wifiUsabilityStatsEntry.probeElapsedTimeSinceLastUpdateMs = - mProbeElapsedTimeSinceLastUpdateMs; - wifiUsabilityStatsEntry.probeMcsRateSinceLastUpdate = mProbeMcsRateSinceLastUpdate; - wifiUsabilityStatsEntry.rxLinkSpeedMbps = info.getRxLinkSpeedMbps(); - wifiUsabilityStatsEntry.isSameBssidAndFreq = isSameBssidAndFreq; - wifiUsabilityStatsEntry.seqNumInsideFramework = mSeqNumInsideFramework; - wifiUsabilityStatsEntry.deviceMobilityState = mCurrentDeviceMobilityState; - - mWifiUsabilityStatsEntriesList.add(wifiUsabilityStatsEntry); - mWifiUsabilityStatsCounter++; - if (mWifiUsabilityStatsCounter >= NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD) { - addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_GOOD, - WifiUsabilityStats.TYPE_UNKNOWN, -1); - } - if (mScoreBreachLowTimeMillis != -1) { - long elapsedTime = mClock.getElapsedSinceBootMillis() - mScoreBreachLowTimeMillis; - if (elapsedTime >= MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS) { - mScoreBreachLowTimeMillis = -1; - if (elapsedTime <= VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS) { - addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_GOOD, - WifiUsabilityStats.TYPE_UNKNOWN, -1); - } - } - } - - // Invoke Wifi usability stats listener. - sendWifiUsabilityStats(mSeqNumInsideFramework, isSameBssidAndFreq, - createNewWifiUsabilityStatsEntryParcelable(wifiUsabilityStatsEntry)); - - mSeqNumInsideFramework++; - mProbeStatusSinceLastUpdate = - android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE; - mProbeElapsedTimeSinceLastUpdateMs = -1; - mProbeMcsRateSinceLastUpdate = -1; - } - } - - /** - * Send Wifi usability stats. - * @param seqNum - * @param isSameBssidAndFreq - * @param statsEntry - */ - private void sendWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, - android.net.wifi.WifiUsabilityStatsEntry statsEntry) { - for (IOnWifiUsabilityStatsListener listener : mOnWifiUsabilityListeners.getCallbacks()) { - try { - listener.onWifiUsabilityStats(seqNum, isSameBssidAndFreq, statsEntry); - } catch (RemoteException e) { - Log.e(TAG, "Unable to invoke Wifi usability stats entry listener " - + listener, e); - } - } - } - - private android.net.wifi.WifiUsabilityStatsEntry createNewWifiUsabilityStatsEntryParcelable( - WifiUsabilityStatsEntry s) { - int probeStatus; - switch (s.probeStatusSinceLastUpdate) { - case WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE: - probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE; - break; - case WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS: - probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS; - break; - case WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE: - probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE; - break; - default: - probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_UNKNOWN; - Log.e(TAG, "Unknown link probe status: " + s.probeStatusSinceLastUpdate); - } - // TODO: remove the following hardcoded values once if they are removed from public API - return new android.net.wifi.WifiUsabilityStatsEntry(s.timeStampMs, s.rssi, - s.linkSpeedMbps, s.totalTxSuccess, s.totalTxRetries, - s.totalTxBad, s.totalRxSuccess, s.totalRadioOnTimeMs, - s.totalRadioTxTimeMs, s.totalRadioRxTimeMs, s.totalScanTimeMs, - s.totalNanScanTimeMs, s.totalBackgroundScanTimeMs, s.totalRoamScanTimeMs, - s.totalPnoScanTimeMs, s.totalHotspot2ScanTimeMs, s.totalCcaBusyFreqTimeMs, - s.totalRadioOnFreqTimeMs, s.totalBeaconRx, probeStatus, - s.probeElapsedTimeSinceLastUpdateMs, s.probeMcsRateSinceLastUpdate, - s.rxLinkSpeedMbps, 0, 0, 0, false - ); - } - - private WifiUsabilityStatsEntry createNewWifiUsabilityStatsEntry(WifiUsabilityStatsEntry s) { - WifiUsabilityStatsEntry out = new WifiUsabilityStatsEntry(); - out.timeStampMs = s.timeStampMs; - out.totalTxSuccess = s.totalTxSuccess; - out.totalTxRetries = s.totalTxRetries; - out.totalTxBad = s.totalTxBad; - out.totalRxSuccess = s.totalRxSuccess; - out.totalRadioOnTimeMs = s.totalRadioOnTimeMs; - out.totalRadioTxTimeMs = s.totalRadioTxTimeMs; - out.totalRadioRxTimeMs = s.totalRadioRxTimeMs; - out.totalScanTimeMs = s.totalScanTimeMs; - out.totalNanScanTimeMs = s.totalNanScanTimeMs; - out.totalBackgroundScanTimeMs = s.totalBackgroundScanTimeMs; - out.totalRoamScanTimeMs = s.totalRoamScanTimeMs; - out.totalPnoScanTimeMs = s.totalPnoScanTimeMs; - out.totalHotspot2ScanTimeMs = s.totalHotspot2ScanTimeMs; - out.rssi = s.rssi; - out.linkSpeedMbps = s.linkSpeedMbps; - out.totalCcaBusyFreqTimeMs = s.totalCcaBusyFreqTimeMs; - out.totalRadioOnFreqTimeMs = s.totalRadioOnFreqTimeMs; - out.totalBeaconRx = s.totalBeaconRx; - out.wifiScore = s.wifiScore; - out.wifiUsabilityScore = s.wifiUsabilityScore; - out.seqNumToFramework = s.seqNumToFramework; - out.predictionHorizonSec = s.predictionHorizonSec; - out.probeStatusSinceLastUpdate = s.probeStatusSinceLastUpdate; - out.probeElapsedTimeSinceLastUpdateMs = s.probeElapsedTimeSinceLastUpdateMs; - out.probeMcsRateSinceLastUpdate = s.probeMcsRateSinceLastUpdate; - out.rxLinkSpeedMbps = s.rxLinkSpeedMbps; - out.isSameBssidAndFreq = s.isSameBssidAndFreq; - out.seqNumInsideFramework = s.seqNumInsideFramework; - out.deviceMobilityState = s.deviceMobilityState; - return out; - } - - private WifiUsabilityStats createWifiUsabilityStatsWithLabel(int label, int triggerType, - int firmwareAlertCode) { - WifiUsabilityStats wifiUsabilityStats = new WifiUsabilityStats(); - wifiUsabilityStats.label = label; - wifiUsabilityStats.triggerType = triggerType; - wifiUsabilityStats.firmwareAlertCode = firmwareAlertCode; - wifiUsabilityStats.timeStampMs = mClock.getElapsedSinceBootMillis(); - wifiUsabilityStats.stats = - new WifiUsabilityStatsEntry[mWifiUsabilityStatsEntriesList.size()]; - for (int i = 0; i < mWifiUsabilityStatsEntriesList.size(); i++) { - wifiUsabilityStats.stats[i] = - createNewWifiUsabilityStatsEntry(mWifiUsabilityStatsEntriesList.get(i)); - } - return wifiUsabilityStats; - } - - /** - * Label the current snapshot of WifiUsabilityStatsEntrys and save the labeled data in memory. - * @param label WifiUsabilityStats.LABEL_GOOD or WifiUsabilityStats.LABEL_BAD - * @param triggerType what event triggers WifiUsabilityStats - * @param firmwareAlertCode the firmware alert code when the stats was triggered by a - * firmware alert - */ - public void addToWifiUsabilityStatsList(int label, int triggerType, int firmwareAlertCode) { - synchronized (mLock) { - if (mWifiUsabilityStatsEntriesList.isEmpty() || !mScreenOn) { - return; - } - if (label == WifiUsabilityStats.LABEL_GOOD) { - // Only add a good event if at least |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS| - // has passed. - if (mWifiUsabilityStatsListGood.isEmpty() - || mWifiUsabilityStatsListGood.getLast().stats[mWifiUsabilityStatsListGood - .getLast().stats.length - 1].timeStampMs - + MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS - < mWifiUsabilityStatsEntriesList.getLast().timeStampMs) { - while (mWifiUsabilityStatsListGood.size() - >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) { - mWifiUsabilityStatsListGood.remove( - mRand.nextInt(mWifiUsabilityStatsListGood.size())); - } - mWifiUsabilityStatsListGood.add( - createWifiUsabilityStatsWithLabel(label, triggerType, - firmwareAlertCode)); - } - } else { - // Only add a bad event if at least |MIN_DATA_STALL_WAIT_MS| - // has passed. - mScoreBreachLowTimeMillis = -1; - if (mWifiUsabilityStatsListBad.isEmpty() - || (mWifiUsabilityStatsListBad.getLast().stats[mWifiUsabilityStatsListBad - .getLast().stats.length - 1].timeStampMs - + MIN_DATA_STALL_WAIT_MS - < mWifiUsabilityStatsEntriesList.getLast().timeStampMs)) { - while (mWifiUsabilityStatsListBad.size() - >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) { - mWifiUsabilityStatsListBad.remove( - mRand.nextInt(mWifiUsabilityStatsListBad.size())); - } - mWifiUsabilityStatsListBad.add( - createWifiUsabilityStatsWithLabel(label, triggerType, - firmwareAlertCode)); - } - } - mWifiUsabilityStatsCounter = 0; - mWifiUsabilityStatsEntriesList.clear(); - } - } - - private DeviceMobilityStatePnoScanStats getOrCreateDeviceMobilityStatePnoScanStats( - @DeviceMobilityState int deviceMobilityState) { - DeviceMobilityStatePnoScanStats stats = mMobilityStatePnoStatsMap.get(deviceMobilityState); - if (stats == null) { - stats = new DeviceMobilityStatePnoScanStats(); - stats.deviceMobilityState = deviceMobilityState; - stats.numTimesEnteredState = 0; - stats.totalDurationMs = 0; - stats.pnoDurationMs = 0; - mMobilityStatePnoStatsMap.put(deviceMobilityState, stats); - } - return stats; - } - - /** - * Updates the current device mobility state's total duration. This method should be called - * before entering a new device mobility state. - */ - private void updateCurrentMobilityStateTotalDuration(long now) { - DeviceMobilityStatePnoScanStats stats = - getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState); - stats.totalDurationMs += now - mCurrentDeviceMobilityStateStartMs; - mCurrentDeviceMobilityStateStartMs = now; - } - - /** - * Convert the IntCounter of passpoint profile types and counts to proto's - * repeated IntKeyVal array. - * - * @param passpointProfileTypes passpoint profile types and counts. - */ - private PasspointProfileTypeCount[] convertPasspointProfilesToProto( - IntCounter passpointProfileTypes) { - return passpointProfileTypes.toProto(PasspointProfileTypeCount.class, (key, count) -> { - PasspointProfileTypeCount entry = new PasspointProfileTypeCount(); - entry.eapMethodType = key; - entry.count = count; - return entry; - }); - } - - /** - * Reports that the device entered a new mobility state. - * - * @param newState the new device mobility state. - */ - public void enterDeviceMobilityState(@DeviceMobilityState int newState) { - synchronized (mLock) { - long now = mClock.getElapsedSinceBootMillis(); - updateCurrentMobilityStateTotalDuration(now); - - if (newState == mCurrentDeviceMobilityState) return; - - mCurrentDeviceMobilityState = newState; - DeviceMobilityStatePnoScanStats stats = - getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState); - stats.numTimesEnteredState++; - } - } - - /** - * Logs the start of a PNO scan. - */ - public void logPnoScanStart() { - synchronized (mLock) { - long now = mClock.getElapsedSinceBootMillis(); - mCurrentDeviceMobilityStatePnoScanStartMs = now; - updateCurrentMobilityStateTotalDuration(now); - } - } - - /** - * Logs the end of a PNO scan. This is attributed to the current device mobility state, as - * logged by {@link #enterDeviceMobilityState(int)}. Thus, if the mobility state changes during - * a PNO scan, one should call {@link #logPnoScanStop()}, {@link #enterDeviceMobilityState(int)} - * , then {@link #logPnoScanStart()} so that the portion of PNO scan before the mobility state - * change can be correctly attributed to the previous mobility state. - */ - public void logPnoScanStop() { - synchronized (mLock) { - if (mCurrentDeviceMobilityStatePnoScanStartMs < 0) { - Log.e(TAG, "Called WifiMetrics#logPNoScanStop() without calling " - + "WifiMetrics#logPnoScanStart() first!"); - return; - } - DeviceMobilityStatePnoScanStats stats = - getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState); - long now = mClock.getElapsedSinceBootMillis(); - stats.pnoDurationMs += now - mCurrentDeviceMobilityStatePnoScanStartMs; - mCurrentDeviceMobilityStatePnoScanStartMs = -1; - updateCurrentMobilityStateTotalDuration(now); - } - } - - /** - * Add a new listener for Wi-Fi usability stats handling. - */ - public void addOnWifiUsabilityListener(IBinder binder, IOnWifiUsabilityStatsListener listener, - int listenerIdentifier) { - if (!mOnWifiUsabilityListeners.add(binder, listener, listenerIdentifier)) { - Log.e(TAG, "Failed to add listener"); - return; - } - if (DBG) { - Log.v(TAG, "Adding listener. Num listeners: " - + mOnWifiUsabilityListeners.getNumCallbacks()); - } - } - - /** - * Remove an existing listener for Wi-Fi usability stats handling. - */ - public void removeOnWifiUsabilityListener(int listenerIdentifier) { - mOnWifiUsabilityListeners.remove(listenerIdentifier); - if (DBG) { - Log.v(TAG, "Removing listener. Num listeners: " - + mOnWifiUsabilityListeners.getNumCallbacks()); - } - } - - /** - * Updates the Wi-Fi usability score and increments occurence of a particular Wifi usability - * score passed in from outside framework. Scores are bounded within - * [MIN_WIFI_USABILITY_SCORE, MAX_WIFI_USABILITY_SCORE]. - * - * Also records events when the Wifi usability score breaches significant thresholds. - * - * @param seqNum Sequence number of the Wi-Fi usability score. - * @param score The Wi-Fi usability score. - * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score. - */ - public void incrementWifiUsabilityScoreCount(int seqNum, int score, int predictionHorizonSec) { - if (score < MIN_WIFI_USABILITY_SCORE || score > MAX_WIFI_USABILITY_SCORE) { - return; - } - synchronized (mLock) { - mSeqNumToFramework = seqNum; - mLastWifiUsabilityScore = score; - mLastWifiUsabilityScoreNoReset = score; - mWifiUsabilityScoreCounts.put(score, mWifiUsabilityScoreCounts.get(score) + 1); - mLastPredictionHorizonSec = predictionHorizonSec; - mLastPredictionHorizonSecNoReset = predictionHorizonSec; - - boolean wifiWins = mWifiWinsUsabilityScore; - if (score > LOW_WIFI_USABILITY_SCORE) { - wifiWins = true; - } else if (score < LOW_WIFI_USABILITY_SCORE) { - wifiWins = false; - } - - if (wifiWins != mWifiWinsUsabilityScore) { - mWifiWinsUsabilityScore = wifiWins; - StaEvent event = new StaEvent(); - event.type = StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH; - addStaEvent(event); - // Only record the first score breach by checking whether mScoreBreachLowTimeMillis - // has been set to -1 - if (!wifiWins && mScoreBreachLowTimeMillis == -1) { - mScoreBreachLowTimeMillis = mClock.getElapsedSinceBootMillis(); - } - } - } - } - - /** - * Reports stats for a successful link probe. - * - * @param timeSinceLastTxSuccessMs At {@code startTimestampMs}, the number of milliseconds since - * the last Tx success (according to - * {@link WifiInfo#txSuccess}). - * @param rssi The Rx RSSI at {@code startTimestampMs}. - * @param linkSpeed The Tx link speed in Mbps at {@code startTimestampMs}. - * @param elapsedTimeMs The number of milliseconds between when the command to transmit the - * probe was sent to the driver and when the driver responded that the - * probe was ACKed. Note: this number should be correlated with the number - * of retries that the driver attempted before the probe was ACKed. - */ - public void logLinkProbeSuccess(long timeSinceLastTxSuccessMs, - int rssi, int linkSpeed, int elapsedTimeMs) { - synchronized (mLock) { - mProbeStatusSinceLastUpdate = - android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS; - mProbeElapsedTimeSinceLastUpdateMs = elapsedTimeMs; - - mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.increment( - (int) (timeSinceLastTxSuccessMs / 1000)); - mLinkProbeSuccessRssiCounts.increment(rssi); - mLinkProbeSuccessLinkSpeedCounts.increment(linkSpeed); - mLinkProbeSuccessElapsedTimeMsHistogram.increment(elapsedTimeMs); - - if (mLinkProbeStaEventCount < MAX_LINK_PROBE_STA_EVENTS) { - StaEvent event = new StaEvent(); - event.type = StaEvent.TYPE_LINK_PROBE; - event.linkProbeWasSuccess = true; - event.linkProbeSuccessElapsedTimeMs = elapsedTimeMs; - addStaEvent(event); - } - mLinkProbeStaEventCount++; - } - } - - /** - * Reports stats for an unsuccessful link probe. - * - * @param timeSinceLastTxSuccessMs At {@code startTimestampMs}, the number of milliseconds since - * the last Tx success (according to - * {@link WifiInfo#txSuccess}). - * @param rssi The Rx RSSI at {@code startTimestampMs}. - * @param linkSpeed The Tx link speed in Mbps at {@code startTimestampMs}. - * @param reason The error code for the failure. See - * {@link WifiNl80211Manager.SendMgmtFrameError}. - */ - public void logLinkProbeFailure(long timeSinceLastTxSuccessMs, - int rssi, int linkSpeed, int reason) { - synchronized (mLock) { - mProbeStatusSinceLastUpdate = - android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE; - mProbeElapsedTimeSinceLastUpdateMs = Integer.MAX_VALUE; - - mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.increment( - (int) (timeSinceLastTxSuccessMs / 1000)); - mLinkProbeFailureRssiCounts.increment(rssi); - mLinkProbeFailureLinkSpeedCounts.increment(linkSpeed); - mLinkProbeFailureReasonCounts.increment(reason); - - if (mLinkProbeStaEventCount < MAX_LINK_PROBE_STA_EVENTS) { - StaEvent event = new StaEvent(); - event.type = StaEvent.TYPE_LINK_PROBE; - event.linkProbeWasSuccess = false; - event.linkProbeFailureReason = linkProbeFailureReasonToProto(reason); - addStaEvent(event); - } - mLinkProbeStaEventCount++; - } - } - - /** - * Increments the number of probes triggered by the experiment `experimentId`. - */ - public void incrementLinkProbeExperimentProbeCount(String experimentId) { - synchronized (mLock) { - mLinkProbeExperimentProbeCounts.increment(experimentId); - } - } - - /** - * Update wifi config store read duration. - * - * @param timeMs Time it took to complete the operation, in milliseconds - */ - public void noteWifiConfigStoreReadDuration(int timeMs) { - synchronized (mLock) { - MetricsUtils.addValueToLinearHistogram(timeMs, mWifiConfigStoreReadDurationHistogram, - WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS); - } - } - - /** - * Update wifi config store write duration. - * - * @param timeMs Time it took to complete the operation, in milliseconds - */ - public void noteWifiConfigStoreWriteDuration(int timeMs) { - synchronized (mLock) { - MetricsUtils.addValueToLinearHistogram(timeMs, mWifiConfigStoreWriteDurationHistogram, - WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS); - } - } - - /** - * Logs the decision of a network selection algorithm when compared against another network - * selection algorithm. - * - * @param experiment1Id ID of one experiment - * @param experiment2Id ID of the other experiment - * @param isSameDecision did the 2 experiments make the same decision? - * @param numNetworkChoices the number of non-null network choices there were, where the null - * choice is not selecting any network - */ - public void logNetworkSelectionDecision(int experiment1Id, int experiment2Id, - boolean isSameDecision, int numNetworkChoices) { - if (numNetworkChoices < 0) { - Log.e(TAG, "numNetworkChoices cannot be negative!"); - return; - } - if (experiment1Id == experiment2Id) { - Log.e(TAG, "comparing the same experiment id: " + experiment1Id); - return; - } - - Pair<Integer, Integer> key = new Pair<>(experiment1Id, experiment2Id); - synchronized (mLock) { - NetworkSelectionExperimentResults results = - mNetworkSelectionExperimentPairNumChoicesCounts - .computeIfAbsent(key, k -> new NetworkSelectionExperimentResults()); - - IntCounter counter = isSameDecision - ? results.sameSelectionNumChoicesCounter - : results.differentSelectionNumChoicesCounter; - - counter.increment(numNetworkChoices); - } - } - - /** Increment number of network request API usage stats */ - public void incrementNetworkRequestApiNumRequest() { - synchronized (mLock) { - mWifiNetworkRequestApiLog.numRequest++; - } - } - - /** Add to the network request API match size histogram */ - public void incrementNetworkRequestApiMatchSizeHistogram(int matchSize) { - synchronized (mLock) { - mWifiNetworkRequestApiMatchSizeHistogram.increment(matchSize); - } - } - - /** Increment number of connection success via network request API */ - public void incrementNetworkRequestApiNumConnectSuccess() { - synchronized (mLock) { - mWifiNetworkRequestApiLog.numConnectSuccess++; - } - } - - /** Increment number of requests that bypassed user approval via network request API */ - public void incrementNetworkRequestApiNumUserApprovalBypass() { - synchronized (mLock) { - mWifiNetworkRequestApiLog.numUserApprovalBypass++; - } - } - - /** Increment number of requests that user rejected via network request API */ - public void incrementNetworkRequestApiNumUserReject() { - synchronized (mLock) { - mWifiNetworkRequestApiLog.numUserReject++; - } - } - - /** Increment number of requests from unique apps via network request API */ - public void incrementNetworkRequestApiNumApps() { - synchronized (mLock) { - mWifiNetworkRequestApiLog.numApps++; - } - } - - /** Increment number of network suggestion API modification by app stats */ - public void incrementNetworkSuggestionApiNumModification() { - synchronized (mLock) { - mWifiNetworkSuggestionApiLog.numModification++; - } - } - - /** Increment number of connection success via network suggestion API */ - public void incrementNetworkSuggestionApiNumConnectSuccess() { - synchronized (mLock) { - mWifiNetworkSuggestionApiLog.numConnectSuccess++; - } - } - - /** Increment number of connection failure via network suggestion API */ - public void incrementNetworkSuggestionApiNumConnectFailure() { - synchronized (mLock) { - mWifiNetworkSuggestionApiLog.numConnectFailure++; - } - } - - /** Increment number of user revoke suggestion permission. Including from settings or - * disallowed from UI. - */ - public void incrementNetworkSuggestionUserRevokePermission() { - synchronized (mLock) { - mWifiNetworkSuggestionApiLog.userRevokeAppSuggestionPermission++; - } - } - - /** Clear and set the latest network suggestion API max list size histogram */ - public void noteNetworkSuggestionApiListSizeHistogram(List<Integer> listSizes) { - synchronized (mLock) { - mWifiNetworkSuggestionApiListSizeHistogram.clear(); - for (Integer listSize : listSizes) { - mWifiNetworkSuggestionApiListSizeHistogram.increment(listSize); - } - } - } - - /** Increment number of app add suggestion with different privilege */ - public void incrementNetworkSuggestionApiUsageNumOfAppInType(int appType) { - int typeCode; - synchronized (mLock) { - switch (appType) { - case WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED: - typeCode = WifiNetworkSuggestionApiLog.TYPE_CARRIER_PRIVILEGED; - break; - case WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING: - typeCode = WifiNetworkSuggestionApiLog.TYPE_NETWORK_PROVISIONING; - break; - case WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED: - typeCode = WifiNetworkSuggestionApiLog.TYPE_NON_PRIVILEGED; - break; - default: - typeCode = WifiNetworkSuggestionApiLog.TYPE_UNKNOWN; - } - mWifiNetworkSuggestionApiAppTypeCounter.increment(typeCode); - } - } - - /** Add user action to the approval suggestion app UI */ - public void addUserApprovalSuggestionAppUiReaction(@WifiNetworkSuggestionsManager.UserActionCode - int actionType, boolean isDialog) { - int actionCode; - switch (actionType) { - case WifiNetworkSuggestionsManager.ACTION_USER_ALLOWED_APP: - actionCode = UserReactionToApprovalUiEvent.ACTION_ALLOWED; - break; - case WifiNetworkSuggestionsManager.ACTION_USER_DISALLOWED_APP: - actionCode = UserReactionToApprovalUiEvent.ACTION_DISALLOWED; - break; - case WifiNetworkSuggestionsManager.ACTION_USER_DISMISS: - actionCode = UserReactionToApprovalUiEvent.ACTION_DISMISS; - break; - default: - actionCode = UserReactionToApprovalUiEvent.ACTION_UNKNOWN; - } - UserReaction event = new UserReaction(); - event.userAction = actionCode; - event.isDialog = isDialog; - synchronized (mLock) { - mUserApprovalSuggestionAppUiReactionList.add(event); - } - } - - /** Add user action to the approval Carrier Imsi protection exemption UI */ - public void addUserApprovalCarrierUiReaction(@WifiCarrierInfoManager.UserActionCode - int actionType, boolean isDialog) { - int actionCode; - switch (actionType) { - case WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER: - actionCode = UserReactionToApprovalUiEvent.ACTION_ALLOWED; - break; - case WifiCarrierInfoManager.ACTION_USER_DISALLOWED_CARRIER: - actionCode = UserReactionToApprovalUiEvent.ACTION_DISALLOWED; - break; - case WifiCarrierInfoManager.ACTION_USER_DISMISS: - actionCode = UserReactionToApprovalUiEvent.ACTION_DISMISS; - break; - default: - actionCode = UserReactionToApprovalUiEvent.ACTION_UNKNOWN; - } - UserReaction event = new UserReaction(); - event.userAction = actionCode; - event.isDialog = isDialog; - - synchronized (mLock) { - mUserApprovalCarrierUiReactionList.add(event); - } - } - - /** - * Sets the nominator for a network (i.e. which entity made the suggestion to connect) - * @param networkId the ID of the network, from its {@link WifiConfiguration} - * @param nominatorId the entity that made the suggestion to connect to this network, - * from {@link WifiMetricsProto.ConnectionEvent.ConnectionNominator} - */ - public void setNominatorForNetwork(int networkId, int nominatorId) { - synchronized (mLock) { - if (networkId == WifiConfiguration.INVALID_NETWORK_ID) return; - mNetworkIdToNominatorId.put(networkId, nominatorId); - - // user connect choice is preventing switcing off from the connected network - if (nominatorId - == WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE - && mWifiStatusBuilder.getNetworkId() == networkId) { - mWifiStatusBuilder.setUserChoice(true); - } - } - } - - /** - * Sets the numeric CandidateScorer id. - */ - public void setNetworkSelectorExperimentId(int expId) { - synchronized (mLock) { - mNetworkSelectorExperimentId = expId; - } - } - - /** Add a WifiLock acqusition session */ - public void addWifiLockAcqSession(int lockType, long duration) { - switch (lockType) { - case WifiManager.WIFI_MODE_FULL_HIGH_PERF: - mWifiLockHighPerfAcqDurationSecHistogram.increment((int) (duration / 1000)); - break; - - case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: - mWifiLockLowLatencyAcqDurationSecHistogram.increment((int) (duration / 1000)); - break; - - default: - Log.e(TAG, "addWifiLockAcqSession: Invalid lock type: " + lockType); - break; - } - } - - /** Add a WifiLock active session */ - public void addWifiLockActiveSession(int lockType, long duration) { - switch (lockType) { - case WifiManager.WIFI_MODE_FULL_HIGH_PERF: - mWifiLockStats.highPerfActiveTimeMs += duration; - mWifiLockHighPerfActiveSessionDurationSecHistogram.increment( - (int) (duration / 1000)); - break; - - case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: - mWifiLockStats.lowLatencyActiveTimeMs += duration; - mWifiLockLowLatencyActiveSessionDurationSecHistogram.increment( - (int) (duration / 1000)); - break; - - default: - Log.e(TAG, "addWifiLockActiveSession: Invalid lock type: " + lockType); - break; - } - } - - /** Increments metrics counting number of addOrUpdateNetwork calls. **/ - public void incrementNumAddOrUpdateNetworkCalls() { - synchronized (mLock) { - mWifiLogProto.numAddOrUpdateNetworkCalls++; - } - } - - /** Increments metrics counting number of enableNetwork calls. **/ - public void incrementNumEnableNetworkCalls() { - synchronized (mLock) { - mWifiLogProto.numEnableNetworkCalls++; - } - } - - /** Add to WifiToggleStats **/ - public void incrementNumWifiToggles(boolean isPrivileged, boolean enable) { - synchronized (mLock) { - if (isPrivileged && enable) { - mWifiToggleStats.numToggleOnPrivileged++; - } else if (isPrivileged && !enable) { - mWifiToggleStats.numToggleOffPrivileged++; - } else if (!isPrivileged && enable) { - mWifiToggleStats.numToggleOnNormal++; - } else { - mWifiToggleStats.numToggleOffNormal++; - } - } - } - - /** - * Increment number of passpoint provision failure - * @param failureCode indicates error condition - */ - public void incrementPasspointProvisionFailure(int failureCode) { - int provisionFailureCode; - synchronized (mLock) { - switch (failureCode) { - case ProvisioningCallback.OSU_FAILURE_AP_CONNECTION: - provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION; - break; - case ProvisioningCallback.OSU_FAILURE_SERVER_URL_INVALID: - provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_URL_INVALID; - break; - case ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION: - provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_CONNECTION; - break; - case ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION: - provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_VALIDATION; - break; - case ProvisioningCallback.OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION; - break; - case ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED: - provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_PROVISIONING_ABORTED; - break; - case ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_PROVISIONING_NOT_AVAILABLE; - break; - case ProvisioningCallback.OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU; - break; - case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_COMMAND_TYPE: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_UNEXPECTED_COMMAND_TYPE; - break; - case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE; - break; - case ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_SOAP_MESSAGE_EXCHANGE; - break; - case ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_START_REDIRECT_LISTENER; - break; - case ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER; - break; - case ProvisioningCallback.OSU_FAILURE_NO_OSU_ACTIVITY_FOUND: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_NO_OSU_ACTIVITY_FOUND; - break; - case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS; - break; - case ProvisioningCallback.OSU_FAILURE_NO_PPS_MO: - provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_NO_PPS_MO; - break; - case ProvisioningCallback.OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE; - break; - case ProvisioningCallback.OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE; - break; - case ProvisioningCallback.OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE; - break; - case ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES; - break; - case ProvisioningCallback.OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE; - break; - case ProvisioningCallback.OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION; - break; - case ProvisioningCallback.OSU_FAILURE_OSU_PROVIDER_NOT_FOUND: - provisionFailureCode = PasspointProvisionStats - .OSU_FAILURE_OSU_PROVIDER_NOT_FOUND; - break; - default: - provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_UNKNOWN; - } - mPasspointProvisionFailureCounts.increment(provisionFailureCode); - } - } - - /** - * Add to the histogram of number of BSSIDs filtered out from network selection. - */ - public void incrementNetworkSelectionFilteredBssidCount(int numBssid) { - mBssidBlocklistStats.networkSelectionFilteredBssidCount.increment(numBssid); - } - - /** - * Increment the number of network connections skipped due to the high movement feature. - */ - public void incrementNumHighMovementConnectionSkipped() { - mBssidBlocklistStats.numHighMovementConnectionSkipped++; - } - - /** - * Increment the number of network connections initiated while under the high movement - * feature. - */ - public void incrementNumHighMovementConnectionStarted() { - mBssidBlocklistStats.numHighMovementConnectionStarted++; - } - - /** - * Increment number of passpoint provision success - */ - public void incrementPasspointProvisionSuccess() { - synchronized (mLock) { - mNumProvisionSuccess++; - } - } - - /** - * Increment number of IP renewal failures. - */ - public void incrementIpRenewalFailure() { - synchronized (mLock) { - mWifiLogProto.numIpRenewalFailure++; - } - } - - /** - * Sets the duration for evaluating Wifi condition to trigger a data stall - */ - public void setDataStallDurationMs(int duration) { - synchronized (mLock) { - mExperimentValues.dataStallDurationMs = duration; - } - } - - /** - * Sets the threshold of Tx throughput below which to trigger a data stall - */ - public void setDataStallTxTputThrKbps(int txTputThr) { - synchronized (mLock) { - mExperimentValues.dataStallTxTputThrKbps = txTputThr; - } - } - - /** - * Sets the threshold of Rx throughput below which to trigger a data stall - */ - public void setDataStallRxTputThrKbps(int rxTputThr) { - synchronized (mLock) { - mExperimentValues.dataStallRxTputThrKbps = rxTputThr; - } - } - - /** - * Sets the threshold of Tx packet error rate above which to trigger a data stall - */ - public void setDataStallTxPerThr(int txPerThr) { - synchronized (mLock) { - mExperimentValues.dataStallTxPerThr = txPerThr; - } - } - - /** - * Sets the threshold of CCA level above which to trigger a data stall - */ - public void setDataStallCcaLevelThr(int ccaLevel) { - synchronized (mLock) { - mExperimentValues.dataStallCcaLevelThr = ccaLevel; - } - } - - /** - * Sets health monitor RSSI poll valid time in ms - */ - public void setHealthMonitorRssiPollValidTimeMs(int rssiPollValidTimeMs) { - synchronized (mLock) { - mExperimentValues.healthMonitorRssiPollValidTimeMs = rssiPollValidTimeMs; - } - } - - /** - * Increment connection duration while link layer stats report are on - */ - public void incrementConnectionDuration(int timeDeltaLastTwoPollsMs, - boolean isThroughputSufficient, boolean isCellularDataAvailable) { - synchronized (mLock) { - mConnectionDurationStats.incrementDurationCount(timeDeltaLastTwoPollsMs, - isThroughputSufficient, isCellularDataAvailable); - } - } - - /** - * Sets the status to indicate whether external WiFi connected network scorer is present or not. - */ - public void setIsExternalWifiScorerOn(boolean value) { - synchronized (mLock) { - mWifiLogProto.isExternalWifiScorerOn = value; - } - } - - /** - * Note Wi-Fi off metrics - */ - public void noteWifiOff(boolean isDeferred, boolean isTimeout, int duration) { - synchronized (mLock) { - mWifiOffMetrics.numWifiOff++; - if (isDeferred) { - mWifiOffMetrics.numWifiOffDeferring++; - if (isTimeout) { - mWifiOffMetrics.numWifiOffDeferringTimeout++; - } - mWifiOffMetrics.wifiOffDeferringTimeHistogram.increment(duration); - } - } - } - - /** - * Increment number of BSSIDs filtered out from network selection due to MBO Association - * disallowed indication. - */ - public void incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd() { - synchronized (mLock) { - mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd++; - } - } - - /** - * Increment number of times force scan is triggered due to a - * BSS transition management request frame from AP. - */ - public void incrementForceScanCountDueToSteeringRequest() { - synchronized (mLock) { - mWifiLogProto.numForceScanDueToSteeringRequest++; - } - } - - /** - * Increment number of times STA received cellular switch - * request from MBO supported AP. - */ - public void incrementMboCellularSwitchRequestCount() { - synchronized (mLock) { - mWifiLogProto.numMboCellularSwitchRequest++; - } - } - - /** - * Increment number of times STA received steering request - * including MBO association retry delay. - */ - public void incrementSteeringRequestCountIncludingMboAssocRetryDelay() { - synchronized (mLock) { - mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay++; - } - } - - /** - * Increment number of connect request to AP adding FILS AKM. - */ - public void incrementConnectRequestWithFilsAkmCount() { - synchronized (mLock) { - mWifiLogProto.numConnectRequestWithFilsAkm++; - } - } - - /** - * Increment number of times STA connected through FILS - * authentication. - */ - public void incrementL2ConnectionThroughFilsAuthCount() { - synchronized (mLock) { - mWifiLogProto.numL2ConnectionThroughFilsAuthentication++; - } - } - - /** - * Note SoftapConfig Reset Metrics - */ - public void noteSoftApConfigReset(SoftApConfiguration originalConfig, - SoftApConfiguration newConfig) { - synchronized (mLock) { - if (originalConfig.getSecurityType() != newConfig.getSecurityType()) { - mSoftApConfigLimitationMetrics.numSecurityTypeResetToDefault++; - } - if (originalConfig.getMaxNumberOfClients() != newConfig.getMaxNumberOfClients()) { - mSoftApConfigLimitationMetrics.numMaxClientSettingResetToDefault++; - } - if (originalConfig.isClientControlByUserEnabled() - != newConfig.isClientControlByUserEnabled()) { - mSoftApConfigLimitationMetrics.numClientControlByUserResetToDefault++; - } - } - } - - /** - * Note Softap client blocked due to max client limitation - */ - public void noteSoftApClientBlocked(int maxClient) { - mSoftApConfigLimitationMetrics.maxClientSettingWhenReachHistogram.increment(maxClient); - } - - /** - * Increment number of connection with different BSSID between framework and firmware selection. - */ - public void incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware() { - synchronized (mLock) { - mWifiLogProto.numBssidDifferentSelectionBetweenFrameworkAndFirmware++; - } - } - - /** - * Note the carrier wifi network connected successfully. - */ - public void incrementNumOfCarrierWifiConnectionSuccess() { - synchronized (mLock) { - mCarrierWifiMetrics.numConnectionSuccess++; - } - } - - /** - * Note the carrier wifi network connection authentication failure. - */ - public void incrementNumOfCarrierWifiConnectionAuthFailure() { - synchronized (mLock) { - mCarrierWifiMetrics.numConnectionAuthFailure++; - } - } - - /** - * Note the carrier wifi network connection non-authentication failure. - */ - public void incrementNumOfCarrierWifiConnectionNonAuthFailure() { - synchronized (mLock) { - mCarrierWifiMetrics.numConnectionNonAuthFailure++; - } - } - - /** - * Set Adaptive Connectivity state (On/Off) - */ - public void setAdaptiveConnectivityState(boolean adaptiveConnectivityEnabled) { - synchronized (mLock) { - mAdaptiveConnectivityEnabled = adaptiveConnectivityEnabled; - } - } -} diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java deleted file mode 100644 index 32a96d0eb..000000000 --- a/service/java/com/android/server/wifi/WifiMonitor.java +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright (C) 2008 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.server.wifi; - -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.Message; -import android.util.ArraySet; -import android.util.Log; -import android.util.SparseArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Protocol; -import com.android.server.wifi.MboOceController.BtmFrameData; -import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData; -import com.android.server.wifi.hotspot2.AnqpEvent; -import com.android.server.wifi.hotspot2.IconEvent; -import com.android.server.wifi.hotspot2.WnmData; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Listen for events from the wpa_supplicant & wificond and broadcast them on - * to the various {@link ClientModeImpl} modules interested in handling these events. - * @hide - */ -public class WifiMonitor { - private static final String TAG = "WifiMonitor"; - - /* Supplicant events reported to a state machine */ - private static final int BASE = Protocol.BASE_WIFI_MONITOR; - - /* Connection to supplicant established */ - public static final int SUP_CONNECTION_EVENT = BASE + 1; - /* Connection to supplicant lost */ - public static final int SUP_DISCONNECTION_EVENT = BASE + 2; - /* Network connection completed */ - public static final int NETWORK_CONNECTION_EVENT = BASE + 3; - /* Network disconnection completed */ - public static final int NETWORK_DISCONNECTION_EVENT = BASE + 4; - /* Scan results are available */ - public static final int SCAN_RESULTS_EVENT = BASE + 5; - /* Supplicate state changed */ - public static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 6; - /* Password failure and EAP authentication failure */ - public static final int AUTHENTICATION_FAILURE_EVENT = BASE + 7; - /* WPS success detected */ - public static final int WPS_SUCCESS_EVENT = BASE + 8; - /* WPS failure detected */ - public static final int WPS_FAIL_EVENT = BASE + 9; - /* WPS overlap detected */ - public static final int WPS_OVERLAP_EVENT = BASE + 10; - /* WPS timeout detected */ - public static final int WPS_TIMEOUT_EVENT = BASE + 11; - - /* Request Identity */ - public static final int SUP_REQUEST_IDENTITY = BASE + 15; - - /* Request SIM Auth */ - public static final int SUP_REQUEST_SIM_AUTH = BASE + 16; - - public static final int SCAN_FAILED_EVENT = BASE + 17; - /* Pno scan results are available */ - public static final int PNO_SCAN_RESULTS_EVENT = BASE + 18; - - - /* Indicates assoc reject event */ - public static final int ASSOCIATION_REJECTION_EVENT = BASE + 43; - public static final int ANQP_DONE_EVENT = BASE + 44; - public static final int ASSOCIATED_BSSID_EVENT = BASE + 45; - public static final int TARGET_BSSID_EVENT = BASE + 46; - - /* hotspot 2.0 ANQP events */ - public static final int GAS_QUERY_START_EVENT = BASE + 51; - public static final int GAS_QUERY_DONE_EVENT = BASE + 52; - public static final int RX_HS20_ANQP_ICON_EVENT = BASE + 53; - - /* hotspot 2.0 events */ - public static final int HS20_REMEDIATION_EVENT = BASE + 61; - - /* MBO/OCE events */ - public static final int MBO_OCE_BSS_TM_HANDLING_DONE = BASE + 71; - - /* WPS config errrors */ - private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12; - private static final int CONFIG_AUTH_FAILURE = 18; - - /* WPS error indications */ - private static final int REASON_TKIP_ONLY_PROHIBITED = 1; - private static final int REASON_WEP_PROHIBITED = 2; - - private final WifiInjector mWifiInjector; - private boolean mVerboseLoggingEnabled = false; - private boolean mConnected = false; - - public WifiMonitor(WifiInjector wifiInjector) { - mWifiInjector = wifiInjector; - } - - void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mVerboseLoggingEnabled = true; - } else { - mVerboseLoggingEnabled = false; - } - } - - private final Map<String, SparseArray<Set<Handler>>> mHandlerMap = new HashMap<>(); - public synchronized void registerHandler(String iface, int what, Handler handler) { - SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); - if (ifaceHandlers == null) { - ifaceHandlers = new SparseArray<>(); - mHandlerMap.put(iface, ifaceHandlers); - } - Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what); - if (ifaceWhatHandlers == null) { - ifaceWhatHandlers = new ArraySet<>(); - ifaceHandlers.put(what, ifaceWhatHandlers); - } - ifaceWhatHandlers.add(handler); - } - - /** - * Deregister the given |handler| - * @param iface - * @param what - * @param handler - */ - public synchronized void deregisterHandler(String iface, int what, Handler handler) { - SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); - if (ifaceHandlers == null) { - return; - } - Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what); - if (ifaceWhatHandlers == null) { - return; - } - ifaceWhatHandlers.remove(handler); - } - - private final Map<String, Boolean> mMonitoringMap = new HashMap<>(); - private boolean isMonitoring(String iface) { - Boolean val = mMonitoringMap.get(iface); - if (val == null) { - return false; - } else { - return val.booleanValue(); - } - } - - /** - * Enable/Disable monitoring for the provided iface. - * - * @param iface Name of the iface. - * @param enabled true to enable, false to disable. - */ - @VisibleForTesting - public void setMonitoring(String iface, boolean enabled) { - mMonitoringMap.put(iface, enabled); - } - - private void setMonitoringNone() { - for (String iface : mMonitoringMap.keySet()) { - setMonitoring(iface, false); - } - } - - /** - * Start Monitoring for wpa_supplicant events. - * - * @param iface Name of iface. - */ - public synchronized void startMonitoring(String iface) { - if (mVerboseLoggingEnabled) Log.d(TAG, "startMonitoring(" + iface + ")"); - setMonitoring(iface, true); - broadcastSupplicantConnectionEvent(iface); - } - - /** - * Stop Monitoring for wpa_supplicant events. - * - * @param iface Name of iface. - */ - public synchronized void stopMonitoring(String iface) { - if (mVerboseLoggingEnabled) Log.d(TAG, "stopMonitoring(" + iface + ")"); - setMonitoring(iface, true); - broadcastSupplicantDisconnectionEvent(iface); - setMonitoring(iface, false); - } - - /** - * Stop Monitoring for wpa_supplicant events. - * - * TODO: Add unit tests for these once we remove the legacy code. - */ - public synchronized void stopAllMonitoring() { - mConnected = false; - setMonitoringNone(); - } - - - /** - * Similar functions to Handler#sendMessage that send the message to the registered handler - * for the given interface and message what. - * All of these should be called with the WifiMonitor class lock - */ - private void sendMessage(String iface, int what) { - sendMessage(iface, Message.obtain(null, what)); - } - - private void sendMessage(String iface, int what, Object obj) { - sendMessage(iface, Message.obtain(null, what, obj)); - } - - private void sendMessage(String iface, int what, int arg1) { - sendMessage(iface, Message.obtain(null, what, arg1, 0)); - } - - private void sendMessage(String iface, int what, int arg1, int arg2) { - sendMessage(iface, Message.obtain(null, what, arg1, arg2)); - } - - private void sendMessage(String iface, int what, int arg1, int arg2, Object obj) { - sendMessage(iface, Message.obtain(null, what, arg1, arg2, obj)); - } - - private void sendMessage(String iface, Message message) { - SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); - if (iface != null && ifaceHandlers != null) { - if (isMonitoring(iface)) { - Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(message.what); - if (ifaceWhatHandlers != null) { - for (Handler handler : ifaceWhatHandlers) { - if (handler != null) { - sendMessage(handler, Message.obtain(message)); - } - } - } - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Dropping event because (" + iface + ") is stopped"); - } - } - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Sending to all monitors because there's no matching iface"); - } - for (Map.Entry<String, SparseArray<Set<Handler>>> entry : mHandlerMap.entrySet()) { - if (isMonitoring(entry.getKey())) { - Set<Handler> ifaceWhatHandlers = entry.getValue().get(message.what); - for (Handler handler : ifaceWhatHandlers) { - if (handler != null) { - sendMessage(handler, Message.obtain(message)); - } - } - } - } - } - - message.recycle(); - } - - private void sendMessage(Handler handler, Message message) { - message.setTarget(handler); - message.sendToTarget(); - } - - /** - * Broadcast the WPS fail event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param cfgError Configuration error code. - * @param vendorErrorCode Vendor specific error indication code. - */ - public void broadcastWpsFailEvent(String iface, int cfgError, int vendorErrorCode) { - int reason = 0; - switch(vendorErrorCode) { - case REASON_TKIP_ONLY_PROHIBITED: - sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_TKIP_ONLY_PROHIBITED); - return; - case REASON_WEP_PROHIBITED: - sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_WEP_PROHIBITED); - return; - default: - reason = vendorErrorCode; - break; - } - switch(cfgError) { - case CONFIG_AUTH_FAILURE: - sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_AUTH_FAILURE); - return; - case CONFIG_MULTIPLE_PBC_DETECTED: - sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_OVERLAP_ERROR); - return; - default: - if (reason == 0) { - reason = cfgError; - } - break; - } - //For all other errors, return a generic internal error - sendMessage(iface, WPS_FAIL_EVENT, WifiManager.ERROR, reason); - } - - /** - * Broadcast the WPS succes event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastWpsSuccessEvent(String iface) { - sendMessage(iface, WPS_SUCCESS_EVENT); - } - - /** - * Broadcast the WPS overlap event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastWpsOverlapEvent(String iface) { - sendMessage(iface, WPS_OVERLAP_EVENT); - } - - /** - * Broadcast the WPS timeout event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastWpsTimeoutEvent(String iface) { - sendMessage(iface, WPS_TIMEOUT_EVENT); - } - - /** - * Broadcast the ANQP done event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param anqpEvent ANQP result retrieved. - */ - public void broadcastAnqpDoneEvent(String iface, AnqpEvent anqpEvent) { - sendMessage(iface, ANQP_DONE_EVENT, anqpEvent); - } - - /** - * Broadcast the Icon done event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param iconEvent Instance of IconEvent containing the icon data retrieved. - */ - public void broadcastIconDoneEvent(String iface, IconEvent iconEvent) { - sendMessage(iface, RX_HS20_ANQP_ICON_EVENT, iconEvent); - } - - /** - * Broadcast the WNM event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param wnmData Instance of WnmData containing the event data. - */ - public void broadcastWnmEvent(String iface, WnmData wnmData) { - sendMessage(iface, HS20_REMEDIATION_EVENT, wnmData); - } - - /** - * Broadcast the Network identity request event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param networkId ID of the network in wpa_supplicant. - * @param ssid SSID of the network. - */ - public void broadcastNetworkIdentityRequestEvent(String iface, int networkId, String ssid) { - sendMessage(iface, SUP_REQUEST_IDENTITY, 0, networkId, ssid); - } - - /** - * Broadcast the Network Gsm Sim auth request event to all the handlers registered for this - * event. - * - * @param iface Name of iface on which this occurred. - * @param networkId ID of the network in wpa_supplicant. - * @param ssid SSID of the network. - * @param data Accompanying event data. - */ - public void broadcastNetworkGsmAuthRequestEvent(String iface, int networkId, String ssid, - String[] data) { - sendMessage(iface, SUP_REQUEST_SIM_AUTH, - new SimAuthRequestData(networkId, WifiEnterpriseConfig.Eap.SIM, ssid, data)); - } - - /** - * Broadcast the Network Umts Sim auth request event to all the handlers registered for this - * event. - * - * @param iface Name of iface on which this occurred. - * @param networkId ID of the network in wpa_supplicant. - * @param ssid SSID of the network. - * @param data Accompanying event data. - */ - public void broadcastNetworkUmtsAuthRequestEvent(String iface, int networkId, String ssid, - String[] data) { - sendMessage(iface, SUP_REQUEST_SIM_AUTH, - new SimAuthRequestData(networkId, WifiEnterpriseConfig.Eap.AKA, ssid, data)); - } - - /** - * Broadcast scan result event to all the handlers registered for this event. - * @param iface Name of iface on which this occurred. - */ - public void broadcastScanResultEvent(String iface) { - sendMessage(iface, SCAN_RESULTS_EVENT); - } - - /** - * Broadcast pno scan result event to all the handlers registered for this event. - * @param iface Name of iface on which this occurred. - */ - public void broadcastPnoScanResultEvent(String iface) { - sendMessage(iface, PNO_SCAN_RESULTS_EVENT); - } - - /** - * Broadcast scan failed event to all the handlers registered for this event. - * @param iface Name of iface on which this occurred. - */ - public void broadcastScanFailedEvent(String iface) { - sendMessage(iface, SCAN_FAILED_EVENT); - } - - /** - * Broadcast the authentication failure event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param reason Reason for authentication failure. This has to be one of the - * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_NONE}, - * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_TIMEOUT}, - * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_WRONG_PSWD}, - * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_EAP_FAILURE} - * @param errorCode Error code associated with the authentication failure event. - * A value of -1 is used when no error code is reported. - */ - public void broadcastAuthenticationFailureEvent(String iface, int reason, int errorCode) { - sendMessage(iface, AUTHENTICATION_FAILURE_EVENT, reason, errorCode); - } - - /** - * Broadcast the association rejection event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param status Status code for association rejection. - * @param timedOut Indicates if the association timed out. - * @param bssid BSSID of the access point from which we received the reject. - */ - public void broadcastAssociationRejectionEvent(String iface, int status, boolean timedOut, - String bssid) { - sendMessage(iface, ASSOCIATION_REJECTION_EVENT, timedOut ? 1 : 0, status, bssid); - } - - /** - * Broadcast the association success event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param bssid BSSID of the access point. - */ - public void broadcastAssociatedBssidEvent(String iface, String bssid) { - sendMessage(iface, ASSOCIATED_BSSID_EVENT, 0, 0, bssid); - } - - /** - * Broadcast the start of association event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param bssid BSSID of the access point. - */ - public void broadcastTargetBssidEvent(String iface, String bssid) { - sendMessage(iface, TARGET_BSSID_EVENT, 0, 0, bssid); - } - - /** - * Broadcast the network connection event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param networkId ID of the network in wpa_supplicant. - * @param filsHlpSent Whether the connection used FILS. - * @param bssid BSSID of the access point. - */ - public void broadcastNetworkConnectionEvent(String iface, int networkId, boolean filsHlpSent, - String bssid) { - sendMessage(iface, NETWORK_CONNECTION_EVENT, networkId, filsHlpSent ? 1 : 0, bssid); - } - - /** - * Broadcast the network disconnection event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param local Whether the disconnect was locally triggered. - * @param reason Disconnect reason code. - * @param bssid BSSID of the access point. - */ - public void broadcastNetworkDisconnectionEvent(String iface, int local, int reason, - String bssid) { - sendMessage(iface, NETWORK_DISCONNECTION_EVENT, local, reason, bssid); - } - - /** - * Broadcast the supplicant state change event to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param networkId ID of the network in wpa_supplicant. - * @param bssid BSSID of the access point. - * @param newSupplicantState New supplicant state. - */ - public void broadcastSupplicantStateChangeEvent(String iface, int networkId, WifiSsid wifiSsid, - String bssid, - SupplicantState newSupplicantState) { - sendMessage(iface, SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(networkId, wifiSsid, bssid, newSupplicantState)); - } - - /** - * Broadcast the connection to wpa_supplicant event to all the handlers registered for - * this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastSupplicantConnectionEvent(String iface) { - sendMessage(iface, SUP_CONNECTION_EVENT); - } - - /** - * Broadcast the loss of connection to wpa_supplicant event to all the handlers registered for - * this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastSupplicantDisconnectionEvent(String iface) { - sendMessage(iface, SUP_DISCONNECTION_EVENT); - } - - /** - * Broadcast the bss transition management frame handling event - * to all the handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastBssTmHandlingDoneEvent(String iface, BtmFrameData btmFrmData) { - sendMessage(iface, MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData); - } -} diff --git a/service/java/com/android/server/wifi/WifiMulticastLockManager.java b/service/java/com/android/server/wifi/WifiMulticastLockManager.java deleted file mode 100644 index d8364822c..000000000 --- a/service/java/com/android/server/wifi/WifiMulticastLockManager.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.os.BatteryStatsManager; -import android.os.Binder; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.WorkSource; -import android.util.Log; - -import com.android.server.wifi.proto.WifiStatsLog; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -/** - * WifiMulticastLockManager tracks holders of multicast locks and - * triggers enabling and disabling of filtering. - * - * @hide - */ -public class WifiMulticastLockManager { - private static final String TAG = "WifiMulticastLockManager"; - private final List<Multicaster> mMulticasters = new ArrayList<>(); - private int mMulticastEnabled = 0; - private int mMulticastDisabled = 0; - private boolean mVerboseLoggingEnabled = false; - private final BatteryStatsManager mBatteryStats; - private final FilterController mFilterController; - - /** Delegate for handling state change events for multicast filtering. */ - public interface FilterController { - /** Called when multicast filtering should be enabled */ - void startFilteringMulticastPackets(); - - /** Called when multicast filtering should be disabled */ - void stopFilteringMulticastPackets(); - } - - public WifiMulticastLockManager(FilterController filterController, - BatteryStatsManager batteryStats) { - mBatteryStats = batteryStats; - mFilterController = filterController; - } - - private class Multicaster implements IBinder.DeathRecipient { - String mTag; - int mUid; - IBinder mBinder; - - Multicaster(String tag, IBinder binder) { - mTag = tag; - mUid = Binder.getCallingUid(); - mBinder = binder; - try { - mBinder.linkToDeath(this, 0); - } catch (RemoteException e) { - binderDied(); - } - } - - @Override - public void binderDied() { - Log.e(TAG, "Multicaster binderDied"); - synchronized (mMulticasters) { - int i = mMulticasters.indexOf(this); - if (i != -1) { - removeMulticasterLocked(i, mUid, mTag); - } - } - } - - void unlinkDeathRecipient() { - mBinder.unlinkToDeath(this, 0); - } - - public int getUid() { - return mUid; - } - - public String getTag() { - return mTag; - } - - public String toString() { - return "Multicaster{" + mTag + " uid=" + mUid + "}"; - } - } - - protected void dump(PrintWriter pw) { - pw.println("mMulticastEnabled " + mMulticastEnabled); - pw.println("mMulticastDisabled " + mMulticastDisabled); - pw.println("Multicast Locks held:"); - for (Multicaster l : mMulticasters) { - pw.print(" "); - pw.println(l); - } - } - - protected void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mVerboseLoggingEnabled = true; - } else { - mVerboseLoggingEnabled = false; - } - } - - /** Start filtering if no multicasters exist. */ - public void initializeFiltering() { - synchronized (mMulticasters) { - // if anybody had requested filters be off, leave off - if (mMulticasters.size() != 0) { - return; - } else { - mFilterController.startFilteringMulticastPackets(); - } - } - } - - /** - * Acquire a multicast lock. - * @param binder a binder used to ensure caller is still alive - * @param tag string name of the caller. - */ - public void acquireLock(IBinder binder, String tag) { - synchronized (mMulticasters) { - mMulticastEnabled++; - mMulticasters.add(new Multicaster(tag, binder)); - // Note that we could call stopFilteringMulticastPackets only when - // our new size == 1 (first call), but this function won't - // be called often and by making the stopPacket call each - // time we're less fragile and self-healing. - mFilterController.stopFilteringMulticastPackets(); - } - - int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - mBatteryStats.reportWifiMulticastEnabled(new WorkSource(uid)); - WifiStatsLog.write_non_chained( - WifiStatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, uid, null, - WifiStatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__ON, tag); - Binder.restoreCallingIdentity(ident); - } - - /** Releases a multicast lock */ - public void releaseLock(String tag) { - int uid = Binder.getCallingUid(); - synchronized (mMulticasters) { - mMulticastDisabled++; - int size = mMulticasters.size(); - for (int i = size - 1; i >= 0; i--) { - Multicaster m = mMulticasters.get(i); - if ((m != null) && (m.getUid() == uid) && (m.getTag().equals(tag))) { - removeMulticasterLocked(i, uid, tag); - break; - } - } - } - } - - private void removeMulticasterLocked(int i, int uid, String tag) { - Multicaster removed = mMulticasters.remove(i); - - if (removed != null) { - removed.unlinkDeathRecipient(); - } - if (mMulticasters.size() == 0) { - mFilterController.startFilteringMulticastPackets(); - } - - final long ident = Binder.clearCallingIdentity(); - mBatteryStats.reportWifiMulticastDisabled(new WorkSource(uid)); - WifiStatsLog.write_non_chained( - WifiStatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, uid, null, - WifiStatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__OFF, tag); - Binder.restoreCallingIdentity(ident); - } - - /** Returns whether multicast should be allowed (filterning disabled). */ - public boolean isMulticastEnabled() { - synchronized (mMulticasters) { - return (mMulticasters.size() > 0); - } - } -} diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java deleted file mode 100644 index cf362d6a8..000000000 --- a/service/java/com/android/server/wifi/WifiNative.java +++ /dev/null @@ -1,3597 +0,0 @@ -/* - * Copyright (C) 2008 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.server.wifi; - -import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.net.MacAddress; -import android.net.TrafficStats; -import android.net.apf.ApfCapabilities; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiAnnotations; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiSsid; -import android.net.wifi.nl80211.DeviceWiphyCapabilities; -import android.net.wifi.nl80211.NativeScanResult; -import android.net.wifi.nl80211.RadioChainInfo; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.Handler; -import android.os.SystemClock; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.Log; - -import com.android.internal.annotations.Immutable; -import com.android.internal.util.HexDump; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.util.FrameParser; -import com.android.server.wifi.util.InformationElementUtil; -import com.android.server.wifi.util.NativeUtil; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.NetdWrapper.NetdEventObserver; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Random; -import java.util.Set; -import java.util.TimeZone; - -/** - * Native calls for bring up/shut down of the supplicant daemon and for - * sending requests to the supplicant daemon - * - * {@hide} - */ -public class WifiNative { - private static final String TAG = "WifiNative"; - - private final SupplicantStaIfaceHal mSupplicantStaIfaceHal; - private final HostapdHal mHostapdHal; - private final WifiVendorHal mWifiVendorHal; - private final WifiNl80211Manager mWifiCondManager; - private final WifiMonitor mWifiMonitor; - private final PropertyService mPropertyService; - private final WifiMetrics mWifiMetrics; - private final Handler mHandler; - private final Random mRandom; - private final WifiInjector mWifiInjector; - private NetdWrapper mNetdWrapper; - private boolean mVerboseLoggingEnabled = false; - - public WifiNative(WifiVendorHal vendorHal, - SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal, - WifiNl80211Manager condManager, WifiMonitor wifiMonitor, - PropertyService propertyService, WifiMetrics wifiMetrics, - Handler handler, Random random, - WifiInjector wifiInjector) { - mWifiVendorHal = vendorHal; - mSupplicantStaIfaceHal = staIfaceHal; - mHostapdHal = hostapdHal; - mWifiCondManager = condManager; - mWifiMonitor = wifiMonitor; - mPropertyService = propertyService; - mWifiMetrics = wifiMetrics; - mHandler = handler; - mRandom = random; - mWifiInjector = wifiInjector; - } - - /** - * Enable verbose logging for all sub modules. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = verbose > 0 ? true : false; - mWifiCondManager.enableVerboseLogging(mVerboseLoggingEnabled); - mSupplicantStaIfaceHal.enableVerboseLogging(mVerboseLoggingEnabled); - mHostapdHal.enableVerboseLogging(mVerboseLoggingEnabled); - mWifiVendorHal.enableVerboseLogging(mVerboseLoggingEnabled); - } - - /** - * Callbacks for SoftAp interface. - */ - public interface SoftApListener extends WifiNl80211Manager.SoftApCallback { - // dummy for now - provide a shell so that clients don't use a - // WifiNl80211Manager-specific API. - } - - /******************************************************** - * Interface management related methods. - ********************************************************/ - /** - * Meta-info about every iface that is active. - */ - private static class Iface { - /** Type of ifaces possible */ - public static final int IFACE_TYPE_AP = 0; - public static final int IFACE_TYPE_STA_FOR_CONNECTIVITY = 1; - public static final int IFACE_TYPE_STA_FOR_SCAN = 2; - - @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA_FOR_CONNECTIVITY, IFACE_TYPE_STA_FOR_SCAN}) - @Retention(RetentionPolicy.SOURCE) - public @interface IfaceType{} - - /** Identifier allocated for the interface */ - public final int id; - /** Type of the iface: STA (for Connectivity or Scan) or AP */ - public @IfaceType int type; - /** Name of the interface */ - public String name; - /** Is the interface up? This is used to mask up/down notifications to external clients. */ - public boolean isUp; - /** External iface destroyed listener for the iface */ - public InterfaceCallback externalListener; - /** Network observer registered for this interface */ - public NetworkObserverInternal networkObserver; - /** Interface feature set / capabilities */ - public long featureSet; - public DeviceWiphyCapabilities phyCapabilities; - - Iface(int id, @Iface.IfaceType int type) { - this.id = id; - this.type = type; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - String typeString; - switch(type) { - case IFACE_TYPE_STA_FOR_CONNECTIVITY: - typeString = "STA_CONNECTIVITY"; - break; - case IFACE_TYPE_STA_FOR_SCAN: - typeString = "STA_SCAN"; - break; - case IFACE_TYPE_AP: - typeString = "AP"; - break; - default: - typeString = "<UNKNOWN>"; - break; - } - sb.append("Iface:") - .append("{") - .append("Name=").append(name) - .append(",") - .append("Id=").append(id) - .append(",") - .append("Type=").append(typeString) - .append("}"); - return sb.toString(); - } - } - - /** - * Iface Management entity. This class maintains list of all the active ifaces. - */ - private static class IfaceManager { - /** Integer to allocate for the next iface being created */ - private int mNextId; - /** Map of the id to the iface structure */ - private HashMap<Integer, Iface> mIfaces = new HashMap<>(); - - /** Allocate a new iface for the given type */ - private Iface allocateIface(@Iface.IfaceType int type) { - Iface iface = new Iface(mNextId, type); - mIfaces.put(mNextId, iface); - mNextId++; - return iface; - } - - /** Remove the iface using the provided id */ - private Iface removeIface(int id) { - return mIfaces.remove(id); - } - - /** Lookup the iface using the provided id */ - private Iface getIface(int id) { - return mIfaces.get(id); - } - - /** Lookup the iface using the provided name */ - private Iface getIface(@NonNull String ifaceName) { - for (Iface iface : mIfaces.values()) { - if (TextUtils.equals(iface.name, ifaceName)) { - return iface; - } - } - return null; - } - - /** Iterator to use for deleting all the ifaces while performing teardown on each of them */ - private Iterator<Integer> getIfaceIdIter() { - return mIfaces.keySet().iterator(); - } - - /** Checks if there are any iface active. */ - private boolean hasAnyIface() { - return !mIfaces.isEmpty(); - } - - /** Checks if there are any iface of the given type active. */ - private boolean hasAnyIfaceOfType(@Iface.IfaceType int type) { - for (Iface iface : mIfaces.values()) { - if (iface.type == type) { - return true; - } - } - return false; - } - - /** Checks if there are any iface of the given type active. */ - private Iface findAnyIfaceOfType(@Iface.IfaceType int type) { - for (Iface iface : mIfaces.values()) { - if (iface.type == type) { - return iface; - } - } - return null; - } - - /** Checks if there are any STA (for connectivity) iface active. */ - private boolean hasAnyStaIfaceForConnectivity() { - return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); - } - - /** Checks if there are any STA (for scan) iface active. */ - private boolean hasAnyStaIfaceForScan() { - return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_SCAN); - } - - /** Checks if there are any AP iface active. */ - private boolean hasAnyApIface() { - return hasAnyIfaceOfType(Iface.IFACE_TYPE_AP); - } - - /** Finds the name of any STA iface active. */ - private String findAnyStaIfaceName() { - Iface iface = findAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); - if (iface == null) { - iface = findAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_SCAN); - } - if (iface == null) { - return null; - } - return iface.name; - } - - /** Finds the name of any AP iface active. */ - private String findAnyApIfaceName() { - Iface iface = findAnyIfaceOfType(Iface.IFACE_TYPE_AP); - if (iface == null) { - return null; - } - return iface.name; - } - - private @NonNull Set<String> findAllStaIfaceNames() { - Set<String> ifaceNames = new ArraySet<>(); - for (Iface iface : mIfaces.values()) { - if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY - || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { - ifaceNames.add(iface.name); - } - } - return ifaceNames; - } - - /** Removes the existing iface that does not match the provided id. */ - public Iface removeExistingIface(int newIfaceId) { - Iface removedIface = null; - // The number of ifaces in the database could be 1 existing & 1 new at the max. - if (mIfaces.size() > 2) { - Log.wtf(TAG, "More than 1 existing interface found"); - } - Iterator<Map.Entry<Integer, Iface>> iter = mIfaces.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry<Integer, Iface> entry = iter.next(); - if (entry.getKey() != newIfaceId) { - removedIface = entry.getValue(); - iter.remove(); - } - } - return removedIface; - } - } - - private class NormalScanEventCallback implements WifiNl80211Manager.ScanEventCallback { - private String mIfaceName; - - NormalScanEventCallback(String ifaceName) { - mIfaceName = ifaceName; - } - - @Override - public void onScanResultReady() { - Log.d(TAG, "Scan result ready event"); - mWifiMonitor.broadcastScanResultEvent(mIfaceName); - } - - @Override - public void onScanFailed() { - Log.d(TAG, "Scan failed event"); - mWifiMonitor.broadcastScanFailedEvent(mIfaceName); - } - } - - private class PnoScanEventCallback implements WifiNl80211Manager.ScanEventCallback { - private String mIfaceName; - - PnoScanEventCallback(String ifaceName) { - mIfaceName = ifaceName; - } - - @Override - public void onScanResultReady() { - Log.d(TAG, "Pno scan result event"); - mWifiMonitor.broadcastPnoScanResultEvent(mIfaceName); - mWifiMetrics.incrementPnoFoundNetworkEventCount(); - } - - @Override - public void onScanFailed() { - Log.d(TAG, "Pno Scan failed event"); - mWifiMetrics.incrementPnoScanFailedCount(); - } - } - - private final Object mLock = new Object(); - private final IfaceManager mIfaceMgr = new IfaceManager(); - private HashSet<StatusListener> mStatusListeners = new HashSet<>(); - - /** Helper method invoked to start supplicant if there were no ifaces */ - private boolean startHal() { - synchronized (mLock) { - if (!mIfaceMgr.hasAnyIface()) { - if (mWifiVendorHal.isVendorHalSupported()) { - if (!mWifiVendorHal.startVendorHal()) { - Log.e(TAG, "Failed to start vendor HAL"); - return false; - } - } else { - Log.i(TAG, "Vendor Hal not supported, ignoring start."); - } - } - return true; - } - } - - /** Helper method invoked to stop HAL if there are no more ifaces */ - private void stopHalAndWificondIfNecessary() { - synchronized (mLock) { - if (!mIfaceMgr.hasAnyIface()) { - if (!mWifiCondManager.tearDownInterfaces()) { - Log.e(TAG, "Failed to teardown ifaces from wificond"); - } - if (mWifiVendorHal.isVendorHalSupported()) { - mWifiVendorHal.stopVendorHal(); - } else { - Log.i(TAG, "Vendor Hal not supported, ignoring stop."); - } - } - } - } - - private static final int CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS = 100; - private static final int CONNECT_TO_SUPPLICANT_RETRY_TIMES = 50; - /** - * This method is called to wait for establishing connection to wpa_supplicant. - * - * @return true if connection is established, false otherwise. - */ - private boolean startAndWaitForSupplicantConnection() { - // Start initialization if not already started. - if (!mSupplicantStaIfaceHal.isInitializationStarted() - && !mSupplicantStaIfaceHal.initialize()) { - return false; - } - if (!mSupplicantStaIfaceHal.startDaemon()) { - Log.e(TAG, "Failed to startup supplicant"); - return false; - } - boolean connected = false; - int connectTries = 0; - while (!connected && connectTries++ < CONNECT_TO_SUPPLICANT_RETRY_TIMES) { - // Check if the initialization is complete. - connected = mSupplicantStaIfaceHal.isInitializationComplete(); - if (connected) { - break; - } - try { - Thread.sleep(CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS); - } catch (InterruptedException ignore) { - } - } - return connected; - } - - /** Helper method invoked to start supplicant if there were no STA ifaces */ - private boolean startSupplicant() { - synchronized (mLock) { - if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) { - if (!startAndWaitForSupplicantConnection()) { - Log.e(TAG, "Failed to connect to supplicant"); - return false; - } - if (!mSupplicantStaIfaceHal.registerDeathHandler( - new SupplicantDeathHandlerInternal())) { - Log.e(TAG, "Failed to register supplicant death handler"); - return false; - } - } - return true; - } - } - - /** Helper method invoked to stop supplicant if there are no more STA ifaces */ - private void stopSupplicantIfNecessary() { - synchronized (mLock) { - if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) { - if (!mSupplicantStaIfaceHal.deregisterDeathHandler()) { - Log.e(TAG, "Failed to deregister supplicant death handler"); - } - mSupplicantStaIfaceHal.terminate(); - } - } - } - - /** Helper method invoked to start hostapd if there were no AP ifaces */ - private boolean startHostapd() { - synchronized (mLock) { - if (!mIfaceMgr.hasAnyApIface()) { - if (!startAndWaitForHostapdConnection()) { - Log.e(TAG, "Failed to connect to hostapd"); - return false; - } - if (!mHostapdHal.registerDeathHandler( - new HostapdDeathHandlerInternal())) { - Log.e(TAG, "Failed to register hostapd death handler"); - return false; - } - } - return true; - } - } - - /** Helper method invoked to stop hostapd if there are no more AP ifaces */ - private void stopHostapdIfNecessary() { - synchronized (mLock) { - if (!mIfaceMgr.hasAnyApIface()) { - if (!mHostapdHal.deregisterDeathHandler()) { - Log.e(TAG, "Failed to deregister hostapd death handler"); - } - mHostapdHal.terminate(); - } - } - } - - /** Helper method to register a network observer and return it */ - private boolean registerNetworkObserver(NetworkObserverInternal observer) { - if (observer == null) return false; - mNetdWrapper.registerObserver(observer); - return true; - } - - /** Helper method to unregister a network observer */ - private boolean unregisterNetworkObserver(NetworkObserverInternal observer) { - if (observer == null) return false; - mNetdWrapper.unregisterObserver(observer); - return true; - } - - /** - * Helper method invoked to teardown client iface (for connectivity) and perform - * necessary cleanup - */ - private void onClientInterfaceForConnectivityDestroyed(@NonNull Iface iface) { - synchronized (mLock) { - mWifiMonitor.stopMonitoring(iface.name); - if (!unregisterNetworkObserver(iface.networkObserver)) { - Log.e(TAG, "Failed to unregister network observer on " + iface); - } - if (!mSupplicantStaIfaceHal.teardownIface(iface.name)) { - Log.e(TAG, "Failed to teardown iface in supplicant on " + iface); - } - if (!mWifiCondManager.tearDownClientInterface(iface.name)) { - Log.e(TAG, "Failed to teardown iface in wificond on " + iface); - } - stopSupplicantIfNecessary(); - stopHalAndWificondIfNecessary(); - } - } - - /** Helper method invoked to teardown client iface (for scan) and perform necessary cleanup */ - private void onClientInterfaceForScanDestroyed(@NonNull Iface iface) { - synchronized (mLock) { - mWifiMonitor.stopMonitoring(iface.name); - if (!unregisterNetworkObserver(iface.networkObserver)) { - Log.e(TAG, "Failed to unregister network observer on " + iface); - } - if (!mWifiCondManager.tearDownClientInterface(iface.name)) { - Log.e(TAG, "Failed to teardown iface in wificond on " + iface); - } - stopHalAndWificondIfNecessary(); - } - } - - /** Helper method invoked to teardown softAp iface and perform necessary cleanup */ - private void onSoftApInterfaceDestroyed(@NonNull Iface iface) { - synchronized (mLock) { - if (!unregisterNetworkObserver(iface.networkObserver)) { - Log.e(TAG, "Failed to unregister network observer on " + iface); - } - if (!mHostapdHal.removeAccessPoint(iface.name)) { - Log.e(TAG, "Failed to remove access point on " + iface); - } - if (!mWifiCondManager.tearDownSoftApInterface(iface.name)) { - Log.e(TAG, "Failed to teardown iface in wificond on " + iface); - } - stopHostapdIfNecessary(); - stopHalAndWificondIfNecessary(); - } - } - - /** Helper method invoked to teardown iface and perform necessary cleanup */ - private void onInterfaceDestroyed(@NonNull Iface iface) { - synchronized (mLock) { - if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY) { - onClientInterfaceForConnectivityDestroyed(iface); - } else if (iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { - onClientInterfaceForScanDestroyed(iface); - } else if (iface.type == Iface.IFACE_TYPE_AP) { - onSoftApInterfaceDestroyed(iface); - } - // Invoke the external callback. - iface.externalListener.onDestroyed(iface.name); - } - } - - /** - * Callback to be invoked by HalDeviceManager when an interface is destroyed. - */ - private class InterfaceDestoyedListenerInternal - implements HalDeviceManager.InterfaceDestroyedListener { - /** Identifier allocated for the interface */ - private final int mInterfaceId; - - InterfaceDestoyedListenerInternal(int ifaceId) { - mInterfaceId = ifaceId; - } - - @Override - public void onDestroyed(@NonNull String ifaceName) { - synchronized (mLock) { - final Iface iface = mIfaceMgr.removeIface(mInterfaceId); - if (iface == null) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Received iface destroyed notification on an invalid iface=" - + ifaceName); - } - return; - } - onInterfaceDestroyed(iface); - Log.i(TAG, "Successfully torn down " + iface); - } - } - } - - /** - * Helper method invoked to trigger the status changed callback after one of the native - * daemon's death. - */ - private void onNativeDaemonDeath() { - synchronized (mLock) { - for (StatusListener listener : mStatusListeners) { - listener.onStatusChanged(false); - } - for (StatusListener listener : mStatusListeners) { - listener.onStatusChanged(true); - } - } - } - - /** - * Death handler for the Vendor HAL daemon. - */ - private class VendorHalDeathHandlerInternal implements VendorHalDeathEventHandler { - @Override - public void onDeath() { - synchronized (mLock) { - Log.i(TAG, "Vendor HAL died. Cleaning up internal state."); - onNativeDaemonDeath(); - mWifiMetrics.incrementNumHalCrashes(); - } - } - } - - /** - * Death handler for the wificond daemon. - */ - private class WificondDeathHandlerInternal implements Runnable { - @Override - public void run() { - synchronized (mLock) { - Log.i(TAG, "wificond died. Cleaning up internal state."); - onNativeDaemonDeath(); - mWifiMetrics.incrementNumWificondCrashes(); - } - } - } - - /** - * Death handler for the supplicant daemon. - */ - private class SupplicantDeathHandlerInternal implements SupplicantDeathEventHandler { - @Override - public void onDeath() { - synchronized (mLock) { - Log.i(TAG, "wpa_supplicant died. Cleaning up internal state."); - onNativeDaemonDeath(); - mWifiMetrics.incrementNumSupplicantCrashes(); - } - } - } - - /** - * Death handler for the hostapd daemon. - */ - private class HostapdDeathHandlerInternal implements HostapdDeathEventHandler { - @Override - public void onDeath() { - synchronized (mLock) { - Log.i(TAG, "hostapd died. Cleaning up internal state."); - onNativeDaemonDeath(); - mWifiMetrics.incrementNumHostapdCrashes(); - } - } - } - - /** Helper method invoked to handle interface change. */ - private void onInterfaceStateChanged(Iface iface, boolean isUp) { - synchronized (mLock) { - // Mask multiple notifications with the same state. - if (isUp == iface.isUp) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Interface status unchanged on " + iface + " from " + isUp - + ", Ignoring..."); - } - return; - } - Log.i(TAG, "Interface state changed on " + iface + ", isUp=" + isUp); - if (isUp) { - iface.externalListener.onUp(iface.name); - } else { - iface.externalListener.onDown(iface.name); - if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY - || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { - mWifiMetrics.incrementNumClientInterfaceDown(); - } else if (iface.type == Iface.IFACE_TYPE_AP) { - mWifiMetrics.incrementNumSoftApInterfaceDown(); - } - } - iface.isUp = isUp; - } - } - - /** - * Network observer to use for all interface up/down notifications. - */ - private class NetworkObserverInternal implements NetdEventObserver { - /** Identifier allocated for the interface */ - private final int mInterfaceId; - - NetworkObserverInternal(int id) { - mInterfaceId = id; - } - - /** - * Note: We should ideally listen to - * {@link NetdEventObserver#interfaceStatusChanged(String, boolean)} here. But, that - * callback is not working currently (broken in netd). So, instead listen to link state - * change callbacks as triggers to query the real interface state. We should get rid of - * this workaround if we get the |interfaceStatusChanged| callback to work in netd. - * Also, this workaround will not detect an interface up event, if the link state is - * still down. - */ - @Override - public void interfaceLinkStateChanged(String ifaceName, boolean unusedIsLinkUp) { - // This is invoked from the main system_server thread. Post to our handler. - mHandler.post(() -> { - synchronized (mLock) { - final Iface ifaceWithId = mIfaceMgr.getIface(mInterfaceId); - if (ifaceWithId == null) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Received iface link up/down notification on an invalid" - + " iface=" + mInterfaceId); - } - return; - } - final Iface ifaceWithName = mIfaceMgr.getIface(ifaceName); - if (ifaceWithName == null || ifaceWithName != ifaceWithId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Received iface link up/down notification on an invalid" - + " iface=" + ifaceName); - } - return; - } - onInterfaceStateChanged(ifaceWithName, isInterfaceUp(ifaceName)); - } - }); - } - - @Override - public void interfaceStatusChanged(String ifaceName, boolean unusedIsLinkUp) { - // unused currently. Look at note above. - } - } - - /** - * Radio mode change handler for the Vendor HAL daemon. - */ - private class VendorHalRadioModeChangeHandlerInternal - implements VendorHalRadioModeChangeEventHandler { - @Override - public void onMcc(int band) { - synchronized (mLock) { - Log.i(TAG, "Device is in MCC mode now"); - mWifiMetrics.incrementNumRadioModeChangeToMcc(); - } - } - @Override - public void onScc(int band) { - synchronized (mLock) { - Log.i(TAG, "Device is in SCC mode now"); - mWifiMetrics.incrementNumRadioModeChangeToScc(); - } - } - @Override - public void onSbs(int band) { - synchronized (mLock) { - Log.i(TAG, "Device is in SBS mode now"); - mWifiMetrics.incrementNumRadioModeChangeToSbs(); - } - } - @Override - public void onDbs() { - synchronized (mLock) { - Log.i(TAG, "Device is in DBS mode now"); - mWifiMetrics.incrementNumRadioModeChangeToDbs(); - } - } - } - - // For devices that don't support the vendor HAL, we will not support any concurrency. - // So simulate the HalDeviceManager behavior by triggering the destroy listener for - // any active interface. - private String handleIfaceCreationWhenVendorHalNotSupported(@NonNull Iface newIface) { - synchronized (mLock) { - Iface existingIface = mIfaceMgr.removeExistingIface(newIface.id); - if (existingIface != null) { - onInterfaceDestroyed(existingIface); - Log.i(TAG, "Successfully torn down " + existingIface); - } - // Return the interface name directly from the system property. - return mPropertyService.getString("wifi.interface", "wlan0"); - } - } - - /** - * Helper function to handle creation of STA iface. - * For devices which do not the support the HAL, this will bypass HalDeviceManager & - * teardown any existing iface. - */ - private String createStaIface(@NonNull Iface iface) { - synchronized (mLock) { - if (mWifiVendorHal.isVendorHalSupported()) { - return mWifiVendorHal.createStaIface( - new InterfaceDestoyedListenerInternal(iface.id)); - } else { - Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface."); - return handleIfaceCreationWhenVendorHalNotSupported(iface); - } - } - } - - /** - * Helper function to handle creation of AP iface. - * For devices which do not the support the HAL, this will bypass HalDeviceManager & - * teardown any existing iface. - */ - private String createApIface(@NonNull Iface iface) { - synchronized (mLock) { - if (mWifiVendorHal.isVendorHalSupported()) { - return mWifiVendorHal.createApIface( - new InterfaceDestoyedListenerInternal(iface.id)); - } else { - Log.i(TAG, "Vendor Hal not supported, ignoring createApIface."); - return handleIfaceCreationWhenVendorHalNotSupported(iface); - } - } - } - - // For devices that don't support the vendor HAL, we will not support any concurrency. - // So simulate the HalDeviceManager behavior by triggering the destroy listener for - // the interface. - private boolean handleIfaceRemovalWhenVendorHalNotSupported(@NonNull Iface iface) { - synchronized (mLock) { - mIfaceMgr.removeIface(iface.id); - onInterfaceDestroyed(iface); - Log.i(TAG, "Successfully torn down " + iface); - return true; - } - } - - /** - * Helper function to handle removal of STA iface. - * For devices which do not the support the HAL, this will bypass HalDeviceManager & - * teardown any existing iface. - */ - private boolean removeStaIface(@NonNull Iface iface) { - synchronized (mLock) { - if (mWifiVendorHal.isVendorHalSupported()) { - return mWifiVendorHal.removeStaIface(iface.name); - } else { - Log.i(TAG, "Vendor Hal not supported, ignoring removeStaIface."); - return handleIfaceRemovalWhenVendorHalNotSupported(iface); - } - } - } - - /** - * Helper function to handle removal of STA iface. - */ - private boolean removeApIface(@NonNull Iface iface) { - synchronized (mLock) { - if (mWifiVendorHal.isVendorHalSupported()) { - return mWifiVendorHal.removeApIface(iface.name); - } else { - Log.i(TAG, "Vendor Hal not supported, ignoring removeApIface."); - return handleIfaceRemovalWhenVendorHalNotSupported(iface); - } - } - } - - /** - * Initialize the native modules. - * - * @return true on success, false otherwise. - */ - public boolean initialize() { - synchronized (mLock) { - if (!mWifiVendorHal.initialize(new VendorHalDeathHandlerInternal())) { - Log.e(TAG, "Failed to initialize vendor HAL"); - return false; - } - mWifiCondManager.setOnServiceDeadCallback(new WificondDeathHandlerInternal()); - mWifiCondManager.tearDownInterfaces(); - mWifiVendorHal.registerRadioModeChangeHandler( - new VendorHalRadioModeChangeHandlerInternal()); - mNetdWrapper = mWifiInjector.makeNetdWrapper(); - return true; - } - } - - /** - * Callback to notify when the status of one of the native daemons - * (wificond, wpa_supplicant & vendor HAL) changes. - */ - public interface StatusListener { - /** - * @param allReady Indicates if all the native daemons are ready for operation or not. - */ - void onStatusChanged(boolean allReady); - } - - /** - * Register a StatusListener to get notified about any status changes from the native daemons. - * - * It is safe to re-register the same callback object - duplicates are detected and only a - * single copy kept. - * - * @param listener StatusListener listener object. - */ - public void registerStatusListener(@NonNull StatusListener listener) { - mStatusListeners.add(listener); - } - - /** - * Callback to notify when the availability of an interface has changed. - */ - public interface InterfaceAvailableForRequestListener { - /** - * @param isAvailable Whether it is possible to create an iface of the specified type or - * not. - */ - void onAvailabilityChanged(boolean isAvailable); - } - - /** - * Register a callback to notify when the availability of Client interface has changed. - * - * It is safe to re-register the same callback object - duplicates are detected and only a - * single copy kept. - * - * @param listener Instance of {@link InterfaceAvailableForRequestListener}. - */ - public void registerClientInterfaceAvailabilityListener( - @NonNull InterfaceAvailableForRequestListener listener) { - mWifiVendorHal.registerStaIfaceAvailabilityListener(listener); - } - - /** - * Register a callback to notify when the availability of SoftAp interface has changed. - * - * It is safe to re-register the same callback object - duplicates are detected and only a - * single copy kept. - * - * @param listener Instance of {@link InterfaceAvailableForRequestListener}. - */ - public void registerSoftApInterfaceAvailabilityListener( - @NonNull InterfaceAvailableForRequestListener listener) { - mWifiVendorHal.registerApIfaceAvailabilityListener(listener); - } - - /** - * Callback to notify when the associated interface is destroyed, up or down. - */ - public interface InterfaceCallback { - /** - * Interface destroyed by HalDeviceManager. - * - * @param ifaceName Name of the iface. - */ - void onDestroyed(String ifaceName); - - /** - * Interface is up. - * - * @param ifaceName Name of the iface. - */ - void onUp(String ifaceName); - - /** - * Interface is down. - * - * @param ifaceName Name of the iface. - */ - void onDown(String ifaceName); - } - - private void initializeNwParamsForClientInterface(@NonNull String ifaceName) { - try { - // A runtime crash or shutting down AP mode can leave - // IP addresses configured, and this affects - // connectivity when supplicant starts up. - // Ensure we have no IP addresses before a supplicant start. - mNetdWrapper.clearInterfaceAddresses(ifaceName); - - // Set privacy extensions - mNetdWrapper.setInterfaceIpv6PrivacyExtensions(ifaceName, true); - - // IPv6 is enabled only as long as access point is connected since: - // - IPv6 addresses and routes stick around after disconnection - // - kernel is unaware when connected and fails to start IPv6 negotiation - // - kernel can start autoconfiguration when 802.1x is not complete - mNetdWrapper.disableIpv6(ifaceName); - } catch (IllegalStateException e) { - Log.e(TAG, "Unable to change interface settings", e); - } - } - - /** - * Setup an interface for client mode (for connectivity) operations. - * - * This method configures an interface in STA mode in all the native daemons - * (wificond, wpa_supplicant & vendor HAL). - * - * @param interfaceCallback Associated callback for notifying status changes for the iface. - * @return Returns the name of the allocated interface, will be null on failure. - */ - public String setupInterfaceForClientInConnectivityMode( - @NonNull InterfaceCallback interfaceCallback) { - synchronized (mLock) { - if (!startHal()) { - Log.e(TAG, "Failed to start Hal"); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); - return null; - } - if (!startSupplicant()) { - Log.e(TAG, "Failed to start supplicant"); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); - return null; - } - Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); - if (iface == null) { - Log.e(TAG, "Failed to allocate new STA iface"); - return null; - } - iface.externalListener = interfaceCallback; - iface.name = createStaIface(iface); - if (TextUtils.isEmpty(iface.name)) { - Log.e(TAG, "Failed to create STA iface in vendor HAL"); - mIfaceMgr.removeIface(iface.id); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); - return null; - } - if (!mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run, - new NormalScanEventCallback(iface.name), - new PnoScanEventCallback(iface.name))) { - Log.e(TAG, "Failed to setup iface in wificond on " + iface); - teardownInterface(iface.name); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); - return null; - } - if (!mSupplicantStaIfaceHal.setupIface(iface.name)) { - Log.e(TAG, "Failed to setup iface in supplicant on " + iface); - teardownInterface(iface.name); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); - return null; - } - iface.networkObserver = new NetworkObserverInternal(iface.id); - if (!registerNetworkObserver(iface.networkObserver)) { - Log.e(TAG, "Failed to register network observer on " + iface); - teardownInterface(iface.name); - return null; - } - mWifiMonitor.startMonitoring(iface.name); - // Just to avoid any race conditions with interface state change callbacks, - // update the interface state before we exit. - onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); - initializeNwParamsForClientInterface(iface.name); - Log.i(TAG, "Successfully setup " + iface); - - iface.featureSet = getSupportedFeatureSetInternal(iface.name); - return iface.name; - } - } - - /** - * Setup an interface for client mode (for scan) operations. - * - * This method configures an interface in STA mode in the native daemons - * (wificond, vendor HAL). - * - * @param interfaceCallback Associated callback for notifying status changes for the iface. - * @return Returns the name of the allocated interface, will be null on failure. - */ - public String setupInterfaceForClientInScanMode( - @NonNull InterfaceCallback interfaceCallback) { - synchronized (mLock) { - if (!startHal()) { - Log.e(TAG, "Failed to start Hal"); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); - return null; - } - Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN); - if (iface == null) { - Log.e(TAG, "Failed to allocate new STA iface"); - return null; - } - iface.externalListener = interfaceCallback; - iface.name = createStaIface(iface); - if (TextUtils.isEmpty(iface.name)) { - Log.e(TAG, "Failed to create iface in vendor HAL"); - mIfaceMgr.removeIface(iface.id); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); - return null; - } - if (!mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run, - new NormalScanEventCallback(iface.name), - new PnoScanEventCallback(iface.name))) { - Log.e(TAG, "Failed to setup iface in wificond=" + iface.name); - teardownInterface(iface.name); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); - return null; - } - iface.networkObserver = new NetworkObserverInternal(iface.id); - if (!registerNetworkObserver(iface.networkObserver)) { - Log.e(TAG, "Failed to register network observer for iface=" + iface.name); - teardownInterface(iface.name); - return null; - } - mWifiMonitor.startMonitoring(iface.name); - // Just to avoid any race conditions with interface state change callbacks, - // update the interface state before we exit. - onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); - Log.i(TAG, "Successfully setup " + iface); - - iface.featureSet = getSupportedFeatureSetInternal(iface.name); - return iface.name; - } - } - - /** - * Setup an interface for Soft AP mode operations. - * - * This method configures an interface in AP mode in all the native daemons - * (wificond, wpa_supplicant & vendor HAL). - * - * @param interfaceCallback Associated callback for notifying status changes for the iface. - * @return Returns the name of the allocated interface, will be null on failure. - */ - public String setupInterfaceForSoftApMode(@NonNull InterfaceCallback interfaceCallback) { - synchronized (mLock) { - if (!startHal()) { - Log.e(TAG, "Failed to start Hal"); - mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); - return null; - } - if (!startHostapd()) { - Log.e(TAG, "Failed to start hostapd"); - mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); - return null; - } - Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_AP); - if (iface == null) { - Log.e(TAG, "Failed to allocate new AP iface"); - return null; - } - iface.externalListener = interfaceCallback; - iface.name = createApIface(iface); - if (TextUtils.isEmpty(iface.name)) { - Log.e(TAG, "Failed to create AP iface in vendor HAL"); - mIfaceMgr.removeIface(iface.id); - mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); - return null; - } - if (!mWifiCondManager.setupInterfaceForSoftApMode(iface.name)) { - Log.e(TAG, "Failed to setup iface in wificond on " + iface); - teardownInterface(iface.name); - mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond(); - return null; - } - iface.networkObserver = new NetworkObserverInternal(iface.id); - if (!registerNetworkObserver(iface.networkObserver)) { - Log.e(TAG, "Failed to register network observer on " + iface); - teardownInterface(iface.name); - return null; - } - // Just to avoid any race conditions with interface state change callbacks, - // update the interface state before we exit. - onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); - Log.i(TAG, "Successfully setup " + iface); - - iface.featureSet = getSupportedFeatureSetInternal(iface.name); - return iface.name; - } - } - - /** - * Switches an existing Client mode interface from connectivity - * {@link Iface#IFACE_TYPE_STA_FOR_CONNECTIVITY} to scan mode - * {@link Iface#IFACE_TYPE_STA_FOR_SCAN}. - * - * @param ifaceName Name of the interface. - * @return true if the operation succeeded, false if there is an error or the iface is already - * in scan mode. - */ - public boolean switchClientInterfaceToScanMode(@NonNull String ifaceName) { - synchronized (mLock) { - final Iface iface = mIfaceMgr.getIface(ifaceName); - if (iface == null) { - Log.e(TAG, "Trying to switch to scan mode on an invalid iface=" + ifaceName); - return false; - } - if (iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { - Log.e(TAG, "Already in scan mode on iface=" + ifaceName); - return true; - } - if (!mSupplicantStaIfaceHal.teardownIface(iface.name)) { - Log.e(TAG, "Failed to teardown iface in supplicant on " + iface); - teardownInterface(iface.name); - return false; - } - iface.type = Iface.IFACE_TYPE_STA_FOR_SCAN; - stopSupplicantIfNecessary(); - iface.featureSet = getSupportedFeatureSetInternal(iface.name); - iface.phyCapabilities = null; - Log.i(TAG, "Successfully switched to scan mode on iface=" + iface); - return true; - } - } - - /** - * Switches an existing Client mode interface from scan mode - * {@link Iface#IFACE_TYPE_STA_FOR_SCAN} to connectivity mode - * {@link Iface#IFACE_TYPE_STA_FOR_CONNECTIVITY}. - * - * @param ifaceName Name of the interface. - * @return true if the operation succeeded, false if there is an error or the iface is already - * in scan mode. - */ - public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName) { - synchronized (mLock) { - final Iface iface = mIfaceMgr.getIface(ifaceName); - if (iface == null) { - Log.e(TAG, "Trying to switch to connectivity mode on an invalid iface=" - + ifaceName); - return false; - } - if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY) { - Log.e(TAG, "Already in connectivity mode on iface=" + ifaceName); - return true; - } - if (!startSupplicant()) { - Log.e(TAG, "Failed to start supplicant"); - teardownInterface(iface.name); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); - return false; - } - if (!mSupplicantStaIfaceHal.setupIface(iface.name)) { - Log.e(TAG, "Failed to setup iface in supplicant on " + iface); - teardownInterface(iface.name); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); - return false; - } - iface.type = Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY; - iface.featureSet = getSupportedFeatureSetInternal(iface.name); - Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface); - return true; - } - } - - /** - * - * Check if the interface is up or down. - * - * @param ifaceName Name of the interface. - * @return true if iface is up, false if it's down or on error. - */ - public boolean isInterfaceUp(@NonNull String ifaceName) { - synchronized (mLock) { - final Iface iface = mIfaceMgr.getIface(ifaceName); - if (iface == null) { - Log.e(TAG, "Trying to get iface state on invalid iface=" + ifaceName); - return false; - } - try { - return mNetdWrapper.isInterfaceUp(ifaceName); - } catch (IllegalStateException e) { - Log.e(TAG, "Unable to get interface config", e); - return false; - } - } - } - - /** - * Teardown an interface in Client/AP mode. - * - * This method tears down the associated interface from all the native daemons - * (wificond, wpa_supplicant & vendor HAL). - * Also, brings down the HAL, supplicant or hostapd as necessary. - * - * @param ifaceName Name of the interface. - */ - public void teardownInterface(@NonNull String ifaceName) { - synchronized (mLock) { - final Iface iface = mIfaceMgr.getIface(ifaceName); - if (iface == null) { - Log.e(TAG, "Trying to teardown an invalid iface=" + ifaceName); - return; - } - // Trigger the iface removal from HAL. The rest of the cleanup will be triggered - // from the interface destroyed callback. - if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY - || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { - if (!removeStaIface(iface)) { - Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName); - return; - } - } else if (iface.type == Iface.IFACE_TYPE_AP) { - if (!removeApIface(iface)) { - Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName); - return; - } - } - Log.i(TAG, "Successfully initiated teardown for iface=" + ifaceName); - } - } - - /** - * Teardown all the active interfaces. - * - * This method tears down the associated interfaces from all the native daemons - * (wificond, wpa_supplicant & vendor HAL). - * Also, brings down the HAL, supplicant or hostapd as necessary. - */ - public void teardownAllInterfaces() { - synchronized (mLock) { - Iterator<Integer> ifaceIdIter = mIfaceMgr.getIfaceIdIter(); - while (ifaceIdIter.hasNext()) { - Iface iface = mIfaceMgr.getIface(ifaceIdIter.next()); - ifaceIdIter.remove(); - onInterfaceDestroyed(iface); - Log.i(TAG, "Successfully torn down " + iface); - } - Log.i(TAG, "Successfully torn down all ifaces"); - } - } - - /** - * Get name of the client interface. - * - * This is mainly used by external modules that needs to perform some - * client operations on the STA interface. - * - * TODO(b/70932231): This may need to be reworked once we start supporting STA + STA. - * - * @return Interface name of any active client interface, null if no active client interface - * exist. - * Return Values for the different scenarios are listed below: - * a) When there are no client interfaces, returns null. - * b) when there is 1 client interface, returns the name of that interface. - * c) When there are 2 or more client interface, returns the name of any client interface. - */ - public String getClientInterfaceName() { - synchronized (mLock) { - return mIfaceMgr.findAnyStaIfaceName(); - } - } - - /** - * Get names of all the client interfaces. - * - * @return List of interface name of all active client interfaces. - */ - public Set<String> getClientInterfaceNames() { - synchronized (mLock) { - return mIfaceMgr.findAllStaIfaceNames(); - } - } - - /** - * Get name of the softap interface. - * - * This is mainly used by external modules that needs to perform some - * operations on the AP interface. - * - * TODO(b/70932231): This may need to be reworked once we start supporting AP + AP. - * - * @return Interface name of any active softap interface, null if no active softap interface - * exist. - * Return Values for the different scenarios are listed below: - * a) When there are no softap interfaces, returns null. - * b) when there is 1 softap interface, returns the name of that interface. - * c) When there are 2 or more softap interface, returns the name of any softap interface. - */ - public String getSoftApInterfaceName() { - synchronized (mLock) { - return mIfaceMgr.findAnyApIfaceName(); - } - } - - /******************************************************** - * Wificond operations - ********************************************************/ - - /** - * Request signal polling to wificond. - * - * @param ifaceName Name of the interface. - * Returns an SignalPollResult object. - * Returns null on failure. - */ - public WifiNl80211Manager.SignalPollResult signalPoll(@NonNull String ifaceName) { - return mWifiCondManager.signalPoll(ifaceName); - } - - /** - * Query the list of valid frequencies for the provided band. - * The result depends on the on the country code that has been set. - * - * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants. - * The following bands are supported {@link WifiAnnotations.WifiBandBasic}: - * WifiScanner.WIFI_BAND_24_GHZ - * WifiScanner.WIFI_BAND_5_GHZ - * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY - * WifiScanner.WIFI_BAND_6_GHZ - * @return frequencies vector of valid frequencies (MHz), or null for error. - * @throws IllegalArgumentException if band is not recognized. - */ - public int [] getChannelsForBand(@WifiAnnotations.WifiBandBasic int band) { - return mWifiCondManager.getChannelsMhzForBand(band); - } - - /** - * Start a scan using wificond for the given parameters. - * @param ifaceName Name of the interface. - * @param scanType Type of scan to perform. One of {@link WifiScanner#SCAN_TYPE_LOW_LATENCY}, - * {@link WifiScanner#SCAN_TYPE_LOW_POWER} or {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}. - * @param freqs list of frequencies to scan for, if null scan all supported channels. - * @param hiddenNetworkSSIDs List of hidden networks to be scanned for. - * @return Returns true on success. - */ - public boolean scan( - @NonNull String ifaceName, @WifiAnnotations.ScanType int scanType, Set<Integer> freqs, - List<String> hiddenNetworkSSIDs) { - List<byte[]> hiddenNetworkSsidsArrays = new ArrayList<>(); - for (String hiddenNetworkSsid : hiddenNetworkSSIDs) { - try { - hiddenNetworkSsidsArrays.add( - NativeUtil.byteArrayFromArrayList( - NativeUtil.decodeSsid(hiddenNetworkSsid))); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + hiddenNetworkSsid, e); - continue; - } - } - return mWifiCondManager.startScan(ifaceName, scanType, freqs, hiddenNetworkSsidsArrays); - } - - /** - * Fetch the latest scan result from kernel via wificond. - * @param ifaceName Name of the interface. - * @return Returns an ArrayList of ScanDetail. - * Returns an empty ArrayList on failure. - */ - public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName) { - return convertNativeScanResults(mWifiCondManager.getScanResults( - ifaceName, WifiNl80211Manager.SCAN_TYPE_SINGLE_SCAN)); - } - - /** - * Fetch the latest scan result from kernel via wificond. - * @param ifaceName Name of the interface. - * @return Returns an ArrayList of ScanDetail. - * Returns an empty ArrayList on failure. - */ - public ArrayList<ScanDetail> getPnoScanResults(@NonNull String ifaceName) { - return convertNativeScanResults(mWifiCondManager.getScanResults(ifaceName, - WifiNl80211Manager.SCAN_TYPE_PNO_SCAN)); - } - - private ArrayList<ScanDetail> convertNativeScanResults(List<NativeScanResult> nativeResults) { - ArrayList<ScanDetail> results = new ArrayList<>(); - for (NativeScanResult result : nativeResults) { - WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.getSsid()); - MacAddress bssidMac = result.getBssid(); - if (bssidMac == null) { - Log.e(TAG, "Invalid MAC (BSSID) for SSID " + wifiSsid); - continue; - } - String bssid = bssidMac.toString(); - ScanResult.InformationElement[] ies = - InformationElementUtil.parseInformationElements(result.getInformationElements()); - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, result.getCapabilities(), isEnhancedOpenSupported()); - String flags = capabilities.generateCapabilitiesString(); - NetworkDetail networkDetail; - try { - networkDetail = new NetworkDetail(bssid, ies, null, result.getFrequencyMhz()); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e); - continue; - } - - ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags, - result.getSignalMbm() / 100, result.getFrequencyMhz(), result.getTsf(), ies, - null, result.getInformationElements()); - ScanResult scanResult = scanDetail.getScanResult(); - scanResult.setWifiStandard(wifiModeToWifiStandard(networkDetail.getWifiMode())); - - // Fill up the radio chain info. - scanResult.radioChainInfos = - new ScanResult.RadioChainInfo[result.getRadioChainInfos().size()]; - int idx = 0; - for (RadioChainInfo nativeRadioChainInfo : result.getRadioChainInfos()) { - scanResult.radioChainInfos[idx] = new ScanResult.RadioChainInfo(); - scanResult.radioChainInfos[idx].id = nativeRadioChainInfo.getChainId(); - scanResult.radioChainInfos[idx].level = nativeRadioChainInfo.getLevelDbm(); - idx++; - } - results.add(scanDetail); - } - if (mVerboseLoggingEnabled) { - Log.d(TAG, "get " + results.size() + " scan results from wificond"); - } - - return results; - } - - @WifiAnnotations.WifiStandard - private static int wifiModeToWifiStandard(int wifiMode) { - switch (wifiMode) { - case InformationElementUtil.WifiMode.MODE_11A: - case InformationElementUtil.WifiMode.MODE_11B: - case InformationElementUtil.WifiMode.MODE_11G: - return ScanResult.WIFI_STANDARD_LEGACY; - case InformationElementUtil.WifiMode.MODE_11N: - return ScanResult.WIFI_STANDARD_11N; - case InformationElementUtil.WifiMode.MODE_11AC: - return ScanResult.WIFI_STANDARD_11AC; - case InformationElementUtil.WifiMode.MODE_11AX: - return ScanResult.WIFI_STANDARD_11AX; - case InformationElementUtil.WifiMode.MODE_UNDEFINED: - default: - return ScanResult.WIFI_STANDARD_UNKNOWN; - } - } - - private boolean mIsEnhancedOpenSupportedInitialized = false; - private boolean mIsEnhancedOpenSupported; - - /** - * Check if OWE (Enhanced Open) is supported on the device - * - * @return true if OWE is supported - */ - private boolean isEnhancedOpenSupported() { - if (mIsEnhancedOpenSupportedInitialized) { - return mIsEnhancedOpenSupported; - } - - String iface = getClientInterfaceName(); - if (iface == null) { - // Client interface might not be initialized during boot or Wi-Fi off - return false; - } - - mIsEnhancedOpenSupportedInitialized = true; - mIsEnhancedOpenSupported = (getSupportedFeatureSet(iface) & WIFI_FEATURE_OWE) != 0; - return mIsEnhancedOpenSupported; - } - - /** - * Start PNO scan. - * @param ifaceName Name of the interface. - * @param pnoSettings Pno scan configuration. - * @return true on success. - */ - public boolean startPnoScan(@NonNull String ifaceName, PnoSettings pnoSettings) { - return mWifiCondManager.startPnoScan(ifaceName, pnoSettings.toNativePnoSettings(), - Runnable::run, - new WifiNl80211Manager.PnoScanRequestCallback() { - @Override - public void onPnoRequestSucceeded() { - mWifiMetrics.incrementPnoScanStartAttemptCount(); - } - - @Override - public void onPnoRequestFailed() { - mWifiMetrics.incrementPnoScanStartAttemptCount(); - mWifiMetrics.incrementPnoScanFailedCount(); - } - }); - } - - /** - * Stop PNO scan. - * @param ifaceName Name of the interface. - * @return true on success. - */ - public boolean stopPnoScan(@NonNull String ifaceName) { - return mWifiCondManager.stopPnoScan(ifaceName); - } - - /** - * Sends an arbitrary 802.11 management frame on the current channel. - * - * @param ifaceName Name of the interface. - * @param frame Bytes of the 802.11 management frame to be sent, including the header, but not - * including the frame check sequence (FCS). - * @param callback A callback triggered when the transmitted frame is ACKed or the transmission - * fails. - * @param mcs The MCS index that the frame will be sent at. If mcs < 0, the driver will select - * the rate automatically. If the device does not support sending the frame at a - * specified MCS rate, the transmission will be aborted and - * {@link WifiNl80211Manager.SendMgmtFrameCallback#onFailure(int)} will be called - * with reason {@link WifiNl80211Manager#SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED}. - */ - public void sendMgmtFrame(@NonNull String ifaceName, @NonNull byte[] frame, - @NonNull WifiNl80211Manager.SendMgmtFrameCallback callback, int mcs) { - mWifiCondManager.sendMgmtFrame(ifaceName, frame, mcs, Runnable::run, callback); - } - - /** - * Sends a probe request to the AP and waits for a response in order to determine whether - * there is connectivity between the device and AP. - * - * @param ifaceName Name of the interface. - * @param receiverMac the MAC address of the AP that the probe request will be sent to. - * @param callback callback triggered when the probe was ACKed by the AP, or when - * an error occurs after the link probe was started. - * @param mcs The MCS index that this probe will be sent at. If mcs < 0, the driver will select - * the rate automatically. If the device does not support sending the frame at a - * specified MCS rate, the transmission will be aborted and - * {@link WifiNl80211Manager.SendMgmtFrameCallback#onFailure(int)} will be called - * with reason {@link WifiNl80211Manager#SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED}. - */ - public void probeLink(@NonNull String ifaceName, @NonNull MacAddress receiverMac, - @NonNull WifiNl80211Manager.SendMgmtFrameCallback callback, int mcs) { - if (callback == null) { - Log.e(TAG, "callback cannot be null!"); - return; - } - - if (receiverMac == null) { - Log.e(TAG, "Receiver MAC address cannot be null!"); - callback.onFailure(WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN); - return; - } - - String senderMacStr = getMacAddress(ifaceName); - if (senderMacStr == null) { - Log.e(TAG, "Failed to get this device's MAC Address"); - callback.onFailure(WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN); - return; - } - - byte[] frame = buildProbeRequestFrame( - receiverMac.toByteArray(), - NativeUtil.macAddressToByteArray(senderMacStr)); - sendMgmtFrame(ifaceName, frame, callback, mcs); - } - - // header = 24 bytes, minimal body = 2 bytes, no FCS (will be added by driver) - private static final int BASIC_PROBE_REQUEST_FRAME_SIZE = 24 + 2; - - private byte[] buildProbeRequestFrame(byte[] receiverMac, byte[] transmitterMac) { - ByteBuffer frame = ByteBuffer.allocate(BASIC_PROBE_REQUEST_FRAME_SIZE); - // ByteBuffer is big endian by default, switch to little endian - frame.order(ByteOrder.LITTLE_ENDIAN); - - // Protocol version = 0, Type = management, Subtype = Probe Request - frame.put((byte) 0x40); - - // no flags set - frame.put((byte) 0x00); - - // duration = 60 microseconds. Note: this is little endian - // Note: driver should calculate the duration and replace it before sending, putting a - // reasonable default value here just in case. - frame.putShort((short) 0x3c); - - // receiver/destination MAC address byte array - frame.put(receiverMac); - // sender MAC address byte array - frame.put(transmitterMac); - // BSSID (same as receiver address since we are sending to the AP) - frame.put(receiverMac); - - // Generate random sequence number, fragment number = 0 - // Note: driver should replace the sequence number with the correct number that is - // incremented from the last used sequence number. Putting a random sequence number as a - // default here just in case. - // bit 0 is least significant bit, bit 15 is most significant bit - // bits [0, 7] go in byte 0 - // bits [8, 15] go in byte 1 - // bits [0, 3] represent the fragment number (which is 0) - // bits [4, 15] represent the sequence number (which is random) - // clear bits [0, 3] to set fragment number = 0 - short sequenceAndFragmentNumber = (short) (mRandom.nextInt() & 0xfff0); - frame.putShort(sequenceAndFragmentNumber); - - // NL80211 rejects frames with an empty body, so we just need to put a placeholder - // information element. - // Tag for SSID - frame.put((byte) 0x00); - // Represents broadcast SSID. Not accurate, but works as placeholder. - frame.put((byte) 0x00); - - return frame.array(); - } - - private static final int CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS = 100; - private static final int CONNECT_TO_HOSTAPD_RETRY_TIMES = 50; - /** - * This method is called to wait for establishing connection to hostapd. - * - * @return true if connection is established, false otherwise. - */ - private boolean startAndWaitForHostapdConnection() { - // Start initialization if not already started. - if (!mHostapdHal.isInitializationStarted() - && !mHostapdHal.initialize()) { - return false; - } - if (!mHostapdHal.startDaemon()) { - Log.e(TAG, "Failed to startup hostapd"); - return false; - } - boolean connected = false; - int connectTries = 0; - while (!connected && connectTries++ < CONNECT_TO_HOSTAPD_RETRY_TIMES) { - // Check if the initialization is complete. - connected = mHostapdHal.isInitializationComplete(); - if (connected) { - break; - } - try { - Thread.sleep(CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS); - } catch (InterruptedException ignore) { - } - } - return connected; - } - - /** - * Start Soft AP operation using the provided configuration. - * - * @param ifaceName Name of the interface. - * @param config Configuration to use for the soft ap created. - * @param listener Callback for AP events. - * @return true on success, false otherwise. - */ - public boolean startSoftAp( - @NonNull String ifaceName, SoftApConfiguration config, SoftApListener listener) { - if (!mWifiCondManager.registerApCallback(ifaceName, Runnable::run, listener)) { - Log.e(TAG, "Failed to register ap listener"); - return false; - } - if (!mHostapdHal.addAccessPoint(ifaceName, config, listener::onFailure)) { - Log.e(TAG, "Failed to add acccess point"); - mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); - return false; - } - return true; - } - - /** - * Force a softap client disconnect with specific reason code. - * - * @param ifaceName Name of the interface. - * @param client Mac address to force disconnect in clients of the SoftAp. - * @param reasonCode One of disconnect reason code which defined in {@link ApConfigUtil}. - * @return true on success, false otherwise. - */ - public boolean forceClientDisconnect(@NonNull String ifaceName, - @NonNull MacAddress client, int reasonCode) { - return mHostapdHal.forceClientDisconnect(ifaceName, client, reasonCode); - } - - /** - * Set MAC address of the given interface - * @param interfaceName Name of the interface - * @param mac Mac address to change into - * @return true on success - */ - public boolean setMacAddress(String interfaceName, MacAddress mac) { - // TODO(b/72459123): Suppress interface down/up events from this call - // Trigger an explicit disconnect to avoid losing the disconnect event reason (if currently - // connected) from supplicant if the interface is brought down for MAC address change. - disconnect(interfaceName); - return mWifiVendorHal.setMacAddress(interfaceName, mac); - } - - /** - * Returns true if Hal version supports setMacAddress, otherwise false. - * - * @param interfaceName Name of the interface - */ - public boolean isSetMacAddressSupported(@NonNull String interfaceName) { - return mWifiVendorHal.isSetMacAddressSupported(interfaceName); - } - - /** - * Get the factory MAC address of the given interface - * @param interfaceName Name of the interface. - * @return factory MAC address, or null on a failed call or if feature is unavailable. - */ - public MacAddress getFactoryMacAddress(@NonNull String interfaceName) { - return mWifiVendorHal.getFactoryMacAddress(interfaceName); - } - - /******************************************************** - * Hostapd operations - ********************************************************/ - - /** - * Callback to notify hostapd death. - */ - public interface HostapdDeathEventHandler { - /** - * Invoked when the supplicant dies. - */ - void onDeath(); - } - - /******************************************************** - * Supplicant operations - ********************************************************/ - - /** - * Callback to notify supplicant death. - */ - public interface SupplicantDeathEventHandler { - /** - * Invoked when the supplicant dies. - */ - void onDeath(); - } - - /** - * Set supplicant log level - * - * @param turnOnVerbose Whether to turn on verbose logging or not. - */ - public void setSupplicantLogLevel(boolean turnOnVerbose) { - mSupplicantStaIfaceHal.setLogLevel(turnOnVerbose); - } - - /** - * Trigger a reconnection if the iface is disconnected. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean reconnect(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.reconnect(ifaceName); - } - - /** - * Trigger a reassociation even if the iface is currently connected. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean reassociate(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.reassociate(ifaceName); - } - - /** - * Trigger a disconnection from the currently connected network. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean disconnect(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.disconnect(ifaceName); - } - - /** - * Makes a callback to HIDL to getMacAddress from supplicant - * - * @param ifaceName Name of the interface. - * @return string containing the MAC address, or null on a failed call - */ - public String getMacAddress(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.getMacAddress(ifaceName); - } - - public static final int RX_FILTER_TYPE_V4_MULTICAST = 0; - public static final int RX_FILTER_TYPE_V6_MULTICAST = 1; - /** - * Start filtering out Multicast V4 packets - * @param ifaceName Name of the interface. - * @return {@code true} if the operation succeeded, {@code false} otherwise - * - * Multicast filtering rules work as follows: - * - * The driver can filter multicast (v4 and/or v6) and broadcast packets when in - * a power optimized mode (typically when screen goes off). - * - * In order to prevent the driver from filtering the multicast/broadcast packets, we have to - * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective - * - * DRIVER RXFILTER-ADD Num - * where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6 - * - * and DRIVER RXFILTER-START - * In order to stop the usage of these rules, we do - * - * DRIVER RXFILTER-STOP - * DRIVER RXFILTER-REMOVE Num - * where Num is as described for RXFILTER-ADD - * - * The SETSUSPENDOPT driver command overrides the filtering rules - */ - public boolean startFilteringMulticastV4Packets(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) - && mSupplicantStaIfaceHal.removeRxFilter( - ifaceName, RX_FILTER_TYPE_V4_MULTICAST) - && mSupplicantStaIfaceHal.startRxFilter(ifaceName); - } - - /** - * Stop filtering out Multicast V4 packets. - * @param ifaceName Name of the interface. - * @return {@code true} if the operation succeeded, {@code false} otherwise - */ - public boolean stopFilteringMulticastV4Packets(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) - && mSupplicantStaIfaceHal.addRxFilter( - ifaceName, RX_FILTER_TYPE_V4_MULTICAST) - && mSupplicantStaIfaceHal.startRxFilter(ifaceName); - } - - /** - * Start filtering out Multicast V6 packets - * @param ifaceName Name of the interface. - * @return {@code true} if the operation succeeded, {@code false} otherwise - */ - public boolean startFilteringMulticastV6Packets(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) - && mSupplicantStaIfaceHal.removeRxFilter( - ifaceName, RX_FILTER_TYPE_V6_MULTICAST) - && mSupplicantStaIfaceHal.startRxFilter(ifaceName); - } - - /** - * Stop filtering out Multicast V6 packets. - * @param ifaceName Name of the interface. - * @return {@code true} if the operation succeeded, {@code false} otherwise - */ - public boolean stopFilteringMulticastV6Packets(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) - && mSupplicantStaIfaceHal.addRxFilter( - ifaceName, RX_FILTER_TYPE_V6_MULTICAST) - && mSupplicantStaIfaceHal.startRxFilter(ifaceName); - } - - public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0; - public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1; - public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2; - /** - * Sets the bluetooth coexistence mode. - * - * @param ifaceName Name of the interface. - * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED}, - * {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or - * {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}. - * @return Whether the mode was successfully set. - */ - public boolean setBluetoothCoexistenceMode(@NonNull String ifaceName, int mode) { - return mSupplicantStaIfaceHal.setBtCoexistenceMode(ifaceName, mode); - } - - /** - * Enable or disable Bluetooth coexistence scan mode. When this mode is on, - * some of the low-level scan parameters used by the driver are changed to - * reduce interference with A2DP streaming. - * - * @param ifaceName Name of the interface. - * @param setCoexScanMode whether to enable or disable this mode - * @return {@code true} if the command succeeded, {@code false} otherwise. - */ - public boolean setBluetoothCoexistenceScanMode( - @NonNull String ifaceName, boolean setCoexScanMode) { - return mSupplicantStaIfaceHal.setBtCoexistenceScanModeEnabled( - ifaceName, setCoexScanMode); - } - - /** - * Enable or disable suspend mode optimizations. - * - * @param ifaceName Name of the interface. - * @param enabled true to enable, false otherwise. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setSuspendOptimizations(@NonNull String ifaceName, boolean enabled) { - return mSupplicantStaIfaceHal.setSuspendModeEnabled(ifaceName, enabled); - } - - /** - * Set country code. - * - * @param ifaceName Name of the interface. - * @param countryCode 2 byte ASCII string. For ex: US, CA. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setCountryCode(@NonNull String ifaceName, String countryCode) { - return mSupplicantStaIfaceHal.setCountryCode(ifaceName, countryCode); - } - - /** - * Flush all previously configured HLPs. - * - * @return true if request is sent successfully, false otherwise. - */ - public boolean flushAllHlp(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.flushAllHlp(ifaceName); - } - - /** - * Set FILS HLP packet. - * - * @param dst Destination MAC address. - * @param hlpPacket Hlp Packet data in hex. - * @return true if request is sent successfully, false otherwise. - */ - public boolean addHlpReq(@NonNull String ifaceName, MacAddress dst, byte [] hlpPacket) { - return mSupplicantStaIfaceHal.addHlpReq(ifaceName, dst.toByteArray(), hlpPacket); - } - - /** - * Initiate TDLS discover and setup or teardown with the specified peer. - * - * @param ifaceName Name of the interface. - * @param macAddr MAC Address of the peer. - * @param enable true to start discovery and setup, false to teardown. - */ - public void startTdls(@NonNull String ifaceName, String macAddr, boolean enable) { - if (enable) { - mSupplicantStaIfaceHal.initiateTdlsDiscover(ifaceName, macAddr); - mSupplicantStaIfaceHal.initiateTdlsSetup(ifaceName, macAddr); - } else { - mSupplicantStaIfaceHal.initiateTdlsTeardown(ifaceName, macAddr); - } - } - - /** - * Start WPS pin display operation with the specified peer. - * - * @param ifaceName Name of the interface. - * @param bssid BSSID of the peer. - * @return true if request is sent successfully, false otherwise. - */ - public boolean startWpsPbc(@NonNull String ifaceName, String bssid) { - return mSupplicantStaIfaceHal.startWpsPbc(ifaceName, bssid); - } - - /** - * Start WPS pin keypad operation with the specified pin. - * - * @param ifaceName Name of the interface. - * @param pin Pin to be used. - * @return true if request is sent successfully, false otherwise. - */ - public boolean startWpsPinKeypad(@NonNull String ifaceName, String pin) { - return mSupplicantStaIfaceHal.startWpsPinKeypad(ifaceName, pin); - } - - /** - * Start WPS pin display operation with the specified peer. - * - * @param ifaceName Name of the interface. - * @param bssid BSSID of the peer. - * @return new pin generated on success, null otherwise. - */ - public String startWpsPinDisplay(@NonNull String ifaceName, String bssid) { - return mSupplicantStaIfaceHal.startWpsPinDisplay(ifaceName, bssid); - } - - /** - * Sets whether to use external sim for SIM/USIM processing. - * - * @param ifaceName Name of the interface. - * @param external true to enable, false otherwise. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setExternalSim(@NonNull String ifaceName, boolean external) { - return mSupplicantStaIfaceHal.setExternalSim(ifaceName, external); - } - - /** - * Sim auth response types. - */ - public static final String SIM_AUTH_RESP_TYPE_GSM_AUTH = "GSM-AUTH"; - public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTH = "UMTS-AUTH"; - public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTS = "UMTS-AUTS"; - - /** - * EAP-SIM Error Codes - */ - public static final int EAP_SIM_NOT_SUBSCRIBED = 1031; - public static final int EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED = 16385; - - /** - * Send the sim auth response for the currently configured network. - * - * @param ifaceName Name of the interface. - * @param type |GSM-AUTH|, |UMTS-AUTH| or |UMTS-AUTS|. - * @param response Response params. - * @return true if succeeds, false otherwise. - */ - public boolean simAuthResponse( - @NonNull String ifaceName, String type, String response) { - if (SIM_AUTH_RESP_TYPE_GSM_AUTH.equals(type)) { - return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthResponse( - ifaceName, response); - } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTH.equals(type)) { - return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthResponse( - ifaceName, response); - } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTS.equals(type)) { - return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAutsResponse( - ifaceName, response); - } else { - return false; - } - } - - /** - * Send the eap sim gsm auth failure for the currently configured network. - * - * @param ifaceName Name of the interface. - * @return true if succeeds, false otherwise. - */ - public boolean simAuthFailedResponse(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthFailure(ifaceName); - } - - /** - * Send the eap sim umts auth failure for the currently configured network. - * - * @param ifaceName Name of the interface. - * @return true if succeeds, false otherwise. - */ - public boolean umtsAuthFailedResponse(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthFailure(ifaceName); - } - - /** - * Send the eap identity response for the currently configured network. - * - * @param ifaceName Name of the interface. - * @param unencryptedResponse String to send. - * @param encryptedResponse String to send. - * @return true if succeeds, false otherwise. - */ - public boolean simIdentityResponse(@NonNull String ifaceName, String unencryptedResponse, - String encryptedResponse) { - return mSupplicantStaIfaceHal.sendCurrentNetworkEapIdentityResponse(ifaceName, - unencryptedResponse, encryptedResponse); - } - - /** - * This get anonymous identity from supplicant and returns it as a string. - * - * @param ifaceName Name of the interface. - * @return anonymous identity string if succeeds, null otherwise. - */ - public String getEapAnonymousIdentity(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(ifaceName); - } - - /** - * Start WPS pin registrar operation with the specified peer and pin. - * - * @param ifaceName Name of the interface. - * @param bssid BSSID of the peer. - * @param pin Pin to be used. - * @return true if request is sent successfully, false otherwise. - */ - public boolean startWpsRegistrar(@NonNull String ifaceName, String bssid, String pin) { - return mSupplicantStaIfaceHal.startWpsRegistrar(ifaceName, bssid, pin); - } - - /** - * Cancels any ongoing WPS requests. - * - * @param ifaceName Name of the interface. - * @return true if request is sent successfully, false otherwise. - */ - public boolean cancelWps(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.cancelWps(ifaceName); - } - - /** - * Set WPS device name. - * - * @param ifaceName Name of the interface. - * @param name String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setDeviceName(@NonNull String ifaceName, String name) { - return mSupplicantStaIfaceHal.setWpsDeviceName(ifaceName, name); - } - - /** - * Set WPS device type. - * - * @param ifaceName Name of the interface. - * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg> - * @return true if request is sent successfully, false otherwise. - */ - public boolean setDeviceType(@NonNull String ifaceName, String type) { - return mSupplicantStaIfaceHal.setWpsDeviceType(ifaceName, type); - } - - /** - * Set WPS config methods - * - * @param cfg List of config methods. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setConfigMethods(@NonNull String ifaceName, String cfg) { - return mSupplicantStaIfaceHal.setWpsConfigMethods(ifaceName, cfg); - } - - /** - * Set WPS manufacturer. - * - * @param ifaceName Name of the interface. - * @param value String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setManufacturer(@NonNull String ifaceName, String value) { - return mSupplicantStaIfaceHal.setWpsManufacturer(ifaceName, value); - } - - /** - * Set WPS model name. - * - * @param ifaceName Name of the interface. - * @param value String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setModelName(@NonNull String ifaceName, String value) { - return mSupplicantStaIfaceHal.setWpsModelName(ifaceName, value); - } - - /** - * Set WPS model number. - * - * @param ifaceName Name of the interface. - * @param value String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setModelNumber(@NonNull String ifaceName, String value) { - return mSupplicantStaIfaceHal.setWpsModelNumber(ifaceName, value); - } - - /** - * Set WPS serial number. - * - * @param ifaceName Name of the interface. - * @param value String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setSerialNumber(@NonNull String ifaceName, String value) { - return mSupplicantStaIfaceHal.setWpsSerialNumber(ifaceName, value); - } - - /** - * Enable or disable power save mode. - * - * @param ifaceName Name of the interface. - * @param enabled true to enable, false to disable. - */ - public void setPowerSave(@NonNull String ifaceName, boolean enabled) { - mSupplicantStaIfaceHal.setPowerSave(ifaceName, enabled); - } - - /** - * Enable or disable low latency mode. - * - * @param enabled true to enable, false to disable. - * @return true on success, false on failure - */ - public boolean setLowLatencyMode(boolean enabled) { - return mWifiVendorHal.setLowLatencyMode(enabled); - } - - /** - * Set concurrency priority between P2P & STA operations. - * - * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, - * false otherwise. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setConcurrencyPriority(boolean isStaHigherPriority) { - return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority); - } - - /** - * Enable/Disable auto reconnect functionality in wpa_supplicant. - * - * @param ifaceName Name of the interface. - * @param enable true to enable auto reconnecting, false to disable. - * @return true if request is sent successfully, false otherwise. - */ - public boolean enableStaAutoReconnect(@NonNull String ifaceName, boolean enable) { - return mSupplicantStaIfaceHal.enableAutoReconnect(ifaceName, enable); - } - - /** - * Add the provided network configuration to wpa_supplicant and initiate connection to it. - * This method does the following: - * 1. Abort any ongoing scan to unblock the connection request. - * 2. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect). - * 3. Add a new network to wpa_supplicant. - * 4. Save the provided configuration to wpa_supplicant. - * 5. Select the new network in wpa_supplicant. - * 6. Triggers reconnect command to wpa_supplicant. - * - * @param ifaceName Name of the interface. - * @param configuration WifiConfiguration parameters for the provided network. - * @return {@code true} if it succeeds, {@code false} otherwise - */ - public boolean connectToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) { - // Abort ongoing scan before connect() to unblock connection request. - mWifiCondManager.abortScan(ifaceName); - return mSupplicantStaIfaceHal.connectToNetwork(ifaceName, configuration); - } - - /** - * Initiates roaming to the already configured network in wpa_supplicant. If the network - * configuration provided does not match the already configured network, then this triggers - * a new connection attempt (instead of roam). - * 1. Abort any ongoing scan to unblock the roam request. - * 2. First check if we're attempting to connect to the same network as we currently have - * configured. - * 3. Set the new bssid for the network in wpa_supplicant. - * 4. Triggers reassociate command to wpa_supplicant. - * - * @param ifaceName Name of the interface. - * @param configuration WifiConfiguration parameters for the provided network. - * @return {@code true} if it succeeds, {@code false} otherwise - */ - public boolean roamToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) { - // Abort ongoing scan before connect() to unblock roaming request. - mWifiCondManager.abortScan(ifaceName); - return mSupplicantStaIfaceHal.roamToNetwork(ifaceName, configuration); - } - - /** - * Remove all the networks. - * - * @param ifaceName Name of the interface. - * @return {@code true} if it succeeds, {@code false} otherwise - */ - public boolean removeAllNetworks(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.removeAllNetworks(ifaceName); - } - - /** - * Set the BSSID for the currently configured network in wpa_supplicant. - * - * @param ifaceName Name of the interface. - * @return true if successful, false otherwise. - */ - public boolean setConfiguredNetworkBSSID(@NonNull String ifaceName, String bssid) { - return mSupplicantStaIfaceHal.setCurrentNetworkBssid(ifaceName, bssid); - } - - /** - * Initiate ANQP query. - * - * @param ifaceName Name of the interface. - * @param bssid BSSID of the AP to be queried - * @param anqpIds Set of anqp IDs. - * @param hs20Subtypes Set of HS20 subtypes. - * @return true on success, false otherwise. - */ - public boolean requestAnqp( - @NonNull String ifaceName, String bssid, Set<Integer> anqpIds, - Set<Integer> hs20Subtypes) { - if (bssid == null || ((anqpIds == null || anqpIds.isEmpty()) - && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) { - Log.e(TAG, "Invalid arguments for ANQP request."); - return false; - } - ArrayList<Short> anqpIdList = new ArrayList<>(); - for (Integer anqpId : anqpIds) { - anqpIdList.add(anqpId.shortValue()); - } - ArrayList<Integer> hs20SubtypeList = new ArrayList<>(); - hs20SubtypeList.addAll(hs20Subtypes); - return mSupplicantStaIfaceHal.initiateAnqpQuery( - ifaceName, bssid, anqpIdList, hs20SubtypeList); - } - - /** - * Request a passpoint icon file |filename| from the specified AP |bssid|. - * - * @param ifaceName Name of the interface. - * @param bssid BSSID of the AP - * @param fileName name of the icon file - * @return true if request is sent successfully, false otherwise - */ - public boolean requestIcon(@NonNull String ifaceName, String bssid, String fileName) { - if (bssid == null || fileName == null) { - Log.e(TAG, "Invalid arguments for Icon request."); - return false; - } - return mSupplicantStaIfaceHal.initiateHs20IconQuery(ifaceName, bssid, fileName); - } - - /** - * Get the currently configured network's WPS NFC token. - * - * @param ifaceName Name of the interface. - * @return Hex string corresponding to the WPS NFC token. - */ - public String getCurrentNetworkWpsNfcConfigurationToken(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken(ifaceName); - } - - /** - * Clean HAL cached data for |networkId|. - * - * @param networkId network id of the network to be removed from supplicant. - */ - public void removeNetworkCachedData(int networkId) { - mSupplicantStaIfaceHal.removeNetworkCachedData(networkId); - } - - /** Clear HAL cached data for |networkId| if MAC address is changed. - * - * @param networkId network id of the network to be checked. - * @param curMacAddress current MAC address - */ - public void removeNetworkCachedDataIfNeeded(int networkId, MacAddress curMacAddress) { - mSupplicantStaIfaceHal.removeNetworkCachedDataIfNeeded(networkId, curMacAddress); - } - - /* - * DPP - */ - - /** - * Adds a DPP peer URI to the URI list. - * - * @param ifaceName Interface name - * @param uri Bootstrap (URI) string (e.g. DPP:....) - * @return ID, or -1 for failure - */ - public int addDppPeerUri(@NonNull String ifaceName, @NonNull String uri) { - return mSupplicantStaIfaceHal.addDppPeerUri(ifaceName, uri); - } - - /** - * Removes a DPP URI to the URI list given an ID. - * - * @param ifaceName Interface name - * @param bootstrapId Bootstrap (URI) ID - * @return true when operation is successful, or false for failure - */ - public boolean removeDppUri(@NonNull String ifaceName, int bootstrapId) { - return mSupplicantStaIfaceHal.removeDppUri(ifaceName, bootstrapId); - } - - /** - * Stops/aborts DPP Initiator request - * - * @param ifaceName Interface name - * @return true when operation is successful, or false for failure - */ - public boolean stopDppInitiator(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.stopDppInitiator(ifaceName); - } - - /** - * Starts DPP Configurator-Initiator request - * - * @param ifaceName Interface name - * @param peerBootstrapId Peer's bootstrap (URI) ID - * @param ownBootstrapId Own bootstrap (URI) ID - Optional, 0 for none - * @param ssid SSID of the selected network - * @param password Password of the selected network, or - * @param psk PSK of the selected network in hexadecimal representation - * @param netRole The network role of the enrollee (STA or AP) - * @param securityAkm Security AKM to use: PSK, SAE - * @return true when operation is successful, or false for failure - */ - public boolean startDppConfiguratorInitiator(@NonNull String ifaceName, int peerBootstrapId, - int ownBootstrapId, @NonNull String ssid, String password, String psk, - int netRole, int securityAkm) { - return mSupplicantStaIfaceHal.startDppConfiguratorInitiator(ifaceName, peerBootstrapId, - ownBootstrapId, ssid, password, psk, netRole, securityAkm); - } - - /** - * Starts DPP Enrollee-Initiator request - * - * @param ifaceName Interface name - * @param peerBootstrapId Peer's bootstrap (URI) ID - * @param ownBootstrapId Own bootstrap (URI) ID - Optional, 0 for none - * @return true when operation is successful, or false for failure - */ - public boolean startDppEnrolleeInitiator(@NonNull String ifaceName, int peerBootstrapId, - int ownBootstrapId) { - return mSupplicantStaIfaceHal.startDppEnrolleeInitiator(ifaceName, peerBootstrapId, - ownBootstrapId); - } - - /** - * Callback to notify about DPP success, failure and progress events. - */ - public interface DppEventCallback { - /** - * Called when local DPP Enrollee successfully receives a new Wi-Fi configuration from the - * peer DPP configurator. - * - * @param newWifiConfiguration New Wi-Fi configuration received from the configurator - */ - void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration); - - /** - * DPP Success event. - * - * @param dppStatusCode Status code of the success event. - */ - void onSuccess(int dppStatusCode); - - /** - * DPP Progress event. - * - * @param dppStatusCode Status code of the progress event. - */ - void onProgress(int dppStatusCode); - - /** - * DPP Failure event. - * - * @param dppStatusCode Status code of the failure event. - * @param ssid SSID of the network the Enrollee tried to connect to. - * @param channelList List of channels the Enrollee scanned for the network. - * @param bandList List of bands the Enrollee supports. - */ - void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList); - } - - /** - * Registers DPP event callbacks. - * - * @param dppEventCallback Callback object. - */ - public void registerDppEventCallback(DppEventCallback dppEventCallback) { - mSupplicantStaIfaceHal.registerDppCallback(dppEventCallback); - } - - /******************************************************** - * Vendor HAL operations - ********************************************************/ - /** - * Callback to notify vendor HAL death. - */ - public interface VendorHalDeathEventHandler { - /** - * Invoked when the vendor HAL dies. - */ - void onDeath(); - } - - /** - * Callback to notify when vendor HAL detects that a change in radio mode. - */ - public interface VendorHalRadioModeChangeEventHandler { - /** - * Invoked when the vendor HAL detects a change to MCC mode. - * MCC (Multi channel concurrency) = Multiple interfaces are active on the same band, - * different channels, same radios. - * - * @param band Band on which MCC is detected (specified by one of the - * WifiScanner.WIFI_BAND_* constants) - */ - void onMcc(int band); - /** - * Invoked when the vendor HAL detects a change to SCC mode. - * SCC (Single channel concurrency) = Multiple interfaces are active on the same band, same - * channels, same radios. - * - * @param band Band on which SCC is detected (specified by one of the - * WifiScanner.WIFI_BAND_* constants) - */ - void onScc(int band); - /** - * Invoked when the vendor HAL detects a change to SBS mode. - * SBS (Single Band Simultaneous) = Multiple interfaces are active on the same band, - * different channels, different radios. - * - * @param band Band on which SBS is detected (specified by one of the - * WifiScanner.WIFI_BAND_* constants) - */ - void onSbs(int band); - /** - * Invoked when the vendor HAL detects a change to DBS mode. - * DBS (Dual Band Simultaneous) = Multiple interfaces are active on the different bands, - * different channels, different radios. - */ - void onDbs(); - } - - /** - * Tests whether the HAL is running or not - */ - public boolean isHalStarted() { - return mWifiVendorHal.isHalStarted(); - } - - // TODO: Change variable names to camel style. - public static class ScanCapabilities { - public int max_scan_cache_size; - public int max_scan_buckets; - public int max_ap_cache_per_scan; - public int max_rssi_sample_size; - public int max_scan_reporting_threshold; - } - - /** - * Gets the scan capabilities - * - * @param ifaceName Name of the interface. - * @param capabilities object to be filled in - * @return true for success. false for failure - */ - public boolean getBgScanCapabilities( - @NonNull String ifaceName, ScanCapabilities capabilities) { - return mWifiVendorHal.getBgScanCapabilities(ifaceName, capabilities); - } - - public static class ChannelSettings { - public int frequency; - public int dwell_time_ms; - public boolean passive; - } - - public static class BucketSettings { - public int bucket; - public int band; - public int period_ms; - public int max_period_ms; - public int step_count; - public int report_events; - public int num_channels; - public ChannelSettings[] channels; - } - - /** - * Network parameters for hidden networks to be scanned for. - */ - public static class HiddenNetwork { - public String ssid; - - @Override - public boolean equals(Object otherObj) { - if (this == otherObj) { - return true; - } else if (otherObj == null || getClass() != otherObj.getClass()) { - return false; - } - HiddenNetwork other = (HiddenNetwork) otherObj; - return Objects.equals(ssid, other.ssid); - } - - @Override - public int hashCode() { - return Objects.hash(ssid); - } - } - - public static class ScanSettings { - /** - * Type of scan to perform. One of {@link WifiScanner#SCAN_TYPE_LOW_LATENCY}, - * {@link WifiScanner#SCAN_TYPE_LOW_POWER} or {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}. - */ - @WifiAnnotations.ScanType - public int scanType; - public int base_period_ms; - public int max_ap_per_scan; - public int report_threshold_percent; - public int report_threshold_num_scans; - public int num_buckets; - /* Not used for bg scans. Only works for single scans. */ - public HiddenNetwork[] hiddenNetworks; - public BucketSettings[] buckets; - } - - /** - * Network parameters to start PNO scan. - */ - public static class PnoNetwork { - public String ssid; - public byte flags; - public byte auth_bit_field; - public int[] frequencies; - - @Override - public boolean equals(Object otherObj) { - if (this == otherObj) { - return true; - } else if (otherObj == null || getClass() != otherObj.getClass()) { - return false; - } - PnoNetwork other = (PnoNetwork) otherObj; - return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags) - && (auth_bit_field == other.auth_bit_field)) - && Arrays.equals(frequencies, other.frequencies); - } - - @Override - public int hashCode() { - return Objects.hash(ssid, flags, auth_bit_field, frequencies); - } - - android.net.wifi.nl80211.PnoNetwork toNativePnoNetwork() { - android.net.wifi.nl80211.PnoNetwork nativePnoNetwork = - new android.net.wifi.nl80211.PnoNetwork(); - nativePnoNetwork.setHidden( - (flags & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0); - try { - nativePnoNetwork.setSsid( - NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid))); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + ssid, e); - return null; - } - nativePnoNetwork.setFrequenciesMhz(frequencies); - return nativePnoNetwork; - } - } - - /** - * Parameters to start PNO scan. This holds the list of networks which are going to used for - * PNO scan. - */ - public static class PnoSettings { - public int min5GHzRssi; - public int min24GHzRssi; - public int min6GHzRssi; - public int periodInMs; - public boolean isConnected; - public PnoNetwork[] networkList; - - android.net.wifi.nl80211.PnoSettings toNativePnoSettings() { - android.net.wifi.nl80211.PnoSettings nativePnoSettings = - new android.net.wifi.nl80211.PnoSettings(); - nativePnoSettings.setIntervalMillis(periodInMs); - nativePnoSettings.setMin2gRssiDbm(min24GHzRssi); - nativePnoSettings.setMin5gRssiDbm(min5GHzRssi); - nativePnoSettings.setMin6gRssiDbm(min6GHzRssi); - - List<android.net.wifi.nl80211.PnoNetwork> pnoNetworks = new ArrayList<>(); - if (networkList != null) { - for (PnoNetwork network : networkList) { - android.net.wifi.nl80211.PnoNetwork nativeNetwork = - network.toNativePnoNetwork(); - if (nativeNetwork != null) { - pnoNetworks.add(nativeNetwork); - } - } - } - nativePnoSettings.setPnoNetworks(pnoNetworks); - return nativePnoSettings; - } - } - - public static interface ScanEventHandler { - /** - * Called for each AP as it is found with the entire contents of the beacon/probe response. - * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified. - */ - void onFullScanResult(ScanResult fullScanResult, int bucketsScanned); - /** - * Callback on an event during a gscan scan. - * See WifiNative.WIFI_SCAN_* for possible values. - */ - void onScanStatus(int event); - /** - * Called with the current cached scan results when gscan is paused. - */ - void onScanPaused(WifiScanner.ScanData[] data); - /** - * Called with the current cached scan results when gscan is resumed. - */ - void onScanRestarted(); - } - - /** - * Handler to notify the occurrence of various events during PNO scan. - */ - public interface PnoEventHandler { - /** - * Callback to notify when one of the shortlisted networks is found during PNO scan. - * @param results List of Scan results received. - */ - void onPnoNetworkFound(ScanResult[] results); - - /** - * Callback to notify when the PNO scan schedule fails. - */ - void onPnoScanFailed(); - } - - public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0; - public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1; - public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2; - public static final int WIFI_SCAN_FAILED = 3; - - /** - * Starts a background scan. - * Any ongoing scan will be stopped first - * - * @param ifaceName Name of the interface. - * @param settings to control the scan - * @param eventHandler to call with the results - * @return true for success - */ - public boolean startBgScan( - @NonNull String ifaceName, ScanSettings settings, ScanEventHandler eventHandler) { - return mWifiVendorHal.startBgScan(ifaceName, settings, eventHandler); - } - - /** - * Stops any ongoing backgound scan - * @param ifaceName Name of the interface. - */ - public void stopBgScan(@NonNull String ifaceName) { - mWifiVendorHal.stopBgScan(ifaceName); - } - - /** - * Pauses an ongoing backgound scan - * @param ifaceName Name of the interface. - */ - public void pauseBgScan(@NonNull String ifaceName) { - mWifiVendorHal.pauseBgScan(ifaceName); - } - - /** - * Restarts a paused scan - * @param ifaceName Name of the interface. - */ - public void restartBgScan(@NonNull String ifaceName) { - mWifiVendorHal.restartBgScan(ifaceName); - } - - /** - * Gets the latest scan results received. - * @param ifaceName Name of the interface. - */ - public WifiScanner.ScanData[] getBgScanResults(@NonNull String ifaceName) { - return mWifiVendorHal.getBgScanResults(ifaceName); - } - - /** - * Gets the latest link layer stats - * @param ifaceName Name of the interface. - */ - public WifiLinkLayerStats getWifiLinkLayerStats(@NonNull String ifaceName) { - return mWifiVendorHal.getWifiLinkLayerStats(ifaceName); - } - - /** - * Returns whether STA/AP concurrency is supported or not. - */ - public boolean isStaApConcurrencySupported() { - synchronized (mLock) { - return mWifiVendorHal.isStaApConcurrencySupported(); - } - } - - /** - * Get the supported features - * - * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - public long getSupportedFeatureSet(@NonNull String ifaceName) { - synchronized (mLock) { - Iface iface = mIfaceMgr.getIface(ifaceName); - if (iface == null) { - Log.e(TAG, "Could not get Iface object for interface " + ifaceName); - return 0; - } - - return iface.featureSet; - } - } - - /** - * Get the supported features - * - * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - private long getSupportedFeatureSetInternal(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.getAdvancedKeyMgmtCapabilities(ifaceName) - | mWifiVendorHal.getSupportedFeatureSet(ifaceName) - | mSupplicantStaIfaceHal.getWpaDriverFeatureSet(ifaceName); - } - - /** - * Class to retrieve connection capability parameters after association - */ - public static class ConnectionCapabilities { - public @WifiAnnotations.WifiStandard int wifiStandard; - public int channelBandwidth; - public int maxNumberTxSpatialStreams; - public int maxNumberRxSpatialStreams; - ConnectionCapabilities() { - wifiStandard = ScanResult.WIFI_STANDARD_UNKNOWN; - channelBandwidth = ScanResult.CHANNEL_WIDTH_20MHZ; - maxNumberTxSpatialStreams = 1; - maxNumberRxSpatialStreams = 1; - } - } - - /** - * Returns connection capabilities of the current network - * - * @param ifaceName Name of the interface. - * @return connection capabilities of the current network - */ - public ConnectionCapabilities getConnectionCapabilities(@NonNull String ifaceName) { - return mSupplicantStaIfaceHal.getConnectionCapabilities(ifaceName); - } - - /** - * Get the APF (Android Packet Filter) capabilities of the device - * @param ifaceName Name of the interface. - */ - public ApfCapabilities getApfCapabilities(@NonNull String ifaceName) { - return mWifiVendorHal.getApfCapabilities(ifaceName); - } - - /** - * Installs an APF program on this iface, replacing any existing program. - * - * @param ifaceName Name of the interface - * @param filter is the android packet filter program - * @return true for success - */ - public boolean installPacketFilter(@NonNull String ifaceName, byte[] filter) { - return mWifiVendorHal.installPacketFilter(ifaceName, filter); - } - - /** - * Reads the APF program and data buffer for this iface. - * - * @param ifaceName Name of the interface - * @return the buffer returned by the driver, or null in case of an error - */ - public byte[] readPacketFilter(@NonNull String ifaceName) { - return mWifiVendorHal.readPacketFilter(ifaceName); - } - - /** - * Set country code for this AP iface. - * @param ifaceName Name of the interface. - * @param countryCode - two-letter country code (as ISO 3166) - * @return true for success - */ - public boolean setCountryCodeHal(@NonNull String ifaceName, String countryCode) { - return mWifiVendorHal.setCountryCodeHal(ifaceName, countryCode); - } - - //--------------------------------------------------------------------------------- - /* Wifi Logger commands/events */ - public static interface WifiLoggerEventHandler { - void onRingBufferData(RingBufferStatus status, byte[] buffer); - void onWifiAlert(int errorCode, byte[] buffer); - } - - /** - * Registers the logger callback and enables alerts. - * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked. - * - * @param handler Callback to be invoked. - * @return true on success, false otherwise. - */ - public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) { - return mWifiVendorHal.setLoggingEventHandler(handler); - } - - /** - * Control debug data collection - * - * @param verboseLevel 0 to 3, inclusive. 0 stops logging. - * @param flags Ignored. - * @param maxInterval Maximum interval between reports; ignore if 0. - * @param minDataSize Minimum data size in buffer for report; ignore if 0. - * @param ringName Name of the ring for which data collection is to start. - * @return true for success, false otherwise. - */ - public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, - int minDataSize, String ringName){ - return mWifiVendorHal.startLoggingRingBuffer( - verboseLevel, flags, maxInterval, minDataSize, ringName); - } - - /** - * Logger features exposed. - * This is a no-op now, will always return -1. - * - * @return true on success, false otherwise. - */ - public int getSupportedLoggerFeatureSet() { - return mWifiVendorHal.getSupportedLoggerFeatureSet(); - } - - /** - * Stops all logging and resets the logger callback. - * This stops both the alerts and ring buffer data collection. - * @return true on success, false otherwise. - */ - public boolean resetLogHandler() { - return mWifiVendorHal.resetLogHandler(); - } - - /** - * Vendor-provided wifi driver version string - * - * @return String returned from the HAL. - */ - public String getDriverVersion() { - return mWifiVendorHal.getDriverVersion(); - } - - /** - * Vendor-provided wifi firmware version string - * - * @return String returned from the HAL. - */ - public String getFirmwareVersion() { - return mWifiVendorHal.getFirmwareVersion(); - } - - public static class RingBufferStatus{ - String name; - int flag; - int ringBufferId; - int ringBufferByteSize; - int verboseLevel; - int writtenBytes; - int readBytes; - int writtenRecords; - - // Bit masks for interpreting |flag| - public static final int HAS_BINARY_ENTRIES = (1 << 0); - public static final int HAS_ASCII_ENTRIES = (1 << 1); - public static final int HAS_PER_PACKET_ENTRIES = (1 << 2); - - @Override - public String toString() { - return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId + - " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel + - " writtenBytes: " + writtenBytes + " readBytes: " + readBytes + - " writtenRecords: " + writtenRecords; - } - } - - /** - * API to get the status of all ring buffers supported by driver - */ - public RingBufferStatus[] getRingBufferStatus() { - return mWifiVendorHal.getRingBufferStatus(); - } - - /** - * Indicates to driver that all the data has to be uploaded urgently - * - * @param ringName Name of the ring buffer requested. - * @return true on success, false otherwise. - */ - public boolean getRingBufferData(String ringName) { - return mWifiVendorHal.getRingBufferData(ringName); - } - - /** - * Request hal to flush ring buffers to files - * - * @return true on success, false otherwise. - */ - public boolean flushRingBufferData() { - return mWifiVendorHal.flushRingBufferData(); - } - - /** - * Request vendor debug info from the firmware - * - * @return Raw data obtained from the HAL. - */ - public byte[] getFwMemoryDump() { - return mWifiVendorHal.getFwMemoryDump(); - } - - /** - * Request vendor debug info from the driver - * - * @return Raw data obtained from the HAL. - */ - public byte[] getDriverStateDump() { - return mWifiVendorHal.getDriverStateDump(); - } - - //--------------------------------------------------------------------------------- - /* Packet fate API */ - - @Immutable - abstract static class FateReport { - final static int USEC_PER_MSEC = 1000; - // The driver timestamp is a 32-bit counter, in microseconds. This field holds the - // maximal value of a driver timestamp in milliseconds. - final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000); - final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS"); - - final byte mFate; - final long mDriverTimestampUSec; - final byte mFrameType; - final byte[] mFrameBytes; - final long mEstimatedWallclockMSec; - - FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { - mFate = fate; - mDriverTimestampUSec = driverTimestampUSec; - mEstimatedWallclockMSec = - convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec); - mFrameType = frameType; - mFrameBytes = frameBytes; - } - - public String toTableRowString() { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - FrameParser parser = new FrameParser(mFrameType, mFrameBytes); - dateFormatter.setTimeZone(TimeZone.getDefault()); - pw.format("%-15s %12s %-9s %-32s %-12s %-23s %s\n", - mDriverTimestampUSec, - dateFormatter.format(new Date(mEstimatedWallclockMSec)), - directionToString(), fateToString(), parser.mMostSpecificProtocolString, - parser.mTypeString, parser.mResultString); - return sw.toString(); - } - - public String toVerboseStringWithPiiAllowed() { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - FrameParser parser = new FrameParser(mFrameType, mFrameBytes); - pw.format("Frame direction: %s\n", directionToString()); - pw.format("Frame timestamp: %d\n", mDriverTimestampUSec); - pw.format("Frame fate: %s\n", fateToString()); - pw.format("Frame type: %s\n", frameTypeToString(mFrameType)); - pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString); - pw.format("Frame protocol type: %s\n", parser.mTypeString); - pw.format("Frame length: %d\n", mFrameBytes.length); - pw.append("Frame bytes"); - pw.append(HexDump.dumpHexString(mFrameBytes)); // potentially contains PII - pw.append("\n"); - return sw.toString(); - } - - /* Returns a header to match the output of toTableRowString(). */ - public static String getTableHeader() { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - pw.format("\n%-15s %-12s %-9s %-32s %-12s %-23s %s\n", - "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result"); - pw.format("%-15s %-12s %-9s %-32s %-12s %-23s %s\n", - "---------", "--------", "---------", "----", "--------", "----", "------"); - return sw.toString(); - } - - protected abstract String directionToString(); - - protected abstract String fateToString(); - - private static String frameTypeToString(byte frameType) { - switch (frameType) { - case WifiLoggerHal.FRAME_TYPE_UNKNOWN: - return "unknown"; - case WifiLoggerHal.FRAME_TYPE_ETHERNET_II: - return "data"; - case WifiLoggerHal.FRAME_TYPE_80211_MGMT: - return "802.11 management"; - default: - return Byte.toString(frameType); - } - } - - /** - * Converts a driver timestamp to a wallclock time, based on the current - * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of - * microseconds, with the same base as BOOTTIME. - */ - private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) { - final long wallclockMillisNow = System.currentTimeMillis(); - final long boottimeMillisNow = SystemClock.elapsedRealtime(); - final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC; - - long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC; - if (boottimeTimestampMillis < driverTimestampMillis) { - // The 32-bit microsecond count has wrapped between the time that the driver - // recorded the packet, and the call to this function. Adjust the BOOTTIME - // timestamp, to compensate. - // - // Note that overflow is not a concern here, since the result is less than - // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above, - // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since - // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit - // within a long. - boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC; - } - - final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis; - return wallclockMillisNow - millisSincePacketTimestamp; - } - } - - /** - * Represents the fate information for one outbound packet. - */ - @Immutable - public static final class TxFateReport extends FateReport { - TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { - super(fate, driverTimestampUSec, frameType, frameBytes); - } - - @Override - protected String directionToString() { - return "TX"; - } - - @Override - protected String fateToString() { - switch (mFate) { - case WifiLoggerHal.TX_PKT_FATE_ACKED: - return "acked"; - case WifiLoggerHal.TX_PKT_FATE_SENT: - return "sent"; - case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED: - return "firmware queued"; - case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID: - return "firmware dropped (invalid frame)"; - case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS: - return "firmware dropped (no bufs)"; - case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER: - return "firmware dropped (other)"; - case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED: - return "driver queued"; - case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID: - return "driver dropped (invalid frame)"; - case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS: - return "driver dropped (no bufs)"; - case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER: - return "driver dropped (other)"; - default: - return Byte.toString(mFate); - } - } - } - - /** - * Represents the fate information for one inbound packet. - */ - @Immutable - public static final class RxFateReport extends FateReport { - RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { - super(fate, driverTimestampUSec, frameType, frameBytes); - } - - @Override - protected String directionToString() { - return "RX"; - } - - @Override - protected String fateToString() { - switch (mFate) { - case WifiLoggerHal.RX_PKT_FATE_SUCCESS: - return "success"; - case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED: - return "firmware queued"; - case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER: - return "firmware dropped (filter)"; - case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID: - return "firmware dropped (invalid frame)"; - case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS: - return "firmware dropped (no bufs)"; - case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER: - return "firmware dropped (other)"; - case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED: - return "driver queued"; - case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER: - return "driver dropped (filter)"; - case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID: - return "driver dropped (invalid frame)"; - case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS: - return "driver dropped (no bufs)"; - case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER: - return "driver dropped (other)"; - default: - return Byte.toString(mFate); - } - } - } - - /** - * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started. - * - * @param ifaceName Name of the interface. - * @return true for success, false otherwise. - */ - public boolean startPktFateMonitoring(@NonNull String ifaceName) { - return mWifiVendorHal.startPktFateMonitoring(ifaceName); - } - - /** - * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started. - * - * @param ifaceName Name of the interface. - * @return true for success, false otherwise. - */ - public boolean getTxPktFates(@NonNull String ifaceName, TxFateReport[] reportBufs) { - return mWifiVendorHal.getTxPktFates(ifaceName, reportBufs); - } - - /** - * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started. - * @param ifaceName Name of the interface. - */ - public boolean getRxPktFates(@NonNull String ifaceName, RxFateReport[] reportBufs) { - return mWifiVendorHal.getRxPktFates(ifaceName, reportBufs); - } - - /** - * Get the tx packet counts for the interface. - * - * @param ifaceName Name of the interface. - * @return tx packet counts - */ - public long getTxPackets(@NonNull String ifaceName) { - return TrafficStats.getTxPackets(ifaceName); - } - - /** - * Get the rx packet counts for the interface. - * - * @param ifaceName Name of the interface - * @return rx packet counts - */ - public long getRxPackets(@NonNull String ifaceName) { - return TrafficStats.getRxPackets(ifaceName); - } - - /** - * Start sending the specified keep alive packets periodically. - * - * @param ifaceName Name of the interface. - * @param slot Integer used to identify each request. - * @param dstMac Destination MAC Address - * @param packet Raw packet contents to send. - * @param protocol The ethernet protocol type - * @param period Period to use for sending these packets. - * @return 0 for success, -1 for error - */ - public int startSendingOffloadedPacket(@NonNull String ifaceName, int slot, - byte[] dstMac, byte[] packet, int protocol, int period) { - byte[] srcMac = NativeUtil.macAddressToByteArray(getMacAddress(ifaceName)); - return mWifiVendorHal.startSendingOffloadedPacket( - ifaceName, slot, srcMac, dstMac, packet, protocol, period); - } - - /** - * Stop sending the specified keep alive packets. - * - * @param ifaceName Name of the interface. - * @param slot id - same as startSendingOffloadedPacket call. - * @return 0 for success, -1 for error - */ - public int stopSendingOffloadedPacket(@NonNull String ifaceName, int slot) { - return mWifiVendorHal.stopSendingOffloadedPacket(ifaceName, slot); - } - - public static interface WifiRssiEventHandler { - void onRssiThresholdBreached(byte curRssi); - } - - /** - * Start RSSI monitoring on the currently connected access point. - * - * @param ifaceName Name of the interface. - * @param maxRssi Maximum RSSI threshold. - * @param minRssi Minimum RSSI threshold. - * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi - * @return 0 for success, -1 for failure - */ - public int startRssiMonitoring( - @NonNull String ifaceName, byte maxRssi, byte minRssi, - WifiRssiEventHandler rssiEventHandler) { - return mWifiVendorHal.startRssiMonitoring( - ifaceName, maxRssi, minRssi, rssiEventHandler); - } - - /** - * Stop RSSI monitoring on the currently connected access point. - * - * @param ifaceName Name of the interface. - * @return 0 for success, -1 for failure - */ - public int stopRssiMonitoring(@NonNull String ifaceName) { - return mWifiVendorHal.stopRssiMonitoring(ifaceName); - } - - /** - * Fetch the host wakeup reasons stats from wlan driver. - * - * @return the |WlanWakeReasonAndCounts| object retrieved from the wlan driver. - */ - public WlanWakeReasonAndCounts getWlanWakeReasonCount() { - return mWifiVendorHal.getWlanWakeReasonCount(); - } - - /** - * Enable/Disable Neighbour discovery offload functionality in the firmware. - * - * @param ifaceName Name of the interface. - * @param enabled true to enable, false to disable. - * @return true for success, false otherwise. - */ - public boolean configureNeighborDiscoveryOffload(@NonNull String ifaceName, boolean enabled) { - return mWifiVendorHal.configureNeighborDiscoveryOffload(ifaceName, enabled); - } - - // Firmware roaming control. - - /** - * Class to retrieve firmware roaming capability parameters. - */ - public static class RoamingCapabilities { - public int maxBlacklistSize; - public int maxWhitelistSize; - } - - /** - * Query the firmware roaming capabilities. - * @param ifaceName Name of the interface. - * @return true for success, false otherwise. - */ - public boolean getRoamingCapabilities( - @NonNull String ifaceName, RoamingCapabilities capabilities) { - return mWifiVendorHal.getRoamingCapabilities(ifaceName, capabilities); - } - - /** - * Macros for controlling firmware roaming. - */ - public static final int DISABLE_FIRMWARE_ROAMING = 0; - public static final int ENABLE_FIRMWARE_ROAMING = 1; - - /** - * Indicates success for enableFirmwareRoaming - */ - public static final int SET_FIRMWARE_ROAMING_SUCCESS = 0; - - /** - * Indicates failure for enableFirmwareRoaming - */ - public static final int SET_FIRMWARE_ROAMING_FAILURE = 1; - - /** - * Indicates temporary failure for enableFirmwareRoaming - try again later - */ - public static final int SET_FIRMWARE_ROAMING_BUSY = 2; - - /** - * Enable/disable firmware roaming. - * - * @param ifaceName Name of the interface. - * @return SET_FIRMWARE_ROAMING_SUCCESS, SET_FIRMWARE_ROAMING_FAILURE, - * or SET_FIRMWARE_ROAMING_BUSY - */ - public int enableFirmwareRoaming(@NonNull String ifaceName, int state) { - return mWifiVendorHal.enableFirmwareRoaming(ifaceName, state); - } - - /** - * Class for specifying the roaming configurations. - */ - public static class RoamingConfig { - public ArrayList<String> blacklistBssids; - public ArrayList<String> whitelistSsids; - } - - /** - * Set firmware roaming configurations. - * @param ifaceName Name of the interface. - */ - public boolean configureRoaming(@NonNull String ifaceName, RoamingConfig config) { - return mWifiVendorHal.configureRoaming(ifaceName, config); - } - - /** - * Reset firmware roaming configuration. - * @param ifaceName Name of the interface. - */ - public boolean resetRoamingConfiguration(@NonNull String ifaceName) { - // Pass in an empty RoamingConfig object which translates to zero size - // blacklist and whitelist to reset the firmware roaming configuration. - return mWifiVendorHal.configureRoaming(ifaceName, new RoamingConfig()); - } - - /** - * Select one of the pre-configured transmit power level scenarios or reset it back to normal. - * Primarily used for meeting SAR requirements. - * - * @param sarInfo The collection of inputs used to select the SAR scenario. - * @return true for success; false for failure or if the HAL version does not support this API. - */ - public boolean selectTxPowerScenario(SarInfo sarInfo) { - return mWifiVendorHal.selectTxPowerScenario(sarInfo); - } - - /** - * Set MBO cellular data status - * - * @param ifaceName Name of the interface. - * @param available cellular data status, - * true means cellular data available, false otherwise. - */ - public void setMboCellularDataStatus(@NonNull String ifaceName, boolean available) { - mSupplicantStaIfaceHal.setMboCellularDataStatus(ifaceName, available); - return; - } - - /** - * Query of support of Wi-Fi standard - * - * @param ifaceName name of the interface to check support on - * @param standard the wifi standard to check on - * @return true if the wifi standard is supported on this interface, false otherwise. - */ - public boolean isWifiStandardSupported(@NonNull String ifaceName, - @WifiAnnotations.WifiStandard int standard) { - synchronized (mLock) { - Iface iface = mIfaceMgr.getIface(ifaceName); - if (iface == null || iface.phyCapabilities == null) { - return false; - } - return iface.phyCapabilities.isWifiStandardSupported(standard); - } - } - - /** - * Get the Wiphy capabilities of a device for a given interface - * If the interface is not associated with one, - * it will be read from the device through wificond - * - * @param ifaceName name of the interface - * @return the device capabilities for this interface - */ - public DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String ifaceName) { - synchronized (mLock) { - Iface iface = mIfaceMgr.getIface(ifaceName); - if (iface == null) { - Log.e(TAG, "Failed to get device capabilities, interface not found: " + ifaceName); - return null; - } - if (iface.phyCapabilities == null) { - iface.phyCapabilities = mWifiCondManager.getDeviceWiphyCapabilities(ifaceName); - } - return iface.phyCapabilities; - } - } - - /** - * Set the Wiphy capabilities of a device for a given interface - * - * @param ifaceName name of the interface - * @param capabilities the wiphy capabilities to set for this interface - */ - public void setDeviceWiphyCapabilities(@NonNull String ifaceName, - DeviceWiphyCapabilities capabilities) { - synchronized (mLock) { - Iface iface = mIfaceMgr.getIface(ifaceName); - if (iface == null) { - Log.e(TAG, "Failed to set device capabilities, interface not found: " + ifaceName); - return; - } - iface.phyCapabilities = capabilities; - } - } -} diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java deleted file mode 100644 index d1f9fbb1f..000000000 --- a/service/java/com/android/server/wifi/WifiNetworkFactory.java +++ /dev/null @@ -1,1534 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static com.android.internal.util.Preconditions.checkNotNull; -import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.app.AlarmManager; -import android.app.AppOpsManager; -import android.companion.CompanionDeviceManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.net.MacAddress; -import android.net.NetworkCapabilities; -import android.net.NetworkFactory; -import android.net.NetworkRequest; -import android.net.NetworkSpecifier; -import android.net.wifi.IActionListener; -import android.net.wifi.INetworkRequestMatchCallback; -import android.net.wifi.INetworkRequestUserSelectionCallback; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.SecurityType; -import android.net.wifi.WifiNetworkSpecifier; -import android.net.wifi.WifiScanner; -import android.os.Binder; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.IBinder; -import android.os.Looper; -import android.os.PatternMatcher; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.WorkSource; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.ExternalCallbackTracker; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Network factory to handle trusted wifi network requests. - */ -public class WifiNetworkFactory extends NetworkFactory { - private static final String TAG = "WifiNetworkFactory"; - @VisibleForTesting - private static final int SCORE_FILTER = 60; - @VisibleForTesting - public static final int CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS = 20 * 1000; // 20 seconds - @VisibleForTesting - public static final int PERIODIC_SCAN_INTERVAL_MS = 10 * 1000; // 10 seconds - @VisibleForTesting - public static final int NETWORK_CONNECTION_TIMEOUT_MS = 30 * 1000; // 30 seconds - @VisibleForTesting - public static final int USER_SELECTED_NETWORK_CONNECT_RETRY_MAX = 3; // max of 3 retries. - @VisibleForTesting - public static final String UI_START_INTENT_ACTION = - "com.android.settings.wifi.action.NETWORK_REQUEST"; - @VisibleForTesting - public static final String UI_START_INTENT_CATEGORY = "android.intent.category.DEFAULT"; - @VisibleForTesting - public static final String UI_START_INTENT_EXTRA_APP_NAME = - "com.android.settings.wifi.extra.APP_NAME"; - @VisibleForTesting - public static final String UI_START_INTENT_EXTRA_REQUEST_IS_FOR_SINGLE_NETWORK = - "com.android.settings.wifi.extra.REQUEST_IS_FOR_SINGLE_NETWORK"; - // Capacity limit of approved Access Point per App - @VisibleForTesting - public static final int NUM_OF_ACCESS_POINT_LIMIT_PER_APP = 50; - - private final Context mContext; - private final ActivityManager mActivityManager; - private final AlarmManager mAlarmManager; - private final AppOpsManager mAppOpsManager; - private final Clock mClock; - private final Handler mHandler; - private final WifiInjector mWifiInjector; - private final WifiConnectivityManager mWifiConnectivityManager; - private final WifiConfigManager mWifiConfigManager; - private final WifiConfigStore mWifiConfigStore; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final WifiMetrics mWifiMetrics; - private final WifiScanner.ScanSettings mScanSettings; - private final NetworkFactoryScanListener mScanListener; - private final PeriodicScanAlarmListener mPeriodicScanTimerListener; - private final ConnectionTimeoutAlarmListener mConnectionTimeoutAlarmListener; - private final ExternalCallbackTracker<INetworkRequestMatchCallback> mRegisteredCallbacks; - // Store all user approved access points for apps. - @VisibleForTesting - public final Map<String, LinkedHashSet<AccessPoint>> mUserApprovedAccessPointMap; - private WifiScanner mWifiScanner; - private CompanionDeviceManager mCompanionDeviceManager; - // Temporary approval set by shell commands. - @Nullable private String mApprovedApp = null; - - private int mGenericConnectionReqCount = 0; - // Request that is being actively processed. All new requests start out as an "active" request - // because we're processing it & handling all the user interactions associated with it. Once we - // successfully connect to the network, we transition that request to "connected". - @Nullable private NetworkRequest mActiveSpecificNetworkRequest; - @Nullable private WifiNetworkSpecifier mActiveSpecificNetworkRequestSpecifier; - // Request corresponding to the the network that the device is currently connected to. - @Nullable private NetworkRequest mConnectedSpecificNetworkRequest; - @Nullable private WifiNetworkSpecifier mConnectedSpecificNetworkRequestSpecifier; - @Nullable private WifiConfiguration mUserSelectedNetwork; - private int mUserSelectedNetworkConnectRetryCount; - // Map of bssid to latest scan results for all scan results matching a request. Will be - // - null, if there are no active requests. - // - empty, if there are no matching scan results received for the active request. - @Nullable private Map<String, ScanResult> mActiveMatchedScanResults; - // Verbose logging flag. - private boolean mVerboseLoggingEnabled = false; - private boolean mPeriodicScanTimerSet = false; - private boolean mConnectionTimeoutSet = false; - private boolean mIsPeriodicScanEnabled = false; - private boolean mIsPeriodicScanPaused = false; - // We sent a new connection request and are waiting for connection success. - private boolean mPendingConnectionSuccess = false; - private boolean mWifiEnabled = false; - /** - * Indicates that we have new data to serialize. - */ - private boolean mHasNewDataToSerialize = false; - - /** - * Helper class to store an access point that the user previously approved for a specific app. - * TODO(b/123014687): Move to a common util class. - */ - public static class AccessPoint { - public final String ssid; - public final MacAddress bssid; - public final @SecurityType int networkType; - - AccessPoint(@NonNull String ssid, @NonNull MacAddress bssid, - @SecurityType int networkType) { - this.ssid = ssid; - this.bssid = bssid; - this.networkType = networkType; - } - - @Override - public int hashCode() { - return Objects.hash(ssid, bssid, networkType); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof AccessPoint)) { - return false; - } - AccessPoint other = (AccessPoint) obj; - return TextUtils.equals(this.ssid, other.ssid) - && Objects.equals(this.bssid, other.bssid) - && this.networkType == other.networkType; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("AccessPoint: "); - return sb.append(ssid) - .append(", ") - .append(bssid) - .append(", ") - .append(networkType) - .toString(); - } - } - - // Scan listener for scan requests. - private class NetworkFactoryScanListener implements WifiScanner.ScanListener { - @Override - public void onSuccess() { - // Scan request succeeded, wait for results to report to external clients. - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Scan request succeeded"); - } - } - - @Override - public void onFailure(int reason, String description) { - Log.e(TAG, "Scan failure received. reason: " + reason - + ", description: " + description); - // TODO(b/113878056): Retry scan to workaround any transient scan failures. - scheduleNextPeriodicScan(); - } - - @Override - public void onResults(WifiScanner.ScanData[] scanDatas) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Scan results received"); - } - // For single scans, the array size should always be 1. - if (scanDatas.length != 1) { - Log.wtf(TAG, "Found more than 1 batch of scan results, Ignoring..."); - return; - } - WifiScanner.ScanData scanData = scanDatas[0]; - ScanResult[] scanResults = scanData.getResults(); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Received " + scanResults.length + " scan results"); - } - handleScanResults(scanResults); - if (mActiveMatchedScanResults != null) { - sendNetworkRequestMatchCallbacksForActiveRequest( - mActiveMatchedScanResults.values()); - } - scheduleNextPeriodicScan(); - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - // Ignore for single scans. - } - - @Override - public void onPeriodChanged(int periodInMs) { - // Ignore for single scans. - } - }; - - private class PeriodicScanAlarmListener implements AlarmManager.OnAlarmListener { - @Override - public void onAlarm() { - // Trigger the next scan. - startScan(); - mPeriodicScanTimerSet = false; - } - } - - private class ConnectionTimeoutAlarmListener implements AlarmManager.OnAlarmListener { - @Override - public void onAlarm() { - Log.e(TAG, "Timed-out connecting to network"); - handleNetworkConnectionFailure(mUserSelectedNetwork); - mConnectionTimeoutSet = false; - } - } - - // Callback result from settings UI. - private class NetworkFactoryUserSelectionCallback extends - INetworkRequestUserSelectionCallback.Stub { - private final NetworkRequest mNetworkRequest; - - NetworkFactoryUserSelectionCallback(NetworkRequest networkRequest) { - mNetworkRequest = networkRequest; - } - - @Override - public void select(WifiConfiguration wifiConfiguration) { - mHandler.post(() -> { - if (mActiveSpecificNetworkRequest != mNetworkRequest) { - Log.e(TAG, "Stale callback select received"); - return; - } - handleConnectToNetworkUserSelection(wifiConfiguration); - }); - } - - @Override - public void reject() { - mHandler.post(() -> { - if (mActiveSpecificNetworkRequest != mNetworkRequest) { - Log.e(TAG, "Stale callback reject received"); - return; - } - handleRejectUserSelection(); - }); - } - } - - private final class ConnectActionListener extends IActionListener.Stub { - @Override - public void onSuccess() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Triggered network connection"); - } - } - - @Override - public void onFailure(int reason) { - Log.e(TAG, "Failed to trigger network connection"); - handleNetworkConnectionFailure(mUserSelectedNetwork); - } - } - - /** - * Module to interact with the wifi config store. - */ - private class NetworkRequestDataSource implements NetworkRequestStoreData.DataSource { - @Override - public Map<String, Set<AccessPoint>> toSerialize() { - // Clear the flag after writing to disk. - mHasNewDataToSerialize = false; - return new HashMap<>(mUserApprovedAccessPointMap); - } - - @Override - public void fromDeserialized(Map<String, Set<AccessPoint>> approvedAccessPointMap) { - approvedAccessPointMap.forEach((key, value) -> - mUserApprovedAccessPointMap.put(key, new LinkedHashSet<>(value))); - } - - @Override - public void reset() { - mUserApprovedAccessPointMap.clear(); - } - - @Override - public boolean hasNewDataToSerialize() { - return mHasNewDataToSerialize; - } - } - - public WifiNetworkFactory(Looper looper, Context context, NetworkCapabilities nc, - ActivityManager activityManager, AlarmManager alarmManager, - AppOpsManager appOpsManager, - Clock clock, WifiInjector wifiInjector, - WifiConnectivityManager connectivityManager, - WifiConfigManager configManager, - WifiConfigStore configStore, - WifiPermissionsUtil wifiPermissionsUtil, - WifiMetrics wifiMetrics) { - super(looper, context, TAG, nc); - mContext = context; - mActivityManager = activityManager; - mAlarmManager = alarmManager; - mAppOpsManager = appOpsManager; - mClock = clock; - mHandler = new Handler(looper); - mWifiInjector = wifiInjector; - mWifiConnectivityManager = connectivityManager; - mWifiConfigManager = configManager; - mWifiConfigStore = configStore; - mWifiPermissionsUtil = wifiPermissionsUtil; - mWifiMetrics = wifiMetrics; - // Create the scan settings. - mScanSettings = new WifiScanner.ScanSettings(); - mScanSettings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - mScanSettings.band = WifiScanner.WIFI_BAND_ALL; - mScanSettings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - mScanListener = new NetworkFactoryScanListener(); - mPeriodicScanTimerListener = new PeriodicScanAlarmListener(); - mConnectionTimeoutAlarmListener = new ConnectionTimeoutAlarmListener(); - mRegisteredCallbacks = new ExternalCallbackTracker<INetworkRequestMatchCallback>(mHandler); - mUserApprovedAccessPointMap = new HashMap<>(); - - // register the data store for serializing/deserializing data. - configStore.registerStoreData( - wifiInjector.makeNetworkRequestStoreData(new NetworkRequestDataSource())); - - setScoreFilter(SCORE_FILTER); - } - - private void saveToStore() { - // Set the flag to let WifiConfigStore that we have new data to write. - mHasNewDataToSerialize = true; - if (!mWifiConfigManager.saveToStore(true)) { - Log.w(TAG, "Failed to save to store"); - } - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = (verbose > 0); - } - - /** - * Add a new callback for network request match handling. - */ - public void addCallback(IBinder binder, INetworkRequestMatchCallback callback, - int callbackIdentifier) { - if (mActiveSpecificNetworkRequest == null) { - Log.wtf(TAG, "No valid network request. Ignoring callback registration"); - try { - callback.onAbort(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to invoke network request abort callback " + callback, e); - } - return; - } - if (!mRegisteredCallbacks.add(binder, callback, callbackIdentifier)) { - Log.e(TAG, "Failed to add callback"); - return; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Adding callback. Num callbacks: " + mRegisteredCallbacks.getNumCallbacks()); - } - // Register our user selection callback. - try { - callback.onUserSelectionCallbackRegistration( - new NetworkFactoryUserSelectionCallback(mActiveSpecificNetworkRequest)); - } catch (RemoteException e) { - Log.e(TAG, "Unable to invoke user selection registration callback " + callback, e); - return; - } - - // If we are already in the midst of processing a request, send matching callbacks - // immediately on registering the callback. - if (mActiveMatchedScanResults != null) { - sendNetworkRequestMatchCallbacksForActiveRequest( - mActiveMatchedScanResults.values()); - } - } - - /** - * Remove an existing callback for network request match handling. - */ - public void removeCallback(int callbackIdentifier) { - mRegisteredCallbacks.remove(callbackIdentifier); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Removing callback. Num callbacks: " - + mRegisteredCallbacks.getNumCallbacks()); - } - } - - private boolean canNewRequestOverrideExistingRequest( - NetworkRequest newRequest, NetworkRequest existingRequest) { - if (existingRequest == null) return true; - // Request from app with NETWORK_SETTINGS can override any existing requests. - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(newRequest.getRequestorUid())) { - return true; - } - // Request from fg app can override any existing requests. - if (isRequestFromForegroundApp(newRequest.getRequestorPackageName())) return true; - // Request from fg service can override only if the existing request is not from a fg app. - if (!isRequestFromForegroundApp(existingRequest.getRequestorPackageName())) return true; - Log.e(TAG, "Already processing request from a foreground app " - + existingRequest.getRequestorPackageName() + ". Rejecting request from " - + newRequest.getRequestorPackageName()); - return false; - } - - boolean isRequestWithNetworkSpecifierValid(NetworkRequest networkRequest) { - NetworkSpecifier ns = networkRequest.getNetworkSpecifier(); - // Invalid network specifier. - if (!(ns instanceof WifiNetworkSpecifier)) { - Log.e(TAG, "Invalid network specifier mentioned. Rejecting"); - return false; - } - // Request cannot have internet capability since such a request can never be fulfilled. - // (NetworkAgent for connection with WifiNetworkSpecifier will not have internet capability) - if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { - Log.e(TAG, "Request with wifi network specifier cannot contain " - + "NET_CAPABILITY_INTERNET. Rejecting"); - return false; - } - if (networkRequest.getRequestorUid() == Process.INVALID_UID) { - Log.e(TAG, "Request with wifi network specifier should contain valid uid. Rejecting"); - return false; - } - if (TextUtils.isEmpty(networkRequest.getRequestorPackageName())) { - Log.e(TAG, "Request with wifi network specifier should contain valid package name." - + "Rejecting"); - return false; - } - try { - mAppOpsManager.checkPackage( - networkRequest.getRequestorUid(), networkRequest.getRequestorPackageName()); - } catch (SecurityException e) { - Log.e(TAG, "Invalid uid/package name " + networkRequest.getRequestorUid() + ", " - + networkRequest.getRequestorPackageName() + ". Rejecting", e); - return false; - } - WifiNetworkSpecifier wns = (WifiNetworkSpecifier) ns; - if (!WifiConfigurationUtil.validateNetworkSpecifier(wns)) { - Log.e(TAG, "Invalid network specifier. Rejecting "); - return false; - } - return true; - } - - /** - * Check whether to accept the new network connection request. - * - * All the validation of the incoming request is done in this method. - */ - @Override - public boolean acceptRequest(NetworkRequest networkRequest, int score) { - NetworkSpecifier ns = networkRequest.getNetworkSpecifier(); - if (ns == null) { - // Generic wifi request. Always accept. - } else { - // Invalid request with network specifier. - if (!isRequestWithNetworkSpecifierValid(networkRequest)) { - releaseRequestAsUnfulfillableByAnyFactory(networkRequest); - return false; - } - if (!mWifiEnabled) { - // Will re-evaluate when wifi is turned on. - Log.e(TAG, "Wifi off. Rejecting"); - return false; - } - WifiNetworkSpecifier wns = (WifiNetworkSpecifier) ns; - // Only allow specific wifi network request from foreground app/service. - if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( - networkRequest.getRequestorUid()) - && !isRequestFromForegroundAppOrService( - networkRequest.getRequestorPackageName())) { - Log.e(TAG, "Request not from foreground app or service." - + " Rejecting request from " + networkRequest.getRequestorPackageName()); - releaseRequestAsUnfulfillableByAnyFactory(networkRequest); - return false; - } - // If there is an active request, only proceed if the new request is from a foreground - // app. - if (!canNewRequestOverrideExistingRequest( - networkRequest, mActiveSpecificNetworkRequest)) { - Log.e(TAG, "Request cannot override active request." - + " Rejecting request from " + networkRequest.getRequestorPackageName()); - releaseRequestAsUnfulfillableByAnyFactory(networkRequest); - return false; - } - // If there is a connected request, only proceed if the new request is from a foreground - // app. - if (!canNewRequestOverrideExistingRequest( - networkRequest, mConnectedSpecificNetworkRequest)) { - Log.e(TAG, "Request cannot override connected request." - + " Rejecting request from " + networkRequest.getRequestorPackageName()); - releaseRequestAsUnfulfillableByAnyFactory(networkRequest); - return false; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Accepted network request with specifier from fg " - + (isRequestFromForegroundApp(networkRequest.getRequestorPackageName()) - ? "app" : "service")); - } - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Accepted network request " + networkRequest); - } - return true; - } - - /** - * Handle new network connection requests. - * - * The assumption here is that {@link #acceptRequest(NetworkRequest, int)} has already sanitized - * the incoming request. - */ - @Override - protected void needNetworkFor(NetworkRequest networkRequest, int score) { - NetworkSpecifier ns = networkRequest.getNetworkSpecifier(); - if (ns == null) { - // Generic wifi request. Turn on auto-join if necessary. - if (++mGenericConnectionReqCount == 1) { - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - } - } else { - // Invalid request with network specifier. - if (!isRequestWithNetworkSpecifierValid(networkRequest)) { - releaseRequestAsUnfulfillableByAnyFactory(networkRequest); - return; - } - if (!mWifiEnabled) { - // Will re-evaluate when wifi is turned on. - Log.e(TAG, "Wifi off. Rejecting"); - return; - } - retrieveWifiScanner(); - // Reset state from any previous request. - setupForActiveRequest(); - - // Store the active network request. - mActiveSpecificNetworkRequest = networkRequest; - WifiNetworkSpecifier wns = (WifiNetworkSpecifier) ns; - mActiveSpecificNetworkRequestSpecifier = new WifiNetworkSpecifier( - wns.ssidPatternMatcher, wns.bssidPatternMatcher, wns.wifiConfiguration); - mWifiMetrics.incrementNetworkRequestApiNumRequest(); - - if (!triggerConnectIfUserApprovedMatchFound()) { - // Start UI to let the user grant/disallow this request from the app. - startUi(); - // Didn't find an approved match, send the matching results to UI and trigger - // periodic scans for finding a network in the request. - // Fetch the latest cached scan results to speed up network matching. - ScanResult[] cachedScanResults = getFilteredCachedScanResults(); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Using cached " + cachedScanResults.length + " scan results"); - } - handleScanResults(cachedScanResults); - if (mActiveMatchedScanResults != null) { - sendNetworkRequestMatchCallbacksForActiveRequest( - mActiveMatchedScanResults.values()); - } - startPeriodicScans(); - } - } - } - - @Override - protected void releaseNetworkFor(NetworkRequest networkRequest) { - NetworkSpecifier ns = networkRequest.getNetworkSpecifier(); - if (ns == null) { - // Generic wifi request. Turn off auto-join if necessary. - if (mGenericConnectionReqCount == 0) { - Log.e(TAG, "No valid network request to release"); - return; - } - if (--mGenericConnectionReqCount == 0) { - mWifiConnectivityManager.setTrustedConnectionAllowed(false); - } - } else { - // Invalid network specifier. - if (!(ns instanceof WifiNetworkSpecifier)) { - Log.e(TAG, "Invalid network specifier mentioned. Ignoring"); - return; - } - if (!mWifiEnabled) { - Log.e(TAG, "Wifi off. Ignoring"); - return; - } - if (mActiveSpecificNetworkRequest == null && mConnectedSpecificNetworkRequest == null) { - Log.e(TAG, "Network release received with no active/connected request." - + " Ignoring"); - return; - } - if (Objects.equals(mActiveSpecificNetworkRequest, networkRequest)) { - Log.i(TAG, "App released active request, cancelling " - + mActiveSpecificNetworkRequest); - teardownForActiveRequest(); - } else if (Objects.equals(mConnectedSpecificNetworkRequest, networkRequest)) { - Log.i(TAG, "App released connected request, cancelling " - + mConnectedSpecificNetworkRequest); - teardownForConnectedNetwork(); - } else { - Log.e(TAG, "Network specifier does not match the active/connected request." - + " Ignoring"); - } - } - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - super.dump(fd, pw, args); - pw.println(TAG + ": mGenericConnectionReqCount " + mGenericConnectionReqCount); - pw.println(TAG + ": mActiveSpecificNetworkRequest " + mActiveSpecificNetworkRequest); - pw.println(TAG + ": mUserApprovedAccessPointMap " + mUserApprovedAccessPointMap); - } - - /** - * Check if there is at least one connection request. - */ - public boolean hasConnectionRequests() { - return mGenericConnectionReqCount > 0 || mActiveSpecificNetworkRequest != null - || mConnectedSpecificNetworkRequest != null; - } - - /** - * Return the uid of the specific network request being processed if connected to the requested - * network. - * - * @param connectedNetwork WifiConfiguration corresponding to the connected network. - * @return Pair of uid & package name of the specific request (if any), else <-1, "">. - */ - public Pair<Integer, String> getSpecificNetworkRequestUidAndPackageName( - @NonNull WifiConfiguration connectedNetwork) { - if (mUserSelectedNetwork == null || connectedNetwork == null) { - return Pair.create(Process.INVALID_UID, ""); - } - if (!isUserSelectedNetwork(connectedNetwork)) { - Log.w(TAG, "Connected to unknown network " + connectedNetwork + ". Ignoring..."); - return Pair.create(Process.INVALID_UID, ""); - } - if (mConnectedSpecificNetworkRequestSpecifier != null) { - return Pair.create(mConnectedSpecificNetworkRequest.getRequestorUid(), - mConnectedSpecificNetworkRequest.getRequestorPackageName()); - } - if (mActiveSpecificNetworkRequestSpecifier != null) { - return Pair.create(mActiveSpecificNetworkRequest.getRequestorUid(), - mActiveSpecificNetworkRequest.getRequestorPackageName()); - } - return Pair.create(Process.INVALID_UID, ""); - } - - // Helper method to add the provided network configuration to WifiConfigManager, if it does not - // already exist & return the allocated network ID. This ID will be used in the CONNECT_NETWORK - // request to ClientModeImpl. - // If the network already exists, just return the network ID of the existing network. - private int addNetworkToWifiConfigManager(@NonNull WifiConfiguration network) { - WifiConfiguration existingSavedNetwork = - mWifiConfigManager.getConfiguredNetwork(network.getKey()); - if (existingSavedNetwork != null) { - if (WifiConfigurationUtil.hasCredentialChanged(existingSavedNetwork, network)) { - // TODO (b/142035508): What if the user has a saved network with different - // credentials? - Log.w(TAG, "Network config already present in config manager, reusing"); - } - return existingSavedNetwork.networkId; - } - NetworkUpdateResult networkUpdateResult = - mWifiConfigManager.addOrUpdateNetwork( - network, mActiveSpecificNetworkRequest.getRequestorUid(), - mActiveSpecificNetworkRequest.getRequestorPackageName()); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Added network to config manager " + networkUpdateResult.netId); - } - return networkUpdateResult.netId; - } - - // Helper method to remove the provided network configuration from WifiConfigManager, if it was - // added by an app's specifier request. - private void disconnectAndRemoveNetworkFromWifiConfigManager( - @Nullable WifiConfiguration network) { - // Trigger a disconnect first. - mWifiInjector.getClientModeImpl().disconnectCommand(); - - if (network == null) return; - WifiConfiguration wcmNetwork = - mWifiConfigManager.getConfiguredNetwork(network.getKey()); - if (wcmNetwork == null) { - Log.e(TAG, "Network not present in config manager"); - return; - } - // Remove the network if it was added previously by an app's specifier request. - if (wcmNetwork.ephemeral && wcmNetwork.fromWifiNetworkSpecifier) { - boolean success = - mWifiConfigManager.removeNetwork( - wcmNetwork.networkId, wcmNetwork.creatorUid, wcmNetwork.creatorName); - if (!success) { - Log.e(TAG, "Failed to remove network from config manager"); - } else if (mVerboseLoggingEnabled) { - Log.v(TAG, "Removed network from config manager " + wcmNetwork.networkId); - } - } - } - - // Helper method to trigger a connection request & schedule a timeout alarm to track the - // connection request. - private void connectToNetwork(@NonNull WifiConfiguration network) { - // Cancel connection timeout alarm for any previous connection attempts. - cancelConnectionTimeout(); - - // First add the network to WifiConfigManager and then use the obtained networkId - // in the CONNECT_NETWORK request. - // Note: We don't do any error checks on the networkId because ClientModeImpl will do the - // necessary checks when processing CONNECT_NETWORK. - int networkId = addNetworkToWifiConfigManager(network); - - mWifiMetrics.setNominatorForNetwork(networkId, - WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER); - - // Send the connect request to ClientModeImpl. - // TODO(b/117601161): Refactor this. - ConnectActionListener connectActionListener = new ConnectActionListener(); - mWifiInjector.getClientModeImpl().connect(null, networkId, new Binder(), - connectActionListener, connectActionListener.hashCode(), - mActiveSpecificNetworkRequest.getRequestorUid()); - - // Post an alarm to handle connection timeout. - scheduleConnectionTimeout(); - } - - private void handleConnectToNetworkUserSelectionInternal(WifiConfiguration network) { - // Disable Auto-join so that NetworkFactory can take control of the network connection. - mWifiConnectivityManager.setSpecificNetworkRequestInProgress(true); - - // Copy over the credentials from the app's request and then copy the ssid from user - // selection. - WifiConfiguration networkToConnect = - new WifiConfiguration(mActiveSpecificNetworkRequestSpecifier.wifiConfiguration); - networkToConnect.SSID = network.SSID; - // Set the WifiConfiguration.BSSID field to prevent roaming. - if (network.BSSID != null) { - // If pre-approved, use the bssid from the request. - networkToConnect.BSSID = network.BSSID; - } else { - // If not pre-approved, find the best bssid matching the request. - networkToConnect.BSSID = - findBestBssidFromActiveMatchedScanResultsForNetwork( - ScanResultMatchInfo.fromWifiConfiguration(networkToConnect)); - } - networkToConnect.ephemeral = true; - // Mark it user private to avoid conflicting with any saved networks the user might have. - // TODO (b/142035508): Use a more generic mechanism to fix this. - networkToConnect.shared = false; - networkToConnect.fromWifiNetworkSpecifier = true; - - // Store the user selected network. - mUserSelectedNetwork = networkToConnect; - - // Disconnect from the current network before issuing a new connect request. - disconnectAndRemoveNetworkFromWifiConfigManager(mUserSelectedNetwork); - - // Trigger connection to the network. - connectToNetwork(networkToConnect); - // Triggered connection to network, now wait for the connection status. - mPendingConnectionSuccess = true; - } - - private void handleConnectToNetworkUserSelection(WifiConfiguration network) { - Log.d(TAG, "User initiated connect to network: " + network.SSID); - - // Cancel the ongoing scans after user selection. - cancelPeriodicScans(); - mIsPeriodicScanEnabled = false; - - // Trigger connection attempts. - handleConnectToNetworkUserSelectionInternal(network); - - // Add the network to the approved access point map for the app. - addNetworkToUserApprovedAccessPointMap(mUserSelectedNetwork); - } - - private void handleRejectUserSelection() { - Log.w(TAG, "User dismissed notification, cancelling " + mActiveSpecificNetworkRequest); - teardownForActiveRequest(); - mWifiMetrics.incrementNetworkRequestApiNumUserReject(); - } - - private boolean isUserSelectedNetwork(WifiConfiguration config) { - if (!TextUtils.equals(mUserSelectedNetwork.SSID, config.SSID)) { - return false; - } - if (!Objects.equals( - mUserSelectedNetwork.allowedKeyManagement, config.allowedKeyManagement)) { - return false; - } - return true; - } - - /** - * Invoked by {@link ClientModeImpl} on end of connection attempt to a network. - */ - public void handleConnectionAttemptEnded( - int failureCode, @NonNull WifiConfiguration network) { - if (failureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) { - handleNetworkConnectionSuccess(network); - } else { - handleNetworkConnectionFailure(network); - } - } - - /** - * Invoked by {@link ClientModeImpl} on successful connection to a network. - */ - private void handleNetworkConnectionSuccess(@NonNull WifiConfiguration connectedNetwork) { - if (mUserSelectedNetwork == null || connectedNetwork == null - || !mPendingConnectionSuccess) { - return; - } - if (!isUserSelectedNetwork(connectedNetwork)) { - Log.w(TAG, "Connected to unknown network " + connectedNetwork + ". Ignoring..."); - return; - } - Log.d(TAG, "Connected to network " + mUserSelectedNetwork); - for (INetworkRequestMatchCallback callback : mRegisteredCallbacks.getCallbacks()) { - try { - callback.onUserSelectionConnectSuccess(mUserSelectedNetwork); - } catch (RemoteException e) { - Log.e(TAG, "Unable to invoke network request connect failure callback " - + callback, e); - } - } - // transition the request from "active" to "connected". - setupForConnectedRequest(); - mWifiMetrics.incrementNetworkRequestApiNumConnectSuccess(); - } - - /** - * Invoked by {@link ClientModeImpl} on failure to connect to a network. - */ - private void handleNetworkConnectionFailure(@NonNull WifiConfiguration failedNetwork) { - if (mUserSelectedNetwork == null || failedNetwork == null || !mPendingConnectionSuccess) { - return; - } - if (!isUserSelectedNetwork(failedNetwork)) { - Log.w(TAG, "Connection failed to unknown network " + failedNetwork + ". Ignoring..."); - return; - } - Log.w(TAG, "Failed to connect to network " + mUserSelectedNetwork); - if (mUserSelectedNetworkConnectRetryCount++ < USER_SELECTED_NETWORK_CONNECT_RETRY_MAX) { - Log.i(TAG, "Retrying connection attempt, attempt# " - + mUserSelectedNetworkConnectRetryCount); - connectToNetwork(mUserSelectedNetwork); - return; - } - Log.e(TAG, "Connection failures, cancelling " + mUserSelectedNetwork); - for (INetworkRequestMatchCallback callback : mRegisteredCallbacks.getCallbacks()) { - try { - callback.onUserSelectionConnectFailure(mUserSelectedNetwork); - } catch (RemoteException e) { - Log.e(TAG, "Unable to invoke network request connect failure callback " - + callback, e); - } - } - teardownForActiveRequest(); - } - - /** - * Invoked by {@link ClientModeImpl} to indicate screen state changes. - */ - public void handleScreenStateChanged(boolean screenOn) { - // If there is no active request or if the user has already selected a network, - // ignore screen state changes. - if (mActiveSpecificNetworkRequest == null || !mIsPeriodicScanEnabled) return; - - // Pause periodic scans when the screen is off & resume when the screen is on. - if (screenOn) { - if (mVerboseLoggingEnabled) Log.v(TAG, "Resuming scans on screen on"); - mIsPeriodicScanPaused = false; - startScan(); - } else { - if (mVerboseLoggingEnabled) Log.v(TAG, "Pausing scans on screen off"); - cancelPeriodicScans(); - mIsPeriodicScanPaused = true; - } - } - - /** - * Invoked by {@link ClientModeImpl} to indicate wifi state toggle. - */ - public void setWifiState(boolean enabled) { - if (mVerboseLoggingEnabled) Log.v(TAG, "setWifiState " + enabled); - if (enabled) { - reevaluateAllRequests(); // Re-evaluate any pending requests. - } else { - if (mActiveSpecificNetworkRequest != null) { - Log.w(TAG, "Wifi off, cancelling " + mActiveSpecificNetworkRequest); - teardownForActiveRequest(); - } - if (mConnectedSpecificNetworkRequest != null) { - Log.w(TAG, "Wifi off, cancelling " + mConnectedSpecificNetworkRequest); - teardownForConnectedNetwork(); - } - } - mWifiEnabled = enabled; - } - - // Common helper method for start/end of active request processing. - private void cleanupActiveRequest() { - // Send the abort to the UI for the current active request. - for (INetworkRequestMatchCallback callback : mRegisteredCallbacks.getCallbacks()) { - try { - callback.onAbort(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to invoke network request abort callback " + callback, e); - } - } - // Force-release the network request to let the app know early that the attempt failed. - if (mActiveSpecificNetworkRequest != null) { - releaseRequestAsUnfulfillableByAnyFactory(mActiveSpecificNetworkRequest); - } - // Reset the active network request. - mActiveSpecificNetworkRequest = null; - mActiveSpecificNetworkRequestSpecifier = null; - mUserSelectedNetwork = null; - mUserSelectedNetworkConnectRetryCount = 0; - mIsPeriodicScanEnabled = false; - mIsPeriodicScanPaused = false; - mActiveMatchedScanResults = null; - mPendingConnectionSuccess = false; - // Cancel periodic scan, connection timeout alarm. - cancelPeriodicScans(); - cancelConnectionTimeout(); - // Remove any callbacks registered for the request. - mRegisteredCallbacks.clear(); - } - - // Invoked at the start of new active request processing. - private void setupForActiveRequest() { - if (mActiveSpecificNetworkRequest != null) { - cleanupActiveRequest(); - } - } - - // Invoked at the termination of current active request processing. - private void teardownForActiveRequest() { - if (mPendingConnectionSuccess) { - Log.i(TAG, "Disconnecting from network on reset"); - disconnectAndRemoveNetworkFromWifiConfigManager(mUserSelectedNetwork); - } - cleanupActiveRequest(); - // ensure there is no connected request in progress. - if (mConnectedSpecificNetworkRequest == null) { - mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false); - } - } - - // Invoked at the start of new connected request processing. - private void setupForConnectedRequest() { - mConnectedSpecificNetworkRequest = mActiveSpecificNetworkRequest; - mConnectedSpecificNetworkRequestSpecifier = mActiveSpecificNetworkRequestSpecifier; - mActiveSpecificNetworkRequest = null; - mActiveSpecificNetworkRequestSpecifier = null; - mActiveMatchedScanResults = null; - mPendingConnectionSuccess = false; - // Cancel connection timeout alarm. - cancelConnectionTimeout(); - } - - // Invoked at the termination of current connected request processing. - private void teardownForConnectedNetwork() { - Log.i(TAG, "Disconnecting from network on reset"); - disconnectAndRemoveNetworkFromWifiConfigManager(mUserSelectedNetwork); - mConnectedSpecificNetworkRequest = null; - mConnectedSpecificNetworkRequestSpecifier = null; - // ensure there is no active request in progress. - if (mActiveSpecificNetworkRequest == null) { - mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false); - } - } - - /** - * Check if the request comes from foreground app/service. - */ - private boolean isRequestFromForegroundAppOrService(@NonNull String requestorPackageName) { - try { - return mActivityManager.getPackageImportance(requestorPackageName) - <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; - } catch (SecurityException e) { - Log.e(TAG, "Failed to check the app state", e); - return false; - } - } - - /** - * Check if the request comes from foreground app. - */ - private boolean isRequestFromForegroundApp(@NonNull String requestorPackageName) { - try { - return mActivityManager.getPackageImportance(requestorPackageName) - <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; - } catch (SecurityException e) { - Log.e(TAG, "Failed to check the app state", e); - return false; - } - } - - /** - * Helper method to populate WifiScanner handle. This is done lazily because - * WifiScanningService is started after WifiService. - */ - private void retrieveWifiScanner() { - if (mWifiScanner != null) return; - mWifiScanner = mWifiInjector.getWifiScanner(); - checkNotNull(mWifiScanner); - } - - private void startPeriodicScans() { - if (mActiveSpecificNetworkRequestSpecifier == null) { - Log.e(TAG, "Periodic scan triggered when there is no active network request. " - + "Ignoring..."); - return; - } - WifiNetworkSpecifier wns = mActiveSpecificNetworkRequestSpecifier; - WifiConfiguration wifiConfiguration = wns.wifiConfiguration; - if (wifiConfiguration.hiddenSSID) { - // Can't search for SSID pattern in hidden networks. - mScanSettings.hiddenNetworks.clear(); - mScanSettings.hiddenNetworks.add(new WifiScanner.ScanSettings.HiddenNetwork( - addEnclosingQuotes(wns.ssidPatternMatcher.getPath()))); - } - mIsPeriodicScanEnabled = true; - startScan(); - } - - private void cancelPeriodicScans() { - if (mPeriodicScanTimerSet) { - mAlarmManager.cancel(mPeriodicScanTimerListener); - mPeriodicScanTimerSet = false; - } - // Clear the hidden networks field after each request. - mScanSettings.hiddenNetworks.clear(); - } - - private void scheduleNextPeriodicScan() { - if (mIsPeriodicScanPaused) { - Log.e(TAG, "Scan triggered when periodic scanning paused. Ignoring..."); - return; - } - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + PERIODIC_SCAN_INTERVAL_MS, - TAG, mPeriodicScanTimerListener, mHandler); - mPeriodicScanTimerSet = true; - } - - private void startScan() { - if (mActiveSpecificNetworkRequestSpecifier == null) { - Log.e(TAG, "Scan triggered when there is no active network request. Ignoring..."); - return; - } - if (!mIsPeriodicScanEnabled) { - Log.e(TAG, "Scan triggered after user selected network. Ignoring..."); - return; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Starting the next scan for " + mActiveSpecificNetworkRequestSpecifier); - } - // Create a worksource using the caller's UID. - WorkSource workSource = new WorkSource(mActiveSpecificNetworkRequest.getRequestorUid()); - mWifiScanner.startScan( - mScanSettings, new HandlerExecutor(mHandler), mScanListener, workSource); - } - - private boolean doesScanResultMatchWifiNetworkSpecifier( - WifiNetworkSpecifier wns, ScanResult scanResult) { - if (!wns.ssidPatternMatcher.match(scanResult.SSID)) { - return false; - } - MacAddress bssid = MacAddress.fromString(scanResult.BSSID); - MacAddress matchBaseAddress = wns.bssidPatternMatcher.first; - MacAddress matchMask = wns.bssidPatternMatcher.second; - if (!bssid.matches(matchBaseAddress, matchMask)) { - return false; - } - ScanResultMatchInfo fromScanResult = ScanResultMatchInfo.fromScanResult(scanResult); - ScanResultMatchInfo fromWifiConfiguration = - ScanResultMatchInfo.fromWifiConfiguration(wns.wifiConfiguration); - return fromScanResult.networkTypeEquals(fromWifiConfiguration, false); - } - - // Loops through the scan results and finds scan results matching the active network - // request. - private List<ScanResult> getNetworksMatchingActiveNetworkRequest( - ScanResult[] scanResults) { - if (mActiveSpecificNetworkRequestSpecifier == null) { - Log.e(TAG, "Scan results received with no active network request. Ignoring..."); - return new ArrayList<>(); - } - List<ScanResult> matchedScanResults = new ArrayList<>(); - WifiNetworkSpecifier wns = mActiveSpecificNetworkRequestSpecifier; - - for (ScanResult scanResult : scanResults) { - if (doesScanResultMatchWifiNetworkSpecifier(wns, scanResult)) { - matchedScanResults.add(scanResult); - } - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "List of scan results matching the active request " - + matchedScanResults); - } - return matchedScanResults; - } - - private void sendNetworkRequestMatchCallbacksForActiveRequest( - @NonNull Collection<ScanResult> matchedScanResults) { - if (matchedScanResults.isEmpty()) return; - if (mRegisteredCallbacks.getNumCallbacks() == 0) { - Log.e(TAG, "No callback registered for sending network request matches. " - + "Ignoring..."); - return; - } - for (INetworkRequestMatchCallback callback : mRegisteredCallbacks.getCallbacks()) { - try { - callback.onMatch(new ArrayList<>(matchedScanResults)); - } catch (RemoteException e) { - Log.e(TAG, "Unable to invoke network request match callback " + callback, e); - } - } - } - - private void cancelConnectionTimeout() { - if (mConnectionTimeoutSet) { - mAlarmManager.cancel(mConnectionTimeoutAlarmListener); - mConnectionTimeoutSet = false; - } - } - - private void scheduleConnectionTimeout() { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + NETWORK_CONNECTION_TIMEOUT_MS, - TAG, mConnectionTimeoutAlarmListener, mHandler); - mConnectionTimeoutSet = true; - } - - private @NonNull CharSequence getAppName(@NonNull String packageName, int uid) { - ApplicationInfo applicationInfo = null; - try { - applicationInfo = mContext.getPackageManager().getApplicationInfoAsUser( - packageName, 0, UserHandle.getUserHandleForUid(uid)); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Failed to find app name for " + packageName); - return ""; - } - CharSequence appName = mContext.getPackageManager().getApplicationLabel(applicationInfo); - return (appName != null) ? appName : ""; - } - - private void startUi() { - Intent intent = new Intent(); - intent.setAction(UI_START_INTENT_ACTION); - intent.addCategory(UI_START_INTENT_CATEGORY); - intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(UI_START_INTENT_EXTRA_APP_NAME, - getAppName(mActiveSpecificNetworkRequest.getRequestorPackageName(), - mActiveSpecificNetworkRequest.getRequestorUid())); - intent.putExtra(UI_START_INTENT_EXTRA_REQUEST_IS_FOR_SINGLE_NETWORK, - isActiveRequestForSingleNetwork()); - mContext.startActivityAsUser(intent, UserHandle.getUserHandleForUid( - mActiveSpecificNetworkRequest.getRequestorUid())); - } - - // Helper method to determine if the specifier does not contain any patterns and matches - // a single access point. - private boolean isActiveRequestForSingleAccessPoint() { - if (mActiveSpecificNetworkRequestSpecifier == null) return false; - - if (mActiveSpecificNetworkRequestSpecifier.ssidPatternMatcher.getType() - != PatternMatcher.PATTERN_LITERAL) { - return false; - } - if (!Objects.equals( - mActiveSpecificNetworkRequestSpecifier.bssidPatternMatcher.second, - MacAddress.BROADCAST_ADDRESS)) { - return false; - } - return true; - } - - // Helper method to determine if the specifier does not contain any patterns and matches - // a single network. - private boolean isActiveRequestForSingleNetwork() { - if (mActiveSpecificNetworkRequestSpecifier == null) return false; - - if (mActiveSpecificNetworkRequestSpecifier.ssidPatternMatcher.getType() - == PatternMatcher.PATTERN_LITERAL) { - return true; - } - if (Objects.equals( - mActiveSpecificNetworkRequestSpecifier.bssidPatternMatcher.second, - MacAddress.BROADCAST_ADDRESS)) { - return true; - } - return false; - } - - // Will return the best bssid to use for the current request's connection. - // - // Note: This will never return null, unless there is some internal error. - // For ex: - // i) The latest scan results were empty. - // ii) The latest scan result did not contain any BSSID for the SSID user chose. - private @Nullable String findBestBssidFromActiveMatchedScanResultsForNetwork( - @NonNull ScanResultMatchInfo scanResultMatchInfo) { - if (mActiveSpecificNetworkRequestSpecifier == null - || mActiveMatchedScanResults == null) return null; - ScanResult selectedScanResult = mActiveMatchedScanResults - .values() - .stream() - .filter(scanResult -> Objects.equals( - ScanResultMatchInfo.fromScanResult(scanResult), - scanResultMatchInfo)) - .max(Comparator.comparing(scanResult -> scanResult.level)) - .orElse(null); - if (selectedScanResult == null) { // Should never happen. - Log.wtf(TAG, "Expected to find at least one matching scan result"); - return null; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Best bssid selected for the request " + selectedScanResult); - } - return selectedScanResult.BSSID; - } - - private boolean isAccessPointApprovedInInternalApprovalList( - @NonNull String ssid, @NonNull MacAddress bssid, @SecurityType int networkType, - @NonNull String requestorPackageName) { - Set<AccessPoint> approvedAccessPoints = - mUserApprovedAccessPointMap.get(requestorPackageName); - if (approvedAccessPoints == null) return false; - AccessPoint accessPoint = - new AccessPoint(ssid, bssid, networkType); - if (!approvedAccessPoints.contains(accessPoint)) return false; - // keep the most recently used AP in the end - approvedAccessPoints.remove(accessPoint); - approvedAccessPoints.add(accessPoint); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Found " + bssid - + " in internal user approved access point for " + requestorPackageName); - } - return true; - } - - private boolean isAccessPointApprovedInCompanionDeviceManager( - @NonNull MacAddress bssid, - @NonNull UserHandle requestorUserHandle, - @NonNull String requestorPackageName) { - if (mCompanionDeviceManager == null) { - mCompanionDeviceManager = mContext.getSystemService(CompanionDeviceManager.class); - } - boolean approved = mCompanionDeviceManager.isDeviceAssociatedForWifiConnection( - requestorPackageName, bssid, requestorUserHandle); - if (!approved) return false; - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Found " + bssid - + " in CompanionDeviceManager approved access point for " - + requestorPackageName); - } - return true; - } - - private boolean isAccessPointApprovedForActiveRequest(@NonNull String ssid, - @NonNull MacAddress bssid, @SecurityType int networkType) { - String requestorPackageName = mActiveSpecificNetworkRequest.getRequestorPackageName(); - UserHandle requestorUserHandle = - UserHandle.getUserHandleForUid(mActiveSpecificNetworkRequest.getRequestorUid()); - // Check if access point is approved via CompanionDeviceManager first. - if (isAccessPointApprovedInCompanionDeviceManager( - bssid, requestorUserHandle, requestorPackageName)) { - return true; - } - // Check if access point is approved in internal approval list next. - if (isAccessPointApprovedInInternalApprovalList( - ssid, bssid, networkType, requestorPackageName)) { - return true; - } - // Shell approved app - if (TextUtils.equals(mApprovedApp, requestorPackageName)) { - return true; - } - // no bypass approvals, show UI. - return false; - } - - - // Helper method to store the all the BSSIDs matching the network from the matched scan results - private void addNetworkToUserApprovedAccessPointMap(@NonNull WifiConfiguration network) { - if (mActiveSpecificNetworkRequestSpecifier == null - || mActiveMatchedScanResults == null) return; - // Note: This hopefully is a list of size 1, because we want to store a 1:1 mapping - // from user selection and the AP that was approved. But, since we get a WifiConfiguration - // object representing an entire network from UI, we need to ensure that all the visible - // BSSIDs matching the original request and the selected network are stored. - Set<AccessPoint> newUserApprovedAccessPoints = new HashSet<>(); - - ScanResultMatchInfo fromWifiConfiguration = - ScanResultMatchInfo.fromWifiConfiguration(network); - for (ScanResult scanResult : mActiveMatchedScanResults.values()) { - ScanResultMatchInfo fromScanResult = ScanResultMatchInfo.fromScanResult(scanResult); - if (fromScanResult.equals(fromWifiConfiguration)) { - AccessPoint approvedAccessPoint = - new AccessPoint(scanResult.SSID, MacAddress.fromString(scanResult.BSSID), - fromScanResult.networkType); - newUserApprovedAccessPoints.add(approvedAccessPoint); - } - } - if (newUserApprovedAccessPoints.isEmpty()) return; - - String requestorPackageName = mActiveSpecificNetworkRequest.getRequestorPackageName(); - LinkedHashSet<AccessPoint> approvedAccessPoints = - mUserApprovedAccessPointMap.get(requestorPackageName); - if (approvedAccessPoints == null) { - approvedAccessPoints = new LinkedHashSet<>(); - mUserApprovedAccessPointMap.put(requestorPackageName, approvedAccessPoints); - // Note the new app in metrics. - mWifiMetrics.incrementNetworkRequestApiNumApps(); - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Adding " + newUserApprovedAccessPoints - + " to user approved access point for " + requestorPackageName); - } - // keep the most recently added APs in the end - approvedAccessPoints.removeAll(newUserApprovedAccessPoints); - approvedAccessPoints.addAll(newUserApprovedAccessPoints); - cleanUpLRUAccessPoints(approvedAccessPoints); - saveToStore(); - } - - /** - * 1) If the request is for a single bssid, check if the matching ScanResult was pre-approved - * by the user. - * 2) If yes to (b), trigger a connect immediately and returns true. Else, returns false. - * - * @return true if a pre-approved network was found for connection, false otherwise. - */ - private boolean triggerConnectIfUserApprovedMatchFound() { - if (mActiveSpecificNetworkRequestSpecifier == null) return false; - if (!isActiveRequestForSingleAccessPoint()) return false; - String ssid = mActiveSpecificNetworkRequestSpecifier.ssidPatternMatcher.getPath(); - MacAddress bssid = mActiveSpecificNetworkRequestSpecifier.bssidPatternMatcher.first; - int networkType = - ScanResultMatchInfo.fromWifiConfiguration( - mActiveSpecificNetworkRequestSpecifier.wifiConfiguration).networkType; - if (!isAccessPointApprovedForActiveRequest(ssid, bssid, networkType) - || mWifiConfigManager.isNetworkTemporarilyDisabledByUser( - ScanResultUtil.createQuotedSSID(ssid))) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "No approved access point found"); - } - return false; - } - Log.v(TAG, "Approved access point found in matching scan results. " - + "Triggering connect " + ssid + "/" + bssid); - WifiConfiguration config = mActiveSpecificNetworkRequestSpecifier.wifiConfiguration; - config.SSID = "\"" + ssid + "\""; - config.BSSID = bssid.toString(); - handleConnectToNetworkUserSelectionInternal(config); - mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass(); - return true; - } - - /** - * Handle scan results - * - * @param scanResults Array of {@link ScanResult} to be processed. - */ - private void handleScanResults(ScanResult[] scanResults) { - List<ScanResult> matchedScanResults = - getNetworksMatchingActiveNetworkRequest(scanResults); - if ((mActiveMatchedScanResults == null || mActiveMatchedScanResults.isEmpty()) - && !matchedScanResults.isEmpty()) { - // only note the first match size in metrics (chances of this changing in further - // scans is pretty low) - mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResults.size()); - } - // First set of scan results for this request. - if (mActiveMatchedScanResults == null) mActiveMatchedScanResults = new HashMap<>(); - // Coalesce the new set of scan results with previous scan results received for request. - mActiveMatchedScanResults.putAll(matchedScanResults - .stream() - .collect(Collectors.toMap( - scanResult -> scanResult.BSSID, scanResult -> scanResult))); - // Weed out any stale cached scan results. - long currentTimeInMillis = mClock.getElapsedSinceBootMillis(); - mActiveMatchedScanResults.entrySet().removeIf( - e -> ((currentTimeInMillis - (e.getValue().timestamp / 1000)) - >= CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS)); - - } - - /** - * Retrieve the latest cached scan results from wifi scanner and filter out any - * {@link ScanResult} older than {@link #CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS}. - */ - private @NonNull ScanResult[] getFilteredCachedScanResults() { - List<ScanResult> cachedScanResults = mWifiScanner.getSingleScanResults(); - if (cachedScanResults == null || cachedScanResults.isEmpty()) return new ScanResult[0]; - long currentTimeInMillis = mClock.getElapsedSinceBootMillis(); - return cachedScanResults.stream() - .filter(scanResult - -> ((currentTimeInMillis - (scanResult.timestamp / 1000)) - < CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS)) - .toArray(ScanResult[]::new); - } - - /** - * Clean up least recently used Access Points if specified app reach the limit. - */ - private static void cleanUpLRUAccessPoints(Set<AccessPoint> approvedAccessPoints) { - if (approvedAccessPoints.size() <= NUM_OF_ACCESS_POINT_LIMIT_PER_APP) { - return; - } - Iterator iter = approvedAccessPoints.iterator(); - while (iter.hasNext() && approvedAccessPoints.size() > NUM_OF_ACCESS_POINT_LIMIT_PER_APP) { - iter.next(); - iter.remove(); - } - } - - /** - * Sets all access points approved for the specified app. - * Used by shell commands. - */ - public void setUserApprovedApp(@NonNull String packageName, boolean approved) { - if (approved) { - mApprovedApp = packageName; - } else if (TextUtils.equals(packageName, mApprovedApp)) { - mApprovedApp = null; - } - } - - /** - * Whether all access points are approved for the specified app. - * Used by shell commands. - */ - public boolean hasUserApprovedApp(@NonNull String packageName) { - return TextUtils.equals(packageName, mApprovedApp); - } - - /** - * Remove all user approved access points for the specified app. - */ - public void removeUserApprovedAccessPointsForApp(@NonNull String packageName) { - if (mUserApprovedAccessPointMap.remove(packageName) != null) { - Log.i(TAG, "Removing all approved access points for " + packageName); - } - saveToStore(); - } - - /** - * Clear all internal state (for network settings reset). - */ - public void clear() { - mUserApprovedAccessPointMap.clear(); - mApprovedApp = null; - Log.i(TAG, "Cleared all internal state"); - saveToStore(); - } -} diff --git a/service/java/com/android/server/wifi/WifiNetworkScoreCache.java b/service/java/com/android/server/wifi/WifiNetworkScoreCache.java deleted file mode 100644 index 6bb3708ac..000000000 --- a/service/java/com/android/server/wifi/WifiNetworkScoreCache.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.Manifest.permission; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.NetworkKey; -import android.net.NetworkScoreManager; -import android.net.ScoredNetwork; -import android.net.wifi.ScanResult; -import android.os.Handler; -import android.os.Process; -import android.util.Log; -import android.util.LruCache; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.Preconditions; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * {@link NetworkScoreManager.NetworkScoreCallback} implementation for Wifi Networks. - * - * Note: This is a copy of WifiNetworkScoreCache for internal usage by the wifi stack. This extends - * the formal API: {@link NetworkScoreManager.NetworkScoreCallback} - */ -public class WifiNetworkScoreCache extends NetworkScoreManager.NetworkScoreCallback { - private static final String TAG = "WifiNetworkScoreCache"; - private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); - - // A Network scorer returns a score in the range [-128, +127] - // We treat the lowest possible score as though there were no score, effectively allowing the - // scorer to provide an RSSI threshold below which a network should not be used. - public static final int INVALID_NETWORK_SCORE = Byte.MIN_VALUE; - - /** Default number entries to be stored in the {@link LruCache}. */ - private static final int DEFAULT_MAX_CACHE_SIZE = 100; - - // See {@link #CacheListener}. - @Nullable - @GuardedBy("mLock") - private CacheListener mListener; - - private final Context mContext; - private final Object mLock = new Object(); - - // The key is of the form "<ssid>"<bssid> - // TODO: What about SSIDs that can't be encoded as UTF-8? - @GuardedBy("mLock") - private final LruCache<String, ScoredNetwork> mCache; - - public WifiNetworkScoreCache(Context context) { - this(context, null /* listener */); - } - - /** - * Instantiates a WifiNetworkScoreCache. - * - * @param context Application context - * @param listener CacheListener for cache updates - */ - public WifiNetworkScoreCache(Context context, @Nullable CacheListener listener) { - this(context, listener, DEFAULT_MAX_CACHE_SIZE); - } - - public WifiNetworkScoreCache( - Context context, @Nullable CacheListener listener, int maxCacheSize) { - mContext = context.getApplicationContext(); - mListener = listener; - mCache = new LruCache<>(maxCacheSize); - } - - @Override - public final void onScoresUpdated(Collection<ScoredNetwork> networks) { - if (networks == null || networks.isEmpty()) { - return; - } - if (DBG) { - Log.d(TAG, "updateScores list size=" + networks.size()); - } - - boolean changed = false; - - synchronized (mLock) { - for (ScoredNetwork network : networks) { - String networkKey = buildNetworkKey(network); - if (networkKey == null) { - if (DBG) { - Log.d(TAG, "Failed to build network key for ScoredNetwork" + network); - } - continue; - } - mCache.put(networkKey, network); - changed = true; - } - - if (mListener != null && changed) { - mListener.post(new ArrayList<>(networks)); - } - } - } - - @Override - public final void onScoresInvalidated() { - synchronized (mLock) { - mCache.evictAll(); - } - } - - /** - * Returns whether there is any score info for the given ScanResult. - * - * This includes null-score info, so it should only be used when determining whether to request - * scores from the network scorer. - */ - public boolean isScoredNetwork(ScanResult result) { - return getScoredNetwork(result) != null; - } - - /** - * Returns whether there is a non-null score curve for the given ScanResult. - * - * A null score curve has special meaning - we should never connect to an ephemeral network if - * the score curve is null. - */ - public boolean hasScoreCurve(ScanResult result) { - ScoredNetwork network = getScoredNetwork(result); - return network != null && network.rssiCurve != null; - } - - private int getNetworkScore(ScanResult result) { - int score = INVALID_NETWORK_SCORE; - - ScoredNetwork network = getScoredNetwork(result); - if (network != null && network.rssiCurve != null) { - score = network.rssiCurve.lookupScore(result.level); - if (DBG) { - Log.d(TAG, "getNetworkScore found scored network " + network.networkKey - + " score " + Integer.toString(score) - + " RSSI " + result.level); - } - } - return score; - } - - /** - * Returns the ScoredNetwork metered hint for a given ScanResult. - * - * If there is no ScoredNetwork associated with the ScanResult then false will be returned. - */ - public boolean getMeteredHint(ScanResult result) { - ScoredNetwork network = getScoredNetwork(result); - return network != null && network.meteredHint; - } - - /** - * Get network score for the provided ScanResult. - */ - public int getNetworkScore(ScanResult result, boolean isActiveNetwork) { - int score = INVALID_NETWORK_SCORE; - - ScoredNetwork network = getScoredNetwork(result); - if (network != null && network.rssiCurve != null) { - score = network.rssiCurve.lookupScore(result.level, isActiveNetwork); - if (DBG) { - Log.d(TAG, "getNetworkScore found scored network " + network.networkKey - + " score " + Integer.toString(score) - + " RSSI " + result.level - + " isActiveNetwork " + isActiveNetwork); - } - } - return score; - } - - @Nullable - private ScoredNetwork getScoredNetwork(ScanResult result) { - String key = buildNetworkKey(result); - if (key == null) return null; - - synchronized (mLock) { - ScoredNetwork network = mCache.get(key); - return network; - } - } - - /** Returns the ScoredNetwork for the given key. */ - @Nullable - public ScoredNetwork getScoredNetwork(NetworkKey networkKey) { - String key = buildNetworkKey(networkKey); - if (key == null) { - if (DBG) { - Log.d(TAG, "Could not build key string for Network Key: " + networkKey); - } - return null; - } - synchronized (mLock) { - return mCache.get(key); - } - } - - private String buildNetworkKey(ScoredNetwork network) { - if (network == null) { - return null; - } - return buildNetworkKey(network.networkKey); - } - - private String buildNetworkKey(NetworkKey networkKey) { - if (networkKey == null) { - return null; - } - if (networkKey.wifiKey == null) return null; - if (networkKey.type == NetworkKey.TYPE_WIFI) { - String key = networkKey.wifiKey.ssid; - if (key == null) return null; - if (networkKey.wifiKey.bssid != null) { - key = key + networkKey.wifiKey.bssid; - } - return key; - } - return null; - } - - private String buildNetworkKey(ScanResult result) { - if (result == null || result.SSID == null) { - return null; - } - StringBuilder key = new StringBuilder("\""); - key.append(result.SSID); - key.append("\""); - if (result.BSSID != null) { - key.append(result.BSSID); - } - return key.toString(); - } - - /** - * This is directly invoked from within Wifi-Service (on it's instance of this class), hence - * avoid making the WifiManager.getScanResults() call to avoid a deadlock. - */ - public final void dumpWithLatestScanResults( - FileDescriptor fd, PrintWriter writer, String[] args, - List<ScanResult> latestScanResults) { - mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); - String header = String.format("WifiNetworkScoreCache (%s/%d)", - mContext.getPackageName(), Process.myUid()); - writer.println(header); - writer.println(" All score curves:"); - synchronized (mLock) { - for (ScoredNetwork score : mCache.snapshot().values()) { - writer.println(" " + score); - } - writer.println(" Network scores for latest ScanResults:"); - for (ScanResult scanResult : latestScanResults) { - writer.println( - " " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult)); - } - } - } - - /** Listener for updates to the cache inside WifiNetworkScoreCache. */ - public abstract static class CacheListener { - private Handler mHandler; - - /** - * Constructor for CacheListener. - * - * @param handler the Handler on which to invoke the {@link #networkCacheUpdated} method. - * This cannot be null. - */ - public CacheListener(@NonNull Handler handler) { - Preconditions.checkNotNull(handler); - mHandler = handler; - } - - /** Invokes the {@link #networkCacheUpdated(List<ScoredNetwork>)} method on the handler. */ - void post(List<ScoredNetwork> updatedNetworks) { - mHandler.post(new Runnable() { - @Override - public void run() { - networkCacheUpdated(updatedNetworks); - } - }); - } - - /** - * Invoked whenever the cache is updated. - * - * <p>Clearing the cache does not invoke this method. - * - * @param updatedNetworks the networks that were updated - */ - public abstract void networkCacheUpdated(List<ScoredNetwork> updatedNetworks); - } -} diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java deleted file mode 100644 index fbbcb3174..000000000 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ /dev/null @@ -1,1135 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.LocalLog; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.InformationElementUtil.BssLoad; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.wifi.resources.R; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * WifiNetworkSelector looks at all the connectivity scan results and - * runs all the nominators to find or create matching configurations. - * Then it makes a final selection from among the resulting candidates. - */ -public class WifiNetworkSelector { - private static final String TAG = "WifiNetworkSelector"; - - private static final long INVALID_TIME_STAMP = Long.MIN_VALUE; - - /** - * Minimum time gap between last successful network selection and a - * new selection attempt. - */ - @VisibleForTesting - public static final int MINIMUM_NETWORK_SELECTION_INTERVAL_MS = 10 * 1000; - - /** - * Connected score value used to decide whether a still-connected wifi should be treated - * as unconnected when filtering scan results. - */ - @VisibleForTesting - public static final int WIFI_POOR_SCORE = ConnectedScore.WIFI_TRANSITION_SCORE - 10; - - /** - * The identifier string of the CandidateScorer to use (in the absence of overrides). - */ - public static final String PRESET_CANDIDATE_SCORER_NAME = "ThroughputScorer"; - - /** - * Experiment ID for the legacy scorer. - */ - public static final int LEGACY_CANDIDATE_SCORER_EXP_ID = 0; - - private final Context mContext; - private final WifiConfigManager mWifiConfigManager; - private final Clock mClock; - private final LocalLog mLocalLog; - private final WifiMetrics mWifiMetrics; - private long mLastNetworkSelectionTimeStamp = INVALID_TIME_STAMP; - // Buffer of filtered scan results (Scan results considered by network selection) & associated - // WifiConfiguration (if any). - private final List<Pair<ScanDetail, WifiConfiguration>> mConnectableNetworks = - new ArrayList<>(); - private List<ScanDetail> mFilteredNetworks = new ArrayList<>(); - private final WifiScoreCard mWifiScoreCard; - private final ScoringParams mScoringParams; - private final WifiNative mWifiNative; - - private final Map<String, WifiCandidates.CandidateScorer> mCandidateScorers = new ArrayMap<>(); - private boolean mIsEnhancedOpenSupportedInitialized = false; - private boolean mIsEnhancedOpenSupported; - private ThroughputPredictor mThroughputPredictor; - private boolean mIsBluetoothConnected = false; - private WifiChannelUtilization mWifiChannelUtilization; - - /** - * Interface for WiFi Network Nominator - * - * A network nominator examines the scan results reports the - * connectable candidates in its category for further consideration. - */ - public interface NetworkNominator { - /** Type of nominators */ - int NOMINATOR_ID_SAVED = 0; - int NOMINATOR_ID_SUGGESTION = 1; - int NOMINATOR_ID_SCORED = 4; - int NOMINATOR_ID_CURRENT = 5; // Should always be last - - @IntDef(prefix = {"NOMINATOR_ID_"}, value = { - NOMINATOR_ID_SAVED, - NOMINATOR_ID_SUGGESTION, - NOMINATOR_ID_SCORED, - NOMINATOR_ID_CURRENT}) - @Retention(RetentionPolicy.SOURCE) - public @interface NominatorId { - } - - /** - * Get the nominator type. - */ - @NominatorId - int getId(); - - /** - * Get the nominator name. - */ - String getName(); - - /** - * Update the nominator. - * - * Certain nominators have to be updated with the new scan results. For example - * the ScoredNetworkNominator needs to refresh its Score Cache. - * - * @param scanDetails a list of scan details constructed from the scan results - */ - void update(List<ScanDetail> scanDetails); - - /** - * Evaluate all the networks from the scan results. - * - * @param scanDetails a list of scan details constructed from the scan results - * @param currentNetwork configuration of the current connected network - * or null if disconnected - * @param currentBssid BSSID of the current connected network or null if - * disconnected - * @param connected a flag to indicate if ClientModeImpl is in connected - * state - * @param untrustedNetworkAllowed a flag to indicate if untrusted networks like - * ephemeral networks are allowed - * @param onConnectableListener callback to record all of the connectable networks - */ - void nominateNetworks(List<ScanDetail> scanDetails, - WifiConfiguration currentNetwork, String currentBssid, - boolean connected, boolean untrustedNetworkAllowed, - OnConnectableListener onConnectableListener); - - /** - * Callback for recording connectable candidates - */ - public interface OnConnectableListener { - /** - * Notes that an access point is an eligible connection candidate - * - * @param scanDetail describes the specific access point - * @param config is the WifiConfiguration for the network - */ - void onConnectable(ScanDetail scanDetail, WifiConfiguration config); - } - } - - private final List<NetworkNominator> mNominators = new ArrayList<>(3); - - // A helper to log debugging information in the local log buffer, which can - // be retrieved in bugreport. - private void localLog(String log) { - mLocalLog.log(log); - } - - /** - * Check if current network has sufficient RSSI - * - * @param wifiInfo info of currently connected network - * @return true if current link quality is sufficient, false otherwise. - */ - public boolean hasSufficientLinkQuality(WifiInfo wifiInfo) { - int currentRssi = wifiInfo.getRssi(); - return currentRssi >= mScoringParams.getSufficientRssi(wifiInfo.getFrequency()); - } - - /** - * Check if current network has active Tx or Rx traffic - * - * @param wifiInfo info of currently connected network - * @return true if it has active Tx or Rx traffic, false otherwise. - */ - public boolean hasActiveStream(WifiInfo wifiInfo) { - return wifiInfo.getSuccessfulTxPacketsPerSecond() - > mScoringParams.getActiveTrafficPacketsPerSecond() - || wifiInfo.getSuccessfulRxPacketsPerSecond() - > mScoringParams.getActiveTrafficPacketsPerSecond(); - } - - /** - * Check if current network has internet or is expected to not have internet - */ - public boolean hasInternetOrExpectNoInternet(WifiInfo wifiInfo) { - WifiConfiguration network = - mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId()); - if (network == null) { - return false; - } - return !network.hasNoInternetAccess() || network.isNoInternetAccessExpected(); - } - /** - * Determines whether the currently connected network is sufficient. - * - * If the network is good enough, or if switching to a new network is likely to - * be disruptive, we should avoid doing a network selection. - * - * @param wifiInfo info of currently connected network - * @return true if the network is sufficient - */ - public boolean isNetworkSufficient(WifiInfo wifiInfo) { - // Currently connected? - if (wifiInfo.getSupplicantState() != SupplicantState.COMPLETED) { - return false; - } - - localLog("Current connected network: " + wifiInfo.getNetworkId()); - - WifiConfiguration network = - mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId()); - - if (network == null) { - localLog("Current network was removed"); - return false; - } - - // Skip autojoin for the first few seconds of a user-initiated connection. - // This delays network selection during the time that connectivity service may be posting - // a dialog about a no-internet network. - if (mWifiConfigManager.getLastSelectedNetwork() == network.networkId - && (mClock.getElapsedSinceBootMillis() - - mWifiConfigManager.getLastSelectedTimeStamp()) - <= mContext.getResources().getInteger( - R.integer.config_wifiSufficientDurationAfterUserSelectionMilliseconds)) { - localLog("Current network is recently user-selected"); - return true; - } - - // Set OSU (Online Sign Up) network for Passpoint Release 2 to sufficient - // so that network select selection is skipped and OSU process can complete. - if (network.osu) { - localLog("Current connection is OSU"); - return true; - } - - // Network without internet access is not sufficient, unless expected - if (!hasInternetOrExpectNoInternet(wifiInfo)) { - localLog("Current network has [" + network.numNoInternetAccessReports - + "] no-internet access reports"); - return false; - } - - if (!hasSufficientLinkQuality(wifiInfo)) { - localLog("Current network link quality is not sufficient"); - return false; - } - - if (!hasActiveStream(wifiInfo)) { - localLog("Current network has low ongoing traffic"); - return false; - } - - return true; - } - - private boolean isNetworkSelectionNeeded(List<ScanDetail> scanDetails, WifiInfo wifiInfo, - boolean connected, boolean disconnected) { - if (scanDetails.size() == 0) { - localLog("Empty connectivity scan results. Skip network selection."); - return false; - } - - if (connected) { - // Is roaming allowed? - if (!mContext.getResources().getBoolean( - R.bool.config_wifi_framework_enable_associated_network_selection)) { - localLog("Switching networks in connected state is not allowed." - + " Skip network selection."); - return false; - } - - // Has it been at least the minimum interval since last network selection? - if (mLastNetworkSelectionTimeStamp != INVALID_TIME_STAMP) { - long gap = mClock.getElapsedSinceBootMillis() - - mLastNetworkSelectionTimeStamp; - if (gap < MINIMUM_NETWORK_SELECTION_INTERVAL_MS) { - localLog("Too short since last network selection: " + gap + " ms." - + " Skip network selection."); - return false; - } - } - // Please note other scans (e.g., location scan or app scan) may also trigger network - // selection and these scans may or may not run sufficiency check. - // So it is better to run sufficiency check here before network selection. - if (isNetworkSufficient(wifiInfo)) { - localLog("Current connected network already sufficient. Skip network selection."); - return false; - } else { - localLog("Current connected network is not sufficient."); - return true; - } - } else if (disconnected) { - return true; - } else { - // No network selection if ClientModeImpl is in a state other than - // CONNECTED or DISCONNECTED. - localLog("ClientModeImpl is in neither CONNECTED nor DISCONNECTED state." - + " Skip network selection."); - return false; - } - } - - /** - * Format the given ScanResult as a scan ID for logging. - */ - public static String toScanId(@Nullable ScanResult scanResult) { - return scanResult == null ? "NULL" - : String.format("%s:%s", scanResult.SSID, scanResult.BSSID); - } - - /** - * Format the given WifiConfiguration as a SSID:netId string - */ - public static String toNetworkString(WifiConfiguration network) { - if (network == null) { - return null; - } - - return (network.SSID + ":" + network.networkId); - } - - /** - * Compares ScanResult level against the minimum threshold for its band, returns true if lower - */ - public boolean isSignalTooWeak(ScanResult scanResult) { - return (scanResult.level < mScoringParams.getEntryRssi(scanResult.frequency)); - } - - private List<ScanDetail> filterScanResults(List<ScanDetail> scanDetails, - Set<String> bssidBlacklist, boolean isConnected, String currentBssid) { - List<ScanDetail> validScanDetails = new ArrayList<>(); - StringBuffer noValidSsid = new StringBuffer(); - StringBuffer blacklistedBssid = new StringBuffer(); - StringBuffer lowRssi = new StringBuffer(); - StringBuffer mboAssociationDisallowedBssid = new StringBuffer(); - boolean scanResultsHaveCurrentBssid = false; - int numBssidFiltered = 0; - - for (ScanDetail scanDetail : scanDetails) { - ScanResult scanResult = scanDetail.getScanResult(); - - if (TextUtils.isEmpty(scanResult.SSID)) { - noValidSsid.append(scanResult.BSSID).append(" / "); - continue; - } - - // Check if the scan results contain the currently connected BSSID - if (scanResult.BSSID.equals(currentBssid)) { - scanResultsHaveCurrentBssid = true; - validScanDetails.add(scanDetail); - continue; - } - - final String scanId = toScanId(scanResult); - - if (bssidBlacklist.contains(scanResult.BSSID)) { - blacklistedBssid.append(scanId).append(" / "); - numBssidFiltered++; - continue; - } - - // Skip network with too weak signals. - if (isSignalTooWeak(scanResult)) { - lowRssi.append(scanId); - if (scanResult.is24GHz()) { - lowRssi.append("(2.4GHz)"); - } else if (scanResult.is5GHz()) { - lowRssi.append("(5GHz)"); - } else if (scanResult.is6GHz()) { - lowRssi.append("(6GHz)"); - } - lowRssi.append(scanResult.level).append(" / "); - continue; - } - - // Skip BSS which is not accepting new connections. - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - if (networkDetail != null) { - if (networkDetail.getMboAssociationDisallowedReasonCode() - != MboOceConstants.MBO_OCE_ATTRIBUTE_NOT_PRESENT) { - mWifiMetrics - .incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd(); - mboAssociationDisallowedBssid.append(scanId).append("(") - .append(networkDetail.getMboAssociationDisallowedReasonCode()) - .append(")").append(" / "); - continue; - } - } - - validScanDetails.add(scanDetail); - } - mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(numBssidFiltered); - - // WNS listens to all single scan results. Some scan requests may not include - // the channel of the currently connected network, so the currently connected - // network won't show up in the scan results. We don't act on these scan results - // to avoid aggressive network switching which might trigger disconnection. - // TODO(b/147751334) this may no longer be needed - if (isConnected && !scanResultsHaveCurrentBssid) { - localLog("Current connected BSSID " + currentBssid + " is not in the scan results." - + " Skip network selection."); - validScanDetails.clear(); - return validScanDetails; - } - - if (noValidSsid.length() != 0) { - localLog("Networks filtered out due to invalid SSID: " + noValidSsid); - } - - if (blacklistedBssid.length() != 0) { - localLog("Networks filtered out due to blocklist: " + blacklistedBssid); - } - - if (lowRssi.length() != 0) { - localLog("Networks filtered out due to low signal strength: " + lowRssi); - } - - if (mboAssociationDisallowedBssid.length() != 0) { - localLog("Networks filtered out due to mbo association disallowed indication: " - + mboAssociationDisallowedBssid); - } - - return validScanDetails; - } - - private ScanDetail findScanDetailForBssid(List<ScanDetail> scanDetails, - String currentBssid) { - for (ScanDetail scanDetail : scanDetails) { - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult.BSSID.equals(currentBssid)) { - return scanDetail; - } - } - return null; - } - - private boolean isEnhancedOpenSupported() { - if (mIsEnhancedOpenSupportedInitialized) { - return mIsEnhancedOpenSupported; - } - - mIsEnhancedOpenSupportedInitialized = true; - mIsEnhancedOpenSupported = (mWifiNative.getSupportedFeatureSet( - mWifiNative.getClientInterfaceName()) & WIFI_FEATURE_OWE) != 0; - return mIsEnhancedOpenSupported; - } - - /** - * This returns a list of ScanDetails that were filtered in the process of network selection. - * The list is further filtered for only open unsaved networks. - * - * @return the list of ScanDetails for open unsaved networks that do not have invalid SSIDS, - * blacklisted BSSIDS, or low signal strength. This will return an empty list when there are - * no open unsaved networks, or when network selection has not been run. - */ - public List<ScanDetail> getFilteredScanDetailsForOpenUnsavedNetworks() { - List<ScanDetail> openUnsavedNetworks = new ArrayList<>(); - boolean enhancedOpenSupported = isEnhancedOpenSupported(); - for (ScanDetail scanDetail : mFilteredNetworks) { - ScanResult scanResult = scanDetail.getScanResult(); - - if (!ScanResultUtil.isScanResultForOpenNetwork(scanResult)) { - continue; - } - - // Filter out Enhanced Open networks on devices that do not support it - if (ScanResultUtil.isScanResultForOweNetwork(scanResult) - && !enhancedOpenSupported) { - continue; - } - - // Skip saved networks - if (mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail) != null) { - continue; - } - - openUnsavedNetworks.add(scanDetail); - } - return openUnsavedNetworks; - } - - /** - * @return the list of ScanDetails scored as potential candidates by the last run of - * selectNetwork, this will be empty if Network selector determined no selection was - * needed on last run. This includes scan details of sufficient signal strength, and - * had an associated WifiConfiguration. - */ - public List<Pair<ScanDetail, WifiConfiguration>> getConnectableScanDetails() { - return mConnectableNetworks; - } - - /** - * This API is called when user explicitly selects a network. Currently, it is used in following - * cases: - * (1) User explicitly chooses to connect to a saved network. - * (2) User saves a network after adding a new network. - * (3) User saves a network after modifying a saved network. - * Following actions will be triggered: - * 1. If this network is disabled, we need re-enable it again. - * 2. This network is favored over all the other networks visible in latest network - * selection procedure. - * - * @param netId ID for the network chosen by the user - * @return true -- There is change made to connection choice of any saved network. - * false -- There is no change made to connection choice of any saved network. - */ - public boolean setUserConnectChoice(int netId) { - localLog("userSelectNetwork: network ID=" + netId); - WifiConfiguration selected = mWifiConfigManager.getConfiguredNetwork(netId); - - if (selected == null || selected.SSID == null) { - localLog("userSelectNetwork: Invalid configuration with nid=" + netId); - return false; - } - - // Enable the network if it is disabled. - if (!selected.getNetworkSelectionStatus().isNetworkEnabled()) { - mWifiConfigManager.updateNetworkSelectionStatus(netId, - WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE); - } - return setLegacyUserConnectChoice(selected); - } - - /** - * This maintains the legacy user connect choice state in the config store - */ - private boolean setLegacyUserConnectChoice(@NonNull final WifiConfiguration selected) { - boolean change = false; - String key = selected.getKey(); - List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); - - for (WifiConfiguration network : configuredNetworks) { - WifiConfiguration.NetworkSelectionStatus status = network.getNetworkSelectionStatus(); - if (network.networkId == selected.networkId) { - if (status.getConnectChoice() != null) { - localLog("Remove user selection preference of " + status.getConnectChoice() - + " from " + network.SSID + " : " + network.networkId); - mWifiConfigManager.clearNetworkConnectChoice(network.networkId); - change = true; - } - continue; - } - - if (status.getSeenInLastQualifiedNetworkSelection() - && !key.equals(status.getConnectChoice())) { - localLog("Add key: " + key + " to " - + toNetworkString(network)); - mWifiConfigManager.setNetworkConnectChoice(network.networkId, key); - change = true; - } - } - - return change; - } - - - /** - * Iterate thru the list of configured networks (includes all saved network configurations + - * any ephemeral network configurations created for passpoint networks, suggestions, carrier - * networks, etc) and do the following: - * a) Try to re-enable any temporarily enabled networks (if the blacklist duration has expired). - * b) Clear the {@link WifiConfiguration.NetworkSelectionStatus#getCandidate()} field for all - * of them to identify networks that are present in the current scan result. - * c) Log any disabled networks. - */ - private void updateConfiguredNetworks() { - List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); - if (configuredNetworks.size() == 0) { - localLog("No configured networks."); - return; - } - - StringBuffer sbuf = new StringBuffer(); - for (WifiConfiguration network : configuredNetworks) { - // If a configuration is temporarily disabled, re-enable it before trying - // to connect to it. - mWifiConfigManager.tryEnableNetwork(network.networkId); - // Clear the cached candidate, score and seen. - mWifiConfigManager.clearNetworkCandidateScanResult(network.networkId); - - // Log disabled network. - WifiConfiguration.NetworkSelectionStatus status = network.getNetworkSelectionStatus(); - if (!status.isNetworkEnabled()) { - sbuf.append(" ").append(toNetworkString(network)).append(" "); - for (int index = WifiConfiguration.NetworkSelectionStatus - .NETWORK_SELECTION_DISABLED_STARTING_INDEX; - index < WifiConfiguration.NetworkSelectionStatus - .NETWORK_SELECTION_DISABLED_MAX; - index++) { - int count = status.getDisableReasonCounter(index); - // Here we log the reason as long as its count is greater than zero. The - // network may not be disabled because of this particular reason. Logging - // this information anyway to help understand what happened to the network. - if (count > 0) { - sbuf.append("reason=") - .append(WifiConfiguration.NetworkSelectionStatus - .getNetworkSelectionDisableReasonString(index)) - .append(", count=").append(count).append("; "); - } - } - sbuf.append("\n"); - } - } - - if (sbuf.length() > 0) { - localLog("Disabled configured networks:"); - localLog(sbuf.toString()); - } - } - - /** - * Overrides the {@code candidate} chosen by the {@link #mNominators} with the user chosen - * {@link WifiConfiguration} if one exists. - * - * @return the user chosen {@link WifiConfiguration} if one exists, {@code candidate} otherwise - */ - private WifiConfiguration overrideCandidateWithUserConnectChoice( - @NonNull WifiConfiguration candidate) { - WifiConfiguration tempConfig = Preconditions.checkNotNull(candidate); - WifiConfiguration originalCandidate = candidate; - ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate(); - - while (tempConfig.getNetworkSelectionStatus().getConnectChoice() != null) { - String key = tempConfig.getNetworkSelectionStatus().getConnectChoice(); - tempConfig = mWifiConfigManager.getConfiguredNetwork(key); - - if (tempConfig != null) { - WifiConfiguration.NetworkSelectionStatus tempStatus = - tempConfig.getNetworkSelectionStatus(); - if (tempStatus.getCandidate() != null && tempStatus.isNetworkEnabled()) { - scanResultCandidate = tempStatus.getCandidate(); - candidate = tempConfig; - } - } else { - localLog("Connect choice: " + key + " has no corresponding saved config."); - break; - } - } - - if (candidate != originalCandidate) { - localLog("After user selection adjustment, the final candidate is:" - + WifiNetworkSelector.toNetworkString(candidate) + " : " - + scanResultCandidate.BSSID); - mWifiMetrics.setNominatorForNetwork(candidate.networkId, - WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE); - } - return candidate; - } - - - /** - * Indicates whether we have ever seen the network to be metered since wifi was enabled. - * - * This is sticky to prevent continuous flip-flopping between networks, when the metered - * status is learned after association. - */ - private boolean isEverMetered(@NonNull WifiConfiguration config, @Nullable WifiInfo info, - @NonNull ScanDetail scanDetail) { - // If info does not match config, don't use it. - if (info != null && info.getNetworkId() != config.networkId) info = null; - boolean metered = WifiConfiguration.isMetered(config, info); - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - if (networkDetail != null - && networkDetail.getAnt() - == NetworkDetail.Ant.ChargeablePublic) { - metered = true; - } - mWifiMetrics.addMeteredStat(config, metered); - if (config.meteredOverride != WifiConfiguration.METERED_OVERRIDE_NONE) { - // User override is in effect; we should trust it - if (mKnownMeteredNetworkIds.remove(config.networkId)) { - localLog("KnownMeteredNetworkIds = " + mKnownMeteredNetworkIds); - } - metered = config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED; - } else if (mKnownMeteredNetworkIds.contains(config.networkId)) { - // Use the saved information - metered = true; - } else if (metered) { - // Update the saved information - mKnownMeteredNetworkIds.add(config.networkId); - localLog("KnownMeteredNetworkIds = " + mKnownMeteredNetworkIds); - } - return metered; - } - - /** - * Returns the set of known metered network ids (for tests. dumpsys, and metrics). - */ - public Set<Integer> getKnownMeteredNetworkIds() { - return new ArraySet<>(mKnownMeteredNetworkIds); - } - - private final ArraySet<Integer> mKnownMeteredNetworkIds = new ArraySet<>(); - - - /** - * Cleans up state that should go away when wifi is disabled. - */ - public void resetOnDisable() { - mWifiConfigManager.clearLastSelectedNetwork(); - mKnownMeteredNetworkIds.clear(); - } - - /** - * Returns the list of Candidates from networks in range. - * - * @param scanDetails List of ScanDetail for all the APs in range - * @param bssidBlacklist Blacklisted BSSIDs - * @param wifiInfo Currently connected network - * @param connected True if the device is connected - * @param disconnected True if the device is disconnected - * @param untrustedNetworkAllowed True if untrusted networks are allowed for connection - * @return list of valid Candidate(s) - */ - public List<WifiCandidates.Candidate> getCandidatesFromScan( - List<ScanDetail> scanDetails, Set<String> bssidBlacklist, WifiInfo wifiInfo, - boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) { - mFilteredNetworks.clear(); - mConnectableNetworks.clear(); - if (scanDetails.size() == 0) { - localLog("Empty connectivity scan result"); - return null; - } - - WifiConfiguration currentNetwork = - mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId()); - - // Always get the current BSSID from WifiInfo in case that firmware initiated - // roaming happened. - String currentBssid = wifiInfo.getBSSID(); - - // Update the scan detail cache at the start, even if we skip network selection - updateScanDetailCache(scanDetails); - - // Shall we start network selection at all? - if (!isNetworkSelectionNeeded(scanDetails, wifiInfo, connected, disconnected)) { - return null; - } - - // Update all configured networks before initiating network selection. - updateConfiguredNetworks(); - - // Update the registered network nominators. - for (NetworkNominator registeredNominator : mNominators) { - registeredNominator.update(scanDetails); - } - - // Filter out unwanted networks. - mFilteredNetworks = filterScanResults(scanDetails, bssidBlacklist, - connected && wifiInfo.getScore() >= WIFI_POOR_SCORE, currentBssid); - if (mFilteredNetworks.size() == 0) { - return null; - } - - WifiCandidates wifiCandidates = new WifiCandidates(mWifiScoreCard, mContext); - if (currentNetwork != null) { - wifiCandidates.setCurrent(currentNetwork.networkId, currentBssid); - // We always want the current network to be a candidate so that it can participate. - // It may also get re-added by a nominator, in which case this fallback - // will be replaced. - MacAddress bssid = MacAddress.fromString(currentBssid); - WifiCandidates.Key key = new WifiCandidates.Key( - ScanResultMatchInfo.fromWifiConfiguration(currentNetwork), - bssid, currentNetwork.networkId); - ScanDetail scanDetail = findScanDetailForBssid(mFilteredNetworks, currentBssid); - int predictedTputMbps = (scanDetail == null) ? 0 : predictThroughput(scanDetail); - wifiCandidates.add(key, currentNetwork, - NetworkNominator.NOMINATOR_ID_CURRENT, - wifiInfo.getRssi(), - wifiInfo.getFrequency(), - calculateLastSelectionWeight(currentNetwork.networkId), - WifiConfiguration.isMetered(currentNetwork, wifiInfo), - isFromCarrierOrPrivilegedApp(currentNetwork), - predictedTputMbps); - } - for (NetworkNominator registeredNominator : mNominators) { - localLog("About to run " + registeredNominator.getName() + " :"); - registeredNominator.nominateNetworks( - new ArrayList<>(mFilteredNetworks), currentNetwork, currentBssid, connected, - untrustedNetworkAllowed, - (scanDetail, config) -> { - WifiCandidates.Key key = wifiCandidates.keyFromScanDetailAndConfig( - scanDetail, config); - if (key != null) { - boolean metered = isEverMetered(config, wifiInfo, scanDetail); - // TODO(b/151981920) Saved passpoint candidates are marked ephemeral - boolean added = wifiCandidates.add(key, config, - registeredNominator.getId(), - scanDetail.getScanResult().level, - scanDetail.getScanResult().frequency, - calculateLastSelectionWeight(config.networkId), - metered, - isFromCarrierOrPrivilegedApp(config), - predictThroughput(scanDetail)); - if (added) { - mConnectableNetworks.add(Pair.create(scanDetail, config)); - mWifiConfigManager.updateScanDetailForNetwork( - config.networkId, scanDetail); - mWifiMetrics.setNominatorForNetwork(config.networkId, - toProtoNominatorId(registeredNominator.getId())); - } - } - }); - } - if (mConnectableNetworks.size() != wifiCandidates.size()) { - localLog("Connectable: " + mConnectableNetworks.size() - + " Candidates: " + wifiCandidates.size()); - } - return wifiCandidates.getCandidates(); - } - - /** - * Using the registered Scorers, choose the best network from the list of Candidate(s). - * The ScanDetailCache is also updated here. - * @param candidates - Candidates to perferm network selection on. - * @return WifiConfiguration - the selected network, or null. - */ - @NonNull - public WifiConfiguration selectNetwork(List<WifiCandidates.Candidate> candidates) { - if (candidates == null || candidates.size() == 0) { - return null; - } - WifiCandidates wifiCandidates = new WifiCandidates(mWifiScoreCard, mContext, candidates); - final WifiCandidates.CandidateScorer activeScorer = getActiveCandidateScorer(); - // Update the NetworkSelectionStatus in the configs for the current candidates - // This is needed for the legacy user connect choice, at least - Collection<Collection<WifiCandidates.Candidate>> groupedCandidates = - wifiCandidates.getGroupedCandidates(); - for (Collection<WifiCandidates.Candidate> group : groupedCandidates) { - WifiCandidates.ScoredCandidate choice = activeScorer.scoreCandidates(group); - if (choice == null) continue; - ScanDetail scanDetail = getScanDetailForCandidateKey(choice.candidateKey); - if (scanDetail == null) continue; - mWifiConfigManager.setNetworkCandidateScanResult(choice.candidateKey.networkId, - scanDetail.getScanResult(), 0); - } - - for (Collection<WifiCandidates.Candidate> group : groupedCandidates) { - for (WifiCandidates.Candidate candidate : group.stream() - .sorted((a, b) -> (b.getScanRssi() - a.getScanRssi())) // decreasing rssi - .collect(Collectors.toList())) { - localLog(candidate.toString()); - } - } - - ArrayMap<Integer, Integer> experimentNetworkSelections = new ArrayMap<>(); // for metrics - - int selectedNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - - // Run all the CandidateScorers - boolean legacyOverrideWanted = true; - for (WifiCandidates.CandidateScorer candidateScorer : mCandidateScorers.values()) { - WifiCandidates.ScoredCandidate choice; - try { - choice = wifiCandidates.choose(candidateScorer); - } catch (RuntimeException e) { - Log.wtf(TAG, "Exception running a CandidateScorer", e); - continue; - } - int networkId = choice.candidateKey == null - ? WifiConfiguration.INVALID_NETWORK_ID - : choice.candidateKey.networkId; - String chooses = " would choose "; - if (candidateScorer == activeScorer) { - chooses = " chooses "; - legacyOverrideWanted = choice.userConnectChoiceOverride; - selectedNetworkId = networkId; - updateChosenPasspointNetwork(choice); - } - String id = candidateScorer.getIdentifier(); - int expid = experimentIdFromIdentifier(id); - localLog(id + chooses + networkId - + " score " + choice.value + "+/-" + choice.err - + " expid " + expid); - experimentNetworkSelections.put(expid, networkId); - } - - // Update metrics about differences in the selections made by various methods - final int activeExperimentId = experimentIdFromIdentifier(activeScorer.getIdentifier()); - for (Map.Entry<Integer, Integer> entry : - experimentNetworkSelections.entrySet()) { - int experimentId = entry.getKey(); - if (experimentId == activeExperimentId) continue; - int thisSelectedNetworkId = entry.getValue(); - mWifiMetrics.logNetworkSelectionDecision(experimentId, activeExperimentId, - selectedNetworkId == thisSelectedNetworkId, - groupedCandidates.size()); - } - - // Get a fresh copy of WifiConfiguration reflecting any scan result updates - WifiConfiguration selectedNetwork = - mWifiConfigManager.getConfiguredNetwork(selectedNetworkId); - if (selectedNetwork != null && legacyOverrideWanted) { - selectedNetwork = overrideCandidateWithUserConnectChoice(selectedNetwork); - } - if (selectedNetwork != null) { - mLastNetworkSelectionTimeStamp = mClock.getElapsedSinceBootMillis(); - } - return selectedNetwork; - } - - /** - * Returns the ScanDetail given the candidate key, using the saved list of connectible networks. - */ - private ScanDetail getScanDetailForCandidateKey(WifiCandidates.Key candidateKey) { - if (candidateKey == null) return null; - String bssid = candidateKey.bssid.toString(); - for (Pair<ScanDetail, WifiConfiguration> pair : mConnectableNetworks) { - if (candidateKey.networkId == pair.second.networkId - && bssid.equals(pair.first.getBSSIDString())) { - return pair.first; - } - } - return null; - } - - private void updateChosenPasspointNetwork(WifiCandidates.ScoredCandidate choice) { - if (choice.candidateKey == null) { - return; - } - WifiConfiguration config = - mWifiConfigManager.getConfiguredNetwork(choice.candidateKey.networkId); - if (config == null) { - return; - } - if (config.isPasspoint()) { - config.SSID = choice.candidateKey.matchInfo.networkSsid; - mWifiConfigManager.addOrUpdateNetwork(config, config.creatorUid, config.creatorName); - } - } - - private void updateScanDetailCache(List<ScanDetail> scanDetails) { - for (ScanDetail scanDetail : scanDetails) { - mWifiConfigManager.updateScanDetailCacheFromScanDetail(scanDetail); - } - } - - private static int toProtoNominatorId(@NetworkNominator.NominatorId int nominatorId) { - switch (nominatorId) { - case NetworkNominator.NOMINATOR_ID_SAVED: - return WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED; - case NetworkNominator.NOMINATOR_ID_SUGGESTION: - return WifiMetricsProto.ConnectionEvent.NOMINATOR_SUGGESTION; - case NetworkNominator.NOMINATOR_ID_SCORED: - return WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED; - case NetworkNominator.NOMINATOR_ID_CURRENT: - Log.e(TAG, "Unexpected NOMINATOR_ID_CURRENT", new RuntimeException()); - return WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN; - default: - Log.e(TAG, "UnrecognizedNominatorId" + nominatorId); - return WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN; - } - } - - private double calculateLastSelectionWeight(int networkId) { - if (networkId != mWifiConfigManager.getLastSelectedNetwork()) return 0.0; - double timeDifference = mClock.getElapsedSinceBootMillis() - - mWifiConfigManager.getLastSelectedTimeStamp(); - long millis = TimeUnit.MINUTES.toMillis(mScoringParams.getLastSelectionMinutes()); - if (timeDifference >= millis) return 0.0; - double unclipped = 1.0 - (timeDifference / millis); - return Math.min(Math.max(unclipped, 0.0), 1.0); - } - - private WifiCandidates.CandidateScorer getActiveCandidateScorer() { - WifiCandidates.CandidateScorer ans = mCandidateScorers.get(PRESET_CANDIDATE_SCORER_NAME); - int overrideExperimentId = mScoringParams.getExperimentIdentifier(); - if (overrideExperimentId >= MIN_SCORER_EXP_ID) { - for (WifiCandidates.CandidateScorer candidateScorer : mCandidateScorers.values()) { - int expId = experimentIdFromIdentifier(candidateScorer.getIdentifier()); - if (expId == overrideExperimentId) { - ans = candidateScorer; - break; - } - } - } - if (ans == null && PRESET_CANDIDATE_SCORER_NAME != null) { - Log.wtf(TAG, PRESET_CANDIDATE_SCORER_NAME + " is not registered!"); - } - mWifiMetrics.setNetworkSelectorExperimentId(ans == null - ? LEGACY_CANDIDATE_SCORER_EXP_ID - : experimentIdFromIdentifier(ans.getIdentifier())); - return ans; - } - - private int predictThroughput(@NonNull ScanDetail scanDetail) { - if (scanDetail.getScanResult() == null || scanDetail.getNetworkDetail() == null) { - return 0; - } - int channelUtilizationLinkLayerStats = BssLoad.INVALID; - if (mWifiChannelUtilization != null) { - channelUtilizationLinkLayerStats = - mWifiChannelUtilization.getUtilizationRatio( - scanDetail.getScanResult().frequency); - } - return mThroughputPredictor.predictThroughput( - mWifiNative.getDeviceWiphyCapabilities(mWifiNative.getClientInterfaceName()), - scanDetail.getScanResult().getWifiStandard(), - scanDetail.getScanResult().channelWidth, - scanDetail.getScanResult().level, - scanDetail.getScanResult().frequency, - scanDetail.getNetworkDetail().getMaxNumberSpatialStreams(), - scanDetail.getNetworkDetail().getChannelUtilization(), - channelUtilizationLinkLayerStats, - mIsBluetoothConnected); - } - - /** - * Register a network nominator - * - * @param nominator the network nominator to be registered - */ - public void registerNetworkNominator(@NonNull NetworkNominator nominator) { - mNominators.add(Preconditions.checkNotNull(nominator)); - } - - /** - * Register a candidate scorer. - * - * Replaces any existing scorer having the same identifier. - */ - public void registerCandidateScorer(@NonNull WifiCandidates.CandidateScorer candidateScorer) { - String name = Preconditions.checkNotNull(candidateScorer).getIdentifier(); - if (name != null) { - mCandidateScorers.put(name, candidateScorer); - } - } - - /** - * Unregister a candidate scorer. - */ - public void unregisterCandidateScorer(@NonNull WifiCandidates.CandidateScorer candidateScorer) { - String name = Preconditions.checkNotNull(candidateScorer).getIdentifier(); - if (name != null) { - mCandidateScorers.remove(name); - } - } - - private static boolean isFromCarrierOrPrivilegedApp(WifiConfiguration config) { - if (config.fromWifiNetworkSuggestion - && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { - // Privileged carrier suggestion - return true; - } - if (config.isEphemeral() - && !config.fromWifiNetworkSpecifier - && !config.fromWifiNetworkSuggestion) { - // From ScoredNetworkNominator - return true; - } - return false; - } - - /** - * Derives a numeric experiment identifier from a CandidateScorer's identifier. - * - * @returns a positive number that starts with the decimal digits ID_PREFIX - */ - public static int experimentIdFromIdentifier(String id) { - final int digits = (int) (((long) id.hashCode()) & Integer.MAX_VALUE) % ID_SUFFIX_MOD; - return ID_PREFIX * ID_SUFFIX_MOD + digits; - } - - private static final int ID_SUFFIX_MOD = 1_000_000; - private static final int ID_PREFIX = 42; - private static final int MIN_SCORER_EXP_ID = ID_PREFIX * ID_SUFFIX_MOD; - - /** - * Set Wifi channel utilization calculated from link layer stats - */ - public void setWifiChannelUtilization(WifiChannelUtilization wifiChannelUtilization) { - mWifiChannelUtilization = wifiChannelUtilization; - } - - /** - * Set whether bluetooth is in the connected state - */ - public void setBluetoothConnected(boolean isBlueToothConnected) { - mIsBluetoothConnected = isBlueToothConnected; - } - - WifiNetworkSelector(Context context, WifiScoreCard wifiScoreCard, ScoringParams scoringParams, - WifiConfigManager configManager, Clock clock, LocalLog localLog, - WifiMetrics wifiMetrics, WifiNative wifiNative, - ThroughputPredictor throughputPredictor) { - mContext = context; - mWifiConfigManager = configManager; - mClock = clock; - mWifiScoreCard = wifiScoreCard; - mScoringParams = scoringParams; - mLocalLog = localLog; - mWifiMetrics = wifiMetrics; - mWifiNative = wifiNative; - mThroughputPredictor = throughputPredictor; - } -} diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java deleted file mode 100644 index 2632835e6..000000000 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ /dev/null @@ -1,2225 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static android.app.AppOpsManager.MODE_IGNORED; -import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.app.AlertDialog; -import android.app.AppOpsManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.graphics.drawable.Icon; -import android.net.MacAddress; -import android.net.NetworkScoreManager; -import android.net.wifi.ISuggestionConnectionStatusListener; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.Handler; -import android.os.IBinder; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; -import android.view.WindowManager; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.server.wifi.util.ExternalCallbackTracker; -import com.android.server.wifi.util.LruConnectionTracker; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.annotation.concurrent.NotThreadSafe; - -/** - * Network Suggestions Manager. - * NOTE: This class should always be invoked from the main wifi service thread. - */ -@NotThreadSafe -public class WifiNetworkSuggestionsManager { - private static final String TAG = "WifiNetworkSuggestionsManager"; - - /** Intent when user tapped action button to allow the app. */ - @VisibleForTesting - public static final String NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION = - "com.android.server.wifi.action.NetworkSuggestion.USER_ALLOWED_APP"; - /** Intent when user tapped action button to disallow the app. */ - @VisibleForTesting - public static final String NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION = - "com.android.server.wifi.action.NetworkSuggestion.USER_DISALLOWED_APP"; - /** Intent when user dismissed the notification. */ - @VisibleForTesting - public static final String NOTIFICATION_USER_DISMISSED_INTENT_ACTION = - "com.android.server.wifi.action.NetworkSuggestion.USER_DISMISSED"; - @VisibleForTesting - public static final String EXTRA_PACKAGE_NAME = - "com.android.server.wifi.extra.NetworkSuggestion.PACKAGE_NAME"; - @VisibleForTesting - public static final String EXTRA_UID = - "com.android.server.wifi.extra.NetworkSuggestion.UID"; - - public static final int APP_TYPE_CARRIER_PRIVILEGED = 1; - public static final int APP_TYPE_NETWORK_PROVISIONING = 2; - public static final int APP_TYPE_NON_PRIVILEGED = 3; - - public static final int ACTION_USER_ALLOWED_APP = 1; - public static final int ACTION_USER_DISALLOWED_APP = 2; - public static final int ACTION_USER_DISMISS = 3; - - @IntDef(prefix = { "ACTION_USER_" }, value = { - ACTION_USER_ALLOWED_APP, - ACTION_USER_DISALLOWED_APP, - ACTION_USER_DISMISS - }) - @Retention(RetentionPolicy.SOURCE) - public @interface UserActionCode { } - - /** - * Limit number of hidden networks attach to scan - */ - private static final int NUMBER_OF_HIDDEN_NETWORK_FOR_ONE_SCAN = 100; - - private final WifiContext mContext; - private final Resources mResources; - private final Handler mHandler; - private final AppOpsManager mAppOps; - private final ActivityManager mActivityManager; - private final NotificationManager mNotificationManager; - private final NetworkScoreManager mNetworkScoreManager; - private final PackageManager mPackageManager; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final WifiConfigManager mWifiConfigManager; - private final WifiMetrics mWifiMetrics; - private final WifiInjector mWifiInjector; - private final FrameworkFacade mFrameworkFacade; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - private final WifiKeyStore mWifiKeyStore; - // Keep order of network connection. - private final LruConnectionTracker mLruConnectionTracker; - - /** - * Per app meta data to store network suggestions, status, etc for each app providing network - * suggestions on the device. - */ - public static class PerAppInfo { - /** - * UID of the app. - */ - public int uid; - /** - * Package Name of the app. - */ - public final String packageName; - /** - * First Feature in the package that registered the suggestion - */ - public final String featureId; - /** - * Set of active network suggestions provided by the app. - */ - public final Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = new HashSet<>(); - /** - * Whether we have shown the user a notification for this app. - */ - public boolean hasUserApproved = false; - /** - * Carrier Id of SIM which give app carrier privileges. - */ - public int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; - - /** Stores the max size of the {@link #extNetworkSuggestions} list ever for this app */ - public int maxSize = 0; - - public PerAppInfo(int uid, @NonNull String packageName, @Nullable String featureId) { - this.uid = uid; - this.packageName = packageName; - this.featureId = featureId; - } - - /** - * Needed for migration of config store data. - */ - public void setUid(int uid) { - if (this.uid == Process.INVALID_UID) { - this.uid = uid; - } - // else ignored. - } - - /** - * Returns true if this app has the necessary approvals to place network suggestions. - */ - private boolean isApproved(@Nullable String activeScorerPkg) { - return hasUserApproved || isExemptFromUserApproval(activeScorerPkg); - } - - /** - * Returns true if this app can suggest networks without user approval. - */ - private boolean isExemptFromUserApproval(@Nullable String activeScorerPkg) { - final boolean isCarrierPrivileged = carrierId != TelephonyManager.UNKNOWN_CARRIER_ID; - if (isCarrierPrivileged) { - return true; - } - return packageName.equals(activeScorerPkg); - } - - // This is only needed for comparison in unit tests. - @Override - public boolean equals(Object other) { - if (other == null) return false; - if (!(other instanceof PerAppInfo)) return false; - PerAppInfo otherPerAppInfo = (PerAppInfo) other; - return uid == otherPerAppInfo.uid - && TextUtils.equals(packageName, otherPerAppInfo.packageName) - && Objects.equals(extNetworkSuggestions, otherPerAppInfo.extNetworkSuggestions) - && hasUserApproved == otherPerAppInfo.hasUserApproved; - } - - // This is only needed for comparison in unit tests. - @Override - public int hashCode() { - return Objects.hash(uid, packageName, extNetworkSuggestions, hasUserApproved); - } - - @Override - public String toString() { - return new StringBuilder("PerAppInfo[ ") - .append("uid=").append(uid) - .append(", packageName=").append(packageName) - .append(", hasUserApproved=").append(hasUserApproved) - .append(", suggestions=").append(extNetworkSuggestions) - .append(" ]") - .toString(); - } - } - - /** - * Internal container class which holds a network suggestion and a pointer to the - * {@link PerAppInfo} entry from {@link #mActiveNetworkSuggestionsPerApp} corresponding to the - * app that made the suggestion. - */ - public static class ExtendedWifiNetworkSuggestion { - public final WifiNetworkSuggestion wns; - // Store the pointer to the corresponding app's meta data. - public final PerAppInfo perAppInfo; - public boolean isAutojoinEnabled; - - public ExtendedWifiNetworkSuggestion(@NonNull WifiNetworkSuggestion wns, - @NonNull PerAppInfo perAppInfo, - boolean isAutoJoinEnabled) { - this.wns = wns; - this.perAppInfo = perAppInfo; - this.isAutojoinEnabled = isAutoJoinEnabled; - this.wns.wifiConfiguration.fromWifiNetworkSuggestion = true; - this.wns.wifiConfiguration.ephemeral = true; - this.wns.wifiConfiguration.creatorName = perAppInfo.packageName; - this.wns.wifiConfiguration.creatorUid = perAppInfo.uid; - } - - @Override - public int hashCode() { - return Objects.hash(wns, perAppInfo.uid, perAppInfo.packageName); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof ExtendedWifiNetworkSuggestion)) { - return false; - } - ExtendedWifiNetworkSuggestion other = (ExtendedWifiNetworkSuggestion) obj; - return wns.equals(other.wns) - && perAppInfo.uid == other.perAppInfo.uid - && TextUtils.equals(perAppInfo.packageName, other.perAppInfo.packageName); - } - - /** - * Helper method to set the carrier Id. - */ - public void setCarrierId(int carrierId) { - if (wns.passpointConfiguration == null) { - wns.wifiConfiguration.carrierId = carrierId; - } else { - wns.passpointConfiguration.setCarrierId(carrierId); - } - } - - @Override - public String toString() { - return new StringBuilder(wns.toString()) - .append(", isAutoJoinEnabled=").append(isAutojoinEnabled) - .toString(); - } - - /** - * Convert from {@link WifiNetworkSuggestion} to a new instance of - * {@link ExtendedWifiNetworkSuggestion}. - */ - public static ExtendedWifiNetworkSuggestion fromWns(@NonNull WifiNetworkSuggestion wns, - @NonNull PerAppInfo perAppInfo, boolean isAutoJoinEnabled) { - return new ExtendedWifiNetworkSuggestion(wns, perAppInfo, isAutoJoinEnabled); - } - - /** - * Create a {@link WifiConfiguration} from suggestion for framework internal use. - */ - public WifiConfiguration createInternalWifiConfiguration() { - WifiConfiguration config = new WifiConfiguration(wns.getWifiConfiguration()); - config.allowAutojoin = isAutojoinEnabled; - return config; - } - } - - /** - * Map of package name of an app to the set of active network suggestions provided by the app. - */ - private final Map<String, PerAppInfo> mActiveNetworkSuggestionsPerApp = new HashMap<>(); - /** - * Map of package name of an app to the app ops changed listener for the app. - */ - private final Map<String, AppOpsChangedListener> mAppOpsChangedListenerPerApp = new HashMap<>(); - /** - * Map maintained to help lookup all the network suggestions (with no bssid) that match a - * provided scan result. - * Note: - * <li>There could be multiple suggestions (provided by different apps) that match a single - * scan result.</li> - * <li>Adding/Removing to this set for scan result lookup is expensive. But, we expect scan - * result lookup to happen much more often than apps modifying network suggestions.</li> - */ - private final Map<ScanResultMatchInfo, Set<ExtendedWifiNetworkSuggestion>> - mActiveScanResultMatchInfoWithNoBssid = new HashMap<>(); - /** - * Map maintained to help lookup all the network suggestions (with bssid) that match a provided - * scan result. - * Note: - * <li>There could be multiple suggestions (provided by different apps) that match a single - * scan result.</li> - * <li>Adding/Removing to this set for scan result lookup is expensive. But, we expect scan - * result lookup to happen much more often than apps modifying network suggestions.</li> - */ - private final Map<Pair<ScanResultMatchInfo, MacAddress>, Set<ExtendedWifiNetworkSuggestion>> - mActiveScanResultMatchInfoWithBssid = new HashMap<>(); - /** - * List of {@link WifiNetworkSuggestion} matching the current connected network. - */ - private Set<ExtendedWifiNetworkSuggestion> mActiveNetworkSuggestionsMatchingConnection; - - private final Map<String, Set<ExtendedWifiNetworkSuggestion>> - mPasspointInfo = new HashMap<>(); - - private final HashMap<String, ExternalCallbackTracker<ISuggestionConnectionStatusListener>> - mSuggestionStatusListenerPerApp = new HashMap<>(); - - /** - * Store the suggestion update listeners. - */ - private final List<OnSuggestionUpdateListener> mListeners = new ArrayList<>(); - - /** - * Intent filter for processing notification actions. - */ - private final IntentFilter mIntentFilter; - - /** - * Verbose logging flag. - */ - private boolean mVerboseLoggingEnabled = false; - /** - * Indicates that we have new data to serialize. - */ - private boolean mHasNewDataToSerialize = false; - /** - * Indicates if the user approval notification is active. - */ - private boolean mUserApprovalUiActive = false; - - private boolean mIsLastUserApprovalUiDialog = false; - - private boolean mUserDataLoaded = false; - - /** - * Listener for app-ops changes for active suggestor apps. - */ - private final class AppOpsChangedListener implements AppOpsManager.OnOpChangedListener { - private final String mPackageName; - private final int mUid; - - AppOpsChangedListener(@NonNull String packageName, int uid) { - mPackageName = packageName; - mUid = uid; - } - - @Override - public void onOpChanged(String op, String packageName) { - mHandler.post(() -> { - if (!mPackageName.equals(packageName)) return; - if (!OPSTR_CHANGE_WIFI_STATE.equals(op)) return; - - // Ensure the uid to package mapping is still correct. - try { - mAppOps.checkPackage(mUid, mPackageName); - } catch (SecurityException e) { - Log.wtf(TAG, "Invalid uid/package" + packageName); - return; - } - - if (mAppOps.unsafeCheckOpNoThrow(OPSTR_CHANGE_WIFI_STATE, mUid, mPackageName) - == AppOpsManager.MODE_IGNORED) { - Log.i(TAG, "User disallowed change wifi state for " + packageName); - // User disabled the app, remove app from database. We want the notification - // again if the user enabled the app-op back. - removeApp(mPackageName); - mWifiMetrics.incrementNetworkSuggestionUserRevokePermission(); - } - }); - } - }; - - /** - * Module to interact with the wifi config store. - */ - private class NetworkSuggestionDataSource implements NetworkSuggestionStoreData.DataSource { - @Override - public Map<String, PerAppInfo> toSerialize() { - for (Map.Entry<String, PerAppInfo> entry : mActiveNetworkSuggestionsPerApp.entrySet()) { - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = - entry.getValue().extNetworkSuggestions; - for (ExtendedWifiNetworkSuggestion ewns : extNetworkSuggestions) { - if (ewns.wns.passpointConfiguration != null) { - continue; - } - ewns.wns.wifiConfiguration.isMostRecentlyConnected = mLruConnectionTracker - .isMostRecentlyConnected(ewns.createInternalWifiConfiguration()); - } - } - // Clear the flag after writing to disk. - // TODO(b/115504887): Don't reset the flag on write failure. - mHasNewDataToSerialize = false; - return mActiveNetworkSuggestionsPerApp; - } - - @Override - public void fromDeserialized(Map<String, PerAppInfo> networkSuggestionsMap) { - mActiveNetworkSuggestionsPerApp.clear(); - mActiveNetworkSuggestionsPerApp.putAll(networkSuggestionsMap); - // Build the scan cache. - for (Map.Entry<String, PerAppInfo> entry : networkSuggestionsMap.entrySet()) { - String packageName = entry.getKey(); - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = - entry.getValue().extNetworkSuggestions; - if (!extNetworkSuggestions.isEmpty()) { - // Start tracking app-op changes from the app if they have active suggestions. - startTrackingAppOpsChange(packageName, - extNetworkSuggestions.iterator().next().perAppInfo.uid); - } - for (ExtendedWifiNetworkSuggestion ewns : extNetworkSuggestions) { - if (ewns.wns.passpointConfiguration != null) { - addToPasspointInfoMap(ewns); - } else { - if (ewns.wns.wifiConfiguration.isMostRecentlyConnected) { - mLruConnectionTracker - .addNetwork(ewns.createInternalWifiConfiguration()); - } - addToScanResultMatchInfoMap(ewns); - } - } - } - mUserDataLoaded = true; - } - - @Override - public void reset() { - mUserDataLoaded = false; - mActiveNetworkSuggestionsPerApp.clear(); - mActiveScanResultMatchInfoWithBssid.clear(); - mActiveScanResultMatchInfoWithNoBssid.clear(); - mPasspointInfo.clear(); - } - - @Override - public boolean hasNewDataToSerialize() { - return mHasNewDataToSerialize; - } - } - - private void handleUserAllowAction(int uid, String packageName) { - Log.i(TAG, "User clicked to allow app"); - // Set the user approved flag. - setHasUserApprovedForApp(true, packageName); - mUserApprovalUiActive = false; - mWifiMetrics.addUserApprovalSuggestionAppUiReaction( - ACTION_USER_ALLOWED_APP, - mIsLastUserApprovalUiDialog); - } - - private void handleUserDisallowAction(int uid, String packageName) { - Log.i(TAG, "User clicked to disallow app"); - // Set the user approved flag. - setHasUserApprovedForApp(false, packageName); - // Take away CHANGE_WIFI_STATE app-ops from the app. - mAppOps.setMode(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, uid, packageName, - MODE_IGNORED); - mUserApprovalUiActive = false; - mWifiMetrics.addUserApprovalSuggestionAppUiReaction( - ACTION_USER_DISALLOWED_APP, - mIsLastUserApprovalUiDialog); - } - - private void handleUserDismissAction() { - Log.i(TAG, "User dismissed the notification"); - mUserApprovalUiActive = false; - mWifiMetrics.addUserApprovalSuggestionAppUiReaction( - ACTION_USER_DISMISS, - mIsLastUserApprovalUiDialog); - } - - private final BroadcastReceiver mBroadcastReceiver = - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); - int uid = intent.getIntExtra(EXTRA_UID, -1); - if (packageName == null || uid == -1) { - Log.e(TAG, "No package name or uid found in intent"); - return; - } - switch (intent.getAction()) { - case NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION: - handleUserAllowAction(uid, packageName); - break; - case NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION: - handleUserDisallowAction(uid, packageName); - break; - case NOTIFICATION_USER_DISMISSED_INTENT_ACTION: - handleUserDismissAction(); - return; // no need to cancel a dismissed notification, return. - default: - Log.e(TAG, "Unknown action " + intent.getAction()); - return; - } - // Clear notification once the user interacts with it. - mNotificationManager.cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - } - }; - - /** - * Interface for other modules to listen to the suggestion updated events. - */ - public interface OnSuggestionUpdateListener { - /** - * Invoked on suggestion being added or updated. - */ - void onSuggestionsAddedOrUpdated(@NonNull List<WifiNetworkSuggestion> addedSuggestions); - /** - * Invoked on suggestion being removed. - */ - void onSuggestionsRemoved(@NonNull List<WifiNetworkSuggestion> removedSuggestions); - } - - private final class UserApproveCarrierListener implements - WifiCarrierInfoManager.OnUserApproveCarrierListener { - - @Override - public void onUserAllowed(int carrierId) { - restoreInitialAutojoinForCarrierId(carrierId); - } - } - - public WifiNetworkSuggestionsManager(WifiContext context, Handler handler, - WifiInjector wifiInjector, WifiPermissionsUtil wifiPermissionsUtil, - WifiConfigManager wifiConfigManager, WifiConfigStore wifiConfigStore, - WifiMetrics wifiMetrics, WifiCarrierInfoManager wifiCarrierInfoManager, - WifiKeyStore keyStore, LruConnectionTracker lruConnectionTracker) { - mContext = context; - mResources = context.getResources(); - mHandler = handler; - mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - mActivityManager = context.getSystemService(ActivityManager.class); - mNotificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - mNetworkScoreManager = context.getSystemService(NetworkScoreManager.class); - mPackageManager = context.getPackageManager(); - mWifiInjector = wifiInjector; - mFrameworkFacade = mWifiInjector.getFrameworkFacade(); - mWifiPermissionsUtil = wifiPermissionsUtil; - mWifiConfigManager = wifiConfigManager; - mWifiMetrics = wifiMetrics; - mWifiCarrierInfoManager = wifiCarrierInfoManager; - mWifiKeyStore = keyStore; - - // register the data store for serializing/deserializing data. - wifiConfigStore.registerStoreData( - wifiInjector.makeNetworkSuggestionStoreData(new NetworkSuggestionDataSource())); - - mWifiCarrierInfoManager.addImsiExemptionUserApprovalListener( - new UserApproveCarrierListener()); - - // Register broadcast receiver for UI interactions. - mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION); - mIntentFilter.addAction(NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION); - mIntentFilter.addAction(NOTIFICATION_USER_DISMISSED_INTENT_ACTION); - - mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, handler); - mLruConnectionTracker = lruConnectionTracker; - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = verbose > 0; - } - - private void saveToStore() { - // Set the flag to let WifiConfigStore that we have new data to write. - mHasNewDataToSerialize = true; - if (!mWifiConfigManager.saveToStore(true)) { - Log.w(TAG, "Failed to save to store"); - } - } - - private void addToScanResultMatchInfoMap( - @NonNull ExtendedWifiNetworkSuggestion extNetworkSuggestion) { - ScanResultMatchInfo scanResultMatchInfo = - ScanResultMatchInfo.fromWifiConfiguration( - extNetworkSuggestion.wns.wifiConfiguration); - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestionsForScanResultMatchInfo; - if (!TextUtils.isEmpty(extNetworkSuggestion.wns.wifiConfiguration.BSSID)) { - Pair<ScanResultMatchInfo, MacAddress> lookupPair = - Pair.create(scanResultMatchInfo, - MacAddress.fromString( - extNetworkSuggestion.wns.wifiConfiguration.BSSID)); - extNetworkSuggestionsForScanResultMatchInfo = - mActiveScanResultMatchInfoWithBssid.get(lookupPair); - if (extNetworkSuggestionsForScanResultMatchInfo == null) { - extNetworkSuggestionsForScanResultMatchInfo = new HashSet<>(); - mActiveScanResultMatchInfoWithBssid.put( - lookupPair, extNetworkSuggestionsForScanResultMatchInfo); - } - } else { - extNetworkSuggestionsForScanResultMatchInfo = - mActiveScanResultMatchInfoWithNoBssid.get(scanResultMatchInfo); - if (extNetworkSuggestionsForScanResultMatchInfo == null) { - extNetworkSuggestionsForScanResultMatchInfo = new HashSet<>(); - mActiveScanResultMatchInfoWithNoBssid.put( - scanResultMatchInfo, extNetworkSuggestionsForScanResultMatchInfo); - } - } - extNetworkSuggestionsForScanResultMatchInfo.remove(extNetworkSuggestion); - extNetworkSuggestionsForScanResultMatchInfo.add(extNetworkSuggestion); - } - - private void removeFromScanResultMatchInfoMapAndRemoveRelatedScoreCard( - @NonNull ExtendedWifiNetworkSuggestion extNetworkSuggestion) { - ScanResultMatchInfo scanResultMatchInfo = - ScanResultMatchInfo.fromWifiConfiguration( - extNetworkSuggestion.wns.wifiConfiguration); - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestionsForScanResultMatchInfo; - if (!TextUtils.isEmpty(extNetworkSuggestion.wns.wifiConfiguration.BSSID)) { - Pair<ScanResultMatchInfo, MacAddress> lookupPair = - Pair.create(scanResultMatchInfo, - MacAddress.fromString( - extNetworkSuggestion.wns.wifiConfiguration.BSSID)); - extNetworkSuggestionsForScanResultMatchInfo = - mActiveScanResultMatchInfoWithBssid.get(lookupPair); - // This should never happen because we should have done necessary error checks in - // the parent method. - if (extNetworkSuggestionsForScanResultMatchInfo == null) { - Log.wtf(TAG, "No scan result match info found."); - return; - } - extNetworkSuggestionsForScanResultMatchInfo.remove(extNetworkSuggestion); - // Remove the set from map if empty. - if (extNetworkSuggestionsForScanResultMatchInfo.isEmpty()) { - mActiveScanResultMatchInfoWithBssid.remove(lookupPair); - if (!mActiveScanResultMatchInfoWithNoBssid.containsKey(scanResultMatchInfo)) { - removeNetworkFromScoreCard(extNetworkSuggestion.wns.wifiConfiguration); - mLruConnectionTracker.removeNetwork( - extNetworkSuggestion.wns.wifiConfiguration); - } - } - } else { - extNetworkSuggestionsForScanResultMatchInfo = - mActiveScanResultMatchInfoWithNoBssid.get(scanResultMatchInfo); - // This should never happen because we should have done necessary error checks in - // the parent method. - if (extNetworkSuggestionsForScanResultMatchInfo == null) { - Log.wtf(TAG, "No scan result match info found."); - return; - } - extNetworkSuggestionsForScanResultMatchInfo.remove(extNetworkSuggestion); - // Remove the set from map if empty. - if (extNetworkSuggestionsForScanResultMatchInfo.isEmpty()) { - mActiveScanResultMatchInfoWithNoBssid.remove(scanResultMatchInfo); - removeNetworkFromScoreCard(extNetworkSuggestion.wns.wifiConfiguration); - mLruConnectionTracker.removeNetwork( - extNetworkSuggestion.wns.wifiConfiguration); - } - } - } - - private void removeNetworkFromScoreCard(WifiConfiguration wifiConfiguration) { - WifiConfiguration existing = - mWifiConfigManager.getConfiguredNetwork(wifiConfiguration.getKey()); - // If there is a saved network, do not remove from the score card. - if (existing != null && !existing.fromWifiNetworkSuggestion) { - return; - } - mWifiInjector.getWifiScoreCard().removeNetwork(wifiConfiguration.SSID); - } - - private void addToPasspointInfoMap(ExtendedWifiNetworkSuggestion ewns) { - Set<ExtendedWifiNetworkSuggestion> extendedWifiNetworkSuggestions = - mPasspointInfo.get(ewns.wns.wifiConfiguration.FQDN); - if (extendedWifiNetworkSuggestions == null) { - extendedWifiNetworkSuggestions = new HashSet<>(); - } - extendedWifiNetworkSuggestions.add(ewns); - mPasspointInfo.put(ewns.wns.wifiConfiguration.FQDN, extendedWifiNetworkSuggestions); - } - - private void removeFromPassPointInfoMap(ExtendedWifiNetworkSuggestion ewns) { - Set<ExtendedWifiNetworkSuggestion> extendedWifiNetworkSuggestions = - mPasspointInfo.get(ewns.wns.wifiConfiguration.FQDN); - if (extendedWifiNetworkSuggestions == null - || !extendedWifiNetworkSuggestions.contains(ewns)) { - Log.wtf(TAG, "No Passpoint info found."); - return; - } - extendedWifiNetworkSuggestions.remove(ewns); - if (extendedWifiNetworkSuggestions.isEmpty()) { - mPasspointInfo.remove(ewns.wns.wifiConfiguration.FQDN); - } - } - - - // Issues a disconnect if the only serving network suggestion is removed. - private void removeFromConfigManagerIfServingNetworkSuggestionRemoved( - Collection<ExtendedWifiNetworkSuggestion> extNetworkSuggestionsRemoved) { - if (mActiveNetworkSuggestionsMatchingConnection == null - || mActiveNetworkSuggestionsMatchingConnection.isEmpty()) { - return; - } - WifiConfiguration activeWifiConfiguration = - mActiveNetworkSuggestionsMatchingConnection.iterator().next().wns.wifiConfiguration; - if (mActiveNetworkSuggestionsMatchingConnection.removeAll(extNetworkSuggestionsRemoved)) { - if (mActiveNetworkSuggestionsMatchingConnection.isEmpty()) { - Log.i(TAG, "Only network suggestion matching the connected network removed. " - + "Removing from config manager..."); - // will trigger a disconnect. - mWifiConfigManager.removeSuggestionConfiguredNetwork( - activeWifiConfiguration.getKey()); - } - } - } - - private void startTrackingAppOpsChange(@NonNull String packageName, int uid) { - AppOpsChangedListener appOpsChangedListener = - new AppOpsChangedListener(packageName, uid); - mAppOps.startWatchingMode(OPSTR_CHANGE_WIFI_STATE, packageName, appOpsChangedListener); - mAppOpsChangedListenerPerApp.put(packageName, appOpsChangedListener); - } - - /** - * Helper method to convert the incoming collection of public {@link WifiNetworkSuggestion} - * objects to a set of corresponding internal wrapper - * {@link ExtendedWifiNetworkSuggestion} objects. - */ - private Set<ExtendedWifiNetworkSuggestion> convertToExtendedWnsSet( - final Collection<WifiNetworkSuggestion> networkSuggestions, - final PerAppInfo perAppInfo) { - return networkSuggestions - .stream() - .collect(Collectors.mapping( - n -> ExtendedWifiNetworkSuggestion.fromWns(n, perAppInfo, - n.isInitialAutoJoinEnabled), - Collectors.toSet())); - } - - /** - * Helper method to convert the incoming collection of internal wrapper - * {@link ExtendedWifiNetworkSuggestion} objects to a set of corresponding public - * {@link WifiNetworkSuggestion} objects. - */ - private Set<WifiNetworkSuggestion> convertToWnsSet( - final Collection<ExtendedWifiNetworkSuggestion> extNetworkSuggestions) { - return extNetworkSuggestions - .stream() - .collect(Collectors.mapping( - n -> n.wns, - Collectors.toSet())); - } - - private void updateWifiConfigInWcmIfPresent( - WifiConfiguration newConfig, int uid, String packageName) { - WifiConfiguration configInWcm = - mWifiConfigManager.getConfiguredNetwork(newConfig.getKey()); - if (configInWcm == null) return; - // !suggestion - if (!configInWcm.fromWifiNetworkSuggestion) return; - // is suggestion from same app. - if (configInWcm.creatorUid != uid - || !TextUtils.equals(configInWcm.creatorName, packageName)) { - return; - } - NetworkUpdateResult result = mWifiConfigManager.addOrUpdateNetwork( - newConfig, uid, packageName); - if (!result.isSuccess()) { - Log.e(TAG, "Failed to update config in WifiConfigManager"); - } else { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Updated config in WifiConfigManager"); - } - } - } - - /** - * Add the provided list of network suggestions from the corresponding app's active list. - */ - public @WifiManager.NetworkSuggestionsStatusCode int add( - List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName, - @Nullable String featureId) { - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL; - } - if (!mUserDataLoaded) { - Log.e(TAG, "Add Network suggestion before boot complete is not allowed."); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL; - } - if (networkSuggestions == null || networkSuggestions.isEmpty()) { - Log.w(TAG, "Empty list of network suggestions for " + packageName + ". Ignoring"); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Adding " + networkSuggestions.size() + " networks from " + packageName); - } - if (!validateNetworkSuggestions(networkSuggestions)) { - Log.e(TAG, "Invalid suggestion add from app: " + packageName); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID; - } - if (!validateCarrierNetworkSuggestions(networkSuggestions, uid, packageName)) { - Log.e(TAG, "bad wifi suggestion from app: " + packageName); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED; - } - - int carrierId = mWifiCarrierInfoManager - .getCarrierIdForPackageWithCarrierPrivileges(packageName); - final String activeScorerPackage = mNetworkScoreManager.getActiveScorerPackage(); - PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); - if (perAppInfo == null) { - perAppInfo = new PerAppInfo(uid, packageName, featureId); - mActiveNetworkSuggestionsPerApp.put(packageName, perAppInfo); - if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)) { - Log.i(TAG, "Setting the carrier provisioning app approved"); - perAppInfo.hasUserApproved = true; - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - APP_TYPE_NETWORK_PROVISIONING); - } else if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { - Log.i(TAG, "Setting the carrier privileged app approved"); - perAppInfo.carrierId = carrierId; - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - APP_TYPE_CARRIER_PRIVILEGED); - } else if (perAppInfo.packageName.equals(activeScorerPackage)) { - Log.i(TAG, "Exempting the active scorer app"); - // nothing more to do, user approval related checks are done at network selection - // time (which also takes care of any dynamic changes in active scorer). - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - APP_TYPE_NON_PRIVILEGED); - } else { - if (isSuggestionFromForegroundApp(packageName)) { - sendUserApprovalDialog(packageName, uid); - } else { - sendUserApprovalNotificationIfNotApproved(packageName, uid); - } - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - APP_TYPE_NON_PRIVILEGED); - } - } - // If PerAppInfo is upgrade from pre-R, uid may not be set. - perAppInfo.setUid(uid); - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = - convertToExtendedWnsSet(networkSuggestions, perAppInfo); - boolean isLowRamDevice = mActivityManager.isLowRamDevice(); - int networkSuggestionsMaxPerApp = - WifiManager.getMaxNumberOfNetworkSuggestionsPerApp(isLowRamDevice); - if (perAppInfo.extNetworkSuggestions.size() + extNetworkSuggestions.size() - > networkSuggestionsMaxPerApp) { - Set<ExtendedWifiNetworkSuggestion> savedNetworkSuggestions = - new HashSet<>(perAppInfo.extNetworkSuggestions); - savedNetworkSuggestions.addAll(extNetworkSuggestions); - if (savedNetworkSuggestions.size() > networkSuggestionsMaxPerApp) { - Log.e(TAG, "Failed to add network suggestions for " + packageName - + ". Exceeds max per app, current list size: " - + perAppInfo.extNetworkSuggestions.size() - + ", new list size: " - + extNetworkSuggestions.size()); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP; - } - } - if (perAppInfo.extNetworkSuggestions.isEmpty()) { - // Start tracking app-op changes from the app if they have active suggestions. - startTrackingAppOpsChange(packageName, uid); - } - - for (ExtendedWifiNetworkSuggestion ewns: extNetworkSuggestions) { - if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { - ewns.setCarrierId(carrierId); - } - // If network has no IMSI protection and user didn't approve exemption, make it initial - // auto join disabled - if (isSimBasedSuggestion(ewns)) { - int subId = mWifiCarrierInfoManager - .getMatchingSubId(getCarrierIdFromSuggestion(ewns)); - if (!(mWifiCarrierInfoManager.requiresImsiEncryption(subId) - || mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier( - getCarrierIdFromSuggestion(ewns)))) { - ewns.isAutojoinEnabled = false; - } - } - if (ewns.wns.passpointConfiguration == null) { - if (ewns.wns.wifiConfiguration.isEnterprise()) { - if (!mWifiKeyStore.updateNetworkKeys(ewns.wns.wifiConfiguration, null)) { - Log.e(TAG, "Enterprise network install failure for SSID: " - + ewns.wns.wifiConfiguration.SSID); - continue; - } - } - // If we have a config in WifiConfigManager for this suggestion, update - // WifiConfigManager with the latest WifiConfig. - // Note: Similar logic is present in PasspointManager for passpoint networks. - updateWifiConfigInWcmIfPresent( - ewns.createInternalWifiConfiguration(), uid, packageName); - addToScanResultMatchInfoMap(ewns); - } else { - ewns.wns.passpointConfiguration.setAutojoinEnabled(ewns.isAutojoinEnabled); - // Install Passpoint config, if failure, ignore that suggestion - if (!mWifiInjector.getPasspointManager().addOrUpdateProvider( - ewns.wns.passpointConfiguration, uid, - packageName, true, !ewns.wns.isUntrusted())) { - Log.e(TAG, "Passpoint profile install failure for FQDN: " - + ewns.wns.wifiConfiguration.FQDN); - continue; - } - addToPasspointInfoMap(ewns); - } - perAppInfo.extNetworkSuggestions.remove(ewns); - perAppInfo.extNetworkSuggestions.add(ewns); - } - for (OnSuggestionUpdateListener listener : mListeners) { - listener.onSuggestionsAddedOrUpdated(networkSuggestions); - } - // Update the max size for this app. - perAppInfo.maxSize = Math.max(perAppInfo.extNetworkSuggestions.size(), perAppInfo.maxSize); - saveToStore(); - mWifiMetrics.incrementNetworkSuggestionApiNumModification(); - mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(getAllMaxSizes()); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; - } - - private int getCarrierIdFromSuggestion(ExtendedWifiNetworkSuggestion ewns) { - if (ewns.wns.passpointConfiguration == null) { - return ewns.wns.wifiConfiguration.carrierId; - } - return ewns.wns.passpointConfiguration.getCarrierId(); - } - - private boolean isSimBasedSuggestion(ExtendedWifiNetworkSuggestion ewns) { - if (ewns.wns.passpointConfiguration == null) { - return ewns.wns.wifiConfiguration.enterpriseConfig != null - && ewns.wns.wifiConfiguration.enterpriseConfig.isAuthenticationSimBased(); - } else { - return ewns.wns.passpointConfiguration.getCredential().getSimCredential() != null; - } - } - - private boolean validateNetworkSuggestions(List<WifiNetworkSuggestion> networkSuggestions) { - for (WifiNetworkSuggestion wns : networkSuggestions) { - if (wns == null || wns.wifiConfiguration == null) { - return false; - } - if (wns.passpointConfiguration == null) { - if (!WifiConfigurationUtil.validate(wns.wifiConfiguration, - WifiConfigurationUtil.VALIDATE_FOR_ADD)) { - return false; - } - if (wns.wifiConfiguration.isEnterprise() - && wns.wifiConfiguration.enterpriseConfig.isInsecure()) { - Log.e(TAG, "Insecure enterprise suggestion is invalid."); - return false; - } - - } else { - if (!wns.passpointConfiguration.validate()) { - return false; - } - } - } - return true; - } - - private boolean validateCarrierNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName) { - if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid) - || mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(packageName) - != TelephonyManager.UNKNOWN_CARRIER_ID) { - return true; - } - // If an app doesn't have carrier privileges or carrier provisioning permission, suggests - // SIM-based network and sets CarrierId are illegal. - for (WifiNetworkSuggestion suggestion : networkSuggestions) { - WifiConfiguration wifiConfiguration = suggestion.wifiConfiguration; - PasspointConfiguration passpointConfiguration = suggestion.passpointConfiguration; - if (passpointConfiguration == null) { - if (wifiConfiguration.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { - return false; - } - if (wifiConfiguration.enterpriseConfig != null - && wifiConfiguration.enterpriseConfig.isAuthenticationSimBased()) { - return false; - } - } else { - if (passpointConfiguration.getCarrierId() != TelephonyManager.UNKNOWN_CARRIER_ID) { - return false; - } - if (passpointConfiguration.getCredential() != null - && passpointConfiguration.getCredential().getSimCredential() != null) { - return false; - } - } - } - return true; - } - - private void stopTrackingAppOpsChange(@NonNull String packageName) { - AppOpsChangedListener appOpsChangedListener = - mAppOpsChangedListenerPerApp.remove(packageName); - if (appOpsChangedListener == null) { - Log.wtf(TAG, "No app ops listener found for " + packageName); - return; - } - mAppOps.stopWatchingMode(appOpsChangedListener); - } - - /** - * Remove provided list from that App active list. If provided list is empty, will remove all. - * Will disconnect network if current connected network is in the remove list. - */ - private void removeInternal( - @NonNull Collection<ExtendedWifiNetworkSuggestion> extNetworkSuggestions, - @NonNull String packageName, - @NonNull PerAppInfo perAppInfo) { - // Get internal suggestions - Set<ExtendedWifiNetworkSuggestion> removingExtSuggestions = - new HashSet<>(perAppInfo.extNetworkSuggestions); - if (!extNetworkSuggestions.isEmpty()) { - // Keep the internal suggestions need to remove. - removingExtSuggestions.retainAll(extNetworkSuggestions); - perAppInfo.extNetworkSuggestions.removeAll(extNetworkSuggestions); - } else { - // empty list is used to clear everything for the app. Store a copy for use below. - perAppInfo.extNetworkSuggestions.clear(); - } - if (perAppInfo.extNetworkSuggestions.isEmpty()) { - // Note: We don't remove the app entry even if there is no active suggestions because - // we want to keep the notification state for all apps that have ever provided - // suggestions. - if (mVerboseLoggingEnabled) Log.v(TAG, "No active suggestions for " + packageName); - // Stop tracking app-op changes from the app if they don't have active suggestions. - stopTrackingAppOpsChange(packageName); - } - // Clear the cache. - List<WifiNetworkSuggestion> removingSuggestions = new ArrayList<>(); - for (ExtendedWifiNetworkSuggestion ewns : removingExtSuggestions) { - if (ewns.wns.passpointConfiguration != null) { - // Clear the Passpoint config. - mWifiInjector.getPasspointManager().removeProvider( - ewns.perAppInfo.uid, - false, - ewns.wns.passpointConfiguration.getUniqueId(), null); - removeFromPassPointInfoMap(ewns); - } else { - if (ewns.wns.wifiConfiguration.isEnterprise()) { - mWifiKeyStore.removeKeys(ewns.wns.wifiConfiguration.enterpriseConfig); - } - removeFromScanResultMatchInfoMapAndRemoveRelatedScoreCard(ewns); - } - removingSuggestions.add(ewns.wns); - } - for (OnSuggestionUpdateListener listener : mListeners) { - listener.onSuggestionsRemoved(removingSuggestions); - } - // Disconnect suggested network if connected - removeFromConfigManagerIfServingNetworkSuggestionRemoved(removingExtSuggestions); - } - - /** - * Remove the provided list of network suggestions from the corresponding app's active list. - */ - public @WifiManager.NetworkSuggestionsStatusCode int remove( - List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName) { - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL; - } - if (!mUserDataLoaded) { - Log.e(TAG, "Remove Network suggestion before boot complete is not allowed."); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL; - } - if (networkSuggestions == null) { - Log.w(TAG, "Null list of network suggestions for " + packageName + ". Ignoring"); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Removing " + networkSuggestions.size() + " networks from " + packageName); - } - - if (!validateNetworkSuggestions(networkSuggestions)) { - Log.e(TAG, "Invalid suggestion remove from app: " + packageName); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID; - } - PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); - if (perAppInfo == null) { - Log.e(TAG, "Failed to remove network suggestions for " + packageName - + ". No network suggestions found"); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID; - } - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = - convertToExtendedWnsSet(networkSuggestions, perAppInfo); - // check if all the request network suggestions are present in the active list. - if (!extNetworkSuggestions.isEmpty() - && !perAppInfo.extNetworkSuggestions.containsAll(extNetworkSuggestions)) { - Log.e(TAG, "Failed to remove network suggestions for " + packageName - + ". Network suggestions not found in active network suggestions"); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID; - } - removeInternal(extNetworkSuggestions, packageName, perAppInfo); - saveToStore(); - mWifiMetrics.incrementNetworkSuggestionApiNumModification(); - mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(getAllMaxSizes()); - return WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; - } - - /** - * Remove all tracking of the app that has been uninstalled. - */ - public void removeApp(@NonNull String packageName) { - PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); - if (perAppInfo == null) return; - removeInternal(Collections.EMPTY_LIST, packageName, perAppInfo); - // Remove the package fully from the internal database. - mActiveNetworkSuggestionsPerApp.remove(packageName); - ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenerTracker = - mSuggestionStatusListenerPerApp.remove(packageName); - if (listenerTracker != null) listenerTracker.clear(); - saveToStore(); - Log.i(TAG, "Removed " + packageName); - } - - /** - * Get all network suggestion for target App - * @return List of WifiNetworkSuggestions - */ - public @NonNull List<WifiNetworkSuggestion> get(@NonNull String packageName, int uid) { - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return networkSuggestionList; - } - if (!mUserDataLoaded) { - Log.e(TAG, "Get Network suggestion before boot complete is not allowed."); - return networkSuggestionList; - } - PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); - // if App never suggested return empty list. - if (perAppInfo == null) return networkSuggestionList; - for (ExtendedWifiNetworkSuggestion extendedSuggestion : perAppInfo.extNetworkSuggestions) { - networkSuggestionList.add(extendedSuggestion.wns); - } - return networkSuggestionList; - } - - /** - * Clear all internal state (for network settings reset). - */ - public void clear() { - Iterator<Map.Entry<String, PerAppInfo>> iter = - mActiveNetworkSuggestionsPerApp.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry<String, PerAppInfo> entry = iter.next(); - removeInternal(Collections.EMPTY_LIST, entry.getKey(), entry.getValue()); - iter.remove(); - } - mSuggestionStatusListenerPerApp.clear(); - saveToStore(); - Log.i(TAG, "Cleared all internal state"); - } - - /** - * Check if network suggestions are enabled or disabled for the app. - */ - public boolean hasUserApprovedForApp(String packageName) { - PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); - if (perAppInfo == null) return false; - - return perAppInfo.hasUserApproved; - } - - /** - * Enable or Disable network suggestions for the app. - */ - public void setHasUserApprovedForApp(boolean approved, String packageName) { - PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); - if (perAppInfo == null) return; - - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Setting the app " + packageName - + (approved ? " approved" : " not approved")); - } - perAppInfo.hasUserApproved = approved; - saveToStore(); - } - - /** - * When user approve the IMSI protection exemption for carrier, restore the initial auto join - * configure. If user already change it to enabled, keep that choice. - */ - private void restoreInitialAutojoinForCarrierId(int carrierId) { - for (PerAppInfo appInfo : mActiveNetworkSuggestionsPerApp.values()) { - for (ExtendedWifiNetworkSuggestion ewns : appInfo.extNetworkSuggestions) { - if (!(isSimBasedSuggestion(ewns) - && getCarrierIdFromSuggestion(ewns) == carrierId)) { - continue; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Restore auto-join for suggestion: " + ewns); - } - ewns.isAutojoinEnabled |= ewns.wns.isInitialAutoJoinEnabled; - // Restore passpoint provider auto join. - if (ewns.wns.passpointConfiguration != null) { - mWifiInjector.getPasspointManager() - .enableAutojoin(ewns.wns.passpointConfiguration.getUniqueId(), - null, ewns.isAutojoinEnabled); - } - } - } - } - - /** - * Returns a set of all network suggestions across all apps. - */ - @VisibleForTesting - public Set<WifiNetworkSuggestion> getAllNetworkSuggestions() { - return mActiveNetworkSuggestionsPerApp.values() - .stream() - .flatMap(e -> convertToWnsSet(e.extNetworkSuggestions) - .stream()) - .collect(Collectors.toSet()); - } - - /** - * Returns a set of all network suggestions across all apps that have been approved by user. - */ - public Set<WifiNetworkSuggestion> getAllApprovedNetworkSuggestions() { - final String activeScorerPackage = mNetworkScoreManager.getActiveScorerPackage(); - return mActiveNetworkSuggestionsPerApp.values() - .stream() - .filter(e -> e.isApproved(activeScorerPackage)) - .flatMap(e -> convertToWnsSet(e.extNetworkSuggestions) - .stream()) - .collect(Collectors.toSet()); - } - - /** - * Get all user approved, non-passpoint networks from suggestion. - */ - public List<WifiConfiguration> getAllScanOptimizationSuggestionNetworks() { - List<WifiConfiguration> networks = new ArrayList<>(); - final String activeScorerPackage = mNetworkScoreManager.getActiveScorerPackage(); - for (PerAppInfo info : mActiveNetworkSuggestionsPerApp.values()) { - if (!info.isApproved(activeScorerPackage)) { - continue; - } - for (ExtendedWifiNetworkSuggestion ewns : info.extNetworkSuggestions) { - if (ewns.wns.getPasspointConfig() != null) { - continue; - } - WifiConfiguration network = mWifiConfigManager - .getConfiguredNetwork(ewns.wns.getWifiConfiguration().getKey()); - if (network == null) { - network = ewns.createInternalWifiConfiguration(); - } - networks.add(network); - } - } - return networks; - } - - private List<Integer> getAllMaxSizes() { - return mActiveNetworkSuggestionsPerApp.values() - .stream() - .map(e -> e.maxSize) - .collect(Collectors.toList()); - } - - private PendingIntent getPrivateBroadcast(@NonNull String action, - @NonNull Pair<String, String> extra1, @NonNull Pair<String, Integer> extra2) { - Intent intent = new Intent(action) - .setPackage(mWifiInjector.getWifiStackPackageName()) - .putExtra(extra1.first, extra1.second) - .putExtra(extra2.first, extra2.second); - return mFrameworkFacade.getBroadcast(mContext, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - } - - private @NonNull CharSequence getAppName(@NonNull String packageName, int uid) { - ApplicationInfo applicationInfo = null; - try { - applicationInfo = mContext.getPackageManager().getApplicationInfoAsUser( - packageName, 0, UserHandle.getUserHandleForUid(uid)); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Failed to find app name for " + packageName); - return ""; - } - CharSequence appName = mPackageManager.getApplicationLabel(applicationInfo); - return (appName != null) ? appName : ""; - } - - /** - * Check if the request came from foreground app. - */ - private boolean isSuggestionFromForegroundApp(@NonNull String packageName) { - try { - return mActivityManager.getPackageImportance(packageName) - <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; - } catch (SecurityException e) { - Log.e(TAG, "Failed to check the app state", e); - return false; - } - } - - private void sendUserApprovalDialog(@NonNull String packageName, int uid) { - CharSequence appName = getAppName(packageName, uid); - AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) - .setTitle(mResources.getString(R.string.wifi_suggestion_title)) - .setMessage(mResources.getString(R.string.wifi_suggestion_content, appName)) - .setPositiveButton( - mResources.getText(R.string.wifi_suggestion_action_allow_app), - (d, which) -> mHandler.post( - () -> handleUserAllowAction(uid, packageName))) - .setNegativeButton( - mResources.getText(R.string.wifi_suggestion_action_disallow_app), - (d, which) -> mHandler.post( - () -> handleUserDisallowAction(uid, packageName))) - .setOnDismissListener( - (d) -> mHandler.post(() -> handleUserDismissAction())) - .setOnCancelListener( - (d) -> mHandler.post(() -> handleUserDismissAction())) - .create(); - dialog.setCanceledOnTouchOutside(false); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - dialog.getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); - dialog.show(); - mUserApprovalUiActive = true; - mIsLastUserApprovalUiDialog = true; - } - - private void sendUserApprovalNotification(@NonNull String packageName, int uid) { - Notification.Action userAllowAppNotificationAction = - new Notification.Action.Builder(null, - mResources.getText(R.string.wifi_suggestion_action_allow_app), - getPrivateBroadcast(NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION, - Pair.create(EXTRA_PACKAGE_NAME, packageName), - Pair.create(EXTRA_UID, uid))) - .build(); - Notification.Action userDisallowAppNotificationAction = - new Notification.Action.Builder(null, - mResources.getText(R.string.wifi_suggestion_action_disallow_app), - getPrivateBroadcast(NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION, - Pair.create(EXTRA_PACKAGE_NAME, packageName), - Pair.create(EXTRA_UID, uid))) - .build(); - - CharSequence appName = getAppName(packageName, uid); - Notification notification = mFrameworkFacade.makeNotificationBuilder( - mContext, WifiService.NOTIFICATION_NETWORK_STATUS) - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range)) - .setTicker(mResources.getString(R.string.wifi_suggestion_title)) - .setContentTitle(mResources.getString(R.string.wifi_suggestion_title)) - .setStyle(new Notification.BigTextStyle() - .bigText(mResources.getString(R.string.wifi_suggestion_content, appName))) - .setDeleteIntent(getPrivateBroadcast(NOTIFICATION_USER_DISMISSED_INTENT_ACTION, - Pair.create(EXTRA_PACKAGE_NAME, packageName), Pair.create(EXTRA_UID, uid))) - .setShowWhen(false) - .setLocalOnly(true) - .setColor(mResources.getColor(android.R.color.system_notification_accent_color, - mContext.getTheme())) - .addAction(userAllowAppNotificationAction) - .addAction(userDisallowAppNotificationAction) - .build(); - - // Post the notification. - mNotificationManager.notify( - SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE, notification); - mUserApprovalUiActive = true; - mIsLastUserApprovalUiDialog = false; - } - - /** - * Send user approval notification if the app is not approved - * @param packageName app package name - * @param uid app UID - * @return true if app is not approved and send notification. - */ - private boolean sendUserApprovalNotificationIfNotApproved( - @NonNull String packageName, @NonNull int uid) { - if (!mActiveNetworkSuggestionsPerApp.containsKey(packageName)) { - Log.wtf(TAG, "AppInfo is missing for " + packageName); - return false; - } - if (mActiveNetworkSuggestionsPerApp.get(packageName).hasUserApproved) { - return false; // already approved. - } - - if (mUserApprovalUiActive) { - return false; // has active notification. - } - Log.i(TAG, "Sending user approval notification for " + packageName); - sendUserApprovalNotification(packageName, uid); - return true; - } - - private @Nullable Set<ExtendedWifiNetworkSuggestion> - getNetworkSuggestionsForScanResultMatchInfo( - @NonNull ScanResultMatchInfo scanResultMatchInfo, @Nullable MacAddress bssid) { - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = new HashSet<>(); - if (bssid != null) { - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestionsWithBssid = - mActiveScanResultMatchInfoWithBssid.get( - Pair.create(scanResultMatchInfo, bssid)); - if (matchingExtNetworkSuggestionsWithBssid != null) { - extNetworkSuggestions.addAll(matchingExtNetworkSuggestionsWithBssid); - } - } - Set<ExtendedWifiNetworkSuggestion> matchingNetworkSuggestionsWithNoBssid = - mActiveScanResultMatchInfoWithNoBssid.get(scanResultMatchInfo); - if (matchingNetworkSuggestionsWithNoBssid != null) { - extNetworkSuggestions.addAll(matchingNetworkSuggestionsWithNoBssid); - } - if (extNetworkSuggestions.isEmpty()) { - return null; - } - return extNetworkSuggestions; - } - - private @Nullable Set<ExtendedWifiNetworkSuggestion> getNetworkSuggestionsForFqdnMatch( - @Nullable String fqdn) { - if (TextUtils.isEmpty(fqdn)) { - return null; - } - return mPasspointInfo.get(fqdn); - } - - /** - * Returns a set of all network suggestions matching the provided FQDN. - */ - public @Nullable Set<ExtendedWifiNetworkSuggestion> getNetworkSuggestionsForFqdn(String fqdn) { - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = - getNetworkSuggestionsForFqdnMatch(fqdn); - if (extNetworkSuggestions == null) { - return null; - } - final String activeScorerPackage = mNetworkScoreManager.getActiveScorerPackage(); - Set<ExtendedWifiNetworkSuggestion> approvedExtNetworkSuggestions = new HashSet<>(); - for (ExtendedWifiNetworkSuggestion ewns : extNetworkSuggestions) { - if (!ewns.perAppInfo.isApproved(activeScorerPackage)) { - sendUserApprovalNotificationIfNotApproved(ewns.perAppInfo.packageName, - ewns.perAppInfo.uid); - continue; - } - if (isSimBasedSuggestion(ewns)) { - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired( - getCarrierIdFromSuggestion(ewns)); - } - approvedExtNetworkSuggestions.add(ewns); - } - - if (approvedExtNetworkSuggestions.isEmpty()) { - return null; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "getNetworkSuggestionsForFqdn Found " - + approvedExtNetworkSuggestions + " for " + fqdn); - } - return approvedExtNetworkSuggestions; - } - - /** - * Returns a set of all network suggestions matching the provided scan detail. - */ - public @Nullable Set<ExtendedWifiNetworkSuggestion> getNetworkSuggestionsForScanDetail( - @NonNull ScanDetail scanDetail) { - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult == null) { - Log.e(TAG, "No scan result found in scan detail"); - return null; - } - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = null; - try { - ScanResultMatchInfo scanResultMatchInfo = - ScanResultMatchInfo.fromScanResult(scanResult); - extNetworkSuggestions = getNetworkSuggestionsForScanResultMatchInfo( - scanResultMatchInfo, MacAddress.fromString(scanResult.BSSID)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Failed to lookup network from scan result match info map", e); - } - if (extNetworkSuggestions == null) { - return null; - } - final String activeScorerPackage = mNetworkScoreManager.getActiveScorerPackage(); - Set<ExtendedWifiNetworkSuggestion> approvedExtNetworkSuggestions = new HashSet<>(); - for (ExtendedWifiNetworkSuggestion ewns : extNetworkSuggestions) { - if (!ewns.perAppInfo.isApproved(activeScorerPackage)) { - sendUserApprovalNotificationIfNotApproved(ewns.perAppInfo.packageName, - ewns.perAppInfo.uid); - continue; - } - if (isSimBasedSuggestion(ewns)) { - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired( - getCarrierIdFromSuggestion(ewns)); - } - approvedExtNetworkSuggestions.add(ewns); - } - - if (approvedExtNetworkSuggestions.isEmpty()) { - return null; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "getNetworkSuggestionsForScanDetail Found " - + approvedExtNetworkSuggestions + " for " + scanResult.SSID - + "[" + scanResult.capabilities + "]"); - } - return approvedExtNetworkSuggestions; - } - - /** - * Returns a set of all network suggestions matching the provided the WifiConfiguration. - */ - public @Nullable Set<ExtendedWifiNetworkSuggestion> getNetworkSuggestionsForWifiConfiguration( - @NonNull WifiConfiguration wifiConfiguration, @Nullable String bssid) { - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = null; - if (wifiConfiguration.isPasspoint()) { - extNetworkSuggestions = getNetworkSuggestionsForFqdnMatch(wifiConfiguration.FQDN); - } else { - try { - ScanResultMatchInfo scanResultMatchInfo = - ScanResultMatchInfo.fromWifiConfiguration(wifiConfiguration); - extNetworkSuggestions = getNetworkSuggestionsForScanResultMatchInfo( - scanResultMatchInfo, bssid == null ? null : MacAddress.fromString(bssid)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Failed to lookup network from scan result match info map", e); - } - } - if (extNetworkSuggestions == null || extNetworkSuggestions.isEmpty()) { - return null; - } - final String activeScorerPackage = mNetworkScoreManager.getActiveScorerPackage(); - Set<ExtendedWifiNetworkSuggestion> approvedExtNetworkSuggestions = - extNetworkSuggestions - .stream() - .filter(n -> n.perAppInfo.isApproved(activeScorerPackage)) - .collect(Collectors.toSet()); - if (approvedExtNetworkSuggestions.isEmpty()) { - return null; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "getNetworkSuggestionsForWifiConfiguration Found " - + approvedExtNetworkSuggestions + " for " + wifiConfiguration.SSID - + wifiConfiguration.FQDN + "[" + wifiConfiguration.allowedKeyManagement + "]"); - } - return approvedExtNetworkSuggestions; - } - - /** - * Retrieve the WifiConfigurations for all matched suggestions which allow user manually connect - * and user already approved for non-open networks. - */ - public @NonNull List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( - List<ScanResult> scanResults) { - // Create a HashSet to avoid return multiple result for duplicate ScanResult. - Set<String> networkKeys = new HashSet<>(); - List<WifiConfiguration> sharedWifiConfigs = new ArrayList<>(); - for (ScanResult scanResult : scanResults) { - ScanResultMatchInfo scanResultMatchInfo = - ScanResultMatchInfo.fromScanResult(scanResult); - if (scanResultMatchInfo.networkType == WifiConfiguration.SECURITY_TYPE_OPEN) { - continue; - } - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = - getNetworkSuggestionsForScanResultMatchInfo( - scanResultMatchInfo, MacAddress.fromString(scanResult.BSSID)); - if (extNetworkSuggestions == null || extNetworkSuggestions.isEmpty()) { - continue; - } - Set<ExtendedWifiNetworkSuggestion> sharedNetworkSuggestions = extNetworkSuggestions - .stream() - .filter(ewns -> ewns.perAppInfo.hasUserApproved - && ewns.wns.isUserAllowedToManuallyConnect) - .collect(Collectors.toSet()); - if (sharedNetworkSuggestions.isEmpty()) { - continue; - } - ExtendedWifiNetworkSuggestion ewns = - sharedNetworkSuggestions.stream().findFirst().get(); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "getWifiConfigForMatchedNetworkSuggestionsSharedWithUser Found " - + ewns + " for " + scanResult.SSID + "[" + scanResult.capabilities + "]"); - } - WifiConfiguration config = ewns.wns.wifiConfiguration; - WifiConfiguration existingConfig = mWifiConfigManager - .getConfiguredNetwork(config.getKey()); - if (existingConfig == null || !existingConfig.fromWifiNetworkSuggestion) { - continue; - } - if (networkKeys.add(existingConfig.getKey())) { - sharedWifiConfigs.add(existingConfig); - } - } - return sharedWifiConfigs; - } - - /** - * Check if the given passpoint suggestion has user approval and allow user manually connect. - */ - public boolean isPasspointSuggestionSharedWithUser(WifiConfiguration config) { - if (WifiConfiguration.isMetered(config, null) - && mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)) { - return false; - } - Set<ExtendedWifiNetworkSuggestion> extendedWifiNetworkSuggestions = - getNetworkSuggestionsForFqdnMatch(config.FQDN); - Set<ExtendedWifiNetworkSuggestion> matchedSuggestions = - extendedWifiNetworkSuggestions == null ? null : extendedWifiNetworkSuggestions - .stream().filter(ewns -> ewns.perAppInfo.uid == config.creatorUid) - .collect(Collectors.toSet()); - if (matchedSuggestions == null || matchedSuggestions.isEmpty()) { - Log.e(TAG, "Matched network suggestion is missing for FQDN:" + config.FQDN); - return false; - } - ExtendedWifiNetworkSuggestion suggestion = matchedSuggestions - .stream().findAny().get(); - return suggestion.wns.isUserAllowedToManuallyConnect - && suggestion.perAppInfo.hasUserApproved; - } - - /** - * Get hidden network from active network suggestions. - * Todo(): Now limit by a fixed number, maybe we can try rotation? - * @return set of WifiConfigurations - */ - public List<WifiScanner.ScanSettings.HiddenNetwork> retrieveHiddenNetworkList() { - List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks = new ArrayList<>(); - for (PerAppInfo appInfo : mActiveNetworkSuggestionsPerApp.values()) { - if (!appInfo.hasUserApproved) continue; - for (ExtendedWifiNetworkSuggestion ewns : appInfo.extNetworkSuggestions) { - if (!ewns.wns.wifiConfiguration.hiddenSSID) continue; - hiddenNetworks.add( - new WifiScanner.ScanSettings.HiddenNetwork( - ewns.wns.wifiConfiguration.SSID)); - if (hiddenNetworks.size() >= NUMBER_OF_HIDDEN_NETWORK_FOR_ONE_SCAN) { - return hiddenNetworks; - } - } - } - return hiddenNetworks; - } - - /** - * Helper method to send the post connection broadcast to specified package. - */ - private void sendPostConnectionBroadcast( - ExtendedWifiNetworkSuggestion extSuggestion) { - Intent intent = new Intent(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION); - intent.putExtra(WifiManager.EXTRA_NETWORK_SUGGESTION, extSuggestion.wns); - // Intended to wakeup the receiving app so set the specific package name. - intent.setPackage(extSuggestion.perAppInfo.packageName); - mContext.sendBroadcastAsUser( - intent, UserHandle.getUserHandleForUid(extSuggestion.perAppInfo.uid)); - } - - /** - * Helper method to send the post connection broadcast to specified package. - */ - private void sendPostConnectionBroadcastIfAllowed( - ExtendedWifiNetworkSuggestion matchingExtSuggestion, @NonNull String message) { - try { - mWifiPermissionsUtil.enforceCanAccessScanResults( - matchingExtSuggestion.perAppInfo.packageName, - matchingExtSuggestion.perAppInfo.featureId, - matchingExtSuggestion.perAppInfo.uid, message); - } catch (SecurityException se) { - Log.w(TAG, "Permission denied for sending post connection broadcast to " - + matchingExtSuggestion.perAppInfo.packageName); - return; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Sending post connection broadcast to " - + matchingExtSuggestion.perAppInfo.packageName); - } - sendPostConnectionBroadcast(matchingExtSuggestion); - } - - /** - * Send out the {@link WifiManager#ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the - * network suggestion that provided credential for the current connection network. - * If current connection network is open user saved network, broadcast will be only sent out to - * one of the carrier apps that suggested matched network suggestions. - * - * @param connectedNetwork {@link WifiConfiguration} representing the network connected to. - * @param connectedBssid BSSID of the network connected to. - */ - private void handleConnectionSuccess( - @NonNull WifiConfiguration connectedNetwork, @NonNull String connectedBssid) { - if (!(connectedNetwork.fromWifiNetworkSuggestion || connectedNetwork.isOpenNetwork())) { - return; - } - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - getNetworkSuggestionsForWifiConfiguration(connectedNetwork, connectedBssid); - - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Network suggestions matching the connection " - + matchingExtNetworkSuggestions); - } - if (matchingExtNetworkSuggestions == null - || matchingExtNetworkSuggestions.isEmpty()) return; - - if (connectedNetwork.fromWifiNetworkSuggestion) { - // Find subset of network suggestions from app suggested the connected network. - matchingExtNetworkSuggestions = - matchingExtNetworkSuggestions.stream() - .filter(x -> x.perAppInfo.uid == connectedNetwork.creatorUid) - .collect(Collectors.toSet()); - if (matchingExtNetworkSuggestions.isEmpty()) { - Log.wtf(TAG, "Current connected network suggestion is missing!"); - return; - } - // Store the set of matching network suggestions. - mActiveNetworkSuggestionsMatchingConnection = - new HashSet<>(matchingExtNetworkSuggestions); - } else { - if (connectedNetwork.isOpenNetwork()) { - // For saved open network, found the matching suggestion from carrier privileged - // apps. As we only expect one suggestor app to take action on post connection, if - // multiple apps suggested matched suggestions, framework will randomly pick one. - matchingExtNetworkSuggestions = matchingExtNetworkSuggestions.stream() - .filter(x -> x.perAppInfo.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID - || mWifiPermissionsUtil - .checkNetworkCarrierProvisioningPermission(x.perAppInfo.uid)) - .limit(1).collect(Collectors.toSet()); - if (matchingExtNetworkSuggestions.isEmpty()) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "No suggestion matched connected user saved open network."); - } - return; - } - } - } - - mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess(); - // Find subset of network suggestions have set |isAppInteractionRequired|. - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestionsWithReqAppInteraction = - matchingExtNetworkSuggestions.stream() - .filter(x -> x.wns.isAppInteractionRequired) - .collect(Collectors.toSet()); - if (matchingExtNetworkSuggestionsWithReqAppInteraction.isEmpty()) return; - - // Iterate over the matching network suggestions list: - // a) Ensure that these apps have the necessary location permissions. - // b) Send directed broadcast to the app with their corresponding network suggestion. - for (ExtendedWifiNetworkSuggestion matchingExtNetworkSuggestion - : matchingExtNetworkSuggestionsWithReqAppInteraction) { - sendPostConnectionBroadcastIfAllowed( - matchingExtNetworkSuggestion, - "Connected to " + matchingExtNetworkSuggestion.wns.wifiConfiguration.SSID - + ". featureId is first feature of the app using network suggestions"); - } - } - - /** - * Handle connection failure. - * - * @param network {@link WifiConfiguration} representing the network that connection failed to. - * @param bssid BSSID of the network connection failed to if known, else null. - * @param failureCode failure reason code. - */ - private void handleConnectionFailure(@NonNull WifiConfiguration network, - @Nullable String bssid, int failureCode) { - if (!network.fromWifiNetworkSuggestion) { - return; - } - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - getNetworkSuggestionsForWifiConfiguration(network, bssid); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Network suggestions matching the connection failure " - + matchingExtNetworkSuggestions); - } - if (matchingExtNetworkSuggestions == null - || matchingExtNetworkSuggestions.isEmpty()) return; - - mWifiMetrics.incrementNetworkSuggestionApiNumConnectFailure(); - // TODO (b/115504887, b/112196799): Blacklist the corresponding network suggestion if - // the connection failed. - - // Find subset of network suggestions which suggested the connection failure network. - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestionsFromTargetApp = - matchingExtNetworkSuggestions.stream() - .filter(x -> x.perAppInfo.uid == network.creatorUid) - .collect(Collectors.toSet()); - if (matchingExtNetworkSuggestionsFromTargetApp.isEmpty()) { - Log.wtf(TAG, "Current connection failure network suggestion is missing!"); - return; - } - - for (ExtendedWifiNetworkSuggestion matchingExtNetworkSuggestion - : matchingExtNetworkSuggestionsFromTargetApp) { - sendConnectionFailureIfAllowed(matchingExtNetworkSuggestion.perAppInfo.packageName, - matchingExtNetworkSuggestion.perAppInfo.featureId, - matchingExtNetworkSuggestion.perAppInfo.uid, - matchingExtNetworkSuggestion.wns, failureCode); - } - } - - private void resetConnectionState() { - mActiveNetworkSuggestionsMatchingConnection = null; - } - - /** - * Invoked by {@link ClientModeImpl} on end of connection attempt to a network. - * - * @param failureCode Failure codes representing {@link WifiMetrics.ConnectionEvent} codes. - * @param network WifiConfiguration corresponding to the current network. - * @param bssid BSSID of the current network. - */ - public void handleConnectionAttemptEnded( - int failureCode, @NonNull WifiConfiguration network, @Nullable String bssid) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "handleConnectionAttemptEnded " + failureCode + ", " + network); - } - resetConnectionState(); - if (failureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) { - handleConnectionSuccess(network, bssid); - } else { - handleConnectionFailure(network, bssid, failureCode); - } - } - - /** - * Invoked by {@link ClientModeImpl} on disconnect from network. - */ - public void handleDisconnect(@NonNull WifiConfiguration network, @NonNull String bssid) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "handleDisconnect " + network); - } - resetConnectionState(); - } - - /** - * Send network connection failure event to app when an connection attempt failure. - * @param packageName package name to send event - * @param featureId The feature in the package - * @param uid uid of the app. - * @param matchingSuggestion suggestion on this connection failure - * @param connectionEvent connection failure code - */ - private void sendConnectionFailureIfAllowed(String packageName, @Nullable String featureId, - int uid, @NonNull WifiNetworkSuggestion matchingSuggestion, int connectionEvent) { - ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = - mSuggestionStatusListenerPerApp.get(packageName); - if (listenersTracker == null || listenersTracker.getNumCallbacks() == 0) { - return; - } - try { - mWifiPermissionsUtil.enforceCanAccessScanResults( - packageName, featureId, uid, "Connection failure"); - } catch (SecurityException se) { - Log.w(TAG, "Permission denied for sending connection failure event to " + packageName); - return; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Sending connection failure event to " + packageName); - } - for (ISuggestionConnectionStatusListener listener : listenersTracker.getCallbacks()) { - try { - listener.onConnectionStatus(matchingSuggestion, - internalConnectionEventToSuggestionFailureCode(connectionEvent)); - } catch (RemoteException e) { - Log.e(TAG, "sendNetworkCallback: remote exception -- " + e); - } - } - } - - private @WifiManager.SuggestionConnectionStatusCode - int internalConnectionEventToSuggestionFailureCode(int connectionEvent) { - switch (connectionEvent) { - case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION: - case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT: - return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION; - case WifiMetrics.ConnectionEvent.FAILURE_SSID_TEMP_DISABLED: - case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE: - return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION; - case WifiMetrics.ConnectionEvent.FAILURE_DHCP: - return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING; - default: - return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN; - } - } - - /** - * Register a SuggestionConnectionStatusListener on network connection failure. - * @param binder IBinder instance to allow cleanup if the app dies. - * @param listener ISuggestionNetworkCallback instance to add. - * @param listenerIdentifier identifier of the listener, should be hash code of listener. - * @param uid uid of the app. - * @return true if succeed otherwise false. - */ - public boolean registerSuggestionConnectionStatusListener(@NonNull IBinder binder, - @NonNull ISuggestionConnectionStatusListener listener, - int listenerIdentifier, String packageName, int uid) { - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return false; - } - ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = - mSuggestionStatusListenerPerApp.get(packageName); - if (listenersTracker == null) { - listenersTracker = - new ExternalCallbackTracker<>(mHandler); - } - listenersTracker.add(binder, listener, listenerIdentifier); - mSuggestionStatusListenerPerApp.put(packageName, listenersTracker); - return true; - } - - /** - * Unregister a listener on network connection failure. - * @param listenerIdentifier identifier of the listener, should be hash code of listener. - * @param uid uid of the app. - */ - public void unregisterSuggestionConnectionStatusListener(int listenerIdentifier, - String packageName, int uid) { - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return; - } - ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = - mSuggestionStatusListenerPerApp.get(packageName); - if (listenersTracker == null || listenersTracker.remove(listenerIdentifier) == null) { - Log.w(TAG, "unregisterSuggestionConnectionStatusListener: Listener[" - + listenerIdentifier + "] from " + packageName + " already unregister."); - } - if (listenersTracker != null && listenersTracker.getNumCallbacks() == 0) { - mSuggestionStatusListenerPerApp.remove(packageName); - } - } - - /** - * When SIM state changes, check if carrier privileges changes for app. - * If app changes from privileged to not privileged, remove all suggestions and reset state. - * If app changes from not privileges to privileged, set target carrier id for all suggestions. - */ - public void resetCarrierPrivilegedApps() { - Log.w(TAG, "SIM state is changed!"); - for (PerAppInfo appInfo : mActiveNetworkSuggestionsPerApp.values()) { - int carrierId = mWifiCarrierInfoManager - .getCarrierIdForPackageWithCarrierPrivileges(appInfo.packageName); - if (carrierId == appInfo.carrierId) { - continue; - } - if (carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { - Log.i(TAG, "Carrier privilege revoked for " + appInfo.packageName); - removeInternal(Collections.EMPTY_LIST, appInfo.packageName, appInfo); - mActiveNetworkSuggestionsPerApp.remove(appInfo.packageName); - continue; - } - Log.i(TAG, "Carrier privilege granted for " + appInfo.packageName); - appInfo.carrierId = carrierId; - for (ExtendedWifiNetworkSuggestion ewns : appInfo.extNetworkSuggestions) { - ewns.wns.wifiConfiguration.carrierId = carrierId; - } - } - saveToStore(); - } - - /** - * Set auto-join enable/disable for suggestion network - * @param config WifiConfiguration which is to change. - * @param choice true to enable auto-join, false to disable. - * @return true on success, false otherwise (e.g. if no match suggestion exists). - */ - public boolean allowNetworkSuggestionAutojoin(WifiConfiguration config, boolean choice) { - if (!config.fromWifiNetworkSuggestion) { - Log.e(TAG, "allowNetworkSuggestionAutojoin: on non-suggestion network: " - + config); - return false; - } - - Set<ExtendedWifiNetworkSuggestion> matchingExtendedWifiNetworkSuggestions = - getNetworkSuggestionsForWifiConfiguration(config, config.BSSID); - if (config.isPasspoint()) { - if (!mWifiInjector.getPasspointManager().enableAutojoin(config.getKey(), - null, choice)) { - return false; - } - } - for (ExtendedWifiNetworkSuggestion ewns : matchingExtendedWifiNetworkSuggestions) { - ewns.isAutojoinEnabled = choice; - } - saveToStore(); - return true; - } - - /** - * Get the filtered ScanResults which may be authenticated by the suggested configurations. - * @param wifiNetworkSuggestions The list of {@link WifiNetworkSuggestion} - * @param scanResults The list of {@link ScanResult} - * @return The filtered ScanResults - */ - @NonNull - public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( - @NonNull List<WifiNetworkSuggestion> wifiNetworkSuggestions, - @NonNull List<ScanResult> scanResults) { - Map<WifiNetworkSuggestion, List<ScanResult>> filteredScanResults = new HashMap<>(); - if (wifiNetworkSuggestions == null || wifiNetworkSuggestions.isEmpty() - || scanResults == null || scanResults.isEmpty()) { - return filteredScanResults; - } - for (WifiNetworkSuggestion suggestion : wifiNetworkSuggestions) { - if (suggestion == null || suggestion.wifiConfiguration == null) { - continue; - } - filteredScanResults.put(suggestion, - getMatchingScanResultsForSuggestion(suggestion, scanResults)); - } - - return filteredScanResults; - } - - private List<ScanResult> getMatchingScanResultsForSuggestion(WifiNetworkSuggestion suggestion, - List<ScanResult> scanResults) { - if (suggestion.passpointConfiguration != null) { - return mWifiInjector.getPasspointManager().getMatchingScanResults( - suggestion.passpointConfiguration, scanResults); - } else { - return getMatchingScanResults(suggestion.wifiConfiguration, scanResults); - } - } - - /** - * Get the filtered ScanResults which may be authenticated by the {@link WifiConfiguration}. - * @param wifiConfiguration The instance of {@link WifiConfiguration} - * @param scanResults The list of {@link ScanResult} - * @return The filtered ScanResults - */ - @NonNull - private List<ScanResult> getMatchingScanResults( - @NonNull WifiConfiguration wifiConfiguration, - @NonNull List<ScanResult> scanResults) { - ScanResultMatchInfo matchInfoFromConfigration = - ScanResultMatchInfo.fromWifiConfiguration(wifiConfiguration); - if (matchInfoFromConfigration == null) { - return new ArrayList<>(); - } - List<ScanResult> filteredScanResult = new ArrayList<>(); - for (ScanResult scanResult : scanResults) { - if (matchInfoFromConfigration.equals(ScanResultMatchInfo.fromScanResult(scanResult))) { - filteredScanResult.add(scanResult); - } - } - - return filteredScanResult; - } - - /** - * Add the suggestion update event listener - */ - public void addOnSuggestionUpdateListener(OnSuggestionUpdateListener listener) { - mListeners.add(listener); - } - - /** - * When a saved open network has a same network suggestion which is from app has - * NETWORK_CARRIER_PROVISIONING permission, also that app suggested secure network suggestion - * for same carrier with higher or equal priority and Auto-Join enabled, also that secure - * network is in the range. The saved open network will be ignored during the network selection. - * TODO (b/142035508): revert all these changes once we build infra needed to solve this. - * @param configuration Saved open network to check if it should be ignored. - * @param scanDetails Available ScanDetail nearby. - * @return True if the open network should be ignored, false otherwise. - */ - public boolean shouldBeIgnoredBySecureSuggestionFromSameCarrier( - @NonNull WifiConfiguration configuration, List<ScanDetail> scanDetails) { - if (!mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) { - return false; - } - if (configuration == null || scanDetails == null || !configuration.isOpenNetwork()) { - return false; - } - Set<ExtendedWifiNetworkSuggestion> matchedExtSuggestions = - getNetworkSuggestionsForWifiConfiguration(configuration, null); - if (matchedExtSuggestions == null || matchedExtSuggestions.isEmpty()) { - return false; - } - matchedExtSuggestions = matchedExtSuggestions.stream().filter(ewns -> - mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(ewns.perAppInfo.uid)) - .collect(Collectors.toSet()); - if (matchedExtSuggestions.isEmpty()) { - return false; - } - for (ExtendedWifiNetworkSuggestion ewns : matchedExtSuggestions) { - if (hasSecureSuggestionFromSameCarrierAvailable(ewns, scanDetails)) { - return true; - } - } - return false; - } - - private boolean hasSecureSuggestionFromSameCarrierAvailable( - ExtendedWifiNetworkSuggestion extendedWifiNetworkSuggestion, - List<ScanDetail> scanDetails) { - boolean isOpenSuggestionMetered = WifiConfiguration.isMetered( - extendedWifiNetworkSuggestion.wns.wifiConfiguration, null); - Set<ExtendedWifiNetworkSuggestion> secureExtSuggestions = new HashSet<>(); - for (ExtendedWifiNetworkSuggestion ewns : extendedWifiNetworkSuggestion.perAppInfo - .extNetworkSuggestions) { - // Open network and auto-join disable suggestion, ignore. - if (isOpenSuggestion(ewns) || !ewns.isAutojoinEnabled) { - continue; - } - // From different carrier as open suggestion, ignore. - if (getCarrierIdFromSuggestion(ewns) - != getCarrierIdFromSuggestion(extendedWifiNetworkSuggestion)) { - continue; - } - // Secure and open has different meterness, ignore - if (WifiConfiguration.isMetered(ewns.wns.wifiConfiguration, null) - != isOpenSuggestionMetered) { - continue; - } - // Low priority than open suggestion, ignore. - if (ewns.wns.wifiConfiguration.priority - < extendedWifiNetworkSuggestion.wns.wifiConfiguration.priority) { - continue; - } - WifiConfiguration wcmConfig = mWifiConfigManager - .getConfiguredNetwork(ewns.wns.wifiConfiguration.getKey()); - // Network selection is disabled, ignore. - if (wcmConfig != null && !wcmConfig.getNetworkSelectionStatus().isNetworkEnabled()) { - continue; - } - secureExtSuggestions.add(ewns); - } - - if (secureExtSuggestions.isEmpty()) { - return false; - } - List<ScanResult> scanResults = scanDetails.stream().map(ScanDetail::getScanResult) - .collect(Collectors.toList()); - // Check if the secure suggestion is in the range. - for (ExtendedWifiNetworkSuggestion ewns : secureExtSuggestions) { - if (!getMatchingScanResultsForSuggestion(ewns.wns, scanResults).isEmpty()) { - return true; - } - } - return false; - } - - private boolean isOpenSuggestion(ExtendedWifiNetworkSuggestion extendedWifiNetworkSuggestion) { - if (extendedWifiNetworkSuggestion.wns.passpointConfiguration != null) { - return false; - } - return extendedWifiNetworkSuggestion.wns.wifiConfiguration.isOpenNetwork(); - } - - /** - * Dump of {@link WifiNetworkSuggestionsManager}. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WifiNetworkSuggestionsManager"); - pw.println("WifiNetworkSuggestionsManager - Networks Begin ----"); - final String activeScorerPackage = mNetworkScoreManager.getActiveScorerPackage(); - for (Map.Entry<String, PerAppInfo> networkSuggestionsEntry - : mActiveNetworkSuggestionsPerApp.entrySet()) { - pw.println("Package Name: " + networkSuggestionsEntry.getKey()); - PerAppInfo appInfo = networkSuggestionsEntry.getValue(); - pw.println("Has user approved: " + appInfo.hasUserApproved); - pw.println("Has carrier privileges: " - + (appInfo.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID)); - pw.println("Is active scorer: " + appInfo.packageName.equals(activeScorerPackage)); - for (ExtendedWifiNetworkSuggestion extNetworkSuggestion - : appInfo.extNetworkSuggestions) { - pw.println("Network: " + extNetworkSuggestion); - } - } - pw.println("WifiNetworkSuggestionsManager - Networks End ----"); - pw.println("WifiNetworkSuggestionsManager - Network Suggestions matching connection: " - + mActiveNetworkSuggestionsMatchingConnection); - } -} diff --git a/service/java/com/android/server/wifi/WifiPowerMetrics.java b/service/java/com/android/server/wifi/WifiPowerMetrics.java deleted file mode 100644 index 48cb1a6e9..000000000 --- a/service/java/com/android/server/wifi/WifiPowerMetrics.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.os.BatteryStatsManager; -import android.os.connectivity.WifiBatteryStats; -import android.text.format.DateUtils; - -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiPowerStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiRadioUsage; - -import java.io.PrintWriter; -import java.text.DecimalFormat; - -/** - * WifiPowerMetrics holds the wifi power metrics and converts them to WifiPowerStats proto buf. - * This proto buf is included in the Wifi proto buf. - */ -public class WifiPowerMetrics { - - private static final String TAG = "WifiPowerMetrics"; - - /* BatteryStats API */ - private final BatteryStatsManager mBatteryStats; - - public WifiPowerMetrics(BatteryStatsManager batteryStats) { - mBatteryStats = batteryStats; - } - - /** - * Build WifiPowerStats proto - * A snapshot of Wifi statistics in Batterystats is obtained. Due to reboots multiple correlated - * logs may be uploaded in a day. Resolution is on the server side. The log with longest - * duration is picked. - * @return WifiPowerStats - */ - public WifiPowerStats buildProto() { - WifiPowerStats m = new WifiPowerStats(); - WifiBatteryStats stats = getStats(); - if (stats != null) { - m.loggingDurationMs = stats.getLoggingDurationMillis(); - m.energyConsumedMah = stats.getEnergyConsumedMaMillis() - / ((double) DateUtils.HOUR_IN_MILLIS); - m.idleTimeMs = stats.getIdleTimeMillis(); - m.rxTimeMs = stats.getRxTimeMillis(); - m.txTimeMs = stats.getTxTimeMillis(); - m.wifiKernelActiveTimeMs = stats.getKernelActiveTimeMillis(); - m.numPacketsTx = stats.getNumPacketsTx(); - m.numBytesTx = stats.getNumBytesTx(); - m.numPacketsRx = stats.getNumPacketsRx(); - m.numBytesRx = stats.getNumBytesRx(); - m.sleepTimeMs = stats.getSleepTimeMillis(); - m.scanTimeMs = stats.getScanTimeMillis(); - m.monitoredRailEnergyConsumedMah = stats.getMonitoredRailChargeConsumedMaMillis() - / ((double) DateUtils.HOUR_IN_MILLIS); - } - return m; - } - - /** - * Build WifiRadioUsage proto - * A snapshot of Wifi statistics in Batterystats is obtained. Due to reboots multiple correlated - * logs may be uploaded in a day. Server side should analyze based the ratio of collected - * properties over the total logging duration (ie. |scanTimeMs| / |loggingDurationMs|) - * - * This proto contains additional wifi usage data that are not directly related to power - * calculations. - * @return WifiRadioUsage - */ - public WifiRadioUsage buildWifiRadioUsageProto() { - WifiRadioUsage m = new WifiRadioUsage(); - WifiBatteryStats stats = getStats(); - if (stats != null) { - m.loggingDurationMs = stats.getLoggingDurationMillis(); - m.scanTimeMs = stats.getScanTimeMillis(); - } - return m; - } - - /** - * Dump all WifiPowerStats to console (pw) - * @param pw - */ - public void dump(PrintWriter pw) { - WifiPowerStats s = buildProto(); - if (s!=null) { - pw.println("Wifi power metrics:"); - pw.println("Logging duration (time on battery): " + s.loggingDurationMs); - pw.println("Energy consumed by wifi (mAh): " + s.energyConsumedMah); - pw.println("Amount of time wifi is in idle (ms): " + s.idleTimeMs); - pw.println("Amount of time wifi is in rx (ms): " + s.rxTimeMs); - pw.println("Amount of time wifi is in tx (ms): " + s.txTimeMs); - pw.println("Amount of time kernel is active because of wifi data (ms): " - + s.wifiKernelActiveTimeMs); - pw.println("Amount of time wifi is in sleep (ms): " + s.sleepTimeMs); - pw.println("Amount of time wifi is scanning (ms): " + s.scanTimeMs); - pw.println("Number of packets sent (tx): " + s.numPacketsTx); - pw.println("Number of bytes sent (tx): " + s.numBytesTx); - pw.println("Number of packets received (rx): " + s.numPacketsRx); - pw.println("Number of bytes sent (rx): " + s.numBytesRx); - pw.println("Energy consumed across measured wifi rails (mAh): " - + new DecimalFormat("#.##").format(s.monitoredRailEnergyConsumedMah)); - } - WifiRadioUsage wifiRadioUsage = buildWifiRadioUsageProto(); - pw.println("Wifi radio usage metrics:"); - pw.println("Logging duration (time on battery): " + wifiRadioUsage.loggingDurationMs); - pw.println("Amount of time wifi is in scan mode while on battery (ms): " - + wifiRadioUsage.scanTimeMs); - } - - /** - * Get wifi stats from batterystats - * @return WifiBatteryStats - */ - private WifiBatteryStats getStats() { - return mBatteryStats.getWifiBatteryStats(); - } -} diff --git a/service/java/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibility.java b/service/java/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibility.java deleted file mode 100644 index 6abdd3162..000000000 --- a/service/java/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibility.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.os.Handler; -import android.provider.Settings; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -/** - * Note: This is a hack to provide backward compatibility with the - * {@link Settings.Global#WIFI_SCAN_ALWAYS_AVAILABLE} @hide settings usage. We migrated storage - * of the scan always available state from this setting to our internal storage, but need to support - * the existing @hide users. - * TODO(b/149954910): We should find a path to stop supporting this! - */ -public class WifiScanAlwaysAvailableSettingsCompatibility { - private static final String TAG = "WifiScanAlwaysAvailableSettingsCompatibility"; - - /** - * Copy of the settings string. Can't directly use the constant because it is @hide. - */ - @VisibleForTesting - public static final String SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE = - "wifi_scan_always_enabled"; - - private final Context mContext; - private final ContentResolver mContentResolver; - private final Handler mHandler; - private final WifiSettingsStore mWifiSettingsStore; - private final ActiveModeWarden mActiveModeWarden; - private final FrameworkFacade mFrameworkFacade; - - public WifiScanAlwaysAvailableSettingsCompatibility(Context context, - Handler handler, WifiSettingsStore wifiSettingsStore, - ActiveModeWarden activeModeWarden, FrameworkFacade frameworkFacade) { - mContext = context; - mHandler = handler; - mWifiSettingsStore = wifiSettingsStore; - mActiveModeWarden = activeModeWarden; - mFrameworkFacade = frameworkFacade; - - // Cache the content resolver to ensure that we can detect self changes. - mContentResolver = context.getContentResolver(); - } - - /** - * Register settings change observer. - */ - public void initialize() { - ContentObserver contentObserver = new ContentObserver(mHandler) { - @Override - public void onChange(boolean selfChange) { - // Ignore any changes we triggered to avoid causing a loop. - if (selfChange) return; - - boolean settingsIsAvailable = - mFrameworkFacade.getIntegerSetting( - mContentResolver, SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE, 0) - == 1; - // Check if the new state is different from our current state. - if (mWifiSettingsStore.isScanAlwaysAvailable() != settingsIsAvailable) { - Log.i(TAG, "settings changed, new value: " + settingsIsAvailable - + ", triggering update"); - mWifiSettingsStore.handleWifiScanAlwaysAvailableToggled(settingsIsAvailable); - mActiveModeWarden.scanAlwaysModeChanged(); - } - } - }; - mContentResolver.registerContentObserver( - Settings.Global.getUriFor(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE), - false, contentObserver); - } - - /** - * Handle scan always available toggle from {@link android.net.wifi.WifiManager# - * setScanAlwaysAvailable(boolean)} - */ - public void handleWifiScanAlwaysAvailableToggled(boolean isAvailable) { - mFrameworkFacade.setIntegerSetting( - mContentResolver, SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE, isAvailable ? 1 : 0); - } -} diff --git a/service/java/com/android/server/wifi/WifiScoreCard.java b/service/java/com/android/server/wifi/WifiScoreCard.java deleted file mode 100644 index 2ab5fb466..000000000 --- a/service/java/com/android/server/wifi/WifiScoreCard.java +++ /dev/null @@ -1,1984 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS; -import static android.net.wifi.WifiInfo.INVALID_RSSI; -import static android.net.wifi.WifiInfo.LINK_SPEED_UNKNOWN; - -import static com.android.server.wifi.WifiHealthMonitor.HEALTH_MONITOR_COUNT_TX_SPEED_MIN_MBPS; -import static com.android.server.wifi.WifiHealthMonitor.HEALTH_MONITOR_MIN_TX_PACKET_PER_SEC; -import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_REJECTION; -import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_TIMEOUT; -import static com.android.server.wifi.WifiHealthMonitor.REASON_AUTH_FAILURE; -import static com.android.server.wifi.WifiHealthMonitor.REASON_CONNECTION_FAILURE; -import static com.android.server.wifi.WifiHealthMonitor.REASON_DISCONNECTION_NONLOCAL; -import static com.android.server.wifi.WifiHealthMonitor.REASON_NO_FAILURE; -import static com.android.server.wifi.WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.MacAddress; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiManager; -import android.util.ArrayMap; -import android.util.Base64; -import android.util.Log; -import android.util.Pair; -import android.util.SparseLongArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; -import com.android.server.wifi.BssidBlocklistMonitor.FailureReason; -import com.android.server.wifi.WifiHealthMonitor.FailureStats; -import com.android.server.wifi.proto.WifiScoreCardProto; -import com.android.server.wifi.proto.WifiScoreCardProto.AccessPoint; -import com.android.server.wifi.proto.WifiScoreCardProto.ConnectionStats; -import com.android.server.wifi.proto.WifiScoreCardProto.Event; -import com.android.server.wifi.proto.WifiScoreCardProto.HistogramBucket; -import com.android.server.wifi.proto.WifiScoreCardProto.Network; -import com.android.server.wifi.proto.WifiScoreCardProto.NetworkList; -import com.android.server.wifi.proto.WifiScoreCardProto.NetworkStats; -import com.android.server.wifi.proto.WifiScoreCardProto.SecurityType; -import com.android.server.wifi.proto.WifiScoreCardProto.Signal; -import com.android.server.wifi.proto.WifiScoreCardProto.UnivariateStatistic; -import com.android.server.wifi.util.IntHistogram; -import com.android.server.wifi.util.LruList; -import com.android.server.wifi.util.NativeUtil; - -import com.google.protobuf.ByteString; -import com.google.protobuf.InvalidProtocolBufferException; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.nio.ByteBuffer; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicReference; - -import javax.annotation.concurrent.NotThreadSafe; - -/** - * Retains statistical information about the performance of various - * access points and networks, as experienced by this device. - * - * The purpose is to better inform future network selection and switching - * by this device and help health monitor detect network issues. - */ -@NotThreadSafe -public class WifiScoreCard { - - public static final String DUMP_ARG = "WifiScoreCard"; - - private static final String TAG = "WifiScoreCard"; - private boolean mVerboseLoggingEnabled = false; - - @VisibleForTesting - boolean mPersistentHistograms = true; - - private static final int TARGET_IN_MEMORY_ENTRIES = 50; - private static final int UNKNOWN_REASON = -1; - - public static final String PER_BSSID_DATA_NAME = "scorecard.proto"; - public static final String PER_NETWORK_DATA_NAME = "perNetworkData"; - - static final int INSUFFICIENT_RECENT_STATS = 0; - static final int SUFFICIENT_RECENT_STATS_ONLY = 1; - static final int SUFFICIENT_RECENT_PREV_STATS = 2; - - private static final int MAX_FREQUENCIES_PER_SSID = 10; - - private final Clock mClock; - private final String mL2KeySeed; - private MemoryStore mMemoryStore; - private final DeviceConfigFacade mDeviceConfigFacade; - - @VisibleForTesting - static final int[] RSSI_BUCKETS = intsInRange(-100, -20); - - private static int[] intsInRange(int min, int max) { - int[] a = new int[max - min + 1]; - for (int i = 0; i < a.length; i++) { - a[i] = min + i; - } - return a; - } - - /** Our view of the memory store */ - public interface MemoryStore { - /** Requests a read, with asynchronous reply */ - void read(String key, String name, BlobListener blobListener); - /** Requests a write, does not wait for completion */ - void write(String key, String name, byte[] value); - /** Sets the cluster identifier */ - void setCluster(String key, String cluster); - /** Requests removal of all entries matching the cluster */ - void removeCluster(String cluster); - } - /** Asynchronous response to a read request */ - public interface BlobListener { - /** Provides the previously stored value, or null if none */ - void onBlobRetrieved(@Nullable byte[] value); - } - - /** - * Installs a memory store. - * - * Normally this happens just once, shortly after we start. But wifi can - * come up before the disk is ready, and we might not yet have a valid wall - * clock when we start up, so we need to be prepared to begin recording data - * even if the MemoryStore is not yet available. - * - * When the store is installed for the first time, we want to merge any - * recently recorded data together with data already in the store. But if - * the store restarts and has to be reinstalled, we don't want to do - * this merge, because that would risk double-counting the old data. - * - */ - public void installMemoryStore(@NonNull MemoryStore memoryStore) { - Preconditions.checkNotNull(memoryStore); - if (mMemoryStore == null) { - mMemoryStore = memoryStore; - Log.i(TAG, "Installing MemoryStore"); - requestReadForAllChanged(); - } else { - mMemoryStore = memoryStore; - Log.e(TAG, "Reinstalling MemoryStore"); - // Our caller will call doWrites() eventually, so nothing more to do here. - } - } - - /** - * Enable/Disable verbose logging. - * - * @param verbose true to enable and false to disable. - */ - public void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - } - - /** - * Timestamp of the start of the most recent connection attempt. - * - * Based on mClock.getElapsedSinceBootMillis(). - * - * This is for calculating the time to connect and the duration of the connection. - * Any negative value means we are not currently connected. - */ - private long mTsConnectionAttemptStart = TS_NONE; - @VisibleForTesting - static final long TS_NONE = -1; - - /** - * Timestamp captured when we find out about a firmware roam - */ - private long mTsRoam = TS_NONE; - - /** - * Becomes true the first time we see a poll with a valid RSSI in a connection - */ - private boolean mPolled = false; - - /** - * Records validation success for the current connection. - * - * We want to gather statistics only on the first success. - */ - private boolean mValidatedThisConnectionAtLeastOnce = false; - - /** - * A note to ourself that we are attempting a network switch - */ - private boolean mAttemptingSwitch = false; - - /** - * SSID of currently connected or connecting network. Used during disconnection - */ - private String mSsidCurr = ""; - /** - * SSID of previously connected network. Used during disconnection when connection attempt - * of current network is issued before the disconnection of previous network. - */ - private String mSsidPrev = ""; - /** - * A flag that notes that current disconnection is not generated by wpa_supplicant - * which may indicate abnormal disconnection. - */ - private boolean mNonlocalDisconnection = false; - private int mDisconnectionReason; - - private long mFirmwareAlertTimeMs = TS_NONE; - - /** - * @param clock is the time source - * @param l2KeySeed is for making our L2Keys usable only on this device - */ - public WifiScoreCard(Clock clock, String l2KeySeed, DeviceConfigFacade deviceConfigFacade) { - mClock = clock; - mL2KeySeed = l2KeySeed; - mDummyPerBssid = new PerBssid("", MacAddress.fromString(DEFAULT_MAC_ADDRESS)); - mDummyPerNetwork = new PerNetwork(""); - mDeviceConfigFacade = deviceConfigFacade; - } - - /** - * Gets the L2Key and GroupHint associated with the connection. - */ - public @NonNull Pair<String, String> getL2KeyAndGroupHint(ExtendedWifiInfo wifiInfo) { - PerBssid perBssid = lookupBssid(wifiInfo.getSSID(), wifiInfo.getBSSID()); - if (perBssid == mDummyPerBssid) { - return new Pair<>(null, null); - } - return new Pair<>(perBssid.getL2Key(), groupHintFromSsid(perBssid.ssid)); - } - - /** - * Computes the GroupHint associated with the given ssid. - */ - public @NonNull String groupHintFromSsid(String ssid) { - final long groupIdHash = computeHashLong(ssid, mDummyPerBssid.bssid, mL2KeySeed); - return groupHintFromLong(groupIdHash); - } - - /** - * Handle network disconnection or shutdown event - */ - public void resetConnectionState() { - String ssidDisconnected = mAttemptingSwitch ? mSsidPrev : mSsidCurr; - updatePerNetwork(Event.DISCONNECTION, ssidDisconnected, INVALID_RSSI, LINK_SPEED_UNKNOWN, - UNKNOWN_REASON); - if (mVerboseLoggingEnabled && mTsConnectionAttemptStart > TS_NONE && !mAttemptingSwitch) { - Log.v(TAG, "handleNetworkDisconnect", new Exception()); - } - resetConnectionStateInternal(true); - } - - /** - * @param calledFromResetConnectionState says the call is from outside the class, - * indicating that we need to respect the value of mAttemptingSwitch. - */ - private void resetConnectionStateInternal(boolean calledFromResetConnectionState) { - if (!calledFromResetConnectionState) { - mAttemptingSwitch = false; - } - if (!mAttemptingSwitch) { - mTsConnectionAttemptStart = TS_NONE; - } - mTsRoam = TS_NONE; - mPolled = false; - mValidatedThisConnectionAtLeastOnce = false; - mNonlocalDisconnection = false; - mFirmwareAlertTimeMs = TS_NONE; - } - - /** - * Updates perBssid using relevant parts of WifiInfo - * - * @param wifiInfo object holding relevant values. - */ - private void updatePerBssid(WifiScoreCardProto.Event event, ExtendedWifiInfo wifiInfo) { - PerBssid perBssid = lookupBssid(wifiInfo.getSSID(), wifiInfo.getBSSID()); - perBssid.updateEventStats(event, - wifiInfo.getFrequency(), - wifiInfo.getRssi(), - wifiInfo.getLinkSpeed()); - perBssid.setNetworkConfigId(wifiInfo.getNetworkId()); - logd("BSSID update " + event + " ID: " + perBssid.id + " " + wifiInfo); - } - - /** - * Updates perNetwork with SSID, current RSSI and failureReason. failureReason is meaningful - * only during connection failure. - */ - private void updatePerNetwork(WifiScoreCardProto.Event event, String ssid, int rssi, - int txSpeed, int failureReason) { - PerNetwork perNetwork = lookupNetwork(ssid); - logd("network update " + event + ((ssid == null) ? " " : " " - + ssid) + " ID: " + perNetwork.id + " RSSI " + rssi + " txSpeed " + txSpeed); - perNetwork.updateEventStats(event, rssi, txSpeed, failureReason); - } - - /** - * Updates the score card after a signal poll - * - * @param wifiInfo object holding relevant values - */ - public void noteSignalPoll(@NonNull ExtendedWifiInfo wifiInfo) { - if (!mPolled && wifiInfo.getRssi() != INVALID_RSSI) { - updatePerBssid(Event.FIRST_POLL_AFTER_CONNECTION, wifiInfo); - mPolled = true; - } - updatePerBssid(Event.SIGNAL_POLL, wifiInfo); - int validTxSpeed = geTxLinkSpeedWithSufficientTxRate(wifiInfo); - updatePerNetwork(Event.SIGNAL_POLL, wifiInfo.getSSID(), wifiInfo.getRssi(), - validTxSpeed, UNKNOWN_REASON); - if (mTsRoam > TS_NONE && wifiInfo.getRssi() != INVALID_RSSI) { - long duration = mClock.getElapsedSinceBootMillis() - mTsRoam; - if (duration >= SUCCESS_MILLIS_SINCE_ROAM) { - updatePerBssid(Event.ROAM_SUCCESS, wifiInfo); - mTsRoam = TS_NONE; - doWritesBssid(); - } - } - } - - private int geTxLinkSpeedWithSufficientTxRate(@NonNull ExtendedWifiInfo wifiInfo) { - int txRate = (int) Math.ceil(wifiInfo.getSuccessfulTxPacketsPerSecond() - + wifiInfo.getLostTxPacketsPerSecond() - + wifiInfo.getRetriedTxPacketsPerSecond()); - int txSpeed = wifiInfo.getTxLinkSpeedMbps(); - logd("txRate: " + txRate + " txSpeed: " + txSpeed); - return (txRate >= HEALTH_MONITOR_MIN_TX_PACKET_PER_SEC) ? txSpeed : LINK_SPEED_UNKNOWN; - } - - /** Wait a few seconds before considering the roam successful */ - private static final long SUCCESS_MILLIS_SINCE_ROAM = 4_000; - - /** - * Updates the score card after IP configuration - * - * @param wifiInfo object holding relevant values - */ - public void noteIpConfiguration(@NonNull ExtendedWifiInfo wifiInfo) { - updatePerBssid(Event.IP_CONFIGURATION_SUCCESS, wifiInfo); - mAttemptingSwitch = false; - doWrites(); - } - - /** - * Updates the score card after network validation success. - * - * @param wifiInfo object holding relevant values - */ - public void noteValidationSuccess(@NonNull ExtendedWifiInfo wifiInfo) { - if (mValidatedThisConnectionAtLeastOnce) return; // Only once per connection - updatePerBssid(Event.VALIDATION_SUCCESS, wifiInfo); - mValidatedThisConnectionAtLeastOnce = true; - doWrites(); - } - - /** - * Updates the score card after network validation failure - * - * @param wifiInfo object holding relevant values - */ - public void noteValidationFailure(@NonNull ExtendedWifiInfo wifiInfo) { - // VALIDATION_FAILURE is not currently recorded. - } - - /** - * Records the start of a connection attempt - * - * @param wifiInfo may have state about an existing connection - * @param scanRssi is the highest RSSI of recent scan found from scanDetailCache - * @param ssid is the network SSID of connection attempt - */ - public void noteConnectionAttempt(@NonNull ExtendedWifiInfo wifiInfo, - int scanRssi, String ssid) { - // We may or may not be currently connected. If not, simply record the start. - // But if we are connected, wrap up the old one first. - if (mTsConnectionAttemptStart > TS_NONE) { - if (mPolled) { - updatePerBssid(Event.LAST_POLL_BEFORE_SWITCH, wifiInfo); - } - mAttemptingSwitch = true; - } - mTsConnectionAttemptStart = mClock.getElapsedSinceBootMillis(); - mPolled = false; - mSsidPrev = mSsidCurr; - mSsidCurr = ssid; - mFirmwareAlertTimeMs = TS_NONE; - - updatePerNetwork(Event.CONNECTION_ATTEMPT, ssid, scanRssi, LINK_SPEED_UNKNOWN, - UNKNOWN_REASON); - logd("CONNECTION_ATTEMPT" + (mAttemptingSwitch ? " X " : " ") + wifiInfo); - } - - /** - * Records a newly assigned NetworkAgent netId. - */ - public void noteNetworkAgentCreated(@NonNull ExtendedWifiInfo wifiInfo, int networkAgentId) { - PerBssid perBssid = lookupBssid(wifiInfo.getSSID(), wifiInfo.getBSSID()); - logd("NETWORK_AGENT_ID: " + networkAgentId + " ID: " + perBssid.id); - perBssid.mNetworkAgentId = networkAgentId; - } - - /** - * Record disconnection not initiated by wpa_supplicant in connected mode - * @param reason is detailed disconnection reason code - */ - public void noteNonlocalDisconnect(int reason) { - mNonlocalDisconnection = true; - mDisconnectionReason = reason; - logd("nonlocal disconnection with reason: " + reason); - } - - /** - * Record firmware alert timestamp and error code - */ - public void noteFirmwareAlert(int errorCode) { - mFirmwareAlertTimeMs = mClock.getElapsedSinceBootMillis(); - logd("firmware alert with error code: " + errorCode); - } - - /** - * Updates the score card after a failed connection attempt - * - * @param wifiInfo object holding relevant values. - * @param scanRssi is the highest RSSI of recent scan found from scanDetailCache - * @param ssid is the network SSID. - * @param failureReason is connection failure reason - */ - public void noteConnectionFailure(@NonNull ExtendedWifiInfo wifiInfo, - int scanRssi, String ssid, @FailureReason int failureReason) { - // TODO: add the breakdown of level2FailureReason - updatePerBssid(Event.CONNECTION_FAILURE, wifiInfo); - - updatePerNetwork(Event.CONNECTION_FAILURE, ssid, scanRssi, LINK_SPEED_UNKNOWN, - failureReason); - resetConnectionStateInternal(false); - } - - /** - * Updates the score card after network reachability failure - * - * @param wifiInfo object holding relevant values - */ - public void noteIpReachabilityLost(@NonNull ExtendedWifiInfo wifiInfo) { - if (mTsRoam > TS_NONE) { - mTsConnectionAttemptStart = mTsRoam; // just to update elapsed - updatePerBssid(Event.ROAM_FAILURE, wifiInfo); - } else { - updatePerBssid(Event.IP_REACHABILITY_LOST, wifiInfo); - } - // No need to call resetConnectionStateInternal() because - // resetConnectionState() will be called after WifiNative.disconnect() in ClientModeImpl - doWrites(); - } - - /** - * Updates the score card before a roam - * - * We may have already done a firmware roam, but wifiInfo has not yet - * been updated, so we still have the old state. - * - * @param wifiInfo object holding relevant values - */ - private void noteRoam(@NonNull ExtendedWifiInfo wifiInfo) { - updatePerBssid(Event.LAST_POLL_BEFORE_ROAM, wifiInfo); - mTsRoam = mClock.getElapsedSinceBootMillis(); - } - - /** - * Called when the supplicant state is about to change, before wifiInfo is updated - * - * @param wifiInfo object holding old values - * @param state the new supplicant state - */ - public void noteSupplicantStateChanging(@NonNull ExtendedWifiInfo wifiInfo, - SupplicantState state) { - if (state == SupplicantState.COMPLETED && wifiInfo.getSupplicantState() == state) { - // Our signal that a firmware roam has occurred - noteRoam(wifiInfo); - } - logd("Changing state to " + state + " " + wifiInfo); - } - - /** - * Called after the supplicant state changed - * - * @param wifiInfo object holding old values - */ - public void noteSupplicantStateChanged(ExtendedWifiInfo wifiInfo) { - logd("STATE " + wifiInfo); - } - - /** - * Updates the score card after wifi is disabled - * - * @param wifiInfo object holding relevant values - */ - public void noteWifiDisabled(@NonNull ExtendedWifiInfo wifiInfo) { - updatePerBssid(Event.WIFI_DISABLED, wifiInfo); - resetConnectionStateInternal(false); - doWrites(); - } - - /** - * Records the last successful L2 connection timestamp for a BSSID. - * @return the previous BSSID connection time. - */ - public long setBssidConnectionTimestampMs(String ssid, String bssid, long timeMs) { - PerBssid perBssid = lookupBssid(ssid, bssid); - long prev = perBssid.lastConnectionTimestampMs; - perBssid.lastConnectionTimestampMs = timeMs; - return prev; - } - - /** - * Returns the last successful L2 connection time for this BSSID. - */ - public long getBssidConnectionTimestampMs(String ssid, String bssid) { - return lookupBssid(ssid, bssid).lastConnectionTimestampMs; - } - - /** - * Increment the blocklist streak count for a failure reason on an AP. - * @return the updated count - */ - public int incrementBssidBlocklistStreak(String ssid, String bssid, - @BssidBlocklistMonitor.FailureReason int reason) { - PerBssid perBssid = lookupBssid(ssid, bssid); - return ++perBssid.blocklistStreakCount[reason]; - } - - /** - * Get the blocklist streak count for a failure reason on an AP. - * @return the blocklist streak count - */ - public int getBssidBlocklistStreak(String ssid, String bssid, - @BssidBlocklistMonitor.FailureReason int reason) { - return lookupBssid(ssid, bssid).blocklistStreakCount[reason]; - } - - /** - * Clear the blocklist streak count for a failure reason on an AP. - */ - public void resetBssidBlocklistStreak(String ssid, String bssid, - @BssidBlocklistMonitor.FailureReason int reason) { - lookupBssid(ssid, bssid).blocklistStreakCount[reason] = 0; - } - - /** - * Clear the blocklist streak count for all APs that belong to this SSID. - */ - public void resetBssidBlocklistStreakForSsid(@NonNull String ssid) { - Iterator<Map.Entry<MacAddress, PerBssid>> it = mApForBssid.entrySet().iterator(); - while (it.hasNext()) { - PerBssid perBssid = it.next().getValue(); - if (!ssid.equals(perBssid.ssid)) { - continue; - } - for (int i = 0; i < perBssid.blocklistStreakCount.length; i++) { - perBssid.blocklistStreakCount[i] = 0; - } - } - } - - /** - * Detect abnormal disconnection at high RSSI with a high rate - */ - public int detectAbnormalDisconnection() { - String ssid = mAttemptingSwitch ? mSsidPrev : mSsidCurr; - PerNetwork perNetwork = lookupNetwork(ssid); - NetworkConnectionStats recentStats = perNetwork.getRecentStats(); - if (recentStats.getRecentCountCode() == CNT_SHORT_CONNECTION_NONLOCAL) { - return detectAbnormalFailureReason(recentStats, CNT_SHORT_CONNECTION_NONLOCAL, - REASON_SHORT_CONNECTION_NONLOCAL, - mDeviceConfigFacade.getShortConnectionNonlocalHighThrPercent(), - mDeviceConfigFacade.getShortConnectionNonlocalCountMin(), - CNT_DISCONNECTION); - } else if (recentStats.getRecentCountCode() == CNT_DISCONNECTION_NONLOCAL) { - return detectAbnormalFailureReason(recentStats, CNT_DISCONNECTION_NONLOCAL, - REASON_DISCONNECTION_NONLOCAL, - mDeviceConfigFacade.getDisconnectionNonlocalHighThrPercent(), - mDeviceConfigFacade.getDisconnectionNonlocalCountMin(), - CNT_DISCONNECTION); - } else { - return REASON_NO_FAILURE; - } - } - - /** - * Detect abnormal connection failure at high RSSI with a high rate - */ - public int detectAbnormalConnectionFailure(String ssid) { - PerNetwork perNetwork = lookupNetwork(ssid); - NetworkConnectionStats recentStats = perNetwork.getRecentStats(); - int recentCountCode = recentStats.getRecentCountCode(); - if (recentCountCode == CNT_AUTHENTICATION_FAILURE) { - return detectAbnormalFailureReason(recentStats, CNT_AUTHENTICATION_FAILURE, - REASON_AUTH_FAILURE, - mDeviceConfigFacade.getAuthFailureHighThrPercent(), - mDeviceConfigFacade.getAuthFailureCountMin(), - CNT_CONNECTION_ATTEMPT); - } else if (recentCountCode == CNT_ASSOCIATION_REJECTION) { - return detectAbnormalFailureReason(recentStats, CNT_ASSOCIATION_REJECTION, - REASON_ASSOC_REJECTION, - mDeviceConfigFacade.getAssocRejectionHighThrPercent(), - mDeviceConfigFacade.getAssocRejectionCountMin(), - CNT_CONNECTION_ATTEMPT); - } else if (recentCountCode == CNT_ASSOCIATION_TIMEOUT) { - return detectAbnormalFailureReason(recentStats, CNT_ASSOCIATION_TIMEOUT, - REASON_ASSOC_TIMEOUT, - mDeviceConfigFacade.getAssocTimeoutHighThrPercent(), - mDeviceConfigFacade.getAssocTimeoutCountMin(), - CNT_CONNECTION_ATTEMPT); - } else if (recentCountCode == CNT_CONNECTION_FAILURE) { - return detectAbnormalFailureReason(recentStats, CNT_CONNECTION_FAILURE, - REASON_CONNECTION_FAILURE, - mDeviceConfigFacade.getConnectionFailureHighThrPercent(), - mDeviceConfigFacade.getConnectionFailureCountMin(), - CNT_CONNECTION_ATTEMPT); - } else { - return REASON_NO_FAILURE; - } - } - - private int detectAbnormalFailureReason(NetworkConnectionStats stats, int countCode, - int reasonCode, int highThresholdPercent, int minCount, int refCountCode) { - // To detect abnormal failure which may trigger bugReport, - // increase the detection threshold by thresholdRatio - int thresholdRatio = - mDeviceConfigFacade.getBugReportThresholdExtraRatio(); - if (isHighPercentageAndEnoughCount(stats, countCode, reasonCode, - highThresholdPercent * thresholdRatio, - minCount * thresholdRatio, - refCountCode)) { - return reasonCode; - } else { - return REASON_NO_FAILURE; - } - } - - private boolean isHighPercentageAndEnoughCount(NetworkConnectionStats stats, int countCode, - int reasonCode, int highThresholdPercent, int minCount, int refCountCode) { - highThresholdPercent = Math.min(highThresholdPercent, 100); - // Use Laplace's rule of succession, useful especially for a small - // connection attempt count - // R = (f+1)/(n+2) with a pseudo count of 2 (one for f and one for s) - return ((stats.getCount(countCode) >= minCount) - && ((stats.getCount(countCode) + 1) * 100) - >= (highThresholdPercent * (stats.getCount(refCountCode) + 2))); - } - - final class PerBssid extends MemoryStoreAccessBase { - public int id; - public final String ssid; - public final MacAddress bssid; - public final int[] blocklistStreakCount = - new int[BssidBlocklistMonitor.NUMBER_REASON_CODES]; - // The wall clock time in milliseconds for the last successful l2 connection. - public long lastConnectionTimestampMs; - public boolean changed; - public boolean referenced; - - private SecurityType mSecurityType = null; - private int mNetworkAgentId = Integer.MIN_VALUE; - private int mNetworkConfigId = Integer.MIN_VALUE; - private final Map<Pair<Event, Integer>, PerSignal> - mSignalForEventAndFrequency = new ArrayMap<>(); - PerBssid(String ssid, MacAddress bssid) { - super(computeHashLong(ssid, bssid, mL2KeySeed)); - this.ssid = ssid; - this.bssid = bssid; - this.id = idFromLong(); - this.changed = false; - this.referenced = false; - } - void updateEventStats(Event event, int frequency, int rssi, int linkspeed) { - PerSignal perSignal = lookupSignal(event, frequency); - if (rssi != INVALID_RSSI) { - perSignal.rssi.update(rssi); - changed = true; - } - if (linkspeed > 0) { - perSignal.linkspeed.update(linkspeed); - changed = true; - } - if (perSignal.elapsedMs != null && mTsConnectionAttemptStart > TS_NONE) { - long millis = mClock.getElapsedSinceBootMillis() - mTsConnectionAttemptStart; - if (millis >= 0) { - perSignal.elapsedMs.update(millis); - changed = true; - } - } - } - PerSignal lookupSignal(Event event, int frequency) { - finishPendingRead(); - Pair<Event, Integer> key = new Pair<>(event, frequency); - PerSignal ans = mSignalForEventAndFrequency.get(key); - if (ans == null) { - ans = new PerSignal(event, frequency); - mSignalForEventAndFrequency.put(key, ans); - } - return ans; - } - SecurityType getSecurityType() { - finishPendingRead(); - return mSecurityType; - } - void setSecurityType(SecurityType securityType) { - finishPendingRead(); - if (!Objects.equals(securityType, mSecurityType)) { - mSecurityType = securityType; - changed = true; - } - } - void setNetworkConfigId(int networkConfigId) { - // Not serialized, so don't need to set changed, etc. - if (networkConfigId >= 0) { - mNetworkConfigId = networkConfigId; - } - } - AccessPoint toAccessPoint() { - return toAccessPoint(false); - } - AccessPoint toAccessPoint(boolean obfuscate) { - finishPendingRead(); - AccessPoint.Builder builder = AccessPoint.newBuilder(); - builder.setId(id); - if (!obfuscate) { - builder.setBssid(ByteString.copyFrom(bssid.toByteArray())); - } - if (mSecurityType != null) { - builder.setSecurityType(mSecurityType); - } - for (PerSignal sig: mSignalForEventAndFrequency.values()) { - builder.addEventStats(sig.toSignal()); - } - return builder.build(); - } - PerBssid merge(AccessPoint ap) { - if (ap.hasId() && this.id != ap.getId()) { - return this; - } - if (ap.hasSecurityType()) { - SecurityType prev = ap.getSecurityType(); - if (mSecurityType == null) { - mSecurityType = prev; - } else if (!mSecurityType.equals(prev)) { - if (mVerboseLoggingEnabled) { - Log.i(TAG, "ID: " + id - + "SecurityType changed: " + prev + " to " + mSecurityType); - } - changed = true; - } - } - for (Signal signal: ap.getEventStatsList()) { - Pair<Event, Integer> key = new Pair<>(signal.getEvent(), signal.getFrequency()); - PerSignal perSignal = mSignalForEventAndFrequency.get(key); - if (perSignal == null) { - mSignalForEventAndFrequency.put(key, - new PerSignal(key.first, key.second).merge(signal)); - // No need to set changed for this, since we are in sync with what's stored - } else { - perSignal.merge(signal); - changed = true; - } - } - return this; - } - - /** - * Handles (when convenient) the arrival of previously stored data. - * - * The response from IpMemoryStore arrives on a different thread, so we - * defer handling it until here, when we're on our favorite thread and - * in a good position to deal with it. We may have already collected some - * data before now, so we need to be prepared to merge the new and old together. - */ - void finishPendingRead() { - final byte[] serialized = finishPendingReadBytes(); - if (serialized == null) return; - AccessPoint ap; - try { - ap = AccessPoint.parseFrom(serialized); - } catch (InvalidProtocolBufferException e) { - Log.e(TAG, "Failed to deserialize", e); - return; - } - merge(ap); - } - - /** - * Estimates the probability of getting internet access, based on the - * device experience. - * - * @return a probability, expressed as a percentage in the range 0 to 100 - */ - public int estimatePercentInternetAvailability() { - // Initialize counts accoring to Laplace's rule of succession - int trials = 2; - int successes = 1; - // Aggregate over all of the frequencies - for (PerSignal s : mSignalForEventAndFrequency.values()) { - switch (s.event) { - case IP_CONFIGURATION_SUCCESS: - if (s.elapsedMs != null) { - trials += s.elapsedMs.count; - } - break; - case VALIDATION_SUCCESS: - if (s.elapsedMs != null) { - successes += s.elapsedMs.count; - } - break; - default: - break; - } - } - // Note that because of roaming it is possible to count successes - // without corresponding trials. - return Math.min(Math.max(Math.round(successes * 100.0f / trials), 0), 100); - } - } - - /** - * A class collecting the connection stats of one network or SSID. - */ - final class PerNetwork extends MemoryStoreAccessBase { - public int id; - public final String ssid; - public boolean changed; - private int mLastRssiPoll = INVALID_RSSI; - private int mLastTxSpeedPoll = LINK_SPEED_UNKNOWN; - private long mLastRssiPollTimeMs = TS_NONE; - private long mConnectionSessionStartTimeMs = TS_NONE; - private NetworkConnectionStats mRecentStats; - private NetworkConnectionStats mStatsCurrBuild; - private NetworkConnectionStats mStatsPrevBuild; - private LruList<Integer> mFrequencyList; - // In memory keep frequency with timestamp last time available, the elapsed time since boot. - private SparseLongArray mFreqTimestamp; - - PerNetwork(String ssid) { - super(computeHashLong(ssid, MacAddress.fromString(DEFAULT_MAC_ADDRESS), mL2KeySeed)); - this.ssid = ssid; - this.id = idFromLong(); - this.changed = false; - mRecentStats = new NetworkConnectionStats(); - mStatsCurrBuild = new NetworkConnectionStats(); - mStatsPrevBuild = new NetworkConnectionStats(); - mFrequencyList = new LruList<>(MAX_FREQUENCIES_PER_SSID); - mFreqTimestamp = new SparseLongArray(); - } - - void updateEventStats(Event event, int rssi, int txSpeed, int failureReason) { - finishPendingRead(); - long currTimeMs = mClock.getElapsedSinceBootMillis(); - switch (event) { - case SIGNAL_POLL: - mLastRssiPoll = rssi; - mLastRssiPollTimeMs = currTimeMs; - mLastTxSpeedPoll = txSpeed; - changed = true; - break; - case CONNECTION_ATTEMPT: - logd(" scan rssi: " + rssi); - if (rssi >= mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()) { - mRecentStats.incrementCount(CNT_CONNECTION_ATTEMPT); - } - mConnectionSessionStartTimeMs = currTimeMs; - changed = true; - break; - case CONNECTION_FAILURE: - mConnectionSessionStartTimeMs = TS_NONE; - if (rssi >= mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()) { - if (failureReason != BssidBlocklistMonitor.REASON_WRONG_PASSWORD) { - mRecentStats.incrementCount(CNT_CONNECTION_FAILURE); - mRecentStats.incrementCount(CNT_CONSECUTIVE_CONNECTION_FAILURE); - } - switch (failureReason) { - case BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA: - case BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION: - mRecentStats.incrementCount(CNT_ASSOCIATION_REJECTION); - break; - case BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT: - mRecentStats.incrementCount(CNT_ASSOCIATION_TIMEOUT); - break; - case BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE: - case BssidBlocklistMonitor.REASON_EAP_FAILURE: - mRecentStats.incrementCount(CNT_AUTHENTICATION_FAILURE); - break; - case BssidBlocklistMonitor.REASON_WRONG_PASSWORD: - case BssidBlocklistMonitor.REASON_DHCP_FAILURE: - default: - break; - } - } - changed = true; - break; - case WIFI_DISABLED: - case DISCONNECTION: - handleDisconnection(); - changed = true; - break; - default: - break; - } - logd(this.toString()); - } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("SSID: ").append(ssid).append("\n"); - if (mLastRssiPollTimeMs != TS_NONE) { - sb.append(" LastRssiPollTime: "); - sb.append(mLastRssiPollTimeMs); - } - sb.append(" LastRssiPoll: " + mLastRssiPoll); - sb.append(" LastTxSpeedPoll: " + mLastTxSpeedPoll); - sb.append("\n"); - sb.append(" StatsRecent: ").append(mRecentStats).append("\n"); - sb.append(" StatsCurr: ").append(mStatsCurrBuild).append("\n"); - sb.append(" StatsPrev: ").append(mStatsPrevBuild); - return sb.toString(); - } - private void handleDisconnection() { - if (mConnectionSessionStartTimeMs > TS_NONE) { - long currTimeMs = mClock.getElapsedSinceBootMillis(); - int currSessionDurationMs = (int) (currTimeMs - mConnectionSessionStartTimeMs); - int currSessionDurationSec = currSessionDurationMs / 1000; - mRecentStats.accumulate(CNT_CONNECTION_DURATION_SEC, currSessionDurationSec); - long timeSinceLastRssiPollMs = currTimeMs - mLastRssiPollTimeMs; - boolean hasRecentRssiPoll = mLastRssiPollTimeMs > TS_NONE - && timeSinceLastRssiPollMs <= mDeviceConfigFacade - .getHealthMonitorRssiPollValidTimeMs(); - if (hasRecentRssiPoll) { - mRecentStats.incrementCount(CNT_DISCONNECTION); - } - int fwAlertValidTimeMs = mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs(); - long timeSinceLastFirmAlert = currTimeMs - mFirmwareAlertTimeMs; - boolean isInvalidFwAlertTime = mFirmwareAlertTimeMs == TS_NONE; - boolean disableFwAlertCheck = fwAlertValidTimeMs == -1; - boolean passFirmwareAlertCheck = disableFwAlertCheck ? true : (isInvalidFwAlertTime - ? false : timeSinceLastFirmAlert < fwAlertValidTimeMs); - boolean hasHighRssiOrHighTxSpeed = - mLastRssiPoll >= mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm() - || mLastTxSpeedPoll >= HEALTH_MONITOR_COUNT_TX_SPEED_MIN_MBPS; - if (mNonlocalDisconnection && hasRecentRssiPoll - && isAbnormalDisconnectionReason(mDisconnectionReason) - && passFirmwareAlertCheck - && hasHighRssiOrHighTxSpeed) { - mRecentStats.incrementCount(CNT_DISCONNECTION_NONLOCAL); - if (currSessionDurationMs <= mDeviceConfigFacade - .getHealthMonitorShortConnectionDurationThrMs()) { - mRecentStats.incrementCount(CNT_SHORT_CONNECTION_NONLOCAL); - } - } - } - // Reset CNT_CONSECUTIVE_CONNECTION_FAILURE here so that it can report the correct - // failure count after a connection success - mRecentStats.clearCount(CNT_CONSECUTIVE_CONNECTION_FAILURE); - mConnectionSessionStartTimeMs = TS_NONE; - mLastRssiPollTimeMs = TS_NONE; - } - - private boolean isAbnormalDisconnectionReason(int disconnectionReason) { - long mask = mDeviceConfigFacade.getAbnormalDisconnectionReasonCodeMask(); - return disconnectionReason >= 0 && disconnectionReason <= 63 - && ((mask >> disconnectionReason) & 0x1) == 0x1; - } - - @NonNull NetworkConnectionStats getRecentStats() { - return mRecentStats; - } - @NonNull NetworkConnectionStats getStatsCurrBuild() { - return mStatsCurrBuild; - } - @NonNull NetworkConnectionStats getStatsPrevBuild() { - return mStatsPrevBuild; - } - - /** - * Retrieve the list of frequencies seen for this network, with the most recent first. - * @param ageInMills Max age to filter the channels. - * @return a list of frequencies - */ - List<Integer> getFrequencies(Long ageInMills) { - List<Integer> results = new ArrayList<>(); - Long nowInMills = mClock.getElapsedSinceBootMillis(); - for (Integer freq : mFrequencyList.getEntries()) { - if (nowInMills - mFreqTimestamp.get(freq, 0L) > ageInMills) { - continue; - } - results.add(freq); - } - return results; - } - - /** - * Add a frequency to the list of frequencies for this network. - * Will evict the least recently added frequency if the cache is full. - */ - void addFrequency(int frequency) { - mFrequencyList.add(frequency); - mFreqTimestamp.put(frequency, mClock.getElapsedSinceBootMillis()); - } - - /** - /* Detect a significant failure stats change with historical data - /* or high failure stats without historical data. - /* @return 0 if recentStats doesn't have sufficient data - * 1 if recentStats has sufficient data while statsPrevBuild doesn't - * 2 if recentStats and statsPrevBuild have sufficient data - */ - int dailyDetection(FailureStats statsDec, FailureStats statsInc, FailureStats statsHigh) { - finishPendingRead(); - dailyDetectionDisconnectionEvent(statsDec, statsInc, statsHigh); - return dailyDetectionConnectionEvent(statsDec, statsInc, statsHigh); - } - - private int dailyDetectionConnectionEvent(FailureStats statsDec, FailureStats statsInc, - FailureStats statsHigh) { - // Skip daily detection if recentStats is not sufficient - if (!isRecentConnectionStatsSufficient()) return INSUFFICIENT_RECENT_STATS; - if (mStatsPrevBuild.getCount(CNT_CONNECTION_ATTEMPT) - < mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()) { - // don't have enough historical data, - // so only detect high failure stats without relying on mStatsPrevBuild. - recentStatsHighDetectionConnection(statsHigh); - return SUFFICIENT_RECENT_STATS_ONLY; - } else { - // mStatsPrevBuild has enough updates, - // detect improvement or degradation - statsDeltaDetectionConnection(statsDec, statsInc); - return SUFFICIENT_RECENT_PREV_STATS; - } - } - - private void dailyDetectionDisconnectionEvent(FailureStats statsDec, FailureStats statsInc, - FailureStats statsHigh) { - // Skip daily detection if recentStats is not sufficient - int minConnectAttempt = mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt(); - if (mRecentStats.getCount(CNT_CONNECTION_ATTEMPT) < minConnectAttempt) { - return; - } - if (mStatsPrevBuild.getCount(CNT_CONNECTION_ATTEMPT) < minConnectAttempt) { - recentStatsHighDetectionDisconnection(statsHigh); - } else { - statsDeltaDetectionDisconnection(statsDec, statsInc); - } - } - - private void statsDeltaDetectionConnection(FailureStats statsDec, - FailureStats statsInc) { - statsDeltaDetection(statsDec, statsInc, CNT_CONNECTION_FAILURE, - REASON_CONNECTION_FAILURE, - mDeviceConfigFacade.getConnectionFailureCountMin(), - CNT_CONNECTION_ATTEMPT); - statsDeltaDetection(statsDec, statsInc, CNT_AUTHENTICATION_FAILURE, - REASON_AUTH_FAILURE, - mDeviceConfigFacade.getAuthFailureCountMin(), - CNT_CONNECTION_ATTEMPT); - statsDeltaDetection(statsDec, statsInc, CNT_ASSOCIATION_REJECTION, - REASON_ASSOC_REJECTION, - mDeviceConfigFacade.getAssocRejectionCountMin(), - CNT_CONNECTION_ATTEMPT); - statsDeltaDetection(statsDec, statsInc, CNT_ASSOCIATION_TIMEOUT, - REASON_ASSOC_TIMEOUT, - mDeviceConfigFacade.getAssocTimeoutCountMin(), - CNT_CONNECTION_ATTEMPT); - } - - private void recentStatsHighDetectionConnection(FailureStats statsHigh) { - recentStatsHighDetection(statsHigh, CNT_CONNECTION_FAILURE, - REASON_CONNECTION_FAILURE, - mDeviceConfigFacade.getConnectionFailureHighThrPercent(), - mDeviceConfigFacade.getConnectionFailureCountMin(), - CNT_CONNECTION_ATTEMPT); - recentStatsHighDetection(statsHigh, CNT_AUTHENTICATION_FAILURE, - REASON_AUTH_FAILURE, - mDeviceConfigFacade.getAuthFailureHighThrPercent(), - mDeviceConfigFacade.getAuthFailureCountMin(), - CNT_CONNECTION_ATTEMPT); - recentStatsHighDetection(statsHigh, CNT_ASSOCIATION_REJECTION, - REASON_ASSOC_REJECTION, - mDeviceConfigFacade.getAssocRejectionHighThrPercent(), - mDeviceConfigFacade.getAssocRejectionCountMin(), - CNT_CONNECTION_ATTEMPT); - recentStatsHighDetection(statsHigh, CNT_ASSOCIATION_TIMEOUT, - REASON_ASSOC_TIMEOUT, - mDeviceConfigFacade.getAssocTimeoutHighThrPercent(), - mDeviceConfigFacade.getAssocTimeoutCountMin(), - CNT_CONNECTION_ATTEMPT); - } - - private void statsDeltaDetectionDisconnection(FailureStats statsDec, - FailureStats statsInc) { - statsDeltaDetection(statsDec, statsInc, CNT_SHORT_CONNECTION_NONLOCAL, - REASON_SHORT_CONNECTION_NONLOCAL, - mDeviceConfigFacade.getShortConnectionNonlocalCountMin(), - CNT_CONNECTION_ATTEMPT); - statsDeltaDetection(statsDec, statsInc, CNT_DISCONNECTION_NONLOCAL, - REASON_DISCONNECTION_NONLOCAL, - mDeviceConfigFacade.getDisconnectionNonlocalCountMin(), - CNT_CONNECTION_ATTEMPT); - } - - private void recentStatsHighDetectionDisconnection(FailureStats statsHigh) { - recentStatsHighDetection(statsHigh, CNT_SHORT_CONNECTION_NONLOCAL, - REASON_SHORT_CONNECTION_NONLOCAL, - mDeviceConfigFacade.getShortConnectionNonlocalHighThrPercent(), - mDeviceConfigFacade.getShortConnectionNonlocalCountMin(), - CNT_DISCONNECTION); - recentStatsHighDetection(statsHigh, CNT_DISCONNECTION_NONLOCAL, - REASON_DISCONNECTION_NONLOCAL, - mDeviceConfigFacade.getDisconnectionNonlocalHighThrPercent(), - mDeviceConfigFacade.getDisconnectionNonlocalCountMin(), - CNT_DISCONNECTION); - } - - private boolean statsDeltaDetection(FailureStats statsDec, - FailureStats statsInc, int countCode, int reasonCode, - int minCount, int refCountCode) { - if (isRatioAboveThreshold(mRecentStats, mStatsPrevBuild, countCode, refCountCode) - && mRecentStats.getCount(countCode) >= minCount) { - statsInc.incrementCount(reasonCode); - return true; - } - - if (isRatioAboveThreshold(mStatsPrevBuild, mRecentStats, countCode, refCountCode) - && mStatsPrevBuild.getCount(countCode) >= minCount) { - statsDec.incrementCount(reasonCode); - return true; - } - return false; - } - - private boolean recentStatsHighDetection(FailureStats statsHigh, int countCode, - int reasonCode, int highThresholdPercent, int minCount, int refCountCode) { - if (isHighPercentageAndEnoughCount(mRecentStats, countCode, reasonCode, - highThresholdPercent, minCount, refCountCode)) { - statsHigh.incrementCount(reasonCode); - return true; - } - return false; - } - - private boolean isRatioAboveThreshold(NetworkConnectionStats stats1, - NetworkConnectionStats stats2, - @ConnectionCountCode int countCode, int refCountCode) { - // Also with Laplace's rule of succession discussed above - // R1 = (stats1(countCode) + 1) / (stats1(refCountCode) + 2) - // R2 = (stats2(countCode) + 1) / (stats2(refCountCode) + 2) - // Check R1 / R2 >= ratioThr - return ((stats1.getCount(countCode) + 1) * (stats2.getCount(refCountCode) + 2) - * mDeviceConfigFacade.HEALTH_MONITOR_RATIO_THR_DENOMINATOR) - >= ((stats1.getCount(refCountCode) + 2) * (stats2.getCount(countCode) + 1) - * mDeviceConfigFacade.getHealthMonitorRatioThrNumerator()); - } - - private boolean isRecentConnectionStatsSufficient() { - return (mRecentStats.getCount(CNT_CONNECTION_ATTEMPT) - >= mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()); - } - - // Update StatsCurrBuild with recentStats and clear recentStats - void updateAfterDailyDetection() { - // Skip update if recentStats is not sufficient since daily detection is also skipped - if (!isRecentConnectionStatsSufficient()) return; - mStatsCurrBuild.accumulateAll(mRecentStats); - mRecentStats.clear(); - changed = true; - } - - // Refresh StatsPrevBuild with StatsCurrBuild which is cleared afterwards - void updateAfterSwBuildChange() { - finishPendingRead(); - mStatsPrevBuild.copy(mStatsCurrBuild); - mRecentStats.clear(); - mStatsCurrBuild.clear(); - changed = true; - } - - NetworkStats toNetworkStats() { - finishPendingRead(); - NetworkStats.Builder builder = NetworkStats.newBuilder(); - builder.setId(id); - builder.setRecentStats(toConnectionStats(mRecentStats)); - builder.setStatsCurrBuild(toConnectionStats(mStatsCurrBuild)); - builder.setStatsPrevBuild(toConnectionStats(mStatsPrevBuild)); - if (mFrequencyList.size() > 0) { - builder.addAllFrequencies(mFrequencyList.getEntries()); - } - return builder.build(); - } - - private ConnectionStats toConnectionStats(NetworkConnectionStats stats) { - ConnectionStats.Builder builder = ConnectionStats.newBuilder(); - builder.setNumConnectionAttempt(stats.getCount(CNT_CONNECTION_ATTEMPT)); - builder.setNumConnectionFailure(stats.getCount(CNT_CONNECTION_FAILURE)); - builder.setConnectionDurationSec(stats.getCount(CNT_CONNECTION_DURATION_SEC)); - builder.setNumDisconnectionNonlocal(stats.getCount(CNT_DISCONNECTION_NONLOCAL)); - builder.setNumDisconnection(stats.getCount(CNT_DISCONNECTION)); - builder.setNumShortConnectionNonlocal(stats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); - builder.setNumAssociationRejection(stats.getCount(CNT_ASSOCIATION_REJECTION)); - builder.setNumAssociationTimeout(stats.getCount(CNT_ASSOCIATION_TIMEOUT)); - builder.setNumAuthenticationFailure(stats.getCount(CNT_AUTHENTICATION_FAILURE)); - return builder.build(); - } - - void finishPendingRead() { - final byte[] serialized = finishPendingReadBytes(); - if (serialized == null) return; - NetworkStats ns; - try { - ns = NetworkStats.parseFrom(serialized); - } catch (InvalidProtocolBufferException e) { - Log.e(TAG, "Failed to deserialize", e); - return; - } - mergeNetworkStatsFromMemory(ns); - changed = true; - } - - PerNetwork mergeNetworkStatsFromMemory(@NonNull NetworkStats ns) { - if (ns.hasId() && this.id != ns.getId()) { - return this; - } - if (ns.hasRecentStats()) { - ConnectionStats recentStats = ns.getRecentStats(); - mergeConnectionStats(recentStats, mRecentStats); - } - if (ns.hasStatsCurrBuild()) { - ConnectionStats statsCurr = ns.getStatsCurrBuild(); - mStatsCurrBuild.clear(); - mergeConnectionStats(statsCurr, mStatsCurrBuild); - } - if (ns.hasStatsPrevBuild()) { - ConnectionStats statsPrev = ns.getStatsPrevBuild(); - mStatsPrevBuild.clear(); - mergeConnectionStats(statsPrev, mStatsPrevBuild); - } - if (ns.getFrequenciesList().size() > 0) { - // This merge assumes that whatever data is in memory is more recent that what's - // in store - List<Integer> mergedFrequencyList = mFrequencyList.getEntries(); - mergedFrequencyList.addAll(ns.getFrequenciesList()); - mFrequencyList = new LruList<>(MAX_FREQUENCIES_PER_SSID); - for (int i = mergedFrequencyList.size() - 1; i >= 0; i--) { - mFrequencyList.add(mergedFrequencyList.get(i)); - } - } - return this; - } - - private void mergeConnectionStats(ConnectionStats source, NetworkConnectionStats target) { - if (source.hasNumConnectionAttempt()) { - target.accumulate(CNT_CONNECTION_ATTEMPT, source.getNumConnectionAttempt()); - } - if (source.hasNumConnectionFailure()) { - target.accumulate(CNT_CONNECTION_ATTEMPT, source.getNumConnectionFailure()); - } - if (source.hasConnectionDurationSec()) { - target.accumulate(CNT_CONNECTION_DURATION_SEC, source.getConnectionDurationSec()); - } - if (source.hasNumDisconnectionNonlocal()) { - target.accumulate(CNT_DISCONNECTION_NONLOCAL, source.getNumDisconnectionNonlocal()); - } - if (source.hasNumDisconnection()) { - target.accumulate(CNT_DISCONNECTION, source.getNumDisconnection()); - } - if (source.hasNumShortConnectionNonlocal()) { - target.accumulate(CNT_SHORT_CONNECTION_NONLOCAL, - source.getNumShortConnectionNonlocal()); - } - if (source.hasNumAssociationRejection()) { - target.accumulate(CNT_ASSOCIATION_REJECTION, source.getNumAssociationRejection()); - } - if (source.hasNumAssociationTimeout()) { - target.accumulate(CNT_ASSOCIATION_TIMEOUT, source.getNumAssociationTimeout()); - } - if (source.hasNumAuthenticationFailure()) { - target.accumulate(CNT_AUTHENTICATION_FAILURE, source.getNumAuthenticationFailure()); - } - } - } - - // Codes for various connection related counts - public static final int CNT_INVALID = -1; - public static final int CNT_CONNECTION_ATTEMPT = 0; - public static final int CNT_CONNECTION_FAILURE = 1; - public static final int CNT_CONNECTION_DURATION_SEC = 2; - public static final int CNT_ASSOCIATION_REJECTION = 3; - public static final int CNT_ASSOCIATION_TIMEOUT = 4; - public static final int CNT_AUTHENTICATION_FAILURE = 5; - public static final int CNT_SHORT_CONNECTION_NONLOCAL = 6; - public static final int CNT_DISCONNECTION_NONLOCAL = 7; - public static final int CNT_DISCONNECTION = 8; - public static final int CNT_CONSECUTIVE_CONNECTION_FAILURE = 9; - // Constant being used to keep track of how many counter there are. - public static final int NUMBER_CONNECTION_CNT_CODE = 10; - private static final String[] CONNECTION_CNT_NAME = { - " ConnectAttempt: ", - " ConnectFailure: ", - " ConnectDurSec: ", - " AssocRej: ", - " AssocTimeout: ", - " AuthFailure: ", - " ShortDiscNonlocal: ", - " DisconnectNonlocal: ", - " Disconnect: ", - " ConsecutiveConnectFailure: " - }; - - @IntDef(prefix = { "CNT_" }, value = { - CNT_CONNECTION_ATTEMPT, - CNT_CONNECTION_FAILURE, - CNT_CONNECTION_DURATION_SEC, - CNT_ASSOCIATION_REJECTION, - CNT_ASSOCIATION_TIMEOUT, - CNT_AUTHENTICATION_FAILURE, - CNT_SHORT_CONNECTION_NONLOCAL, - CNT_DISCONNECTION_NONLOCAL, - CNT_DISCONNECTION, - CNT_CONSECUTIVE_CONNECTION_FAILURE - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ConnectionCountCode {} - - /** - * A class maintaining the connection related statistics of a Wifi network. - */ - public static class NetworkConnectionStats { - private final int[] mCount = new int[NUMBER_CONNECTION_CNT_CODE]; - private int mRecentCountCode = CNT_INVALID; - /** - * Copy all values - * @param src is the source of copy - */ - public void copy(NetworkConnectionStats src) { - for (int i = 0; i < NUMBER_CONNECTION_CNT_CODE; i++) { - mCount[i] = src.getCount(i); - } - mRecentCountCode = src.mRecentCountCode; - } - - /** - * Clear all counters - */ - public void clear() { - for (int i = 0; i < NUMBER_CONNECTION_CNT_CODE; i++) { - mCount[i] = 0; - } - mRecentCountCode = CNT_INVALID; - } - - /** - * Get counter value - * @param countCode is the selected counter - * @return the value of selected counter - */ - public int getCount(@ConnectionCountCode int countCode) { - return mCount[countCode]; - } - - /** - * Clear counter value - * @param countCode is the selected counter to be cleared - */ - public void clearCount(@ConnectionCountCode int countCode) { - mCount[countCode] = 0; - } - - /** - * Increment count value by 1 - * @param countCode is the selected counter - */ - public void incrementCount(@ConnectionCountCode int countCode) { - mCount[countCode]++; - mRecentCountCode = countCode; - } - - /** - * Got the recent incremented count code - */ - public int getRecentCountCode() { - return mRecentCountCode; - } - - /** - * Decrement count value by 1 - * @param countCode is the selected counter - */ - public void decrementCount(@ConnectionCountCode int countCode) { - mCount[countCode]--; - } - - /** - * Add and accumulate the selected counter - * @param countCode is the selected counter - * @param cnt is the value to be added to the counter - */ - public void accumulate(@ConnectionCountCode int countCode, int cnt) { - mCount[countCode] += cnt; - } - - /** - * Accumulate daily stats to historical data - * @param recentStats are the raw daily counts - */ - public void accumulateAll(NetworkConnectionStats recentStats) { - // 32-bit counter in second can support connection duration up to 68 years. - // Similarly 32-bit counter can support up to continuous connection attempt - // up to 68 years with one attempt per second. - for (int i = 0; i < NUMBER_CONNECTION_CNT_CODE; i++) { - mCount[i] += recentStats.getCount(i); - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < NUMBER_CONNECTION_CNT_CODE; i++) { - sb.append(CONNECTION_CNT_NAME[i]); - sb.append(mCount[i]); - } - return sb.toString(); - } - } - /** - * A base class dealing with common operations of MemoryStore. - */ - public static class MemoryStoreAccessBase { - private final String mL2Key; - private final long mHash; - private static final String TAG = "WifiMemoryStoreAccessBase"; - private final AtomicReference<byte[]> mPendingReadFromStore = new AtomicReference<>(); - MemoryStoreAccessBase(long hash) { - mHash = hash; - mL2Key = l2KeyFromLong(); - } - String getL2Key() { - return mL2Key; - } - - private String l2KeyFromLong() { - return "W" + Long.toHexString(mHash); - } - - /** - * Callback function when MemoryStore read is done - * @param serialized is the readback value - */ - void readBackListener(byte[] serialized) { - if (serialized == null) return; - byte[] old = mPendingReadFromStore.getAndSet(serialized); - if (old != null) { - Log.e(TAG, "More answers than we expected!"); - } - } - - /** - * Handles (when convenient) the arrival of previously stored data. - * - * The response from IpMemoryStore arrives on a different thread, so we - * defer handling it until here, when we're on our favorite thread and - * in a good position to deal with it. We may have already collected some - * data before now, so we need to be prepared to merge the new and old together. - */ - byte[] finishPendingReadBytes() { - return mPendingReadFromStore.getAndSet(null); - } - - int idFromLong() { - return (int) mHash & 0x7fffffff; - } - } - - private void logd(String string) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, string); - } - } - // Returned by lookupBssid when the BSSID is not available, - // for instance when we are not associated. - private final PerBssid mDummyPerBssid; - - private final Map<MacAddress, PerBssid> mApForBssid = new ArrayMap<>(); - private int mApForBssidTargetSize = TARGET_IN_MEMORY_ENTRIES; - private int mApForBssidReferenced = 0; - - // TODO should be private, but WifiCandidates needs it - @NonNull PerBssid lookupBssid(String ssid, String bssid) { - MacAddress mac; - if (ssid == null || WifiManager.UNKNOWN_SSID.equals(ssid) || bssid == null) { - return mDummyPerBssid; - } - try { - mac = MacAddress.fromString(bssid); - } catch (IllegalArgumentException e) { - return mDummyPerBssid; - } - if (mac.equals(mDummyPerBssid.bssid)) { - return mDummyPerBssid; - } - PerBssid ans = mApForBssid.get(mac); - if (ans == null || !ans.ssid.equals(ssid)) { - ans = new PerBssid(ssid, mac); - PerBssid old = mApForBssid.put(mac, ans); - if (old != null) { - Log.i(TAG, "Discarding stats for score card (ssid changed) ID: " + old.id); - if (old.referenced) mApForBssidReferenced--; - } - requestReadBssid(ans); - } - if (!ans.referenced) { - ans.referenced = true; - mApForBssidReferenced++; - clean(); - } - return ans; - } - - private void requestReadBssid(final PerBssid perBssid) { - if (mMemoryStore != null) { - mMemoryStore.read(perBssid.getL2Key(), PER_BSSID_DATA_NAME, - (value) -> perBssid.readBackListener(value)); - } - } - - private void requestReadForAllChanged() { - for (PerBssid perBssid : mApForBssid.values()) { - if (perBssid.changed) { - requestReadBssid(perBssid); - } - } - } - - // Returned by lookupNetwork when the network is not available, - // for instance when we are not associated. - private final PerNetwork mDummyPerNetwork; - private final Map<String, PerNetwork> mApForNetwork = new ArrayMap<>(); - PerNetwork lookupNetwork(String ssid) { - if (ssid == null || WifiManager.UNKNOWN_SSID.equals(ssid)) { - return mDummyPerNetwork; - } - - PerNetwork ans = mApForNetwork.get(ssid); - if (ans == null) { - ans = new PerNetwork(ssid); - mApForNetwork.put(ssid, ans); - requestReadNetwork(ans); - } - return ans; - } - - /** - * Remove network from cache and memory store - * @param ssid is the network SSID - */ - public void removeNetwork(String ssid) { - if (ssid == null || WifiManager.UNKNOWN_SSID.equals(ssid)) { - return; - } - mApForNetwork.remove(ssid); - mApForBssid.entrySet().removeIf(entry -> ssid.equals(entry.getValue().ssid)); - if (mMemoryStore == null) return; - mMemoryStore.removeCluster(groupHintFromSsid(ssid)); - } - - void requestReadNetwork(final PerNetwork perNetwork) { - if (mMemoryStore != null) { - mMemoryStore.read(perNetwork.getL2Key(), PER_NETWORK_DATA_NAME, - (value) -> perNetwork.readBackListener(value)); - } - } - - /** - * Issues write requests for all changed entries. - * - * This should be called from time to time to save the state to persistent - * storage. Since we always check internal state first, this does not need - * to be called very often, but it should be called before shutdown. - * - * @returns number of writes issued. - */ - public int doWrites() { - return doWritesBssid() + doWritesNetwork(); - } - - private int doWritesBssid() { - if (mMemoryStore == null) return 0; - int count = 0; - int bytes = 0; - for (PerBssid perBssid : mApForBssid.values()) { - if (perBssid.changed) { - perBssid.finishPendingRead(); - byte[] serialized = perBssid.toAccessPoint(/* No BSSID */ true).toByteArray(); - mMemoryStore.setCluster(perBssid.getL2Key(), groupHintFromSsid(perBssid.ssid)); - mMemoryStore.write(perBssid.getL2Key(), PER_BSSID_DATA_NAME, serialized); - - perBssid.changed = false; - count++; - bytes += serialized.length; - } - } - if (mVerboseLoggingEnabled && count > 0) { - Log.v(TAG, "Write count: " + count + ", bytes: " + bytes); - } - return count; - } - - private int doWritesNetwork() { - if (mMemoryStore == null) return 0; - int count = 0; - int bytes = 0; - for (PerNetwork perNetwork : mApForNetwork.values()) { - if (perNetwork.changed) { - perNetwork.finishPendingRead(); - byte[] serialized = perNetwork.toNetworkStats().toByteArray(); - mMemoryStore.setCluster(perNetwork.getL2Key(), groupHintFromSsid(perNetwork.ssid)); - mMemoryStore.write(perNetwork.getL2Key(), PER_NETWORK_DATA_NAME, serialized); - perNetwork.changed = false; - count++; - bytes += serialized.length; - } - } - if (mVerboseLoggingEnabled && count > 0) { - Log.v(TAG, "Write count: " + count + ", bytes: " + bytes); - } - return count; - } - - /** - * Evicts older entries from memory. - * - * This uses an approximate least-recently-used method. When the number of - * referenced entries exceeds the target value, any items that have not been - * referenced since the last round are evicted, and the remaining entries - * are marked as unreferenced. The total count varies between the target - * value and twice the target value. - */ - private void clean() { - if (mMemoryStore == null) return; - if (mApForBssidReferenced >= mApForBssidTargetSize) { - doWritesBssid(); // Do not want to evict changed items - // Evict the unreferenced ones, and clear all the referenced bits for the next round. - Iterator<Map.Entry<MacAddress, PerBssid>> it = mApForBssid.entrySet().iterator(); - while (it.hasNext()) { - PerBssid perBssid = it.next().getValue(); - if (perBssid.referenced) { - perBssid.referenced = false; - } else { - it.remove(); - if (mVerboseLoggingEnabled) Log.v(TAG, "Evict " + perBssid.id); - } - } - mApForBssidReferenced = 0; - } - } - - /** - * Compute a hash value with the given SSID and MAC address - * @param ssid is the network SSID - * @param mac is the network MAC address - * @param l2KeySeed is the seed for hash generation - * @return - */ - public static long computeHashLong(String ssid, MacAddress mac, String l2KeySeed) { - final ArrayList<Byte> decodedSsid; - try { - decodedSsid = NativeUtil.decodeSsid(ssid); - } catch (IllegalArgumentException e) { - Log.e(TAG, "NativeUtil.decodeSsid failed: malformed string: " + ssid); - return 0; - } - byte[][] parts = { - // Our seed keeps the L2Keys specific to this device - l2KeySeed.getBytes(), - // ssid is either quoted utf8 or hex-encoded bytes; turn it into plain bytes. - NativeUtil.byteArrayFromArrayList(decodedSsid), - // And the BSSID - mac.toByteArray() - }; - // Assemble the parts into one, with single-byte lengths before each. - int n = 0; - for (int i = 0; i < parts.length; i++) { - n += 1 + parts[i].length; - } - byte[] mashed = new byte[n]; - int p = 0; - for (int i = 0; i < parts.length; i++) { - byte[] part = parts[i]; - mashed[p++] = (byte) part.length; - for (int j = 0; j < part.length; j++) { - mashed[p++] = part[j]; - } - } - // Finally, turn that into a long - MessageDigest md; - try { - md = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - Log.e(TAG, "SHA-256 not supported."); - return 0; - } - ByteBuffer buffer = ByteBuffer.wrap(md.digest(mashed)); - return buffer.getLong(); - } - - private static String groupHintFromLong(long hash) { - return "G" + Long.toHexString(hash); - } - - @VisibleForTesting - PerBssid fetchByBssid(MacAddress mac) { - return mApForBssid.get(mac); - } - - @VisibleForTesting - PerNetwork fetchByNetwork(String ssid) { - return mApForNetwork.get(ssid); - } - - @VisibleForTesting - PerBssid perBssidFromAccessPoint(String ssid, AccessPoint ap) { - MacAddress bssid = MacAddress.fromBytes(ap.getBssid().toByteArray()); - return new PerBssid(ssid, bssid).merge(ap); - } - - @VisibleForTesting - PerNetwork perNetworkFromNetworkStats(String ssid, NetworkStats ns) { - return new PerNetwork(ssid).mergeNetworkStatsFromMemory(ns); - } - - final class PerSignal { - public final Event event; - public final int frequency; - public final PerUnivariateStatistic rssi; - public final PerUnivariateStatistic linkspeed; - @Nullable public final PerUnivariateStatistic elapsedMs; - PerSignal(Event event, int frequency) { - this.event = event; - this.frequency = frequency; - switch (event) { - case SIGNAL_POLL: - case IP_CONFIGURATION_SUCCESS: - case IP_REACHABILITY_LOST: - this.rssi = new PerUnivariateStatistic(RSSI_BUCKETS); - break; - default: - this.rssi = new PerUnivariateStatistic(); - break; - } - this.linkspeed = new PerUnivariateStatistic(); - switch (event) { - case FIRST_POLL_AFTER_CONNECTION: - case IP_CONFIGURATION_SUCCESS: - case VALIDATION_SUCCESS: - case CONNECTION_FAILURE: - case DISCONNECTION: - case WIFI_DISABLED: - case ROAM_FAILURE: - this.elapsedMs = new PerUnivariateStatistic(); - break; - default: - this.elapsedMs = null; - break; - } - } - PerSignal merge(Signal signal) { - Preconditions.checkArgument(event == signal.getEvent()); - Preconditions.checkArgument(frequency == signal.getFrequency()); - rssi.merge(signal.getRssi()); - linkspeed.merge(signal.getLinkspeed()); - if (elapsedMs != null && signal.hasElapsedMs()) { - elapsedMs.merge(signal.getElapsedMs()); - } - return this; - } - Signal toSignal() { - Signal.Builder builder = Signal.newBuilder(); - builder.setEvent(event) - .setFrequency(frequency) - .setRssi(rssi.toUnivariateStatistic()) - .setLinkspeed(linkspeed.toUnivariateStatistic()); - if (elapsedMs != null) { - builder.setElapsedMs(elapsedMs.toUnivariateStatistic()); - } - if (rssi.intHistogram != null - && rssi.intHistogram.numNonEmptyBuckets() > 0) { - logd("Histogram " + event + " RSSI" + rssi.intHistogram); - } - return builder.build(); - } - } - - final class PerUnivariateStatistic { - public long count = 0; - public double sum = 0.0; - public double sumOfSquares = 0.0; - public double minValue = Double.POSITIVE_INFINITY; - public double maxValue = Double.NEGATIVE_INFINITY; - public double historicalMean = 0.0; - public double historicalVariance = Double.POSITIVE_INFINITY; - public IntHistogram intHistogram = null; - PerUnivariateStatistic() {} - PerUnivariateStatistic(int[] bucketBoundaries) { - intHistogram = new IntHistogram(bucketBoundaries); - } - void update(double value) { - count++; - sum += value; - sumOfSquares += value * value; - minValue = Math.min(minValue, value); - maxValue = Math.max(maxValue, value); - if (intHistogram != null) { - intHistogram.add(Math.round((float) value), 1); - } - } - void age() { - //TODO Fold the current stats into the historical stats - } - void merge(UnivariateStatistic stats) { - if (stats.hasCount()) { - count += stats.getCount(); - sum += stats.getSum(); - sumOfSquares += stats.getSumOfSquares(); - } - if (stats.hasMinValue()) { - minValue = Math.min(minValue, stats.getMinValue()); - } - if (stats.hasMaxValue()) { - maxValue = Math.max(maxValue, stats.getMaxValue()); - } - if (stats.hasHistoricalVariance()) { - if (historicalVariance < Double.POSITIVE_INFINITY) { - // Combine the estimates; c.f. - // Maybeck, Stochasic Models, Estimation, and Control, Vol. 1 - // equations (1-3) and (1-4) - double numer1 = stats.getHistoricalVariance(); - double numer2 = historicalVariance; - double denom = numer1 + numer2; - historicalMean = (numer1 * historicalMean - + numer2 * stats.getHistoricalMean()) - / denom; - historicalVariance = numer1 * numer2 / denom; - } else { - historicalMean = stats.getHistoricalMean(); - historicalVariance = stats.getHistoricalVariance(); - } - } - if (intHistogram != null) { - for (HistogramBucket bucket : stats.getBucketsList()) { - long low = bucket.getLow(); - long count = bucket.getNumber(); - if (low != (int) low || count != (int) count || count < 0) { - Log.e(TAG, "Found corrupted histogram! Clearing."); - intHistogram.clear(); - break; - } - intHistogram.add((int) low, (int) count); - } - } - } - UnivariateStatistic toUnivariateStatistic() { - UnivariateStatistic.Builder builder = UnivariateStatistic.newBuilder(); - if (count != 0) { - builder.setCount(count) - .setSum(sum) - .setSumOfSquares(sumOfSquares) - .setMinValue(minValue) - .setMaxValue(maxValue); - } - if (historicalVariance < Double.POSITIVE_INFINITY) { - builder.setHistoricalMean(historicalMean) - .setHistoricalVariance(historicalVariance); - } - if (mPersistentHistograms - && intHistogram != null && intHistogram.numNonEmptyBuckets() > 0) { - for (IntHistogram.Bucket b : intHistogram) { - if (b.count == 0) continue; - builder.addBuckets( - HistogramBucket.newBuilder().setLow(b.start).setNumber(b.count)); - } - } - return builder.build(); - } - } - - /** - * Returns the current scorecard in the form of a protobuf com_android_server_wifi.NetworkList - * - * Synchronization is the caller's responsibility. - * - * @param obfuscate - if true, ssids and bssids are omitted (short id only) - */ - public byte[] getNetworkListByteArray(boolean obfuscate) { - // These are really grouped by ssid, ignoring the security type. - Map<String, Network.Builder> networks = new ArrayMap<>(); - for (PerBssid perBssid: mApForBssid.values()) { - String key = perBssid.ssid; - Network.Builder network = networks.get(key); - if (network == null) { - network = Network.newBuilder(); - networks.put(key, network); - if (!obfuscate) { - network.setSsid(perBssid.ssid); - } - } - if (perBssid.mNetworkAgentId >= network.getNetworkAgentId()) { - network.setNetworkAgentId(perBssid.mNetworkAgentId); - } - if (perBssid.mNetworkConfigId >= network.getNetworkConfigId()) { - network.setNetworkConfigId(perBssid.mNetworkConfigId); - } - network.addAccessPoints(perBssid.toAccessPoint(obfuscate)); - } - for (PerNetwork perNetwork: mApForNetwork.values()) { - String key = perNetwork.ssid; - Network.Builder network = networks.get(key); - if (network != null) { - network.setNetworkStats(perNetwork.toNetworkStats()); - } - } - NetworkList.Builder builder = NetworkList.newBuilder(); - for (Network.Builder network: networks.values()) { - builder.addNetworks(network); - } - return builder.build().toByteArray(); - } - - /** - * Returns the current scorecard as a base64-encoded protobuf - * - * Synchronization is the caller's responsibility. - * - * @param obfuscate - if true, bssids are omitted (short id only) - */ - public String getNetworkListBase64(boolean obfuscate) { - byte[] raw = getNetworkListByteArray(obfuscate); - return Base64.encodeToString(raw, Base64.DEFAULT); - } - - /** - * Clears the internal state. - * - * This is called in response to a factoryReset call from Settings. - * The memory store will be called after we are called, to wipe the stable - * storage as well. Since we will have just removed all of our networks, - * it is very unlikely that we're connected, or will connect immediately. - * Any in-flight reads will land in the objects we are dropping here, and - * the memory store should drop the in-flight writes. Ideally we would - * avoid issuing reads until we were sure that the memory store had - * received the factoryReset. - */ - public void clear() { - mApForBssid.clear(); - mApForNetwork.clear(); - resetConnectionStateInternal(false); - } -} diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java deleted file mode 100644 index bd92c6dac..000000000 --- a/service/java/com/android/server/wifi/WifiScoreReport.java +++ /dev/null @@ -1,796 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.content.Context; -import android.database.ContentObserver; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.Uri; -import android.net.wifi.IScoreUpdateObserver; -import android.net.wifi.IWifiConnectedNetworkScorer; -import android.net.wifi.WifiInfo; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.RemoteException; -import android.provider.Settings; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.LinkedList; -import java.util.Locale; - -/** - * Class used to calculate scores for connected wifi networks and report it to the associated - * network agent. - */ -public class WifiScoreReport { - private static final String TAG = "WifiScoreReport"; - - private static final int DUMPSYS_ENTRY_COUNT_LIMIT = 3600; // 3 hours on 3 second poll - - private boolean mVerboseLoggingEnabled = false; - private static final long FIRST_REASONABLE_WALL_CLOCK = 1490000000000L; // mid-December 2016 - - private static final long MIN_TIME_TO_KEEP_BELOW_TRANSITION_SCORE_MILLIS = 9000; - private long mLastDownwardBreachTimeMillis = 0; - - private static final int WIFI_CONNECTED_NETWORK_SCORER_IDENTIFIER = 0; - private static final int INVALID_SESSION_ID = -1; - private static final long MIN_TIME_TO_WAIT_BEFORE_BLOCKLIST_BSSID_MILLIS = 29000; - private static final long INVALID_WALL_CLOCK_MILLIS = -1; - - /** - * Copy of the settings string. Can't directly use the constant because it is @hide. - * See {@link android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED}. - * TODO(b/167709538) remove this hardcoded string and create new API in Wifi mainline. - */ - @VisibleForTesting - public static final String SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED = - "adaptive_connectivity_enabled"; - - // Cache of the last score - private int mScore = ConnectedScore.WIFI_MAX_SCORE; - - private final ScoringParams mScoringParams; - private final Clock mClock; - private int mSessionNumber = 0; // not to be confused with sessionid, this just counts resets - private String mInterfaceName; - private final BssidBlocklistMonitor mBssidBlocklistMonitor; - private final Context mContext; - private long mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS; - private long mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS; - - ConnectedScore mAggressiveConnectedScore; - VelocityBasedConnectedScore mVelocityBasedConnectedScore; - - NetworkAgent mNetworkAgent; - WifiMetrics mWifiMetrics; - WifiInfo mWifiInfo; - WifiNative mWifiNative; - WifiThreadRunner mWifiThreadRunner; - DeviceConfigFacade mDeviceConfigFacade; - Handler mHandler; - FrameworkFacade mFrameworkFacade; - - /** - * Callback proxy. See {@link android.net.wifi.WifiManager.ScoreUpdateObserver}. - */ - private class ScoreUpdateObserverProxy extends IScoreUpdateObserver.Stub { - @Override - public void notifyScoreUpdate(int sessionId, int score) { - mWifiThreadRunner.post(() -> { - if (mWifiConnectedNetworkScorerHolder == null - || sessionId == INVALID_SESSION_ID - || sessionId != getCurrentSessionId()) { - Log.w(TAG, "Ignoring stale/invalid external score" - + " sessionId=" + sessionId - + " currentSessionId=" + getCurrentSessionId() - + " score=" + score); - return; - } - long millis = mClock.getWallClockMillis(); - if (score < ConnectedScore.WIFI_TRANSITION_SCORE) { - if (mScore >= ConnectedScore.WIFI_TRANSITION_SCORE) { - mLastScoreBreachLowTimeMillis = millis; - } - } else { - mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS; - } - if (score > ConnectedScore.WIFI_TRANSITION_SCORE) { - if (mScore <= ConnectedScore.WIFI_TRANSITION_SCORE) { - mLastScoreBreachHighTimeMillis = millis; - } - } else { - mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS; - } - reportNetworkScoreToConnectivityServiceIfNecessary(score); - mScore = score; - updateWifiMetrics(millis, -1, mScore); - }); - } - - @Override - public void triggerUpdateOfWifiUsabilityStats(int sessionId) { - mWifiThreadRunner.post(() -> { - if (mWifiConnectedNetworkScorerHolder == null - || sessionId == INVALID_SESSION_ID - || sessionId != getCurrentSessionId() - || mInterfaceName == null) { - Log.w(TAG, "Ignoring triggerUpdateOfWifiUsabilityStats" - + " sessionId=" + sessionId - + " currentSessionId=" + getCurrentSessionId() - + " interfaceName=" + mInterfaceName); - return; - } - WifiLinkLayerStats stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName); - - // update mWifiInfo - // TODO(b/153075963): Better coordinate this class and ClientModeImpl to remove - // redundant codes below and in ClientModeImpl#fetchRssiLinkSpeedAndFrequencyNative. - WifiNl80211Manager.SignalPollResult pollResult = - mWifiNative.signalPoll(mInterfaceName); - if (pollResult != null) { - int newRssi = pollResult.currentRssiDbm; - int newTxLinkSpeed = pollResult.txBitrateMbps; - int newFrequency = pollResult.associationFrequencyMHz; - int newRxLinkSpeed = pollResult.rxBitrateMbps; - - if (newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) { - if (newRssi > (WifiInfo.INVALID_RSSI + 256)) { - Log.wtf(TAG, "Error! +ve value RSSI: " + newRssi); - newRssi -= 256; - } - mWifiInfo.setRssi(newRssi); - } else { - mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); - } - /* - * set Tx link speed only if it is valid - */ - if (newTxLinkSpeed > 0) { - mWifiInfo.setLinkSpeed(newTxLinkSpeed); - mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed); - } - /* - * set Rx link speed only if it is valid - */ - if (newRxLinkSpeed > 0) { - mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed); - } - if (newFrequency > 0) { - mWifiInfo.setFrequency(newFrequency); - } - } - - // TODO(b/153075963): This should not be plumbed through WifiMetrics - mWifiMetrics.updateWifiUsabilityStatsEntries(mWifiInfo, stats); - }); - } - } - - /** - * Report network score to connectivity service. - */ - private void reportNetworkScoreToConnectivityServiceIfNecessary(int score) { - if (mNetworkAgent == null) { - return; - } - if (mWifiConnectedNetworkScorerHolder == null && score == mWifiInfo.getScore()) { - return; - } - if (mWifiConnectedNetworkScorerHolder != null - && mContext.getResources().getBoolean( - R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)) { - long millis = mClock.getWallClockMillis(); - if (mLastScoreBreachLowTimeMillis != INVALID_WALL_CLOCK_MILLIS) { - if (mWifiInfo.getRssi() - >= mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm()) { - Log.d(TAG, "Not reporting low score because RSSI is high " - + mWifiInfo.getRssi()); - return; - } - if ((millis - mLastScoreBreachLowTimeMillis) - < mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()) { - Log.d(TAG, "Not reporting low score because elapsed time is shorter than " - + "the minimum confirmation duration"); - return; - } - } - if (mLastScoreBreachHighTimeMillis != INVALID_WALL_CLOCK_MILLIS - && (millis - mLastScoreBreachHighTimeMillis) - < mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()) { - Log.d(TAG, "Not reporting high score because elapsed time is shorter than " - + "the minimum confirmation duration"); - return; - } - } - // Stay a notch above the transition score if adaptive connectivity is disabled. - if (!mAdaptiveConnectivityEnabled) { - score = ConnectedScore.WIFI_TRANSITION_SCORE + 1; - } - mNetworkAgent.sendNetworkScore(score); - } - - /** - * Container for storing info about external scorer and tracking its death. - */ - private final class WifiConnectedNetworkScorerHolder implements IBinder.DeathRecipient { - private final IBinder mBinder; - private final IWifiConnectedNetworkScorer mScorer; - private int mSessionId = INVALID_SESSION_ID; - - WifiConnectedNetworkScorerHolder(IBinder binder, IWifiConnectedNetworkScorer scorer) { - mBinder = binder; - mScorer = scorer; - } - - /** - * Link WiFi connected scorer to death listener. - */ - public boolean linkScorerToDeath() { - try { - mBinder.linkToDeath(this, 0); - } catch (RemoteException e) { - Log.e(TAG, "Unable to linkToDeath Wifi connected network scorer " + mScorer, e); - return false; - } - return true; - } - - /** - * App hosting the binder has died. - */ - @Override - public void binderDied() { - mWifiThreadRunner.post(() -> revertToDefaultConnectedScorer()); - } - - /** - * Unlink this object from binder death. - */ - public void reset() { - mBinder.unlinkToDeath(this, 0); - } - - /** - * Starts a new scoring session. - */ - public void startSession(int sessionId) { - if (sessionId == INVALID_SESSION_ID) { - throw new IllegalArgumentException(); - } - if (mSessionId != INVALID_SESSION_ID) { - // This is not expected to happen, log if it does - Log.e(TAG, "Stopping session " + mSessionId + " before starting " + sessionId); - stopSession(); - } - // Bail now if the scorer has gone away - if (this != mWifiConnectedNetworkScorerHolder) { - return; - } - mSessionId = sessionId; - try { - mScorer.onStart(sessionId); - } catch (RemoteException e) { - Log.e(TAG, "Unable to start Wifi connected network scorer " + this, e); - revertToDefaultConnectedScorer(); - } - } - public void stopSession() { - final int sessionId = mSessionId; - if (sessionId == INVALID_SESSION_ID) return; - mSessionId = INVALID_SESSION_ID; - try { - mScorer.onStop(sessionId); - } catch (RemoteException e) { - Log.e(TAG, "Unable to stop Wifi connected network scorer " + this, e); - revertToDefaultConnectedScorer(); - } - } - } - - private final ScoreUpdateObserverProxy mScoreUpdateObserver = - new ScoreUpdateObserverProxy(); - - private WifiConnectedNetworkScorerHolder mWifiConnectedNetworkScorerHolder; - - /** - * Observer for adaptive connectivity enable settings changes. - * This is enabled by default. Will be toggled off via adb command or a settings - * toggle by the user to disable adaptive connectivity. - */ - private class AdaptiveConnectivityEnabledSettingObserver extends ContentObserver { - AdaptiveConnectivityEnabledSettingObserver(Handler handler) { - super(handler); - } - - @Override - public void onChange(boolean selfChange) { - super.onChange(selfChange); - mAdaptiveConnectivityEnabled = getValue(); - Log.d(TAG, "Adaptive connectivity status changed: " + mAdaptiveConnectivityEnabled); - mWifiMetrics.setAdaptiveConnectivityState(mAdaptiveConnectivityEnabled); - mWifiMetrics.logUserActionEvent( - mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType( - mAdaptiveConnectivityEnabled)); - } - - /** - * Register settings change observer. - */ - public void initialize() { - Uri uri = Settings.Secure.getUriFor(SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED); - if (uri == null) { - Log.e(TAG, "Adaptive connectivity user toggle does not exist in Settings"); - return; - } - mFrameworkFacade.registerContentObserver(mContext, uri, true, this); - mAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabledSettingObserver.getValue(); - mWifiMetrics.setAdaptiveConnectivityState(mAdaptiveConnectivityEnabled); - } - - public boolean getValue() { - return mFrameworkFacade.getIntegerSetting( - mContext, SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED, 1) == 1; - } - } - - private final AdaptiveConnectivityEnabledSettingObserver - mAdaptiveConnectivityEnabledSettingObserver; - private boolean mAdaptiveConnectivityEnabled = true; - - WifiScoreReport(ScoringParams scoringParams, Clock clock, WifiMetrics wifiMetrics, - WifiInfo wifiInfo, WifiNative wifiNative, BssidBlocklistMonitor bssidBlocklistMonitor, - WifiThreadRunner wifiThreadRunner, DeviceConfigFacade deviceConfigFacade, - Context context, Looper looper, FrameworkFacade frameworkFacade) { - mScoringParams = scoringParams; - mClock = clock; - mAggressiveConnectedScore = new AggressiveConnectedScore(scoringParams, clock); - mVelocityBasedConnectedScore = new VelocityBasedConnectedScore(scoringParams, clock); - mWifiMetrics = wifiMetrics; - mWifiInfo = wifiInfo; - mWifiNative = wifiNative; - mBssidBlocklistMonitor = bssidBlocklistMonitor; - mWifiThreadRunner = wifiThreadRunner; - mDeviceConfigFacade = deviceConfigFacade; - mContext = context; - mFrameworkFacade = frameworkFacade; - mHandler = new Handler(looper); - mAdaptiveConnectivityEnabledSettingObserver = - new AdaptiveConnectivityEnabledSettingObserver(mHandler); - } - - /** - * Reset the last calculated score. - */ - public void reset() { - mSessionNumber++; - mScore = ConnectedScore.WIFI_MAX_SCORE; - mLastKnownNudCheckScore = ConnectedScore.WIFI_TRANSITION_SCORE; - mAggressiveConnectedScore.reset(); - if (mVelocityBasedConnectedScore != null) { - mVelocityBasedConnectedScore.reset(); - } - mLastDownwardBreachTimeMillis = 0; - mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS; - mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS; - if (mVerboseLoggingEnabled) Log.d(TAG, "reset"); - } - - /** - * Enable/Disable verbose logging in score report generation. - */ - public void enableVerboseLogging(boolean enable) { - mVerboseLoggingEnabled = enable; - } - - /** - * Calculate wifi network score based on updated link layer stats and send the score to - * the WifiNetworkAgent. - * - * If the score has changed from the previous value, update the WifiNetworkAgent. - * - * Called periodically (POLL_RSSI_INTERVAL_MSECS) about every 3 seconds. - */ - public void calculateAndReportScore() { - // Bypass AOSP scorer if Wifi connected network scorer is set - if (mWifiConnectedNetworkScorerHolder != null) { - return; - } - - if (mWifiInfo.getRssi() == mWifiInfo.INVALID_RSSI) { - Log.d(TAG, "Not reporting score because RSSI is invalid"); - return; - } - int score; - - long millis = mClock.getWallClockMillis(); - mVelocityBasedConnectedScore.updateUsingWifiInfo(mWifiInfo, millis); - - int s2 = mVelocityBasedConnectedScore.generateScore(); - score = s2; - - if (mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE - && score <= ConnectedScore.WIFI_TRANSITION_SCORE - && mWifiInfo.getSuccessfulTxPacketsPerSecond() - >= mScoringParams.getYippeeSkippyPacketsPerSecond() - && mWifiInfo.getSuccessfulRxPacketsPerSecond() - >= mScoringParams.getYippeeSkippyPacketsPerSecond() - ) { - score = ConnectedScore.WIFI_TRANSITION_SCORE + 1; - } - - if (mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE - && score <= ConnectedScore.WIFI_TRANSITION_SCORE) { - // We don't want to trigger a downward breach unless the rssi is - // below the entry threshold. There is noise in the measured rssi, and - // the kalman-filtered rssi is affected by the trend, so check them both. - // TODO(b/74613347) skip this if there are other indications to support the low score - int entry = mScoringParams.getEntryRssi(mWifiInfo.getFrequency()); - if (mVelocityBasedConnectedScore.getFilteredRssi() >= entry - || mWifiInfo.getRssi() >= entry) { - // Stay a notch above the transition score to reduce ambiguity. - score = ConnectedScore.WIFI_TRANSITION_SCORE + 1; - } - } - - if (mWifiInfo.getScore() >= ConnectedScore.WIFI_TRANSITION_SCORE - && score < ConnectedScore.WIFI_TRANSITION_SCORE) { - mLastDownwardBreachTimeMillis = millis; - } else if (mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE - && score >= ConnectedScore.WIFI_TRANSITION_SCORE) { - // Staying at below transition score for a certain period of time - // to prevent going back to wifi network again in a short time. - long elapsedMillis = millis - mLastDownwardBreachTimeMillis; - if (elapsedMillis < MIN_TIME_TO_KEEP_BELOW_TRANSITION_SCORE_MILLIS) { - score = mWifiInfo.getScore(); - } - } - //sanitize boundaries - if (score > ConnectedScore.WIFI_MAX_SCORE) { - score = ConnectedScore.WIFI_MAX_SCORE; - } - if (score < 0) { - score = 0; - } - - //report score - reportNetworkScoreToConnectivityServiceIfNecessary(score); - updateWifiMetrics(millis, s2, score); - mScore = score; - } - - private int getCurrentNetId() { - int netId = 0; - if (mNetworkAgent != null) { - final Network network = mNetworkAgent.getNetwork(); - if (network != null) { - netId = network.getNetId(); - } - } - return netId; - } - - private int getCurrentSessionId() { - return sessionIdFromNetId(getCurrentNetId()); - } - - /** - * Encodes a network id into a scoring session id. - * - * We use a different numeric value for session id and the network id - * to make it clear that these are not the same thing. However, for - * easier debugging, the network id can be recovered by dropping the - * last decimal digit (at least until they get very, very, large). - */ - public static int sessionIdFromNetId(final int netId) { - if (netId <= 0) return INVALID_SESSION_ID; - return (int) (((long) netId * 10 + (8 - (netId % 9))) % Integer.MAX_VALUE + 1); - } - - private void updateWifiMetrics(long now, int s2, int score) { - int netId = getCurrentNetId(); - - mAggressiveConnectedScore.updateUsingWifiInfo(mWifiInfo, now); - int s1 = mAggressiveConnectedScore.generateScore(); - logLinkMetrics(now, netId, s1, s2, score); - - if (score != mWifiInfo.getScore()) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "report new wifi score " + score); - } - mWifiInfo.setScore(score); - } - mWifiMetrics.incrementWifiScoreCount(score); - } - - private static final double TIME_CONSTANT_MILLIS = 30.0e+3; - private static final long NUD_THROTTLE_MILLIS = 5000; - private long mLastKnownNudCheckTimeMillis = 0; - private int mLastKnownNudCheckScore = ConnectedScore.WIFI_TRANSITION_SCORE; - private int mNudYes = 0; // Counts when we voted for a NUD - private int mNudCount = 0; // Counts when we were told a NUD was sent - - /** - * Recommends that a layer 3 check be done - * - * The caller can use this to (help) decide that an IP reachability check - * is desirable. The check is not done here; that is the caller's responsibility. - * - * @return true to indicate that an IP reachability check is recommended - */ - public boolean shouldCheckIpLayer() { - // Don't recommend if adaptive connectivity is disabled. - if (!mAdaptiveConnectivityEnabled) { - return false; - } - int nud = mScoringParams.getNudKnob(); - if (nud == 0) { - return false; - } - long millis = mClock.getWallClockMillis(); - long deltaMillis = millis - mLastKnownNudCheckTimeMillis; - // Don't ever ask back-to-back - allow at least 5 seconds - // for the previous one to finish. - if (deltaMillis < NUD_THROTTLE_MILLIS) { - return false; - } - // nextNudBreach is the bar the score needs to cross before we ask for NUD - double nextNudBreach = ConnectedScore.WIFI_TRANSITION_SCORE; - if (mWifiConnectedNetworkScorerHolder == null) { - // nud is between 1 and 10 at this point - double deltaLevel = 11 - nud; - // If we were below threshold the last time we checked, then compute a new bar - // that starts down from there and decays exponentially back up to the steady-state - // bar. If 5 time constants have passed, we are 99% of the way there, so skip the math. - if (mLastKnownNudCheckScore < ConnectedScore.WIFI_TRANSITION_SCORE - && deltaMillis < 5.0 * TIME_CONSTANT_MILLIS) { - double a = Math.exp(-deltaMillis / TIME_CONSTANT_MILLIS); - nextNudBreach = - a * (mLastKnownNudCheckScore - deltaLevel) + (1.0 - a) * nextNudBreach; - } - } - if (mScore >= nextNudBreach) { - return false; - } - mNudYes++; - return true; - } - - /** - * Should be called when a reachability check has been issued - * - * When the caller has requested an IP reachability check, calling this will - * help to rate-limit requests via shouldCheckIpLayer() - */ - public void noteIpCheck() { - long millis = mClock.getWallClockMillis(); - mLastKnownNudCheckTimeMillis = millis; - mLastKnownNudCheckScore = mScore; - mNudCount++; - } - - /** - * Data for dumpsys - * - * These are stored as csv formatted lines - */ - private LinkedList<String> mLinkMetricsHistory = new LinkedList<String>(); - - /** - * Data logging for dumpsys - */ - private void logLinkMetrics(long now, int netId, int s1, int s2, int score) { - if (now < FIRST_REASONABLE_WALL_CLOCK) return; - double rssi = mWifiInfo.getRssi(); - double filteredRssi = -1; - double rssiThreshold = -1; - if (mWifiConnectedNetworkScorerHolder == null) { - filteredRssi = mVelocityBasedConnectedScore.getFilteredRssi(); - rssiThreshold = mVelocityBasedConnectedScore.getAdjustedRssiThreshold(); - } - int freq = mWifiInfo.getFrequency(); - int txLinkSpeed = mWifiInfo.getLinkSpeed(); - int rxLinkSpeed = mWifiInfo.getRxLinkSpeedMbps(); - double txSuccessRate = mWifiInfo.getSuccessfulTxPacketsPerSecond(); - double txRetriesRate = mWifiInfo.getRetriedTxPacketsPerSecond(); - double txBadRate = mWifiInfo.getLostTxPacketsPerSecond(); - double rxSuccessRate = mWifiInfo.getSuccessfulRxPacketsPerSecond(); - String s; - try { - String timestamp = new SimpleDateFormat("MM-dd HH:mm:ss.SSS").format(new Date(now)); - s = String.format(Locale.US, // Use US to avoid comma/decimal confusion - "%s,%d,%d,%.1f,%.1f,%.1f,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%d,%d,%d,%d,%d", - timestamp, mSessionNumber, netId, - rssi, filteredRssi, rssiThreshold, freq, txLinkSpeed, rxLinkSpeed, - txSuccessRate, txRetriesRate, txBadRate, rxSuccessRate, - mNudYes, mNudCount, - s1, s2, score); - } catch (Exception e) { - Log.e(TAG, "format problem", e); - return; - } - synchronized (mLinkMetricsHistory) { - mLinkMetricsHistory.add(s); - while (mLinkMetricsHistory.size() > DUMPSYS_ENTRY_COUNT_LIMIT) { - mLinkMetricsHistory.removeFirst(); - } - } - } - - /** - * Tag to be used in dumpsys request - */ - public static final String DUMP_ARG = "WifiScoreReport"; - - /** - * Dump logged signal strength and traffic measurements. - * @param fd unused - * @param pw PrintWriter for writing dump to - * @param args unused - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - LinkedList<String> history; - synchronized (mLinkMetricsHistory) { - history = new LinkedList<>(mLinkMetricsHistory); - } - pw.println("time,session,netid,rssi,filtered_rssi,rssi_threshold,freq,txLinkSpeed," - + "rxLinkSpeed,tx_good,tx_retry,tx_bad,rx_pps,nudrq,nuds,s1,s2,score"); - for (String line : history) { - pw.println(line); - } - history.clear(); - } - - /** - * Set a scorer for Wi-Fi connected network score handling. - * @param binder - * @param scorer - */ - public boolean setWifiConnectedNetworkScorer(IBinder binder, - IWifiConnectedNetworkScorer scorer) { - if (binder == null || scorer == null) return false; - // Enforce that only a single scorer can be set successfully. - if (mWifiConnectedNetworkScorerHolder != null) { - Log.e(TAG, "Failed to set current scorer because one scorer is already set"); - return false; - } - WifiConnectedNetworkScorerHolder scorerHolder = - new WifiConnectedNetworkScorerHolder(binder, scorer); - if (!scorerHolder.linkScorerToDeath()) { - return false; - } - mWifiConnectedNetworkScorerHolder = scorerHolder; - - try { - scorer.onSetScoreUpdateObserver(mScoreUpdateObserver); - } catch (RemoteException e) { - Log.e(TAG, "Unable to set score update observer " + scorer, e); - revertToDefaultConnectedScorer(); - return false; - } - // Disable AOSP scorer - mVelocityBasedConnectedScore = null; - mWifiMetrics.setIsExternalWifiScorerOn(true); - // If there is already a connection, start a new session - final int netId = getCurrentNetId(); - if (netId > 0) { - startConnectedNetworkScorer(netId); - } - return true; - } - - /** - * Clear an existing scorer for Wi-Fi connected network score handling. - */ - public void clearWifiConnectedNetworkScorer() { - if (mWifiConnectedNetworkScorerHolder == null) { - return; - } - mWifiConnectedNetworkScorerHolder.reset(); - revertToDefaultConnectedScorer(); - } - - /** - * Start the registered Wi-Fi connected network scorer. - * @param netId identifies the current android.net.Network - */ - public void startConnectedNetworkScorer(int netId) { - final int sessionId = getCurrentSessionId(); - if (mWifiConnectedNetworkScorerHolder == null - || netId != getCurrentNetId() - || sessionId == INVALID_SESSION_ID) { - Log.w(TAG, "Cannot start external scoring" - + " netId=" + netId - + " currentNetId=" + getCurrentNetId() - + " sessionId=" + sessionId); - return; - } - mWifiInfo.setScore(ConnectedScore.WIFI_MAX_SCORE); - mWifiConnectedNetworkScorerHolder.startSession(sessionId); - mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS; - mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS; - } - - /** - * Stop the registered Wi-Fi connected network scorer. - */ - public void stopConnectedNetworkScorer() { - mNetworkAgent = null; - if (mWifiConnectedNetworkScorerHolder == null) { - return; - } - mWifiConnectedNetworkScorerHolder.stopSession(); - - long millis = mClock.getWallClockMillis(); - // Blocklist the current BSS - if ((mLastScoreBreachLowTimeMillis != INVALID_WALL_CLOCK_MILLIS) - && ((millis - mLastScoreBreachLowTimeMillis) - >= MIN_TIME_TO_WAIT_BEFORE_BLOCKLIST_BSSID_MILLIS)) { - mBssidBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(), - mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE, - mWifiInfo.getRssi()); - mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS; - } - } - - /** - * Set NetworkAgent - */ - public void setNetworkAgent(NetworkAgent agent) { - mNetworkAgent = agent; - } - - /** - * Get cached score - */ - public int getScore() { - return mScore; - } - - /** - * Set interface name - * @param ifaceName - */ - public void setInterfaceName(String ifaceName) { - mInterfaceName = ifaceName; - } - - private void revertToDefaultConnectedScorer() { - Log.d(TAG, "Using VelocityBasedConnectedScore"); - mVelocityBasedConnectedScore = new VelocityBasedConnectedScore(mScoringParams, mClock); - mWifiConnectedNetworkScorerHolder = null; - mWifiMetrics.setIsExternalWifiScorerOn(false); - } - - /** - * Initialize WifiScoreReport - */ - public void initialize() { - mAdaptiveConnectivityEnabledSettingObserver.initialize(); - } -} diff --git a/service/java/com/android/server/wifi/WifiService.java b/service/java/com/android/server/wifi/WifiService.java deleted file mode 100644 index 0197246c8..000000000 --- a/service/java/com/android/server/wifi/WifiService.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.content.Context; -import android.util.Log; - -import com.android.server.SystemService; -import com.android.server.wifi.util.WifiAsyncChannel; - -import java.util.ArrayList; -import java.util.List; - -/** - * Service implementing Wi-Fi functionality. Delegates actual interface - * implementation to WifiServiceImpl. - */ -public final class WifiService extends SystemService { - - private static final String TAG = "WifiService"; - // Notification channels used by the wifi service. - public static final String NOTIFICATION_NETWORK_STATUS = "NETWORK_STATUS"; - public static final String NOTIFICATION_NETWORK_ALERTS = "NETWORK_ALERTS"; - public static final String NOTIFICATION_NETWORK_AVAILABLE = "NETWORK_AVAILABLE"; - - private final WifiServiceImpl mImpl; - private final WifiContext mWifiContext; - - public WifiService(Context contextBase) { - super(contextBase); - mWifiContext = new WifiContext(contextBase); - WifiInjector injector = new WifiInjector(mWifiContext); - WifiAsyncChannel channel = new WifiAsyncChannel(TAG); - mImpl = new WifiServiceImpl(mWifiContext, injector, channel); - } - - @Override - public void onStart() { - Log.i(TAG, "Registering " + Context.WIFI_SERVICE); - publishBinderService(Context.WIFI_SERVICE, mImpl); - } - - @Override - public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { - createNotificationChannels(mWifiContext); - mImpl.checkAndStartWifi(); - } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { - mImpl.handleBootCompleted(); - } - } - - @Override - public void onUserSwitching(TargetUser from, TargetUser to) { - mImpl.handleUserSwitch(to.getUserHandle().getIdentifier()); - } - - @Override - public void onUserUnlocking(TargetUser user) { - mImpl.handleUserUnlock(user.getUserHandle().getIdentifier()); - } - - @Override - public void onUserStopping(TargetUser user) { - mImpl.handleUserStop(user.getUserHandle().getIdentifier()); - } - - // Create notification channels used by wifi. - private static void createNotificationChannels(Context ctx) { - final NotificationManager nm = ctx.getSystemService(NotificationManager.class); - List<NotificationChannel> channelsList = new ArrayList<>(); - final NotificationChannel networkStatusChannel = new NotificationChannel( - NOTIFICATION_NETWORK_STATUS, - ctx.getResources().getString( - com.android.wifi.resources.R.string.notification_channel_network_status), - NotificationManager.IMPORTANCE_LOW); - channelsList.add(networkStatusChannel); - - final NotificationChannel networkAlertsChannel = new NotificationChannel( - NOTIFICATION_NETWORK_ALERTS, - ctx.getResources().getString( - com.android.wifi.resources.R.string.notification_channel_network_alerts), - NotificationManager.IMPORTANCE_HIGH); - networkAlertsChannel.setBlockable(true); - channelsList.add(networkAlertsChannel); - - final NotificationChannel networkAvailable = new NotificationChannel( - NOTIFICATION_NETWORK_AVAILABLE, - ctx.getResources().getString( - com.android.wifi.resources.R.string.notification_channel_network_available), - NotificationManager.IMPORTANCE_LOW); - networkAvailable.setBlockable(true); - channelsList.add(networkAvailable); - - nm.createNotificationChannels(channelsList); - } -} diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java deleted file mode 100644 index 3b4f39796..000000000 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ /dev/null @@ -1,4352 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import static android.app.AppOpsManager.MODE_ALLOWED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC; -import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL; -import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; - -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; - -import android.annotation.CheckResult; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.AppOpsManager; -import android.bluetooth.BluetoothAdapter; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.ParceledListSlice; -import android.content.pm.ResolveInfo; -import android.net.DhcpInfo; -import android.net.DhcpResultsParcelable; -import android.net.InetAddresses; -import android.net.Network; -import android.net.NetworkStack; -import android.net.Uri; -import android.net.ip.IpClientUtil; -import android.net.wifi.IActionListener; -import android.net.wifi.IDppCallback; -import android.net.wifi.ILocalOnlyHotspotCallback; -import android.net.wifi.INetworkRequestMatchCallback; -import android.net.wifi.IOnWifiActivityEnergyInfoListener; -import android.net.wifi.IOnWifiUsabilityStatsListener; -import android.net.wifi.IScanResultsCallback; -import android.net.wifi.ISoftApCallback; -import android.net.wifi.ISuggestionConnectionStatusListener; -import android.net.wifi.ITrafficStateCallback; -import android.net.wifi.IWifiConnectedNetworkScorer; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApInfo; -import android.net.wifi.WifiAnnotations.WifiStandard; -import android.net.wifi.WifiClient; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.DeviceMobilityState; -import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; -import android.net.wifi.WifiManager.SuggestionConnectionStatusListener; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.AsyncTask; -import android.os.Binder; -import android.os.Build; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.ParcelFileDescriptor; -import android.os.PersistableBundle; -import android.os.PowerManager; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.WorkSource; -import android.os.connectivity.WifiActivityEnergyInfo; -import android.provider.Settings; -import android.telephony.CarrierConfigManager; -import android.telephony.PhoneStateListener; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; -import android.util.MutableBoolean; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; -import com.android.net.module.util.Inet4AddressUtils; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.hotspot2.PasspointProvider; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; -import com.android.server.wifi.util.ApConfigUtil; -import com.android.server.wifi.util.ExternalCallbackTracker; -import com.android.server.wifi.util.RssiUtil; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiHandler; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.wifi.resources.R; - -import java.io.BufferedReader; -import java.io.FileDescriptor; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintWriter; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; -import java.security.cert.CertificateFactory; -import java.security.cert.PKIXParameters; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -/** - * WifiService handles remote WiFi operation requests by implementing - * the IWifiManager interface. - */ -public class WifiServiceImpl extends BaseWifiService { - private static final String TAG = "WifiService"; - private static final int APP_INFO_FLAGS_SYSTEM_APP = - ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; - private static final boolean VDBG = false; - - /** Max wait time for posting blocking runnables */ - private static final int RUN_WITH_SCISSORS_TIMEOUT_MILLIS = 4000; - - private final ClientModeImpl mClientModeImpl; - private final ActiveModeWarden mActiveModeWarden; - private final ScanRequestProxy mScanRequestProxy; - - private final Context mContext; - private final FrameworkFacade mFacade; - private final Clock mClock; - - private final PowerManager mPowerManager; - private final AppOpsManager mAppOps; - private final UserManager mUserManager; - private final WifiCountryCode mCountryCode; - - /** Polls traffic stats and notifies clients */ - private final WifiTrafficPoller mWifiTrafficPoller; - /** Tracks the persisted states for wi-fi & airplane mode */ - private final WifiSettingsStore mSettingsStore; - /** Logs connection events and some general router and scan stats */ - private final WifiMetrics mWifiMetrics; - - private final WifiInjector mWifiInjector; - /** Backup/Restore Module */ - private final WifiBackupRestore mWifiBackupRestore; - private final SoftApBackupRestore mSoftApBackupRestore; - private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private final WifiConfigManager mWifiConfigManager; - private final PasspointManager mPasspointManager; - private final WifiLog mLog; - /** - * Verbose logging flag. Toggled by developer options. - */ - private boolean mVerboseLoggingEnabled = false; - - /** - * Asynchronous channel to ClientModeImpl - */ - @VisibleForTesting - AsyncChannel mClientModeImplChannel; - - private final FrameworkFacade mFrameworkFacade; - - private final WifiPermissionsUtil mWifiPermissionsUtil; - - private final TetheredSoftApTracker mTetheredSoftApTracker; - - private final LohsSoftApTracker mLohsSoftApTracker; - - private WifiScanner mWifiScanner; - - /** - * Callback for use with LocalOnlyHotspot to unregister requesting applications upon death. - */ - public final class LocalOnlyRequestorCallback - implements LocalOnlyHotspotRequestInfo.RequestingApplicationDeathCallback { - /** - * Called with requesting app has died. - */ - @Override - public void onLocalOnlyHotspotRequestorDeath(LocalOnlyHotspotRequestInfo requestor) { - mLog.trace("onLocalOnlyHotspotRequestorDeath pid=%") - .c(requestor.getPid()).flush(); - mLohsSoftApTracker.stopByRequest(requestor); - } - } - - /** - * Handles interaction with ClientModeImpl - */ - private class ClientModeImplHandler extends WifiHandler { - private AsyncChannel mCmiChannel; - - ClientModeImplHandler(String tag, Looper looper, AsyncChannel asyncChannel) { - super(tag, looper); - mCmiChannel = asyncChannel; - mCmiChannel.connect(mContext, this, mClientModeImpl.getHandler()); - } - - @Override - public void handleMessage(Message msg) { - super.handleMessage(msg); - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - mClientModeImplChannel = mCmiChannel; - } else { - Log.e(TAG, "ClientModeImpl connection failure, error=" + msg.arg1); - mClientModeImplChannel = null; - } - break; - } - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { - Log.e(TAG, "ClientModeImpl channel lost, msg.arg1 =" + msg.arg1); - mClientModeImplChannel = null; - //Re-establish connection to state machine - mCmiChannel.connect(mContext, this, mClientModeImpl.getHandler()); - break; - } - default: { - Log.d(TAG, "ClientModeImplHandler.handleMessage ignoring msg=" + msg); - break; - } - } - } - } - - /** - * Listen for phone call state events to get active data subcription id. - */ - private class WifiPhoneStateListener extends PhoneStateListener { - WifiPhoneStateListener(Looper looper) { - super(new HandlerExecutor(new Handler(looper))); - } - - @Override - public void onActiveDataSubscriptionIdChanged(int subId) { - Log.d(TAG, "OBSERVED active data subscription change, subId: " + subId); - - mTetheredSoftApTracker.updateSoftApCapability(subId); - mActiveModeWarden.updateSoftApCapability(mTetheredSoftApTracker.getSoftApCapability()); - } - } - - private final ClientModeImplHandler mClientModeImplHandler; - private final WifiLockManager mWifiLockManager; - private final WifiMulticastLockManager mWifiMulticastLockManager; - private final DppManager mDppManager; - private final WifiApConfigStore mWifiApConfigStore; - private final WifiThreadRunner mWifiThreadRunner; - private final MemoryStoreImpl mMemoryStoreImpl; - private final WifiScoreCard mWifiScoreCard; - - public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) { - mContext = context; - mWifiInjector = wifiInjector; - mClock = wifiInjector.getClock(); - - mFacade = mWifiInjector.getFrameworkFacade(); - mWifiMetrics = mWifiInjector.getWifiMetrics(); - mWifiTrafficPoller = mWifiInjector.getWifiTrafficPoller(); - mUserManager = mWifiInjector.getUserManager(); - mCountryCode = mWifiInjector.getWifiCountryCode(); - mClientModeImpl = mWifiInjector.getClientModeImpl(); - mActiveModeWarden = mWifiInjector.getActiveModeWarden(); - mScanRequestProxy = mWifiInjector.getScanRequestProxy(); - mSettingsStore = mWifiInjector.getWifiSettingsStore(); - mPowerManager = mContext.getSystemService(PowerManager.class); - mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); - mWifiLockManager = mWifiInjector.getWifiLockManager(); - mWifiMulticastLockManager = mWifiInjector.getWifiMulticastLockManager(); - mClientModeImplHandler = new ClientModeImplHandler(TAG, - mWifiInjector.getAsyncChannelHandlerThread().getLooper(), asyncChannel); - mWifiBackupRestore = mWifiInjector.getWifiBackupRestore(); - mSoftApBackupRestore = mWifiInjector.getSoftApBackupRestore(); - mWifiApConfigStore = mWifiInjector.getWifiApConfigStore(); - mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); - mLog = mWifiInjector.makeLog(TAG); - mFrameworkFacade = wifiInjector.getFrameworkFacade(); - mTetheredSoftApTracker = new TetheredSoftApTracker(); - mActiveModeWarden.registerSoftApCallback(mTetheredSoftApTracker); - mLohsSoftApTracker = new LohsSoftApTracker(); - mActiveModeWarden.registerLohsCallback(mLohsSoftApTracker); - mWifiNetworkSuggestionsManager = mWifiInjector.getWifiNetworkSuggestionsManager(); - mDppManager = mWifiInjector.getDppManager(); - mWifiThreadRunner = mWifiInjector.getWifiThreadRunner(); - mWifiConfigManager = mWifiInjector.getWifiConfigManager(); - mPasspointManager = mWifiInjector.getPasspointManager(); - mWifiScoreCard = mWifiInjector.getWifiScoreCard(); - mMemoryStoreImpl = new MemoryStoreImpl(mContext, mWifiInjector, - mWifiScoreCard, mWifiInjector.getWifiHealthMonitor()); - } - - /** - * Check if we are ready to start wifi. - * - * First check if we will be restarting system services to decrypt the device. If the device is - * not encrypted, check if Wi-Fi needs to be enabled and start if needed - * - * This function is used only at boot time. - */ - public void checkAndStartWifi() { - mWifiThreadRunner.post(() -> { - if (!mWifiConfigManager.loadFromStore()) { - Log.e(TAG, "Failed to load from config store"); - } - // config store is read, check if verbose logging is enabled. - enableVerboseLoggingInternal(getVerboseLoggingLevel()); - // Check if wi-fi needs to be enabled - boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled(); - Log.i(TAG, - "WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled")); - - mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility().initialize(); - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mSettingsStore.handleAirplaneModeToggled()) { - mActiveModeWarden.airplaneModeToggled(); - } - } - }, - new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); - - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - int state = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE, - TelephonyManager.SIM_STATE_UNKNOWN); - if (TelephonyManager.SIM_STATE_ABSENT == state) { - Log.d(TAG, "resetting networks because SIM was removed"); - mClientModeImpl.resetSimAuthNetworks( - ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED); - } - } - }, - new IntentFilter(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)); - - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - int state = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE, - TelephonyManager.SIM_STATE_UNKNOWN); - if (TelephonyManager.SIM_STATE_LOADED == state) { - Log.d(TAG, "resetting networks because SIM was loaded"); - mClientModeImpl.resetSimAuthNetworks( - ClientModeImpl.RESET_SIM_REASON_SIM_INSERTED); - } - } - }, - new IntentFilter(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)); - - mContext.registerReceiver( - new BroadcastReceiver() { - private int mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - @Override - public void onReceive(Context context, Intent intent) { - final int subId = intent.getIntExtra("subscription", - SubscriptionManager.INVALID_SUBSCRIPTION_ID); - if (subId != mLastSubId) { - Log.d(TAG, "resetting networks as default data SIM is changed"); - mClientModeImpl.resetSimAuthNetworks( - ClientModeImpl.RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED); - mLastSubId = subId; - } - } - }, - new IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)); - - // Adding optimizations of only receiving broadcasts when wifi is enabled - // can result in race conditions when apps toggle wifi in the background - // without active user involvement. Always receive broadcasts. - registerForBroadcasts(); - mInIdleMode = mPowerManager.isDeviceIdleMode(); - - mClientModeImpl.initialize(); - mActiveModeWarden.start(); - registerForCarrierConfigChange(); - }); - } - - public void handleBootCompleted() { - mWifiThreadRunner.post(() -> { - Log.d(TAG, "Handle boot completed"); - - // Register for system broadcasts. - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_USER_REMOVED); - intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - intentFilter.addAction(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); - intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - intentFilter.addAction(Intent.ACTION_SHUTDOWN); - boolean trackEmergencyCallState = mContext.getResources().getBoolean( - R.bool.config_wifi_turn_off_during_emergency_call); - if (trackEmergencyCallState) { - intentFilter.addAction(TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED); - } - mContext.registerReceiver(mReceiver, intentFilter); - mMemoryStoreImpl.start(); - mPasspointManager.initializeProvisioner( - mWifiInjector.getPasspointProvisionerHandlerThread().getLooper()); - mClientModeImpl.handleBootCompleted(); - }); - } - - public void handleUserSwitch(int userId) { - Log.d(TAG, "Handle user switch " + userId); - mWifiThreadRunner.post(() -> mWifiConfigManager.handleUserSwitch(userId)); - } - - public void handleUserUnlock(int userId) { - Log.d(TAG, "Handle user unlock " + userId); - mWifiThreadRunner.post(() -> mWifiConfigManager.handleUserUnlock(userId)); - } - - public void handleUserStop(int userId) { - Log.d(TAG, "Handle user stop " + userId); - mWifiThreadRunner.post(() -> mWifiConfigManager.handleUserStop(userId)); - } - - /** - * See {@link android.net.wifi.WifiManager#startScan} - * - * @param packageName Package name of the app that requests wifi scan. - * @param featureId The feature in the package - */ - @Override - public boolean startScan(String packageName, String featureId) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - - int callingUid = Binder.getCallingUid(); - long ident = Binder.clearCallingIdentity(); - mLog.info("startScan uid=%").c(callingUid).flush(); - synchronized (this) { - if (mInIdleMode) { - // Need to send an immediate scan result broadcast in case the - // caller is waiting for a result .. - - // TODO: investigate if the logic to cancel scans when idle can move to - // WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 - - // avoid plumbing an awkward path to report a cancelled/failed scan. This will - // be sent directly until b/31398592 is fixed. - sendFailedScanBroadcast(); - mScanPending = true; - return false; - } - } - try { - mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid, - null); - Boolean scanSuccess = mWifiThreadRunner.call(() -> - mScanRequestProxy.startScan(callingUid, packageName), null); - if (scanSuccess == null) { - sendFailedScanBroadcast(); - return false; - } - if (!scanSuccess) { - Log.e(TAG, "Failed to start scan"); - return false; - } - } catch (SecurityException e) { - Log.e(TAG, "Permission violation - startScan not allowed for" - + " uid=" + callingUid + ", packageName=" + packageName + ", reason=" + e); - return false; - } finally { - Binder.restoreCallingIdentity(ident); - } - return true; - } - - // Send a failed scan broadcast to indicate the current scan request failed. - private void sendFailedScanBroadcast() { - // clear calling identity to send broadcast - long callingIdentity = Binder.clearCallingIdentity(); - try { - Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } finally { - // restore calling identity - Binder.restoreCallingIdentity(callingIdentity); - } - - } - - /** - * WPS support in Client mode is deprecated. Return null. - */ - @Override - public String getCurrentNetworkWpsNfcConfigurationToken() { - // while CLs are in flight, return null here, will be removed (b/72423090) - enforceNetworkStackPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("getCurrentNetworkWpsNfcConfigurationToken uid=%") - .c(Binder.getCallingUid()).flush(); - } - return null; - } - - private boolean mInIdleMode; - private boolean mScanPending; - - private void handleIdleModeChanged() { - boolean doScan = false; - synchronized (this) { - boolean idle = mPowerManager.isDeviceIdleMode(); - if (mInIdleMode != idle) { - mInIdleMode = idle; - if (!idle) { - if (mScanPending) { - mScanPending = false; - doScan = true; - } - } - } - } - if (doScan) { - // Someone requested a scan while we were idle; do a full scan now. - // A security check of the caller's identity was made when the request arrived via - // Binder. Now we'll pass the current process's identity to startScan(). - startScan(mContext.getOpPackageName(), mContext.getAttributionTag()); - } - } - - private void handleShutDown() { - // Direct call to notify ActiveModeWarden as soon as possible with the assumption that - // notifyShuttingDown() doesn't have codes that may cause concurrentModificationException, - // e.g., access to a collection. - mActiveModeWarden.notifyShuttingDown(); - mWifiThreadRunner.post(()-> { - // There is no explicit disconnection event in clientModeImpl during shutdown. - // Call resetConnectionState() so that connection duration is calculated - // before memory store write triggered by mMemoryStoreImpl.stop(). - mWifiScoreCard.resetConnectionState(); - mMemoryStoreImpl.stop(); - }); - } - - private boolean checkNetworkSettingsPermission(int pid, int uid) { - return mContext.checkPermission(android.Manifest.permission.NETWORK_SETTINGS, pid, uid) - == PERMISSION_GRANTED; - } - - private boolean checkNetworkSetupWizardPermission(int pid, int uid) { - return mContext.checkPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, pid, uid) - == PackageManager.PERMISSION_GRANTED; - } - - private boolean checkNetworkStackPermission(int pid, int uid) { - return mContext.checkPermission(android.Manifest.permission.NETWORK_STACK, pid, uid) - == PackageManager.PERMISSION_GRANTED; - } - - private boolean checkNetworkManagedProvisioningPermission(int pid, int uid) { - return mContext.checkPermission(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, - pid, uid) == PackageManager.PERMISSION_GRANTED; - } - - /** - * Helper method to check if the entity initiating the binder call has any of the signature only - * permissions. - */ - private boolean isPrivileged(int pid, int uid) { - return checkNetworkSettingsPermission(pid, uid) - || checkNetworkSetupWizardPermission(pid, uid) - || checkNetworkStackPermission(pid, uid) - || checkNetworkManagedProvisioningPermission(pid, uid); - } - - /** - * Helper method to check if the entity initiating the binder call has setup wizard or settings - * permissions. - */ - private boolean isSettingsOrSuw(int pid, int uid) { - return checkNetworkSettingsPermission(pid, uid) - || checkNetworkSetupWizardPermission(pid, uid); - } - - /** Helper method to check if the entity initiating the binder call is a system app. */ - private boolean isSystem(String packageName, int uid) { - long ident = Binder.clearCallingIdentity(); - try { - ApplicationInfo info = mContext.getPackageManager().getApplicationInfoAsUser( - packageName, 0, UserHandle.getUserHandleForUid(uid)); - return (info.flags & APP_INFO_FLAGS_SYSTEM_APP) != 0; - } catch (PackageManager.NameNotFoundException e) { - // In case of exception, assume unknown app (more strict checking) - // Note: This case will never happen since checkPackage is - // called to verify validity before checking App's version. - } finally { - Binder.restoreCallingIdentity(ident); - } - return false; - } - - /** Helper method to check if the entity initiating the binder call is a DO/PO app. */ - private boolean isDeviceOrProfileOwner(int uid, String packageName) { - return mWifiPermissionsUtil.isDeviceOwner(uid, packageName) - || mWifiPermissionsUtil.isProfileOwner(uid, packageName); - } - - private void enforceNetworkSettingsPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS, - "WifiService"); - } - - private boolean checkAnyPermissionOf(String... permissions) { - for (String permission : permissions) { - if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { - return true; - } - } - return false; - } - - private void enforceAnyPermissionOf(String... permissions) { - if (!checkAnyPermissionOf(permissions)) { - throw new SecurityException("Requires one of the following permissions: " - + String.join(", ", permissions) + "."); - } - } - - private void enforceNetworkStackOrSettingsPermission() { - enforceAnyPermissionOf( - android.Manifest.permission.NETWORK_SETTINGS, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private void enforceNetworkStackPermission() { - // TODO(b/142554155): Only check for MAINLINE_NETWORK_STACK permission - boolean granted = mContext.checkCallingOrSelfPermission( - android.Manifest.permission.NETWORK_STACK) - == PackageManager.PERMISSION_GRANTED; - if (granted) { - return; - } - mContext.enforceCallingOrSelfPermission( - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, "WifiService"); - } - - private void enforceAccessPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, - "WifiService"); - } - - /** - * Checks whether the caller can change the wifi state. - * Possible results: - * 1. Operation is allowed. No exception thrown, and AppOpsManager.MODE_ALLOWED returned. - * 2. Operation is not allowed, and caller must be told about this. SecurityException is thrown. - * 3. Operation is not allowed, and caller must not be told about this (i.e. must silently - * ignore the operation). No exception is thrown, and AppOpsManager.MODE_IGNORED returned. - */ - @CheckResult - private int enforceChangePermission(String callingPackage) { - mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); - if (checkNetworkSettingsPermission(Binder.getCallingPid(), Binder.getCallingUid())) { - return MODE_ALLOWED; - } - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, - "WifiService"); - - return mAppOps.noteOp( - AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Binder.getCallingUid(), callingPackage); - } - - private void enforceReadCredentialPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL, - "WifiService"); - } - - private void enforceMulticastChangePermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, - "WifiService"); - } - - private void enforceConnectivityInternalPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_INTERNAL, - "ConnectivityService"); - } - - private void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid) { - mWifiPermissionsUtil.enforceLocationPermission(pkgName, featureId, uid); - } - - /** - * Helper method to check if the app is allowed to access public API's deprecated in - * {@link Build.VERSION_CODES#Q}. - * Note: Invoke mAppOps.checkPackage(uid, packageName) before to ensure correct package name. - */ - private boolean isTargetSdkLessThanQOrPrivileged(String packageName, int pid, int uid) { - return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.Q, uid) - || isPrivileged(pid, uid) - || isDeviceOrProfileOwner(uid, packageName) - || isSystem(packageName, uid) - // TODO(b/140540984): Remove this bypass. - || mWifiPermissionsUtil.checkSystemAlertWindowPermission(uid, packageName); - } - - /** - * Helper method to check if the app is allowed to access public API's deprecated in - * {@link Build.VERSION_CODES#R}. - * Note: Invoke mAppOps.checkPackage(uid, packageName) before to ensure correct package name. - */ - private boolean isTargetSdkLessThanROrPrivileged(String packageName, int pid, int uid) { - return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.R, uid) - || isPrivileged(pid, uid) - || isDeviceOrProfileOwner(uid, packageName) - || isSystem(packageName, uid); - } - - /** - * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} - * @param enable {@code true} to enable, {@code false} to disable. - * @return {@code true} if the enable/disable operation was - * started or is already in the queue. - */ - @Override - public synchronized boolean setWifiEnabled(String packageName, boolean enable) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - boolean isPrivileged = isPrivileged(Binder.getCallingPid(), Binder.getCallingUid()); - if (!isPrivileged && !isDeviceOrProfileOwner(Binder.getCallingUid(), packageName) - && !mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.Q, - Binder.getCallingUid()) - && !isSystem(packageName, Binder.getCallingUid())) { - mLog.info("setWifiEnabled not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return false; - } - // If Airplane mode is enabled, only privileged apps are allowed to toggle Wifi - if (mSettingsStore.isAirplaneModeOn() && !isPrivileged) { - mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush(); - return false; - } - - // If SoftAp is enabled, only privileged apps are allowed to toggle wifi - if (!isPrivileged && mTetheredSoftApTracker.getState() == WIFI_AP_STATE_ENABLED) { - mLog.err("setWifiEnabled with SoftAp enabled: only Settings can toggle wifi").flush(); - return false; - } - - mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName) - .c(Binder.getCallingUid()).c(enable).flush(); - long ident = Binder.clearCallingIdentity(); - try { - if (!mSettingsStore.handleWifiToggled(enable)) { - // Nothing to do if wifi cannot be toggled - return true; - } - } finally { - Binder.restoreCallingIdentity(ident); - } - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) { - if (enable) { - mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON); - } else { - WifiInfo wifiInfo = mClientModeImpl.syncRequestConnectionInfo(); - mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF, - wifiInfo == null ? -1 : wifiInfo.getNetworkId()); - } - } - mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable); - mActiveModeWarden.wifiToggled(); - return true; - } - - /** - * see {@link WifiManager#getWifiState()} - * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, - * {@link WifiManager#WIFI_STATE_DISABLING}, - * {@link WifiManager#WIFI_STATE_ENABLED}, - * {@link WifiManager#WIFI_STATE_ENABLING}, - * {@link WifiManager#WIFI_STATE_UNKNOWN} - */ - @Override - public int getWifiEnabledState() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("getWifiEnabledState uid=%").c(Binder.getCallingUid()).flush(); - } - return mClientModeImpl.syncGetWifiState(); - } - - /** - * see {@link WifiManager#getWifiApState()} - * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, - * {@link WifiManager#WIFI_AP_STATE_DISABLING}, - * {@link WifiManager#WIFI_AP_STATE_ENABLED}, - * {@link WifiManager#WIFI_AP_STATE_ENABLING}, - * {@link WifiManager#WIFI_AP_STATE_FAILED} - */ - @Override - public int getWifiApEnabledState() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("getWifiApEnabledState uid=%").c(Binder.getCallingUid()).flush(); - } - return mTetheredSoftApTracker.getState(); - } - - /** - * see {@link android.net.wifi.WifiManager#updateInterfaceIpState(String, int)} - * - * The possible modes include: {@link WifiManager#IFACE_IP_MODE_TETHERED}, - * {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}, - * {@link WifiManager#IFACE_IP_MODE_CONFIGURATION_ERROR} - * - * @param ifaceName String name of the updated interface - * @param mode new operating mode of the interface - * - * @throws SecurityException if the caller does not have permission to call update - */ - @Override - public void updateInterfaceIpState(String ifaceName, int mode) { - // NETWORK_STACK is a signature only permission. - enforceNetworkStackPermission(); - mLog.info("updateInterfaceIpState uid=%").c(Binder.getCallingUid()).flush(); - - // hand off the work to our handler thread - mWifiThreadRunner.post(() -> mLohsSoftApTracker.updateInterfaceIpState(ifaceName, mode)); - } - - /** - * see {@link android.net.wifi.WifiManager#startSoftAp(WifiConfiguration)} - * @param wifiConfig SSID, security and channel details as part of WifiConfiguration - * @return {@code true} if softap start was triggered - * @throws SecurityException if the caller does not have permission to start softap - */ - @Override - public boolean startSoftAp(WifiConfiguration wifiConfig) { - // NETWORK_STACK is a signature only permission. - enforceNetworkStackPermission(); - - mLog.info("startSoftAp uid=%").c(Binder.getCallingUid()).flush(); - - SoftApConfiguration softApConfig = null; - if (wifiConfig != null) { - softApConfig = ApConfigUtil.fromWifiConfiguration(wifiConfig); - if (softApConfig == null) { - return false; - } - } - - if (!mTetheredSoftApTracker.setEnablingIfAllowed()) { - mLog.err("Tethering is already active.").flush(); - return false; - } - - if (!mWifiThreadRunner.call( - () -> mActiveModeWarden.canRequestMoreSoftApManagers(), false)) { - // Take down LOHS if it is up. - mLohsSoftApTracker.stopAll(); - } - - if (!startSoftApInternal(new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, softApConfig, - mTetheredSoftApTracker.getSoftApCapability()))) { - mTetheredSoftApTracker.setFailedWhileEnabling(); - return false; - } - - return true; - } - - private boolean validateSoftApBand(int apBand) { - if (!ApConfigUtil.isBandValid(apBand)) { - mLog.err("Invalid SoftAp band. ").flush(); - return false; - } - - if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_5GHZ) - && !is5GhzBandSupportedInternal()) { - mLog.err("Can not start softAp with 5GHz band, not supported.").flush(); - return false; - } - - if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_6GHZ)) { - if (!is6GhzBandSupportedInternal() - || !mContext.getResources().getBoolean( - R.bool.config_wifiSoftap6ghzSupported)) { - mLog.err("Can not start softAp with 6GHz band, not supported.").flush(); - return false; - } - } - - return true; - } - - /** - * see {@link android.net.wifi.WifiManager#startTetheredHotspot(SoftApConfiguration)} - * @param softApConfig SSID, security and channel details as part of SoftApConfiguration - * @return {@code true} if softap start was triggered - * @throws SecurityException if the caller does not have permission to start softap - */ - @Override - public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) { - // NETWORK_STACK is a signature only permission. - enforceNetworkStackPermission(); - - mLog.info("startTetheredHotspot uid=%").c(Binder.getCallingUid()).flush(); - - if (!mTetheredSoftApTracker.setEnablingIfAllowed()) { - mLog.err("Tethering is already active.").flush(); - return false; - } - - if (!mWifiThreadRunner.call( - () -> mActiveModeWarden.canRequestMoreSoftApManagers(), false)) { - // Take down LOHS if it is up. - mLohsSoftApTracker.stopAll(); - } - - if (!startSoftApInternal(new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, softApConfig, - mTetheredSoftApTracker.getSoftApCapability()))) { - mTetheredSoftApTracker.setFailedWhileEnabling(); - return false; - } - - return true; - } - - /** - * Internal method to start softap mode. Callers of this method should have already checked - * proper permissions beyond the NetworkStack permission. - */ - private boolean startSoftApInternal(SoftApModeConfiguration apConfig) { - int uid = Binder.getCallingUid(); - boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid); - mLog.trace("startSoftApInternal uid=% mode=%") - .c(uid).c(apConfig.getTargetMode()).flush(); - - // null wifiConfig is a meaningful input for CMD_SET_AP; it means to use the persistent - // AP config. - SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration(); - if (softApConfig != null - && (!WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged) - || !validateSoftApBand(softApConfig.getBand()))) { - Log.e(TAG, "Invalid SoftApConfiguration"); - return false; - } - - mActiveModeWarden.startSoftAp(apConfig); - return true; - } - - /** - * see {@link android.net.wifi.WifiManager#stopSoftAp()} - * @return {@code true} if softap stop was triggered - * @throws SecurityException if the caller does not have permission to stop softap - */ - @Override - public boolean stopSoftAp() { - // NETWORK_STACK is a signature only permission. - enforceNetworkStackPermission(); - - // only permitted callers are allowed to this point - they must have gone through - // connectivity service since this method is protected with the NETWORK_STACK PERMISSION - - mLog.info("stopSoftAp uid=%").c(Binder.getCallingUid()).flush(); - - stopSoftApInternal(WifiManager.IFACE_IP_MODE_TETHERED); - return true; - } - - /** - * Internal method to stop softap mode. - * - * Callers of this method should have already checked - * proper permissions beyond the NetworkStack permission. - * - * @param mode the operating mode of APs to bring down (ex, - * {@link WifiManager.IFACE_IP_MODE_TETHERED} or - * {@link WifiManager.IFACE_IP_MODE_LOCAL_ONLY}). - * Use {@link WifiManager.IFACE_IP_MODE_UNSPECIFIED} to stop all APs. - */ - private void stopSoftApInternal(int mode) { - mLog.trace("stopSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush(); - - mActiveModeWarden.stopSoftAp(mode); - } - - /** - * SoftAp callback - */ - private final class TetheredSoftApTracker implements WifiManager.SoftApCallback { - /** - * State of tethered SoftAP - * One of: {@link WifiManager#WIFI_AP_STATE_DISABLED}, - * {@link WifiManager#WIFI_AP_STATE_DISABLING}, - * {@link WifiManager#WIFI_AP_STATE_ENABLED}, - * {@link WifiManager#WIFI_AP_STATE_ENABLING}, - * {@link WifiManager#WIFI_AP_STATE_FAILED} - */ - private final Object mLock = new Object(); - private int mTetheredSoftApState = WIFI_AP_STATE_DISABLED; - private List<WifiClient> mTetheredSoftApConnectedClients = new ArrayList<>(); - private SoftApInfo mTetheredSoftApInfo = new SoftApInfo(); - // TODO: We need to maintain two capability. One for LTE + SAP and one for WIFI + SAP - private SoftApCapability mTetheredSoftApCapability = null; - - public int getState() { - synchronized (mLock) { - return mTetheredSoftApState; - } - } - - public boolean setEnablingIfAllowed() { - synchronized (mLock) { - if (mTetheredSoftApState != WIFI_AP_STATE_DISABLED - && mTetheredSoftApState != WIFI_AP_STATE_FAILED) { - return false; - } - mTetheredSoftApState = WIFI_AP_STATE_ENABLING; - return true; - } - } - - public void setFailedWhileEnabling() { - synchronized (mLock) { - if (mTetheredSoftApState == WIFI_AP_STATE_ENABLING) { - mTetheredSoftApState = WIFI_AP_STATE_FAILED; - } - } - } - - public List<WifiClient> getConnectedClients() { - synchronized (mLock) { - return mTetheredSoftApConnectedClients; - } - } - - public SoftApInfo getSoftApInfo() { - synchronized (mLock) { - return mTetheredSoftApInfo; - } - } - - public SoftApCapability getSoftApCapability() { - synchronized (mLock) { - if (mTetheredSoftApCapability == null) { - mTetheredSoftApCapability = ApConfigUtil.updateCapabilityFromResource(mContext); - } - return mTetheredSoftApCapability; - } - } - - public void updateSoftApCapability(int subId) { - synchronized (mLock) { - CarrierConfigManager carrierConfigManager = - (CarrierConfigManager) mContext.getSystemService( - Context.CARRIER_CONFIG_SERVICE); - if (carrierConfigManager == null) return; - PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId); - if (carrierConfig == null) return; - int carrierMaxClient = carrierConfig.getInt( - CarrierConfigManager.Wifi.KEY_HOTSPOT_MAX_CLIENT_COUNT); - int finalSupportedClientNumber = mContext.getResources().getInteger( - R.integer.config_wifiHardwareSoftapMaxClientCount); - if (carrierMaxClient > 0) { - finalSupportedClientNumber = Math.min(finalSupportedClientNumber, - carrierMaxClient); - } - if (finalSupportedClientNumber == getSoftApCapability().getMaxSupportedClients()) { - return; - } - mTetheredSoftApCapability.setMaxSupportedClients( - finalSupportedClientNumber); - } - onCapabilityChanged(mTetheredSoftApCapability); - } - - private final ExternalCallbackTracker<ISoftApCallback> mRegisteredSoftApCallbacks = - new ExternalCallbackTracker<>(mClientModeImplHandler); - - public boolean registerSoftApCallback(IBinder binder, ISoftApCallback callback, - int callbackIdentifier) { - return mRegisteredSoftApCallbacks.add(binder, callback, callbackIdentifier); - } - - public void unregisterSoftApCallback(int callbackIdentifier) { - mRegisteredSoftApCallbacks.remove(callbackIdentifier); - } - - /** - * Called when soft AP state changes. - * - * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, - * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, - * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} - * @param failureReason reason when in failed state. One of - * {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL} - */ - @Override - public void onStateChanged(int state, int failureReason) { - synchronized (mLock) { - mTetheredSoftApState = state; - } - - Iterator<ISoftApCallback> iterator = - mRegisteredSoftApCallbacks.getCallbacks().iterator(); - while (iterator.hasNext()) { - ISoftApCallback callback = iterator.next(); - try { - callback.onStateChanged(state, failureReason); - } catch (RemoteException e) { - Log.e(TAG, "onStateChanged: remote exception -- " + e); - // TODO(b/138863863) remove does nothing, getCallbacks() returns a copy - iterator.remove(); - } - } - } - - /** - * Called when the connected clients to soft AP changes. - * - * @param clients connected clients to soft AP - */ - @Override - public void onConnectedClientsChanged(List<WifiClient> clients) { - synchronized (mLock) { - mTetheredSoftApConnectedClients = new ArrayList<>(clients); - } - - Iterator<ISoftApCallback> iterator = - mRegisteredSoftApCallbacks.getCallbacks().iterator(); - while (iterator.hasNext()) { - ISoftApCallback callback = iterator.next(); - try { - callback.onConnectedClientsChanged(mTetheredSoftApConnectedClients); - } catch (RemoteException e) { - Log.e(TAG, "onConnectedClientsChanged: remote exception -- " + e); - // TODO(b/138863863) remove does nothing, getCallbacks() returns a copy - iterator.remove(); - } - } - } - - /** - * Called when information of softap changes. - * - * @param softApInfo is the softap information. {@link SoftApInfo} - */ - @Override - public void onInfoChanged(SoftApInfo softApInfo) { - synchronized (mLock) { - mTetheredSoftApInfo = new SoftApInfo(softApInfo); - } - - Iterator<ISoftApCallback> iterator = - mRegisteredSoftApCallbacks.getCallbacks().iterator(); - while (iterator.hasNext()) { - ISoftApCallback callback = iterator.next(); - try { - callback.onInfoChanged(mTetheredSoftApInfo); - } catch (RemoteException e) { - Log.e(TAG, "onInfoChanged: remote exception -- " + e); - } - } - } - - /** - * Called when capability of softap changes. - * - * @param capability is the softap capability. {@link SoftApCapability} - */ - @Override - public void onCapabilityChanged(SoftApCapability capability) { - synchronized (mLock) { - mTetheredSoftApCapability = new SoftApCapability(capability); - } - - Iterator<ISoftApCallback> iterator = - mRegisteredSoftApCallbacks.getCallbacks().iterator(); - while (iterator.hasNext()) { - ISoftApCallback callback = iterator.next(); - try { - callback.onCapabilityChanged(mTetheredSoftApCapability); - } catch (RemoteException e) { - Log.e(TAG, "onCapabiliyChanged: remote exception -- " + e); - } - } - } - - /** - * Called when client trying to connect but device blocked the client with specific reason. - * - * @param client the currently blocked client. - * @param blockedReason one of blocked reason from - * {@link WifiManager.SapClientBlockedReason} - */ - @Override - public void onBlockedClientConnecting(WifiClient client, int blockedReason) { - Iterator<ISoftApCallback> iterator = - mRegisteredSoftApCallbacks.getCallbacks().iterator(); - while (iterator.hasNext()) { - ISoftApCallback callback = iterator.next(); - try { - callback.onBlockedClientConnecting(client, blockedReason); - } catch (RemoteException e) { - Log.e(TAG, "onBlockedClientConnecting: remote exception -- " + e); - } - } - } - } - - /** - * Implements LOHS behavior on top of the existing SoftAp API. - */ - private final class LohsSoftApTracker implements WifiManager.SoftApCallback { - @GuardedBy("mLocalOnlyHotspotRequests") - private final HashMap<Integer, LocalOnlyHotspotRequestInfo> - mLocalOnlyHotspotRequests = new HashMap<>(); - - /** Currently-active config, to be sent to shared clients registering later. */ - @GuardedBy("mLocalOnlyHotspotRequests") - private SoftApModeConfiguration mActiveConfig = null; - - /** - * Whether we are currently operating in exclusive mode (i.e. whether a custom config is - * active). - */ - @GuardedBy("mLocalOnlyHotspotRequests") - private boolean mIsExclusive = false; - - @GuardedBy("mLocalOnlyHotspotRequests") - private String mLohsInterfaceName; - - /** - * State of local-only hotspot - * One of: {@link WifiManager#WIFI_AP_STATE_DISABLED}, - * {@link WifiManager#WIFI_AP_STATE_DISABLING}, - * {@link WifiManager#WIFI_AP_STATE_ENABLED}, - * {@link WifiManager#WIFI_AP_STATE_ENABLING}, - * {@link WifiManager#WIFI_AP_STATE_FAILED} - */ - @GuardedBy("mLocalOnlyHotspotRequests") - private int mLohsState = WIFI_AP_STATE_DISABLED; - - @GuardedBy("mLocalOnlyHotspotRequests") - private int mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; - - private SoftApCapability mLohsSoftApCapability = null; - - public SoftApCapability getSoftApCapability() { - if (mLohsSoftApCapability == null) { - mLohsSoftApCapability = ApConfigUtil.updateCapabilityFromResource(mContext); - } - return mLohsSoftApCapability; - } - - public void updateInterfaceIpState(String ifaceName, int mode) { - // update interface IP state related to local-only hotspot - synchronized (mLocalOnlyHotspotRequests) { - Log.d(TAG, "updateInterfaceIpState: ifaceName=" + ifaceName + " mode=" + mode - + " previous LOHS mode= " + mLohsInterfaceMode); - - switch (mode) { - case WifiManager.IFACE_IP_MODE_LOCAL_ONLY: - // first make sure we have registered requests. - if (mLocalOnlyHotspotRequests.isEmpty()) { - // we don't have requests... stop the hotspot - Log.wtf(TAG, "Starting LOHS without any requests?"); - stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - return; - } - // LOHS is ready to go! Call our registered requestors! - mLohsInterfaceName = ifaceName; - mLohsInterfaceMode = mode; - sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked(); - break; - case WifiManager.IFACE_IP_MODE_TETHERED: - if (mLohsInterfaceName != null - && mLohsInterfaceName.equals(ifaceName)) { - /* This shouldn't happen except in a race, but if it does, tear down - * the LOHS and let tethering win. - * - * If concurrent SAPs are allowed, the interface names will differ, - * so we don't have to check the config here. - */ - Log.e(TAG, "Unexpected IP mode change on " + ifaceName); - mLohsInterfaceName = null; - mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; - sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( - LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE); - } - break; - case WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR: - if (ifaceName == null) { - // All softAps - mLohsInterfaceName = null; - mLohsInterfaceMode = mode; - sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( - LocalOnlyHotspotCallback.ERROR_GENERIC); - stopSoftApInternal(WifiManager.IFACE_IP_MODE_UNSPECIFIED); - } else if (ifaceName.equals(mLohsInterfaceName)) { - mLohsInterfaceName = null; - mLohsInterfaceMode = mode; - sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( - LocalOnlyHotspotCallback.ERROR_GENERIC); - stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - } else { - // Not for LOHS. This is the wrong place to do this, but... - stopSoftApInternal(WifiManager.IFACE_IP_MODE_TETHERED); - } - break; - case WifiManager.IFACE_IP_MODE_UNSPECIFIED: - if (ifaceName == null || ifaceName.equals(mLohsInterfaceName)) { - mLohsInterfaceName = null; - mLohsInterfaceMode = mode; - } - break; - default: - mLog.warn("updateInterfaceIpState: unknown mode %").c(mode).flush(); - } - } - } - - /** - * Helper method to send a HOTSPOT_FAILED message to all registered LocalOnlyHotspotRequest - * callers and clear the registrations. - * - * Callers should already hold the mLocalOnlyHotspotRequests lock. - */ - @GuardedBy("mLocalOnlyHotspotRequests") - private void sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int reason) { - for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { - try { - requestor.sendHotspotFailedMessage(reason); - requestor.unlinkDeathRecipient(); - } catch (RemoteException e) { - // This will be cleaned up by binder death handling - } - } - - // Since all callers were notified, now clear the registrations. - mLocalOnlyHotspotRequests.clear(); - } - - /** - * Helper method to send a HOTSPOT_STOPPED message to all registered LocalOnlyHotspotRequest - * callers and clear the registrations. - * - * Callers should already hold the mLocalOnlyHotspotRequests lock. - */ - @GuardedBy("mLocalOnlyHotspotRequests") - private void sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked() { - for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { - try { - requestor.sendHotspotStoppedMessage(); - requestor.unlinkDeathRecipient(); - } catch (RemoteException e) { - // This will be cleaned up by binder death handling - } - } - - // Since all callers were notified, now clear the registrations. - mLocalOnlyHotspotRequests.clear(); - } - - /** - * Add a new LOHS client - */ - private int start(int pid, LocalOnlyHotspotRequestInfo request) { - synchronized (mLocalOnlyHotspotRequests) { - // does this caller already have a request? - if (mLocalOnlyHotspotRequests.get(pid) != null) { - mLog.trace("caller already has an active request").flush(); - throw new IllegalStateException( - "Caller already has an active LocalOnlyHotspot request"); - } - - // Never accept exclusive requests (with custom configuration) at the same time as - // shared requests. - if (!mLocalOnlyHotspotRequests.isEmpty()) { - boolean requestIsExclusive = request.getCustomConfig() != null; - if (mIsExclusive || requestIsExclusive) { - mLog.trace("Cannot share with existing LOHS request due to custom config") - .flush(); - return LocalOnlyHotspotCallback.ERROR_GENERIC; - } - } - - // At this point, the request is accepted. - if (mLocalOnlyHotspotRequests.isEmpty()) { - startForFirstRequestLocked(request); - } else if (mLohsInterfaceMode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY) { - // LOHS has already started up for an earlier request, so we can send the - // current config to the incoming request right away. - try { - mLog.trace("LOHS already up, trigger onStarted callback").flush(); - request.sendHotspotStartedMessage(mActiveConfig.getSoftApConfiguration()); - } catch (RemoteException e) { - return LocalOnlyHotspotCallback.ERROR_GENERIC; - } - } - - mLocalOnlyHotspotRequests.put(pid, request); - return LocalOnlyHotspotCallback.REQUEST_REGISTERED; - } - } - - @GuardedBy("mLocalOnlyHotspotRequests") - private void startForFirstRequestLocked(LocalOnlyHotspotRequestInfo request) { - int band = SoftApConfiguration.BAND_2GHZ; - - // For auto only - if (hasAutomotiveFeature(mContext)) { - if (mContext.getResources().getBoolean(R.bool.config_wifiLocalOnlyHotspot6ghz) - && mContext.getResources().getBoolean(R.bool.config_wifiSoftap6ghzSupported) - && is6GhzBandSupportedInternal()) { - band = SoftApConfiguration.BAND_6GHZ; - } else if (mContext.getResources().getBoolean( - R.bool.config_wifi_local_only_hotspot_5ghz) - && is5GhzBandSupportedInternal()) { - band = SoftApConfiguration.BAND_5GHZ; - } - } - - SoftApConfiguration softApConfig = WifiApConfigStore.generateLocalOnlyHotspotConfig( - mContext, band, request.getCustomConfig()); - - mActiveConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_LOCAL_ONLY, - softApConfig, mLohsSoftApTracker.getSoftApCapability()); - mIsExclusive = (request.getCustomConfig() != null); - - startSoftApInternal(mActiveConfig); - } - - /** - * Requests that any local-only hotspot be stopped. - */ - public void stopAll() { - synchronized (mLocalOnlyHotspotRequests) { - if (!mLocalOnlyHotspotRequests.isEmpty()) { - // This is used to take down LOHS when tethering starts, and in that - // case we send failed instead of stopped. - // TODO check if that is right. Calling onFailed instead of onStopped when the - // hotspot is already started does not seem to match the documentation - sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( - LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE); - stopIfEmptyLocked(); - } - } - } - - /** - * Unregisters the LOHS request from the given process and stops LOHS if no other clients. - */ - public void stopByPid(int pid) { - synchronized (mLocalOnlyHotspotRequests) { - LocalOnlyHotspotRequestInfo requestInfo = mLocalOnlyHotspotRequests.remove(pid); - if (requestInfo == null) return; - requestInfo.unlinkDeathRecipient(); - stopIfEmptyLocked(); - } - } - - /** - * Unregisters LocalOnlyHotspot request and stops the hotspot if needed. - */ - public void stopByRequest(LocalOnlyHotspotRequestInfo request) { - synchronized (mLocalOnlyHotspotRequests) { - if (mLocalOnlyHotspotRequests.remove(request.getPid()) == null) { - mLog.trace("LocalOnlyHotspotRequestInfo not found to remove").flush(); - return; - } - stopIfEmptyLocked(); - } - } - - @GuardedBy("mLocalOnlyHotspotRequests") - private void stopIfEmptyLocked() { - if (mLocalOnlyHotspotRequests.isEmpty()) { - mActiveConfig = null; - mIsExclusive = false; - mLohsInterfaceName = null; - mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; - stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - } - } - - /** - * Helper method to send a HOTSPOT_STARTED message to all registered LocalOnlyHotspotRequest - * callers. - * - * Callers should already hold the mLocalOnlyHotspotRequests lock. - */ - @GuardedBy("mLocalOnlyHotspotRequests") - private void sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked() { - for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { - try { - requestor.sendHotspotStartedMessage(mActiveConfig.getSoftApConfiguration()); - } catch (RemoteException e) { - // This will be cleaned up by binder death handling - } - } - } - - @Override - public void onStateChanged(int state, int failureReason) { - // The AP state update from ClientModeImpl for softap - synchronized (mLocalOnlyHotspotRequests) { - Log.d(TAG, "lohs.onStateChanged: currentState=" + state - + " previousState=" + mLohsState + " errorCode= " + failureReason - + " ifaceName=" + mLohsInterfaceName); - - // check if we have a failure - since it is possible (worst case scenario where - // WifiController and ClientModeImpl are out of sync wrt modes) to get two FAILED - // notifications in a row, we need to handle this first. - if (state == WIFI_AP_STATE_FAILED) { - // update registered LOHS callbacks if we see a failure - int errorToReport = ERROR_GENERIC; - if (failureReason == SAP_START_FAILURE_NO_CHANNEL) { - errorToReport = ERROR_NO_CHANNEL; - } - // holding the required lock: send message to requestors and clear the list - sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(errorToReport); - // also need to clear interface ip state - updateInterfaceIpState(mLohsInterfaceName, - WifiManager.IFACE_IP_MODE_UNSPECIFIED); - } else if (state == WIFI_AP_STATE_DISABLING || state == WIFI_AP_STATE_DISABLED) { - // softap is shutting down or is down... let requestors know via the - // onStopped call - // if we are currently in hotspot mode, then trigger onStopped for registered - // requestors, otherwise something odd happened and we should clear state - if (mLohsInterfaceName != null - && mLohsInterfaceMode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY) { - // holding the required lock: send message to requestors and clear the list - sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked(); - } else { - // LOHS not active: report an error (still holding the required lock) - sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(ERROR_GENERIC); - } - // also clear interface ip state - updateInterfaceIpState(mLohsInterfaceName, - WifiManager.IFACE_IP_MODE_UNSPECIFIED); - } - // For enabling and enabled, just record the new state - mLohsState = state; - } - } - - @Override - public void onConnectedClientsChanged(List<WifiClient> clients) { - // Nothing to do - } - - /** - * Called when information of softap changes. - * - * @param softApInfo is the softap information. {@link SoftApInfo} - */ - @Override - public void onInfoChanged(SoftApInfo softApInfo) { - // Nothing to do - } - - /** - * Called when capability of softap changes. - * - * @param capability is the softap information. {@link SoftApCapability} - */ - @Override - public void onCapabilityChanged(SoftApCapability capability) { - // Nothing to do - } - - /** - * Called when client trying to connect but device blocked the client with specific reason. - * - * @param client the currently blocked client. - * @param blockedReason one of blocked reason from - * {@link WifiManager.SapClientBlockedReason} - */ - @Override - public void onBlockedClientConnecting(WifiClient client, int blockedReason) { - // Nothing to do - } - } - - /** - * see {@link android.net.wifi.WifiManager#registerSoftApCallback(Executor, SoftApCallback)} - * - * @param binder IBinder instance to allow cleanup if the app dies - * @param callback Soft AP callback to register - * @param callbackIdentifier Unique ID of the registering callback. This ID will be used to - * unregister the callback. See {@link unregisterSoftApCallback(int)} - * - * @throws SecurityException if the caller does not have permission to register a callback - * @throws RemoteException if remote exception happens - * @throws IllegalArgumentException if the arguments are null or invalid - */ - @Override - public void registerSoftApCallback(IBinder binder, ISoftApCallback callback, - int callbackIdentifier) { - // verify arguments - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - - enforceNetworkStackOrSettingsPermission(); - - if (mVerboseLoggingEnabled) { - mLog.info("registerSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); - } - - // post operation to handler thread - mWifiThreadRunner.post(() -> { - if (!mTetheredSoftApTracker.registerSoftApCallback(binder, callback, - callbackIdentifier)) { - Log.e(TAG, "registerSoftApCallback: Failed to add callback"); - return; - } - // Update the client about the current state immediately after registering the callback - try { - callback.onStateChanged(mTetheredSoftApTracker.getState(), 0); - callback.onConnectedClientsChanged(mTetheredSoftApTracker.getConnectedClients()); - callback.onInfoChanged(mTetheredSoftApTracker.getSoftApInfo()); - callback.onCapabilityChanged(mTetheredSoftApTracker.getSoftApCapability()); - } catch (RemoteException e) { - Log.e(TAG, "registerSoftApCallback: remote exception -- " + e); - } - }); - } - - /** - * see {@link android.net.wifi.WifiManager#unregisterSoftApCallback(SoftApCallback)} - * - * @param callbackIdentifier Unique ID of the callback to be unregistered. - * - * @throws SecurityException if the caller does not have permission to register a callback - */ - @Override - public void unregisterSoftApCallback(int callbackIdentifier) { - enforceNetworkStackOrSettingsPermission(); - - if (mVerboseLoggingEnabled) { - mLog.info("unregisterSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); - } - - // post operation to handler thread - mWifiThreadRunner.post(() -> - mTetheredSoftApTracker.unregisterSoftApCallback(callbackIdentifier)); - } - - /** - * Temporary method used for testing while start is not fully implemented. This - * method allows unit tests to register callbacks directly for testing mechanisms triggered by - * softap mode changes. - */ - @VisibleForTesting - void registerLOHSForTest(int pid, LocalOnlyHotspotRequestInfo request) { - mLohsSoftApTracker.start(pid, request); - } - - /** - * Method to start LocalOnlyHotspot. In this method, permissions, settings and modes are - * checked to verify that we can enter softapmode. This method returns - * {@link LocalOnlyHotspotCallback#REQUEST_REGISTERED} if we will attempt to start, otherwise, - * possible startup erros may include tethering being disallowed failure reason {@link - * LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED} or an incompatible mode failure reason - * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE}. - * - * see {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)} - * - * @param callback Callback to communicate with WifiManager and allow cleanup if the app dies. - * @param packageName String name of the calling package. - * @param featureId The feature in the package - * @param customConfig Custom configuration to be applied to the hotspot, or null for a shared - * hotspot with framework-generated config. - * - * @return int return code for attempt to start LocalOnlyHotspot. - * - * @throws SecurityException if the caller does not have permission to start a Local Only - * Hotspot. - * @throws IllegalStateException if the caller attempts to start the LocalOnlyHotspot while they - * have an outstanding request. - */ - @Override - public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName, - String featureId, SoftApConfiguration customConfig) { - // first check if the caller has permission to start a local only hotspot - // need to check for WIFI_STATE_CHANGE and location permission - final int uid = Binder.getCallingUid(); - final int pid = Binder.getCallingPid(); - - mLog.info("start uid=% pid=%").c(uid).c(pid).flush(); - - // Permission requirements are different with/without custom config. - if (customConfig == null) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return LocalOnlyHotspotCallback.ERROR_GENERIC; - } - enforceLocationPermission(packageName, featureId, uid); - long ident = Binder.clearCallingIdentity(); - try { - // also need to verify that Locations services are enabled. - if (!mWifiPermissionsUtil.isLocationModeEnabled()) { - throw new SecurityException("Location mode is not enabled."); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } else { - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - } - - // verify that tethering is not disabled - if (mUserManager.hasUserRestrictionForUser( - UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.getUserHandleForUid(uid))) { - return LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; - } - - // the app should be in the foreground - long ident = Binder.clearCallingIdentity(); - try { - // also need to verify that Locations services are enabled. - if (!mFrameworkFacade.isAppForeground(mContext, uid)) { - return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; - } - } finally { - Binder.restoreCallingIdentity(ident); - } - - // check if we are currently tethering - if (!mActiveModeWarden.canRequestMoreSoftApManagers() - && mTetheredSoftApTracker.getState() == WIFI_AP_STATE_ENABLED) { - // Tethering is enabled, cannot start LocalOnlyHotspot - mLog.info("Cannot start localOnlyHotspot when WiFi Tethering is active.") - .flush(); - return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; - } - - // now create the new LOHS request info object - LocalOnlyHotspotRequestInfo request = new LocalOnlyHotspotRequestInfo(callback, - new LocalOnlyRequestorCallback(), customConfig); - - return mLohsSoftApTracker.start(pid, request); - } - - /** - * see {@link WifiManager#stopLocalOnlyHotspot()} - * - * @throws SecurityException if the caller does not have permission to stop a Local Only - * Hotspot. - */ - @Override - public void stopLocalOnlyHotspot() { - // don't do a permission check here. if the app's permission to change the wifi state is - // revoked, we still want them to be able to stop a previously created hotspot (otherwise - // it could cost the user money). When the app created the hotspot, its permission was - // checked. - final int uid = Binder.getCallingUid(); - final int pid = Binder.getCallingPid(); - - mLog.info("stopLocalOnlyHotspot uid=% pid=%").c(uid).c(pid).flush(); - - mLohsSoftApTracker.stopByPid(pid); - } - - /** - * see {@link WifiManager#watchLocalOnlyHotspot(LocalOnlyHotspotObserver)} - * - * This call requires the android.permission.NETWORK_SETTINGS permission. - * - * @param callback Callback to communicate with WifiManager and allow cleanup if the app dies. - * - * @throws SecurityException if the caller does not have permission to watch Local Only Hotspot - * status updates. - * @throws IllegalStateException if the caller attempts to watch LocalOnlyHotspot updates with - * an existing subscription. - */ - @Override - public void startWatchLocalOnlyHotspot(ILocalOnlyHotspotCallback callback) { - // NETWORK_SETTINGS is a signature only permission. - enforceNetworkSettingsPermission(); - - throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); - } - - /** - * see {@link WifiManager#unregisterLocalOnlyHotspotObserver()} - */ - @Override - public void stopWatchLocalOnlyHotspot() { - // NETWORK_STACK is a signature only permission. - enforceNetworkSettingsPermission(); - throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); - } - - /** - * see {@link WifiManager#getWifiApConfiguration()} - * @return soft access point configuration - * @throws SecurityException if the caller does not have permission to retrieve the softap - * config - */ - @Nullable - @Override - public WifiConfiguration getWifiApConfiguration() { - enforceAccessPermission(); - int uid = Binder.getCallingUid(); - // only allow Settings UI to get the saved SoftApConfig - if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { - // random apps should not be allowed to read the user specified config - throw new SecurityException("App not allowed to read or update stored WiFi Ap config " - + "(uid = " + uid + ")"); - } - - if (mVerboseLoggingEnabled) { - mLog.info("getWifiApConfiguration uid=%").c(uid).flush(); - } - - // hand off work to the ClientModeImpl handler thread to sync work between calls - // and SoftApManager starting up softap - return (mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, - new SoftApConfiguration.Builder().build())).toWifiConfiguration(); - } - - /** - * see {@link WifiManager#getSoftApConfiguration()} - * @return soft access point configuration {@link SoftApConfiguration} - * @throws SecurityException if the caller does not have permission to retrieve the softap - * config - */ - @NonNull - @Override - public SoftApConfiguration getSoftApConfiguration() { - enforceNetworkSettingsPermission(); - int uid = Binder.getCallingUid(); - if (mVerboseLoggingEnabled) { - mLog.info("getSoftApConfiguration uid=%").c(uid).flush(); - } - - // hand off work to the ClientModeImpl handler thread to sync work between calls - // and SoftApManager starting up softap - return mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, - new SoftApConfiguration.Builder().build()); - } - - /** - * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)} - * @param wifiConfig WifiConfiguration details for soft access point - * @return boolean indicating success or failure of the operation - * @throws SecurityException if the caller does not have permission to write the softap config - */ - @Override - public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - int uid = Binder.getCallingUid(); - // only allow Settings UI to write the stored SoftApConfig - if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { - // random apps should not be allowed to read the user specified config - throw new SecurityException("App not allowed to read or update stored WiFi AP config " - + "(uid = " + uid + ")"); - } - mLog.info("setWifiApConfiguration uid=%").c(uid).flush(); - if (wifiConfig == null) - return false; - SoftApConfiguration softApConfig = ApConfigUtil.fromWifiConfiguration(wifiConfig); - if (softApConfig == null) return false; - if (WifiApConfigStore.validateApWifiConfiguration( - softApConfig, false)) { - mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration(softApConfig)); - return true; - } else { - Log.e(TAG, "Invalid WifiConfiguration"); - return false; - } - } - - /** - * see {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)} - * @param softApConfig {@link SoftApConfiguration} details for soft access point - * @return boolean indicating success or failure of the operation - * @throws SecurityException if the caller does not have permission to write the softap config - */ - @Override - public boolean setSoftApConfiguration( - @NonNull SoftApConfiguration softApConfig, @NonNull String packageName) { - enforceNetworkSettingsPermission(); - int uid = Binder.getCallingUid(); - boolean privileged = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); - mLog.info("setSoftApConfiguration uid=%").c(uid).flush(); - if (softApConfig == null) return false; - if (WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged)) { - mActiveModeWarden.updateSoftApConfiguration(softApConfig); - mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration(softApConfig)); - return true; - } else { - Log.e(TAG, "Invalid SoftAp Configuration"); - return false; - } - } - - /** - * see {@link android.net.wifi.WifiManager#setScanAlwaysAvailable(boolean)} - */ - @Override - public void setScanAlwaysAvailable(boolean isAvailable) { - enforceNetworkSettingsPermission(); - mLog.info("setScanAlwaysAvailable uid=%").c(Binder.getCallingUid()).flush(); - mSettingsStore.handleWifiScanAlwaysAvailableToggled(isAvailable); - long ident = Binder.clearCallingIdentity(); - try { - mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility() - .handleWifiScanAlwaysAvailableToggled(isAvailable); - } finally { - Binder.restoreCallingIdentity(ident); - } - mActiveModeWarden.scanAlwaysModeChanged(); - } - - /** - * see {@link android.net.wifi.WifiManager#isScanAlwaysAvailable()} - */ - @Override - public boolean isScanAlwaysAvailable() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("isScanAlwaysAvailable uid=%").c(Binder.getCallingUid()).flush(); - } - return mSettingsStore.isScanAlwaysAvailable(); - } - - /** - * see {@link android.net.wifi.WifiManager#disconnect()} - */ - @Override - public boolean disconnect(String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - if (!isTargetSdkLessThanQOrPrivileged( - packageName, Binder.getCallingPid(), Binder.getCallingUid())) { - mLog.info("disconnect not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return false; - } - mLog.info("disconnect uid=%").c(Binder.getCallingUid()).flush(); - mClientModeImpl.disconnectCommand(); - return true; - } - - /** - * see {@link android.net.wifi.WifiManager#reconnect()} - */ - @Override - public boolean reconnect(String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - if (!isTargetSdkLessThanQOrPrivileged( - packageName, Binder.getCallingPid(), Binder.getCallingUid())) { - mLog.info("reconnect not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return false; - } - mLog.info("reconnect uid=%").c(Binder.getCallingUid()).flush(); - mClientModeImpl.reconnectCommand(new WorkSource(Binder.getCallingUid())); - return true; - } - - /** - * see {@link android.net.wifi.WifiManager#reassociate()} - */ - @Override - public boolean reassociate(String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - if (!isTargetSdkLessThanQOrPrivileged( - packageName, Binder.getCallingPid(), Binder.getCallingUid())) { - mLog.info("reassociate not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return false; - } - mLog.info("reassociate uid=%").c(Binder.getCallingUid()).flush(); - mClientModeImpl.reassociateCommand(); - return true; - } - - /** - * see {@link android.net.wifi.WifiManager#getSupportedFeatures} - */ - @Override - public long getSupportedFeatures() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("getSupportedFeatures uid=%").c(Binder.getCallingUid()).flush(); - } - return getSupportedFeaturesInternal(); - } - - @Override - public void getWifiActivityEnergyInfoAsync(IOnWifiActivityEnergyInfoListener listener) { - if (mVerboseLoggingEnabled) { - mLog.info("getWifiActivityEnergyInfoAsync uid=%") - .c(Binder.getCallingUid()) - .flush(); - } - // getWifiActivityEnergyInfo() performs permission checking - WifiActivityEnergyInfo info = getWifiActivityEnergyInfo(); - try { - listener.onWifiActivityEnergyInfo(info); - } catch (RemoteException e) { - Log.e(TAG, "onWifiActivityEnergyInfo: RemoteException -- ", e); - } - } - - private WifiActivityEnergyInfo getWifiActivityEnergyInfo() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("getWifiActivityEnergyInfo uid=%").c(Binder.getCallingUid()).flush(); - } - if ((getSupportedFeatures() & WifiManager.WIFI_FEATURE_LINK_LAYER_STATS) == 0) { - return null; - } - if (mClientModeImplChannel == null) { - Log.e(TAG, "mClientModeImplChannel is not initialized"); - return null; - } - WifiLinkLayerStats stats = mClientModeImpl.syncGetLinkLayerStats(mClientModeImplChannel); - if (stats == null) { - return null; - } - - final long rxIdleTimeMillis = stats.on_time - stats.tx_time - stats.rx_time; - final long[] txTimePerLevelMillis; - if (stats.tx_time_per_level == null) { - // This will happen if the HAL get link layer API returned null. - txTimePerLevelMillis = new long[0]; - } else { - // need to manually copy since we are converting an int[] to a long[] - txTimePerLevelMillis = new long[stats.tx_time_per_level.length]; - for (int i = 0; i < txTimePerLevelMillis.length; i++) { - txTimePerLevelMillis[i] = stats.tx_time_per_level[i]; - // TODO(b/27227497): Need to read the power consumed per level from config - } - } - if (VDBG || rxIdleTimeMillis < 0 || stats.on_time < 0 || stats.tx_time < 0 - || stats.rx_time < 0 || stats.on_time_scan < 0) { - Log.d(TAG, " getWifiActivityEnergyInfo: " - + " on_time_millis=" + stats.on_time - + " tx_time_millis=" + stats.tx_time - + " tx_time_per_level_millis=" + Arrays.toString(txTimePerLevelMillis) - + " rx_time_millis=" + stats.rx_time - + " rxIdleTimeMillis=" + rxIdleTimeMillis - + " scan_time_millis=" + stats.on_time_scan); - } - - // Convert the LinkLayerStats into WifiActivityEnergyInfo - return new WifiActivityEnergyInfo( - mClock.getElapsedSinceBootMillis(), - WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, - stats.tx_time, - stats.rx_time, - stats.on_time_scan, - rxIdleTimeMillis); - } - - /** - * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()} - * - * @param packageName String name of the calling package - * @param featureId The feature in the package - * @return the list of configured networks - */ - @Override - public ParceledListSlice<WifiConfiguration> getConfiguredNetworks(String packageName, - String featureId) { - enforceAccessPermission(); - int callingUid = Binder.getCallingUid(); - // bypass shell: can get varioud pkg name - if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) { - long ident = Binder.clearCallingIdentity(); - try { - mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, - callingUid, null); - } catch (SecurityException e) { - Log.e(TAG, "Permission violation - getConfiguredNetworks not allowed for uid=" - + callingUid + ", packageName=" + packageName + ", reason=" + e); - return new ParceledListSlice<>(new ArrayList<>()); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - boolean isTargetSdkLessThanQOrPrivileged = isTargetSdkLessThanQOrPrivileged( - packageName, Binder.getCallingPid(), callingUid); - boolean isCarrierApp = mWifiInjector.makeTelephonyManager() - .checkCarrierPrivilegesForPackageAnyPhone(packageName) - == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; - if (!isTargetSdkLessThanQOrPrivileged && !isCarrierApp) { - mLog.info("getConfiguredNetworks not allowed for uid=%") - .c(callingUid).flush(); - return new ParceledListSlice<>(new ArrayList<>()); - } - if (mVerboseLoggingEnabled) { - mLog.info("getConfiguredNetworks uid=%").c(callingUid).flush(); - } - - int targetConfigUid = Process.INVALID_UID; // don't expose any MAC addresses - if (isPrivileged(getCallingPid(), callingUid) - || isDeviceOrProfileOwner(callingUid, packageName)) { - targetConfigUid = Process.WIFI_UID; // expose all MAC addresses - } else if (isCarrierApp) { - targetConfigUid = callingUid; // expose only those configs created by the Carrier App - } - int finalTargetConfigUid = targetConfigUid; - List<WifiConfiguration> configs = mWifiThreadRunner.call( - () -> mWifiConfigManager.getSavedNetworks(finalTargetConfigUid), - Collections.emptyList()); - if (isTargetSdkLessThanQOrPrivileged) { - return new ParceledListSlice<>(configs); - } - // Carrier app: should only get its own configs - List<WifiConfiguration> creatorConfigs = new ArrayList<>(); - for (WifiConfiguration config : configs) { - if (config.creatorUid == callingUid) { - creatorConfigs.add(config); - } - } - return new ParceledListSlice<>(creatorConfigs); - } - - /** - * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()} - * - * @param packageName String name of the calling package - * @param featureId The feature in the package - * @return the list of configured networks with real preSharedKey - */ - @Override - public ParceledListSlice<WifiConfiguration> getPrivilegedConfiguredNetworks( - String packageName, String featureId) { - enforceReadCredentialPermission(); - enforceAccessPermission(); - int callingUid = Binder.getCallingUid(); - long ident = Binder.clearCallingIdentity(); - try { - mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid, - null); - } catch (SecurityException e) { - Log.e(TAG, "Permission violation - getPrivilegedConfiguredNetworks not allowed for" - + " uid=" + callingUid + ", packageName=" + packageName + ", reason=" + e); - return null; - } finally { - Binder.restoreCallingIdentity(ident); - } - if (mVerboseLoggingEnabled) { - mLog.info("getPrivilegedConfiguredNetworks uid=%").c(callingUid).flush(); - } - List<WifiConfiguration> configs = mWifiThreadRunner.call( - () -> mWifiConfigManager.getConfiguredNetworksWithPasswords(), - Collections.emptyList()); - return new ParceledListSlice<>(configs); - } - - /** - * Return a map of all matching configurations keys with corresponding scanResults (or an empty - * map if none). - * - * @param scanResults The list of scan results - * @return Map that consists of FQDN (Fully Qualified Domain Name) and corresponding - * scanResults per network type({@link WifiManager#PASSPOINT_HOME_NETWORK} and {@link - * WifiManager#PASSPOINT_ROAMING_NETWORK}). - */ - @Override - public Map<String, Map<Integer, List<ScanResult>>> - getAllMatchingPasspointProfilesForScanResults(List<ScanResult> scanResults) { - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - if (mVerboseLoggingEnabled) { - mLog.info("getMatchingPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); - } - if (!ScanResultUtil.validateScanResultList(scanResults)) { - Log.e(TAG, "Attempt to retrieve passpoint with invalid scanResult List"); - return Collections.emptyMap(); - } - return mWifiThreadRunner.call( - () -> mPasspointManager.getAllMatchingPasspointProfilesForScanResults(scanResults), - Collections.emptyMap()); - } - - /** - * Returns list of OSU (Online Sign-Up) providers associated with the given list of ScanResult. - * - * @param scanResults a list of ScanResult that has Passpoint APs. - * @return Map that consists of {@link OsuProvider} and a matching list of {@link ScanResult}. - */ - @Override - public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( - List<ScanResult> scanResults) { - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - if (mVerboseLoggingEnabled) { - mLog.info("getMatchingOsuProviders uid=%").c(Binder.getCallingUid()).flush(); - } - - if (!ScanResultUtil.validateScanResultList(scanResults)) { - Log.e(TAG, "Attempt to retrieve OsuProviders with invalid scanResult List"); - return Collections.emptyMap(); - } - return mWifiThreadRunner.call( - () -> mPasspointManager.getMatchingOsuProviders(scanResults), Collections.emptyMap()); - } - - /** - * Returns the matching Passpoint configurations for given OSU(Online Sign-Up) providers. - * - * @param osuProviders a list of {@link OsuProvider} - * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}. - */ - @Override - public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( - List<OsuProvider> osuProviders) { - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - if (mVerboseLoggingEnabled) { - mLog.info("getMatchingPasspointConfigsForOsuProviders uid=%").c( - Binder.getCallingUid()).flush(); - } - if (osuProviders == null) { - Log.e(TAG, "Attempt to retrieve Passpoint configuration with null osuProviders"); - return new HashMap<>(); - } - return mWifiThreadRunner.call( - () -> mPasspointManager.getMatchingPasspointConfigsForOsuProviders(osuProviders), - Collections.emptyMap()); - } - - /** - * Returns the corresponding wifi configurations for given FQDN (Fully Qualified Domain Name) - * list. - * - * An empty list will be returned when no match is found. - * - * @param fqdnList a list of FQDN - * @return List of {@link WifiConfiguration} converted from {@link PasspointProvider} - */ - @Override - public List<WifiConfiguration> getWifiConfigsForPasspointProfiles(List<String> fqdnList) { - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - if (mVerboseLoggingEnabled) { - mLog.info("getWifiConfigsForPasspointProfiles uid=%").c( - Binder.getCallingUid()).flush(); - } - if (fqdnList == null) { - Log.e(TAG, "Attempt to retrieve WifiConfiguration with null fqdn List"); - return new ArrayList<>(); - } - return mWifiThreadRunner.call( - () -> mPasspointManager.getWifiConfigsForPasspointProfiles(fqdnList), - Collections.emptyList()); - } - - /** - * Returns a list of Wifi configurations for matched available WifiNetworkSuggestion - * corresponding to the given scan results. - * - * An empty list will be returned when no match is found or all matched suggestions is not - * available(not allow user manually connect, user not approved or open network). - * - * @param scanResults a list of {@link ScanResult}. - * @return a list of {@link WifiConfiguration} from matched {@link WifiNetworkSuggestion}. - */ - @Override - public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( - List<ScanResult> scanResults) { - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - if (mVerboseLoggingEnabled) { - mLog.info("getWifiConfigsForMatchedNetworkSuggestions uid=%").c( - Binder.getCallingUid()).flush(); - } - if (!ScanResultUtil.validateScanResultList(scanResults)) { - Log.e(TAG, "Attempt to retrieve WifiConfiguration with invalid scanResult List"); - return new ArrayList<>(); - } - return mWifiThreadRunner.call( - () -> mWifiNetworkSuggestionsManager - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults), - Collections.emptyList()); - } - - /** - * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)} - * @return the supplicant-assigned identifier for the new or updated - * network if the operation succeeds, or {@code -1} if it fails - */ - @Override - public int addOrUpdateNetwork(WifiConfiguration config, String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return -1; - } - int callingUid = Binder.getCallingUid(); - if (!isTargetSdkLessThanQOrPrivileged( - packageName, Binder.getCallingPid(), callingUid)) { - mLog.info("addOrUpdateNetwork not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return -1; - } - mLog.info("addOrUpdateNetwork uid=%").c(Binder.getCallingUid()).flush(); - - if (config == null) { - Log.e(TAG, "bad network configuration"); - return -1; - } - mWifiMetrics.incrementNumAddOrUpdateNetworkCalls(); - - // Previously, this API is overloaded for installing Passpoint profiles. Now - // that we have a dedicated API for doing it, redirect the call to the dedicated API. - if (config.isPasspoint()) { - PasspointConfiguration passpointConfig = - PasspointProvider.convertFromWifiConfig(config); - if (passpointConfig == null || passpointConfig.getCredential() == null) { - Log.e(TAG, "Missing credential for Passpoint profile"); - return -1; - } - - // Copy over certificates and keys. - X509Certificate[] x509Certificates = null; - if (config.enterpriseConfig.getCaCertificate() != null) { - x509Certificates = - new X509Certificate[]{config.enterpriseConfig.getCaCertificate()}; - } - passpointConfig.getCredential().setCaCertificates(x509Certificates); - passpointConfig.getCredential().setClientCertificateChain( - config.enterpriseConfig.getClientCertificateChain()); - passpointConfig.getCredential().setClientPrivateKey( - config.enterpriseConfig.getClientPrivateKey()); - if (!addOrUpdatePasspointConfiguration(passpointConfig, packageName)) { - Log.e(TAG, "Failed to add Passpoint profile"); - return -1; - } - // There is no network ID associated with a Passpoint profile. - return 0; - } - - Log.i("addOrUpdateNetwork", " uid = " + Binder.getCallingUid() - + " SSID " + config.SSID - + " nid=" + config.networkId); - return mWifiThreadRunner.call( - () -> mWifiConfigManager.addOrUpdateNetwork(config, callingUid, packageName) - .getNetworkId(), - WifiConfiguration.INVALID_NETWORK_ID); - } - - public static void verifyCert(X509Certificate caCert) - throws GeneralSecurityException, IOException { - CertificateFactory factory = CertificateFactory.getInstance("X.509"); - CertPathValidator validator = - CertPathValidator.getInstance(CertPathValidator.getDefaultType()); - CertPath path = factory.generateCertPath( - Arrays.asList(caCert)); - KeyStore ks = KeyStore.getInstance("AndroidCAStore"); - ks.load(null, null); - PKIXParameters params = new PKIXParameters(ks); - params.setRevocationEnabled(false); - validator.validate(path, params); - } - - /** - * See {@link android.net.wifi.WifiManager#removeNetwork(int)} - * @param netId the integer that identifies the network configuration - * to the supplicant - * @return {@code true} if the operation succeeded - */ - @Override - public boolean removeNetwork(int netId, String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - if (!isTargetSdkLessThanQOrPrivileged( - packageName, Binder.getCallingPid(), Binder.getCallingUid())) { - mLog.info("removeNetwork not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return false; - } - int callingUid = Binder.getCallingUid(); - mLog.info("removeNetwork uid=%").c(callingUid).flush(); - return mWifiThreadRunner.call( - () -> mWifiConfigManager.removeNetwork(netId, callingUid, packageName), false); - } - - /** - * Trigger a connect request and wait for the callback to return status. - * This preserves the legacy connect API behavior, i.e. {@link WifiManager#enableNetwork( - * int, true)} - * @return - */ - private boolean triggerConnectAndReturnStatus(int netId, int callingUid) { - final CountDownLatch countDownLatch = new CountDownLatch(1); - final MutableBoolean success = new MutableBoolean(false); - IActionListener.Stub connectListener = new IActionListener.Stub() { - @Override - public void onSuccess() { - success.value = true; - countDownLatch.countDown(); - } - @Override - public void onFailure(int reason) { - success.value = false; - countDownLatch.countDown(); - } - }; - mClientModeImpl.connect(null, netId, new Binder(), connectListener, - connectListener.hashCode(), callingUid); - // now wait for response. - try { - countDownLatch.await(RUN_WITH_SCISSORS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Log.e(TAG, "Failed to retrieve connect status"); - } - return success.value; - } - - /** - * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)} - * @param netId the integer that identifies the network configuration - * to the supplicant - * @param disableOthers if true, disable all other networks. - * @return {@code true} if the operation succeeded - */ - @Override - public boolean enableNetwork(int netId, boolean disableOthers, String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - if (!isTargetSdkLessThanQOrPrivileged( - packageName, Binder.getCallingPid(), Binder.getCallingUid())) { - mLog.info("enableNetwork not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return false; - } - int callingUid = Binder.getCallingUid(); - // TODO b/33807876 Log netId - mLog.info("enableNetwork uid=% disableOthers=%") - .c(callingUid) - .c(disableOthers).flush(); - - mWifiMetrics.incrementNumEnableNetworkCalls(); - if (disableOthers) { - return triggerConnectAndReturnStatus(netId, callingUid); - } else { - return mWifiThreadRunner.call( - () -> mWifiConfigManager.enableNetwork(netId, false, callingUid, packageName), - false); - } - } - - /** - * See {@link android.net.wifi.WifiManager#disableNetwork(int)} - * @param netId the integer that identifies the network configuration - * to the supplicant - * @return {@code true} if the operation succeeded - */ - @Override - public boolean disableNetwork(int netId, String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - if (!isTargetSdkLessThanQOrPrivileged( - packageName, Binder.getCallingPid(), Binder.getCallingUid())) { - mLog.info("disableNetwork not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return false; - } - int callingUid = Binder.getCallingUid(); - mLog.info("disableNetwork uid=%").c(callingUid).flush(); - return mWifiThreadRunner.call( - () -> mWifiConfigManager.disableNetwork(netId, callingUid, packageName), false); - } - - /** - * See {@link android.net.wifi.WifiManager#allowAutojoinGlobal(boolean)} - * @param choice the OEM's choice to allow auto-join - */ - @Override - public void allowAutojoinGlobal(boolean choice) { - enforceNetworkSettingsPermission(); - - int callingUid = Binder.getCallingUid(); - mLog.info("allowAutojoin=% uid=%").c(choice).c(callingUid).flush(); - - mWifiThreadRunner.post(() -> mClientModeImpl.allowAutoJoinGlobal(choice)); - } - - /** - * See {@link android.net.wifi.WifiManager#allowAutojoin(int, boolean)} - * @param netId the integer that identifies the network configuration - * @param choice the user's choice to allow auto-join - */ - @Override - public void allowAutojoin(int netId, boolean choice) { - enforceNetworkSettingsPermission(); - - int callingUid = Binder.getCallingUid(); - mLog.info("allowAutojoin=% uid=%").c(choice).c(callingUid).flush(); - mWifiThreadRunner.post(() -> { - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); - if (config == null) { - return; - } - if (config.fromWifiNetworkSpecifier) { - Log.e(TAG, "Auto-join configuration is not permitted for NetworkSpecifier " - + "connections: " + config); - return; - } - if (config.isPasspoint() && !config.isEphemeral()) { - Log.e(TAG, - "Auto-join configuration for a non-ephemeral Passpoint network should be " - + "configured using FQDN: " - + config); - return; - } - // If the network is a suggestion, store the auto-join configure to the - // WifiNetWorkSuggestionsManager. - if (config.fromWifiNetworkSuggestion) { - if (!mWifiNetworkSuggestionsManager - .allowNetworkSuggestionAutojoin(config, choice)) { - return; - } - } - // even for Suggestion, modify the current ephemeral configuration so that - // existing configuration auto-connection is updated correctly - if (choice != config.allowAutojoin) { - mWifiConfigManager.allowAutojoin(netId, choice); - // do not log this metrics for passpoint networks again here since it's already - // logged in PasspointManager. - if (!config.isPasspoint()) { - mWifiMetrics.logUserActionEvent(choice - ? UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON - : UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF, netId); - } - } - }); - } - - /** - * See {@link android.net.wifi.WifiManager#allowAutojoinPasspoint(String, boolean)} - * @param fqdn the FQDN that identifies the passpoint configuration - * @param enableAutojoin true to enable auto-join, false to disable - */ - @Override - public void allowAutojoinPasspoint(String fqdn, boolean enableAutojoin) { - enforceNetworkSettingsPermission(); - if (fqdn == null) { - throw new IllegalArgumentException("FQDN cannot be null"); - } - - int callingUid = Binder.getCallingUid(); - mLog.info("allowAutojoinPasspoint=% uid=%").c(enableAutojoin).c(callingUid).flush(); - mWifiThreadRunner.post( - () -> mPasspointManager.enableAutojoin(null, fqdn, enableAutojoin)); - } - - /** - * See {@link android.net.wifi.WifiManager - * #setMacRandomizationSettingPasspointEnabled(String, boolean)} - * @param fqdn the FQDN that identifies the passpoint configuration - * @param enable true to enable mac randomization, false to disable - */ - @Override - public void setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable) { - enforceNetworkSettingsPermission(); - if (fqdn == null) { - throw new IllegalArgumentException("FQDN cannot be null"); - } - - int callingUid = Binder.getCallingUid(); - mLog.info("setMacRandomizationSettingPasspointEnabled=% uid=%") - .c(enable).c(callingUid).flush(); - mWifiThreadRunner.post( - () -> mPasspointManager.enableMacRandomization(fqdn, enable)); - } - - /** - * See {@link android.net.wifi.WifiManager#setPasspointMeteredOverride(String, boolean)} - * @param fqdn the FQDN that identifies the passpoint configuration - * @param meteredOverride One of the values in {@link MeteredOverride} - */ - @Override - public void setPasspointMeteredOverride(String fqdn, int meteredOverride) { - enforceNetworkSettingsPermission(); - if (fqdn == null) { - throw new IllegalArgumentException("FQDN cannot be null"); - } - - int callingUid = Binder.getCallingUid(); - mLog.info("setPasspointMeteredOverride=% uid=%") - .c(meteredOverride).c(callingUid).flush(); - mWifiThreadRunner.post( - () -> mPasspointManager.setMeteredOverride(fqdn, meteredOverride)); - } - - /** - * See {@link android.net.wifi.WifiManager#getConnectionInfo()} - * @return the Wi-Fi information, contained in {@link WifiInfo}. - */ - @Override - public WifiInfo getConnectionInfo(String callingPackage, String callingFeatureId) { - enforceAccessPermission(); - int uid = Binder.getCallingUid(); - if (mVerboseLoggingEnabled) { - mLog.info("getConnectionInfo uid=%").c(uid).flush(); - } - long ident = Binder.clearCallingIdentity(); - try { - WifiInfo result = mClientModeImpl.syncRequestConnectionInfo(); - boolean hideDefaultMacAddress = true; - boolean hideBssidSsidNetworkIdAndFqdn = true; - - try { - if (mWifiInjector.getWifiPermissionsWrapper().getLocalMacAddressPermission(uid) - == PERMISSION_GRANTED) { - hideDefaultMacAddress = false; - } - mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, - uid, null); - hideBssidSsidNetworkIdAndFqdn = false; - } catch (SecurityException ignored) { - } - if (hideDefaultMacAddress) { - result.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); - } - if (hideBssidSsidNetworkIdAndFqdn) { - result.setBSSID(WifiInfo.DEFAULT_MAC_ADDRESS); - result.setSSID(WifiSsid.createFromHex(null)); - result.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); - result.setFQDN(null); - result.setProviderFriendlyName(null); - result.setPasspointUniqueId(null); - } - - if (mVerboseLoggingEnabled - && (hideBssidSsidNetworkIdAndFqdn || hideDefaultMacAddress)) { - mLog.v("getConnectionInfo: hideBssidSsidAndNetworkId=" - + hideBssidSsidNetworkIdAndFqdn - + ", hideDefaultMacAddress=" - + hideDefaultMacAddress); - } - return result; - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - /** - * Return the results of the most recent access point scan, in the form of - * a list of {@link ScanResult} objects. - * @return the list of results - */ - @Override - public List<ScanResult> getScanResults(String callingPackage, String callingFeatureId) { - enforceAccessPermission(); - int uid = Binder.getCallingUid(); - long ident = Binder.clearCallingIdentity(); - if (mVerboseLoggingEnabled) { - mLog.info("getScanResults uid=%").c(uid).flush(); - } - try { - mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, - uid, null); - List<ScanResult> scanResults = mWifiThreadRunner.call( - mScanRequestProxy::getScanResults, Collections.emptyList()); - return scanResults; - } catch (SecurityException e) { - Log.e(TAG, "Permission violation - getScanResults not allowed for uid=" - + uid + ", packageName=" + callingPackage + ", reason=" + e); - return new ArrayList<>(); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - /** - * Return the filtered ScanResults which may be authenticated by the suggested network - * configurations. - * @return The map of {@link WifiNetworkSuggestion} and the list of {@link ScanResult} which - * may be authenticated by the corresponding network configuration. - */ - @Override - @NonNull - public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( - @NonNull List<WifiNetworkSuggestion> networkSuggestions, - @Nullable List<ScanResult> scanResults, - String callingPackage, String callingFeatureId) { - enforceAccessPermission(); - int uid = Binder.getCallingUid(); - long ident = Binder.clearCallingIdentity(); - try { - mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, - uid, null); - - return mWifiThreadRunner.call( - () -> { - if (!ScanResultUtil.validateScanResultList(scanResults)) { - return mWifiNetworkSuggestionsManager.getMatchingScanResults( - networkSuggestions, mScanRequestProxy.getScanResults()); - } else { - return mWifiNetworkSuggestionsManager.getMatchingScanResults( - networkSuggestions, scanResults); - } - }, - Collections.emptyMap()); - } catch (SecurityException e) { - Log.e(TAG, "Permission violation - getMatchingScanResults not allowed for uid=" - + uid + ", packageName=" + callingPackage + ", reason + e"); - } finally { - Binder.restoreCallingIdentity(ident); - } - - return Collections.emptyMap(); - } - - /** - * Add or update a Passpoint configuration. - * - * @param config The Passpoint configuration to be added - * @return true on success or false on failure - */ - @Override - public boolean addOrUpdatePasspointConfiguration( - PasspointConfiguration config, String packageName) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return false; - } - int callingUid = Binder.getCallingUid(); - if (!isTargetSdkLessThanROrPrivileged( - packageName, Binder.getCallingPid(), callingUid)) { - mLog.info("addOrUpdatePasspointConfiguration not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return false; - } - mLog.info("addorUpdatePasspointConfiguration uid=%").c(callingUid).flush(); - return mWifiThreadRunner.call( - () -> mPasspointManager.addOrUpdateProvider(config, callingUid, packageName, - false, true), false); - } - - /** - * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). - * - * @param fqdn The FQDN of the Passpoint configuration to be removed - * @return true on success or false on failure - */ - @Override - public boolean removePasspointConfiguration(String fqdn, String packageName) { - return removePasspointConfigurationInternal(fqdn, null); - } - - /** - * Remove a Passpoint profile based on either FQDN (multiple matching profiles) or a unique - * identifier (one matching profile). - * - * @param fqdn The FQDN of the Passpoint configuration to be removed - * @param uniqueId The unique identifier of the Passpoint configuration to be removed - * @return true on success or false on failure - */ - private boolean removePasspointConfigurationInternal(String fqdn, String uniqueId) { - final int uid = Binder.getCallingUid(); - boolean privileged = false; - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) - || mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)) { - privileged = true; - } - mLog.info("removePasspointConfigurationInternal uid=%").c(Binder.getCallingUid()).flush(); - final boolean privilegedFinal = privileged; - return mWifiThreadRunner.call( - () -> mPasspointManager.removeProvider(uid, privilegedFinal, uniqueId, fqdn), - false); - } - - /** - * Return the list of the installed Passpoint configurations. - * - * An empty list will be returned when no configuration is installed. - * @param packageName String name of the calling package - * @return A list of {@link PasspointConfiguration}. - */ - @Override - public List<PasspointConfiguration> getPasspointConfigurations(String packageName) { - final int uid = Binder.getCallingUid(); - boolean privileged = false; - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) - || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) { - privileged = true; - } - if (mVerboseLoggingEnabled) { - mLog.info("getPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); - } - final boolean privilegedFinal = privileged; - return mWifiThreadRunner.call( - () -> mPasspointManager.getProviderConfigs(uid, privilegedFinal), - Collections.emptyList()); - } - - /** - * Query for a Hotspot 2.0 release 2 OSU icon - * @param bssid The BSSID of the AP - * @param fileName Icon file name - */ - @Override - public void queryPasspointIcon(long bssid, String fileName) { - enforceAccessPermission(); - mLog.info("queryPasspointIcon uid=%").c(Binder.getCallingUid()).flush(); - mClientModeImpl.syncQueryPasspointIcon(mClientModeImplChannel, bssid, fileName); - } - - /** - * Match the currently associated network against the SP matching the given FQDN - * @param fqdn FQDN of the SP - * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] - */ - @Override - public int matchProviderWithCurrentNetwork(String fqdn) { - mLog.info("matchProviderWithCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); - return 0; - } - - /** - * Deauthenticate and set the re-authentication hold off time for the current network - * @param holdoff hold off time in milliseconds - * @param ess set if the hold off pertains to an ESS rather than a BSS - */ - @Override - public void deauthenticateNetwork(long holdoff, boolean ess) { - mLog.info("deauthenticateNetwork uid=%").c(Binder.getCallingUid()).flush(); - mClientModeImpl.deauthenticateNetwork(mClientModeImplChannel, holdoff, ess); - } - - /** - * Get the country code - * @return Get the best choice country code for wifi, regardless of if it was set or - * not. - * Returns null when there is no country code available. - */ - @Override - public String getCountryCode() { - enforceNetworkSettingsPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("getCountryCode uid=%").c(Binder.getCallingUid()).flush(); - } - return mCountryCode.getCountryCode(); - } - - @Override - public boolean is5GHzBandSupported() { - if (mVerboseLoggingEnabled) { - mLog.info("is5GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); - } - - return is5GhzBandSupportedInternal(); - } - - private boolean is5GhzBandSupportedInternal() { - return mWifiThreadRunner.call( - () -> mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ), false); - } - - @Override - public boolean is6GHzBandSupported() { - if (mVerboseLoggingEnabled) { - mLog.info("is6GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); - } - - return is6GhzBandSupportedInternal(); - } - - private boolean is6GhzBandSupportedInternal() { - return mWifiThreadRunner.call( - () -> mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ), false); - } - - @Override - public boolean isWifiStandardSupported(@WifiStandard int standard) { - return mWifiThreadRunner.call( - () -> mClientModeImpl.isWifiStandardSupported(standard), false); - } - - /** - * Return the DHCP-assigned addresses from the last successful DHCP request, - * if any. - * @return the DHCP information - * @deprecated - */ - @Override - @Deprecated - public DhcpInfo getDhcpInfo() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("getDhcpInfo uid=%").c(Binder.getCallingUid()).flush(); - } - DhcpResultsParcelable dhcpResults = mClientModeImpl.syncGetDhcpResultsParcelable(); - - DhcpInfo info = new DhcpInfo(); - - if (dhcpResults.baseConfiguration != null) { - if (dhcpResults.baseConfiguration.getIpAddress() != null - && dhcpResults.baseConfiguration.getIpAddress().getAddress() - instanceof Inet4Address) { - info.ipAddress = Inet4AddressUtils.inet4AddressToIntHTL( - (Inet4Address) dhcpResults.baseConfiguration.getIpAddress().getAddress()); - } - - if (dhcpResults.baseConfiguration.getGateway() != null) { - info.gateway = Inet4AddressUtils.inet4AddressToIntHTL( - (Inet4Address) dhcpResults.baseConfiguration.getGateway()); - } - - int dnsFound = 0; - for (InetAddress dns : dhcpResults.baseConfiguration.getDnsServers()) { - if (dns instanceof Inet4Address) { - if (dnsFound == 0) { - info.dns1 = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) dns); - } else { - info.dns2 = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) dns); - } - if (++dnsFound > 1) break; - } - } - } - String serverAddress = dhcpResults.serverAddress; - if (serverAddress != null) { - InetAddress serverInetAddress = InetAddresses.parseNumericAddress(serverAddress); - info.serverAddress = - Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) serverInetAddress); - } - info.leaseDuration = dhcpResults.leaseDuration; - - return info; - } - - /** - * enable TDLS for the local NIC to remote NIC - * The APPs don't know the remote MAC address to identify NIC though, - * so we need to do additional work to find it from remote IP address - */ - - private static class TdlsTaskParams { - String mRemoteIpAddress; - boolean mEnable; - } - - private class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { - @Override - protected Integer doInBackground(TdlsTaskParams... params) { - - // Retrieve parameters for the call - TdlsTaskParams param = params[0]; - String remoteIpAddress = param.mRemoteIpAddress.trim(); - boolean enable = param.mEnable; - - // Get MAC address of Remote IP - String macAddress = null; - - try (BufferedReader reader = new BufferedReader(new FileReader("/proc/net/arp"))) { - // Skip over the line bearing column titles - reader.readLine(); - - String line; - while ((line = reader.readLine()) != null) { - String[] tokens = line.split("[ ]+"); - if (tokens.length < 6) { - continue; - } - - // ARP column format is - // Address HWType HWAddress Flags Mask IFace - String ip = tokens[0]; - String mac = tokens[3]; - - if (remoteIpAddress.equals(ip)) { - macAddress = mac; - break; - } - } - - if (macAddress == null) { - Log.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " - + "/proc/net/arp"); - } else { - enableTdlsWithMacAddress(macAddress, enable); - } - - } catch (FileNotFoundException e) { - Log.e(TAG, "Could not open /proc/net/arp to lookup mac address"); - } catch (IOException e) { - Log.e(TAG, "Could not read /proc/net/arp to lookup mac address"); - } - return 0; - } - } - - @Override - public void enableTdls(String remoteAddress, boolean enable) { - if (remoteAddress == null) { - throw new IllegalArgumentException("remoteAddress cannot be null"); - } - mLog.info("enableTdls uid=% enable=%").c(Binder.getCallingUid()).c(enable).flush(); - TdlsTaskParams params = new TdlsTaskParams(); - params.mRemoteIpAddress = remoteAddress; - params.mEnable = enable; - new TdlsTask().execute(params); - } - - - @Override - public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { - mLog.info("enableTdlsWithMacAddress uid=% enable=%") - .c(Binder.getCallingUid()) - .c(enable) - .flush(); - if (remoteMacAddress == null) { - throw new IllegalArgumentException("remoteMacAddress cannot be null"); - } - - mClientModeImpl.enableTdls(remoteMacAddress, enable); - } - - /** - * Temporarily disable a network, should be trigger when user disconnect a network - */ - @Override - public void disableEphemeralNetwork(String network, String packageName) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, - "WifiService"); - if (!isPrivileged(Binder.getCallingPid(), Binder.getCallingUid())) { - mLog.info("disableEphemeralNetwork not allowed for uid=%") - .c(Binder.getCallingUid()).flush(); - return; - } - mLog.info("disableEphemeralNetwork uid=%").c(Binder.getCallingUid()).flush(); - mWifiThreadRunner.post(() -> mWifiConfigManager.userTemporarilyDisabledNetwork(network, - Binder.getCallingUid())); - } - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(Intent.ACTION_USER_REMOVED)) { - UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER); - if (userHandle == null) { - Log.e(TAG, "User removed broadcast received with no user handle"); - return; - } - mWifiThreadRunner.post(() -> - mWifiConfigManager.removeNetworksForUser(userHandle.getIdentifier())); - } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, - BluetoothAdapter.STATE_DISCONNECTED); - mClientModeImpl.sendBluetoothAdapterConnectionStateChange(state); - } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.STATE_OFF); - mClientModeImpl.sendBluetoothAdapterStateChange(state); - } else if (action.equals(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { - boolean emergencyMode = - intent.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false); - mActiveModeWarden.emergencyCallbackModeChanged(emergencyMode); - } else if (action.equals(TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED)) { - boolean inCall = - intent.getBooleanExtra( - TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, false); - mActiveModeWarden.emergencyCallStateChanged(inCall); - } else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { - handleIdleModeChanged(); - } else if (action.equals(Intent.ACTION_SHUTDOWN)) { - handleShutDown(); - } - } - }; - - private void registerForBroadcasts() { - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); - intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); - intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); - intentFilter.addDataScheme("package"); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); - Uri uri = intent.getData(); - if (uid == -1 || uri == null) { - Log.e(TAG, "Uid or Uri is missing for action:" + intent.getAction()); - return; - } - String pkgName = uri.getSchemeSpecificPart(); - PackageManager pm = context.getPackageManager(); - PackageInfo packageInfo = null; - try { - packageInfo = pm.getPackageInfo(pkgName, 0); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Couldn't get PackageInfo for package:" + pkgName); - } - // If package is not removed or disabled, just ignore. - if (packageInfo != null - && packageInfo.applicationInfo != null - && packageInfo.applicationInfo.enabled) { - return; - } - Log.d(TAG, "Remove settings for package:" + pkgName); - // Call the method in the main Wifi thread. - mWifiThreadRunner.post(() -> { - ApplicationInfo ai = new ApplicationInfo(); - ai.packageName = pkgName; - ai.uid = uid; - mWifiConfigManager.removeNetworksForApp(ai); - mScanRequestProxy.clearScanRequestTimestampsForApp(pkgName, uid); - - // Remove all suggestions from the package. - mWifiNetworkSuggestionsManager.removeApp(pkgName); - mClientModeImpl.removeNetworkRequestUserApprovedAccessPointsForApp(pkgName); - - // Remove all Passpoint profiles from package. - mWifiInjector.getPasspointManager().removePasspointProviderWithPackage( - pkgName); - }); - } - }, intentFilter); - } - - private void registerForCarrierConfigChange() { - IntentFilter filter = new IntentFilter(); - filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final int subId = SubscriptionManager.getActiveDataSubscriptionId(); - Log.d(TAG, "ACTION_CARRIER_CONFIG_CHANGED, active subId: " + subId); - - mTetheredSoftApTracker.updateSoftApCapability(subId); - mActiveModeWarden.updateSoftApCapability( - mTetheredSoftApTracker.getSoftApCapability()); - } - }, filter); - - WifiPhoneStateListener phoneStateListener = new WifiPhoneStateListener( - mWifiInjector.getWifiHandlerThread().getLooper()); - - mContext.getSystemService(TelephonyManager.class).listen( - phoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); - } - - @Override - public int handleShellCommand(@NonNull ParcelFileDescriptor in, - @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, - @NonNull String[] args) { - return new WifiShellCommand(mWifiInjector, this, mContext).exec( - this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), - args); - } - - private void updateWifiMetrics() { - mWifiThreadRunner.run(() -> { - mWifiMetrics.updateSavedNetworks( - mWifiConfigManager.getSavedNetworks(Process.WIFI_UID)); - mPasspointManager.updateMetrics(); - }); - boolean isEnhancedMacRandEnabled = mFrameworkFacade.getIntegerSetting(mContext, - WifiConfigManager.ENHANCED_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG, 0) == 1 - ? true : false; - mWifiMetrics.setEnhancedMacRandomizationForceEnabled(isEnhancedMacRandEnabled); - mWifiMetrics.setIsScanningAlwaysEnabled(mSettingsStore.isScanAlwaysAvailable()); - mWifiMetrics.setVerboseLoggingEnabled(mVerboseLoggingEnabled); - mWifiMetrics.setWifiWakeEnabled(mWifiInjector.getWakeupController().isEnabled()); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump WifiService from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - if (args != null && args.length > 0 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0])) { - // WifiMetrics proto bytes were requested. Dump only these. - updateWifiMetrics(); - mWifiMetrics.dump(fd, pw, args); - } else if (args != null && args.length > 0 && IpClientUtil.DUMP_ARG.equals(args[0])) { - // IpClient dump was requested. Pass it along and take no further action. - String[] ipClientArgs = new String[args.length - 1]; - System.arraycopy(args, 1, ipClientArgs, 0, ipClientArgs.length); - mClientModeImpl.dumpIpClient(fd, pw, ipClientArgs); - } else if (args != null && args.length > 0 && WifiScoreReport.DUMP_ARG.equals(args[0])) { - WifiScoreReport wifiScoreReport = mClientModeImpl.getWifiScoreReport(); - if (wifiScoreReport != null) wifiScoreReport.dump(fd, pw, args); - } else if (args != null && args.length > 0 && WifiScoreCard.DUMP_ARG.equals(args[0])) { - WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard(); - String networkListBase64 = mWifiThreadRunner.call(() -> - wifiScoreCard.getNetworkListBase64(true), ""); - pw.println(networkListBase64); - } else { - // Polls link layer stats and RSSI. This allows the stats to show up in - // WifiScoreReport's dump() output when taking a bug report even if the screen is off. - mClientModeImpl.updateLinkLayerStatsRssiAndScoreReport(); - pw.println("Wi-Fi is " + mClientModeImpl.syncGetWifiStateByName()); - pw.println("Verbose logging is " + (mVerboseLoggingEnabled ? "on" : "off")); - pw.println("Stay-awake conditions: " + - mFacade.getIntegerSetting(mContext, - Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); - pw.println("mInIdleMode " + mInIdleMode); - pw.println("mScanPending " + mScanPending); - mSettingsStore.dump(fd, pw, args); - mWifiTrafficPoller.dump(fd, pw, args); - pw.println(); - pw.println("Locks held:"); - mWifiLockManager.dump(pw); - pw.println(); - mWifiMulticastLockManager.dump(pw); - pw.println(); - mActiveModeWarden.dump(fd, pw, args); - pw.println(); - mClientModeImpl.dump(fd, pw, args); - pw.println(); - WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard(); - String networkListBase64 = mWifiThreadRunner.call(() -> - wifiScoreCard.getNetworkListBase64(true), ""); - pw.println("WifiScoreCard:"); - pw.println(networkListBase64); - - updateWifiMetrics(); - mWifiMetrics.dump(fd, pw, args); - - pw.println(); - mWifiThreadRunner.run(() -> mWifiNetworkSuggestionsManager.dump(fd, pw, args)); - pw.println(); - mWifiBackupRestore.dump(fd, pw, args); - pw.println(); - pw.println("ScoringParams: " + mWifiInjector.getScoringParams()); - pw.println(); - pw.println("WifiScoreReport:"); - WifiScoreReport wifiScoreReport = mClientModeImpl.getWifiScoreReport(); - wifiScoreReport.dump(fd, pw, args); - pw.println(); - SarManager sarManager = mWifiInjector.getSarManager(); - sarManager.dump(fd, pw, args); - pw.println(); - mWifiThreadRunner.run(() -> { - mWifiInjector.getWifiNetworkScoreCache().dumpWithLatestScanResults( - fd, pw, args, mScanRequestProxy.getScanResults()); - mWifiInjector.getSettingsConfigStore().dump(fd, pw, args); - }); - pw.println(); - } - } - - @Override - public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) { - mLog.info("acquireWifiLock uid=% lockMode=%") - .c(Binder.getCallingUid()) - .c(lockMode).flush(); - - // Check on permission to make this call - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); - - // If no UID is provided in worksource, use the calling UID - WorkSource updatedWs = (ws == null || ws.isEmpty()) - ? new WorkSource(Binder.getCallingUid()) : ws; - - if (!WifiLockManager.isValidLockMode(lockMode)) { - throw new IllegalArgumentException("lockMode =" + lockMode); - } - - return mWifiThreadRunner.call(() -> - mWifiLockManager.acquireWifiLock(lockMode, tag, binder, updatedWs), false); - } - - @Override - public void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { - mLog.info("updateWifiLockWorkSource uid=%").c(Binder.getCallingUid()).flush(); - - // Check on permission to make this call - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.UPDATE_DEVICE_STATS, null); - - // If no UID is provided in worksource, use the calling UID - WorkSource updatedWs = (ws == null || ws.isEmpty()) - ? new WorkSource(Binder.getCallingUid()) : ws; - - mWifiThreadRunner.run(() -> - mWifiLockManager.updateWifiLockWorkSource(binder, updatedWs)); - } - - @Override - public boolean releaseWifiLock(IBinder binder) { - mLog.info("releaseWifiLock uid=%").c(Binder.getCallingUid()).flush(); - - // Check on permission to make this call - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); - - return mWifiThreadRunner.call(() -> - mWifiLockManager.releaseWifiLock(binder), false); - } - - @Override - public void initializeMulticastFiltering() { - enforceMulticastChangePermission(); - mLog.info("initializeMulticastFiltering uid=%").c(Binder.getCallingUid()).flush(); - mWifiMulticastLockManager.initializeFiltering(); - } - - @Override - public void acquireMulticastLock(IBinder binder, String tag) { - enforceMulticastChangePermission(); - mLog.info("acquireMulticastLock uid=%").c(Binder.getCallingUid()).flush(); - mWifiMulticastLockManager.acquireLock(binder, tag); - } - - @Override - public void releaseMulticastLock(String tag) { - enforceMulticastChangePermission(); - mLog.info("releaseMulticastLock uid=%").c(Binder.getCallingUid()).flush(); - mWifiMulticastLockManager.releaseLock(tag); - } - - @Override - public boolean isMulticastEnabled() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("isMulticastEnabled uid=%").c(Binder.getCallingUid()).flush(); - } - return mWifiMulticastLockManager.isMulticastEnabled(); - } - - @Override - public void enableVerboseLogging(int verbose) { - enforceAccessPermission(); - enforceNetworkSettingsPermission(); - mLog.info("enableVerboseLogging uid=% verbose=%") - .c(Binder.getCallingUid()) - .c(verbose).flush(); - mWifiInjector.getSettingsConfigStore().put(WIFI_VERBOSE_LOGGING_ENABLED, verbose > 0); - enableVerboseLoggingInternal(verbose); - } - - private void enableVerboseLoggingInternal(int verbose) { - mVerboseLoggingEnabled = verbose > 0; - mClientModeImpl.enableVerboseLogging(verbose); - mWifiLockManager.enableVerboseLogging(verbose); - mWifiMulticastLockManager.enableVerboseLogging(verbose); - mWifiInjector.enableVerboseLogging(verbose); - } - - @Override - public int getVerboseLoggingLevel() { - if (mVerboseLoggingEnabled) { - mLog.info("getVerboseLoggingLevel uid=%").c(Binder.getCallingUid()).flush(); - } - return mWifiInjector.getSettingsConfigStore().get(WIFI_VERBOSE_LOGGING_ENABLED) ? 1 : 0; - } - - @Override - public void factoryReset(String packageName) { - enforceNetworkSettingsPermission(); - if (enforceChangePermission(packageName) != MODE_ALLOWED) { - return; - } - mLog.info("factoryReset uid=%").c(Binder.getCallingUid()).flush(); - if (mUserManager.hasUserRestrictionForUser( - UserManager.DISALLOW_NETWORK_RESET, - UserHandle.getUserHandleForUid(Binder.getCallingUid()))) { - return; - } - if (!mUserManager.hasUserRestrictionForUser( - UserManager.DISALLOW_CONFIG_TETHERING, - UserHandle.getUserHandleForUid(Binder.getCallingUid()))) { - // Turn mobile hotspot off - stopSoftApInternal(WifiManager.IFACE_IP_MODE_UNSPECIFIED); - } - - if (mUserManager.hasUserRestrictionForUser( - UserManager.DISALLOW_CONFIG_WIFI, - UserHandle.getUserHandleForUid(Binder.getCallingUid()))) { - return; - } - // Delete all Wifi SSIDs - List<WifiConfiguration> networks = mWifiThreadRunner.call( - () -> mWifiConfigManager.getSavedNetworks(Process.WIFI_UID), - Collections.emptyList()); - for (WifiConfiguration network : networks) { - removeNetwork(network.networkId, packageName); - } - // Delete all Passpoint configurations - List<PasspointConfiguration> configs = mWifiThreadRunner.call( - () -> mPasspointManager.getProviderConfigs(Process.WIFI_UID /* ignored */, true), - Collections.emptyList()); - for (PasspointConfiguration config : configs) { - removePasspointConfigurationInternal(null, config.getUniqueId()); - } - mWifiThreadRunner.post(() -> { - mPasspointManager.clearAnqpRequestsAndFlushCache(); - mWifiConfigManager.clearUserTemporarilyDisabledList(); - mWifiConfigManager.removeAllEphemeralOrPasspointConfiguredNetworks(); - mClientModeImpl.clearNetworkRequestUserApprovedAccessPoints(); - mWifiNetworkSuggestionsManager.clear(); - mWifiInjector.getWifiScoreCard().clear(); - mWifiInjector.getWifiHealthMonitor().clear(); - notifyFactoryReset(); - }); - } - - /** - * Notify the Factory Reset Event to application who may installed wifi configurations. - */ - private void notifyFactoryReset() { - Intent intent = new Intent(WifiManager.ACTION_NETWORK_SETTINGS_RESET); - - // Retrieve list of broadcast receivers for this broadcast & send them directed broadcasts - // to wake them up (if they're in background). - List<ResolveInfo> resolveInfos = - mContext.getPackageManager().queryBroadcastReceiversAsUser( - intent, 0, - UserHandle.of(mWifiInjector.getWifiPermissionsWrapper().getCurrentUser())); - if (resolveInfos == null || resolveInfos.isEmpty()) return; // No need to send broadcast. - - for (ResolveInfo resolveInfo : resolveInfos) { - Intent intentToSend = new Intent(intent); - intentToSend.setComponent(new ComponentName( - resolveInfo.activityInfo.applicationInfo.packageName, - resolveInfo.activityInfo.name)); - mContext.sendBroadcastAsUser(intentToSend, UserHandle.ALL, - android.Manifest.permission.NETWORK_CARRIER_PROVISIONING); - } - } - - @Override - public Network getCurrentNetwork() { - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - if (mVerboseLoggingEnabled) { - mLog.info("getCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); - } - return mClientModeImpl.syncGetCurrentNetwork(mClientModeImplChannel); - } - - public static String toHexString(String s) { - if (s == null) { - return "null"; - } - StringBuilder sb = new StringBuilder(); - sb.append('\'').append(s).append('\''); - for (int n = 0; n < s.length(); n++) { - sb.append(String.format(" %02x", s.charAt(n) & 0xffff)); - } - return sb.toString(); - } - - /** - * Retrieve the data to be backed to save the current state. - * - * @return Raw byte stream of the data to be backed up. - */ - @Override - public byte[] retrieveBackupData() { - enforceNetworkSettingsPermission(); - mLog.info("retrieveBackupData uid=%").c(Binder.getCallingUid()).flush(); - if (mClientModeImplChannel == null) { - Log.e(TAG, "mClientModeImplChannel is not initialized"); - return null; - } - - Log.d(TAG, "Retrieving backup data"); - List<WifiConfiguration> wifiConfigurations = mWifiThreadRunner.call( - () -> mWifiConfigManager.getConfiguredNetworksWithPasswords(), null); - byte[] backupData = - mWifiBackupRestore.retrieveBackupDataFromConfigurations(wifiConfigurations); - Log.d(TAG, "Retrieved backup data"); - return backupData; - } - - /** - * Helper method to restore networks retrieved from backup data. - * - * @param configurations list of WifiConfiguration objects parsed from the backup data. - */ - private void restoreNetworks(List<WifiConfiguration> configurations) { - if (configurations == null) { - Log.e(TAG, "Backup data parse failed"); - return; - } - int callingUid = Binder.getCallingUid(); - mWifiThreadRunner.run( - () -> { - for (WifiConfiguration configuration : configurations) { - int networkId = - mWifiConfigManager.addOrUpdateNetwork(configuration, callingUid) - .getNetworkId(); - if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { - Log.e(TAG, "Restore network failed: " + configuration.getKey()); - continue; - } - // Enable all networks restored. - mWifiConfigManager.enableNetwork(networkId, false, callingUid, null); - // Restore auto-join param. - mWifiConfigManager.allowAutojoin(networkId, configuration.allowAutojoin); - } - }); - } - - /** - * Restore state from the backed up data. - * - * @param data Raw byte stream of the backed up data. - */ - @Override - public void restoreBackupData(byte[] data) { - enforceNetworkSettingsPermission(); - mLog.info("restoreBackupData uid=%").c(Binder.getCallingUid()).flush(); - if (mClientModeImplChannel == null) { - Log.e(TAG, "mClientModeImplChannel is not initialized"); - return; - } - - Log.d(TAG, "Restoring backup data"); - List<WifiConfiguration> wifiConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(data); - restoreNetworks(wifiConfigurations); - Log.d(TAG, "Restored backup data"); - } - - /** - * Retrieve the soft ap config data to be backed to save current config data. - * - * @return Raw byte stream of the data to be backed up. - */ - @Override - public byte[] retrieveSoftApBackupData() { - enforceNetworkSettingsPermission(); - mLog.info("retrieveSoftApBackupData uid=%").c(Binder.getCallingUid()).flush(); - SoftApConfiguration config = mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, - new SoftApConfiguration.Builder().build()); - byte[] backupData = - mSoftApBackupRestore.retrieveBackupDataFromSoftApConfiguration(config); - Log.d(TAG, "Retrieved soft ap backup data"); - return backupData; - } - - /** - * Restore soft ap config from the backed up data. - * - * @param data Raw byte stream of the backed up data. - * @return restored SoftApConfiguration or Null if data is invalid. - */ - @Override - public SoftApConfiguration restoreSoftApBackupData(byte[] data) { - enforceNetworkSettingsPermission(); - mLog.info("restoreSoftApBackupData uid=%").c(Binder.getCallingUid()).flush(); - SoftApConfiguration softApConfig = - mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); - if (softApConfig != null) { - mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration( - mWifiApConfigStore.resetToDefaultForUnsupportedConfig(softApConfig))); - Log.d(TAG, "Restored soft ap backup data"); - } - return softApConfig; - } - - - /** - * Restore state from the older supplicant back up data. - * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file. - * - * @param supplicantData Raw byte stream of wpa_supplicant.conf - * @param ipConfigData Raw byte stream of ipconfig.txt - */ - public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { - enforceNetworkSettingsPermission(); - mLog.trace("restoreSupplicantBackupData uid=%").c(Binder.getCallingUid()).flush(); - if (mClientModeImplChannel == null) { - Log.e(TAG, "mClientModeImplChannel is not initialized"); - return; - } - - Log.d(TAG, "Restoring supplicant backup data"); - List<WifiConfiguration> wifiConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - restoreNetworks(wifiConfigurations); - Log.d(TAG, "Restored supplicant backup data"); - } - - /** - * Starts subscription provisioning with a provider. - * - * @param provider {@link OsuProvider} the provider to provision with - * @param callback {@link IProvisioningCallback} the callback object to inform status - */ - @Override - public void startSubscriptionProvisioning(OsuProvider provider, - IProvisioningCallback callback) { - if (provider == null) { - throw new IllegalArgumentException("Provider must not be null"); - } - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - final int uid = Binder.getCallingUid(); - mLog.trace("startSubscriptionProvisioning uid=%").c(uid).flush(); - if (mClientModeImpl.syncStartSubscriptionProvisioning(uid, provider, - callback, mClientModeImplChannel)) { - mLog.trace("Subscription provisioning started with %") - .c(provider.toString()).flush(); - } - } - - /** - * See - * {@link WifiManager#registerTrafficStateCallback(Executor, WifiManager.TrafficStateCallback)} - * - * @param binder IBinder instance to allow cleanup if the app dies - * @param callback Traffic State callback to register - * @param callbackIdentifier Unique ID of the registering callback. This ID will be used to - * unregister the callback. See {@link unregisterTrafficStateCallback(int)} - * - * @throws SecurityException if the caller does not have permission to register a callback - * @throws RemoteException if remote exception happens - * @throws IllegalArgumentException if the arguments are null or invalid - */ - @Override - public void registerTrafficStateCallback(IBinder binder, ITrafficStateCallback callback, - int callbackIdentifier) { - // verify arguments - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - enforceNetworkSettingsPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("registerTrafficStateCallback uid=%").c(Binder.getCallingUid()).flush(); - } - // Post operation to handler thread - mWifiThreadRunner.post(() -> - mWifiTrafficPoller.addCallback(binder, callback, callbackIdentifier)); - } - - /** - * see {@link android.net.wifi.WifiManager#unregisterTrafficStateCallback( - * WifiManager.TrafficStateCallback)} - * - * @param callbackIdentifier Unique ID of the callback to be unregistered. - * - * @throws SecurityException if the caller does not have permission to register a callback - */ - @Override - public void unregisterTrafficStateCallback(int callbackIdentifier) { - enforceNetworkSettingsPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("unregisterTrafficStateCallback uid=%").c(Binder.getCallingUid()).flush(); - } - // Post operation to handler thread - mWifiThreadRunner.post(() -> - mWifiTrafficPoller.removeCallback(callbackIdentifier)); - } - - private long getSupportedFeaturesInternal() { - final AsyncChannel channel = mClientModeImplChannel; - long supportedFeatureSet = 0L; - if (channel != null) { - supportedFeatureSet = mClientModeImpl.syncGetSupportedFeatures(channel); - } else { - Log.e(TAG, "mClientModeImplChannel is not initialized"); - return supportedFeatureSet; - } - // Mask the feature set against system properties. - boolean rttSupported = mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_RTT); - if (!rttSupported) { - // flags filled in by vendor HAL, remove if overlay disables it. - supportedFeatureSet &= - ~(WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT); - } - if (!mContext.getResources().getBoolean( - R.bool.config_wifi_p2p_mac_randomization_supported)) { - // flags filled in by vendor HAL, remove if overlay disables it. - supportedFeatureSet &= ~WifiManager.WIFI_FEATURE_P2P_RAND_MAC; - } - if (mContext.getResources().getBoolean( - R.bool.config_wifi_connected_mac_randomization_supported)) { - // no corresponding flags in vendor HAL, set if overlay enables it. - supportedFeatureSet |= WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; - } - if (mContext.getResources().getBoolean( - R.bool.config_wifi_ap_mac_randomization_supported)) { - // no corresponding flags in vendor HAL, set if overlay enables it. - supportedFeatureSet |= WifiManager.WIFI_FEATURE_AP_RAND_MAC; - } - if (mWifiThreadRunner.call( - () -> mActiveModeWarden.isStaApConcurrencySupported(), - false)) { - supportedFeatureSet |= WifiManager.WIFI_FEATURE_AP_STA; - } - return supportedFeatureSet; - } - - private static boolean hasAutomotiveFeature(Context context) { - return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); - } - - /** - * See - * {@link WifiManager#registerNetworkRequestMatchCallback( - * Executor, WifiManager.NetworkRequestMatchCallback)} - * - * @param binder IBinder instance to allow cleanup if the app dies - * @param callback Network Request Match callback to register - * @param callbackIdentifier Unique ID of the registering callback. This ID will be used to - * unregister the callback. - * See {@link #unregisterNetworkRequestMatchCallback(int)} (int)} - * - * @throws SecurityException if the caller does not have permission to register a callback - * @throws RemoteException if remote exception happens - * @throws IllegalArgumentException if the arguments are null or invalid - */ - @Override - public void registerNetworkRequestMatchCallback(IBinder binder, - INetworkRequestMatchCallback callback, - int callbackIdentifier) { - // verify arguments - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - enforceNetworkSettingsPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("registerNetworkRequestMatchCallback uid=%") - .c(Binder.getCallingUid()).flush(); - } - // Post operation to handler thread - mWifiThreadRunner.post(() -> mClientModeImpl.addNetworkRequestMatchCallback( - binder, callback, callbackIdentifier)); - } - - /** - * see {@link android.net.wifi.WifiManager#unregisterNetworkRequestMatchCallback( - * WifiManager.NetworkRequestMatchCallback)} - * - * @param callbackIdentifier Unique ID of the callback to be unregistered. - * - * @throws SecurityException if the caller does not have permission to register a callback - */ - @Override - public void unregisterNetworkRequestMatchCallback(int callbackIdentifier) { - enforceNetworkSettingsPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("unregisterNetworkRequestMatchCallback uid=%") - .c(Binder.getCallingUid()).flush(); - } - // Post operation to handler thread - mWifiThreadRunner.post(() -> - mClientModeImpl.removeNetworkRequestMatchCallback(callbackIdentifier)); - } - - /** - * See {@link android.net.wifi.WifiManager#addNetworkSuggestions(List)} - * - * @param networkSuggestions List of network suggestions to be added. - * @param callingPackageName Package Name of the app adding the suggestions. - * @param callingFeatureId Feature in the calling package - * @throws SecurityException if the caller does not have permission. - * @return One of status codes from {@link WifiManager.NetworkSuggestionsStatusCode}. - */ - @Override - public int addNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, - String callingFeatureId) { - if (enforceChangePermission(callingPackageName) != MODE_ALLOWED) { - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; - } - if (mVerboseLoggingEnabled) { - mLog.info("addNetworkSuggestions uid=%").c(Binder.getCallingUid()).flush(); - } - int callingUid = Binder.getCallingUid(); - - int success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.add( - networkSuggestions, callingUid, callingPackageName, callingFeatureId), - WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL); - if (success != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { - Log.e(TAG, "Failed to add network suggestions"); - } - return success; - } - - /** - * See {@link android.net.wifi.WifiManager#removeNetworkSuggestions(List)} - * - * @param networkSuggestions List of network suggestions to be removed. - * @param callingPackageName Package Name of the app removing the suggestions. - * @throws SecurityException if the caller does not have permission. - * @return One of status codes from {@link WifiManager.NetworkSuggestionsStatusCode}. - */ - @Override - public int removeNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName) { - if (enforceChangePermission(callingPackageName) != MODE_ALLOWED) { - return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; - } - if (mVerboseLoggingEnabled) { - mLog.info("removeNetworkSuggestions uid=%").c(Binder.getCallingUid()).flush(); - } - int callingUid = Binder.getCallingUid(); - - int success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.remove( - networkSuggestions, callingUid, callingPackageName), - WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL); - if (success != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { - Log.e(TAG, "Failed to remove network suggestions"); - } - return success; - } - - /** - * See {@link android.net.wifi.WifiManager#getNetworkSuggestions()} - * @param callingPackageName Package Name of the app getting the suggestions. - * @return a list of network suggestions suggested by this app - */ - public List<WifiNetworkSuggestion> getNetworkSuggestions(String callingPackageName) { - int callingUid = Binder.getCallingUid(); - mAppOps.checkPackage(callingUid, callingPackageName); - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("getNetworkSuggestionList uid=%").c(Binder.getCallingUid()).flush(); - } - return mWifiThreadRunner.call(() -> - mWifiNetworkSuggestionsManager.get(callingPackageName, callingUid), - Collections.emptyList()); - } - - /** - * Gets the factory Wi-Fi MAC addresses. - * @throws SecurityException if the caller does not have permission. - * @return Array of String representing Wi-Fi MAC addresses, or empty array if failed. - */ - @Override - public String[] getFactoryMacAddresses() { - final int uid = Binder.getCallingUid(); - if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { - throw new SecurityException("App not allowed to get Wi-Fi factory MAC address " - + "(uid = " + uid + ")"); - } - String result = mWifiThreadRunner.call(mClientModeImpl::getFactoryMacAddress, null); - // result can be empty array if either: WifiThreadRunner.call() timed out, or - // ClientModeImpl.getFactoryMacAddress() returned null. - // In this particular instance, we don't differentiate the two types of nulls. - if (result == null) { - return new String[0]; - } - return new String[]{result}; - } - - /** - * Sets the current device mobility state. - * @param state the new device mobility state - */ - @Override - public void setDeviceMobilityState(@DeviceMobilityState int state) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE, "WifiService"); - - if (mVerboseLoggingEnabled) { - mLog.info("setDeviceMobilityState uid=% state=%") - .c(Binder.getCallingUid()) - .c(state) - .flush(); - } - // Post operation to handler thread - mWifiThreadRunner.post(() -> mClientModeImpl.setDeviceMobilityState(state)); - } - - /** - * Proxy for the final native call of the parent class. Enables mocking of - * the function. - */ - public int getMockableCallingUid() { - return getCallingUid(); - } - - /** - * Start DPP in Configurator-Initiator role. The current device will initiate DPP bootstrapping - * with a peer, and send the SSID and password of the selected network. - * - * @param binder Caller's binder context - * @param enrolleeUri URI of the Enrollee obtained externally (e.g. QR code scanning) - * @param selectedNetworkId Selected network ID to be sent to the peer - * @param netRole The network role of the enrollee - * @param callback Callback for status updates - */ - @Override - public void startDppAsConfiguratorInitiator(IBinder binder, String enrolleeUri, - int selectedNetworkId, int netRole, IDppCallback callback) { - // verify arguments - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (TextUtils.isEmpty(enrolleeUri)) { - throw new IllegalArgumentException("Enrollee URI must not be null or empty"); - } - if (selectedNetworkId < 0) { - throw new IllegalArgumentException("Selected network ID invalid"); - } - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - - final int uid = getMockableCallingUid(); - - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - - mWifiThreadRunner.post(() -> mDppManager.startDppAsConfiguratorInitiator( - uid, binder, enrolleeUri, selectedNetworkId, netRole, callback)); - } - - /** - * Start DPP in Enrollee-Initiator role. The current device will initiate DPP bootstrapping - * with a peer, and receive the SSID and password from the peer configurator. - * - * @param binder Caller's binder context - * @param configuratorUri URI of the Configurator obtained externally (e.g. QR code scanning) - * @param callback Callback for status updates - */ - @Override - public void startDppAsEnrolleeInitiator(IBinder binder, String configuratorUri, - IDppCallback callback) { - // verify arguments - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (TextUtils.isEmpty(configuratorUri)) { - throw new IllegalArgumentException("Enrollee URI must not be null or empty"); - } - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - - final int uid = getMockableCallingUid(); - - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - - mWifiThreadRunner.post(() -> - mDppManager.startDppAsEnrolleeInitiator(uid, binder, configuratorUri, callback)); - } - - /** - * Stop or abort a current DPP session. - */ - @Override - public void stopDppSession() throws RemoteException { - if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - final int uid = getMockableCallingUid(); - - mWifiThreadRunner.post(() -> mDppManager.stopDppSession(uid)); - } - - /** - * see {@link android.net.wifi.WifiManager#addOnWifiUsabilityStatsListener(Executor, - * OnWifiUsabilityStatsListener)} - * - * @param binder IBinder instance to allow cleanup if the app dies - * @param listener WifiUsabilityStatsEntry listener to add - * @param listenerIdentifier Unique ID of the adding listener. This ID will be used to - * remove the listener. See {@link removeOnWifiUsabilityStatsListener(int)} - * - * @throws SecurityException if the caller does not have permission to add a listener - * @throws RemoteException if remote exception happens - * @throws IllegalArgumentException if the arguments are null or invalid - */ - @Override - public void addOnWifiUsabilityStatsListener(IBinder binder, - IOnWifiUsabilityStatsListener listener, int listenerIdentifier) { - // verify arguments - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (listener == null) { - throw new IllegalArgumentException("Listener must not be null"); - } - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); - if (mVerboseLoggingEnabled) { - mLog.info("addOnWifiUsabilityStatsListener uid=%") - .c(Binder.getCallingUid()).flush(); - } - // Post operation to handler thread - mWifiThreadRunner.post(() -> - mWifiMetrics.addOnWifiUsabilityListener(binder, listener, listenerIdentifier)); - } - - /** - * see {@link android.net.wifi.WifiManager#removeOnWifiUsabilityStatsListener( - * OnWifiUsabilityStatsListener)} - * - * @param listenerIdentifier Unique ID of the listener to be removed. - * - * @throws SecurityException if the caller does not have permission to add a listener - */ - @Override - public void removeOnWifiUsabilityStatsListener(int listenerIdentifier) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); - if (mVerboseLoggingEnabled) { - mLog.info("removeOnWifiUsabilityStatsListener uid=%") - .c(Binder.getCallingUid()).flush(); - } - // Post operation to handler thread - mWifiThreadRunner.post(() -> - mWifiMetrics.removeOnWifiUsabilityListener(listenerIdentifier)); - } - - /** - * Updates the Wi-Fi usability score. - * @param seqNum Sequence number of the Wi-Fi usability score. - * @param score The Wi-Fi usability score. - * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second. - */ - @Override - public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); - - if (mVerboseLoggingEnabled) { - mLog.info("updateWifiUsabilityScore uid=% seqNum=% score=% predictionHorizonSec=%") - .c(Binder.getCallingUid()) - .c(seqNum) - .c(score) - .c(predictionHorizonSec) - .flush(); - } - // Post operation to handler thread - mWifiThreadRunner.post(() -> - mClientModeImpl.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec)); - } - - /** - * see {@link android.net.wifi.WifiManager#connect(int, WifiManager.ActionListener)} - */ - @Override - public void connect(WifiConfiguration config, int netId, IBinder binder, - @Nullable IActionListener callback, int callbackIdentifier) { - int uid = Binder.getCallingUid(); - if (!isPrivileged(Binder.getCallingPid(), uid)) { - throw new SecurityException(TAG + ": Permission denied"); - } - mLog.info("connect uid=%").c(uid).flush(); - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { - if (config == null) { - mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_MANUAL_CONNECT, netId); - } else { - mWifiMetrics.logUserActionEvent( - UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId); - } - } - mClientModeImpl.connect(config, netId, binder, callback, callbackIdentifier, uid); - } - - /** - * see {@link android.net.wifi.WifiManager#save(WifiConfiguration, - * WifiManager.ActionListener)} - */ - @Override - public void save(WifiConfiguration config, IBinder binder, @Nullable IActionListener callback, - int callbackIdentifier) { - if (!isPrivileged(Binder.getCallingPid(), Binder.getCallingUid())) { - throw new SecurityException(TAG + ": Permission denied"); - } - mLog.info("save uid=%").c(Binder.getCallingUid()).flush(); - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) { - mWifiMetrics.logUserActionEvent( - UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId); - } - mClientModeImpl.save( - config, binder, callback, callbackIdentifier, Binder.getCallingUid()); - } - - /** - * see {@link android.net.wifi.WifiManager#forget(int, WifiManager.ActionListener)} - */ - @Override - public void forget(int netId, IBinder binder, @Nullable IActionListener callback, - int callbackIdentifier) { - int uid = Binder.getCallingUid(); - if (!isPrivileged(Binder.getCallingPid(), uid)) { - throw new SecurityException(TAG + ": Permission denied"); - } - mLog.info("forget uid=%").c(Binder.getCallingUid()).flush(); - if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { - // It's important to log this metric before the actual forget executes because - // the netId becomes invalid after the forget operation. - mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_FORGET_WIFI, netId); - } - mClientModeImpl.forget(netId, binder, callback, callbackIdentifier, uid); - } - - /** - * See {@link WifiManager#registerScanResultsCallback(WifiManager.ScanResultsCallback)} - */ - public void registerScanResultsCallback(@NonNull IScanResultsCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("callback must not be null"); - } - enforceAccessPermission(); - - if (mVerboseLoggingEnabled) { - mLog.info("registerScanResultsCallback uid=%").c(Binder.getCallingUid()).flush(); - } - mWifiThreadRunner.post(() -> { - if (!mWifiInjector.getScanRequestProxy().registerScanResultsCallback(callback)) { - Log.e(TAG, "registerScanResultsCallback: Failed to register callback"); - } - }); - } - - /** - * See {@link WifiManager#registerScanResultsCallback(WifiManager.ScanResultsCallback)} - */ - public void unregisterScanResultsCallback(@NonNull IScanResultsCallback callback) { - if (mVerboseLoggingEnabled) { - mLog.info("unregisterScanResultCallback uid=%").c(Binder.getCallingUid()).flush(); - } - enforceAccessPermission(); - // post operation to handler thread - mWifiThreadRunner.post(() -> mWifiInjector.getScanRequestProxy() - .unregisterScanResultsCallback(callback)); - - } - - /** - * See {@link WifiManager#addSuggestionConnectionStatusListener(Executor, - * SuggestionConnectionStatusListener)} - */ - public void registerSuggestionConnectionStatusListener(IBinder binder, - @NonNull ISuggestionConnectionStatusListener listener, - int listenerIdentifier, String packageName, @Nullable String featureId) { - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - final int uid = Binder.getCallingUid(); - enforceAccessPermission(); - enforceLocationPermission(packageName, featureId, uid); - if (mVerboseLoggingEnabled) { - mLog.info("registerSuggestionConnectionStatusListener uid=%").c(uid).flush(); - } - mWifiThreadRunner.post(() -> - mWifiNetworkSuggestionsManager - .registerSuggestionConnectionStatusListener(binder, listener, - listenerIdentifier, packageName, uid)); - } - - /** - * See {@link WifiManager#removeSuggestionConnectionStatusListener( - * SuggestionConnectionStatusListener)} - */ - public void unregisterSuggestionConnectionStatusListener( - int listenerIdentifier, String packageName) { - enforceAccessPermission(); - int uid = Binder.getCallingUid(); - if (mVerboseLoggingEnabled) { - mLog.info("unregisterSuggestionConnectionStatusListener uid=%") - .c(uid).flush(); - } - mWifiThreadRunner.post(() -> - mWifiNetworkSuggestionsManager - .unregisterSuggestionConnectionStatusListener(listenerIdentifier, - packageName, uid)); - } - - @Override - public int calculateSignalLevel(int rssi) { - return RssiUtil.calculateSignalLevel(mContext, rssi); - } - - /** - * See {@link android.net.wifi.WifiManager#setWifiConnectedNetworkScorer(Executor, - * WifiConnectedNetworkScorer)} - * - * @param binder IBinder instance to allow cleanup if the app dies. - * @param scorer Wifi connected network scorer to set. - * @return true Scorer is set successfully. - * - * @throws RemoteException if remote exception happens - * @throws IllegalArgumentException if the arguments are null or invalid - */ - @Override - public boolean setWifiConnectedNetworkScorer(IBinder binder, - IWifiConnectedNetworkScorer scorer) { - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (scorer == null) { - throw new IllegalArgumentException("Scorer must not be null"); - } - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); - if (mVerboseLoggingEnabled) { - mLog.info("setWifiConnectedNetworkScorer uid=%").c(Binder.getCallingUid()).flush(); - } - // Post operation to handler thread - WifiScoreReport wifiScoreReport = mClientModeImpl.getWifiScoreReport(); - return mWifiThreadRunner.call(() -> wifiScoreReport.setWifiConnectedNetworkScorer( - binder, scorer), false); - } - /** - * See {@link android.net.wifi.WifiManager#clearWifiConnectedNetworkScorer( - * WifiConnectedNetworkScorer)} - */ - @Override - public void clearWifiConnectedNetworkScorer() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); - if (mVerboseLoggingEnabled) { - mLog.info("clearWifiConnectedNetworkScorer uid=%").c(Binder.getCallingUid()).flush(); - } - // Post operation to handler thread - WifiScoreReport wifiScoreReport = mClientModeImpl.getWifiScoreReport(); - mWifiThreadRunner.post(() -> - wifiScoreReport.clearWifiConnectedNetworkScorer()); - } - - /** - * See {@link android.net.wifi.WifiManager#setScanThrottleEnabled(boolean)} - */ - @Override - public void setScanThrottleEnabled(boolean enable) { - enforceNetworkSettingsPermission(); - mLog.info("setScanThrottleEnabled uid=% verbose=%") - .c(Binder.getCallingUid()) - .c(enable).flush(); - mWifiThreadRunner.post(()-> mScanRequestProxy.setScanThrottleEnabled(enable)); - } - - /** - * See {@link android.net.wifi.WifiManager#isScanThrottleEnabled()} - */ - @Override - public boolean isScanThrottleEnabled() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("isScanThrottleEnabled uid=%").c(Binder.getCallingUid()).flush(); - } - return mWifiThreadRunner.call(()-> mScanRequestProxy.isScanThrottleEnabled(), true); - } - - /** - * See {@link android.net.wifi.WifiManager#setAutoWakeupEnabled(boolean)} - */ - @Override - public void setAutoWakeupEnabled(boolean enable) { - enforceNetworkSettingsPermission(); - mLog.info("setWalkeupEnabled uid=% verbose=%") - .c(Binder.getCallingUid()) - .c(enable).flush(); - mWifiThreadRunner.post(()-> mWifiInjector.getWakeupController().setEnabled(enable)); - } - - /** - * See {@link android.net.wifi.WifiManager#isAutoWakeupEnabled()} - */ - @Override - public boolean isAutoWakeupEnabled() { - enforceAccessPermission(); - if (mVerboseLoggingEnabled) { - mLog.info("isAutoWakeupEnabled uid=%").c(Binder.getCallingUid()).flush(); - } - return mWifiThreadRunner.call(()-> mWifiInjector.getWakeupController().isEnabled(), false); - } -} diff --git a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java deleted file mode 100644 index d77aa4803..000000000 --- a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.wifi.WifiMigration; -import android.os.Handler; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; -import com.android.server.wifi.util.SettingsMigrationDataHolder; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -/** - * Store data for storing wifi settings. These are key (string) / value pairs that are stored in - * WifiConfigStore.xml file in a separate section. - */ -public class WifiSettingsConfigStore { - private static final String TAG = "WifiSettingsConfigStore"; - - // List of all allowed keys. - private static final ArrayList<Key> sKeys = new ArrayList<>(); - - /******** Wifi shared pref keys ***************/ - /** - * Indicate whether factory reset request is pending. - */ - public static final Key<Boolean> WIFI_P2P_PENDING_FACTORY_RESET = - new Key<>("wifi_p2p_pending_factory_reset", false); - - /** - * Allow scans to be enabled even wifi is turned off. - */ - public static final Key<Boolean> WIFI_SCAN_ALWAYS_AVAILABLE = - new Key<>("wifi_scan_always_enabled", false); - - /** - * Whether wifi scan throttle is enabled or not. - */ - public static final Key<Boolean> WIFI_SCAN_THROTTLE_ENABLED = - new Key<>("wifi_scan_throttle_enabled", true); - - /** - * Setting to enable verbose logging in Wi-Fi; disabled by default, and setting to 1 - * will enable it. In the future, additional values may be supported. - */ - public static final Key<Boolean> WIFI_VERBOSE_LOGGING_ENABLED = - new Key<>("wifi_verbose_logging_enabled", false); - - /** - * The Wi-Fi peer-to-peer device name - */ - public static final Key<String> WIFI_P2P_DEVICE_NAME = - new Key<>("wifi_p2p_device_name", null); - - /******** Wifi shared pref keys ***************/ - - private final Context mContext; - private final Handler mHandler; - private final SettingsMigrationDataHolder mSettingsMigrationDataHolder; - private final WifiConfigManager mWifiConfigManager; - - private final Object mLock = new Object(); - @GuardedBy("mLock") - private final Map<String, Object> mSettings = new HashMap<>(); - @GuardedBy("mLock") - private final Map<String, Map<OnSettingsChangedListener, Handler>> mListeners = - new HashMap<>(); - private WifiMigration.SettingsMigrationData mCachedMigrationData = null; - - private boolean mHasNewDataToSerialize = false; - - /** - * Interface for a settings change listener. - * @param <T> Type of the value. - */ - public interface OnSettingsChangedListener<T> { - /** - * Invoked when a particular key settings changes. - * - * @param key Key that was changed. - * @param newValue New value that was assigned to the key. - */ - void onSettingsChanged(@NonNull Key<T> key, @Nullable T newValue); - } - - public WifiSettingsConfigStore(@NonNull Context context, @NonNull Handler handler, - @NonNull SettingsMigrationDataHolder settingsMigrationDataHolder, - @NonNull WifiConfigManager wifiConfigManager, - @NonNull WifiConfigStore wifiConfigStore) { - mContext = context; - mHandler = handler; - mSettingsMigrationDataHolder = settingsMigrationDataHolder; - mWifiConfigManager = wifiConfigManager; - - // Register our data store. - wifiConfigStore.registerStoreData(new StoreData()); - } - - private void invokeAllListeners() { - synchronized (mLock) { - for (Key key : sKeys) { - invokeListeners(key); - } - } - } - - private <T> void invokeListeners(@NonNull Key<T> key) { - synchronized (mLock) { - if (!mSettings.containsKey(key.key)) return; - Object newValue = mSettings.get(key.key); - Map<OnSettingsChangedListener, Handler> listeners = mListeners.get(key.key); - if (listeners == null || listeners.isEmpty()) return; - for (Map.Entry<OnSettingsChangedListener, Handler> listener - : listeners.entrySet()) { - // Trigger the callback in the appropriate handler. - listener.getValue().post(() -> - listener.getKey().onSettingsChanged(key, newValue)); - } - } - } - - /** - * Trigger config store writes and invoke listeners in the main wifi service looper's handler. - */ - private void triggerSaveToStoreAndInvokeAllListeners() { - mHandler.post(() -> { - mHasNewDataToSerialize = true; - mWifiConfigManager.saveToStore(true); - - invokeAllListeners(); - }); - } - - /** - * Trigger config store writes and invoke listeners in the main wifi service looper's handler. - */ - private <T> void triggerSaveToStoreAndInvokeListeners(@NonNull Key<T> key) { - mHandler.post(() -> { - mHasNewDataToSerialize = true; - mWifiConfigManager.saveToStore(true); - - invokeListeners(key); - }); - } - - /** - * Performs a one time migration from Settings.Global values to settings store. Only - * performed one time if the settings store is empty. - */ - private void migrateFromSettingsIfNeeded() { - if (!mSettings.isEmpty()) return; // already migrated. - - mCachedMigrationData = mSettingsMigrationDataHolder.retrieveData(); - if (mCachedMigrationData == null) { - Log.e(TAG, "No settings data to migrate"); - return; - } - Log.i(TAG, "Migrating data out of settings to shared preferences"); - - mSettings.put(WIFI_P2P_DEVICE_NAME.key, - mCachedMigrationData.getP2pDeviceName()); - mSettings.put(WIFI_P2P_PENDING_FACTORY_RESET.key, - mCachedMigrationData.isP2pFactoryResetPending()); - mSettings.put(WIFI_SCAN_ALWAYS_AVAILABLE.key, - mCachedMigrationData.isScanAlwaysAvailable()); - mSettings.put(WIFI_SCAN_THROTTLE_ENABLED.key, - mCachedMigrationData.isScanThrottleEnabled()); - mSettings.put(WIFI_VERBOSE_LOGGING_ENABLED.key, - mCachedMigrationData.isVerboseLoggingEnabled()); - triggerSaveToStoreAndInvokeAllListeners(); - } - - /** - * Store a value to the stored settings. - * - * @param key One of the settings keys. - * @param value Value to be stored. - */ - public <T> void put(@NonNull Key<T> key, @Nullable T value) { - synchronized (mLock) { - mSettings.put(key.key, value); - } - triggerSaveToStoreAndInvokeListeners(key); - } - - /** - * Retrieve a value from the stored settings. - * - * @param key One of the settings keys. - * @return value stored in settings, defValue if the key does not exist. - */ - public @Nullable <T> T get(@NonNull Key<T> key) { - synchronized (mLock) { - return (T) mSettings.getOrDefault(key.key, key.defaultValue); - } - } - - /** - * Register for settings change listener. - * - * @param key One of the settings keys. - * @param listener Listener to be registered. - * @param handler Handler to post the listener - */ - public <T> void registerChangeListener(@NonNull Key<T> key, - @NonNull OnSettingsChangedListener<T> listener, @NonNull Handler handler) { - synchronized (mLock) { - mListeners.computeIfAbsent( - key.key, ignore -> new HashMap<>()).put(listener, handler); - } - } - - /** - * Unregister for settings change listener. - * - * @param key One of the settings keys. - * @param listener Listener to be unregistered. - */ - public <T> void unregisterChangeListener(@NonNull Key<T> key, - @NonNull OnSettingsChangedListener<T> listener) { - synchronized (mLock) { - Map<OnSettingsChangedListener, Handler> listeners = mListeners.get(key.key); - if (listeners == null || listeners.isEmpty()) { - Log.e(TAG, "No listeners for " + key); - return; - } - if (listeners.remove(listener) == null) { - Log.e(TAG, "Unknown listener for " + key); - } - } - } - - /** - * Dump output for debugging. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(); - pw.println("Dump of " + TAG); - pw.println("Settings:"); - for (Map.Entry<String, Object> entry : mSettings.entrySet()) { - pw.print(entry.getKey()); - pw.print("="); - pw.println(entry.getValue()); - } - if (mCachedMigrationData == null) return; - pw.println("Migration data:"); - pw.print(WIFI_P2P_DEVICE_NAME.key); - pw.print("="); - pw.println(mCachedMigrationData.getP2pDeviceName()); - pw.print(WIFI_P2P_PENDING_FACTORY_RESET.key); - pw.print("="); - pw.println(mCachedMigrationData.isP2pFactoryResetPending()); - pw.print(WIFI_SCAN_ALWAYS_AVAILABLE.key); - pw.print("="); - pw.println(mCachedMigrationData.isScanAlwaysAvailable()); - pw.print(WIFI_SCAN_THROTTLE_ENABLED.key); - pw.print("="); - pw.println(mCachedMigrationData.isScanThrottleEnabled()); - pw.print(WIFI_VERBOSE_LOGGING_ENABLED.key); - pw.print("="); - pw.println(mCachedMigrationData.isVerboseLoggingEnabled()); - pw.println(); - } - - /** - * Base class to store string key and its default value. - * @param <T> Type of the value. - */ - public static class Key<T> { - public final String key; - public final T defaultValue; - - private Key(@NonNull String key, T defaultValue) { - this.key = key; - this.defaultValue = defaultValue; - sKeys.add(this); - } - - @Override - public String toString() { - return "[Key " + key + ", DefaultValue: " + defaultValue + "]"; - } - } - - /** - * Store data for persisting the settings data to config store. - */ - private class StoreData implements WifiConfigStore.StoreData { - private static final String XML_TAG_SECTION_HEADER = "Settings"; - private static final String XML_TAG_VALUES = "Values"; - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - synchronized (mLock) { - XmlUtil.writeNextValue(out, XML_TAG_VALUES, mSettings); - } - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - if (in == null) { - // Empty read triggers the migration since it indicates that there is no settings - // data stored in the settings store. - migrateFromSettingsIfNeeded(); - return; - } - Map<String, Object> values = null; - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (TextUtils.isEmpty(valueName[0])) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_VALUES: - values = (Map) value; - break; - default: - Log.w(TAG, "Ignoring unknown tag under " + XML_TAG_SECTION_HEADER + ": " - + valueName[0]); - break; - } - } - if (values != null) { - synchronized (mLock) { - mSettings.putAll(values); - // Invoke all the registered listeners. - invokeAllListeners(); - } - } - } - - @Override - public void resetData() { - synchronized (mLock) { - mSettings.clear(); - } - } - - @Override - public boolean hasNewDataToSerialize() { - return mHasNewDataToSerialize; - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - // Shared general store. - return WifiConfigStore.STORE_FILE_SHARED_GENERAL; - } - } -} diff --git a/service/java/com/android/server/wifi/WifiSettingsStore.java b/service/java/com/android/server/wifi/WifiSettingsStore.java deleted file mode 100644 index 5cc27d022..000000000 --- a/service/java/com/android/server/wifi/WifiSettingsStore.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2013 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.server.wifi; - -import android.content.ContentResolver; -import android.content.Context; -import android.provider.Settings; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/* Tracks persisted settings for Wi-Fi and airplane mode interaction */ -public class WifiSettingsStore { - /* Values tracked in Settings.Global.WIFI_ON */ - static final int WIFI_DISABLED = 0; - static final int WIFI_ENABLED = 1; - - /* Wifi enabled while in airplane mode */ - private static final int WIFI_ENABLED_AIRPLANE_OVERRIDE = 2; - /* Wifi disabled due to airplane mode on */ - private static final int WIFI_DISABLED_AIRPLANE_ON = 3; - - /* Persisted state that tracks the wifi & airplane interaction from settings */ - private int mPersistWifiState = WIFI_DISABLED; - /* Tracks current airplane mode state */ - private boolean mAirplaneModeOn = false; - - private final Context mContext; - private final WifiSettingsConfigStore mSettingsConfigStore; - - WifiSettingsStore(Context context, WifiSettingsConfigStore sharedPreferences) { - mContext = context; - mSettingsConfigStore = sharedPreferences; - mAirplaneModeOn = getPersistedAirplaneModeOn(); - mPersistWifiState = getPersistedWifiState(); - } - - public synchronized boolean isWifiToggleEnabled() { - if (mAirplaneModeOn) { - return mPersistWifiState == WIFI_ENABLED_AIRPLANE_OVERRIDE; - } else { - return mPersistWifiState != WIFI_DISABLED; - } - } - - /** - * Returns true if airplane mode is currently on. - * @return {@code true} if airplane mode is on. - */ - public synchronized boolean isAirplaneModeOn() { - return mAirplaneModeOn; - } - - public synchronized boolean isScanAlwaysAvailable() { - return !mAirplaneModeOn && getPersistedScanAlwaysAvailable(); - } - - public synchronized boolean handleWifiToggled(boolean wifiEnabled) { - // Can Wi-Fi be toggled in airplane mode ? - if (mAirplaneModeOn && !isAirplaneToggleable()) { - return false; - } - - if (wifiEnabled) { - if (mAirplaneModeOn) { - persistWifiState(WIFI_ENABLED_AIRPLANE_OVERRIDE); - } else { - persistWifiState(WIFI_ENABLED); - } - } else { - // When wifi state is disabled, we do not care - // if airplane mode is on or not. The scenario of - // wifi being disabled due to airplane mode being turned on - // is handled handleAirplaneModeToggled() - persistWifiState(WIFI_DISABLED); - } - return true; - } - - synchronized boolean handleAirplaneModeToggled() { - // Is Wi-Fi sensitive to airplane mode changes ? - if (!isAirplaneSensitive()) { - return false; - } - - mAirplaneModeOn = getPersistedAirplaneModeOn(); - if (mAirplaneModeOn) { - // Wifi disabled due to airplane on - if (mPersistWifiState == WIFI_ENABLED) { - persistWifiState(WIFI_DISABLED_AIRPLANE_ON); - } - } else { - /* On airplane mode disable, restore wifi state if necessary */ - if (mPersistWifiState == WIFI_ENABLED_AIRPLANE_OVERRIDE - || mPersistWifiState == WIFI_DISABLED_AIRPLANE_ON) { - persistWifiState(WIFI_ENABLED); - } - } - return true; - } - - synchronized void handleWifiScanAlwaysAvailableToggled(boolean isAvailable) { - persistScanAlwaysAvailableState(isAvailable); - } - - void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("mPersistWifiState " + mPersistWifiState); - pw.println("mAirplaneModeOn " + mAirplaneModeOn); - } - - private void persistWifiState(int state) { - final ContentResolver cr = mContext.getContentResolver(); - mPersistWifiState = state; - Settings.Global.putInt(cr, Settings.Global.WIFI_ON, state); - } - - private void persistScanAlwaysAvailableState(boolean isAvailable) { - mSettingsConfigStore.put( - WifiSettingsConfigStore.WIFI_SCAN_ALWAYS_AVAILABLE, isAvailable); - } - - /* Does Wi-Fi need to be disabled when airplane mode is on ? */ - private boolean isAirplaneSensitive() { - String airplaneModeRadios = Settings.Global.getString(mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_RADIOS); - return airplaneModeRadios == null - || airplaneModeRadios.contains(Settings.Global.RADIO_WIFI); - } - - /* Is Wi-Fi allowed to be re-enabled while airplane mode is on ? */ - private boolean isAirplaneToggleable() { - String toggleableRadios = Settings.Global.getString(mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); - return toggleableRadios != null - && toggleableRadios.contains(Settings.Global.RADIO_WIFI); - } - - private int getPersistedWifiState() { - final ContentResolver cr = mContext.getContentResolver(); - try { - return Settings.Global.getInt(cr, Settings.Global.WIFI_ON); - } catch (Settings.SettingNotFoundException e) { - Settings.Global.putInt(cr, Settings.Global.WIFI_ON, WIFI_DISABLED); - return WIFI_DISABLED; - } - } - - private boolean getPersistedAirplaneModeOn() { - return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, 0) == 1; - } - - private boolean getPersistedScanAlwaysAvailable() { - return mSettingsConfigStore.get( - WifiSettingsConfigStore.WIFI_SCAN_ALWAYS_AVAILABLE); - } -} diff --git a/service/java/com/android/server/wifi/WifiShellCommand.java b/service/java/com/android/server/wifi/WifiShellCommand.java deleted file mode 100644 index a3cae7755..000000000 --- a/service/java/com/android/server/wifi/WifiShellCommand.java +++ /dev/null @@ -1,1140 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; -import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; - -import android.content.Context; -import android.content.pm.ParceledListSlice; -import android.net.ConnectivityManager; -import android.net.MacAddress; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.wifi.IActionListener; -import android.net.wifi.IScoreUpdateObserver; -import android.net.wifi.IWifiConnectedNetworkScorer; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiNetworkSpecifier; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.BasicShellCommandHandler; -import android.os.Binder; -import android.os.Process; -import android.os.RemoteException; -import android.os.SystemClock; -import android.text.TextUtils; -import android.util.Pair; - -import com.android.server.wifi.util.ApConfigUtil; -import com.android.server.wifi.util.ArrayUtils; -import com.android.server.wifi.util.GeneralUtil; -import com.android.server.wifi.util.ScanResultUtil; - -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Interprets and executes 'adb shell cmd wifi [args]'. - * - * To add new commands: - * - onCommand: Add a case "<command>" execute. Return a 0 - * if command executed successfully. - * - onHelp: add a description string. - * - * Permissions: currently root permission is required for some commands. Others will - * enforce the corresponding API permissions. - */ -public class WifiShellCommand extends BasicShellCommandHandler { - private static String SHELL_PACKAGE_NAME = "com.android.shell"; - // These don't require root access. - // However, these do perform permission checks in the corresponding WifiService methods. - private static final String[] NON_PRIVILEGED_COMMANDS = { - "add-suggestion", - "add-network", - "connect-network", - "forget-network", - "get-country-code", - "help", - "-h", - "list-scan-results", - "list-networks", - "list-suggestions", - "remove-suggestion", - "remove-all-suggestions", - "reset-connected-score", - "set-connected-score", - "set-scan-always-available", - "set-verbose-logging", - "set-wifi-enabled", - "start-scan", - "start-softap", - "status", - "stop-softap", - }; - - private static final Map<String, Pair<NetworkRequest, ConnectivityManager.NetworkCallback>> - sActiveRequests = new ConcurrentHashMap<>(); - - private final ClientModeImpl mClientModeImpl; - private final WifiLockManager mWifiLockManager; - private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private final WifiConfigManager mWifiConfigManager; - private final WifiNative mWifiNative; - private final HostapdHal mHostapdHal; - private final WifiCountryCode mWifiCountryCode; - private final WifiLastResortWatchdog mWifiLastResortWatchdog; - private final WifiServiceImpl mWifiService; - private final Context mContext; - private final ConnectivityManager mConnectivityManager; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - - WifiShellCommand(WifiInjector wifiInjector, WifiServiceImpl wifiService, Context context) { - mClientModeImpl = wifiInjector.getClientModeImpl(); - mWifiLockManager = wifiInjector.getWifiLockManager(); - mWifiNetworkSuggestionsManager = wifiInjector.getWifiNetworkSuggestionsManager(); - mWifiConfigManager = wifiInjector.getWifiConfigManager(); - mHostapdHal = wifiInjector.getHostapdHal(); - mWifiNative = wifiInjector.getWifiNative(); - mWifiCountryCode = wifiInjector.getWifiCountryCode(); - mWifiLastResortWatchdog = wifiInjector.getWifiLastResortWatchdog(); - mWifiService = wifiService; - mContext = context; - mConnectivityManager = context.getSystemService(ConnectivityManager.class); - mWifiCarrierInfoManager = wifiInjector.getWifiCarrierInfoManager(); - } - - @Override - public int onCommand(String cmd) { - // Treat no command as help command. - if (cmd == null || cmd.equals("")) { - cmd = "help"; - } - // Explicit exclusion from root permission - if (ArrayUtils.indexOf(NON_PRIVILEGED_COMMANDS, cmd) == -1) { - final int uid = Binder.getCallingUid(); - if (uid != Process.ROOT_UID) { - throw new SecurityException( - "Uid " + uid + " does not have access to " + cmd + " wifi command"); - } - } - - final PrintWriter pw = getOutPrintWriter(); - try { - switch (cmd) { - case "set-ipreach-disconnect": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - mClientModeImpl.setIpReachabilityDisconnectEnabled(enabled); - return 0; - } - case "get-ipreach-disconnect": - pw.println("IPREACH_DISCONNECT state is " - + mClientModeImpl.getIpReachabilityDisconnectEnabled()); - return 0; - case "set-poll-rssi-interval-msecs": - int newPollIntervalMsecs; - try { - newPollIntervalMsecs = Integer.parseInt(getNextArgRequired()); - } catch (NumberFormatException e) { - pw.println( - "Invalid argument to 'set-poll-rssi-interval-msecs' " - + "- must be a positive integer"); - return -1; - } - - if (newPollIntervalMsecs < 1) { - pw.println( - "Invalid argument to 'set-poll-rssi-interval-msecs' " - + "- must be a positive integer"); - return -1; - } - - mClientModeImpl.setPollRssiIntervalMsecs(newPollIntervalMsecs); - return 0; - case "get-poll-rssi-interval-msecs": - pw.println("ClientModeImpl.mPollRssiIntervalMsecs = " - + mClientModeImpl.getPollRssiIntervalMsecs()); - return 0; - case "force-hi-perf-mode": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - if (!mWifiLockManager.forceHiPerfMode(enabled)) { - pw.println("Command execution failed"); - } - return 0; - } - case "force-low-latency-mode": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - if (!mWifiLockManager.forceLowLatencyMode(enabled)) { - pw.println("Command execution failed"); - } - return 0; - } - case "network-suggestions-set-user-approved": { - String packageName = getNextArgRequired(); - boolean approved = getNextArgRequiredTrueOrFalse("yes", "no"); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(approved, packageName); - return 0; - } - case "network-suggestions-has-user-approved": { - String packageName = getNextArgRequired(); - boolean hasUserApproved = - mWifiNetworkSuggestionsManager.hasUserApprovedForApp(packageName); - pw.println(hasUserApproved ? "yes" : "no"); - return 0; - } - case "imsi-protection-exemption-set-user-approved-for-carrier": { - String arg1 = getNextArgRequired(); - int carrierId = -1; - try { - carrierId = Integer.parseInt(arg1); - } catch (NumberFormatException e) { - pw.println("Invalid argument to " - + "'imsi-protection-exemption-set-user-approved-for-carrier' " - + "- carrierId must be an Integer"); - return -1; - } - boolean approved = getNextArgRequiredTrueOrFalse("yes", "no"); - mWifiCarrierInfoManager - .setHasUserApprovedImsiPrivacyExemptionForCarrier(approved, carrierId); - return 0; - } - case "imsi-protection-exemption-has-user-approved-for-carrier": { - String arg1 = getNextArgRequired(); - int carrierId = -1; - try { - carrierId = Integer.parseInt(arg1); - } catch (NumberFormatException e) { - pw.println("Invalid argument to " - + "'imsi-protection-exemption-has-user-approved-for-carrier' " - + "- 'carrierId' must be an Integer"); - return -1; - } - boolean hasUserApproved = mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(carrierId); - pw.println(hasUserApproved ? "yes" : "no"); - return 0; - } - case "imsi-protection-exemption-clear-user-approved-for-carrier": { - String arg1 = getNextArgRequired(); - int carrierId = -1; - try { - carrierId = Integer.parseInt(arg1); - } catch (NumberFormatException e) { - pw.println("Invalid argument to " - + "'imsi-protection-exemption-clear-user-approved-for-carrier' " - + "- 'carrierId' must be an Integer"); - return -1; - } - mWifiCarrierInfoManager.clearImsiPrivacyExemptionForCarrier(carrierId); - return 0; - } - case "network-requests-remove-user-approved-access-points": { - String packageName = getNextArgRequired(); - mClientModeImpl.removeNetworkRequestUserApprovedAccessPointsForApp(packageName); - return 0; - } - case "clear-user-disabled-networks": { - mWifiConfigManager.clearUserTemporarilyDisabledList(); - return 0; - } - case "send-link-probe": { - return sendLinkProbe(pw); - } - case "force-softap-channel": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - if (enabled) { - int apChannelMHz; - try { - apChannelMHz = Integer.parseInt(getNextArgRequired()); - } catch (NumberFormatException e) { - pw.println("Invalid argument to 'force-softap-channel enabled' " - + "- must be a positive integer"); - return -1; - } - int apChannel = ScanResult.convertFrequencyMhzToChannel(apChannelMHz); - int band = ApConfigUtil.convertFrequencyToBand(apChannelMHz); - if (apChannel == -1 || band == -1 || !isApChannelMHzValid(apChannelMHz)) { - pw.println("Invalid argument to 'force-softap-channel enabled' " - + "- must be a valid WLAN channel"); - return -1; - } - - if ((band == SoftApConfiguration.BAND_5GHZ - && !mWifiService.is5GHzBandSupported()) - || (band == SoftApConfiguration.BAND_6GHZ - && !mWifiService.is6GHzBandSupported())) { - pw.println("Invalid argument to 'force-softap-channel enabled' " - + "- channel band is not supported by the device"); - return -1; - } - - mHostapdHal.enableForceSoftApChannel(apChannel, band); - return 0; - } else { - mHostapdHal.disableForceSoftApChannel(); - return 0; - } - } - case "start-softap": { - SoftApConfiguration config = buildSoftApConfiguration(pw); - if (mWifiService.startTetheredHotspot(config)) { - pw.println("Soft AP started successfully"); - } else { - pw.println("Soft AP failed to start. Please check config parameters"); - } - return 0; - } - case "stop-softap": { - if (mWifiService.stopSoftAp()) { - pw.println("Soft AP stopped successfully"); - } else { - pw.println("Soft AP failed to stop"); - } - return 0; - } - case "force-country-code": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - if (enabled) { - String countryCode = getNextArgRequired(); - if (!(countryCode.length() == 2 - && countryCode.chars().allMatch(Character::isLetter))) { - pw.println("Invalid argument to 'force-country-code enabled' " - + "- must be a two-letter string"); - return -1; - } - mWifiCountryCode.enableForceCountryCode(countryCode); - return 0; - } else { - mWifiCountryCode.disableForceCountryCode(); - return 0; - } - } - case "get-country-code": { - pw.println("Wifi Country Code = " - + mWifiCountryCode.getCountryCode()); - return 0; - } - case "set-wifi-watchdog": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - mWifiLastResortWatchdog.setWifiWatchdogFeature(enabled); - return 0; - } - case "get-wifi-watchdog": { - pw.println("wifi watchdog state is " - + mWifiLastResortWatchdog.getWifiWatchdogFeature()); - return 0; - } - case "set-wifi-enabled": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - mWifiService.setWifiEnabled(SHELL_PACKAGE_NAME, enabled); - return 0; - } - case "set-scan-always-available": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - mWifiService.setScanAlwaysAvailable(enabled); - return 0; - } - case "get-softap-supported-features": - // This command is used for vts to check softap supported features. - if (ApConfigUtil.isAcsSupported(mContext)) { - pw.println("wifi_softap_acs_supported"); - } - if (ApConfigUtil.isWpa3SaeSupported(mContext)) { - pw.println("wifi_softap_wpa3_sae_supported"); - } - return 0; - case "settings-reset": - mWifiService.factoryReset(SHELL_PACKAGE_NAME); - return 0; - case "list-scan-results": - List<ScanResult> scanResults = - mWifiService.getScanResults(SHELL_PACKAGE_NAME, null); - if (scanResults.isEmpty()) { - pw.println("No scan results"); - } else { - ScanResultUtil.dumpScanResults(pw, scanResults, - SystemClock.elapsedRealtime()); - } - return 0; - case "start-scan": - mWifiService.startScan(SHELL_PACKAGE_NAME, null); - return 0; - case "list-networks": - ParceledListSlice<WifiConfiguration> networks = - mWifiService.getConfiguredNetworks(SHELL_PACKAGE_NAME, null); - if (networks == null || networks.getList().isEmpty()) { - pw.println("No networks"); - } else { - pw.println("Network Id SSID Security type"); - for (WifiConfiguration network : networks.getList()) { - String securityType = null; - if (WifiConfigurationUtil.isConfigForSaeNetwork(network)) { - securityType = "wpa3"; - } else if (WifiConfigurationUtil.isConfigForPskNetwork(network)) { - securityType = "wpa2"; - } else if (WifiConfigurationUtil.isConfigForEapNetwork(network)) { - securityType = "eap"; - } else if (WifiConfigurationUtil.isConfigForOweNetwork(network)) { - securityType = "owe"; - } else if (WifiConfigurationUtil.isConfigForOpenNetwork(network)) { - securityType = "open"; - } - pw.println(String.format("%-12d %-32s %-4s", - network.networkId, WifiInfo.sanitizeSsid(network.SSID), - securityType)); - } - } - return 0; - case "connect-network": { - CountDownLatch countDownLatch = new CountDownLatch(1); - IActionListener.Stub actionListener = new IActionListener.Stub() { - @Override - public void onSuccess() throws RemoteException { - pw.println("Connection initiated "); - countDownLatch.countDown(); - } - - @Override - public void onFailure(int i) throws RemoteException { - pw.println("Connection failed"); - countDownLatch.countDown(); - } - }; - WifiConfiguration config = buildWifiConfiguration(pw); - mWifiService.connect( - config, -1, new Binder(), actionListener, actionListener.hashCode()); - // wait for status. - countDownLatch.await(500, TimeUnit.MILLISECONDS); - setAutoJoin(pw, config.SSID, config.allowAutojoin); - return 0; - } - case "add-network": { - CountDownLatch countDownLatch = new CountDownLatch(1); - IActionListener.Stub actionListener = new IActionListener.Stub() { - @Override - public void onSuccess() throws RemoteException { - pw.println("Save successful"); - countDownLatch.countDown(); - } - - @Override - public void onFailure(int i) throws RemoteException { - pw.println("Save failed"); - countDownLatch.countDown(); - } - }; - WifiConfiguration config = buildWifiConfiguration(pw); - mWifiService.save( - config, new Binder(), actionListener, actionListener.hashCode()); - // wait for status. - countDownLatch.await(500, TimeUnit.MILLISECONDS); - setAutoJoin(pw, config.SSID, config.allowAutojoin); - return 0; - } - case "forget-network": { - String networkId = getNextArgRequired(); - CountDownLatch countDownLatch = new CountDownLatch(1); - IActionListener.Stub actionListener = new IActionListener.Stub() { - @Override - public void onSuccess() throws RemoteException { - pw.println("Forget successful"); - countDownLatch.countDown(); - } - - @Override - public void onFailure(int i) throws RemoteException { - pw.println("Forget failed"); - countDownLatch.countDown(); - } - }; - mWifiService.forget( - Integer.parseInt(networkId), new Binder(), actionListener, - actionListener.hashCode()); - // wait for status. - countDownLatch.await(500, TimeUnit.MILLISECONDS); - return 0; - } - case "status": - printStatus(pw); - return 0; - case "set-verbose-logging": { - boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); - mWifiService.enableVerboseLogging(enabled ? 1 : 0); - return 0; - } - case "add-suggestion": { - WifiNetworkSuggestion suggestion = buildSuggestion(pw); - mWifiService.addNetworkSuggestions( - Arrays.asList(suggestion), SHELL_PACKAGE_NAME, null); - return 0; - } - case "remove-suggestion": { - String ssid = getNextArgRequired(); - List<WifiNetworkSuggestion> suggestions = - mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME); - WifiNetworkSuggestion suggestion = suggestions.stream() - .filter(s -> s.getSsid().equals(ssid)) - .findAny() - .orElse(null); - if (suggestion == null) { - pw.println("No matching suggestion to remove"); - return -1; - } - mWifiService.removeNetworkSuggestions( - Arrays.asList(suggestion), SHELL_PACKAGE_NAME); - return 0; - } - case "remove-all-suggestions": - mWifiService.removeNetworkSuggestions( - Collections.emptyList(), SHELL_PACKAGE_NAME); - return 0; - case "list-suggestions": { - List<WifiNetworkSuggestion> suggestions = - mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME); - if (suggestions == null || suggestions.isEmpty()) { - pw.println("No suggestions"); - } else { - pw.println("SSID Security type"); - for (WifiNetworkSuggestion suggestion : suggestions) { - String securityType = null; - if (WifiConfigurationUtil.isConfigForSaeNetwork( - suggestion.getWifiConfiguration())) { - securityType = "wpa3"; - } else if (WifiConfigurationUtil.isConfigForPskNetwork( - suggestion.getWifiConfiguration())) { - securityType = "wpa2"; - } else if (WifiConfigurationUtil.isConfigForEapNetwork( - suggestion.getWifiConfiguration())) { - securityType = "eap"; - } else if (WifiConfigurationUtil.isConfigForOweNetwork( - suggestion.getWifiConfiguration())) { - securityType = "owe"; - } else if (WifiConfigurationUtil.isConfigForOpenNetwork( - suggestion.getWifiConfiguration())) { - securityType = "open"; - } - pw.println(String.format("%-32s %-4s", - WifiInfo.sanitizeSsid(suggestion.getWifiConfiguration().SSID), - securityType)); - } - } - return 0; - } - case "add-request": { - NetworkRequest networkRequest = buildNetworkRequest(pw); - ConnectivityManager.NetworkCallback networkCallback = - new ConnectivityManager.NetworkCallback(); - pw.println("Adding request: " + networkRequest); - mConnectivityManager.requestNetwork(networkRequest, networkCallback); - String ssid = getAllArgs()[1]; - sActiveRequests.put(ssid, Pair.create(networkRequest, networkCallback)); - return 0; - } - case "remove-request": { - String ssid = getNextArgRequired(); - Pair<NetworkRequest, ConnectivityManager.NetworkCallback> nrAndNc = - sActiveRequests.remove(ssid); - if (nrAndNc == null) { - pw.println("No matching request to remove"); - return -1; - } - pw.println("Removing request: " + nrAndNc.first); - mConnectivityManager.unregisterNetworkCallback(nrAndNc.second); - return 0; - } - case "remove-all-requests": - if (sActiveRequests.isEmpty()) { - pw.println("No active requests"); - return -1; - } - for (Pair<NetworkRequest, ConnectivityManager.NetworkCallback> nrAndNc - : sActiveRequests.values()) { - pw.println("Removing request: " + nrAndNc.first); - mConnectivityManager.unregisterNetworkCallback(nrAndNc.second); - } - sActiveRequests.clear(); - return 0; - case "list-requests": - if (sActiveRequests.isEmpty()) { - pw.println("No active requests"); - } else { - pw.println("SSID NetworkRequest"); - for (Map.Entry<String, - Pair<NetworkRequest, ConnectivityManager.NetworkCallback>> entry : - sActiveRequests.entrySet()) { - pw.println(String.format("%-32s %-4s", - entry.getKey(), entry.getValue().first)); - } - } - return 0; - case "network-requests-set-user-approved": { - String packageName = getNextArgRequired(); - boolean approved = getNextArgRequiredTrueOrFalse("yes", "no"); - mClientModeImpl.setNetworkRequestUserApprovedApp(packageName, approved); - return 0; - } - case "network-requests-has-user-approved": { - String packageName = getNextArgRequired(); - boolean hasUserApproved = - mClientModeImpl.hasNetworkRequestUserApprovedApp(packageName); - pw.println(hasUserApproved ? "yes" : "no"); - return 0; - } - case "set-connected-score": { - int score = Integer.parseInt(getNextArgRequired()); - CountDownLatch countDownLatch = new CountDownLatch(2); - GeneralUtil.Mutable<IScoreUpdateObserver> scoreUpdateObserverMutable = - new GeneralUtil.Mutable<>(); - GeneralUtil.Mutable<Integer> sessionIdMutable = new GeneralUtil.Mutable<>(); - IWifiConnectedNetworkScorer.Stub connectedScorer = - new IWifiConnectedNetworkScorer.Stub() { - @Override - public void onStart(int sessionId) { - sessionIdMutable.value = sessionId; - countDownLatch.countDown(); - } - @Override - public void onStop(int sessionId) { - // clear the external scorer on disconnect. - mWifiService.clearWifiConnectedNetworkScorer(); - } - @Override - public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) { - scoreUpdateObserverMutable.value = observerImpl; - countDownLatch.countDown(); - } - }; - mWifiService.clearWifiConnectedNetworkScorer(); // clear any previous scorer - if (mWifiService.setWifiConnectedNetworkScorer(new Binder(), connectedScorer)) { - // wait for retrieving the session id & score observer. - countDownLatch.await(1000, TimeUnit.MILLISECONDS); - } - if (scoreUpdateObserverMutable.value == null - || sessionIdMutable.value == null) { - pw.println("Did not receive session id and/or the score update observer. " - + "Is the device connected to a wifi network?"); - mWifiService.clearWifiConnectedNetworkScorer(); - return -1; - } - pw.println("Updating score: " + score + " for session id: " - + sessionIdMutable.value); - try { - scoreUpdateObserverMutable.value.notifyScoreUpdate( - sessionIdMutable.value, score); - } catch (RemoteException e) { - pw.println("Failed to send the score update"); - mWifiService.clearWifiConnectedNetworkScorer(); - return -1; - } - return 0; - } - case "reset-connected-score": { - mWifiService.clearWifiConnectedNetworkScorer(); // clear any previous scorer - return 0; - } - default: - return handleDefaultCommands(cmd); - } - } catch (IllegalArgumentException e) { - pw.println("Invalid args for " + cmd + ": " + e); - return -1; - } catch (Exception e) { - pw.println("Exception while executing WifiShellCommand: "); - e.printStackTrace(pw); - return -1; - } - } - - private boolean getNextArgRequiredTrueOrFalse(String trueString, String falseString) - throws IllegalArgumentException { - String nextArg = getNextArgRequired(); - if (trueString.equals(nextArg)) { - return true; - } else if (falseString.equals(nextArg)) { - return false; - } else { - throw new IllegalArgumentException("Expected '" + trueString + "' or '" + falseString - + "' as next arg but got '" + nextArg + "'"); - } - } - - private WifiConfiguration buildWifiConfiguration(PrintWriter pw) { - String ssid = getNextArgRequired(); - String type = getNextArgRequired(); - WifiConfiguration configuration = new WifiConfiguration(); - configuration.SSID = "\"" + ssid + "\""; - if (TextUtils.equals(type, "wpa3")) { - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); - configuration.preSharedKey = "\"" + getNextArgRequired() + "\""; - } else if (TextUtils.equals(type, "wpa2")) { - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); - configuration.preSharedKey = "\"" + getNextArgRequired() + "\""; - } else if (TextUtils.equals(type, "owe")) { - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE); - } else if (TextUtils.equals(type, "open")) { - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); - } else { - throw new IllegalArgumentException("Unknown network type " + type); - } - String option = getNextOption(); - while (option != null) { - if (option.equals("-m")) { - configuration.meteredOverride = METERED_OVERRIDE_METERED; - } else if (option.equals("-d")) { - configuration.allowAutojoin = false; - } else if (option.equals("-b")) { - configuration.BSSID = getNextArgRequired(); - } else { - pw.println("Ignoring unknown option " + option); - } - option = getNextOption(); - } - return configuration; - } - - private SoftApConfiguration buildSoftApConfiguration(PrintWriter pw) { - String ssid = getNextArgRequired(); - String type = getNextArgRequired(); - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid("\"" + ssid + "\""); - if (TextUtils.equals(type, "wpa2")) { - configBuilder.setPassphrase(getNextArgRequired(), - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - } else if (TextUtils.equals(type, "open")) { - configBuilder.setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN); - } else { - throw new IllegalArgumentException("Unknown network type " + type); - } - String option = getNextOption(); - while (option != null) { - if (option.equals("-b")) { - String preferredBand = getNextArgRequired(); - if (preferredBand.equals("2")) { - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - } else if (preferredBand.equals("5")) { - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - } else if (preferredBand.equals("6")) { - configBuilder.setBand(SoftApConfiguration.BAND_6GHZ); - } else if (preferredBand.equals("any")) { - configBuilder.setBand(SoftApConfiguration.BAND_ANY); - } else { - throw new IllegalArgumentException("Invalid band option " + preferredBand); - } - } else { - pw.println("Ignoring unknown option " + option); - } - option = getNextOption(); - } - return configBuilder.build(); - } - - private WifiNetworkSuggestion buildSuggestion(PrintWriter pw) { - String ssid = getNextArgRequired(); - String type = getNextArgRequired(); - WifiNetworkSuggestion.Builder suggestionBuilder = - new WifiNetworkSuggestion.Builder(); - suggestionBuilder.setSsid(ssid); - if (TextUtils.equals(type, "wpa3")) { - suggestionBuilder.setWpa3Passphrase(getNextArgRequired()); - } else if (TextUtils.equals(type, "wpa2")) { - suggestionBuilder.setWpa2Passphrase(getNextArgRequired()); - } else if (TextUtils.equals(type, "owe")) { - suggestionBuilder.setIsEnhancedOpen(true); - } else if (TextUtils.equals(type, "open")) { - // nothing to do. - } else { - throw new IllegalArgumentException("Unknown network type " + type); - } - String option = getNextOption(); - while (option != null) { - if (option.equals("-u")) { - suggestionBuilder.setUntrusted(true); - } else if (option.equals("-m")) { - suggestionBuilder.setIsMetered(true); - } else if (option.equals("-s")) { - suggestionBuilder.setCredentialSharedWithUser(true); - } else if (option.equals("-d")) { - suggestionBuilder.setIsInitialAutojoinEnabled(false); - } else if (option.equals("-b")) { - suggestionBuilder.setBssid(MacAddress.fromString(getNextArgRequired())); - } else { - pw.println("Ignoring unknown option " + option); - } - option = getNextOption(); - } - return suggestionBuilder.build(); - } - - private NetworkRequest buildNetworkRequest(PrintWriter pw) { - String ssid = getNextArgRequired(); - String type = getNextArgRequired(); - WifiNetworkSpecifier.Builder specifierBuilder = - new WifiNetworkSpecifier.Builder(); - specifierBuilder.setSsid(ssid); - if (TextUtils.equals(type, "wpa3")) { - specifierBuilder.setWpa3Passphrase(getNextArgRequired()); - } else if (TextUtils.equals(type, "wpa2")) { - specifierBuilder.setWpa2Passphrase(getNextArgRequired()); - } else if (TextUtils.equals(type, "owe")) { - specifierBuilder.setIsEnhancedOpen(true); - } else if (TextUtils.equals(type, "open")) { - // nothing to do. - } else { - throw new IllegalArgumentException("Unknown network type " + type); - } - String bssid = null; - String option = getNextOption(); - while (option != null) { - if (option.equals("-b")) { - bssid = getNextArgRequired(); - } else { - pw.println("Ignoring unknown option " + option); - } - option = getNextOption(); - } - - // Permission approval bypass is only available to requests with both ssid & bssid set. - // So, find scan result with the best rssi level to set in the request. - if (bssid == null) { - ScanResult matchingScanResult = - mWifiService.getScanResults(SHELL_PACKAGE_NAME, null) - .stream() - .filter(s -> s.SSID.equals(ssid)) - .max(Comparator.comparingInt(s -> s.level)) - .orElse(null); - if (matchingScanResult != null) { - bssid = matchingScanResult.BSSID; - } else { - pw.println("No matching bssid found, request will need UI approval"); - } - } - if (bssid != null) specifierBuilder.setBssid(MacAddress.fromString(bssid)); - return new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI) - .removeCapability(NET_CAPABILITY_INTERNET) - .setNetworkSpecifier(specifierBuilder.build()) - .build(); - } - - private void setAutoJoin(PrintWriter pw, String ssid, boolean allowAutojoin) { - // For suggestions, this will work only if the config has already been added - // to WifiConfigManager. - WifiConfiguration retrievedConfig = - mWifiService.getPrivilegedConfiguredNetworks(SHELL_PACKAGE_NAME, null) - .getList() - .stream() - .filter(n -> n.SSID.equals(ssid)) - .findAny() - .orElse(null); - if (retrievedConfig == null) { - pw.println("Cannot retrieve config, autojoin setting skipped."); - return; - } - mWifiService.allowAutojoin(retrievedConfig.networkId, allowAutojoin); - } - - private int sendLinkProbe(PrintWriter pw) throws InterruptedException { - // Note: should match WifiNl80211Manager#SEND_MGMT_FRAME_TIMEOUT_MS - final int sendMgmtFrameTimeoutMs = 1000; - - ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1); - mClientModeImpl.probeLink(new WifiNl80211Manager.SendMgmtFrameCallback() { - @Override - public void onAck(int elapsedTimeMs) { - queue.offer("Link probe succeeded after " + elapsedTimeMs + " ms"); - } - - @Override - public void onFailure(int reason) { - queue.offer("Link probe failed with reason " + reason); - } - }, -1); - - // block until msg is received, or timed out - String msg = queue.poll(sendMgmtFrameTimeoutMs + 1000, TimeUnit.MILLISECONDS); - if (msg == null) { - pw.println("Link probe timed out"); - } else { - pw.println(msg); - } - return 0; - } - - private boolean isApChannelMHzValid(int apChannelMHz) { - int[] allowed2gFreq = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ); - int[] allowed5gFreq = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ); - int[] allowed5gDfsFreq = - mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY); - int[] allowed6gFreq = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ); - if (allowed2gFreq == null) { - allowed2gFreq = new int[0]; - } - if (allowed5gFreq == null) { - allowed5gFreq = new int[0]; - } - if (allowed5gDfsFreq == null) { - allowed5gDfsFreq = new int[0]; - } - if (allowed6gFreq == null) { - allowed6gFreq = new int[0]; - } - - return (Arrays.binarySearch(allowed2gFreq, apChannelMHz) >= 0 - || Arrays.binarySearch(allowed5gFreq, apChannelMHz) >= 0 - || Arrays.binarySearch(allowed5gDfsFreq, apChannelMHz) >= 0) - || Arrays.binarySearch(allowed6gFreq, apChannelMHz) >= 0; - } - - private void printStatus(PrintWriter pw) { - boolean wifiEnabled = mWifiService.getWifiEnabledState() == WIFI_STATE_ENABLED; - pw.println("Wifi is " + (wifiEnabled ? "enabled" : "disabled")); - pw.println("Wifi scanning is " - + (mWifiService.isScanAlwaysAvailable() - ? "always available" : "only available when wifi is enabled")); - if (!wifiEnabled) { - return; - } - WifiInfo info = mWifiService.getConnectionInfo(SHELL_PACKAGE_NAME, null); - if (info.getSupplicantState() != SupplicantState.COMPLETED) { - pw.println("Wifi is not connected"); - return; - } - pw.println("Wifi is connected to " + info.getSSID()); - pw.println("WifiInfo: " + info); - // additional diagnostics not printed by WifiInfo.toString() - pw.println("successfulTxPackets: " + info.txSuccess); - pw.println("successfulTxPacketsPerSecond: " + info.getSuccessfulTxPacketsPerSecond()); - pw.println("retriedTxPackets: " + info.txRetries); - pw.println("retriedTxPacketsPerSecond: " + info.getRetriedTxPacketsPerSecond()); - pw.println("lostTxPackets: " + info.txBad); - pw.println("lostTxPacketsPerSecond: " + info.getLostTxPacketsPerSecond()); - pw.println("successfulRxPackets: " + info.rxSuccess); - pw.println("successfulRxPacketsPerSecond: " + info.getSuccessfulRxPacketsPerSecond()); - - Network network = mWifiService.getCurrentNetwork(); - try { - NetworkCapabilities capabilities = mConnectivityManager.getNetworkCapabilities(network); - pw.println("NetworkCapabilities: " + capabilities); - } catch (SecurityException e) { - // ignore on unrooted shell. - } - } - - private void onHelpNonPrivileged(PrintWriter pw) { - pw.println(" get-country-code"); - pw.println(" Gets country code as a two-letter string"); - pw.println(" set-wifi-enabled enabled|disabled"); - pw.println(" Enables/disables Wifi on this device."); - pw.println(" set-scan-always-available enabled|disabled"); - pw.println(" Sets whether scanning should be available even when wifi is off."); - pw.println(" list-scan-results"); - pw.println(" Lists the latest scan results"); - pw.println(" start-scan"); - pw.println(" Start a new scan"); - pw.println(" list-networks"); - pw.println(" Lists the saved networks"); - pw.println(" connect-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m] [-d] " - + "[-b <bssid>]"); - pw.println(" Connect to a network with provided params and add to saved networks list"); - pw.println(" <ssid> - SSID of the network"); - pw.println(" open|owe|wpa2|wpa3 - Security type of the network."); - pw.println(" - Use 'open' or 'owe' for networks with no passphrase"); - pw.println(" - 'open' - Open networks (Most prevalent)"); - pw.println(" - 'owe' - Enhanced open networks"); - pw.println(" - Use 'wpa2' or 'wpa3' for networks with passphrase"); - pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); - pw.println(" - 'wpa3' - WPA-3 PSK networks"); - pw.println(" -m - Mark the network metered."); - pw.println(" -d - Mark the network autojoin disabled."); - pw.println(" -b <bssid> - Set specific BSSID."); - pw.println(" add-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m] [-d] " - + "[-b <bssid>]"); - pw.println(" Add/update saved network with provided params"); - pw.println(" <ssid> - SSID of the network"); - pw.println(" open|owe|wpa2|wpa3 - Security type of the network."); - pw.println(" - Use 'open' or 'owe' for networks with no passphrase"); - pw.println(" - 'open' - Open networks (Most prevalent)"); - pw.println(" - 'owe' - Enhanced open networks"); - pw.println(" - Use 'wpa2' or 'wpa3' for networks with passphrase"); - pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); - pw.println(" - 'wpa3' - WPA-3 PSK networks"); - pw.println(" -m - Mark the network metered."); - pw.println(" -d - Mark the network autojoin disabled."); - pw.println(" -b <bssid> - Set specific BSSID."); - pw.println(" forget-network <networkId>"); - pw.println(" Remove the network mentioned by <networkId>"); - pw.println(" - Use list-networks to retrieve <networkId> for the network"); - pw.println(" status"); - pw.println(" Current wifi status"); - pw.println(" set-verbose-logging enabled|disabled "); - pw.println(" Set the verbose logging enabled or disabled"); - pw.println(" add-suggestion <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-u] [-m] [-s] [-d]" - + "[-b <bssid>]"); - pw.println(" Add a network suggestion with provided params"); - pw.println(" Use 'network-suggestions-set-user-approved " + SHELL_PACKAGE_NAME + " yes'" - + " to approve suggestions added via shell (Needs root access)"); - pw.println(" <ssid> - SSID of the network"); - pw.println(" open|owe|wpa2|wpa3 - Security type of the network."); - pw.println(" - Use 'open' or 'owe' for networks with no passphrase"); - pw.println(" - 'open' - Open networks (Most prevalent)"); - pw.println(" - 'owe' - Enhanced open networks"); - pw.println(" - Use 'wpa2' or 'wpa3' for networks with passphrase"); - pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); - pw.println(" - 'wpa3' - WPA-3 PSK networks"); - pw.println(" -u - Mark the suggestion untrusted."); - pw.println(" -m - Mark the suggestion metered."); - pw.println(" -s - Share the suggestion with user."); - pw.println(" -d - Mark the suggestion autojoin disabled."); - pw.println(" -b <bssid> - Set specific BSSID."); - pw.println(" remove-suggestion <ssid>"); - pw.println(" Remove a network suggestion with provided SSID of the network"); - pw.println(" remove-all-suggestions"); - pw.println(" Removes all suggestions added via shell"); - pw.println(" list-suggestions"); - pw.println(" Lists the suggested networks added via shell"); - pw.println(" set-connected-score <score>"); - pw.println(" Set connected wifi network score (to choose between LTE & Wifi for " - + "default route)."); - pw.println(" This turns off the active connected scorer (default or external)."); - pw.println(" Only works while connected to a wifi network. This score will stay in " - + "effect until you call reset-connected-score or the device disconnects from the " - + "current network."); - pw.println(" <score> - Integer score should be in the range of 0 - 60"); - pw.println(" reset-connected-score"); - pw.println(" Turns on the default connected scorer."); - pw.println(" Note: Will clear any external scorer set."); - pw.println(" start-softap <ssid> (open|wpa2) <passphrase> [-b 2|5|6|any]"); - pw.println(" Start softap with provided params"); - pw.println(" Note that the shell command doesn't activate internet tethering. In some " - + "devices, internet sharing is possible when Wi-Fi STA is also enabled and is" - + "associated to another AP with internet access."); - pw.println(" <ssid> - SSID of the network"); - pw.println(" open|wpa2 - Security type of the network."); - pw.println(" - Use 'open' for networks with no passphrase"); - pw.println(" - Use 'wpa2' for networks with passphrase"); - pw.println(" -b 2|5|6|any - select the preferred band."); - pw.println(" - Use '2' to select 2.4GHz band as the preferred band"); - pw.println(" - Use '5' to select 5GHz band as the preferred band"); - pw.println(" - Use '6' to select 6GHz band as the preferred band"); - pw.println(" - Use 'any' to indicate no band preference"); - pw.println(" Note: If the band option is not provided, 2.4GHz is the preferred band."); - pw.println(" The exact channel is auto-selected by FW unless overridden by " - + "force-softap-channel command"); - pw.println(" stop-softap"); - pw.println(" Stop softap (hotspot)"); - } - - private void onHelpPrivileged(PrintWriter pw) { - pw.println(" set-ipreach-disconnect enabled|disabled"); - pw.println(" Sets whether CMD_IP_REACHABILITY_LOST events should trigger disconnects."); - pw.println(" get-ipreach-disconnect"); - pw.println(" Gets setting of CMD_IP_REACHABILITY_LOST events triggering disconnects."); - pw.println(" set-poll-rssi-interval-msecs <int>"); - pw.println(" Sets the interval between RSSI polls to <int> milliseconds."); - pw.println(" get-poll-rssi-interval-msecs"); - pw.println(" Gets current interval between RSSI polls, in milliseconds."); - pw.println(" force-hi-perf-mode enabled|disabled"); - pw.println(" Sets whether hi-perf mode is forced or left for normal operation."); - pw.println(" force-low-latency-mode enabled|disabled"); - pw.println(" Sets whether low latency mode is forced or left for normal operation."); - pw.println(" network-suggestions-set-user-approved <package name> yes|no"); - pw.println(" Sets whether network suggestions from the app is approved or not."); - pw.println(" network-suggestions-has-user-approved <package name>"); - pw.println(" Queries whether network suggestions from the app is approved or not."); - pw.println(" imsi-protection-exemption-set-user-approved-for-carrier <carrier id> yes|no"); - pw.println(" Sets whether Imsi protection exemption for carrier is approved or not"); - pw.println(" imsi-protection-exemption-has-user-approved-for-carrier <carrier id>"); - pw.println(" Queries whether Imsi protection exemption for carrier is approved or not"); - pw.println(" imsi-protection-exemption-clear-user-approved-for-carrier <carrier id>"); - pw.println(" Clear the user choice on Imsi protection exemption for carrier"); - pw.println(" network-requests-remove-user-approved-access-points <package name>"); - pw.println(" Removes all user approved network requests for the app."); - pw.println(" clear-user-disabled-networks"); - pw.println(" Clears the user disabled networks list."); - pw.println(" send-link-probe"); - pw.println(" Manually triggers a link probe."); - pw.println(" force-softap-channel enabled <int> | disabled"); - pw.println(" Sets whether soft AP channel is forced to <int> MHz"); - pw.println(" or left for normal operation."); - pw.println(" force-country-code enabled <two-letter code> | disabled "); - pw.println(" Sets country code to <two-letter code> or left for normal value"); - pw.println(" set-wifi-watchdog enabled|disabled"); - pw.println(" Sets whether wifi watchdog should trigger recovery"); - pw.println(" get-wifi-watchdog"); - pw.println(" Gets setting of wifi watchdog trigger recovery."); - pw.println(" get-softap-supported-features"); - pw.println(" Gets softap supported features. Will print 'wifi_softap_acs_supported'"); - pw.println(" and/or 'wifi_softap_wpa3_sae_supported', each on a separate line."); - pw.println(" settings-reset"); - pw.println(" Initiates wifi settings reset"); - pw.println(" add-request <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-b <bssid>]"); - pw.println(" Add a network request with provided params"); - pw.println(" Use 'network-requests-set-user-approved android yes'" - + " to pre-approve requests added via rooted shell (Not persisted)"); - pw.println(" <ssid> - SSID of the network"); - pw.println(" open|owe|wpa2|wpa3 - Security type of the network."); - pw.println(" - Use 'open' or 'owe' for networks with no passphrase"); - pw.println(" - 'open' - Open networks (Most prevalent)"); - pw.println(" - 'owe' - Enhanced open networks"); - pw.println(" - Use 'wpa2' or 'wpa3' for networks with passphrase"); - pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); - pw.println(" - 'wpa3' - WPA-3 PSK networks"); - pw.println(" -b <bssid> - Set specific BSSID."); - pw.println(" remove-request <ssid>"); - pw.println(" Remove a network request with provided SSID of the network"); - pw.println(" remove-all-requests"); - pw.println(" Removes all active requests added via shell"); - pw.println(" list-requests"); - pw.println(" Lists the requested networks added via shell"); - pw.println(" network-requests-set-user-approved <package name> yes|no"); - pw.println(" Sets whether network requests from the app is approved or not."); - pw.println(" Note: Only 1 such app can be approved from the shell at a time"); - pw.println(" network-requests-has-user-approved <package name>"); - pw.println(" Queries whether network requests from the app is approved or not."); - pw.println(" Note: This only returns whether the app was set via the " + - "'network-requests-set-user-approved' shell command"); - } - - @Override - public void onHelp() { - final PrintWriter pw = getOutPrintWriter(); - pw.println("Wi-Fi (wifi) commands:"); - pw.println(" help or -h"); - pw.println(" Print this help text."); - onHelpNonPrivileged(pw); - if (Binder.getCallingUid() == Process.ROOT_UID) { - onHelpPrivileged(pw); - } - pw.println(); - } -} diff --git a/service/java/com/android/server/wifi/WifiStateTracker.java b/service/java/com/android/server/wifi/WifiStateTracker.java deleted file mode 100644 index c516a8f04..000000000 --- a/service/java/com/android/server/wifi/WifiStateTracker.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import android.os.BatteryStatsManager; -import android.util.Log; - -import java.util.concurrent.RejectedExecutionException; - -/** - * This class is used to track WifiState to update BatteryStats - */ -public class WifiStateTracker { - private static final String TAG = "WifiStateTracker"; - - public static final int INVALID = 0; - public static final int SCAN_MODE = 1; - public static final int DISCONNECTED = 2; - public static final int CONNECTED = 3; - public static final int SOFT_AP = 4; - private int mWifiState; - private BatteryStatsManager mBatteryStatsManager; - - public WifiStateTracker(BatteryStatsManager batteryStatsManager) { - mWifiState = INVALID; - mBatteryStatsManager = batteryStatsManager; - } - - private void informWifiStateBatteryStats(int state) { - try { - mBatteryStatsManager.reportWifiState(state, null); - } catch (RejectedExecutionException e) { - Log.e(TAG, "Battery stats executor is being shutdown " + e.getMessage()); - } - } - - /** - * Inform the WifiState to this tracker to translate into the - * WifiState corresponding to BatteryStatsManager. - * @param state state corresponding to the ClientModeImpl state - */ - public void updateState(int state) { - int reportState = BatteryStatsManager.WIFI_STATE_OFF; - if (state != mWifiState) { - switch(state) { - case SCAN_MODE: - reportState = BatteryStatsManager.WIFI_STATE_OFF_SCANNING; - break; - case DISCONNECTED: - reportState = BatteryStatsManager.WIFI_STATE_ON_DISCONNECTED; - break; - case CONNECTED: - reportState = BatteryStatsManager.WIFI_STATE_ON_CONNECTED_STA; - break; - case SOFT_AP: - reportState = BatteryStatsManager.WIFI_STATE_SOFT_AP; - break; - case INVALID: - mWifiState = INVALID; - /* Fall through */ - default: - return; - } - mWifiState = state; - informWifiStateBatteryStats(reportState); - } - return; - } -} diff --git a/service/java/com/android/server/wifi/WifiThreadRunner.java b/service/java/com/android/server/wifi/WifiThreadRunner.java deleted file mode 100644 index e478c82ca..000000000 --- a/service/java/com/android/server/wifi/WifiThreadRunner.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Handler; -import android.os.Looper; -import android.os.SystemClock; -import android.util.Log; - -import com.android.server.wifi.util.GeneralUtil.Mutable; - -import java.util.function.Supplier; - -import javax.annotation.concurrent.ThreadSafe; - -/** - * Runs code on one of the Wifi service threads from another thread (For ex: incoming AIDL call from - * a binder thread), in order to prevent race conditions. - * Note: This is a utility class and each wifi service may have separate instances of this class on - * their corresponding main thread for servicing incoming AIDL calls. - */ -@ThreadSafe -public class WifiThreadRunner { - private static final String TAG = "WifiThreadRunner"; - - /** Max wait time for posting blocking runnables */ - private static final int RUN_WITH_SCISSORS_TIMEOUT_MILLIS = 4000; - - private final Handler mHandler; - - public WifiThreadRunner(Handler handler) { - mHandler = handler; - } - - /** - * Synchronously runs code on the main Wifi thread and return a value. - * <b>Blocks</b> the calling thread until the callable completes execution on the main Wifi - * thread. - * - * BEWARE OF DEADLOCKS!!! - * - * @param <T> the return type - * @param supplier the lambda that should be run on the main Wifi thread - * e.g. wifiThreadRunner.call(() -> mWifiApConfigStore.getApConfiguration()) - * or wifiThreadRunner.call(mWifiApConfigStore::getApConfiguration) - * @param valueToReturnOnTimeout If the lambda provided could not be run within the timeout ( - * {@link #RUN_WITH_SCISSORS_TIMEOUT_MILLIS}), will return this provided value - * instead. - * @return value retrieved from Wifi thread, or |valueToReturnOnTimeout| if the call failed. - * Beware of NullPointerExceptions when expecting a primitive (e.g. int, long) return - * type, it may still return null and throw a NullPointerException when auto-unboxing! - * Recommend capturing the return value in an Integer or Long instead and explicitly - * handling nulls. - */ - @Nullable - public <T> T call(@NonNull Supplier<T> supplier, T valueToReturnOnTimeout) { - Mutable<T> result = new Mutable<>(); - boolean runWithScissorsSuccess = runWithScissors(mHandler, - () -> result.value = supplier.get(), - RUN_WITH_SCISSORS_TIMEOUT_MILLIS); - if (runWithScissorsSuccess) { - return result.value; - } else { - Log.e(TAG, "WifiThreadRunner.call() timed out!", new Throwable("Stack trace:")); - return valueToReturnOnTimeout; - } - } - - /** - * Runs a Runnable on the main Wifi thread and <b>blocks</b> the calling thread until the - * Runnable completes execution on the main Wifi thread. - * - * BEWARE OF DEADLOCKS!!! - * - * @return true if the runnable executed successfully, false otherwise - */ - public boolean run(@NonNull Runnable runnable) { - boolean runWithScissorsSuccess = - runWithScissors(mHandler, runnable, RUN_WITH_SCISSORS_TIMEOUT_MILLIS); - if (runWithScissorsSuccess) { - return true; - } else { - Log.e(TAG, "WifiThreadRunner.run() timed out!", new Throwable("Stack trace:")); - return false; - } - } - - /** - * Asynchronously runs a Runnable on the main Wifi thread. - * - * @return true if the runnable was successfully posted <b>(not executed)</b> to the main Wifi - * thread, false otherwise - */ - public boolean post(@NonNull Runnable runnable) { - return mHandler.post(runnable); - } - - // Note: @hide methods copied from android.os.Handler - /** - * Runs the specified task synchronously. - * <p> - * If the current thread is the same as the handler thread, then the runnable - * runs immediately without being enqueued. Otherwise, posts the runnable - * to the handler and waits for it to complete before returning. - * </p><p> - * This method is dangerous! Improper use can result in deadlocks. - * Never call this method while any locks are held or use it in a - * possibly re-entrant manner. - * </p><p> - * This method is occasionally useful in situations where a background thread - * must synchronously await completion of a task that must run on the - * handler's thread. However, this problem is often a symptom of bad design. - * Consider improving the design (if possible) before resorting to this method. - * </p><p> - * One example of where you might want to use this method is when you just - * set up a Handler thread and need to perform some initialization steps on - * it before continuing execution. - * </p><p> - * If timeout occurs then this method returns <code>false</code> but the runnable - * will remain posted on the handler and may already be in progress or - * complete at a later time. - * </p><p> - * When using this method, be sure to use {@link Looper#quitSafely} when - * quitting the looper. Otherwise {@link #runWithScissors} may hang indefinitely. - * (TODO: We should fix this by making MessageQueue aware of blocking runnables.) - * </p> - * - * @param r The Runnable that will be executed synchronously. - * @param timeout The timeout in milliseconds, or 0 to wait indefinitely. - * - * @return Returns true if the Runnable was successfully executed. - * Returns false on failure, usually because the - * looper processing the message queue is exiting. - * - * @hide This method is prone to abuse and should probably not be in the API. - * If we ever do make it part of the API, we might want to rename it to something - * less funny like runUnsafe(). - */ - private static boolean runWithScissors(@NonNull Handler handler, @NonNull Runnable r, - long timeout) { - if (r == null) { - throw new IllegalArgumentException("runnable must not be null"); - } - if (timeout < 0) { - throw new IllegalArgumentException("timeout must be non-negative"); - } - - if (Looper.myLooper() == handler.getLooper()) { - r.run(); - return true; - } - - BlockingRunnable br = new BlockingRunnable(r); - return br.postAndWait(handler, timeout); - } - - private static final class BlockingRunnable implements Runnable { - private final Runnable mTask; - private boolean mDone; - - BlockingRunnable(Runnable task) { - mTask = task; - } - - @Override - public void run() { - try { - mTask.run(); - } finally { - synchronized (this) { - mDone = true; - notifyAll(); - } - } - } - - public boolean postAndWait(Handler handler, long timeout) { - if (!handler.post(this)) { - return false; - } - - synchronized (this) { - if (timeout > 0) { - final long expirationTime = SystemClock.uptimeMillis() + timeout; - while (!mDone) { - long delay = expirationTime - SystemClock.uptimeMillis(); - if (delay <= 0) { - return false; // timeout - } - try { - wait(delay); - } catch (InterruptedException ex) { - } - } - } else { - while (!mDone) { - try { - wait(); - } catch (InterruptedException ex) { - } - } - } - } - return true; - } - } -} diff --git a/service/java/com/android/server/wifi/WifiTrafficPoller.java b/service/java/com/android/server/wifi/WifiTrafficPoller.java deleted file mode 100644 index 8349f7b13..000000000 --- a/service/java/com/android/server/wifi/WifiTrafficPoller.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2013 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.server.wifi; - -import android.annotation.NonNull; -import android.net.wifi.ITrafficStateCallback; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import com.android.server.wifi.util.ExternalCallbackTracker; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Polls for traffic stats and notifies the clients - */ -public class WifiTrafficPoller { - private static final String TAG = "WifiTrafficPoller"; - - private long mTxPkts = 0; - private long mRxPkts = 0; - - private int mLastActivity = -1; - - private static class CallbackWrapper { - public final ITrafficStateCallback callback; - /** - * On the first invocation, the callback is invoked no matter if the data activity changed - * or not. - */ - public boolean isFirstInvocation = true; - - CallbackWrapper(ITrafficStateCallback callback) { - this.callback = callback; - } - } - - private final ExternalCallbackTracker<CallbackWrapper> mRegisteredCallbacks; - - public WifiTrafficPoller(@NonNull Handler handler) { - mRegisteredCallbacks = new ExternalCallbackTracker<>(handler); - } - - /** - * Add a new callback to the traffic poller. - */ - public void addCallback(IBinder binder, ITrafficStateCallback callback, int callbackId) { - if (!mRegisteredCallbacks.add(binder, new CallbackWrapper(callback), callbackId)) { - Log.e(TAG, "Failed to add callback"); - } - } - - /** - * Remove an existing callback from the traffic poller. - */ - public void removeCallback(int callbackId) { - mRegisteredCallbacks.remove(callbackId); - } - - /** - * Notifies clients of data activity if the activity changed since the last update. - */ - public void notifyOnDataActivity(long newTxPkts, long newRxPkts) { - if (newTxPkts <= 0 && newRxPkts <= 0) { - return; - } - - long sent = newTxPkts - mTxPkts; - long received = newRxPkts - mRxPkts; - int dataActivity = WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE; - if (sent > 0) { - dataActivity |= WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT; - } - if (received > 0) { - dataActivity |= WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN; - } - - for (CallbackWrapper wrapper : mRegisteredCallbacks.getCallbacks()) { - // if this callback hasn't been triggered before, or the data activity changed, - // notify the callback - if (wrapper.isFirstInvocation || dataActivity != mLastActivity) { - wrapper.isFirstInvocation = false; - try { - wrapper.callback.onStateChanged(dataActivity); - } catch (RemoteException e) { - // Failed to reach, skip - // Client removal is handled in WifiService - } - } - } - - mTxPkts = newTxPkts; - mRxPkts = newRxPkts; - mLastActivity = dataActivity; - } - - /** - * Dump method for traffic poller. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("mTxPkts " + mTxPkts); - pw.println("mRxPkts " + mRxPkts); - pw.println("mLastActivity " + mLastActivity); - pw.println("mRegisteredCallbacks " + mRegisteredCallbacks.getNumCallbacks()); - } -} diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java deleted file mode 100644 index fd90c35df..000000000 --- a/service/java/com/android/server/wifi/WifiVendorHal.java +++ /dev/null @@ -1,3115 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.annotation.NonNull; -import android.hardware.wifi.V1_0.IWifiApIface; -import android.hardware.wifi.V1_0.IWifiChip; -import android.hardware.wifi.V1_0.IWifiChipEventCallback; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiStaIface; -import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.StaBackgroundScanBucketEventReportSchemeMask; -import android.hardware.wifi.V1_0.StaBackgroundScanBucketParameters; -import android.hardware.wifi.V1_0.StaBackgroundScanParameters; -import android.hardware.wifi.V1_0.StaLinkLayerIfaceStats; -import android.hardware.wifi.V1_0.StaLinkLayerRadioStats; -import android.hardware.wifi.V1_0.StaLinkLayerStats; -import android.hardware.wifi.V1_0.StaRoamingConfig; -import android.hardware.wifi.V1_0.StaRoamingState; -import android.hardware.wifi.V1_0.StaScanData; -import android.hardware.wifi.V1_0.StaScanDataFlagMask; -import android.hardware.wifi.V1_0.StaScanResult; -import android.hardware.wifi.V1_0.WifiBand; -import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; -import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; -import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags; -import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; -import android.hardware.wifi.V1_0.WifiDebugRxPacketFate; -import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport; -import android.hardware.wifi.V1_0.WifiDebugTxPacketFate; -import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport; -import android.hardware.wifi.V1_0.WifiInformationElement; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_2.IWifiChipEventCallback.IfaceInfo; -import android.net.MacAddress; -import android.net.apf.ApfCapabilities; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; -import android.util.MutableBoolean; -import android.util.MutableLong; -import android.util.SparseArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.HexDump; -import com.android.internal.util.Preconditions; -import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; -import com.android.server.wifi.WifiLinkLayerStats.ChannelStats; -import com.android.server.wifi.util.ArrayUtils; -import com.android.server.wifi.util.BitMask; -import com.android.server.wifi.util.NativeUtil; - -import com.google.errorprone.annotations.CompileTimeConstant; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Vendor HAL via HIDL - */ -public class WifiVendorHal { - - private static final WifiLog sNoLog = new FakeWifiLog(); - - /** - * Chatty logging should use mVerboseLog - */ - @VisibleForTesting - WifiLog mVerboseLog = sNoLog; - - /** - * Errors should use mLog - */ - @VisibleForTesting - WifiLog mLog = new LogcatLog("WifiVendorHal"); - - /** - * Enables or disables verbose logging - * - * @param verbose - with the obvious interpretation - */ - public void enableVerboseLogging(boolean verbose) { - synchronized (sLock) { - if (verbose) { - mVerboseLog = mLog; - enter("verbose=true").flush(); - } else { - enter("verbose=false").flush(); - mVerboseLog = sNoLog; - } - } - } - - /** - * Checks for a successful status result. - * - * Failures are logged to mLog. - * - * @param status is the WifiStatus generated by a hal call - * @return true for success, false for failure - */ - private boolean ok(WifiStatus status) { - if (status.code == WifiStatusCode.SUCCESS) return true; - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mLog.err("% failed %") - .c(niceMethodName(trace, 3)) - .c(status.toString()) - .flush(); - - return false; - } - - /** - * Logs the argument along with the method name. - * - * Always returns its argument. - */ - private boolean boolResult(boolean result) { - if (mVerboseLog == sNoLog) return result; - // Currently only seen if verbose logging is on - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mVerboseLog.err("% returns %") - .c(niceMethodName(trace, 3)) - .c(result) - .flush(); - - return result; - } - - /** - * Logs the argument along with the method name. - * - * Always returns its argument. - */ - private String stringResult(String result) { - if (mVerboseLog == sNoLog) return result; - // Currently only seen if verbose logging is on - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mVerboseLog.err("% returns %") - .c(niceMethodName(trace, 3)) - .c(result) - .flush(); - - return result; - } - - /** - * Logs the argument along with the method name. - * - * Always returns its argument. - */ - private byte[] byteArrayResult(byte[] result) { - if (mVerboseLog == sNoLog) return result; - // Currently only seen if verbose logging is on - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mVerboseLog.err("% returns %") - .c(niceMethodName(trace, 3)) - .c(result == null ? "(null)" : HexDump.dumpHexString(result)) - .flush(); - - return result; - } - - /** - * Logs at method entry - * - * @param format string with % placeholders - * @return LogMessage formatter (remember to .flush()) - */ - private WifiLog.LogMessage enter(@CompileTimeConstant final String format) { - if (mVerboseLog == sNoLog) return sNoLog.info(format); - return mVerboseLog.trace(format, 1); - } - - /** - * Gets the method name and line number from a stack trace. - * - * Attempts to skip frames created by lambdas to get a human-sensible name. - * - * @param trace, fo example obtained by Thread.currentThread().getStackTrace() - * @param start frame number to log, typically 3 - * @return string containing the method name and line number - */ - private static String niceMethodName(StackTraceElement[] trace, int start) { - if (start >= trace.length) return ""; - StackTraceElement s = trace[start]; - String name = s.getMethodName(); - if (name.contains("lambda$")) { - // Try to find a friendlier method name - String myFile = s.getFileName(); - if (myFile != null) { - for (int i = start + 1; i < trace.length; i++) { - if (myFile.equals(trace[i].getFileName())) { - name = trace[i].getMethodName(); - break; - } - } - } - } - return (name + "(l." + s.getLineNumber() + ")"); - } - - // Vendor HAL HIDL interface objects. - private IWifiChip mIWifiChip; - private HashMap<String, IWifiStaIface> mIWifiStaIfaces = new HashMap<>(); - private HashMap<String, IWifiApIface> mIWifiApIfaces = new HashMap<>(); - private HalDeviceManager.InterfaceAvailableForRequestListener - mStaIfaceAvailableForRequestListener; - private HalDeviceManager.InterfaceAvailableForRequestListener - mApIfaceAvailableForRequestListener; - private final HalDeviceManager mHalDeviceManager; - private final HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; - private final IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback; - private final ChipEventCallback mIWifiChipEventCallback; - private final ChipEventCallbackV12 mIWifiChipEventCallbackV12; - private final ChipEventCallbackV14 mIWifiChipEventCallbackV14; - - // Plumbing for event handling. - // - // Being final fields, they can be accessed without synchronization under - // some reasonable assumptions. See - // https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5 - private final Handler mHalEventHandler; - - public WifiVendorHal(HalDeviceManager halDeviceManager, Handler handler) { - mHalDeviceManager = halDeviceManager; - mHalEventHandler = handler; - mHalDeviceManagerStatusCallbacks = new HalDeviceManagerStatusListener(); - mIWifiStaIfaceEventCallback = new StaIfaceEventCallback(); - mIWifiChipEventCallback = new ChipEventCallback(); - mIWifiChipEventCallbackV12 = new ChipEventCallbackV12(); - mIWifiChipEventCallbackV14 = new ChipEventCallbackV14(); - } - - public static final Object sLock = new Object(); - - private void handleRemoteException(RemoteException e) { - String methodName = niceMethodName(Thread.currentThread().getStackTrace(), 3); - mVerboseLog.err("% RemoteException in HIDL call %").c(methodName).c(e.toString()).flush(); - clearState(); - } - - private WifiNative.VendorHalDeathEventHandler mDeathEventHandler; - - /** - * Initialize the Hal device manager and register for status callbacks. - * - * @param handler Handler to notify if the vendor HAL dies. - * @return true on success, false otherwise. - */ - public boolean initialize(WifiNative.VendorHalDeathEventHandler handler) { - synchronized (sLock) { - mHalDeviceManager.initialize(); - mHalDeviceManager.registerStatusListener( - mHalDeviceManagerStatusCallbacks, mHalEventHandler); - mDeathEventHandler = handler; - return true; - } - } - - private WifiNative.VendorHalRadioModeChangeEventHandler mRadioModeChangeEventHandler; - - /** - * Register to listen for radio mode change events from the HAL. - * - * @param handler Handler to notify when the vendor HAL detects a radio mode change. - */ - public void registerRadioModeChangeHandler( - WifiNative.VendorHalRadioModeChangeEventHandler handler) { - synchronized (sLock) { - mRadioModeChangeEventHandler = handler; - } - } - - /** - * Returns whether the vendor HAL is supported on this device or not. - */ - public boolean isVendorHalSupported() { - synchronized (sLock) { - return mHalDeviceManager.isSupported(); - } - } - - /** - * Bring up the HIDL Vendor HAL and configure for AP (Access Point) mode - * - * @return true for success - */ - public boolean startVendorHalAp() { - synchronized (sLock) { - if (!startVendorHal()) { - return false; - } - if (TextUtils.isEmpty(createApIface(null))) { - stopVendorHal(); - return false; - } - return true; - } - } - - /** - * Bring up the HIDL Vendor HAL and configure for STA (Station) mode - * - * @return true for success - */ - public boolean startVendorHalSta() { - synchronized (sLock) { - if (!startVendorHal()) { - return false; - } - if (TextUtils.isEmpty(createStaIface(null))) { - stopVendorHal(); - return false; - } - return true; - } - } - - /** - * Bring up the HIDL Vendor HAL. - * @return true on success, false otherwise. - */ - public boolean startVendorHal() { - synchronized (sLock) { - if (!mHalDeviceManager.start()) { - mLog.err("Failed to start vendor HAL").flush(); - return false; - } - mLog.info("Vendor Hal started successfully").flush(); - return true; - } - } - - /** - * Register a STA iface availability listener listed with {@link HalDeviceManager}. - * - * @param listener Instance of {@link WifiNative.InterfaceAvailableForRequestListener}. - */ - public void registerStaIfaceAvailabilityListener( - @NonNull WifiNative.InterfaceAvailableForRequestListener listener) { - synchronized (sLock) { - Preconditions.checkState(mStaIfaceAvailableForRequestListener == null); - mStaIfaceAvailableForRequestListener = - (isAvailable) -> listener.onAvailabilityChanged(isAvailable); - if (mHalDeviceManager.isStarted()) { - mHalDeviceManager.registerInterfaceAvailableForRequestListener( - IfaceType.STA, mStaIfaceAvailableForRequestListener, - mHalEventHandler); - } - } - } - - /** - * Register a AP iface availability listener listed with {@link HalDeviceManager}. - * - * @param listener Instance of {@link WifiNative.InterfaceAvailableForRequestListener}. - * - */ - public void registerApIfaceAvailabilityListener( - @NonNull WifiNative.InterfaceAvailableForRequestListener listener) { - synchronized (sLock) { - Preconditions.checkState(mApIfaceAvailableForRequestListener == null); - mApIfaceAvailableForRequestListener = - (isAvailable) -> listener.onAvailabilityChanged(isAvailable); - if (mHalDeviceManager.isStarted()) { - mHalDeviceManager.registerInterfaceAvailableForRequestListener( - IfaceType.AP, mApIfaceAvailableForRequestListener, - mHalEventHandler); - } - } - } - - /** Helper method to lookup the corresponding STA iface object using iface name. */ - private IWifiStaIface getStaIface(@NonNull String ifaceName) { - synchronized (sLock) { - return mIWifiStaIfaces.get(ifaceName); - } - } - - private class StaInterfaceDestroyedListenerInternal implements InterfaceDestroyedListener { - private final InterfaceDestroyedListener mExternalListener; - - StaInterfaceDestroyedListenerInternal(InterfaceDestroyedListener externalListener) { - mExternalListener = externalListener; - } - - @Override - public void onDestroyed(@NonNull String ifaceName) { - synchronized (sLock) { - mIWifiStaIfaces.remove(ifaceName); - } - if (mExternalListener != null) { - mExternalListener.onDestroyed(ifaceName); - } - } - } - - /** - * Create a STA iface using {@link HalDeviceManager}. - * - * @param destroyedListener Listener to be invoked when the interface is destroyed. - * @return iface name on success, null otherwise. - */ - public String createStaIface(InterfaceDestroyedListener destroyedListener) { - synchronized (sLock) { - IWifiStaIface iface = mHalDeviceManager.createStaIface( - new StaInterfaceDestroyedListenerInternal(destroyedListener), null); - if (iface == null) { - mLog.err("Failed to create STA iface").flush(); - return stringResult(null); - } - String ifaceName = mHalDeviceManager.getName((IWifiIface) iface); - if (TextUtils.isEmpty(ifaceName)) { - mLog.err("Failed to get iface name").flush(); - return stringResult(null); - } - if (!registerStaIfaceCallback(iface)) { - mLog.err("Failed to register STA iface callback").flush(); - return stringResult(null); - } - if (!retrieveWifiChip((IWifiIface) iface)) { - mLog.err("Failed to get wifi chip").flush(); - return stringResult(null); - } - enableLinkLayerStats(iface); - mIWifiStaIfaces.put(ifaceName, iface); - return ifaceName; - } - } - - /** - * Remove a STA iface using {@link HalDeviceManager}. - * - * @param ifaceName Name of the interface being removed. - * @return true on success, false otherwise. - */ - public boolean removeStaIface(@NonNull String ifaceName) { - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - - if (!mHalDeviceManager.removeIface((IWifiIface) iface)) { - mLog.err("Failed to remove STA iface").flush(); - return boolResult(false); - } - mIWifiStaIfaces.remove(ifaceName); - return true; - } - } - - /** Helper method to lookup the corresponding AP iface object using iface name. */ - private IWifiApIface getApIface(@NonNull String ifaceName) { - synchronized (sLock) { - return mIWifiApIfaces.get(ifaceName); - } - } - - private class ApInterfaceDestroyedListenerInternal implements InterfaceDestroyedListener { - private final InterfaceDestroyedListener mExternalListener; - - ApInterfaceDestroyedListenerInternal(InterfaceDestroyedListener externalListener) { - mExternalListener = externalListener; - } - - @Override - public void onDestroyed(@NonNull String ifaceName) { - synchronized (sLock) { - mIWifiApIfaces.remove(ifaceName); - } - if (mExternalListener != null) { - mExternalListener.onDestroyed(ifaceName); - } - } - } - - /** - * Create a AP iface using {@link HalDeviceManager}. - * - * @param destroyedListener Listener to be invoked when the interface is destroyed. - * @return iface name on success, null otherwise. - */ - public String createApIface(InterfaceDestroyedListener destroyedListener) { - synchronized (sLock) { - IWifiApIface iface = mHalDeviceManager.createApIface( - new ApInterfaceDestroyedListenerInternal(destroyedListener), null); - if (iface == null) { - mLog.err("Failed to create AP iface").flush(); - return stringResult(null); - } - String ifaceName = mHalDeviceManager.getName((IWifiIface) iface); - if (TextUtils.isEmpty(ifaceName)) { - mLog.err("Failed to get iface name").flush(); - return stringResult(null); - } - if (!retrieveWifiChip((IWifiIface) iface)) { - mLog.err("Failed to get wifi chip").flush(); - return stringResult(null); - } - mIWifiApIfaces.put(ifaceName, iface); - return ifaceName; - } - } - - /** - * Remove an AP iface using {@link HalDeviceManager}. - * - * @param ifaceName Name of the interface being removed. - * @return true on success, false otherwise. - */ - public boolean removeApIface(@NonNull String ifaceName) { - synchronized (sLock) { - IWifiApIface iface = getApIface(ifaceName); - if (iface == null) return boolResult(false); - - if (!mHalDeviceManager.removeIface((IWifiIface) iface)) { - mLog.err("Failed to remove AP iface").flush(); - return boolResult(false); - } - mIWifiApIfaces.remove(ifaceName); - return true; - } - } - - private boolean retrieveWifiChip(IWifiIface iface) { - synchronized (sLock) { - boolean registrationNeeded = mIWifiChip == null; - mIWifiChip = mHalDeviceManager.getChip(iface); - if (mIWifiChip == null) { - mLog.err("Failed to get the chip created for the Iface").flush(); - return false; - } - if (!registrationNeeded) { - return true; - } - if (!registerChipCallback()) { - mLog.err("Failed to register chip callback").flush(); - mIWifiChip = null; - return false; - } - return true; - } - } - - /** - * Registers the sta iface callback. - */ - private boolean registerStaIfaceCallback(IWifiStaIface iface) { - synchronized (sLock) { - if (iface == null) return boolResult(false); - if (mIWifiStaIfaceEventCallback == null) return boolResult(false); - try { - WifiStatus status = - iface.registerEventCallback(mIWifiStaIfaceEventCallback); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Registers the sta iface callback. - */ - private boolean registerChipCallback() { - synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - try { - WifiStatus status; - android.hardware.wifi.V1_4.IWifiChip iWifiChipV14 = getWifiChipForV1_4Mockable(); - android.hardware.wifi.V1_2.IWifiChip iWifiChipV12 = getWifiChipForV1_2Mockable(); - - if (iWifiChipV14 != null) { - status = iWifiChipV14.registerEventCallback_1_4(mIWifiChipEventCallbackV14); - } else if (iWifiChipV12 != null) { - status = iWifiChipV12.registerEventCallback_1_2(mIWifiChipEventCallbackV12); - } else { - status = mIWifiChip.registerEventCallback(mIWifiChipEventCallback); - } - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Stops the HAL - */ - public void stopVendorHal() { - synchronized (sLock) { - mHalDeviceManager.stop(); - clearState(); - mLog.info("Vendor Hal stopped").flush(); - } - } - - /** - * Clears the state associated with a started Iface - * - * Caller should hold the lock. - */ - private void clearState() { - mIWifiChip = null; - mIWifiStaIfaces.clear(); - mIWifiApIfaces.clear(); - mDriverDescription = null; - mFirmwareDescription = null; - } - - /** - * Tests whether the HAL is started and atleast one iface is up. - */ - public boolean isHalStarted() { - // For external use only. Methods in this class should test for null directly. - synchronized (sLock) { - return (!mIWifiStaIfaces.isEmpty() || !mIWifiApIfaces.isEmpty()); - } - } - - /** - * Gets the scan capabilities - * - * @param ifaceName Name of the interface. - * @param capabilities object to be filled in - * @return true for success, false for failure - */ - public boolean getBgScanCapabilities( - @NonNull String ifaceName, WifiNative.ScanCapabilities capabilities) { - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - MutableBoolean ans = new MutableBoolean(false); - WifiNative.ScanCapabilities out = capabilities; - iface.getBackgroundScanCapabilities((status, cap) -> { - if (!ok(status)) return; - mVerboseLog.info("scan capabilities %").c(cap.toString()).flush(); - out.max_scan_cache_size = cap.maxCacheSize; - out.max_ap_cache_per_scan = cap.maxApCachePerScan; - out.max_scan_buckets = cap.maxBuckets; - out.max_rssi_sample_size = 0; - out.max_scan_reporting_threshold = cap.maxReportingThreshold; - ans.value = true; - } - ); - return ans.value; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Holds the current background scan state, to implement pause and restart - */ - @VisibleForTesting - class CurrentBackgroundScan { - public int cmdId; - public StaBackgroundScanParameters param; - public WifiNative.ScanEventHandler eventHandler = null; - public boolean paused = false; - public WifiScanner.ScanData[] latestScanResults = null; - - CurrentBackgroundScan(int id, WifiNative.ScanSettings settings) { - cmdId = id; - param = new StaBackgroundScanParameters(); - param.basePeriodInMs = settings.base_period_ms; - param.maxApPerScan = settings.max_ap_per_scan; - param.reportThresholdPercent = settings.report_threshold_percent; - param.reportThresholdNumScans = settings.report_threshold_num_scans; - if (settings.buckets != null) { - for (WifiNative.BucketSettings bs : settings.buckets) { - param.buckets.add(makeStaBackgroundScanBucketParametersFromBucketSettings(bs)); - } - } - } - } - - /** - * Makes the Hal flavor of WifiNative.BucketSettings - * - * @param bs WifiNative.BucketSettings - * @return Hal flavor of bs - * @throws IllegalArgumentException if band value is not recognized - */ - private StaBackgroundScanBucketParameters - makeStaBackgroundScanBucketParametersFromBucketSettings(WifiNative.BucketSettings bs) { - StaBackgroundScanBucketParameters pa = new StaBackgroundScanBucketParameters(); - pa.bucketIdx = bs.bucket; - pa.band = makeWifiBandFromFrameworkBand(bs.band); - if (bs.channels != null) { - for (WifiNative.ChannelSettings cs : bs.channels) { - pa.frequencies.add(cs.frequency); - } - } - pa.periodInMs = bs.period_ms; - pa.eventReportScheme = makeReportSchemeFromBucketSettingsReportEvents(bs.report_events); - pa.exponentialMaxPeriodInMs = bs.max_period_ms; - // Although HAL API allows configurable base value for the truncated - // exponential back off scan. Native API and above support only - // truncated binary exponential back off scan. - // Hard code value of base to 2 here. - pa.exponentialBase = 2; - pa.exponentialStepCount = bs.step_count; - return pa; - } - - /** - * Makes the Hal flavor of WifiScanner's band indication - * - * Note: This method is only used by background scan which does not - * support 6GHz, hence band combinations including 6GHz are considered invalid - * - * @param frameworkBand one of WifiScanner.WIFI_BAND_* - * @return A WifiBand value - * @throws IllegalArgumentException if frameworkBand is not recognized - */ - private int makeWifiBandFromFrameworkBand(int frameworkBand) { - switch (frameworkBand) { - case WifiScanner.WIFI_BAND_UNSPECIFIED: - return WifiBand.BAND_UNSPECIFIED; - case WifiScanner.WIFI_BAND_24_GHZ: - return WifiBand.BAND_24GHZ; - case WifiScanner.WIFI_BAND_5_GHZ: - return WifiBand.BAND_5GHZ; - case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: - return WifiBand.BAND_5GHZ_DFS; - case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: - return WifiBand.BAND_5GHZ_WITH_DFS; - case WifiScanner.WIFI_BAND_BOTH: - return WifiBand.BAND_24GHZ_5GHZ; - case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: - return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS; - default: - throw new IllegalArgumentException("bad band " + frameworkBand); - } - } - - /** - * Makes the Hal flavor of WifiScanner's report event mask - * - * @param reportUnderscoreEvents is logical OR of WifiScanner.REPORT_EVENT_* values - * @return Corresponding StaBackgroundScanBucketEventReportSchemeMask value - * @throws IllegalArgumentException if a mask bit is not recognized - */ - private int makeReportSchemeFromBucketSettingsReportEvents(int reportUnderscoreEvents) { - int ans = 0; - BitMask in = new BitMask(reportUnderscoreEvents); - if (in.testAndClear(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)) { - ans |= StaBackgroundScanBucketEventReportSchemeMask.EACH_SCAN; - } - if (in.testAndClear(WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)) { - ans |= StaBackgroundScanBucketEventReportSchemeMask.FULL_RESULTS; - } - if (in.testAndClear(WifiScanner.REPORT_EVENT_NO_BATCH)) { - ans |= StaBackgroundScanBucketEventReportSchemeMask.NO_BATCH; - } - if (in.value != 0) throw new IllegalArgumentException("bad " + reportUnderscoreEvents); - return ans; - } - - private int mLastScanCmdId; // For assigning cmdIds to scans - - @VisibleForTesting - CurrentBackgroundScan mScan = null; - - /** - * Starts a background scan - * - * Any ongoing scan will be stopped first - * - * @param ifaceName Name of the interface. - * @param settings to control the scan - * @param eventHandler to call with the results - * @return true for success - */ - public boolean startBgScan(@NonNull String ifaceName, - WifiNative.ScanSettings settings, - WifiNative.ScanEventHandler eventHandler) { - WifiStatus status; - if (eventHandler == null) return boolResult(false); - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - if (mScan != null && !mScan.paused) { - ok(iface.stopBackgroundScan(mScan.cmdId)); - mScan = null; - } - mLastScanCmdId = (mLastScanCmdId % 9) + 1; // cycle through non-zero single digits - CurrentBackgroundScan scan = new CurrentBackgroundScan(mLastScanCmdId, settings); - status = iface.startBackgroundScan(scan.cmdId, scan.param); - if (!ok(status)) return false; - scan.eventHandler = eventHandler; - mScan = scan; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - - /** - * Stops any ongoing backgound scan - * - * @param ifaceName Name of the interface. - */ - public void stopBgScan(@NonNull String ifaceName) { - WifiStatus status; - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return; - try { - if (mScan != null) { - ok(iface.stopBackgroundScan(mScan.cmdId)); - mScan = null; - } - } catch (RemoteException e) { - handleRemoteException(e); - } - } - } - - /** - * Pauses an ongoing backgound scan - * - * @param ifaceName Name of the interface. - */ - public void pauseBgScan(@NonNull String ifaceName) { - WifiStatus status; - synchronized (sLock) { - try { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return; - if (mScan != null && !mScan.paused) { - status = iface.stopBackgroundScan(mScan.cmdId); - if (!ok(status)) return; - mScan.paused = true; - } - } catch (RemoteException e) { - handleRemoteException(e); - } - } - } - - /** - * Restarts a paused background scan - * - * @param ifaceName Name of the interface. - */ - public void restartBgScan(@NonNull String ifaceName) { - WifiStatus status; - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return; - try { - if (mScan != null && mScan.paused) { - status = iface.startBackgroundScan(mScan.cmdId, mScan.param); - if (!ok(status)) return; - mScan.paused = false; - } - } catch (RemoteException e) { - handleRemoteException(e); - } - } - } - - /** - * Gets the latest scan results received from the HIDL interface callback. - * TODO(b/35754840): This hop to fetch scan results after callback is unnecessary. Refactor - * WifiScanner to use the scan results from the callback. - * - * @param ifaceName Name of the interface. - */ - public WifiScanner.ScanData[] getBgScanResults(@NonNull String ifaceName) { - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - if (mScan == null) return null; - return mScan.latestScanResults; - } - } - - /** - * Get the link layer statistics - * - * Note - we always enable link layer stats on a STA interface. - * - * @param ifaceName Name of the interface. - * @return the statistics, or null if unable to do so - */ - public WifiLinkLayerStats getWifiLinkLayerStats(@NonNull String ifaceName) { - if (getWifiStaIfaceForV1_3Mockable(ifaceName) != null) { - return getWifiLinkLayerStats_1_3_Internal(ifaceName); - } - return getWifiLinkLayerStats_internal(ifaceName); - } - - private WifiLinkLayerStats getWifiLinkLayerStats_internal(@NonNull String ifaceName) { - class AnswerBox { - public StaLinkLayerStats value = null; - } - AnswerBox answer = new AnswerBox(); - synchronized (sLock) { - try { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - iface.getLinkLayerStats((status, stats) -> { - if (!ok(status)) return; - answer.value = stats; - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - WifiLinkLayerStats stats = frameworkFromHalLinkLayerStats(answer.value); - return stats; - } - - private WifiLinkLayerStats getWifiLinkLayerStats_1_3_Internal(@NonNull String ifaceName) { - class AnswerBox { - public android.hardware.wifi.V1_3.StaLinkLayerStats value = null; - } - AnswerBox answer = new AnswerBox(); - synchronized (sLock) { - try { - android.hardware.wifi.V1_3.IWifiStaIface iface = - getWifiStaIfaceForV1_3Mockable(ifaceName); - if (iface == null) return null; - iface.getLinkLayerStats_1_3((status, stats) -> { - if (!ok(status)) return; - answer.value = stats; - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - WifiLinkLayerStats stats = frameworkFromHalLinkLayerStats_1_3(answer.value); - return stats; - } - - - /** - * Makes the framework version of link layer stats from the hal version. - */ - @VisibleForTesting - static WifiLinkLayerStats frameworkFromHalLinkLayerStats(StaLinkLayerStats stats) { - if (stats == null) return null; - WifiLinkLayerStats out = new WifiLinkLayerStats(); - setIfaceStats(out, stats.iface); - setRadioStats(out, stats.radios); - setTimeStamp(out, stats.timeStampInMs); - out.version = WifiLinkLayerStats.V1_0; - return out; - } - - /** - * Makes the framework version of link layer stats from the hal version. - */ - @VisibleForTesting - static WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_3( - android.hardware.wifi.V1_3.StaLinkLayerStats stats) { - if (stats == null) return null; - WifiLinkLayerStats out = new WifiLinkLayerStats(); - setIfaceStats(out, stats.iface); - setRadioStats_1_3(out, stats.radios); - setTimeStamp(out, stats.timeStampInMs); - out.version = WifiLinkLayerStats.V1_3; - return out; - } - - private static void setIfaceStats(WifiLinkLayerStats stats, StaLinkLayerIfaceStats iface) { - if (iface == null) return; - stats.beacon_rx = iface.beaconRx; - stats.rssi_mgmt = iface.avgRssiMgmt; - // Statistics are broken out by Wireless Multimedia Extensions categories - // WME Best Effort Access Category - stats.rxmpdu_be = iface.wmeBePktStats.rxMpdu; - stats.txmpdu_be = iface.wmeBePktStats.txMpdu; - stats.lostmpdu_be = iface.wmeBePktStats.lostMpdu; - stats.retries_be = iface.wmeBePktStats.retries; - // WME Background Access Category - stats.rxmpdu_bk = iface.wmeBkPktStats.rxMpdu; - stats.txmpdu_bk = iface.wmeBkPktStats.txMpdu; - stats.lostmpdu_bk = iface.wmeBkPktStats.lostMpdu; - stats.retries_bk = iface.wmeBkPktStats.retries; - // WME Video Access Category - stats.rxmpdu_vi = iface.wmeViPktStats.rxMpdu; - stats.txmpdu_vi = iface.wmeViPktStats.txMpdu; - stats.lostmpdu_vi = iface.wmeViPktStats.lostMpdu; - stats.retries_vi = iface.wmeViPktStats.retries; - // WME Voice Access Category - stats.rxmpdu_vo = iface.wmeVoPktStats.rxMpdu; - stats.txmpdu_vo = iface.wmeVoPktStats.txMpdu; - stats.lostmpdu_vo = iface.wmeVoPktStats.lostMpdu; - stats.retries_vo = iface.wmeVoPktStats.retries; - } - - private static void setRadioStats(WifiLinkLayerStats stats, - List<StaLinkLayerRadioStats> radios) { - if (radios == null) return; - // NOTE(b/36176141): Figure out how to coalesce this info for multi radio devices. - if (radios.size() > 0) { - StaLinkLayerRadioStats radioStats = radios.get(0); - stats.on_time = radioStats.onTimeInMs; - stats.tx_time = radioStats.txTimeInMs; - stats.tx_time_per_level = new int[radioStats.txTimeInMsPerLevel.size()]; - for (int i = 0; i < stats.tx_time_per_level.length; i++) { - stats.tx_time_per_level[i] = radioStats.txTimeInMsPerLevel.get(i); - } - stats.rx_time = radioStats.rxTimeInMs; - stats.on_time_scan = radioStats.onTimeInMsForScan; - } - } - - private static void setRadioStats_1_3(WifiLinkLayerStats stats, - List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios) { - if (radios == null) return; - // NOTE(b/36176141): Figure out how to coalesce this info for multi radio devices. - if (radios.size() > 0) { - android.hardware.wifi.V1_3.StaLinkLayerRadioStats radioStats = radios.get(0); - stats.on_time = radioStats.V1_0.onTimeInMs; - stats.tx_time = radioStats.V1_0.txTimeInMs; - stats.tx_time_per_level = new int[radioStats.V1_0.txTimeInMsPerLevel.size()]; - for (int i = 0; i < stats.tx_time_per_level.length; i++) { - stats.tx_time_per_level[i] = radioStats.V1_0.txTimeInMsPerLevel.get(i); - } - stats.rx_time = radioStats.V1_0.rxTimeInMs; - stats.on_time_scan = radioStats.V1_0.onTimeInMsForScan; - stats.on_time_nan_scan = radioStats.onTimeInMsForNanScan; - stats.on_time_background_scan = radioStats.onTimeInMsForBgScan; - stats.on_time_roam_scan = radioStats.onTimeInMsForRoamScan; - stats.on_time_pno_scan = radioStats.onTimeInMsForPnoScan; - stats.on_time_hs20_scan = radioStats.onTimeInMsForHs20Scan; - /* Copy list of channel stats */ - for (int i = 0; i < radioStats.channelStats.size(); i++) { - android.hardware.wifi.V1_3.WifiChannelStats channelStats = - radioStats.channelStats.get(i); - ChannelStats channelStatsEntry = new ChannelStats(); - channelStatsEntry.frequency = channelStats.channel.centerFreq; - channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; - channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; - stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); - } - } - } - - private static void setTimeStamp(WifiLinkLayerStats stats, long timeStampInMs) { - stats.timeStampInMs = timeStampInMs; - } - - @VisibleForTesting - boolean mLinkLayerStatsDebug = false; // Passed to Hal - - /** - * Enables the linkLayerStats in the Hal. - * - * This is called unconditionally whenever we create a STA interface. - * - * @param iface Iface object. - */ - private void enableLinkLayerStats(IWifiStaIface iface) { - synchronized (sLock) { - try { - WifiStatus status; - status = iface.enableLinkLayerStatsCollection(mLinkLayerStatsDebug); - if (!ok(status)) { - mLog.err("unable to enable link layer stats collection").flush(); - } - } catch (RemoteException e) { - handleRemoteException(e); - } - } - } - - /** - * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for V1.1 - */ - private static final long[][] sChipFeatureCapabilityTranslation = { - {WifiManager.WIFI_FEATURE_TX_POWER_LIMIT, - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT - }, - {WifiManager.WIFI_FEATURE_D2D_RTT, - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT - }, - {WifiManager.WIFI_FEATURE_D2AP_RTT, - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT - } - }; - - /** - * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for - * additional capabilities introduced in V1.3 - */ - private static final long[][] sChipFeatureCapabilityTranslation13 = { - {WifiManager.WIFI_FEATURE_LOW_LATENCY, - android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE - }, - {WifiManager.WIFI_FEATURE_P2P_RAND_MAC, - android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.P2P_RAND_MAC - } - - }; - - /** - * Feature bit mask translation for Chip V1.1 - * - * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - @VisibleForTesting - int wifiFeatureMaskFromChipCapabilities(int capabilities) { - int features = 0; - for (int i = 0; i < sChipFeatureCapabilityTranslation.length; i++) { - if ((capabilities & sChipFeatureCapabilityTranslation[i][1]) != 0) { - features |= sChipFeatureCapabilityTranslation[i][0]; - } - } - return features; - } - - /** - * Feature bit mask translation for Chip V1.3 - * - * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - @VisibleForTesting - long wifiFeatureMaskFromChipCapabilities_1_3(int capabilities) { - // First collect features from previous versions - long features = wifiFeatureMaskFromChipCapabilities(capabilities); - - // Next collect features for V1_3 version - for (int i = 0; i < sChipFeatureCapabilityTranslation13.length; i++) { - if ((capabilities & sChipFeatureCapabilityTranslation13[i][1]) != 0) { - features |= sChipFeatureCapabilityTranslation13[i][0]; - } - } - return features; - } - - /** - * Translation table used by getSupportedFeatureSet for translating IWifiStaIface caps - */ - private static final long[][] sStaFeatureCapabilityTranslation = { - {WifiManager.WIFI_FEATURE_PASSPOINT, - IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT - }, - {WifiManager.WIFI_FEATURE_SCANNER, - IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN, - }, - {WifiManager.WIFI_FEATURE_PNO, - IWifiStaIface.StaIfaceCapabilityMask.PNO - }, - {WifiManager.WIFI_FEATURE_TDLS, - IWifiStaIface.StaIfaceCapabilityMask.TDLS - }, - {WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL, - IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL - }, - {WifiManager.WIFI_FEATURE_LINK_LAYER_STATS, - IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS - }, - {WifiManager.WIFI_FEATURE_RSSI_MONITOR, - IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR - }, - {WifiManager.WIFI_FEATURE_MKEEP_ALIVE, - IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE - }, - {WifiManager.WIFI_FEATURE_CONFIG_NDO, - IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD - }, - {WifiManager.WIFI_FEATURE_CONTROL_ROAMING, - IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING - }, - {WifiManager.WIFI_FEATURE_IE_WHITELIST, - IWifiStaIface.StaIfaceCapabilityMask.PROBE_IE_WHITELIST - }, - {WifiManager.WIFI_FEATURE_SCAN_RAND, - IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND - } - }; - - /** - * Feature bit mask translation for STAs - * - * @param capabilities bitmask defined IWifiStaIface.StaIfaceCapabilityMask - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - @VisibleForTesting - long wifiFeatureMaskFromStaCapabilities(int capabilities) { - long features = 0; - for (int i = 0; i < sStaFeatureCapabilityTranslation.length; i++) { - if ((capabilities & sStaFeatureCapabilityTranslation[i][1]) != 0) { - features |= sStaFeatureCapabilityTranslation[i][0]; - } - } - return features; - } - - /** - * Get the supported features - * - * The result may differ depending on the mode (STA or AP) - * - * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - public long getSupportedFeatureSet(@NonNull String ifaceName) { - long featureSet = 0; - if (!mHalDeviceManager.isStarted()) { - return featureSet; // TODO: can't get capabilities with Wi-Fi down - } - try { - final MutableLong feat = new MutableLong(0); - synchronized (sLock) { - android.hardware.wifi.V1_3.IWifiChip iWifiChipV13 = getWifiChipForV1_3Mockable(); - if (iWifiChipV13 != null) { - iWifiChipV13.getCapabilities_1_3((status, capabilities) -> { - if (!ok(status)) return; - feat.value = wifiFeatureMaskFromChipCapabilities_1_3(capabilities); - }); - } else if (mIWifiChip != null) { - mIWifiChip.getCapabilities((status, capabilities) -> { - if (!ok(status)) return; - feat.value = wifiFeatureMaskFromChipCapabilities(capabilities); - }); - } - - IWifiStaIface iface = getStaIface(ifaceName); - if (iface != null) { - iface.getCapabilities((status, capabilities) -> { - if (!ok(status)) return; - feat.value |= wifiFeatureMaskFromStaCapabilities(capabilities); - }); - } - } - featureSet = feat.value; - } catch (RemoteException e) { - handleRemoteException(e); - return 0; - } - - Set<Integer> supportedIfaceTypes = mHalDeviceManager.getSupportedIfaceTypes(); - if (supportedIfaceTypes.contains(IfaceType.STA)) { - featureSet |= WifiManager.WIFI_FEATURE_INFRA; - } - if (supportedIfaceTypes.contains(IfaceType.AP)) { - featureSet |= WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT; - } - if (supportedIfaceTypes.contains(IfaceType.P2P)) { - featureSet |= WifiManager.WIFI_FEATURE_P2P; - } - if (supportedIfaceTypes.contains(IfaceType.NAN)) { - featureSet |= WifiManager.WIFI_FEATURE_AWARE; - } - - return featureSet; - } - - /** - * Set Mac address on the given interface - * - * @param ifaceName Name of the interface - * @param mac MAC address to change into - * @return true for success - */ - public boolean setMacAddress(@NonNull String ifaceName, @NonNull MacAddress mac) { - byte[] macByteArray = mac.toByteArray(); - synchronized (sLock) { - try { - android.hardware.wifi.V1_2.IWifiStaIface sta12 = - getWifiStaIfaceForV1_2Mockable(ifaceName); - if (sta12 != null) { - return ok(sta12.setMacAddress(macByteArray)); - } - - android.hardware.wifi.V1_4.IWifiApIface ap14 = - getWifiApIfaceForV1_4Mockable(ifaceName); - if (ap14 != null) { - return ok(ap14.setMacAddress(macByteArray)); - } - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - return boolResult(false); - } - - /** - * Returns true if Hal version supports setMacAddress, otherwise false. - * - * @param ifaceName Name of the interface - */ - public boolean isSetMacAddressSupported(@NonNull String ifaceName) { - synchronized (sLock) { - android.hardware.wifi.V1_2.IWifiStaIface sta12 = - getWifiStaIfaceForV1_2Mockable(ifaceName); - if (sta12 != null) { - return true; - } - - android.hardware.wifi.V1_4.IWifiApIface ap14 = - getWifiApIfaceForV1_4Mockable(ifaceName); - if (ap14 != null) { - return true; - } - } - return false; - } - - /** - * Get factory MAC address of the given interface - * - * @param ifaceName Name of the interface - * @return factory MAC address of the interface or null. - */ - public MacAddress getFactoryMacAddress(@NonNull String ifaceName) { - class AnswerBox { - public MacAddress mac = null; - } - synchronized (sLock) { - try { - AnswerBox box = new AnswerBox(); - - android.hardware.wifi.V1_3.IWifiStaIface sta13 = - getWifiStaIfaceForV1_3Mockable(ifaceName); - if (sta13 != null) { - sta13.getFactoryMacAddress((status, macBytes) -> { - if (!ok(status)) return; - box.mac = MacAddress.fromBytes(macBytes); - }); - return box.mac; - } - - android.hardware.wifi.V1_4.IWifiApIface ap14 = - getWifiApIfaceForV1_4Mockable(ifaceName); - if (ap14 != null) { - ap14.getFactoryMacAddress((status, macBytes) -> { - if (!ok(status)) return; - box.mac = MacAddress.fromBytes(macBytes); - }); - return box.mac; - } - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - return null; - } - - /** - * Get the APF (Android Packet Filter) capabilities of the device - * - * @param ifaceName Name of the interface. - * @return APF capabilities object. - */ - public ApfCapabilities getApfCapabilities(@NonNull String ifaceName) { - class AnswerBox { - public ApfCapabilities value = sNoApfCapabilities; - } - synchronized (sLock) { - try { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return sNoApfCapabilities; - AnswerBox box = new AnswerBox(); - iface.getApfPacketFilterCapabilities((status, capabilities) -> { - if (!ok(status)) return; - box.value = new ApfCapabilities( - /* apfVersionSupported */ capabilities.version, - /* maximumApfProgramSize */ capabilities.maxLength, - /* apfPacketFormat */ android.system.OsConstants.ARPHRD_ETHER); - }); - return box.value; - } catch (RemoteException e) { - handleRemoteException(e); - return sNoApfCapabilities; - } - } - } - - private static final ApfCapabilities sNoApfCapabilities = new ApfCapabilities(0, 0, 0); - - /** - * Installs an APF program on this iface, replacing any existing program. - * - * @param ifaceName Name of the interface. - * @param filter is the android packet filter program - * @return true for success - */ - public boolean installPacketFilter(@NonNull String ifaceName, byte[] filter) { - int cmdId = 0; // We only aspire to support one program at a time - if (filter == null) return boolResult(false); - // Copy the program before taking the lock. - ArrayList<Byte> program = NativeUtil.byteArrayToArrayList(filter); - enter("filter length %").c(filter.length).flush(); - synchronized (sLock) { - try { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - WifiStatus status = iface.installApfPacketFilter(cmdId, program); - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Reads the APF program and data buffer on this iface. - * - * @param ifaceName Name of the interface - * @return the buffer returned by the driver, or null in case of an error - */ - public byte[] readPacketFilter(@NonNull String ifaceName) { - class AnswerBox { - public byte[] data = null; - } - AnswerBox answer = new AnswerBox(); - enter("").flush(); - // TODO: Must also take the wakelock here to prevent going to sleep with APF disabled. - synchronized (sLock) { - try { - android.hardware.wifi.V1_2.IWifiStaIface ifaceV12 = - getWifiStaIfaceForV1_2Mockable(ifaceName); - if (ifaceV12 == null) return byteArrayResult(null); - ifaceV12.readApfPacketFilterData((status, dataByteArray) -> { - if (!ok(status)) return; - answer.data = NativeUtil.byteArrayFromArrayList(dataByteArray); - }); - return byteArrayResult(answer.data); - } catch (RemoteException e) { - handleRemoteException(e); - return byteArrayResult(null); - } - } - } - - /** - * Set country code for this AP iface. - * - * @param ifaceName Name of the interface. - * @param countryCode - two-letter country code (as ISO 3166) - * @return true for success - */ - public boolean setCountryCodeHal(@NonNull String ifaceName, String countryCode) { - if (countryCode == null) return boolResult(false); - if (countryCode.length() != 2) return boolResult(false); - byte[] code; - try { - code = NativeUtil.stringToByteArray(countryCode); - } catch (IllegalArgumentException e) { - return boolResult(false); - } - synchronized (sLock) { - try { - IWifiApIface iface = getApIface(ifaceName); - if (iface == null) return boolResult(false); - WifiStatus status = iface.setCountryCode(code); - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - private WifiNative.WifiLoggerEventHandler mLogEventHandler = null; - - /** - * Registers the logger callback and enables alerts. - * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked. - */ - public boolean setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler) { - if (handler == null) return boolResult(false); - synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - if (mLogEventHandler != null) return boolResult(false); - try { - WifiStatus status = mIWifiChip.enableDebugErrorAlerts(true); - if (!ok(status)) return false; - mLogEventHandler = handler; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Stops all logging and resets the logger callback. - * This stops both the alerts and ring buffer data collection. - * Existing log handler is cleared. - */ - public boolean resetLogHandler() { - synchronized (sLock) { - mLogEventHandler = null; - if (mIWifiChip == null) return boolResult(false); - try { - WifiStatus status = mIWifiChip.enableDebugErrorAlerts(false); - if (!ok(status)) return false; - status = mIWifiChip.stopLoggingToDebugRingBuffer(); - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Control debug data collection - * - * @param verboseLevel 0 to 3, inclusive. 0 stops logging. - * @param flags Ignored. - * @param maxIntervalInSec Maximum interval between reports; ignore if 0. - * @param minDataSizeInBytes Minimum data size in buffer for report; ignore if 0. - * @param ringName Name of the ring for which data collection is to start. - * @return true for success - */ - public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxIntervalInSec, - int minDataSizeInBytes, String ringName) { - enter("verboseLevel=%, flags=%, maxIntervalInSec=%, minDataSizeInBytes=%, ringName=%") - .c(verboseLevel).c(flags).c(maxIntervalInSec).c(minDataSizeInBytes).c(ringName) - .flush(); - synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - try { - // note - flags are not used - WifiStatus status = mIWifiChip.startLoggingToDebugRingBuffer( - ringName, - verboseLevel, - maxIntervalInSec, - minDataSizeInBytes - ); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Pointlessly fail - * - * @return -1 - */ - public int getSupportedLoggerFeatureSet() { - return -1; - } - - private String mDriverDescription; // Cached value filled by requestChipDebugInfo() - - /** - * Vendor-provided wifi driver version string - */ - public String getDriverVersion() { - synchronized (sLock) { - if (mDriverDescription == null) requestChipDebugInfo(); - return mDriverDescription; - } - } - - private String mFirmwareDescription; // Cached value filled by requestChipDebugInfo() - - /** - * Vendor-provided wifi firmware version string - */ - public String getFirmwareVersion() { - synchronized (sLock) { - if (mFirmwareDescription == null) requestChipDebugInfo(); - return mFirmwareDescription; - } - } - - /** - * Refreshes our idea of the driver and firmware versions - */ - private void requestChipDebugInfo() { - mDriverDescription = null; - mFirmwareDescription = null; - try { - if (mIWifiChip == null) return; - mIWifiChip.requestChipDebugInfo((status, chipDebugInfo) -> { - if (!ok(status)) return; - mDriverDescription = chipDebugInfo.driverDescription; - mFirmwareDescription = chipDebugInfo.firmwareDescription; - }); - } catch (RemoteException e) { - handleRemoteException(e); - return; - } - mLog.info("Driver: % Firmware: %") - .c(mDriverDescription) - .c(mFirmwareDescription) - .flush(); - } - - /** - * Creates RingBufferStatus from the Hal version - */ - private static WifiNative.RingBufferStatus ringBufferStatus(WifiDebugRingBufferStatus h) { - WifiNative.RingBufferStatus ans = new WifiNative.RingBufferStatus(); - ans.name = h.ringName; - ans.flag = frameworkRingBufferFlagsFromHal(h.flags); - ans.ringBufferId = h.ringId; - ans.ringBufferByteSize = h.sizeInBytes; - ans.verboseLevel = h.verboseLevel; - // Remaining fields are unavailable - // writtenBytes; - // readBytes; - // writtenRecords; - return ans; - } - - /** - * Translates a hal wifiDebugRingBufferFlag to the WifiNative version - */ - private static int frameworkRingBufferFlagsFromHal(int wifiDebugRingBufferFlag) { - BitMask checkoff = new BitMask(wifiDebugRingBufferFlag); - int flags = 0; - if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES)) { - flags |= WifiNative.RingBufferStatus.HAS_BINARY_ENTRIES; - } - if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES)) { - flags |= WifiNative.RingBufferStatus.HAS_ASCII_ENTRIES; - } - if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES)) { - flags |= WifiNative.RingBufferStatus.HAS_PER_PACKET_ENTRIES; - } - if (checkoff.value != 0) { - throw new IllegalArgumentException("Unknown WifiDebugRingBufferFlag " + checkoff.value); - } - return flags; - } - - /** - * Creates array of RingBufferStatus from the Hal version - */ - private static WifiNative.RingBufferStatus[] makeRingBufferStatusArray( - ArrayList<WifiDebugRingBufferStatus> ringBuffers) { - WifiNative.RingBufferStatus[] ans = new WifiNative.RingBufferStatus[ringBuffers.size()]; - int i = 0; - for (WifiDebugRingBufferStatus b : ringBuffers) { - ans[i++] = ringBufferStatus(b); - } - return ans; - } - - /** - * API to get the status of all ring buffers supported by driver - */ - public WifiNative.RingBufferStatus[] getRingBufferStatus() { - class AnswerBox { - public WifiNative.RingBufferStatus[] value = null; - } - AnswerBox ans = new AnswerBox(); - synchronized (sLock) { - if (mIWifiChip == null) return null; - try { - mIWifiChip.getDebugRingBuffersStatus((status, ringBuffers) -> { - if (!ok(status)) return; - ans.value = makeRingBufferStatusArray(ringBuffers); - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - return ans.value; - } - - /** - * Indicates to driver that all the data has to be uploaded urgently - */ - public boolean getRingBufferData(String ringName) { - enter("ringName %").c(ringName).flush(); - synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - try { - WifiStatus status = mIWifiChip.forceDumpToDebugRingBuffer(ringName); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * request hal to flush ring buffers to files - */ - public boolean flushRingBufferData() { - synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - android.hardware.wifi.V1_3.IWifiChip iWifiChipV13 = getWifiChipForV1_3Mockable(); - if (iWifiChipV13 != null) { - try { - WifiStatus status = iWifiChipV13.flushRingBufferToFile(); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - return false; - } - } - - /** - * Request vendor debug info from the firmware - */ - public byte[] getFwMemoryDump() { - class AnswerBox { - public byte[] value; - } - AnswerBox ans = new AnswerBox(); - synchronized (sLock) { - if (mIWifiChip == null) return (null); - try { - mIWifiChip.requestFirmwareDebugDump((status, blob) -> { - if (!ok(status)) return; - ans.value = NativeUtil.byteArrayFromArrayList(blob); - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - return ans.value; - } - - /** - * Request vendor debug info from the driver - */ - public byte[] getDriverStateDump() { - class AnswerBox { - public byte[] value; - } - AnswerBox ans = new AnswerBox(); - synchronized (sLock) { - if (mIWifiChip == null) return (null); - try { - mIWifiChip.requestDriverDebugDump((status, blob) -> { - if (!ok(status)) return; - ans.value = NativeUtil.byteArrayFromArrayList(blob); - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - return ans.value; - } - - /** - * Start packet fate monitoring - * <p> - * Once started, monitoring remains active until HAL is unloaded. - * - * @param ifaceName Name of the interface. - * @return true for success - */ - public boolean startPktFateMonitoring(@NonNull String ifaceName) { - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - WifiStatus status = iface.startDebugPacketFateMonitoring(); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - private byte halToFrameworkPktFateFrameType(int type) { - switch (type) { - case WifiDebugPacketFateFrameType.UNKNOWN: - return WifiLoggerHal.FRAME_TYPE_UNKNOWN; - case WifiDebugPacketFateFrameType.ETHERNET_II: - return WifiLoggerHal.FRAME_TYPE_ETHERNET_II; - case WifiDebugPacketFateFrameType.MGMT_80211: - return WifiLoggerHal.FRAME_TYPE_80211_MGMT; - default: - throw new IllegalArgumentException("bad " + type); - } - } - - private byte halToFrameworkRxPktFate(int type) { - switch (type) { - case WifiDebugRxPacketFate.SUCCESS: - return WifiLoggerHal.RX_PKT_FATE_SUCCESS; - case WifiDebugRxPacketFate.FW_QUEUED: - return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED; - case WifiDebugRxPacketFate.FW_DROP_FILTER: - return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER; - case WifiDebugRxPacketFate.FW_DROP_INVALID: - return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID; - case WifiDebugRxPacketFate.FW_DROP_NOBUFS: - return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS; - case WifiDebugRxPacketFate.FW_DROP_OTHER: - return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER; - case WifiDebugRxPacketFate.DRV_QUEUED: - return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED; - case WifiDebugRxPacketFate.DRV_DROP_FILTER: - return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER; - case WifiDebugRxPacketFate.DRV_DROP_INVALID: - return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID; - case WifiDebugRxPacketFate.DRV_DROP_NOBUFS: - return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS; - case WifiDebugRxPacketFate.DRV_DROP_OTHER: - return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER; - default: - throw new IllegalArgumentException("bad " + type); - } - } - - private byte halToFrameworkTxPktFate(int type) { - switch (type) { - case WifiDebugTxPacketFate.ACKED: - return WifiLoggerHal.TX_PKT_FATE_ACKED; - case WifiDebugTxPacketFate.SENT: - return WifiLoggerHal.TX_PKT_FATE_SENT; - case WifiDebugTxPacketFate.FW_QUEUED: - return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED; - case WifiDebugTxPacketFate.FW_DROP_INVALID: - return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID; - case WifiDebugTxPacketFate.FW_DROP_NOBUFS: - return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS; - case WifiDebugTxPacketFate.FW_DROP_OTHER: - return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER; - case WifiDebugTxPacketFate.DRV_QUEUED: - return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; - case WifiDebugTxPacketFate.DRV_DROP_INVALID: - return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID; - case WifiDebugTxPacketFate.DRV_DROP_NOBUFS: - return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS; - case WifiDebugTxPacketFate.DRV_DROP_OTHER: - return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER; - default: - throw new IllegalArgumentException("bad " + type); - } - } - - /** - * Retrieve fates of outbound packets - * <p> - * Reports the outbound frames for the most recent association (space allowing). - * - * @param ifaceName Name of the interface. - * @param reportBufs - * @return true for success - */ - public boolean getTxPktFates(@NonNull String ifaceName, WifiNative.TxFateReport[] reportBufs) { - if (ArrayUtils.isEmpty(reportBufs)) return boolResult(false); - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - MutableBoolean ok = new MutableBoolean(false); - iface.getDebugTxPacketFates((status, fates) -> { - if (!ok(status)) return; - int i = 0; - for (WifiDebugTxPacketFateReport fate : fates) { - if (i >= reportBufs.length) break; - byte code = halToFrameworkTxPktFate(fate.fate); - long us = fate.frameInfo.driverTimestampUsec; - byte type = - halToFrameworkPktFateFrameType(fate.frameInfo.frameType); - byte[] frame = - NativeUtil.byteArrayFromArrayList( - fate.frameInfo.frameContent); - reportBufs[i++] = - new WifiNative.TxFateReport(code, us, type, frame); - } - ok.value = true; - } - ); - return ok.value; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Retrieve fates of inbound packets - * <p> - * Reports the inbound frames for the most recent association (space allowing). - * - * @param ifaceName Name of the interface. - * @param reportBufs - * @return true for success - */ - public boolean getRxPktFates(@NonNull String ifaceName, WifiNative.RxFateReport[] reportBufs) { - if (ArrayUtils.isEmpty(reportBufs)) return boolResult(false); - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - MutableBoolean ok = new MutableBoolean(false); - iface.getDebugRxPacketFates((status, fates) -> { - if (!ok(status)) return; - int i = 0; - for (WifiDebugRxPacketFateReport fate : fates) { - if (i >= reportBufs.length) break; - byte code = halToFrameworkRxPktFate(fate.fate); - long us = fate.frameInfo.driverTimestampUsec; - byte type = - halToFrameworkPktFateFrameType(fate.frameInfo.frameType); - byte[] frame = - NativeUtil.byteArrayFromArrayList( - fate.frameInfo.frameContent); - reportBufs[i++] = - new WifiNative.RxFateReport(code, us, type, frame); - } - ok.value = true; - } - ); - return ok.value; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Start sending the specified keep alive packets periodically. - * - * @param ifaceName Name of the interface. - * @param slot - * @param srcMac - * @param dstMac - * @param keepAlivePacket - * @param protocol - * @param periodInMs - * @return 0 for success, -1 for error - */ - public int startSendingOffloadedPacket( - @NonNull String ifaceName, int slot, byte[] srcMac, byte[] dstMac, - byte[] packet, int protocol, int periodInMs) { - enter("slot=% periodInMs=%").c(slot).c(periodInMs).flush(); - - ArrayList<Byte> data = NativeUtil.byteArrayToArrayList(packet); - - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return -1; - try { - WifiStatus status = iface.startSendingKeepAlivePackets( - slot, - data, - (short) protocol, - srcMac, - dstMac, - periodInMs); - if (!ok(status)) return -1; - return 0; - } catch (RemoteException e) { - handleRemoteException(e); - return -1; - } - } - } - - /** - * Stop sending the specified keep alive packets. - * - * @param ifaceName Name of the interface. - * @param slot id - same as startSendingOffloadedPacket call. - * @return 0 for success, -1 for error - */ - public int stopSendingOffloadedPacket(@NonNull String ifaceName, int slot) { - enter("slot=%").c(slot).flush(); - - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return -1; - try { - WifiStatus status = iface.stopSendingKeepAlivePackets(slot); - if (!ok(status)) return -1; - return 0; - } catch (RemoteException e) { - handleRemoteException(e); - return -1; - } - } - } - - /** - * A fixed cmdId for our RssiMonitoring (we only do one at a time) - */ - @VisibleForTesting - static final int sRssiMonCmdId = 7551; - - /** - * Our client's handler - */ - private WifiNative.WifiRssiEventHandler mWifiRssiEventHandler; - - /** - * Start RSSI monitoring on the currently connected access point. - * - * @param ifaceName Name of the interface. - * @param maxRssi Maximum RSSI threshold. - * @param minRssi Minimum RSSI threshold. - * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi - * @return 0 for success, -1 for failure - */ - public int startRssiMonitoring(@NonNull String ifaceName, byte maxRssi, byte minRssi, - WifiNative.WifiRssiEventHandler rssiEventHandler) { - enter("maxRssi=% minRssi=%").c(maxRssi).c(minRssi).flush(); - if (maxRssi <= minRssi) return -1; - if (rssiEventHandler == null) return -1; - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return -1; - try { - iface.stopRssiMonitoring(sRssiMonCmdId); - WifiStatus status; - status = iface.startRssiMonitoring(sRssiMonCmdId, maxRssi, minRssi); - if (!ok(status)) return -1; - mWifiRssiEventHandler = rssiEventHandler; - return 0; - } catch (RemoteException e) { - handleRemoteException(e); - return -1; - } - } - } - - /** - * Stop RSSI monitoring - * - * @param ifaceName Name of the interface. - * @return 0 for success, -1 for failure - */ - public int stopRssiMonitoring(@NonNull String ifaceName) { - synchronized (sLock) { - mWifiRssiEventHandler = null; - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return -1; - try { - WifiStatus status = iface.stopRssiMonitoring(sRssiMonCmdId); - if (!ok(status)) return -1; - return 0; - } catch (RemoteException e) { - handleRemoteException(e); - return -1; - } - } - } - - //TODO - belongs in NativeUtil - private static int[] intsFromArrayList(ArrayList<Integer> a) { - if (a == null) return null; - int[] b = new int[a.size()]; - int i = 0; - for (Integer e : a) b[i++] = e; - return b; - } - - /** - * Translates from Hal version of wake reason stats to the framework version of same - * - * @param h - Hal version of wake reason stats - * @return framework version of same - */ - private static WlanWakeReasonAndCounts halToFrameworkWakeReasons( - WifiDebugHostWakeReasonStats h) { - if (h == null) return null; - WlanWakeReasonAndCounts ans = new WlanWakeReasonAndCounts(); - ans.totalCmdEventWake = h.totalCmdEventWakeCnt; - ans.totalDriverFwLocalWake = h.totalDriverFwLocalWakeCnt; - ans.totalRxDataWake = h.totalRxPacketWakeCnt; - ans.rxUnicast = h.rxPktWakeDetails.rxUnicastCnt; - ans.rxMulticast = h.rxPktWakeDetails.rxMulticastCnt; - ans.rxBroadcast = h.rxPktWakeDetails.rxBroadcastCnt; - ans.icmp = h.rxIcmpPkWakeDetails.icmpPkt; - ans.icmp6 = h.rxIcmpPkWakeDetails.icmp6Pkt; - ans.icmp6Ra = h.rxIcmpPkWakeDetails.icmp6Ra; - ans.icmp6Na = h.rxIcmpPkWakeDetails.icmp6Na; - ans.icmp6Ns = h.rxIcmpPkWakeDetails.icmp6Ns; - ans.ipv4RxMulticast = h.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt; - ans.ipv6Multicast = h.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt; - ans.otherRxMulticast = h.rxMulticastPkWakeDetails.otherRxMulticastAddrCnt; - ans.cmdEventWakeCntArray = intsFromArrayList(h.cmdEventWakeCntPerType); - ans.driverFWLocalWakeCntArray = intsFromArrayList(h.driverFwLocalWakeCntPerType); - return ans; - } - - /** - * Fetch the host wakeup reasons stats from wlan driver. - * - * @return the |WlanWakeReasonAndCounts| from the wlan driver, or null on failure. - */ - public WlanWakeReasonAndCounts getWlanWakeReasonCount() { - class AnswerBox { - public WifiDebugHostWakeReasonStats value = null; - } - AnswerBox ans = new AnswerBox(); - synchronized (sLock) { - if (mIWifiChip == null) return null; - try { - mIWifiChip.getDebugHostWakeReasonStats((status, stats) -> { - if (ok(status)) { - ans.value = stats; - } - }); - return halToFrameworkWakeReasons(ans.value); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - } - - /** - * Enable/Disable Neighbour discovery offload functionality in the firmware. - * - * @param ifaceName Name of the interface. - * @param enabled true to enable, false to disable. - * @return true for success, false for failure - */ - public boolean configureNeighborDiscoveryOffload(@NonNull String ifaceName, boolean enabled) { - enter("enabled=%").c(enabled).flush(); - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - WifiStatus status = iface.enableNdOffload(enabled); - if (!ok(status)) return false; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - return true; - } - - // Firmware roaming control. - - /** - * Query the firmware roaming capabilities. - * - * @param ifaceName Name of the interface. - * @param capabilities object to be filled in - * @return true for success; false for failure - */ - public boolean getRoamingCapabilities(@NonNull String ifaceName, - WifiNative.RoamingCapabilities capabilities) { - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - MutableBoolean ok = new MutableBoolean(false); - WifiNative.RoamingCapabilities out = capabilities; - iface.getRoamingCapabilities((status, cap) -> { - if (!ok(status)) return; - out.maxBlacklistSize = cap.maxBlacklistSize; - out.maxWhitelistSize = cap.maxWhitelistSize; - ok.value = true; - }); - return ok.value; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Enable/disable firmware roaming. - * - * @param ifaceName Name of the interface. - * @param state the intended roaming state - * @return SET_FIRMWARE_ROAMING_SUCCESS, SET_FIRMWARE_ROAMING_FAILURE, - * or SET_FIRMWARE_ROAMING_BUSY - */ - public int enableFirmwareRoaming(@NonNull String ifaceName, int state) { - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return WifiNative.SET_FIRMWARE_ROAMING_FAILURE; - try { - byte val; - switch (state) { - case WifiNative.DISABLE_FIRMWARE_ROAMING: - val = StaRoamingState.DISABLED; - break; - case WifiNative.ENABLE_FIRMWARE_ROAMING: - val = StaRoamingState.ENABLED; - break; - default: - mLog.err("enableFirmwareRoaming invalid argument %").c(state).flush(); - return WifiNative.SET_FIRMWARE_ROAMING_FAILURE; - } - WifiStatus status = iface.setRoamingState(val); - if (ok(status)) { - return WifiNative.SET_FIRMWARE_ROAMING_SUCCESS; - } else if (status.code == WifiStatusCode.ERROR_BUSY) { - return WifiNative.SET_FIRMWARE_ROAMING_BUSY; - } else { - return WifiNative.SET_FIRMWARE_ROAMING_FAILURE; - } - } catch (RemoteException e) { - handleRemoteException(e); - return WifiNative.SET_FIRMWARE_ROAMING_FAILURE; - } - } - } - - /** - * Set firmware roaming configurations. - * - * @param ifaceName Name of the interface. - * @param config new roaming configuration object - * @return true for success; false for failure - */ - public boolean configureRoaming(@NonNull String ifaceName, WifiNative.RoamingConfig config) { - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - StaRoamingConfig roamingConfig = new StaRoamingConfig(); - - // parse the blacklist BSSIDs if any - if (config.blacklistBssids != null) { - for (String bssid : config.blacklistBssids) { - byte[] mac = NativeUtil.macAddressToByteArray(bssid); - roamingConfig.bssidBlacklist.add(mac); - } - } - - // parse the whitelist SSIDs if any - if (config.whitelistSsids != null) { - for (String ssidStr : config.whitelistSsids) { - byte[] ssid = NativeUtil.byteArrayFromArrayList( - NativeUtil.decodeSsid(ssidStr)); - roamingConfig.ssidWhitelist.add(ssid); - } - } - - WifiStatus status = iface.configureRoaming(roamingConfig); - if (!ok(status)) return false; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } catch (IllegalArgumentException e) { - mLog.err("Illegal argument for roaming configuration").c(e.toString()).flush(); - return false; - } - return true; - } - } - - /** - * Method to mock out the V1_1 IWifiChip retrieval in unit tests. - * - * @return 1.1 IWifiChip object if the device is running the 1.1 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_1.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_2 IWifiChip retrieval in unit tests. - * - * @return 1.2 IWifiChip object if the device is running the 1.2 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_2.IWifiChip getWifiChipForV1_2Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_2.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_3 IWifiChip retrieval in unit tests. - * - * @return 1.3 IWifiChip object if the device is running the 1.3 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_3.IWifiChip getWifiChipForV1_3Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_3.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_4 IWifiChip retrieval in unit tests. - * - * @return 1.4 IWifiChip object if the device is running the 1.4 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_4.IWifiChip getWifiChipForV1_4Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_4.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_2 IWifiStaIface retrieval in unit tests. - * - * @param ifaceName Name of the interface - * @return 1.2 IWifiStaIface object if the device is running the 1.2 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceForV1_2Mockable( - @NonNull String ifaceName) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_2.IWifiStaIface.castFrom(iface); - } - - /** - * Method to mock out the V1_3 IWifiStaIface retrieval in unit tests. - * - * @param ifaceName Name of the interface - * @return 1.3 IWifiStaIface object if the device is running the 1.3 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceForV1_3Mockable( - @NonNull String ifaceName) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_3.IWifiStaIface.castFrom(iface); - } - - protected android.hardware.wifi.V1_4.IWifiApIface getWifiApIfaceForV1_4Mockable( - String ifaceName) { - IWifiApIface iface = getApIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_4.IWifiApIface.castFrom(iface); - } - - /** - * sarPowerBackoffRequired_1_1() - * This method checks if we need to backoff wifi Tx power due to SAR requirements. - * It handles the case when the device is running the V1_1 version of WifiChip HAL - * In that HAL version, it is required to perform wifi Tx power backoff only if - * a voice call is ongoing. - */ - private boolean sarPowerBackoffRequired_1_1(SarInfo sarInfo) { - /* As long as no voice call is active (in case voice call is supported), - * no backoff is needed */ - if (sarInfo.sarVoiceCallSupported) { - return (sarInfo.isVoiceCall || sarInfo.isEarPieceActive); - } else { - return false; - } - } - - /** - * frameworkToHalTxPowerScenario_1_1() - * This method maps the information inside the SarInfo instance into a SAR scenario - * when device is running the V1_1 version of WifiChip HAL. - * In this HAL version, only one scenario is defined which is for VOICE_CALL (if voice call is - * supported). - * Otherwise, an exception is thrown. - */ - private int frameworkToHalTxPowerScenario_1_1(SarInfo sarInfo) { - if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) { - return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL; - } else { - throw new IllegalArgumentException("bad scenario: voice call not active/supported"); - } - } - - /** - * sarPowerBackoffRequired_1_2() - * This method checks if we need to backoff wifi Tx power due to SAR requirements. - * It handles the case when the device is running the V1_2 version of WifiChip HAL - */ - private boolean sarPowerBackoffRequired_1_2(SarInfo sarInfo) { - if (sarInfo.sarSapSupported && sarInfo.isWifiSapEnabled) { - return true; - } - if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) { - return true; - } - return false; - } - - /** - * frameworkToHalTxPowerScenario_1_2() - * This method maps the information inside the SarInfo instance into a SAR scenario - * when device is running the V1_2 version of WifiChip HAL. - * If SAR SoftAP input is supported, - * we make these assumptions: - * - All voice calls are treated as if device is near the head. - * - SoftAP scenario is treated as if device is near the body. - * In case SoftAP is not supported, then we should revert to the V1_1 HAL - * behavior, and the only valid scenario would be when a voice call is ongoing. - */ - private int frameworkToHalTxPowerScenario_1_2(SarInfo sarInfo) { - if (sarInfo.sarSapSupported && sarInfo.sarVoiceCallSupported) { - if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) { - return android.hardware.wifi.V1_2.IWifiChip - .TxPowerScenario.ON_HEAD_CELL_ON; - } else if (sarInfo.isWifiSapEnabled) { - return android.hardware.wifi.V1_2.IWifiChip - .TxPowerScenario.ON_BODY_CELL_ON; - } else { - throw new IllegalArgumentException("bad scenario: no voice call/softAP active"); - } - } else if (sarInfo.sarVoiceCallSupported) { - /* SAR SoftAP input not supported, act like V1_1 */ - if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) { - return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL; - } else { - throw new IllegalArgumentException("bad scenario: voice call not active"); - } - } else { - throw new IllegalArgumentException("Invalid case: voice call not supported"); - } - } - - /** - * Select one of the pre-configured TX power level scenarios or reset it back to normal. - * Primarily used for meeting SAR requirements during voice calls. - * - * Note: If it was found out that the scenario to be reported is the same as last reported one, - * then exit with success. - * This is to handle the case when some HAL versions deal with different inputs equally, - * in that case, we should not call the hal unless there is a change in scenario. - * Note: It is assumed that this method is only called if SAR is enabled. The logic of whether - * to call it or not resides in SarManager class. - * - * @param sarInfo The collection of inputs to select the SAR scenario. - * @return true for success; false for failure or if the HAL version does not support this API. - */ - public boolean selectTxPowerScenario(SarInfo sarInfo) { - synchronized (sLock) { - // First attempt to get a V_1_2 instance of the Wifi HAL. - android.hardware.wifi.V1_2.IWifiChip iWifiChipV12 = getWifiChipForV1_2Mockable(); - if (iWifiChipV12 != null) { - return selectTxPowerScenario_1_2(iWifiChipV12, sarInfo); - } - - // Now attempt to get a V_1_1 instance of the Wifi HAL. - android.hardware.wifi.V1_1.IWifiChip iWifiChipV11 = getWifiChipForV1_1Mockable(); - if (iWifiChipV11 != null) { - return selectTxPowerScenario_1_1(iWifiChipV11, sarInfo); - } - - // HAL version does not support SAR - return false; - } - } - - private boolean selectTxPowerScenario_1_1( - android.hardware.wifi.V1_1.IWifiChip iWifiChip, SarInfo sarInfo) { - WifiStatus status; - try { - if (sarPowerBackoffRequired_1_1(sarInfo)) { - // Power backoff is needed, so calculate the required scenario, - // and attempt to set it. - int halScenario = frameworkToHalTxPowerScenario_1_1(sarInfo); - if (sarInfo.setSarScenarioNeeded(halScenario)) { - status = iWifiChip.selectTxPowerScenario(halScenario); - if (ok(status)) { - mLog.d("Setting SAR scenario to " + halScenario); - return true; - } else { - mLog.e("Failed to set SAR scenario to " + halScenario); - return false; - } - } - - // Reaching here means setting SAR scenario would be redundant, - // do nothing and return with success. - return true; - } - - // We don't need to perform power backoff, so attempt to reset SAR scenario. - if (sarInfo.resetSarScenarioNeeded()) { - status = iWifiChip.resetTxPowerScenario(); - if (ok(status)) { - mLog.d("Resetting SAR scenario"); - return true; - } else { - mLog.e("Failed to reset SAR scenario"); - return false; - } - } - - // Resetting SAR scenario would be redundant, - // do nothing and return with success. - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } catch (IllegalArgumentException e) { - mLog.err("Illegal argument for selectTxPowerScenario_1_1()").c(e.toString()).flush(); - return false; - } - } - - private boolean selectTxPowerScenario_1_2( - android.hardware.wifi.V1_2.IWifiChip iWifiChip, SarInfo sarInfo) { - WifiStatus status; - try { - if (sarPowerBackoffRequired_1_2(sarInfo)) { - // Power backoff is needed, so calculate the required scenario, - // and attempt to set it. - int halScenario = frameworkToHalTxPowerScenario_1_2(sarInfo); - if (sarInfo.setSarScenarioNeeded(halScenario)) { - status = iWifiChip.selectTxPowerScenario_1_2(halScenario); - if (ok(status)) { - mLog.d("Setting SAR scenario to " + halScenario); - return true; - } else { - mLog.e("Failed to set SAR scenario to " + halScenario); - return false; - } - } - - // Reaching here means setting SAR scenario would be redundant, - // do nothing and return with success. - return true; - } - - // We don't need to perform power backoff, so attempt to reset SAR scenario. - if (sarInfo.resetSarScenarioNeeded()) { - status = iWifiChip.resetTxPowerScenario(); - if (ok(status)) { - mLog.d("Resetting SAR scenario"); - return true; - } else { - mLog.e("Failed to reset SAR scenario"); - return false; - } - } - - // Resetting SAR scenario would be redundant, - // do nothing and return with success. - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } catch (IllegalArgumentException e) { - mLog.err("Illegal argument for selectTxPowerScenario_1_2()").c(e.toString()).flush(); - return false; - } - } - - /** - * Enable/Disable low-latency mode - * - * @param enabled true to enable low-latency mode, false to disable it - */ - public boolean setLowLatencyMode(boolean enabled) { - synchronized (sLock) { - android.hardware.wifi.V1_3.IWifiChip iWifiChipV13 = getWifiChipForV1_3Mockable(); - if (iWifiChipV13 != null) { - try { - int mode; - if (enabled) { - mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.LOW; - } else { - mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.NORMAL; - } - - WifiStatus status = iWifiChipV13.setLatencyMode(mode); - if (ok(status)) { - mVerboseLog.d("Setting low-latency mode to " + enabled); - return true; - } else { - mLog.e("Failed to set low-latency mode to " + enabled); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - - // HAL version does not support this api - return false; - } - } - - /** - * Returns whether STA/AP concurrency is supported or not. - */ - public boolean isStaApConcurrencySupported() { - synchronized (sLock) { - return mHalDeviceManager.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.AP, 1); - }}); - } - } - - // This creates a blob of IE elements from the array received. - // TODO: This ugly conversion can be removed if we put IE elements in ScanResult. - private static byte[] hidlIeArrayToFrameworkIeBlob(ArrayList<WifiInformationElement> ies) { - if (ies == null || ies.isEmpty()) return new byte[0]; - ArrayList<Byte> ieBlob = new ArrayList<>(); - for (WifiInformationElement ie : ies) { - ieBlob.add(ie.id); - ieBlob.addAll(ie.data); - } - return NativeUtil.byteArrayFromArrayList(ieBlob); - } - - // This is only filling up the fields of Scan Result used by Gscan clients. - private static ScanResult hidlToFrameworkScanResult(StaScanResult scanResult) { - if (scanResult == null) return null; - ScanResult frameworkScanResult = new ScanResult(); - frameworkScanResult.SSID = NativeUtil.encodeSsid(scanResult.ssid); - frameworkScanResult.wifiSsid = - WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(scanResult.ssid)); - frameworkScanResult.BSSID = NativeUtil.macAddressFromByteArray(scanResult.bssid); - frameworkScanResult.level = scanResult.rssi; - frameworkScanResult.frequency = scanResult.frequency; - frameworkScanResult.timestamp = scanResult.timeStampInUs; - return frameworkScanResult; - } - - private static ScanResult[] hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults) { - if (scanResults == null || scanResults.isEmpty()) return new ScanResult[0]; - ScanResult[] frameworkScanResults = new ScanResult[scanResults.size()]; - int i = 0; - for (StaScanResult scanResult : scanResults) { - frameworkScanResults[i++] = hidlToFrameworkScanResult(scanResult); - } - return frameworkScanResults; - } - - /** - * This just returns whether the scan was interrupted or not. - */ - private static int hidlToFrameworkScanDataFlags(int flag) { - if (flag == StaScanDataFlagMask.INTERRUPTED) { - return 1; - } else { - return 0; - } - } - - private static WifiScanner.ScanData[] hidlToFrameworkScanDatas( - int cmdId, ArrayList<StaScanData> scanDatas) { - if (scanDatas == null || scanDatas.isEmpty()) return new WifiScanner.ScanData[0]; - WifiScanner.ScanData[] frameworkScanDatas = new WifiScanner.ScanData[scanDatas.size()]; - int i = 0; - for (StaScanData scanData : scanDatas) { - int flags = hidlToFrameworkScanDataFlags(scanData.flags); - ScanResult[] frameworkScanResults = hidlToFrameworkScanResults(scanData.results); - frameworkScanDatas[i++] = - new WifiScanner.ScanData(cmdId, flags, scanData.bucketsScanned, - WifiScanner.WIFI_BAND_UNSPECIFIED, frameworkScanResults); - } - return frameworkScanDatas; - } - - /** - * Callback for events on the STA interface. - */ - private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub { - @Override - public void onBackgroundScanFailure(int cmdId) { - mVerboseLog.d("onBackgroundScanFailure " + cmdId); - WifiNative.ScanEventHandler eventHandler; - synchronized (sLock) { - if (mScan == null || cmdId != mScan.cmdId) return; - eventHandler = mScan.eventHandler; - } - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED); - } - - @Override - public void onBackgroundFullScanResult( - int cmdId, int bucketsScanned, StaScanResult result) { - mVerboseLog.d("onBackgroundFullScanResult " + cmdId); - WifiNative.ScanEventHandler eventHandler; - synchronized (sLock) { - if (mScan == null || cmdId != mScan.cmdId) return; - eventHandler = mScan.eventHandler; - } - eventHandler.onFullScanResult(hidlToFrameworkScanResult(result), bucketsScanned); - } - - @Override - public void onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas) { - mVerboseLog.d("onBackgroundScanResults " + cmdId); - WifiNative.ScanEventHandler eventHandler; - // WifiScanner currently uses the results callback to fetch the scan results. - // So, simulate that by sending out the notification and then caching the results - // locally. This will then be returned to WifiScanner via getScanResults. - synchronized (sLock) { - if (mScan == null || cmdId != mScan.cmdId) return; - eventHandler = mScan.eventHandler; - mScan.latestScanResults = hidlToFrameworkScanDatas(cmdId, scanDatas); - } - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - } - - @Override - public void onRssiThresholdBreached(int cmdId, byte[/* 6 */] currBssid, int currRssi) { - mVerboseLog.d("onRssiThresholdBreached " + cmdId + "currRssi " + currRssi); - WifiNative.WifiRssiEventHandler eventHandler; - synchronized (sLock) { - if (mWifiRssiEventHandler == null || cmdId != sRssiMonCmdId) return; - eventHandler = mWifiRssiEventHandler; - } - eventHandler.onRssiThresholdBreached((byte) currRssi); - } - } - - /** - * Callback for events on the chip. - */ - private class ChipEventCallback extends IWifiChipEventCallback.Stub { - @Override - public void onChipReconfigured(int modeId) { - mVerboseLog.d("onChipReconfigured " + modeId); - } - - @Override - public void onChipReconfigureFailure(WifiStatus status) { - mVerboseLog.d("onChipReconfigureFailure " + status); - } - - public void onIfaceAdded(int type, String name) { - mVerboseLog.d("onIfaceAdded " + type + ", name: " + name); - } - - @Override - public void onIfaceRemoved(int type, String name) { - mVerboseLog.d("onIfaceRemoved " + type + ", name: " + name); - } - - @Override - public void onDebugRingBufferDataAvailable( - WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { - //TODO(b/35875078) Reinstate logging when execessive callbacks are fixed - // mVerboseLog.d("onDebugRingBufferDataAvailable " + status); - mHalEventHandler.post(() -> { - WifiNative.WifiLoggerEventHandler eventHandler; - synchronized (sLock) { - if (mLogEventHandler == null || status == null || data == null) return; - eventHandler = mLogEventHandler; - } - // Because |sLock| has been released, there is a chance that we'll execute - // a spurious callback (after someone has called resetLogHandler()). - // - // However, the alternative risks deadlock. Consider: - // [T1.1] WifiDiagnostics.captureBugReport() - // [T1.2] -- acquire WifiDiagnostics object's intrinsic lock - // [T1.3] -> WifiVendorHal.getRingBufferData() - // [T1.4] -- acquire WifiVendorHal.sLock - // [T2.1] <lambda>() - // [T2.2] -- acquire WifiVendorHal.sLock - // [T2.3] -> WifiDiagnostics.onRingBufferData() - // [T2.4] -- acquire WifiDiagnostics object's intrinsic lock - // - // The problem here is that the two threads acquire the locks in opposite order. - // If, for example, T2.2 executes between T1.2 and 1.4, then T1 and T2 - // will be deadlocked. - int sizeBefore = data.size(); - boolean conversionFailure = false; - try { - eventHandler.onRingBufferData( - ringBufferStatus(status), NativeUtil.byteArrayFromArrayList(data)); - int sizeAfter = data.size(); - if (sizeAfter != sizeBefore) { - conversionFailure = true; - } - } catch (ArrayIndexOutOfBoundsException e) { - conversionFailure = true; - } - if (conversionFailure) { - Log.wtf("WifiVendorHal", "Conversion failure detected in " - + "onDebugRingBufferDataAvailable. " - + "The input ArrayList |data| is potentially corrupted. " - + "Starting size=" + sizeBefore + ", " - + "final size=" + data.size()); - } - }); - } - - @Override - public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { - mLog.w("onDebugErrorAlert " + errorCode); - mHalEventHandler.post(() -> { - WifiNative.WifiLoggerEventHandler eventHandler; - synchronized (sLock) { - if (mLogEventHandler == null || debugData == null) return; - eventHandler = mLogEventHandler; - } - // See comment in onDebugRingBufferDataAvailable(), for an explanation - // of why this callback is invoked without |sLock| held. - eventHandler.onWifiAlert( - errorCode, NativeUtil.byteArrayFromArrayList(debugData)); - }); - } - } - - private boolean areSameIfaceNames(List<IfaceInfo> ifaceList1, List<IfaceInfo> ifaceList2) { - List<String> ifaceNamesList1 = ifaceList1 - .stream() - .map(i -> i.name) - .collect(Collectors.toList()); - List<String> ifaceNamesList2 = ifaceList2 - .stream() - .map(i -> i.name) - .collect(Collectors.toList()); - return ifaceNamesList1.containsAll(ifaceNamesList2); - } - - /** - * Callback for events on the 1.2 chip. - */ - private class ChipEventCallbackV12 extends - android.hardware.wifi.V1_2.IWifiChipEventCallback.Stub { - @Override - public void onChipReconfigured(int modeId) { - mIWifiChipEventCallback.onChipReconfigured(modeId); - } - - @Override - public void onChipReconfigureFailure(WifiStatus status) { - mIWifiChipEventCallback.onChipReconfigureFailure(status); - } - - public void onIfaceAdded(int type, String name) { - mIWifiChipEventCallback.onIfaceAdded(type, name); - } - - @Override - public void onIfaceRemoved(int type, String name) { - mIWifiChipEventCallback.onIfaceRemoved(type, name); - } - - @Override - public void onDebugRingBufferDataAvailable( - WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { - mIWifiChipEventCallback.onDebugRingBufferDataAvailable(status, data); - } - - @Override - public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { - mIWifiChipEventCallback.onDebugErrorAlert(errorCode, debugData); - } - - @Override - public void onRadioModeChange(ArrayList<RadioModeInfo> radioModeInfoList) { - mVerboseLog.d("onRadioModeChange " + radioModeInfoList); - WifiNative.VendorHalRadioModeChangeEventHandler handler; - synchronized (sLock) { - if (mRadioModeChangeEventHandler == null || radioModeInfoList == null) return; - handler = mRadioModeChangeEventHandler; - } - // Should only contain 1 or 2 radio infos. - if (radioModeInfoList.size() == 0 || radioModeInfoList.size() > 2) { - mLog.e("Unexpected number of radio info in list " + radioModeInfoList.size()); - return; - } - RadioModeInfo radioModeInfo0 = radioModeInfoList.get(0); - RadioModeInfo radioModeInfo1 = - radioModeInfoList.size() == 2 ? radioModeInfoList.get(1) : null; - // Number of ifaces on each radio should be equal. - if (radioModeInfo1 != null - && radioModeInfo0.ifaceInfos.size() != radioModeInfo1.ifaceInfos.size()) { - mLog.e("Unexpected number of iface info in list " - + radioModeInfo0.ifaceInfos.size() + ", " - + radioModeInfo1.ifaceInfos.size()); - return; - } - int numIfacesOnEachRadio = radioModeInfo0.ifaceInfos.size(); - // Only 1 or 2 ifaces should be present on each radio. - if (numIfacesOnEachRadio == 0 || numIfacesOnEachRadio > 2) { - mLog.e("Unexpected number of iface info in list " + numIfacesOnEachRadio); - return; - } - Runnable runnable = null; - // 2 ifaces simultaneous on 2 radios. - if (radioModeInfoList.size() == 2 && numIfacesOnEachRadio == 1) { - // Iface on radio0 should be different from the iface on radio1 for DBS & SBS. - if (areSameIfaceNames(radioModeInfo0.ifaceInfos, radioModeInfo1.ifaceInfos)) { - mLog.e("Unexpected for both radio infos to have same iface"); - return; - } - if (radioModeInfo0.bandInfo != radioModeInfo1.bandInfo) { - runnable = () -> { - handler.onDbs(); - }; - } else { - runnable = () -> { - handler.onSbs(radioModeInfo0.bandInfo); - }; - } - // 2 ifaces time sharing on 1 radio. - } else if (radioModeInfoList.size() == 1 && numIfacesOnEachRadio == 2) { - IfaceInfo ifaceInfo0 = radioModeInfo0.ifaceInfos.get(0); - IfaceInfo ifaceInfo1 = radioModeInfo0.ifaceInfos.get(1); - if (ifaceInfo0.channel != ifaceInfo1.channel) { - runnable = () -> { - handler.onMcc(radioModeInfo0.bandInfo); - }; - } else { - runnable = () -> { - handler.onScc(radioModeInfo0.bandInfo); - }; - } - } else { - // Not concurrency scenario, uninteresting... - } - if (runnable != null) mHalEventHandler.post(runnable); - } - } - - /** - * Callback for events on the 1.4 chip. - */ - private class ChipEventCallbackV14 extends - android.hardware.wifi.V1_4.IWifiChipEventCallback.Stub { - @Override - public void onChipReconfigured(int modeId) { - mIWifiChipEventCallback.onChipReconfigured(modeId); - } - - @Override - public void onChipReconfigureFailure(WifiStatus status) { - mIWifiChipEventCallback.onChipReconfigureFailure(status); - } - - public void onIfaceAdded(int type, String name) { - mIWifiChipEventCallback.onIfaceAdded(type, name); - } - - @Override - public void onIfaceRemoved(int type, String name) { - mIWifiChipEventCallback.onIfaceRemoved(type, name); - } - - @Override - public void onDebugRingBufferDataAvailable( - WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { - mIWifiChipEventCallback.onDebugRingBufferDataAvailable(status, data); - } - - @Override - public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { - mIWifiChipEventCallback.onDebugErrorAlert(errorCode, debugData); - } - - @Override - public void onRadioModeChange( - ArrayList<android.hardware.wifi.V1_2.IWifiChipEventCallback.RadioModeInfo> - radioModeInfoList) { - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfoList); - } - - @Override - public void onRadioModeChange_1_4(ArrayList<RadioModeInfo> radioModeInfoList) { - mVerboseLog.d("onRadioModeChange_1_4 " + radioModeInfoList); - WifiNative.VendorHalRadioModeChangeEventHandler handler; - synchronized (sLock) { - if (mRadioModeChangeEventHandler == null || radioModeInfoList == null) return; - handler = mRadioModeChangeEventHandler; - } - // Should only contain 1 or 2 radio infos. - if (radioModeInfoList.size() == 0 || radioModeInfoList.size() > 2) { - mLog.e("Unexpected number of radio info in list " + radioModeInfoList.size()); - return; - } - RadioModeInfo radioModeInfo0 = radioModeInfoList.get(0); - RadioModeInfo radioModeInfo1 = - radioModeInfoList.size() == 2 ? radioModeInfoList.get(1) : null; - // Number of ifaces on each radio should be equal. - if (radioModeInfo1 != null - && radioModeInfo0.ifaceInfos.size() != radioModeInfo1.ifaceInfos.size()) { - mLog.e("Unexpected number of iface info in list " - + radioModeInfo0.ifaceInfos.size() + ", " - + radioModeInfo1.ifaceInfos.size()); - return; - } - int numIfacesOnEachRadio = radioModeInfo0.ifaceInfos.size(); - // Only 1 or 2 ifaces should be present on each radio. - if (numIfacesOnEachRadio == 0 || numIfacesOnEachRadio > 2) { - mLog.e("Unexpected number of iface info in list " + numIfacesOnEachRadio); - return; - } - Runnable runnable = null; - // 2 ifaces simultaneous on 2 radios. - if (radioModeInfoList.size() == 2 && numIfacesOnEachRadio == 1) { - // Iface on radio0 should be different from the iface on radio1 for DBS & SBS. - if (areSameIfaceNames(radioModeInfo0.ifaceInfos, radioModeInfo1.ifaceInfos)) { - mLog.e("Unexpected for both radio infos to have same iface"); - return; - } - if (radioModeInfo0.bandInfo != radioModeInfo1.bandInfo) { - runnable = () -> { - handler.onDbs(); - }; - } else { - runnable = () -> { - handler.onSbs(radioModeInfo0.bandInfo); - }; - } - // 2 ifaces time sharing on 1 radio. - } else if (radioModeInfoList.size() == 1 && numIfacesOnEachRadio == 2) { - IfaceInfo ifaceInfo0 = radioModeInfo0.ifaceInfos.get(0); - IfaceInfo ifaceInfo1 = radioModeInfo0.ifaceInfos.get(1); - if (ifaceInfo0.channel != ifaceInfo1.channel) { - runnable = () -> { - handler.onMcc(radioModeInfo0.bandInfo); - }; - } else { - runnable = () -> { - handler.onScc(radioModeInfo0.bandInfo); - }; - } - } else { - // Not concurrency scenario, uninteresting... - } - if (runnable != null) mHalEventHandler.post(runnable); - } - } - - /** - * Hal Device Manager callbacks. - */ - public class HalDeviceManagerStatusListener implements HalDeviceManager.ManagerStatusListener { - @Override - public void onStatusChanged() { - boolean isReady = mHalDeviceManager.isReady(); - boolean isStarted = mHalDeviceManager.isStarted(); - - mVerboseLog.i("Device Manager onStatusChanged. isReady(): " + isReady - + ", isStarted(): " + isStarted); - if (!isReady) { - // Probably something unpleasant, e.g. the server died - WifiNative.VendorHalDeathEventHandler handler; - synchronized (sLock) { - clearState(); - handler = mDeathEventHandler; - } - if (handler != null) { - handler.onDeath(); - } - } - if (isStarted) { - synchronized (sLock) { - if (mStaIfaceAvailableForRequestListener != null) { - mHalDeviceManager.registerInterfaceAvailableForRequestListener( - IfaceType.STA, mStaIfaceAvailableForRequestListener, - mHalEventHandler); - } - if (mApIfaceAvailableForRequestListener != null) { - mHalDeviceManager.registerInterfaceAvailableForRequestListener( - IfaceType.AP, mApIfaceAvailableForRequestListener, - mHalEventHandler); - } - } - } - } - } -} diff --git a/service/java/com/android/server/wifi/WifiWakeMetrics.java b/service/java/com/android/server/wifi/WifiWakeMetrics.java deleted file mode 100644 index 64b13be45..000000000 --- a/service/java/com/android/server/wifi/WifiWakeMetrics.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import android.annotation.Nullable; -import android.os.SystemClock; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiWakeStats; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -/** - * Holds WifiWake metrics and converts them to a protobuf included in WifiLog. - */ -public class WifiWakeMetrics { - - /** Maximum number of sessions to store in WifiWakeStats proto. */ - @VisibleForTesting - static final int MAX_RECORDED_SESSIONS = 10; - - @GuardedBy("mLock") - private final List<Session> mSessions = new ArrayList<>(); - @GuardedBy("mLock") - private Session mCurrentSession; - - private boolean mIsInSession = false; - private int mTotalSessions = 0; - private int mTotalWakeups = 0; - private int mIgnoredStarts = 0; - - private final Object mLock = new Object(); - - /** - * Records the beginning of a Wifi Wake session. - * - * <p>Starts the session. - * - * @param numNetworks The total number of networks stored in the WakeupLock at start. - */ - public void recordStartEvent(int numNetworks) { - synchronized (mLock) { - mCurrentSession = new Session(numNetworks, SystemClock.elapsedRealtime()); - mIsInSession = true; - } - } - - /** - * Records the initialize event of the current Wifi Wake session. - * - * <p>Note: The start event must be recorded before this event, otherwise this call will be - * ignored. - * - * @param numScans The total number of elapsed scans since start. - * @param numNetworks The total number of networks in the lock. - */ - public void recordInitializeEvent(int numScans, int numNetworks) { - synchronized (mLock) { - if (!mIsInSession) { - return; - } - mCurrentSession.recordInitializeEvent(numScans, numNetworks, - SystemClock.elapsedRealtime()); - } - } - - /** - * Records the unlock event of the current Wifi Wake session. - * - * <p>The unlock event occurs when the WakeupLock has all of its networks removed. This event - * will not be recorded if the initialize event recorded 0 locked networks. - * - * <p>Note: The start event must be recorded before this event, otherwise this call will be - * ignored. - * - * @param numScans The total number of elapsed scans since start. - */ - public void recordUnlockEvent(int numScans) { - synchronized (mLock) { - if (!mIsInSession) { - return; - } - mCurrentSession.recordUnlockEvent(numScans, SystemClock.elapsedRealtime()); - } - } - - /** - * Records the wakeup event of the current Wifi Wake session. - * - * <p>The wakeup event occurs when Wifi is re-enabled by the WakeupController. - * - * <p>Note: The start event must be recorded before this event, otherwise this call will be - * ignored. - * - * @param numScans The total number of elapsed scans since start. - */ - public void recordWakeupEvent(int numScans) { - synchronized (mLock) { - if (!mIsInSession) { - return; - } - mCurrentSession.recordWakeupEvent(numScans, SystemClock.elapsedRealtime()); - } - } - - /** - * Records the reset event of the current Wifi Wake session. - * - * <p>The reset event occurs when Wifi enters client mode. Stores the first - * {@link #MAX_RECORDED_SESSIONS} in the session list. - * - * <p>Note: The start event must be recorded before this event, otherwise this call will be - * ignored. This event ends the current session. - * - * @param numScans The total number of elapsed scans since start. - */ - public void recordResetEvent(int numScans) { - synchronized (mLock) { - if (!mIsInSession) { - return; - } - mCurrentSession.recordResetEvent(numScans, SystemClock.elapsedRealtime()); - - // tally successful wakeups here since this is the actual point when wifi is turned on - if (mCurrentSession.hasWakeupTriggered()) { - mTotalWakeups++; - } - - mTotalSessions++; - if (mSessions.size() < MAX_RECORDED_SESSIONS) { - mSessions.add(mCurrentSession); - } - mIsInSession = false; - } - } - - /** - * Records instance of the start event being ignored due to the controller already being active. - */ - public void recordIgnoredStart() { - mIgnoredStarts++; - } - - /** - * Returns the consolidated WifiWakeStats proto for WifiMetrics. - */ - public WifiWakeStats buildProto() { - WifiWakeStats proto = new WifiWakeStats(); - - proto.numSessions = mTotalSessions; - proto.numWakeups = mTotalWakeups; - proto.numIgnoredStarts = mIgnoredStarts; - proto.sessions = new WifiWakeStats.Session[mSessions.size()]; - - for (int i = 0; i < mSessions.size(); i++) { - proto.sessions[i] = mSessions.get(i).buildProto(); - } - - return proto; - } - - /** - * Dump all WifiWake stats to console (pw) - * @param pw - */ - public void dump(PrintWriter pw) { - synchronized (mLock) { - pw.println("-------WifiWake metrics-------"); - pw.println("mTotalSessions: " + mTotalSessions); - pw.println("mTotalWakeups: " + mTotalWakeups); - pw.println("mIgnoredStarts: " + mIgnoredStarts); - pw.println("mIsInSession: " + mIsInSession); - pw.println("Stored Sessions: " + mSessions.size()); - for (Session session : mSessions) { - session.dump(pw); - } - if (mCurrentSession != null) { - pw.println("Current Session: "); - mCurrentSession.dump(pw); - } - pw.println("----end of WifiWake metrics----"); - } - } - - /** - * Clears WifiWakeMetrics. - * - * <p>Keeps the current WifiWake session. - */ - public void clear() { - synchronized (mLock) { - mSessions.clear(); - mTotalSessions = 0; - mTotalWakeups = 0; - mIgnoredStarts = 0; - } - } - - /** A single WifiWake session. */ - public static class Session { - - private final long mStartTimestamp; - private final int mStartNetworks; - private int mInitializeNetworks = 0; - - @VisibleForTesting - @Nullable - Event mUnlockEvent; - @VisibleForTesting - @Nullable - Event mInitEvent; - @VisibleForTesting - @Nullable - Event mWakeupEvent; - @VisibleForTesting - @Nullable - Event mResetEvent; - - /** Creates a new WifiWake session. */ - public Session(int numNetworks, long timestamp) { - mStartNetworks = numNetworks; - mStartTimestamp = timestamp; - } - - /** - * Records an initialize event. - * - * <p>Ignores subsequent calls. - * - * @param numScans Total number of scans at the time of this event. - * @param numNetworks Total number of networks in the lock. - * @param timestamp The timestamp of the event. - */ - public void recordInitializeEvent(int numScans, int numNetworks, long timestamp) { - if (mInitEvent == null) { - mInitializeNetworks = numNetworks; - mInitEvent = new Event(numScans, timestamp - mStartTimestamp); - } - } - - /** - * Records an unlock event. - * - * <p>Ignores subsequent calls. - * - * @param numScans Total number of scans at the time of this event. - * @param timestamp The timestamp of the event. - */ - public void recordUnlockEvent(int numScans, long timestamp) { - if (mUnlockEvent == null) { - mUnlockEvent = new Event(numScans, timestamp - mStartTimestamp); - } - } - - /** - * Records a wakeup event. - * - * <p>Ignores subsequent calls. - * - * @param numScans Total number of scans at the time of this event. - * @param timestamp The timestamp of the event. - */ - public void recordWakeupEvent(int numScans, long timestamp) { - if (mWakeupEvent == null) { - mWakeupEvent = new Event(numScans, timestamp - mStartTimestamp); - } - } - - /** - * Returns whether the current session has had its wakeup event triggered. - */ - public boolean hasWakeupTriggered() { - return mWakeupEvent != null; - } - - /** - * Records a reset event. - * - * <p>Ignores subsequent calls. - * - * @param numScans Total number of scans at the time of this event. - * @param timestamp The timestamp of the event. - */ - public void recordResetEvent(int numScans, long timestamp) { - if (mResetEvent == null) { - mResetEvent = new Event(numScans, timestamp - mStartTimestamp); - } - } - - /** Returns the proto representation of this session. */ - public WifiWakeStats.Session buildProto() { - WifiWakeStats.Session sessionProto = new WifiWakeStats.Session(); - sessionProto.startTimeMillis = mStartTimestamp; - sessionProto.lockedNetworksAtStart = mStartNetworks; - - if (mInitEvent != null) { - sessionProto.lockedNetworksAtInitialize = mInitializeNetworks; - sessionProto.initializeEvent = mInitEvent.buildProto(); - } - if (mUnlockEvent != null) { - sessionProto.unlockEvent = mUnlockEvent.buildProto(); - } - if (mWakeupEvent != null) { - sessionProto.wakeupEvent = mWakeupEvent.buildProto(); - } - if (mResetEvent != null) { - sessionProto.resetEvent = mResetEvent.buildProto(); - } - - return sessionProto; - } - - /** Dumps the current state of the session. */ - public void dump(PrintWriter pw) { - pw.println("WifiWakeMetrics.Session:"); - pw.println("mStartTimestamp: " + mStartTimestamp); - pw.println("mStartNetworks: " + mStartNetworks); - pw.println("mInitializeNetworks: " + mInitializeNetworks); - pw.println("mInitEvent: " + (mInitEvent == null ? "{}" : mInitEvent.toString())); - pw.println("mUnlockEvent: " + (mUnlockEvent == null ? "{}" : mUnlockEvent.toString())); - pw.println("mWakeupEvent: " + (mWakeupEvent == null ? "{}" : mWakeupEvent.toString())); - pw.println("mResetEvent: " + (mResetEvent == null ? "{}" : mResetEvent.toString())); - } - } - - /** An event in a WifiWake session. */ - public static class Event { - - /** Total number of scans that have elapsed prior to this event. */ - public final int mNumScans; - /** Total elapsed time in milliseconds at the instant of this event. */ - public final long mElapsedTime; - - public Event(int numScans, long elapsedTime) { - mNumScans = numScans; - mElapsedTime = elapsedTime; - } - - /** Returns the proto representation of this event. */ - public WifiWakeStats.Session.Event buildProto() { - WifiWakeStats.Session.Event eventProto = new WifiWakeStats.Session.Event(); - eventProto.elapsedScans = mNumScans; - eventProto.elapsedTimeMillis = mElapsedTime; - return eventProto; - } - - @Override - public String toString() { - return "{ mNumScans: " + mNumScans + ", elapsedTime: " + mElapsedTime + " }"; - } - } -} diff --git a/service/java/com/android/server/wifi/WlanWakeReasonAndCounts.java b/service/java/com/android/server/wifi/WlanWakeReasonAndCounts.java deleted file mode 100644 index 3311ec7d6..000000000 --- a/service/java/com/android/server/wifi/WlanWakeReasonAndCounts.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * A class representing WLAN wake reason accounting. - */ - -/** @hide */ -public class WlanWakeReasonAndCounts implements Parcelable { - private static final String TAG = "WlanWakeReasonAndCounts"; - /** - * Wlan can wake host, only when it is cmd/event, local driver-fw - * functions(non-data, non cmd/event) and rx data.The first packet - * from wlan that woke up a sleep host is what is accounted here. - * Total wlan wake to application processor would be: - * [cmdEventWake + driverFwLocalWake + totalRxDataWake] - * A further classification is provided for identifying the reasons - * for wakeup. - */ - public int totalCmdEventWake; - public int totalDriverFwLocalWake; - public int totalRxDataWake; - - public int rxUnicast; - public int rxMulticast; - public int rxBroadcast; - - public int icmp; - public int icmp6; - public int icmp6Ra; - public int icmp6Na; - public int icmp6Ns; - - public int ipv4RxMulticast; - public int ipv6Multicast; - public int otherRxMulticast; - public int[] cmdEventWakeCntArray; - public int[] driverFWLocalWakeCntArray; - - /* {@hide} */ - public WlanWakeReasonAndCounts() { - } - - @Override - /* {@hide} */ - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(" totalCmdEventWake ").append(totalCmdEventWake); - sb.append(" totalDriverFwLocalWake ").append(totalDriverFwLocalWake); - sb.append(" totalRxDataWake ").append(totalRxDataWake); - - sb.append(" rxUnicast ").append(rxUnicast); - sb.append(" rxMulticast ").append(rxMulticast); - sb.append(" rxBroadcast ").append(rxBroadcast); - - sb.append(" icmp ").append(icmp); - sb.append(" icmp6 ").append(icmp6); - sb.append(" icmp6Ra ").append(icmp6Ra); - sb.append(" icmp6Na ").append(icmp6Na); - sb.append(" icmp6Ns ").append(icmp6Ns); - - sb.append(" ipv4RxMulticast ").append(ipv4RxMulticast); - sb.append(" ipv6Multicast ").append(ipv6Multicast); - sb.append(" otherRxMulticast ").append(otherRxMulticast); - for (int i = 0; i < cmdEventWakeCntArray.length; i++) { - sb.append(" cmdEventWakeCntArray[" + i + "] " + cmdEventWakeCntArray[i]); - } - for (int i = 0; i < driverFWLocalWakeCntArray.length; i++) { - sb.append(" driverFWLocalWakeCntArray[" + i + "] " + driverFWLocalWakeCntArray[i]); - } - - return sb.toString(); - } - - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public int describeContents() { - return 0; - } - - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(totalCmdEventWake); - dest.writeInt(totalDriverFwLocalWake); - dest.writeInt(totalRxDataWake); - - dest.writeInt(rxUnicast); - dest.writeInt(rxMulticast); - dest.writeInt(rxBroadcast); - - dest.writeInt(icmp); - dest.writeInt(icmp6); - dest.writeInt(icmp6Ra); - dest.writeInt(icmp6Na); - dest.writeInt(icmp6Ns); - - dest.writeInt(ipv4RxMulticast); - dest.writeInt(ipv6Multicast); - dest.writeInt(otherRxMulticast); - dest.writeIntArray(cmdEventWakeCntArray); - dest.writeIntArray(driverFWLocalWakeCntArray); - } - - /* Implement the Parcelable interface - * {@hide} - */ - public static final Creator<WlanWakeReasonAndCounts> CREATOR = - new Creator<WlanWakeReasonAndCounts>() { - public WlanWakeReasonAndCounts createFromParcel(Parcel in) { - WlanWakeReasonAndCounts counts = new WlanWakeReasonAndCounts(); - counts.totalCmdEventWake = in.readInt(); - counts.totalDriverFwLocalWake = in.readInt(); - counts.totalRxDataWake = in.readInt(); - - counts.rxUnicast = in.readInt(); - counts.rxMulticast = in.readInt(); - counts.rxBroadcast = in.readInt(); - - counts.icmp = in.readInt(); - counts.icmp6 = in.readInt(); - counts.icmp6Ra = in.readInt(); - counts.icmp6Na = in.readInt(); - counts.icmp6Ns = in.readInt(); - - counts.ipv4RxMulticast = in.readInt(); - counts.ipv6Multicast = in.readInt(); - counts.otherRxMulticast = in.readInt(); - in.readIntArray(counts.cmdEventWakeCntArray); - in.readIntArray(counts.driverFWLocalWakeCntArray); - return counts; - } - - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public WlanWakeReasonAndCounts[] newArray(int size) { - return new WlanWakeReasonAndCounts[size]; - } - }; -} diff --git a/service/java/com/android/server/wifi/WrongPasswordNotifier.java b/service/java/com/android/server/wifi/WrongPasswordNotifier.java deleted file mode 100644 index c645ccf6f..000000000 --- a/service/java/com/android/server/wifi/WrongPasswordNotifier.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.app.ActivityManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.drawable.Icon; -import android.os.UserHandle; -import android.provider.Settings; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.server.wifi.util.NativeUtil; - -import java.util.List; - -/** - * Responsible for notifying user for wrong password errors. - */ -public class WrongPasswordNotifier { - private static final String TAG = "WrongPasswordNotifier"; - // Number of milliseconds to wait before automatically dismiss the notification. - private static final long CANCEL_TIMEOUT_MILLISECONDS = 5 * 60 * 1000; - - // Unique ID associated with the notification. - @VisibleForTesting - public static final int NOTIFICATION_ID = SystemMessage.NOTE_WIFI_WRONG_PASSWORD; - - // Flag indicating if a wrong password error is detected for the current connection. - private boolean mWrongPasswordDetected; - - private final WifiContext mContext; - private final NotificationManager mNotificationManager; - private final FrameworkFacade mFrameworkFacade; - - public WrongPasswordNotifier(WifiContext context, FrameworkFacade frameworkFacade) { - mContext = context; - mFrameworkFacade = frameworkFacade; - mNotificationManager = - (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); - } - - /** - * Invoked when a wrong password error for a Wi-Fi network is detected. - * - * @param ssid The SSID of the Wi-Fi network - */ - public void onWrongPasswordError(String ssid) { - showNotification(ssid); - mWrongPasswordDetected = true; - } - - /** - * Invoked when attempting a new Wi-Fi network connection. - */ - public void onNewConnectionAttempt() { - if (mWrongPasswordDetected) { - dismissNotification(); - mWrongPasswordDetected = false; - } - } - - private String getSettingsPackageName() { - Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); - List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentActivitiesAsUser( - intent, PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEFAULT_ONLY, - UserHandle.of(ActivityManager.getCurrentUser())); - if (resolveInfos == null || resolveInfos.isEmpty()) { - Log.e(TAG, "Failed to resolve wifi settings activity"); - return null; - } - // Pick the first one if there are more than 1 since the list is ordered from best to worst. - return resolveInfos.get(0).activityInfo.packageName; - } - - /** - * Display wrong password notification for a given Wi-Fi network (specified by its SSID). - * - * @param ssid SSID of the Wi-FI network - */ - private void showNotification(String ssid) { - String settingsPackage = getSettingsPackageName(); - if (settingsPackage == null) return; - Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS) - .setPackage(settingsPackage) - .putExtra("wifi_start_connect_ssid", NativeUtil.removeEnclosingQuotes(ssid)); - Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext, - WifiService.NOTIFICATION_NETWORK_ALERTS) - .setAutoCancel(true) - .setTimeoutAfter(CANCEL_TIMEOUT_MILLISECONDS) - // TODO(zqiu): consider creating a new icon. - .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), - com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range)) - .setContentTitle(mContext.getString( - com.android.wifi.resources.R.string.wifi_available_title_failed_to_connect)) - .setContentText(ssid) - .setContentIntent(mFrameworkFacade.getActivity( - mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)) - .setColor(mContext.getResources().getColor( - android.R.color.system_notification_accent_color)); - mNotificationManager.notify(NOTIFICATION_ID, builder.build()); - } - - /** - * Dismiss the notification that was generated by {@link #showNotification}. The notification - * might have already been dismissed, either by user or timeout. We'll attempt to dismiss it - * regardless if it is been dismissed or not, to reduce code complexity. - */ - private void dismissNotification() { - // Notification might have already been dismissed, either by user or timeout. It is - // still okay to cancel it if already dismissed. - mNotificationManager.cancel(null, NOTIFICATION_ID); - } -} diff --git a/service/java/com/android/server/wifi/aware/Capabilities.java b/service/java/com/android/server/wifi/aware/Capabilities.java deleted file mode 100644 index 68480c77a..000000000 --- a/service/java/com/android/server/wifi/aware/Capabilities.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import android.hardware.wifi.V1_0.NanCipherSuiteType; -import android.net.wifi.aware.Characteristics; -import android.os.Bundle; - -/** - * A container class for Aware (vendor) implementation capabilities (or - * limitations). Filled-in by the firmware. - */ -public class Capabilities { - public int maxConcurrentAwareClusters; - public int maxPublishes; - public int maxSubscribes; - public int maxServiceNameLen; - public int maxMatchFilterLen; - public int maxTotalMatchFilterLen; - public int maxServiceSpecificInfoLen; - public int maxExtendedServiceSpecificInfoLen; - public int maxNdiInterfaces; - public int maxNdpSessions; - public int maxAppInfoLen; - public int maxQueuedTransmitMessages; - public int maxSubscribeInterfaceAddresses; - public int supportedCipherSuites; - - /** - * Converts the internal capabilities to a parcelable & potentially app-facing - * characteristics bundle. Only some of the information is exposed. - */ - public Characteristics toPublicCharacteristics() { - Bundle bundle = new Bundle(); - bundle.putInt(Characteristics.KEY_MAX_SERVICE_NAME_LENGTH, maxServiceNameLen); - bundle.putInt(Characteristics.KEY_MAX_SERVICE_SPECIFIC_INFO_LENGTH, - maxServiceSpecificInfoLen); - bundle.putInt(Characteristics.KEY_MAX_MATCH_FILTER_LENGTH, maxMatchFilterLen); - bundle.putInt(Characteristics.KEY_SUPPORTED_CIPHER_SUITES, - toPublicCipherSuites(supportedCipherSuites)); - return new Characteristics(bundle); - } - - private int toPublicCipherSuites(int nativeCipherSuites) { - int publicCipherSuites = 0; - - if ((nativeCipherSuites & NanCipherSuiteType.SHARED_KEY_128_MASK) != 0) { - publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128; - } - if ((nativeCipherSuites & NanCipherSuiteType.SHARED_KEY_256_MASK) != 0) { - publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; - } - - return publicCipherSuites; - } - - @Override - public String toString() { - return "Capabilities [maxConcurrentAwareClusters=" + maxConcurrentAwareClusters - + ", maxPublishes=" + maxPublishes + ", maxSubscribes=" + maxSubscribes - + ", maxServiceNameLen=" + maxServiceNameLen + ", maxMatchFilterLen=" - + maxMatchFilterLen + ", maxTotalMatchFilterLen=" + maxTotalMatchFilterLen - + ", maxServiceSpecificInfoLen=" + maxServiceSpecificInfoLen - + ", maxExtendedServiceSpecificInfoLen=" + maxExtendedServiceSpecificInfoLen - + ", maxNdiInterfaces=" + maxNdiInterfaces + ", maxNdpSessions=" - + maxNdpSessions + ", maxAppInfoLen=" + maxAppInfoLen - + ", maxQueuedTransmitMessages=" + maxQueuedTransmitMessages - + ", maxSubscribeInterfaceAddresses=" + maxSubscribeInterfaceAddresses - + ", supportedCipherSuites=" + supportedCipherSuites - + "]"; - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareClientState.java b/service/java/com/android/server/wifi/aware/WifiAwareClientState.java deleted file mode 100644 index c96cf2843..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareClientState.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import android.annotation.Nullable; -import android.app.AppOpsManager; -import android.content.Context; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.IWifiAwareEventCallback; -import android.net.wifi.util.HexEncoding; -import android.os.RemoteException; -import android.util.Log; -import android.util.SparseArray; - -import com.android.server.wifi.util.WifiPermissionsUtil; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Arrays; - -/** - * Manages the service-side Aware state of an individual "client". A client - * corresponds to a single instantiation of the WifiAwareManager - there could be - * multiple ones per UID/process (each of which is a separate client with its - * own session namespace). The client state is primarily: (1) callback (a - * singleton per client) through which Aware-wide events are called, and (2) a set - * of discovery sessions (publish and/or subscribe) which are created through - * this client and whose lifetime is tied to the lifetime of the client. - */ -public class WifiAwareClientState { - private static final String TAG = "WifiAwareClientState"; - private static final boolean VDBG = false; // STOPSHIP if true - private boolean mDbg = false; - - /* package */ static final int CLUSTER_CHANGE_EVENT_STARTED = 0; - /* package */ static final int CLUSTER_CHANGE_EVENT_JOINED = 1; - - private final Context mContext; - private final IWifiAwareEventCallback mCallback; - private final SparseArray<WifiAwareDiscoverySessionState> mSessions = new SparseArray<>(); - - private final int mClientId; - private ConfigRequest mConfigRequest; - private final int mUid; - private final int mPid; - private final String mCallingPackage; - private final @Nullable String mCallingFeatureId; - private final boolean mNotifyIdentityChange; - private final WifiPermissionsUtil mWifiPermissionsUtil; - - private final AppOpsManager mAppOps; - private final long mCreationTime; - - private static final byte[] ALL_ZERO_MAC = new byte[] {0, 0, 0, 0, 0, 0}; - private byte[] mLastDiscoveryInterfaceMac = ALL_ZERO_MAC; - - public WifiAwareClientState(Context context, int clientId, int uid, int pid, - String callingPackage, @Nullable String callingFeatureId, - IWifiAwareEventCallback callback, ConfigRequest configRequest, - boolean notifyIdentityChange, long creationTime, - WifiPermissionsUtil wifiPermissionsUtil) { - mContext = context; - mClientId = clientId; - mUid = uid; - mPid = pid; - mCallingPackage = callingPackage; - mCallingFeatureId = callingFeatureId; - mCallback = callback; - mConfigRequest = configRequest; - mNotifyIdentityChange = notifyIdentityChange; - - mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - mCreationTime = creationTime; - mWifiPermissionsUtil = wifiPermissionsUtil; - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(boolean verbose) { - mDbg = verbose | VDBG; - } - - /** - * Destroy the current client - corresponds to a disconnect() request from - * the client. Destroys all discovery sessions belonging to this client. - */ - public void destroy() { - for (int i = 0; i < mSessions.size(); ++i) { - mSessions.valueAt(i).terminate(); - } - mSessions.clear(); - mConfigRequest = null; - } - - public ConfigRequest getConfigRequest() { - return mConfigRequest; - } - - public int getClientId() { - return mClientId; - } - - public int getUid() { - return mUid; - } - - public String getCallingPackage() { - return mCallingPackage; - } - - public boolean getNotifyIdentityChange() { - return mNotifyIdentityChange; - } - - public long getCreationTime() { - return mCreationTime; - } - - public SparseArray<WifiAwareDiscoverySessionState> getSessions() { - return mSessions; - } - - /** - * Searches the discovery sessions of this client and returns the one - * corresponding to the publish/subscribe ID. Used on callbacks from HAL to - * map callbacks to the correct discovery session. - * - * @param pubSubId The publish/subscribe match session ID. - * @return Aware session corresponding to the requested ID. - */ - public WifiAwareDiscoverySessionState getAwareSessionStateForPubSubId(int pubSubId) { - for (int i = 0; i < mSessions.size(); ++i) { - WifiAwareDiscoverySessionState session = mSessions.valueAt(i); - if (session.isPubSubIdSession(pubSubId)) { - return session; - } - } - - return null; - } - - /** - * Add the session to the client database. - * - * @param session Session to be added. - */ - public void addSession(WifiAwareDiscoverySessionState session) { - int sessionId = session.getSessionId(); - if (mSessions.get(sessionId) != null) { - Log.w(TAG, "createSession: sessionId already exists (replaced) - " + sessionId); - } - - mSessions.put(sessionId, session); - } - - /** - * Remove the specified session from the client database - without doing a - * terminate on the session. The assumption is that it is already - * terminated. - * - * @param sessionId The session ID of the session to be removed. - */ - public void removeSession(int sessionId) { - if (mSessions.get(sessionId) == null) { - Log.e(TAG, "removeSession: sessionId doesn't exist - " + sessionId); - return; - } - - mSessions.delete(sessionId); - } - - /** - * Destroy the discovery session: terminates discovery and frees up - * resources. - * - * @param sessionId The session ID of the session to be destroyed. - */ - public WifiAwareDiscoverySessionState terminateSession(int sessionId) { - WifiAwareDiscoverySessionState session = mSessions.get(sessionId); - if (session == null) { - Log.e(TAG, "terminateSession: sessionId doesn't exist - " + sessionId); - return null; - } - - session.terminate(); - mSessions.delete(sessionId); - - return session; - } - - /** - * Retrieve a session. - * - * @param sessionId Session ID of the session to be retrieved. - * @return Session or null if there's no session corresponding to the - * sessionId. - */ - public WifiAwareDiscoverySessionState getSession(int sessionId) { - return mSessions.get(sessionId); - } - - /** - * Called to dispatch the Aware interface address change to the client - as an - * identity change (interface address information not propagated to client - - * privacy concerns). - * - * @param mac The new MAC address of the discovery interface - optionally propagated to the - * client. - */ - public void onInterfaceAddressChange(byte[] mac) { - if (mDbg) { - Log.v(TAG, - "onInterfaceAddressChange: mClientId=" + mClientId + ", mNotifyIdentityChange=" - + mNotifyIdentityChange + ", mac=" + String.valueOf( - HexEncoding.encode(mac)) + ", mLastDiscoveryInterfaceMac=" - + String.valueOf(HexEncoding.encode(mLastDiscoveryInterfaceMac))); - } - if (mNotifyIdentityChange && !Arrays.equals(mac, mLastDiscoveryInterfaceMac)) { - try { - boolean hasPermission = mWifiPermissionsUtil.checkCallersLocationPermission( - mCallingPackage, mCallingFeatureId, mUid, - /* coarseForTargetSdkLessThanQ */ true, null); - if (VDBG) Log.v(TAG, "hasPermission=" + hasPermission); - mCallback.onIdentityChanged(hasPermission ? mac : ALL_ZERO_MAC); - } catch (RemoteException e) { - Log.w(TAG, "onIdentityChanged: RemoteException - ignored: " + e); - } - } - - mLastDiscoveryInterfaceMac = mac; - } - - /** - * Called to dispatch the Aware cluster change (due to joining of a new - * cluster or starting a cluster) to the client - as an identity change - * (interface address information not propagated to client - privacy - * concerns). Dispatched if the client registered for the identity changed - * event. - * - * @param mac The cluster ID of the cluster started or joined. - * @param currentDiscoveryInterfaceMac The MAC address of the discovery interface. - */ - public void onClusterChange(int flag, byte[] mac, byte[] currentDiscoveryInterfaceMac) { - if (mDbg) { - Log.v(TAG, - "onClusterChange: mClientId=" + mClientId + ", mNotifyIdentityChange=" - + mNotifyIdentityChange + ", mac=" + String.valueOf( - HexEncoding.encode(mac)) + ", currentDiscoveryInterfaceMac=" - + String.valueOf(HexEncoding.encode(currentDiscoveryInterfaceMac)) - + ", mLastDiscoveryInterfaceMac=" + String.valueOf( - HexEncoding.encode(mLastDiscoveryInterfaceMac))); - } - if (mNotifyIdentityChange && !Arrays.equals(currentDiscoveryInterfaceMac, - mLastDiscoveryInterfaceMac)) { - try { - boolean hasPermission = mWifiPermissionsUtil.checkCallersLocationPermission( - mCallingPackage, mCallingFeatureId, mUid, - /* coarseForTargetSdkLessThanQ */ true, null); - if (VDBG) Log.v(TAG, "hasPermission=" + hasPermission); - mCallback.onIdentityChanged( - hasPermission ? currentDiscoveryInterfaceMac : ALL_ZERO_MAC); - } catch (RemoteException e) { - Log.w(TAG, "onIdentityChanged: RemoteException - ignored: " + e); - } - } - - mLastDiscoveryInterfaceMac = currentDiscoveryInterfaceMac; - } - - /** - * Check if client needs ranging enabled. - * @return True if one of the discovery session has ranging enabled, false otherwise. - */ - public boolean isRangingEnabled() { - for (int i = 0; i < mSessions.size(); ++i) { - if (mSessions.valueAt(i).isRangingEnabled()) { - return true; - } - } - return false; - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("AwareClientState:"); - pw.println(" mClientId: " + mClientId); - pw.println(" mConfigRequest: " + mConfigRequest); - pw.println(" mNotifyIdentityChange: " + mNotifyIdentityChange); - pw.println(" mCallback: " + mCallback); - pw.println(" mSessions: [" + mSessions + "]"); - for (int i = 0; i < mSessions.size(); ++i) { - mSessions.valueAt(i).dump(fd, pw, args); - } - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java deleted file mode 100644 index 226304019..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java +++ /dev/null @@ -1,1739 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import static android.net.RouteInfo.RTN_UNICAST; - -import android.content.Context; -import android.hardware.wifi.V1_0.NanDataPathChannelCfg; -import android.hardware.wifi.V1_0.NanStatusType; -import android.hardware.wifi.V1_2.NanDataPathChannelInfo; -import android.net.ConnectivityManager; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.MacAddress; -import android.net.MatchAllNetworkSpecifier; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkFactory; -import android.net.NetworkProvider; -import android.net.NetworkRequest; -import android.net.NetworkSpecifier; -import android.net.RouteInfo; -import android.net.wifi.aware.TlvBufferUtils; -import android.net.wifi.aware.WifiAwareAgentNetworkSpecifier; -import android.net.wifi.aware.WifiAwareManager; -import android.net.wifi.aware.WifiAwareNetworkInfo; -import android.net.wifi.aware.WifiAwareNetworkSpecifier; -import android.net.wifi.aware.WifiAwareUtils; -import android.net.wifi.util.HexEncoding; -import android.os.Build; -import android.os.Handler; -import android.os.Looper; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.Clock; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.net.DatagramSocket; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.nio.ByteOrder; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; - -/** - * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down. - * The Aware network configuration is: - * - transport = TRANSPORT_WIFI_AWARE - * - capabilities = NET_CAPABILITY_NOT_VPN - * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or - * WifiAwareManager.createNetworkSpecifier(...). - */ -public class WifiAwareDataPathStateManager { - private static final String TAG = "WifiAwareDataPathStMgr"; - private static final boolean VDBG = false; // STOPSHIP if true - private boolean mDbg = false; - - private static final String AWARE_INTERFACE_PREFIX = "aware_data"; - private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY"; - private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_"; - private static final int NETWORK_FACTORY_SCORE_AVAIL = 1; - private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1; - private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1; - - @VisibleForTesting - public static final int ADDRESS_VALIDATION_RETRY_INTERVAL_MS = 1_000; // 1 second - @VisibleForTesting - public static final int ADDRESS_VALIDATION_TIMEOUT_MS = 5_000; // 5 seconds - - private final WifiAwareStateManager mMgr; - private final Clock mClock; - public NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper(); - private static final NetworkCapabilities sNetworkCapabilitiesFilter = - makeNetworkCapabilitiesFilter(); - private final Set<String> mInterfaces = new HashSet<>(); - private final Map<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> - mNetworkRequestsCache = new ArrayMap<>(); - private Context mContext; - private WifiAwareMetrics mAwareMetrics; - private WifiPermissionsUtil mWifiPermissionsUtil; - private WifiPermissionsWrapper mPermissionsWrapper; - private Looper mLooper; - private Handler mHandler; - private WifiAwareNetworkFactory mNetworkFactory; - public NetdWrapper mNetdWrapper; - - // internal debug flag to override API check - /* package */ boolean mAllowNdpResponderFromAnyOverride = false; - - public WifiAwareDataPathStateManager(WifiAwareStateManager mgr, Clock clock) { - mMgr = mgr; - mClock = clock; - } - - private static NetworkCapabilities makeNetworkCapabilitiesFilter() { - return new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .setNetworkSpecifier(new MatchAllNetworkSpecifier()) - .setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL) - .setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL) - .setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL) - .build(); - } - - /** - * Initialize the Aware data-path state manager. Specifically register the network factory with - * connectivity service. - */ - public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics, - WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, - NetdWrapper netdWrapper) { - if (VDBG) Log.v(TAG, "start"); - - mContext = context; - mAwareMetrics = awareMetrics; - mWifiPermissionsUtil = wifiPermissionsUtil; - mPermissionsWrapper = permissionsWrapper; - mNetdWrapper = netdWrapper; - mLooper = looper; - mHandler = new Handler(mLooper); - - - mNetworkFactory = new WifiAwareNetworkFactory(looper, context, sNetworkCapabilitiesFilter); - mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL); - mNetworkFactory.register(); - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(boolean verbose) { - mDbg = verbose | VDBG; - } - - private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> - getNetworkRequestByNdpId(int ndpId) { - for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : - mNetworkRequestsCache.entrySet()) { - if (entry.getValue().ndpId == ndpId) { - return entry; - } - } - - return null; - } - - private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> - getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci) { - if (VDBG) Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: cci=" + cci); - for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : - mNetworkRequestsCache.entrySet()) { - if (VDBG) { - Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: entry=" + entry.getValue() - + " --> cci=" + entry.getValue().getCanonicalDescriptor()); - } - if (entry.getValue().getCanonicalDescriptor().matches(cci)) { - return entry; - } - } - - return null; - } - - /** - * Create all Aware data-path interfaces which are possible on the device - based on the - * capabilities of the firmware. - */ - public void createAllInterfaces() { - if (mDbg) Log.v(TAG, "createAllInterfaces"); - - if (mMgr.getCapabilities() == null) { - Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!"); - return; - } - - for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) { - String name = AWARE_INTERFACE_PREFIX + i; - if (mInterfaces.contains(name)) { - Log.e(TAG, "createAllInterfaces(): interface already up, " + name - + ", possibly failed to delete - deleting/creating again to be safe"); - mMgr.deleteDataPathInterface(name); - - // critical to remove so that don't get infinite loop if the delete fails again - mInterfaces.remove(name); - } - - mMgr.createDataPathInterface(name); - } - } - - /** - * Delete all Aware data-path interfaces which are currently up. - */ - public void deleteAllInterfaces() { - if (mDbg) Log.v(TAG, "deleteAllInterfaces"); - onAwareDownCleanupDataPaths(); - - if (mMgr.getCapabilities() == null) { - Log.e(TAG, "deleteAllInterfaces: capabilities aren't initialized yet!"); - return; - } - - for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) { - String name = AWARE_INTERFACE_PREFIX + i; - mMgr.deleteDataPathInterface(name); - } - mMgr.releaseAwareInterface(); - } - - /** - * Called when firmware indicates the an interface was created. - */ - public void onInterfaceCreated(String interfaceName) { - if (mDbg) Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName); - - if (mInterfaces.contains(interfaceName)) { - Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName); - } - - mInterfaces.add(interfaceName); - } - - /** - * Called when firmware indicates the an interface was deleted. - */ - public void onInterfaceDeleted(String interfaceName) { - if (mDbg) Log.v(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName); - - if (!mInterfaces.contains(interfaceName)) { - Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName); - } - - mInterfaces.remove(interfaceName); - } - - /** - * Response to initiating data-path request. Indicates that request is successful (not - * complete!) and is now in progress. - * - * @param networkSpecifier The network specifier provided as part of the initiate request. - * @param ndpId The ID assigned to the data-path. - */ - public void onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier, int ndpId) { - if (mDbg) { - Log.v(TAG, - "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId=" - + ndpId); - } - - AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); - if (nnri == null) { - Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier=" - + networkSpecifier); - mMgr.endDataPath(ndpId); - return; - } - - if (nnri.state - != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { - Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state=" - + nnri.state); - mNetworkRequestsCache.remove(networkSpecifier); - declareUnfullfillableAndEndDp(nnri, ndpId); - return; - } - - nnri.state = AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM; - nnri.ndpId = ndpId; - } - - /** - * Response to an attempt to set up a data-path (on the initiator side). - * - * @param networkSpecifier The network specifier provided as part of the initiate request. - * @param reason Failure reason. - */ - public void onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason) { - if (mDbg) { - Log.v(TAG, - "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason=" - + reason); - } - - AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier); - if (nnri == null) { - Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier=" - + networkSpecifier); - return; - } - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - - if (nnri.state - != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { - Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state=" - + nnri.state); - } - - mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), nnri.startTimestamp); - } - - - /** - * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path - * connection with us. - * - * @param pubSubId The ID of the discovery session context for the data-path - or 0 if not - * related to a discovery session. - * @param mac The discovery MAC address of the peer. - * @param ndpId The locally assigned ID for the data-path. - * @param message The app_info HAL field (peer's info: binary blob) - * @return The network specifier of the data-path (or null if none/error) - */ - public WifiAwareNetworkSpecifier onDataPathRequest(int pubSubId, byte[] mac, int ndpId, - byte[] message) { - if (mDbg) { - Log.v(TAG, - "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf( - HexEncoding.encode(mac)) + ", ndpId=" + ndpId); - } - - WifiAwareNetworkSpecifier networkSpecifier = null; - AwareNetworkRequestInformation nnri = null; - for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : - mNetworkRequestsCache.entrySet()) { - /* - * Checking that the incoming request (from the Initiator) matches the request - * we (the Responder) already have set up. The rules are: - * - The discovery session (pub/sub ID) must match. - * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC == - * accept (otherwise matching) requests from any peer MAC. - * - The request must be pending (i.e. we could have completed requests for the same - * parameters) - */ - if (entry.getValue().pubSubId != 0 && entry.getValue().pubSubId != pubSubId) { - continue; - } - - if (entry.getValue().peerDiscoveryMac != null && !Arrays.equals( - entry.getValue().peerDiscoveryMac, mac)) { - continue; - } - - if (entry.getValue().state - != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) { - continue; - } - - networkSpecifier = entry.getKey(); - nnri = entry.getValue(); - break; - } - - // it is also possible that this is an initiator-side data-path request indication (which - // happens when the Responder responds). In such a case it will be matched by the NDP ID. - Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = - getNetworkRequestByNdpId(ndpId); - if (nnriE != null) { - if (VDBG) { - Log.v(TAG, - "onDataPathRequest: initiator-side indication for " + nnriE.getValue()); - } - - // potential transmission mechanism for port/transport-protocol information from - // Responder (alternative to confirm message) - NetworkInformationData.ParsedResults peerServerInfo = NetworkInformationData.parseTlv( - message); - if (peerServerInfo != null) { - if (peerServerInfo.port != 0) { - nnriE.getValue().peerPort = peerServerInfo.port; - } - if (peerServerInfo.transportProtocol != -1) { - nnriE.getValue().peerTransportProtocol = peerServerInfo.transportProtocol; - } - if (peerServerInfo.ipv6Override != null) { - nnriE.getValue().peerIpv6Override = peerServerInfo.ipv6Override; - } - } - - return null; // ignore this for NDP set up flow: it is used to obtain app_info from Resp - } - - if (nnri == null) { - Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId - + ", mac=" + String.valueOf(HexEncoding.encode(mac))); - if (VDBG) { - Log.v(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache); - } - mMgr.respondToDataPathRequest(false, ndpId, "", null, null, null, false); - return null; - } - - if (nnri.peerDiscoveryMac == null) { - // the "accept anyone" request is now specific - nnri.peerDiscoveryMac = mac; - } - nnri.interfaceName = selectInterfaceForRequest(nnri); - if (nnri.interfaceName == null) { - Log.w(TAG, - "onDataPathRequest: request " + networkSpecifier + " no interface available"); - mMgr.respondToDataPathRequest(false, ndpId, "", null, null, null, false); - mNetworkRequestsCache.remove(networkSpecifier); - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - return null; - } - - nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE; - nnri.ndpId = ndpId; - nnri.startTimestamp = mClock.getElapsedSinceBootMillis(); - mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.networkSpecifier.pmk, - nnri.networkSpecifier.passphrase, - NetworkInformationData.buildTlv(nnri.networkSpecifier.port, - nnri.networkSpecifier.transportProtocol), - nnri.networkSpecifier.isOutOfBand()); - - return networkSpecifier; - } - - /** - * Called on the RESPONDER when the response to data-path request has been completed. - * - * @param ndpId The ID of the data-path (NDP) - * @param success Whether or not the 'RespondToDataPathRequest' operation was a success. - */ - public void onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure) { - if (mDbg) { - Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success); - } - - WifiAwareNetworkSpecifier networkSpecifier = null; - AwareNetworkRequestInformation nnri = null; - for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : - mNetworkRequestsCache.entrySet()) { - if (entry.getValue().ndpId == ndpId) { - networkSpecifier = entry.getKey(); - nnri = entry.getValue(); - break; - } - } - - if (nnri == null) { - Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId=" - + ndpId); - if (VDBG) { - Log.v(TAG, "onRespondToDataPathRequest: network request cache = " - + mNetworkRequestsCache); - } - return; - } - - if (!success) { - Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier - + " failed responding"); - mMgr.endDataPath(ndpId); - mNetworkRequestsCache.remove(networkSpecifier); - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - mAwareMetrics.recordNdpStatus(reasonOnFailure, networkSpecifier.isOutOfBand(), - nnri.startTimestamp); - return; - } - - if (nnri.state - != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE) { - Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier - + " is incorrect state=" + nnri.state); - mMgr.endDataPath(ndpId); - mNetworkRequestsCache.remove(networkSpecifier); - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - return; - } - - nnri.state = AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM; - } - - /** - * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up) - * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's - * perspective - now can do L3 configuration. - * - * @param ndpId Id of the data-path - * @param mac The MAC address of the peer's data-path (not discovery interface). Only - * valid - * if {@code accept} is {@code true}. - * @param accept Indicates whether the data-path setup has succeeded (been accepted) or - * failed (been rejected). - * @param reason If {@code accept} is {@code false} provides a reason code for the - * rejection/failure. - * @param message The message provided by the peer as part of the data-path setup - * process. - * @param channelInfo Lists of channels used for this NDP. - * @return The network specifier of the data-path or a null if none/error. - */ - public WifiAwareNetworkSpecifier onDataPathConfirm(int ndpId, byte[] mac, boolean accept, - int reason, byte[] message, List<NanDataPathChannelInfo> channelInfo) { - if (mDbg) { - Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId + ", mac=" + String.valueOf( - HexEncoding.encode(mac)) + ", accept=" + accept + ", reason=" + reason - + ", message.length=" + ((message == null) ? 0 : message.length) - + ", channelInfo=" + channelInfo); - } - - Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = - getNetworkRequestByNdpId(ndpId); - if (nnriE == null) { - Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId); - if (accept) { - mMgr.endDataPath(ndpId); - } - return null; - } - - WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey(); - AwareNetworkRequestInformation nnri = nnriE.getValue(); - - // validate state - if (nnri.state != AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM) { - Log.w(TAG, "onDataPathConfirm: invalid state=" + nnri.state); - mNetworkRequestsCache.remove(networkSpecifier); - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - if (accept) { - mMgr.endDataPath(ndpId); - } - return networkSpecifier; - } - - if (accept) { - nnri.state = AwareNetworkRequestInformation.STATE_CONFIRMED; - nnri.peerDataMac = mac; - nnri.channelInfo = channelInfo; - - if (!isInterfaceUpAndUsedByAnotherNdp(nnri)) { - try { - mNetdWrapper.setInterfaceUp(nnri.interfaceName); - mNetdWrapper.enableIpv6(nnri.interfaceName); - } catch (Exception e) { // NwService throws runtime exceptions for errors - Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri - + ": can't configure network - " - + e); - declareUnfullfillableAndEndDp(nnri, ndpId); - return networkSpecifier; - } - } else { - if (VDBG) { - Log.v(TAG, "onDataPathConfirm: interface already configured: " - + nnri.interfaceName); - } - } - - // only relevant for the initiator - if (nnri.networkSpecifier.role - == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) { - NetworkInformationData.ParsedResults peerServerInfo = - NetworkInformationData.parseTlv(message); - if (peerServerInfo != null) { - if (peerServerInfo.port != 0) { - nnri.peerPort = peerServerInfo.port; - } - if (peerServerInfo.transportProtocol != -1) { - nnri.peerTransportProtocol = peerServerInfo.transportProtocol; - } - if (peerServerInfo.ipv6Override != null) { - nnri.peerIpv6Override = peerServerInfo.ipv6Override; - } - } - } - - nnri.startValidationTimestamp = mClock.getElapsedSinceBootMillis(); - handleAddressValidation(nnri, ndpId, networkSpecifier.isOutOfBand(), mac); - } else { - if (VDBG) { - Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier - + " rejected - reason=" + reason); - } - mNetworkRequestsCache.remove(networkSpecifier); - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), - nnri.startTimestamp); - } - - return networkSpecifier; - } - - private void getInet6Address(AwareNetworkRequestInformation nnri, byte[] mac) { - try { - byte[] addr; - if (nnri.peerIpv6Override == null) { - addr = MacAddress.fromBytes(mac).getLinkLocalIpv6FromEui48Mac().getAddress(); - } else { - addr = new byte[16]; - addr[0] = (byte) 0xfe; - addr[1] = (byte) 0x80; - addr[8] = nnri.peerIpv6Override[0]; - addr[9] = nnri.peerIpv6Override[1]; - addr[10] = nnri.peerIpv6Override[2]; - addr[11] = nnri.peerIpv6Override[3]; - addr[12] = nnri.peerIpv6Override[4]; - addr[13] = nnri.peerIpv6Override[5]; - addr[14] = nnri.peerIpv6Override[6]; - addr[15] = nnri.peerIpv6Override[7]; - } - nnri.peerIpv6 = Inet6Address.getByAddress(null, addr, - NetworkInterface.getByName(nnri.interfaceName)); - } catch (SocketException | UnknownHostException e) { - if (mDbg) { - Log.d(TAG, "onDataPathConfirm: error obtaining scoped IPv6 address -- " + e); - } - nnri.peerIpv6 = null; - } - } - - private void handleAddressValidation(AwareNetworkRequestInformation nnri, int ndpId, - boolean isOutOfBand, byte[] mac) { - final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder( - sNetworkCapabilitiesFilter); - LinkProperties linkProperties = new LinkProperties(); - getInet6Address(nnri, mac); - if (!(nnri.peerIpv6 != null && mNiWrapper.configureAgentProperties(nnri, - nnri.equivalentRequests, ndpId, ncBuilder, linkProperties) - && mNiWrapper.isAddressUsable(linkProperties))) { - if (VDBG) { - Log.d(TAG, "Failed address validation"); - } - if (!isAddressValidationExpired(nnri, ndpId)) { - mHandler.postDelayed(() -> { - handleAddressValidation(nnri, ndpId, isOutOfBand, mac); - }, ADDRESS_VALIDATION_RETRY_INTERVAL_MS); - } - return; - } - final WifiAwareNetworkInfo ni = new WifiAwareNetworkInfo( - nnri.peerIpv6, nnri.peerPort, nnri.peerTransportProtocol); - ncBuilder.setTransportInfo(ni); - if (VDBG) { - Log.v(TAG, "onDataPathConfirm: AwareNetworkInfo=" + ni); - } - final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder() - .setLegacyType(ConnectivityManager.TYPE_NONE) - .setLegacyTypeName(NETWORK_TAG) - .build(); - nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext, - AGENT_TAG_PREFIX + nnri.ndpId, ncBuilder.build(), linkProperties, - NETWORK_FACTORY_SCORE_AVAIL, naConfig, mNetworkFactory.getProvider(), nnri); - mNiWrapper.setConnected(nnri.networkAgent); - mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, isOutOfBand, nnri.startTimestamp); - nnri.startTimestamp = mClock.getElapsedSinceBootMillis(); // update time-stamp - mAwareMetrics.recordNdpCreation(nnri.uid, nnri.packageName, mNetworkRequestsCache); - } - - private boolean isAddressValidationExpired(AwareNetworkRequestInformation nnri, int ndpId) { - if (mClock.getElapsedSinceBootMillis() - nnri.startValidationTimestamp - > ADDRESS_VALIDATION_TIMEOUT_MS) { - Log.e(TAG, "Timed-out while waiting for IPv6 address to be usable"); - mMgr.endDataPath(ndpId); - nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; - declareUnfullfillableAndEndDp(nnri, ndpId); - return true; - } - return false; - } - - private void declareUnfullfillableAndEndDp(AwareNetworkRequestInformation nnri, int ndpId) { - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - mMgr.endDataPath(ndpId); - nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; - } - - /** - * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has - * been terminated. - * - * @param ndpId The ID of the terminated data-path. - */ - public void onDataPathEnd(int ndpId) { - if (mDbg) Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId); - - Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = - getNetworkRequestByNdpId(ndpId); - if (nnriE == null) { - if (VDBG) { - Log.v(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId); - } - return; - } - - tearDownInterfaceIfPossible(nnriE.getValue()); - if (nnriE.getValue().state == AwareNetworkRequestInformation.STATE_CONFIRMED - || nnriE.getValue().state == AwareNetworkRequestInformation.STATE_TERMINATING) { - mAwareMetrics.recordNdpSessionDuration(nnriE.getValue().startTimestamp); - } - mNetworkRequestsCache.remove(nnriE.getKey()); - - mNetworkFactory.tickleConnectivityIfWaiting(); - } - - /** - * Notification (unsolicited/asynchronous) from the firmware that the channel for the specified - * NDP ids has been updated. - */ - public void onDataPathSchedUpdate(byte[] peerMac, List<Integer> ndpIds, - List<NanDataPathChannelInfo> channelInfo) { - if (mDbg) { - Log.v(TAG, "onDataPathSchedUpdate: peerMac=" + MacAddress.fromBytes(peerMac).toString() - + ", ndpIds=" + ndpIds + ", channelInfo=" + channelInfo); - } - - for (int ndpId : ndpIds) { - Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = - getNetworkRequestByNdpId(ndpId); - if (nnriE == null) { - Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + " - not found"); - continue; - } - if (!Arrays.equals(peerMac, nnriE.getValue().peerDiscoveryMac)) { - Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + ", report NMI=" - + MacAddress.fromBytes(peerMac).toString() + " doesn't match NDP NMI=" - + MacAddress.fromBytes(nnriE.getValue().peerDiscoveryMac).toString()); - continue; - } - - nnriE.getValue().channelInfo = channelInfo; - } - } - - /** - * Called whenever Aware comes down. Clean up all pending and up network requests and agents. - */ - public void onAwareDownCleanupDataPaths() { - if (mDbg) Log.v(TAG, "onAwareDownCleanupDataPaths"); - - Iterator<Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>> it = - mNetworkRequestsCache.entrySet().iterator(); - while (it.hasNext()) { - tearDownInterfaceIfPossible(it.next().getValue()); - it.remove(); - } - } - - /** - * Called when timed-out waiting for confirmation of the data-path setup (i.e. - * onDataPathConfirm). Started on the initiator when executing the request for the data-path - * and on the responder when received a request for data-path (in both cases only on success - * - i.e. when we're proceeding with data-path setup). - */ - public void handleDataPathTimeout(NetworkSpecifier networkSpecifier) { - if (mDbg) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + networkSpecifier); - - AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier); - if (nnri == null) { - if (VDBG) { - Log.v(TAG, - "handleDataPathTimeout: network request not found for networkSpecifier=" - + networkSpecifier); - } - return; - } - mAwareMetrics.recordNdpStatus(NanStatusType.INTERNAL_FAILURE, - nnri.networkSpecifier.isOutOfBand(), nnri.startTimestamp); - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - - mMgr.endDataPath(nnri.ndpId); - nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; - } - - private class WifiAwareNetworkFactory extends NetworkFactory { - // Request received while waiting for confirmation that a canonically identical data-path - // (NDP) is in the process of being terminated - private boolean mWaitingForTermination = false; - - WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) { - super(looper, context, NETWORK_TAG, filter); - } - - public void tickleConnectivityIfWaiting() { - if (mWaitingForTermination) { - if (VDBG) Log.v(TAG, "tickleConnectivityIfWaiting: was waiting!"); - mWaitingForTermination = false; - reevaluateAllRequests(); - } - } - - @Override - public boolean acceptRequest(NetworkRequest request, int score) { - if (VDBG) { - Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request + ", score=" - + score); - } - - if (!mMgr.isUsageEnabled()) { - if (VDBG) { - Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request - + " -- Aware disabled"); - } - return false; - } - - if (mInterfaces.isEmpty()) { - Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request - + " -- No Aware interfaces are up"); - return false; - } - - NetworkSpecifier networkSpecifierBase = request.getNetworkSpecifier(); - if (!(networkSpecifierBase instanceof WifiAwareNetworkSpecifier)) { - Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request - + " - not a WifiAwareNetworkSpecifier"); - return false; - } - - WifiAwareNetworkSpecifier networkSpecifier = - (WifiAwareNetworkSpecifier) networkSpecifierBase; - - // look up specifier - are we being called again? - AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); - if (nnri != null) { - if (VDBG) { - Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request - + " - already in cache with state=" + nnri.state); - } - - if (nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) { - mWaitingForTermination = true; - return false; - } - - // seems to happen after a network agent is created - trying to rematch all - // requests again!? - return true; - } - - nnri = AwareNetworkRequestInformation.processNetworkSpecifier(request, networkSpecifier, - mMgr, mWifiPermissionsUtil, mPermissionsWrapper, - mAllowNdpResponderFromAnyOverride); - if (nnri == null) { - Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request - + " - can't parse network specifier"); - releaseRequestAsUnfulfillableByAnyFactory(request); - return false; - } - - // check to see if a canonical version exists - Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> primaryRequest = - getNetworkRequestByCanonicalDescriptor(nnri.getCanonicalDescriptor()); - if (primaryRequest != null) { - if (VDBG) { - Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request - + ", already has a primary request=" + primaryRequest.getKey() - + " with state=" + primaryRequest.getValue().state); - } - - if (primaryRequest.getValue().state - == AwareNetworkRequestInformation.STATE_TERMINATING) { - mWaitingForTermination = true; - } else { - primaryRequest.getValue().updateToSupportNewRequest(request); - } - return false; - } - - mNetworkRequestsCache.put(networkSpecifier, nnri); - - return true; - } - - @Override - protected void needNetworkFor(NetworkRequest networkRequest, int score) { - if (mDbg) { - Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" - + networkRequest + ", score=" + score); - } - - NetworkSpecifier networkSpecifierObj = networkRequest.getNetworkSpecifier(); - WifiAwareNetworkSpecifier networkSpecifier = null; - if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) { - networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj; - } - AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); - if (nnri == null) { - Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" - + networkRequest + " not in cache!?"); - return; - } - - if (nnri.state != AwareNetworkRequestInformation.STATE_IDLE) { - if (VDBG) { - Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" - + networkRequest + " - already in progress"); - // TODO: understand how/when can be called again/while in progress (seems - // to be related to score re-calculation after a network agent is created) - } - return; - } - if (nnri.networkSpecifier.role - == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) { - nnri.interfaceName = selectInterfaceForRequest(nnri); - if (nnri.interfaceName == null) { - Log.w(TAG, "needNetworkFor: request " + networkSpecifier - + " no interface available"); - mNetworkRequestsCache.remove(networkSpecifier); - letAppKnowThatRequestsAreUnavailable(nnri); - return; - } - - mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerInstanceId, - NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED, selectChannelForRequest(nnri), - nnri.peerDiscoveryMac, nnri.interfaceName, nnri.networkSpecifier.pmk, - nnri.networkSpecifier.passphrase, nnri.networkSpecifier.isOutOfBand(), - null); - nnri.state = - AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE; - nnri.startTimestamp = mClock.getElapsedSinceBootMillis(); - } else { - nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST; - } - } - - @Override - protected void releaseNetworkFor(NetworkRequest networkRequest) { - if (mDbg) { - Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" - + networkRequest); - } - - NetworkSpecifier networkSpecifierObj = networkRequest.getNetworkSpecifier(); - WifiAwareNetworkSpecifier networkSpecifier = null; - if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) { - networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj; - } - - AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); - if (nnri == null) { - Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" - + networkRequest + " not in cache!?"); - return; - } - - if (nnri.networkAgent != null) { - if (VDBG) { - Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" - + networkRequest + ", nnri=" + nnri - + ": agent already created - deferring ending data-path to agent" - + ".unwanted()"); - } - return; - } - - /* - * Since there's no agent it means we're in the process of setting up the NDP. - * However, it is possible that there were other equivalent requests for this NDP. We - * should keep going in that case. - */ - nnri.removeSupportForRequest(networkRequest); - if (nnri.equivalentRequests.isEmpty()) { - if (mDbg) { - Log.v(TAG, "releaseNetworkFor: there are no further requests, networkRequest=" - + networkRequest); - } - if (nnri.ndpId != 0) { // 0 is never a valid ID! - if (VDBG) Log.v(TAG, "releaseNetworkFor: in progress NDP being terminated"); - mMgr.endDataPath(nnri.ndpId); - nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; - } else { - mNetworkRequestsCache.remove(networkSpecifier); - if (nnri.networkAgent != null) { - letAppKnowThatRequestsAreUnavailable(nnri); - } - } - } else { - if (VDBG) { - Log.v(TAG, "releaseNetworkFor: equivalent requests exist - not terminating " - + "networkRequest=" + networkRequest); - } - } - } - - void letAppKnowThatRequestsAreUnavailable(AwareNetworkRequestInformation nnri) { - for (NetworkRequest nr : nnri.equivalentRequests) { - releaseRequestAsUnfulfillableByAnyFactory(nr); - } - } - } - - /** - * Network agent for Wi-Fi Aware. - */ - @VisibleForTesting - public class WifiAwareNetworkAgent extends NetworkAgent { - private AwareNetworkRequestInformation mAwareNetworkRequestInfo; - - WifiAwareNetworkAgent(Looper looper, Context context, String logTag, - NetworkCapabilities nc, LinkProperties lp, int score, - NetworkAgentConfig config, NetworkProvider provider, - AwareNetworkRequestInformation anri) { - super(context, looper, logTag, nc, lp, score, config, provider); - mAwareNetworkRequestInfo = anri; - register(); - } - - @Override - public void onNetworkUnwanted() { - if (mDbg) { - Log.v(TAG, "WifiAwareNetworkAgent.unwanted: request=" + mAwareNetworkRequestInfo); - } - - mMgr.endDataPath(mAwareNetworkRequestInfo.ndpId); - mAwareNetworkRequestInfo.state = AwareNetworkRequestInformation.STATE_TERMINATING; - - // Will get a callback (on both initiator and responder) when data-path actually - // terminated. At that point will inform the agent and will clear the cache. - } - - void reconfigureAgentAsDisconnected() { - if (mDbg) { - Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: request=" - + mAwareNetworkRequestInfo); - } - unregister(); - } - } - - private void tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri) { - if (VDBG) Log.v(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri); - - if (!TextUtils.isEmpty(nnri.interfaceName)) { - boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri); - if (interfaceUsedByAnotherNdp) { - if (mDbg) { - Log.v(TAG, "tearDownInterfaceIfPossible: interfaceName=" + nnri.interfaceName - + ", still in use - not turning down"); - } - } else { - try { - mNetdWrapper.setInterfaceDown(nnri.interfaceName); - } catch (Exception e) { // NwService throws runtime exceptions for errors - Log.e(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri - + ": can't bring interface down - " + e); - } - } - } - - if (nnri.networkAgent == null) { - mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri); - } else { - nnri.networkAgent.reconfigureAgentAsDisconnected(); - } - } - - private boolean isInterfaceUpAndUsedByAnotherNdp(AwareNetworkRequestInformation nri) { - for (AwareNetworkRequestInformation lnri : mNetworkRequestsCache.values()) { - if (lnri == nri) { - continue; - } - - if (nri.interfaceName.equals(lnri.interfaceName) && ( - lnri.state == AwareNetworkRequestInformation.STATE_CONFIRMED - || lnri.state == AwareNetworkRequestInformation.STATE_TERMINATING)) { - return true; - } - } - - return false; - } - - /** - * Select one of the existing interfaces for the new network request. A request is canonical - * (otherwise it wouldn't be executed). - * - * Construct a list of all interfaces currently used to communicate to the peer. The remaining - * interfaces are available for use for this request - if none are left then the request should - * fail (signaled to the caller by returning a null). - */ - private String selectInterfaceForRequest(AwareNetworkRequestInformation req) { - SortedSet<String> potential = new TreeSet<>(mInterfaces); - Set<String> used = new HashSet<>(); - - if (mDbg) { - Log.v(TAG, "selectInterfaceForRequest: req=" + req + ", mNetworkRequestsCache=" - + mNetworkRequestsCache); - } - - for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) { - if (nnri == req) { - continue; - } - - if (Arrays.equals(req.peerDiscoveryMac, nnri.peerDiscoveryMac)) { - used.add(nnri.interfaceName); - } - } - - if (VDBG) { - Log.v(TAG, "selectInterfaceForRequest: potential=" + potential + ", used=" + used); - } - - for (String ifName: potential) { - if (!used.contains(ifName)) { - return ifName; - } - } - - Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - no interfaces available!"); - return null; - } - - /** - * Select a channel for the network request. - * - * TODO (b/38209409): The value from this function isn't currently used - the channel selection - * is delegated to the HAL. - */ - private int selectChannelForRequest(AwareNetworkRequestInformation req) { - return 2437; - } - - /** - * Aware network request. State object: contains network request information/state through its - * lifetime. - */ - @VisibleForTesting - public static class AwareNetworkRequestInformation { - static final int STATE_IDLE = 100; - static final int STATE_WAIT_FOR_CONFIRM = 101; - static final int STATE_CONFIRMED = 102; - static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 103; - static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 104; - static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 105; - static final int STATE_TERMINATING = 106; - - public int state; - - public int uid; - public String packageName; - public String interfaceName; - public int pubSubId = 0; - public int peerInstanceId = 0; - public byte[] peerDiscoveryMac = null; - public int ndpId = 0; // 0 is never a valid ID! - public byte[] peerDataMac; - public Inet6Address peerIpv6; - public int peerPort = 0; // uninitialized (invalid) value - public int peerTransportProtocol = -1; // uninitialized (invalid) value - public byte[] peerIpv6Override = null; - public WifiAwareNetworkSpecifier networkSpecifier; - public List<NanDataPathChannelInfo> channelInfo; - public long startTimestamp = 0; // request is made (initiator) / get request (responder) - public long startValidationTimestamp = 0; // NDP created and starting to validate IPv6 addr - - public WifiAwareNetworkAgent networkAgent; - - /* A collection of request which are equivalent to the current request and are - * supported by it's agent. This list DOES include the original (first) network request - * (whose specifier is also stored separately above). - */ - public Set<NetworkRequest> equivalentRequests = new HashSet<>(); - - void updateToSupportNewRequest(NetworkRequest ns) { - if (VDBG) Log.v(TAG, "updateToSupportNewRequest: ns=" + ns); - if (equivalentRequests.add(ns) && state == STATE_CONFIRMED) { - if (networkAgent == null) { - Log.wtf(TAG, "updateToSupportNewRequest: null agent in CONFIRMED state!?"); - return; - } - - networkAgent.sendNetworkCapabilities(getNetworkCapabilities()); - } - } - - void removeSupportForRequest(NetworkRequest ns) { - if (VDBG) Log.v(TAG, "removeSupportForRequest: ns=" + ns); - equivalentRequests.remove(ns); - - // we will not update the agent: - // 1. this will only get called before the agent is created - // 2. connectivity service does not allow (WTF) updates with reduced capabilities - } - - private NetworkCapabilities getNetworkCapabilities() { - final NetworkCapabilities.Builder builder = - new NetworkCapabilities.Builder(sNetworkCapabilitiesFilter); - builder.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier( - equivalentRequests.stream() - .map(NetworkRequest::getNetworkSpecifier) - .toArray(WifiAwareNetworkSpecifier[]::new))); - if (peerIpv6 != null) { - builder.setTransportInfo( - new WifiAwareNetworkInfo(peerIpv6, peerPort, peerTransportProtocol)); - } - return builder.build(); - } - - /** - * Returns a canonical descriptor for the network request. - */ - CanonicalConnectionInfo getCanonicalDescriptor() { - return new CanonicalConnectionInfo(peerDiscoveryMac, networkSpecifier.pmk, - networkSpecifier.sessionId, networkSpecifier.passphrase); - } - - static AwareNetworkRequestInformation processNetworkSpecifier(NetworkRequest request, - WifiAwareNetworkSpecifier ns, WifiAwareStateManager mgr, - WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionWrapper, - boolean allowNdpResponderFromAnyOverride) { - int uid, pubSubId = 0; - int peerInstanceId = 0; - String packageName = null; - byte[] peerMac = ns.peerMac; - - if (VDBG) { - Log.v(TAG, "processNetworkSpecifier: networkSpecifier=" + ns); - } - - // type: always valid - if (ns.type < 0 - || ns.type > WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_MAX_VALID) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + ", invalid 'type' value"); - return null; - } - - // role: always valid - if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR - && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- invalid 'role' value"); - return null; - } - - if (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR - && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB - && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- invalid 'type' value for INITIATOR (only IB and OOB are " - + "permitted)"); - return null; - } - - // look up network specifier information in Aware state manager - WifiAwareClientState client = mgr.getClient(ns.clientId); - if (client == null) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- not client with this id -- clientId=" + ns.clientId); - return null; - } - uid = client.getUid(); - packageName = client.getCallingPackage(); - - // API change post 27: no longer allow "ANY"-style responders (initiators were never - // permitted). - // Note: checks are done on the manager. This is a backup for apps which bypass the - // check. - if (!allowNdpResponderFromAnyOverride && !wifiPermissionsUtil.isTargetSdkLessThan( - client.getCallingPackage(), Build.VERSION_CODES.P, uid)) { - if (ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB - && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- no ANY specifications allowed for this API level"); - return null; - } - } - - // validate the port & transportProtocol - if (ns.port < 0 || ns.transportProtocol < -1) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- invalid port/transportProtocol"); - return null; - } - if (ns.port != 0 || ns.transportProtocol != -1) { - if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- port/transportProtocol can only be specified on responder"); - return null; - } - if (TextUtils.isEmpty(ns.passphrase) && ns.pmk == null) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- port/transportProtocol can only be specified on secure ndp"); - return null; - } - } - - // validate the role (if session ID provided: i.e. session 1xx) - if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB - || ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) { - WifiAwareDiscoverySessionState session = client.getSession(ns.sessionId); - if (session == null) { - Log.e(TAG, - "processNetworkSpecifier: networkSpecifier=" + ns - + " -- no session with this id -- sessionId=" + ns.sessionId); - return null; - } - - if ((session.isPublishSession() - && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || ( - !session.isPublishSession() && ns.role - != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- invalid role for session type"); - return null; - } - - if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB) { - pubSubId = session.getPubSubId(); - WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo( - ns.peerId); - if (peerInfo == null) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- no peer info associated with this peer id -- peerId=" - + ns.peerId); - return null; - } - peerInstanceId = peerInfo.mInstanceId; - try { - peerMac = peerInfo.mMac; - if (peerMac == null || peerMac.length != 6) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" - + ns + " -- invalid peer MAC address"); - return null; - } - } catch (IllegalArgumentException e) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns - + " -- invalid peer MAC address -- e=" + e); - return null; - } - } - } - - // validate UID && package name - if (request.getRequestorUid() != uid - || !TextUtils.equals(request.getRequestorPackageName(), packageName)) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() - + " -- UID or package name mismatch to clientId's uid=" + uid - + ", packageName=" + packageName); - return null; - } - - // validate passphrase & PMK (if provided) - if (!TextUtils.isEmpty(ns.passphrase)) { // non-null indicates usage - if (!WifiAwareUtils.validatePassphrase(ns.passphrase)) { - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() - + " -- invalid passphrase length: " + ns.passphrase.length()); - return null; - } - } - if (ns.pmk != null && !WifiAwareUtils.validatePmk(ns.pmk)) { // non-null indicates usage - Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() - + " -- invalid pmk length: " + ns.pmk.length); - return null; - } - - // create container and populate - AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation(); - nnri.state = AwareNetworkRequestInformation.STATE_IDLE; - nnri.uid = uid; - nnri.packageName = packageName; - nnri.pubSubId = pubSubId; - nnri.peerInstanceId = peerInstanceId; - nnri.peerDiscoveryMac = peerMac; - nnri.networkSpecifier = ns; - nnri.equivalentRequests.add(request); - - return nnri; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: "); - sb.append("state=").append(state).append(", ns=").append(networkSpecifier) - .append(", uid=").append(uid) - .append(", packageName=").append(packageName) - .append(", interfaceName=").append(interfaceName).append( - ", pubSubId=").append(pubSubId).append(", peerInstanceId=").append( - peerInstanceId).append(", peerDiscoveryMac=").append( - peerDiscoveryMac == null ? "" - : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append( - ", ndpId=").append(ndpId).append(", peerDataMac=").append( - peerDataMac == null ? "" - : String.valueOf(HexEncoding.encode(peerDataMac))) - .append(", peerIpv6=").append(peerIpv6).append(", peerPort=").append( - peerPort).append(", peerTransportProtocol=").append( - peerTransportProtocol).append(", startTimestamp=").append( - startTimestamp).append(", channelInfo=").append( - channelInfo).append(", equivalentSpecifiers=["); - for (NetworkRequest nr : equivalentRequests) { - sb.append(nr.toString()).append(", "); - } - return sb.append("]").toString(); - } - } - - /** - * A canonical (unique) descriptor of the peer connection. - */ - static class CanonicalConnectionInfo { - CanonicalConnectionInfo(byte[] peerDiscoveryMac, byte[] pmk, int sessionId, - String passphrase) { - this.peerDiscoveryMac = peerDiscoveryMac; - this.pmk = pmk; - this.sessionId = sessionId; - this.passphrase = passphrase; - } - - public final byte[] peerDiscoveryMac; - - /* - * Security configuration matching: - * - open: pmk/passphrase = null - * - pmk: pmk != null, passphrase = null - * - passphrase: passphrase != null, sessionId used (==0 for OOB), pmk=null - */ - public final byte[] pmk; - - public final int sessionId; - public final String passphrase; - - public boolean matches(CanonicalConnectionInfo other) { - return (other.peerDiscoveryMac == null || Arrays - .equals(peerDiscoveryMac, other.peerDiscoveryMac)) - && Arrays.equals(pmk, other.pmk) - && TextUtils.equals(passphrase, other.passphrase) - && (TextUtils.isEmpty(passphrase) || sessionId == other.sessionId); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("CanonicalConnectionInfo: ["); - sb.append("peerDiscoveryMac=").append(peerDiscoveryMac == null ? "" - : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(", pmk=").append( - pmk == null ? "" : "*").append(", sessionId=").append(sessionId).append( - ", passphrase=").append(passphrase == null ? "" : "*").append("]"); - return sb.toString(); - } - } - - /** - * Enables mocking. - */ - @VisibleForTesting - public class NetworkInterfaceWrapper { - /** - * Configures network agent properties: link-local address, connected status, interface - * name. Delegated to enable mocking. - */ - public boolean configureAgentProperties(AwareNetworkRequestInformation nnri, - Set<NetworkRequest> networkRequests, int ndpId, - NetworkCapabilities.Builder ncBuilder, LinkProperties linkProperties) { - // find link-local address - InetAddress linkLocal = null; - NetworkInterface ni; - try { - ni = NetworkInterface.getByName(nnri.interfaceName); - } catch (SocketException e) { - Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri - + ": can't get network interface - " + e); - return false; - } - if (ni == null) { - Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri - + ": can't get network interface (null)"); - return false; - } - Enumeration<InetAddress> addresses = ni.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress ip = addresses.nextElement(); - if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) { - linkLocal = ip; - break; - } - } - - if (linkLocal == null) { - Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses"); - return false; - } - - ncBuilder.setRequestorUid(nnri.uid); - ncBuilder.setRequestorPackageName(nnri.packageName); - ncBuilder.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier( - networkRequests.stream() - .map(NetworkRequest::getNetworkSpecifier) - .toArray(WifiAwareNetworkSpecifier[]::new))); - - linkProperties.setInterfaceName(nnri.interfaceName); - linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64)); - linkProperties.addRoute( - new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName, - RTN_UNICAST)); - - return true; - } - - /** - * Tries binding to the input address to check whether it is configured (and therefore - * usable). - */ - public boolean isAddressUsable(LinkProperties linkProperties) { - InetAddress address = linkProperties.getLinkAddresses().get(0).getAddress(); - DatagramSocket testDatagramSocket = null; - try { - testDatagramSocket = new DatagramSocket(0, address); - } catch (SocketException e) { - if (mDbg) { - Log.v(TAG, "Can't create socket on address " + address + " -- " + e); - } - return false; - } finally { - if (testDatagramSocket != null) { - testDatagramSocket.close(); - } - } - return true; - } - - /** - * Tell the network agent the network is now connected. - */ - public void setConnected(WifiAwareNetworkAgent networkAgent) { - networkAgent.markConnected(); - } - } - - /** - * Utility (hence static) class encapsulating the data structure used to communicate Wi-Fi Aware - * specific network capabilities. The TLV is defined as part of the NANv3 spec: - * - * - Generic Service Protocol - * - Port - * - Transport protocol - */ - @VisibleForTesting - public static class NetworkInformationData { - // All package visible to allow usage in unit testing - /* package */ static final int IPV6_LL_TYPE = 0x00; // Table 82 - /* package */ static final int SERVICE_INFO_TYPE = 0x01; // Table 83 - /* package */ static final byte[] WFA_OUI = {0x50, 0x6F, (byte) 0x9A}; // Table 83 - /* package */ static final int GENERIC_SERVICE_PROTOCOL_TYPE = 0x02; // Table 50 - /* package */ static final int SUB_TYPE_PORT = 0x00; // Table 127 - /* package */ static final int SUB_TYPE_TRANSPORT_PROTOCOL = 0x01; // Table 128 - - /** - * Construct the TLV. - */ - public static byte[] buildTlv(int port, int transportProtocol) { - if (port == 0 && transportProtocol == -1) { - return null; - } - - TlvBufferUtils.TlvConstructor tlvc = new TlvBufferUtils.TlvConstructor(1, 2); - tlvc.setByteOrder(ByteOrder.LITTLE_ENDIAN); - tlvc.allocate(20); // safe size for now - - tlvc.putRawByteArray(WFA_OUI); - tlvc.putRawByte((byte) GENERIC_SERVICE_PROTOCOL_TYPE); - - if (port != 0) { - tlvc.putShort(SUB_TYPE_PORT, (short) port); - } - if (transportProtocol != -1) { - tlvc.putByte(SUB_TYPE_TRANSPORT_PROTOCOL, (byte) transportProtocol); - } - - byte[] subTypes = tlvc.getArray(); - - tlvc.allocate(20); - tlvc.putByteArray(SERVICE_INFO_TYPE, subTypes); - - return tlvc.getArray(); - } - - static class ParsedResults { - ParsedResults(int port, int transportProtocol, byte[] ipv6Override) { - this.port = port; - this.transportProtocol = transportProtocol; - this.ipv6Override = ipv6Override; - } - - public int port = 0; - public int transportProtocol = -1; - public byte[] ipv6Override = null; - } - - /** - * Parse the TLV and returns: - * - Null on parsing error - * - <port | 0, transport-protocol | -1, ipv6-override | null> otherwise - */ - public static ParsedResults parseTlv(byte[] tlvs) { - int port = 0; - int transportProtocol = -1; - byte[] ipv6Override = null; - - try { - TlvBufferUtils.TlvIterable tlvi = new TlvBufferUtils.TlvIterable(1, 2, tlvs); - tlvi.setByteOrder(ByteOrder.LITTLE_ENDIAN); - for (TlvBufferUtils.TlvElement tlve : tlvi) { - switch (tlve.type) { - case IPV6_LL_TYPE: - if (tlve.length != 8) { // 8 bytes in IPv6 address - Log.e(TAG, "NetworkInformationData: invalid IPv6 TLV -- length: " - + tlve.length); - return null; - } - ipv6Override = tlve.getRawData(); - break; - case SERVICE_INFO_TYPE: - Pair<Integer, Integer> serviceInfo = parseServiceInfoTlv( - tlve.getRawData()); - if (serviceInfo == null) { - return null; - } - port = serviceInfo.first; - transportProtocol = serviceInfo.second; - break; - default: - Log.w(TAG, - "NetworkInformationData: ignoring unknown T -- " + tlve.type); - break; - } - } - } catch (Exception e) { - Log.e(TAG, "NetworkInformationData: error parsing TLV -- " + e); - return null; - } - return new ParsedResults(port, transportProtocol, ipv6Override); - } - - /** - * Parse the Service Info TLV: - * - Returns null on error - * - Returns <port | 0, transport-protocol | -1> otherwise - */ - private static Pair<Integer, Integer> parseServiceInfoTlv(byte[] tlv) { - int port = 0; - int transportProtocol = -1; - - if (tlv.length < 4) { - Log.e(TAG, "NetworkInformationData: invalid SERVICE_INFO_TYPE length"); - return null; - } - if (tlv[0] != WFA_OUI[0] || tlv[1] != WFA_OUI[1] || tlv[2] != WFA_OUI[2]) { - Log.e(TAG, "NetworkInformationData: unexpected OUI"); - return null; - } - if (tlv[3] != GENERIC_SERVICE_PROTOCOL_TYPE) { - Log.e(TAG, "NetworkInformationData: invalid type -- " + tlv[3]); - return null; - } - TlvBufferUtils.TlvIterable subTlvi = new TlvBufferUtils.TlvIterable(1, - 2, Arrays.copyOfRange(tlv, 4, tlv.length)); - subTlvi.setByteOrder(ByteOrder.LITTLE_ENDIAN); - for (TlvBufferUtils.TlvElement subTlve : subTlvi) { - switch (subTlve.type) { - case SUB_TYPE_PORT: - if (subTlve.length != 2) { - Log.e(TAG, - "NetworkInformationData: invalid port TLV " - + "length -- " + subTlve.length); - return null; - } - port = subTlve.getShort(); - if (port < 0) { - port += -2 * (int) Short.MIN_VALUE; - } - if (port == 0) { - Log.e(TAG, "NetworkInformationData: invalid port " - + port); - return null; - } - break; - case SUB_TYPE_TRANSPORT_PROTOCOL: - if (subTlve.length != 1) { - Log.e(TAG, "NetworkInformationData: invalid transport " - + "protocol TLV length -- " + subTlve.length); - return null; - } - transportProtocol = subTlve.getByte(); - if (transportProtocol < 0) { - transportProtocol += -2 * (int) Byte.MIN_VALUE; - } - break; - default: - Log.w(TAG, "NetworkInformationData: ignoring unknown " - + "SERVICE_INFO.T -- " + subTlve.type); - break; - } - } - return Pair.create(port, transportProtocol); - } - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("WifiAwareDataPathStateManager:"); - pw.println(" mInterfaces: " + mInterfaces); - pw.println(" sNetworkCapabilitiesFilter: " + sNetworkCapabilitiesFilter); - pw.println(" mNetworkRequestsCache: " + mNetworkRequestsCache); - pw.println(" mNetworkFactory:"); - mNetworkFactory.dump(fd, pw, args); - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java deleted file mode 100644 index bfd3e2c19..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import android.hardware.wifi.V1_0.NanStatusType; -import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.net.wifi.util.HexEncoding; -import android.os.RemoteException; -import android.util.Log; -import android.util.SparseArray; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Arrays; - -/** - * Manages the state of a single Aware discovery session (publish or subscribe). - * Primary state consists of a callback through which session callbacks are - * executed as well as state related to currently active discovery sessions: - * publish/subscribe ID, and MAC address caching (hiding) from clients. - */ -public class WifiAwareDiscoverySessionState { - private static final String TAG = "WifiAwareDiscSessState"; - private boolean mDbg = false; - - private static int sNextPeerIdToBeAllocated = 100; // used to create a unique peer ID - - private final WifiAwareNativeApi mWifiAwareNativeApi; - private int mSessionId; - private byte mPubSubId; - private IWifiAwareDiscoverySessionCallback mCallback; - private boolean mIsPublishSession; - private boolean mIsRangingEnabled; - private final long mCreationTime; - - static class PeerInfo { - PeerInfo(int instanceId, byte[] mac) { - mInstanceId = instanceId; - mMac = mac; - } - - int mInstanceId; - byte[] mMac; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("instanceId ["); - sb.append(mInstanceId).append(", mac=").append(HexEncoding.encode(mMac)).append("]"); - return sb.toString(); - } - } - - private final SparseArray<PeerInfo> mPeerInfoByRequestorInstanceId = new SparseArray<>(); - - public WifiAwareDiscoverySessionState(WifiAwareNativeApi wifiAwareNativeApi, int sessionId, - byte pubSubId, IWifiAwareDiscoverySessionCallback callback, boolean isPublishSession, - boolean isRangingEnabled, long creationTime) { - mWifiAwareNativeApi = wifiAwareNativeApi; - mSessionId = sessionId; - mPubSubId = pubSubId; - mCallback = callback; - mIsPublishSession = isPublishSession; - mIsRangingEnabled = isRangingEnabled; - mCreationTime = creationTime; - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(boolean verbose) { - mDbg = verbose; - } - - public int getSessionId() { - return mSessionId; - } - - public int getPubSubId() { - return mPubSubId; - } - - public boolean isPublishSession() { - return mIsPublishSession; - } - - public boolean isRangingEnabled() { - return mIsRangingEnabled; - } - - public void setRangingEnabled(boolean enabled) { - mIsRangingEnabled = enabled; - } - - public long getCreationTime() { - return mCreationTime; - } - - public IWifiAwareDiscoverySessionCallback getCallback() { - return mCallback; - } - - /** - * Return the peer information of the specified peer ID - or a null if no such peer ID is - * registered. - */ - public PeerInfo getPeerInfo(int peerId) { - return mPeerInfoByRequestorInstanceId.get(peerId); - } - - /** - * Destroy the current discovery session - stops publishing or subscribing - * if currently active. - */ - public void terminate() { - mCallback = null; - - if (mIsPublishSession) { - mWifiAwareNativeApi.stopPublish((short) 0, mPubSubId); - } else { - mWifiAwareNativeApi.stopSubscribe((short) 0, mPubSubId); - } - } - - /** - * Indicates whether the publish/subscribe ID (a HAL ID) corresponds to this - * session. - * - * @param pubSubId The publish/subscribe HAL ID to be tested. - * @return true if corresponds to this session, false otherwise. - */ - public boolean isPubSubIdSession(int pubSubId) { - return mPubSubId == pubSubId; - } - - /** - * Modify a publish discovery session. - * - * @param transactionId Transaction ID for the transaction - used in the - * async callback to match with the original request. - * @param config Configuration of the publish session. - */ - public boolean updatePublish(short transactionId, PublishConfig config) { - if (!mIsPublishSession) { - Log.e(TAG, "A SUBSCRIBE session is being used to publish"); - try { - mCallback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.e(TAG, "updatePublish: RemoteException=" + e); - } - return false; - } - - boolean success = mWifiAwareNativeApi.publish(transactionId, mPubSubId, config); - if (!success) { - try { - mCallback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.w(TAG, "updatePublish onSessionConfigFail(): RemoteException (FYI): " + e); - } - } - - return success; - } - - /** - * Modify a subscribe discovery session. - * - * @param transactionId Transaction ID for the transaction - used in the - * async callback to match with the original request. - * @param config Configuration of the subscribe session. - */ - public boolean updateSubscribe(short transactionId, SubscribeConfig config) { - if (mIsPublishSession) { - Log.e(TAG, "A PUBLISH session is being used to subscribe"); - try { - mCallback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.e(TAG, "updateSubscribe: RemoteException=" + e); - } - return false; - } - - boolean success = mWifiAwareNativeApi.subscribe(transactionId, mPubSubId, config); - if (!success) { - try { - mCallback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.w(TAG, "updateSubscribe onSessionConfigFail(): RemoteException (FYI): " + e); - } - } - - return success; - } - - /** - * Send a message to a peer which is part of a discovery session. - * - * @param transactionId Transaction ID for the transaction - used in the - * async callback to match with the original request. - * @param peerId ID of the peer. Obtained through previous communication (a - * match indication). - * @param message Message byte array to send to the peer. - * @param messageId A message ID provided by caller to be used in any - * callbacks related to the message (success/failure). - */ - public boolean sendMessage(short transactionId, int peerId, byte[] message, int messageId) { - PeerInfo peerInfo = mPeerInfoByRequestorInstanceId.get(peerId); - if (peerInfo == null) { - Log.e(TAG, "sendMessage: attempting to send a message to an address which didn't " - + "match/contact us"); - try { - mCallback.onMessageSendFail(messageId, NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.e(TAG, "sendMessage: RemoteException=" + e); - } - return false; - } - - boolean success = mWifiAwareNativeApi.sendMessage(transactionId, mPubSubId, - peerInfo.mInstanceId, peerInfo.mMac, message, messageId); - if (!success) { - try { - mCallback.onMessageSendFail(messageId, NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.e(TAG, "sendMessage: RemoteException=" + e); - } - return false; - } - - return success; - } - - /** - * Callback from HAL when a discovery occurs - i.e. when a match to an - * active subscription request or to a solicited publish request occurs. - * Propagates to client if registered. - * - * @param requestorInstanceId The ID used to identify the peer in this - * matched session. - * @param peerMac The MAC address of the peer. Never propagated to client - * due to privacy concerns. - * @param serviceSpecificInfo Information from the discovery advertisement - * (usually not used in the match decisions). - * @param matchFilter The filter from the discovery advertisement (which was - * used in the match decision). - * @param rangingIndication Bit mask indicating the type of ranging event triggered. - * @param rangeMm The range to the peer in mm (valid if rangingIndication specifies ingress - * or egress events - i.e. non-zero). - */ - public void onMatch(int requestorInstanceId, byte[] peerMac, byte[] serviceSpecificInfo, - byte[] matchFilter, int rangingIndication, int rangeMm) { - int peerId = getPeerIdOrAddIfNew(requestorInstanceId, peerMac); - - try { - if (rangingIndication == 0) { - mCallback.onMatch(peerId, serviceSpecificInfo, matchFilter); - } else { - mCallback.onMatchWithDistance(peerId, serviceSpecificInfo, matchFilter, rangeMm); - } - } catch (RemoteException e) { - Log.w(TAG, "onMatch: RemoteException (FYI): " + e); - } - } - - /** - * Callback from HAL when a message is received from a peer in a discovery - * session. Propagated to client if registered. - * - * @param requestorInstanceId An ID used to identify the peer. - * @param peerMac The MAC address of the peer sending the message. This - * information is never propagated to the client due to privacy - * concerns. - * @param message The received message. - */ - public void onMessageReceived(int requestorInstanceId, byte[] peerMac, byte[] message) { - int peerId = getPeerIdOrAddIfNew(requestorInstanceId, peerMac); - - try { - mCallback.onMessageReceived(peerId, message); - } catch (RemoteException e) { - Log.w(TAG, "onMessageReceived: RemoteException (FYI): " + e); - } - } - - private int getPeerIdOrAddIfNew(int requestorInstanceId, byte[] peerMac) { - for (int i = 0; i < mPeerInfoByRequestorInstanceId.size(); ++i) { - PeerInfo peerInfo = mPeerInfoByRequestorInstanceId.valueAt(i); - if (peerInfo.mInstanceId == requestorInstanceId && Arrays.equals(peerMac, - peerInfo.mMac)) { - return mPeerInfoByRequestorInstanceId.keyAt(i); - } - } - - int newPeerId = sNextPeerIdToBeAllocated++; - PeerInfo newPeerInfo = new PeerInfo(requestorInstanceId, peerMac); - mPeerInfoByRequestorInstanceId.put(newPeerId, newPeerInfo); - - if (mDbg) { - Log.v(TAG, "New peer info: peerId=" + newPeerId + ", peerInfo=" + newPeerInfo); - } - - return newPeerId; - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("AwareSessionState:"); - pw.println(" mSessionId: " + mSessionId); - pw.println(" mIsPublishSession: " + mIsPublishSession); - pw.println(" mPubSubId: " + mPubSubId); - pw.println(" mPeerInfoByRequestorInstanceId: [" + mPeerInfoByRequestorInstanceId + "]"); - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java b/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java deleted file mode 100644 index e9043f820..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java +++ /dev/null @@ -1,875 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.aware; - -import android.hardware.wifi.V1_0.NanStatusType; -import android.net.wifi.aware.WifiAwareNetworkSpecifier; -import android.text.TextUtils; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.Clock; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.MetricsUtils; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Wi-Fi Aware metric container/processor. - */ -public class WifiAwareMetrics { - private static final String TAG = "WifiAwareMetrics"; - - // Histogram: 8 buckets (i=0, ..., 7) of 9 slots in range 10^i -> 10^(i+1) - // Buckets: - // 1 -> 10: 9 @ 1 - // 10 -> 100: 9 @ 10 - // 100 -> 1000: 9 @ 10^2 - // 10^3 -> 10^4: 9 @ 10^3 - // 10^4 -> 10^5: 9 @ 10^4 - // 10^5 -> 10^6: 9 @ 10^5 - // 10^6 -> 10^7: 9 @ 10^6 - // 10^7 -> 10^8: 9 @ 10^7 --> 10^8 ms -> 10^5s -> 28 hours - private static final MetricsUtils.LogHistParms DURATION_LOG_HISTOGRAM = - new MetricsUtils.LogHistParms(0, 1, 10, 9, 8); - - // Histogram for ranging limits in discovery. Indicates the following 5 buckets (in meters): - // < 10 - // [10, 30) - // [30, 60) - // [60, 100) - // >= 100 - private static final int[] RANGING_LIMIT_METERS = { 10, 30, 60, 100 }; - - private final Object mLock = new Object(); - private final Clock mClock; - - // enableUsage/disableUsage data - private long mLastEnableUsageMs = 0; - private long mLastEnableUsageInThisSampleWindowMs = 0; - private long mAvailableTimeMs = 0; - private SparseIntArray mHistogramAwareAvailableDurationMs = new SparseIntArray(); - - // enabled data - private long mLastEnableAwareMs = 0; - private long mLastEnableAwareInThisSampleWindowMs = 0; - private long mEnabledTimeMs = 0; - private SparseIntArray mHistogramAwareEnabledDurationMs = new SparseIntArray(); - - // attach data - private static class AttachData { - boolean mUsesIdentityCallback; // do any attach sessions of the UID use identity callback - int mMaxConcurrentAttaches; - } - private Map<Integer, AttachData> mAttachDataByUid = new HashMap<>(); - private SparseIntArray mAttachStatusData = new SparseIntArray(); - private SparseIntArray mHistogramAttachDuration = new SparseIntArray(); - - // discovery data - private int mMaxPublishInApp = 0; - private int mMaxSubscribeInApp = 0; - private int mMaxDiscoveryInApp = 0; - private int mMaxPublishInSystem = 0; - private int mMaxSubscribeInSystem = 0; - private int mMaxDiscoveryInSystem = 0; - private SparseIntArray mPublishStatusData = new SparseIntArray(); - private SparseIntArray mSubscribeStatusData = new SparseIntArray(); - private SparseIntArray mHistogramPublishDuration = new SparseIntArray(); - private SparseIntArray mHistogramSubscribeDuration = new SparseIntArray(); - private Set<Integer> mAppsWithDiscoverySessionResourceFailure = new HashSet<>(); - - // discovery with ranging data - private int mMaxPublishWithRangingInApp = 0; - private int mMaxSubscribeWithRangingInApp = 0; - private int mMaxPublishWithRangingInSystem = 0; - private int mMaxSubscribeWithRangingInSystem = 0; - private SparseIntArray mHistogramSubscribeGeofenceMin = new SparseIntArray(); - private SparseIntArray mHistogramSubscribeGeofenceMax = new SparseIntArray(); - private int mNumSubscribesWithRanging = 0; - private int mNumMatchesWithRanging = 0; - private int mNumMatchesWithoutRangingForRangingEnabledSubscribes = 0; - - // data-path (NDI/NDP) data - private int mMaxNdiInApp = 0; - private int mMaxNdpInApp = 0; - private int mMaxSecureNdpInApp = 0; - private int mMaxNdiInSystem = 0; - private int mMaxNdpInSystem = 0; - private int mMaxSecureNdpInSystem = 0; - private int mMaxNdpPerNdi = 0; - private SparseIntArray mInBandNdpStatusData = new SparseIntArray(); - private SparseIntArray mOutOfBandNdpStatusData = new SparseIntArray(); - - private SparseIntArray mNdpCreationTimeDuration = new SparseIntArray(); - private long mNdpCreationTimeMin = -1; - private long mNdpCreationTimeMax = 0; - private long mNdpCreationTimeSum = 0; - private long mNdpCreationTimeSumSq = 0; - private long mNdpCreationTimeNumSamples = 0; - - private SparseIntArray mHistogramNdpDuration = new SparseIntArray(); - - public WifiAwareMetrics(Clock clock) { - mClock = clock; - } - - /** - * Push usage stats for WifiAwareStateMachine.enableUsage() to - * histogram_aware_available_duration_ms. - */ - public void recordEnableUsage() { - synchronized (mLock) { - if (mLastEnableUsageMs != 0) { - Log.w(TAG, "enableUsage: mLastEnableUsage*Ms initialized!?"); - } - mLastEnableUsageMs = mClock.getElapsedSinceBootMillis(); - mLastEnableUsageInThisSampleWindowMs = mLastEnableUsageMs; - } - } - - /** - * Push usage stats for WifiAwareStateMachine.disableUsage() to - * histogram_aware_available_duration_ms. - */ - - public void recordDisableUsage() { - synchronized (mLock) { - if (mLastEnableUsageMs == 0) { - Log.e(TAG, "disableUsage: mLastEnableUsage not initialized!?"); - return; - } - - long now = mClock.getElapsedSinceBootMillis(); - MetricsUtils.addValueToLogHistogram(now - mLastEnableUsageMs, - mHistogramAwareAvailableDurationMs, DURATION_LOG_HISTOGRAM); - mAvailableTimeMs += now - mLastEnableUsageInThisSampleWindowMs; - mLastEnableUsageMs = 0; - mLastEnableUsageInThisSampleWindowMs = 0; - } - } - - /** - * Push usage stats of Aware actually being enabled on-the-air: start - */ - public void recordEnableAware() { - synchronized (mLock) { - if (mLastEnableAwareMs != 0) { - return; // already enabled - } - mLastEnableAwareMs = mClock.getElapsedSinceBootMillis(); - mLastEnableAwareInThisSampleWindowMs = mLastEnableAwareMs; - } - } - - /** - * Push usage stats of Aware actually being enabled on-the-air: stop (disable) - */ - public void recordDisableAware() { - synchronized (mLock) { - if (mLastEnableAwareMs == 0) { - return; // already disabled - } - - long now = mClock.getElapsedSinceBootMillis(); - MetricsUtils.addValueToLogHistogram(now - mLastEnableAwareMs, - mHistogramAwareEnabledDurationMs, DURATION_LOG_HISTOGRAM); - mEnabledTimeMs += now - mLastEnableAwareInThisSampleWindowMs; - mLastEnableAwareMs = 0; - mLastEnableAwareInThisSampleWindowMs = 0; - } - } - - /** - * Push information about a new attach session. - */ - public void recordAttachSession(int uid, boolean usesIdentityCallback, - SparseArray<WifiAwareClientState> clients) { - // count the number of clients with the specific uid - int currentConcurrentCount = 0; - for (int i = 0; i < clients.size(); ++i) { - if (clients.valueAt(i).getUid() == uid) { - ++currentConcurrentCount; - } - } - - synchronized (mLock) { - AttachData data = mAttachDataByUid.get(uid); - if (data == null) { - data = new AttachData(); - mAttachDataByUid.put(uid, data); - } - data.mUsesIdentityCallback |= usesIdentityCallback; - data.mMaxConcurrentAttaches = Math.max(data.mMaxConcurrentAttaches, - currentConcurrentCount); - recordAttachStatus(NanStatusType.SUCCESS); - } - } - - /** - * Push information about a new attach session status (recorded when attach session is created). - */ - public void recordAttachStatus(int status) { - synchronized (mLock) { - addNanHalStatusToHistogram(status, mAttachStatusData); - } - } - - /** - * Push duration information of an attach session. - */ - public void recordAttachSessionDuration(long creationTime) { - synchronized (mLock) { - MetricsUtils.addValueToLogHistogram(mClock.getElapsedSinceBootMillis() - creationTime, - mHistogramAttachDuration, DURATION_LOG_HISTOGRAM); - } - } - - /** - * Push information about the new discovery session. - */ - public void recordDiscoverySession(int uid, SparseArray<WifiAwareClientState> clients) { - recordDiscoverySessionInternal(uid, clients, false, -1, -1); - } - - /** - * Push information about the new discovery session with ranging enabled - */ - public void recordDiscoverySessionWithRanging(int uid, boolean isSubscriberWithRanging, - int minRange, int maxRange, SparseArray<WifiAwareClientState> clients) { - recordDiscoverySessionInternal(uid, clients, isSubscriberWithRanging, minRange, maxRange); - } - - /** - * Internal combiner of discovery session information. - */ - private void recordDiscoverySessionInternal(int uid, SparseArray<WifiAwareClientState> clients, - boolean isRangingEnabledSubscriber, int minRange, int maxRange) { - // count the number of sessions per uid and overall - int numPublishesInSystem = 0; - int numSubscribesInSystem = 0; - int numPublishesOnUid = 0; - int numSubscribesOnUid = 0; - - int numPublishesWithRangingInSystem = 0; - int numSubscribesWithRangingInSystem = 0; - int numPublishesWithRangingOnUid = 0; - int numSubscribesWithRangingOnUid = 0; - - for (int i = 0; i < clients.size(); ++i) { - WifiAwareClientState client = clients.valueAt(i); - boolean sameUid = client.getUid() == uid; - - SparseArray<WifiAwareDiscoverySessionState> sessions = client.getSessions(); - for (int j = 0; j < sessions.size(); ++j) { - WifiAwareDiscoverySessionState session = sessions.valueAt(j); - boolean isRangingEnabledForThisSession = session.isRangingEnabled(); - - if (session.isPublishSession()) { - numPublishesInSystem += 1; - if (isRangingEnabledForThisSession) { - numPublishesWithRangingInSystem += 1; - } - if (sameUid) { - numPublishesOnUid += 1; - if (isRangingEnabledForThisSession) { - numPublishesWithRangingOnUid += 1; - } - } - } else { - numSubscribesInSystem += 1; - if (isRangingEnabledForThisSession) { - numSubscribesWithRangingInSystem += 1; - } - if (sameUid) { - numSubscribesOnUid += 1; - if (isRangingEnabledForThisSession) { - numSubscribesWithRangingOnUid += 1; - } - } - } - } - } - - synchronized (mLock) { - mMaxPublishInApp = Math.max(mMaxPublishInApp, numPublishesOnUid); - mMaxSubscribeInApp = Math.max(mMaxSubscribeInApp, numSubscribesOnUid); - mMaxDiscoveryInApp = Math.max(mMaxDiscoveryInApp, - numPublishesOnUid + numSubscribesOnUid); - mMaxPublishInSystem = Math.max(mMaxPublishInSystem, numPublishesInSystem); - mMaxSubscribeInSystem = Math.max(mMaxSubscribeInSystem, numSubscribesInSystem); - mMaxDiscoveryInSystem = Math.max(mMaxDiscoveryInSystem, - numPublishesInSystem + numSubscribesInSystem); - - mMaxPublishWithRangingInApp = Math.max(mMaxPublishWithRangingInApp, - numPublishesWithRangingOnUid); - mMaxSubscribeWithRangingInApp = Math.max(mMaxSubscribeWithRangingInApp, - numSubscribesWithRangingOnUid); - mMaxPublishWithRangingInSystem = Math.max(mMaxPublishWithRangingInSystem, - numPublishesWithRangingInSystem); - mMaxSubscribeWithRangingInSystem = Math.max(mMaxSubscribeWithRangingInSystem, - numSubscribesWithRangingInSystem); - if (isRangingEnabledSubscriber) { - mNumSubscribesWithRanging += 1; - } - - if (minRange != -1) { - MetricsUtils.addValueToLinearHistogram(minRange, mHistogramSubscribeGeofenceMin, - RANGING_LIMIT_METERS); - } - if (maxRange != -1) { - MetricsUtils.addValueToLinearHistogram(maxRange, mHistogramSubscribeGeofenceMax, - RANGING_LIMIT_METERS); - } - } - } - - /** - * Push information about a new discovery session status (recorded when the discovery session is - * created). - */ - public void recordDiscoveryStatus(int uid, int status, boolean isPublish) { - synchronized (mLock) { - if (isPublish) { - addNanHalStatusToHistogram(status, mPublishStatusData); - } else { - addNanHalStatusToHistogram(status, mSubscribeStatusData); - } - - if (status == NanStatusType.NO_RESOURCES_AVAILABLE) { - mAppsWithDiscoverySessionResourceFailure.add(uid); - } - } - } - - /** - * Push duration information of a discovery session. - */ - public void recordDiscoverySessionDuration(long creationTime, boolean isPublish) { - synchronized (mLock) { - MetricsUtils.addValueToLogHistogram(mClock.getElapsedSinceBootMillis() - creationTime, - isPublish ? mHistogramPublishDuration : mHistogramSubscribeDuration, - DURATION_LOG_HISTOGRAM); - } - } - - /** - * Push information about Match indication (aka service discovered) for subscribe sessions - * which enabled ranging. Collect information about whether or not service discovery was - * triggered with ranging information or without (i.e. ranging disabled for some reason). - */ - public void recordMatchIndicationForRangeEnabledSubscribe(boolean rangeProvided) { - if (rangeProvided) { - mNumMatchesWithRanging++; - } else { - mNumMatchesWithoutRangingForRangingEnabledSubscribes++; - } - } - - /** - * Record NDP (and by extension NDI) usage - on successful creation of an NDP. - */ - public void recordNdpCreation(int uid, String packageName, - Map<WifiAwareNetworkSpecifier, WifiAwareDataPathStateManager - .AwareNetworkRequestInformation> networkRequestCache) { - int numNdpInApp = 0; - int numSecureNdpInApp = 0; - int numNdpInSystem = 0; - int numSecureNdpInSystem = 0; - - Map<String, Integer> ndpPerNdiMap = new HashMap<>(); - Set<String> ndiInApp = new HashSet<>(); - Set<String> ndiInSystem = new HashSet<>(); - - for (WifiAwareDataPathStateManager.AwareNetworkRequestInformation anri : - networkRequestCache.values()) { - if (anri.state - != WifiAwareDataPathStateManager.AwareNetworkRequestInformation - .STATE_CONFIRMED) { - continue; // only count completed (up-and-running) NDPs - } - - boolean sameApp = (anri.uid == uid) && TextUtils.equals(anri.packageName, packageName); - boolean isSecure = !TextUtils.isEmpty(anri.networkSpecifier.passphrase) || ( - anri.networkSpecifier.pmk != null && anri.networkSpecifier.pmk.length != 0); - - // in-app stats - if (sameApp) { - numNdpInApp += 1; - if (isSecure) { - numSecureNdpInApp += 1; - } - - ndiInApp.add(anri.interfaceName); - } - - // system stats - numNdpInSystem += 1; - if (isSecure) { - numSecureNdpInSystem += 1; - } - - // ndp/ndi stats - Integer ndpCount = ndpPerNdiMap.get(anri.interfaceName); - if (ndpCount == null) { - ndpPerNdiMap.put(anri.interfaceName, 1); - } else { - ndpPerNdiMap.put(anri.interfaceName, ndpCount + 1); - } - - // ndi stats - ndiInSystem.add(anri.interfaceName); - } - - synchronized (mLock) { - mMaxNdiInApp = Math.max(mMaxNdiInApp, ndiInApp.size()); - mMaxNdpInApp = Math.max(mMaxNdpInApp, numNdpInApp); - mMaxSecureNdpInApp = Math.max(mMaxSecureNdpInApp, numSecureNdpInApp); - mMaxNdiInSystem = Math.max(mMaxNdiInSystem, ndiInSystem.size()); - mMaxNdpInSystem = Math.max(mMaxNdpInSystem, numNdpInSystem); - mMaxSecureNdpInSystem = Math.max(mMaxSecureNdpInSystem, numSecureNdpInSystem); - mMaxNdpPerNdi = Math.max(mMaxNdpPerNdi, Collections.max(ndpPerNdiMap.values())); - } - } - - /** - * Record the completion status of NDP negotiation. There are multiple steps in NDP negotiation - * a failure on any aborts the process and is recorded. A success on intermediate stages is - * not recorded - only the final success. - */ - public void recordNdpStatus(int status, boolean isOutOfBand, long startTimestamp) { - synchronized (mLock) { - if (isOutOfBand) { - addNanHalStatusToHistogram(status, mOutOfBandNdpStatusData); - } else { - addNanHalStatusToHistogram(status, mInBandNdpStatusData); - } - - if (status == NanStatusType.SUCCESS) { - long creationTime = mClock.getElapsedSinceBootMillis() - startTimestamp; - MetricsUtils.addValueToLogHistogram(creationTime, mNdpCreationTimeDuration, - DURATION_LOG_HISTOGRAM); - mNdpCreationTimeMin = (mNdpCreationTimeMin == -1) ? creationTime : Math.min( - mNdpCreationTimeMin, creationTime); - mNdpCreationTimeMax = Math.max(mNdpCreationTimeMax, creationTime); - mNdpCreationTimeSum += creationTime; - mNdpCreationTimeSumSq += creationTime * creationTime; - mNdpCreationTimeNumSamples += 1; - } - } - } - - /** - * Record the duration of the NDP session. The creation time is assumed to be the time at - * which a confirm message was received (i.e. the end of the setup negotiation). - */ - public void recordNdpSessionDuration(long creationTime) { - synchronized (mLock) { - MetricsUtils.addValueToLogHistogram(mClock.getElapsedSinceBootMillis() - creationTime, - mHistogramNdpDuration, DURATION_LOG_HISTOGRAM); - } - } - - /** - * Consolidate all metrics into the proto. - */ - public WifiMetricsProto.WifiAwareLog consolidateProto() { - WifiMetricsProto.WifiAwareLog log = new WifiMetricsProto.WifiAwareLog(); - long now = mClock.getElapsedSinceBootMillis(); - synchronized (mLock) { - log.histogramAwareAvailableDurationMs = histogramToProtoArray( - MetricsUtils.logHistogramToGenericBuckets(mHistogramAwareAvailableDurationMs, - DURATION_LOG_HISTOGRAM)); - log.availableTimeMs = mAvailableTimeMs; - if (mLastEnableUsageInThisSampleWindowMs != 0) { - log.availableTimeMs += now - mLastEnableUsageInThisSampleWindowMs; - } - - log.histogramAwareEnabledDurationMs = histogramToProtoArray( - MetricsUtils.logHistogramToGenericBuckets(mHistogramAwareEnabledDurationMs, - DURATION_LOG_HISTOGRAM)); - log.enabledTimeMs = mEnabledTimeMs; - if (mLastEnableAwareInThisSampleWindowMs != 0) { - log.enabledTimeMs += now - mLastEnableAwareInThisSampleWindowMs; - } - - log.numApps = mAttachDataByUid.size(); - log.numAppsUsingIdentityCallback = 0; - log.maxConcurrentAttachSessionsInApp = 0; - for (AttachData ad: mAttachDataByUid.values()) { - if (ad.mUsesIdentityCallback) { - ++log.numAppsUsingIdentityCallback; - } - log.maxConcurrentAttachSessionsInApp = Math.max( - log.maxConcurrentAttachSessionsInApp, ad.mMaxConcurrentAttaches); - } - log.histogramAttachSessionStatus = histogramToProtoArray(mAttachStatusData); - log.histogramAttachDurationMs = histogramToProtoArray( - MetricsUtils.logHistogramToGenericBuckets(mHistogramAttachDuration, - DURATION_LOG_HISTOGRAM)); - - log.maxConcurrentPublishInApp = mMaxPublishInApp; - log.maxConcurrentSubscribeInApp = mMaxSubscribeInApp; - log.maxConcurrentDiscoverySessionsInApp = mMaxDiscoveryInApp; - log.maxConcurrentPublishInSystem = mMaxPublishInSystem; - log.maxConcurrentSubscribeInSystem = mMaxSubscribeInSystem; - log.maxConcurrentDiscoverySessionsInSystem = mMaxDiscoveryInSystem; - log.histogramPublishStatus = histogramToProtoArray(mPublishStatusData); - log.histogramSubscribeStatus = histogramToProtoArray(mSubscribeStatusData); - log.numAppsWithDiscoverySessionFailureOutOfResources = - mAppsWithDiscoverySessionResourceFailure.size(); - log.histogramPublishSessionDurationMs = histogramToProtoArray( - MetricsUtils.logHistogramToGenericBuckets(mHistogramPublishDuration, - DURATION_LOG_HISTOGRAM)); - log.histogramSubscribeSessionDurationMs = histogramToProtoArray( - MetricsUtils.logHistogramToGenericBuckets(mHistogramSubscribeDuration, - DURATION_LOG_HISTOGRAM)); - - log.maxConcurrentPublishWithRangingInApp = mMaxPublishWithRangingInApp; - log.maxConcurrentSubscribeWithRangingInApp = mMaxSubscribeWithRangingInApp; - log.maxConcurrentPublishWithRangingInSystem = mMaxPublishWithRangingInSystem; - log.maxConcurrentSubscribeWithRangingInSystem = mMaxSubscribeWithRangingInSystem; - log.histogramSubscribeGeofenceMin = histogramToProtoArray( - MetricsUtils.linearHistogramToGenericBuckets(mHistogramSubscribeGeofenceMin, - RANGING_LIMIT_METERS)); - log.histogramSubscribeGeofenceMax = histogramToProtoArray( - MetricsUtils.linearHistogramToGenericBuckets(mHistogramSubscribeGeofenceMax, - RANGING_LIMIT_METERS)); - log.numSubscribesWithRanging = mNumSubscribesWithRanging; - log.numMatchesWithRanging = mNumMatchesWithRanging; - log.numMatchesWithoutRangingForRangingEnabledSubscribes = - mNumMatchesWithoutRangingForRangingEnabledSubscribes; - - log.maxConcurrentNdiInApp = mMaxNdiInApp; - log.maxConcurrentNdiInSystem = mMaxNdiInSystem; - log.maxConcurrentNdpInApp = mMaxNdpInApp; - log.maxConcurrentNdpInSystem = mMaxNdpInSystem; - log.maxConcurrentSecureNdpInApp = mMaxSecureNdpInApp; - log.maxConcurrentSecureNdpInSystem = mMaxSecureNdpInSystem; - log.maxConcurrentNdpPerNdi = mMaxNdpPerNdi; - log.histogramRequestNdpStatus = histogramToProtoArray(mInBandNdpStatusData); - log.histogramRequestNdpOobStatus = histogramToProtoArray(mOutOfBandNdpStatusData); - - log.histogramNdpCreationTimeMs = histogramToProtoArray( - MetricsUtils.logHistogramToGenericBuckets(mNdpCreationTimeDuration, - DURATION_LOG_HISTOGRAM)); - log.ndpCreationTimeMsMin = mNdpCreationTimeMin; - log.ndpCreationTimeMsMax = mNdpCreationTimeMax; - log.ndpCreationTimeMsSum = mNdpCreationTimeSum; - log.ndpCreationTimeMsSumOfSq = mNdpCreationTimeSumSq; - log.ndpCreationTimeMsNumSamples = mNdpCreationTimeNumSamples; - - log.histogramNdpSessionDurationMs = histogramToProtoArray( - MetricsUtils.logHistogramToGenericBuckets(mHistogramNdpDuration, - DURATION_LOG_HISTOGRAM)); - } - return log; - } - - /** - * clear Wi-Fi Aware metrics - */ - public void clear() { - long now = mClock.getElapsedSinceBootMillis(); - synchronized (mLock) { - // don't clear mLastEnableUsage since could be valid for next measurement period - mHistogramAwareAvailableDurationMs.clear(); - mAvailableTimeMs = 0; - if (mLastEnableUsageInThisSampleWindowMs != 0) { - mLastEnableUsageInThisSampleWindowMs = now; - } - - // don't clear mLastEnableAware since could be valid for next measurement period - mHistogramAwareEnabledDurationMs.clear(); - mEnabledTimeMs = 0; - if (mLastEnableAwareInThisSampleWindowMs != 0) { - mLastEnableAwareInThisSampleWindowMs = now; - } - - mAttachDataByUid.clear(); - mAttachStatusData.clear(); - mHistogramAttachDuration.clear(); - - mMaxPublishInApp = 0; - mMaxSubscribeInApp = 0; - mMaxDiscoveryInApp = 0; - mMaxPublishInSystem = 0; - mMaxSubscribeInSystem = 0; - mMaxDiscoveryInSystem = 0; - mPublishStatusData.clear(); - mSubscribeStatusData.clear(); - mHistogramPublishDuration.clear(); - mHistogramSubscribeDuration.clear(); - mAppsWithDiscoverySessionResourceFailure.clear(); - - mMaxPublishWithRangingInApp = 0; - mMaxSubscribeWithRangingInApp = 0; - mMaxPublishWithRangingInSystem = 0; - mMaxSubscribeWithRangingInSystem = 0; - mHistogramSubscribeGeofenceMin.clear(); - mHistogramSubscribeGeofenceMax.clear(); - mNumSubscribesWithRanging = 0; - mNumMatchesWithRanging = 0; - mNumMatchesWithoutRangingForRangingEnabledSubscribes = 0; - - mMaxNdiInApp = 0; - mMaxNdpInApp = 0; - mMaxSecureNdpInApp = 0; - mMaxNdiInSystem = 0; - mMaxNdpInSystem = 0; - mMaxSecureNdpInSystem = 0; - mMaxNdpPerNdi = 0; - mInBandNdpStatusData.clear(); - mOutOfBandNdpStatusData.clear(); - - mNdpCreationTimeDuration.clear(); - mNdpCreationTimeMin = -1; - mNdpCreationTimeMax = 0; - mNdpCreationTimeSum = 0; - mNdpCreationTimeSumSq = 0; - mNdpCreationTimeNumSamples = 0; - - mHistogramNdpDuration.clear(); - } - } - - /** - * Dump all WifiAwareMetrics to console (pw) - this method is never called to dump the - * serialized metrics (handled by parent WifiMetrics). - * - * @param fd unused - * @param pw PrintWriter for writing dump to - * @param args unused - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - synchronized (mLock) { - pw.println("mLastEnableUsageMs:" + mLastEnableUsageMs); - pw.println( - "mLastEnableUsageInThisSampleWindowMs:" + mLastEnableUsageInThisSampleWindowMs); - pw.println("mAvailableTimeMs:" + mAvailableTimeMs); - pw.println("mHistogramAwareAvailableDurationMs:"); - for (int i = 0; i < mHistogramAwareAvailableDurationMs.size(); ++i) { - pw.println(" " + mHistogramAwareAvailableDurationMs.keyAt(i) + ": " - + mHistogramAwareAvailableDurationMs.valueAt(i)); - } - - pw.println("mLastEnableAwareMs:" + mLastEnableAwareMs); - pw.println( - "mLastEnableAwareInThisSampleWindowMs:" + mLastEnableAwareInThisSampleWindowMs); - pw.println("mEnabledTimeMs:" + mEnabledTimeMs); - pw.println("mHistogramAwareEnabledDurationMs:"); - for (int i = 0; i < mHistogramAwareEnabledDurationMs.size(); ++i) { - pw.println(" " + mHistogramAwareEnabledDurationMs.keyAt(i) + ": " - + mHistogramAwareEnabledDurationMs.valueAt(i)); - } - - pw.println("mAttachDataByUid:"); - for (Map.Entry<Integer, AttachData> ade: mAttachDataByUid.entrySet()) { - pw.println(" " + "uid=" + ade.getKey() + ": identity=" - + ade.getValue().mUsesIdentityCallback + ", maxConcurrent=" - + ade.getValue().mMaxConcurrentAttaches); - } - pw.println("mAttachStatusData:"); - for (int i = 0; i < mAttachStatusData.size(); ++i) { - pw.println(" " + mAttachStatusData.keyAt(i) + ": " - + mAttachStatusData.valueAt(i)); - } - pw.println("mHistogramAttachDuration:"); - for (int i = 0; i < mHistogramAttachDuration.size(); ++i) { - pw.println(" " + mHistogramAttachDuration.keyAt(i) + ": " - + mHistogramAttachDuration.valueAt(i)); - } - - pw.println("mMaxPublishInApp:" + mMaxPublishInApp); - pw.println("mMaxSubscribeInApp:" + mMaxSubscribeInApp); - pw.println("mMaxDiscoveryInApp:" + mMaxDiscoveryInApp); - pw.println("mMaxPublishInSystem:" + mMaxPublishInSystem); - pw.println("mMaxSubscribeInSystem:" + mMaxSubscribeInSystem); - pw.println("mMaxDiscoveryInSystem:" + mMaxDiscoveryInSystem); - pw.println("mPublishStatusData:"); - for (int i = 0; i < mPublishStatusData.size(); ++i) { - pw.println(" " + mPublishStatusData.keyAt(i) + ": " - + mPublishStatusData.valueAt(i)); - } - pw.println("mSubscribeStatusData:"); - for (int i = 0; i < mSubscribeStatusData.size(); ++i) { - pw.println(" " + mSubscribeStatusData.keyAt(i) + ": " - + mSubscribeStatusData.valueAt(i)); - } - pw.println("mHistogramPublishDuration:"); - for (int i = 0; i < mHistogramPublishDuration.size(); ++i) { - pw.println(" " + mHistogramPublishDuration.keyAt(i) + ": " - + mHistogramPublishDuration.valueAt(i)); - } - pw.println("mHistogramSubscribeDuration:"); - for (int i = 0; i < mHistogramSubscribeDuration.size(); ++i) { - pw.println(" " + mHistogramSubscribeDuration.keyAt(i) + ": " - + mHistogramSubscribeDuration.valueAt(i)); - } - pw.println("mAppsWithDiscoverySessionResourceFailure:"); - for (Integer uid: mAppsWithDiscoverySessionResourceFailure) { - pw.println(" " + uid); - - } - - pw.println("mMaxPublishWithRangingInApp:" + mMaxPublishWithRangingInApp); - pw.println("mMaxSubscribeWithRangingInApp:" + mMaxSubscribeWithRangingInApp); - pw.println("mMaxPublishWithRangingInSystem:" + mMaxPublishWithRangingInSystem); - pw.println("mMaxSubscribeWithRangingInSystem:" + mMaxSubscribeWithRangingInSystem); - pw.println("mHistogramSubscribeGeofenceMin:"); - for (int i = 0; i < mHistogramSubscribeGeofenceMin.size(); ++i) { - pw.println(" " + mHistogramSubscribeGeofenceMin.keyAt(i) + ": " - + mHistogramSubscribeGeofenceMin.valueAt(i)); - } - pw.println("mHistogramSubscribeGeofenceMax:"); - for (int i = 0; i < mHistogramSubscribeGeofenceMax.size(); ++i) { - pw.println(" " + mHistogramSubscribeGeofenceMax.keyAt(i) + ": " - + mHistogramSubscribeGeofenceMax.valueAt(i)); - } - pw.println("mNumSubscribesWithRanging:" + mNumSubscribesWithRanging); - pw.println("mNumMatchesWithRanging:" + mNumMatchesWithRanging); - pw.println("mNumMatchesWithoutRangingForRangingEnabledSubscribes:" - + mNumMatchesWithoutRangingForRangingEnabledSubscribes); - - pw.println("mMaxNdiInApp:" + mMaxNdiInApp); - pw.println("mMaxNdpInApp:" + mMaxNdpInApp); - pw.println("mMaxSecureNdpInApp:" + mMaxSecureNdpInApp); - pw.println("mMaxNdiInSystem:" + mMaxNdiInSystem); - pw.println("mMaxNdpInSystem:" + mMaxNdpInSystem); - pw.println("mMaxSecureNdpInSystem:" + mMaxSecureNdpInSystem); - pw.println("mMaxNdpPerNdi:" + mMaxNdpPerNdi); - pw.println("mInBandNdpStatusData:"); - for (int i = 0; i < mInBandNdpStatusData.size(); ++i) { - pw.println(" " + mInBandNdpStatusData.keyAt(i) + ": " - + mInBandNdpStatusData.valueAt(i)); - } - pw.println("mOutOfBandNdpStatusData:"); - for (int i = 0; i < mOutOfBandNdpStatusData.size(); ++i) { - pw.println(" " + mOutOfBandNdpStatusData.keyAt(i) + ": " - + mOutOfBandNdpStatusData.valueAt(i)); - } - - pw.println("mNdpCreationTimeDuration:"); - for (int i = 0; i < mNdpCreationTimeDuration.size(); ++i) { - pw.println(" " + mNdpCreationTimeDuration.keyAt(i) + ": " - + mNdpCreationTimeDuration.valueAt(i)); - } - pw.println("mNdpCreationTimeMin:" + mNdpCreationTimeMin); - pw.println("mNdpCreationTimeMax:" + mNdpCreationTimeMax); - pw.println("mNdpCreationTimeSum:" + mNdpCreationTimeSum); - pw.println("mNdpCreationTimeSumSq:" + mNdpCreationTimeSumSq); - pw.println("mNdpCreationTimeNumSamples:" + mNdpCreationTimeNumSamples); - - pw.println("mHistogramNdpDuration:"); - for (int i = 0; i < mHistogramNdpDuration.size(); ++i) { - pw.println(" " + mHistogramNdpDuration.keyAt(i) + ": " - + mHistogramNdpDuration.valueAt(i)); - } - } - } - - // histogram utilities - /** - * Convert a generic bucket to Aware HistogramBucket proto. - */ - @VisibleForTesting - public static WifiMetricsProto.WifiAwareLog.HistogramBucket[] histogramToProtoArray( - MetricsUtils.GenericBucket[] buckets) { - WifiMetricsProto.WifiAwareLog.HistogramBucket[] protoArray = - new WifiMetricsProto.WifiAwareLog.HistogramBucket[buckets.length]; - - for (int i = 0; i < buckets.length; ++i) { - protoArray[i] = new WifiMetricsProto.WifiAwareLog.HistogramBucket(); - protoArray[i].start = buckets[i].start; - protoArray[i].end = buckets[i].end; - protoArray[i].count = buckets[i].count; - } - - return protoArray; - } - - /** - * Adds the NanStatusType to the histogram (translating to the proto enumeration of the status). - */ - public static void addNanHalStatusToHistogram(int halStatus, SparseIntArray histogram) { - int protoStatus = convertNanStatusTypeToProtoEnum(halStatus); - int newValue = histogram.get(protoStatus) + 1; - histogram.put(protoStatus, newValue); - } - - /** - * Converts a histogram of proto NanStatusTypeEnum to a raw proto histogram. - */ - @VisibleForTesting - public static WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket[] histogramToProtoArray( - SparseIntArray histogram) { - WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket[] protoArray = - new WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket[histogram.size()]; - - for (int i = 0; i < histogram.size(); ++i) { - protoArray[i] = new WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket(); - protoArray[i].nanStatusType = histogram.keyAt(i); - protoArray[i].count = histogram.valueAt(i); - } - - return protoArray; - } - - /** - * Convert a HAL NanStatusType enum to a Metrics proto enum NanStatusTypeEnum. - */ - public static int convertNanStatusTypeToProtoEnum(int nanStatusType) { - switch (nanStatusType) { - case NanStatusType.SUCCESS: - return WifiMetricsProto.WifiAwareLog.SUCCESS; - case NanStatusType.INTERNAL_FAILURE: - return WifiMetricsProto.WifiAwareLog.INTERNAL_FAILURE; - case NanStatusType.PROTOCOL_FAILURE: - return WifiMetricsProto.WifiAwareLog.PROTOCOL_FAILURE; - case NanStatusType.INVALID_SESSION_ID: - return WifiMetricsProto.WifiAwareLog.INVALID_SESSION_ID; - case NanStatusType.NO_RESOURCES_AVAILABLE: - return WifiMetricsProto.WifiAwareLog.NO_RESOURCES_AVAILABLE; - case NanStatusType.INVALID_ARGS: - return WifiMetricsProto.WifiAwareLog.INVALID_ARGS; - case NanStatusType.INVALID_PEER_ID: - return WifiMetricsProto.WifiAwareLog.INVALID_PEER_ID; - case NanStatusType.INVALID_NDP_ID: - return WifiMetricsProto.WifiAwareLog.INVALID_NDP_ID; - case NanStatusType.NAN_NOT_ALLOWED: - return WifiMetricsProto.WifiAwareLog.NAN_NOT_ALLOWED; - case NanStatusType.NO_OTA_ACK: - return WifiMetricsProto.WifiAwareLog.NO_OTA_ACK; - case NanStatusType.ALREADY_ENABLED: - return WifiMetricsProto.WifiAwareLog.ALREADY_ENABLED; - case NanStatusType.FOLLOWUP_TX_QUEUE_FULL: - return WifiMetricsProto.WifiAwareLog.FOLLOWUP_TX_QUEUE_FULL; - case NanStatusType.UNSUPPORTED_CONCURRENCY_NAN_DISABLED: - return WifiMetricsProto.WifiAwareLog.UNSUPPORTED_CONCURRENCY_NAN_DISABLED; - default: - Log.e(TAG, "Unrecognized NanStatusType: " + nanStatusType); - return WifiMetricsProto.WifiAwareLog.UNKNOWN_HAL_STATUS; - } - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java deleted file mode 100644 index 38400223a..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java +++ /dev/null @@ -1,1306 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.NanBandIndex; -import android.hardware.wifi.V1_0.NanBandSpecificConfig; -import android.hardware.wifi.V1_0.NanCipherSuiteType; -import android.hardware.wifi.V1_0.NanConfigRequest; -import android.hardware.wifi.V1_0.NanDataPathSecurityType; -import android.hardware.wifi.V1_0.NanEnableRequest; -import android.hardware.wifi.V1_0.NanInitiateDataPathRequest; -import android.hardware.wifi.V1_0.NanMatchAlg; -import android.hardware.wifi.V1_0.NanPublishRequest; -import android.hardware.wifi.V1_0.NanRangingIndication; -import android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest; -import android.hardware.wifi.V1_0.NanSubscribeRequest; -import android.hardware.wifi.V1_0.NanTransmitFollowupRequest; -import android.hardware.wifi.V1_0.NanTxType; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_2.NanConfigRequestSupplemental; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.net.wifi.util.HexEncoding; -import android.os.BasicShellCommandHandler; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; -import android.util.SparseIntArray; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -/** - * Translates Wi-Fi Aware requests from the framework to the HAL (HIDL). - * - * Delegates the management of the NAN interface to WifiAwareNativeManager. - */ -public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellCommand { - private static final String TAG = "WifiAwareNativeApi"; - private static final boolean VDBG = false; // STOPSHIP if true - private boolean mDbg = false; - - @VisibleForTesting - static final String SERVICE_NAME_FOR_OOB_DATA_PATH = "Wi-Fi Aware Data Path"; - - private final WifiAwareNativeManager mHal; - private SparseIntArray mTransactionIds; // VDBG only! - - public WifiAwareNativeApi(WifiAwareNativeManager wifiAwareNativeManager) { - mHal = wifiAwareNativeManager; - onReset(); - if (VDBG) { - mTransactionIds = new SparseIntArray(); - } - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(boolean verbose) { - mDbg = verbose | VDBG; - } - - - private void recordTransactionId(int transactionId) { - if (!VDBG) return; - - if (transactionId == 0) { - return; // tid == 0 is used as a dummy transaction ID in several commands - acceptable - } - - int count = mTransactionIds.get(transactionId); - if (count != 0) { - Log.wtf(TAG, "Repeated transaction ID == " + transactionId); - } - mTransactionIds.append(transactionId, count + 1); - } - - /** - * (HIDL) Cast the input to a 1.2 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { - return android.hardware.wifi.V1_2.IWifiNanIface.castFrom(iface); - } - - /** - * (HIDL) Cast the input to a 1.4 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_4.IWifiNanIface mockableCastTo_1_4(IWifiNanIface iface) { - return android.hardware.wifi.V1_4.IWifiNanIface.castFrom(iface); - } - - /* - * Parameters settable through the shell command. - * see wifi/1.0/types.hal NanBandSpecificConfig.discoveryWindowIntervalVal and - * wifi/1.2/types.hal NanConfigRequestSupplemental_1_2 for description - */ - /* package */ static final String POWER_PARAM_DEFAULT_KEY = "default"; - /* package */ static final String POWER_PARAM_INACTIVE_KEY = "inactive"; - /* package */ static final String POWER_PARAM_IDLE_KEY = "idle"; - - /* package */ static final String PARAM_DW_24GHZ = "dw_24ghz"; - private static final int PARAM_DW_24GHZ_DEFAULT = 1; // 1 -> DW=1, latency=512ms - private static final int PARAM_DW_24GHZ_INACTIVE = 4; // 4 -> DW=8, latency=4s - private static final int PARAM_DW_24GHZ_IDLE = 4; // == inactive - - /* package */ static final String PARAM_DW_5GHZ = "dw_5ghz"; - private static final int PARAM_DW_5GHZ_DEFAULT = 1; // 1 -> DW=1, latency=512ms - private static final int PARAM_DW_5GHZ_INACTIVE = 0; // 0 = disabled - private static final int PARAM_DW_5GHZ_IDLE = 0; // == inactive - - // TODO: - /* package */ static final String PARAM_DW_6GHZ = "dw_6ghz"; - private static final int PARAM_DW_6GHZ_DEFAULT = 1; // 1 -> DW=1, latency=512ms - private static final int PARAM_DW_6GHZ_INACTIVE = 0; // 0 = disabled - private static final int PARAM_DW_6GHZ_IDLE = 0; // == inactive - - /* package */ static final String PARAM_DISCOVERY_BEACON_INTERVAL_MS = - "disc_beacon_interval_ms"; - private static final int PARAM_DISCOVERY_BEACON_INTERVAL_MS_DEFAULT = 0; // Firmware defaults - private static final int PARAM_DISCOVERY_BEACON_INTERVAL_MS_INACTIVE = 0; // Firmware defaults - private static final int PARAM_DISCOVERY_BEACON_INTERVAL_MS_IDLE = 0; // Firmware defaults - - /* package */ static final String PARAM_NUM_SS_IN_DISCOVERY = "num_ss_in_discovery"; - private static final int PARAM_NUM_SS_IN_DISCOVERY_DEFAULT = 0; // Firmware defaults - private static final int PARAM_NUM_SS_IN_DISCOVERY_INACTIVE = 0; // Firmware defaults - private static final int PARAM_NUM_SS_IN_DISCOVERY_IDLE = 0; // Firmware defaults - - /* package */ static final String PARAM_ENABLE_DW_EARLY_TERM = "enable_dw_early_term"; - private static final int PARAM_ENABLE_DW_EARLY_TERM_DEFAULT = 0; // boolean: 0 = false - private static final int PARAM_ENABLE_DW_EARLY_TERM_INACTIVE = 0; // boolean: 0 = false - private static final int PARAM_ENABLE_DW_EARLY_TERM_IDLE = 0; // boolean: 0 = false - - /* package */ static final String PARAM_MAC_RANDOM_INTERVAL_SEC = "mac_random_interval_sec"; - private static final int PARAM_MAC_RANDOM_INTERVAL_SEC_DEFAULT = 1800; // 30 minutes - - private Map<String, Map<String, Integer>> mSettablePowerParameters = new HashMap<>(); - private Map<String, Integer> mSettableParameters = new HashMap<>(); - - /** - * Interpreter of adb shell command 'adb shell wifiaware native_api ...'. - * - * @return -1 if parameter not recognized or invalid value, 0 otherwise. - */ - @Override - public int onCommand(BasicShellCommandHandler parentShell) { - final PrintWriter pw = parentShell.getErrPrintWriter(); - - String subCmd = parentShell.getNextArgRequired(); - if (VDBG) Log.v(TAG, "onCommand: subCmd='" + subCmd + "'"); - switch (subCmd) { - case "set": { - String name = parentShell.getNextArgRequired(); - if (VDBG) Log.v(TAG, "onCommand: name='" + name + "'"); - if (!mSettableParameters.containsKey(name)) { - pw.println("Unknown parameter name -- '" + name + "'"); - return -1; - } - - String valueStr = parentShell.getNextArgRequired(); - if (VDBG) Log.v(TAG, "onCommand: valueStr='" + valueStr + "'"); - int value; - try { - value = Integer.valueOf(valueStr); - } catch (NumberFormatException e) { - pw.println("Can't convert value to integer -- '" + valueStr + "'"); - return -1; - } - mSettableParameters.put(name, value); - return 0; - } - case "set-power": { - String mode = parentShell.getNextArgRequired(); - String name = parentShell.getNextArgRequired(); - String valueStr = parentShell.getNextArgRequired(); - - if (VDBG) { - Log.v(TAG, "onCommand: mode='" + mode + "', name='" + name + "'" + ", value='" - + valueStr + "'"); - } - - if (!mSettablePowerParameters.containsKey(mode)) { - pw.println("Unknown mode name -- '" + mode + "'"); - return -1; - } - if (!mSettablePowerParameters.get(mode).containsKey(name)) { - pw.println("Unknown parameter name '" + name + "' in mode '" + mode + "'"); - return -1; - } - - int value; - try { - value = Integer.valueOf(valueStr); - } catch (NumberFormatException e) { - pw.println("Can't convert value to integer -- '" + valueStr + "'"); - return -1; - } - mSettablePowerParameters.get(mode).put(name, value); - return 0; - } - case "get": { - String name = parentShell.getNextArgRequired(); - if (VDBG) Log.v(TAG, "onCommand: name='" + name + "'"); - if (!mSettableParameters.containsKey(name)) { - pw.println("Unknown parameter name -- '" + name + "'"); - return -1; - } - - parentShell.getOutPrintWriter().println((int) mSettableParameters.get(name)); - return 0; - } - case "get-power": { - String mode = parentShell.getNextArgRequired(); - String name = parentShell.getNextArgRequired(); - if (VDBG) Log.v(TAG, "onCommand: mode='" + mode + "', name='" + name + "'"); - if (!mSettablePowerParameters.containsKey(mode)) { - pw.println("Unknown mode -- '" + mode + "'"); - return -1; - } - if (!mSettablePowerParameters.get(mode).containsKey(name)) { - pw.println("Unknown parameter name -- '" + name + "' in mode '" + mode + "'"); - return -1; - } - - parentShell.getOutPrintWriter().println( - (int) mSettablePowerParameters.get(mode).get(name)); - return 0; - } - default: - pw.println("Unknown 'wifiaware native_api <cmd>'"); - } - - return -1; - } - - @Override - public void onReset() { - Map<String, Integer> defaultMap = new HashMap<>(); - defaultMap.put(PARAM_DW_24GHZ, PARAM_DW_24GHZ_DEFAULT); - defaultMap.put(PARAM_DW_5GHZ, PARAM_DW_5GHZ_DEFAULT); - defaultMap.put(PARAM_DW_6GHZ, PARAM_DW_6GHZ_DEFAULT); - defaultMap.put(PARAM_DISCOVERY_BEACON_INTERVAL_MS, - PARAM_DISCOVERY_BEACON_INTERVAL_MS_DEFAULT); - defaultMap.put(PARAM_NUM_SS_IN_DISCOVERY, PARAM_NUM_SS_IN_DISCOVERY_DEFAULT); - defaultMap.put(PARAM_ENABLE_DW_EARLY_TERM, PARAM_ENABLE_DW_EARLY_TERM_DEFAULT); - - Map<String, Integer> inactiveMap = new HashMap<>(); - inactiveMap.put(PARAM_DW_24GHZ, PARAM_DW_24GHZ_INACTIVE); - inactiveMap.put(PARAM_DW_5GHZ, PARAM_DW_5GHZ_INACTIVE); - inactiveMap.put(PARAM_DW_6GHZ, PARAM_DW_6GHZ_INACTIVE); - inactiveMap.put(PARAM_DISCOVERY_BEACON_INTERVAL_MS, - PARAM_DISCOVERY_BEACON_INTERVAL_MS_INACTIVE); - inactiveMap.put(PARAM_NUM_SS_IN_DISCOVERY, PARAM_NUM_SS_IN_DISCOVERY_INACTIVE); - inactiveMap.put(PARAM_ENABLE_DW_EARLY_TERM, PARAM_ENABLE_DW_EARLY_TERM_INACTIVE); - - Map<String, Integer> idleMap = new HashMap<>(); - idleMap.put(PARAM_DW_24GHZ, PARAM_DW_24GHZ_IDLE); - idleMap.put(PARAM_DW_5GHZ, PARAM_DW_5GHZ_IDLE); - idleMap.put(PARAM_DW_6GHZ, PARAM_DW_6GHZ_IDLE); - idleMap.put(PARAM_DISCOVERY_BEACON_INTERVAL_MS, - PARAM_DISCOVERY_BEACON_INTERVAL_MS_IDLE); - idleMap.put(PARAM_NUM_SS_IN_DISCOVERY, PARAM_NUM_SS_IN_DISCOVERY_IDLE); - idleMap.put(PARAM_ENABLE_DW_EARLY_TERM, PARAM_ENABLE_DW_EARLY_TERM_IDLE); - - mSettablePowerParameters.put(POWER_PARAM_DEFAULT_KEY, defaultMap); - mSettablePowerParameters.put(POWER_PARAM_INACTIVE_KEY, inactiveMap); - mSettablePowerParameters.put(POWER_PARAM_IDLE_KEY, idleMap); - - mSettableParameters.put(PARAM_MAC_RANDOM_INTERVAL_SEC, - PARAM_MAC_RANDOM_INTERVAL_SEC_DEFAULT); - } - - @Override - public void onHelp(String command, BasicShellCommandHandler parentShell) { - final PrintWriter pw = parentShell.getOutPrintWriter(); - - pw.println(" " + command); - pw.println(" set <name> <value>: sets named parameter to value. Names: " - + mSettableParameters.keySet()); - pw.println(" set-power <mode> <name> <value>: sets named power parameter to value." - + " Modes: " + mSettablePowerParameters.keySet() - + ", Names: " + mSettablePowerParameters.get(POWER_PARAM_DEFAULT_KEY).keySet()); - pw.println(" get <name>: gets named parameter value. Names: " - + mSettableParameters.keySet()); - pw.println(" get-power <mode> <name>: gets named parameter value." - + " Modes: " + mSettablePowerParameters.keySet() - + ", Names: " + mSettablePowerParameters.get(POWER_PARAM_DEFAULT_KEY).keySet()); - } - - /** - * Query the firmware's capabilities. - * - * @param transactionId Transaction ID for the transaction - used in the async callback to - * match with the original request. - */ - public boolean getCapabilities(short transactionId) { - if (mDbg) Log.v(TAG, "getCapabilities: transactionId=" + transactionId); - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "getCapabilities: null interface"); - return false; - } - - try { - WifiStatus status = iface.getCapabilitiesRequest(transactionId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "getCapabilities: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "getCapabilities: exception: " + e); - return false; - } - } - - /** - * Enable and configure Aware. - * - * @param transactionId Transaction ID for the transaction - used in the - * async callback to match with the original request. - * @param configRequest Requested Aware configuration. - * @param notifyIdentityChange Indicates whether or not to get address change callbacks. - * @param initialConfiguration Specifies whether initial configuration - * (true) or an update (false) to the configuration. - * @param isInteractive PowerManager.isInteractive - * @param isIdle PowerManager.isIdle - * @param rangingEnabled Indicates whether or not enable ranging. - */ - public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest, - boolean notifyIdentityChange, boolean initialConfiguration, boolean isInteractive, - boolean isIdle, boolean rangingEnabled) { - if (mDbg) { - Log.v(TAG, "enableAndConfigure: transactionId=" + transactionId + ", configRequest=" - + configRequest + ", notifyIdentityChange=" + notifyIdentityChange - + ", initialConfiguration=" + initialConfiguration - + ", isInteractive=" + isInteractive + ", isIdle=" + isIdle); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "enableAndConfigure: null interface"); - return false; - } - android.hardware.wifi.V1_2.IWifiNanIface iface12 = mockableCastTo_1_2(iface); - android.hardware.wifi.V1_4.IWifiNanIface iface14 = mockableCastTo_1_4(iface); - NanConfigRequestSupplemental configSupplemental12 = new NanConfigRequestSupplemental(); - if (iface12 != null || iface14 != null) { - configSupplemental12.discoveryBeaconIntervalMs = 0; - configSupplemental12.numberOfSpatialStreamsInDiscovery = 0; - configSupplemental12.enableDiscoveryWindowEarlyTermination = false; - configSupplemental12.enableRanging = rangingEnabled; - } - - NanBandSpecificConfig config24 = new NanBandSpecificConfig(); - config24.rssiClose = 60; - config24.rssiMiddle = 70; - config24.rssiCloseProximity = 60; - config24.dwellTimeMs = (byte) 200; - config24.scanPeriodSec = 20; - if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ] - == ConfigRequest.DW_INTERVAL_NOT_INIT) { - config24.validDiscoveryWindowIntervalVal = false; - } else { - config24.validDiscoveryWindowIntervalVal = true; - config24.discoveryWindowIntervalVal = - (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest - .NAN_BAND_24GHZ]; - } - - NanBandSpecificConfig config5 = new NanBandSpecificConfig(); - config5.rssiClose = 60; - config5.rssiMiddle = 75; - config5.rssiCloseProximity = 60; - config5.dwellTimeMs = (byte) 200; - config5.scanPeriodSec = 20; - if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ] - == ConfigRequest.DW_INTERVAL_NOT_INIT) { - config5.validDiscoveryWindowIntervalVal = false; - } else { - config5.validDiscoveryWindowIntervalVal = true; - config5.discoveryWindowIntervalVal = - (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest - .NAN_BAND_5GHZ]; - } - - // TODO: b/145609058 - // Need to review values for this config, currently it is a copy from config5 - NanBandSpecificConfig config6 = new NanBandSpecificConfig(); - config6.rssiClose = 60; - config6.rssiMiddle = 75; - config6.rssiCloseProximity = 60; - config6.dwellTimeMs = (byte) 200; - config6.scanPeriodSec = 20; - if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_6GHZ] - == ConfigRequest.DW_INTERVAL_NOT_INIT) { - config6.validDiscoveryWindowIntervalVal = false; - } else { - config6.validDiscoveryWindowIntervalVal = true; - config6.discoveryWindowIntervalVal = - (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest - .NAN_BAND_6GHZ]; - } - - try { - WifiStatus status; - if (initialConfiguration) { - if (iface14 != null) { - // translate framework to HIDL configuration (V_1.4) - android.hardware.wifi.V1_4.NanEnableRequest req = - new android.hardware.wifi.V1_4.NanEnableRequest(); - - req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true; - req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand; - req.operateInBand[android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = - configRequest.mSupport6gBand; - req.hopCountMax = 2; - req.configParams.masterPref = (byte) configRequest.mMasterPreference; - req.configParams.disableDiscoveryAddressChangeIndication = - !notifyIdentityChange; - req.configParams.disableStartedClusterIndication = !notifyIdentityChange; - req.configParams.disableJoinedClusterIndication = !notifyIdentityChange; - req.configParams.includePublishServiceIdsInBeacon = true; - req.configParams.numberOfPublishServiceIdsInBeacon = 0; - req.configParams.includeSubscribeServiceIdsInBeacon = true; - req.configParams.numberOfSubscribeServiceIdsInBeacon = 0; - req.configParams.rssiWindowSize = 8; - req.configParams.macAddressRandomizationIntervalSec = mSettableParameters.get( - PARAM_MAC_RANDOM_INTERVAL_SEC); - - req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; - req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; - req.configParams.bandSpecificConfig[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = config6; - - req.debugConfigs.validClusterIdVals = true; - req.debugConfigs.clusterIdTopRangeVal = (short) configRequest.mClusterHigh; - req.debugConfigs.clusterIdBottomRangeVal = (short) configRequest.mClusterLow; - req.debugConfigs.validIntfAddrVal = false; - req.debugConfigs.validOuiVal = false; - req.debugConfigs.ouiVal = 0; - req.debugConfigs.validRandomFactorForceVal = false; - req.debugConfigs.randomFactorForceVal = 0; - req.debugConfigs.validHopCountForceVal = false; - req.debugConfigs.hopCountForceVal = 0; - req.debugConfigs.validDiscoveryChannelVal = false; - req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0; - req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0; - req.debugConfigs.discoveryChannelMhzVal[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = 0; - req.debugConfigs.validUseBeaconsInBandVal = false; - req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; - req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; - req.debugConfigs.useBeaconsInBandVal[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = true; - req.debugConfigs.validUseSdfInBandVal = false; - req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; - req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; - req.debugConfigs.useSdfInBandVal[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = true; - - updateConfigForPowerSettings14(req.configParams, configSupplemental12, - isInteractive, isIdle); - - status = iface14.enableRequest_1_4(transactionId, req, configSupplemental12); - } else { - // translate framework to HIDL configuration (before V_1.4) - NanEnableRequest req = new NanEnableRequest(); - - req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true; - req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand; - req.hopCountMax = 2; - req.configParams.masterPref = (byte) configRequest.mMasterPreference; - req.configParams.disableDiscoveryAddressChangeIndication = - !notifyIdentityChange; - req.configParams.disableStartedClusterIndication = !notifyIdentityChange; - req.configParams.disableJoinedClusterIndication = !notifyIdentityChange; - req.configParams.includePublishServiceIdsInBeacon = true; - req.configParams.numberOfPublishServiceIdsInBeacon = 0; - req.configParams.includeSubscribeServiceIdsInBeacon = true; - req.configParams.numberOfSubscribeServiceIdsInBeacon = 0; - req.configParams.rssiWindowSize = 8; - req.configParams.macAddressRandomizationIntervalSec = mSettableParameters.get( - PARAM_MAC_RANDOM_INTERVAL_SEC); - - req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; - req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; - - req.debugConfigs.validClusterIdVals = true; - req.debugConfigs.clusterIdTopRangeVal = (short) configRequest.mClusterHigh; - req.debugConfigs.clusterIdBottomRangeVal = (short) configRequest.mClusterLow; - req.debugConfigs.validIntfAddrVal = false; - req.debugConfigs.validOuiVal = false; - req.debugConfigs.ouiVal = 0; - req.debugConfigs.validRandomFactorForceVal = false; - req.debugConfigs.randomFactorForceVal = 0; - req.debugConfigs.validHopCountForceVal = false; - req.debugConfigs.hopCountForceVal = 0; - req.debugConfigs.validDiscoveryChannelVal = false; - req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0; - req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0; - req.debugConfigs.validUseBeaconsInBandVal = false; - req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; - req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; - req.debugConfigs.validUseSdfInBandVal = false; - req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; - req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; - - updateConfigForPowerSettings(req.configParams, configSupplemental12, - isInteractive, isIdle); - - if (iface12 != null) { - status = iface12.enableRequest_1_2(transactionId, req, - configSupplemental12); - } else { - status = iface.enableRequest(transactionId, req); - } - } - } else { - if (iface14 != null) { - android.hardware.wifi.V1_4.NanConfigRequest req = - new android.hardware.wifi.V1_4.NanConfigRequest(); - req.masterPref = (byte) configRequest.mMasterPreference; - req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; - req.disableStartedClusterIndication = !notifyIdentityChange; - req.disableJoinedClusterIndication = !notifyIdentityChange; - req.includePublishServiceIdsInBeacon = true; - req.numberOfPublishServiceIdsInBeacon = 0; - req.includeSubscribeServiceIdsInBeacon = true; - req.numberOfSubscribeServiceIdsInBeacon = 0; - req.rssiWindowSize = 8; - req.macAddressRandomizationIntervalSec = mSettableParameters.get( - PARAM_MAC_RANDOM_INTERVAL_SEC); - - req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; - req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; - req.bandSpecificConfig[android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = - config6; - - updateConfigForPowerSettings14(req, configSupplemental12, isInteractive, - isIdle); - - status = iface14.configRequest_1_4(transactionId, req, configSupplemental12); - } else { - NanConfigRequest req = new NanConfigRequest(); - req.masterPref = (byte) configRequest.mMasterPreference; - req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; - req.disableStartedClusterIndication = !notifyIdentityChange; - req.disableJoinedClusterIndication = !notifyIdentityChange; - req.includePublishServiceIdsInBeacon = true; - req.numberOfPublishServiceIdsInBeacon = 0; - req.includeSubscribeServiceIdsInBeacon = true; - req.numberOfSubscribeServiceIdsInBeacon = 0; - req.rssiWindowSize = 8; - req.macAddressRandomizationIntervalSec = mSettableParameters.get( - PARAM_MAC_RANDOM_INTERVAL_SEC); - - req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; - req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; - - updateConfigForPowerSettings(req, configSupplemental12, isInteractive, isIdle); - - if (iface12 != null) { - status = iface12.configRequest_1_2(transactionId, req, - configSupplemental12); - } else { - status = iface.configRequest(transactionId, req); - } - } - } - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "enableAndConfigure: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "enableAndConfigure: exception: " + e); - return false; - } - } - - /** - * Disable Aware. - * - * @param transactionId transactionId Transaction ID for the transaction - - * used in the async callback to match with the original request. - */ - public boolean disable(short transactionId) { - if (mDbg) Log.d(TAG, "disable"); - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "disable: null interface"); - return false; - } - - try { - WifiStatus status = iface.disableRequest(transactionId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "disable: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "disable: exception: " + e); - return false; - } - } - - /** - * Start or modify a service publish session. - * - * @param transactionId transactionId Transaction ID for the transaction - - * used in the async callback to match with the original request. - * @param publishId ID of the requested session - 0 to request a new publish - * session. - * @param publishConfig Configuration of the discovery session. - */ - public boolean publish(short transactionId, byte publishId, PublishConfig publishConfig) { - if (mDbg) { - Log.d(TAG, "publish: transactionId=" + transactionId + ", publishId=" + publishId - + ", config=" + publishConfig); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "publish: null interface"); - return false; - } - - NanPublishRequest req = new NanPublishRequest(); - req.baseConfigs.sessionId = publishId; - req.baseConfigs.ttlSec = (short) publishConfig.mTtlSec; - req.baseConfigs.discoveryWindowPeriod = 1; - req.baseConfigs.discoveryCount = 0; - convertNativeByteArrayToArrayList(publishConfig.mServiceName, req.baseConfigs.serviceName); - req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_NEVER; - convertNativeByteArrayToArrayList(publishConfig.mServiceSpecificInfo, - req.baseConfigs.serviceSpecificInfo); - convertNativeByteArrayToArrayList(publishConfig.mMatchFilter, - publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED - ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); - req.baseConfigs.useRssiThreshold = false; - req.baseConfigs.disableDiscoveryTerminationIndication = - !publishConfig.mEnableTerminateNotification; - req.baseConfigs.disableMatchExpirationIndication = true; - req.baseConfigs.disableFollowupReceivedIndication = false; - - req.autoAcceptDataPathRequests = false; - - req.baseConfigs.rangingRequired = publishConfig.mEnableRanging; - - // TODO: configure security - req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; - - req.publishType = publishConfig.mPublishType; - req.txType = NanTxType.BROADCAST; - - try { - WifiStatus status = iface.startPublishRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "publish: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "publish: exception: " + e); - return false; - } - } - - /** - * Start or modify a service subscription session. - * - * @param transactionId transactionId Transaction ID for the transaction - - * used in the async callback to match with the original request. - * @param subscribeId ID of the requested session - 0 to request a new - * subscribe session. - * @param subscribeConfig Configuration of the discovery session. - */ - public boolean subscribe(short transactionId, byte subscribeId, - SubscribeConfig subscribeConfig) { - if (mDbg) { - Log.d(TAG, "subscribe: transactionId=" + transactionId + ", subscribeId=" + subscribeId - + ", config=" + subscribeConfig); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "subscribe: null interface"); - return false; - } - - NanSubscribeRequest req = new NanSubscribeRequest(); - req.baseConfigs.sessionId = subscribeId; - req.baseConfigs.ttlSec = (short) subscribeConfig.mTtlSec; - req.baseConfigs.discoveryWindowPeriod = 1; - req.baseConfigs.discoveryCount = 0; - convertNativeByteArrayToArrayList(subscribeConfig.mServiceName, - req.baseConfigs.serviceName); - req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_ONCE; - convertNativeByteArrayToArrayList(subscribeConfig.mServiceSpecificInfo, - req.baseConfigs.serviceSpecificInfo); - convertNativeByteArrayToArrayList(subscribeConfig.mMatchFilter, - subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE - ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); - req.baseConfigs.useRssiThreshold = false; - req.baseConfigs.disableDiscoveryTerminationIndication = - !subscribeConfig.mEnableTerminateNotification; - req.baseConfigs.disableMatchExpirationIndication = true; - req.baseConfigs.disableFollowupReceivedIndication = false; - - req.baseConfigs.rangingRequired = - subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet; - req.baseConfigs.configRangingIndications = 0; - // TODO: b/69428593 remove correction factors once HAL converted from CM to MM - if (subscribeConfig.mMinDistanceMmSet) { - req.baseConfigs.distanceEgressCm = (short) Math.min( - subscribeConfig.mMinDistanceMm / 10, Short.MAX_VALUE); - req.baseConfigs.configRangingIndications |= NanRangingIndication.EGRESS_MET_MASK; - } - if (subscribeConfig.mMaxDistanceMmSet) { - req.baseConfigs.distanceIngressCm = (short) Math.min( - subscribeConfig.mMaxDistanceMm / 10, Short.MAX_VALUE); - req.baseConfigs.configRangingIndications |= NanRangingIndication.INGRESS_MET_MASK; - } - - // TODO: configure security - req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; - - req.subscribeType = subscribeConfig.mSubscribeType; - - try { - WifiStatus status = iface.startSubscribeRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "subscribe: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "subscribe: exception: " + e); - return false; - } - } - - /** - * Send a message through an existing discovery session. - * - * @param transactionId transactionId Transaction ID for the transaction - - * used in the async callback to match with the original request. - * @param pubSubId ID of the existing publish/subscribe session. - * @param requestorInstanceId ID of the peer to communicate with - obtained - * through a previous discovery (match) operation with that peer. - * @param dest MAC address of the peer to communicate with - obtained - * together with requestorInstanceId. - * @param message Message. - * @param messageId Arbitary integer from host (not sent to HAL - useful for - * testing/debugging at this level) - */ - public boolean sendMessage(short transactionId, byte pubSubId, int requestorInstanceId, - byte[] dest, byte[] message, int messageId) { - if (mDbg) { - Log.d(TAG, - "sendMessage: transactionId=" + transactionId + ", pubSubId=" + pubSubId - + ", requestorInstanceId=" + requestorInstanceId + ", dest=" - + String.valueOf(HexEncoding.encode(dest)) + ", messageId=" + messageId - + ", message=" + (message == null ? "<null>" - : HexEncoding.encode(message)) + ", message.length=" + (message == null - ? 0 : message.length)); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "sendMessage: null interface"); - return false; - } - - NanTransmitFollowupRequest req = new NanTransmitFollowupRequest(); - req.discoverySessionId = pubSubId; - req.peerId = requestorInstanceId; - copyArray(dest, req.addr); - req.isHighPriority = false; - req.shouldUseDiscoveryWindow = true; - convertNativeByteArrayToArrayList(message, req.serviceSpecificInfo); - req.disableFollowupResultIndication = false; - - try { - WifiStatus status = iface.transmitFollowupRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "sendMessage: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "sendMessage: exception: " + e); - return false; - } - } - - /** - * Terminate a publish discovery session. - * - * @param transactionId transactionId Transaction ID for the transaction - - * used in the async callback to match with the original request. - * @param pubSubId ID of the publish/subscribe session - obtained when - * creating a session. - */ - public boolean stopPublish(short transactionId, byte pubSubId) { - if (mDbg) { - Log.d(TAG, "stopPublish: transactionId=" + transactionId + ", pubSubId=" + pubSubId); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "stopPublish: null interface"); - return false; - } - - try { - WifiStatus status = iface.stopPublishRequest(transactionId, pubSubId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "stopPublish: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "stopPublish: exception: " + e); - return false; - } - } - - /** - * Terminate a subscribe discovery session. - * - * @param transactionId transactionId Transaction ID for the transaction - - * used in the async callback to match with the original request. - * @param pubSubId ID of the publish/subscribe session - obtained when - * creating a session. - */ - public boolean stopSubscribe(short transactionId, byte pubSubId) { - if (mDbg) { - Log.d(TAG, "stopSubscribe: transactionId=" + transactionId + ", pubSubId=" + pubSubId); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "stopSubscribe: null interface"); - return false; - } - - try { - WifiStatus status = iface.stopSubscribeRequest(transactionId, pubSubId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "stopSubscribe: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "stopSubscribe: exception: " + e); - return false; - } - } - - /** - * Create a Aware network interface. This only creates the Linux interface - it doesn't actually - * create the data connection. - * - * @param transactionId Transaction ID for the transaction - used in the async callback to - * match with the original request. - * @param interfaceName The name of the interface, e.g. "aware0". - */ - public boolean createAwareNetworkInterface(short transactionId, String interfaceName) { - if (mDbg) { - Log.v(TAG, "createAwareNetworkInterface: transactionId=" + transactionId + ", " - + "interfaceName=" + interfaceName); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "createAwareNetworkInterface: null interface"); - return false; - } - - try { - WifiStatus status = iface.createDataInterfaceRequest(transactionId, interfaceName); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "createAwareNetworkInterface: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "createAwareNetworkInterface: exception: " + e); - return false; - } - } - - /** - * Deletes a Aware network interface. The data connection can (should?) be torn down previously. - * - * @param transactionId Transaction ID for the transaction - used in the async callback to - * match with the original request. - * @param interfaceName The name of the interface, e.g. "aware0". - */ - public boolean deleteAwareNetworkInterface(short transactionId, String interfaceName) { - if (mDbg) { - Log.v(TAG, "deleteAwareNetworkInterface: transactionId=" + transactionId + ", " - + "interfaceName=" + interfaceName); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "deleteAwareNetworkInterface: null interface"); - return false; - } - - try { - WifiStatus status = iface.deleteDataInterfaceRequest(transactionId, interfaceName); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "deleteAwareNetworkInterface: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "deleteAwareNetworkInterface: exception: " + e); - return false; - } - } - - /** - * Initiates setting up a data-path between device and peer. Security is provided by either - * PMK or Passphrase (not both) - if both are null then an open (unencrypted) link is set up. - * - * @param transactionId Transaction ID for the transaction - used in the async callback to - * match with the original request. - * @param peerId ID of the peer ID to associate the data path with. A value of 0 - * indicates that not associated with an existing session. - * @param channelRequestType Indicates whether the specified channel is available, if available - * requested or forced (resulting in failure if cannot be - * accommodated). - * @param channel The channel on which to set up the data-path. - * @param peer The MAC address of the peer to create a connection with. - * @param interfaceName The interface on which to create the data connection. - * @param pmk Pairwise master key (PMK - see IEEE 802.11i) for the data-path. - * @param passphrase Passphrase for the data-path. - * @param isOutOfBand Is the data-path out-of-band (i.e. without a corresponding Aware discovery - * session). - * @param appInfo Arbitrary binary blob transmitted to the peer. - * @param capabilities The capabilities of the firmware. - */ - public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType, - int channel, byte[] peer, String interfaceName, byte[] pmk, String passphrase, - boolean isOutOfBand, byte[] appInfo, Capabilities capabilities) { - if (mDbg) { - Log.v(TAG, "initiateDataPath: transactionId=" + transactionId + ", peerId=" + peerId - + ", channelRequestType=" + channelRequestType + ", channel=" + channel - + ", peer=" + String.valueOf(HexEncoding.encode(peer)) + ", interfaceName=" - + interfaceName + ", pmk=" + ((pmk == null) ? "<null>" : "<*>") - + ", passphrase=" + (TextUtils.isEmpty(passphrase) ? "<empty>" : "<*>") - + ", isOutOfBand=" + isOutOfBand + ", appInfo.length=" - + ((appInfo == null) ? 0 : appInfo.length) + ", capabilities=" + capabilities); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "initiateDataPath: null interface"); - return false; - } - - if (capabilities == null) { - Log.e(TAG, "initiateDataPath: null capabilities"); - return false; - } - - NanInitiateDataPathRequest req = new NanInitiateDataPathRequest(); - req.peerId = peerId; - copyArray(peer, req.peerDiscMacAddr); - req.channelRequestType = channelRequestType; - req.channel = channel; - req.ifaceName = interfaceName; - req.securityConfig.securityType = NanDataPathSecurityType.OPEN; - if (pmk != null && pmk.length != 0) { - req.securityConfig.cipherType = getStrongestCipherSuiteType( - capabilities.supportedCipherSuites); - req.securityConfig.securityType = NanDataPathSecurityType.PMK; - copyArray(pmk, req.securityConfig.pmk); - } - if (passphrase != null && passphrase.length() != 0) { - req.securityConfig.cipherType = getStrongestCipherSuiteType( - capabilities.supportedCipherSuites); - req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; - convertNativeByteArrayToArrayList(passphrase.getBytes(), req.securityConfig.passphrase); - } - - if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { - convertNativeByteArrayToArrayList( - SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(StandardCharsets.UTF_8), - req.serviceNameOutOfBand); - } - convertNativeByteArrayToArrayList(appInfo, req.appInfo); - - try { - WifiStatus status = iface.initiateDataPathRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "initiateDataPath: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "initiateDataPath: exception: " + e); - return false; - } - } - - /** - * Responds to a data request from a peer. Security is provided by either PMK or Passphrase (not - * both) - if both are null then an open (unencrypted) link is set up. - * - * @param transactionId Transaction ID for the transaction - used in the async callback to - * match with the original request. - * @param accept Accept (true) or reject (false) the original call. - * @param ndpId The NDP (Aware data path) ID. Obtained from the request callback. - * @param interfaceName The interface on which the data path will be setup. Obtained from the - * request callback. - * @param pmk Pairwise master key (PMK - see IEEE 802.11i) for the data-path. - * @param passphrase Passphrase for the data-path. - * @param appInfo Arbitrary binary blob transmitted to the peer. - * @param isOutOfBand Is the data-path out-of-band (i.e. without a corresponding Aware discovery - * session). - * @param capabilities The capabilities of the firmware. - */ - public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId, - String interfaceName, byte[] pmk, String passphrase, byte[] appInfo, - boolean isOutOfBand, Capabilities capabilities) { - if (mDbg) { - Log.v(TAG, "respondToDataPathRequest: transactionId=" + transactionId + ", accept=" - + accept + ", int ndpId=" + ndpId + ", interfaceName=" + interfaceName - + ", appInfo.length=" + ((appInfo == null) ? 0 : appInfo.length)); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "respondToDataPathRequest: null interface"); - return false; - } - - if (capabilities == null) { - Log.e(TAG, "initiateDataPath: null capabilities"); - return false; - } - - NanRespondToDataPathIndicationRequest req = new NanRespondToDataPathIndicationRequest(); - req.acceptRequest = accept; - req.ndpInstanceId = ndpId; - req.ifaceName = interfaceName; - req.securityConfig.securityType = NanDataPathSecurityType.OPEN; - if (pmk != null && pmk.length != 0) { - req.securityConfig.cipherType = getStrongestCipherSuiteType( - capabilities.supportedCipherSuites); - req.securityConfig.securityType = NanDataPathSecurityType.PMK; - copyArray(pmk, req.securityConfig.pmk); - } - if (passphrase != null && passphrase.length() != 0) { - req.securityConfig.cipherType = getStrongestCipherSuiteType( - capabilities.supportedCipherSuites); - req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; - convertNativeByteArrayToArrayList(passphrase.getBytes(), req.securityConfig.passphrase); - } - - if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { - convertNativeByteArrayToArrayList( - SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(StandardCharsets.UTF_8), - req.serviceNameOutOfBand); - } - convertNativeByteArrayToArrayList(appInfo, req.appInfo); - - try { - WifiStatus status = iface.respondToDataPathIndicationRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "respondToDataPathRequest: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "respondToDataPathRequest: exception: " + e); - return false; - } - } - - /** - * Terminate an existing data-path (does not delete the interface). - * - * @param transactionId Transaction ID for the transaction - used in the async callback to - * match with the original request. - * @param ndpId The NDP (Aware data path) ID to be terminated. - */ - public boolean endDataPath(short transactionId, int ndpId) { - if (mDbg) { - Log.v(TAG, "endDataPath: transactionId=" + transactionId + ", ndpId=" + ndpId); - } - recordTransactionId(transactionId); - - IWifiNanIface iface = mHal.getWifiNanIface(); - if (iface == null) { - Log.e(TAG, "endDataPath: null interface"); - return false; - } - - try { - WifiStatus status = iface.terminateDataPathRequest(transactionId, ndpId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "endDataPath: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "endDataPath: exception: " + e); - return false; - } - } - - - // utilities - - /** - * Update the NAN configuration to reflect the current power settings (before V1.4) - */ - private void updateConfigForPowerSettings(NanConfigRequest req, - NanConfigRequestSupplemental configSupplemental12, boolean isInteractive, - boolean isIdle) { - String key = POWER_PARAM_DEFAULT_KEY; - if (isIdle) { - key = POWER_PARAM_IDLE_KEY; - } else if (!isInteractive) { - key = POWER_PARAM_INACTIVE_KEY; - } - - updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ], - mSettablePowerParameters.get(key).get(PARAM_DW_5GHZ)); - updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ], - mSettablePowerParameters.get(key).get(PARAM_DW_24GHZ)); - - configSupplemental12.discoveryBeaconIntervalMs = mSettablePowerParameters.get(key).get( - PARAM_DISCOVERY_BEACON_INTERVAL_MS); - configSupplemental12.numberOfSpatialStreamsInDiscovery = mSettablePowerParameters.get( - key).get(PARAM_NUM_SS_IN_DISCOVERY); - configSupplemental12.enableDiscoveryWindowEarlyTermination = mSettablePowerParameters.get( - key).get(PARAM_ENABLE_DW_EARLY_TERM) != 0; - } - - /** - * Update the NAN configuration to reflect the current power settings (V1.4) - */ - private void updateConfigForPowerSettings14(android.hardware.wifi.V1_4.NanConfigRequest req, - NanConfigRequestSupplemental configSupplemental12, boolean isInteractive, - boolean isIdle) { - String key = POWER_PARAM_DEFAULT_KEY; - if (isIdle) { - key = POWER_PARAM_IDLE_KEY; - } else if (!isInteractive) { - key = POWER_PARAM_INACTIVE_KEY; - } - - updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ], - mSettablePowerParameters.get(key).get(PARAM_DW_5GHZ)); - updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ], - mSettablePowerParameters.get(key).get(PARAM_DW_24GHZ)); - updateSingleConfigForPowerSettings(req.bandSpecificConfig[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ], - mSettablePowerParameters.get(key).get(PARAM_DW_6GHZ)); - - configSupplemental12.discoveryBeaconIntervalMs = mSettablePowerParameters.get(key).get( - PARAM_DISCOVERY_BEACON_INTERVAL_MS); - configSupplemental12.numberOfSpatialStreamsInDiscovery = mSettablePowerParameters.get( - key).get(PARAM_NUM_SS_IN_DISCOVERY); - configSupplemental12.enableDiscoveryWindowEarlyTermination = mSettablePowerParameters.get( - key).get(PARAM_ENABLE_DW_EARLY_TERM) != 0; - } - - private void updateSingleConfigForPowerSettings(NanBandSpecificConfig cfg, int override) { - if (override != -1) { - cfg.validDiscoveryWindowIntervalVal = true; - cfg.discoveryWindowIntervalVal = (byte) override; - } - } - - /** - * Returns the strongest supported cipher suite. - * - * Baseline is very simple: 256 > 128 > 0. - */ - private int getStrongestCipherSuiteType(int supportedCipherSuites) { - if ((supportedCipherSuites & NanCipherSuiteType.SHARED_KEY_256_MASK) != 0) { - return NanCipherSuiteType.SHARED_KEY_256_MASK; - } - if ((supportedCipherSuites & NanCipherSuiteType.SHARED_KEY_128_MASK) != 0) { - return NanCipherSuiteType.SHARED_KEY_128_MASK; - } - return NanCipherSuiteType.NONE; - } - - /** - * Converts a byte[] to an ArrayList<Byte>. Fills in the entries of the 'to' array if - * provided (non-null), otherwise creates and returns a new ArrayList<>. - * - * @param from The input byte[] to convert from. - * @param to An optional ArrayList<> to fill in from 'from'. - * - * @return A newly allocated ArrayList<> if 'to' is null, otherwise null. - */ - private ArrayList<Byte> convertNativeByteArrayToArrayList(byte[] from, ArrayList<Byte> to) { - if (from == null) { - from = new byte[0]; - } - - if (to == null) { - to = new ArrayList<>(from.length); - } else { - to.ensureCapacity(from.length); - } - for (int i = 0; i < from.length; ++i) { - to.add(from[i]); - } - return to; - } - - private void copyArray(byte[] from, byte[] to) { - if (from == null || to == null || from.length != to.length) { - Log.e(TAG, "copyArray error: from=" + from + ", to=" + to); - return; - } - for (int i = 0; i < from.length; ++i) { - to[i] = from[i]; - } - } - - private static String statusString(WifiStatus status) { - if (status == null) { - return "status=null"; - } - StringBuilder sb = new StringBuilder(); - sb.append(status.code).append(" (").append(status.description).append(")"); - return sb.toString(); - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("WifiAwareNativeApi:"); - pw.println(" mSettableParameters: " + mSettableParameters); - mHal.dump(fd, pw, args); - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java deleted file mode 100644 index c9616db37..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.aware; - -import android.hardware.wifi.V1_0.NanCapabilities; -import android.hardware.wifi.V1_0.NanClusterEventInd; -import android.hardware.wifi.V1_0.NanClusterEventType; -import android.hardware.wifi.V1_0.NanDataPathConfirmInd; -import android.hardware.wifi.V1_0.NanDataPathRequestInd; -import android.hardware.wifi.V1_0.NanFollowupReceivedInd; -import android.hardware.wifi.V1_0.NanMatchInd; -import android.hardware.wifi.V1_0.NanStatusType; -import android.hardware.wifi.V1_0.WifiNanStatus; -import android.hardware.wifi.V1_2.IWifiNanIfaceEventCallback; -import android.hardware.wifi.V1_2.NanDataPathChannelInfo; -import android.hardware.wifi.V1_2.NanDataPathScheduleUpdateInd; -import android.net.MacAddress; -import android.net.wifi.util.HexEncoding; -import android.os.BasicShellCommandHandler; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Manages the callbacks from Wi-Fi Aware HIDL (HAL). - */ -public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub implements - WifiAwareShellCommand.DelegatedShellCommand { - private static final String TAG = "WifiAwareNativeCallback"; - private boolean mDbg = false; - - /* package */ boolean mIsHal12OrLater = false; - - private final WifiAwareStateManager mWifiAwareStateManager; - - public WifiAwareNativeCallback(WifiAwareStateManager wifiAwareStateManager) { - mWifiAwareStateManager = wifiAwareStateManager; - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(boolean verbose) { - mDbg = verbose; - } - - - /* - * Counts of callbacks from HAL. Retrievable through shell command. - */ - private static final int CB_EV_CLUSTER = 0; - private static final int CB_EV_DISABLED = 1; - private static final int CB_EV_PUBLISH_TERMINATED = 2; - private static final int CB_EV_SUBSCRIBE_TERMINATED = 3; - private static final int CB_EV_MATCH = 4; - private static final int CB_EV_MATCH_EXPIRED = 5; - private static final int CB_EV_FOLLOWUP_RECEIVED = 6; - private static final int CB_EV_TRANSMIT_FOLLOWUP = 7; - private static final int CB_EV_DATA_PATH_REQUEST = 8; - private static final int CB_EV_DATA_PATH_CONFIRM = 9; - private static final int CB_EV_DATA_PATH_TERMINATED = 10; - private static final int CB_EV_DATA_PATH_SCHED_UPDATE = 11; - - private SparseIntArray mCallbackCounter = new SparseIntArray(); - private SparseArray<ArrayList<NanDataPathChannelInfo>> mChannelInfoPerNdp = new SparseArray<>(); - - private void incrementCbCount(int callbackId) { - mCallbackCounter.put(callbackId, mCallbackCounter.get(callbackId) + 1); - } - - /** - * Interpreter of adb shell command 'adb shell cmd wifiaware native_cb ...'. - * - * @return -1 if parameter not recognized or invalid value, 0 otherwise. - */ - @Override - public int onCommand(BasicShellCommandHandler parentShell) { - final PrintWriter pwe = parentShell.getErrPrintWriter(); - final PrintWriter pwo = parentShell.getOutPrintWriter(); - - String subCmd = parentShell.getNextArgRequired(); - switch (subCmd) { - case "get_cb_count": { - String option = parentShell.getNextOption(); - boolean reset = false; - if (option != null) { - if ("--reset".equals(option)) { - reset = true; - } else { - pwe.println("Unknown option to 'get_cb_count'"); - return -1; - } - } - - JSONObject j = new JSONObject(); - try { - for (int i = 0; i < mCallbackCounter.size(); ++i) { - j.put(Integer.toString(mCallbackCounter.keyAt(i)), - mCallbackCounter.valueAt(i)); - } - } catch (JSONException e) { - Log.e(TAG, "onCommand: get_cb_count e=" + e); - } - pwo.println(j.toString()); - if (reset) { - mCallbackCounter.clear(); - } - return 0; - } - case "get_channel_info": { - String option = parentShell.getNextOption(); - if (option != null) { - pwe.println("Unknown option to 'get_channel_info'"); - return -1; - } - String channelInfoString = convertChannelInfoToJsonString(); - pwo.println(channelInfoString); - return 0; - } - default: - pwe.println("Unknown 'wifiaware native_cb <cmd>'"); - } - - return -1; - } - - @Override - public void onReset() { - // NOP (onReset is intended for configuration reset - not data reset) - } - - @Override - public void onHelp(String command, BasicShellCommandHandler parentShell) { - final PrintWriter pw = parentShell.getOutPrintWriter(); - - pw.println(" " + command); - pw.println(" get_cb_count [--reset]: gets the number of callbacks (and optionally reset " - + "count)"); - pw.println(" get_channel_info: prints out existing NDP channel info as a JSON String"); - } - - @Override - public void notifyCapabilitiesResponse(short id, WifiNanStatus status, - NanCapabilities capabilities) { - if (mDbg) { - Log.v(TAG, "notifyCapabilitiesResponse: id=" + id + ", status=" + statusString(status) - + ", capabilities=" + capabilities); - } - - if (status.status == NanStatusType.SUCCESS) { - Capabilities frameworkCapabilities = new Capabilities(); - frameworkCapabilities.maxConcurrentAwareClusters = capabilities.maxConcurrentClusters; - frameworkCapabilities.maxPublishes = capabilities.maxPublishes; - frameworkCapabilities.maxSubscribes = capabilities.maxSubscribes; - frameworkCapabilities.maxServiceNameLen = capabilities.maxServiceNameLen; - frameworkCapabilities.maxMatchFilterLen = capabilities.maxMatchFilterLen; - frameworkCapabilities.maxTotalMatchFilterLen = capabilities.maxTotalMatchFilterLen; - frameworkCapabilities.maxServiceSpecificInfoLen = - capabilities.maxServiceSpecificInfoLen; - frameworkCapabilities.maxExtendedServiceSpecificInfoLen = - capabilities.maxExtendedServiceSpecificInfoLen; - frameworkCapabilities.maxNdiInterfaces = capabilities.maxNdiInterfaces; - frameworkCapabilities.maxNdpSessions = capabilities.maxNdpSessions; - frameworkCapabilities.maxAppInfoLen = capabilities.maxAppInfoLen; - frameworkCapabilities.maxQueuedTransmitMessages = - capabilities.maxQueuedTransmitFollowupMsgs; - frameworkCapabilities.maxSubscribeInterfaceAddresses = - capabilities.maxSubscribeInterfaceAddresses; - frameworkCapabilities.supportedCipherSuites = capabilities.supportedCipherSuites; - - mWifiAwareStateManager.onCapabilitiesUpdateResponse(id, frameworkCapabilities); - } else { - Log.e(TAG, "notifyCapabilitiesResponse: error code=" + status.status + " (" - + status.description + ")"); - } - } - - @Override - public void notifyEnableResponse(short id, WifiNanStatus status) { - if (mDbg) Log.v(TAG, "notifyEnableResponse: id=" + id + ", status=" + statusString(status)); - - if (status.status == NanStatusType.ALREADY_ENABLED) { - Log.wtf(TAG, "notifyEnableResponse: id=" + id + ", already enabled!?"); - } - - if (status.status == NanStatusType.SUCCESS - || status.status == NanStatusType.ALREADY_ENABLED) { - mWifiAwareStateManager.onConfigSuccessResponse(id); - } else { - mWifiAwareStateManager.onConfigFailedResponse(id, status.status); - } - } - - @Override - public void notifyConfigResponse(short id, WifiNanStatus status) { - if (mDbg) Log.v(TAG, "notifyConfigResponse: id=" + id + ", status=" + statusString(status)); - - if (status.status == NanStatusType.SUCCESS) { - mWifiAwareStateManager.onConfigSuccessResponse(id); - } else { - mWifiAwareStateManager.onConfigFailedResponse(id, status.status); - } - } - - @Override - public void notifyDisableResponse(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "notifyDisableResponse: id=" + id + ", status=" + statusString(status)); - } - - if (status.status != NanStatusType.SUCCESS) { - Log.e(TAG, "notifyDisableResponse: failure - code=" + status.status + " (" - + status.description + ")"); - } - mWifiAwareStateManager.onDisableResponse(id, status.status); - } - - @Override - public void notifyStartPublishResponse(short id, WifiNanStatus status, byte publishId) { - if (mDbg) { - Log.v(TAG, "notifyStartPublishResponse: id=" + id + ", status=" + statusString(status) - + ", publishId=" + publishId); - } - - if (status.status == NanStatusType.SUCCESS) { - mWifiAwareStateManager.onSessionConfigSuccessResponse(id, true, publishId); - } else { - mWifiAwareStateManager.onSessionConfigFailResponse(id, true, status.status); - } - } - - @Override - public void notifyStopPublishResponse(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "notifyStopPublishResponse: id=" + id + ", status=" + statusString(status)); - } - - if (status.status == NanStatusType.SUCCESS) { - // NOP - } else { - Log.e(TAG, "notifyStopPublishResponse: failure - code=" + status.status + " (" - + status.description + ")"); - } - } - - @Override - public void notifyStartSubscribeResponse(short id, WifiNanStatus status, byte subscribeId) { - if (mDbg) { - Log.v(TAG, "notifyStartSubscribeResponse: id=" + id + ", status=" + statusString(status) - + ", subscribeId=" + subscribeId); - } - - if (status.status == NanStatusType.SUCCESS) { - mWifiAwareStateManager.onSessionConfigSuccessResponse(id, false, subscribeId); - } else { - mWifiAwareStateManager.onSessionConfigFailResponse(id, false, status.status); - } - } - - @Override - public void notifyStopSubscribeResponse(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "notifyStopSubscribeResponse: id=" + id + ", status=" - + statusString(status)); - } - - if (status.status == NanStatusType.SUCCESS) { - // NOP - } else { - Log.e(TAG, "notifyStopSubscribeResponse: failure - code=" + status.status + " (" - + status.description + ")"); - } - } - - @Override - public void notifyTransmitFollowupResponse(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "notifyTransmitFollowupResponse: id=" + id + ", status=" - + statusString(status)); - } - - if (status.status == NanStatusType.SUCCESS) { - mWifiAwareStateManager.onMessageSendQueuedSuccessResponse(id); - } else { - mWifiAwareStateManager.onMessageSendQueuedFailResponse(id, status.status); - } - } - - @Override - public void notifyCreateDataInterfaceResponse(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "notifyCreateDataInterfaceResponse: id=" + id + ", status=" - + statusString(status)); - } - - mWifiAwareStateManager.onCreateDataPathInterfaceResponse(id, - status.status == NanStatusType.SUCCESS, status.status); - } - - @Override - public void notifyDeleteDataInterfaceResponse(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "notifyDeleteDataInterfaceResponse: id=" + id + ", status=" - + statusString(status)); - } - - mWifiAwareStateManager.onDeleteDataPathInterfaceResponse(id, - status.status == NanStatusType.SUCCESS, status.status); - } - - @Override - public void notifyInitiateDataPathResponse(short id, WifiNanStatus status, - int ndpInstanceId) { - if (mDbg) { - Log.v(TAG, "notifyInitiateDataPathResponse: id=" + id + ", status=" - + statusString(status) + ", ndpInstanceId=" + ndpInstanceId); - } - - if (status.status == NanStatusType.SUCCESS) { - mWifiAwareStateManager.onInitiateDataPathResponseSuccess(id, ndpInstanceId); - } else { - mWifiAwareStateManager.onInitiateDataPathResponseFail(id, status.status); - } - } - - @Override - public void notifyRespondToDataPathIndicationResponse(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "notifyRespondToDataPathIndicationResponse: id=" + id - + ", status=" + statusString(status)); - } - - mWifiAwareStateManager.onRespondToDataPathSetupRequestResponse(id, - status.status == NanStatusType.SUCCESS, status.status); - } - - @Override - public void notifyTerminateDataPathResponse(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "notifyTerminateDataPathResponse: id=" + id + ", status=" - + statusString(status)); - } - - mWifiAwareStateManager.onEndDataPathResponse(id, status.status == NanStatusType.SUCCESS, - status.status); - } - - @Override - public void eventClusterEvent(NanClusterEventInd event) { - if (mDbg) { - Log.v(TAG, "eventClusterEvent: eventType=" + event.eventType + ", addr=" - + String.valueOf(HexEncoding.encode(event.addr))); - } - incrementCbCount(CB_EV_CLUSTER); - - if (event.eventType == NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED) { - mWifiAwareStateManager.onInterfaceAddressChangeNotification(event.addr); - } else if (event.eventType == NanClusterEventType.STARTED_CLUSTER) { - mWifiAwareStateManager.onClusterChangeNotification( - WifiAwareClientState.CLUSTER_CHANGE_EVENT_STARTED, event.addr); - } else if (event.eventType == NanClusterEventType.JOINED_CLUSTER) { - mWifiAwareStateManager.onClusterChangeNotification( - WifiAwareClientState.CLUSTER_CHANGE_EVENT_JOINED, event.addr); - } else { - Log.e(TAG, "eventClusterEvent: invalid eventType=" + event.eventType); - } - } - - @Override - public void eventDisabled(WifiNanStatus status) { - if (mDbg) Log.v(TAG, "eventDisabled: status=" + statusString(status)); - incrementCbCount(CB_EV_DISABLED); - - mWifiAwareStateManager.onAwareDownNotification(status.status); - } - - @Override - public void eventPublishTerminated(byte sessionId, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "eventPublishTerminated: sessionId=" + sessionId + ", status=" - + statusString(status)); - } - incrementCbCount(CB_EV_PUBLISH_TERMINATED); - - mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status.status, true); - } - - @Override - public void eventSubscribeTerminated(byte sessionId, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "eventSubscribeTerminated: sessionId=" + sessionId + ", status=" - + statusString(status)); - } - incrementCbCount(CB_EV_SUBSCRIBE_TERMINATED); - - mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status.status, false); - } - - @Override - public void eventMatch(NanMatchInd event) { - if (mDbg) { - Log.v(TAG, "eventMatch: discoverySessionId=" + event.discoverySessionId + ", peerId=" - + event.peerId + ", addr=" + String.valueOf(HexEncoding.encode(event.addr)) - + ", serviceSpecificInfo=" + Arrays.toString( - convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()=" - + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size()) - + ", matchFilter=" + Arrays.toString( - convertArrayListToNativeByteArray(event.matchFilter)) + ", mf.size()=" + ( - event.matchFilter == null ? 0 : event.matchFilter.size()) - + ", rangingIndicationType=" + event.rangingIndicationType - + ", rangingMeasurementInCm=" + event.rangingMeasurementInCm); - } - incrementCbCount(CB_EV_MATCH); - - // TODO: b/69428593 get rid of conversion once HAL moves from CM to MM - mWifiAwareStateManager.onMatchNotification(event.discoverySessionId, event.peerId, - event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo), - convertArrayListToNativeByteArray(event.matchFilter), event.rangingIndicationType, - event.rangingMeasurementInCm * 10); - } - - @Override - public void eventMatchExpired(byte discoverySessionId, int peerId) { - if (mDbg) { - Log.v(TAG, "eventMatchExpired: discoverySessionId=" + discoverySessionId - + ", peerId=" + peerId); - } - incrementCbCount(CB_EV_MATCH_EXPIRED); - - // NOP - } - - @Override - public void eventFollowupReceived(NanFollowupReceivedInd event) { - if (mDbg) { - Log.v(TAG, "eventFollowupReceived: discoverySessionId=" + event.discoverySessionId - + ", peerId=" + event.peerId + ", addr=" + String.valueOf( - HexEncoding.encode(event.addr)) + ", serviceSpecificInfo=" + Arrays.toString( - convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()=" - + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size())); - } - incrementCbCount(CB_EV_FOLLOWUP_RECEIVED); - - mWifiAwareStateManager.onMessageReceivedNotification(event.discoverySessionId, event.peerId, - event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo)); - } - - @Override - public void eventTransmitFollowup(short id, WifiNanStatus status) { - if (mDbg) { - Log.v(TAG, "eventTransmitFollowup: id=" + id + ", status=" + statusString(status)); - } - incrementCbCount(CB_EV_TRANSMIT_FOLLOWUP); - - if (status.status == NanStatusType.SUCCESS) { - mWifiAwareStateManager.onMessageSendSuccessNotification(id); - } else { - mWifiAwareStateManager.onMessageSendFailNotification(id, status.status); - } - } - - @Override - public void eventDataPathRequest(NanDataPathRequestInd event) { - if (mDbg) { - Log.v(TAG, "eventDataPathRequest: discoverySessionId=" + event.discoverySessionId - + ", peerDiscMacAddr=" + String.valueOf( - HexEncoding.encode(event.peerDiscMacAddr)) + ", ndpInstanceId=" - + event.ndpInstanceId + ", appInfo.size()=" + event.appInfo.size()); - } - incrementCbCount(CB_EV_DATA_PATH_REQUEST); - - mWifiAwareStateManager.onDataPathRequestNotification(event.discoverySessionId, - event.peerDiscMacAddr, event.ndpInstanceId, - convertArrayListToNativeByteArray(event.appInfo)); - } - - @Override - public void eventDataPathConfirm(NanDataPathConfirmInd event) { - if (mDbg) { - Log.v(TAG, "onDataPathConfirm: ndpInstanceId=" + event.ndpInstanceId - + ", peerNdiMacAddr=" + String.valueOf(HexEncoding.encode(event.peerNdiMacAddr)) - + ", dataPathSetupSuccess=" + event.dataPathSetupSuccess + ", reason=" - + event.status.status + ", appInfo.size()=" + event.appInfo.size()); - } - if (mIsHal12OrLater) { - Log.wtf(TAG, "eventDataPathConfirm should not be called by a >=1.2 HAL!"); - } - incrementCbCount(CB_EV_DATA_PATH_CONFIRM); - - mWifiAwareStateManager.onDataPathConfirmNotification(event.ndpInstanceId, - event.peerNdiMacAddr, event.dataPathSetupSuccess, event.status.status, - convertArrayListToNativeByteArray(event.appInfo), null); - } - - @Override - public void eventDataPathConfirm_1_2(android.hardware.wifi.V1_2.NanDataPathConfirmInd event) { - if (mDbg) { - Log.v(TAG, "eventDataPathConfirm_1_2: ndpInstanceId=" + event.V1_0.ndpInstanceId - + ", peerNdiMacAddr=" + String.valueOf( - HexEncoding.encode(event.V1_0.peerNdiMacAddr)) + ", dataPathSetupSuccess=" - + event.V1_0.dataPathSetupSuccess + ", reason=" + event.V1_0.status.status - + ", appInfo.size()=" + event.V1_0.appInfo.size() - + ", channelInfo" + event.channelInfo); - } - if (!mIsHal12OrLater) { - Log.wtf(TAG, "eventDataPathConfirm_1_2 should not be called by a <1.2 HAL!"); - return; - } - incrementCbCount(CB_EV_DATA_PATH_CONFIRM); - mChannelInfoPerNdp.put(event.V1_0.ndpInstanceId, event.channelInfo); - - mWifiAwareStateManager.onDataPathConfirmNotification(event.V1_0.ndpInstanceId, - event.V1_0.peerNdiMacAddr, event.V1_0.dataPathSetupSuccess, - event.V1_0.status.status, convertArrayListToNativeByteArray(event.V1_0.appInfo), - event.channelInfo); - } - - @Override - public void eventDataPathScheduleUpdate(NanDataPathScheduleUpdateInd event) { - if (mDbg) { - Log.v(TAG, "eventDataPathScheduleUpdate: peerMac=" - + MacAddress.fromBytes(event.peerDiscoveryAddress).toString() - + ", ndpIds=" + event.ndpInstanceIds + ", channelInfo=" + event.channelInfo); - } - if (!mIsHal12OrLater) { - Log.wtf(TAG, "eventDataPathScheduleUpdate should not be called by a <1.2 HAL!"); - return; - } - incrementCbCount(CB_EV_DATA_PATH_SCHED_UPDATE); - for (int ndpInstanceId : event.ndpInstanceIds) { - mChannelInfoPerNdp.put(ndpInstanceId, event.channelInfo); - } - - mWifiAwareStateManager.onDataPathScheduleUpdateNotification(event.peerDiscoveryAddress, - event.ndpInstanceIds, event.channelInfo); - } - - @Override - public void eventDataPathTerminated(int ndpInstanceId) { - if (mDbg) Log.v(TAG, "eventDataPathTerminated: ndpInstanceId=" + ndpInstanceId); - incrementCbCount(CB_EV_DATA_PATH_TERMINATED); - mChannelInfoPerNdp.remove(ndpInstanceId); - - mWifiAwareStateManager.onDataPathEndNotification(ndpInstanceId); - } - - /** - * Reset the channel info when Aware is down. - */ - /* package */ void resetChannelInfo() { - mChannelInfoPerNdp.clear(); - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("WifiAwareNativeCallback:"); - pw.println(" mCallbackCounter: " + mCallbackCounter); - pw.println(" mChannelInfoPerNdp: " + mChannelInfoPerNdp); - } - - - // utilities - - /** - * Converts an ArrayList<Byte> to a byte[]. - * - * @param from The input ArrayList<Byte></Byte> to convert from. - * - * @return A newly allocated byte[]. - */ - private byte[] convertArrayListToNativeByteArray(ArrayList<Byte> from) { - if (from == null) { - return null; - } - - byte[] to = new byte[from.size()]; - for (int i = 0; i < from.size(); ++i) { - to[i] = from.get(i); - } - return to; - } - - private static String statusString(WifiNanStatus status) { - if (status == null) { - return "status=null"; - } - StringBuilder sb = new StringBuilder(); - sb.append(status.status).append(" (").append(status.description).append(")"); - return sb.toString(); - } - - /** - * Transfer the channel Info dict into a Json String which can be decoded by Json reader. - * The Format is: "{ndpInstanceId: [{"channelFreq": channelFreq, - * "channelBandwidth": channelBandwidth, "numSpatialStreams": numSpatialStreams}]}" - * @return Json String. - */ - private String convertChannelInfoToJsonString() { - JSONObject channelInfoJson = new JSONObject(); - try { - for (int i = 0; i < mChannelInfoPerNdp.size(); i++) { - JSONArray infoJsonArray = new JSONArray(); - for (NanDataPathChannelInfo info : mChannelInfoPerNdp.valueAt(i)) { - JSONObject j = new JSONObject(); - j.put("channelFreq", info.channelFreq); - j.put("channelBandwidth", info.channelBandwidth); - j.put("numSpatialStreams", info.numSpatialStreams); - infoJsonArray.put(j); - } - channelInfoJson.put(Integer.toString(mChannelInfoPerNdp.keyAt(i)), infoJsonArray); - } - } catch (JSONException e) { - Log.e(TAG, "onCommand: get_channel_info e=" + e); - } - return channelInfoJson.toString(); - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java deleted file mode 100644 index ec6c0ade5..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import android.annotation.NonNull; -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.os.Handler; -import android.os.RemoteException; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.HalDeviceManager; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Manages the interface to Wi-Fi Aware HIDL (HAL). - */ -public class WifiAwareNativeManager { - private static final String TAG = "WifiAwareNativeManager"; - private boolean mDbg = false; - - // to be used for synchronizing access to any of the WifiAwareNative objects - private final Object mLock = new Object(); - - private WifiAwareStateManager mWifiAwareStateManager; - private HalDeviceManager mHalDeviceManager; - private Handler mHandler; - private WifiAwareNativeCallback mWifiAwareNativeCallback; - private IWifiNanIface mWifiNanIface = null; - private InterfaceDestroyedListener mInterfaceDestroyedListener; - private InterfaceAvailableForRequestListener mInterfaceAvailableForRequestListener = - new InterfaceAvailableForRequestListener(); - private int mReferenceCount = 0; - private volatile boolean mAwareNativeAvailable = false; - - WifiAwareNativeManager(WifiAwareStateManager awareStateManager, - HalDeviceManager halDeviceManager, - WifiAwareNativeCallback wifiAwareNativeCallback) { - mWifiAwareStateManager = awareStateManager; - mHalDeviceManager = halDeviceManager; - mWifiAwareNativeCallback = wifiAwareNativeCallback; - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(boolean verbose) { - mDbg = verbose; - } - - /** - * (HIDL) Cast the input to a 1.2 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { - return android.hardware.wifi.V1_2.IWifiNanIface.castFrom(iface); - } - - /** - * Initialize the class - intended for late initialization. - * - * @param handler Handler on which to execute interface available callbacks. - */ - public void start(Handler handler) { - mHandler = handler; - mHalDeviceManager.initialize(); - mHalDeviceManager.registerStatusListener( - new HalDeviceManager.ManagerStatusListener() { - @Override - public void onStatusChanged() { - if (mDbg) Log.v(TAG, "onStatusChanged"); - // only care about isStarted (Wi-Fi started) not isReady - since if not - // ready then Wi-Fi will also be down. - if (mHalDeviceManager.isStarted()) { - // 1. no problem registering duplicates - only one will be called - // 2. will be called immediately if available - mHalDeviceManager.registerInterfaceAvailableForRequestListener( - IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler); - } else { - awareIsDown(); - } - } - }, mHandler); - if (mHalDeviceManager.isStarted()) { - mHalDeviceManager.registerInterfaceAvailableForRequestListener( - IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler); - } - } - - /** - * Return the Availability of WifiAware native HAL - */ - public boolean isAwareNativeAvailable() { - return mAwareNativeAvailable; - } - - /** - * Returns the native HAL WifiNanIface through which commands to the NAN HAL are dispatched. - * Return may be null if not initialized/available. - */ - @VisibleForTesting - public IWifiNanIface getWifiNanIface() { - synchronized (mLock) { - return mWifiNanIface; - } - } - - /** - * Attempt to obtain the HAL NAN interface. - */ - public void tryToGetAware() { - synchronized (mLock) { - if (mDbg) { - Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount=" - + mReferenceCount); - } - - if (mWifiNanIface != null) { - mReferenceCount++; - return; - } - if (mHalDeviceManager == null) { - Log.e(TAG, "tryToGetAware: mHalDeviceManager is null!?"); - awareIsDown(); - return; - } - - mInterfaceDestroyedListener = new InterfaceDestroyedListener(); - IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener, - mHandler); - if (iface == null) { - Log.e(TAG, "Was not able to obtain an IWifiNanIface (even though enabled!?)"); - awareIsDown(); - } else { - if (mDbg) Log.v(TAG, "Obtained an IWifiNanIface"); - - try { - android.hardware.wifi.V1_2.IWifiNanIface iface12 = mockableCastTo_1_2(iface); - WifiStatus status; - if (iface12 == null) { - mWifiAwareNativeCallback.mIsHal12OrLater = false; - status = iface.registerEventCallback(mWifiAwareNativeCallback); - } else { - mWifiAwareNativeCallback.mIsHal12OrLater = true; - status = iface12.registerEventCallback_1_2(mWifiAwareNativeCallback); - } - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString( - status)); - mHalDeviceManager.removeIface(iface); - awareIsDown(); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e); - awareIsDown(); - return; - } - mWifiNanIface = iface; - mReferenceCount = 1; - } - } - } - - /** - * Release the HAL NAN interface. - */ - public void releaseAware() { - if (mDbg) { - Log.d(TAG, "releaseAware: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount=" - + mReferenceCount); - } - - if (mWifiNanIface == null) { - return; - } - if (mHalDeviceManager == null) { - Log.e(TAG, "releaseAware: mHalDeviceManager is null!?"); - return; - } - - synchronized (mLock) { - mReferenceCount--; - if (mReferenceCount != 0) { - return; - } - mInterfaceDestroyedListener.active = false; - mInterfaceDestroyedListener = null; - mHalDeviceManager.removeIface(mWifiNanIface); - mWifiNanIface = null; - mWifiAwareNativeCallback.resetChannelInfo(); - } - } - - private void awareIsDown() { - synchronized (mLock) { - if (mDbg) { - Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount =" - + mReferenceCount); - } - mWifiNanIface = null; - mReferenceCount = 0; - mAwareNativeAvailable = false; - mWifiAwareStateManager.disableUsage(); - } - } - - private class InterfaceDestroyedListener implements - HalDeviceManager.InterfaceDestroyedListener { - public boolean active = true; - - @Override - public void onDestroyed(@NonNull String ifaceName) { - if (mDbg) { - Log.d(TAG, "Interface was destroyed: mWifiNanIface=" + mWifiNanIface + ", active=" - + active); - } - if (active && mWifiNanIface != null) { - awareIsDown(); - } // else: we released it locally so no need to disable usage - } - } - - private class InterfaceAvailableForRequestListener implements - HalDeviceManager.InterfaceAvailableForRequestListener { - @Override - public void onAvailabilityChanged(boolean isAvailable) { - if (mDbg) { - Log.d(TAG, "Interface availability = " + isAvailable + ", mWifiNanIface=" - + mWifiNanIface); - } - synchronized (mLock) { - if (isAvailable) { - mAwareNativeAvailable = true; - mWifiAwareStateManager.enableUsage(); - } else if (mWifiNanIface == null) { // not available could mean already have NAN - mAwareNativeAvailable = false; - mWifiAwareStateManager.disableUsage(); - } - } - } - } - - private static String statusString(WifiStatus status) { - if (status == null) { - return "status=null"; - } - StringBuilder sb = new StringBuilder(); - sb.append(status.code).append(" (").append(status.description).append(")"); - return sb.toString(); - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("WifiAwareNativeManager:"); - pw.println(" mWifiNanIface: " + mWifiNanIface); - pw.println(" mReferenceCount: " + mReferenceCount); - mWifiAwareNativeCallback.dump(fd, pw, args); - mHalDeviceManager.dump(fd, pw, args); - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareService.java b/service/java/com/android/server/wifi/aware/WifiAwareService.java deleted file mode 100644 index 2389b9ccd..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareService.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import android.content.Context; -import android.os.HandlerThread; -import android.util.Log; - -import com.android.server.SystemService; -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.WifiContext; -import com.android.server.wifi.WifiInjector; - -/** - * Service implementing Wi-Fi Aware functionality. Delegates actual interface - * implementation to WifiAwareServiceImpl. - */ -public final class WifiAwareService extends SystemService { - private static final String TAG = "WifiAwareService"; - final WifiAwareServiceImpl mImpl; - - public WifiAwareService(Context contextBase) { - super(new WifiContext(contextBase)); - mImpl = new WifiAwareServiceImpl(getContext()); - } - - @Override - public void onStart() { - Log.i(TAG, "Registering " + Context.WIFI_AWARE_SERVICE); - publishBinderService(Context.WIFI_AWARE_SERVICE, mImpl); - } - - @Override - public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { - WifiInjector wifiInjector = WifiInjector.getInstance(); - if (wifiInjector == null) { - Log.e(TAG, "onBootPhase(PHASE_SYSTEM_SERVICES_READY): NULL injector!"); - return; - } - - HalDeviceManager halDeviceManager = wifiInjector.getHalDeviceManager(); - - WifiAwareStateManager wifiAwareStateManager = new WifiAwareStateManager(); - WifiAwareNativeCallback wifiAwareNativeCallback = new WifiAwareNativeCallback( - wifiAwareStateManager); - WifiAwareNativeManager wifiAwareNativeManager = new WifiAwareNativeManager( - wifiAwareStateManager, halDeviceManager, wifiAwareNativeCallback); - WifiAwareNativeApi wifiAwareNativeApi = new WifiAwareNativeApi(wifiAwareNativeManager); - wifiAwareStateManager.setNative(wifiAwareNativeManager, wifiAwareNativeApi); - WifiAwareShellCommand wifiAwareShellCommand = new WifiAwareShellCommand(); - wifiAwareShellCommand.register("native_api", wifiAwareNativeApi); - wifiAwareShellCommand.register("native_cb", wifiAwareNativeCallback); - wifiAwareShellCommand.register("state_mgr", wifiAwareStateManager); - - HandlerThread awareHandlerThread = wifiInjector.getWifiAwareHandlerThread(); - mImpl.start(awareHandlerThread, wifiAwareStateManager, wifiAwareShellCommand, - wifiInjector.getWifiMetrics().getWifiAwareMetrics(), - wifiInjector.getWifiPermissionsUtil(), - wifiInjector.getWifiPermissionsWrapper(), wifiInjector.getSettingsConfigStore(), - wifiAwareNativeManager, wifiAwareNativeApi, wifiAwareNativeCallback, - wifiInjector.makeNetdWrapper()); - } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { - mImpl.startLate(); - } - } -} - diff --git a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java deleted file mode 100644 index 3e33cc1aa..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; - -import android.Manifest; -import android.annotation.NonNull; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.hardware.wifi.V1_0.NanStatusType; -import android.net.wifi.aware.Characteristics; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.DiscoverySession; -import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; -import android.net.wifi.aware.IWifiAwareEventCallback; -import android.net.wifi.aware.IWifiAwareMacAddressProvider; -import android.net.wifi.aware.IWifiAwareManager; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.os.Binder; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiSettingsConfigStore; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.List; - -/** - * Implementation of the IWifiAwareManager AIDL interface. Performs validity - * (permission and clientID-UID mapping) checks and delegates execution to the - * WifiAwareStateManager singleton handler. Limited state to feedback which has to - * be provided instantly: client and session IDs. - */ -public class WifiAwareServiceImpl extends IWifiAwareManager.Stub { - private static final String TAG = "WifiAwareService"; - private boolean mDbg = false; - - private Context mContext; - private AppOpsManager mAppOps; - private WifiPermissionsUtil mWifiPermissionsUtil; - private WifiAwareStateManager mStateManager; - private WifiAwareShellCommand mShellCommand; - private Handler mHandler; - - private final Object mLock = new Object(); - private final SparseArray<IBinder.DeathRecipient> mDeathRecipientsByClientId = - new SparseArray<>(); - private int mNextClientId = 1; - private final SparseIntArray mUidByClientId = new SparseIntArray(); - - public WifiAwareServiceImpl(Context context) { - mContext = context; - mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - } - - /** - * Proxy for the final native call of the parent class. Enables mocking of - * the function. - */ - public int getMockableCallingUid() { - return getCallingUid(); - } - - /** - * Start the service: allocate a new thread (for now), start the handlers of - * the components of the service. - */ - public void start(HandlerThread handlerThread, WifiAwareStateManager awareStateManager, - WifiAwareShellCommand awareShellCommand, WifiAwareMetrics awareMetrics, - WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, - WifiSettingsConfigStore settingsConfigStore, - WifiAwareNativeManager wifiAwareNativeManager, WifiAwareNativeApi wifiAwareNativeApi, - WifiAwareNativeCallback wifiAwareNativeCallback, NetdWrapper netdWrapper) { - Log.i(TAG, "Starting Wi-Fi Aware service"); - - mWifiPermissionsUtil = wifiPermissionsUtil; - mStateManager = awareStateManager; - mShellCommand = awareShellCommand; - mHandler = new Handler(handlerThread.getLooper()); - - mHandler.post(() -> { - mStateManager.start(mContext, handlerThread.getLooper(), awareMetrics, - wifiPermissionsUtil, permissionsWrapper, new Clock(), netdWrapper); - - settingsConfigStore.registerChangeListener( - WIFI_VERBOSE_LOGGING_ENABLED, - (key, newValue) -> enableVerboseLogging(newValue, awareStateManager, - wifiAwareNativeManager, wifiAwareNativeApi, wifiAwareNativeCallback), - mHandler); - enableVerboseLogging(settingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED), - awareStateManager, - wifiAwareNativeManager, wifiAwareNativeApi, - wifiAwareNativeCallback); - }); - } - - private void enableVerboseLogging(boolean dbg, WifiAwareStateManager awareStateManager, - WifiAwareNativeManager wifiAwareNativeManager, WifiAwareNativeApi wifiAwareNativeApi, - WifiAwareNativeCallback wifiAwareNativeCallback) { - mDbg = dbg; - awareStateManager.enableVerboseLogging(dbg); - if (awareStateManager.mDataPathMgr != null) { // needed for unit tests - awareStateManager.mDataPathMgr.enableVerboseLogging(dbg); - } - wifiAwareNativeCallback.enableVerboseLogging(dbg); - wifiAwareNativeManager.enableVerboseLogging(dbg); - wifiAwareNativeApi.enableVerboseLogging(dbg); - } - - /** - * Start/initialize portions of the service which require the boot stage to be complete. - */ - public void startLate() { - Log.i(TAG, "Late initialization of Wi-Fi Aware service"); - - mHandler.post(() -> mStateManager.startLate()); - } - - @Override - public boolean isUsageEnabled() { - enforceAccessPermission(); - - return mStateManager.isUsageEnabled(); - } - - @Override - public Characteristics getCharacteristics() { - enforceAccessPermission(); - - return mStateManager.getCapabilities() == null ? null - : mStateManager.getCapabilities().toPublicCharacteristics(); - } - - @Override - public void connect(final IBinder binder, String callingPackage, String callingFeatureId, - IWifiAwareEventCallback callback, ConfigRequest configRequest, - boolean notifyOnIdentityChanged) { - enforceAccessPermission(); - enforceChangePermission(); - - final int uid = getMockableCallingUid(); - mAppOps.checkPackage(uid, callingPackage); - - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - - if (notifyOnIdentityChanged) { - enforceLocationPermission(callingPackage, callingFeatureId, getMockableCallingUid()); - } - - if (configRequest != null) { - enforceNetworkStackPermission(); - } else { - configRequest = new ConfigRequest.Builder().build(); - } - configRequest.validate(); - - - int pid = getCallingPid(); - - final int clientId; - synchronized (mLock) { - clientId = mNextClientId++; - } - - if (mDbg) { - Log.v(TAG, "connect: uid=" + uid + ", clientId=" + clientId + ", configRequest" - + configRequest + ", notifyOnIdentityChanged=" + notifyOnIdentityChanged); - } - - IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { - @Override - public void binderDied() { - if (mDbg) Log.v(TAG, "binderDied: clientId=" + clientId); - binder.unlinkToDeath(this, 0); - - synchronized (mLock) { - mDeathRecipientsByClientId.delete(clientId); - mUidByClientId.delete(clientId); - } - - mStateManager.disconnect(clientId); - } - }; - - try { - binder.linkToDeath(dr, 0); - } catch (RemoteException e) { - Log.e(TAG, "Error on linkToDeath - " + e); - try { - callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e1) { - Log.e(TAG, "Error on onConnectFail()"); - } - return; - } - - synchronized (mLock) { - mDeathRecipientsByClientId.put(clientId, dr); - mUidByClientId.put(clientId, uid); - } - - mStateManager.connect(clientId, uid, pid, callingPackage, callingFeatureId, callback, - configRequest, notifyOnIdentityChanged); - } - - @Override - public void disconnect(int clientId, IBinder binder) { - enforceAccessPermission(); - enforceChangePermission(); - - int uid = getMockableCallingUid(); - enforceClientValidity(uid, clientId); - if (mDbg) Log.v(TAG, "disconnect: uid=" + uid + ", clientId=" + clientId); - - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - - synchronized (mLock) { - IBinder.DeathRecipient dr = mDeathRecipientsByClientId.get(clientId); - if (dr != null) { - binder.unlinkToDeath(dr, 0); - mDeathRecipientsByClientId.delete(clientId); - } - mUidByClientId.delete(clientId); - } - - mStateManager.disconnect(clientId); - } - - @Override - public void terminateSession(int clientId, int sessionId) { - enforceAccessPermission(); - enforceChangePermission(); - - int uid = getMockableCallingUid(); - enforceClientValidity(uid, clientId); - if (mDbg) { - Log.v(TAG, "terminateSession: sessionId=" + sessionId + ", uid=" + uid + ", clientId=" - + clientId); - } - - mStateManager.terminateSession(clientId, sessionId); - } - - @Override - public void publish(String callingPackage, String callingFeatureId, int clientId, - PublishConfig publishConfig, IWifiAwareDiscoverySessionCallback callback) { - enforceAccessPermission(); - enforceChangePermission(); - - int uid = getMockableCallingUid(); - mAppOps.checkPackage(uid, callingPackage); - - enforceLocationPermission(callingPackage, callingFeatureId, getMockableCallingUid()); - - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - if (publishConfig == null) { - throw new IllegalArgumentException("PublishConfig must not be null"); - } - publishConfig.assertValid(mStateManager.getCharacteristics(), - mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)); - - enforceClientValidity(uid, clientId); - if (mDbg) { - Log.v(TAG, "publish: uid=" + uid + ", clientId=" + clientId + ", publishConfig=" - + publishConfig + ", callback=" + callback); - } - - mStateManager.publish(clientId, publishConfig, callback); - } - - @Override - public void updatePublish(int clientId, int sessionId, PublishConfig publishConfig) { - enforceAccessPermission(); - enforceChangePermission(); - - if (publishConfig == null) { - throw new IllegalArgumentException("PublishConfig must not be null"); - } - publishConfig.assertValid(mStateManager.getCharacteristics(), - mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)); - - int uid = getMockableCallingUid(); - enforceClientValidity(uid, clientId); - if (mDbg) { - Log.v(TAG, "updatePublish: uid=" + uid + ", clientId=" + clientId + ", sessionId=" - + sessionId + ", config=" + publishConfig); - } - - mStateManager.updatePublish(clientId, sessionId, publishConfig); - } - - @Override - public void subscribe(String callingPackage, String callingFeatureId, int clientId, - SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback) { - enforceAccessPermission(); - enforceChangePermission(); - - int uid = getMockableCallingUid(); - mAppOps.checkPackage(uid, callingPackage); - - enforceLocationPermission(callingPackage, callingFeatureId, getMockableCallingUid()); - - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - if (subscribeConfig == null) { - throw new IllegalArgumentException("SubscribeConfig must not be null"); - } - subscribeConfig.assertValid(mStateManager.getCharacteristics(), - mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)); - - enforceClientValidity(uid, clientId); - if (mDbg) { - Log.v(TAG, "subscribe: uid=" + uid + ", clientId=" + clientId + ", config=" - + subscribeConfig + ", callback=" + callback); - } - - mStateManager.subscribe(clientId, subscribeConfig, callback); - } - - @Override - public void updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig) { - enforceAccessPermission(); - enforceChangePermission(); - - if (subscribeConfig == null) { - throw new IllegalArgumentException("SubscribeConfig must not be null"); - } - subscribeConfig.assertValid(mStateManager.getCharacteristics(), - mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)); - - int uid = getMockableCallingUid(); - enforceClientValidity(uid, clientId); - if (mDbg) { - Log.v(TAG, "updateSubscribe: uid=" + uid + ", clientId=" + clientId + ", sessionId=" - + sessionId + ", config=" + subscribeConfig); - } - - mStateManager.updateSubscribe(clientId, sessionId, subscribeConfig); - } - - @Override - public void sendMessage(int clientId, int sessionId, int peerId, byte[] message, int messageId, - int retryCount) { - enforceAccessPermission(); - enforceChangePermission(); - - if (retryCount != 0) { - enforceNetworkStackPermission(); - } - - if (message != null && message.length - > mStateManager.getCharacteristics().getMaxServiceSpecificInfoLength()) { - throw new IllegalArgumentException( - "Message length longer than supported by device characteristics"); - } - if (retryCount < 0 || retryCount > DiscoverySession.getMaxSendRetryCount()) { - throw new IllegalArgumentException("Invalid 'retryCount' must be non-negative " - + "and <= DiscoverySession.MAX_SEND_RETRY_COUNT"); - } - - int uid = getMockableCallingUid(); - enforceClientValidity(uid, clientId); - if (mDbg) { - Log.v(TAG, - "sendMessage: sessionId=" + sessionId + ", uid=" + uid + ", clientId=" - + clientId + ", peerId=" + peerId + ", messageId=" + messageId - + ", retryCount=" + retryCount); - } - - mStateManager.sendMessage(uid, clientId, sessionId, peerId, message, messageId, retryCount); - } - - @Override - public void requestMacAddresses(int uid, List peerIds, IWifiAwareMacAddressProvider callback) { - enforceNetworkStackPermission(); - - mStateManager.requestMacAddresses(uid, peerIds, callback); - } - - @Override - public int handleShellCommand(@NonNull ParcelFileDescriptor in, - @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, - @NonNull String[] args) { - return mShellCommand.exec( - this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), - args); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission( - android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump WifiAwareService from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); - return; - } - pw.println("Wi-Fi Aware Service"); - synchronized (mLock) { - pw.println(" mNextClientId: " + mNextClientId); - pw.println(" mDeathRecipientsByClientId: " + mDeathRecipientsByClientId); - pw.println(" mUidByClientId: " + mUidByClientId); - } - mStateManager.dump(fd, pw, args); - } - - private void enforceClientValidity(int uid, int clientId) { - synchronized (mLock) { - int uidIndex = mUidByClientId.indexOfKey(clientId); - if (uidIndex < 0 || mUidByClientId.valueAt(uidIndex) != uid) { - throw new SecurityException("Attempting to use invalid uid+clientId mapping: uid=" - + uid + ", clientId=" + clientId); - } - } - } - - private void enforceAccessPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, TAG); - } - - private void enforceChangePermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, TAG); - } - - private void enforceLocationPermission(String callingPackage, String callingFeatureId, - int uid) { - mWifiPermissionsUtil.enforceLocationPermission(callingPackage, callingFeatureId, uid); - } - - private void enforceNetworkStackPermission() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.NETWORK_STACK, TAG); - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareShellCommand.java b/service/java/com/android/server/wifi/aware/WifiAwareShellCommand.java deleted file mode 100644 index 61afe1a8e..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareShellCommand.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.aware; - -import android.os.BasicShellCommandHandler; -import android.os.Binder; -import android.text.TextUtils; -import android.util.Log; - -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Map; - -/** - * Interprets and executes 'adb shell cmd wifiaware [args]'. - */ -public class WifiAwareShellCommand extends BasicShellCommandHandler { - private static final String TAG = "WifiAwareShellCommand"; - - private Map<String, DelegatedShellCommand> mDelegatedCommands = new HashMap<>(); - - /** - * Register an delegated command interpreter for the specified 'command'. Each class can - * interpret and execute their own commands. - */ - public void register(String command, DelegatedShellCommand shellCommand) { - if (mDelegatedCommands.containsKey(command)) { - Log.e(TAG, "register: overwriting existing command -- '" + command + "'"); - } - - mDelegatedCommands.put(command, shellCommand); - } - - @Override - public int onCommand(String cmd) { - checkRootPermission(); - - final PrintWriter pw = getErrPrintWriter(); - try { - if ("reset".equals(cmd)) { - for (DelegatedShellCommand dsc: mDelegatedCommands.values()) { - dsc.onReset(); - } - return 0; - } else { - DelegatedShellCommand delegatedCmd = null; - if (!TextUtils.isEmpty(cmd)) { - delegatedCmd = mDelegatedCommands.get(cmd); - } - - if (delegatedCmd != null) { - return delegatedCmd.onCommand(this); - } else { - return handleDefaultCommands(cmd); - } - } - } catch (Exception e) { - pw.println("Exception: " + e); - } - return -1; - } - - private void checkRootPermission() { - final int uid = Binder.getCallingUid(); - if (uid == 0) { - // Root can do anything. - return; - } - throw new SecurityException("Uid " + uid + " does not have access to wifiaware commands"); - } - - @Override - public void onHelp() { - final PrintWriter pw = getOutPrintWriter(); - - pw.println("Wi-Fi Aware (wifiaware) commands:"); - pw.println(" help"); - pw.println(" Print this help text."); - pw.println(" reset"); - pw.println(" Reset parameters to default values."); - for (Map.Entry<String, DelegatedShellCommand> sce: mDelegatedCommands.entrySet()) { - sce.getValue().onHelp(sce.getKey(), this); - } - pw.println(); - } - - /** - * Interface that delegated command targets must implement. They are passed the parent shell - * command (the real command interpreter) from which they can obtain arguments. - */ - public interface DelegatedShellCommand { - /** - * Execute the specified command. Use the parent shell to obtain arguments. Note that the - * first argument (which specified the delegated shell) has already been extracted. - */ - int onCommand(BasicShellCommandHandler parentShell); - - /** - * Reset all parameters to their default values. - */ - void onReset(); - - /** - * Print out help for the delegated command. The name of the delegated command is passed - * as a first argument as an assist (prevents hard-coding of that string in multiple - * places). - */ - void onHelp(String command, BasicShellCommandHandler parentShell); - - } -} diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java deleted file mode 100644 index baa822e11..000000000 --- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java +++ /dev/null @@ -1,3309 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import android.annotation.Nullable; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.wifi.V1_0.NanStatusType; -import android.hardware.wifi.V1_2.NanDataPathChannelInfo; -import android.location.LocationManager; -import android.net.wifi.WifiManager; -import android.net.wifi.aware.Characteristics; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; -import android.net.wifi.aware.IWifiAwareEventCallback; -import android.net.wifi.aware.IWifiAwareMacAddressProvider; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.net.wifi.aware.WifiAwareManager; -import android.net.wifi.aware.WifiAwareNetworkSpecifier; -import android.net.wifi.util.HexEncoding; -import android.os.BasicShellCommandHandler; -import android.os.Bundle; -import android.os.Looper; -import android.os.Message; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.SystemClock; -import android.os.UserHandle; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Log; -import android.util.Pair; -import android.util.SparseArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.MessageUtils; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import com.android.internal.util.WakeupMessage; -import com.android.server.wifi.Clock; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * Manages the state of the Wi-Fi Aware system service. - */ -public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShellCommand { - private static final String TAG = "WifiAwareStateManager"; - private static final boolean VDBG = false; // STOPSHIP if true - for detailed state machine - private boolean mDbg = false; - - @VisibleForTesting - public static final String HAL_COMMAND_TIMEOUT_TAG = TAG + " HAL Command Timeout"; - - @VisibleForTesting - public static final String HAL_SEND_MESSAGE_TIMEOUT_TAG = TAG + " HAL Send Message Timeout"; - - @VisibleForTesting - public static final String HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG = - TAG + " HAL Data Path Confirm Timeout"; - - /* - * State machine message types. There are sub-types for the messages (except for TIMEOUTs). - * Format: - * - Message.arg1: contains message sub-type - * - Message.arg2: contains transaction ID for RESPONSE & RESPONSE_TIMEOUT - */ - private static final int MESSAGE_TYPE_COMMAND = 1; - private static final int MESSAGE_TYPE_RESPONSE = 2; - private static final int MESSAGE_TYPE_NOTIFICATION = 3; - private static final int MESSAGE_TYPE_RESPONSE_TIMEOUT = 4; - private static final int MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT = 5; - private static final int MESSAGE_TYPE_DATA_PATH_TIMEOUT = 6; - - /* - * Message sub-types: - */ - private static final int COMMAND_TYPE_CONNECT = 100; - private static final int COMMAND_TYPE_DISCONNECT = 101; - private static final int COMMAND_TYPE_TERMINATE_SESSION = 102; - private static final int COMMAND_TYPE_PUBLISH = 103; - private static final int COMMAND_TYPE_UPDATE_PUBLISH = 104; - private static final int COMMAND_TYPE_SUBSCRIBE = 105; - private static final int COMMAND_TYPE_UPDATE_SUBSCRIBE = 106; - private static final int COMMAND_TYPE_ENQUEUE_SEND_MESSAGE = 107; - private static final int COMMAND_TYPE_ENABLE_USAGE = 108; - private static final int COMMAND_TYPE_DISABLE_USAGE = 109; - private static final int COMMAND_TYPE_GET_CAPABILITIES = 111; - private static final int COMMAND_TYPE_CREATE_ALL_DATA_PATH_INTERFACES = 112; - private static final int COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES = 113; - private static final int COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE = 114; - private static final int COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE = 115; - private static final int COMMAND_TYPE_INITIATE_DATA_PATH_SETUP = 116; - private static final int COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST = 117; - private static final int COMMAND_TYPE_END_DATA_PATH = 118; - private static final int COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE = 119; - private static final int COMMAND_TYPE_RECONFIGURE = 120; - private static final int COMMAND_TYPE_DELAYED_INITIALIZATION = 121; - private static final int COMMAND_TYPE_GET_AWARE = 122; - private static final int COMMAND_TYPE_RELEASE_AWARE = 123; - - private static final int RESPONSE_TYPE_ON_CONFIG_SUCCESS = 200; - private static final int RESPONSE_TYPE_ON_CONFIG_FAIL = 201; - private static final int RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS = 202; - private static final int RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL = 203; - private static final int RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS = 204; - private static final int RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL = 205; - private static final int RESPONSE_TYPE_ON_CAPABILITIES_UPDATED = 206; - private static final int RESPONSE_TYPE_ON_CREATE_INTERFACE = 207; - private static final int RESPONSE_TYPE_ON_DELETE_INTERFACE = 208; - private static final int RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS = 209; - private static final int RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL = 210; - private static final int RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST = 211; - private static final int RESPONSE_TYPE_ON_END_DATA_PATH = 212; - private static final int RESPONSE_TYPE_ON_DISABLE = 213; - - private static final int NOTIFICATION_TYPE_INTERFACE_CHANGE = 301; - private static final int NOTIFICATION_TYPE_CLUSTER_CHANGE = 302; - private static final int NOTIFICATION_TYPE_MATCH = 303; - private static final int NOTIFICATION_TYPE_SESSION_TERMINATED = 304; - private static final int NOTIFICATION_TYPE_MESSAGE_RECEIVED = 305; - private static final int NOTIFICATION_TYPE_AWARE_DOWN = 306; - private static final int NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS = 307; - private static final int NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL = 308; - private static final int NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST = 309; - private static final int NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM = 310; - private static final int NOTIFICATION_TYPE_ON_DATA_PATH_END = 311; - private static final int NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE = 312; - - private static final SparseArray<String> sSmToString = MessageUtils.findMessageNames( - new Class[]{WifiAwareStateManager.class}, - new String[]{"MESSAGE_TYPE", "COMMAND_TYPE", "RESPONSE_TYPE", "NOTIFICATION_TYPE"}); - - /* - * Keys used when passing (some) arguments to the Handler thread (too many - * arguments to pass in the short-cut Message members). - */ - private static final String MESSAGE_BUNDLE_KEY_SESSION_TYPE = "session_type"; - private static final String MESSAGE_BUNDLE_KEY_SESSION_ID = "session_id"; - private static final String MESSAGE_BUNDLE_KEY_CONFIG = "config"; - private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message"; - private static final String MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID = "message_peer_id"; - private static final String MESSAGE_BUNDLE_KEY_MESSAGE_ID = "message_id"; - private static final String MESSAGE_BUNDLE_KEY_SSI_DATA = "ssi_data"; - private static final String MESSAGE_BUNDLE_KEY_FILTER_DATA = "filter_data"; - private static final String MESSAGE_BUNDLE_KEY_MAC_ADDRESS = "mac_address"; - private static final String MESSAGE_BUNDLE_KEY_MESSAGE_DATA = "message_data"; - private static final String MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID = "req_instance_id"; - private static final String MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME = "message_queue_time"; - private static final String MESSAGE_BUNDLE_KEY_RETRY_COUNT = "retry_count"; - private static final String MESSAGE_BUNDLE_KEY_SUCCESS_FLAG = "success_flag"; - private static final String MESSAGE_BUNDLE_KEY_STATUS_CODE = "status_code"; - private static final String MESSAGE_BUNDLE_KEY_INTERFACE_NAME = "interface_name"; - private static final String MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE = "channel_request_type"; - private static final String MESSAGE_BUNDLE_KEY_CHANNEL = "channel"; - private static final String MESSAGE_BUNDLE_KEY_PEER_ID = "peer_id"; - private static final String MESSAGE_BUNDLE_KEY_UID = "uid"; - private static final String MESSAGE_BUNDLE_KEY_PID = "pid"; - private static final String MESSAGE_BUNDLE_KEY_CALLING_PACKAGE = "calling_package"; - private static final String MESSAGE_BUNDLE_KEY_CALLING_FEATURE_ID = "calling_feature_id"; - private static final String MESSAGE_BUNDLE_KEY_SENT_MESSAGE = "send_message"; - private static final String MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ = "message_arrival_seq"; - private static final String MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE = "notify_identity_chg"; - private static final String MESSAGE_BUNDLE_KEY_PMK = "pmk"; - private static final String MESSAGE_BUNDLE_KEY_PASSPHRASE = "passphrase"; - private static final String MESSAGE_BUNDLE_KEY_OOB = "out_of_band"; - private static final String MESSAGE_RANGING_INDICATION = "ranging_indication"; - private static final String MESSAGE_RANGE_MM = "range_mm"; - private static final String MESSAGE_BUNDLE_KEY_NDP_IDS = "ndp_ids"; - private static final String MESSAGE_BUNDLE_KEY_APP_INFO = "app_info"; - - private WifiAwareNativeApi mWifiAwareNativeApi; - private WifiAwareNativeManager mWifiAwareNativeManager; - - /* - * Asynchronous access with no lock - */ - private volatile boolean mUsageEnabled = false; - - /* - * Synchronous access: state is only accessed through the state machine - * handler thread: no need to use a lock. - */ - private Context mContext; - private WifiAwareMetrics mAwareMetrics; - private WifiPermissionsUtil mWifiPermissionsUtil; - private volatile Capabilities mCapabilities; - private volatile Characteristics mCharacteristics = null; - private WifiAwareStateMachine mSm; - public WifiAwareDataPathStateManager mDataPathMgr; - private PowerManager mPowerManager; - private LocationManager mLocationManager; - private WifiManager mWifiManager; - - private final SparseArray<WifiAwareClientState> mClients = new SparseArray<>(); - private ConfigRequest mCurrentAwareConfiguration = null; - private boolean mCurrentIdentityNotification = false; - private boolean mCurrentRangingEnabled = false; - - private static final byte[] ALL_ZERO_MAC = new byte[] {0, 0, 0, 0, 0, 0}; - private byte[] mCurrentDiscoveryInterfaceMac = ALL_ZERO_MAC; - - public WifiAwareStateManager() { - onReset(); - } - - /** - * Enable verbose logging. - */ - public void enableVerboseLogging(boolean verbose) { - mDbg = verbose | VDBG; - } - - - /** - * Inject references to other manager objects. Needed to resolve - * circular dependencies and to allow mocking. - */ - public void setNative(WifiAwareNativeManager wifiAwareNativeManager, - WifiAwareNativeApi wifiAwareNativeApi) { - mWifiAwareNativeManager = wifiAwareNativeManager; - mWifiAwareNativeApi = wifiAwareNativeApi; - } - - /* - * parameters settable through shell command - */ - public static final String PARAM_ON_IDLE_DISABLE_AWARE = "on_idle_disable_aware"; - public static final int PARAM_ON_IDLE_DISABLE_AWARE_DEFAULT = 1; // 0 = false, 1 = true - - private Map<String, Integer> mSettableParameters = new HashMap<>(); - - /** - * Interpreter of adb shell command 'adb shell wifiaware native_api ...'. - * - * @return -1 if parameter not recognized or invalid value, 0 otherwise. - */ - @Override - public int onCommand(BasicShellCommandHandler parentShell) { - final PrintWriter pw_err = parentShell.getErrPrintWriter(); - final PrintWriter pw_out = parentShell.getOutPrintWriter(); - - String subCmd = parentShell.getNextArgRequired(); - switch (subCmd) { - case "set": { - String name = parentShell.getNextArgRequired(); - if (!mSettableParameters.containsKey(name)) { - pw_err.println("Unknown parameter name -- '" + name + "'"); - return -1; - } - - String valueStr = parentShell.getNextArgRequired(); - int value; - try { - value = Integer.valueOf(valueStr); - } catch (NumberFormatException e) { - pw_err.println("Can't convert value to integer -- '" + valueStr + "'"); - return -1; - } - mSettableParameters.put(name, value); - return 0; - } - case "get": { - String name = parentShell.getNextArgRequired(); - if (!mSettableParameters.containsKey(name)) { - pw_err.println("Unknown parameter name -- '" + name + "'"); - return -1; - } - - pw_out.println((int) mSettableParameters.get(name)); - return 0; - } - case "get_capabilities": { - JSONObject j = new JSONObject(); - if (mCapabilities != null) { - try { - j.put("maxConcurrentAwareClusters", - mCapabilities.maxConcurrentAwareClusters); - j.put("maxPublishes", mCapabilities.maxPublishes); - j.put("maxSubscribes", mCapabilities.maxSubscribes); - j.put("maxServiceNameLen", mCapabilities.maxServiceNameLen); - j.put("maxMatchFilterLen", mCapabilities.maxMatchFilterLen); - j.put("maxTotalMatchFilterLen", mCapabilities.maxTotalMatchFilterLen); - j.put("maxServiceSpecificInfoLen", mCapabilities.maxServiceSpecificInfoLen); - j.put("maxExtendedServiceSpecificInfoLen", - mCapabilities.maxExtendedServiceSpecificInfoLen); - j.put("maxNdiInterfaces", mCapabilities.maxNdiInterfaces); - j.put("maxNdpSessions", mCapabilities.maxNdpSessions); - j.put("maxAppInfoLen", mCapabilities.maxAppInfoLen); - j.put("maxQueuedTransmitMessages", mCapabilities.maxQueuedTransmitMessages); - j.put("maxSubscribeInterfaceAddresses", - mCapabilities.maxSubscribeInterfaceAddresses); - j.put("supportedCipherSuites", mCapabilities.supportedCipherSuites); - } catch (JSONException e) { - Log.e(TAG, "onCommand: get_capabilities e=" + e); - } - } - pw_out.println(j.toString()); - return 0; - } - case "allow_ndp_any": { - String flag = parentShell.getNextArgRequired(); - if (mDataPathMgr == null) { - pw_err.println("Null Aware data-path manager - can't configure"); - return -1; - } - if (TextUtils.equals("true", flag)) { - mDataPathMgr.mAllowNdpResponderFromAnyOverride = true; - } else if (TextUtils.equals("false", flag)) { - mDataPathMgr.mAllowNdpResponderFromAnyOverride = false; - } else { - pw_err.println( - "Unknown configuration flag for 'allow_ndp_any' - true|false expected" - + " -- '" - + flag + "'"); - return -1; - } - } - default: - pw_err.println("Unknown 'wifiaware state_mgr <cmd>'"); - } - - return -1; - } - - @Override - public void onReset() { - mSettableParameters.put(PARAM_ON_IDLE_DISABLE_AWARE, PARAM_ON_IDLE_DISABLE_AWARE_DEFAULT); - if (mDataPathMgr != null) { - mDataPathMgr.mAllowNdpResponderFromAnyOverride = false; - } - } - - @Override - public void onHelp(String command, BasicShellCommandHandler parentShell) { - final PrintWriter pw = parentShell.getOutPrintWriter(); - - pw.println(" " + command); - pw.println(" set <name> <value>: sets named parameter to value. Names: " - + mSettableParameters.keySet()); - pw.println(" get <name>: gets named parameter value. Names: " - + mSettableParameters.keySet()); - pw.println(" get_capabilities: prints out the capabilities as a JSON string"); - pw.println( - " allow_ndp_any true|false: configure whether Responders can be specified to " - + "accept requests from ANY requestor (null peer spec)"); - } - - /** - * Initialize the handler of the state manager with the specified thread - * looper. - * - * @param looper Thread looper on which to run the handler. - */ - public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics, - WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, - Clock clock, NetdWrapper netdWrapper) { - Log.i(TAG, "start()"); - - mContext = context; - mAwareMetrics = awareMetrics; - mWifiPermissionsUtil = wifiPermissionsUtil; - mSm = new WifiAwareStateMachine(TAG, looper); - mSm.setDbg(VDBG); - mSm.start(); - - mDataPathMgr = new WifiAwareDataPathStateManager(this, clock); - mDataPathMgr.start(mContext, mSm.getHandler().getLooper(), awareMetrics, - wifiPermissionsUtil, permissionsWrapper, netdWrapper); - - mPowerManager = mContext.getSystemService(PowerManager.class); - mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); - mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_SCREEN_ON); - intentFilter.addAction(Intent.ACTION_SCREEN_OFF); - intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (mDbg) Log.v(TAG, "BroadcastReceiver: action=" + action); - if (action.equals(Intent.ACTION_SCREEN_ON) - || action.equals(Intent.ACTION_SCREEN_OFF)) { - reconfigure(); - } - - if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { - if (mSettableParameters.get(PARAM_ON_IDLE_DISABLE_AWARE) != 0) { - if (mPowerManager.isDeviceIdleMode()) { - disableUsage(); - } else { - enableUsage(); - } - } else { - reconfigure(); - } - } - } - }, intentFilter); - - intentFilter = new IntentFilter(); - intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mDbg) Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent); - if (wifiPermissionsUtil.isLocationModeEnabled()) { - enableUsage(); - } else { - disableUsage(); - } - } - }, intentFilter); - - intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - boolean isEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; - if (isEnabled) { - enableUsage(); - } else { - disableUsage(); - } - } - }, intentFilter); - } - - /** - * Initialize the late-initialization sub-services: depend on other services already existing. - */ - public void startLate() { - delayedInitialization(); - } - - /** - * Get the client state for the specified ID (or null if none exists). - */ - /* package */ WifiAwareClientState getClient(int clientId) { - return mClients.get(clientId); - } - - /** - * Get the capabilities. - */ - public Capabilities getCapabilities() { - return mCapabilities; - } - - /** - * Get the public characteristics derived from the capabilities. Use lazy initialization. - */ - public Characteristics getCharacteristics() { - if (mCharacteristics == null && mCapabilities != null) { - mCharacteristics = mCapabilities.toPublicCharacteristics(); - } - - return mCharacteristics; - } - - /* - * Cross-service API: synchronized but independent of state machine - */ - - /** - * Translate (and return in the callback) the peerId to its MAC address representation. - */ - public void requestMacAddresses(int uid, List<Integer> peerIds, - IWifiAwareMacAddressProvider callback) { - mSm.getHandler().post(() -> { - if (VDBG) Log.v(TAG, "requestMacAddresses: uid=" + uid + ", peerIds=" + peerIds); - Map<Integer, byte[]> peerIdToMacMap = new HashMap<>(); - for (int i = 0; i < mClients.size(); ++i) { - WifiAwareClientState client = mClients.valueAt(i); - if (client.getUid() != uid) { - continue; - } - - SparseArray<WifiAwareDiscoverySessionState> sessions = client.getSessions(); - for (int j = 0; j < sessions.size(); ++j) { - WifiAwareDiscoverySessionState session = sessions.valueAt(j); - - for (int peerId : peerIds) { - WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo( - peerId); - if (peerInfo != null) { - peerIdToMacMap.put(peerId, peerInfo.mMac); - } - } - } - } - - try { - if (mDbg) Log.v(TAG, "requestMacAddresses: peerIdToMacMap=" + peerIdToMacMap); - callback.macAddress(peerIdToMacMap); - } catch (RemoteException e) { - Log.e(TAG, "requestMacAddress (sync): exception on callback -- " + e); - - } - }); - } - - /* - * COMMANDS - */ - - /** - * Place a request for delayed start operation on the state machine queue. - */ - public void delayedInitialization() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_DELAYED_INITIALIZATION; - mSm.sendMessage(msg); - } - - /** - * Place a request to get the Wi-Fi Aware interface (before which no HAL command can be - * executed). - */ - public void getAwareInterface() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_GET_AWARE; - mSm.sendMessage(msg); - } - - /** - * Place a request to release the Wi-Fi Aware interface (after which no HAL command can be - * executed). - */ - public void releaseAwareInterface() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_RELEASE_AWARE; - mSm.sendMessage(msg); - } - - /** - * Place a request for a new client connection on the state machine queue. - */ - public void connect(int clientId, int uid, int pid, String callingPackage, - @Nullable String callingFeatureId, IWifiAwareEventCallback callback, - ConfigRequest configRequest, boolean notifyOnIdentityChanged) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_CONNECT; - msg.arg2 = clientId; - msg.obj = callback; - msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, configRequest); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_UID, uid); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_PID, pid); - msg.getData().putString(MESSAGE_BUNDLE_KEY_CALLING_PACKAGE, callingPackage); - msg.getData().putString(MESSAGE_BUNDLE_KEY_CALLING_FEATURE_ID, callingFeatureId); - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE, - notifyOnIdentityChanged); - mSm.sendMessage(msg); - } - - /** - * Place a request to disconnect (destroy) an existing client on the state - * machine queue. - */ - public void disconnect(int clientId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_DISCONNECT; - msg.arg2 = clientId; - mSm.sendMessage(msg); - } - - /** - * Place a request to reconfigure Aware. No additional input - intended to use current - * power settings when executed. Thus possibly entering or exiting power saving mode if - * needed (or do nothing if Aware is not active). - */ - public void reconfigure() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_RECONFIGURE; - mSm.sendMessage(msg); - } - - /** - * Place a request to stop a discovery session on the state machine queue. - */ - public void terminateSession(int clientId, int sessionId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_TERMINATE_SESSION; - msg.arg2 = clientId; - msg.obj = sessionId; - mSm.sendMessage(msg); - } - - /** - * Place a request to start a new publish discovery session on the state - * machine queue. - */ - public void publish(int clientId, PublishConfig publishConfig, - IWifiAwareDiscoverySessionCallback callback) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_PUBLISH; - msg.arg2 = clientId; - msg.obj = callback; - msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, publishConfig); - mSm.sendMessage(msg); - } - - /** - * Place a request to modify an existing publish discovery session on the - * state machine queue. - */ - public void updatePublish(int clientId, int sessionId, PublishConfig publishConfig) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_UPDATE_PUBLISH; - msg.arg2 = clientId; - msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, publishConfig); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId); - mSm.sendMessage(msg); - } - - /** - * Place a request to start a new subscribe discovery session on the state - * machine queue. - */ - public void subscribe(int clientId, SubscribeConfig subscribeConfig, - IWifiAwareDiscoverySessionCallback callback) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_SUBSCRIBE; - msg.arg2 = clientId; - msg.obj = callback; - msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, subscribeConfig); - mSm.sendMessage(msg); - } - - /** - * Place a request to modify an existing subscribe discovery session on the - * state machine queue. - */ - public void updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_UPDATE_SUBSCRIBE; - msg.arg2 = clientId; - msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, subscribeConfig); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId); - mSm.sendMessage(msg); - } - - /** - * Place a request to send a message on a discovery session on the state - * machine queue. - */ - public void sendMessage(int uid, int clientId, int sessionId, int peerId, byte[] message, - int messageId, int retryCount) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_ENQUEUE_SEND_MESSAGE; - msg.arg2 = clientId; - msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID, peerId); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID, messageId); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT, retryCount); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_UID, uid); - mSm.sendMessage(msg); - } - - /** - * Enable usage of Aware. Doesn't actually turn on Aware (form clusters) - that - * only happens when a connection is created. - */ - public void enableUsage() { - if (mSettableParameters.get(PARAM_ON_IDLE_DISABLE_AWARE) != 0 - && mPowerManager.isDeviceIdleMode()) { - if (mDbg) Log.d(TAG, "enableUsage(): while device is in IDLE mode - ignoring"); - return; - } - if (!mWifiPermissionsUtil.isLocationModeEnabled()) { - if (mDbg) Log.d(TAG, "enableUsage(): while location is disabled - ignoring"); - return; - } - if (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED) { - if (mDbg) Log.d(TAG, "enableUsage(): while Wi-Fi is disabled - ignoring"); - return; - } - if (!mWifiAwareNativeManager.isAwareNativeAvailable()) { - if (mDbg) Log.d(TAG, "enableUsage(): while Aware Native isn't Available - ignoring"); - return; - } - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_ENABLE_USAGE; - mSm.sendMessage(msg); - } - - /** - * Disable usage of Aware. Terminates all existing clients with onAwareDown(). - */ - public void disableUsage() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_DISABLE_USAGE; - mSm.sendMessage(msg); - } - - /** - * Checks whether Aware usage is enabled (not necessarily that Aware is up right - * now) or disabled. - * - * @return A boolean indicating whether Aware usage is enabled (true) or - * disabled (false). - */ - public boolean isUsageEnabled() { - return mUsageEnabled; - } - - /** - * Get the capabilities of the current Aware firmware. - */ - public void queryCapabilities() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_GET_CAPABILITIES; - mSm.sendMessage(msg); - } - - /** - * Create all Aware data path interfaces which are supported by the firmware capabilities. - */ - public void createAllDataPathInterfaces() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_CREATE_ALL_DATA_PATH_INTERFACES; - mSm.sendMessage(msg); - } - - /** - * delete all Aware data path interfaces. - */ - public void deleteAllDataPathInterfaces() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES; - mSm.sendMessage(msg); - } - - /** - * Create the specified data-path interface. Doesn't actually creates a data-path. - */ - public void createDataPathInterface(String interfaceName) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE; - msg.obj = interfaceName; - mSm.sendMessage(msg); - } - - /** - * Deletes the specified data-path interface. - */ - public void deleteDataPathInterface(String interfaceName) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE; - msg.obj = interfaceName; - mSm.sendMessage(msg); - } - - /** - * Command to initiate a data-path (executed by the initiator). - */ - public void initiateDataPathSetup(WifiAwareNetworkSpecifier networkSpecifier, int peerId, - int channelRequestType, int channel, byte[] peer, String interfaceName, byte[] pmk, - String passphrase, boolean isOutOfBand, byte[] appInfo) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_INITIATE_DATA_PATH_SETUP; - msg.obj = networkSpecifier; - msg.getData().putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE, channelRequestType); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_CHANNEL, channel); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peer); - msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PMK, pmk); - msg.getData().putString(MESSAGE_BUNDLE_KEY_PASSPHRASE, passphrase); - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_OOB, isOutOfBand); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_APP_INFO, appInfo); - mSm.sendMessage(msg); - } - - /** - * Command to respond to the data-path request (executed by the responder). - */ - public void respondToDataPathRequest(boolean accept, int ndpId, String interfaceName, - byte[] pmk, String passphrase, byte[] appInfo, boolean isOutOfBand) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST; - msg.arg2 = ndpId; - msg.obj = accept; - msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PMK, pmk); - msg.getData().putString(MESSAGE_BUNDLE_KEY_PASSPHRASE, passphrase); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_APP_INFO, appInfo); - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_OOB, isOutOfBand); - mSm.sendMessage(msg); - } - - /** - * Command to terminate the specified data-path. - */ - public void endDataPath(int ndpId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_END_DATA_PATH; - msg.arg2 = ndpId; - mSm.sendMessage(msg); - } - - /** - * Aware follow-on messages (L2 messages) are queued by the firmware for transmission - * on-the-air. The firmware has limited queue depth. The host queues all messages and doles - * them out to the firmware when possible. This command removes the next messages for - * transmission from the host queue and attempts to send it through the firmware. The queues - * are inspected when the command is executed - not when the command is placed on the handler - * (i.e. not evaluated here). - */ - private void transmitNextMessage() { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); - msg.arg1 = COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE; - mSm.sendMessage(msg); - } - - /* - * RESPONSES - */ - - /** - * Place a callback request on the state machine queue: configuration - * request completed (successfully). - */ - public void onConfigSuccessResponse(short transactionId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_CONFIG_SUCCESS; - msg.arg2 = transactionId; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: configuration - * request failed. - */ - public void onConfigFailedResponse(short transactionId, int reason) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_CONFIG_FAIL; - msg.arg2 = transactionId; - msg.obj = reason; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the stage machine queue: disable request finished - * (with the provided reason code). - */ - public void onDisableResponse(short transactionId, int reason) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_DISABLE; - msg.arg2 = transactionId; - msg.obj = reason; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: session - * configuration (new or update) request succeeded. - */ - public void onSessionConfigSuccessResponse(short transactionId, boolean isPublish, - byte pubSubId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS; - msg.arg2 = transactionId; - msg.obj = pubSubId; - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish); - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: session - * configuration (new or update) request failed. - */ - public void onSessionConfigFailResponse(short transactionId, boolean isPublish, int reason) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL; - msg.arg2 = transactionId; - msg.obj = reason; - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish); - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: message has been queued successfully. - */ - public void onMessageSendQueuedSuccessResponse(short transactionId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS; - msg.arg2 = transactionId; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: attempt to queue the message failed. - */ - public void onMessageSendQueuedFailResponse(short transactionId, int reason) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL; - msg.arg2 = transactionId; - msg.obj = reason; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: update vendor - * capabilities of the Aware stack. - */ - public void onCapabilitiesUpdateResponse(short transactionId, - Capabilities capabilities) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_CAPABILITIES_UPDATED; - msg.arg2 = transactionId; - msg.obj = capabilities; - mSm.sendMessage(msg); - } - - /** - * Places a callback request on the state machine queue: data-path interface creation command - * completed. - */ - public void onCreateDataPathInterfaceResponse(short transactionId, boolean success, - int reasonOnFailure) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_CREATE_INTERFACE; - msg.arg2 = transactionId; - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure); - mSm.sendMessage(msg); - } - - /** - * Places a callback request on the state machine queue: data-path interface deletion command - * completed. - */ - public void onDeleteDataPathInterfaceResponse(short transactionId, boolean success, - int reasonOnFailure) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_DELETE_INTERFACE; - msg.arg2 = transactionId; - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure); - mSm.sendMessage(msg); - } - - /** - * Response from firmware to initiateDataPathSetup(...). Indicates that command has started - * succesfully (not completed!). - */ - public void onInitiateDataPathResponseSuccess(short transactionId, int ndpId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS; - msg.arg2 = transactionId; - msg.obj = ndpId; - mSm.sendMessage(msg); - } - - /** - * Response from firmware to initiateDataPathSetup(...). - * Indicates that command has failed. - */ - public void onInitiateDataPathResponseFail(short transactionId, int reason) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL; - msg.arg2 = transactionId; - msg.obj = reason; - mSm.sendMessage(msg); - } - - /** - * Response from firmware to - * {@link #respondToDataPathRequest(boolean, int, String, byte[], String, boolean)} - */ - public void onRespondToDataPathSetupRequestResponse(short transactionId, boolean success, - int reasonOnFailure) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST; - msg.arg2 = transactionId; - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure); - mSm.sendMessage(msg); - } - - /** - * Response from firmware to {@link #endDataPath(int)}. - */ - public void onEndDataPathResponse(short transactionId, boolean success, int reasonOnFailure) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); - msg.arg1 = RESPONSE_TYPE_ON_END_DATA_PATH; - msg.arg2 = transactionId; - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure); - mSm.sendMessage(msg); - } - - /* - * NOTIFICATIONS - */ - - /** - * Place a callback request on the state machine queue: the discovery - * interface has changed. - */ - public void onInterfaceAddressChangeNotification(byte[] mac) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_INTERFACE_CHANGE; - msg.obj = mac; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: the cluster - * membership has changed (e.g. due to starting a new cluster or joining - * another cluster). - */ - public void onClusterChangeNotification(int flag, byte[] clusterId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_CLUSTER_CHANGE; - msg.arg2 = flag; - msg.obj = clusterId; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: a discovery match - * has occurred - e.g. our subscription discovered someone else publishing a - * matching service (to the one we were looking for). - */ - public void onMatchNotification(int pubSubId, int requestorInstanceId, byte[] peerMac, - byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndication, int rangeMm) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_MATCH; - msg.arg2 = pubSubId; - msg.getData().putInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID, requestorInstanceId); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_SSI_DATA, serviceSpecificInfo); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_FILTER_DATA, matchFilter); - msg.getData().putInt(MESSAGE_RANGING_INDICATION, rangingIndication); - msg.getData().putInt(MESSAGE_RANGE_MM, rangeMm); - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: a session (publish - * or subscribe) has terminated (per plan or due to an error). - */ - public void onSessionTerminatedNotification(int pubSubId, int reason, boolean isPublish) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_SESSION_TERMINATED; - msg.arg2 = pubSubId; - msg.obj = reason; - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish); - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: a message has been - * received as part of a discovery session. - */ - public void onMessageReceivedNotification(int pubSubId, int requestorInstanceId, byte[] peerMac, - byte[] message) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_MESSAGE_RECEIVED; - msg.arg2 = pubSubId; - msg.obj = requestorInstanceId; - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA, message); - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: Aware is going down. - */ - public void onAwareDownNotification(int reason) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_AWARE_DOWN; - msg.arg2 = reason; - mSm.sendMessage(msg); - } - - /** - * Notification that a message has been sent successfully (i.e. an ACK has been received). - */ - public void onMessageSendSuccessNotification(short transactionId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS; - msg.arg2 = transactionId; - mSm.sendMessage(msg); - } - - /** - * Notification that a message transmission has failed due to the indicated reason - e.g. no ACK - * was received. - */ - public void onMessageSendFailNotification(short transactionId, int reason) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL; - msg.arg2 = transactionId; - msg.obj = reason; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: data-path request (from peer) received. - */ - public void onDataPathRequestNotification(int pubSubId, byte[] mac, int ndpId, byte[] message) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST; - msg.arg2 = pubSubId; - msg.obj = ndpId; - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message); - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: data-path confirmation received - i.e. - * data-path is now up. - */ - public void onDataPathConfirmNotification(int ndpId, byte[] mac, boolean accept, int reason, - byte[] message, List<NanDataPathChannelInfo> channelInfo) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM; - msg.arg2 = ndpId; - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac); - msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, accept); - msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reason); - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA, message); - msg.obj = channelInfo; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: the specified data-path has been - * terminated. - */ - public void onDataPathEndNotification(int ndpId) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_END; - msg.arg2 = ndpId; - mSm.sendMessage(msg); - } - - /** - * Place a callback request on the state machine queue: schedule update for the specified - * data-paths. - */ - public void onDataPathScheduleUpdateNotification(byte[] peerMac, ArrayList<Integer> ndpIds, - List<NanDataPathChannelInfo> channelInfo) { - Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); - msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE; - msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac); - msg.getData().putIntegerArrayList(MESSAGE_BUNDLE_KEY_NDP_IDS, ndpIds); - msg.obj = channelInfo; - mSm.sendMessage(msg); - } - - /** - * State machine. - */ - @VisibleForTesting - class WifiAwareStateMachine extends StateMachine { - private static final int TRANSACTION_ID_IGNORE = 0; - - private DefaultState mDefaultState = new DefaultState(); - private WaitState mWaitState = new WaitState(); - private WaitForResponseState mWaitForResponseState = new WaitForResponseState(); - - private short mNextTransactionId = 1; - public int mNextSessionId = 1; - - private Message mCurrentCommand; - private short mCurrentTransactionId = TRANSACTION_ID_IGNORE; - - private static final long AWARE_SEND_MESSAGE_TIMEOUT = 10_000; - private static final int MESSAGE_QUEUE_DEPTH_PER_UID = 50; - private int mSendArrivalSequenceCounter = 0; - private boolean mSendQueueBlocked = false; - private final SparseArray<Message> mHostQueuedSendMessages = new SparseArray<>(); - private final Map<Short, Message> mFwQueuedSendMessages = new LinkedHashMap<>(); - private WakeupMessage mSendMessageTimeoutMessage = new WakeupMessage(mContext, getHandler(), - HAL_SEND_MESSAGE_TIMEOUT_TAG, MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT); - - private static final long AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT = 20_000; - private final Map<WifiAwareNetworkSpecifier, WakeupMessage> - mDataPathConfirmTimeoutMessages = new ArrayMap<>(); - - WifiAwareStateMachine(String name, Looper looper) { - super(name, looper); - - addState(mDefaultState); - /* --> */ addState(mWaitState, mDefaultState); - /* --> */ addState(mWaitForResponseState, mDefaultState); - - setInitialState(mWaitState); - } - - public void onAwareDownCleanupSendQueueState() { - mSendQueueBlocked = false; - mHostQueuedSendMessages.clear(); - mFwQueuedSendMessages.clear(); - } - - private class DefaultState extends State { - @Override - public boolean processMessage(Message msg) { - if (VDBG) { - Log.v(TAG, getName() + msg.toString()); - } - - switch (msg.what) { - case MESSAGE_TYPE_NOTIFICATION: - processNotification(msg); - return HANDLED; - case MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT: - processSendMessageTimeout(); - return HANDLED; - case MESSAGE_TYPE_DATA_PATH_TIMEOUT: { - WifiAwareNetworkSpecifier networkSpecifier = - (WifiAwareNetworkSpecifier) msg.obj; - - if (mDbg) { - Log.v(TAG, "MESSAGE_TYPE_DATA_PATH_TIMEOUT: networkSpecifier=" - + networkSpecifier); - } - - mDataPathMgr.handleDataPathTimeout(networkSpecifier); - mDataPathConfirmTimeoutMessages.remove(networkSpecifier); - return HANDLED; - } - default: - /* fall-through */ - } - - Log.wtf(TAG, - "DefaultState: should not get non-NOTIFICATION in this state: msg=" + msg); - return NOT_HANDLED; - } - } - - private class WaitState extends State { - @Override - public boolean processMessage(Message msg) { - if (VDBG) { - Log.v(TAG, getName() + msg.toString()); - } - - switch (msg.what) { - case MESSAGE_TYPE_COMMAND: - if (processCommand(msg)) { - transitionTo(mWaitForResponseState); - } - return HANDLED; - case MESSAGE_TYPE_RESPONSE: - /* fall-through */ - case MESSAGE_TYPE_RESPONSE_TIMEOUT: - /* - * remnants/delayed/out-of-sync messages - but let - * WaitForResponseState deal with them (identified as - * out-of-date by transaction ID). - */ - deferMessage(msg); - return HANDLED; - default: - /* fall-through */ - } - - return NOT_HANDLED; - } - } - - private class WaitForResponseState extends State { - private static final long AWARE_COMMAND_TIMEOUT = 5_000; - private WakeupMessage mTimeoutMessage; - - @Override - public void enter() { - mTimeoutMessage = new WakeupMessage(mContext, getHandler(), HAL_COMMAND_TIMEOUT_TAG, - MESSAGE_TYPE_RESPONSE_TIMEOUT, mCurrentCommand.arg1, mCurrentTransactionId); - mTimeoutMessage.schedule(SystemClock.elapsedRealtime() + AWARE_COMMAND_TIMEOUT); - } - - @Override - public void exit() { - mTimeoutMessage.cancel(); - } - - @Override - public boolean processMessage(Message msg) { - if (VDBG) { - Log.v(TAG, getName() + msg.toString()); - } - - switch (msg.what) { - case MESSAGE_TYPE_COMMAND: - /* - * don't want COMMANDs in this state - defer until back - * in WaitState - */ - deferMessage(msg); - return HANDLED; - case MESSAGE_TYPE_RESPONSE: - if (msg.arg2 == mCurrentTransactionId) { - processResponse(msg); - transitionTo(mWaitState); - } else { - Log.w(TAG, - "WaitForResponseState: processMessage: non-matching " - + "transaction ID on RESPONSE (a very late " - + "response) -- msg=" + msg); - /* no transition */ - } - return HANDLED; - case MESSAGE_TYPE_RESPONSE_TIMEOUT: - if (msg.arg2 == mCurrentTransactionId) { - processTimeout(msg); - transitionTo(mWaitState); - } else { - Log.w(TAG, "WaitForResponseState: processMessage: non-matching " - + "transaction ID on RESPONSE_TIMEOUT (either a non-cancelled " - + "timeout or a race condition with cancel) -- msg=" + msg); - /* no transition */ - } - return HANDLED; - default: - /* fall-through */ - } - - return NOT_HANDLED; - } - } - - private void processNotification(Message msg) { - if (VDBG) { - Log.v(TAG, "processNotification: msg=" + msg); - } - - switch (msg.arg1) { - case NOTIFICATION_TYPE_INTERFACE_CHANGE: { - byte[] mac = (byte[]) msg.obj; - - onInterfaceAddressChangeLocal(mac); - break; - } - case NOTIFICATION_TYPE_CLUSTER_CHANGE: { - int flag = msg.arg2; - byte[] clusterId = (byte[]) msg.obj; - - onClusterChangeLocal(flag, clusterId); - break; - } - case NOTIFICATION_TYPE_MATCH: { - int pubSubId = msg.arg2; - int requestorInstanceId = msg.getData() - .getInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID); - byte[] peerMac = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS); - byte[] serviceSpecificInfo = msg.getData() - .getByteArray(MESSAGE_BUNDLE_KEY_SSI_DATA); - byte[] matchFilter = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_FILTER_DATA); - int rangingIndication = msg.getData().getInt(MESSAGE_RANGING_INDICATION); - int rangeMm = msg.getData().getInt(MESSAGE_RANGE_MM); - - onMatchLocal(pubSubId, requestorInstanceId, peerMac, serviceSpecificInfo, - matchFilter, rangingIndication, rangeMm); - break; - } - case NOTIFICATION_TYPE_SESSION_TERMINATED: { - int pubSubId = msg.arg2; - int reason = (Integer) msg.obj; - boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE); - - onSessionTerminatedLocal(pubSubId, isPublish, reason); - break; - } - case NOTIFICATION_TYPE_MESSAGE_RECEIVED: { - int pubSubId = msg.arg2; - int requestorInstanceId = (Integer) msg.obj; - byte[] peerMac = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS); - byte[] message = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA); - - onMessageReceivedLocal(pubSubId, requestorInstanceId, peerMac, message); - break; - } - case NOTIFICATION_TYPE_AWARE_DOWN: { - int reason = msg.arg2; - - /* - * TODO: b/28615938. Use reason code to determine whether or not need clean-up - * local state (only needed if AWARE_DOWN is due to internal firmware reason, - * e.g. concurrency, rather than due to a requested shutdown). - */ - - onAwareDownLocal(); - if (reason != NanStatusType.SUCCESS) { - sendAwareStateChangedBroadcast(false); - } - break; - } - case NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: { - short transactionId = (short) msg.arg2; - Message queuedSendCommand = mFwQueuedSendMessages.get(transactionId); - if (VDBG) { - Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: queuedSendCommand=" - + queuedSendCommand); - } - if (queuedSendCommand == null) { - Log.w(TAG, - "processNotification: NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS:" - + " transactionId=" + transactionId - + " - no such queued send command (timed-out?)"); - } else { - mFwQueuedSendMessages.remove(transactionId); - updateSendMessageTimeout(); - onMessageSendSuccessLocal(queuedSendCommand); - } - mSendQueueBlocked = false; - transmitNextMessage(); - - break; - } - case NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: { - short transactionId = (short) msg.arg2; - int reason = (Integer) msg.obj; - Message sentMessage = mFwQueuedSendMessages.get(transactionId); - if (VDBG) { - Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: sentMessage=" - + sentMessage); - } - if (sentMessage == null) { - Log.w(TAG, - "processNotification: NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL:" - + " transactionId=" + transactionId - + " - no such queued send command (timed-out?)"); - } else { - mFwQueuedSendMessages.remove(transactionId); - updateSendMessageTimeout(); - - int retryCount = sentMessage.getData() - .getInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT); - if (retryCount > 0 && reason == NanStatusType.NO_OTA_ACK) { - if (mDbg) { - Log.v(TAG, - "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: transactionId=" - + transactionId + ", reason=" + reason - + ": retransmitting - retryCount=" + retryCount); - } - sentMessage.getData().putInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT, - retryCount - 1); - - int arrivalSeq = sentMessage.getData().getInt( - MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ); - mHostQueuedSendMessages.put(arrivalSeq, sentMessage); - } else { - onMessageSendFailLocal(sentMessage, reason); - } - mSendQueueBlocked = false; - transmitNextMessage(); - } - break; - } - case NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST: { - WifiAwareNetworkSpecifier networkSpecifier = mDataPathMgr.onDataPathRequest( - msg.arg2, msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS), - (int) msg.obj, msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE)); - - if (networkSpecifier != null) { - WakeupMessage timeout = new WakeupMessage(mContext, getHandler(), - HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_DATA_PATH_TIMEOUT, - 0, 0, networkSpecifier); - mDataPathConfirmTimeoutMessages.put(networkSpecifier, timeout); - timeout.schedule( - SystemClock.elapsedRealtime() + AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT); - } - - break; - } - case NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM: { - WifiAwareNetworkSpecifier networkSpecifier = mDataPathMgr.onDataPathConfirm( - msg.arg2, msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS), - msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), - msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE), - msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA), - (List<NanDataPathChannelInfo>) msg.obj); - - if (networkSpecifier != null) { - WakeupMessage timeout = mDataPathConfirmTimeoutMessages.remove( - networkSpecifier); - if (timeout != null) { - timeout.cancel(); - } - } - - break; - } - case NOTIFICATION_TYPE_ON_DATA_PATH_END: - mDataPathMgr.onDataPathEnd(msg.arg2); - break; - case NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE: - mDataPathMgr.onDataPathSchedUpdate( - msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS), - msg.getData().getIntegerArrayList(MESSAGE_BUNDLE_KEY_NDP_IDS), - (List<NanDataPathChannelInfo>) msg.obj); - break; - default: - Log.wtf(TAG, "processNotification: this isn't a NOTIFICATION -- msg=" + msg); - return; - } - } - - /** - * Execute the command specified by the input Message. Returns a true if - * need to wait for a RESPONSE, otherwise a false. We may not have to - * wait for a RESPONSE if there was an error in the state (so no command - * is sent to HAL) OR if we choose not to wait for response - e.g. for - * disconnected/terminate commands failure is not possible. - */ - private boolean processCommand(Message msg) { - if (VDBG) { - Log.v(TAG, "processCommand: msg=" + msg); - } - - if (mCurrentCommand != null) { - Log.wtf(TAG, - "processCommand: receiving a command (msg=" + msg - + ") but current (previous) command isn't null (prev_msg=" - + mCurrentCommand + ")"); - mCurrentCommand = null; - } - - mCurrentTransactionId = mNextTransactionId++; - - boolean waitForResponse = true; - - switch (msg.arg1) { - case COMMAND_TYPE_CONNECT: { - int clientId = msg.arg2; - IWifiAwareEventCallback callback = (IWifiAwareEventCallback) msg.obj; - ConfigRequest configRequest = (ConfigRequest) msg.getData() - .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); - int uid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_UID); - int pid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_PID); - String callingPackage = msg.getData().getString( - MESSAGE_BUNDLE_KEY_CALLING_PACKAGE); - String callingFeatureId = msg.getData().getString( - MESSAGE_BUNDLE_KEY_CALLING_FEATURE_ID); - boolean notifyIdentityChange = msg.getData().getBoolean( - MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE); - - waitForResponse = connectLocal(mCurrentTransactionId, clientId, uid, pid, - callingPackage, callingFeatureId, callback, configRequest, - notifyIdentityChange); - break; - } - case COMMAND_TYPE_DISCONNECT: { - int clientId = msg.arg2; - - waitForResponse = disconnectLocal(mCurrentTransactionId, clientId); - break; - } - case COMMAND_TYPE_RECONFIGURE: - waitForResponse = reconfigureLocal(mCurrentTransactionId); - break; - case COMMAND_TYPE_TERMINATE_SESSION: { - int clientId = msg.arg2; - int sessionId = (Integer) msg.obj; - - terminateSessionLocal(clientId, sessionId); - waitForResponse = false; - break; - } - case COMMAND_TYPE_PUBLISH: { - int clientId = msg.arg2; - IWifiAwareDiscoverySessionCallback callback = - (IWifiAwareDiscoverySessionCallback) msg.obj; - PublishConfig publishConfig = (PublishConfig) msg.getData() - .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); - - waitForResponse = publishLocal(mCurrentTransactionId, clientId, publishConfig, - callback); - break; - } - case COMMAND_TYPE_UPDATE_PUBLISH: { - int clientId = msg.arg2; - int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); - PublishConfig publishConfig = (PublishConfig) msg.getData() - .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); - waitForResponse = updatePublishLocal(mCurrentTransactionId, clientId, sessionId, - publishConfig); - break; - } - case COMMAND_TYPE_SUBSCRIBE: { - int clientId = msg.arg2; - IWifiAwareDiscoverySessionCallback callback = - (IWifiAwareDiscoverySessionCallback) msg.obj; - SubscribeConfig subscribeConfig = (SubscribeConfig) msg.getData() - .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); - - waitForResponse = subscribeLocal(mCurrentTransactionId, clientId, - subscribeConfig, callback); - break; - } - case COMMAND_TYPE_UPDATE_SUBSCRIBE: { - int clientId = msg.arg2; - int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); - SubscribeConfig subscribeConfig = (SubscribeConfig) msg.getData() - .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); - - waitForResponse = updateSubscribeLocal(mCurrentTransactionId, clientId, - sessionId, subscribeConfig); - break; - } - case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE: { - if (VDBG) { - Log.v(TAG, "processCommand: ENQUEUE_SEND_MESSAGE - messageId=" - + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID) - + ", mSendArrivalSequenceCounter=" + mSendArrivalSequenceCounter); - } - int uid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_UID); - if (isUidExceededMessageQueueDepthLimit(uid)) { - if (mDbg) { - Log.v(TAG, "message queue limit exceeded for uid=" + uid - + " at messageId=" - + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID)); - } - onMessageSendFailLocal(msg, NanStatusType.INTERNAL_FAILURE); - waitForResponse = false; - break; - } - Message sendMsg = obtainMessage(msg.what); - sendMsg.copyFrom(msg); - sendMsg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ, - mSendArrivalSequenceCounter); - mHostQueuedSendMessages.put(mSendArrivalSequenceCounter, sendMsg); - mSendArrivalSequenceCounter++; - waitForResponse = false; - - if (!mSendQueueBlocked) { - transmitNextMessage(); - } - - break; - } - case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE: { - if (mSendQueueBlocked || mHostQueuedSendMessages.size() == 0) { - if (VDBG) { - Log.v(TAG, "processCommand: SEND_TOP_OF_QUEUE_MESSAGE - blocked or " - + "empty host queue"); - } - waitForResponse = false; - } else { - if (VDBG) { - Log.v(TAG, "processCommand: SEND_TOP_OF_QUEUE_MESSAGE - " - + "sendArrivalSequenceCounter=" - + mHostQueuedSendMessages.keyAt(0)); - } - Message sendMessage = mHostQueuedSendMessages.valueAt(0); - mHostQueuedSendMessages.removeAt(0); - - Bundle data = sendMessage.getData(); - int clientId = sendMessage.arg2; - int sessionId = sendMessage.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); - int peerId = data.getInt(MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID); - byte[] message = data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE); - int messageId = data.getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID); - - msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_SENT_MESSAGE, sendMessage); - - waitForResponse = sendFollowonMessageLocal(mCurrentTransactionId, clientId, - sessionId, peerId, message, messageId); - } - break; - } - case COMMAND_TYPE_ENABLE_USAGE: - enableUsageLocal(); - waitForResponse = false; - break; - case COMMAND_TYPE_DISABLE_USAGE: - waitForResponse = disableUsageLocal(mCurrentTransactionId); - break; - case COMMAND_TYPE_GET_CAPABILITIES: - if (mCapabilities == null) { - waitForResponse = mWifiAwareNativeApi.getCapabilities( - mCurrentTransactionId); - } else { - if (VDBG) { - Log.v(TAG, "COMMAND_TYPE_GET_CAPABILITIES: already have capabilities - " - + "skipping"); - } - waitForResponse = false; - } - break; - case COMMAND_TYPE_CREATE_ALL_DATA_PATH_INTERFACES: - mDataPathMgr.createAllInterfaces(); - waitForResponse = false; - break; - case COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES: - mDataPathMgr.deleteAllInterfaces(); - waitForResponse = false; - break; - case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE: - waitForResponse = mWifiAwareNativeApi.createAwareNetworkInterface( - mCurrentTransactionId, (String) msg.obj); - break; - case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE: - waitForResponse = mWifiAwareNativeApi.deleteAwareNetworkInterface( - mCurrentTransactionId, (String) msg.obj); - break; - case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP: { - Bundle data = msg.getData(); - - WifiAwareNetworkSpecifier networkSpecifier = - (WifiAwareNetworkSpecifier) msg.obj; - - int peerId = data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID); - int channelRequestType = data.getInt(MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE); - int channel = data.getInt(MESSAGE_BUNDLE_KEY_CHANNEL); - byte[] peer = data.getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS); - String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME); - byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PMK); - String passphrase = data.getString(MESSAGE_BUNDLE_KEY_PASSPHRASE); - boolean isOutOfBand = data.getBoolean(MESSAGE_BUNDLE_KEY_OOB); - byte[] appInfo = data.getByteArray(MESSAGE_BUNDLE_KEY_APP_INFO); - - waitForResponse = initiateDataPathSetupLocal(mCurrentTransactionId, - networkSpecifier, peerId, channelRequestType, channel, peer, - interfaceName, pmk, passphrase, isOutOfBand, appInfo); - - if (waitForResponse) { - WakeupMessage timeout = new WakeupMessage(mContext, getHandler(), - HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_DATA_PATH_TIMEOUT, - 0, 0, networkSpecifier); - mDataPathConfirmTimeoutMessages.put(networkSpecifier, timeout); - timeout.schedule( - SystemClock.elapsedRealtime() + AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT); - } - break; - } - case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST: { - Bundle data = msg.getData(); - - int ndpId = msg.arg2; - boolean accept = (boolean) msg.obj; - String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME); - byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PMK); - String passphrase = data.getString(MESSAGE_BUNDLE_KEY_PASSPHRASE); - byte[] appInfo = data.getByteArray(MESSAGE_BUNDLE_KEY_APP_INFO); - boolean isOutOfBand = data.getBoolean(MESSAGE_BUNDLE_KEY_OOB); - - waitForResponse = respondToDataPathRequestLocal(mCurrentTransactionId, accept, - ndpId, interfaceName, pmk, passphrase, appInfo, isOutOfBand); - - break; - } - case COMMAND_TYPE_END_DATA_PATH: - waitForResponse = endDataPathLocal(mCurrentTransactionId, msg.arg2); - break; - case COMMAND_TYPE_DELAYED_INITIALIZATION: - mWifiAwareNativeManager.start(getHandler()); - waitForResponse = false; - break; - case COMMAND_TYPE_GET_AWARE: - mWifiAwareNativeManager.tryToGetAware(); - waitForResponse = false; - break; - case COMMAND_TYPE_RELEASE_AWARE: - mWifiAwareNativeManager.releaseAware(); - waitForResponse = false; - break; - default: - waitForResponse = false; - Log.wtf(TAG, "processCommand: this isn't a COMMAND -- msg=" + msg); - /* fall-through */ - } - - if (!waitForResponse) { - mCurrentTransactionId = TRANSACTION_ID_IGNORE; - } else { - mCurrentCommand = obtainMessage(msg.what); - mCurrentCommand.copyFrom(msg); - } - - return waitForResponse; - } - - private void processResponse(Message msg) { - if (VDBG) { - Log.v(TAG, "processResponse: msg=" + msg); - } - - if (mCurrentCommand == null) { - Log.wtf(TAG, "processResponse: no existing command stored!? msg=" + msg); - mCurrentTransactionId = TRANSACTION_ID_IGNORE; - return; - } - - switch (msg.arg1) { - case RESPONSE_TYPE_ON_CONFIG_SUCCESS: - onConfigCompletedLocal(mCurrentCommand); - break; - case RESPONSE_TYPE_ON_CONFIG_FAIL: { - int reason = (Integer) msg.obj; - - onConfigFailedLocal(mCurrentCommand, reason); - break; - } - case RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS: { - byte pubSubId = (Byte) msg.obj; - boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE); - - onSessionConfigSuccessLocal(mCurrentCommand, pubSubId, isPublish); - break; - } - case RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL: { - int reason = (Integer) msg.obj; - boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE); - - onSessionConfigFailLocal(mCurrentCommand, isPublish, reason); - break; - } - case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS: { - Message sentMessage = mCurrentCommand.getData().getParcelable( - MESSAGE_BUNDLE_KEY_SENT_MESSAGE); - sentMessage.getData().putLong(MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME, - SystemClock.elapsedRealtime()); - mFwQueuedSendMessages.put(mCurrentTransactionId, sentMessage); - updateSendMessageTimeout(); - if (!mSendQueueBlocked) { - transmitNextMessage(); - } - - if (VDBG) { - Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_SUCCESS - arrivalSeq=" - + sentMessage.getData().getInt( - MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ)); - } - break; - } - case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL: { - if (VDBG) { - Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - blocking!"); - } - int reason = (Integer) msg.obj; - if (reason == NanStatusType.FOLLOWUP_TX_QUEUE_FULL) { - Message sentMessage = mCurrentCommand.getData().getParcelable( - MESSAGE_BUNDLE_KEY_SENT_MESSAGE); - int arrivalSeq = sentMessage.getData().getInt( - MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ); - mHostQueuedSendMessages.put(arrivalSeq, sentMessage); - mSendQueueBlocked = true; - - if (VDBG) { - Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - arrivalSeq=" - + arrivalSeq + " -- blocking"); - } - } else { - Message sentMessage = mCurrentCommand.getData().getParcelable( - MESSAGE_BUNDLE_KEY_SENT_MESSAGE); - onMessageSendFailLocal(sentMessage, NanStatusType.INTERNAL_FAILURE); - if (!mSendQueueBlocked) { - transmitNextMessage(); - } - } - break; - } - case RESPONSE_TYPE_ON_CAPABILITIES_UPDATED: { - onCapabilitiesUpdatedResponseLocal((Capabilities) msg.obj); - break; - } - case RESPONSE_TYPE_ON_CREATE_INTERFACE: - onCreateDataPathInterfaceResponseLocal(mCurrentCommand, - msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), - msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE)); - break; - case RESPONSE_TYPE_ON_DELETE_INTERFACE: - onDeleteDataPathInterfaceResponseLocal(mCurrentCommand, - msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), - msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE)); - break; - case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS: - onInitiateDataPathResponseSuccessLocal(mCurrentCommand, (int) msg.obj); - break; - case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL: - onInitiateDataPathResponseFailLocal(mCurrentCommand, (int) msg.obj); - break; - case RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST: - onRespondToDataPathSetupRequestResponseLocal(mCurrentCommand, - msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), - msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE)); - break; - case RESPONSE_TYPE_ON_END_DATA_PATH: - onEndPathEndResponseLocal(mCurrentCommand, - msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), - msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE)); - break; - case RESPONSE_TYPE_ON_DISABLE: - onDisableResponseLocal(mCurrentCommand, (Integer) msg.obj); - break; - default: - Log.wtf(TAG, "processResponse: this isn't a RESPONSE -- msg=" + msg); - mCurrentCommand = null; - mCurrentTransactionId = TRANSACTION_ID_IGNORE; - return; - } - - mCurrentCommand = null; - mCurrentTransactionId = TRANSACTION_ID_IGNORE; - } - - private void processTimeout(Message msg) { - if (mDbg) { - Log.v(TAG, "processTimeout: msg=" + msg); - } - - if (mCurrentCommand == null) { - Log.wtf(TAG, "processTimeout: no existing command stored!? msg=" + msg); - mCurrentTransactionId = TRANSACTION_ID_IGNORE; - return; - } - - /* - * Only have to handle those COMMANDs which wait for a response. - */ - switch (msg.arg1) { - case COMMAND_TYPE_CONNECT: - case COMMAND_TYPE_DISCONNECT: - onConfigFailedLocal(mCurrentCommand, NanStatusType.INTERNAL_FAILURE); - break; - - case COMMAND_TYPE_RECONFIGURE: - /* - * Reconfigure timed-out. There is nothing to do but log the issue - which - * will be done in the callback. - */ - onConfigFailedLocal(mCurrentCommand, NanStatusType.INTERNAL_FAILURE); - break; - case COMMAND_TYPE_TERMINATE_SESSION: { - Log.wtf(TAG, "processTimeout: TERMINATE_SESSION - shouldn't be waiting!"); - break; - } - case COMMAND_TYPE_PUBLISH: - case COMMAND_TYPE_UPDATE_PUBLISH: { - onSessionConfigFailLocal(mCurrentCommand, true, NanStatusType.INTERNAL_FAILURE); - break; - } - case COMMAND_TYPE_SUBSCRIBE: - case COMMAND_TYPE_UPDATE_SUBSCRIBE: { - onSessionConfigFailLocal(mCurrentCommand, false, - NanStatusType.INTERNAL_FAILURE); - break; - } - case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE: { - Log.wtf(TAG, "processTimeout: ENQUEUE_SEND_MESSAGE - shouldn't be waiting!"); - break; - } - case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE: { - Message sentMessage = mCurrentCommand.getData().getParcelable( - MESSAGE_BUNDLE_KEY_SENT_MESSAGE); - onMessageSendFailLocal(sentMessage, NanStatusType.INTERNAL_FAILURE); - mSendQueueBlocked = false; - transmitNextMessage(); - break; - } - case COMMAND_TYPE_ENABLE_USAGE: - Log.wtf(TAG, "processTimeout: ENABLE_USAGE - shouldn't be waiting!"); - break; - case COMMAND_TYPE_DISABLE_USAGE: - Log.wtf(TAG, "processTimeout: DISABLE_USAGE - shouldn't be waiting!"); - break; - case COMMAND_TYPE_GET_CAPABILITIES: - Log.e(TAG, - "processTimeout: GET_CAPABILITIES timed-out - strange, will try again" - + " when next enabled!?"); - break; - case COMMAND_TYPE_CREATE_ALL_DATA_PATH_INTERFACES: - Log.wtf(TAG, - "processTimeout: CREATE_ALL_DATA_PATH_INTERFACES - shouldn't be " - + "waiting!"); - break; - case COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES: - Log.wtf(TAG, - "processTimeout: DELETE_ALL_DATA_PATH_INTERFACES - shouldn't be " - + "waiting!"); - break; - case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE: - // TODO: fix status: timeout - onCreateDataPathInterfaceResponseLocal(mCurrentCommand, false, 0); - break; - case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE: - // TODO: fix status: timeout - onDeleteDataPathInterfaceResponseLocal(mCurrentCommand, false, 0); - break; - case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP: - // TODO: fix status: timeout - onInitiateDataPathResponseFailLocal(mCurrentCommand, 0); - break; - case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST: - // TODO: fix status: timeout - onRespondToDataPathSetupRequestResponseLocal(mCurrentCommand, false, 0); - break; - case COMMAND_TYPE_END_DATA_PATH: - // TODO: fix status: timeout - onEndPathEndResponseLocal(mCurrentCommand, false, 0); - break; - case COMMAND_TYPE_DELAYED_INITIALIZATION: - Log.wtf(TAG, - "processTimeout: COMMAND_TYPE_DELAYED_INITIALIZATION - shouldn't be " - + "waiting!"); - break; - case COMMAND_TYPE_GET_AWARE: - Log.wtf(TAG, - "processTimeout: COMMAND_TYPE_GET_AWARE - shouldn't be waiting!"); - break; - case COMMAND_TYPE_RELEASE_AWARE: - Log.wtf(TAG, - "processTimeout: COMMAND_TYPE_RELEASE_AWARE - shouldn't be waiting!"); - break; - default: - Log.wtf(TAG, "processTimeout: this isn't a COMMAND -- msg=" + msg); - /* fall-through */ - } - - mCurrentCommand = null; - mCurrentTransactionId = TRANSACTION_ID_IGNORE; - } - - private void updateSendMessageTimeout() { - if (VDBG) { - Log.v(TAG, "updateSendMessageTimeout: mHostQueuedSendMessages.size()=" - + mHostQueuedSendMessages.size() + ", mFwQueuedSendMessages.size()=" - + mFwQueuedSendMessages.size() + ", mSendQueueBlocked=" - + mSendQueueBlocked); - } - Iterator<Message> it = mFwQueuedSendMessages.values().iterator(); - if (it.hasNext()) { - /* - * Schedule timeout based on the first message in the queue (which is the earliest - * submitted message). Timeout = queuing time + timeout constant. - */ - Message msg = it.next(); - mSendMessageTimeoutMessage.schedule( - msg.getData().getLong(MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME) - + AWARE_SEND_MESSAGE_TIMEOUT); - } else { - mSendMessageTimeoutMessage.cancel(); - } - } - - private void processSendMessageTimeout() { - if (mDbg) { - Log.v(TAG, "processSendMessageTimeout: mHostQueuedSendMessages.size()=" - + mHostQueuedSendMessages.size() + ", mFwQueuedSendMessages.size()=" - + mFwQueuedSendMessages.size() + ", mSendQueueBlocked=" - + mSendQueueBlocked); - - } - /* - * Note: using 'first' to always time-out (remove) at least 1 notification (partially) - * due to test code needs: there's no way to mock elapsedRealtime(). TODO: replace with - * injected getClock() once moved off of mmwd. - */ - boolean first = true; - long currentTime = SystemClock.elapsedRealtime(); - Iterator<Map.Entry<Short, Message>> it = mFwQueuedSendMessages.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<Short, Message> entry = it.next(); - short transactionId = entry.getKey(); - Message message = entry.getValue(); - long messageEnqueueTime = message.getData().getLong( - MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME); - if (first || messageEnqueueTime + AWARE_SEND_MESSAGE_TIMEOUT <= currentTime) { - if (mDbg) { - Log.v(TAG, "processSendMessageTimeout: expiring - transactionId=" - + transactionId + ", message=" + message - + ", due to messageEnqueueTime=" + messageEnqueueTime - + ", currentTime=" + currentTime); - } - onMessageSendFailLocal(message, NanStatusType.INTERNAL_FAILURE); - it.remove(); - first = false; - } else { - break; - } - } - updateSendMessageTimeout(); - mSendQueueBlocked = false; - transmitNextMessage(); - } - - private boolean isUidExceededMessageQueueDepthLimit(int uid) { - int size = mHostQueuedSendMessages.size(); - int numOfMessages = 0; - if (size < MESSAGE_QUEUE_DEPTH_PER_UID) { - return false; - } - for (int i = 0; i < size; ++i) { - if (mHostQueuedSendMessages.valueAt(i).getData() - .getInt(MESSAGE_BUNDLE_KEY_UID) == uid) { - numOfMessages++; - if (numOfMessages >= MESSAGE_QUEUE_DEPTH_PER_UID) { - return true; - } - } - } - return false; - } - - @Override - protected String getLogRecString(Message msg) { - StringBuilder sb = new StringBuilder(WifiAwareStateManager.messageToString(msg)); - - if (msg.what == MESSAGE_TYPE_COMMAND - && mCurrentTransactionId != TRANSACTION_ID_IGNORE) { - sb.append(" (Transaction ID=").append(mCurrentTransactionId).append(")"); - } - - return sb.toString(); - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("WifiAwareStateMachine:"); - pw.println(" mNextTransactionId: " + mNextTransactionId); - pw.println(" mNextSessionId: " + mNextSessionId); - pw.println(" mCurrentCommand: " + mCurrentCommand); - pw.println(" mCurrentTransaction: " + mCurrentTransactionId); - pw.println(" mSendQueueBlocked: " + mSendQueueBlocked); - pw.println(" mSendArrivalSequenceCounter: " + mSendArrivalSequenceCounter); - pw.println(" mHostQueuedSendMessages: [" + mHostQueuedSendMessages + "]"); - pw.println(" mFwQueuedSendMessages: [" + mFwQueuedSendMessages + "]"); - super.dump(fd, pw, args); - } - } - - private void sendAwareStateChangedBroadcast(boolean enabled) { - if (VDBG) { - Log.v(TAG, "sendAwareStateChangedBroadcast: enabled=" + enabled); - } - final Intent intent = new Intent(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - /* - * COMMANDS - */ - - private boolean connectLocal(short transactionId, int clientId, int uid, int pid, - String callingPackage, @Nullable String callingFeatureId, - IWifiAwareEventCallback callback, ConfigRequest configRequest, - boolean notifyIdentityChange) { - if (VDBG) { - Log.v(TAG, "connectLocal(): transactionId=" + transactionId + ", clientId=" + clientId - + ", uid=" + uid + ", pid=" + pid + ", callingPackage=" + callingPackage - + ", callback=" + callback + ", configRequest=" + configRequest - + ", notifyIdentityChange=" + notifyIdentityChange); - } - - if (!mUsageEnabled) { - Log.w(TAG, "connect(): called with mUsageEnabled=false"); - try { - callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); - mAwareMetrics.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e); - } - return false; - } - - if (mClients.get(clientId) != null) { - Log.e(TAG, "connectLocal: entry already exists for clientId=" + clientId); - } - - if (VDBG) { - Log.v(TAG, "mCurrentAwareConfiguration=" + mCurrentAwareConfiguration - + ", mCurrentIdentityNotification=" + mCurrentIdentityNotification); - } - - ConfigRequest merged = mergeConfigRequests(configRequest); - if (merged == null) { - Log.e(TAG, "connectLocal: requested configRequest=" + configRequest - + ", incompatible with current configurations"); - try { - callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); - mAwareMetrics.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e); - } - return false; - } else if (VDBG) { - Log.v(TAG, "connectLocal: merged=" + merged); - } - - if (mCurrentAwareConfiguration != null && mCurrentAwareConfiguration.equals(merged) - && (mCurrentIdentityNotification || !notifyIdentityChange)) { - try { - callback.onConnectSuccess(clientId); - } catch (RemoteException e) { - Log.w(TAG, "connectLocal onConnectSuccess(): RemoteException (FYI): " + e); - } - WifiAwareClientState client = new WifiAwareClientState(mContext, clientId, uid, pid, - callingPackage, callingFeatureId, callback, configRequest, notifyIdentityChange, - SystemClock.elapsedRealtime(), mWifiPermissionsUtil); - client.enableVerboseLogging(mDbg); - client.onInterfaceAddressChange(mCurrentDiscoveryInterfaceMac); - mClients.append(clientId, client); - mAwareMetrics.recordAttachSession(uid, notifyIdentityChange, mClients); - return false; - } - boolean notificationRequired = - doesAnyClientNeedIdentityChangeNotifications() || notifyIdentityChange; - - if (mCurrentAwareConfiguration == null) { - mWifiAwareNativeManager.tryToGetAware(); - } - - boolean success = mWifiAwareNativeApi.enableAndConfigure(transactionId, merged, - notificationRequired, mCurrentAwareConfiguration == null, - mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode(), - mCurrentRangingEnabled); - if (!success) { - try { - callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); - mAwareMetrics.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e); - } - } - - return success; - } - - private boolean disconnectLocal(short transactionId, int clientId) { - if (VDBG) { - Log.v(TAG, - "disconnectLocal(): transactionId=" + transactionId + ", clientId=" + clientId); - } - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "disconnectLocal: no entry for clientId=" + clientId); - return false; - } - mClients.delete(clientId); - mAwareMetrics.recordAttachSessionDuration(client.getCreationTime()); - SparseArray<WifiAwareDiscoverySessionState> sessions = client.getSessions(); - for (int i = 0; i < sessions.size(); ++i) { - mAwareMetrics.recordDiscoverySessionDuration(sessions.valueAt(i).getCreationTime(), - sessions.valueAt(i).isPublishSession()); - } - client.destroy(); - - if (mClients.size() == 0) { - mCurrentAwareConfiguration = null; - deleteAllDataPathInterfaces(); - return mWifiAwareNativeApi.disable(transactionId); - } - - ConfigRequest merged = mergeConfigRequests(null); - if (merged == null) { - Log.wtf(TAG, "disconnectLocal: got an incompatible merge on remaining configs!?"); - return false; - } - boolean notificationReqs = doesAnyClientNeedIdentityChangeNotifications(); - boolean rangingEnabled = doesAnyClientNeedRanging(); - if (merged.equals(mCurrentAwareConfiguration) - && mCurrentIdentityNotification == notificationReqs - && mCurrentRangingEnabled == rangingEnabled) { - return false; - } - - return mWifiAwareNativeApi.enableAndConfigure(transactionId, merged, notificationReqs, - false, mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode(), - rangingEnabled); - } - - private boolean reconfigureLocal(short transactionId) { - if (VDBG) Log.v(TAG, "reconfigureLocal(): transactionId=" + transactionId); - - if (mClients.size() == 0) { - // no clients - Aware is not enabled, nothing to reconfigure - return false; - } - - boolean notificationReqs = doesAnyClientNeedIdentityChangeNotifications(); - boolean rangingEnabled = doesAnyClientNeedRanging(); - - return mWifiAwareNativeApi.enableAndConfigure(transactionId, mCurrentAwareConfiguration, - notificationReqs, false, mPowerManager.isInteractive(), - mPowerManager.isDeviceIdleMode(), rangingEnabled); - } - - private void terminateSessionLocal(int clientId, int sessionId) { - if (VDBG) { - Log.v(TAG, - "terminateSessionLocal(): clientId=" + clientId + ", sessionId=" + sessionId); - } - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "terminateSession: no client exists for clientId=" + clientId); - return; - } - - WifiAwareDiscoverySessionState session = client.terminateSession(sessionId); - // If Ranging enabled require changes, reconfigure. - if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) { - reconfigure(); - } - if (session != null) { - mAwareMetrics.recordDiscoverySessionDuration(session.getCreationTime(), - session.isPublishSession()); - } - } - - private boolean publishLocal(short transactionId, int clientId, PublishConfig publishConfig, - IWifiAwareDiscoverySessionCallback callback) { - if (VDBG) { - Log.v(TAG, "publishLocal(): transactionId=" + transactionId + ", clientId=" + clientId - + ", publishConfig=" + publishConfig + ", callback=" + callback); - } - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "publishLocal: no client exists for clientId=" + clientId); - return false; - } - - boolean success = mWifiAwareNativeApi.publish(transactionId, (byte) 0, publishConfig); - if (!success) { - try { - callback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.w(TAG, "publishLocal onSessionConfigFail(): RemoteException (FYI): " + e); - } - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.INTERNAL_FAILURE, - true); - } - - return success; - } - - private boolean updatePublishLocal(short transactionId, int clientId, int sessionId, - PublishConfig publishConfig) { - if (VDBG) { - Log.v(TAG, "updatePublishLocal(): transactionId=" + transactionId + ", clientId=" - + clientId + ", sessionId=" + sessionId + ", publishConfig=" + publishConfig); - } - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "updatePublishLocal: no client exists for clientId=" + clientId); - return false; - } - - WifiAwareDiscoverySessionState session = client.getSession(sessionId); - if (session == null) { - Log.e(TAG, "updatePublishLocal: no session exists for clientId=" + clientId - + ", sessionId=" + sessionId); - return false; - } - - boolean status = session.updatePublish(transactionId, publishConfig); - if (!status) { - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.INTERNAL_FAILURE, - true); - } - return status; - } - - private boolean subscribeLocal(short transactionId, int clientId, - SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback) { - if (VDBG) { - Log.v(TAG, "subscribeLocal(): transactionId=" + transactionId + ", clientId=" + clientId - + ", subscribeConfig=" + subscribeConfig + ", callback=" + callback); - } - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "subscribeLocal: no client exists for clientId=" + clientId); - return false; - } - - boolean success = mWifiAwareNativeApi.subscribe(transactionId, (byte) 0, subscribeConfig); - if (!success) { - try { - callback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - } catch (RemoteException e) { - Log.w(TAG, "subscribeLocal onSessionConfigFail(): RemoteException (FYI): " + e); - } - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.INTERNAL_FAILURE, - false); - } - - return success; - } - - private boolean updateSubscribeLocal(short transactionId, int clientId, int sessionId, - SubscribeConfig subscribeConfig) { - if (VDBG) { - Log.v(TAG, - "updateSubscribeLocal(): transactionId=" + transactionId + ", clientId=" - + clientId + ", sessionId=" + sessionId + ", subscribeConfig=" - + subscribeConfig); - } - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "updateSubscribeLocal: no client exists for clientId=" + clientId); - return false; - } - - WifiAwareDiscoverySessionState session = client.getSession(sessionId); - if (session == null) { - Log.e(TAG, "updateSubscribeLocal: no session exists for clientId=" + clientId - + ", sessionId=" + sessionId); - return false; - } - - boolean status = session.updateSubscribe(transactionId, subscribeConfig); - if (!status) { - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.INTERNAL_FAILURE, - false); - } - return status; - } - - private boolean sendFollowonMessageLocal(short transactionId, int clientId, int sessionId, - int peerId, byte[] message, int messageId) { - if (VDBG) { - Log.v(TAG, - "sendFollowonMessageLocal(): transactionId=" + transactionId + ", clientId=" - + clientId + ", sessionId=" + sessionId + ", peerId=" + peerId - + ", messageId=" + messageId); - } - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "sendFollowonMessageLocal: no client exists for clientId=" + clientId); - return false; - } - - WifiAwareDiscoverySessionState session = client.getSession(sessionId); - if (session == null) { - Log.e(TAG, "sendFollowonMessageLocal: no session exists for clientId=" + clientId - + ", sessionId=" + sessionId); - return false; - } - - return session.sendMessage(transactionId, peerId, message, messageId); - } - - private void enableUsageLocal() { - if (VDBG) Log.v(TAG, "enableUsageLocal: mUsageEnabled=" + mUsageEnabled); - - if (mCapabilities == null) { - getAwareInterface(); - queryCapabilities(); - releaseAwareInterface(); - } - - if (mUsageEnabled) { - return; - } - mUsageEnabled = true; - sendAwareStateChangedBroadcast(true); - - mAwareMetrics.recordEnableUsage(); - } - - private boolean disableUsageLocal(short transactionId) { - if (VDBG) { - Log.v(TAG, "disableUsageLocal: transactionId=" + transactionId + ", mUsageEnabled=" - + mUsageEnabled); - } - - if (!mUsageEnabled) { - return false; - } - - onAwareDownLocal(); - - mUsageEnabled = false; - boolean callDispatched = mWifiAwareNativeApi.disable(transactionId); - - sendAwareStateChangedBroadcast(false); - - mAwareMetrics.recordDisableUsage(); - - return callDispatched; - } - - private boolean initiateDataPathSetupLocal(short transactionId, - WifiAwareNetworkSpecifier networkSpecifier, int peerId, int channelRequestType, - int channel, byte[] peer, String interfaceName, byte[] pmk, String passphrase, - boolean isOutOfBand, byte[] appInfo) { - if (VDBG) { - Log.v(TAG, "initiateDataPathSetupLocal(): transactionId=" + transactionId - + ", networkSpecifier=" + networkSpecifier + ", peerId=" + peerId - + ", channelRequestType=" + channelRequestType + ", channel=" + channel - + ", peer=" - + String.valueOf(HexEncoding.encode(peer)) + ", interfaceName=" + interfaceName - + ", pmk=" + ((pmk == null) ? "" : "*") + ", passphrase=" + ( - (passphrase == null) ? "" : "*") + ", isOutOfBand=" - + isOutOfBand + ", appInfo=" + (appInfo == null ? "<null>" : "<non-null>")); - } - - boolean success = mWifiAwareNativeApi.initiateDataPath(transactionId, peerId, - channelRequestType, channel, peer, interfaceName, pmk, passphrase, isOutOfBand, - appInfo, mCapabilities); - if (!success) { - mDataPathMgr.onDataPathInitiateFail(networkSpecifier, NanStatusType.INTERNAL_FAILURE); - } - - return success; - } - - private boolean respondToDataPathRequestLocal(short transactionId, boolean accept, - int ndpId, String interfaceName, byte[] pmk, String passphrase, byte[] appInfo, - boolean isOutOfBand) { - if (VDBG) { - Log.v(TAG, - "respondToDataPathRequestLocal(): transactionId=" + transactionId + ", accept=" - + accept + ", ndpId=" + ndpId + ", interfaceName=" + interfaceName - + ", pmk=" + ((pmk == null) ? "" : "*") + ", passphrase=" - + ((passphrase == null) ? "" : "*") + ", isOutOfBand=" - + isOutOfBand + ", appInfo=" + (appInfo == null ? "<null>" - : "<non-null>")); - } - boolean success = mWifiAwareNativeApi.respondToDataPathRequest(transactionId, accept, ndpId, - interfaceName, pmk, passphrase, appInfo, isOutOfBand, mCapabilities); - if (!success) { - mDataPathMgr.onRespondToDataPathRequest(ndpId, false, NanStatusType.INTERNAL_FAILURE); - } - return success; - } - - private boolean endDataPathLocal(short transactionId, int ndpId) { - if (VDBG) { - Log.v(TAG, - "endDataPathLocal: transactionId=" + transactionId + ", ndpId=" + ndpId); - } - - return mWifiAwareNativeApi.endDataPath(transactionId, ndpId); - } - - /* - * RESPONSES - */ - - private void onConfigCompletedLocal(Message completedCommand) { - if (VDBG) { - Log.v(TAG, "onConfigCompleted: completedCommand=" + completedCommand); - } - - if (completedCommand.arg1 == COMMAND_TYPE_CONNECT) { - if (mCurrentAwareConfiguration == null) { // enabled (as opposed to re-configured) - createAllDataPathInterfaces(); - } - - Bundle data = completedCommand.getData(); - - int clientId = completedCommand.arg2; - IWifiAwareEventCallback callback = (IWifiAwareEventCallback) completedCommand.obj; - ConfigRequest configRequest = (ConfigRequest) data - .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); - int uid = data.getInt(MESSAGE_BUNDLE_KEY_UID); - int pid = data.getInt(MESSAGE_BUNDLE_KEY_PID); - boolean notifyIdentityChange = data.getBoolean( - MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE); - String callingPackage = data.getString(MESSAGE_BUNDLE_KEY_CALLING_PACKAGE); - String callingFeatureId = data.getString(MESSAGE_BUNDLE_KEY_CALLING_FEATURE_ID); - - WifiAwareClientState client = new WifiAwareClientState(mContext, clientId, uid, pid, - callingPackage, callingFeatureId, callback, configRequest, notifyIdentityChange, - SystemClock.elapsedRealtime(), mWifiPermissionsUtil); - client.enableVerboseLogging(mDbg); - mClients.put(clientId, client); - mAwareMetrics.recordAttachSession(uid, notifyIdentityChange, mClients); - try { - callback.onConnectSuccess(clientId); - } catch (RemoteException e) { - Log.w(TAG, - "onConfigCompletedLocal onConnectSuccess(): RemoteException (FYI): " + e); - } - client.onInterfaceAddressChange(mCurrentDiscoveryInterfaceMac); - } else if (completedCommand.arg1 == COMMAND_TYPE_DISCONNECT) { - /* - * NOP (i.e. updated configuration after disconnecting a client) - */ - } else if (completedCommand.arg1 == COMMAND_TYPE_RECONFIGURE) { - /* - * NOP (i.e. updated configuration at power saving event) - */ - } else { - Log.wtf(TAG, "onConfigCompletedLocal: unexpected completedCommand=" + completedCommand); - return; - } - - mCurrentAwareConfiguration = mergeConfigRequests(null); - if (mCurrentAwareConfiguration == null) { - Log.wtf(TAG, "onConfigCompletedLocal: got a null merged configuration after config!?"); - } - mCurrentIdentityNotification = doesAnyClientNeedIdentityChangeNotifications(); - mCurrentRangingEnabled = doesAnyClientNeedRanging(); - } - - private void onConfigFailedLocal(Message failedCommand, int reason) { - if (VDBG) { - Log.v(TAG, - "onConfigFailedLocal: failedCommand=" + failedCommand + ", reason=" + reason); - } - - if (failedCommand.arg1 == COMMAND_TYPE_CONNECT) { - IWifiAwareEventCallback callback = (IWifiAwareEventCallback) failedCommand.obj; - - try { - callback.onConnectFail(reason); - mAwareMetrics.recordAttachStatus(reason); - } catch (RemoteException e) { - Log.w(TAG, "onConfigFailedLocal onConnectFail(): RemoteException (FYI): " + e); - } - } else if (failedCommand.arg1 == COMMAND_TYPE_DISCONNECT) { - /* - * NOP (tried updating configuration after disconnecting a client - - * shouldn't fail but there's nothing to do - the old configuration - * is still up-and-running). - * - * OR: timed-out getting a response to a disable. Either way a NOP. - */ - } else if (failedCommand.arg1 == COMMAND_TYPE_RECONFIGURE) { - /* - * NOP (configuration change as part of possibly power saving event - should not - * fail but there's nothing to do). - */ - } else { - Log.wtf(TAG, "onConfigFailedLocal: unexpected failedCommand=" + failedCommand); - return; - } - } - - private void onDisableResponseLocal(Message command, int reason) { - if (VDBG) { - Log.v(TAG, "onDisableResponseLocal: command=" + command + ", reason=" + reason); - } - - /* - * do nothing: - * - success: was waiting so that don't enable while disabling - * - fail: shouldn't happen (though can if already disabled for instance) - */ - if (reason != NanStatusType.SUCCESS) { - Log.e(TAG, "onDisableResponseLocal: FAILED!? command=" + command + ", reason=" - + reason); - } - - mAwareMetrics.recordDisableAware(); - } - - private void onSessionConfigSuccessLocal(Message completedCommand, byte pubSubId, - boolean isPublish) { - if (VDBG) { - Log.v(TAG, "onSessionConfigSuccessLocal: completedCommand=" + completedCommand - + ", pubSubId=" + pubSubId + ", isPublish=" + isPublish); - } - - boolean isRangingEnabled = false; - int minRange = -1; - int maxRange = -1; - if (isPublish) { - PublishConfig publishConfig = completedCommand.getData().getParcelable( - MESSAGE_BUNDLE_KEY_CONFIG); - isRangingEnabled = publishConfig.mEnableRanging; - } else { - SubscribeConfig subscribeConfig = completedCommand.getData().getParcelable( - MESSAGE_BUNDLE_KEY_CONFIG); - isRangingEnabled = - subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet; - if (subscribeConfig.mMinDistanceMmSet) { - minRange = subscribeConfig.mMinDistanceMm; - } - if (subscribeConfig.mMaxDistanceMmSet) { - maxRange = subscribeConfig.mMaxDistanceMm; - } - } - - if (completedCommand.arg1 == COMMAND_TYPE_PUBLISH - || completedCommand.arg1 == COMMAND_TYPE_SUBSCRIBE) { - int clientId = completedCommand.arg2; - IWifiAwareDiscoverySessionCallback callback = - (IWifiAwareDiscoverySessionCallback) completedCommand.obj; - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, - "onSessionConfigSuccessLocal: no client exists for clientId=" + clientId); - return; - } - - int sessionId = mSm.mNextSessionId++; - try { - callback.onSessionStarted(sessionId); - } catch (RemoteException e) { - Log.e(TAG, "onSessionConfigSuccessLocal: onSessionStarted() RemoteException=" + e); - return; - } - - WifiAwareDiscoverySessionState session = new WifiAwareDiscoverySessionState( - mWifiAwareNativeApi, sessionId, pubSubId, callback, isPublish, isRangingEnabled, - SystemClock.elapsedRealtime()); - session.enableVerboseLogging(mDbg); - client.addSession(session); - - if (isRangingEnabled) { - mAwareMetrics.recordDiscoverySessionWithRanging(client.getUid(), - completedCommand.arg1 != COMMAND_TYPE_PUBLISH, minRange, maxRange, - mClients); - } else { - mAwareMetrics.recordDiscoverySession(client.getUid(), mClients); - } - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.SUCCESS, - completedCommand.arg1 == COMMAND_TYPE_PUBLISH); - - } else if (completedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH - || completedCommand.arg1 == COMMAND_TYPE_UPDATE_SUBSCRIBE) { - int clientId = completedCommand.arg2; - int sessionId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, - "onSessionConfigSuccessLocal: no client exists for clientId=" + clientId); - return; - } - - WifiAwareDiscoverySessionState session = client.getSession(sessionId); - if (session == null) { - Log.e(TAG, "onSessionConfigSuccessLocal: no session exists for clientId=" + clientId - + ", sessionId=" + sessionId); - return; - } - - try { - session.getCallback().onSessionConfigSuccess(); - } catch (RemoteException e) { - Log.e(TAG, "onSessionConfigSuccessLocal: onSessionConfigSuccess() RemoteException=" - + e); - } - session.setRangingEnabled(isRangingEnabled); - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.SUCCESS, - completedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH); - } else { - Log.wtf(TAG, - "onSessionConfigSuccessLocal: unexpected completedCommand=" + completedCommand); - return; - } - // If ranging require changes, reconfigure. - if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) { - reconfigure(); - } - } - - private void onSessionConfigFailLocal(Message failedCommand, boolean isPublish, int reason) { - if (VDBG) { - Log.v(TAG, "onSessionConfigFailLocal: failedCommand=" + failedCommand + ", isPublish=" - + isPublish + ", reason=" + reason); - } - - if (failedCommand.arg1 == COMMAND_TYPE_PUBLISH - || failedCommand.arg1 == COMMAND_TYPE_SUBSCRIBE) { - int clientId = failedCommand.arg2; - IWifiAwareDiscoverySessionCallback callback = - (IWifiAwareDiscoverySessionCallback) failedCommand.obj; - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "onSessionConfigFailLocal: no client exists for clientId=" + clientId); - return; - } - - try { - callback.onSessionConfigFail(reason); - } catch (RemoteException e) { - Log.w(TAG, "onSessionConfigFailLocal onSessionConfigFail(): RemoteException (FYI): " - + e); - } - mAwareMetrics.recordDiscoveryStatus(client.getUid(), reason, - failedCommand.arg1 == COMMAND_TYPE_PUBLISH); - } else if (failedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH - || failedCommand.arg1 == COMMAND_TYPE_UPDATE_SUBSCRIBE) { - int clientId = failedCommand.arg2; - int sessionId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "onSessionConfigFailLocal: no client exists for clientId=" + clientId); - return; - } - - WifiAwareDiscoverySessionState session = client.getSession(sessionId); - if (session == null) { - Log.e(TAG, "onSessionConfigFailLocal: no session exists for clientId=" + clientId - + ", sessionId=" + sessionId); - return; - } - - try { - session.getCallback().onSessionConfigFail(reason); - } catch (RemoteException e) { - Log.e(TAG, "onSessionConfigFailLocal: onSessionConfigFail() RemoteException=" + e); - } - mAwareMetrics.recordDiscoveryStatus(client.getUid(), reason, - failedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH); - - if (reason == NanStatusType.INVALID_SESSION_ID) { - client.removeSession(sessionId); - if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) { - reconfigure(); - } - } - } else { - Log.wtf(TAG, "onSessionConfigFailLocal: unexpected failedCommand=" + failedCommand); - } - } - - private void onMessageSendSuccessLocal(Message completedCommand) { - if (VDBG) { - Log.v(TAG, "onMessageSendSuccess: completedCommand=" + completedCommand); - } - - int clientId = completedCommand.arg2; - int sessionId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); - int messageId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID); - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "onMessageSendSuccessLocal: no client exists for clientId=" + clientId); - return; - } - - WifiAwareDiscoverySessionState session = client.getSession(sessionId); - if (session == null) { - Log.e(TAG, "onMessageSendSuccessLocal: no session exists for clientId=" + clientId - + ", sessionId=" + sessionId); - return; - } - - try { - session.getCallback().onMessageSendSuccess(messageId); - } catch (RemoteException e) { - Log.w(TAG, "onMessageSendSuccessLocal: RemoteException (FYI): " + e); - } - } - - private void onMessageSendFailLocal(Message failedCommand, int reason) { - if (VDBG) { - Log.v(TAG, "onMessageSendFail: failedCommand=" + failedCommand + ", reason=" + reason); - } - - int clientId = failedCommand.arg2; - int sessionId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); - int messageId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID); - - WifiAwareClientState client = mClients.get(clientId); - if (client == null) { - Log.e(TAG, "onMessageSendFailLocal: no client exists for clientId=" + clientId); - return; - } - - WifiAwareDiscoverySessionState session = client.getSession(sessionId); - if (session == null) { - Log.e(TAG, "onMessageSendFailLocal: no session exists for clientId=" + clientId - + ", sessionId=" + sessionId); - return; - } - - try { - session.getCallback().onMessageSendFail(messageId, reason); - } catch (RemoteException e) { - Log.e(TAG, "onMessageSendFailLocal: onMessageSendFail RemoteException=" + e); - } - } - - private void onCapabilitiesUpdatedResponseLocal(Capabilities capabilities) { - if (VDBG) { - Log.v(TAG, "onCapabilitiesUpdatedResponseLocal: capabilites=" + capabilities); - } - - mCapabilities = capabilities; - mCharacteristics = null; - } - - private void onCreateDataPathInterfaceResponseLocal(Message command, boolean success, - int reasonOnFailure) { - if (VDBG) { - Log.v(TAG, "onCreateDataPathInterfaceResponseLocal: command=" + command + ", success=" - + success + ", reasonOnFailure=" + reasonOnFailure); - } - - if (success) { - if (VDBG) { - Log.v(TAG, "onCreateDataPathInterfaceResponseLocal: successfully created interface " - + command.obj); - } - mDataPathMgr.onInterfaceCreated((String) command.obj); - } else { - Log.e(TAG, - "onCreateDataPathInterfaceResponseLocal: failed when trying to create " - + "interface " - + command.obj + ". Reason code=" + reasonOnFailure); - } - } - - private void onDeleteDataPathInterfaceResponseLocal(Message command, boolean success, - int reasonOnFailure) { - if (VDBG) { - Log.v(TAG, "onDeleteDataPathInterfaceResponseLocal: command=" + command + ", success=" - + success + ", reasonOnFailure=" + reasonOnFailure); - } - - if (success) { - if (VDBG) { - Log.v(TAG, "onDeleteDataPathInterfaceResponseLocal: successfully deleted interface " - + command.obj); - } - mDataPathMgr.onInterfaceDeleted((String) command.obj); - } else { - Log.e(TAG, - "onDeleteDataPathInterfaceResponseLocal: failed when trying to delete " - + "interface " - + command.obj + ". Reason code=" + reasonOnFailure); - } - } - - private void onInitiateDataPathResponseSuccessLocal(Message command, int ndpId) { - if (VDBG) { - Log.v(TAG, "onInitiateDataPathResponseSuccessLocal: command=" + command + ", ndpId=" - + ndpId); - } - - mDataPathMgr.onDataPathInitiateSuccess((WifiAwareNetworkSpecifier) command.obj, ndpId); - } - - private void onInitiateDataPathResponseFailLocal(Message command, int reason) { - if (VDBG) { - Log.v(TAG, "onInitiateDataPathResponseFailLocal: command=" + command + ", reason=" - + reason); - } - - mDataPathMgr.onDataPathInitiateFail((WifiAwareNetworkSpecifier) command.obj, reason); - } - - private void onRespondToDataPathSetupRequestResponseLocal(Message command, boolean success, - int reasonOnFailure) { - if (VDBG) { - Log.v(TAG, "onRespondToDataPathSetupRequestResponseLocal: command=" + command - + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure); - } - - mDataPathMgr.onRespondToDataPathRequest(command.arg2, success, reasonOnFailure); - } - - private void onEndPathEndResponseLocal(Message command, boolean success, int reasonOnFailure) { - if (VDBG) { - Log.v(TAG, "onEndPathEndResponseLocal: command=" + command - + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure); - } - - // TODO: do something with this - } - - /* - * NOTIFICATIONS - */ - - private void onInterfaceAddressChangeLocal(byte[] mac) { - if (VDBG) { - Log.v(TAG, "onInterfaceAddressChange: mac=" + String.valueOf(HexEncoding.encode(mac))); - } - - mCurrentDiscoveryInterfaceMac = mac; - - for (int i = 0; i < mClients.size(); ++i) { - WifiAwareClientState client = mClients.valueAt(i); - client.onInterfaceAddressChange(mac); - } - - mAwareMetrics.recordEnableAware(); - } - - private void onClusterChangeLocal(int flag, byte[] clusterId) { - if (VDBG) { - Log.v(TAG, "onClusterChange: flag=" + flag + ", clusterId=" - + String.valueOf(HexEncoding.encode(clusterId))); - } - - for (int i = 0; i < mClients.size(); ++i) { - WifiAwareClientState client = mClients.valueAt(i); - client.onClusterChange(flag, clusterId, mCurrentDiscoveryInterfaceMac); - } - - mAwareMetrics.recordEnableAware(); - } - - private void onMatchLocal(int pubSubId, int requestorInstanceId, byte[] peerMac, - byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndication, int rangeMm) { - if (VDBG) { - Log.v(TAG, - "onMatch: pubSubId=" + pubSubId + ", requestorInstanceId=" + requestorInstanceId - + ", peerDiscoveryMac=" + String.valueOf(HexEncoding.encode(peerMac)) - + ", serviceSpecificInfo=" + Arrays.toString(serviceSpecificInfo) - + ", matchFilter=" + Arrays.toString(matchFilter) - + ", rangingIndication=" + rangingIndication + ", rangeMm=" + rangeMm); - } - - Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data = - getClientSessionForPubSubId(pubSubId); - if (data == null) { - Log.e(TAG, "onMatch: no session found for pubSubId=" + pubSubId); - return; - } - - if (data.second.isRangingEnabled()) { - mAwareMetrics.recordMatchIndicationForRangeEnabledSubscribe(rangingIndication != 0); - } - data.second.onMatch(requestorInstanceId, peerMac, serviceSpecificInfo, matchFilter, - rangingIndication, rangeMm); - } - - private void onSessionTerminatedLocal(int pubSubId, boolean isPublish, int reason) { - if (VDBG) { - Log.v(TAG, "onSessionTerminatedLocal: pubSubId=" + pubSubId + ", isPublish=" + isPublish - + ", reason=" + reason); - } - - Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data = - getClientSessionForPubSubId(pubSubId); - if (data == null) { - Log.e(TAG, "onSessionTerminatedLocal: no session found for pubSubId=" + pubSubId); - return; - } - - try { - data.second.getCallback().onSessionTerminated(reason); - } catch (RemoteException e) { - Log.w(TAG, - "onSessionTerminatedLocal onSessionTerminated(): RemoteException (FYI): " + e); - } - data.first.removeSession(data.second.getSessionId()); - if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) { - reconfigure(); - } - mAwareMetrics.recordDiscoverySessionDuration(data.second.getCreationTime(), - data.second.isPublishSession()); - } - - private void onMessageReceivedLocal(int pubSubId, int requestorInstanceId, byte[] peerMac, - byte[] message) { - if (VDBG) { - Log.v(TAG, - "onMessageReceivedLocal: pubSubId=" + pubSubId + ", requestorInstanceId=" - + requestorInstanceId + ", peerDiscoveryMac=" - + String.valueOf(HexEncoding.encode(peerMac))); - } - - Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data = - getClientSessionForPubSubId(pubSubId); - if (data == null) { - Log.e(TAG, "onMessageReceivedLocal: no session found for pubSubId=" + pubSubId); - return; - } - - data.second.onMessageReceived(requestorInstanceId, peerMac, message); - } - - private void onAwareDownLocal() { - if (VDBG) { - Log.v(TAG, "onAwareDown: mCurrentAwareConfiguration=" + mCurrentAwareConfiguration); - } - if (mCurrentAwareConfiguration == null) { - return; - } - - for (int i = 0; i < mClients.size(); ++i) { - mAwareMetrics.recordAttachSessionDuration(mClients.valueAt(i).getCreationTime()); - SparseArray<WifiAwareDiscoverySessionState> sessions = mClients.valueAt( - i).getSessions(); - for (int j = 0; j < sessions.size(); ++j) { - mAwareMetrics.recordDiscoverySessionDuration(sessions.valueAt(j).getCreationTime(), - sessions.valueAt(j).isPublishSession()); - } - } - mAwareMetrics.recordDisableAware(); - - mClients.clear(); - mCurrentAwareConfiguration = null; - mSm.onAwareDownCleanupSendQueueState(); - mDataPathMgr.onAwareDownCleanupDataPaths(); - mCurrentDiscoveryInterfaceMac = ALL_ZERO_MAC; - deleteAllDataPathInterfaces(); - } - - /* - * Utilities - */ - - private Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> getClientSessionForPubSubId( - int pubSubId) { - for (int i = 0; i < mClients.size(); ++i) { - WifiAwareClientState client = mClients.valueAt(i); - WifiAwareDiscoverySessionState session = client.getAwareSessionStateForPubSubId( - pubSubId); - if (session != null) { - return new Pair<>(client, session); - } - } - - return null; - } - - /** - * Merge all the existing client configurations with the (optional) input configuration request. - * If the configurations are "incompatible" (rules in comment below) return a null. - */ - private ConfigRequest mergeConfigRequests(ConfigRequest configRequest) { - if (mDbg) { - Log.v(TAG, "mergeConfigRequests(): mClients=[" + mClients + "], configRequest=" - + configRequest); - } - - if (mClients.size() == 0 && configRequest == null) { - Log.e(TAG, "mergeConfigRequests: invalid state - called with 0 clients registered!"); - return null; - } - - // TODO: continue working on merge algorithm: - // - if any request 5g: enable - // - maximal master preference - // - cluster range: must be identical - // - if any request identity change: enable - // - discovery window: minimum value if specified, 0 (disable) is considered an infinity - boolean support5gBand = false; - boolean support6gBand = false; - int masterPreference = 0; - boolean clusterIdValid = false; - int clusterLow = 0; - int clusterHigh = ConfigRequest.CLUSTER_ID_MAX; - int[] discoveryWindowInterval = - {ConfigRequest.DW_INTERVAL_NOT_INIT, ConfigRequest.DW_INTERVAL_NOT_INIT}; - if (configRequest != null) { - support5gBand = configRequest.mSupport5gBand; - support6gBand = configRequest.mSupport6gBand; - masterPreference = configRequest.mMasterPreference; - clusterIdValid = true; - clusterLow = configRequest.mClusterLow; - clusterHigh = configRequest.mClusterHigh; - discoveryWindowInterval = configRequest.mDiscoveryWindowInterval; - } - for (int i = 0; i < mClients.size(); ++i) { - ConfigRequest cr = mClients.valueAt(i).getConfigRequest(); - - // any request turns on 5G - if (cr.mSupport5gBand) { - support5gBand = true; - } - - // any request turns on 5G - if (cr.mSupport6gBand) { - support6gBand = true; - } - - // maximal master preference - masterPreference = Math.max(masterPreference, cr.mMasterPreference); - - // cluster range must be the same across all config requests - if (!clusterIdValid) { - clusterIdValid = true; - clusterLow = cr.mClusterLow; - clusterHigh = cr.mClusterHigh; - } else { - if (clusterLow != cr.mClusterLow) return null; - if (clusterHigh != cr.mClusterHigh) return null; - } - - for (int band = ConfigRequest.NAN_BAND_24GHZ; band <= ConfigRequest.NAN_BAND_5GHZ; - ++band) { - if (discoveryWindowInterval[band] == ConfigRequest.DW_INTERVAL_NOT_INIT) { - discoveryWindowInterval[band] = cr.mDiscoveryWindowInterval[band]; - } else if (cr.mDiscoveryWindowInterval[band] - == ConfigRequest.DW_INTERVAL_NOT_INIT) { - // do nothing: keep my values - } else if (discoveryWindowInterval[band] == ConfigRequest.DW_DISABLE) { - discoveryWindowInterval[band] = cr.mDiscoveryWindowInterval[band]; - } else if (cr.mDiscoveryWindowInterval[band] == ConfigRequest.DW_DISABLE) { - // do nothing: keep my values - } else { - discoveryWindowInterval[band] = Math.min(discoveryWindowInterval[band], - cr.mDiscoveryWindowInterval[band]); - } - } - } - ConfigRequest.Builder builder = new ConfigRequest.Builder().setSupport5gBand(support5gBand) - .setMasterPreference(masterPreference).setClusterLow(clusterLow) - .setClusterHigh(clusterHigh); - for (int band = ConfigRequest.NAN_BAND_24GHZ; band <= ConfigRequest.NAN_BAND_5GHZ; ++band) { - if (discoveryWindowInterval[band] != ConfigRequest.DW_INTERVAL_NOT_INIT) { - builder.setDiscoveryWindowInterval(band, discoveryWindowInterval[band]); - } - } - return builder.build(); - } - - private boolean doesAnyClientNeedIdentityChangeNotifications() { - for (int i = 0; i < mClients.size(); ++i) { - if (mClients.valueAt(i).getNotifyIdentityChange()) { - return true; - } - } - return false; - } - - private boolean doesAnyClientNeedRanging() { - for (int i = 0; i < mClients.size(); ++i) { - if (mClients.valueAt(i).isRangingEnabled()) { - return true; - } - } - return false; - } - - private static String messageToString(Message msg) { - StringBuilder sb = new StringBuilder(); - - String s = sSmToString.get(msg.what); - if (s == null) { - s = "<unknown>"; - } - sb.append(s).append("/"); - - if (msg.what == MESSAGE_TYPE_NOTIFICATION || msg.what == MESSAGE_TYPE_COMMAND - || msg.what == MESSAGE_TYPE_RESPONSE) { - s = sSmToString.get(msg.arg1); - if (s == null) { - s = "<unknown>"; - } - sb.append(s); - } - - if (msg.what == MESSAGE_TYPE_RESPONSE || msg.what == MESSAGE_TYPE_RESPONSE_TIMEOUT) { - sb.append(" (Transaction ID=").append(msg.arg2).append(")"); - } - - return sb.toString(); - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("AwareStateManager:"); - pw.println(" mClients: [" + mClients + "]"); - pw.println(" mUsageEnabled: " + mUsageEnabled); - pw.println(" mCapabilities: [" + mCapabilities + "]"); - pw.println(" mCurrentAwareConfiguration: " + mCurrentAwareConfiguration); - pw.println(" mCurrentIdentityNotification: " + mCurrentIdentityNotification); - for (int i = 0; i < mClients.size(); ++i) { - mClients.valueAt(i).dump(fd, pw, args); - } - pw.println(" mSettableParameters: " + mSettableParameters); - mSm.dump(fd, pw, args); - mDataPathMgr.dump(fd, pw, args); - mWifiAwareNativeApi.dump(fd, pw, args); - pw.println("mAwareMetrics:"); - mAwareMetrics.dump(fd, pw, args); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/ANQPData.java b/service/java/com/android/server/wifi/hotspot2/ANQPData.java deleted file mode 100644 index 26286a881..000000000 --- a/service/java/com/android/server/wifi/hotspot2/ANQPData.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.Clock; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * Class for maintaining ANQP elements and managing the lifetime of the elements. - */ -public class ANQPData { - /** - * Entry lifetime. - */ - @VisibleForTesting - public static final long DATA_LIFETIME_MILLISECONDS = 3600000L; - - private final Clock mClock; - private final Map<Constants.ANQPElementType, ANQPElement> mANQPElements; - private final long mExpiryTime; - - public ANQPData(Clock clock, Map<Constants.ANQPElementType, ANQPElement> anqpElements) { - mClock = clock; - mANQPElements = new HashMap<>(); - if (anqpElements != null) { - mANQPElements.putAll(anqpElements); - } - mExpiryTime = mClock.getElapsedSinceBootMillis() + DATA_LIFETIME_MILLISECONDS; - } - - /** - * Return the ANQP elements. - * - * @return Map of ANQP elements - */ - public Map<Constants.ANQPElementType, ANQPElement> getElements() { - return Collections.unmodifiableMap(mANQPElements); - } - - /** - * Check if this entry is expired at the specified time. - * - * @param at The time to check for - * @return true if it is expired at the given time - */ - public boolean expired(long at) { - return mExpiryTime <= at; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(mANQPElements.size()).append(" elements, "); - long now = mClock.getElapsedSinceBootMillis(); - sb.append(" expires in ").append(Utils.toHMS(mExpiryTime - now)).append(' '); - sb.append(expired(now) ? 'x' : '-').append("\n"); - for (Map.Entry<Constants.ANQPElementType, ANQPElement> entry: mANQPElements.entrySet()) { - sb.append(entry.getValue()).append("\n"); - } - return sb.toString(); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java b/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java deleted file mode 100644 index 6bb834d4b..000000000 --- a/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import android.text.TextUtils; - -import com.android.server.wifi.IMSIParameter; -import com.android.server.wifi.hotspot2.anqp.CellularNetwork; -import com.android.server.wifi.hotspot2.anqp.DomainNameElement; -import com.android.server.wifi.hotspot2.anqp.NAIRealmData; -import com.android.server.wifi.hotspot2.anqp.NAIRealmElement; -import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement; -import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement; - -import java.util.List; - -/** - * Utility class for providing matching functions against ANQP elements. - */ -public class ANQPMatcher { - /** - * Match the domain names in the ANQP element against the provider's FQDN and SIM credential. - * The Domain Name ANQP element might contain domains for 3GPP network (e.g. - * wlan.mnc*.mcc*.3gppnetwork.org), so we should match that against the provider's SIM - * credential if one is provided. - * - * @param element The Domain Name ANQP element - * @param fqdn The FQDN to compare against - * @param imsiParam The IMSI parameter of the provider (needed only for IMSI matching) - * @param simImsi The IMSI from the installed SIM cards that best matched provider's - * IMSI parameter (needed only for IMSI matching) - * @return true if a match is found - */ - public static boolean matchDomainName(DomainNameElement element, String fqdn, - IMSIParameter imsiParam, String simImsi) { - if (element == null) { - return false; - } - - for (String domain : element.getDomains()) { - if (DomainMatcher.arg2SubdomainOfArg1(fqdn, domain)) { - return true; - } - - if (imsiParam == null || simImsi == null) { - continue; - } - - // Try to retrieve the MCC-MNC string from the domain (for 3GPP network domain) and - // match against the provider's SIM credential. - if (matchMccMnc(Utils.getMccMnc(Utils.splitDomain(domain)), imsiParam, simImsi)) { - return true; - } - } - return false; - } - - /** - * Match the roaming consortium OIs in the ANQP element against the roaming consortium OIs - * of a provider. - * - * @param element The Roaming Consortium ANQP element - * @param providerOIs The roaming consortium OIs of the provider - * @param matchAll Indicates if a match with all OIs must be done - * @return true if a match is found - */ - public static boolean matchRoamingConsortium(RoamingConsortiumElement element, - long[] providerOIs, boolean matchAll) { - if (element == null) { - return false; - } - if (providerOIs == null) { - return false; - } - List<Long> rcOIs = element.getOIs(); - for (long oi : providerOIs) { - if (rcOIs.contains(oi)) { - if (!matchAll) { - return true; - } - } else if (matchAll) { - return false; - } - } - return matchAll; - } - - /** - * Match the NAI realm in the ANQP element against the realm and authentication method of - * a provider. - * - * @param element The NAI Realm ANQP element - * @param realm The realm of the provider's credential - * @return true if there is a NAI Realm match, false otherwise - */ - public static boolean matchNAIRealm(NAIRealmElement element, String realm) { - if (element == null || element.getRealmDataList().isEmpty()) { - return false; - } - - for (NAIRealmData realmData : element.getRealmDataList()) { - if (matchNAIRealmData(realmData, realm)) { - return true; - } - } - return false; - } - - /** - * Match the 3GPP Network in the ANQP element against the SIM credential of a provider. - * - * @param element 3GPP Network ANQP element - * @param imsiParam The IMSI parameter of the provider's SIM credential - * @param simImsi The IMSI from the installed SIM cards that best matched provider's - * IMSI parameter - * @return true if a match is found - */ - public static boolean matchThreeGPPNetwork(ThreeGPPNetworkElement element, - IMSIParameter imsiParam, String simImsi) { - if (element == null) { - return false; - } - for (CellularNetwork network : element.getNetworks()) { - if (matchCellularNetwork(network, imsiParam, simImsi)) { - return true; - } - } - return false; - } - - /** - * Match the given NAI Realm data against the realm and authentication method of a provider. - * - * @param realmData The NAI Realm data - * @param realm The realm of the provider's credential - * @return true if a match is found - */ - private static boolean matchNAIRealmData(NAIRealmData realmData, String realm) { - // Check for realm domain name match. - for (String realmStr : realmData.getRealms()) { - if (DomainMatcher.arg2SubdomainOfArg1(realm, realmStr)) { - return true; - } - } - return false; - } - - /** - * Match a cellular network information in the 3GPP Network ANQP element against the SIM - * credential of a provider. - * - * @param network The cellular network that contained list of PLMNs - * @param imsiParam IMSI parameter of the provider - * @param simImsi The IMSI from the installed SIM cards that best matched provider's - * IMSI parameter - * @return true if a match is found - */ - private static boolean matchCellularNetwork(CellularNetwork network, IMSIParameter imsiParam, - String simImsi) { - for (String plmn : network.getPlmns()) { - if (matchMccMnc(plmn, imsiParam, simImsi)) { - return true; - } - } - - return false; - } - - /** - * Match a MCC-MNC against the SIM credential of a provider. - * - * @param mccMnc The string containing MCC-MNC - * @param imsiParam The IMSI parameter of the provider - * @param simImsi The IMSI from the installed SIM cards that best matched provider's - * IMSI parameter - * @return true if a match is found - */ - private static boolean matchMccMnc(String mccMnc, IMSIParameter imsiParam, - String simImsi) { - if (imsiParam == null || TextUtils.isEmpty(simImsi) || mccMnc == null) { - return false; - } - // Match against the IMSI parameter in the provider. - if (!imsiParam.matchesMccMnc(mccMnc)) { - return false; - } - // Additional check for verifying the match with IMSI from the SIM card, since the IMSI - // parameter might not contain the full 6-digit MCC MNC (e.g. IMSI parameter is an IMSI - // prefix that contained less than 6-digit of numbers "12345*"). - return simImsi.startsWith(mccMnc); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/ANQPNetworkKey.java b/service/java/com/android/server/wifi/hotspot2/ANQPNetworkKey.java deleted file mode 100644 index 19590b37a..000000000 --- a/service/java/com/android/server/wifi/hotspot2/ANQPNetworkKey.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import android.text.TextUtils; - -/** - * Unique key for identifying APs that will contain the same ANQP information. - * - * APs in the same ESS (SSID or HESSID) with the same ANQP domain ID will have the same ANQP - * information. Thus, those APs will be keyed by the ESS identifier (SSID or HESSID) and the - * ANQP domain ID. - * - * APs without ANQP domain ID set will assumed to have unique ANQP information. Thus, those - * APs will be keyed by SSID and BSSID. - */ -public class ANQPNetworkKey { - private final String mSSID; - private final long mBSSID; - private final long mHESSID; - private final int mAnqpDomainID; - - public ANQPNetworkKey(String ssid, long bssid, long hessid, int anqpDomainID) { - mSSID = ssid; - mBSSID = bssid; - mHESSID = hessid; - mAnqpDomainID = anqpDomainID; - } - - /** - * Build an ANQP network key suitable for the granularity of the key space as follows: - * - * HESSID domainID Key content Rationale - * -------- ----------- ----------- -------------------- - * n/a zero SSID/BSSID Domain ID indicates unique AP info - * not set set SSID/domainID Standard definition of an ESS - * set set HESSID/domainID The ESS is defined by the HESSID - * - * @param ssid The SSID of the AP - * @param bssid The BSSID of the AP - * @param hessid The HESSID of the AP - * @param anqpDomainId The ANQP Domain ID of the AP - * @return {@link ANQPNetworkKey} - */ - public static ANQPNetworkKey buildKey(String ssid, long bssid, long hessid, int anqpDomainId) { - if (anqpDomainId == 0) { - return new ANQPNetworkKey(ssid, bssid, 0, 0); - } else if (hessid != 0L) { - return new ANQPNetworkKey(null, 0, hessid, anqpDomainId); - } - return new ANQPNetworkKey(ssid, 0, 0, anqpDomainId); - } - - @Override - public int hashCode() { - if (mHESSID != 0) { - return (int) (((mHESSID >>> 32) * 31 + mHESSID) * 31 + mAnqpDomainID); - } else if (mBSSID != 0) { - return (int) ((mSSID.hashCode() * 31 + (mBSSID >>> 32)) * 31 + mBSSID); - } else { - return mSSID.hashCode() * 31 + mAnqpDomainID; - } - } - - @Override - public boolean equals(Object thatObject) { - if (thatObject == this) { - return true; - } - if (!(thatObject instanceof ANQPNetworkKey)) { - return false; - } - ANQPNetworkKey that = (ANQPNetworkKey) thatObject; - return TextUtils.equals(that.mSSID, mSSID) - && that.mBSSID == mBSSID - && that.mHESSID == mHESSID - && that.mAnqpDomainID == mAnqpDomainID; - } - - @Override - public String toString() { - if (mHESSID != 0L) { - return Utils.macToString(mHESSID) + ":" + mAnqpDomainID; - } else if (mBSSID != 0L) { - return Utils.macToString(mBSSID) + ":<" + mSSID + ">"; - } else { - return "<" + mSSID + ">:" + mAnqpDomainID; - } - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/ANQPRequestManager.java b/service/java/com/android/server/wifi/hotspot2/ANQPRequestManager.java deleted file mode 100644 index 2634fa820..000000000 --- a/service/java/com/android/server/wifi/hotspot2/ANQPRequestManager.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.Clock; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Class for managing sending of ANQP requests. This manager will ignore ANQP requests for a - * period of time (hold off time) to a specified AP if the previous request to that AP goes - * unanswered or failed. The hold off time will increase exponentially until the max is reached. - */ -public class ANQPRequestManager { - private static final String TAG = "ANQPRequestManager"; - - private final PasspointEventHandler mPasspointHandler; - private final Clock mClock; - - /** - * List of pending ANQP request associated with an AP (BSSID). - */ - private final Map<Long, ANQPNetworkKey> mPendingQueries; - - /** - * List of hold off time information associated with APs specified by their BSSID. - * Used to determine when an ANQP request can be send to the corresponding AP after the - * previous request goes unanswered or failed. - */ - private final Map<Long, HoldOffInfo> mHoldOffInfo; - - /** - * Minimum number of milliseconds to wait for before attempting ANQP queries to the same AP - * after previous request goes unanswered or failed. - */ - @VisibleForTesting - public static final int BASE_HOLDOFF_TIME_MILLISECONDS = 10000; - - /** - * Max value for the hold off counter for unanswered/failed queries. This limits the maximum - * hold off time to: - * BASE_HOLDOFF_TIME_MILLISECONDS * 2^MAX_HOLDOFF_COUNT - * which is 640 seconds. - */ - @VisibleForTesting - public static final int MAX_HOLDOFF_COUNT = 6; - - private static final List<Constants.ANQPElementType> R1_ANQP_BASE_SET = Arrays.asList( - Constants.ANQPElementType.ANQPVenueName, - Constants.ANQPElementType.ANQPIPAddrAvailability, - Constants.ANQPElementType.ANQPNAIRealm, - Constants.ANQPElementType.ANQP3GPPNetwork, - Constants.ANQPElementType.ANQPDomName, - Constants.ANQPElementType.HSFriendlyName, - Constants.ANQPElementType.HSWANMetrics, - Constants.ANQPElementType.HSConnCapability); - - private static final List<Constants.ANQPElementType> R2_ANQP_BASE_SET = Arrays.asList( - Constants.ANQPElementType.HSOSUProviders); - - /** - * Class to keep track of AP status for ANQP requests. - */ - private class HoldOffInfo { - /** - * Current hold off count. Will max out at {@link #MAX_HOLDOFF_COUNT}. - */ - public int holdOffCount; - /** - * The time stamp in milliseconds when we're allow to send ANQP request to the - * corresponding AP. - */ - public long holdOffExpirationTime; - } - - public ANQPRequestManager(PasspointEventHandler handler, Clock clock) { - mPasspointHandler = handler; - mClock = clock; - mPendingQueries = new HashMap<>(); - mHoldOffInfo = new HashMap<>(); - } - - /** - * Request ANQP elements from the specified AP. This will request the basic Release 1 ANQP - * elements {@link #R1_ANQP_BASE_SET}. Additional elements will be requested based on the - * information provided in the Information Element (Roaming Consortium OI count and the - * supported Hotspot 2.0 release version). - * - * @param bssid The BSSID of the AP - * @param anqpNetworkKey The unique network key associated with this request - * @param rcOIs Flag indicating the inclusion of roaming consortium OIs. When set to true, - * Roaming Consortium ANQP element will be requested - * @param hsReleaseVer Indicates Hotspot 2.0 Release version. When set to R2 or higher, - * the Release 2 ANQP elements {@link #R2_ANQP_BASE_SET} will be requested - * @return true if a request was sent successfully - */ - public boolean requestANQPElements(long bssid, ANQPNetworkKey anqpNetworkKey, boolean rcOIs, - NetworkDetail.HSRelease hsReleaseVer) { - // Check if we are allow to send the request now. - if (!canSendRequestNow(bssid)) { - return false; - } - - // No need to hold off future requests for send failures. - if (!mPasspointHandler.requestANQP(bssid, getRequestElementIDs(rcOIs, hsReleaseVer))) { - return false; - } - - // Update hold off info on when we are allowed to send the next ANQP request to - // the given AP. - updateHoldOffInfo(bssid); - - mPendingQueries.put(bssid, anqpNetworkKey); - return true; - } - - /** - * Notification of the completion of an ANQP request. - * - * @param bssid The BSSID of the AP - * @param success Flag indicating the result of the query - * @return {@link ANQPNetworkKey} associated with the completed request - */ - public ANQPNetworkKey onRequestCompleted(long bssid, boolean success) { - if (success) { - // Query succeeded. No need to hold off request to the given AP. - mHoldOffInfo.remove(bssid); - } - return mPendingQueries.remove(bssid); - } - - /** - * Check if we are allowed to send ANQP request to the specified AP now. - * - * @param bssid The BSSID of an AP - * @return true if we are allowed to send the request now - */ - private boolean canSendRequestNow(long bssid) { - long currentTime = mClock.getElapsedSinceBootMillis(); - HoldOffInfo info = mHoldOffInfo.get(bssid); - if (info != null && info.holdOffExpirationTime > currentTime) { - Log.d(TAG, "Not allowed to send ANQP request to " + Utils.macToString(bssid) - + " for another " + (info.holdOffExpirationTime - currentTime) / 1000 - + " seconds"); - return false; - } - - return true; - } - - /** - * Update the ANQP request hold off info associated with the given AP. - * - * @param bssid The BSSID of an AP - */ - private void updateHoldOffInfo(long bssid) { - HoldOffInfo info = mHoldOffInfo.get(bssid); - if (info == null) { - info = new HoldOffInfo(); - mHoldOffInfo.put(bssid, info); - } - info.holdOffExpirationTime = mClock.getElapsedSinceBootMillis() - + BASE_HOLDOFF_TIME_MILLISECONDS * (1 << info.holdOffCount); - if (info.holdOffCount < MAX_HOLDOFF_COUNT) { - info.holdOffCount++; - } - } - - /** - * Get the list of ANQP element IDs to request based on the Hotspot 2.0 release number - * and the ANQP OI count indicated in the Information Element. - * - * @param rcOIs Flag indicating the inclusion of roaming consortium OIs - * @param hsRelease Hotspot 2.0 Release version of the AP - * @return List of ANQP Element ID - */ - private static List<Constants.ANQPElementType> getRequestElementIDs(boolean rcOIs, - NetworkDetail.HSRelease hsRelease) { - List<Constants.ANQPElementType> requestList = new ArrayList<>(); - requestList.addAll(R1_ANQP_BASE_SET); - if (rcOIs) { - requestList.add(Constants.ANQPElementType.ANQPRoamingConsortium); - } - - if (hsRelease == NetworkDetail.HSRelease.R1) { - // Return R1 ANQP request list - return requestList; - } - - requestList.addAll(R2_ANQP_BASE_SET); - - // Return R2+ ANQP request list. This also includes the Unknown version, which may imply - // a future version. - return requestList; - } - - /** - * Dump the current state of ANQPRequestManager to the provided output stream. - * - * @param pw The output stream to write to - */ - public void dump(PrintWriter pw) { - pw.println("ANQPRequestManager - Begin ---"); - for (Map.Entry<Long, HoldOffInfo> holdOffInfo : mHoldOffInfo.entrySet()) { - long bssid = holdOffInfo.getKey(); - pw.println("For BBSID: " + Utils.macToString(bssid)); - pw.println("holdOffCount: " + holdOffInfo.getValue().holdOffCount); - pw.println("Not allowed to send ANQP request for another " - + (holdOffInfo.getValue().holdOffExpirationTime - - mClock.getElapsedSinceBootMillis()) / 1000 + " seconds"); - } - pw.println("ANQPRequestManager - End ---"); - } - - /** - * Clear all pending ANQP requests - */ - public void clear() { - mPendingQueries.clear(); - mHoldOffInfo.clear(); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/AnqpCache.java b/service/java/com/android/server/wifi/hotspot2/AnqpCache.java deleted file mode 100644 index 9a3a1fb00..000000000 --- a/service/java/com/android/server/wifi/hotspot2/AnqpCache.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.Clock; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Cache for storing ANQP data. This is simply a data cache, all the logic related to - * ANQP data query will be handled elsewhere (e.g. the consumer of the cache). - */ -public class AnqpCache { - @VisibleForTesting - public static final long CACHE_SWEEP_INTERVAL_MILLISECONDS = 60000L; - - private long mLastSweep; - private Clock mClock; - - private final Map<ANQPNetworkKey, ANQPData> mANQPCache; - - public AnqpCache(Clock clock) { - mClock = clock; - mANQPCache = new HashMap<>(); - mLastSweep = mClock.getElapsedSinceBootMillis(); - } - - /** - * Add an ANQP entry associated with the given key. - * - * @param key The key that's associated with the entry - * @param anqpElements The ANQP elements from the AP - */ - public void addEntry(ANQPNetworkKey key, - Map<Constants.ANQPElementType, ANQPElement> anqpElements) { - ANQPData data = new ANQPData(mClock, anqpElements); - mANQPCache.put(key, data); - } - - /** - * Get the ANQP data associated with the given AP. - * - * @param key The key that's associated with the entry - * @return {@link ANQPData} - */ - public ANQPData getEntry(ANQPNetworkKey key) { - return mANQPCache.get(key); - } - - /** - * Go through the cache to remove any expired entries. - */ - public void sweep() { - long now = mClock.getElapsedSinceBootMillis(); - // Check if it is time to perform the sweep. - if (now < mLastSweep + CACHE_SWEEP_INTERVAL_MILLISECONDS) { - return; - } - - // Get all expired keys. - List<ANQPNetworkKey> expiredKeys = new ArrayList<>(); - for (Map.Entry<ANQPNetworkKey, ANQPData> entry : mANQPCache.entrySet()) { - if (entry.getValue().expired(now)) { - expiredKeys.add(entry.getKey()); - } - } - - // Remove all expired entries. - for (ANQPNetworkKey key : expiredKeys) { - mANQPCache.remove(key); - } - mLastSweep = now; - } - - public void dump(PrintWriter out) { - out.println("Last sweep " + Utils.toHMS(mClock.getElapsedSinceBootMillis() - mLastSweep) - + " ago."); - for (Map.Entry<ANQPNetworkKey, ANQPData> entry : mANQPCache.entrySet()) { - out.println(entry.getKey() + ": " + entry.getValue()); - } - } - - /** - * Flush the ANQP cache - */ - public void flush() { - mANQPCache.clear(); - mLastSweep = mClock.getElapsedSinceBootMillis(); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/AnqpEvent.java b/service/java/com/android/server/wifi/hotspot2/AnqpEvent.java deleted file mode 100644 index 0fe8a3a25..000000000 --- a/service/java/com/android/server/wifi/hotspot2/AnqpEvent.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import java.util.HashMap; -import java.util.Map; - -/** - * This class carries the response of an ANQP request. - */ -public class AnqpEvent { - private static final String TAG = "AnqpEvent"; - private static final Map<String, Constants.ANQPElementType> sWpsNames = new HashMap<>(); - - static { - sWpsNames.put("anqp_venue_name", Constants.ANQPElementType.ANQPVenueName); - sWpsNames.put("anqp_roaming_consortium", Constants.ANQPElementType.ANQPRoamingConsortium); - sWpsNames.put("anqp_ip_addr_type_availability", - Constants.ANQPElementType.ANQPIPAddrAvailability); - sWpsNames.put("anqp_nai_realm", Constants.ANQPElementType.ANQPNAIRealm); - sWpsNames.put("anqp_3gpp", Constants.ANQPElementType.ANQP3GPPNetwork); - sWpsNames.put("anqp_domain_name", Constants.ANQPElementType.ANQPDomName); - sWpsNames.put("hs20_operator_friendly_name", Constants.ANQPElementType.HSFriendlyName); - sWpsNames.put("hs20_wan_metrics", Constants.ANQPElementType.HSWANMetrics); - sWpsNames.put("hs20_connection_capability", Constants.ANQPElementType.HSConnCapability); - sWpsNames.put("hs20_osu_providers_list", Constants.ANQPElementType.HSOSUProviders); - } - - /** - * Bssid of the access point. - */ - private final long mBssid; - - /** - * Map of ANQP element type to the data retrieved from the access point. - */ - private final Map<Constants.ANQPElementType, ANQPElement> mElements; - - public AnqpEvent(long bssid, Map<Constants.ANQPElementType, ANQPElement> elements) { - mBssid = bssid; - mElements = elements; - } - - /** - * Get the bssid of the access point from which this ANQP result was created. - */ - public long getBssid() { - return mBssid; - } - - /** - * Get the map of ANQP elements retrieved from the access point. - */ - public Map<Constants.ANQPElementType, ANQPElement> getElements() { - return mElements; - } - -} diff --git a/service/java/com/android/server/wifi/hotspot2/DomainMatcher.java b/service/java/com/android/server/wifi/hotspot2/DomainMatcher.java deleted file mode 100644 index ce60c55b0..000000000 --- a/service/java/com/android/server/wifi/hotspot2/DomainMatcher.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import android.text.TextUtils; - -import com.android.server.wifi.hotspot2.Utils; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** - * Utility class for matching domain names. - */ -public class DomainMatcher { - public static final int MATCH_NONE = 0; - public static final int MATCH_PRIMARY = 1; - public static final int MATCH_SECONDARY = 2; - - /** - * The root of the Label tree. - */ - private final Label mRoot; - - /** - * Label tree representation for the domain name. Labels are delimited by "." in the domain - * name. - * - * For example, the tree representation of "android.google.com" as a primary domain: - * [com, None] -> [google, None] -> [android, Primary] - * - */ - private static class Label { - private final Map<String, Label> mSubDomains; - private int mMatch; - - Label(int match) { - mMatch = match; - mSubDomains = new HashMap<String, Label>(); - } - - /** - * Add sub-domains to this label. - * - * @param labels The iterator of domain label strings - * @param match The match status of the domain - */ - public void addDomain(Iterator<String> labels, int match) { - String labelName = labels.next(); - // Create the Label object if it doesn't exist yet. - Label subLabel = mSubDomains.get(labelName); - if (subLabel == null) { - subLabel = new Label(MATCH_NONE); - mSubDomains.put(labelName, subLabel); - } - - if (labels.hasNext()) { - // Adding sub-domain. - subLabel.addDomain(labels, match); - } else { - // End of the domain, update the match status. - subLabel.mMatch = match; - } - } - - /** - * Return the Label for the give label string. - * @param labelString The label string to look for - * @return {@link Label} - */ - public Label getSubLabel(String labelString) { - return mSubDomains.get(labelString); - } - - /** - * Return the match status - * - * @return The match status - */ - public int getMatch() { - return mMatch; - } - - private void toString(StringBuilder sb) { - if (mSubDomains != null) { - sb.append(".{"); - for (Map.Entry<String, Label> entry : mSubDomains.entrySet()) { - sb.append(entry.getKey()); - entry.getValue().toString(sb); - } - sb.append('}'); - } else { - sb.append('=').append(mMatch); - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - toString(sb); - return sb.toString(); - } - } - - public DomainMatcher(String primaryDomain, List<String> secondaryDomains) { - // Create the root label. - mRoot = new Label(MATCH_NONE); - - // Add secondary domains. - if (secondaryDomains != null) { - for (String domain : secondaryDomains) { - if (!TextUtils.isEmpty(domain)) { - List<String> secondaryLabel = Utils.splitDomain(domain); - mRoot.addDomain(secondaryLabel.iterator(), MATCH_SECONDARY); - } - } - } - - // Add primary domain, primary overwrites secondary. - if (!TextUtils.isEmpty(primaryDomain)) { - List<String> primaryLabel = Utils.splitDomain(primaryDomain); - mRoot.addDomain(primaryLabel.iterator(), MATCH_PRIMARY); - } - } - - /** - * Check if domain is either the same or a sub-domain of any of the domains in the - * domain tree in this matcher, i.e. all or a sub-set of the labels in domain matches - * a path in the tree. - * - * This will have precedence for matching primary domain over secondary domain if both - * are found. - * - * For example, with primary domain set to "test.google.com" and secondary domain set to - * "google.com": - * "test2.test.google.com" -> Match.Primary - * "test1.google.com" -> Match.Secondary - * - * @param domainName Domain name to be checked. - * @return The match status - */ - public int isSubDomain(String domainName) { - if (TextUtils.isEmpty(domainName)) { - return MATCH_NONE; - } - List<String> domainLabels = Utils.splitDomain(domainName); - - Label label = mRoot; - int match = MATCH_NONE; - for (String labelString : domainLabels) { - label = label.getSubLabel(labelString); - if (label == null) { - break; - } else if (label.getMatch() != MATCH_NONE) { - match = label.getMatch(); - if (match == MATCH_PRIMARY) { - break; - } - } - } - return match; - } - - /** - * Check if domain2 is a sub-domain of domain1. - * - * @param domain1 The string of the first domain - * @param domain2 The string of the second domain - * @return true if the second domain is the sub-domain of the first - */ - public static boolean arg2SubdomainOfArg1(String domain1, String domain2) { - if (TextUtils.isEmpty(domain1) || TextUtils.isEmpty(domain2)) { - return false; - } - - List<String> labels1 = Utils.splitDomain(domain1); - List<String> labels2 = Utils.splitDomain(domain2); - - // domain2 must be the same or longer than domain1 in order to be a sub-domain. - if (labels2.size() < labels1.size()) { - return false; - } - - Iterator<String> l1 = labels1.iterator(); - Iterator<String> l2 = labels2.iterator(); - - while(l1.hasNext()) { - if (!TextUtils.equals(l1.next(), l2.next())) { - return false; - } - } - return true; - } - - @Override - public String toString() { - return "Domain matcher " + mRoot; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/IconEvent.java b/service/java/com/android/server/wifi/hotspot2/IconEvent.java deleted file mode 100644 index 406c03cd3..000000000 --- a/service/java/com/android/server/wifi/hotspot2/IconEvent.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.android.server.wifi.hotspot2; - -public class IconEvent { - private final long mBSSID; - private final String mFileName; - private final int mSize; - private final byte[] mData; - - public IconEvent(long bssid, String fileName, int size, byte[] data) { - mBSSID = bssid; - mFileName = fileName; - mSize = size; - mData = data; - } - - public long getBSSID() { - return mBSSID; - } - - public String getFileName() { - return mFileName; - } - - public int getSize() { - return mSize; - } - - public byte[] getData() { - return mData; - } - - @Override - public String toString() { - return "IconEvent: " + - "BSSID=" + String.format("%012x", mBSSID) + - ", fileName='" + mFileName + '\'' + - ", size=" + mSize; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfig.java b/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfig.java deleted file mode 100644 index 5f455f517..000000000 --- a/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfig.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2; - -import android.text.TextUtils; - -import java.util.Arrays; -import java.util.Objects; - -/** - * Class representing the relevant configurations in the legacy Passpoint (N and older) - * configuration file (/data/misc/wifi/PerProviderSubscription.conf). Most of the configurations - * (e.g. user credential) are saved elsewhere, the relevant configurations in this file are: - * - FQDN - * - Friendly Name - * - Roaming Consortium - * - Realm - * - IMSI (for SIM credential) - */ -public class LegacyPasspointConfig { - public String mFqdn; - public String mFriendlyName; - public long[] mRoamingConsortiumOis; - public String mRealm; - public String mImsi; - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof LegacyPasspointConfig)) { - return false; - } - LegacyPasspointConfig that = (LegacyPasspointConfig) thatObject; - return TextUtils.equals(mFqdn, that.mFqdn) - && TextUtils.equals(mFriendlyName, that.mFriendlyName) - && Arrays.equals(mRoamingConsortiumOis, that.mRoamingConsortiumOis) - && TextUtils.equals(mRealm, that.mRealm) - && TextUtils.equals(mImsi, that.mImsi); - } - - @Override - public int hashCode() { - return Objects.hash(mFqdn, mFriendlyName, mRoamingConsortiumOis, mRealm, mImsi); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java deleted file mode 100644 index 752cebf7c..000000000 --- a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java +++ /dev/null @@ -1,649 +0,0 @@ -package com.android.server.wifi.hotspot2; - -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTES_IN_EUI48; -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK; - -import android.net.wifi.ScanResult; -import android.util.Log; - -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; -import com.android.server.wifi.hotspot2.anqp.RawByteElement; -import com.android.server.wifi.util.InformationElementUtil; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class NetworkDetail { - - private static final boolean DBG = false; - - private static final String TAG = "NetworkDetail"; - - public enum Ant { - Private, - PrivateWithGuest, - ChargeablePublic, - FreePublic, - Personal, - EmergencyOnly, - Resvd6, - Resvd7, - Resvd8, - Resvd9, - Resvd10, - Resvd11, - Resvd12, - Resvd13, - TestOrExperimental, - Wildcard - } - - public enum HSRelease { - R1, - R2, - R3, - Unknown - } - - // General identifiers: - private final String mSSID; - private final long mHESSID; - private final long mBSSID; - // True if the SSID is potentially from a hidden network - private final boolean mIsHiddenSsid; - - // BSS Load element: - private final int mStationCount; - private final int mChannelUtilization; - private final int mCapacity; - - //channel detailed information - /* - * 0 -- 20 MHz - * 1 -- 40 MHz - * 2 -- 80 MHz - * 3 -- 160 MHz - * 4 -- 80 + 80 MHz - */ - private final int mChannelWidth; - private final int mPrimaryFreq; - private final int mCenterfreq0; - private final int mCenterfreq1; - - /* - * 802.11 Standard (calculated from Capabilities and Supported Rates) - * 0 -- Unknown - * 1 -- 802.11a - * 2 -- 802.11b - * 3 -- 802.11g - * 4 -- 802.11n - * 7 -- 802.11ac - */ - private final int mWifiMode; - private final int mMaxRate; - private final int mMaxNumberSpatialStreams; - - /* - * From Interworking element: - * mAnt non null indicates the presence of Interworking, i.e. 802.11u - */ - private final Ant mAnt; - private final boolean mInternet; - - /* - * From HS20 Indication element: - * mHSRelease is null only if the HS20 Indication element was not present. - * mAnqpDomainID is set to -1 if not present in the element. - */ - private final HSRelease mHSRelease; - private final int mAnqpDomainID; - - /* - * From beacon: - * mAnqpOICount is how many additional OIs are available through ANQP. - * mRoamingConsortiums is either null, if the element was not present, or is an array of - * 1, 2 or 3 longs in which the roaming consortium values occupy the LSBs. - */ - private final int mAnqpOICount; - private final long[] mRoamingConsortiums; - private int mDtimInterval = -1; - - private final InformationElementUtil.ExtendedCapabilities mExtendedCapabilities; - - private final Map<Constants.ANQPElementType, ANQPElement> mANQPElements; - - /* - * From Wi-Fi Alliance MBO-OCE Information element. - * mMboAssociationDisallowedReasonCode is the reason code for AP not accepting new connections - * and is set to -1 if association disallowed attribute is not present in the element. - */ - private final int mMboAssociationDisallowedReasonCode; - private final boolean mMboSupported; - private final boolean mMboCellularDataAware; - private final boolean mOceSupported; - - public NetworkDetail(String bssid, ScanResult.InformationElement[] infoElements, - List<String> anqpLines, int freq) { - if (infoElements == null) { - throw new IllegalArgumentException("Null information elements"); - } - - mBSSID = Utils.parseMac(bssid); - - String ssid = null; - boolean isHiddenSsid = false; - byte[] ssidOctets = null; - - InformationElementUtil.BssLoad bssLoad = new InformationElementUtil.BssLoad(); - - InformationElementUtil.Interworking interworking = - new InformationElementUtil.Interworking(); - - InformationElementUtil.RoamingConsortium roamingConsortium = - new InformationElementUtil.RoamingConsortium(); - - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - - InformationElementUtil.HtOperation htOperation = new InformationElementUtil.HtOperation(); - InformationElementUtil.VhtOperation vhtOperation = - new InformationElementUtil.VhtOperation(); - InformationElementUtil.HeOperation heOperation = new InformationElementUtil.HeOperation(); - - InformationElementUtil.HtCapabilities htCapabilities = - new InformationElementUtil.HtCapabilities(); - InformationElementUtil.VhtCapabilities vhtCapabilities = - new InformationElementUtil.VhtCapabilities(); - InformationElementUtil.HeCapabilities heCapabilities = - new InformationElementUtil.HeCapabilities(); - - InformationElementUtil.ExtendedCapabilities extendedCapabilities = - new InformationElementUtil.ExtendedCapabilities(); - - InformationElementUtil.TrafficIndicationMap trafficIndicationMap = - new InformationElementUtil.TrafficIndicationMap(); - - InformationElementUtil.SupportedRates supportedRates = - new InformationElementUtil.SupportedRates(); - InformationElementUtil.SupportedRates extendedSupportedRates = - new InformationElementUtil.SupportedRates(); - - RuntimeException exception = null; - - ArrayList<Integer> iesFound = new ArrayList<Integer>(); - try { - for (ScanResult.InformationElement ie : infoElements) { - iesFound.add(ie.id); - switch (ie.id) { - case ScanResult.InformationElement.EID_SSID: - ssidOctets = ie.bytes; - break; - case ScanResult.InformationElement.EID_BSS_LOAD: - bssLoad.from(ie); - break; - case ScanResult.InformationElement.EID_HT_OPERATION: - htOperation.from(ie); - break; - case ScanResult.InformationElement.EID_VHT_OPERATION: - vhtOperation.from(ie); - break; - case ScanResult.InformationElement.EID_HT_CAPABILITIES: - htCapabilities.from(ie); - break; - case ScanResult.InformationElement.EID_VHT_CAPABILITIES: - vhtCapabilities.from(ie); - break; - case ScanResult.InformationElement.EID_INTERWORKING: - interworking.from(ie); - break; - case ScanResult.InformationElement.EID_ROAMING_CONSORTIUM: - roamingConsortium.from(ie); - break; - case ScanResult.InformationElement.EID_VSA: - vsa.from(ie); - break; - case ScanResult.InformationElement.EID_EXTENDED_CAPS: - extendedCapabilities.from(ie); - break; - case ScanResult.InformationElement.EID_TIM: - trafficIndicationMap.from(ie); - break; - case ScanResult.InformationElement.EID_SUPPORTED_RATES: - supportedRates.from(ie); - break; - case ScanResult.InformationElement.EID_EXTENDED_SUPPORTED_RATES: - extendedSupportedRates.from(ie); - break; - case ScanResult.InformationElement.EID_EXTENSION_PRESENT: - switch(ie.idExt) { - case ScanResult.InformationElement.EID_EXT_HE_OPERATION: - heOperation.from(ie); - break; - case ScanResult.InformationElement.EID_EXT_HE_CAPABILITIES: - heCapabilities.from(ie); - break; - default: - break; - } - break; - default: - break; - } - } - } - catch (IllegalArgumentException | BufferUnderflowException | ArrayIndexOutOfBoundsException e) { - Log.d(Utils.hs2LogTag(getClass()), "Caught " + e); - if (ssidOctets == null) { - throw new IllegalArgumentException("Malformed IE string (no SSID)", e); - } - exception = e; - } - if (ssidOctets != null) { - /* - * Strict use of the "UTF-8 SSID" bit by APs appears to be spotty at best even if the - * encoding truly is in UTF-8. An unconditional attempt to decode the SSID as UTF-8 is - * therefore always made with a fall back to 8859-1 under normal circumstances. - * If, however, a previous exception was detected and the UTF-8 bit is set, failure to - * decode the SSID will be used as an indication that the whole frame is malformed and - * an exception will be triggered. - */ - CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder(); - try { - CharBuffer decoded = decoder.decode(ByteBuffer.wrap(ssidOctets)); - ssid = decoded.toString(); - } - catch (CharacterCodingException cce) { - ssid = null; - } - - if (ssid == null) { - if (extendedCapabilities.isStrictUtf8() && exception != null) { - throw new IllegalArgumentException("Failed to decode SSID in dubious IE string"); - } - else { - ssid = new String(ssidOctets, StandardCharsets.ISO_8859_1); - } - } - isHiddenSsid = true; - for (byte byteVal : ssidOctets) { - if (byteVal != 0) { - isHiddenSsid = false; - break; - } - } - } - - mSSID = ssid; - mHESSID = interworking.hessid; - mIsHiddenSsid = isHiddenSsid; - mStationCount = bssLoad.stationCount; - mChannelUtilization = bssLoad.channelUtilization; - mCapacity = bssLoad.capacity; - mAnt = interworking.ant; - mInternet = interworking.internet; - mHSRelease = vsa.hsRelease; - mAnqpDomainID = vsa.anqpDomainID; - mMboSupported = vsa.IsMboCapable; - mMboCellularDataAware = vsa.IsMboApCellularDataAware; - mOceSupported = vsa.IsOceCapable; - mMboAssociationDisallowedReasonCode = vsa.mboAssociationDisallowedReasonCode; - mAnqpOICount = roamingConsortium.anqpOICount; - mRoamingConsortiums = roamingConsortium.getRoamingConsortiums(); - mExtendedCapabilities = extendedCapabilities; - mANQPElements = null; - //set up channel info - mPrimaryFreq = freq; - int channelWidth = ScanResult.UNSPECIFIED; - int centerFreq0 = 0; - int centerFreq1 = 0; - - // First check if HE Operation IE is present - if (heOperation.isPresent()) { - // If 6GHz info is present, then parameters should be acquired from HE Operation IE - if (heOperation.is6GhzInfoPresent()) { - channelWidth = heOperation.getChannelWidth(); - centerFreq0 = heOperation.getCenterFreq0(); - centerFreq1 = heOperation.getCenterFreq1(); - } else if (heOperation.isVhtInfoPresent()) { - // VHT Operation Info could be included inside the HE Operation IE - vhtOperation.from(heOperation.getVhtInfoElement()); - } - } - - // Proceed to VHT Operation IE if parameters were not obtained from HE Operation IE - // Not operating in 6GHz - if (channelWidth == ScanResult.UNSPECIFIED) { - if (vhtOperation.isPresent()) { - channelWidth = vhtOperation.getChannelWidth(); - if (channelWidth != ScanResult.UNSPECIFIED) { - centerFreq0 = vhtOperation.getCenterFreq0(); - centerFreq1 = vhtOperation.getCenterFreq1(); - } - } - } - - // Proceed to HT Operation IE if parameters were not obtained from VHT/HE Operation IEs - // Apply to operating in 2.4/5GHz with 20/40MHz channels - if (channelWidth == ScanResult.UNSPECIFIED) { - //Either no vht, or vht shows BW is 40/20 MHz - if (htOperation.isPresent()) { - channelWidth = htOperation.getChannelWidth(); - centerFreq0 = htOperation.getCenterFreq0(mPrimaryFreq); - } - } - mChannelWidth = channelWidth; - mCenterfreq0 = centerFreq0; - mCenterfreq1 = centerFreq1; - - // If trafficIndicationMap is not valid, mDtimPeriod will be negative - if (trafficIndicationMap.isValid()) { - mDtimInterval = trafficIndicationMap.mDtimPeriod; - } - - mMaxNumberSpatialStreams = Math.max(heCapabilities.getMaxNumberSpatialStreams(), - Math.max(vhtCapabilities.getMaxNumberSpatialStreams(), - htCapabilities.getMaxNumberSpatialStreams())); - - int maxRateA = 0; - int maxRateB = 0; - // If we got some Extended supported rates, consider them, if not default to 0 - if (extendedSupportedRates.isValid()) { - // rates are sorted from smallest to largest in InformationElement - maxRateB = extendedSupportedRates.mRates.get(extendedSupportedRates.mRates.size() - 1); - } - // Only process the determination logic if we got a 'SupportedRates' - if (supportedRates.isValid()) { - maxRateA = supportedRates.mRates.get(supportedRates.mRates.size() - 1); - mMaxRate = maxRateA > maxRateB ? maxRateA : maxRateB; - mWifiMode = InformationElementUtil.WifiMode.determineMode(mPrimaryFreq, mMaxRate, - heOperation.isPresent(), vhtOperation.isPresent(), htOperation.isPresent(), - iesFound.contains(ScanResult.InformationElement.EID_ERP)); - } else { - mWifiMode = 0; - mMaxRate = 0; - } - if (DBG) { - Log.d(TAG, mSSID + "ChannelWidth is: " + mChannelWidth + " PrimaryFreq: " - + mPrimaryFreq + " Centerfreq0: " + mCenterfreq0 + " Centerfreq1: " - + mCenterfreq1 + (extendedCapabilities.is80211McRTTResponder() - ? " Support RTT responder" : " Do not support RTT responder") - + " MaxNumberSpatialStreams: " + mMaxNumberSpatialStreams - + " MboAssociationDisallowedReasonCode: " - + mMboAssociationDisallowedReasonCode); - Log.v("WifiMode", mSSID - + ", WifiMode: " + InformationElementUtil.WifiMode.toString(mWifiMode) - + ", Freq: " + mPrimaryFreq - + ", MaxRate: " + mMaxRate - + ", HE: " + String.valueOf(heOperation.isPresent()) - + ", VHT: " + String.valueOf(vhtOperation.isPresent()) - + ", HT: " + String.valueOf(htOperation.isPresent()) - + ", ERP: " + String.valueOf( - iesFound.contains(ScanResult.InformationElement.EID_ERP)) - + ", SupportedRates: " + supportedRates.toString() - + " ExtendedSupportedRates: " + extendedSupportedRates.toString()); - } - } - - private static ByteBuffer getAndAdvancePayload(ByteBuffer data, int plLength) { - ByteBuffer payload = data.duplicate().order(data.order()); - payload.limit(payload.position() + plLength); - data.position(data.position() + plLength); - return payload; - } - - private NetworkDetail(NetworkDetail base, Map<Constants.ANQPElementType, ANQPElement> anqpElements) { - mSSID = base.mSSID; - mIsHiddenSsid = base.mIsHiddenSsid; - mBSSID = base.mBSSID; - mHESSID = base.mHESSID; - mStationCount = base.mStationCount; - mChannelUtilization = base.mChannelUtilization; - mCapacity = base.mCapacity; - mAnt = base.mAnt; - mInternet = base.mInternet; - mHSRelease = base.mHSRelease; - mAnqpDomainID = base.mAnqpDomainID; - mAnqpOICount = base.mAnqpOICount; - mRoamingConsortiums = base.mRoamingConsortiums; - mExtendedCapabilities = - new InformationElementUtil.ExtendedCapabilities(base.mExtendedCapabilities); - mANQPElements = anqpElements; - mChannelWidth = base.mChannelWidth; - mPrimaryFreq = base.mPrimaryFreq; - mCenterfreq0 = base.mCenterfreq0; - mCenterfreq1 = base.mCenterfreq1; - mDtimInterval = base.mDtimInterval; - mWifiMode = base.mWifiMode; - mMaxRate = base.mMaxRate; - mMaxNumberSpatialStreams = base.mMaxNumberSpatialStreams; - mMboSupported = base.mMboSupported; - mMboCellularDataAware = base.mMboCellularDataAware; - mOceSupported = base.mOceSupported; - mMboAssociationDisallowedReasonCode = base.mMboAssociationDisallowedReasonCode; - } - - public NetworkDetail complete(Map<Constants.ANQPElementType, ANQPElement> anqpElements) { - return new NetworkDetail(this, anqpElements); - } - - public boolean queriable(List<Constants.ANQPElementType> queryElements) { - return mAnt != null && - (Constants.hasBaseANQPElements(queryElements) || - Constants.hasR2Elements(queryElements) && mHSRelease == HSRelease.R2); - } - - public boolean has80211uInfo() { - return mAnt != null || mRoamingConsortiums != null || mHSRelease != null; - } - - public boolean hasInterworking() { - return mAnt != null; - } - - public String getSSID() { - return mSSID; - } - - public String getTrimmedSSID() { - if (mSSID != null) { - for (int n = 0; n < mSSID.length(); n++) { - if (mSSID.charAt(n) != 0) { - return mSSID; - } - } - } - return ""; - } - - public long getHESSID() { - return mHESSID; - } - - public long getBSSID() { - return mBSSID; - } - - public int getStationCount() { - return mStationCount; - } - - public int getChannelUtilization() { - return mChannelUtilization; - } - - public int getCapacity() { - return mCapacity; - } - - public boolean isInterworking() { - return mAnt != null; - } - - public Ant getAnt() { - return mAnt; - } - - public boolean isInternet() { - return mInternet; - } - - public HSRelease getHSRelease() { - return mHSRelease; - } - - public int getAnqpDomainID() { - return mAnqpDomainID; - } - - public byte[] getOsuProviders() { - if (mANQPElements == null) { - return null; - } - ANQPElement osuProviders = mANQPElements.get(Constants.ANQPElementType.HSOSUProviders); - return osuProviders != null ? ((RawByteElement) osuProviders).getPayload() : null; - } - - public int getAnqpOICount() { - return mAnqpOICount; - } - - public long[] getRoamingConsortiums() { - return mRoamingConsortiums; - } - - public Map<Constants.ANQPElementType, ANQPElement> getANQPElements() { - return mANQPElements; - } - - public int getChannelWidth() { - return mChannelWidth; - } - - public int getCenterfreq0() { - return mCenterfreq0; - } - - public int getCenterfreq1() { - return mCenterfreq1; - } - - public int getWifiMode() { - return mWifiMode; - } - - public int getMaxNumberSpatialStreams() { - return mMaxNumberSpatialStreams; - } - - public int getDtimInterval() { - return mDtimInterval; - } - - public boolean is80211McResponderSupport() { - return mExtendedCapabilities.is80211McRTTResponder(); - } - - public boolean isSSID_UTF8() { - return mExtendedCapabilities.isStrictUtf8(); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (thatObject == null || getClass() != thatObject.getClass()) { - return false; - } - - NetworkDetail that = (NetworkDetail)thatObject; - - return getSSID().equals(that.getSSID()) && getBSSID() == that.getBSSID(); - } - - @Override - public int hashCode() { - return ((mSSID.hashCode() * 31) + (int)(mBSSID >>> 32)) * 31 + (int)mBSSID; - } - - @Override - public String toString() { - return String.format("NetworkInfo{SSID='%s', HESSID=%x, BSSID=%x, StationCount=%d, " + - "ChannelUtilization=%d, Capacity=%d, Ant=%s, Internet=%s, " + - "HSRelease=%s, AnqpDomainID=%d, " + - "AnqpOICount=%d, RoamingConsortiums=%s}", - mSSID, mHESSID, mBSSID, mStationCount, - mChannelUtilization, mCapacity, mAnt, mInternet, - mHSRelease, mAnqpDomainID, - mAnqpOICount, Utils.roamingConsortiumsToString(mRoamingConsortiums)); - } - - public String toKeyString() { - return mHESSID != 0 ? - String.format("'%s':%012x (%012x)", mSSID, mBSSID, mHESSID) : - String.format("'%s':%012x", mSSID, mBSSID); - } - - public String getBSSIDString() { - return toMACString(mBSSID); - } - - /** - * Evaluates the ScanResult this NetworkDetail is built from - * returns true if built from a Beacon Frame - * returns false if built from a Probe Response - */ - public boolean isBeaconFrame() { - // Beacon frames have a 'Traffic Indication Map' Information element - // Probe Responses do not. This is indicated by a DTIM period > 0 - return mDtimInterval > 0; - } - - /** - * Evaluates the ScanResult this NetworkDetail is built from - * returns true if built from a hidden Beacon Frame - * returns false if not hidden or not a Beacon - */ - public boolean isHiddenBeaconFrame() { - // Hidden networks are not 80211 standard, but it is common for a hidden network beacon - // frame to either send zero-value bytes as the SSID, or to send no bytes at all. - return isBeaconFrame() && mIsHiddenSsid; - } - - public static String toMACString(long mac) { - StringBuilder sb = new StringBuilder(); - boolean first = true; - for (int n = BYTES_IN_EUI48 - 1; n >= 0; n--) { - if (first) { - first = false; - } else { - sb.append(':'); - } - sb.append(String.format("%02x", (mac >>> (n * Byte.SIZE)) & BYTE_MASK)); - } - return sb.toString(); - } - - public int getMboAssociationDisallowedReasonCode() { - return mMboAssociationDisallowedReasonCode; - } - - public boolean isMboSupported() { - return mMboSupported; - } - - public boolean isMboCellularDataAware() { - return mMboCellularDataAware; - } - - public boolean isOceSupported() { - return mOceSupported; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/OsuNetworkConnection.java b/service/java/com/android/server/wifi/hotspot2/OsuNetworkConnection.java deleted file mode 100644 index b3bab6432..000000000 --- a/service/java/com/android/server/wifi/hotspot2/OsuNetworkConnection.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright 2017 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.server.wifi.hotspot2; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.text.TextUtils; -import android.util.Log; - -/** - * Responsible for setup/monitor on Wi-Fi state and connection to the OSU AP. - */ -public class OsuNetworkConnection { - private static final String TAG = "PasspointOsuNetworkConnection"; - private static final int TIMEOUT_MS = 10000; - - private final Context mContext; - - private boolean mVerboseLoggingEnabled = false; - private WifiManager mWifiManager; - private ConnectivityManager mConnectivityManager; - private ConnectivityCallbacks mConnectivityCallbacks; - private Callbacks mCallbacks; - private Handler mHandler; - private Network mNetwork = null; - private boolean mConnected = false; - private int mNetworkId = -1; - private boolean mWifiEnabled = false; - - /** - * Callbacks on Wi-Fi connection state changes. - */ - public interface Callbacks { - /** - * Invoked when network connection is established with IP connectivity. - * - * @param network {@link Network} associated with the connected network. - */ - void onConnected(Network network); - - /** - * Invoked when the targeted network is disconnected. - */ - void onDisconnected(); - - /** - * Invoked when a timer tracking connection request is not reset by successful connection. - */ - void onTimeOut(); - - /** - * Invoked when Wifi is enabled. - */ - void onWifiEnabled(); - - /** - * Invoked when Wifi is disabled. - */ - void onWifiDisabled(); - } - - public OsuNetworkConnection(Context context) { - mContext = context; - } - - /** - * Called to initialize tracking of wifi state and network events by registering for the - * corresponding intents. - */ - public void init(Handler handler) { - IntentFilter filter = new IntentFilter(); - filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - BroadcastReceiver receiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN); - if (state == WifiManager.WIFI_STATE_DISABLED && mWifiEnabled) { - mWifiEnabled = false; - if (mCallbacks != null) mCallbacks.onWifiDisabled(); - } - if (state == WifiManager.WIFI_STATE_ENABLED && !mWifiEnabled) { - mWifiEnabled = true; - if (mCallbacks != null) mCallbacks.onWifiEnabled(); - } - } - } - }; - mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - mContext.registerReceiver(receiver, filter, null, handler); - mWifiEnabled = mWifiManager.isWifiEnabled(); - mConnectivityManager = - (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - mConnectivityCallbacks = new ConnectivityCallbacks(); - mHandler = handler; - } - - /** - * Disconnect, if required in the two cases - * - still connected to the OSU AP - * - connection to OSU AP was requested and in progress - */ - public void disconnectIfNeeded() { - if (mNetworkId < 0) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "No connection to tear down"); - } - return; - } - mConnectivityManager.unregisterNetworkCallback(mConnectivityCallbacks); - mWifiManager.removeNetwork(mNetworkId); - mNetworkId = -1; - mNetwork = null; - mConnected = false; - } - - /** - * Register for network and Wifi state events - * - * @param callbacks The callbacks to be invoked on network change events - */ - public void setEventCallback(Callbacks callbacks) { - mCallbacks = callbacks; - } - - /** - * Connect to a OSU Wi-Fi network specified by the given SSID. The security type of the Wi-Fi - * network is either open or OSEN (OSU Server-only authenticated layer 2 Encryption Network). - * When network access identifier is provided, OSEN is used. - * - * @param ssid The SSID to connect to - * @param nai Network access identifier of the network - * @param friendlyName a friendly name of service provider - * - * @return boolean true if connection was successfully initiated - */ - public boolean connect(WifiSsid ssid, String nai, String friendlyName) { - if (mConnected) { - if (mVerboseLoggingEnabled) { - // Already connected - Log.v(TAG, "Connect called twice"); - } - return true; - } - if (!mWifiEnabled) { - Log.w(TAG, "Wifi is not enabled"); - return false; - } - WifiConfiguration config = new WifiConfiguration(); - config.SSID = "\"" + ssid.toString() + "\""; - - // To suppress Wi-Fi has no internet access notification. - config.noInternetAccessExpected = true; - - // To suppress Wi-Fi Sign-in notification for captive portal. - config.osu = true; - - // Do not save this network - config.ephemeral = true; - config.providerFriendlyName = friendlyName; - - if (TextUtils.isEmpty(nai)) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - } else { - // Setup OSEN connection with Unauthenticated user TLS and WFA Root certs - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OSEN); - config.allowedProtocols.set(WifiConfiguration.Protocol.OSEN); - config.enterpriseConfig.setDomainSuffixMatch(nai); - config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.UNAUTH_TLS); - config.enterpriseConfig.setCaPath(WfaKeyStore.DEFAULT_WFA_CERT_DIR); - } - mNetworkId = mWifiManager.addNetwork(config); - if (mNetworkId < 0) { - Log.e(TAG, "Unable to add network"); - return false; - } - - // NET_CAPABILITY_TRUSTED is added by builder by default. - // But for ephemeral network, the capability needs to be removed - // as wifi stack creates network agent without the capability. - // That could cause connectivity service not to find the matching agent. - NetworkRequest networkRequest = new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .removeCapability(NET_CAPABILITY_TRUSTED) - .build(); - mConnectivityManager.requestNetwork(networkRequest, mConnectivityCallbacks, mHandler, - TIMEOUT_MS); - - // TODO(b/112195429): replace it with new connectivity API. - if (!mWifiManager.enableNetwork(mNetworkId, true)) { - Log.e(TAG, "Unable to enable network " + mNetworkId); - disconnectIfNeeded(); - return false; - } - - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Current network ID " + mNetworkId); - } - return true; - } - - /** - * Method to update logging level in this class - * - * @param verbose more than 0 enables verbose logging - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = verbose > 0 ? true : false; - } - - private class ConnectivityCallbacks extends ConnectivityManager.NetworkCallback { - @Override - public void onAvailable(Network network) { - WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); - if (wifiInfo == null) { - Log.w(TAG, "wifiInfo is not valid"); - return; - } - if (mNetworkId < 0 || mNetworkId != wifiInfo.getNetworkId()) { - Log.w(TAG, "Irrelevant network available notification for netId: " - + wifiInfo.getNetworkId()); - return; - } - mNetwork = network; - mConnected = true; - } - - @Override - public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onLinkPropertiesChanged for network=" + network - + " isProvisioned?" + linkProperties.isProvisioned()); - } - if (mNetwork == null) { - Log.w(TAG, "ignore onLinkPropertyChanged event for null network"); - return; - } - if (linkProperties.isProvisioned()) { - if (mCallbacks != null) { - mCallbacks.onConnected(network); - } - } - } - - @Override - public void onUnavailable() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onUnvailable "); - } - if (mCallbacks != null) { - mCallbacks.onTimeOut(); - } - } - - @Override - public void onLost(Network network) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onLost " + network); - } - if (network != mNetwork) { - Log.w(TAG, "Irrelevant network lost notification"); - return; - } - if (mCallbacks != null) { - mCallbacks.onDisconnected(); - } - } - } -} - diff --git a/service/java/com/android/server/wifi/hotspot2/OsuServerConnection.java b/service/java/com/android/server/wifi/hotspot2/OsuServerConnection.java deleted file mode 100644 index f9c9df13c..000000000 --- a/service/java/com/android/server/wifi/hotspot2/OsuServerConnection.java +++ /dev/null @@ -1,699 +0,0 @@ -/* - * Copyright 2017 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.server.wifi.hotspot2; - -import android.annotation.NonNull; -import android.net.Network; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.hotspot2.soap.HttpsServiceConnection; -import com.android.server.wifi.hotspot2.soap.HttpsTransport; -import com.android.server.wifi.hotspot2.soap.SoapParser; -import com.android.server.wifi.hotspot2.soap.SppResponseMessage; - -import org.ksoap2.HeaderProperty; -import org.ksoap2.serialization.AttributeInfo; -import org.ksoap2.serialization.SoapObject; -import org.ksoap2.serialization.SoapSerializationEnvelope; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; -import java.security.KeyManagementException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.CertificateParsingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -/** - * Provides methods to interface with the OSU server - */ -public class OsuServerConnection { - private static final String TAG = "PasspointOsuServerConnection"; - - private static final int DNS_NAME = 2; - - private SSLSocketFactory mSocketFactory; - private URL mUrl; - private Network mNetwork; - private WFATrustManager mTrustManager; - private HttpsTransport mHttpsTransport; - private HttpsServiceConnection mServiceConnection = null; - private HttpsURLConnection mUrlConnection = null; - private HandlerThread mOsuServerHandlerThread; - private Handler mHandler; - private PasspointProvisioner.OsuServerCallbacks mOsuServerCallbacks; - private boolean mSetupComplete = false; - private boolean mVerboseLoggingEnabled = false; - private Looper mLooper; - - public static final int TRUST_CERT_TYPE_AAA = 1; - public static final int TRUST_CERT_TYPE_REMEDIATION = 2; - public static final int TRUST_CERT_TYPE_POLICY = 3; - - @VisibleForTesting - /* package */ OsuServerConnection(Looper looper) { - mLooper = looper; - } - - /** - * Sets up callback for event - * - * @param callbacks OsuServerCallbacks to be invoked for server related events - */ - public void setEventCallback(PasspointProvisioner.OsuServerCallbacks callbacks) { - mOsuServerCallbacks = callbacks; - } - - /** - * Initializes socket factory for server connection using HTTPS - * - * @param tlsContext SSLContext that will be used for HTTPS connection - * @param trustManagerFactory TrustManagerFactory to extract the trust manager from - */ - public void init(SSLContext tlsContext, TrustManagerFactory trustManagerFactory) { - if (tlsContext == null || trustManagerFactory == null) { - Log.e(TAG, "Invalid arguments passed to init"); - return; - } - try { - X509TrustManager x509TrustManager = null; - for (TrustManager tm : trustManagerFactory.getTrustManagers()) { - if (tm instanceof X509TrustManager) { - x509TrustManager = (X509TrustManager) tm; - break; - } - } - if (x509TrustManager == null) { - Log.e(TAG, "Unable to initialize trust manager"); - return; - } - mTrustManager = new WFATrustManager(x509TrustManager); - tlsContext.init(null, new TrustManager[]{mTrustManager}, null); - mSocketFactory = tlsContext.getSocketFactory(); - } catch (KeyManagementException e) { - Log.w(TAG, "Initialization failed"); - e.printStackTrace(); - return; - } - mSetupComplete = true; - - // If mLooper is already set by unit test, don't overwrite it. - if (mLooper == null) { - mOsuServerHandlerThread = new HandlerThread("OsuServerHandler"); - mOsuServerHandlerThread.start(); - mLooper = mOsuServerHandlerThread.getLooper(); - } - mHandler = new Handler(mLooper); - } - - /** - * Provides the capability to run OSU server validation - * - * @return boolean true if capability available - */ - public boolean canValidateServer() { - return mSetupComplete; - } - - /** - * Enables verbose logging - * - * @param verbose a value greater than zero enables verbose logging - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = verbose > 0 ? true : false; - } - - /** - * Connects to the OSU server - * - * @param url Osu Server's URL - * @param network current network connection - * @return {@code true} if {@code url} and {@code network} are not null - * - * Note: Relies on the caller to ensure that the capability to validate the OSU - * Server is available. - */ - public boolean connect(@NonNull URL url, @NonNull Network network) { - if (url == null) { - Log.e(TAG, "URL is null"); - return false; - } - if (network == null) { - Log.e(TAG, "network is null"); - return false; - } - - String protocol = url.getProtocol(); - // According to section 7.5.1 OSU operational requirements, in HS2.0 R3 specification, - // the URL must be HTTPS. Enforce it here. - if (!TextUtils.equals(protocol, "https")) { - Log.e(TAG, "OSU server URL must be HTTPS"); - return false; - } - - mHandler.post(() -> performTlsConnection(url, network)); - return true; - } - - /** - * Validates the service provider by comparing its identities found in OSU Server cert - * to the friendlyName obtained from ANQP exchange that is displayed to the user. - * - * @param friendlyNames the friendly names used for finding the same name in - * subjectAltName section of the certificate, which is a map of language - * codes from ISO-639 and names. - * @return boolean true if friendlyName shows up as one of the identities in the cert - */ - public boolean validateProvider( - Map<String, String> friendlyNames) { - - if (friendlyNames.size() == 0) { - return false; - } - - for (Pair<Locale, String> identity : ServiceProviderVerifier.getProviderNames( - mTrustManager.getProviderCert())) { - if (identity.first == null || TextUtils.isEmpty(identity.second)) continue; - - // Compare the language code for ISO-639. - if (TextUtils.equals(identity.second, - friendlyNames.get(identity.first.getISO3Language()))) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "OSU certificate is valid for " - + identity.first.getISO3Language() + "/" + identity.second); - } - return true; - } - } - return false; - } - - /** - * The helper method to exchange a SOAP message. - * - * @param soapEnvelope the soap message to be sent. - * @return {@code true} if {@link Network} is valid and {@code soapEnvelope} is not {@code - * null}, {@code false} otherwise. - */ - public boolean exchangeSoapMessage(@NonNull SoapSerializationEnvelope soapEnvelope) { - if (mNetwork == null) { - Log.e(TAG, "Network is not established"); - return false; - } - - if (mUrlConnection == null) { - Log.e(TAG, "Server certificate is not validated"); - return false; - } - - if (soapEnvelope == null) { - Log.e(TAG, "soapEnvelope is null"); - return false; - } - - mHandler.post(() -> performSoapMessageExchange(soapEnvelope)); - return true; - } - - /** - * Retrieves Trust Root CA certificates for AAA, Remediation, Policy Server - * - * @param trustCertsInfo trust cert information for each type (AAA,Remediation and Policy). - * {@code Key} is the cert type. - * {@code Value} is the map that has a key for certUrl and a value for - * fingerprint of the certificate. - * @return {@code true} if {@link Network} is valid and {@code trustCertsInfo} is not {@code - * null}, {@code false} otherwise. - */ - public boolean retrieveTrustRootCerts( - @NonNull Map<Integer, Map<String, byte[]>> trustCertsInfo) { - if (mNetwork == null) { - Log.e(TAG, "Network is not established"); - return false; - } - - if (mUrlConnection == null) { - Log.e(TAG, "Server certificate is not validated"); - return false; - } - - if (trustCertsInfo == null || trustCertsInfo.isEmpty()) { - Log.e(TAG, "TrustCertsInfo is not valid"); - return false; - } - mHandler.post(() -> performRetrievingTrustRootCerts(trustCertsInfo)); - return true; - } - - private void performTlsConnection(URL url, Network network) { - mNetwork = network; - mUrl = url; - - URLConnection urlConnection; - HttpsURLConnection httpsURLConnection; - - try { - urlConnection = mNetwork.openConnection(mUrl); - } catch (IOException e) { - Log.e(TAG, "Unable to establish a URL connection: " + e); - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onServerConnectionStatus( - mOsuServerCallbacks.getSessionId(), - false); - } - return; - } - - if (urlConnection instanceof HttpsURLConnection) { - httpsURLConnection = (HttpsURLConnection) urlConnection; - } else { - Log.e(TAG, "Invalid URL connection"); - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onServerConnectionStatus(mOsuServerCallbacks.getSessionId(), - false); - } - return; - } - - try { - httpsURLConnection.setSSLSocketFactory(mSocketFactory); - httpsURLConnection.setConnectTimeout(HttpsServiceConnection.DEFAULT_TIMEOUT_MS); - httpsURLConnection.setReadTimeout(HttpsServiceConnection.DEFAULT_TIMEOUT_MS); - httpsURLConnection.connect(); - } catch (IOException e) { - Log.e(TAG, "Unable to establish a URL connection: " + e); - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onServerConnectionStatus(mOsuServerCallbacks.getSessionId(), - false); - } - return; - } - mUrlConnection = httpsURLConnection; - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onServerConnectionStatus(mOsuServerCallbacks.getSessionId(), true); - } - } - - private void performSoapMessageExchange(@NonNull SoapSerializationEnvelope soapEnvelope) { - if (mServiceConnection != null) { - mServiceConnection.disconnect(); - } - - mServiceConnection = getServiceConnection(mUrl, mNetwork); - if (mServiceConnection == null) { - Log.e(TAG, "ServiceConnection for https is null"); - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), null); - } - return; - } - - SppResponseMessage sppResponse; - try { - // Sending the SOAP message - mHttpsTransport.call("", soapEnvelope); - Object response = soapEnvelope.bodyIn; - if (response == null) { - Log.e(TAG, "SoapObject is null"); - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - null); - } - return; - } - if (!(response instanceof SoapObject)) { - Log.e(TAG, "Not a SoapObject instance"); - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - null); - } - return; - } - SoapObject soapResponse = (SoapObject) response; - if (mVerboseLoggingEnabled) { - for (int i = 0; i < soapResponse.getAttributeCount(); i++) { - AttributeInfo attributeInfo = new AttributeInfo(); - soapResponse.getAttributeInfo(i, attributeInfo); - Log.v(TAG, "Attribute : " + attributeInfo.toString()); - } - Log.v(TAG, "response : " + soapResponse.toString()); - } - - // Get the parsed SOAP SPP Response message - sppResponse = SoapParser.getResponse(soapResponse); - } catch (Exception e) { - if (e instanceof SSLHandshakeException) { - Log.e(TAG, "Failed to make TLS connection: " + e); - } else { - Log.e(TAG, "Failed to exchange the SOAP message: " + e); - } - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), null); - } - return; - } finally { - mServiceConnection.disconnect(); - mServiceConnection = null; - } - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - sppResponse); - } - } - - private void performRetrievingTrustRootCerts( - @NonNull Map<Integer, Map<String, byte[]>> trustCertsInfo) { - // Key: CERT_TYPE (AAA, REMEDIATION, POLICY), Value: a list of X509Certificate retrieved for - // the type. - Map<Integer, List<X509Certificate>> trustRootCertificates = new HashMap<>(); - - for (Map.Entry<Integer, Map<String, byte[]>> certInfoPerType : trustCertsInfo.entrySet()) { - List<X509Certificate> certificates = new ArrayList<>(); - - // Iterates certInfo to get a cert with a url provided in certInfo.key(). - // Key: Cert url, Value: SHA-256 hash bytes to match the fingerprint of a - // certificates retrieved from server. - for (Map.Entry<String, byte[]> certInfo : certInfoPerType.getValue().entrySet()) { - if (certInfo.getValue() == null) { - // clear all of retrieved CA certs so that PasspointProvisioner aborts - // current flow. - trustRootCertificates.clear(); - break; - } - X509Certificate certificate = getCert(certInfo.getKey()); - - if (certificate == null) { - // In case of an invalid cert, clear all of retrieved CA certs so that - // PasspointProvisioner aborts current flow. getCert already logs the error. - trustRootCertificates.clear(); - break; - } - - // Verify that the certificate's fingerprint matches the one provided in the PPS-MO - // profile, in accordance with section 7.3.1 of the HS2.0 specification. - if (!ServiceProviderVerifier.verifyCertFingerprint( - certificate, certInfo.getValue())) { - // If fingerprint does not match, clear all of retrieved CA certs so that - // PasspointProvisioner aborts current flow. - trustRootCertificates.clear(); - String certName = ""; - if (certificate.getSubjectDN() != null) { - certName = certificate.getSubjectDN().getName(); - } - Log.e(TAG, "Fingerprint does not match the certificate " + certName); - break; - } - certificates.add(certificate); - } - if (!certificates.isEmpty()) { - trustRootCertificates.put(certInfoPerType.getKey(), certificates); - } - } - - if (mOsuServerCallbacks != null) { - // If it passes empty trustRootCertificates here, PasspointProvisioner will abort - // current flow because it indicates that client device doesn't get any trust root - // certificates from server. - mOsuServerCallbacks.onReceivedTrustRootCertificates(mOsuServerCallbacks.getSessionId(), - trustRootCertificates); - } - } - - /** - * Retrieves a X.509 Certificate from server. - * - * @param certUrl url to retrieve a X.509 Certificate - * @return {@link X509Certificate} in success, {@code null} otherwise. - */ - private X509Certificate getCert(@NonNull String certUrl) { - if (certUrl == null || !certUrl.toLowerCase(Locale.US).startsWith("https://")) { - Log.e(TAG, "invalid certUrl provided"); - return null; - } - - try { - URL serverUrl = new URL(certUrl); - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - if (mServiceConnection != null) { - mServiceConnection.disconnect(); - } - mServiceConnection = getServiceConnection(serverUrl, mNetwork); - if (mServiceConnection == null) { - return null; - } - mServiceConnection.setRequestMethod("GET"); - mServiceConnection.setRequestProperty("Accept-Encoding", "gzip"); - - if (mServiceConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { - Log.e(TAG, "The response code of the HTTPS GET to " + certUrl - + " is not OK, but " + mServiceConnection.getResponseCode()); - return null; - } - boolean bPkcs7 = false; - boolean bBase64 = false; - List<HeaderProperty> properties = mServiceConnection.getResponseProperties(); - for (HeaderProperty property : properties) { - if (property == null || property.getKey() == null || property.getValue() == null) { - continue; - } - if (property.getKey().equalsIgnoreCase("Content-Type")) { - if (property.getValue().equals("application/pkcs7-mime") - || property.getValue().equals("application/x-x509-ca-cert")) { - // application/x-x509-ca-cert : File content is a DER encoded X.509 - // certificate - if (mVerboseLoggingEnabled) { - Log.v(TAG, "a certificate found in a HTTPS response from " + certUrl); - } - - // ca cert - bPkcs7 = true; - } - } - if (property.getKey().equalsIgnoreCase("Content-Transfer-Encoding") - && property.getValue().equalsIgnoreCase("base64")) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, - "base64 encoding content in a HTTP response from " + certUrl); - } - bBase64 = true; - } - } - if (!bPkcs7) { - Log.e(TAG, "no X509Certificate found in the HTTPS response"); - return null; - } - InputStream in = mServiceConnection.openInputStream(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] buf = new byte[8192]; - while (true) { - int rd = in.read(buf, 0, 8192); - if (rd == -1) { - break; - } - bos.write(buf, 0, rd); - } - in.close(); - bos.flush(); - byte[] byteArray = bos.toByteArray(); - if (bBase64) { - String s = new String(byteArray); - byteArray = android.util.Base64.decode(s, android.util.Base64.DEFAULT); - } - - X509Certificate certificate = (X509Certificate) certFactory.generateCertificate( - new ByteArrayInputStream(byteArray)); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "cert : " + certificate.getSubjectDN()); - } - return certificate; - } catch (IOException e) { - Log.e(TAG, "Failed to get the data from " + certUrl + ": " + e); - } catch (CertificateException e) { - Log.e(TAG, "Failed to get instance for CertificateFactory " + e); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Failed to decode the data: " + e); - } finally { - mServiceConnection.disconnect(); - mServiceConnection = null; - } - return null; - } - - /** - * Gets the HTTPS service connection used for SOAP message exchange. - * - * @return {@link HttpsServiceConnection} - */ - private HttpsServiceConnection getServiceConnection(@NonNull URL url, - @NonNull Network network) { - HttpsServiceConnection serviceConnection; - try { - // Creates new HTTPS connection. - mHttpsTransport = HttpsTransport.createInstance(network, url); - serviceConnection = (HttpsServiceConnection) mHttpsTransport.getServiceConnection(); - if (serviceConnection != null) { - serviceConnection.setSSLSocketFactory(mSocketFactory); - } - } catch (IOException e) { - Log.e(TAG, "Unable to establish a URL connection"); - return null; - } - return serviceConnection; - } - - private void cleanupConnection() { - if (mUrlConnection != null) { - mUrlConnection.disconnect(); - mUrlConnection = null; - } - if (mServiceConnection != null) { - mServiceConnection.disconnect(); - mServiceConnection = null; - } - } - - /** - * Cleans up - */ - public void cleanup() { - mHandler.post(() -> cleanupConnection()); - } - - private class WFATrustManager implements X509TrustManager { - private X509TrustManager mDelegate; - private List<X509Certificate> mServerCerts; - - WFATrustManager(@NonNull X509TrustManager x509TrustManager) { - mDelegate = x509TrustManager; - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "checkClientTrusted " + authType); - } - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "checkServerTrusted " + authType); - } - boolean certsValid = false; - try { - // Perform certificate path validation and get validated certs - mDelegate.checkServerTrusted(chain, authType); - mServerCerts = Arrays.asList(chain); - certsValid = true; - } catch (CertificateException e) { - Log.e(TAG, "Certificate validation failure: " + e); - int i = 0; - for (X509Certificate cert : chain) { - // Provide some more details about the invalid certificate - Log.e(TAG, "Cert " + i + " details: " + cert.getSubjectDN()); - Log.e(TAG, "Not before: " + cert.getNotBefore() + ", not after: " - + cert.getNotAfter()); - Log.e(TAG, "Cert " + i + " issuer: " + cert.getIssuerDN()); - i++; - } - } - if (mOsuServerCallbacks != null) { - mOsuServerCallbacks.onServerValidationStatus(mOsuServerCallbacks.getSessionId(), - certsValid); - } - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "getAcceptedIssuers "); - } - return null; - } - - /** - * Returns the OSU certificate matching the FQDN of the OSU server - * - * @return {@link X509Certificate} OSU certificate matching FQDN of OSU server - */ - public X509Certificate getProviderCert() { - if (mServerCerts == null || mServerCerts.size() <= 0) { - return null; - } - X509Certificate providerCert = null; - String fqdn = mUrl.getHost(); - try { - for (X509Certificate certificate : mServerCerts) { - Collection<List<?>> col = certificate.getSubjectAlternativeNames(); - if (col == null) { - continue; - } - for (List<?> name : col) { - if (name == null) { - continue; - } - if (name.size() >= DNS_NAME - && name.get(0).getClass() == Integer.class - && name.get(1).toString().equals(fqdn)) { - providerCert = certificate; - if (mVerboseLoggingEnabled) { - Log.v(TAG, "OsuCert found"); - } - break; - } - } - } - } catch (CertificateParsingException e) { - Log.e(TAG, "Unable to match certificate to " + fqdn); - if (mVerboseLoggingEnabled) { - e.printStackTrace(); - } - } - return providerCert; - } - } -} - diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java deleted file mode 100644 index b956983c4..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2; - -import android.annotation.Nullable; -import android.util.Log; - -import com.android.server.wifi.WifiConfigStore; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; - -/** - * Responsible for Passpoint specific configuration store data. There are two types of - * configuration data, system wide and user specific. The system wide configurations are stored - * in the share store and user specific configurations are store in the user store. - * - * Below are the current configuration data for each respective store file, the list will - * probably grow in the future. - * - * Share Store (system wide configurations) - * - Current provider index - use for assigning provider ID during provider creation, to make - * sure each provider will have an unique ID across all users. - * - * User Store (user specific configurations) - * - Provider list - list of Passpoint provider configurations - * - */ -public class PasspointConfigSharedStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "PasspointConfigSharedStoreData"; - private static final String XML_TAG_SECTION_HEADER_PASSPOINT_CONFIG_DATA = - "PasspointConfigData"; - private static final String XML_TAG_PROVIDER_INDEX = "ProviderIndex"; - - private final DataSource mDataSource; - - /** - * Interface define the data source for the Passpoint configuration store data. - */ - public interface DataSource { - /** - * Retrieve the current provider index. - * - * @return long - */ - long getProviderIndex(); - - /** - * Set the current provider index. - * - * @param providerIndex The provider index used for provider creation - */ - void setProviderIndex(long providerIndex); - } - - PasspointConfigSharedStoreData(DataSource dataSource) { - mDataSource = dataSource; - } - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - serializeShareData(out); - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - // Ignore empty reads. - if (in == null) { - return; - } - deserializeShareData(in, outerTagDepth); - } - - /** - * Reset share data (system wide Passpoint configurations). - */ - @Override - public void resetData() { - mDataSource.setProviderIndex(0); - } - - @Override - public boolean hasNewDataToSerialize() { - // always persist. - return true; - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER_PASSPOINT_CONFIG_DATA; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - // Shared general store. - return WifiConfigStore.STORE_FILE_SHARED_GENERAL; - } - - /** - * Serialize share data (system wide Passpoint configurations) to a XML block. - * - * @param out The output stream to serialize data to - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeShareData(XmlSerializer out) throws XmlPullParserException, IOException { - XmlUtil.writeNextValue(out, XML_TAG_PROVIDER_INDEX, mDataSource.getProviderIndex()); - } - - /** - * Deserialize share data (system wide Passpoint configurations) from the input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @throws XmlPullParserException - * @throws IOException - */ - private void deserializeShareData(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_PROVIDER_INDEX: - mDataSource.setProviderIndex((long) value); - break; - default: - Log.w(TAG, "Ignoring unknown value under share store data " + valueName[0]); - break; - } - } - } -} - - diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java deleted file mode 100644 index 8400bb581..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2; - -import android.annotation.Nullable; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.text.TextUtils; -import android.util.Log; - -import com.android.server.wifi.WifiCarrierInfoManager; -import com.android.server.wifi.WifiConfigStore; -import com.android.server.wifi.WifiKeyStore; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Responsible for Passpoint specific configuration store data. There are two types of - * configuration data, system wide and user specific. The system wide configurations are stored - * in the share store and user specific configurations are store in the user store. - * - * Below are the current configuration data for each respective store file, the list will - * probably grow in the future. - * - * Share Store (system wide configurations) - * - Current provider index - use for assigning provider ID during provider creation, to make - * sure each provider will have an unique ID across all users. - * - * User Store (user specific configurations) - * - Provider list - list of Passpoint provider configurations - * - */ -public class PasspointConfigUserStoreData implements WifiConfigStore.StoreData { - private static final String TAG = "PasspointConfigUserStoreData"; - private static final String XML_TAG_SECTION_HEADER_PASSPOINT_CONFIG_DATA = - "PasspointConfigData"; - private static final String XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER_LIST = - "ProviderList"; - private static final String XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER = - "Provider"; - private static final String XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION = - "Configuration"; - - private static final String XML_TAG_PROVIDER_ID = "ProviderID"; - private static final String XML_TAG_CREATOR_UID = "CreatorUID"; - private static final String XML_TAG_PACKAGE_NAME = "PackageName"; - private static final String XML_TAG_CA_CERTIFICATE_ALIASES = "CaCertificateAliases"; - private static final String XML_TAG_CA_CERTIFICATE_ALIAS = "CaCertificateAlias"; - private static final String XML_TAG_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS = "ClientPrivateKeyAlias"; - private static final String XML_TAG_REMEDIATION_CA_CERTIFICATE_ALIAS = - "RemediationCaCertificateAlias"; - - private static final String XML_TAG_HAS_EVER_CONNECTED = "HasEverConnected"; - private static final String XML_TAG_IS_FROM_SUGGESTION = "IsFromSuggestion"; - private static final String XML_TAG_IS_TRUSTED = "IsTrusted"; - - private final WifiKeyStore mKeyStore; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - private final DataSource mDataSource; - - /** - * Interface define the data source for the Passpoint configuration store data. - */ - public interface DataSource { - /** - * Retrieve the provider list from the data source. - * - * @return List of {@link PasspointProvider} - */ - List<PasspointProvider> getProviders(); - - /** - * Set the provider list in the data source. - * - * @param providers The list of providers - */ - void setProviders(List<PasspointProvider> providers); - } - - PasspointConfigUserStoreData(WifiKeyStore keyStore, - WifiCarrierInfoManager wifiCarrierInfoManager, DataSource dataSource) { - mKeyStore = keyStore; - mWifiCarrierInfoManager = wifiCarrierInfoManager; - mDataSource = dataSource; - } - - @Override - public void serializeData(XmlSerializer out, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - serializeUserData(out); - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, - @WifiConfigStore.Version int version, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - // Ignore empty reads. - if (in == null) { - return; - } - deserializeUserData(in, outerTagDepth); - } - - /** - * Reset user data (user specific Passpoint configurations). - */ - @Override - public void resetData() { - mDataSource.setProviders(new ArrayList<PasspointProvider>()); - } - - @Override - public boolean hasNewDataToSerialize() { - // always persist. - return true; - } - - @Override - public String getName() { - return XML_TAG_SECTION_HEADER_PASSPOINT_CONFIG_DATA; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - // Shared general store. - return WifiConfigStore.STORE_FILE_USER_GENERAL; - } - - /** - * Serialize user data (user specific Passpoint configurations) to a XML block. - * - * @param out The output stream to serialize data to - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeUserData(XmlSerializer out) throws XmlPullParserException, IOException { - serializeProviderList(out, mDataSource.getProviders()); - } - - /** - * Serialize the list of Passpoint providers from the data source to a XML block. - * - * @param out The output stream to serialize data to - * @param providerList The list of providers to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeProviderList(XmlSerializer out, List<PasspointProvider> providerList) - throws XmlPullParserException, IOException { - if (providerList == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER_LIST); - for (PasspointProvider provider : providerList) { - serializeProvider(out, provider); - } - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER_LIST); - } - - /** - * Serialize a Passpoint provider to a XML block. - * - * @param out The output stream to serialize data to - * @param provider The provider to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private void serializeProvider(XmlSerializer out, PasspointProvider provider) - throws XmlPullParserException, IOException { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER); - XmlUtil.writeNextValue(out, XML_TAG_PROVIDER_ID, provider.getProviderId()); - XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, provider.getCreatorUid()); - if (provider.getPackageName() != null) { - XmlUtil.writeNextValue(out, XML_TAG_PACKAGE_NAME, provider.getPackageName()); - } - XmlUtil.writeNextValue(out, XML_TAG_CA_CERTIFICATE_ALIASES, - provider.getCaCertificateAliases()); - XmlUtil.writeNextValue(out, XML_TAG_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, - provider.getClientPrivateKeyAndCertificateAlias()); - XmlUtil.writeNextValue(out, XML_TAG_HAS_EVER_CONNECTED, provider.getHasEverConnected()); - XmlUtil.writeNextValue(out, XML_TAG_IS_FROM_SUGGESTION, provider.isFromSuggestion()); - XmlUtil.writeNextValue(out, XML_TAG_IS_TRUSTED, provider.isTrusted()); - if (provider.getConfig() != null) { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION); - PasspointXmlUtils.serializePasspointConfiguration(out, provider.getConfig()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION); - } - XmlUtil.writeNextValue(out, XML_TAG_REMEDIATION_CA_CERTIFICATE_ALIAS, - provider.getRemediationCaCertificateAlias()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER); - } - - /** - * Deserialize user data (user specific Passpoint configurations) from the input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @throws XmlPullParserException - * @throws IOException - */ - private void deserializeUserData(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - String[] headerName = new String[1]; - while (XmlUtil.gotoNextSectionOrEnd(in, headerName, outerTagDepth)) { - switch (headerName[0]) { - case XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER_LIST: - mDataSource.setProviders(deserializeProviderList(in, outerTagDepth + 1)); - break; - default: - Log.w(TAG, "Ignoring unknown Passpoint user store data " + headerName[0]); - break; - } - } - } - - /** - * Deserialize a list of Passpoint providers from the input stream. - * - * @param in The input stream to read data form - * @param outerTagDepth The tag depth of the current XML section - * @return List of {@link PasspointProvider} - * @throws XmlPullParserException - * @throws IOException - */ - private List<PasspointProvider> deserializeProviderList(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - List<PasspointProvider> providerList = new ArrayList<>(); - while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER, - outerTagDepth)) { - providerList.add(deserializeProvider(in, outerTagDepth + 1)); - } - return providerList; - } - - /** - * Deserialize a Passpoint provider from the input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link PasspointProvider} - * @throws XmlPullParserException - * @throws IOException - */ - private PasspointProvider deserializeProvider(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - long providerId = Long.MIN_VALUE; - int creatorUid = Integer.MIN_VALUE; - List<String> caCertificateAliases = null; - String caCertificateAlias = null; - String clientPrivateKeyAndCertificateAlias = null; - String remediationCaCertificateAlias = null; - String packageName = null; - boolean hasEverConnected = false; - boolean isFromSuggestion = false; - boolean shared = false; - boolean isTrusted = true; - PasspointConfiguration config = null; - while (XmlUtil.nextElementWithin(in, outerTagDepth)) { - if (in.getAttributeValue(null, "name") != null) { - // Value elements. - String[] name = new String[1]; - Object value = XmlUtil.readCurrentValue(in, name); - switch (name[0]) { - case XML_TAG_PROVIDER_ID: - providerId = (long) value; - break; - case XML_TAG_CREATOR_UID: - creatorUid = (int) value; - break; - case XML_TAG_PACKAGE_NAME: - packageName = (String) value; - break; - case XML_TAG_CA_CERTIFICATE_ALIASES: - caCertificateAliases = (List) value; - break; - case XML_TAG_CA_CERTIFICATE_ALIAS: - // Backwards compatibility: for the case that installs a profile that - // uses this alias. - caCertificateAlias = (String) value; - break; - case XML_TAG_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS: - clientPrivateKeyAndCertificateAlias = (String) value; - break; - case XML_TAG_REMEDIATION_CA_CERTIFICATE_ALIAS: - remediationCaCertificateAlias = (String) value; - break; - case XML_TAG_HAS_EVER_CONNECTED: - hasEverConnected = (boolean) value; - break; - case XML_TAG_IS_FROM_SUGGESTION: - isFromSuggestion = (boolean) value; - break; - case XML_TAG_IS_TRUSTED: - isTrusted = (boolean) value; - break; - default: - Log.w(TAG, "Ignoring unknown value name found " + name[0]); - break; - } - } else { - if (TextUtils.equals(in.getName(), - XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION)) { - config = PasspointXmlUtils.deserializePasspointConfiguration(in, - outerTagDepth + 1); - } else { - Log.w(TAG, "Ignoring unexpected section under Provider: " - + in.getName()); - } - } - } - if (providerId == Long.MIN_VALUE) { - throw new XmlPullParserException("Missing provider ID"); - } - - if (caCertificateAliases != null && caCertificateAlias != null) { - throw new XmlPullParserException( - "Should not have valid entry for caCertificateAliases and caCertificateAlias " - + "at the same time"); - } - - if (caCertificateAlias != null) { - caCertificateAliases = Arrays.asList(caCertificateAlias); - } - if (config == null) { - throw new XmlPullParserException("Missing Passpoint configuration"); - } - PasspointProvider provider = new PasspointProvider(config, mKeyStore, - mWifiCarrierInfoManager, - providerId, creatorUid, packageName, isFromSuggestion, caCertificateAliases, - clientPrivateKeyAndCertificateAlias, remediationCaCertificateAlias, - hasEverConnected, shared); - if (isFromSuggestion) { - provider.setTrusted(isTrusted); - } - return provider; - } -} - diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointEventHandler.java b/service/java/com/android/server/wifi/hotspot2/PasspointEventHandler.java deleted file mode 100644 index 3815c30b0..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointEventHandler.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import android.util.Log; -import android.util.Pair; - -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * This class handles passpoint specific interactions with the AP, such as ANQP - * elements requests, passpoint icon requests, and wireless network management - * event notifications. - */ -public class PasspointEventHandler { - private final WifiNative mSupplicantHook; - private final Callbacks mCallbacks; - - /** - * Interface to be implemented by the client to receive callbacks for passpoint - * related events. - */ - public interface Callbacks { - /** - * Invoked on received of ANQP response. |anqpElements| will be null on failure. - * @param bssid BSSID of the AP - * @param anqpElements ANQP elements to be queried - */ - void onANQPResponse(long bssid, - Map<Constants.ANQPElementType, ANQPElement> anqpElements); - - /** - * Invoked on received of icon response. |filename| and |data| will be null - * on failure. - * @param bssid BSSID of the AP - * @param filename Name of the icon file - * @data icon data bytes - */ - void onIconResponse(long bssid, String filename, byte[] data); - - /** - * Invoked on received of Hotspot 2.0 Wireless Network Management frame. - * @param data Wireless Network Management frame data - */ - void onWnmFrameReceived(WnmData data); - } - - public PasspointEventHandler(WifiNative supplicantHook, Callbacks callbacks) { - mSupplicantHook = supplicantHook; - mCallbacks = callbacks; - } - - /** - * Request the specified ANQP elements |elements| from the specified AP |bssid|. - * @param bssid BSSID of the AP - * @param elements ANQP elements to be queried - * @return true if request is sent successfully, false otherwise. - */ - public boolean requestANQP(long bssid, List<Constants.ANQPElementType> elements) { - Pair<Set<Integer>, Set<Integer>> querySets = buildAnqpIdSet(elements); - if (bssid == 0 || querySets == null) return false; - if (!mSupplicantHook.requestAnqp( - mSupplicantHook.getClientInterfaceName(), - Utils.macToString(bssid), querySets.first, querySets.second)) { - Log.d(Utils.hs2LogTag(getClass()), "ANQP failed on " + Utils.macToString(bssid)); - return false; - } - Log.d(Utils.hs2LogTag(getClass()), "ANQP initiated on " + Utils.macToString(bssid)); - return true; - } - - /** - * Request a passpoint icon file |filename| from the specified AP |bssid|. - * @param bssid BSSID of the AP - * @param fileName name of the icon file - * @return true if request is sent successfully, false otherwise - */ - public boolean requestIcon(long bssid, String fileName) { - if (bssid == 0 || fileName == null) return false; - return mSupplicantHook.requestIcon( - mSupplicantHook.getClientInterfaceName(), Utils.macToString(bssid), fileName); - } - - /** - * Invoked when ANQP query is completed. - * TODO(zqiu): currently ANQP completion notification is through WifiMonitor, - * this shouldn't be needed once we switch over to wificond for ANQP requests. - * @param anqpEvent ANQP result data retrieved. ANQP elements could be empty in the event to - * indicate any failures. - */ - public void notifyANQPDone(AnqpEvent anqpEvent) { - if (anqpEvent == null) return; - mCallbacks.onANQPResponse(anqpEvent.getBssid(), anqpEvent.getElements()); - } - - /** - * Invoked when icon query is completed. - * TODO(zqiu): currently icon completion notification is through WifiMonitor, - * this shouldn't be needed once we switch over to wificond for icon requests. - * @param iconEvent icon event data - */ - public void notifyIconDone(IconEvent iconEvent) { - if (iconEvent == null) return; - mCallbacks.onIconResponse( - iconEvent.getBSSID(), iconEvent.getFileName(), iconEvent.getData()); - } - - /** - * Invoked when a Wireless Network Management (WNM) frame is received. - * TODO(zqiu): currently WNM frame notification is through WifiMonitor, - * this shouldn't be needed once we switch over to wificond for WNM frame monitoring. - * @param data WNM frame data - */ - public void notifyWnmFrameReceived(WnmData data) { - mCallbacks.onWnmFrameReceived(data); - } - - /** - * Create the set of ANQP ID's to query. - * - * @param querySet elements to query - * @return Pair of <set of ANQP ID's, set of HS20 subtypes> - */ - private static Pair<Set<Integer>, Set<Integer>> buildAnqpIdSet( - List<Constants.ANQPElementType> querySet) { - Set<Integer> anqpIds = new HashSet<>(); - Set<Integer> hs20Subtypes = new HashSet<>(); - for (Constants.ANQPElementType elementType : querySet) { - Integer id = Constants.getANQPElementID(elementType); - if (id != null) { - anqpIds.add(id); - } else { - id = Constants.getHS20ElementID(elementType); - hs20Subtypes.add(id); - } - } - return Pair.create(anqpIds, hs20Subtypes); - } - -} diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java deleted file mode 100644 index d398759ab..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java +++ /dev/null @@ -1,1337 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE; -import static android.net.wifi.WifiConfiguration.MeteredOverride; -import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS; - -import static java.security.cert.PKIXReason.NO_TRUST_ANCHOR; - -import android.annotation.NonNull; -import android.app.AppOpsManager; -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.Handler; -import android.os.Looper; -import android.os.Process; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.MacAddressUtil; -import com.android.server.wifi.NetworkUpdateResult; -import com.android.server.wifi.WifiCarrierInfoManager; -import com.android.server.wifi.WifiConfigManager; -import com.android.server.wifi.WifiConfigStore; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiKeyStore; -import com.android.server.wifi.WifiMetrics; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; -import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement; -import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; -import com.android.server.wifi.util.InformationElementUtil; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import java.io.IOException; -import java.io.PrintWriter; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; -import java.security.cert.CertPathValidatorException; -import java.security.cert.CertificateFactory; -import java.security.cert.PKIXParameters; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * This class provides the APIs to manage Passpoint provider configurations. - * It deals with the following: - * - Maintaining a list of configured Passpoint providers for provider matching. - * - Persisting the providers configurations to store when required. - * - matching Passpoint providers based on the scan results - * - Supporting WifiManager Public API calls: - * > addOrUpdatePasspointConfiguration() - * > removePasspointConfiguration() - * > getPasspointConfigurations() - * - * The provider matching requires obtaining additional information from the AP (ANQP elements). - * The ANQP elements will be cached using {@link AnqpCache} to avoid unnecessary requests. - * - * NOTE: These API's are not thread safe and should only be used from the main Wifi thread. - */ -public class PasspointManager { - private static final String TAG = "PasspointManager"; - - /** - * Handle for the current {@link PasspointManager} instance. This is needed to avoid - * circular dependency with the WifiConfigManger, it will be used for adding the - * legacy Passpoint configurations. - * - * This can be eliminated once we can remove the dependency for WifiConfigManager (for - * triggering config store write) from this class. - */ - private static PasspointManager sPasspointManager; - - private final PasspointEventHandler mPasspointEventHandler; - private final WifiInjector mWifiInjector; - private final Handler mHandler; - private final WifiKeyStore mKeyStore; - private final PasspointObjectFactory mObjectFactory; - - private final Map<String, PasspointProvider> mProviders; - private final AnqpCache mAnqpCache; - private final ANQPRequestManager mAnqpRequestManager; - private final WifiConfigManager mWifiConfigManager; - private final WifiMetrics mWifiMetrics; - private final PasspointProvisioner mPasspointProvisioner; - private final AppOpsManager mAppOps; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - private final MacAddressUtil mMacAddressUtil; - private final WifiPermissionsUtil mWifiPermissionsUtil; - - /** - * Map of package name of an app to the app ops changed listener for the app. - */ - private final Map<String, AppOpsChangedListener> mAppOpsChangedListenerPerApp = new HashMap<>(); - - // Counter used for assigning unique identifier to each provider. - private long mProviderIndex; - private boolean mVerboseLoggingEnabled = false; - - private class CallbackHandler implements PasspointEventHandler.Callbacks { - private final Context mContext; - CallbackHandler(Context context) { - mContext = context; - } - - @Override - public void onANQPResponse(long bssid, - Map<Constants.ANQPElementType, ANQPElement> anqpElements) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "ANQP response received from BSSID " - + Utils.macToString(bssid)); - } - // Notify request manager for the completion of a request. - ANQPNetworkKey anqpKey = - mAnqpRequestManager.onRequestCompleted(bssid, anqpElements != null); - if (anqpElements == null || anqpKey == null) { - // Query failed or the request wasn't originated from us (not tracked by the - // request manager). Nothing to be done. - return; - } - - // Add new entry to the cache. - mAnqpCache.addEntry(anqpKey, anqpElements); - } - - @Override - public void onIconResponse(long bssid, String fileName, byte[] data) { - // Empty - } - - @Override - public void onWnmFrameReceived(WnmData event) { - // Empty - } - } - - /** - * Data provider for the Passpoint configuration store data - * {@link PasspointConfigUserStoreData}. - */ - private class UserDataSourceHandler implements PasspointConfigUserStoreData.DataSource { - @Override - public List<PasspointProvider> getProviders() { - List<PasspointProvider> providers = new ArrayList<>(); - for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { - providers.add(entry.getValue()); - } - return providers; - } - - @Override - public void setProviders(List<PasspointProvider> providers) { - mProviders.clear(); - for (PasspointProvider provider : providers) { - provider.enableVerboseLogging(mVerboseLoggingEnabled ? 1 : 0); - mProviders.put(provider.getConfig().getUniqueId(), provider); - if (provider.getPackageName() != null) { - startTrackingAppOpsChange(provider.getPackageName(), - provider.getCreatorUid()); - } - } - } - } - - /** - * Data provider for the Passpoint configuration store data - * {@link PasspointConfigSharedStoreData}. - */ - private class SharedDataSourceHandler implements PasspointConfigSharedStoreData.DataSource { - @Override - public long getProviderIndex() { - return mProviderIndex; - } - - @Override - public void setProviderIndex(long providerIndex) { - mProviderIndex = providerIndex; - } - } - - /** - * Listener for app-ops changes for apps to remove the corresponding Passpoint profiles. - */ - private final class AppOpsChangedListener implements AppOpsManager.OnOpChangedListener { - private final String mPackageName; - private final int mUid; - - AppOpsChangedListener(@NonNull String packageName, int uid) { - mPackageName = packageName; - mUid = uid; - } - - @Override - public void onOpChanged(String op, String packageName) { - mHandler.post(() -> { - if (!mPackageName.equals(packageName)) return; - if (!OPSTR_CHANGE_WIFI_STATE.equals(op)) return; - - // Ensures the uid to package mapping is still correct. - try { - mAppOps.checkPackage(mUid, mPackageName); - } catch (SecurityException e) { - Log.wtf(TAG, "Invalid uid/package" + packageName); - return; - } - if (mAppOps.unsafeCheckOpNoThrow(OPSTR_CHANGE_WIFI_STATE, mUid, mPackageName) - == AppOpsManager.MODE_IGNORED) { - Log.i(TAG, "User disallowed change wifi state for " + packageName); - - // Removes the profiles installed by the app from database. - removePasspointProviderWithPackage(mPackageName); - } - }); - } - } - - /** - * Remove all Passpoint profiles installed by the app that has been disabled or uninstalled. - * - * @param packageName Package name of the app to remove the corresponding Passpoint profiles. - */ - public void removePasspointProviderWithPackage(@NonNull String packageName) { - stopTrackingAppOpsChange(packageName); - for (Map.Entry<String, PasspointProvider> entry : getPasspointProviderWithPackage( - packageName).entrySet()) { - String uniqueId = entry.getValue().getConfig().getUniqueId(); - removeProvider(Process.WIFI_UID /* ignored */, true, uniqueId, null); - disconnectIfPasspointNetwork(uniqueId); - } - } - - private Map<String, PasspointProvider> getPasspointProviderWithPackage( - @NonNull String packageName) { - return mProviders.entrySet().stream().filter( - entry -> TextUtils.equals(packageName, - entry.getValue().getPackageName())).collect( - Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue())); - } - - private void startTrackingAppOpsChange(@NonNull String packageName, int uid) { - // The package is already registered. - if (mAppOpsChangedListenerPerApp.containsKey(packageName)) return; - AppOpsChangedListener appOpsChangedListener = new AppOpsChangedListener(packageName, uid); - mAppOps.startWatchingMode(OPSTR_CHANGE_WIFI_STATE, packageName, appOpsChangedListener); - mAppOpsChangedListenerPerApp.put(packageName, appOpsChangedListener); - } - - private void stopTrackingAppOpsChange(@NonNull String packageName) { - AppOpsChangedListener appOpsChangedListener = mAppOpsChangedListenerPerApp.remove( - packageName); - if (appOpsChangedListener == null) { - Log.i(TAG, "No app ops listener found for " + packageName); - return; - } - mAppOps.stopWatchingMode(appOpsChangedListener); - } - - private void disconnectIfPasspointNetwork(String uniqueId) { - WifiConfiguration currentConfiguration = - mWifiInjector.getClientModeImpl().getCurrentWifiConfiguration(); - if (currentConfiguration == null) return; - if (currentConfiguration.isPasspoint() && TextUtils.equals(currentConfiguration.getKey(), - uniqueId)) { - Log.i(TAG, "Disconnect current Passpoint network for FQDN: " - + currentConfiguration.FQDN + " and ID: " + uniqueId - + " because the profile was removed"); - mWifiInjector.getClientModeImpl().disconnectCommand(); - } - } - - public PasspointManager(Context context, WifiInjector wifiInjector, Handler handler, - WifiNative wifiNative, WifiKeyStore keyStore, Clock clock, - PasspointObjectFactory objectFactory, WifiConfigManager wifiConfigManager, - WifiConfigStore wifiConfigStore, - WifiMetrics wifiMetrics, - WifiCarrierInfoManager wifiCarrierInfoManager, - MacAddressUtil macAddressUtil, - WifiPermissionsUtil wifiPermissionsUtil) { - mPasspointEventHandler = objectFactory.makePasspointEventHandler(wifiNative, - new CallbackHandler(context)); - mWifiInjector = wifiInjector; - mHandler = handler; - mKeyStore = keyStore; - mObjectFactory = objectFactory; - mProviders = new HashMap<>(); - mAnqpCache = objectFactory.makeAnqpCache(clock); - mAnqpRequestManager = objectFactory.makeANQPRequestManager(mPasspointEventHandler, clock); - mWifiConfigManager = wifiConfigManager; - mWifiMetrics = wifiMetrics; - mProviderIndex = 0; - mWifiCarrierInfoManager = wifiCarrierInfoManager; - wifiConfigStore.registerStoreData(objectFactory.makePasspointConfigUserStoreData( - mKeyStore, mWifiCarrierInfoManager, new UserDataSourceHandler())); - wifiConfigStore.registerStoreData(objectFactory.makePasspointConfigSharedStoreData( - new SharedDataSourceHandler())); - mPasspointProvisioner = objectFactory.makePasspointProvisioner(context, wifiNative, - this, wifiMetrics); - mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - sPasspointManager = this; - mMacAddressUtil = macAddressUtil; - mWifiPermissionsUtil = wifiPermissionsUtil; - } - - /** - * Initializes the provisioning flow with a looper. - * This looper should be tied to a background worker thread since PasspointProvisioner has a - * heavy workload. - */ - public void initializeProvisioner(Looper looper) { - mPasspointProvisioner.init(looper); - } - - /** - * Enable verbose logging - * @param verbose more than 0 enables verbose logging - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = (verbose > 0) ? true : false; - mPasspointProvisioner.enableVerboseLogging(verbose); - for (PasspointProvider provider : mProviders.values()) { - provider.enableVerboseLogging(verbose); - } - } - - private void updateWifiConfigInWcmIfPresent( - WifiConfiguration newConfig, int uid, String packageName, boolean isFromSuggestion) { - WifiConfiguration configInWcm = - mWifiConfigManager.getConfiguredNetwork(newConfig.getKey()); - if (configInWcm == null) return; - // suggestion != saved - if (isFromSuggestion != configInWcm.fromWifiNetworkSuggestion) return; - // is suggestion from same app. - if (isFromSuggestion - && (configInWcm.creatorUid != uid - || !TextUtils.equals(configInWcm.creatorName, packageName))) { - return; - } - NetworkUpdateResult result = mWifiConfigManager.addOrUpdateNetwork( - newConfig, uid, packageName); - if (!result.isSuccess()) { - Log.e(TAG, "Failed to update config in WifiConfigManager"); - } else { - mWifiConfigManager.allowAutojoin(result.getNetworkId(), newConfig.allowAutojoin); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Updated config in WifiConfigManager"); - } - } - } - - /** - * Add or update a Passpoint provider with the given configuration. - * - * Each provider is uniquely identified by its unique identifier, see - * {@link PasspointConfiguration#getUniqueId()}. - * In the case when there is an existing configuration with the same unique identifier, - * a provider with the new configuration will replace the existing provider. - * - * @param config Configuration of the Passpoint provider to be added - * @param uid Uid of the app adding/Updating {@code config} - * @param packageName Package name of the app adding/Updating {@code config} - * @param isFromSuggestion Whether this {@code config} is from suggestion API - * @param isTrusted Whether this {@code config} an trusted network, default should be true. - * Only able set to false when {@code isFromSuggestion} is true, otherwise - * adding {@code config} will be false. - * @return true if provider is added, false otherwise - */ - public boolean addOrUpdateProvider(PasspointConfiguration config, int uid, - String packageName, boolean isFromSuggestion, boolean isTrusted) { - mWifiMetrics.incrementNumPasspointProviderInstallation(); - if (config == null) { - Log.e(TAG, "Configuration not provided"); - return false; - } - if (!config.validate()) { - Log.e(TAG, "Invalid configuration"); - return false; - } - if (!(isFromSuggestion || isTrusted)) { - Log.e(TAG, "Set isTrusted to false on a non suggestion passpoint is not allowed"); - return false; - } - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { - Log.e(TAG, "UID " + uid + " not visible to the current user"); - return false; - } - - mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config); - // Create a provider and install the necessary certificates and keys. - PasspointProvider newProvider = mObjectFactory.makePasspointProvider(config, mKeyStore, - mWifiCarrierInfoManager, mProviderIndex++, uid, packageName, isFromSuggestion); - newProvider.setTrusted(isTrusted); - - boolean metricsNoRootCa = false; - boolean metricsSelfSignedRootCa = false; - boolean metricsSubscriptionExpiration = false; - - if (config.getCredential().getUserCredential() != null - || config.getCredential().getCertCredential() != null) { - X509Certificate[] x509Certificates = config.getCredential().getCaCertificates(); - if (x509Certificates == null) { - metricsNoRootCa = true; - } else { - try { - for (X509Certificate certificate : x509Certificates) { - verifyCaCert(certificate); - } - } catch (CertPathValidatorException e) { - // A self signed Root CA will fail path validation checks with NO_TRUST_ANCHOR - if (e.getReason() == NO_TRUST_ANCHOR) { - metricsSelfSignedRootCa = true; - } - } catch (Exception e) { - // Other exceptions, fall through, will be handled below - } - } - } - if (config.getSubscriptionExpirationTimeMillis() != Long.MIN_VALUE) { - metricsSubscriptionExpiration = true; - } - - if (!newProvider.installCertsAndKeys()) { - Log.e(TAG, "Failed to install certificates and keys to keystore"); - return false; - } - - // Remove existing provider with the same unique ID. - if (mProviders.containsKey(config.getUniqueId())) { - PasspointProvider old = mProviders.get(config.getUniqueId()); - // If new profile is from suggestion and from a different App, ignore new profile, - // return false. - // If from same app, update it. - if (isFromSuggestion && !old.getPackageName().equals(packageName)) { - newProvider.uninstallCertsAndKeys(); - return false; - } - Log.d(TAG, "Replacing configuration for FQDN: " + config.getHomeSp().getFqdn() - + " and unique ID: " + config.getUniqueId()); - old.uninstallCertsAndKeys(); - mProviders.remove(config.getUniqueId()); - // New profile changes the credential, remove the related WifiConfig. - if (!old.equals(newProvider)) { - mWifiConfigManager.removePasspointConfiguredNetwork( - newProvider.getWifiConfig().getKey()); - } else { - // If there is a config cached in WifiConfigManager, update it with new info. - updateWifiConfigInWcmIfPresent( - newProvider.getWifiConfig(), uid, packageName, isFromSuggestion); - } - } - newProvider.enableVerboseLogging(mVerboseLoggingEnabled ? 1 : 0); - mProviders.put(config.getUniqueId(), newProvider); - mWifiConfigManager.saveToStore(true /* forceWrite */); - if (!isFromSuggestion && newProvider.getPackageName() != null) { - startTrackingAppOpsChange(newProvider.getPackageName(), uid); - } - Log.d(TAG, "Added/updated Passpoint configuration for FQDN: " - + config.getHomeSp().getFqdn() + " with unique ID: " + config.getUniqueId() - + " by UID: " + uid); - if (metricsNoRootCa) { - mWifiMetrics.incrementNumPasspointProviderWithNoRootCa(); - } - if (metricsSelfSignedRootCa) { - mWifiMetrics.incrementNumPasspointProviderWithSelfSignedRootCa(); - } - if (metricsSubscriptionExpiration) { - mWifiMetrics.incrementNumPasspointProviderWithSubscriptionExpiration(); - } - mWifiMetrics.incrementNumPasspointProviderInstallSuccess(); - return true; - } - - private boolean removeProviderInternal(PasspointProvider provider, int callingUid, - boolean privileged) { - if (!privileged && callingUid != provider.getCreatorUid()) { - Log.e(TAG, "UID " + callingUid + " cannot remove profile created by " - + provider.getCreatorUid()); - return false; - } - if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(callingUid)) { - Log.e(TAG, "UID " + callingUid + " not visible to the current user"); - return false; - } - provider.uninstallCertsAndKeys(); - String packageName = provider.getPackageName(); - // Remove any configs corresponding to the profile in WifiConfigManager. - mWifiConfigManager.removePasspointConfiguredNetwork( - provider.getWifiConfig().getKey()); - String uniqueId = provider.getConfig().getUniqueId(); - mProviders.remove(uniqueId); - mWifiConfigManager.saveToStore(true /* forceWrite */); - - // Stop monitoring the package if there is no Passpoint profile installed by the package - if (mAppOpsChangedListenerPerApp.containsKey(packageName) - && getPasspointProviderWithPackage(packageName).size() == 0) { - stopTrackingAppOpsChange(packageName); - } - Log.d(TAG, "Removed Passpoint configuration: " + uniqueId); - mWifiMetrics.incrementNumPasspointProviderUninstallSuccess(); - return true; - } - - /** - * Remove a Passpoint provider identified by the given its unique identifier. - * - * @param callingUid Calling UID. - * @param privileged Whether the caller is a privileged entity - * @param uniqueId The ID of the provider to remove. Not required if FQDN is specified. - * @param fqdn The FQDN of the provider to remove. Not required if unique ID is specified. - * @return true if a provider is removed, false otherwise - */ - public boolean removeProvider(int callingUid, boolean privileged, String uniqueId, - String fqdn) { - if (uniqueId == null && fqdn == null) { - mWifiMetrics.incrementNumPasspointProviderUninstallation(); - Log.e(TAG, "Cannot remove provider, both FQDN and unique ID are null"); - return false; - } - - if (uniqueId != null) { - // Unique identifier provided - mWifiMetrics.incrementNumPasspointProviderUninstallation(); - PasspointProvider provider = mProviders.get(uniqueId); - if (provider == null) { - Log.e(TAG, "Config doesn't exist"); - return false; - } - return removeProviderInternal(provider, callingUid, privileged); - } - - // FQDN provided, loop through all profiles with matching FQDN - ArrayList<PasspointProvider> passpointProviders = new ArrayList<>(mProviders.values()); - int removedProviders = 0; - int numOfUninstallations = 0; - for (PasspointProvider provider : passpointProviders) { - if (!TextUtils.equals(provider.getConfig().getHomeSp().getFqdn(), fqdn)) { - continue; - } - mWifiMetrics.incrementNumPasspointProviderUninstallation(); - numOfUninstallations++; - if (removeProviderInternal(provider, callingUid, privileged)) { - removedProviders++; - } - } - - if (numOfUninstallations == 0) { - // Update uninstallation requests metrics here to cover the corner case of trying to - // uninstall a non-existent provider. - mWifiMetrics.incrementNumPasspointProviderUninstallation(); - } - - return removedProviders > 0; - } - - /** - * Enable or disable the auto-join configuration. Auto-join controls whether or not the - * passpoint configuration is used for auto connection (network selection). Note that even - * when auto-join is disabled the configuration can still be used for manual connection. - * - * @param uniqueId The unique identifier of the configuration. Not required if FQDN is specified - * @param fqdn The FQDN of the configuration. Not required if uniqueId is specified. - * @param enableAutojoin true to enable auto-join, false to disable. - * @return true on success, false otherwise (e.g. if no such provider exists). - */ - public boolean enableAutojoin(String uniqueId, String fqdn, boolean enableAutojoin) { - if (uniqueId == null && fqdn == null) { - return false; - } - if (uniqueId != null) { - // Unique identifier provided - PasspointProvider provider = mProviders.get(uniqueId); - if (provider == null) { - Log.e(TAG, "Config doesn't exist"); - return false; - } - if (provider.setAutojoinEnabled(enableAutojoin)) { - mWifiMetrics.logUserActionEvent(enableAutojoin - ? UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON - : UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF, - provider.isFromSuggestion(), true); - } - mWifiConfigManager.saveToStore(true); - return true; - } - - ArrayList<PasspointProvider> passpointProviders = new ArrayList<>(mProviders.values()); - boolean found = false; - - // FQDN provided, loop through all profiles with matching FQDN - for (PasspointProvider provider : passpointProviders) { - if (TextUtils.equals(provider.getConfig().getHomeSp().getFqdn(), fqdn)) { - if (provider.setAutojoinEnabled(enableAutojoin)) { - mWifiMetrics.logUserActionEvent(enableAutojoin - ? UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON - : UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF, - provider.isFromSuggestion(), true); - } - found = true; - } - } - if (found) { - mWifiConfigManager.saveToStore(true); - } - return found; - } - - /** - * Enable or disable MAC randomization for this passpoint profile. - * @param fqdn The FQDN of the configuration - * @param enable true to enable MAC randomization, false to disable - * @return true on success, false otherwise (e.g. if no such provider exists). - */ - public boolean enableMacRandomization(@NonNull String fqdn, boolean enable) { - ArrayList<PasspointProvider> passpointProviders = new ArrayList<>(mProviders.values()); - boolean found = false; - - // Loop through all profiles with matching FQDN - for (PasspointProvider provider : passpointProviders) { - if (TextUtils.equals(provider.getConfig().getHomeSp().getFqdn(), fqdn)) { - boolean settingChanged = provider.setMacRandomizationEnabled(enable); - if (settingChanged) { - mWifiMetrics.logUserActionEvent(enable - ? UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_ON - : UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF, - provider.isFromSuggestion(), true); - mWifiConfigManager.removePasspointConfiguredNetwork( - provider.getWifiConfig().getKey()); - } - found = true; - } - } - if (found) { - mWifiConfigManager.saveToStore(true); - } - return found; - } - - /** - * Set the metered override value for this passpoint profile - * @param fqdn The FQDN of the configuration - * @param meteredOverride One of the values in {@link MeteredOverride} - * @return true on success, false otherwise (e.g. if no such provider exists). - */ - public boolean setMeteredOverride(@NonNull String fqdn, @MeteredOverride int meteredOverride) { - ArrayList<PasspointProvider> passpointProviders = new ArrayList<>(mProviders.values()); - boolean found = false; - - // Loop through all profiles with matching FQDN - for (PasspointProvider provider : passpointProviders) { - if (TextUtils.equals(provider.getConfig().getHomeSp().getFqdn(), fqdn)) { - if (provider.setMeteredOverride(meteredOverride)) { - mWifiMetrics.logUserActionEvent( - WifiMetrics.convertMeteredOverrideEnumToUserActionEventType( - meteredOverride), - provider.isFromSuggestion(), true); - } - found = true; - } - } - if (found) { - mWifiConfigManager.saveToStore(true); - } - return found; - } - - /** - * Return the installed Passpoint provider configurations. - * An empty list will be returned when no provider is installed. - * - * @param callingUid Calling UID. - * @param privileged Whether the caller is a privileged entity - * @return A list of {@link PasspointConfiguration} - */ - public List<PasspointConfiguration> getProviderConfigs(int callingUid, - boolean privileged) { - List<PasspointConfiguration> configs = new ArrayList<>(); - for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { - PasspointProvider provider = entry.getValue(); - if (privileged || callingUid == provider.getCreatorUid()) { - if (provider.isFromSuggestion()) { - continue; - } - configs.add(provider.getConfig()); - } - } - return configs; - } - - /** - * Find all providers that can provide service through the given AP, which means the - * providers contained credential to authenticate with the given AP. - * - * If there is any home provider available, will return a list of matched home providers. - * Otherwise will return a list of matched roaming providers. - * - * A empty list will be returned if no matching is found. - * - * @param scanResult The scan result associated with the AP - * @return a list of pairs of {@link PasspointProvider} and match status. - */ - public @NonNull List<Pair<PasspointProvider, PasspointMatch>> matchProvider( - ScanResult scanResult) { - return matchProvider(scanResult, true); - } - - /** - * Find all providers that can provide service through the given AP, which means the - * providers contained credential to authenticate with the given AP. - * - * If there is any home provider available, will return a list of matched home providers. - * Otherwise will return a list of matched roaming providers. - * - * A empty list will be returned if no matching is found. - * - * @param scanResult The scan result associated with the AP - * @param anqpRequestAllowed Indicates if to allow ANQP request if the provider's entry is empty - * @return a list of pairs of {@link PasspointProvider} and match status. - */ - public @NonNull List<Pair<PasspointProvider, PasspointMatch>> matchProvider( - ScanResult scanResult, boolean anqpRequestAllowed) { - List<Pair<PasspointProvider, PasspointMatch>> allMatches = getAllMatchedProviders( - scanResult, anqpRequestAllowed); - if (allMatches.isEmpty()) { - return allMatches; - } - List<Pair<PasspointProvider, PasspointMatch>> homeProviders = new ArrayList<>(); - List<Pair<PasspointProvider, PasspointMatch>> roamingProviders = new ArrayList<>(); - for (Pair<PasspointProvider, PasspointMatch> match : allMatches) { - if (isExpired(match.first.getConfig())) { - continue; - } - if (match.second == PasspointMatch.HomeProvider) { - homeProviders.add(match); - } else { - roamingProviders.add(match); - } - } - - if (!homeProviders.isEmpty()) { - Log.d(TAG, String.format("Matched %s to %s providers as %s", scanResult.SSID, - homeProviders.size(), "Home Provider")); - return homeProviders; - } - - if (!roamingProviders.isEmpty()) { - Log.d(TAG, String.format("Matched %s to %s providers as %s", scanResult.SSID, - roamingProviders.size(), "Roaming Provider")); - return roamingProviders; - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "No service provider found for " + scanResult.SSID); - } - return new ArrayList<>(); - } - - /** - * Return a list of all providers that can provide service through the given AP. - * - * @param scanResult The scan result associated with the AP - * @return a list of pairs of {@link PasspointProvider} and match status. - */ - public @NonNull List<Pair<PasspointProvider, PasspointMatch>> getAllMatchedProviders( - ScanResult scanResult) { - return getAllMatchedProviders(scanResult, true); - } - - /** - * Return a list of all providers that can provide service through the given AP. - * - * @param scanResult The scan result associated with the AP - * @param anqpRequestAllowed Indicates if to allow ANQP request if the provider's entry is empty - * @return a list of pairs of {@link PasspointProvider} and match status. - */ - private @NonNull List<Pair<PasspointProvider, PasspointMatch>> getAllMatchedProviders( - ScanResult scanResult, boolean anqpRequestAllowed) { - List<Pair<PasspointProvider, PasspointMatch>> allMatches = new ArrayList<>(); - - // Retrieve the relevant information elements, mainly Roaming Consortium IE and Hotspot 2.0 - // Vendor Specific IE. - InformationElementUtil.RoamingConsortium roamingConsortium = - InformationElementUtil.getRoamingConsortiumIE(scanResult.informationElements); - InformationElementUtil.Vsa vsa = InformationElementUtil.getHS2VendorSpecificIE( - scanResult.informationElements); - - // Lookup ANQP data in the cache. - long bssid; - try { - bssid = Utils.parseMac(scanResult.BSSID); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Invalid BSSID provided in the scan result: " + scanResult.BSSID); - return allMatches; - } - ANQPNetworkKey anqpKey = ANQPNetworkKey.buildKey(scanResult.SSID, bssid, scanResult.hessid, - vsa.anqpDomainID); - ANQPData anqpEntry = mAnqpCache.getEntry(anqpKey); - if (anqpEntry == null) { - if (anqpRequestAllowed) { - mAnqpRequestManager.requestANQPElements(bssid, anqpKey, - roamingConsortium.anqpOICount > 0, vsa.hsRelease); - } - Log.d(TAG, "ANQP entry not found for: " + anqpKey); - return allMatches; - } - boolean anyProviderUpdated = false; - for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { - PasspointProvider provider = entry.getValue(); - if (provider.tryUpdateCarrierId()) { - anyProviderUpdated = true; - } - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Matching provider " + provider.getConfig().getHomeSp().getFqdn() - + " with " - + anqpEntry.getElements().get(Constants.ANQPElementType.ANQPDomName)); - } - PasspointMatch matchStatus = provider.match(anqpEntry.getElements(), - roamingConsortium); - if (matchStatus == PasspointMatch.HomeProvider - || matchStatus == PasspointMatch.RoamingProvider) { - allMatches.add(Pair.create(provider, matchStatus)); - } - } - if (anyProviderUpdated) { - mWifiConfigManager.saveToStore(true); - } - if (allMatches.size() != 0) { - for (Pair<PasspointProvider, PasspointMatch> match : allMatches) { - Log.d(TAG, String.format("Matched %s to %s as %s", scanResult.SSID, - match.first.getConfig().getHomeSp().getFqdn(), - match.second == PasspointMatch.HomeProvider ? "Home Provider" - : "Roaming Provider")); - } - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "No service providers found for " + scanResult.SSID); - } - } - return allMatches; - } - - /** - * Add a legacy Passpoint configuration represented by a {@link WifiConfiguration} to the - * current {@link PasspointManager}. - * - * This will not trigger a config store write, since this will be invoked as part of the - * configuration migration, the caller will be responsible for triggering store write - * after the migration is completed. - * - * @param config {@link WifiConfiguration} representation of the Passpoint configuration - * @return true on success - */ - public static boolean addLegacyPasspointConfig(WifiConfiguration config) { - if (sPasspointManager == null) { - Log.e(TAG, "PasspointManager have not been initialized yet"); - return false; - } - Log.d(TAG, "Installing legacy Passpoint configuration: " + config.FQDN); - return sPasspointManager.addWifiConfig(config); - } - - /** - * Sweep the ANQP cache to remove expired entries. - */ - public void sweepCache() { - mAnqpCache.sweep(); - } - - /** - * Notify the completion of an ANQP request. - * TODO(zqiu): currently the notification is done through WifiMonitor, - * will no longer be the case once we switch over to use wificond. - */ - public void notifyANQPDone(AnqpEvent anqpEvent) { - mPasspointEventHandler.notifyANQPDone(anqpEvent); - } - - /** - * Notify the completion of an icon request. - * TODO(zqiu): currently the notification is done through WifiMonitor, - * will no longer be the case once we switch over to use wificond. - */ - public void notifyIconDone(IconEvent iconEvent) { - mPasspointEventHandler.notifyIconDone(iconEvent); - } - - /** - * Notify the reception of a Wireless Network Management (WNM) frame. - * TODO(zqiu): currently the notification is done through WifiMonitor, - * will no longer be the case once we switch over to use wificond. - */ - public void receivedWnmFrame(WnmData data) { - mPasspointEventHandler.notifyWnmFrameReceived(data); - } - - /** - * Request the specified icon file |fileName| from the specified AP |bssid|. - * @return true if the request is sent successfully, false otherwise - */ - public boolean queryPasspointIcon(long bssid, String fileName) { - return mPasspointEventHandler.requestIcon(bssid, fileName); - } - - /** - * Lookup the ANQP elements associated with the given AP from the cache. An empty map - * will be returned if no match found in the cache. - * - * @param scanResult The scan result associated with the AP - * @return Map of ANQP elements - */ - public Map<Constants.ANQPElementType, ANQPElement> getANQPElements(ScanResult scanResult) { - // Retrieve the Hotspot 2.0 Vendor Specific IE. - InformationElementUtil.Vsa vsa = - InformationElementUtil.getHS2VendorSpecificIE(scanResult.informationElements); - - // Lookup ANQP data in the cache. - long bssid; - try { - bssid = Utils.parseMac(scanResult.BSSID); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Invalid BSSID provided in the scan result: " + scanResult.BSSID); - return new HashMap<>(); - } - ANQPData anqpEntry = mAnqpCache.getEntry(ANQPNetworkKey.buildKey( - scanResult.SSID, bssid, scanResult.hessid, vsa.anqpDomainID)); - if (anqpEntry != null) { - return anqpEntry.getElements(); - } - return new HashMap<>(); - } - - /** - * Return a map of all matching configurations keys with corresponding scanResults (or an empty - * map if none). - * - * @param scanResults The list of scan results - * @return Map that consists of identifies and corresponding scanResults per network type - * ({@link WifiManager#PASSPOINT_HOME_NETWORK}, {@link WifiManager#PASSPOINT_ROAMING_NETWORK}). - */ - public Map<String, Map<Integer, List<ScanResult>>> - getAllMatchingPasspointProfilesForScanResults(List<ScanResult> scanResults) { - if (scanResults == null) { - Log.e(TAG, "Attempt to get matching config for a null ScanResults"); - return new HashMap<>(); - } - Map<String, Map<Integer, List<ScanResult>>> configs = new HashMap<>(); - - for (ScanResult scanResult : scanResults) { - if (!scanResult.isPasspointNetwork()) continue; - List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = getAllMatchedProviders( - scanResult); - for (Pair<PasspointProvider, PasspointMatch> matchedProvider : matchedProviders) { - WifiConfiguration config = matchedProvider.first.getWifiConfig(); - int type = WifiManager.PASSPOINT_HOME_NETWORK; - if (!config.isHomeProviderNetwork) { - type = WifiManager.PASSPOINT_ROAMING_NETWORK; - } - Map<Integer, List<ScanResult>> scanResultsPerNetworkType = - configs.get(config.getKey()); - if (scanResultsPerNetworkType == null) { - scanResultsPerNetworkType = new HashMap<>(); - configs.put(config.getKey(), scanResultsPerNetworkType); - } - List<ScanResult> matchingScanResults = scanResultsPerNetworkType.get(type); - if (matchingScanResults == null) { - matchingScanResults = new ArrayList<>(); - scanResultsPerNetworkType.put(type, matchingScanResults); - } - matchingScanResults.add(scanResult); - } - } - - return configs; - } - - /** - * Returns the list of Hotspot 2.0 OSU (Online Sign-Up) providers associated with the given list - * of ScanResult. - * - * An empty map will be returned when an invalid scanResults are provided or no match is found. - * - * @param scanResults a list of ScanResult that has Passpoint APs. - * @return Map that consists of {@link OsuProvider} and a matching list of {@link ScanResult} - */ - public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( - List<ScanResult> scanResults) { - if (scanResults == null) { - Log.e(TAG, "Attempt to retrieve OSU providers for a null ScanResult"); - return new HashMap(); - } - - Map<OsuProvider, List<ScanResult>> osuProviders = new HashMap<>(); - for (ScanResult scanResult : scanResults) { - if (!scanResult.isPasspointNetwork()) continue; - - // Lookup OSU Providers ANQP element. - Map<Constants.ANQPElementType, ANQPElement> anqpElements = getANQPElements(scanResult); - if (!anqpElements.containsKey(Constants.ANQPElementType.HSOSUProviders)) { - continue; - } - HSOsuProvidersElement element = - (HSOsuProvidersElement) anqpElements.get( - Constants.ANQPElementType.HSOSUProviders); - for (OsuProviderInfo info : element.getProviders()) { - // Set null for OSU-SSID in the class because OSU-SSID is a factor for hotspot - // operator rather than service provider, which means it can be different for - // each hotspot operators. - OsuProvider provider = new OsuProvider((WifiSsid) null, info.getFriendlyNames(), - info.getServiceDescription(), info.getServerUri(), - info.getNetworkAccessIdentifier(), info.getMethodList()); - List<ScanResult> matchingScanResults = osuProviders.get(provider); - if (matchingScanResults == null) { - matchingScanResults = new ArrayList<>(); - osuProviders.put(provider, matchingScanResults); - } - matchingScanResults.add(scanResult); - } - } - return osuProviders; - } - - /** - * Returns the matching Passpoint configurations for given OSU(Online Sign-Up) providers - * - * An empty map will be returned when an invalid {@code osuProviders} are provided or no match - * is found. - * - * @param osuProviders a list of {@link OsuProvider} - * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}. - */ - public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( - List<OsuProvider> osuProviders) { - Map<OsuProvider, PasspointConfiguration> matchingPasspointConfigs = new HashMap<>(); - - for (OsuProvider osuProvider : osuProviders) { - Map<String, String> friendlyNamesForOsuProvider = osuProvider.getFriendlyNameList(); - if (friendlyNamesForOsuProvider == null) continue; - for (PasspointProvider provider : mProviders.values()) { - PasspointConfiguration passpointConfiguration = provider.getConfig(); - Map<String, String> serviceFriendlyNamesForPpsMo = - passpointConfiguration.getServiceFriendlyNames(); - if (serviceFriendlyNamesForPpsMo == null) continue; - - for (Map.Entry<String, String> entry : serviceFriendlyNamesForPpsMo.entrySet()) { - String lang = entry.getKey(); - String friendlyName = entry.getValue(); - if (friendlyName == null) continue; - String osuFriendlyName = friendlyNamesForOsuProvider.get(lang); - if (osuFriendlyName == null) continue; - if (friendlyName.equals(osuFriendlyName)) { - matchingPasspointConfigs.put(osuProvider, passpointConfiguration); - break; - } - } - } - } - return matchingPasspointConfigs; - } - - /** - * Returns the corresponding wifi configurations for given a list Passpoint profile unique - * identifiers. - * - * An empty list will be returned when no match is found. - * - * @param idList a list of unique identifiers - * @return List of {@link WifiConfiguration} converted from {@link PasspointProvider} - */ - public List<WifiConfiguration> getWifiConfigsForPasspointProfiles(List<String> idList) { - if (mProviders.isEmpty()) { - return Collections.emptyList(); - } - List<WifiConfiguration> configs = new ArrayList<>(); - Set<String> uniqueIdSet = new HashSet<>(); - uniqueIdSet.addAll(idList); - for (String uniqueId : uniqueIdSet) { - PasspointProvider provider = mProviders.get(uniqueId); - if (provider == null) { - continue; - } - WifiConfiguration config = provider.getWifiConfig(); - if (mWifiConfigManager.shouldUseAggressiveRandomization(config)) { - config.setRandomizedMacAddress(MacAddress.fromString(DEFAULT_MAC_ADDRESS)); - } else { - MacAddress result = mMacAddressUtil.calculatePersistentMac(config.getKey(), - mMacAddressUtil.obtainMacRandHashFunction(Process.WIFI_UID)); - if (result != null) { - config.setRandomizedMacAddress(result); - } - } - // If the Passpoint configuration is from a suggestion, check if the app shares this - // suggestion with the user. - if (provider.isFromSuggestion() - && !mWifiInjector.getWifiNetworkSuggestionsManager() - .isPasspointSuggestionSharedWithUser(config)) { - continue; - } - configs.add(config); - } - return configs; - } - - /** - * Invoked when a Passpoint network was successfully connected based on the credentials - * provided by the given Passpoint provider - * - * @param uniqueId The unique identifier of the Passpointprofile - */ - public void onPasspointNetworkConnected(String uniqueId) { - PasspointProvider provider = mProviders.get(uniqueId); - if (provider == null) { - Log.e(TAG, "Passpoint network connected without provider: " + uniqueId); - return; - } - if (!provider.getHasEverConnected()) { - // First successful connection using this provider. - provider.setHasEverConnected(true); - } - } - - /** - * Update metrics related to installed Passpoint providers, this includes the number of - * installed providers and the number of those providers that results in a successful network - * connection. - */ - public void updateMetrics() { - int numProviders = mProviders.size(); - int numConnectedProviders = 0; - for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { - if (entry.getValue().getHasEverConnected()) { - numConnectedProviders++; - } - } - mWifiMetrics.updateSavedPasspointProfilesInfo(mProviders); - mWifiMetrics.updateSavedPasspointProfiles(numProviders, numConnectedProviders); - } - - /** - * Dump the current state of PasspointManager to the provided output stream. - * - * @param pw The output stream to write to - */ - public void dump(PrintWriter pw) { - pw.println("Dump of PasspointManager"); - pw.println("PasspointManager - Providers Begin ---"); - for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { - pw.println(entry.getValue()); - } - pw.println("PasspointManager - Providers End ---"); - pw.println("PasspointManager - Next provider ID to be assigned " + mProviderIndex); - mAnqpCache.dump(pw); - mAnqpRequestManager.dump(pw); - } - - /** - * Add a legacy Passpoint configuration represented by a {@link WifiConfiguration}. - * - * @param wifiConfig {@link WifiConfiguration} representation of the Passpoint configuration - * @return true on success - */ - private boolean addWifiConfig(WifiConfiguration wifiConfig) { - if (wifiConfig == null) { - return false; - } - - // Convert to PasspointConfiguration - PasspointConfiguration passpointConfig = - PasspointProvider.convertFromWifiConfig(wifiConfig); - if (passpointConfig == null) { - return false; - } - - // Setup aliases for enterprise certificates and key. - WifiEnterpriseConfig enterpriseConfig = wifiConfig.enterpriseConfig; - String caCertificateAliasSuffix = enterpriseConfig.getCaCertificateAlias(); - String clientCertAndKeyAliasSuffix = enterpriseConfig.getClientCertificateAlias(); - if (passpointConfig.getCredential().getUserCredential() != null - && TextUtils.isEmpty(caCertificateAliasSuffix)) { - Log.e(TAG, "Missing CA Certificate for user credential"); - return false; - } - if (passpointConfig.getCredential().getCertCredential() != null) { - if (TextUtils.isEmpty(caCertificateAliasSuffix)) { - Log.e(TAG, "Missing CA certificate for Certificate credential"); - return false; - } - if (TextUtils.isEmpty(clientCertAndKeyAliasSuffix)) { - Log.e(TAG, "Missing client certificate and key for certificate credential"); - return false; - } - } - - // Note that for legacy configuration, the alias for client private key is the same as the - // alias for the client certificate. - PasspointProvider provider = new PasspointProvider(passpointConfig, mKeyStore, - mWifiCarrierInfoManager, - mProviderIndex++, wifiConfig.creatorUid, null, false, - Arrays.asList(enterpriseConfig.getCaCertificateAlias()), - enterpriseConfig.getClientCertificateAlias(), null, false, false); - provider.enableVerboseLogging(mVerboseLoggingEnabled ? 1 : 0); - mProviders.put(passpointConfig.getUniqueId(), provider); - return true; - } - - /** - * Start the subscription provisioning flow with a provider. - * @param callingUid integer indicating the uid of the caller - * @param provider {@link OsuProvider} the provider to subscribe to - * @param callback {@link IProvisioningCallback} callback to update status to the caller - * @return boolean return value from the provisioning method - */ - public boolean startSubscriptionProvisioning(int callingUid, OsuProvider provider, - IProvisioningCallback callback) { - return mPasspointProvisioner.startSubscriptionProvisioning(callingUid, provider, callback); - } - - /** - * Check if a Passpoint configuration is expired - * - * @param config {@link PasspointConfiguration} Passpoint configuration - * @return True if the configuration is expired, false if not or expiration is unset - */ - private boolean isExpired(@NonNull PasspointConfiguration config) { - long expirationTime = config.getSubscriptionExpirationTimeMillis(); - - if (expirationTime != Long.MIN_VALUE) { - long curTime = System.currentTimeMillis(); - - // Check expiration and return true for expired profiles - if (curTime >= expirationTime) { - Log.d(TAG, "Profile for " + config.getServiceFriendlyName() + " has expired, " - + "expiration time: " + expirationTime + ", current time: " - + curTime); - return true; - } - } - return false; - } - - /** - * Get the filtered ScanResults which could be served by the {@link PasspointConfiguration}. - * @param passpointConfiguration The instance of {@link PasspointConfiguration} - * @param scanResults The list of {@link ScanResult} - * @return The filtered ScanResults - */ - @NonNull - public List<ScanResult> getMatchingScanResults( - @NonNull PasspointConfiguration passpointConfiguration, - @NonNull List<ScanResult> scanResults) { - PasspointProvider provider = mObjectFactory.makePasspointProvider(passpointConfiguration, - null, mWifiCarrierInfoManager, 0, 0, null, false); - List<ScanResult> filteredScanResults = new ArrayList<>(); - for (ScanResult scanResult : scanResults) { - PasspointMatch matchInfo = provider.match(getANQPElements(scanResult), - InformationElementUtil.getRoamingConsortiumIE(scanResult.informationElements)); - if (matchInfo == PasspointMatch.HomeProvider - || matchInfo == PasspointMatch.RoamingProvider) { - filteredScanResults.add(scanResult); - } - } - - return filteredScanResults; - } - - /** - * Check if the providers list is empty - * - * @return true if the providers list is empty, false otherwise - */ - public boolean isProvidersListEmpty() { - return mProviders.isEmpty(); - } - - /** - * Clear ANQP requests and flush ANQP Cache (for factory reset) - */ - public void clearAnqpRequestsAndFlushCache() { - mAnqpRequestManager.clear(); - mAnqpCache.flush(); - } - - /** - * Verify that the given certificate is trusted by one of the pre-loaded public CAs in the - * system key store. - * - * @param caCert The CA Certificate to verify - * @throws CertPathValidatorException - * @throws Exception - */ - private void verifyCaCert(X509Certificate caCert) - throws GeneralSecurityException, IOException { - CertificateFactory factory = CertificateFactory.getInstance("X.509"); - CertPathValidator validator = - CertPathValidator.getInstance(CertPathValidator.getDefaultType()); - CertPath path = factory.generateCertPath(Arrays.asList(caCert)); - KeyStore ks = KeyStore.getInstance("AndroidCAStore"); - ks.load(null, null); - PKIXParameters params = new PKIXParameters(ks); - params.setRevocationEnabled(false); - validator.validate(path, params); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointMatch.java b/service/java/com/android/server/wifi/hotspot2/PasspointMatch.java deleted file mode 100644 index 8825dad97..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointMatch.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.android.server.wifi.hotspot2; - -public enum PasspointMatch { - HomeProvider, - RoamingProvider, - Incomplete, - None, - Declined -} diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelper.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelper.java deleted file mode 100644 index bf2e460d8..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelper.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import android.annotation.NonNull; -import android.net.wifi.WifiConfiguration; -import android.os.Process; -import android.util.LocalLog; -import android.util.Pair; - -import com.android.server.wifi.NetworkUpdateResult; -import com.android.server.wifi.ScanDetail; -import com.android.server.wifi.WifiConfigManager; -import com.android.server.wifi.WifiNetworkSelector; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; -import com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement; -import com.android.server.wifi.util.ScanResultUtil; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * This class is the WifiNetworkSelector.NetworkNominator implementation for - * Passpoint networks. - */ -public class PasspointNetworkNominateHelper { - private final PasspointManager mPasspointManager; - private final WifiConfigManager mWifiConfigManager; - private final LocalLog mLocalLog; - /** - * Contained information for a Passpoint network candidate. - */ - private class PasspointNetworkCandidate { - PasspointNetworkCandidate(PasspointProvider provider, PasspointMatch matchStatus, - ScanDetail scanDetail) { - mProvider = provider; - mMatchStatus = matchStatus; - mScanDetail = scanDetail; - } - PasspointProvider mProvider; - PasspointMatch mMatchStatus; - ScanDetail mScanDetail; - } - - public PasspointNetworkNominateHelper(PasspointManager passpointManager, - WifiConfigManager wifiConfigManager, LocalLog localLog) { - mPasspointManager = passpointManager; - mWifiConfigManager = wifiConfigManager; - mLocalLog = localLog; - } - - /** - * Get best matched available Passpoint network candidates for scanDetails. - * @param scanDetails List of ScanDetail. - * @param isFromSuggestion True to indicate profile from suggestion, false for user saved. - * @return List of pair of scanDetail and WifiConfig from matched available provider. - */ - public List<Pair<ScanDetail, WifiConfiguration>> getPasspointNetworkCandidates( - List<ScanDetail> scanDetails, boolean isFromSuggestion) { - // Sweep the ANQP cache to remove any expired ANQP entries. - mPasspointManager.sweepCache(); - List<ScanDetail> filteredScanDetails = new ArrayList<>(); - // Filter out all invalid scanDetail - for (ScanDetail scanDetail : scanDetails) { - if (scanDetail.getNetworkDetail() == null - || !scanDetail.getNetworkDetail().isInterworking() - || scanDetail.getNetworkDetail().getHSRelease() == null) { - // If scanDetail is not Passpoint network, ignore. - continue; - } - if (!scanDetail.getNetworkDetail().isInternet() - || isApWanLinkStatusDown(scanDetail)) { - // If scanDetail has no internet connection, ignore. - mLocalLog.log("Ignoring no internet connection Passpoint AP: " - + WifiNetworkSelector.toScanId(scanDetail.getScanResult())); - continue; - } - filteredScanDetails.add(scanDetail); - } - - return findBestMatchScanDetailForProviders(filteredScanDetails, isFromSuggestion); - } - - /** - * Check if ANQP element inside that scanDetail indicate AP WAN port link status is down. - * - * @param scanDetail contains ANQP element to check. - * @return return true is link status is down, otherwise return false. - */ - private boolean isApWanLinkStatusDown(ScanDetail scanDetail) { - Map<Constants.ANQPElementType, ANQPElement> anqpElements = - mPasspointManager.getANQPElements(scanDetail.getScanResult()); - if (anqpElements == null) { - return false; - } - HSWanMetricsElement wm = (HSWanMetricsElement) anqpElements.get( - Constants.ANQPElementType.HSWANMetrics); - if (wm == null) { - return false; - } - return wm.getStatus() != HSWanMetricsElement.LINK_STATUS_UP || wm.isCapped(); - } - - /** - * Match available providers for each scan detail. Then for each available provider, find the - * best scan detail for it. - * @param scanDetails all details for this scan. - * @param isFromSuggestion True to indicate profile from suggestion, false for user saved. - * @return List of pair of scanDetail and WifiConfig from matched available provider. - */ - private @NonNull List<Pair<ScanDetail, WifiConfiguration>> findBestMatchScanDetailForProviders( - List<ScanDetail> scanDetails, boolean isFromSuggestion) { - if (mPasspointManager.isProvidersListEmpty()) { - return Collections.emptyList(); - } - List<Pair<ScanDetail, WifiConfiguration>> results = new ArrayList<>(); - Map<PasspointProvider, List<PasspointNetworkCandidate>> candidatesPerProvider = - new HashMap<>(); - // Match each scanDetail with best provider (home > roaming), and grouped by FQDN. - for (ScanDetail scanDetail : scanDetails) { - List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = - mPasspointManager.matchProvider(scanDetail.getScanResult()); - if (matchedProviders == null) { - continue; - } - for (Pair<PasspointProvider, PasspointMatch> matchedProvider : matchedProviders) { - if (matchedProvider.first.isFromSuggestion() != isFromSuggestion) { - continue; - } - List<PasspointNetworkCandidate> candidates = candidatesPerProvider - .computeIfAbsent(matchedProvider.first, k -> new ArrayList<>()); - candidates.add(new PasspointNetworkCandidate(matchedProvider.first, - matchedProvider.second, scanDetail)); - } - } - // For each provider find the best scanDetail for it and create selection candidate pair. - for (List<PasspointNetworkCandidate> candidates : candidatesPerProvider.values()) { - List<PasspointNetworkCandidate> bestCandidates = findHomeNetworksIfPossible(candidates); - for (PasspointNetworkCandidate candidate : bestCandidates) { - WifiConfiguration config = createWifiConfigForProvider(candidate); - if (config == null) { - continue; - } - if (mWifiConfigManager.isNetworkTemporarilyDisabledByUser(config.FQDN)) { - mLocalLog.log("Ignoring user disabled FQDN: " + config.FQDN); - continue; - } - results.add(Pair.create(candidate.mScanDetail, config)); - } - } - return results; - } - - /** - * Create and return a WifiConfiguration for the given ScanDetail and PasspointProvider. - * The newly created WifiConfiguration will also be added to WifiConfigManager. - * - * @return {@link WifiConfiguration} - */ - private WifiConfiguration createWifiConfigForProvider( - PasspointNetworkCandidate candidate) { - WifiConfiguration config = candidate.mProvider.getWifiConfig(); - config.SSID = ScanResultUtil.createQuotedSSID(candidate.mScanDetail.getSSID()); - config.isHomeProviderNetwork = candidate.mMatchStatus == PasspointMatch.HomeProvider; - if (candidate.mScanDetail.getNetworkDetail().getAnt() - == NetworkDetail.Ant.ChargeablePublic) { - config.meteredHint = true; - } - WifiConfiguration existingNetwork = mWifiConfigManager.getConfiguredNetwork( - config.getKey()); - if (existingNetwork != null) { - WifiConfiguration.NetworkSelectionStatus status = - existingNetwork.getNetworkSelectionStatus(); - if (!(status.isNetworkEnabled() - || mWifiConfigManager.tryEnableNetwork(existingNetwork.networkId))) { - mLocalLog.log("Current configuration for the Passpoint AP " + config.SSID - + " is disabled, skip this candidate"); - return null; - } - } - - // Add or update with the newly created WifiConfiguration to WifiConfigManager. - // NOTE: if existingNetwork != null, this update is a no-op in most cases if the SSID is the - // same (since we update the cached config in PasspointManager#addOrUpdateProvider(). - NetworkUpdateResult result = mWifiConfigManager.addOrUpdateNetwork( - config, config.creatorUid, config.creatorName); - - if (!result.isSuccess()) { - mLocalLog.log("Failed to add passpoint network"); - return existingNetwork; - } - mWifiConfigManager.allowAutojoin(result.getNetworkId(), config.allowAutojoin); - mWifiConfigManager.enableNetwork(result.getNetworkId(), false, Process.WIFI_UID, null); - mWifiConfigManager.setNetworkCandidateScanResult(result.getNetworkId(), - candidate.mScanDetail.getScanResult(), 0); - mWifiConfigManager.updateScanDetailForNetwork( - result.getNetworkId(), candidate.mScanDetail); - return mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - } - - /** - * Given a list of Passpoint networks (with both provider and scan info), return all - * homeProvider matching networks if there is any, otherwise return all roamingProvider matching - * networks. - * - * @param networkList List of Passpoint networks - * @return List of {@link PasspointNetworkCandidate} - */ - private @NonNull List<PasspointNetworkCandidate> findHomeNetworksIfPossible( - @NonNull List<PasspointNetworkCandidate> networkList) { - List<PasspointNetworkCandidate> homeProviderCandidates = networkList.stream() - .filter(candidate -> candidate.mMatchStatus == PasspointMatch.HomeProvider) - .collect(Collectors.toList()); - if (homeProviderCandidates.isEmpty()) { - return networkList; - } - return homeProviderCandidates; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java b/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java deleted file mode 100644 index 2ce1b1a6d..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import android.content.Context; -import android.net.wifi.hotspot2.PasspointConfiguration; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiCarrierInfoManager; -import com.android.server.wifi.WifiKeyStore; -import com.android.server.wifi.WifiMetrics; -import com.android.server.wifi.WifiNative; - -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; - -/** - * Factory class for creating Passpoint related objects. Useful for mocking object creations - * in the unit tests. - */ -public class PasspointObjectFactory{ - /** - * Create a PasspointEventHandler instance. - * - * @param wifiNative Instance of {@link WifiNative} - * @param callbacks Instance of {@link PasspointEventHandler.Callbacks} - * @return {@link PasspointEventHandler} - */ - public PasspointEventHandler makePasspointEventHandler(WifiNative wifiNative, - PasspointEventHandler.Callbacks callbacks) { - return new PasspointEventHandler(wifiNative, callbacks); - } - - /** - * Create a PasspointProvider instance. - * - * @param keyStore Instance of {@link WifiKeyStore} - * @param config Configuration for the provider - * @param providerId Unique identifier for the provider - * @param packageName Package name of app adding/updating the {@code config} - * @return {@link PasspointProvider} - */ - public PasspointProvider makePasspointProvider(PasspointConfiguration config, - WifiKeyStore keyStore, WifiCarrierInfoManager wifiCarrierInfoManager, long providerId, - int creatorUid, String packageName, boolean isFromSuggestion) { - return new PasspointProvider(config, keyStore, wifiCarrierInfoManager, providerId, - creatorUid, packageName, isFromSuggestion); - } - - /** - * Create a {@link PasspointConfigUserStoreData} instance. - * - * @param keyStore Instance of {@link WifiKeyStore} - * @param wifiCarrierInfoManager Instance of {@link WifiCarrierInfoManager} - * @param dataSource Passpoint configuration data source - * @return {@link PasspointConfigUserStoreData} - */ - public PasspointConfigUserStoreData makePasspointConfigUserStoreData(WifiKeyStore keyStore, - WifiCarrierInfoManager wifiCarrierInfoManager, - PasspointConfigUserStoreData.DataSource dataSource) { - return new PasspointConfigUserStoreData(keyStore, wifiCarrierInfoManager, dataSource); - } - - /** - * Create a {@link PasspointConfigSharedStoreData} instance. - * @param dataSource Passpoint configuration data source - * @return {@link PasspointConfigSharedStoreData} - */ - public PasspointConfigSharedStoreData makePasspointConfigSharedStoreData( - PasspointConfigSharedStoreData.DataSource dataSource) { - return new PasspointConfigSharedStoreData(dataSource); - } - - /** - * Create a AnqpCache instance. - * - * @param clock Instance of {@link Clock} - * @return {@link AnqpCache} - */ - public AnqpCache makeAnqpCache(Clock clock) { - return new AnqpCache(clock); - } - - /** - * Create an instance of {@link ANQPRequestManager}. - * - * @param handler Instance of {@link PasspointEventHandler} - * @param clock Instance of {@link Clock} - * @return {@link ANQPRequestManager} - */ - public ANQPRequestManager makeANQPRequestManager(PasspointEventHandler handler, Clock clock) { - return new ANQPRequestManager(handler, clock); - } - - /** - * Create an instance of {@link PasspointProvisioner}. - * - * @param context Instance of {@link Context} - * @param wifiNative Instance of {@link WifiNative} - * @param passpointManager Instance of {@link PasspointManager} - * @return {@link PasspointProvisioner} - */ - public PasspointProvisioner makePasspointProvisioner(Context context, WifiNative wifiNative, - PasspointManager passpointManager, WifiMetrics wifiMetrics) { - return new PasspointProvisioner(context, wifiNative, this, passpointManager, wifiMetrics); - } - - /** - * Create an instance of {@link OsuNetworkConnection}. - * - * @param context - * @return {@link OsuNetworkConnection} - */ - public OsuNetworkConnection makeOsuNetworkConnection(Context context) { - return new OsuNetworkConnection(context); - } - - /** - * Create an instance of {@link OsuServerConnection}. - * - * @return {@link OsuServerConnection} - */ - public OsuServerConnection makeOsuServerConnection() { - return new OsuServerConnection(null); - } - - - /** - * Create an instance of {@link WfaKeyStore}. - * - * @return WfaKeyStore {@link WfaKeyStore} - */ - public WfaKeyStore makeWfaKeyStore() { - return new WfaKeyStore(); - } - - /** - * Create an instance of {@link SSLContext}. - * - * @param tlsVersion String indicate TLS version - * @return SSLContext an instance, corresponding to the TLS version - */ - public SSLContext getSSLContext(String tlsVersion) { - SSLContext tlsContext = null; - try { - tlsContext = SSLContext.getInstance(tlsVersion); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return tlsContext; - } - - /** - * Create an instance of {@link TrustManagerFactory}. - * - * @param ks KeyStore used to get root certs - * @return TrustManagerFactory an instance for root cert validation - */ - public TrustManagerFactory getTrustManagerFactory(KeyStore ks) { - try { - TrustManagerFactory trustManagerFactory = TrustManagerFactory - .getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(ks); - return trustManagerFactory; - } catch (NoSuchAlgorithmException | KeyStoreException e) { - return null; - } - } - - /** - * Create an instance of {@link SystemInfo}. - * - * @param context Instance of {@link Context} - * @param wifiNative Instance of {@link WifiNative} - * @return {@Link Systeminfo} that is used for getting system related info. - */ - public SystemInfo getSystemInfo(Context context, WifiNative wifiNative) { - return SystemInfo.getInstance(context, wifiNative); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java deleted file mode 100644 index 8e7364d4b..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java +++ /dev/null @@ -1,1009 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static android.net.wifi.WifiConfiguration.MeteredOverride; - -import android.annotation.Nullable; -import android.net.wifi.EAPConstants; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.Credential.SimCredential; -import android.net.wifi.hotspot2.pps.Credential.UserCredential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Base64; -import android.util.Log; -import android.util.Pair; - -import com.android.server.wifi.IMSIParameter; -import com.android.server.wifi.WifiCarrierInfoManager; -import com.android.server.wifi.WifiKeyStore; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; -import com.android.server.wifi.hotspot2.anqp.DomainNameElement; -import com.android.server.wifi.hotspot2.anqp.NAIRealmElement; -import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement; -import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement; -import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; -import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; -import com.android.server.wifi.util.ArrayUtils; -import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * Abstraction for Passpoint service provider. This class contains the both static - * Passpoint configuration data and the runtime data (e.g. blacklisted SSIDs, statistics). - */ -public class PasspointProvider { - private static final String TAG = "PasspointProvider"; - - /** - * Used as part of alias string for certificates and keys. The alias string is in the format - * of: [KEY_TYPE]_HS2_[ProviderID] - * For example: "CACERT_HS2_0", "USRCERT_HS2_0", "USRPKEY_HS2_0", "CACERT_HS2_REMEDIATION_0" - */ - private static final String ALIAS_HS_TYPE = "HS2_"; - private static final String ALIAS_ALIAS_REMEDIATION_TYPE = "REMEDIATION_"; - - private static final String SYSTEM_CA_STORE_PATH = "/system/etc/security/cacerts"; - - private final PasspointConfiguration mConfig; - private final WifiKeyStore mKeyStore; - - /** - * Aliases for the private keys and certificates installed in the keystore. Each alias - * is a suffix of the actual certificate or key name installed in the keystore. The - * certificate or key name in the keystore is consist of |Type|_|alias|. - * This will be consistent with the usage of the term "alias" in {@link WifiEnterpriseConfig}. - */ - private List<String> mCaCertificateAliases; - private String mClientPrivateKeyAndCertificateAlias; - private String mRemediationCaCertificateAlias; - - private final long mProviderId; - private final int mCreatorUid; - private final String mPackageName; - - private final IMSIParameter mImsiParameter; - - private final int mEAPMethodID; - private final AuthParam mAuthParam; - private final WifiCarrierInfoManager mWifiCarrierInfoManager; - - private int mBestGuessCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; - private boolean mHasEverConnected; - private boolean mIsShared; - private boolean mIsFromSuggestion; - private boolean mIsTrusted; - private boolean mVerboseLoggingEnabled; - - public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore, - WifiCarrierInfoManager wifiCarrierInfoManager, long providerId, int creatorUid, - String packageName, boolean isFromSuggestion) { - this(config, keyStore, wifiCarrierInfoManager, providerId, creatorUid, packageName, - isFromSuggestion, null, null, null, false, false); - } - - public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore, - WifiCarrierInfoManager wifiCarrierInfoManager, long providerId, int creatorUid, - String packageName, boolean isFromSuggestion, List<String> caCertificateAliases, - String clientPrivateKeyAndCertificateAlias, String remediationCaCertificateAlias, - boolean hasEverConnected, boolean isShared) { - // Maintain a copy of the configuration to avoid it being updated by others. - mConfig = new PasspointConfiguration(config); - mKeyStore = keyStore; - mProviderId = providerId; - mCreatorUid = creatorUid; - mPackageName = packageName; - mCaCertificateAliases = caCertificateAliases; - mClientPrivateKeyAndCertificateAlias = clientPrivateKeyAndCertificateAlias; - mRemediationCaCertificateAlias = remediationCaCertificateAlias; - mHasEverConnected = hasEverConnected; - mIsShared = isShared; - mIsFromSuggestion = isFromSuggestion; - mWifiCarrierInfoManager = wifiCarrierInfoManager; - mIsTrusted = true; - - // Setup EAP method and authentication parameter based on the credential. - if (mConfig.getCredential().getUserCredential() != null) { - mEAPMethodID = EAPConstants.EAP_TTLS; - mAuthParam = new NonEAPInnerAuth(NonEAPInnerAuth.getAuthTypeID( - mConfig.getCredential().getUserCredential().getNonEapInnerMethod())); - mImsiParameter = null; - } else if (mConfig.getCredential().getCertCredential() != null) { - mEAPMethodID = EAPConstants.EAP_TLS; - mAuthParam = null; - mImsiParameter = null; - } else { - mEAPMethodID = mConfig.getCredential().getSimCredential().getEapType(); - mAuthParam = null; - mImsiParameter = IMSIParameter.build( - mConfig.getCredential().getSimCredential().getImsi()); - } - } - - /** - * Set passpoint network trusted or not. - * Default is true. Only allows to change when it is from suggestion. - */ - public void setTrusted(boolean trusted) { - if (!mIsFromSuggestion) { - Log.e(TAG, "setTrusted can only be called for suggestion passpoint network"); - return; - } - mIsTrusted = trusted; - } - - public boolean isTrusted() { - return mIsTrusted; - } - - public PasspointConfiguration getConfig() { - // Return a copy of the configuration to avoid it being updated by others. - return new PasspointConfiguration(mConfig); - } - - public List<String> getCaCertificateAliases() { - return mCaCertificateAliases; - } - - public String getClientPrivateKeyAndCertificateAlias() { - return mClientPrivateKeyAndCertificateAlias; - } - - public String getRemediationCaCertificateAlias() { - return mRemediationCaCertificateAlias; - } - - public long getProviderId() { - return mProviderId; - } - - public int getCreatorUid() { - return mCreatorUid; - } - - @Nullable - public String getPackageName() { - return mPackageName; - } - - public boolean getHasEverConnected() { - return mHasEverConnected; - } - - public void setHasEverConnected(boolean hasEverConnected) { - mHasEverConnected = hasEverConnected; - } - - public boolean isFromSuggestion() { - return mIsFromSuggestion; - } - - /** - * Enable/disable the auto-join configuration of the corresponding passpoint configuration. - * - * @return true if the setting has changed - */ - public boolean setAutojoinEnabled(boolean autoJoinEnabled) { - boolean changed = mConfig.isAutojoinEnabled() != autoJoinEnabled; - mConfig.setAutojoinEnabled(autoJoinEnabled); - return changed; - } - - public boolean isAutojoinEnabled() { - return mConfig.isAutojoinEnabled(); - } - - /** - * Enable/disable mac randomization for this passpoint profile. - * - * @return true if the setting has changed - */ - public boolean setMacRandomizationEnabled(boolean enabled) { - boolean changed = mConfig.isMacRandomizationEnabled() != enabled; - mConfig.setMacRandomizationEnabled(enabled); - return changed; - } - - /** - * Get whether mac randomization is enabled for this passpoint profile. - */ - public boolean isMacRandomizationEnabled() { - return mConfig.isMacRandomizationEnabled(); - } - - /** - * Get the metered override for this passpoint profile. - * - * @return true if the setting has changed - */ - public boolean setMeteredOverride(@MeteredOverride int meteredOverride) { - boolean changed = mConfig.getMeteredOverride() != meteredOverride; - mConfig.setMeteredOverride(meteredOverride); - return changed; - } - - /** - * Install certificates and key based on current configuration. - * Note: the certificates and keys in the configuration will get cleared once - * they're installed in the keystore. - * - * @return true on success - */ - public boolean installCertsAndKeys() { - // Install CA certificate. - X509Certificate[] x509Certificates = mConfig.getCredential().getCaCertificates(); - if (x509Certificates != null) { - mCaCertificateAliases = new ArrayList<>(); - for (int i = 0; i < x509Certificates.length; i++) { - String alias = String.format("%s%s_%d", ALIAS_HS_TYPE, mProviderId, i); - if (!mKeyStore.putCaCertInKeyStore(alias, x509Certificates[i])) { - Log.e(TAG, "Failed to install CA Certificate " + alias); - uninstallCertsAndKeys(); - return false; - } else { - mCaCertificateAliases.add(alias); - } - } - } - - // Install the client private key & certificate. - if (mConfig.getCredential().getClientPrivateKey() != null - && mConfig.getCredential().getClientCertificateChain() != null) { - String keyName = ALIAS_HS_TYPE + mProviderId; - PrivateKey clientKey = mConfig.getCredential().getClientPrivateKey(); - X509Certificate clientCert = getClientCertificate( - mConfig.getCredential().getClientCertificateChain(), - mConfig.getCredential().getCertCredential().getCertSha256Fingerprint()); - if (clientCert == null) { - Log.e(TAG, "Failed to locate client certificate"); - uninstallCertsAndKeys(); - return false; - } - if (!mKeyStore.putUserPrivKeyAndCertsInKeyStore( - keyName, clientKey, new Certificate[] {clientCert})) { - Log.e(TAG, "Failed to install client private key or certificate"); - uninstallCertsAndKeys(); - return false; - } - mClientPrivateKeyAndCertificateAlias = keyName; - } - - if (mConfig.getSubscriptionUpdate() != null) { - X509Certificate certificate = mConfig.getSubscriptionUpdate().getCaCertificate(); - if (certificate == null) { - Log.e(TAG, "Failed to locate CA certificate for remediation"); - uninstallCertsAndKeys(); - return false; - } - String certName = ALIAS_HS_TYPE + ALIAS_ALIAS_REMEDIATION_TYPE + mProviderId; - if (!mKeyStore.putCaCertInKeyStore(certName, certificate)) { - Log.e(TAG, "Failed to install CA certificate for remediation"); - uninstallCertsAndKeys(); - return false; - } - mRemediationCaCertificateAlias = certName; - } - - // Clear the keys and certificates in the configuration. - mConfig.getCredential().setCaCertificates(null); - mConfig.getCredential().setClientPrivateKey(null); - mConfig.getCredential().setClientCertificateChain(null); - if (mConfig.getSubscriptionUpdate() != null) { - mConfig.getSubscriptionUpdate().setCaCertificate(null); - } - return true; - } - - /** - * Remove any installed certificates and key. - */ - public void uninstallCertsAndKeys() { - if (mCaCertificateAliases != null) { - for (String certificateAlias : mCaCertificateAliases) { - if (!mKeyStore.removeEntryFromKeyStore(certificateAlias)) { - Log.e(TAG, "Failed to remove entry: " + certificateAlias); - } - } - mCaCertificateAliases = null; - } - if (mClientPrivateKeyAndCertificateAlias != null) { - if (!mKeyStore.removeEntryFromKeyStore(mClientPrivateKeyAndCertificateAlias)) { - Log.e(TAG, "Failed to remove entry: " + mClientPrivateKeyAndCertificateAlias); - } - mClientPrivateKeyAndCertificateAlias = null; - } - if (mRemediationCaCertificateAlias != null) { - if (!mKeyStore.removeEntryFromKeyStore(mRemediationCaCertificateAlias)) { - Log.e(TAG, "Failed to remove entry: " + mRemediationCaCertificateAlias); - } - mRemediationCaCertificateAlias = null; - } - } - - /** - * Try to update the carrier ID according to the IMSI parameter of passpoint configuration. - * - * @return true if the carrier ID is updated, otherwise false. - */ - public boolean tryUpdateCarrierId() { - return mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(mConfig); - } - - private @Nullable String getMatchingSimImsi() { - String matchingSIMImsi = null; - if (mConfig.getCarrierId() != TelephonyManager.UNKNOWN_CARRIER_ID) { - matchingSIMImsi = mWifiCarrierInfoManager - .getMatchingImsi(mConfig.getCarrierId()); - } else { - // Get the IMSI and carrier ID of SIM card which match with the IMSI prefix from - // passpoint profile - Pair<String, Integer> imsiCarrierIdPair = mWifiCarrierInfoManager - .getMatchingImsiCarrierId(mConfig.getCredential().getSimCredential().getImsi()); - if (imsiCarrierIdPair != null) { - matchingSIMImsi = imsiCarrierIdPair.first; - mBestGuessCarrierId = imsiCarrierIdPair.second; - } - } - - return matchingSIMImsi; - } - - /** - * Return the matching status with the given AP, based on the ANQP elements from the AP. - * - * @param anqpElements ANQP elements from the AP - * @param roamingConsortiumFromAp Roaming Consortium information element from the AP - * @return {@link PasspointMatch} - */ - public PasspointMatch match(Map<ANQPElementType, ANQPElement> anqpElements, - RoamingConsortium roamingConsortiumFromAp) { - // If the profile requires a SIM credential, make sure that the installed SIM matches - String matchingSimImsi = null; - if (mConfig.getCredential().getSimCredential() != null) { - matchingSimImsi = getMatchingSimImsi(); - if (TextUtils.isEmpty(matchingSimImsi)) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "No SIM card with IMSI " - + mConfig.getCredential().getSimCredential().getImsi() - + " is installed, final match: " + PasspointMatch.None); - } - return PasspointMatch.None; - } - } - - // Match FQDN for Home provider or RCOI(s) for Roaming provider - // For SIM credential, the FQDN is in the format of wlan.mnc*.mcc*.3gppnetwork.org - PasspointMatch providerMatch = matchFqdnAndRcoi(anqpElements, roamingConsortiumFromAp, - matchingSimImsi); - - // 3GPP Network matching - if (providerMatch == PasspointMatch.None && ANQPMatcher.matchThreeGPPNetwork( - (ThreeGPPNetworkElement) anqpElements.get(ANQPElementType.ANQP3GPPNetwork), - mImsiParameter, matchingSimImsi)) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Final RoamingProvider match with " - + anqpElements.get(ANQPElementType.ANQP3GPPNetwork)); - } - return PasspointMatch.RoamingProvider; - } - - // Perform NAI Realm matching - boolean realmMatch = ANQPMatcher.matchNAIRealm( - (NAIRealmElement) anqpElements.get(ANQPElementType.ANQPNAIRealm), - mConfig.getCredential().getRealm()); - - // In case of no realm match, return provider match as is. - if (!realmMatch) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "No NAI realm match, final match: " + providerMatch); - } - return providerMatch; - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "NAI realm match with " + mConfig.getCredential().getRealm()); - } - - // Promote the provider match to RoamingProvider if provider match is not found, but NAI - // realm is matched. - if (providerMatch == PasspointMatch.None) { - providerMatch = PasspointMatch.RoamingProvider; - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Final match: " + providerMatch); - } - return providerMatch; - } - - /** - * Generate a WifiConfiguration based on the provider's configuration. The generated - * WifiConfiguration will include all the necessary credentials for network connection except - * the SSID, which should be added by the caller when the config is being used for network - * connection. - * - * @return {@link WifiConfiguration} - */ - public WifiConfiguration getWifiConfig() { - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = mConfig.getHomeSp().getFqdn(); - wifiConfig.setPasspointUniqueId(mConfig.getUniqueId()); - if (mConfig.getHomeSp().getRoamingConsortiumOis() != null) { - wifiConfig.roamingConsortiumIds = Arrays.copyOf( - mConfig.getHomeSp().getRoamingConsortiumOis(), - mConfig.getHomeSp().getRoamingConsortiumOis().length); - } - if (mConfig.getUpdateIdentifier() != Integer.MIN_VALUE) { - // R2 profile, it needs to set updateIdentifier HS2.0 Indication element as PPS MO - // ID in Association Request. - wifiConfig.updateIdentifier = Integer.toString(mConfig.getUpdateIdentifier()); - if (isMeteredNetwork(mConfig)) { - wifiConfig.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED; - } - } - wifiConfig.providerFriendlyName = mConfig.getHomeSp().getFriendlyName(); - wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - int carrierId = mConfig.getCarrierId(); - if (carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { - carrierId = mBestGuessCarrierId; - } - wifiConfig.carrierId = carrierId; - - // Set RSN only to tell wpa_supplicant that this network is for Passpoint. - wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN); - - WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); - enterpriseConfig.setRealm(mConfig.getCredential().getRealm()); - enterpriseConfig.setDomainSuffixMatch(mConfig.getHomeSp().getFqdn()); - if (mConfig.getCredential().getUserCredential() != null) { - buildEnterpriseConfigForUserCredential(enterpriseConfig, - mConfig.getCredential().getUserCredential()); - setAnonymousIdentityToNaiRealm(enterpriseConfig, mConfig.getCredential().getRealm()); - } else if (mConfig.getCredential().getCertCredential() != null) { - buildEnterpriseConfigForCertCredential(enterpriseConfig); - setAnonymousIdentityToNaiRealm(enterpriseConfig, mConfig.getCredential().getRealm()); - } else { - buildEnterpriseConfigForSimCredential(enterpriseConfig, - mConfig.getCredential().getSimCredential()); - } - // If AAA server trusted names are specified, use it to replace HOME SP FQDN - // and use system CA regardless of provisioned CA certificate. - if (!ArrayUtils.isEmpty(mConfig.getAaaServerTrustedNames())) { - enterpriseConfig.setDomainSuffixMatch( - String.join(";", mConfig.getAaaServerTrustedNames())); - enterpriseConfig.setCaPath(SYSTEM_CA_STORE_PATH); - } - wifiConfig.enterpriseConfig = enterpriseConfig; - // PPS MO Credential/CheckAAAServerCertStatus node contains a flag which indicates - // if the mobile device needs to check the AAA server certificate's revocation status - // during EAP authentication. - if (mConfig.getCredential().getCheckAaaServerCertStatus()) { - // Check server certificate using OCSP (Online Certificate Status Protocol). - wifiConfig.enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); - } - wifiConfig.allowAutojoin = isAutojoinEnabled(); - wifiConfig.shared = mIsShared; - wifiConfig.fromWifiNetworkSuggestion = mIsFromSuggestion; - wifiConfig.ephemeral = mIsFromSuggestion; - wifiConfig.creatorName = mPackageName; - wifiConfig.creatorUid = mCreatorUid; - wifiConfig.trusted = mIsTrusted; - if (mConfig.isMacRandomizationEnabled()) { - wifiConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - } else { - wifiConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - } - wifiConfig.meteredOverride = mConfig.getMeteredOverride(); - return wifiConfig; - } - - /** - * @return true if provider is backed by a SIM credential. - */ - public boolean isSimCredential() { - return mConfig.getCredential().getSimCredential() != null; - } - - /** - * Convert a legacy {@link WifiConfiguration} representation of a Passpoint configuration to - * a {@link PasspointConfiguration}. This is used for migrating legacy Passpoint - * configuration (release N and older). - * - * @param wifiConfig The {@link WifiConfiguration} to convert - * @return {@link PasspointConfiguration} - */ - public static PasspointConfiguration convertFromWifiConfig(WifiConfiguration wifiConfig) { - PasspointConfiguration passpointConfig = new PasspointConfiguration(); - - // Setup HomeSP. - HomeSp homeSp = new HomeSp(); - if (TextUtils.isEmpty(wifiConfig.FQDN)) { - Log.e(TAG, "Missing FQDN"); - return null; - } - homeSp.setFqdn(wifiConfig.FQDN); - homeSp.setFriendlyName(wifiConfig.providerFriendlyName); - if (wifiConfig.roamingConsortiumIds != null) { - homeSp.setRoamingConsortiumOis(Arrays.copyOf( - wifiConfig.roamingConsortiumIds, wifiConfig.roamingConsortiumIds.length)); - } - passpointConfig.setHomeSp(homeSp); - passpointConfig.setCarrierId(wifiConfig.carrierId); - - // Setup Credential. - Credential credential = new Credential(); - credential.setRealm(wifiConfig.enterpriseConfig.getRealm()); - switch (wifiConfig.enterpriseConfig.getEapMethod()) { - case WifiEnterpriseConfig.Eap.TTLS: - credential.setUserCredential(buildUserCredentialFromEnterpriseConfig( - wifiConfig.enterpriseConfig)); - break; - case WifiEnterpriseConfig.Eap.TLS: - Credential.CertificateCredential certCred = new Credential.CertificateCredential(); - certCred.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3); - credential.setCertCredential(certCred); - break; - case WifiEnterpriseConfig.Eap.SIM: - credential.setSimCredential(buildSimCredentialFromEnterpriseConfig( - EAPConstants.EAP_SIM, wifiConfig.enterpriseConfig)); - break; - case WifiEnterpriseConfig.Eap.AKA: - credential.setSimCredential(buildSimCredentialFromEnterpriseConfig( - EAPConstants.EAP_AKA, wifiConfig.enterpriseConfig)); - break; - case WifiEnterpriseConfig.Eap.AKA_PRIME: - credential.setSimCredential(buildSimCredentialFromEnterpriseConfig( - EAPConstants.EAP_AKA_PRIME, wifiConfig.enterpriseConfig)); - break; - default: - Log.e(TAG, "Unsupported EAP method: " - + wifiConfig.enterpriseConfig.getEapMethod()); - return null; - } - if (credential.getUserCredential() == null && credential.getCertCredential() == null - && credential.getSimCredential() == null) { - Log.e(TAG, "Missing credential"); - return null; - } - passpointConfig.setCredential(credential); - - return passpointConfig; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof PasspointProvider)) { - return false; - } - PasspointProvider that = (PasspointProvider) thatObject; - return mProviderId == that.mProviderId - && (mCaCertificateAliases == null ? that.mCaCertificateAliases == null - : mCaCertificateAliases.equals(that.mCaCertificateAliases)) - && TextUtils.equals(mClientPrivateKeyAndCertificateAlias, - that.mClientPrivateKeyAndCertificateAlias) - && (mConfig == null ? that.mConfig == null : mConfig.equals(that.mConfig)) - && TextUtils.equals(mRemediationCaCertificateAlias, - that.mRemediationCaCertificateAlias); - } - - @Override - public int hashCode() { - return Objects.hash(mProviderId, mCaCertificateAliases, - mClientPrivateKeyAndCertificateAlias, mConfig, mRemediationCaCertificateAlias); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("ProviderId: ").append(mProviderId).append("\n"); - builder.append("CreatorUID: ").append(mCreatorUid).append("\n"); - builder.append("Best guess Carrier ID: ").append(mBestGuessCarrierId).append("\n"); - builder.append("Ever connected: ").append(mHasEverConnected).append("\n"); - builder.append("Shared: ").append(mIsShared).append("\n"); - builder.append("Suggestion: ").append(mIsFromSuggestion).append("\n"); - builder.append("Trusted: ").append(mIsTrusted).append("\n"); - - if (mPackageName != null) { - builder.append("PackageName: ").append(mPackageName).append("\n"); - } - builder.append("Configuration Begin ---\n"); - builder.append(mConfig); - builder.append("Configuration End ---\n"); - builder.append("WifiConfiguration Begin ---\n"); - builder.append(getWifiConfig()); - builder.append("WifiConfiguration End ---\n"); - return builder.toString(); - } - - /** - * Retrieve the client certificate from the certificates chain. The certificate - * with the matching SHA256 digest is the client certificate. - * - * @param certChain The client certificates chain - * @param expectedSha256Fingerprint The expected SHA256 digest of the client certificate - * @return {@link java.security.cert.X509Certificate} - */ - private static X509Certificate getClientCertificate(X509Certificate[] certChain, - byte[] expectedSha256Fingerprint) { - if (certChain == null) { - return null; - } - try { - MessageDigest digester = MessageDigest.getInstance("SHA-256"); - for (X509Certificate certificate : certChain) { - digester.reset(); - byte[] fingerprint = digester.digest(certificate.getEncoded()); - if (Arrays.equals(expectedSha256Fingerprint, fingerprint)) { - return certificate; - } - } - } catch (CertificateEncodingException | NoSuchAlgorithmException e) { - return null; - } - - return null; - } - - /** - * Determines the Passpoint network is a metered network. - * - * Expiration date -> non-metered - * Data limit -> metered - * Time usage limit -> metered - * @param passpointConfig instance of {@link PasspointConfiguration} - * @return {@code true} if the network is a metered network, {@code false} otherwise. - */ - private boolean isMeteredNetwork(PasspointConfiguration passpointConfig) { - if (passpointConfig == null) return false; - - // If DataLimit is zero, there is unlimited data usage for the account. - // If TimeLimit is zero, there is unlimited time usage for the account. - return passpointConfig.getUsageLimitDataLimit() > 0 - || passpointConfig.getUsageLimitTimeLimitInMinutes() > 0; - } - - /** - * Match given OIs to the Roaming Consortium OIs - * - * @param providerOis Provider OIs to match against - * @param roamingConsortiumElement RCOIs in the ANQP element - * @param roamingConsortiumFromAp RCOIs in the AP scan results - * @param matchAll Indicates if all providerOis must match the RCOIs elements - * @return {@code true} if there is a match, {@code false} otherwise. - */ - private boolean matchOis(long[] providerOis, - RoamingConsortiumElement roamingConsortiumElement, - RoamingConsortium roamingConsortiumFromAp, - boolean matchAll) { - - - // ANQP Roaming Consortium OI matching. - if (ANQPMatcher.matchRoamingConsortium(roamingConsortiumElement, providerOis, matchAll)) { - if (mVerboseLoggingEnabled) { - Log.e(TAG, "ANQP RCOI match " + roamingConsortiumElement); - } - return true; - } - - // AP Roaming Consortium OI matching. - long[] apRoamingConsortiums = roamingConsortiumFromAp.getRoamingConsortiums(); - if (apRoamingConsortiums == null || providerOis == null) { - return false; - } - // Roaming Consortium OI information element matching. - for (long apOi: apRoamingConsortiums) { - boolean matched = false; - for (long providerOi: providerOis) { - if (apOi == providerOi) { - if (mVerboseLoggingEnabled) { - Log.e(TAG, "AP RCOI match: " + apOi); - } - if (!matchAll) { - return true; - } else { - matched = true; - break; - } - } - } - if (matchAll && !matched) { - return false; - } - } - return matchAll; - } - - /** - * Perform a provider match based on the given ANQP elements for FQDN and RCOI - * - * @param anqpElements List of ANQP elements - * @param roamingConsortiumFromAp Roaming Consortium information element from the AP - * @param matchingSIMImsi Installed SIM IMSI that matches the SIM credential ANQP element - * @return {@link PasspointMatch} - */ - private PasspointMatch matchFqdnAndRcoi(Map<ANQPElementType, ANQPElement> anqpElements, - RoamingConsortium roamingConsortiumFromAp, String matchingSIMImsi) { - // Domain name matching. - if (ANQPMatcher.matchDomainName( - (DomainNameElement) anqpElements.get(ANQPElementType.ANQPDomName), - mConfig.getHomeSp().getFqdn(), mImsiParameter, matchingSIMImsi)) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Domain name " + mConfig.getHomeSp().getFqdn() - + " match: HomeProvider"); - } - return PasspointMatch.HomeProvider; - } - - // Other Home Partners matching. - if (mConfig.getHomeSp().getOtherHomePartners() != null) { - for (String otherHomePartner : mConfig.getHomeSp().getOtherHomePartners()) { - if (ANQPMatcher.matchDomainName( - (DomainNameElement) anqpElements.get(ANQPElementType.ANQPDomName), - otherHomePartner, null, null)) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Other Home Partner " + otherHomePartner - + " match: HomeProvider"); - } - return PasspointMatch.HomeProvider; - } - } - } - - // HomeOI matching - if (mConfig.getHomeSp().getMatchAllOis() != null) { - // Ensure that every HomeOI whose corresponding HomeOIRequired value is true shall match - // an OI in the Roaming Consortium advertised by the hotspot operator. - if (matchOis(mConfig.getHomeSp().getMatchAllOis(), (RoamingConsortiumElement) - anqpElements.get(ANQPElementType.ANQPRoamingConsortium), - roamingConsortiumFromAp, true)) { - if (mVerboseLoggingEnabled) { - Log.e(TAG, "All HomeOI RCOI match: HomeProvider"); - } - return PasspointMatch.HomeProvider; - } - } else if (mConfig.getHomeSp().getMatchAnyOis() != null) { - // Ensure that any HomeOI whose corresponding HomeOIRequired value is false shall match - // an OI in the Roaming Consortium advertised by the hotspot operator. - if (matchOis(mConfig.getHomeSp().getMatchAnyOis(), (RoamingConsortiumElement) - anqpElements.get(ANQPElementType.ANQPRoamingConsortium), - roamingConsortiumFromAp, false)) { - if (mVerboseLoggingEnabled) { - Log.e(TAG, "Any HomeOI RCOI match: HomeProvider"); - } - return PasspointMatch.HomeProvider; - } - } - - // Roaming Consortium OI matching. - if (matchOis(mConfig.getHomeSp().getRoamingConsortiumOis(), (RoamingConsortiumElement) - anqpElements.get(ANQPElementType.ANQPRoamingConsortium), - roamingConsortiumFromAp, false)) { - if (mVerboseLoggingEnabled) { - Log.e(TAG, "ANQP RCOI match: RoamingProvider"); - } - return PasspointMatch.RoamingProvider; - } - if (mVerboseLoggingEnabled) { - Log.e(TAG, "No domain name or RCOI match"); - } - return PasspointMatch.None; - } - - /** - * Fill in WifiEnterpriseConfig with information from an user credential. - * - * @param config Instance of {@link WifiEnterpriseConfig} - * @param credential Instance of {@link UserCredential} - */ - private void buildEnterpriseConfigForUserCredential(WifiEnterpriseConfig config, - Credential.UserCredential credential) { - String password; - try { - byte[] pwOctets = Base64.decode(credential.getPassword(), Base64.DEFAULT); - password = new String(pwOctets, StandardCharsets.UTF_8); - } catch (IllegalArgumentException e) { - Log.w(TAG, "Failed to decode password"); - password = credential.getPassword(); - } - config.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); - config.setIdentity(credential.getUsername()); - config.setPassword(password); - if (!ArrayUtils.isEmpty(mCaCertificateAliases)) { - config.setCaCertificateAliases(mCaCertificateAliases.toArray(new String[0])); - } else { - config.setCaPath(SYSTEM_CA_STORE_PATH); - } - int phase2Method = WifiEnterpriseConfig.Phase2.NONE; - switch (credential.getNonEapInnerMethod()) { - case Credential.UserCredential.AUTH_METHOD_PAP: - phase2Method = WifiEnterpriseConfig.Phase2.PAP; - break; - case Credential.UserCredential.AUTH_METHOD_MSCHAP: - phase2Method = WifiEnterpriseConfig.Phase2.MSCHAP; - break; - case Credential.UserCredential.AUTH_METHOD_MSCHAPV2: - phase2Method = WifiEnterpriseConfig.Phase2.MSCHAPV2; - break; - default: - // Should never happen since this is already validated when the provider is - // added. - Log.wtf(TAG, "Unsupported Auth: " + credential.getNonEapInnerMethod()); - break; - } - config.setPhase2Method(phase2Method); - } - - /** - * Fill in WifiEnterpriseConfig with information from a certificate credential. - * - * @param config Instance of {@link WifiEnterpriseConfig} - */ - private void buildEnterpriseConfigForCertCredential(WifiEnterpriseConfig config) { - config.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - config.setClientCertificateAlias(mClientPrivateKeyAndCertificateAlias); - if (!ArrayUtils.isEmpty(mCaCertificateAliases)) { - config.setCaCertificateAliases(mCaCertificateAliases.toArray(new String[0])); - } else { - config.setCaPath(SYSTEM_CA_STORE_PATH); - } - } - - /** - * Fill in WifiEnterpriseConfig with information from a SIM credential. - * - * @param config Instance of {@link WifiEnterpriseConfig} - * @param credential Instance of {@link SimCredential} - */ - private void buildEnterpriseConfigForSimCredential(WifiEnterpriseConfig config, - Credential.SimCredential credential) { - int eapMethod = WifiEnterpriseConfig.Eap.NONE; - switch(credential.getEapType()) { - case EAPConstants.EAP_SIM: - eapMethod = WifiEnterpriseConfig.Eap.SIM; - break; - case EAPConstants.EAP_AKA: - eapMethod = WifiEnterpriseConfig.Eap.AKA; - break; - case EAPConstants.EAP_AKA_PRIME: - eapMethod = WifiEnterpriseConfig.Eap.AKA_PRIME; - break; - default: - // Should never happen since this is already validated when the provider is - // added. - Log.wtf(TAG, "Unsupported EAP Method: " + credential.getEapType()); - break; - } - config.setEapMethod(eapMethod); - config.setPlmn(credential.getImsi()); - } - - private static void setAnonymousIdentityToNaiRealm(WifiEnterpriseConfig config, String realm) { - /** - * Set WPA supplicant's anonymous identity field to a string containing the NAI realm, so - * that this value will be sent to the EAP server as part of the EAP-Response/ Identity - * packet. WPA supplicant will reset this field after using it for the EAP-Response/Identity - * packet, and revert to using the (real) identity field for subsequent transactions that - * request an identity (e.g. in EAP-TTLS). - * - * This NAI realm value (the portion of the identity after the '@') is used to tell the - * AAA server which AAA/H to forward packets to. The hardcoded username, "anonymous", is a - * placeholder that is not used--it is set to this value by convention. See Section 5.1 of - * RFC3748 for more details. - * - * NOTE: we do not set this value for EAP-SIM/AKA/AKA', since the EAP server expects the - * EAP-Response/Identity packet to contain an actual, IMSI-based identity, in order to - * identify the device. - */ - config.setAnonymousIdentity("anonymous@" + realm); - } - - /** - * Helper function for creating a - * {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} from the given - * {@link WifiEnterpriseConfig} - * - * @param config The enterprise configuration containing the credential - * @return {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} - */ - private static Credential.UserCredential buildUserCredentialFromEnterpriseConfig( - WifiEnterpriseConfig config) { - Credential.UserCredential userCredential = new Credential.UserCredential(); - userCredential.setEapType(EAPConstants.EAP_TTLS); - - if (TextUtils.isEmpty(config.getIdentity())) { - Log.e(TAG, "Missing username for user credential"); - return null; - } - userCredential.setUsername(config.getIdentity()); - - if (TextUtils.isEmpty(config.getPassword())) { - Log.e(TAG, "Missing password for user credential"); - return null; - } - String encodedPassword = - new String(Base64.encode(config.getPassword().getBytes(StandardCharsets.UTF_8), - Base64.DEFAULT), StandardCharsets.UTF_8); - userCredential.setPassword(encodedPassword); - - switch(config.getPhase2Method()) { - case WifiEnterpriseConfig.Phase2.PAP: - userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_PAP); - break; - case WifiEnterpriseConfig.Phase2.MSCHAP: - userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP); - break; - case WifiEnterpriseConfig.Phase2.MSCHAPV2: - userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); - break; - default: - Log.e(TAG, "Unsupported phase2 method for TTLS: " + config.getPhase2Method()); - return null; - } - return userCredential; - } - - /** - * Helper function for creating a - * {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} from the given - * {@link WifiEnterpriseConfig} - * - * @param eapType The EAP type of the SIM credential - * @param config The enterprise configuration containing the credential - * @return {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} - */ - private static Credential.SimCredential buildSimCredentialFromEnterpriseConfig( - int eapType, WifiEnterpriseConfig config) { - Credential.SimCredential simCredential = new Credential.SimCredential(); - if (TextUtils.isEmpty(config.getPlmn())) { - Log.e(TAG, "Missing IMSI for SIM credential"); - return null; - } - simCredential.setImsi(config.getPlmn()); - simCredential.setEapType(eapType); - return simCredential; - } - - /** - * Enable verbose logging - * @param verbose more than 0 enables verbose logging - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = (verbose > 0) ? true : false; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java deleted file mode 100644 index ad8480ae4..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java +++ /dev/null @@ -1,1198 +0,0 @@ -/* - * Copyright 2017 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.server.wifi.hotspot2; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.net.Network; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.ProvisioningCallback; -import android.net.wifi.hotspot2.omadm.PpsMoParser; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.RemoteException; -import android.os.UserHandle; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.WifiMetrics; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; -import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement; -import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; -import com.android.server.wifi.hotspot2.soap.ExchangeCompleteMessage; -import com.android.server.wifi.hotspot2.soap.PostDevDataMessage; -import com.android.server.wifi.hotspot2.soap.PostDevDataResponse; -import com.android.server.wifi.hotspot2.soap.RedirectListener; -import com.android.server.wifi.hotspot2.soap.SppConstants; -import com.android.server.wifi.hotspot2.soap.SppResponseMessage; -import com.android.server.wifi.hotspot2.soap.UpdateResponseMessage; -import com.android.server.wifi.hotspot2.soap.command.BrowserUri; -import com.android.server.wifi.hotspot2.soap.command.PpsMoData; -import com.android.server.wifi.hotspot2.soap.command.SppCommand; -import com.android.server.wifi.util.Environment; - -import java.net.MalformedURLException; -import java.net.URL; -import java.security.cert.X509Certificate; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Provides methods to carry out provisioning flow - */ -public class PasspointProvisioner { - private static final String TAG = "PasspointProvisioner"; - - // Indicates callback type for caller initiating provisioning - private static final int PROVISIONING_STATUS = 0; - private static final int PROVISIONING_FAILURE = 1; - - // TLS version to be used for HTTPS connection with OSU server - private static final String TLS_VERSION = "TLSv1"; - - private final Context mContext; - private final ProvisioningStateMachine mProvisioningStateMachine; - private final OsuNetworkCallbacks mOsuNetworkCallbacks; - private final OsuNetworkConnection mOsuNetworkConnection; - private final OsuServerConnection mOsuServerConnection; - private final WfaKeyStore mWfaKeyStore; - private final PasspointObjectFactory mObjectFactory; - private final SystemInfo mSystemInfo; - private int mCurrentSessionId = 0; - private int mCallingUid; - private boolean mVerboseLoggingEnabled = false; - private WifiManager mWifiManager; - private PasspointManager mPasspointManager; - private Looper mLooper; - private final WifiMetrics mWifiMetrics; - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public PasspointProvisioner(Context context, WifiNative wifiNative, - PasspointObjectFactory objectFactory, PasspointManager passpointManager, - WifiMetrics wifiMetrics) { - mContext = context; - mOsuNetworkConnection = objectFactory.makeOsuNetworkConnection(context); - mProvisioningStateMachine = new ProvisioningStateMachine(); - mOsuNetworkCallbacks = new OsuNetworkCallbacks(); - mOsuServerConnection = objectFactory.makeOsuServerConnection(); - mWfaKeyStore = objectFactory.makeWfaKeyStore(); - mSystemInfo = objectFactory.getSystemInfo(context, wifiNative); - mObjectFactory = objectFactory; - mPasspointManager = passpointManager; - mWifiMetrics = wifiMetrics; - } - - /** - * Sets up for provisioning - * - * @param looper Looper on which the Provisioning state machine will run - */ - public void init(Looper looper) { - mLooper = looper; - mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - mProvisioningStateMachine.start(new Handler(mLooper)); - mOsuNetworkConnection.init(mProvisioningStateMachine.getHandler()); - // Offload the heavy load job to another thread - mProvisioningStateMachine.getHandler().post(() -> { - mWfaKeyStore.load(); - mOsuServerConnection.init(mObjectFactory.getSSLContext(TLS_VERSION), - mObjectFactory.getTrustManagerFactory(mWfaKeyStore.get())); - }); - } - - /** - * Enable verbose logging to help debug failures - * - * @param level integer indicating verbose logging enabled if > 0 - */ - public void enableVerboseLogging(int level) { - mVerboseLoggingEnabled = (level > 0) ? true : false; - mOsuNetworkConnection.enableVerboseLogging(level); - mOsuServerConnection.enableVerboseLogging(level); - } - - /** - * Start provisioning flow with a given provider. - * - * @param callingUid calling uid. - * @param provider {@link OsuProvider} to provision with. - * @param callback {@link IProvisioningCallback} to provide provisioning status. - * @return boolean value, true if provisioning was started, false otherwise. - * - * Implements HS2.0 provisioning flow with a given HS2.0 provider. - */ - public boolean startSubscriptionProvisioning(int callingUid, OsuProvider provider, - IProvisioningCallback callback) { - mCallingUid = callingUid; - - Log.v(TAG, "Provisioning started with " + provider.toString()); - - mProvisioningStateMachine.getHandler().post(() -> { - mProvisioningStateMachine.startProvisioning(provider, callback); - }); - - return true; - } - - /** - * Handles the provisioning flow state transitions - */ - class ProvisioningStateMachine { - private static final String TAG = "PasspointProvisioningStateMachine"; - - static final int STATE_INIT = 1; - static final int STATE_AP_CONNECTING = 2; - static final int STATE_OSU_SERVER_CONNECTING = 3; - static final int STATE_WAITING_FOR_FIRST_SOAP_RESPONSE = 4; - static final int STATE_WAITING_FOR_REDIRECT_RESPONSE = 5; - static final int STATE_WAITING_FOR_SECOND_SOAP_RESPONSE = 6; - static final int STATE_WAITING_FOR_THIRD_SOAP_RESPONSE = 7; - static final int STATE_WAITING_FOR_TRUST_ROOT_CERTS = 8; - - private OsuProvider mOsuProvider; - private IProvisioningCallback mProvisioningCallback; - private int mState = STATE_INIT; - private Handler mHandler; - private URL mServerUrl; - private Network mNetwork; - private String mSessionId; - private String mWebUrl; - private PasspointConfiguration mPasspointConfiguration; - private RedirectListener mRedirectListener; - private HandlerThread mRedirectHandlerThread; - private Handler mRedirectStartStopHandler; - - /** - * Initializes and starts the state machine with a handler to handle incoming events - */ - public void start(Handler handler) { - mHandler = handler; - if (mRedirectHandlerThread == null) { - mRedirectHandlerThread = new HandlerThread("RedirectListenerHandler"); - mRedirectHandlerThread.start(); - mRedirectStartStopHandler = new Handler(mRedirectHandlerThread.getLooper()); - } - } - - /** - * Returns the handler on which a runnable can be posted - * - * @return Handler State Machine's handler - */ - public Handler getHandler() { - return mHandler; - } - - /** - * Start Provisioning with the Osuprovider and invoke callbacks - * - * @param provider OsuProvider to provision with - * @param callback IProvisioningCallback to invoke callbacks on - * Note: Called on main thread (WifiService thread). - */ - public void startProvisioning(OsuProvider provider, IProvisioningCallback callback) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "startProvisioning received in state=" + mState); - } - - if (mState != STATE_INIT) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "State Machine needs to be reset before starting provisioning"); - } - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - } - mProvisioningCallback = callback; - mRedirectListener = RedirectListener.createInstance(mLooper); - - if (mRedirectListener == null) { - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER); - return; - } - - if (!mOsuServerConnection.canValidateServer()) { - Log.w(TAG, "Provisioning is not possible"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE); - return; - } - URL serverUrl; - try { - serverUrl = new URL(provider.getServerUri().toString()); - } catch (MalformedURLException e) { - Log.e(TAG, "Invalid Server URL"); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SERVER_URL_INVALID); - return; - } - mServerUrl = serverUrl; - mOsuProvider = provider; - if (mOsuProvider.getOsuSsid() == null) { - // Find a best matching OsuProvider that has an OSU SSID from current scanResults - List<ScanResult> scanResults = mWifiManager.getScanResults(); - mOsuProvider = getBestMatchingOsuProvider(scanResults, mOsuProvider); - if (mOsuProvider == null) { - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_OSU_PROVIDER_NOT_FOUND); - return; - } - } - - // Register for network and wifi state events during provisioning flow - mOsuNetworkConnection.setEventCallback(mOsuNetworkCallbacks); - - // Register for OSU server callbacks - mOsuServerConnection.setEventCallback(new OsuServerCallbacks(++mCurrentSessionId)); - - if (!mOsuNetworkConnection.connect(mOsuProvider.getOsuSsid(), - mOsuProvider.getNetworkAccessIdentifier(), mOsuProvider.getFriendlyName())) { - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION); - return; - } - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_AP_CONNECTING); - changeState(STATE_AP_CONNECTING); - } - - /** - * Handles Wifi Disable event - * - * Note: Called on main thread (WifiService thread). - */ - public void handleWifiDisabled() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Wifi Disabled in state=" + mState); - } - if (mState == STATE_INIT) { - Log.w(TAG, "Wifi Disable unhandled in state=" + mState); - return; - } - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION); - } - - /** - * Handles server connection status - * - * @param sessionId indicating current session ID - * @param succeeded boolean indicating success/failure of server connection - * Note: Called on main thread (WifiService thread). - */ - public void handleServerConnectionStatus(int sessionId, boolean succeeded) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Server Connection status received in " + mState); - } - if (sessionId != mCurrentSessionId) { - Log.w(TAG, "Expected server connection failure callback for currentSessionId=" - + mCurrentSessionId); - return; - } - if (mState != STATE_OSU_SERVER_CONNECTING) { - Log.wtf(TAG, "Server Validation Failure unhandled in mState=" + mState); - return; - } - if (!succeeded) { - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION); - return; - } - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_SERVER_CONNECTED); - mProvisioningStateMachine.getHandler().post(() -> initSoapExchange()); - } - - /** - * Handles server validation failure - * - * @param sessionId indicating current session ID - * Note: Called on main thread (WifiService thread). - */ - public void handleServerValidationFailure(int sessionId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Server Validation failure received in " + mState); - } - if (sessionId != mCurrentSessionId) { - Log.w(TAG, "Expected server validation callback for currentSessionId=" - + mCurrentSessionId); - return; - } - if (mState != STATE_OSU_SERVER_CONNECTING) { - Log.wtf(TAG, "Server Validation Failure unhandled in mState=" + mState); - return; - } - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION); - } - - /** - * Handles status of server validation success - * - * @param sessionId indicating current session ID - * Note: Called on main thread (WifiService thread). - */ - public void handleServerValidationSuccess(int sessionId) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Server Validation Success received in " + mState); - } - if (sessionId != mCurrentSessionId) { - Log.w(TAG, "Expected server validation callback for currentSessionId=" - + mCurrentSessionId); - return; - } - if (mState != STATE_OSU_SERVER_CONNECTING) { - Log.wtf(TAG, "Server validation success event unhandled in state=" + mState); - return; - } - if (!mOsuServerConnection.validateProvider( - mOsuProvider.getFriendlyNameList())) { - Log.e(TAG, - "OSU Server certificate does not have the one matched with the selected " - + "Service Name: " - + mOsuProvider.getFriendlyName()); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION); - return; - } - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_SERVER_VALIDATED); - } - - /** - * Handles next step once receiving a HTTP redirect response. - * - * Note: Called on main thread (WifiService thread). - */ - public void handleRedirectResponse() { - if (mState != STATE_WAITING_FOR_REDIRECT_RESPONSE) { - Log.e(TAG, "Received redirect request in wrong state=" + mState); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - return; - } - - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_REDIRECT_RESPONSE_RECEIVED); - mRedirectListener.stopServer(mRedirectStartStopHandler); - secondSoapExchange(); - } - - /** - * Handles next step when timeout occurs because {@link RedirectListener} doesn't - * receive a HTTP redirect response. - * - * Note: Called on main thread (WifiService thread). - */ - public void handleTimeOutForRedirectResponse() { - Log.e(TAG, "Timed out for HTTP redirect response"); - - if (mState != STATE_WAITING_FOR_REDIRECT_RESPONSE) { - Log.e(TAG, "Received timeout error for HTTP redirect response in wrong state=" - + mState); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - return; - } - mRedirectListener.stopServer(mRedirectStartStopHandler); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER); - } - - /** - * Connected event received - * - * @param network Network object for this connection - * Note: Called on main thread (WifiService thread). - */ - public void handleConnectedEvent(Network network) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Connected event received in state=" + mState); - } - if (mState != STATE_AP_CONNECTING) { - // Not waiting for a connection - Log.wtf(TAG, "Connection event unhandled in state=" + mState); - return; - } - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_AP_CONNECTED); - initiateServerConnection(network); - } - - /** - * Handles SOAP message response sent by server - * - * @param sessionId indicating current session ID - * @param responseMessage SOAP SPP response, or {@code null} in any failure. - * Note: Called on main thread (WifiService thread). - */ - public void handleSoapMessageResponse(int sessionId, - @Nullable SppResponseMessage responseMessage) { - if (sessionId != mCurrentSessionId) { - Log.w(TAG, "Expected soapMessageResponse callback for currentSessionId=" - + mCurrentSessionId); - return; - } - - if (responseMessage == null) { - Log.e(TAG, "failed to send the sppPostDevData message"); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE); - return; - } - - if (mState == STATE_WAITING_FOR_FIRST_SOAP_RESPONSE) { - if (responseMessage.getMessageType() - != SppResponseMessage.MessageType.POST_DEV_DATA_RESPONSE) { - Log.e(TAG, "Expected a PostDevDataResponse, but got " - + responseMessage.getMessageType()); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE); - return; - } - - PostDevDataResponse devDataResponse = (PostDevDataResponse) responseMessage; - mSessionId = devDataResponse.getSessionID(); - if (devDataResponse.getSppCommand().getExecCommandId() - != SppCommand.ExecCommandId.BROWSER) { - Log.e(TAG, "Expected a launchBrowser command, but got " - + devDataResponse.getSppCommand().getExecCommandId()); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_UNEXPECTED_COMMAND_TYPE); - return; - } - - Log.d(TAG, "Exec: " + devDataResponse.getSppCommand().getExecCommandId() + ", for '" - + devDataResponse.getSppCommand().getCommandData() + "'"); - - mWebUrl = ((BrowserUri) devDataResponse.getSppCommand().getCommandData()).getUri(); - if (mWebUrl == null) { - Log.e(TAG, "No Web-Url"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU); - return; - } - - if (!mWebUrl.toLowerCase(Locale.US).contains(mSessionId.toLowerCase(Locale.US))) { - Log.e(TAG, "Bad or Missing session ID in webUrl"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU); - return; - } - launchOsuWebView(); - } else if (mState == STATE_WAITING_FOR_SECOND_SOAP_RESPONSE) { - if (responseMessage.getMessageType() - != SppResponseMessage.MessageType.POST_DEV_DATA_RESPONSE) { - Log.e(TAG, "Expected a PostDevDataResponse, but got " - + responseMessage.getMessageType()); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE); - return; - } - - PostDevDataResponse devDataResponse = (PostDevDataResponse) responseMessage; - if (devDataResponse.getSppCommand() == null - || devDataResponse.getSppCommand().getSppCommandId() - != SppCommand.CommandId.ADD_MO) { - Log.e(TAG, "Expected a ADD_MO command, but got " + ( - (devDataResponse.getSppCommand() == null) ? "null" - : devDataResponse.getSppCommand().getSppCommandId())); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_UNEXPECTED_COMMAND_TYPE); - return; - } - - mPasspointConfiguration = buildPasspointConfiguration( - (PpsMoData) devDataResponse.getSppCommand().getCommandData()); - thirdSoapExchange(mPasspointConfiguration == null); - } else if (mState == STATE_WAITING_FOR_THIRD_SOAP_RESPONSE) { - if (responseMessage.getMessageType() - != SppResponseMessage.MessageType.EXCHANGE_COMPLETE) { - Log.e(TAG, "Expected a ExchangeCompleteMessage, but got " - + responseMessage.getMessageType()); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE); - return; - } - - ExchangeCompleteMessage exchangeCompleteMessage = - (ExchangeCompleteMessage) responseMessage; - if (exchangeCompleteMessage.getStatus() - != SppConstants.SppStatus.EXCHANGE_COMPLETE) { - Log.e(TAG, "Expected a ExchangeCompleteMessage Status, but got " - + exchangeCompleteMessage.getStatus()); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS); - return; - } - - if (exchangeCompleteMessage.getError() != SppConstants.INVALID_SPP_CONSTANT) { - Log.e(TAG, - "In the SppExchangeComplete, got error " - + exchangeCompleteMessage.getError()); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - return; - } - if (mPasspointConfiguration == null) { - Log.e(TAG, "No PPS MO to use for retrieving TrustCerts"); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_NO_PPS_MO); - return; - } - retrieveTrustRootCerts(mPasspointConfiguration); - } else { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Received an unexpected SOAP message in state=" + mState); - } - } - } - - /** - * Installs the trust root CA certificates for AAA, Remediation and Policy Server - * - * @param sessionId indicating current session ID - * @param trustRootCertificates trust root CA certificates to be installed. - */ - public void installTrustRootCertificates(int sessionId, - @NonNull Map<Integer, List<X509Certificate>> trustRootCertificates) { - if (sessionId != mCurrentSessionId) { - Log.w(TAG, "Expected TrustRootCertificates callback for currentSessionId=" - + mCurrentSessionId); - return; - } - if (mState != STATE_WAITING_FOR_TRUST_ROOT_CERTS) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Received an unexpected TrustRootCertificates in state=" + mState); - } - return; - } - - if (trustRootCertificates.isEmpty()) { - Log.e(TAG, "fails to retrieve trust root certificates"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES); - return; - } - - List<X509Certificate> certificates = trustRootCertificates.get( - OsuServerConnection.TRUST_CERT_TYPE_AAA); - if (certificates == null || certificates.isEmpty()) { - Log.e(TAG, "fails to retrieve trust root certificate for AAA server"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE); - return; - } - - // Save the service friendly names from OsuProvider to keep this in the profile. - mPasspointConfiguration.setServiceFriendlyNames(mOsuProvider.getFriendlyNameList()); - - mPasspointConfiguration.getCredential().setCaCertificates( - certificates.toArray(new X509Certificate[0])); - - certificates = trustRootCertificates.get( - OsuServerConnection.TRUST_CERT_TYPE_REMEDIATION); - if (certificates == null || certificates.isEmpty()) { - Log.e(TAG, "fails to retrieve trust root certificate for Remediation"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES); - return; - } - - if (mPasspointConfiguration.getSubscriptionUpdate() != null) { - mPasspointConfiguration.getSubscriptionUpdate().setCaCertificate( - certificates.get(0)); - } - - try { - mWifiManager.addOrUpdatePasspointConfiguration(mPasspointConfiguration); - } catch (IllegalArgumentException e) { - Log.e(TAG, "fails to add a new PasspointConfiguration: " + e); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION); - return; - } - - invokeProvisioningCompleteCallback(); - if (mVerboseLoggingEnabled) { - Log.i(TAG, "Provisioning is complete for " - + mPasspointConfiguration.getHomeSp().getFqdn()); - } - resetStateMachine(); - } - - /** - * Disconnect event received - * - * Note: Called on main thread (WifiService thread). - */ - public void handleDisconnect() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Connection failed in state=" + mState); - } - if (mState == STATE_INIT) { - Log.w(TAG, "Disconnect event unhandled in state=" + mState); - return; - } - mNetwork = null; - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION); - } - - /** - * Establishes TLS session to the server(OSU Server, Remediation or Policy Server). - * - * @param network current {@link Network} associated with the target AP. - */ - private void initiateServerConnection(Network network) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Initiating server connection in state=" + mState); - } - - if (!mOsuServerConnection.connect(mServerUrl, network)) { - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION); - return; - } - mNetwork = network; - changeState(STATE_OSU_SERVER_CONNECTING); - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_SERVER_CONNECTING); - } - - private void invokeProvisioningCallback(int callbackType, int status) { - if (mProvisioningCallback == null) { - Log.e(TAG, "Provisioning callback " + callbackType + " with status " + status - + " not invoked"); - return; - } - try { - if (callbackType == PROVISIONING_STATUS) { - mProvisioningCallback.onProvisioningStatus(status); - } else { - mProvisioningCallback.onProvisioningFailure(status); - } - } catch (RemoteException e) { - Log.e(TAG, "Remote Exception while posting callback type=" + callbackType - + " status=" + status); - } - } - - private void invokeProvisioningCompleteCallback() { - mWifiMetrics.incrementPasspointProvisionSuccess(); - if (mProvisioningCallback == null) { - Log.e(TAG, "No provisioning complete callback registered"); - return; - } - try { - mProvisioningCallback.onProvisioningComplete(); - } catch (RemoteException e) { - Log.e(TAG, "Remote Exception while posting provisioning complete"); - } - } - - /** - * Initiates the SOAP message exchange with sending the sppPostDevData message. - */ - private void initSoapExchange() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Initiates soap message exchange in state =" + mState); - } - - if (mState != STATE_OSU_SERVER_CONNECTING) { - Log.e(TAG, "Initiates soap message exchange in wrong state=" + mState); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - return; - } - - // Redirect uri used for signal of completion for registration process. - final URL redirectUri = mRedirectListener.getServerUrl(); - - // Sending the first sppPostDevDataRequest message. - if (mOsuServerConnection.exchangeSoapMessage( - PostDevDataMessage.serializeToSoapEnvelope(mContext, mSystemInfo, - redirectUri.toString(), - SppConstants.SppReason.SUBSCRIPTION_REGISTRATION, null))) { - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_INIT_SOAP_EXCHANGE); - // Move to initiate soap exchange - changeState(STATE_WAITING_FOR_FIRST_SOAP_RESPONSE); - } else { - Log.e(TAG, "HttpsConnection is not established for soap message exchange"); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE); - return; - } - } - - /** - * Launches OsuLogin Application for users to register a new subscription. - */ - private void launchOsuWebView() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "launch Osu webview in state =" + mState); - } - - if (mState != STATE_WAITING_FOR_FIRST_SOAP_RESPONSE) { - Log.e(TAG, "launch Osu webview in wrong state =" + mState); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - return; - } - - // Start the redirect server to listen the HTTP redirect response from server - // as completion of user input. - if (!mRedirectListener.startServer(new RedirectListener.RedirectCallback() { - /** Called on different thread (RedirectListener thread). */ - @Override - public void onRedirectReceived() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Received HTTP redirect response"); - } - mProvisioningStateMachine.getHandler().post(() -> handleRedirectResponse()); - } - - /** Called on main thread (WifiService thread). */ - @Override - public void onRedirectTimedOut() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Timed out to receive a HTTP redirect response"); - } - mProvisioningStateMachine.handleTimeOutForRedirectResponse(); - } - }, mRedirectStartStopHandler)) { - Log.e(TAG, "fails to start redirect listener"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER); - return; - } - - Intent intent = new Intent(WifiManager.ACTION_PASSPOINT_LAUNCH_OSU_VIEW); - intent.putExtra(WifiManager.EXTRA_OSU_NETWORK, mNetwork); - intent.putExtra(WifiManager.EXTRA_URL, mWebUrl); - intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); - - List<ResolveInfo> resolveInfos = mContext.getPackageManager() - .queryIntentActivities( - intent, - PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_SYSTEM_ONLY); - if (resolveInfos == null || resolveInfos.isEmpty()) { - Log.e(TAG, "can't resolve the activity for the intent"); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_NO_OSU_ACTIVITY_FOUND); - return; - } - - if (resolveInfos.size() > 1) { - if (mVerboseLoggingEnabled) { - Log.i(TAG, "Multiple OsuLogin apps found: " - + resolveInfos.stream() - .map(info -> info.activityInfo.applicationInfo.packageName) - .collect(Collectors.joining(", "))); - } - - // if multiple apps are found, filter out the default implementation supplied - // in the Wifi apex and let other implementations override. - resolveInfos.removeIf(info -> - Environment.isAppInWifiApex(info.activityInfo.applicationInfo)); - } - // forcefully resolve to the first one - String packageName = resolveInfos.get(0).activityInfo.applicationInfo.packageName; - intent.setPackage(packageName); - if (mVerboseLoggingEnabled) { - Log.i(TAG, "Opening OsuLogin app: " + packageName); - } - mContext.startActivityAsUser(intent, UserHandle.CURRENT); - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE); - changeState(STATE_WAITING_FOR_REDIRECT_RESPONSE); - } - - /** - * Initiates the second SOAP message exchange with sending the sppPostDevData message. - */ - private void secondSoapExchange() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Initiates the second soap message exchange in state =" + mState); - } - - if (mState != STATE_WAITING_FOR_REDIRECT_RESPONSE) { - Log.e(TAG, "Initiates the second soap message exchange in wrong state=" + mState); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - return; - } - - // Sending the second sppPostDevDataRequest message. - if (mOsuServerConnection.exchangeSoapMessage( - PostDevDataMessage.serializeToSoapEnvelope(mContext, mSystemInfo, - mRedirectListener.getServerUrl().toString(), - SppConstants.SppReason.USER_INPUT_COMPLETED, mSessionId))) { - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_SECOND_SOAP_EXCHANGE); - changeState(STATE_WAITING_FOR_SECOND_SOAP_RESPONSE); - } else { - Log.e(TAG, "HttpsConnection is not established for soap message exchange"); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE); - return; - } - } - - /** - * Initiates the third SOAP message exchange with sending the sppUpdateResponse message. - */ - private void thirdSoapExchange(boolean isError) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Initiates the third soap message exchange in state =" + mState); - } - - if (mState != STATE_WAITING_FOR_SECOND_SOAP_RESPONSE) { - Log.e(TAG, "Initiates the third soap message exchange in wrong state=" + mState); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - return; - } - - // Sending the sppUpdateResponse message. - if (mOsuServerConnection.exchangeSoapMessage( - UpdateResponseMessage.serializeToSoapEnvelope(mSessionId, isError))) { - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_THIRD_SOAP_EXCHANGE); - changeState(STATE_WAITING_FOR_THIRD_SOAP_RESPONSE); - } else { - Log.e(TAG, "HttpsConnection is not established for soap message exchange"); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE); - return; - } - } - - /** - * Builds {@link PasspointConfiguration} object from PPS(PerProviderSubscription) - * MO(Management Object). - */ - private PasspointConfiguration buildPasspointConfiguration(@NonNull PpsMoData moData) { - String moTree = moData.getPpsMoTree(); - - PasspointConfiguration passpointConfiguration = PpsMoParser.parseMoText(moTree); - if (passpointConfiguration == null) { - Log.e(TAG, "fails to parse the MoTree"); - return null; - } - - if (!passpointConfiguration.validateForR2()) { - Log.e(TAG, "PPS MO received is invalid: " + passpointConfiguration); - return null; - } - - if (mVerboseLoggingEnabled) { - Log.d(TAG, "The parsed PasspointConfiguration: " + passpointConfiguration); - } - - return passpointConfiguration; - } - - /** - * Retrieves Trust Root CA Certificates from server url defined in PPS - * (PerProviderSubscription) MO(Management Object). - */ - private void retrieveTrustRootCerts(@NonNull PasspointConfiguration passpointConfig) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Initiates retrieving trust root certs in state =" + mState); - } - - Map<String, byte[]> trustCertInfo = passpointConfig.getTrustRootCertList(); - if (trustCertInfo == null || trustCertInfo.isEmpty()) { - Log.e(TAG, "no AAATrustRoot Node found"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE); - return; - } - Map<Integer, Map<String, byte[]>> allTrustCerts = new HashMap<>(); - allTrustCerts.put(OsuServerConnection.TRUST_CERT_TYPE_AAA, trustCertInfo); - - // SubscriptionUpdate is a required node. - if (passpointConfig.getSubscriptionUpdate() != null - && passpointConfig.getSubscriptionUpdate().getTrustRootCertUrl() != null) { - trustCertInfo = new HashMap<>(); - trustCertInfo.put( - passpointConfig.getSubscriptionUpdate().getTrustRootCertUrl(), - passpointConfig.getSubscriptionUpdate() - .getTrustRootCertSha256Fingerprint()); - allTrustCerts.put(OsuServerConnection.TRUST_CERT_TYPE_REMEDIATION, trustCertInfo); - } else { - Log.e(TAG, "no TrustRoot Node for remediation server found"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE); - return; - } - - // Policy is an optional node - if (passpointConfig.getPolicy() != null) { - if (passpointConfig.getPolicy().getPolicyUpdate() != null - && passpointConfig.getPolicy().getPolicyUpdate().getTrustRootCertUrl() - != null) { - trustCertInfo = new HashMap<>(); - trustCertInfo.put( - passpointConfig.getPolicy().getPolicyUpdate() - .getTrustRootCertUrl(), - passpointConfig.getPolicy().getPolicyUpdate() - .getTrustRootCertSha256Fingerprint()); - allTrustCerts.put(OsuServerConnection.TRUST_CERT_TYPE_POLICY, trustCertInfo); - } else { - Log.e(TAG, "no TrustRoot Node for policy server found"); - resetStateMachineForFailure( - ProvisioningCallback.OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE); - return; - } - } - - if (mOsuServerConnection.retrieveTrustRootCerts(allTrustCerts)) { - invokeProvisioningCallback(PROVISIONING_STATUS, - ProvisioningCallback.OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS); - changeState(STATE_WAITING_FOR_TRUST_ROOT_CERTS); - } else { - Log.e(TAG, "HttpsConnection is not established for retrieving trust root certs"); - resetStateMachineForFailure(ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION); - return; - } - } - - private void changeState(int nextState) { - if (nextState != mState) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Changing state from " + mState + " -> " + nextState); - } - mState = nextState; - } - } - - private void resetStateMachineForFailure(int failureCode) { - mWifiMetrics.incrementPasspointProvisionFailure(failureCode); - invokeProvisioningCallback(PROVISIONING_FAILURE, failureCode); - resetStateMachine(); - } - - private void resetStateMachine() { - if (mRedirectListener != null) { - mRedirectListener.stopServer(mRedirectStartStopHandler); - } - mOsuNetworkConnection.setEventCallback(null); - mOsuNetworkConnection.disconnectIfNeeded(); - mOsuServerConnection.setEventCallback(null); - mOsuServerConnection.cleanup(); - mPasspointConfiguration = null; - mProvisioningCallback = null; - changeState(STATE_INIT); - } - - /** - * Get a best matching osuProvider from scanResults with provided osuProvider - * - * @param scanResults a list of {@link ScanResult} to find a best osuProvider - * @param osuProvider an instance of {@link OsuProvider} used to match with scanResults - * @return a best matching {@link OsuProvider}, {@code null} when an invalid scanResults are - * provided or no match is found. - */ - private OsuProvider getBestMatchingOsuProvider( - List<ScanResult> scanResults, - OsuProvider osuProvider) { - if (scanResults == null) { - Log.e(TAG, "Attempt to retrieve OSU providers for a null ScanResult"); - return null; - } - - if (osuProvider == null) { - Log.e(TAG, "Attempt to retrieve best OSU provider for a null osuProvider"); - return null; - } - - // Clear the OSU SSID to compare it with other OsuProviders only about service - // provider information. - osuProvider.setOsuSsid(null); - - // Filter non-Passpoint AP out and sort it by descending order of signal strength. - scanResults = scanResults.stream() - .filter((scanResult) -> scanResult.isPasspointNetwork()) - .sorted((sr1, sr2) -> sr2.level - sr1.level) - .collect(Collectors.toList()); - - for (ScanResult scanResult : scanResults) { - // Lookup OSU Providers ANQP element by ANQPNetworkKey. - // It might have same ANQP element with another one which has same ANQP domain id. - Map<Constants.ANQPElementType, ANQPElement> anqpElements = - mPasspointManager.getANQPElements( - scanResult); - HSOsuProvidersElement element = - (HSOsuProvidersElement) anqpElements.get( - Constants.ANQPElementType.HSOSUProviders); - if (element == null) continue; - for (OsuProviderInfo info : element.getProviders()) { - OsuProvider candidate = new OsuProvider( - (WifiSsid) null, info.getFriendlyNames(), - info.getServiceDescription(), info.getServerUri(), - info.getNetworkAccessIdentifier(), info.getMethodList()); - if (candidate.equals(osuProvider)) { - // Found a matching candidate and then set OSU SSID for the OSU provider. - candidate.setOsuSsid(element.getOsuSsid()); - return candidate; - } - } - } - return null; - } - } - - /** - * Callbacks for network and wifi events - * - * Note: Called on main thread (WifiService thread). - */ - class OsuNetworkCallbacks implements OsuNetworkConnection.Callbacks { - - @Override - public void onConnected(Network network) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onConnected to " + network); - } - if (network == null) { - mProvisioningStateMachine.handleDisconnect(); - } else { - mProvisioningStateMachine.handleConnectedEvent(network); - } - } - - @Override - public void onDisconnected() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onDisconnected"); - } - mProvisioningStateMachine.handleDisconnect(); - } - - @Override - public void onTimeOut() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Timed out waiting for connection to OSU AP"); - } - mProvisioningStateMachine.handleDisconnect(); - } - - @Override - public void onWifiEnabled() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onWifiEnabled"); - } - } - - @Override - public void onWifiDisabled() { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onWifiDisabled"); - } - mProvisioningStateMachine.handleWifiDisabled(); - } - } - - /** - * Defines the callbacks expected from OsuServerConnection - * - * Note: Called on main thread (WifiService thread). - */ - public class OsuServerCallbacks { - private final int mSessionId; - - OsuServerCallbacks(int sessionId) { - mSessionId = sessionId; - } - - /** - * Returns the session ID corresponding to this callback - * - * @return int sessionID - */ - public int getSessionId() { - return mSessionId; - } - - /** - * Callback when a TLS connection to the server is failed. - * - * @param sessionId indicating current session ID - * @param succeeded boolean indicating success/failure of server connection - */ - public void onServerConnectionStatus(int sessionId, boolean succeeded) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "OSU Server connection status=" + succeeded + " sessionId=" + sessionId); - } - mProvisioningStateMachine.getHandler().post(() -> - mProvisioningStateMachine.handleServerConnectionStatus(sessionId, succeeded)); - } - - /** - * Provides a server validation status for the session ID - * - * @param sessionId integer indicating current session ID - * @param succeeded boolean indicating success/failure of server validation - */ - public void onServerValidationStatus(int sessionId, boolean succeeded) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "OSU Server Validation status=" + succeeded + " sessionId=" + sessionId); - } - if (succeeded) { - mProvisioningStateMachine.getHandler().post(() -> { - mProvisioningStateMachine.handleServerValidationSuccess(sessionId); - }); - } else { - mProvisioningStateMachine.getHandler().post(() -> { - mProvisioningStateMachine.handleServerValidationFailure(sessionId); - }); - } - } - - /** - * Callback when soap message is received from server. - * - * @param sessionId indicating current session ID - * @param responseMessage SOAP SPP response parsed or {@code null} in any failure - * Note: Called on different thread (OsuServer Thread)! - */ - public void onReceivedSoapMessage(int sessionId, - @Nullable SppResponseMessage responseMessage) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onReceivedSoapMessage with sessionId=" + sessionId); - } - mProvisioningStateMachine.getHandler().post(() -> - mProvisioningStateMachine.handleSoapMessageResponse(sessionId, - responseMessage)); - } - - /** - * Callback when trust root certificates are retrieved from server. - * - * @param sessionId indicating current session ID - * @param trustRootCertificates trust root CA certificates retrieved from server - * Note: Called on different thread (OsuServer Thread)! - */ - public void onReceivedTrustRootCertificates(int sessionId, - @NonNull Map<Integer, List<X509Certificate>> trustRootCertificates) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onReceivedTrustRootCertificates with sessionId=" + sessionId); - } - mProvisioningStateMachine.getHandler().post(() -> - mProvisioningStateMachine.installTrustRootCertificates(sessionId, - trustRootCertificates)); - } - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointXmlUtils.java b/service/java/com/android/server/wifi/hotspot2/PasspointXmlUtils.java deleted file mode 100644 index f50192c65..000000000 --- a/service/java/com/android/server/wifi/hotspot2/PasspointXmlUtils.java +++ /dev/null @@ -1,918 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2; - -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.net.wifi.hotspot2.pps.Policy; -import android.net.wifi.hotspot2.pps.UpdateParameter; - -import com.android.server.wifi.util.XmlUtil; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Utility class for serialize and deserialize Passpoint related configurations to/from XML string. - */ -public class PasspointXmlUtils { - // XML section header tags. - private static final String XML_TAG_SECTION_HEADER_HOMESP = "HomeSP"; - private static final String XML_TAG_SECTION_HEADER_CREDENTIAL = "Credential"; - private static final String XML_TAG_SECTION_HEADER_USER_CREDENTIAL = "UserCredential"; - private static final String XML_TAG_SECTION_HEADER_CERT_CREDENTIAL = "CertCredential"; - private static final String XML_TAG_SECTION_HEADER_SIM_CREDENTIAL = "SimCredential"; - private static final String XML_TAG_SECTION_HEADER_POLICY = "Policy"; - private static final String XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST = - "RoamingPartnerList"; - private static final String XML_TAG_SECTION_HEADER_ROAMING_PARTNER = "RoamingPartner"; - private static final String XML_TAG_SECTION_HEADER_POLICY_UPDATE = "PolicyUpdate"; - private static final String XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE = "SubscriptionUpdate"; - private static final String XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP = - "RequiredProtoPortMap"; - private static final String XML_TAG_SECTION_HEADER_PROTO_PORT = "ProtoPort"; - - // XML value tags. - private static final String XML_TAG_FQDN = "FQDN"; - private static final String XML_TAG_FRIENDLY_NAME = "FriendlyName"; - private static final String XML_TAG_FRIENDLY_NAME_LIST = "FriendlyNameList"; - private static final String XML_TAG_ICON_URL = "IconURL"; - private static final String XML_TAG_HOME_NETWORK_IDS = "HomeNetworkIDs"; - private static final String XML_TAG_MATCH_ALL_OIS = "MatchAllOIs"; - private static final String XML_TAG_MATCH_ANY_OIS = "MatchAnyOIs"; - private static final String XML_TAG_OTHER_HOME_PARTNERS = "OtherHomePartners"; - private static final String XML_TAG_ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs"; - private static final String XML_TAG_CREATION_TIME = "CreationTime"; - private static final String XML_TAG_EXPIRATION_TIME = "ExpirationTime"; - private static final String XML_TAG_REALM = "Realm"; - private static final String XML_TAG_CHECK_AAA_SERVER_CERT_STATUS = "CheckAAAServerCertStatus"; - private static final String XML_TAG_USERNAME = "Username"; - private static final String XML_TAG_PASSWORD = "Password"; - private static final String XML_TAG_MACHINE_MANAGED = "MachineManaged"; - private static final String XML_TAG_SOFT_TOKEN_APP = "SoftTokenApp"; - private static final String XML_TAG_ABLE_TO_SHARE = "AbleToShare"; - private static final String XML_TAG_EAP_TYPE = "EAPType"; - private static final String XML_TAG_NON_EAP_INNER_METHOD = "NonEAPInnerMethod"; - private static final String XML_TAG_CERT_TYPE = "CertType"; - private static final String XML_TAG_CERT_SHA256_FINGERPRINT = "CertSHA256Fingerprint"; - private static final String XML_TAG_IMSI = "IMSI"; - private static final String XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH = "MinHomeDownlinkBandwidth"; - private static final String XML_TAG_MIN_HOME_UPLINK_BANDWIDTH = "MinHomeUplinkBandwidth"; - private static final String XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH = - "MinRoamingDownlinkBandwidth"; - private static final String XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH = - "MinRoamingUplinkBandwidth"; - private static final String XML_TAG_EXCLUDED_SSID_LIST = "ExcludedSSIDList"; - private static final String XML_TAG_PROTO = "Proto"; - private static final String XML_TAG_PORTS = "Ports"; - private static final String XML_TAG_MAXIMUM_BSS_LOAD_VALUE = "MaximumBSSLoadValue"; - private static final String XML_TAG_FQDN_EXACT_MATCH = "FQDNExactMatch"; - private static final String XML_TAG_PRIORITY = "Priority"; - private static final String XML_TAG_COUNTRIES = "Countries"; - private static final String XML_TAG_UPDATE_INTERVAL = "UpdateInterval"; - private static final String XML_TAG_UPDATE_METHOD = "UpdateMethod"; - private static final String XML_TAG_RESTRICTION = "Restriction"; - private static final String XML_TAG_SERVER_URI = "ServerURI"; - private static final String XML_TAG_TRUST_ROOT_CERT_URL = "TrustRootCertURL"; - private static final String XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT = - "TrustRootCertSHA256Fingerprint"; - private static final String XML_TAG_TRUST_ROOT_CERT_LIST = "TrustRootCertList"; - private static final String XML_TAG_UPDATE_IDENTIFIER = "UpdateIdentifier"; - private static final String XML_TAG_CREDENTIAL_PRIORITY = "CredentialPriority"; - private static final String XML_TAG_SUBSCRIPTION_CREATION_TIME = "SubscriptionCreationTime"; - private static final String XML_TAG_SUBSCRIPTION_EXPIRATION_TIME = - "SubscriptionExpirationTime"; - private static final String XML_TAG_SUBSCRIPTION_TYPE = "SubscriptionType"; - private static final String XML_TAG_USAGE_LIMIT_TIME_PERIOD = "UsageLimitTimePeriod"; - private static final String XML_TAG_USAGE_LIMIT_START_TIME = "UsageLimitStartTime"; - private static final String XML_TAG_USAGE_LIMIT_DATA_LIMIT = "UsageLimitDataLimit"; - private static final String XML_TAG_USAGE_LIMIT_TIME_LIMIT = "UsageLimitTimeLimit"; - private static final String XML_TAG_CARRIER_ID = "CarrierId"; - private static final String XML_TAG_IS_AUTO_JOIN = "AutoJoinEnabled"; - private static final String XML_TAG_IS_MAC_RANDOMIZATION_ENABLED = "IsMacRandomizationEnabled"; - private static final String XML_TAG_METERED_OVERRIDE = "MeteredOverride"; - - /** - * Serialize a {@link PasspointConfiguration} to the output stream as a XML block. - * - * @param out The output stream to serialize to - * @param config The configuration to serialize - * @throws XmlPullParserException - * @throws IOException - */ - public static void serializePasspointConfiguration(XmlSerializer out, - PasspointConfiguration config) throws XmlPullParserException, IOException { - XmlUtil.writeNextValue(out, XML_TAG_UPDATE_IDENTIFIER, config.getUpdateIdentifier()); - XmlUtil.writeNextValue(out, XML_TAG_CREDENTIAL_PRIORITY, config.getCredentialPriority()); - XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_LIST, config.getTrustRootCertList()); - XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_CREATION_TIME, - config.getSubscriptionCreationTimeInMillis()); - XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_EXPIRATION_TIME, - config.getSubscriptionExpirationTimeMillis()); - XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_TYPE, config.getSubscriptionType()); - XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_TIME_PERIOD, - config.getUsageLimitUsageTimePeriodInMinutes()); - XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_START_TIME, - config.getUsageLimitStartTimeInMillis()); - XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_DATA_LIMIT, - config.getUsageLimitDataLimit()); - XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_TIME_LIMIT, - config.getUsageLimitTimeLimitInMinutes()); - serializeHomeSp(out, config.getHomeSp()); - serializeCredential(out, config.getCredential()); - serializePolicy(out, config.getPolicy()); - serializeUpdateParameter(out, XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE, - config.getSubscriptionUpdate()); - if (config.getServiceFriendlyNames() != null) { - XmlUtil.writeNextValue(out, XML_TAG_FRIENDLY_NAME_LIST, - config.getServiceFriendlyNames()); - } - XmlUtil.writeNextValue(out, XML_TAG_CARRIER_ID, config.getCarrierId()); - XmlUtil.writeNextValue(out, XML_TAG_IS_AUTO_JOIN, config.isAutojoinEnabled()); - XmlUtil.writeNextValue(out, XML_TAG_IS_MAC_RANDOMIZATION_ENABLED, - config.isMacRandomizationEnabled()); - XmlUtil.writeNextValue(out, XML_TAG_METERED_OVERRIDE, config.getMeteredOverride()); - } - - /** - * Deserialize a {@link PasspointConfiguration} from an input stream containing XML block. - * - * @param in The input stream to read from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link PasspointConfiguration} - * @throws XmlPullParserException - * @throws IOException - */ - public static PasspointConfiguration deserializePasspointConfiguration(XmlPullParser in, - int outerTagDepth) throws XmlPullParserException, IOException { - PasspointConfiguration config = new PasspointConfiguration(); - while (XmlUtil.nextElementWithin(in, outerTagDepth)) { - if (isValueElement(in)) { - // Value elements. - String[] name = new String[1]; - Object value = XmlUtil.readCurrentValue(in, name); - switch (name[0]) { - case XML_TAG_UPDATE_IDENTIFIER: - config.setUpdateIdentifier((int) value); - break; - case XML_TAG_CREDENTIAL_PRIORITY: - config.setCredentialPriority((int) value); - break; - case XML_TAG_TRUST_ROOT_CERT_LIST: - config.setTrustRootCertList((Map<String, byte[]>) value); - break; - case XML_TAG_SUBSCRIPTION_CREATION_TIME: - config.setSubscriptionCreationTimeInMillis((long) value); - break; - case XML_TAG_SUBSCRIPTION_EXPIRATION_TIME: - config.setSubscriptionExpirationTimeInMillis((long) value); - break; - case XML_TAG_SUBSCRIPTION_TYPE: - config.setSubscriptionType((String) value); - break; - case XML_TAG_USAGE_LIMIT_TIME_PERIOD: - config.setUsageLimitUsageTimePeriodInMinutes((long) value); - break; - case XML_TAG_USAGE_LIMIT_START_TIME: - config.setUsageLimitStartTimeInMillis((long) value); - break; - case XML_TAG_USAGE_LIMIT_DATA_LIMIT: - config.setUsageLimitDataLimit((long) value); - break; - case XML_TAG_USAGE_LIMIT_TIME_LIMIT: - config.setUsageLimitTimeLimitInMinutes((long) value); - break; - case XML_TAG_FRIENDLY_NAME_LIST: - config.setServiceFriendlyNames((Map<String, String>) value); - break; - case XML_TAG_CARRIER_ID: - config.setCarrierId((int) value); - break; - case XML_TAG_IS_AUTO_JOIN: - config.setAutojoinEnabled((boolean) value); - break; - case XML_TAG_IS_MAC_RANDOMIZATION_ENABLED: - config.setMacRandomizationEnabled((boolean) value); - break; - case XML_TAG_METERED_OVERRIDE: - config.setMeteredOverride((int) value); - break; - default: - throw new XmlPullParserException("Unknown value under " - + "PasspointConfiguration: " + in.getName()); - } - } else { - // Section elements. - switch (in.getName()) { - case XML_TAG_SECTION_HEADER_HOMESP: - config.setHomeSp(deserializeHomeSP(in, outerTagDepth + 1)); - break; - case XML_TAG_SECTION_HEADER_CREDENTIAL: - config.setCredential(deserializeCredential(in, outerTagDepth + 1)); - break; - case XML_TAG_SECTION_HEADER_POLICY: - config.setPolicy(deserializePolicy(in, outerTagDepth + 1)); - break; - case XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE: - config.setSubscriptionUpdate( - deserializeUpdateParameter(in, outerTagDepth + 1)); - break; - default: - throw new XmlPullParserException("Unknown section under " - + "PasspointConfiguration: " + in.getName()); - } - } - } - return config; - } - - /** - * Serialize a {@link HomeSp} to an output stream as a XML block. - * - * @param out The output stream to serialize data to - * @param homeSp The {@link HomeSp} to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializeHomeSp(XmlSerializer out, HomeSp homeSp) - throws XmlPullParserException, IOException { - if (homeSp == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_HOMESP); - XmlUtil.writeNextValue(out, XML_TAG_FQDN, homeSp.getFqdn()); - XmlUtil.writeNextValue(out, XML_TAG_FRIENDLY_NAME, homeSp.getFriendlyName()); - XmlUtil.writeNextValue(out, XML_TAG_ICON_URL, homeSp.getIconUrl()); - XmlUtil.writeNextValue(out, XML_TAG_HOME_NETWORK_IDS, homeSp.getHomeNetworkIds()); - XmlUtil.writeNextValue(out, XML_TAG_MATCH_ALL_OIS, homeSp.getMatchAllOis()); - XmlUtil.writeNextValue(out, XML_TAG_MATCH_ANY_OIS, homeSp.getMatchAnyOis()); - XmlUtil.writeNextValue(out, XML_TAG_OTHER_HOME_PARTNERS, homeSp.getOtherHomePartners()); - XmlUtil.writeNextValue(out, XML_TAG_ROAMING_CONSORTIUM_OIS, - homeSp.getRoamingConsortiumOis()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_HOMESP); - } - - /** - * Serialize a {@link Credential} to an output stream as a XML block. - * - * @param out The output stream to serialize to - * @param credential The {@link Credential} to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializeCredential(XmlSerializer out, Credential credential) - throws XmlPullParserException, IOException { - if (credential == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_CREDENTIAL); - XmlUtil.writeNextValue(out, XML_TAG_CREATION_TIME, credential.getCreationTimeInMillis()); - XmlUtil.writeNextValue(out, XML_TAG_EXPIRATION_TIME, - credential.getExpirationTimeInMillis()); - XmlUtil.writeNextValue(out, XML_TAG_REALM, credential.getRealm()); - XmlUtil.writeNextValue(out, XML_TAG_CHECK_AAA_SERVER_CERT_STATUS, - credential.getCheckAaaServerCertStatus()); - serializeUserCredential(out, credential.getUserCredential()); - serializeCertCredential(out, credential.getCertCredential()); - serializeSimCredential(out, credential.getSimCredential()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_CREDENTIAL); - } - - /** - * Serialize a {@link Policy} to an output stream as a XML block. - * - * @param out The output stream to serialize to - * @param policy The {@link Policy} to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializePolicy(XmlSerializer out, Policy policy) - throws XmlPullParserException, IOException { - if (policy == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_POLICY); - XmlUtil.writeNextValue(out, XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH, - policy.getMinHomeDownlinkBandwidth()); - XmlUtil.writeNextValue(out, XML_TAG_MIN_HOME_UPLINK_BANDWIDTH, - policy.getMinHomeUplinkBandwidth()); - XmlUtil.writeNextValue(out, XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH, - policy.getMinRoamingDownlinkBandwidth()); - XmlUtil.writeNextValue(out, XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH, - policy.getMinRoamingUplinkBandwidth()); - XmlUtil.writeNextValue(out, XML_TAG_EXCLUDED_SSID_LIST, policy.getExcludedSsidList()); - XmlUtil.writeNextValue(out, XML_TAG_MAXIMUM_BSS_LOAD_VALUE, - policy.getMaximumBssLoadValue()); - serializeProtoPortMap(out, policy.getRequiredProtoPortMap()); - serializeUpdateParameter(out, XML_TAG_SECTION_HEADER_POLICY_UPDATE, - policy.getPolicyUpdate()); - serializePreferredRoamingPartnerList(out, policy.getPreferredRoamingPartnerList()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_POLICY); - } - - /** - * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} to an output - * stream as a XML block. - * - * @param out The output stream to serialize data to - * @param userCredential The UserCredential to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializeUserCredential(XmlSerializer out, - Credential.UserCredential userCredential) throws XmlPullParserException, IOException { - if (userCredential == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_USER_CREDENTIAL); - XmlUtil.writeNextValue(out, XML_TAG_USERNAME, userCredential.getUsername()); - XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, userCredential.getPassword()); - XmlUtil.writeNextValue(out, XML_TAG_MACHINE_MANAGED, userCredential.getMachineManaged()); - XmlUtil.writeNextValue(out, XML_TAG_SOFT_TOKEN_APP, userCredential.getSoftTokenApp()); - XmlUtil.writeNextValue(out, XML_TAG_ABLE_TO_SHARE, userCredential.getAbleToShare()); - XmlUtil.writeNextValue(out, XML_TAG_EAP_TYPE, userCredential.getEapType()); - XmlUtil.writeNextValue(out, XML_TAG_NON_EAP_INNER_METHOD, - userCredential.getNonEapInnerMethod()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_USER_CREDENTIAL); - } - - /** - * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} to an - * output stream as a XML block. - * - * @param out The output stream to serialize data to - * @param certCredential The CertificateCredential to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializeCertCredential(XmlSerializer out, - Credential.CertificateCredential certCredential) - throws XmlPullParserException, IOException { - if (certCredential == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_CERT_CREDENTIAL); - XmlUtil.writeNextValue(out, XML_TAG_CERT_TYPE, certCredential.getCertType()); - XmlUtil.writeNextValue(out, XML_TAG_CERT_SHA256_FINGERPRINT, - certCredential.getCertSha256Fingerprint()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_CERT_CREDENTIAL); - } - - /** - * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} to an - * output stream as a XML block. - * - * @param out The output stream to serialize data to - * @param simCredential The SimCredential to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializeSimCredential(XmlSerializer out, - Credential.SimCredential simCredential) throws XmlPullParserException, IOException { - if (simCredential == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_SIM_CREDENTIAL); - XmlUtil.writeNextValue(out, XML_TAG_IMSI, simCredential.getImsi()); - XmlUtil.writeNextValue(out, XML_TAG_EAP_TYPE, simCredential.getEapType()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_SIM_CREDENTIAL); - } - - /** - * Serialize a preferred roaming partner list to an output stream as a XML block. - * - * @param out The output stream to serialize data to - * @param preferredRoamingPartnerList The partner list to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializePreferredRoamingPartnerList(XmlSerializer out, - List<Policy.RoamingPartner> preferredRoamingPartnerList) - throws XmlPullParserException, IOException { - if (preferredRoamingPartnerList == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST); - for (Policy.RoamingPartner partner : preferredRoamingPartnerList) { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_ROAMING_PARTNER); - XmlUtil.writeNextValue(out, XML_TAG_FQDN, partner.getFqdn()); - XmlUtil.writeNextValue(out, XML_TAG_FQDN_EXACT_MATCH, partner.getFqdnExactMatch()); - XmlUtil.writeNextValue(out, XML_TAG_PRIORITY, partner.getPriority()); - XmlUtil.writeNextValue(out, XML_TAG_COUNTRIES, partner.getCountries()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_ROAMING_PARTNER); - } - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST); - } - - /** - * Serialize a {@link UpdateParameter} to an output stream as a XML block. The - * {@link UpdateParameter} are used for describing Subscription Update and Policy Update. - * - * @param out The output stream to serialize data to - * @param type The type the {@link UpdateParameter} is used for - * @param param The {@link UpdateParameter} to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializeUpdateParameter(XmlSerializer out, String type, - UpdateParameter param) throws XmlPullParserException, IOException { - if (param == null) { - return; - } - XmlUtil.writeNextSectionStart(out, type); - XmlUtil.writeNextValue(out, XML_TAG_UPDATE_INTERVAL, param.getUpdateIntervalInMinutes()); - XmlUtil.writeNextValue(out, XML_TAG_UPDATE_METHOD, param.getUpdateMethod()); - XmlUtil.writeNextValue(out, XML_TAG_RESTRICTION, param.getRestriction()); - XmlUtil.writeNextValue(out, XML_TAG_SERVER_URI, param.getServerUri()); - XmlUtil.writeNextValue(out, XML_TAG_USERNAME, param.getUsername()); - XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, param.getBase64EncodedPassword()); - XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_URL, param.getTrustRootCertUrl()); - XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT, - param.getTrustRootCertSha256Fingerprint()); - XmlUtil.writeNextSectionEnd(out, type); - } - - /** - * Serialize a Protocol-to-Ports map to an output stream as a XML block. We're not able - * to use {@link XmlUtil#writeNextValue} to write this map, since that function only works for - * maps with String key. - * - * @param out The output stream to serialize data to - * @param protoPortMap The proto port map to serialize - * @throws XmlPullParserException - * @throws IOException - */ - private static void serializeProtoPortMap(XmlSerializer out, Map<Integer, String> protoPortMap) - throws XmlPullParserException, IOException { - if (protoPortMap == null) { - return; - } - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP); - for (Map.Entry<Integer, String> entry : protoPortMap.entrySet()) { - XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PROTO_PORT); - XmlUtil.writeNextValue(out, XML_TAG_PROTO, entry.getKey()); - XmlUtil.writeNextValue(out, XML_TAG_PORTS, entry.getValue()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PROTO_PORT); - } - XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP); - } - - /** - * Deserialize a {@link HomeSp} from an input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link HomeSp} - * @throws XmlPullParserException - * @throws IOException - */ - private static HomeSp deserializeHomeSP(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - HomeSp homeSp = new HomeSp(); - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_FQDN: - homeSp.setFqdn((String) value); - break; - case XML_TAG_FRIENDLY_NAME: - homeSp.setFriendlyName((String) value); - break; - case XML_TAG_ICON_URL: - homeSp.setIconUrl((String) value); - break; - case XML_TAG_HOME_NETWORK_IDS: - homeSp.setHomeNetworkIds((Map<String, Long>) value); - break; - case XML_TAG_MATCH_ALL_OIS: - homeSp.setMatchAllOis((long[]) value); - break; - case XML_TAG_MATCH_ANY_OIS: - homeSp.setMatchAnyOis((long[]) value); - break; - case XML_TAG_ROAMING_CONSORTIUM_OIS: - homeSp.setRoamingConsortiumOis((long[]) value); - break; - case XML_TAG_OTHER_HOME_PARTNERS: - homeSp.setOtherHomePartners((String[]) value); - break; - default: - throw new XmlPullParserException("Unknown data under HomeSP: " + valueName[0]); - } - } - return homeSp; - } - - /** - * Deserialize a {@link Credential} from an input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link Credential} - * @throws XmlPullParserException - * @throws IOException - */ - private static Credential deserializeCredential(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - Credential credential = new Credential(); - while (XmlUtil.nextElementWithin(in, outerTagDepth)) { - if (isValueElement(in)) { - // Value elements. - String[] name = new String[1]; - Object value = XmlUtil.readCurrentValue(in, name); - switch (name[0]) { - case XML_TAG_CREATION_TIME: - credential.setCreationTimeInMillis((long) value); - break; - case XML_TAG_EXPIRATION_TIME: - credential.setExpirationTimeInMillis((long) value); - break; - case XML_TAG_REALM: - credential.setRealm((String) value); - break; - case XML_TAG_CHECK_AAA_SERVER_CERT_STATUS: - credential.setCheckAaaServerCertStatus((boolean) value); - break; - default: - throw new XmlPullParserException("Unknown value under Credential: " - + name[0]); - } - } else { - // Subsection elements. - switch (in.getName()) { - case XML_TAG_SECTION_HEADER_USER_CREDENTIAL: - credential.setUserCredential( - deserializeUserCredential(in, outerTagDepth + 1)); - break; - case XML_TAG_SECTION_HEADER_CERT_CREDENTIAL: - credential.setCertCredential( - deserializeCertCredential(in, outerTagDepth + 1)); - break; - case XML_TAG_SECTION_HEADER_SIM_CREDENTIAL: - credential.setSimCredential( - deserializeSimCredential(in, outerTagDepth + 1)); - break; - default: - throw new XmlPullParserException("Unknown section under Credential: " - + in.getName()); - } - } - } - return credential; - } - - /** - * Deserialize a {@link Policy} from an input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link Policy} - * @throws XmlPullParserException - * @throws IOException - */ - private static Policy deserializePolicy(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - Policy policy = new Policy(); - while (XmlUtil.nextElementWithin(in, outerTagDepth)) { - if (isValueElement(in)) { - // Value elements. - String[] name = new String[1]; - Object value = XmlUtil.readCurrentValue(in, name); - switch (name[0]) { - case XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH: - policy.setMinHomeDownlinkBandwidth((long) value); - break; - case XML_TAG_MIN_HOME_UPLINK_BANDWIDTH: - policy.setMinHomeUplinkBandwidth((long) value); - break; - case XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH: - policy.setMinRoamingDownlinkBandwidth((long) value); - break; - case XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH: - policy.setMinRoamingUplinkBandwidth((long) value); - break; - case XML_TAG_EXCLUDED_SSID_LIST: - policy.setExcludedSsidList((String[]) value); - break; - case XML_TAG_MAXIMUM_BSS_LOAD_VALUE: - policy.setMaximumBssLoadValue((int) value); - break; - } - } else { - // Subsection elements. - switch (in.getName()) { - case XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP: - policy.setRequiredProtoPortMap( - deserializeProtoPortMap(in, outerTagDepth + 1)); - break; - case XML_TAG_SECTION_HEADER_POLICY_UPDATE: - policy.setPolicyUpdate(deserializeUpdateParameter(in, outerTagDepth + 1)); - break; - case XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST: - policy.setPreferredRoamingPartnerList( - deserializePreferredRoamingPartnerList(in, outerTagDepth + 1)); - break; - default: - throw new XmlPullParserException("Unknown section under Policy: " - + in.getName()); - } - } - } - return policy; - } - - /** - * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} from an - * input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} - * @throws XmlPullParserException - * @throws IOException - */ - private static Credential.UserCredential deserializeUserCredential(XmlPullParser in, - int outerTagDepth) throws XmlPullParserException, IOException { - Credential.UserCredential userCredential = new Credential.UserCredential(); - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_USERNAME: - userCredential.setUsername((String) value); - break; - case XML_TAG_PASSWORD: - userCredential.setPassword((String) value); - break; - case XML_TAG_MACHINE_MANAGED: - userCredential.setMachineManaged((boolean) value); - break; - case XML_TAG_SOFT_TOKEN_APP: - userCredential.setSoftTokenApp((String) value); - break; - case XML_TAG_ABLE_TO_SHARE: - userCredential.setAbleToShare((boolean) value); - break; - case XML_TAG_EAP_TYPE: - userCredential.setEapType((int) value); - break; - case XML_TAG_NON_EAP_INNER_METHOD: - userCredential.setNonEapInnerMethod((String) value); - break; - default: - throw new XmlPullParserException("Unknown value under UserCredential: " - + valueName[0]); - } - } - return userCredential; - } - - /** - * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} - * from an input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} - * @throws XmlPullParserException - * @throws IOException - */ - private static Credential.CertificateCredential deserializeCertCredential(XmlPullParser in, - int outerTagDepth) throws XmlPullParserException, IOException { - Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_CERT_TYPE: - certCredential.setCertType((String) value); - break; - case XML_TAG_CERT_SHA256_FINGERPRINT: - certCredential.setCertSha256Fingerprint((byte[]) value); - break; - default: - throw new XmlPullParserException("Unknown value under CertCredential: " - + valueName[0]); - } - } - return certCredential; - } - - /** - * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} from an - * input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} - * @throws XmlPullParserException - * @throws IOException - */ - private static Credential.SimCredential deserializeSimCredential(XmlPullParser in, - int outerTagDepth) throws XmlPullParserException, IOException { - Credential.SimCredential simCredential = new Credential.SimCredential(); - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_IMSI: - simCredential.setImsi((String) value); - break; - case XML_TAG_EAP_TYPE: - simCredential.setEapType((int) value); - break; - default: - throw new XmlPullParserException("Unknown value under CertCredential: " - + valueName[0]); - } - } - return simCredential; - } - - /** - * Deserialize a list of {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} from an - * input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return List of {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} - * @throws XmlPullParserException - * @throws IOException - */ - private static List<Policy.RoamingPartner> deserializePreferredRoamingPartnerList( - XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { - List<Policy.RoamingPartner> roamingPartnerList = new ArrayList<>(); - while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_ROAMING_PARTNER, - outerTagDepth)) { - roamingPartnerList.add(deserializeRoamingPartner(in, outerTagDepth + 1)); - } - return roamingPartnerList; - } - - /** - * Deserialize a {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} from an input - * stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} - * @throws XmlPullParserException - * @throws IOException - */ - private static Policy.RoamingPartner deserializeRoamingPartner(XmlPullParser in, - int outerTagDepth) throws XmlPullParserException, IOException { - Policy.RoamingPartner partner = new Policy.RoamingPartner(); - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_FQDN: - partner.setFqdn((String) value); - break; - case XML_TAG_FQDN_EXACT_MATCH: - partner.setFqdnExactMatch((boolean) value); - break; - case XML_TAG_PRIORITY: - partner.setPriority((int) value); - break; - case XML_TAG_COUNTRIES: - partner.setCountries((String) value); - break; - default: - throw new XmlPullParserException("Unknown value under RoamingPartner: " - + valueName[0]); - } - } - return partner; - } - - /** - * Deserialize a {@link UpdateParameter} from an input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return {@link UpdateParameter} - * @throws XmlPullParserException - * @throws IOException - */ - private static UpdateParameter deserializeUpdateParameter(XmlPullParser in, - int outerTagDepth) throws XmlPullParserException, IOException { - UpdateParameter param = new UpdateParameter(); - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_UPDATE_INTERVAL: - param.setUpdateIntervalInMinutes((long) value); - break; - case XML_TAG_UPDATE_METHOD: - param.setUpdateMethod((String) value); - break; - case XML_TAG_RESTRICTION: - param.setRestriction((String) value); - break; - case XML_TAG_SERVER_URI: - param.setServerUri((String) value); - break; - case XML_TAG_USERNAME: - param.setUsername((String) value); - break; - case XML_TAG_PASSWORD: - param.setBase64EncodedPassword((String) value); - break; - case XML_TAG_TRUST_ROOT_CERT_URL: - param.setTrustRootCertUrl((String) value); - break; - case XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT: - param.setTrustRootCertSha256Fingerprint((byte[]) value); - break; - default: - throw new XmlPullParserException("Unknown value under UpdateParameter: " - + valueName[0]); - } - } - return param; - } - - /** - * Deserialize a Protocol-Port map from an input stream. - * - * @param in The input stream to read data from - * @param outerTagDepth The tag depth of the current XML section - * @return Proocol-Port map - * @throws XmlPullParserException - * @throws IOException - */ - private static Map<Integer, String> deserializeProtoPortMap(XmlPullParser in, - int outerTagDepth) throws XmlPullParserException, IOException { - Map<Integer, String> protoPortMap = new HashMap<>(); - while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_PROTO_PORT, - outerTagDepth)) { - int proto = (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROTO); - String ports = (String) XmlUtil.readNextValueWithName(in, XML_TAG_PORTS); - protoPortMap.put(proto, ports); - } - return protoPortMap; - } - - /** - * Determine if the current element is a value or a section. The "name" attribute of the - * element is used as the indicator, when it is present, the element is considered a value - * element. - * - * Value element: - * <int name="test">12</int> - * - * Section element: - * <Test> - * ... - * </Test> - * - * @param in XML input stream - * @return true if the current element is a value - */ - private static boolean isValueElement(XmlPullParser in) { - return in.getAttributeValue(null, "name") != null; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/ServiceProviderVerifier.java b/service/java/com/android/server/wifi/hotspot2/ServiceProviderVerifier.java deleted file mode 100644 index bae7b7019..000000000 --- a/service/java/com/android/server/wifi/hotspot2/ServiceProviderVerifier.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2018 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.server.wifi.hotspot2; - -import android.annotation.NonNull; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; - -import org.bouncycastle.asn1.ASN1Encodable; -import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Sequence; -import org.bouncycastle.asn1.DERTaggedObject; -import org.bouncycastle.asn1.DERUTF8String; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Locale; - -/** - * Utility class to validate a server X.509 Certificate of a service provider. - */ -public class ServiceProviderVerifier { - private static final String TAG = "PasspointServiceProviderVerifier"; - - private static final int OTHER_NAME = 0; - private static final int ENTRY_COUNT = 2; - private static final int LANGUAGE_CODE_LENGTH = 3; - - /** - * The Operator Friendly Name shall be an {@code otherName} sequence for the subjectAltName. - * If multiple Operator Friendly name values are required, then multiple {@code otherName} - * fields shall be present in the OSU certificate. - * The type-id of the {@code otherName} shall be an {@code ID_WFA_OID_HOTSPOT_FRIENDLYNAME}. - * {@code ID_WFA_OID_HOTSPOT_FRIENDLYNAME} OBJECT IDENTIFIER ::= { 1.3.6.1.4.1.40808.1.1.1} - * The {@code ID_WFA_OID_HOTSPOT_FRIENDLYNAME} contains only one language code and - * friendly name for an operator and shall be encoded as an ASN.1 type UTF8String. - * Refer to 7.3.2 section in Hotspot 2.0 R2 Technical_Specification document in detail. - */ - @VisibleForTesting - public static final String ID_WFA_OID_HOTSPOT_FRIENDLYNAME = "1.3.6.1.4.1.40808.1.1.1"; - - /** - * Extracts provider names from a certificate by parsing subjectAltName extensions field - * as an otherName sequence, which contains - * id-wfa-hotspot-friendlyName oid + UTF8String denoting the friendlyName in the format below - * <languageCode><friendlyName> - * Note: Multiple language code will appear as additional UTF8 strings. - * Note: Multiple friendly names will appear as multiple otherName sequences. - * - * @param providerCert the X509Certificate to be parsed - * @return List of Pair representing {@Locale} and friendly Name for Operator found in the - * certificate. - */ - public static List<Pair<Locale, String>> getProviderNames(X509Certificate providerCert) { - List<Pair<Locale, String>> providerNames = new ArrayList<>(); - Pair<Locale, String> providerName; - if (providerCert == null) { - return providerNames; - } - try { - /** - * The ASN.1 definition of the {@code SubjectAltName} extension is: - * SubjectAltName ::= GeneralNames - * GeneralNames :: = SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName, - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER} - * If this certificate does not contain a SubjectAltName extension, null is returned. - * Otherwise, a Collection is returned with an entry representing each - * GeneralName included in the extension. - */ - Collection<List<?>> col = providerCert.getSubjectAlternativeNames(); - if (col == null) { - return providerNames; - } - for (List<?> entry : col) { - // Each entry is a List whose first entry is an Integer(the name type, 0-8) - // and whose second entry is a String or a byte array. - if (entry == null || entry.size() != ENTRY_COUNT) { - continue; - } - - // The UTF-8 encoded Friendly Name shall be an otherName sequence. - if ((Integer) entry.get(0) != OTHER_NAME) { - continue; - } - - if (!(entry.toArray()[1] instanceof byte[])) { - continue; - } - - byte[] octets = (byte[]) entry.toArray()[1]; - ASN1Encodable obj = new ASN1InputStream(octets).readObject(); - - if (!(obj instanceof DERTaggedObject)) { - continue; - } - - DERTaggedObject taggedObject = (DERTaggedObject) obj; - ASN1Encodable encodedObject = taggedObject.getObject(); - - if (!(encodedObject instanceof ASN1Sequence)) { - continue; - } - - ASN1Sequence innerSequence = (ASN1Sequence) (encodedObject); - ASN1Encodable innerObject = innerSequence.getObjectAt(0); - - if (!(innerObject instanceof ASN1ObjectIdentifier)) { - continue; - } - - ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(innerObject); - if (!oid.getId().equals(ID_WFA_OID_HOTSPOT_FRIENDLYNAME)) { - continue; - } - - for (int index = 1; index < innerSequence.size(); index++) { - innerObject = innerSequence.getObjectAt(index); - if (!(innerObject instanceof DERTaggedObject)) { - continue; - } - - DERTaggedObject innerSequenceObj = (DERTaggedObject) innerObject; - ASN1Encodable innerSequenceEncodedObject = innerSequenceObj.getObject(); - - if (!(innerSequenceEncodedObject instanceof DERUTF8String)) { - continue; - } - - DERUTF8String providerNameUtf8 = (DERUTF8String) innerSequenceEncodedObject; - providerName = getFriendlyName(providerNameUtf8.getString()); - if (providerName != null) { - providerNames.add(providerName); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return providerNames; - } - - /** - * Verifies a SHA-256 fingerprint of a X.509 Certificate. - * - * The SHA-256 fingerprint is calculated over the X.509 ASN.1 DER encoded certificate. - * @param x509Cert a server X.509 Certificate to verify - * @param certSHA256Fingerprint a SHA-256 hash value stored in PPS(PerProviderSubscription) - * MO(Management Object) - * SubscriptionUpdate/TrustRoot/CertSHA256Fingerprint for - * remediation server - * AAAServerTrustRoot/CertSHA256Fingerprint for AAA server - * PolicyUpdate/TrustRoot/CertSHA256Fingerprint for Policy Server - * - * @return {@code true} if the fingerprint of {@code x509Cert} is equal to {@code - * certSHA256Fingerprint}, {@code false} otherwise. - */ - public static boolean verifyCertFingerprint(@NonNull X509Certificate x509Cert, - @NonNull byte[] certSHA256Fingerprint) { - try { - byte[] fingerPrintSha256 = computeHash(x509Cert.getEncoded()); - if (fingerPrintSha256 == null) return false; - if (Arrays.equals(fingerPrintSha256, certSHA256Fingerprint)) { - return true; - } - } catch (Exception e) { - Log.e(TAG, "verifyCertFingerprint err:" + e); - } - return false; - } - - /** - * Computes a hash with SHA-256 algorithm for the input. - */ - private static byte[] computeHash(byte[] input) { - try { - MessageDigest digest = MessageDigest.getInstance("SHA-256"); - return digest.digest(input); - } catch (NoSuchAlgorithmException e) { - return null; - } - } - - /** - * Extracts the language code and friendly Name from the alternativeName. - */ - private static Pair<Locale, String> getFriendlyName(String alternativeName) { - - // Check for the minimum required length. - if (TextUtils.isEmpty(alternativeName) || alternativeName.length() < LANGUAGE_CODE_LENGTH) { - return null; - } - - // Read the language string. - String language = alternativeName.substring(0, LANGUAGE_CODE_LENGTH); - Locale locale; - try { - // The language code is a two or three character language code defined in ISO-639. - locale = new Locale.Builder().setLanguage(language).build(); - } catch (Exception e) { - return null; - } - - // Read the friendlyName - String friendlyName = alternativeName.substring(LANGUAGE_CODE_LENGTH); - return Pair.create(locale, friendlyName); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/SystemInfo.java b/service/java/com/android/server/wifi/hotspot2/SystemInfo.java deleted file mode 100644 index 5f7f7a679..000000000 --- a/service/java/com/android/server/wifi/hotspot2/SystemInfo.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2; - -import android.annotation.NonNull; -import android.content.Context; -import android.os.Build; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.WifiNative; - -import java.util.Locale; - -/** - * Provide APIs for retrieving system information, so that they can be mocked for unit tests. - */ -public class SystemInfo { - public static final String TAG = "SystemInfo"; - public static final String UNKNOWN_INFO = "Unknown"; - - private final TelephonyManager mTelephonyManager; - private final WifiNative mWifiNative; - private static SystemInfo sSystemInfo = null; - - @VisibleForTesting - SystemInfo(Context context, WifiNative wifiNative) { - // TODO(b/132188983): inject this using WifiInjector - mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - mWifiNative = wifiNative; - } - - public static SystemInfo getInstance(@NonNull Context context, @NonNull WifiNative wifiNative) { - if (sSystemInfo == null) { - sSystemInfo = new SystemInfo(context, wifiNative); - } - return sSystemInfo; - } - - /** - * Get the system language. - * - * @return current language code - */ - public String getLanguage() { - return Locale.getDefault().getLanguage(); - } - - /** - * Get the device manufacturer info - * - * @return the device manufacturer info or {@link Build#UNKNOWN} if not set - */ - public String getDeviceManufacturer() { - return Build.MANUFACTURER; - } - - /** - * Get the device model info. - * - * @return the device model info or {@link Build#UNKNOWN} if not set - */ - public String getDeviceModel() { - return Build.MODEL; - } - - /** - * Get the Wifi Mac address for primary interface. - * - * TODO(b/80092273): need to check if this privacy information is required for Passpoint R2. - * @param ifaceName Name of the interface. - * @return string containing the MAC address or null on a failed call - */ - public String getMacAddress(@NonNull String ifaceName) { - return mWifiNative.getMacAddress(ifaceName); - } - - /** - * Get the device ID. Either IMEI or MEID will be returned based on the installed SIM. - * {@link #UNKNOWN_INFO} will be returned if no SIM is installed. - * - * @return String representing device ID - */ - public String getDeviceId() { - TelephonyManager defaultDataTm = mTelephonyManager.createForSubscriptionId( - SubscriptionManager.getDefaultDataSubscriptionId()); - // IMEI will be provided for GSM SIM. - String imei = defaultDataTm.getImei(); - if (!TextUtils.isEmpty(imei)) { - return imei; - } - - // MEID will be provided for CMDA SIM. - String meid = defaultDataTm.getMeid(); - if (!TextUtils.isEmpty(meid)) { - return meid; - } - return UNKNOWN_INFO; - } - - /** - * Get the software version. - * - * @return the build release version. - */ - public String getSoftwareVersion() { - return String.format("Android %s %s", Build.VERSION.RELEASE, Build.VERSION.INCREMENTAL); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/Utils.java b/service/java/com/android/server/wifi/hotspot2/Utils.java deleted file mode 100644 index ec3e7d875..000000000 --- a/service/java/com/android/server/wifi/hotspot2/Utils.java +++ /dev/null @@ -1,290 +0,0 @@ -package com.android.server.wifi.hotspot2; - -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK; -import static com.android.server.wifi.hotspot2.anqp.Constants.NIBBLE_MASK; - -import com.android.server.wifi.hotspot2.anqp.Constants; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.TimeZone; - -public abstract class Utils { - - public static final long UNSET_TIME = -1; - - private static final int EUI48Length = 6; - private static final int EUI64Length = 8; - private static final long EUI48Mask = 0xffffffffffffL; - private static final String[] PLMNText = {"org", "3gppnetwork", "mcc*", "mnc*", "wlan" }; - - public static String hs2LogTag(Class c) { - return "HS20"; - } - - public static List<String> splitDomain(String domain) { - - if (domain.endsWith(".")) - domain = domain.substring(0, domain.length() - 1); - int at = domain.indexOf('@'); - if (at >= 0) - domain = domain.substring(at + 1); - - String[] labels = domain.toLowerCase().split("\\."); - LinkedList<String> labelList = new LinkedList<String>(); - for (String label : labels) { - labelList.addFirst(label); - } - - return labelList; - } - - public static long parseMac(String s) { - if (s == null) { - throw new IllegalArgumentException("Null MAC adddress"); - } - long mac = 0; - int count = 0; - for (int n = 0; n < s.length(); n++) { - int nibble = Utils.fromHex(s.charAt(n), true); // Set lenient to not blow up on ':' - if (nibble >= 0) { // ... and use only legit hex. - mac = (mac << 4) | nibble; - count++; - } - } - if (count < 12 || (count&1) == 1) { - throw new IllegalArgumentException("Bad MAC address: '" + s + "'"); - } - return mac; - } - - public static String macToString(long mac) { - int len = (mac & ~EUI48Mask) != 0 ? EUI64Length : EUI48Length; - StringBuilder sb = new StringBuilder(); - boolean first = true; - for (int n = (len - 1)*Byte.SIZE; n >= 0; n -= Byte.SIZE) { - if (first) { - first = false; - } - else { - sb.append(':'); - } - sb.append(String.format("%02x", (mac >>> n) & Constants.BYTE_MASK)); - } - return sb.toString(); - } - - public static String getMccMnc(List<String> domain) { - if (domain.size() != PLMNText.length) { - return null; - } - - for (int n = 0; n < PLMNText.length; n++ ) { - String expect = PLMNText[n]; - int len = expect.endsWith("*") ? expect.length() - 1 : expect.length(); - if (!domain.get(n).regionMatches(0, expect, 0, len)) { - return null; - } - } - - String prefix = domain.get(2).substring(3) + domain.get(3).substring(3); - for (int n = 0; n < prefix.length(); n++) { - char ch = prefix.charAt(n); - if (ch < '0' || ch > '9') { - return null; - } - } - return prefix; - } - - public static String roamingConsortiumsToString(long[] ois) { - if (ois == null) { - return "null"; - } - List<Long> list = new ArrayList<Long>(ois.length); - for (long oi : ois) { - list.add(oi); - } - return roamingConsortiumsToString(list); - } - - public static String roamingConsortiumsToString(Collection<Long> ois) { - StringBuilder sb = new StringBuilder(); - boolean first = true; - for (long oi : ois) { - if (first) { - first = false; - } else { - sb.append(", "); - } - if (Long.numberOfLeadingZeros(oi) > 40) { - sb.append(String.format("%06x", oi)); - } else { - sb.append(String.format("%010x", oi)); - } - } - return sb.toString(); - } - - public static String toUnicodeEscapedString(String s) { - StringBuilder sb = new StringBuilder(s.length()); - for (int n = 0; n < s.length(); n++) { - char ch = s.charAt(n); - if (ch>= ' ' && ch < 127) { - sb.append(ch); - } - else { - sb.append("\\u").append(String.format("%04x", (int)ch)); - } - } - return sb.toString(); - } - - public static String toHexString(byte[] data) { - if (data == null) { - return "null"; - } - StringBuilder sb = new StringBuilder(data.length * 3); - - boolean first = true; - for (byte b : data) { - if (first) { - first = false; - } else { - sb.append(' '); - } - sb.append(String.format("%02x", b & BYTE_MASK)); - } - return sb.toString(); - } - - public static String toHex(byte[] octets) { - StringBuilder sb = new StringBuilder(octets.length * 2); - for (byte o : octets) { - sb.append(String.format("%02x", o & BYTE_MASK)); - } - return sb.toString(); - } - - public static byte[] hexToBytes(String text) { - if ((text.length() & 1) == 1) { - throw new NumberFormatException("Odd length hex string: " + text.length()); - } - byte[] data = new byte[text.length() >> 1]; - int position = 0; - for (int n = 0; n < text.length(); n += 2) { - data[position] = - (byte) (((fromHex(text.charAt(n), false) & NIBBLE_MASK) << 4) | - (fromHex(text.charAt(n + 1), false) & NIBBLE_MASK)); - position++; - } - return data; - } - - public static int fromHex(char ch, boolean lenient) throws NumberFormatException { - if (ch <= '9' && ch >= '0') { - return ch - '0'; - } else if (ch >= 'a' && ch <= 'f') { - return ch + 10 - 'a'; - } else if (ch <= 'F' && ch >= 'A') { - return ch + 10 - 'A'; - } else if (lenient) { - return -1; - } else { - throw new NumberFormatException("Bad hex-character: " + ch); - } - } - - private static char toAscii(int b) { - return b >= ' ' && b < 0x7f ? (char) b : '.'; - } - - static boolean isDecimal(String s) { - for (int n = 0; n < s.length(); n++) { - char ch = s.charAt(n); - if (ch < '0' || ch > '9') { - return false; - } - } - return true; - } - - public static <T extends Comparable> int compare(Comparable<T> c1, T c2) { - if (c1 == null) { - return c2 == null ? 0 : -1; - } - else if (c2 == null) { - return 1; - } - else { - return c1.compareTo(c2); - } - } - - public static String bytesToBingoCard(ByteBuffer data, int len) { - ByteBuffer dup = data.duplicate(); - dup.limit(dup.position() + len); - return bytesToBingoCard(dup); - } - - public static String bytesToBingoCard(ByteBuffer data) { - ByteBuffer dup = data.duplicate(); - StringBuilder sbx = new StringBuilder(); - while (dup.hasRemaining()) { - sbx.append(String.format("%02x ", dup.get() & BYTE_MASK)); - } - dup = data.duplicate(); - sbx.append(' '); - while (dup.hasRemaining()) { - sbx.append(String.format("%c", toAscii(dup.get() & BYTE_MASK))); - } - return sbx.toString(); - } - - public static String toHMS(long millis) { - long time = millis >= 0 ? millis : -millis; - long tmp = time / 1000L; - long ms = time - tmp * 1000L; - - time = tmp; - tmp /= 60L; - long s = time - tmp * 60L; - - time = tmp; - tmp /= 60L; - long m = time - tmp * 60L; - - return String.format("%s%d:%02d:%02d.%03d", millis < 0 ? "-" : "", tmp, m, s, ms); - } - - public static String toUTCString(long ms) { - if (ms < 0) { - return "unset"; - } - Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - c.setTimeInMillis(ms); - return String.format("%4d/%02d/%02d %2d:%02d:%02dZ", - c.get(Calendar.YEAR), - c.get(Calendar.MONTH) + 1, - c.get(Calendar.DAY_OF_MONTH), - c.get(Calendar.HOUR_OF_DAY), - c.get(Calendar.MINUTE), - c.get(Calendar.SECOND)); - } - - public static String unquote(String s) { - if (s == null) { - return null; - } - else if (s.length() > 1 && s.startsWith("\"") && s.endsWith("\"")) { - return s.substring(1, s.length()-1); - } - else { - return s; - } - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/WfaCertBuilder.java b/service/java/com/android/server/wifi/hotspot2/WfaCertBuilder.java deleted file mode 100644 index 4abf3769a..000000000 --- a/service/java/com/android/server/wifi/hotspot2/WfaCertBuilder.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2; - -import android.util.Log; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.HashSet; -import java.util.Set; - -/** - * Provides static method to build certificate set from cert files - */ -public class WfaCertBuilder { - - private static final String TAG = "PasspointWfaCertBuilder"; - - /** - * Returns a set of X509 Certificates from a set of WFA cert files - * @param directory the location where the cert files are stored - * @return Set<X509Certificate> certificates obtained from the files - */ - public static Set<X509Certificate> loadCertsFromDisk(String directory) { - Set<X509Certificate> certs = new HashSet<>(); - try { - File certDir = new File(directory); - File[] certFiles = certDir.listFiles(); - if (certFiles == null || certFiles.length <= 0) { - return certs; - } - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - for (File certFile : certFiles) { - FileInputStream fis = new FileInputStream(certFile); - Certificate cert = certFactory.generateCertificate(fis); - if (cert instanceof X509Certificate) { - certs.add((X509Certificate) cert); - } - fis.close(); - } - } catch (CertificateException | IOException | SecurityException e) { - Log.e(TAG, "Unable to read cert " + e.getMessage()); - } - return certs; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/WfaKeyStore.java b/service/java/com/android/server/wifi/hotspot2/WfaKeyStore.java deleted file mode 100644 index b67009751..000000000 --- a/service/java/com/android/server/wifi/hotspot2/WfaKeyStore.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2017 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.server.wifi.hotspot2; - -import android.util.Log; - -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Set; - -/** - * WFA Keystore - */ -public class WfaKeyStore { - private static final String TAG = "PasspointWfaKeyStore"; - /* package */ static final String DEFAULT_WFA_CERT_DIR = - "/apex/com.android.wifi/etc/security/cacerts_wfa"; - - private boolean mVerboseLoggingEnabled = false; - private KeyStore mKeyStore = null; - - /** - * Loads the keystore with root certificates - */ - public void load() { - if (mKeyStore != null) { - return; - } - int index = 0; - try { - mKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - mKeyStore.load(null, null); - Set<X509Certificate> certs = WfaCertBuilder.loadCertsFromDisk(DEFAULT_WFA_CERT_DIR); - for (X509Certificate cert : certs) { - mKeyStore.setCertificateEntry(String.format("%d", index), cert); - index++; - } - if (index <= 0) { - Log.wtf(TAG, "No certs loaded"); - } - } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException - | IOException e) { - e.printStackTrace(); - } - } - - /** - * Returns the underlying keystore object - * @return KeyStore Underlying keystore object created - */ - public KeyStore get() { - return mKeyStore; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/WnmData.java b/service/java/com/android/server/wifi/hotspot2/WnmData.java deleted file mode 100644 index 97a7d1103..000000000 --- a/service/java/com/android/server/wifi/hotspot2/WnmData.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -/** - * This class carries the payload of a Hotspot 2.0 Wireless Network Management (WNM) frame, - * described in the Hotspot 2.0 spec, section 3.2. - */ -public class WnmData { - public static final int ESS = 1; // HS2.0 spec section 3.2.1.2, table 4 - - private final long mBssid; - private final String mUrl; - private final boolean mDeauthEvent; - private final int mMethod; - private final boolean mEss; - private final int mDelay; - - public WnmData(long bssid, String url, int method) { - mBssid = bssid; - mUrl = url; - mMethod = method; - mEss = false; - mDelay = -1; - mDeauthEvent = false; - } - - public WnmData(long bssid, String url, boolean ess, int delay) { - mBssid = bssid; - mUrl = url; - mEss = ess; - mDelay = delay; - mMethod = -1; - mDeauthEvent = true; - } - - public long getBssid() { - return mBssid; - } - - public String getUrl() { - return mUrl; - } - - public boolean isDeauthEvent() { - return mDeauthEvent; - } - - public int getMethod() { - return mMethod; - } - - public boolean isEss() { - return mEss; - } - - public int getDelay() { - return mDelay; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/ANQPElement.java deleted file mode 100644 index b237b77f7..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPElement.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.android.server.wifi.hotspot2.anqp; - -/** - * Base class for an IEEE802.11u ANQP element. - */ -public abstract class ANQPElement { - private final Constants.ANQPElementType mID; - - protected ANQPElement(Constants.ANQPElementType id) { - mID = id; - } - - public Constants.ANQPElementType getID() { - return mID; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPParser.java b/service/java/com/android/server/wifi/hotspot2/anqp/ANQPParser.java deleted file mode 100644 index 89bcfcb78..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPParser.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * Factory to build a collection of 802.11u ANQP elements from a byte buffer. - */ -public class ANQPParser { - /** - * The OI value for Hotspot 2.0 ANQP-element. - */ - @VisibleForTesting - public static final int VENDOR_SPECIFIC_HS20_OI = 0x506F9A; - - /** - * The Type value for Hotspot 2.0 ANQP-element. - */ - @VisibleForTesting - public static final int VENDOR_SPECIFIC_HS20_TYPE = 0x11; - - /** - * Parse an ANQP element from the pass-in byte buffer. - * - * Note: Each Hotspot 2.0 Release 2 element will be wrapped inside a Vendor Specific element - * in the ANQP response from the AP. However, the lower layer (e.g. wpa_supplicant) should - * already take care of parsing those elements out of Vendor Specific elements. To be safe, - * we will parse the Vendor Specific elements for non-Hotspot 2.0 Release elements or in - * the case they're not parsed by the lower layer. - * - * @param infoID The ANQP element type - * @param payload The buffer to read from - * @return {@link com.android.server.wifi.hotspot2.anqp.ANQPElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static ANQPElement parseElement(Constants.ANQPElementType infoID, ByteBuffer payload) - throws ProtocolException { - switch (infoID) { - case ANQPVenueName: - return VenueNameElement.parse(payload); - case ANQPRoamingConsortium: - return RoamingConsortiumElement.parse(payload); - case ANQPIPAddrAvailability: - return IPAddressTypeAvailabilityElement.parse(payload); - case ANQPNAIRealm: - return NAIRealmElement.parse(payload); - case ANQP3GPPNetwork: - return ThreeGPPNetworkElement.parse(payload); - case ANQPDomName: - return DomainNameElement.parse(payload); - case ANQPVendorSpec: - return parseVendorSpecificElement(payload); - default: - throw new ProtocolException("Unknown element ID: " + infoID); - } - } - - /** - * Parse a Hotspot 2.0 Release 2 ANQP element from the pass-in byte buffer. - * - * @param infoID The ANQP element ID - * @param payload The buffer to read from - * @return {@link com.android.server.wifi.hotspot2.anqp.ANQPElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static ANQPElement parseHS20Element(Constants.ANQPElementType infoID, - ByteBuffer payload) throws ProtocolException { - switch (infoID) { - case HSFriendlyName: - return HSFriendlyNameElement.parse(payload); - case HSWANMetrics: - return HSWanMetricsElement.parse(payload); - case HSConnCapability: - return HSConnectionCapabilityElement.parse(payload); - case HSOSUProviders: - return HSOsuProvidersElement.parse(payload); - default: - throw new ProtocolException("Unknown element ID: " + infoID); - } - } - - /** - * Parse the ANQP vendor specific element. Currently only supports the vendor specific - * element that contained Hotspot 2.0 ANQP-element. - * - * Format of a ANQP Vendor Specific element: - * | OI | Type | Subtype | Reserved | Payload | - * 3 1 1 1 variable - * - * @param payload The buffer to read from - * @return {@link ANQPElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - private static ANQPElement parseVendorSpecificElement(ByteBuffer payload) - throws ProtocolException { - int oi = (int) ByteBufferReader.readInteger(payload, ByteOrder.BIG_ENDIAN, 3); - int type = payload.get() & 0xFF; - - if (oi != VENDOR_SPECIFIC_HS20_OI || type != VENDOR_SPECIFIC_HS20_TYPE) { - throw new ProtocolException("Unsupported vendor specific OI=" + oi + " type=" + type); - } - - int subType = payload.get() & 0xFF; - Constants.ANQPElementType hs20ID = Constants.mapHS20Element(subType); - if (hs20ID == null) { - throw new ProtocolException("Unsupported subtype: " + subType); - } - payload.get(); // Skip the reserved byte - return parseHS20Element(hs20ID, payload); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/CellularNetwork.java b/service/java/com/android/server/wifi/hotspot2/anqp/CellularNetwork.java deleted file mode 100644 index cc39b3f2b..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/CellularNetwork.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * The IEI (Information Element Identity) contained in the Generic Container for the - * 3GPP Cellular Network ANQP element. - * - * Refer to Annex A of 3GPP TS 24.234 version 11.3.0 for information on the data format: - * (http://www.etsi.org/deliver/etsi_ts/124200_124299/124234/11.03.00_60/ts_124234v110300p.pdf) - */ -public class CellularNetwork { - private static final String TAG = "CellularNetwork"; - - /** - * IEI type for PLMN (Public Land Mobile Network) list. - */ - @VisibleForTesting - public static final int IEI_TYPE_PLMN_LIST = 0; - - @VisibleForTesting - public static final int IEI_CONTENT_LENGTH_MASK = 0x7F; - - /** - * Number of bytes for each PLMN (Public Land Mobile Network). - */ - @VisibleForTesting - public static final int PLMN_DATA_BYTES = 3; - - /** - * The value for comparing the third digit of MNC data with to determine if the MNC is - * two or three digits. - */ - private static final int MNC_2DIGIT_VALUE = 0xF; - - /** - * List of PLMN (Public Land Mobile Network) information. - */ - private final List<String> mPlmnList; - - @VisibleForTesting - public CellularNetwork(List<String> plmnList) { - mPlmnList = plmnList; - } - - /** - * Parse a CellularNetwork from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link CellularNetwork} - * @throws ProtocolException - * @throws BufferUnderflowException - */ - public static CellularNetwork parse(ByteBuffer payload) throws ProtocolException { - int ieiType = payload.get() & 0xFF; - int ieiSize = payload.get() & IEI_CONTENT_LENGTH_MASK; - - // Skip this IEI if it is an unsupported type. - if (ieiType != IEI_TYPE_PLMN_LIST) { - Log.e(TAG, "Ignore unsupported IEI Type: " + ieiType); - // Advance the buffer position to the next IEI. - payload.position(payload.position() + ieiSize); - return null; - } - - // Get PLMN count. - int plmnCount = payload.get() & 0xFF; - - // Verify IEI size with PLMN count. The IEI size contained the PLMN count field plus - // the bytes for the PLMNs. - if (ieiSize != (plmnCount * PLMN_DATA_BYTES + 1)) { - throw new ProtocolException("IEI size and PLMN count mismatched: IEI Size=" + ieiSize - + " PLMN Count=" + plmnCount); - } - - // Process each PLMN. - List<String> plmnList = new ArrayList<>(); - while (plmnCount > 0) { - plmnList.add(parsePlmn(payload)); - plmnCount--; - } - return new CellularNetwork(plmnList); - } - - public List<String> getPlmns() { - return Collections.unmodifiableList(mPlmnList); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof CellularNetwork)) { - return false; - } - CellularNetwork that = (CellularNetwork) thatObject; - return mPlmnList.equals(that.mPlmnList); - } - - @Override - public int hashCode() { - return mPlmnList.hashCode(); - } - - @Override - public String toString() { - return "CellularNetwork{mPlmnList=" + mPlmnList + "}"; - } - - /** - * Parse the PLMN information from the given buffer. A string representing a hex value - * of |MCC|MNC| will be returned. - * - * PLMN Coding Format: - * b7 b0 - * | MCC Digit 2 | MCC Digit 1 | - * | MNC Digit 3 | MCC Digit 3 | - * | MNC Digit 2 | MNC Digit 1 | - * - * @param payload The buffer to read from. - * @return {@Link String} - * @throws BufferUnderflowException - */ - private static String parsePlmn(ByteBuffer payload) { - byte[] plmn = new byte[PLMN_DATA_BYTES]; - payload.get(plmn); - - // Formatted as | MCC Digit 1 | MCC Digit 2 | MCC Digit 3 | - int mcc = ((plmn[0] << 8) & 0xF00) | (plmn[0] & 0x0F0) | (plmn[1] & 0x00F); - - // Formated as |MNC Digit 1 | MNC Digit 2 | - int mnc = ((plmn[2] << 4) & 0xF0) | ((plmn[2] >> 4) & 0x0F); - - // The digit 3 of MNC decides if the MNC is 2 or 3 digits number. When it is equal to - // 0xF, MNC is a 2 digit value. Otherwise, it is a 3 digit number. - int mncDigit3 = (plmn[1] >> 4) & 0x0F; - return (mncDigit3 != MNC_2DIGIT_VALUE) - ? String.format("%03x%03x", mcc, (mnc << 4) | mncDigit3) - : String.format("%03x%02x", mcc, mnc); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/Constants.java b/service/java/com/android/server/wifi/hotspot2/anqp/Constants.java deleted file mode 100644 index c45b3c5d7..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/Constants.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.android.server.wifi.hotspot2.anqp; - -import java.net.ProtocolException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.Charset; -import java.util.Collection; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * ANQP related constants (802.11-2012) - */ -public class Constants { - - public static final int NIBBLE_MASK = 0x0f; - public static final int BYTE_MASK = 0xff; - public static final int SHORT_MASK = 0xffff; - public static final long INT_MASK = 0xffffffffL; - public static final int BYTES_IN_SHORT = 2; - public static final int BYTES_IN_INT = 4; - public static final int BYTES_IN_EUI48 = 6; - public static final long MILLIS_IN_A_SEC = 1000L; - - public static final int HS20_PREFIX = 0x119a6f50; // Note that this is represented as a LE int - public static final int HS20_FRAME_PREFIX = 0x109a6f50; - public static final int UTF8_INDICATOR = 1; - - public static final int LANG_CODE_LENGTH = 3; - // From IEEE802.11-2012 section 8.4.1.34. - public static final int VENUE_INFO_LENGTH = 2; - - public static final int ANQP_QUERY_LIST = 256; - public static final int ANQP_VENUE_NAME = 258; - public static final int ANQP_ROAMING_CONSORTIUM = 261; - public static final int ANQP_IP_ADDR_AVAILABILITY = 262; - public static final int ANQP_NAI_REALM = 263; - public static final int ANQP_3GPP_NETWORK = 264; - public static final int ANQP_DOM_NAME = 268; - public static final int ANQP_VENDOR_SPEC = 56797; - - public static final int HS_QUERY_LIST = 1; - public static final int HS_FRIENDLY_NAME = 3; - public static final int HS_WAN_METRICS = 4; - public static final int HS_CONN_CAPABILITY = 5; - public static final int HS_NAI_HOME_REALM_QUERY = 6; - public static final int HS_OSU_PROVIDERS = 8; - public static final int HS_ICON_REQUEST = 10; - public static final int HS_ICON_FILE = 11; - - public enum ANQPElementType { - ANQPQueryList, - ANQPVenueName, - ANQPRoamingConsortium, - ANQPIPAddrAvailability, - ANQPNAIRealm, - ANQP3GPPNetwork, - ANQPDomName, - ANQPVendorSpec, - HSQueryList, - HSFriendlyName, - HSWANMetrics, - HSConnCapability, - HSNAIHomeRealmQuery, - HSOSUProviders, - HSIconRequest, - HSIconFile - } - - private static final Map<Integer, ANQPElementType> sAnqpMap = new HashMap<>(); - private static final Map<Integer, ANQPElementType> sHs20Map = new HashMap<>(); - private static final Map<ANQPElementType, Integer> sRevAnqpmap = - new EnumMap<>(ANQPElementType.class); - private static final Map<ANQPElementType, Integer> sRevHs20map = - new EnumMap<>(ANQPElementType.class); - - static { - sAnqpMap.put(ANQP_QUERY_LIST, ANQPElementType.ANQPQueryList); - sAnqpMap.put(ANQP_VENUE_NAME, ANQPElementType.ANQPVenueName); - sAnqpMap.put(ANQP_ROAMING_CONSORTIUM, ANQPElementType.ANQPRoamingConsortium); - sAnqpMap.put(ANQP_IP_ADDR_AVAILABILITY, ANQPElementType.ANQPIPAddrAvailability); - sAnqpMap.put(ANQP_NAI_REALM, ANQPElementType.ANQPNAIRealm); - sAnqpMap.put(ANQP_3GPP_NETWORK, ANQPElementType.ANQP3GPPNetwork); - sAnqpMap.put(ANQP_DOM_NAME, ANQPElementType.ANQPDomName); - sAnqpMap.put(ANQP_VENDOR_SPEC, ANQPElementType.ANQPVendorSpec); - - sHs20Map.put(HS_QUERY_LIST, ANQPElementType.HSQueryList); - sHs20Map.put(HS_FRIENDLY_NAME, ANQPElementType.HSFriendlyName); - sHs20Map.put(HS_WAN_METRICS, ANQPElementType.HSWANMetrics); - sHs20Map.put(HS_CONN_CAPABILITY, ANQPElementType.HSConnCapability); - sHs20Map.put(HS_NAI_HOME_REALM_QUERY, ANQPElementType.HSNAIHomeRealmQuery); - sHs20Map.put(HS_OSU_PROVIDERS, ANQPElementType.HSOSUProviders); - sHs20Map.put(HS_ICON_REQUEST, ANQPElementType.HSIconRequest); - sHs20Map.put(HS_ICON_FILE, ANQPElementType.HSIconFile); - - for (Map.Entry<Integer, ANQPElementType> entry : sAnqpMap.entrySet()) { - sRevAnqpmap.put(entry.getValue(), entry.getKey()); - } - for (Map.Entry<Integer, ANQPElementType> entry : sHs20Map.entrySet()) { - sRevHs20map.put(entry.getValue(), entry.getKey()); - } - } - - public static ANQPElementType mapANQPElement(int id) { - return sAnqpMap.get(id); - } - - public static ANQPElementType mapHS20Element(int id) { - return sHs20Map.get(id); - } - - public static Integer getANQPElementID(ANQPElementType elementType) { - return sRevAnqpmap.get(elementType); - } - - public static Integer getHS20ElementID(ANQPElementType elementType) { - return sRevHs20map.get(elementType); - } - - public static boolean hasBaseANQPElements(Collection<ANQPElementType> elements) { - if (elements == null) { - return false; - } - for (ANQPElementType element : elements) { - if (sRevAnqpmap.containsKey(element)) { - return true; - } - } - return false; - } - - public static boolean hasR2Elements(List<ANQPElementType> elements) { - return elements.contains(ANQPElementType.HSOSUProviders); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java deleted file mode 100644 index 35b39565e..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * The Domain Name ANQP Element, IEEE802.11-2012 section 8.4.4.15. - * - * Format: - * | Domain Name Field #1 (optional) | ... - * variable - * - * Domain Name Field Format: - * | Length | Domain Name | - * 1 variable - */ -public class DomainNameElement extends ANQPElement { - private final List<String> mDomains; - - @VisibleForTesting - public DomainNameElement(List<String> domains) { - super(Constants.ANQPElementType.ANQPDomName); - mDomains = domains; - } - - /** - * Parse a DomainNameElement from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link DomainNameElement} - * @throws BufferUnderflowException - */ - public static DomainNameElement parse(ByteBuffer payload) { - List<String> domains = new ArrayList<>(); - while (payload.hasRemaining()) { - // Use latin-1 to decode for now - safe for ASCII and retains encoding - domains.add(ByteBufferReader.readStringWithByteLength( - payload, StandardCharsets.ISO_8859_1)); - } - return new DomainNameElement(domains); - } - - public List<String> getDomains() { - return Collections.unmodifiableList(mDomains); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof DomainNameElement)) { - return false; - } - DomainNameElement that = (DomainNameElement) thatObject; - return mDomains.equals(that.mDomains); - } - - @Override - public int hashCode() { - return mDomains.hashCode(); - } - - @Override - public String toString() { - return "DomainName{" + - "mDomains=" + mDomains + - '}'; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/GenericBlobElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/GenericBlobElement.java deleted file mode 100644 index f3279c8ad..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/GenericBlobElement.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.android.server.wifi.hotspot2.anqp; - -import com.android.server.wifi.hotspot2.Utils; - -import java.nio.ByteBuffer; - -/** - * ANQP Element to hold a raw, unparsed, octet blob - */ -public class GenericBlobElement extends ANQPElement { - private final byte[] mData; - - public GenericBlobElement(Constants.ANQPElementType infoID, ByteBuffer payload) { - super(infoID); - mData = new byte[payload.remaining()]; - payload.get(mData); - } - - public byte[] getData() { - return mData; - } - - @Override - public String toString() { - return "Element ID " + getID() + ": " + Utils.toHexString(mData); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElement.java deleted file mode 100644 index 2c9a2b30c..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElement.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * The Connection Capability vendor specific ANQP Element, - * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, - * section 4.5 - * - * Format: - * | ProtoPort Tuple #1 (optiional) | .... - * 4 - */ -public class HSConnectionCapabilityElement extends ANQPElement { - private final List<ProtocolPortTuple> mStatusList; - - @VisibleForTesting - public HSConnectionCapabilityElement(List<ProtocolPortTuple> statusList) { - super(Constants.ANQPElementType.HSConnCapability); - mStatusList = statusList; - } - - /** - * Parse a HSConnectionCapabilityElement from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link HSConnectionCapabilityElement} - * @throws BufferUnderflowException - */ - public static HSConnectionCapabilityElement parse(ByteBuffer payload) { - List<ProtocolPortTuple> statusList = new ArrayList<>(); - while (payload.hasRemaining()) { - statusList.add(ProtocolPortTuple.parse(payload)); - } - return new HSConnectionCapabilityElement(statusList); - } - - public List<ProtocolPortTuple> getStatusList() { - return Collections.unmodifiableList(mStatusList); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof HSConnectionCapabilityElement)) { - return false; - } - HSConnectionCapabilityElement that = (HSConnectionCapabilityElement) thatObject; - return mStatusList.equals(that.mStatusList); - } - - @Override - public int hashCode() { - return mStatusList.hashCode(); - } - - @Override - public String toString() { - return "HSConnectionCapability{" + - "mStatusList=" + mStatusList + - '}'; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/HSFriendlyNameElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/HSFriendlyNameElement.java deleted file mode 100644 index c6794c86e..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/HSFriendlyNameElement.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.android.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * The Operator Friendly Name vendor specific ANQP Element, - * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, - * section 4.3. - * - * Format: - * - * | Operator Name Duple #1 (optional) | ... - * variable - * - * | Operator Name Duple #N (optional) | - * variable - */ -public class HSFriendlyNameElement extends ANQPElement { - /** - * Maximum length for an Operator Name. Refer to Hotspot 2.0 (Release 2) Technical - * Specification section 4.3 for more info. - */ - @VisibleForTesting - public static final int MAXIMUM_OPERATOR_NAME_LENGTH = 252; - - private final List<I18Name> mNames; - - @VisibleForTesting - public HSFriendlyNameElement(List<I18Name> names) { - super(Constants.ANQPElementType.HSFriendlyName); - mNames = names; - } - - /** - * Parse a HSFriendlyNameElement from the given buffer. - * - * @param payload The buffer to read from - * @return {@link HSFriendlyNameElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static HSFriendlyNameElement parse(ByteBuffer payload) - throws ProtocolException { - List<I18Name> names = new ArrayList<I18Name>(); - while (payload.hasRemaining()) { - I18Name name = I18Name.parse(payload); - // Verify that the number of bytes for the operator name doesn't exceed the max - // allowed. - int textBytes = name.getText().getBytes(StandardCharsets.UTF_8).length; - if (textBytes > MAXIMUM_OPERATOR_NAME_LENGTH) { - throw new ProtocolException("Operator Name exceeds the maximum allowed " - + textBytes); - } - names.add(name); - } - return new HSFriendlyNameElement(names); - } - - public List<I18Name> getNames() { - return Collections.unmodifiableList(mNames); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof HSFriendlyNameElement)) { - return false; - } - HSFriendlyNameElement that = (HSFriendlyNameElement) thatObject; - return mNames.equals(that.mNames); - } - - @Override - public int hashCode() { - return mNames.hashCode(); - } - - @Override - public String toString() { - return "HSFriendlyName{" + - "mNames=" + mNames + - '}'; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/HSIconFileElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/HSIconFileElement.java deleted file mode 100644 index ed0c4728e..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/HSIconFileElement.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Objects; - -/** - * The Icon Binary File vendor specific ANQP Element, - * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, - * section 4.10. - * - * Format: - * - * | Status Code | Type Length | Type | Data Length | Data | - * 1 1 variable 2 variable - * - */ -public class HSIconFileElement extends ANQPElement { - private static final String TAG = "HSIconFileElement"; - - /** - * Icon download status code. - */ - public static final int STATUS_CODE_SUCCESS = 0; - public static final int STATUS_CODE_FILE_NOT_FOUND = 1; - public static final int STATUS_CODE_UNSPECIFIED_ERROR = 2; - - private final int mStatusCode; - private final String mIconType; - private final byte[] mIconData; - - @VisibleForTesting - public HSIconFileElement(int statusCode, String iconType, byte[] iconData) { - super(Constants.ANQPElementType.HSIconFile); - mStatusCode = statusCode; - mIconType = iconType; - mIconData = iconData; - } - - /** - * Parse a HSIconFileElement from the given buffer. - * - * @param payload The buffer to read from - * @return {@link HSIconFileElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static HSIconFileElement parse(ByteBuffer payload) - throws ProtocolException { - // Parse status code. - int status = payload.get() & 0xFF; - if (status != STATUS_CODE_SUCCESS) { - // No more data if status code is not success. - Log.e(TAG, "Icon file download failed: " + status); - return new HSIconFileElement(status, null, null); - } - - // Parse icon type. - String iconType = - ByteBufferReader.readStringWithByteLength(payload, StandardCharsets.US_ASCII); - - // Parse icon data. - int iconDataLength = - (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) & 0xFFFF; - byte[] iconData = new byte[iconDataLength]; - payload.get(iconData); - - return new HSIconFileElement(status, iconType, iconData); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof HSIconFileElement)) { - return false; - } - HSIconFileElement that = (HSIconFileElement) thatObject; - return mStatusCode == that.mStatusCode - && TextUtils.equals(mIconType, that.mIconType) - && Arrays.equals(mIconData, that.mIconData); - } - - @Override - public int hashCode() { - return Objects.hash(mStatusCode, mIconType, Arrays.hashCode(mIconData)); - } - - @Override - public String toString() { - return "HSIconFileElement{" + "mStatusCode=" + mStatusCode - + "mIconType=" + mIconType + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/HSOsuProvidersElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/HSOsuProvidersElement.java deleted file mode 100644 index 146a44ca9..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/HSOsuProvidersElement.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import android.net.wifi.WifiSsid; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -/** - * The OSU Providers List vendor specific ANQP Element, - * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, - * section 4.8. - * - * Format: - * - * | OSU SSID Length | OSU SSID | Number of OSU Providers | Provider #1 | ... - * 1 variable 1 variable - * - */ -public class HSOsuProvidersElement extends ANQPElement { - /** - * Maximum length for a SSID. Refer to IEEE 802.11-2012 Section 8.4.2.2 - * for more info. - */ - @VisibleForTesting - public static final int MAXIMUM_OSU_SSID_LENGTH = 32; - - private final WifiSsid mOsuSsid; - private final List<OsuProviderInfo> mProviders; - - @VisibleForTesting - public HSOsuProvidersElement(WifiSsid osuSsid, List<OsuProviderInfo> providers) { - super(Constants.ANQPElementType.HSOSUProviders); - mOsuSsid = osuSsid; - mProviders = providers; - } - - /** - * Parse a HSOsuProvidersElement from the given buffer. - * - * @param payload The buffer to read from - * @return {@link HSOsuProvidersElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static HSOsuProvidersElement parse(ByteBuffer payload) - throws ProtocolException { - int ssidLength = payload.get() & 0xFF; - if (ssidLength > MAXIMUM_OSU_SSID_LENGTH) { - throw new ProtocolException("Invalid SSID length: " + ssidLength); - } - byte[] ssidBytes = new byte[ssidLength]; - payload.get(ssidBytes); - - int numProviders = payload.get() & 0xFF; - List<OsuProviderInfo> providers = new ArrayList<>(); - while (numProviders > 0) { - providers.add(OsuProviderInfo.parse(payload)); - numProviders--; - } - - return new HSOsuProvidersElement(WifiSsid.createFromByteArray(ssidBytes), providers); - } - - public WifiSsid getOsuSsid() { - return mOsuSsid; - } - - public List<OsuProviderInfo> getProviders() { - return Collections.unmodifiableList(mProviders); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof HSOsuProvidersElement)) { - return false; - } - HSOsuProvidersElement that = (HSOsuProvidersElement) thatObject; - return (mOsuSsid == null ? that.mOsuSsid == null : mOsuSsid.equals(that.mOsuSsid)) - && (mProviders == null ? that.mProviders == null - : mProviders.equals(that.mProviders)); - } - - @Override - public int hashCode() { - return Objects.hash(mOsuSsid, mProviders); - } - - @Override - public String toString() { - return "OSUProviders{" + "mOsuSsid=" + mOsuSsid + ", mProviders=" + mProviders + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElement.java deleted file mode 100644 index b55fefb9b..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElement.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.net.ProtocolException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * The WAN Metrics vendor specific ANQP Element, - * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, - * section 4.4 - * - * Format: - * | WAN Info | Downlink Speed | Uplink Speed | Downlink Load | Uplink Load | LMD | - * 1 4 4 1 1 2 - * - * WAN Info Format: - * | Link Status | Symmetric Link | At Capacity | Reserved | - * B0 B1 B2 B3 B4 - B7 - */ -public class HSWanMetricsElement extends ANQPElement { - public static final int LINK_STATUS_RESERVED = 0; - public static final int LINK_STATUS_UP = 1; - public static final int LINK_STATUS_DOWN = 2; - public static final int LINK_STATUS_TEST = 3; - - @VisibleForTesting - public static final int EXPECTED_BUFFER_SIZE = 13; - - @VisibleForTesting - public static final int LINK_STATUS_MASK = (1 << 0 | 1 << 1); - - @VisibleForTesting - public static final int SYMMETRIC_LINK_MASK = 1 << 2; - - @VisibleForTesting - public static final int AT_CAPACITY_MASK = 1 << 3; - - private static final int MAX_LOAD = 256; - - private final int mStatus; - private final boolean mSymmetric; - private final boolean mCapped; - private final long mDownlinkSpeed; - private final long mUplinkSpeed; - private final int mDownlinkLoad; - private final int mUplinkLoad; - private final int mLMD; // Load Measurement Duration. - - @VisibleForTesting - public HSWanMetricsElement(int status, boolean symmetric, boolean capped, long downlinkSpeed, - long uplinkSpeed, int downlinkLoad, int uplinkLoad, int lmd) { - super(Constants.ANQPElementType.HSWANMetrics); - mStatus = status; - mSymmetric = symmetric; - mCapped = capped; - mDownlinkSpeed = downlinkSpeed; - mUplinkSpeed = uplinkSpeed; - mDownlinkLoad = downlinkLoad; - mUplinkLoad = uplinkLoad; - mLMD = lmd; - } - - /** - * Parse a HSWanMetricsElement from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link HSWanMetricsElement} - * @throws ProtocolException - */ - public static HSWanMetricsElement parse(ByteBuffer payload) - throws ProtocolException { - if (payload.remaining() != EXPECTED_BUFFER_SIZE) { - throw new ProtocolException("Unexpected buffer size: " + payload.remaining()); - } - - int wanInfo = payload.get() & 0xFF; - int status = wanInfo & LINK_STATUS_MASK; - boolean symmetric = (wanInfo & SYMMETRIC_LINK_MASK) != 0; - boolean capped = (wanInfo & AT_CAPACITY_MASK) != 0; - long downlinkSpeed = ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 4) - & 0xFFFFFFFFL; - long uplinkSpeed = ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 4) - & 0xFFFFFFFFL; - int downlinkLoad = payload.get() & 0xFF; - int uplinkLoad = payload.get() & 0xFF; - int lmd = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) & 0xFFFF; - return new HSWanMetricsElement(status, symmetric, capped, downlinkSpeed, uplinkSpeed, - downlinkLoad, uplinkLoad, lmd); - } - - public int getStatus() { - return mStatus; - } - - public boolean isSymmetric() { - return mSymmetric; - } - - public boolean isCapped() { - return mCapped; - } - - public long getDownlinkSpeed() { - return mDownlinkSpeed; - } - - public long getUplinkSpeed() { - return mUplinkSpeed; - } - - public int getDownlinkLoad() { - return mDownlinkLoad; - } - - public int getUplinkLoad() { - return mUplinkLoad; - } - - public int getLMD() { - return mLMD; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof HSWanMetricsElement)) { - return false; - } - HSWanMetricsElement that = (HSWanMetricsElement) thatObject; - return mStatus == that.mStatus - && mSymmetric == that.mSymmetric - && mCapped == that.mCapped - && mDownlinkSpeed == that.mDownlinkSpeed - && mUplinkSpeed == that.mUplinkSpeed - && mDownlinkLoad == that.mDownlinkLoad - && mUplinkLoad == that.mUplinkLoad - && mLMD == that.mLMD; - } - - @Override - public int hashCode() { - return (int) (mStatus + mDownlinkSpeed + mUplinkSpeed + mDownlinkLoad - + mUplinkLoad + mLMD); - } - - @Override - public String toString() { - return String.format("HSWanMetrics{mStatus=%s, mSymmetric=%s, mCapped=%s, " + - "mDlSpeed=%d, mUlSpeed=%d, mDlLoad=%f, mUlLoad=%f, mLMD=%d}", - mStatus, mSymmetric, mCapped, - mDownlinkSpeed, mUplinkSpeed, - mDownlinkLoad * 100.0 / MAX_LOAD, - mUplinkLoad * 100.0 / MAX_LOAD, - mLMD); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/I18Name.java b/service/java/com/android/server/wifi/hotspot2/anqp/I18Name.java deleted file mode 100644 index 17ce48395..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/I18Name.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Locale; - -/** - * A generic Internationalized name field used in the Operator Friendly Name ANQP element - * (see HS2.0 R2 Spec 4.2) and the Venue Name ANQP element (see 802.11-2012 8.4.4.4). - * - * Format: - * - * | Length | Language Code | Name | - * 1 3 variable - */ -public class I18Name { - @VisibleForTesting - public static final int LANGUAGE_CODE_LENGTH = 3; - - @VisibleForTesting - public static final int MINIMUM_LENGTH = LANGUAGE_CODE_LENGTH; - - private final String mLanguage; - private final Locale mLocale; - private final String mText; - - @VisibleForTesting - public I18Name(String language, Locale locale, String text) { - mLanguage = language; - mLocale = locale; - mText = text; - } - - /** - * Parse a I18Name from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link I18Name} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static I18Name parse(ByteBuffer payload) throws ProtocolException { - // Retrieve the length field. - int length = payload.get() & 0xFF; - - // Check for the minimum required length. - if (length < MINIMUM_LENGTH) { - throw new ProtocolException("Invalid length: " + length); - } - - // Read the language string. - String language = ByteBufferReader.readString( - payload, LANGUAGE_CODE_LENGTH, StandardCharsets.US_ASCII).trim(); - Locale locale; - try { - // The language code is a two or three character language code defined in ISO-639. - locale = new Locale.Builder().setLanguage(language).build(); - } catch (Exception e) { - throw new ProtocolException("Invalid language: " + language); - } - // Read the text string. - String text = ByteBufferReader.readString(payload, length - LANGUAGE_CODE_LENGTH, - StandardCharsets.UTF_8); - return new I18Name(language, locale, text); - } - - public String getLanguage() { - return mLanguage; - } - - public Locale getLocale() { - return mLocale; - } - - public String getText() { - return mText; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof I18Name)) { - return false; - } - - I18Name that = (I18Name) thatObject; - return TextUtils.equals(mLanguage, that.mLanguage) - && TextUtils.equals(mText, that.mText); - } - - @Override - public int hashCode() { - int result = mLanguage.hashCode(); - result = 31 * result + mText.hashCode(); - return result; - } - - @Override - public String toString() { - return mText + ':' + mLocale.getLanguage(); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/IPAddressTypeAvailabilityElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/IPAddressTypeAvailabilityElement.java deleted file mode 100644 index ed8f8c19f..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/IPAddressTypeAvailabilityElement.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.android.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.ByteBuffer; -import java.util.HashSet; -import java.util.Set; - -/** - * The IP Address Type availability ANQP Element, IEEE802.11-2012 section 8.4.4.9 - * - * Format: - * - * | IP Address | - * 1 - * b0 b7 - * | IPv6 Address | IPv4 Address | - * 2 bits 6 bits - * - * IPv4 Address field values: - * 0 - Address type not available - * 1 - Public IPv4 address available - * 2 - Port-restricted IPv4 address available - * 3 - Single NATed private IPv4 address available - * 4 - Single NATed private IPv4 address available - * 5 - Port-restricted IPv4 address and single NATed IPv4 address available - * 6 - Port-restricted IPv4 address and double NATed IPv4 address available - * 7 - Availability of the address type is not known - * - * IPv6 Address field values: - * 0 - Address type not available - * 1 - Address type not available - * 2 - Availability of the address type not known - * - */ -public class IPAddressTypeAvailabilityElement extends ANQPElement { - @VisibleForTesting - public static final int EXPECTED_BUFFER_LENGTH = 1; - - /** - * Constants for IPv4 availability. - */ - public static final int IPV4_NOT_AVAILABLE = 0; - public static final int IPV4_PUBLIC = 1; - public static final int IPV4_PORT_RESTRICTED = 2; - public static final int IPV4_SINGLE_NAT = 3; - public static final int IPV4_DOUBLE_NAT = 4; - public static final int IPV4_PORT_RESTRICTED_AND_SINGLE_NAT = 5; - public static final int IPV4_PORT_RESTRICTED_AND_DOUBLE_NAT = 6; - public static final int IPV4_UNKNOWN = 7; - private static final Set<Integer> IPV4_AVAILABILITY = new HashSet<Integer>(); - static { - IPV4_AVAILABILITY.add(IPV4_NOT_AVAILABLE); - IPV4_AVAILABILITY.add(IPV4_PUBLIC); - IPV4_AVAILABILITY.add(IPV4_PORT_RESTRICTED); - IPV4_AVAILABILITY.add(IPV4_SINGLE_NAT); - IPV4_AVAILABILITY.add(IPV4_DOUBLE_NAT); - IPV4_AVAILABILITY.add(IPV4_PORT_RESTRICTED_AND_SINGLE_NAT); - IPV4_AVAILABILITY.add(IPV4_PORT_RESTRICTED_AND_DOUBLE_NAT); - } - - /** - * Constants for IPv6 availability. - */ - public static final int IPV6_NOT_AVAILABLE = 0; - public static final int IPV6_AVAILABLE = 1; - public static final int IPV6_UNKNOWN = 2; - private static final Set<Integer> IPV6_AVAILABILITY = new HashSet<Integer>(); - static { - IPV6_AVAILABILITY.add(IPV6_NOT_AVAILABLE); - IPV6_AVAILABILITY.add(IPV6_AVAILABLE); - IPV6_AVAILABILITY.add(IPV6_UNKNOWN); - } - - private static final int IPV4_AVAILABILITY_MASK = 0x3F; - private static final int IPV6_AVAILABILITY_MASK = 0x3; - - private final int mV4Availability; - private final int mV6Availability; - - @VisibleForTesting - public IPAddressTypeAvailabilityElement(int v4Availability, int v6Availability) { - super(Constants.ANQPElementType.ANQPIPAddrAvailability); - mV4Availability = v4Availability; - mV6Availability = v6Availability; - } - - /** - * Parse an IPAddressTypeAvailabilityElement from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link IPAddressTypeAvailabilityElement} - * @throws ProtocolException - */ - public static IPAddressTypeAvailabilityElement parse(ByteBuffer payload) - throws ProtocolException { - if (payload.remaining() != EXPECTED_BUFFER_LENGTH) { - throw new ProtocolException("Unexpected buffer length: " + payload.remaining()); - } - - int ipField = payload.get() & 0xFF; - - int v6Availability = ipField & IPV6_AVAILABILITY_MASK; - if (!IPV6_AVAILABILITY.contains(v6Availability)) { - v6Availability = IPV6_UNKNOWN; - } - - int v4Availability = (ipField >> 2) & IPV4_AVAILABILITY_MASK; - if (!IPV4_AVAILABILITY.contains(v4Availability)) { - v4Availability = IPV4_UNKNOWN; - } - - return new IPAddressTypeAvailabilityElement(v4Availability, v6Availability); - } - - public int getV4Availability() { - return mV4Availability; - } - - public int getV6Availability() { - return mV6Availability; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof IPAddressTypeAvailabilityElement)) { - return false; - } - IPAddressTypeAvailabilityElement that = (IPAddressTypeAvailabilityElement) thatObject; - return mV4Availability == that.mV4Availability && mV6Availability == that.mV6Availability; - } - - @Override - public int hashCode() { - return mV4Availability << 2 + mV6Availability; - } - - @Override - public String toString() { - return "IPAddressTypeAvailability{" + - "mV4Availability=" + mV4Availability + - ", mV6Availability=" + mV6Availability + - '}'; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/IconInfo.java b/service/java/com/android/server/wifi/hotspot2/anqp/IconInfo.java deleted file mode 100644 index e35ca4502..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/IconInfo.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.Objects; - -/** - * The Icons available OSU Providers sub field, as specified in - * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, - * section 4.8.1.4 - * - * Format: - * - * | Width | Height | Language | Type Length | Type | Filename Length | Filename | - * 2 2 3 1 variable 1 variable - */ -public class IconInfo { - private static final int LANGUAGE_CODE_LENGTH = 3; - - private final int mWidth; - private final int mHeight; - private final String mLanguage; - private final String mIconType; - private final String mFileName; - - @VisibleForTesting - public IconInfo(int width, int height, String language, String iconType, String fileName) { - mWidth = width; - mHeight = height; - mLanguage = language; - mIconType = iconType; - mFileName = fileName; - } - - /** - * Parse a IconInfo from the given buffer. - * - * @param payload The buffer to read from - * @return {@link IconInfo} - * @throws BufferUnderflowException - */ - public static IconInfo parse(ByteBuffer payload) { - int width = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) - & 0xFFFF; - int height = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) - & 0xFFFF; - - // Read the language string. - String language = ByteBufferReader.readString( - payload, LANGUAGE_CODE_LENGTH, StandardCharsets.US_ASCII).trim(); - - String iconType = - ByteBufferReader.readStringWithByteLength(payload, StandardCharsets.US_ASCII); - String fileName = - ByteBufferReader.readStringWithByteLength(payload, StandardCharsets.UTF_8); - - return new IconInfo(width, height, language, iconType, fileName); - } - - public int getWidth() { - return mWidth; - } - - public int getHeight() { - return mHeight; - } - - public String getLanguage() { - return mLanguage; - } - - public String getIconType() { - return mIconType; - } - - public String getFileName() { - return mFileName; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof IconInfo)) { - return false; - } - - IconInfo that = (IconInfo) thatObject; - return mWidth == that.mWidth - && mHeight == that.mHeight - && TextUtils.equals(mLanguage, that.mLanguage) - && TextUtils.equals(mIconType, that.mIconType) - && TextUtils.equals(mFileName, that.mFileName); - } - - @Override - public int hashCode() { - return Objects.hash(mWidth, mHeight, mLanguage, mIconType, mFileName); - } - - @Override - public String toString() { - return "IconInfo{" - + "Width=" + mWidth - + ", Height=" + mHeight - + ", Language=" + mLanguage - + ", IconType='" + mIconType + "\'" - + ", FileName='" + mFileName + "\'" - + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java deleted file mode 100644 index 7b3144969..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; -import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * The NAI Realm Data ANQP sub-element, IEEE802.11-2012 section 8.4.4.10 figure 8-418. - * - * Format: - * | Length | Encoding | NAIRealm Length | NAIRealm | EAPMethod Count | EAPMethod #1 (optional) | - * 2 1 1 variable 1 variable - */ -public class NAIRealmData { - /** - * Mask for determining NAI Realm String encoding type. - */ - @VisibleForTesting - public static final int NAI_ENCODING_UTF8_MASK = 0x1; - - @VisibleForTesting - public static final String NAI_REALM_STRING_SEPARATOR = ";"; - - private final List<String> mRealms; - private final List<EAPMethod> mEAPMethods; - - @VisibleForTesting - public NAIRealmData(List<String> realms, List<EAPMethod> eapMethods) { - mRealms = realms; - mEAPMethods = eapMethods; - } - - /** - * Parse a NAIRealmData from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link NAIRealmElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static NAIRealmData parse(ByteBuffer payload) throws ProtocolException { - // Read and verify the length field. - int length = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) - & 0xFFFF; - if (length > payload.remaining()) { - throw new ProtocolException("Invalid data length: " + length); - } - - // Read the encoding field. - boolean utf8 = (payload.get() & NAI_ENCODING_UTF8_MASK) != 0; - - // Read the realm string. - String realm = ByteBufferReader.readStringWithByteLength( - payload, utf8 ? StandardCharsets.UTF_8 : StandardCharsets.US_ASCII); - List<String> realmList = Arrays.asList(realm.split(NAI_REALM_STRING_SEPARATOR)); - - // Read the EAP methods. - int methodCount = payload.get() & 0xFF; - List<EAPMethod> eapMethodList = new ArrayList<>(); - while (methodCount > 0) { - eapMethodList.add(EAPMethod.parse(payload)); - methodCount--; - } - return new NAIRealmData(realmList, eapMethodList); - } - - public List<String> getRealms() { - return Collections.unmodifiableList(mRealms); - } - - public List<EAPMethod> getEAPMethods() { - return Collections.unmodifiableList(mEAPMethods); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof NAIRealmData)) { - return false; - } - NAIRealmData that = (NAIRealmData) thatObject; - return mRealms.equals(that.mRealms) && mEAPMethods.equals(that.mEAPMethods); - } - - @Override - public int hashCode() { - return mRealms.hashCode() * 31 + mEAPMethods.hashCode(); - } - - @Override - public String toString() { - return "NAIRealmElement{mRealms=" + mRealms + " mEAPMethods=" + mEAPMethods + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java deleted file mode 100644 index 6f18bad7a..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - - -/** - * The NAI (Network Access Identifier) Realm ANQP Element, IEEE802.11-2012 section 8.4.4.10. - * - * Format: - * | NAI Realm Count (optional) | NAI Realm Data #1 (optional) | .... - * 2 variable - */ -public class NAIRealmElement extends ANQPElement { - private final List<NAIRealmData> mRealmDataList; - - @VisibleForTesting - public NAIRealmElement(List<NAIRealmData> realmDataList) { - super(Constants.ANQPElementType.ANQPNAIRealm); - mRealmDataList = realmDataList; - } - - /** - * Parse a NAIRealmElement from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link NAIRealmElement} - * @throws BufferUnderflowException - */ - public static NAIRealmElement parse(ByteBuffer payload) - throws ProtocolException { - List<NAIRealmData> realmDataList = new ArrayList<>(); - if (payload.hasRemaining()) { - int count = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) - & 0xFFFF; - while (count > 0) { - realmDataList.add(NAIRealmData.parse(payload)); - count--; - } - } - return new NAIRealmElement(realmDataList); - } - - public List<NAIRealmData> getRealmDataList() { - return Collections.unmodifiableList(mRealmDataList); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof NAIRealmElement)) { - return false; - } - NAIRealmElement that = (NAIRealmElement) thatObject; - return mRealmDataList.equals(that.mRealmDataList); - } - - @Override - public int hashCode() { - return mRealmDataList.hashCode(); - } - - @Override - public String toString() { - return "NAIRealmElement{mRealmDataList=" + mRealmDataList + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/OsuProviderInfo.java b/service/java/com/android/server/wifi/hotspot2/anqp/OsuProviderInfo.java deleted file mode 100644 index bc66ff6f0..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/OsuProviderInfo.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import android.net.Uri; -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; - -/** - * The OSU Provider subfield in the OSU Providers List ANQP Element, - * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, - * section 4.8.1 - * - * Format: - * - * | Length | Friendly Name Length | Friendly Name #1 | ... | Friendly Name #n | - * 2 2 variable variable - * | Server URI length | Server URI | Method List Length | Method List | - * 1 variable 1 variable - * | Icon Available Length | Icon Available | NAI Length | NAI | Description Length | - * 2 variable 1 variable 2 - * | Description #1 | ... | Description #n | - * variable variable - * - * | Operator Name Duple #N (optional) | - * variable - */ -public class OsuProviderInfo { - /** - * The raw payload should minimum include the following fields: - * - Friendly Name Length (2) - * - Server URI Length (1) - * - Method List Length (1) - * - Icon Available Length (2) - * - NAI Length (1) - * - Description Length (2) - */ - @VisibleForTesting - public static final int MINIMUM_LENGTH = 9; - - /** - * Maximum octets for a I18N string. - */ - private static final int MAXIMUM_I18N_STRING_LENGTH = 252; - - private final Map<String, String> mFriendlyNames; - private final Uri mServerUri; - private final List<Integer> mMethodList; - private final List<IconInfo> mIconInfoList; - private final String mNetworkAccessIdentifier; - private final List<I18Name> mServiceDescriptions; - - @VisibleForTesting - public OsuProviderInfo(List<I18Name> friendlyNames, Uri serverUri, List<Integer> methodList, - List<IconInfo> iconInfoList, String nai, List<I18Name> serviceDescriptions) { - mFriendlyNames = new HashMap<>(); - if (friendlyNames != null) { - friendlyNames.forEach( - e -> mFriendlyNames.put(e.getLocale().getLanguage(), e.getText())); - } - mServerUri = serverUri; - mMethodList = methodList; - mIconInfoList = iconInfoList; - mNetworkAccessIdentifier = nai; - mServiceDescriptions = serviceDescriptions; - } - - /** - * Parse a OsuProviderInfo from the given buffer. - * - * @param payload The buffer to read from - * @return {@link OsuProviderInfo} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static OsuProviderInfo parse(ByteBuffer payload) - throws ProtocolException { - // Parse length field. - int length = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) - & 0xFFFF; - if (length < MINIMUM_LENGTH) { - throw new ProtocolException("Invalid length value: " + length); - } - - // Parse friendly names. - int friendlyNameLength = - (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) & 0xFFFF; - ByteBuffer friendlyNameBuffer = getSubBuffer(payload, friendlyNameLength); - List<I18Name> friendlyNameList = parseI18Names(friendlyNameBuffer); - - // Parse server URI. - Uri serverUri = Uri.parse( - ByteBufferReader.readStringWithByteLength(payload, StandardCharsets.UTF_8)); - - // Parse method list. - int methodListLength = payload.get() & 0xFF; - List<Integer> methodList = new ArrayList<>(); - while (methodListLength > 0) { - methodList.add(payload.get() & 0xFF); - methodListLength--; - } - - // Parse list of icon info. - int availableIconLength = - (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) & 0xFFFF; - ByteBuffer iconBuffer = getSubBuffer(payload, availableIconLength); - List<IconInfo> iconInfoList = new ArrayList<>(); - while (iconBuffer.hasRemaining()) { - iconInfoList.add(IconInfo.parse(iconBuffer)); - } - - // Parse Network Access Identifier. - String nai = ByteBufferReader.readStringWithByteLength(payload, StandardCharsets.UTF_8); - - // Parse service descriptions. - int serviceDescriptionLength = - (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) & 0xFFFF; - ByteBuffer descriptionsBuffer = getSubBuffer(payload, serviceDescriptionLength); - List<I18Name> serviceDescriptionList = parseI18Names(descriptionsBuffer); - - return new OsuProviderInfo(friendlyNameList, serverUri, methodList, iconInfoList, nai, - serviceDescriptionList); - } - - /** - * Returns friendly names for the OSU Provider. - * - * @return {@link Map} that consists of language code and friendly name expressed in the locale. - */ - public Map<String, String> getFriendlyNames() { - return mFriendlyNames; - } - - public Uri getServerUri() { - return mServerUri; - } - - public List<Integer> getMethodList() { - return Collections.unmodifiableList(mMethodList); - } - - public List<IconInfo> getIconInfoList() { - return Collections.unmodifiableList(mIconInfoList); - } - - public String getNetworkAccessIdentifier() { - return mNetworkAccessIdentifier; - } - - public List<I18Name> getServiceDescriptions() { - return Collections.unmodifiableList(mServiceDescriptions); - } - - /** - * Return the friendly Name for current language from the list of friendly names of OSU - * provider. - * - * The string matching the default locale will be returned if it is found, otherwise the string - * in english or the first string in the list will be returned if english is not found. - * A null will be returned if the list is empty. - * - * @return String matching the default locale, null otherwise - */ - public String getFriendlyName() { - if (mFriendlyNames == null || mFriendlyNames.isEmpty()) return null; - String lang = Locale.getDefault().getLanguage(); - String friendlyName = mFriendlyNames.get(lang); - if (friendlyName != null) { - return friendlyName; - } - friendlyName = mFriendlyNames.get("en"); - if (friendlyName != null) { - return friendlyName; - } - return mFriendlyNames.get(mFriendlyNames.keySet().stream().findFirst().get()); - } - - /** - * Return the service description string from the service description list. The string - * matching the default locale will be returned if it is found, otherwise the first element in - * the list will be returned. A null will be returned if the list is empty. - * - * @return service description string - */ - public String getServiceDescription() { - return getI18String(mServiceDescriptions); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof OsuProviderInfo)) { - return false; - } - OsuProviderInfo that = (OsuProviderInfo) thatObject; - return (mFriendlyNames == null ? that.mFriendlyNames == null - : mFriendlyNames.equals(that.mFriendlyNames)) - && (mServerUri == null ? that.mServerUri == null - : mServerUri.equals(that.mServerUri)) - && (mMethodList == null ? that.mMethodList == null - : mMethodList.equals(that.mMethodList)) - && (mIconInfoList == null ? that.mIconInfoList == null - : mIconInfoList.equals(that.mIconInfoList)) - && TextUtils.equals(mNetworkAccessIdentifier, that.mNetworkAccessIdentifier) - && (mServiceDescriptions == null ? that.mServiceDescriptions == null - : mServiceDescriptions.equals(that.mServiceDescriptions)); - } - - @Override - public int hashCode() { - return Objects.hash(mFriendlyNames, mServerUri, mMethodList, mIconInfoList, - mNetworkAccessIdentifier, mServiceDescriptions); - } - - @Override - public String toString() { - return "OsuProviderInfo{" - + "mFriendlyNames=" + mFriendlyNames - + ", mServerUri=" + mServerUri - + ", mMethodList=" + mMethodList - + ", mIconInfoList=" + mIconInfoList - + ", mNetworkAccessIdentifier=" + mNetworkAccessIdentifier - + ", mServiceDescriptions=" + mServiceDescriptions - + "}"; - } - - /** - * Parse list of I18N string from the given payload. - * - * @param payload The payload to parse from - * @return List of {@link I18Name} - * @throws ProtocolException - */ - private static List<I18Name> parseI18Names(ByteBuffer payload) throws ProtocolException { - List<I18Name> results = new ArrayList<>(); - while (payload.hasRemaining()) { - I18Name name = I18Name.parse(payload); - // Verify that the number of bytes for the operator name doesn't exceed the max - // allowed. - int textBytes = name.getText().getBytes(StandardCharsets.UTF_8).length; - if (textBytes > MAXIMUM_I18N_STRING_LENGTH) { - throw new ProtocolException("I18Name string exceeds the maximum allowed " - + textBytes); - } - results.add(name); - } - return results; - } - - /** - * Creates a new byte buffer whose content is a shared subsequence of - * the given buffer's content. - * - * The sub buffer will starts from |payload|'s current position - * and ends at |payload|'s current position plus |length|. The |payload|'s current - * position will advance pass |length| bytes. - * - * @param payload The original buffer - * @param length The length of the new buffer - * @return {@link ByteBuffer} - * @throws BufferUnderflowException - */ - private static ByteBuffer getSubBuffer(ByteBuffer payload, int length) { - if (payload.remaining() < length) { - throw new BufferUnderflowException(); - } - // Set the subBuffer's starting and ending position. - ByteBuffer subBuffer = payload.slice(); - subBuffer.limit(length); - // Advance the original buffer's current position. - payload.position(payload.position() + length); - return subBuffer; - } - - /** - * Return the appropriate I18 string value from the list of I18 string values. - * The string matching the default locale will be returned if it is found, otherwise the - * first string in the list will be returned. A null will be returned if the list is empty. - * - * @param i18Strings List of I18 string values - * @return String matching the default locale, null otherwise - */ - private static String getI18String(List<I18Name> i18Strings) { - for (I18Name name : i18Strings) { - if (name.getLanguage().equals(Locale.getDefault().getLanguage())) { - return name.getText(); - } - } - if (i18Strings.size() > 0) { - return i18Strings.get(0).getText(); - } - return null; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ProtocolPortTuple.java b/service/java/com/android/server/wifi/hotspot2/anqp/ProtocolPortTuple.java deleted file mode 100644 index c097ad349..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/ProtocolPortTuple.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * The ProtoPort Tuple used by Connection Capability vendor specific ANQP Element, - * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, - * section 4.5 - * - * Format: - * | IP Procotol | Port Number | Status | - * 1 2 1 - */ -public class ProtocolPortTuple { - /** - * Number of raw bytes needed for the tuple. - */ - @VisibleForTesting - public static final int RAW_BYTE_SIZE = 4; - - public static final int PROTO_STATUS_CLOSED = 0; - public static final int PROTO_STATUS_OPEN = 1; - public static final int PROTO_STATUS_UNKNOWN = 2; - - private final int mProtocol; - private final int mPort; - private final int mStatus; - - @VisibleForTesting - public ProtocolPortTuple(int protocol, int port, int status) { - mProtocol = protocol; - mPort = port; - mStatus = status; - } - - /** - * Parse a ProtocolPortTuple from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link ProtocolPortTuple} - * @throws BufferUnderflowException - */ - public static ProtocolPortTuple parse(ByteBuffer payload) { - int protocol = payload.get(); - int port = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) - & 0xFFFF; - int status = payload.get() & 0xFF; - return new ProtocolPortTuple(protocol, port, status); - } - - public int getProtocol() { - return mProtocol; - } - - public int getPort() { - return mPort; - } - - public int getStatus() { - return mStatus; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof ProtocolPortTuple)) { - return false; - } - ProtocolPortTuple that = (ProtocolPortTuple) thatObject; - return mProtocol == that.mProtocol - && mPort == that.mPort - && mStatus == that.mStatus; - } - - @Override - public int hashCode() { - return (mProtocol * 31 + mPort) * 31 + mStatus; - } - - @Override - public String toString() { - return "ProtocolTuple{" + "mProtocol=" + mProtocol + ", mPort=" + mPort - + ", mStatus=" + mStatus + '}'; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/RawByteElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/RawByteElement.java deleted file mode 100644 index 633147d45..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/RawByteElement.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; - -import java.nio.ByteBuffer; -import java.util.Arrays; - -/** - * An object holding the raw octets of an ANQP element as provided by the wpa_supplicant. - */ -public class RawByteElement extends ANQPElement { - private final byte[] mPayload; - - @VisibleForTesting - public RawByteElement(Constants.ANQPElementType infoID, byte[] payload) { - super(infoID); - mPayload = payload; - } - - /** - * Parse a RawByteElement from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link HSConnectionCapabilityElement} - */ - public static RawByteElement parse(Constants.ANQPElementType infoID, ByteBuffer payload) { - byte[] rawBytes = new byte[payload.remaining()]; - if (payload.hasRemaining()) { - payload.get(rawBytes); - } - return new RawByteElement(infoID, rawBytes); - } - - public byte[] getPayload() { - return mPayload; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof RawByteElement)) { - return false; - } - RawByteElement that = (RawByteElement) thatObject; - return getID() == that.getID() && Arrays.equals(mPayload, that.mPayload); - } - - @Override - public int hashCode() { - return Arrays.hashCode(mPayload); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElement.java deleted file mode 100644 index a40e9d63b..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElement.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.android.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; -import com.android.server.wifi.hotspot2.Utils; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * The Roaming Consortium ANQP Element, IEEE802.11-2012 section 8.4.4.7 - * - ** Format: - * - * | OI Duple #1 (optional) | ... - * variable - * - * | OI Length | OI | - * 1 variable - * - */ -public class RoamingConsortiumElement extends ANQPElement { - @VisibleForTesting - public static final int MINIMUM_OI_LENGTH = Byte.BYTES; - - @VisibleForTesting - public static final int MAXIMUM_OI_LENGTH = Long.BYTES; - - private final List<Long> mOIs; - - @VisibleForTesting - public RoamingConsortiumElement(List<Long> ois) { - super(Constants.ANQPElementType.ANQPRoamingConsortium); - mOIs = ois; - } - - /** - * Parse a VenueNameElement from the given payload. - * - * @param payload The byte buffer to read from - * @return {@link RoamingConsortiumElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static RoamingConsortiumElement parse(ByteBuffer payload) - throws ProtocolException { - List<Long> OIs = new ArrayList<Long>(); - while (payload.hasRemaining()) { - int length = payload.get() & 0xFF; - if (length < MINIMUM_OI_LENGTH || length > MAXIMUM_OI_LENGTH) { - throw new ProtocolException("Bad OI length: " + length); - } - OIs.add(ByteBufferReader.readInteger(payload, ByteOrder.BIG_ENDIAN, length)); - } - return new RoamingConsortiumElement(OIs); - } - - public List<Long> getOIs() { - return Collections.unmodifiableList(mOIs); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof RoamingConsortiumElement)) { - return false; - } - RoamingConsortiumElement that = (RoamingConsortiumElement) thatObject; - return mOIs.equals(that.mOIs); - } - - @Override - public int hashCode() { - return mOIs.hashCode(); - } - - @Override - public String toString() { - return "RoamingConsortium{mOis=[" + Utils.roamingConsortiumsToString(mOIs) + "]}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElement.java deleted file mode 100644 index d9795c63d..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElement.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - - -/** - * The 3GPP Cellular Network ANQP Element, IEEE802.11-2012 section 8.4.4.11. - * The value is embedded in a Generic container User Data (GUD). - * Refer to Annex A of 3GPP TS 24.234 version 11.3.0 for more info: - * (http://www.etsi.org/deliver/etsi_ts/124200_124299/124234/11.03.00_60/ts_124234v110300p.pdf). - * - * Format: - * | GUD Version | Length | IEI 1 | ... | IEI N| - * 1 1 variable - * - */ -public class ThreeGPPNetworkElement extends ANQPElement { - /** - * The expected protocol version number of the Generic container User Data (GUD). - */ - @VisibleForTesting - public static final int GUD_VERSION_1 = 0; - - private final List<CellularNetwork> mNetworks; - - @VisibleForTesting - public ThreeGPPNetworkElement(List<CellularNetwork> networks) { - super(Constants.ANQPElementType.ANQP3GPPNetwork); - mNetworks = networks; - } - - /** - * Parse a ThreeGPPNetworkElement from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link ThreeGPPNetworkElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static ThreeGPPNetworkElement parse(ByteBuffer payload) - throws ProtocolException { - // Verify version. - int gudVersion = payload.get() & 0xFF; - if (gudVersion != GUD_VERSION_1) { - throw new ProtocolException("Unsupported GUD version: " + gudVersion); - } - - // Verify length. - int length = payload.get() & 0xFF; - if (length != payload.remaining()) { - throw new ProtocolException("Mismatch length and buffer size: length=" + length - + " bufferSize=" + payload.remaining()); - } - - // Parse each IEI (Information Element Identity) content. - List<CellularNetwork> networks = new ArrayList<>(); - while (payload.hasRemaining()) { - CellularNetwork network = CellularNetwork.parse(payload); - if (network != null) { - networks.add(network); - } - } - return new ThreeGPPNetworkElement(networks); - } - - public List<CellularNetwork> getNetworks() { - return Collections.unmodifiableList(mNetworks); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof ThreeGPPNetworkElement)) { - return false; - } - ThreeGPPNetworkElement that = (ThreeGPPNetworkElement) thatObject; - return mNetworks.equals(that.mNetworks); - - } - - @Override - public int hashCode() { - return mNetworks.hashCode(); - } - - @Override - public String toString() { - return "ThreeGPPNetwork{mNetworks=" + mNetworks + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/VenueNameElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/VenueNameElement.java deleted file mode 100644 index 9a4e64b39..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/VenueNameElement.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * The Venue Name ANQP Element, IEEE802.11-2012 section 8.4.4.4. - * - * Format: - * - * | Venue Info | Venue Name Duple #1 (optional) | ... - * 2 variable - * - * | Venue Name Duple #N (optional) | - * variable - * - * Refer to {@link I18Name} for the format of the Venue Name Duple - * fields. - */ -public class VenueNameElement extends ANQPElement { - @VisibleForTesting - public static final int VENUE_INFO_LENGTH = 2; - - /** - * Maximum length for a Venue Name. Refer to IEEE802.11-2012 section 8.4.4.4 for more info. - */ - @VisibleForTesting - public static final int MAXIMUM_VENUE_NAME_LENGTH = 252; - - private final List<I18Name> mNames; - - @VisibleForTesting - public VenueNameElement(List<I18Name> names) { - super(Constants.ANQPElementType.ANQPVenueName); - mNames = names; - } - - /** - * Parse a VenueNameElement from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link VenueNameElement} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - public static VenueNameElement parse(ByteBuffer payload) - throws ProtocolException { - // Skip the Venue Info field, which we don't use. - for (int i = 0; i < VENUE_INFO_LENGTH; ++i) { - payload.get(); - } - - List<I18Name> names = new ArrayList<I18Name>(); - while (payload.hasRemaining()) { - I18Name name = I18Name.parse(payload); - // Verify that the number of octets for the venue name doesn't exceed the max allowed. - int textBytes = name.getText().getBytes(StandardCharsets.UTF_8).length; - if (textBytes > MAXIMUM_VENUE_NAME_LENGTH) { - throw new ProtocolException("Venue Name exceeds the maximum allowed " + textBytes); - } - names.add(name); - } - return new VenueNameElement(names); - } - - public List<I18Name> getNames() { - return Collections.unmodifiableList(mNames); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) { - return true; - } - if (!(thatObject instanceof VenueNameElement)) { - return false; - } - VenueNameElement that = (VenueNameElement) thatObject; - return mNames.equals(that.mNames); - } - - @Override - public int hashCode() { - return mNames.hashCode(); - } - - @Override - public String toString() { - return "VenueName{ mNames=" + mNames + "}"; - } - -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/AuthParam.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/AuthParam.java deleted file mode 100644 index ce4edb216..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/AuthParam.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -/** - * An Authentication parameter, part of the NAI Realm ANQP element, specified in - * IEEE802.11-2012 section 8.4.4.10, table 8-188 - */ -public abstract class AuthParam { - public static final int PARAM_TYPE_EXPANDED_EAP_METHOD = 1; - public static final int PARAM_TYPE_NON_EAP_INNER_AUTH_TYPE = 2; - public static final int PARAM_TYPE_INNER_AUTH_EAP_METHOD_TYPE = 3; - public static final int PARAM_TYPE_EXPANDED_INNER_EAP_METHOD = 4; - public static final int PARAM_TYPE_CREDENTIAL_TYPE = 5; - public static final int PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE = 6; - public static final int PARAM_TYPE_VENDOR_SPECIFIC = 221; - - private final int mAuthTypeID; - - protected AuthParam(int authTypeID) { - mAuthTypeID = authTypeID; - } - - public int getAuthTypeID() { - return mAuthTypeID; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/CredentialType.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/CredentialType.java deleted file mode 100644 index 1efc00bc5..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/CredentialType.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * The Credential Type authentication parameter, IEEE802.11-2012, table 8-188. - * Used by both Credential Type and Tunneled EAP Method Credential Type authentication - * parameter. - * - * Format: - * | Type | - * 1 - */ -public class CredentialType extends AuthParam { - public static final int CREDENTIAL_TYPE_SIM = 1; - public static final int CREDENTIAL_TYPE_USIM = 2; - public static final int CREDENTIAL_TYPE_NFC = 3; - public static final int CREDENTIAL_TYPE_HARDWARE_TOKEN = 4; - public static final int CREDENTIAL_TYPE_SOFTWARE_TOKEN = 5; - public static final int CREDENTIAL_TYPE_CERTIFICATE = 6; - public static final int CREDENTIAL_TYPE_USERNAME_PASSWORD = 7; - public static final int CREDENTIAL_TYPE_NONE = 8; - public static final int CREDENTIAL_TYPE_ANONYMOUS = 9; - public static final int CREDENTIAL_TYPE_VENDOR_SPECIFIC = 10; - - @VisibleForTesting - public static final int EXPECTED_LENGTH_VALUE = 1; - - private final int mType; - - @VisibleForTesting - public CredentialType(int authType, int credType) { - super(authType); - mType = credType; - } - - /** - * Parse a CredentialType from the given buffer. - * - * @param payload The byte buffer to read from - * @param length The length of the data - * @param tunneled Flag indicating if this is for a Tunneled EAP Method - * @return {@link CredentialType} - * @throws ProtocolException - * @throws BufferUnderflowException - */ - public static CredentialType parse(ByteBuffer payload, int length, boolean tunneled) - throws ProtocolException { - if (length != EXPECTED_LENGTH_VALUE) { - throw new ProtocolException("Invalid length: " + length); - } - int credType = payload.get() & 0xFF; - int authType = tunneled ? AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE - : AuthParam.PARAM_TYPE_CREDENTIAL_TYPE; - return new CredentialType(authType, credType); - } - - public int getType() { - return mType; - } - - @Override - public boolean equals(Object thatObject) { - if (thatObject == this) { - return true; - } - if (!(thatObject instanceof CredentialType)) { - return false; - } - CredentialType that = (CredentialType) thatObject; - return mType == that.mType; - } - - @Override - public int hashCode() { - return mType; - } - - @Override - public String toString() { - return "CredentialType{mType=" + mType + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAPMethod.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAPMethod.java deleted file mode 100644 index 6879d4135..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAPMethod.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * An EAP Method part of the NAI Realm ANQP element, specified in - * IEEE802.11-2012 section 8.4.4.10, figure 8-420 - * - * Format: - * | Length | EAP Method | Auth Param Count | Auth Param #1 (optional) | .... - * 1 1 1 variable - */ -public class EAPMethod { - private final int mEAPMethodID; - private final Map<Integer, Set<AuthParam>> mAuthParams; - - @VisibleForTesting - public EAPMethod(int methodID, Map<Integer, Set<AuthParam>> authParams) { - mEAPMethodID = methodID; - mAuthParams = authParams; - } - - /** - * Parse a EAPMethod from the given buffer. - * - * @param payload The byte buffer to read from - * @return {@link EAPMethod} - * @throws ProtocolException - * @throws BufferUnderflowException - */ - public static EAPMethod parse(ByteBuffer payload) throws ProtocolException { - // Read and verify the length field. - int length = payload.get() & 0xFF; - if (length > payload.remaining()) { - throw new ProtocolException("Invalid data length: " + length); - } - - int methodID = payload.get() & 0xFF; - int authCount = payload.get() & 0xFF; - Map<Integer, Set<AuthParam>> authParams = new HashMap<>(); - while (authCount > 0) { - addAuthParam(authParams, parseAuthParam(payload)); - authCount--; - } - return new EAPMethod(methodID, authParams); - } - - /** - * Parse a AuthParam from the given buffer. - * - * Format: - * | Auth ID | Length | Value | - * 1 1 variable - * - * @param payload The byte buffer to read from - * @return {@link AuthParam} - * @throws BufferUnderflowException - * @throws ProtocolException - */ - private static AuthParam parseAuthParam(ByteBuffer payload) throws ProtocolException { - int authID = payload.get() & 0xFF; - int length = payload.get() & 0xFF; - switch (authID) { - case AuthParam.PARAM_TYPE_EXPANDED_EAP_METHOD: - return ExpandedEAPMethod.parse(payload, length, false); - case AuthParam.PARAM_TYPE_NON_EAP_INNER_AUTH_TYPE: - return NonEAPInnerAuth.parse(payload, length); - case AuthParam.PARAM_TYPE_INNER_AUTH_EAP_METHOD_TYPE: - return InnerAuthEAP.parse(payload, length); - case AuthParam.PARAM_TYPE_EXPANDED_INNER_EAP_METHOD: - return ExpandedEAPMethod.parse(payload, length, true); - case AuthParam.PARAM_TYPE_CREDENTIAL_TYPE: - return CredentialType.parse(payload, length, false); - case AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE: - return CredentialType.parse(payload, length, true); - case AuthParam.PARAM_TYPE_VENDOR_SPECIFIC: - return VendorSpecificAuth.parse(payload, length); - default: - throw new ProtocolException("Unknow Auth Type ID: " + authID); - } - } - - /** - * Add an AuthParam to a map of authentication parameters. It is possible to have - * multiple authentication parameters for the same type. - * - * @param paramsMap The authentication parameter map to add the new parameter to - * @param authParam The authentication parameter to add - */ - private static void addAuthParam(Map<Integer, Set<AuthParam>> paramsMap, - AuthParam authParam) { - Set<AuthParam> authParams = paramsMap.get(authParam.getAuthTypeID()); - if (authParams == null) { - authParams = new HashSet<>(); - paramsMap.put(authParam.getAuthTypeID(), authParams); - } - authParams.add(authParam); - } - - public Map<Integer, Set<AuthParam>> getAuthParams() { - return Collections.unmodifiableMap(mAuthParams); - } - - public int getEAPMethodID() { - return mEAPMethodID; - } - - @Override - public boolean equals(Object thatObject) { - if (thatObject == this) { - return true; - } - if (!(thatObject instanceof EAPMethod)) { - return false; - } - EAPMethod that = (EAPMethod) thatObject; - return mEAPMethodID == that.mEAPMethodID && mAuthParams.equals(that.mAuthParams); - } - - @Override - public int hashCode() { - return mEAPMethodID * 31 + mAuthParams.hashCode(); - } - - @Override - public String toString() { - return "EAPMethod{mEAPMethodID=" + mEAPMethodID + " mAuthParams=" + mAuthParams + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethod.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethod.java deleted file mode 100644 index a2a303f5e..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethod.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ByteBufferReader; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * The Expanded EAP Method authentication parameter, IEEE802.11-2012, table 8-189. - * Used by both Expanded EAP Method and Expanded Inner EAP Method. - * - * Format: - * | Vendor ID | Vendor Type | - * 3 4 - */ -public class ExpandedEAPMethod extends AuthParam { - public static final int EXPECTED_LENGTH_VALUE = 7; - - private final int mVendorID; - private final long mVendorType; - - @VisibleForTesting - public ExpandedEAPMethod(int authType, int vendorID, long vendorType) { - super(authType); - mVendorID = vendorID; - mVendorType = vendorType; - } - - /** - * Parse a ExpandedEAPMethod from the given buffer. - * - * @param payload The byte buffer to read from - * @param length The length of the data - * @param inner Flag indicating if this is for an Inner EAP method - * @return {@link ExpandedEAPMethod} - * @throws ProtocolException - * @throws BufferUnderflowException - */ - public static ExpandedEAPMethod parse(ByteBuffer payload, int length, boolean inner) - throws ProtocolException { - if (length != EXPECTED_LENGTH_VALUE) { - throw new ProtocolException("Invalid length value: " + length); - } - - // Vendor ID and Vendor Type are expressed in big-endian byte order according to - // the spec. - int vendorID = (int) ByteBufferReader.readInteger(payload, ByteOrder.BIG_ENDIAN, 3) - & 0xFFFFFF; - long vendorType = ByteBufferReader.readInteger(payload, ByteOrder.BIG_ENDIAN, 4) - & 0xFFFFFFFF; - - int authType = inner ? AuthParam.PARAM_TYPE_EXPANDED_INNER_EAP_METHOD - : AuthParam.PARAM_TYPE_EXPANDED_EAP_METHOD; - return new ExpandedEAPMethod(authType, vendorID, vendorType); - } - - public int getVendorID() { - return mVendorID; - } - - public long getVendorType() { - return mVendorType; - } - - @Override - public boolean equals(Object thatObject) { - if (thatObject == this) { - return true; - } - if (!(thatObject instanceof ExpandedEAPMethod)) { - return false; - } - ExpandedEAPMethod that = (ExpandedEAPMethod) thatObject; - return mVendorID == that.mVendorID && mVendorType == that.mVendorType; - } - - @Override - public int hashCode() { - return (mVendorID) * 31 + (int) mVendorType; - } - - @Override - public String toString() { - return "ExpandedEAPMethod{mVendorID=" + mVendorID + " mVendorType=" + mVendorType + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAP.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAP.java deleted file mode 100644 index a7dbdac37..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAP.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * The Inner Authentication EAP Method Type authentication parameter, IEEE802.11-2012, table 8-188. - * - * Format: - * | EAP Method ID | - * 1 - */ -public class InnerAuthEAP extends AuthParam { - @VisibleForTesting - public static final int EXPECTED_LENGTH_VALUE = 1; - - private final int mEAPMethodID; - - @VisibleForTesting - public InnerAuthEAP(int eapMethodID) { - super(AuthParam.PARAM_TYPE_INNER_AUTH_EAP_METHOD_TYPE); - mEAPMethodID = eapMethodID; - } - - /** - * Parse a InnerAuthEAP from the given buffer. - * - * @param payload The byte buffer to read from - * @param length The length of the data - * @return {@link InnerAuthEAP} - * @throws ProtocolException - * @throws BufferUnderflowException - */ - public static InnerAuthEAP parse(ByteBuffer payload, int length) throws ProtocolException { - if (length != EXPECTED_LENGTH_VALUE) { - throw new ProtocolException("Invalid length: " + length); - } - int eapMethodID = payload.get() & 0xFF; - return new InnerAuthEAP(eapMethodID); - } - - public int getEAPMethodID() { - return mEAPMethodID; - } - - @Override - public boolean equals(Object thatObject) { - if (thatObject == this) { - return true; - } - if (!(thatObject instanceof InnerAuthEAP)) { - return false; - } - InnerAuthEAP that = (InnerAuthEAP) thatObject; - return mEAPMethodID == that.mEAPMethodID; - } - - @Override - public int hashCode() { - return mEAPMethodID; - } - - @Override - public String toString() { - return "InnerAuthEAP{mEAPMethodID=" + mEAPMethodID + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuth.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuth.java deleted file mode 100644 index b69339315..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuth.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import com.android.internal.annotations.VisibleForTesting; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; - -/** - * The Non-EAP Inner Authentication Type authentication parameter, IEEE802.11-2012, table 8-188. - * - * Format: - * | Type | - * 1 - */ -public class NonEAPInnerAuth extends AuthParam { - public static final int AUTH_TYPE_UNKNOWN = 0; - public static final int AUTH_TYPE_PAP = 1; - public static final int AUTH_TYPE_CHAP = 2; - public static final int AUTH_TYPE_MSCHAP = 3; - public static final int AUTH_TYPE_MSCHAPV2 = 4; - - private static final Map<String, Integer> AUTH_TYPE_MAP = new HashMap<>(); - static { - AUTH_TYPE_MAP.put("PAP", AUTH_TYPE_PAP); - AUTH_TYPE_MAP.put("CHAP", AUTH_TYPE_CHAP); - AUTH_TYPE_MAP.put("MS-CHAP", AUTH_TYPE_MSCHAP); - AUTH_TYPE_MAP.put("MS-CHAP-V2", AUTH_TYPE_MSCHAPV2); - } - - @VisibleForTesting - public static final int EXPECTED_LENGTH_VALUE = 1; - - private final int mAuthType; - - public NonEAPInnerAuth(int authType) { - super(AuthParam.PARAM_TYPE_NON_EAP_INNER_AUTH_TYPE); - mAuthType = authType; - } - - /** - * Parse a NonEAPInnerAuth from the given buffer. - * - * @param payload The byte buffer to read from - * @param length The length of the data - * @return {@link NonEAPInnerAuth} - * @throws BufferUnderflowException - */ - public static NonEAPInnerAuth parse(ByteBuffer payload, int length) throws ProtocolException { - if (length != EXPECTED_LENGTH_VALUE) { - throw new ProtocolException("Invalid length: " + length); - } - int authType = payload.get() & 0xFF; - return new NonEAPInnerAuth(authType); - } - - /** - * Convert an authentication type string to an integer representation. - * - * @param typeStr The string of authentication type - * @return int - */ - public static int getAuthTypeID(String typeStr) { - if (AUTH_TYPE_MAP.containsKey(typeStr)) { - return AUTH_TYPE_MAP.get(typeStr).intValue(); - } - return AUTH_TYPE_UNKNOWN; - } - - @Override - public boolean equals(Object thatObject) { - if (thatObject == this) { - return true; - } - if (!(thatObject instanceof NonEAPInnerAuth)) { - return false; - } - NonEAPInnerAuth that = (NonEAPInnerAuth) thatObject; - return mAuthType == that.mAuthType; - } - - @Override - public int hashCode() { - return mAuthType; - } - - @Override - public String toString() { - return "NonEAPInnerAuth{mAuthType=" + mAuthType + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuth.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuth.java deleted file mode 100644 index 048f0d637..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuth.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import com.android.internal.annotations.VisibleForTesting; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.Arrays; - -/** - * The Vendor Specific authentication parameter, IEEE802.11-2012, table 8-188. - * - * Format: - * | Data | - * variable - */ -public class VendorSpecificAuth extends AuthParam { - private final byte[] mData; - - @VisibleForTesting - public VendorSpecificAuth(byte[] data) { - super(AuthParam.PARAM_TYPE_VENDOR_SPECIFIC); - mData = data; - } - - /** - * Parse a VendorSpecificAuth from the given buffer. - * - * @param payload The byte buffer to read from - * @param length The length of the data - * @return {@link VendorSpecificAuth} - * @throws BufferUnderflowException - */ - public static VendorSpecificAuth parse(ByteBuffer payload, int length) { - byte[] data = new byte[length]; - payload.get(data); - return new VendorSpecificAuth(data); - } - - public byte[] getData() { - return mData; - } - - @Override - public boolean equals(Object thatObject) { - if (thatObject == this) { - return true; - } - if (!(thatObject instanceof VendorSpecificAuth)) { - return false; - } - VendorSpecificAuth that = (VendorSpecificAuth) thatObject; - return Arrays.equals(mData, that.mData); - } - - @Override - public int hashCode() { - return Arrays.hashCode(mData); - } - - @Override - public String toString() { - return "VendorSpecificAuth{mData=" + Arrays.toString(mData) + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/omadm/DevDetailMo.java b/service/java/com/android/server/wifi/hotspot2/omadm/DevDetailMo.java deleted file mode 100644 index 54ab547a3..000000000 --- a/service/java/com/android/server/wifi/hotspot2/omadm/DevDetailMo.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.omadm; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.wifi.EAPConstants; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.hotspot2.SystemInfo; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.parsers.ParserConfigurationException; - -/** - * Provides serialization API for DevDetail MO (Management Object). - */ -public class DevDetailMo { - private static final String TAG = "DevDetailMo"; - // Refer to 9.2 DevDetail MO vendor specific extensions - // in the Hotspot2.0 R2 Technical Specification document in detail - @VisibleForTesting - public static final String URN = "urn:oma:mo:oma-dm-devdetail:1.0"; - @VisibleForTesting - public static final String HS20_URN = "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0"; - - private static final String MO_NAME = "DevDetail"; - - private static final String TAG_EXT = "ext"; - private static final String TAG_ORG_WIFI = "org.wi-fi"; - private static final String TAG_WIFI = "Wi-Fi"; - private static final String TAG_EAP_METHOD_LIST = "EAPMethodList"; //Required field - private static final String TAG_EAP_METHOD = "EAPMethod"; //Required field - private static final String TAG_EAP_TYPE = "EAPType"; //Required field - private static final String TAG_VENDOR_ID = "VendorId"; - private static final String TAG_VENDOR_TYPE = "VendorType"; - private static final String TAG_INNER_EAP_TYPE = "InnerEAPType"; - private static final String TAG_INNER_VENDOR_ID = "InnerVendorID"; - private static final String TAG_INNER_VENDOR_TYPE = "InnerVendorType"; - private static final String TAG_INNER_METHOD = "InnerMethod"; //Required field - - // Mobile device information related to certificates provisioned by SPs - private static final String TAG_SP_CERTIFICATE = "SPCertificate"; - private static final String TAG_CERTIFICATE_ISSUER_NAME = "CertificateIssuerName"; - - // Required if the mobile device is in possession of an IEEE 802.1ar-compliant - // manufacturing certificate and is authorized to use that certificate for - // mobile device AAA authentication - private static final String TAG_MANUFACTURING_CERT = "ManufacturingCertificate"; - // Required for a device having a SIM, but will not provide the IMSI to an SP that - // did not issue the IMSI. - private static final String TAG_IMSI = "IMSI"; - // Required for the device having a SIM. - private static final String TAG_IMEI_MEID = "IMEI_MEID"; - - private static final String TAG_WIFI_MAC_ADDR = "Wi-FiMACAddress"; // Required field - - // Required field - private static final String TAG_CLIENT_TRIGGER_REDIRECT_URI = "ClientTriggerRedirectURI"; - - private static final String TAG_OPS = "Ops"; - private static final String TAG_LAUNCH_BROWSER_TO_URI = "launchBrowserToURI"; - private static final String TAG_NEGOTIATE_CLIENT_CERT_TLS = "negotiateClientCertTLS"; - private static final String TAG_GET_CERTIFICATE = "getCertificate"; - - private static final List<String> sSupportedOps = new ArrayList<>(); - private static final String TAG_URI = "URI"; - private static final String TAG_MAX_DEPTH = "MaxDepth"; - private static final String TAG_MAX_TOT_LEN = "MaxTotLen"; - private static final String TAG_MAX_SEG_LEN = "MaxSegLen"; - private static final String TAG_OEM = "OEM"; - private static final String TAG_SW_VER = "SwV"; - private static final String TAG_LRG_ORJ = "LrgOrj"; - - private static final String INNER_METHOD_PAP = "PAP"; - private static final String INNER_METHOD_MS_CHAP = "MS-CHAP"; - private static final String INNER_METHOD_MS_CHAP_V2 = "MS-CHAP-V2"; - - private static final String IFNAME = "wlan0"; - - private static final List<Pair<Integer, String>> sEapMethods = new ArrayList<>(); - static { - sEapMethods.add(Pair.create(EAPConstants.EAP_TTLS, INNER_METHOD_MS_CHAP_V2)); - sEapMethods.add(Pair.create(EAPConstants.EAP_TTLS, INNER_METHOD_MS_CHAP)); - sEapMethods.add(Pair.create(EAPConstants.EAP_TTLS, INNER_METHOD_PAP)); - - sEapMethods.add(Pair.create(EAPConstants.EAP_TLS, null)); - sEapMethods.add(Pair.create(EAPConstants.EAP_SIM, null)); - sEapMethods.add(Pair.create(EAPConstants.EAP_AKA, null)); - sEapMethods.add(Pair.create(EAPConstants.EAP_AKA_PRIME, null)); - - sSupportedOps.add(TAG_LAUNCH_BROWSER_TO_URI); - } - - // Whether to send IMSI and IMEI information or not during OSU provisioning flow; Mandatory (as - // per standard) for mobile devices possessing a SIM card. However, it is unclear why this is - // needed. Default to false due to privacy concerns. - private static boolean sAllowToSendImsiImeiInfo = false; - - /** - * Allow or disallow to send IMSI and IMEI information during OSU provisioning flow. - * - * @param allowToSendImsiImeiInfo flag to allow/disallow to send IMSI and IMEI. - */ - @VisibleForTesting - public static void setAllowToSendImsiImeiInfo(boolean allowToSendImsiImeiInfo) { - sAllowToSendImsiImeiInfo = allowToSendImsiImeiInfo; - } - - /** - * Make a format of XML based on the DDF(Data Definition Format) of DevDetail MO. - * - * expected_output : refer to Figure 73: example sppPostDevData SOAP message in Hotspot 2.0 - * Rel 2.0 Specification document. - * @param context {@link Context} - * @param info {@link SystemInfo} - * @param redirectUri redirect uri that server uses as completion of subscription. - * @return the XML that has format of OMA DM DevDetail Management Object, <code>null</code> in - * case of any failure. - */ - public static String serializeToXml(@NonNull Context context, @NonNull SystemInfo info, - @NonNull String redirectUri) { - String macAddress = info.getMacAddress(IFNAME); - if (macAddress != null) { - macAddress = macAddress.replace(":", ""); - } - if (TextUtils.isEmpty(macAddress)) { - Log.e(TAG, "mac address is empty"); - return null; - } - MoSerializer moSerializer; - try { - moSerializer = new MoSerializer(); - } catch (ParserConfigurationException e) { - Log.e(TAG, "failed to create the MoSerializer: " + e); - return null; - } - - // Create the XML document for DevInfoMo - Document doc = moSerializer.createNewDocument(); - Element rootElement = moSerializer.createMgmtTree(doc); - rootElement.appendChild(moSerializer.writeVersion(doc)); - // <Node><NodeName>DevDetail</NodeName> - Element moNode = moSerializer.createNode(doc, MO_NAME); - - - moNode.appendChild(moSerializer.createNodeForUrn(doc, URN)); - // <Node><NodeName>Ext</NodeName> - Element extNode = moSerializer.createNode(doc, TAG_EXT); - // <Node><NodeName>org.wi-fi</NodeName> - Element orgNode = moSerializer.createNode(doc, TAG_ORG_WIFI); - orgNode.appendChild(moSerializer.createNodeForUrn(doc, HS20_URN)); - // <Node><NodeName>Wi-Fi</NodeName> - Element wifiNode = moSerializer.createNode(doc, TAG_WIFI); - // <Node><NodeName>EAPMethodList</NodeName> - Element eapMethodListNode = moSerializer.createNode(doc, TAG_EAP_METHOD_LIST); - - String tagName; - Element eapMethodNode; - - int i = 0; - for (Pair<Integer, String> entry : sEapMethods) { - tagName = String.format("%s%02d", TAG_EAP_METHOD, ++i); - eapMethodNode = moSerializer.createNode(doc, tagName); - eapMethodNode.appendChild( - moSerializer.createNodeForValue(doc, TAG_EAP_TYPE, entry.first.toString())); - if (entry.second != null) { - eapMethodNode.appendChild( - moSerializer.createNodeForValue(doc, TAG_INNER_METHOD, entry.second)); - } - eapMethodListNode.appendChild(eapMethodNode); - - } - wifiNode.appendChild(eapMethodListNode); // TAG_EAP_METHOD_LIST - - wifiNode.appendChild(moSerializer.createNodeForValue(doc, TAG_MANUFACTURING_CERT, "FALSE")); - wifiNode.appendChild(moSerializer.createNodeForValue(doc, TAG_CLIENT_TRIGGER_REDIRECT_URI, - redirectUri)); - wifiNode.appendChild(moSerializer.createNodeForValue(doc, TAG_WIFI_MAC_ADDR, macAddress)); - - // TODO(b/132188983): Inject this using WifiInjector - TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); - String imsi = telephonyManager - .createForSubscriptionId(SubscriptionManager.getDefaultDataSubscriptionId()) - .getSubscriberId(); - if (imsi != null && sAllowToSendImsiImeiInfo) { - // Don't provide the IMSI to an SP that did not issue the IMSI - wifiNode.appendChild(moSerializer.createNodeForValue(doc, TAG_IMSI, imsi)); - wifiNode.appendChild( - moSerializer.createNodeForValue(doc, TAG_IMEI_MEID, info.getDeviceId())); - } - - // <Node><NodeName>Ops</NodeName> - Element opsNode = moSerializer.createNode(doc, TAG_OPS); - for (String op: sSupportedOps) { - opsNode.appendChild(moSerializer.createNodeForValue(doc, op, "")); - } - wifiNode.appendChild(opsNode); // TAG_OPS - orgNode.appendChild(wifiNode); // TAG_WIFI - extNode.appendChild(orgNode); // TAG_ORG_WIFI - moNode.appendChild(extNode); // TAG_EXT - // <Node><NodeName>URI</NodeName> - Element uriNode = moSerializer.createNode(doc, TAG_URI); - - uriNode.appendChild(moSerializer.createNodeForValue(doc, TAG_MAX_DEPTH, "32")); - uriNode.appendChild(moSerializer.createNodeForValue(doc, TAG_MAX_TOT_LEN, "2048")); - uriNode.appendChild(moSerializer.createNodeForValue(doc, TAG_MAX_SEG_LEN, "64")); - moNode.appendChild(uriNode); // TAG_URI - - moNode.appendChild( - moSerializer.createNodeForValue(doc, TAG_OEM, info.getDeviceManufacturer())); - moNode.appendChild( - moSerializer.createNodeForValue(doc, TAG_SW_VER, info.getSoftwareVersion())); - moNode.appendChild(moSerializer.createNodeForValue(doc, TAG_LRG_ORJ, "TRUE")); - rootElement.appendChild(moNode); // TAG_DEVDETAIL - - return moSerializer.serialize(doc); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/omadm/DevInfoMo.java b/service/java/com/android/server/wifi/hotspot2/omadm/DevInfoMo.java deleted file mode 100644 index 28ebf7e56..000000000 --- a/service/java/com/android/server/wifi/hotspot2/omadm/DevInfoMo.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.omadm; - -import android.util.Log; - -import com.android.server.wifi.hotspot2.SystemInfo; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.xml.parsers.ParserConfigurationException; - -import android.annotation.NonNull; - -/** - * Provides serialization API for DevInfo MO (Management Object). - * - * Devinfo---|- DevId - * |- Man - * |- Mod - * |- Dmv - * |- Lang - */ -public class DevInfoMo { - public static final String TAG = "DevInfoMo"; - public static final String URN = "urn:oma:mo:oma-dm-devinfo:1.0"; - - private static final String MO_NAME = "DevInfo"; - private static final String TAG_DEVID = "DevID"; - private static final String TAG_MANUFACTURE = "Man"; - private static final String TAG_MODEL = "Mod"; - private static final String TAG_DM_VERSION = "DmV"; - private static final String TAG_LANGUAGE = "Lang"; - - /** - * Make a format of XML based on the DDF(Data Definition Format) of DevInfo MO. - * - * @return the XML that has format of OMA DM DevInfo Management Object, <code>null</code> in - * case of any failure. - */ - public static String serializeToXml(@NonNull SystemInfo systemInfo) { - MoSerializer moSerializer; - try { - moSerializer = new MoSerializer(); - } catch (ParserConfigurationException e) { - Log.e(TAG, "failed to create the MoSerializer: " + e); - return null; - } - // Create the XML document for DevInfoMo - Document doc = moSerializer.createNewDocument(); - Element rootElement = moSerializer.createMgmtTree(doc); - rootElement.appendChild(moSerializer.writeVersion(doc)); - Element moNode = moSerializer.createNode(doc, MO_NAME); - moNode.appendChild(moSerializer.createNodeForUrn(doc, URN)); - rootElement.appendChild(moNode); - rootElement.appendChild( - moSerializer.createNodeForValue(doc, TAG_DEVID, systemInfo.getDeviceId())); - - rootElement.appendChild(moSerializer.createNodeForValue(doc, TAG_MANUFACTURE, - systemInfo.getDeviceManufacturer())); - rootElement.appendChild( - moSerializer.createNodeForValue(doc, TAG_MODEL, systemInfo.getDeviceModel())); - rootElement.appendChild( - moSerializer.createNodeForValue(doc, TAG_DM_VERSION, MoSerializer.DM_VERSION)); - rootElement.appendChild( - moSerializer.createNodeForValue(doc, TAG_LANGUAGE, systemInfo.getLanguage())); - - return moSerializer.serialize(doc); - } -}
\ No newline at end of file diff --git a/service/java/com/android/server/wifi/hotspot2/omadm/MoSerializer.java b/service/java/com/android/server/wifi/hotspot2/omadm/MoSerializer.java deleted file mode 100644 index f804fdeb9..000000000 --- a/service/java/com/android/server/wifi/hotspot2/omadm/MoSerializer.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.omadm; - -import android.annotation.NonNull; -import android.util.Log; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.io.StringWriter; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -/** - * Provides serialization API for OMA DM Management Object. - */ -class MoSerializer { - static final String TAG = "MoSerializable"; - static final String DM_VERSION = "1.2"; - static final String TAG_MGMT_TREE = "MgmtTree"; - static final String TAG_VERSION = "VerDTD"; - static final String TAG_NODE = "Node"; - static final String TAG_NODENAME = "NodeName"; - static final String TAG_PATH = "Path"; - static final String TAG_VALUE = "Value"; - static final String TAG_RTPROPERTIES = "RTProperties"; - static final String TAG_TYPE = "Type"; - static final String TAG_DDF_NAME = "DDFName"; - private DocumentBuilder mDbBuilder; - - public MoSerializer() throws ParserConfigurationException { - mDbBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - } - - /** - * Serializes the Management Object into a XML format. - * - * @return {@link String) that indicates the entire xml of {@link MoSerializer}}, - * <code>null<code/> in case of failure. - */ - String serialize(@NonNull Document doc) { - StringWriter writer = new StringWriter(); - try { - TransformerFactory tf = TransformerFactory.newInstance(); - Transformer transformer = tf.newTransformer(); - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - transformer.transform(new DOMSource(doc), new StreamResult(writer)); - } catch (TransformerException e) { - e.printStackTrace(); - return null; - } - return writer.toString(); - } - - /** - * Create new Document to make a XML document of OMA DM Management Object. - * - * @return new {@link Document} - */ - Document createNewDocument() { - return mDbBuilder.newDocument(); - } - - /** - * Generates root Node starting a "MgmtTree". - * - * Expected output: <MgmtTree></MgmtTree> - * @param doc {@link Document} that indicates an entire xml document. - * @return {@link Element} for Root - */ - Element createMgmtTree(@NonNull Document doc) { - // root element - Element rootElement = doc.createElement(TAG_MGMT_TREE); - doc.appendChild(rootElement); - return rootElement; - } - - /** - * Generates DTD version Node. - * - * Expected output: <VerDTD>[value]</VerDTD> - * @param doc {@link Document} that indicates an entire xml document. - * @return {@link Element} for new Node - */ - Element writeVersion(@NonNull Document doc) { - Element dtdElement = doc.createElement(TAG_VERSION); - dtdElement.appendChild(doc.createTextNode(DM_VERSION)); - return dtdElement; - } - - /** - * Generates Node having {@param nodeName} - * - * Expected output: <Node><NodeName>[nodeName]</NodeName></Node> - * @param doc {@link Document} that indicates an entire xml document. - * @param nodeName node name for new node. - * @return {@link Element} for new Node - */ - Element createNode(@NonNull Document doc, @NonNull String nodeName) { - Element node = doc.createElement(TAG_NODE); - Element nameNode = doc.createElement(TAG_NODENAME); - nameNode.appendChild(doc.createTextNode(nodeName)); - node.appendChild(nameNode); - return node; - } - - /** Generates Node with the Unique Resource Name (URN). - * - * URN is encapsulated inside RTProperties node. - * - * Expected output: <RTProperties><Type><DDFName>[urn]</DDFName></Type></RTProperites> - * @param doc {@link Document} that indicates an entire xml document. - * @param urn The unique resource name - * - * @return {@link Element} for new Node - */ - Element createNodeForUrn(@NonNull Document doc, @NonNull String urn) { - Element node = doc.createElement(TAG_RTPROPERTIES); - Element type = doc.createElement(TAG_TYPE); - Element ddfName = doc.createElement(TAG_DDF_NAME); - ddfName.appendChild(doc.createTextNode(urn)); - type.appendChild(ddfName); - node.appendChild(type); - return node; - } - - /** - * Generates for a node with a value. - * - * Expected output: - * <Node><NodeName>[name]</NodeName><Value>[value]</Value></Node> - * @param doc {@link Document} that indicates an entire xml document. - * @param name name of the node. - * @param value value of the node - * - * @return {@link Element} for new Node - */ - Element createNodeForValue(@NonNull Document doc, @NonNull String name, @NonNull String value) { - Element node = doc.createElement(TAG_NODE); - Element nameNode = doc.createElement(TAG_NODENAME); - nameNode.appendChild(doc.createTextNode(name)); - node.appendChild(nameNode); - - Element valueNode = doc.createElement(TAG_VALUE); - valueNode.appendChild(doc.createTextNode(value)); - - node.appendChild(valueNode); - return node; - } -}
\ No newline at end of file diff --git a/service/java/com/android/server/wifi/hotspot2/soap/ExchangeCompleteMessage.java b/service/java/com/android/server/wifi/hotspot2/soap/ExchangeCompleteMessage.java deleted file mode 100644 index bd753f16a..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/ExchangeCompleteMessage.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import android.annotation.NonNull; -import android.util.Log; - -import org.ksoap2.serialization.SoapObject; - -/** - * Represents the sppExchangeComplete message sent by the server. - * For the details, refer to A.3.2 section in Hotspot2.0 rel2 specification. - */ -public class ExchangeCompleteMessage extends SppResponseMessage { - private static final String TAG = "PasspointExchangeCompleteMessage"; - - private ExchangeCompleteMessage(@NonNull SoapObject response) throws IllegalArgumentException { - super(response, MessageType.EXCHANGE_COMPLETE); - } - - /** - * create an instance of {@link ExchangeCompleteMessage} - * - * @param response SOAP response message received from server. - * @return Instance of {@link ExchangeCompleteMessage}, {@code null} in any failure. - */ - public static ExchangeCompleteMessage createInstance(@NonNull SoapObject response) { - ExchangeCompleteMessage exchangeCompleteMessage; - - try { - exchangeCompleteMessage = new ExchangeCompleteMessage(response); - } catch (IllegalArgumentException e) { - Log.e(TAG, "fails to create an Instance: " + e); - return null; - } - return exchangeCompleteMessage; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/HttpsServiceConnection.java b/service/java/com/android/server/wifi/hotspot2/soap/HttpsServiceConnection.java deleted file mode 100644 index 99f2f21a6..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/HttpsServiceConnection.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2018 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.server.wifi.hotspot2.soap; - -import android.net.Network; -import android.text.TextUtils; - -import org.ksoap2.HeaderProperty; -import org.ksoap2.transport.ServiceConnection; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; - -/** - * A wrapper class for {@link HttpsURLConnection} that requires {@link Network} to open the - * https connection for SOAP message. - */ -public class HttpsServiceConnection implements ServiceConnection { - // TODO(117906601): find an optimal value for a connection timeout - public static final int DEFAULT_TIMEOUT_MS = 5000; // 5 seconds - private HttpsURLConnection mConnection; - - public HttpsServiceConnection(Network network, URL url) throws IOException { - mConnection = (HttpsURLConnection) network.openConnection(url); - mConnection.setConnectTimeout(DEFAULT_TIMEOUT_MS); - mConnection.setReadTimeout(DEFAULT_TIMEOUT_MS); - } - - @Override - public void connect() throws IOException { - mConnection.connect(); - } - - @Override - public void disconnect() { - mConnection.disconnect(); - } - - @Override - public List<HeaderProperty> getResponseProperties() { - Map<String, List<String>> properties = mConnection.getHeaderFields(); - Set<String> keys = properties.keySet(); - List<HeaderProperty> retList = new ArrayList<>(); - - keys.forEach(key -> { - List<String> values = properties.get(key); - values.forEach(value -> retList.add(new HeaderProperty(key, value))); - }); - - return retList; - } - - @Override - public int getResponseCode() throws IOException { - return mConnection.getResponseCode(); - } - - @Override - public void setRequestProperty(String propertyName, String value) { - // Ignore any settings of "the Connection: close" as android network uses the keep alive - // by default. - if (!TextUtils.equals("Connection", propertyName) || !TextUtils.equals("close", value)) { - mConnection.setRequestProperty(propertyName, value); - } - } - - @Override - public void setRequestMethod(String requestMethodType) throws IOException { - mConnection.setRequestMethod(requestMethodType); - } - - @Override - public void setFixedLengthStreamingMode(int contentLength) { - mConnection.setFixedLengthStreamingMode(contentLength); - } - - @Override - public void setChunkedStreamingMode() { - mConnection.setChunkedStreamingMode(0); - } - - @Override - public OutputStream openOutputStream() throws IOException { - return mConnection.getOutputStream(); - } - - @Override - public InputStream openInputStream() throws IOException { - return mConnection.getInputStream(); - } - - @Override - public InputStream getErrorStream() { - return mConnection.getErrorStream(); - } - - @Override - public String getHost() { - return mConnection.getURL().getHost(); - } - - @Override - public int getPort() { - return mConnection.getURL().getPort(); - } - - - @Override - public String getPath() { - return mConnection.getURL().getPath(); - } - - /** - * Wrapper function for {@link HttpsURLConnection#setSSLSocketFactory(SSLSocketFactory)} - * - * @param sslSocketFactory SSL Socket factory - */ - public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) { - mConnection.setSSLSocketFactory(sslSocketFactory); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/HttpsTransport.java b/service/java/com/android/server/wifi/hotspot2/soap/HttpsTransport.java deleted file mode 100644 index e299ee443..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/HttpsTransport.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2018 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.server.wifi.hotspot2.soap; - -import android.annotation.NonNull; -import android.net.Network; - -import org.ksoap2.transport.HttpTransportSE; -import org.ksoap2.transport.ServiceConnection; - -import java.io.IOException; -import java.net.URL; - -/** - * Https Transport Layer for SOAP message over the {@link HttpsServiceConnection}. - */ -public class HttpsTransport extends HttpTransportSE { - private Network mNetwork; - private URL mUrl; - private ServiceConnection mServiceConnection; - - private HttpsTransport(@NonNull Network network, @NonNull URL url) { - super(url.toString()); - mNetwork = network; - mUrl = url; - } - - /** - * Create an instance of {@link HttpsTransport}. - * - * @param network instance of {@link Network} that indicates current connection. - * @param url server url used for HTTPS connection. - * @return instance of {@link HttpsTransport} - */ - public static HttpsTransport createInstance(@NonNull Network network, @NonNull URL url) { - return new HttpsTransport(network, url); - } - - @Override - public ServiceConnection getServiceConnection() throws IOException { - if (mServiceConnection == null) { - mServiceConnection = new HttpsServiceConnection(mNetwork, mUrl); - } - return mServiceConnection; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/PostDevDataMessage.java b/service/java/com/android/server/wifi/hotspot2/soap/PostDevDataMessage.java deleted file mode 100644 index 12ef0a91b..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/PostDevDataMessage.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import android.annotation.NonNull; -import android.content.Context; - -import com.android.server.wifi.hotspot2.SystemInfo; -import com.android.server.wifi.hotspot2.omadm.DevDetailMo; -import com.android.server.wifi.hotspot2.omadm.DevInfoMo; - -import org.ksoap2.SoapEnvelope; -import org.ksoap2.serialization.SoapObject; -import org.ksoap2.serialization.SoapPrimitive; -import org.ksoap2.serialization.SoapSerializationEnvelope; - -/** - * This class represents sppPostDevData message, as part of the - * Subscription Provisioning Protocol. - * For the detail, refer to the Hotspot 2.0 rel2 specification. - */ -public class PostDevDataMessage { - - /** - * Serialize the given request to a SOAP envelope. - * - * @param context the instance of {@link Context} - * @param info the instance of {@link SystemInfo} that has system information about - * the device. - * @param redirectUri the redirect uri generated by the device and is used for indication - * of user input from the server. - * @param requestReason the reason that make a request to the server. - * @param sessionId session id generated by the server to identify the session between - * device and server. It is <code>null</code> for the first request. - * @return {@link SoapSerializationEnvelope} - */ - public static SoapSerializationEnvelope serializeToSoapEnvelope(@NonNull Context context, - @NonNull SystemInfo info, @NonNull String redirectUri, @NonNull String requestReason, - String sessionId) { - SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12); - envelope.implicitTypes = true; // Do not include type in element attribute - envelope.setAddAdornments(false); // Do not generate/include IDs for each element - - SoapObject requestObject = - new SoapObject(SoapEnvelope.NS20, SppConstants.METHOD_POST_DEV_DATA); - requestObject.addAttribute(SoapEnvelope.NS20, SppConstants.ATTRIBUTE_SPP_VERSION, - SppConstants.SUPPORTED_SPP_VERSION); - requestObject.addAttribute(SppConstants.ATTRIBUTE_REQUEST_REASON, requestReason); - - requestObject.addAttribute(SppConstants.ATTRIBUTE_REDIRECT_URI, redirectUri); - - if (sessionId != null) { - requestObject.addAttribute(SoapEnvelope.NS20, SppConstants.ATTRIBUTE_SESSION_ID, - sessionId); - } - - requestObject.addProperty(SoapEnvelope.NS20, SppConstants.PROPERTY_SUPPORTED_SPP_VERSIONS, - SppConstants.SUPPORTED_SPP_VERSION); - requestObject.addProperty(SoapEnvelope.NS20, SppConstants.PROPERTY_SUPPORTED_MO_LIST, - String.join(" ", SppConstants.SUPPORTED_MO_LIST)); - addMoContainer(requestObject, DevInfoMo.URN, DevInfoMo.serializeToXml(info)); - addMoContainer(requestObject, DevDetailMo.URN, - DevDetailMo.serializeToXml(context, info, redirectUri)); - envelope.setOutputSoapObject(requestObject); - return envelope; - } - - /** - * Add an Management Object (MO) tree to the given {@link SoapObject}. - * - * @param soapObject the object to add to - * @param moUrn the URN of the MO tree - * @param moText the string representation of the MO tree - */ - private static void addMoContainer(SoapObject soapObject, String moUrn, String moText) { - SoapPrimitive moContainer = - new SoapPrimitive(SoapEnvelope.NS20, SppConstants.PROPERTY_MO_CONTAINER, moText); - moContainer.addAttribute(SoapEnvelope.NS20, SppConstants.ATTRIBUTE_MO_URN, moUrn); - soapObject.addProperty(SoapEnvelope.NS20, SppConstants.PROPERTY_MO_CONTAINER, moContainer); - } -}
\ No newline at end of file diff --git a/service/java/com/android/server/wifi/hotspot2/soap/PostDevDataResponse.java b/service/java/com/android/server/wifi/hotspot2/soap/PostDevDataResponse.java deleted file mode 100644 index 7b5ddb583..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/PostDevDataResponse.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import android.annotation.NonNull; -import android.util.Log; - -import com.android.server.wifi.hotspot2.soap.command.SppCommand; - -import org.ksoap2.serialization.PropertyInfo; -import org.ksoap2.serialization.SoapObject; - -import java.util.Objects; - -/** - * Represents the sppPostDevDataResponse message sent by the server. - * For the details, refer to A.3.2 section in Hotspot2.0 rel2 specification. - */ -public class PostDevDataResponse extends SppResponseMessage { - private static final String TAG = "PasspointPostDevDataResponse"; - private static final int MAX_COMMAND_COUNT = 1; - private final SppCommand mSppCommand; - - private PostDevDataResponse(@NonNull SoapObject response) throws IllegalArgumentException { - super(response, MessageType.POST_DEV_DATA_RESPONSE); - if (getStatus() == SppConstants.SppStatus.ERROR) { - mSppCommand = null; - return; - } - - PropertyInfo propertyInfo = new PropertyInfo(); - response.getPropertyInfo(0, propertyInfo); - // Get SPP(Subscription Provisioning Protocol) command from the original message. - mSppCommand = SppCommand.createInstance(propertyInfo); - } - - /** - * create an instance of {@link PostDevDataResponse} - * - * @param response SOAP response message received from server. - * @return Instance of {@link PostDevDataResponse}, {@code null} in any failure. - */ - public static PostDevDataResponse createInstance(@NonNull SoapObject response) { - if (response.getPropertyCount() != MAX_COMMAND_COUNT) { - Log.e(TAG, "max command count exceeds: " + response.getPropertyCount()); - return null; - } - - PostDevDataResponse postDevDataResponse; - try { - postDevDataResponse = new PostDevDataResponse(response); - } catch (IllegalArgumentException e) { - Log.e(TAG, "fails to create an Instance: " + e); - return null; - } - - return postDevDataResponse; - } - - /** - * Get a SppCommand for the current {@code PostDevDataResponse} instance. - * - * @return {@link SppCommand} - */ - public SppCommand getSppCommand() { - return mSppCommand; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), mSppCommand); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) return true; - if (!(thatObject instanceof PostDevDataResponse)) return false; - if (!super.equals(thatObject)) return false; - PostDevDataResponse that = (PostDevDataResponse) thatObject; - return Objects.equals(mSppCommand, that.getSppCommand()); - } - - @Override - public String toString() { - return super.toString() + ", commands " + mSppCommand; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/RedirectListener.java b/service/java/com/android/server/wifi/hotspot2/soap/RedirectListener.java deleted file mode 100644 index 103aecb4c..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/RedirectListener.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import android.annotation.NonNull; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.URL; -import java.util.Random; - -import fi.iki.elonen.NanoHTTPD; - -/** - * Server for listening for redirect request from the OSU server to indicate the completion - * of user input. - * - * A HTTP server will be started in the {@link RedirectListener#startServer} of {@link - * RedirectListener}, so the caller will need to invoke {@link RedirectListener#stop} once the - * redirect server no longer needed. - */ -public class RedirectListener extends NanoHTTPD { - // 10 minutes for the maximum wait time. - @VisibleForTesting - static final int USER_TIMEOUT_MILLIS = 10 * 60 * 1000; - - private static final String TAG = "PasspointRedirectListener"; - private final String mPath; - private final URL mServerUrl; - private final Handler mHandler; - private Runnable mTimeOutTask; - private RedirectCallback mRedirectCallback; - - /** - * Listener interface for handling redirect events. - */ - public interface RedirectCallback { - - /** - * Invoked when HTTP redirect response is received. - */ - void onRedirectReceived(); - - /** - * Invoked when timeout occurs on receiving HTTP redirect response. - */ - void onRedirectTimedOut(); - } - - @VisibleForTesting - /* package */ RedirectListener(Looper looper, int port) - throws IOException { - super(InetAddress.getLocalHost().getHostAddress(), port); - - Random rnd = new Random(System.currentTimeMillis()); - - mPath = "rnd" + Integer.toString(Math.abs(rnd.nextInt()), Character.MAX_RADIX); - mServerUrl = new URL("http", getHostname(), port, mPath); - mHandler = new Handler(looper); - mTimeOutTask = () -> mRedirectCallback.onRedirectTimedOut(); - } - - /** - * Create an instance of {@link RedirectListener} - * - * @param looper Looper on which the {@link RedirectCallback} will be called. - * @return Instance of {@link RedirectListener}, {@code null} in any failure. - */ - public static RedirectListener createInstance(@NonNull Looper looper) { - RedirectListener redirectListener; - try { - ServerSocket serverSocket = new ServerSocket(0, 1, InetAddress.getLocalHost()); - redirectListener = new RedirectListener(looper, serverSocket.getLocalPort()); - redirectListener.setServerSocketFactory(() -> { - // Close current server socket so that new server socket is able to bind the port - // in the start() of NanoHTTPD. - serverSocket.close(); - return new ServerSocket(); - }); - } catch (IOException e) { - Log.e(TAG, "fails to create an instance: " + e); - return null; - } - return redirectListener; - } - - /** - * Start redirect listener - * - * @param callback to be notified when the redirect request is received or timed out. - * @param startHandler handler on which the start code is executed. - * @return {@code true} in success, {@code false} if the {@code callback} and {@code - * startHandler} are {@code null} or the server is already running. - */ - public boolean startServer(@NonNull RedirectCallback callback, @NonNull Handler startHandler) { - if (callback == null) { - return false; - } - - if (startHandler == null) { - return false; - } - - if (isAlive()) { - Log.e(TAG, "redirect listener is already running"); - return false; - } - mRedirectCallback = callback; - - startHandler.post(() -> { - try { - start(); - } catch (IOException e) { - Log.e(TAG, "unable to start redirect listener: " + e); - } - }); - mHandler.postDelayed(mTimeOutTask, USER_TIMEOUT_MILLIS); - return true; - } - - /** - * Stop redirect listener - * - * @param stopHandler handler on which the stop code is executed. - */ - public void stopServer(@NonNull Handler stopHandler) { - if (mHandler.hasCallbacks(mTimeOutTask)) { - mHandler.removeCallbacks(mTimeOutTask); - } - if (stopHandler == null) { - return; - } - if (isServerAlive()) { - stopHandler.post(() -> stop()); - } - } - - /** - * Check if the server is alive or not. - * - * @return {@code true} if the server is alive. - */ - public boolean isServerAlive() { - return isAlive(); - } - - /** - * Get URL to which the local redirect server listens - * - * @return The URL for the local redirect server. - */ - public URL getServerUrl() { - return mServerUrl; - } - - @Override - public Response serve(IHTTPSession session) { - - // Ignore all other requests except for a HTTP request that has the server url path with - // GET method. - if (session.getMethod() != Method.GET || !mServerUrl.getPath().equals(session.getUri())) { - return newFixedLengthResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_HTML, ""); - } - - mHandler.removeCallbacks(mTimeOutTask); - mRedirectCallback.onRedirectReceived(); - return newFixedLengthResponse(""); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/SoapParser.java b/service/java/com/android/server/wifi/hotspot2/soap/SoapParser.java deleted file mode 100644 index e8f725440..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/SoapParser.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import android.annotation.NonNull; - -import org.ksoap2.serialization.SoapObject; - -/** - * Utility to parse the raw soap SPP (Subscription Provisioning Protocol) response message - * sent by server and make the instance of {@link SppResponseMessage} - */ -public class SoapParser { - /** - * Get a SppResponseMessage from the original SOAP response. - * - * @param response original SOAP response sent by server - * @return {@link SppResponseMessage}, or {@code null} in any failure - */ - public static SppResponseMessage getResponse(@NonNull SoapObject response) { - SppResponseMessage responseMessage; - switch (response.getName()) { - case "sppPostDevDataResponse": - responseMessage = PostDevDataResponse.createInstance(response); - break; - case "sppExchangeComplete": - responseMessage = ExchangeCompleteMessage.createInstance(response); - break; - default: - responseMessage = null; - } - return responseMessage; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/SppConstants.java b/service/java/com/android/server/wifi/hotspot2/soap/SppConstants.java deleted file mode 100644 index 01cec0a7d..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/SppConstants.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import android.util.SparseArray; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -/** - * Constant definitions for SPP (Subscription Provisioning Protocol). - */ -public class SppConstants { - // Supported SPP Version. - public static final String SUPPORTED_SPP_VERSION = "1.0"; - - // Supported Management Objects as required by SPP Version 1.0. - public static final List<String> SUPPORTED_MO_LIST = Arrays.asList( - "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0", // Hotspot 2.0 PPS MO tree - "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0", // Hotspot 2.0 DevDetail extension - "urn:oma:mo:oma-dm-devinfo:1.0", // OMA-DM DevInfo - "urn:oma:mo:oma-dm-devdetail:1.0"); // OMA-DM DevDetail - - // Method names. - public static final String METHOD_POST_DEV_DATA = "sppPostDevData"; - public static final String METHOD_UPDATE_RESPONSE = "sppUpdateResponse"; - - // SOAP properties. - public static final String PROPERTY_SUPPORTED_SPP_VERSIONS = "supportedSPPVersions"; - public static final String PROPERTY_SUPPORTED_MO_LIST = "supportedMOList"; - public static final String PROPERTY_MO_CONTAINER = "moContainer"; - public static final String PROPERTY_SPP_ERROR = "sppError"; - - // SOAP attributes. - public static final String ATTRIBUTE_SPP_VERSION = "sppVersion"; - public static final String ATTRIBUTE_SPP_STATUS = "sppStatus"; - - public static final String ATTRIBUTE_REQUEST_REASON = "requestReason"; - public static final String ATTRIBUTE_SESSION_ID = "sessionID"; - public static final String ATTRIBUTE_REDIRECT_URI = "redirectURI"; - public static final String ATTRIBUTE_MO_URN = "moURN"; - public static final String ATTRIBUTE_ERROR_CODE = "errorCode"; - - public static final int INVALID_SPP_CONSTANT = -1; - - private static final SparseArray<String> sStatusStrings = new SparseArray<>(); - private static final Map<String, Integer> sStatusEnums = new HashMap<>(); - static { - sStatusStrings.put(SppStatus.OK, "OK"); - sStatusStrings.put(SppStatus.PROV_COMPLETE, - "Provisioning complete, request sppUpdateResponse"); - sStatusStrings.put(SppStatus.REMEDIATION_COMPLETE, - "Remediation complete, request sppUpdateResponse"); - sStatusStrings.put(SppStatus.UPDATE_COMPLETE, "Update complete, request sppUpdateResponse"); - sStatusStrings.put(SppStatus.EXCHANGE_COMPLETE, - "Exchange complete, release TLS connection"); - sStatusStrings.put(SppStatus.UNKOWN, "No update available at this time"); - sStatusStrings.put(SppStatus.ERROR, "Error occurred"); - - for (int i = 0; i < sStatusStrings.size(); i++) { - sStatusEnums.put(sStatusStrings.valueAt(i).toLowerCase(), sStatusStrings.keyAt(i)); - } - } - - private static final SparseArray<String> sErrorStrings = new SparseArray<>(); - private static final Map<String, Integer> sErrorEnums = new HashMap<>(); - static { - sErrorStrings.put(SppError.VERSION_NOT_SUPPORTED, "SPP version not supported"); - sErrorStrings.put(SppError.MOS_NOT_SUPPORTED, "One or more mandatory MOs not supported"); - sErrorStrings.put(SppError.CREDENTIALS_FAILURE, - "Credentials cannot be provisioned at this time"); - sErrorStrings.put(SppError.REMEDIATION_FAILURE, - "Remediation cannot be completed at this time"); - sErrorStrings.put(SppError.PROVISIONING_FAILED, - "Provisioning cannot be completed at this time"); - sErrorStrings.put(SppError.EXISITING_CERTIFICATE, "Continue to use existing certificate"); - sErrorStrings.put(SppError.COOKIE_INVALID, "Cookie invalid"); - sErrorStrings.put(SppError.WEB_SESSION_ID, - "No corresponding web-browser-connection Session ID"); - sErrorStrings.put(SppError.PERMISSION_DENITED, "Permission denied"); - sErrorStrings.put(SppError.COMMAND_FAILED, "Command failed"); - sErrorStrings.put(SppError.MO_ADD_OR_UPDATE_FAILED, "MO addition or update failed"); - sErrorStrings.put(SppError.DEVICE_FULL, "Device full"); - sErrorStrings.put(SppError.BAD_TREE_URI, "Bad management tree URI"); - sErrorStrings.put(SppError.TOO_LARGE, "Requested entity too large"); - sErrorStrings.put(SppError.COMMAND_NOT_ALLOWED, "Command not allowed"); - sErrorStrings.put(SppError.USER_ABORTED, "Command not executed due to user"); - sErrorStrings.put(SppError.NOT_FOUND, "Not found"); - sErrorStrings.put(SppError.OTHER, "Other"); - - for (int i = 0; i < sErrorStrings.size(); i++) { - sErrorEnums.put(sErrorStrings.valueAt(i).toLowerCase(), sErrorStrings.keyAt(i)); - } - } - - /** - * Convert the {@link SppStatus} to <code>String</code> - * - * @param status value of {@link SppStatus} - * @return string of the status - */ - public static String mapStatusIntToString(int status) { - return sStatusStrings.get(status); - } - - /** - * Convert the status string to {@link SppStatus} - * - * @param status string of the status - * @return <code>int</code> value of {@link SppStatus} if found; {@link #INVALID_SPP_CONSTANT} - * otherwise. - */ - public static int mapStatusStringToInt(String status) { - Integer value = sStatusEnums.get(status.toLowerCase(Locale.US)); - return (value == null) ? INVALID_SPP_CONSTANT : value; - } - - /** - * Convert the {@link SppError} to <code>String</code> - * - * @param error value of {@link SppError} - * @return string of error - */ - public static String mapErrorIntToString(int error) { - return sErrorStrings.get(error); - } - - /** - * Convert the error string to {@link SppError} - * - * @param error string of the error - * @return <code>int</code> value of {@link SppError} if found; {@link #INVALID_SPP_CONSTANT} - * otherwise. - */ - public static int mapErrorStringToInt(String error) { - Integer value = sErrorEnums.get(error.toLowerCase()); - return (value == null) ? INVALID_SPP_CONSTANT : value; - } - - // Request reasons for sppPostDevData requests. - // Refer to Table 13(sppPostDevData Elements and Attributes Descriptions) - // in Hotspot2.0 R2 Technical specification. - public class SppReason { - public static final String SUBSCRIPTION_REGISTRATION = - "Subscription registration"; - public static final String SUBSCRIPTION_PROVISIONING = - "Subscription provisioning"; - public static final String SUBSCRIPTION_REMEDIATION = - "Subscription remediation"; - public static final String USER_INPUT_COMPLETED = "User input completed"; - public static final String NO_ACCEPTABLE_CLIENT_CERTIFICATE = - "No acceptable client certificate"; - public static final String CERTIFICATE_ENROLLMENT_COMPLETED = - "Certificate enrollment completed"; - public static final String CERTIFICATE_ENROLLMENT_FAILED = - "Certificate enrollment failed"; - public static final String SUBSCRIPTION_METADATA_UPDATE = - "Subscription metadata update"; - public static final String POLICY_UPDATE = "Policy update"; - public static final String MO_UPLOAD = "MO upload"; - public static final String RETRIEVE_NEXT_COMMAND = "Retrieve next command"; - public static final String UNSPECIFIED = "Unspecified"; - } - - /** - * enumeration values for the status defined by SPP (Subscription Provisioning Protocol). - * - * @see <a href=https://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp/spp-v1.0.xsd>SPP - * protocol 1.0</a> - */ - public class SppStatus { - public static final int OK = 0; - public static final int PROV_COMPLETE = 1; - public static final int REMEDIATION_COMPLETE = 2; - public static final int UPDATE_COMPLETE = 3; - public static final int EXCHANGE_COMPLETE = 4; - public static final int UNKOWN = 5; - public static final int ERROR = 6; - } - - /** - * Enumeration values for the errors defined by SPP (Subscription Provisioning Protocol). - * - * @see <a href=https://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp/spp-v1.0.xsd>SPP - * protocol 1.0</a> - */ - public class SppError { - public static final int VERSION_NOT_SUPPORTED = 0; - public static final int MOS_NOT_SUPPORTED = 1; - public static final int CREDENTIALS_FAILURE = 2; - public static final int REMEDIATION_FAILURE = 3; - public static final int PROVISIONING_FAILED = 4; - public static final int EXISITING_CERTIFICATE = 5; - public static final int COOKIE_INVALID = 6; - public static final int WEB_SESSION_ID = 7; - public static final int PERMISSION_DENITED = 8; - public static final int COMMAND_FAILED = 9; - public static final int MO_ADD_OR_UPDATE_FAILED = 10; - public static final int DEVICE_FULL = 11; - public static final int BAD_TREE_URI = 12; - public static final int TOO_LARGE = 13; - public static final int COMMAND_NOT_ALLOWED = 14; - public static final int USER_ABORTED = 15; - public static final int NOT_FOUND = 16; - public static final int OTHER = 17; - } -}
\ No newline at end of file diff --git a/service/java/com/android/server/wifi/hotspot2/soap/SppResponseMessage.java b/service/java/com/android/server/wifi/hotspot2/soap/SppResponseMessage.java deleted file mode 100644 index 72f97ba9c..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/SppResponseMessage.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import android.annotation.NonNull; -import android.text.TextUtils; - -import org.ksoap2.serialization.AttributeInfo; -import org.ksoap2.serialization.SoapObject; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** - * Base SOAP SPP (Subscription Provisioning Protocol) response message sent by server - */ -public class SppResponseMessage { - static final String SPPVersionAttribute = "sppVersion"; - static final String SPPStatusAttribute = "sppStatus"; - static final String SPPSessionIDAttribute = "sessionID"; - static final String SPPErrorCodeAttribute = "errorCode"; - static final String SPPErrorProperty = "sppError"; - - private final int mMessageType; - private final String mVersion; - private final String mSessionID; - private int mStatus; - private int mError = SppConstants.INVALID_SPP_CONSTANT; - private Map<String, String> mAttributes; - - /** - * Message types of SOAP SPP response. - */ - public static class MessageType { - /* SOAP method response from the subscription server */ - public static final int POST_DEV_DATA_RESPONSE = 0; - - /* Message exchange sequence has been completed and the TLS connection should be released */ - public static final int EXCHANGE_COMPLETE = 1; - } - - protected SppResponseMessage(@NonNull SoapObject response, int messageType) - throws IllegalArgumentException { - if (!response.hasAttribute(SPPStatusAttribute)) { - throw new IllegalArgumentException("Missing status"); - } - - mMessageType = messageType; - mStatus = SppConstants.mapStatusStringToInt( - response.getAttributeAsString(SPPStatusAttribute)); - if (!response.hasAttribute(SPPVersionAttribute) || !response.hasAttribute( - SPPSessionIDAttribute) || mStatus == SppConstants.INVALID_SPP_CONSTANT) { - throw new IllegalArgumentException("Incomplete request: " + messageType); - } - - // Validation check for error status - if (mStatus == SppConstants.SppStatus.ERROR) { - if (!response.hasProperty(SPPErrorProperty)) { - throw new IllegalArgumentException("Missing sppError"); - } - } - - if (response.hasProperty(SPPErrorProperty)) { - SoapObject errorInfo = (SoapObject) response.getProperty(SPPErrorProperty); - if (!errorInfo.hasAttribute(SPPErrorCodeAttribute)) { - throw new IllegalArgumentException("Missing errorCode"); - } - mError = SppConstants.mapErrorStringToInt( - errorInfo.getAttributeAsString(SPPErrorCodeAttribute)); - } - - mSessionID = response.getAttributeAsString(SPPSessionIDAttribute); - mVersion = response.getAttributeAsString(SPPVersionAttribute); - if (response.getAttributeCount() > 0) { - mAttributes = new HashMap<>(); - for (int i = 0; i < response.getAttributeCount(); i++) { - AttributeInfo attributeInfo = new AttributeInfo(); - response.getAttributeInfo(i, attributeInfo); - mAttributes.put(attributeInfo.getName(), - response.getAttributeAsString(attributeInfo.getName())); - - } - } - } - - public int getMessageType() { - return mMessageType; - } - - public String getVersion() { - return mVersion; - } - - public String getSessionID() { - return mSessionID; - } - - public int getStatus() { - return mStatus; - } - - public int getError() { - return mError; - } - - protected final Map<String, String> getAttributes() { - return Collections.unmodifiableMap(mAttributes); - } - - @Override - public int hashCode() { - return Objects.hash(mMessageType, mVersion, mSessionID, mStatus, mError, mAttributes); - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) return true; - if (!(thatObject instanceof SppResponseMessage)) return false; - SppResponseMessage that = (SppResponseMessage) thatObject; - return mMessageType == that.mMessageType - && mStatus == that.mStatus - && mError == that.mError - && TextUtils.equals(mVersion, that.mVersion) - && TextUtils.equals(mSessionID, that.mSessionID) - && ((mAttributes == null) ? (that.mAttributes == null) : mAttributes.equals( - that.mAttributes)); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(mMessageType); - sb.append(", version ").append(mVersion); - sb.append(", status ").append(mStatus); - sb.append(", session-id ").append(mSessionID); - if (mError != SppConstants.INVALID_SPP_CONSTANT) { - sb.append(", error ").append(mError); - } - return sb.toString(); - } -} - diff --git a/service/java/com/android/server/wifi/hotspot2/soap/UpdateResponseMessage.java b/service/java/com/android/server/wifi/hotspot2/soap/UpdateResponseMessage.java deleted file mode 100644 index 53c2a5e78..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/UpdateResponseMessage.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import android.annotation.NonNull; - -import org.ksoap2.SoapEnvelope; -import org.ksoap2.serialization.SoapObject; -import org.ksoap2.serialization.SoapSerializationEnvelope; - -/** - * This class represents sppUpdateResponse message, as part of the - * Subscription Provisioning Protocol. - * For the detail, refer to the Hotspot 2.0 rel2 specification. - */ -public class UpdateResponseMessage { - - /** - * Serialize the given request to a SOAP envelope. - * - * @param sessionId session id generated by the server to identify the session between device - * and server. - * @param isError {@code true} if the error happens during updating or installing PPS MO. - * @return {@link SoapSerializationEnvelope} - */ - public static SoapSerializationEnvelope serializeToSoapEnvelope(@NonNull String sessionId, - boolean isError) { - SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12); - envelope.implicitTypes = true; // Do not include type in element attribute - envelope.setAddAdornments(false); // Do not generate/include IDs for each element - - SoapObject requestObject = - new SoapObject(SoapEnvelope.NS20, SppConstants.METHOD_UPDATE_RESPONSE); - requestObject.addAttribute(SoapEnvelope.NS20, SppConstants.ATTRIBUTE_SPP_VERSION, - SppConstants.SUPPORTED_SPP_VERSION); - requestObject.addAttribute(SoapEnvelope.NS20, SppConstants.ATTRIBUTE_SESSION_ID, sessionId); - if (isError) { - requestObject.addAttribute(SoapEnvelope.NS20, SppConstants.ATTRIBUTE_SPP_STATUS, - SppConstants.mapStatusIntToString(SppConstants.SppStatus.ERROR)); - SoapObject sppError = - new SoapObject(SoapEnvelope.NS20, SppConstants.PROPERTY_SPP_ERROR); - sppError.addAttribute(SppConstants.ATTRIBUTE_ERROR_CODE, - SppConstants.mapErrorIntToString( - SppConstants.SppError.MO_ADD_OR_UPDATE_FAILED)); - requestObject.addProperty(SoapEnvelope.NS20, SppConstants.PROPERTY_SPP_ERROR, sppError); - } else { - requestObject.addAttribute(SoapEnvelope.NS20, SppConstants.ATTRIBUTE_SPP_STATUS, - SppConstants.mapStatusIntToString(SppConstants.SppStatus.OK)); - } - - envelope.setOutputSoapObject(requestObject); - return envelope; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/command/BrowserUri.java b/service/java/com/android/server/wifi/hotspot2/soap/command/BrowserUri.java deleted file mode 100644 index 7b226c414..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/command/BrowserUri.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap.command; - -import android.text.TextUtils; -import android.util.Log; - -import org.ksoap2.serialization.PropertyInfo; - -import java.util.Objects; - -/** - * Represents URI of LaunchBrowser command defined by SPP (Subscription Provisioning Protocol). - */ -public class BrowserUri implements SppCommand.SppCommandData { - private static final String TAG = "PasspointBrowserUri"; - private final String mUri; - - private BrowserUri(PropertyInfo command) { - mUri = command.getValue().toString(); - } - - /** - * Create an instance of {@link BrowserUri} - * - * @param command command message embedded in SOAP sppPostDevDataResponse. - * @return instance of {@link BrowserUri}, {@code null} in any failure. - */ - public static BrowserUri createInstance(PropertyInfo command) { - if (!TextUtils.equals(command.getName(), "launchBrowserToURI")) { - Log.e(TAG, "received wrong command : " + ((command == null) ? "" : command.getName())); - return null; - } - return new BrowserUri(command); - } - - public String getUri() { - return mUri; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) return true; - if (!(thatObject instanceof BrowserUri)) return false; - BrowserUri that = (BrowserUri) thatObject; - return TextUtils.equals(mUri, that.mUri); - } - - @Override - public int hashCode() { - return Objects.hash(mUri); - } - - @Override - public String toString() { - return "BrowserUri{mUri: " + mUri + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/command/PpsMoData.java b/service/java/com/android/server/wifi/hotspot2/soap/command/PpsMoData.java deleted file mode 100644 index 9c44a10a5..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/command/PpsMoData.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap.command; - -import android.annotation.NonNull; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import org.ksoap2.serialization.PropertyInfo; -import org.ksoap2.serialization.SoapPrimitive; - -import java.util.Objects; - -/** - * Represents PPS (PerProviderSubscription) MO (Management Object) defined by SPP (Subscription - * Provisioning Protocol). - */ -public class PpsMoData implements SppCommand.SppCommandData { - @VisibleForTesting - public static final String ADD_MO_COMMAND = "addMO"; - @VisibleForTesting - public static final String ATTRIBUTE_MANAGEMENT_TREE_URI = "managementTreeURI"; - @VisibleForTesting - public static final String ATTRIBUTE_MO_URN = "moURN"; - - private static final String TAG = "PasspointPpsMoData"; - private final String mBaseUri; - private final String mUrn; - private final String mPpsMoTree; - - private PpsMoData(String baseUri, String urn, String ppsMoTree) { - mBaseUri = baseUri; - mUrn = urn; - mPpsMoTree = ppsMoTree; - } - - /** - * Create an instance of {@link PpsMoData} - * - * @param command command message embedded in SOAP sppPostDevDataResponse. - * @return instance of {@link PpsMoData}, {@code null} in any failure. - */ - public static PpsMoData createInstance(@NonNull PropertyInfo command) { - if (command == null || command.getValue() == null) { - Log.e(TAG, "command message is null"); - return null; - } - - if (!TextUtils.equals(command.getName(), ADD_MO_COMMAND)) { - Log.e(TAG, "the response is not for addMO command"); - return null; - } - - if (!(command.getValue() instanceof SoapPrimitive)) { - Log.e(TAG, "the addMO element is not valid format"); - return null; - } - - SoapPrimitive soapObject = (SoapPrimitive) command.getValue(); - if (!soapObject.hasAttribute(ATTRIBUTE_MANAGEMENT_TREE_URI)) { - Log.e(TAG, "managementTreeURI Attribute is missing"); - return null; - } - - if (!soapObject.hasAttribute(ATTRIBUTE_MO_URN)) { - Log.e(TAG, "moURN Attribute is missing"); - return null; - } - - if (soapObject.getValue() == null) { - Log.e(TAG, "PPSMO Tree is missing"); - return null; - } - - return new PpsMoData( - (String) soapObject.getAttributeSafelyAsString(ATTRIBUTE_MANAGEMENT_TREE_URI), - (String) soapObject.getAttributeSafelyAsString(ATTRIBUTE_MO_URN), - soapObject.getValue().toString()); - } - - /** - * Get PPS (PerProviderSubscription) MO (Management Object) with XML format. - * - * @return PPS MO Tree - */ - public String getPpsMoTree() { - return mPpsMoTree; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) return true; - if (thatObject == null) return false; - if (!(thatObject instanceof PpsMoData)) return false; - PpsMoData ppsMoData = (PpsMoData) thatObject; - return TextUtils.equals(mBaseUri, ppsMoData.mBaseUri) - && TextUtils.equals(mUrn, ppsMoData.mUrn) - && TextUtils.equals(mPpsMoTree, ppsMoData.mPpsMoTree); - } - - @Override - public int hashCode() { - return Objects.hash(mBaseUri, mUrn, mPpsMoTree); - } - - @Override - public String toString() { - return "PpsMoData{Base URI: " + mBaseUri + ", MOURN: " + mUrn + ", PPS MO: " + mPpsMoTree - + "}"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/soap/command/SppCommand.java b/service/java/com/android/server/wifi/hotspot2/soap/command/SppCommand.java deleted file mode 100644 index f22bc75c0..000000000 --- a/service/java/com/android/server/wifi/hotspot2/soap/command/SppCommand.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap.command; - -import android.annotation.NonNull; -import android.util.Log; - -import org.ksoap2.serialization.PropertyInfo; -import org.ksoap2.serialization.SoapObject; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** - * Commands that the mobile device is being requested to execute, which is defined in SPP - * (Subscription Provisioning Protocol). - * - * For the details, refer to A.3.2 of Hotspot 2.0 rel2 technical specification. - */ -public class SppCommand { - private static final String TAG = "PasspointSppCommand"; - private int mSppCommandId; - private int mExecCommandId = -1; - private SppCommandData mCommandData; - - /** - * Marker interface to indicate data used for a SPP(Subscription Provisioning Protocol) command - */ - public interface SppCommandData { - - } - - /** - * Commands embedded in sppPostDevDataResponse message for client to take an action. - */ - public class CommandId { - public static final int EXEC = 0; - public static final int ADD_MO = 1; - public static final int UPDATE_NODE = 2; - public static final int NO_MO_UPDATE = 3; - } - - private static final Map<String, Integer> sCommands = new HashMap<>(); - static { - sCommands.put("exec", CommandId.EXEC); - sCommands.put("addMO", CommandId.ADD_MO); - sCommands.put("updateNode", CommandId.UPDATE_NODE); - sCommands.put("noMOUpdate", CommandId.NO_MO_UPDATE); - } - - /** - * Execution types embedded in exec command for client to execute it. - */ - public class ExecCommandId { - public static final int BROWSER = 0; - public static final int GET_CERT = 1; - public static final int USE_CLIENT_CERT_TLS = 2; - public static final int UPLOAD_MO = 3; - } - - private static final Map<String, Integer> sExecs = new HashMap<>(); - static { - sExecs.put("launchBrowserToURI", ExecCommandId.BROWSER); - sExecs.put("getCertificate", ExecCommandId.GET_CERT); - sExecs.put("useClientCertTLS", ExecCommandId.USE_CLIENT_CERT_TLS); - sExecs.put("uploadMO", ExecCommandId.UPLOAD_MO); - } - - private SppCommand(PropertyInfo soapResponse) throws IllegalArgumentException { - if (!sCommands.containsKey(soapResponse.getName())) { - throw new IllegalArgumentException("can't find the command: " + soapResponse.getName()); - } - mSppCommandId = sCommands.get(soapResponse.getName()); - - Log.i(TAG, "command name: " + soapResponse.getName()); - - switch(mSppCommandId) { - case CommandId.EXEC: - /* - * Receipt of this element by a mobile device causes the following command - * to be executed. - */ - SoapObject subCommand = (SoapObject) soapResponse.getValue(); - if (subCommand.getPropertyCount() != 1) { - throw new IllegalArgumentException( - "more than one child element found for exec command: " - + subCommand.getPropertyCount()); - } - - PropertyInfo commandInfo = new PropertyInfo(); - subCommand.getPropertyInfo(0, commandInfo); - if (!sExecs.containsKey(commandInfo.getName())) { - throw new IllegalArgumentException( - "Unrecognized exec command: " + commandInfo.getName()); - } - mExecCommandId = sExecs.get(commandInfo.getName()); - Log.i(TAG, "exec command: " + commandInfo.getName()); - - switch (mExecCommandId) { - case ExecCommandId.BROWSER: - /* - * When the mobile device receives this command, it launches its default - * browser to the URI contained in this element. The URI must use HTTPS as - * the protocol and must contain a FQDN. - */ - mCommandData = BrowserUri.createInstance(commandInfo); - break; - case ExecCommandId.GET_CERT: //fall-through - case ExecCommandId.UPLOAD_MO: //fall-through - case ExecCommandId.USE_CLIENT_CERT_TLS: //fall-through - /* - * Command to mobile to re-negotiate the TLS connection using a client - * certificate of the accepted type or Issuer to authenticate with the - * Subscription server. - */ - default: - mCommandData = null; - break; - } - break; - case CommandId.ADD_MO: - /* - * This command causes an management object in the mobile devices management tree - * at the specified location to be added. - * If there is already a management object at that location, the object is replaced. - */ - mCommandData = PpsMoData.createInstance(soapResponse); - break; - case CommandId.UPDATE_NODE: - /* - * This command causes the update of an interior node and its child nodes (if any) - * at the location specified in the management tree URI attribute. The content of - * this element is the MO node XML. - */ - break; - case CommandId.NO_MO_UPDATE: - /* - * This response is used when there is no command to be executed nor update of - * any MO required. - */ - break; - default: - mExecCommandId = -1; - mCommandData = null; - break; - } - } - - /** - * Create an instance of {@link SppCommand} - * - * @param soapResponse SOAP Response received from server. - * @return instance of {@link SppCommand} - */ - public static SppCommand createInstance(@NonNull PropertyInfo soapResponse) { - SppCommand sppCommand; - try { - sppCommand = new SppCommand(soapResponse); - } catch (IllegalArgumentException e) { - Log.e(TAG, "fails to create an instance: " + e); - return null; - } - return sppCommand; - } - - public int getSppCommandId() { - return mSppCommandId; - } - - public int getExecCommandId() { - return mExecCommandId; - } - - public SppCommandData getCommandData() { - return mCommandData; - } - - @Override - public boolean equals(Object thatObject) { - if (this == thatObject) return true; - if (!(thatObject instanceof SppCommand)) return false; - SppCommand that = (SppCommand) thatObject; - return (mSppCommandId == that.getSppCommandId()) - && (mExecCommandId == that.getExecCommandId()) - && Objects.equals(mCommandData, that.getCommandData()); - } - - @Override - public int hashCode() { - return Objects.hash(mSppCommandId, mExecCommandId, mCommandData); - } - - @Override - public String toString() { - return "SppCommand{" - + "mSppCommandId=" + mSppCommandId - + ", mExecCommandId=" + mExecCommandId - + ", mCommandData=" + mCommandData - + "}"; - } -} diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallback.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallback.java deleted file mode 100644 index ea7467842..000000000 --- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallback.java +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.p2p; - -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback; -import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; -import android.net.wifi.WpsInfo; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pProvDiscEvent; -import android.net.wifi.p2p.WifiP2pWfdInfo; -import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; -import android.util.Log; - -import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus; -import com.android.server.wifi.util.NativeUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Class used for processing all P2P callbacks. - */ -public class SupplicantP2pIfaceCallback extends ISupplicantP2pIfaceCallback.Stub { - private static final String TAG = "SupplicantP2pIfaceCallback"; - private static boolean sVerboseLoggingEnabled = true; - - private final String mInterface; - private final WifiP2pMonitor mMonitor; - - public SupplicantP2pIfaceCallback(String iface, WifiP2pMonitor monitor) { - mInterface = iface; - mMonitor = monitor; - } - - /** - * Enable verbose logging for all sub modules. - */ - public static void enableVerboseLogging(int verbose) { - sVerboseLoggingEnabled = verbose > 0; - } - - protected static void logd(String s) { - if (sVerboseLoggingEnabled) Log.d(TAG, s); - } - - /** - * Used to indicate that a new network has been added. - * - * @param networkId Network ID allocated to the corresponding network. - */ - public void onNetworkAdded(int networkId) { - } - - - /** - * Used to indicate that a network has been removed. - * - * @param networkId Network ID allocated to the corresponding network. - */ - public void onNetworkRemoved(int networkId) { - } - - - /** - * Used to indicate that a P2P device has been found. - * - * @param srcAddress MAC address of the device found. This must either - * be the P2P device address or the P2P interface address. - * @param p2pDeviceAddress P2P device address. - * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P - * Technical specification v1.2. - * @param deviceName Name of the device. - * @param configMethods Mask of WPS configuration methods supported by the - * device. - * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical - * specification v1.2. - * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical - * specification v1.2. - * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD - * technical specification v1.0.0. - */ - public void onDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, - String deviceName, short configMethods, byte deviceCapabilities, int groupCapabilities, - byte[] wfdDeviceInfo) { - WifiP2pDevice device = new WifiP2pDevice(); - device.deviceName = deviceName; - if (deviceName == null) { - Log.e(TAG, "Missing device name."); - return; - } - - try { - device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); - } catch (Exception e) { - Log.e(TAG, "Could not decode device address.", e); - return; - } - - try { - device.primaryDeviceType = NativeUtil.wpsDevTypeStringFromByteArray(primaryDeviceType); - } catch (Exception e) { - Log.e(TAG, "Could not encode device primary type.", e); - return; - } - - device.deviceCapability = deviceCapabilities; - device.groupCapability = groupCapabilities; - device.wpsConfigMethodsSupported = configMethods; - device.status = WifiP2pDevice.AVAILABLE; - - if (wfdDeviceInfo != null && wfdDeviceInfo.length >= 6) { - device.wfdInfo = new WifiP2pWfdInfo( - ((wfdDeviceInfo[0] & 0xFF) << 8) + (wfdDeviceInfo[1] & 0xFF), - ((wfdDeviceInfo[2] & 0xFF) << 8) + (wfdDeviceInfo[3] & 0xFF), - ((wfdDeviceInfo[4] & 0xFF) << 8) + (wfdDeviceInfo[5] & 0xFF)); - } - - logd("Device discovered on " + mInterface + ": " + device); - mMonitor.broadcastP2pDeviceFound(mInterface, device); - } - - /** - * Used to indicate that a P2P device has been lost. - * - * @param p2pDeviceAddress P2P device address. - */ - public void onDeviceLost(byte[] p2pDeviceAddress) { - WifiP2pDevice device = new WifiP2pDevice(); - - try { - device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); - } catch (Exception e) { - Log.e(TAG, "Could not decode device address.", e); - return; - } - - device.status = WifiP2pDevice.UNAVAILABLE; - - logd("Device lost on " + mInterface + ": " + device); - mMonitor.broadcastP2pDeviceLost(mInterface, device); - } - - - /** - * Used to indicate the termination of P2P find operation. - */ - public void onFindStopped() { - logd("Search stopped on " + mInterface); - mMonitor.broadcastP2pFindStopped(mInterface); - } - - - /** - * Used to indicate the reception of a P2P Group Owner negotiation request. - * - * @param srcAddress MAC address of the device that initiated the GO - * negotiation request. - * @param passwordId Type of password. - */ - public void onGoNegotiationRequest(byte[] srcAddress, short passwordId) { - WifiP2pConfig config = new WifiP2pConfig(); - - try { - config.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress); - } catch (Exception e) { - Log.e(TAG, "Could not decode device address.", e); - return; - } - - config.wps = new WpsInfo(); - - switch (passwordId) { - case WpsDevPasswordId.USER_SPECIFIED: - config.wps.setup = WpsInfo.DISPLAY; - break; - - case WpsDevPasswordId.PUSHBUTTON: - config.wps.setup = WpsInfo.PBC; - break; - - case WpsDevPasswordId.REGISTRAR_SPECIFIED: - config.wps.setup = WpsInfo.KEYPAD; - break; - - default: - config.wps.setup = WpsInfo.PBC; - break; - } - - logd("Group Owner negotiation initiated on " + mInterface + ": " + config); - mMonitor.broadcastP2pGoNegotiationRequest(mInterface, config); - } - - - /** - * Used to indicate the completion of a P2P Group Owner negotiation request. - * - * @param status Status of the GO negotiation. - */ - public void onGoNegotiationCompleted(int status) { - logd("Group Owner negotiation completed with status: " + status); - P2pStatus result = halStatusToP2pStatus(status); - - if (result == P2pStatus.SUCCESS) { - mMonitor.broadcastP2pGoNegotiationSuccess(mInterface); - } else { - mMonitor.broadcastP2pGoNegotiationFailure(mInterface, result); - } - } - - - /** - * Used to indicate a successful formation of a P2P group. - */ - public void onGroupFormationSuccess() { - logd("Group formation successful on " + mInterface); - mMonitor.broadcastP2pGroupFormationSuccess(mInterface); - } - - - /** - * Used to indicate a failure to form a P2P group. - * - * @param failureReason Failure reason string for debug purposes. - */ - public void onGroupFormationFailure(String failureReason) { - // TODO(ender): failureReason should probably be an int (P2pStatusCode). - logd("Group formation failed on " + mInterface + ": " + failureReason); - mMonitor.broadcastP2pGroupFormationFailure(mInterface, failureReason); - } - - - /** - * Used to indicate the start of a P2P group. - * - * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1) - * @param isGo Whether this device is owner of the group. - * @param ssid SSID of the group. - * @param frequency Frequency on which this group is created. - * @param psk PSK used to secure the group. - * @param passphrase PSK passphrase used to secure the group. - * @param goDeviceAddress MAC Address of the owner of this group. - * @param isPersistent Whether this group is persisted or not. - */ - public void onGroupStarted(String groupIfName, boolean isGo, ArrayList<Byte> ssid, - int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, - boolean isPersistent) { - if (groupIfName == null) { - Log.e(TAG, "Missing group interface name."); - return; - } - - logd("Group " + groupIfName + " started on " + mInterface); - - WifiP2pGroup group = new WifiP2pGroup(); - group.setInterface(groupIfName); - - try { - String quotedSsid = NativeUtil.encodeSsid(ssid); - group.setNetworkName(NativeUtil.removeEnclosingQuotes(quotedSsid)); - } catch (Exception e) { - Log.e(TAG, "Could not encode SSID.", e); - return; - } - - group.setFrequency(frequency); - group.setIsGroupOwner(isGo); - group.setPassphrase(passphrase); - - if (isPersistent) { - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - } else { - group.setNetworkId(WifiP2pGroup.NETWORK_ID_TEMPORARY); - } - - WifiP2pDevice owner = new WifiP2pDevice(); - - try { - owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress); - } catch (Exception e) { - Log.e(TAG, "Could not decode Group Owner address.", e); - return; - } - - group.setOwner(owner); - mMonitor.broadcastP2pGroupStarted(mInterface, group); - } - - - /** - * Used to indicate the removal of a P2P group. - * - * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1) - * @param isGo Whether this device is owner of the group. - */ - public void onGroupRemoved(String groupIfName, boolean isGo) { - if (groupIfName == null) { - Log.e(TAG, "Missing group name."); - return; - } - - logd("Group " + groupIfName + " removed from " + mInterface); - WifiP2pGroup group = new WifiP2pGroup(); - group.setInterface(groupIfName); - group.setIsGroupOwner(isGo); - mMonitor.broadcastP2pGroupRemoved(mInterface, group); - } - - - /** - * Used to indicate the reception of a P2P invitation. - * - * @param srcAddress MAC address of the device that sent the invitation. - * @param goDeviceAddress MAC Address of the owner of this group. - * @param bssid Bssid of the group. - * @param persistentNetworkId Persistent network Id of the group. - * @param operatingFrequency Frequency on which the invitation was received. - */ - public void onInvitationReceived(byte[] srcAddress, byte[] goDeviceAddress, - byte[] bssid, int persistentNetworkId, int operatingFrequency) { - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(persistentNetworkId); - - WifiP2pDevice client = new WifiP2pDevice(); - - try { - client.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress); - } catch (Exception e) { - Log.e(TAG, "Could not decode MAC address.", e); - return; - } - - group.addClient(client); - - WifiP2pDevice owner = new WifiP2pDevice(); - - try { - owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress); - } catch (Exception e) { - Log.e(TAG, "Could not decode Group Owner MAC address.", e); - return; - } - - group.setOwner(owner); - - logd("Invitation received on " + mInterface + ": " + group); - mMonitor.broadcastP2pInvitationReceived(mInterface, group); - } - - - /** - * Used to indicate the result of the P2P invitation request. - * - * @param bssid Bssid of the group. - * @param status Status of the invitation. - */ - public void onInvitationResult(byte[] bssid, int status) { - logd("Invitation completed with status: " + status); - mMonitor.broadcastP2pInvitationResult(mInterface, halStatusToP2pStatus(status)); - } - - - /** - * Used to indicate the completion of a P2P provision discovery request. - * - * @param p2pDeviceAddress P2P device address. - * @param isRequest Whether we received or sent the provision discovery. - * @param status Status of the provision discovery (SupplicantStatusCode). - * @param configMethods Mask of WPS configuration methods supported. - * Only one configMethod bit should be set per call. - * @param generatedPin 8 digit pin generated. - */ - public void onProvisionDiscoveryCompleted(byte[] p2pDeviceAddress, boolean isRequest, - byte status, short configMethods, String generatedPin) { - if (status != ISupplicantP2pIfaceCallback.P2pProvDiscStatusCode.SUCCESS) { - Log.e(TAG, "Provision discovery failed: " + status); - mMonitor.broadcastP2pProvisionDiscoveryFailure(mInterface); - return; - } - - logd("Provision discovery " + (isRequest ? "request" : "response") - + " for WPS Config method: " + configMethods); - - WifiP2pProvDiscEvent event = new WifiP2pProvDiscEvent(); - event.device = new WifiP2pDevice(); - - try { - event.device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); - } catch (Exception e) { - Log.e(TAG, "Could not decode MAC address.", e); - return; - } - - if ((configMethods & WpsConfigMethods.PUSHBUTTON) != 0) { - if (isRequest) { - event.event = WifiP2pProvDiscEvent.PBC_REQ; - mMonitor.broadcastP2pProvisionDiscoveryPbcRequest(mInterface, event); - } else { - event.event = WifiP2pProvDiscEvent.PBC_RSP; - mMonitor.broadcastP2pProvisionDiscoveryPbcResponse(mInterface, event); - } - } else if (!isRequest && (configMethods & WpsConfigMethods.KEYPAD) != 0) { - event.event = WifiP2pProvDiscEvent.SHOW_PIN; - event.pin = generatedPin; - mMonitor.broadcastP2pProvisionDiscoveryShowPin(mInterface, event); - } else if (!isRequest && (configMethods & WpsConfigMethods.DISPLAY) != 0) { - event.event = WifiP2pProvDiscEvent.ENTER_PIN; - mMonitor.broadcastP2pProvisionDiscoveryEnterPin(mInterface, event); - } else if (isRequest && (configMethods & WpsConfigMethods.DISPLAY) != 0) { - event.event = WifiP2pProvDiscEvent.SHOW_PIN; - event.pin = generatedPin; - mMonitor.broadcastP2pProvisionDiscoveryShowPin(mInterface, event); - } else if (isRequest && (configMethods & WpsConfigMethods.KEYPAD) != 0) { - event.event = WifiP2pProvDiscEvent.ENTER_PIN; - mMonitor.broadcastP2pProvisionDiscoveryEnterPin(mInterface, event); - } else { - Log.e(TAG, "Unsupported config methods: " + configMethods); - } - } - - - /** - * Used to indicate the reception of a P2P service discovery response. - * - * @param srcAddress MAC address of the device that sent the service discovery. - * @param updateIndicator Service update indicator. Refer to section 3.1.3 of - * Wifi P2P Technical specification v1.2. - * @param tlvs Refer to section 3.1.3.1 of Wifi P2P Technical specification v1.2. - */ - public void onServiceDiscoveryResponse(byte[] srcAddress, short updateIndicator, - ArrayList<Byte> tlvs) { - List<WifiP2pServiceResponse> response = null; - - logd("Service discovery response received on " + mInterface); - try { - String srcAddressStr = NativeUtil.macAddressFromByteArray(srcAddress); - // updateIndicator is not used - response = WifiP2pServiceResponse.newInstance(srcAddressStr, - NativeUtil.byteArrayFromArrayList(tlvs)); - } catch (Exception e) { - Log.e(TAG, "Could not process service discovery response.", e); - return; - } - mMonitor.broadcastP2pServiceDiscoveryResponse(mInterface, response); - } - - private WifiP2pDevice createStaEventDevice(byte[] srcAddress, byte[] p2pDeviceAddress) { - WifiP2pDevice device = new WifiP2pDevice(); - byte[] deviceAddressBytes; - // Legacy STAs may not supply a p2pDeviceAddress (signaled by a zero'd p2pDeviceAddress) - // In this case, use srcAddress instead - if (!Arrays.equals(NativeUtil.ANY_MAC_BYTES, p2pDeviceAddress)) { - deviceAddressBytes = p2pDeviceAddress; - } else { - deviceAddressBytes = srcAddress; - } - try { - device.deviceAddress = NativeUtil.macAddressFromByteArray(deviceAddressBytes); - } catch (Exception e) { - Log.e(TAG, "Could not decode MAC address", e); - return null; - } - return device; - } - - /** - * Used to indicate when a STA device is connected to this device. - * - * @param srcAddress MAC address of the device that was authorized. - * @param p2pDeviceAddress P2P device address. - */ - public void onStaAuthorized(byte[] srcAddress, byte[] p2pDeviceAddress) { - logd("STA authorized on " + mInterface); - WifiP2pDevice device = createStaEventDevice(srcAddress, p2pDeviceAddress); - if (device == null) { - return; - } - mMonitor.broadcastP2pApStaConnected(mInterface, device); - } - - - /** - * Used to indicate when a STA device is disconnected from this device. - * - * @param srcAddress MAC address of the device that was deauthorized. - * @param p2pDeviceAddress P2P device address. - */ - public void onStaDeauthorized(byte[] srcAddress, byte[] p2pDeviceAddress) { - logd("STA deauthorized on " + mInterface); - WifiP2pDevice device = createStaEventDevice(srcAddress, p2pDeviceAddress); - if (device == null) { - return; - } - mMonitor.broadcastP2pApStaDisconnected(mInterface, device); - } - - - private static P2pStatus halStatusToP2pStatus(int status) { - P2pStatus result = P2pStatus.UNKNOWN; - - switch (status) { - case P2pStatusCode.SUCCESS: - case P2pStatusCode.SUCCESS_DEFERRED: - result = P2pStatus.SUCCESS; - break; - - case P2pStatusCode.FAIL_INFO_CURRENTLY_UNAVAILABLE: - result = P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE; - break; - - case P2pStatusCode.FAIL_INCOMPATIBLE_PARAMS: - result = P2pStatus.INCOMPATIBLE_PARAMETERS; - break; - - case P2pStatusCode.FAIL_LIMIT_REACHED: - result = P2pStatus.LIMIT_REACHED; - break; - - case P2pStatusCode.FAIL_INVALID_PARAMS: - result = P2pStatus.INVALID_PARAMETER; - break; - - case P2pStatusCode.FAIL_UNABLE_TO_ACCOMMODATE: - result = P2pStatus.UNABLE_TO_ACCOMMODATE_REQUEST; - break; - - case P2pStatusCode.FAIL_PREV_PROTOCOL_ERROR: - result = P2pStatus.PREVIOUS_PROTOCOL_ERROR; - break; - - case P2pStatusCode.FAIL_NO_COMMON_CHANNELS: - result = P2pStatus.NO_COMMON_CHANNEL; - break; - - case P2pStatusCode.FAIL_UNKNOWN_GROUP: - result = P2pStatus.UNKNOWN_P2P_GROUP; - break; - - case P2pStatusCode.FAIL_BOTH_GO_INTENT_15: - result = P2pStatus.BOTH_GO_INTENT_15; - break; - - case P2pStatusCode.FAIL_INCOMPATIBLE_PROV_METHOD: - result = P2pStatus.INCOMPATIBLE_PROVISIONING_METHOD; - break; - - case P2pStatusCode.FAIL_REJECTED_BY_USER: - result = P2pStatus.REJECTED_BY_USER; - break; - } - return result; - } -} - diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java deleted file mode 100644 index dca3a6082..000000000 --- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java +++ /dev/null @@ -1,2472 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.p2p; - -import android.annotation.NonNull; -import android.hardware.wifi.supplicant.V1_0.ISupplicant; -import android.hardware.wifi.supplicant.V1_0.ISupplicantIface; -import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork; -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIface; -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback; -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pNetwork; -import android.hardware.wifi.supplicant.V1_0.IfaceType; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; -import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; -import android.hidl.manager.V1_0.IServiceManager; -import android.hidl.manager.V1_0.IServiceNotification; -import android.net.wifi.WpsInfo; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pGroupList; -import android.net.wifi.p2p.WifiP2pManager; -import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; -import android.os.IHwBinder.DeathRecipient; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; - -import com.android.server.wifi.util.ArrayUtils; -import com.android.server.wifi.util.NativeUtil; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * Native calls sending requests to the P2P Hals, and callbacks for receiving P2P events - * - * {@hide} - */ -public class SupplicantP2pIfaceHal { - private static final String TAG = "SupplicantP2pIfaceHal"; - private static boolean sVerboseLoggingEnabled = true; - private static final int RESULT_NOT_VALID = -1; - private static final int DEFAULT_OPERATING_CLASS = 81; - /** - * Regex pattern for extracting the wps device type bytes. - * Matches a strings like the following: "<categ>-<OUI>-<subcateg>"; - */ - private static final Pattern WPS_DEVICE_TYPE_PATTERN = - Pattern.compile("^(\\d{1,2})-([0-9a-fA-F]{8})-(\\d{1,2})$"); - - private Object mLock = new Object(); - - // Supplicant HAL HIDL interface objects - private IServiceManager mIServiceManager = null; - private ISupplicant mISupplicant = null; - private ISupplicantIface mHidlSupplicantIface = null; - private ISupplicantP2pIface mISupplicantP2pIface = null; - private final IServiceNotification mServiceNotificationCallback = - new IServiceNotification.Stub() { - public void onRegistration(String fqName, String name, boolean preexisting) { - synchronized (mLock) { - if (sVerboseLoggingEnabled) { - Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName - + ", " + name + " preexisting=" + preexisting); - } - if (!initSupplicantService()) { - Log.e(TAG, "initalizing ISupplicant failed."); - supplicantServiceDiedHandler(); - } else { - Log.i(TAG, "Completed initialization of ISupplicant interfaces."); - } - } - } - }; - private final DeathRecipient mServiceManagerDeathRecipient = - cookie -> { - Log.w(TAG, "IServiceManager died: cookie=" + cookie); - synchronized (mLock) { - supplicantServiceDiedHandler(); - mIServiceManager = null; // Will need to register a new ServiceNotification - } - }; - private final DeathRecipient mSupplicantDeathRecipient = - cookie -> { - Log.w(TAG, "ISupplicant/ISupplicantP2pIface died: cookie=" + cookie); - synchronized (mLock) { - supplicantServiceDiedHandler(); - } - }; - - private final WifiP2pMonitor mMonitor; - private SupplicantP2pIfaceCallback mCallback = null; - - public SupplicantP2pIfaceHal(WifiP2pMonitor monitor) { - mMonitor = monitor; - } - - private boolean linkToServiceManagerDeath() { - if (mIServiceManager == null) return false; - try { - if (!mIServiceManager.linkToDeath(mServiceManagerDeathRecipient, 0)) { - Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); - supplicantServiceDiedHandler(); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "IServiceManager.linkToDeath exception", e); - return false; - } - return true; - } - - /** - * Enable verbose logging for all sub modules. - */ - public static void enableVerboseLogging(int verbose) { - sVerboseLoggingEnabled = verbose > 0; - SupplicantP2pIfaceCallback.enableVerboseLogging(verbose); - } - - /** - * Registers a service notification for the ISupplicant service, which triggers intialization of - * the ISupplicantP2pIface - * @return true if the service notification was successfully registered - */ - public boolean initialize() { - if (sVerboseLoggingEnabled) Log.i(TAG, "Registering ISupplicant service ready callback."); - synchronized (mLock) { - if (mIServiceManager != null) { - Log.i(TAG, "Supplicant HAL already initialized."); - // Already have an IServiceManager and serviceNotification registered, don't - // don't register another. - return true; - } - mISupplicant = null; - mISupplicantP2pIface = null; - try { - mIServiceManager = getServiceManagerMockable(); - if (mIServiceManager == null) { - Log.e(TAG, "Failed to get HIDL Service Manager"); - return false; - } - if (!linkToServiceManagerDeath()) { - return false; - } - /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it - exists */ - if (!mIServiceManager.registerForNotifications( - ISupplicant.kInterfaceName, "", mServiceNotificationCallback)) { - Log.e(TAG, "Failed to register for notifications to " - + ISupplicant.kInterfaceName); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - - // Successful completion by the end of the 'try' block. This will prevent reporting - // proper initialization after exception is caught. - return true; - } catch (RemoteException e) { - Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: " - + e); - supplicantServiceDiedHandler(); - } - return false; - } - } - - private boolean linkToSupplicantDeath() { - if (mISupplicant == null) return false; - try { - if (!mISupplicant.linkToDeath(mSupplicantDeathRecipient, 0)) { - Log.wtf(TAG, "Error on linkToDeath on ISupplicant"); - supplicantServiceDiedHandler(); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.linkToDeath exception", e); - return false; - } - return true; - } - - private boolean initSupplicantService() { - synchronized (mLock) { - try { - mISupplicant = getSupplicantMockable(); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.getService exception: " + e); - return false; - } - if (mISupplicant == null) { - Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup"); - return false; - } - if (!linkToSupplicantDeath()) { - return false; - } - } - return true; - } - - private boolean linkToSupplicantP2pIfaceDeath() { - if (mISupplicantP2pIface == null) return false; - try { - if (!mISupplicantP2pIface.linkToDeath(mSupplicantDeathRecipient, 0)) { - Log.wtf(TAG, "Error on linkToDeath on ISupplicantP2pIface"); - supplicantServiceDiedHandler(); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface.linkToDeath exception", e); - return false; - } - return true; - } - - /** - * Setup the P2p iface. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - public boolean setupIface(@NonNull String ifaceName) { - synchronized (mLock) { - if (mISupplicantP2pIface != null) return false; - ISupplicantIface ifaceHwBinder; - if (isV1_1()) { - ifaceHwBinder = addIfaceV1_1(ifaceName); - } else { - ifaceHwBinder = getIfaceV1_0(ifaceName); - } - if (ifaceHwBinder == null) { - Log.e(TAG, "initSupplicantP2pIface got null iface"); - return false; - } - mISupplicantP2pIface = getP2pIfaceMockable(ifaceHwBinder); - if (!linkToSupplicantP2pIfaceDeath()) { - return false; - } - if (mISupplicantP2pIface != null && mMonitor != null) { - mCallback = new SupplicantP2pIfaceCallback(ifaceName, mMonitor); - if (!registerCallback(mCallback)) { - Log.e(TAG, "Callback registration failed. Initialization incomplete."); - return false; - } - } - return true; - } - } - - private ISupplicantIface getIfaceV1_0(@NonNull String ifaceName) { - /** List all supplicant Ifaces */ - final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList(); - try { - mISupplicant.listInterfaces((SupplicantStatus status, - ArrayList<ISupplicant.IfaceInfo> ifaces) -> { - if (status.code != SupplicantStatusCode.SUCCESS) { - Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code); - return; - } - supplicantIfaces.addAll(ifaces); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.listInterfaces exception: " + e); - return null; - } - if (supplicantIfaces.size() == 0) { - Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup."); - supplicantServiceDiedHandler(); - return null; - } - SupplicantResult<ISupplicantIface> supplicantIface = - new SupplicantResult("getInterface()"); - for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) { - if (ifaceInfo.type == IfaceType.P2P && ifaceName.equals(ifaceInfo.name)) { - try { - mISupplicant.getInterface(ifaceInfo, - (SupplicantStatus status, ISupplicantIface iface) -> { - if (status.code != SupplicantStatusCode.SUCCESS) { - Log.e(TAG, "Failed to get ISupplicantIface " + status.code); - return; - } - supplicantIface.setResult(status, iface); - }); - } catch (RemoteException | IllegalArgumentException e) { - Log.e(TAG, "ISupplicant.getInterface exception: " + e); - supplicantServiceDiedHandler(); - return null; - } - break; - } - } - return supplicantIface.getResult(); - } - - private ISupplicantIface addIfaceV1_1(@NonNull String ifaceName) { - synchronized (mLock) { - ISupplicant.IfaceInfo ifaceInfo = new ISupplicant.IfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.type = IfaceType.P2P; - SupplicantResult<ISupplicantIface> supplicantIface = - new SupplicantResult("addInterface(" + ifaceInfo + ")"); - try { - android.hardware.wifi.supplicant.V1_1.ISupplicant supplicant_v1_1 = - getSupplicantMockableV1_1(); - if (supplicant_v1_1 == null) { - Log.e(TAG, "Can't call addIface: ISupplicantP2pIface is null"); - return null; - } - supplicant_v1_1.addInterface(ifaceInfo, - (SupplicantStatus status, ISupplicantIface iface) -> { - if (status.code != SupplicantStatusCode.SUCCESS - && status.code != SupplicantStatusCode.FAILURE_IFACE_EXISTS) { - Log.e(TAG, "Failed to get ISupplicantIface " + status.code); - return; - } - supplicantIface.setResult(status, iface); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.addInterface exception: " + e); - supplicantServiceDiedHandler(); - return null; - } - return supplicantIface.getResult(); - } - } - - /** - * Teardown the P2P interface. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - public boolean teardownIface(@NonNull String ifaceName) { - synchronized (mLock) { - if (mISupplicantP2pIface == null) return false; - // Only supported for V1.1 - if (isV1_1()) { - return removeIfaceV1_1(ifaceName); - } - return true; - } - } - - /** - * Remove the P2p iface. - * - * @return true on success, false otherwise. - */ - private boolean removeIfaceV1_1(@NonNull String ifaceName) { - synchronized (mLock) { - try { - android.hardware.wifi.supplicant.V1_1.ISupplicant supplicant_v1_1 = - getSupplicantMockableV1_1(); - if (supplicant_v1_1 == null) { - Log.e(TAG, "Can't call removeIface: ISupplicantP2pIface is null"); - return false; - } - ISupplicant.IfaceInfo ifaceInfo = new ISupplicant.IfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.type = IfaceType.P2P; - SupplicantStatus status = supplicant_v1_1.removeInterface(ifaceInfo); - if (status.code != SupplicantStatusCode.SUCCESS) { - Log.e(TAG, "Failed to remove iface " + status.code); - return false; - } - mCallback = null; - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.removeInterface exception: " + e); - supplicantServiceDiedHandler(); - return false; - } - mISupplicantP2pIface = null; - return true; - } - } - - private void supplicantServiceDiedHandler() { - synchronized (mLock) { - mISupplicant = null; - mISupplicantP2pIface = null; - } - } - - - /** - * Signals whether Initialization completed successfully. - */ - public boolean isInitializationStarted() { - synchronized (mLock) { - return mIServiceManager != null; - } - } - - /** - * Signals whether Initialization completed successfully. Only necessary for testing, is not - * needed to guard calls etc. - */ - public boolean isInitializationComplete() { - return mISupplicant != null; - } - - /** - * Wrapper functions to access static HAL methods, created to be mockable in unit tests - */ - protected IServiceManager getServiceManagerMockable() throws RemoteException { - return IServiceManager.getService(); - } - - protected ISupplicant getSupplicantMockable() throws RemoteException { - try { - return ISupplicant.getService(); - } catch (NoSuchElementException e) { - Log.e(TAG, "Failed to get ISupplicant", e); - return null; - } - } - - protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1() - throws RemoteException { - synchronized (mLock) { - try { - return android.hardware.wifi.supplicant.V1_1.ISupplicant.castFrom( - mISupplicant); - } catch (NoSuchElementException e) { - Log.e(TAG, "Failed to get ISupplicant", e); - return null; - } - } - } - - protected ISupplicantP2pIface getP2pIfaceMockable(ISupplicantIface iface) { - return ISupplicantP2pIface.asInterface(iface.asBinder()); - } - - protected android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface - getP2pIfaceMockableV1_2() { - if (mISupplicantP2pIface == null) return null; - return android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface.castFrom( - mISupplicantP2pIface); - } - - protected ISupplicantP2pNetwork getP2pNetworkMockable(ISupplicantNetwork network) { - return ISupplicantP2pNetwork.asInterface(network.asBinder()); - } - - /** - * Check if the device is running V1_1 supplicant service. - * @return - */ - private boolean isV1_1() { - synchronized (mLock) { - try { - return (getSupplicantMockableV1_1() != null); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicant.getService exception: " + e); - supplicantServiceDiedHandler(); - return false; - } - } - } - - protected static void logd(String s) { - if (sVerboseLoggingEnabled) Log.d(TAG, s); - } - - protected static void logCompletion(String operation, SupplicantStatus status) { - if (status == null) { - Log.w(TAG, operation + " failed: no status code returned."); - } else if (status.code == SupplicantStatusCode.SUCCESS) { - logd(operation + " completed successfully."); - } else { - Log.w(TAG, operation + " failed: " + status.code + " (" + status.debugMessage + ")"); - } - } - - - /** - * Returns false if SupplicantP2pIface is null, and logs failure to call methodStr - */ - private boolean checkSupplicantP2pIfaceAndLogFailure(String method) { - if (mISupplicantP2pIface == null) { - Log.e(TAG, "Can't call " + method + ": ISupplicantP2pIface is null"); - return false; - } - return true; - } - - /** - * Returns SupplicantP2pIface on success, logs failure to call methodStr - * and returns false otherwise - */ - private android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface - getSupplicantP2pIfaceAndLogFailureV1_2(String method) { - synchronized (mLock) { - android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface p2pIfaceV12 = - getP2pIfaceMockableV1_2(); - if (p2pIfaceV12 == null) { - Log.e(TAG, "Can't call " + method + ": ISupplicantP2pIface is null"); - return null; - } - return p2pIfaceV12; - } - } - - private int wpsInfoToConfigMethod(int info) { - switch (info) { - case WpsInfo.PBC: - return ISupplicantP2pIface.WpsProvisionMethod.PBC; - - case WpsInfo.DISPLAY: - return ISupplicantP2pIface.WpsProvisionMethod.DISPLAY; - - case WpsInfo.KEYPAD: - case WpsInfo.LABEL: - return ISupplicantP2pIface.WpsProvisionMethod.KEYPAD; - - default: - Log.e(TAG, "Unsupported WPS provision method: " + info); - return RESULT_NOT_VALID; - } - } - - /** - * Retrieves the name of the network interface. - * - * @return name Name of the network interface, e.g., wlan0 - */ - public String getName() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("getName")) return null; - SupplicantResult<String> result = new SupplicantResult("getName()"); - - try { - mISupplicantP2pIface.getName( - (SupplicantStatus status, String name) -> { - result.setResult(status, name); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.getResult(); - } - } - - - /** - * Register for callbacks from this interface. - * - * These callbacks are invoked for events that are specific to this interface. - * Registration of multiple callback objects is supported. These objects must - * be automatically deleted when the corresponding client process is dead or - * if this interface is removed. - * - * @param receiver An instance of the |ISupplicantP2pIfaceCallback| HIDL - * interface object. - * @return boolean value indicating whether operation was successful. - */ - public boolean registerCallback(ISupplicantP2pIfaceCallback receiver) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("registerCallback")) return false; - SupplicantResult<Void> result = new SupplicantResult("registerCallback()"); - try { - result.setResult(mISupplicantP2pIface.registerCallback(receiver)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Initiate a P2P service discovery with a (optional) timeout. - * - * @param timeout Max time to be spent is peforming discovery. - * Set to 0 to indefinely continue discovery untill and explicit - * |stopFind| is sent. - * @return boolean value indicating whether operation was successful. - */ - public boolean find(int timeout) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("find")) return false; - - if (timeout < 0) { - Log.e(TAG, "Invalid timeout value: " + timeout); - return false; - } - SupplicantResult<Void> result = new SupplicantResult("find(" + timeout + ")"); - try { - result.setResult(mISupplicantP2pIface.find(timeout)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Stop an ongoing P2P service discovery. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean stopFind() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("stopFind")) return false; - SupplicantResult<Void> result = new SupplicantResult("stopFind()"); - try { - result.setResult(mISupplicantP2pIface.stopFind()); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Flush P2P peer table and state. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean flush() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("flush")) return false; - SupplicantResult<Void> result = new SupplicantResult("flush()"); - try { - result.setResult(mISupplicantP2pIface.flush()); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * This command can be used to flush all services from the - * device. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean serviceFlush() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("serviceFlush")) return false; - SupplicantResult<Void> result = new SupplicantResult("serviceFlush()"); - try { - result.setResult(mISupplicantP2pIface.flushServices()); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Turn on/off power save mode for the interface. - * - * @param groupIfName Group interface name to use. - * @param enable Indicate if power save is to be turned on/off. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean setPowerSave(String groupIfName, boolean enable) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setPowerSave")) return false; - SupplicantResult<Void> result = new SupplicantResult( - "setPowerSave(" + groupIfName + ", " + enable + ")"); - try { - result.setResult(mISupplicantP2pIface.setPowerSave(groupIfName, enable)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Set the Maximum idle time in seconds for P2P groups. - * This value controls how long a P2P group is maintained after there - * is no other members in the group. As a group owner, this means no - * associated stations in the group. As a P2P client, this means no - * group owner seen in scan results. - * - * @param groupIfName Group interface name to use. - * @param timeoutInSec Timeout value in seconds. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean setGroupIdle(String groupIfName, int timeoutInSec) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setGroupIdle")) return false; - // Basic checking here. Leave actual parameter validation to supplicant. - if (timeoutInSec < 0) { - Log.e(TAG, "Invalid group timeout value " + timeoutInSec); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "setGroupIdle(" + groupIfName + ", " + timeoutInSec + ")"); - try { - result.setResult(mISupplicantP2pIface.setGroupIdle(groupIfName, timeoutInSec)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Set the postfix to be used for P2P SSID's. - * - * @param postfix String to be appended to SSID. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean setSsidPostfix(String postfix) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setSsidPostfix")) return false; - // Basic checking here. Leave actual parameter validation to supplicant. - if (postfix == null) { - Log.e(TAG, "Invalid SSID postfix value (null)."); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult("setSsidPostfix(" + postfix + ")"); - try { - result.setResult(mISupplicantP2pIface.setSsidPostfix( - NativeUtil.decodeSsid("\"" + postfix + "\""))); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Could not decode SSID.", e); - return false; - } - - return result.isSuccess(); - } - } - - - /** - * Start P2P group formation with a discovered P2P peer. This includes - * optional group owner negotiation, group interface setup, provisioning, - * and establishing data connection. - * - * @param config Configuration to use to connect to remote device. - * @param joinExistingGroup Indicates that this is a command to join an - * existing group as a client. It skips the group owner negotiation - * part. This must send a Provision Discovery Request message to the - * target group owner before associating for WPS provisioning. - * - * @return String containing generated pin, if selected provision method - * uses PIN. - */ - public String connect(WifiP2pConfig config, boolean joinExistingGroup) { - if (config == null) return null; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setSsidPostfix")) return null; - - if (config == null) { - Log.e(TAG, "Could not connect: null config."); - return null; - } - - if (config.deviceAddress == null) { - Log.e(TAG, "Could not parse null mac address."); - return null; - } - - if (config.wps.setup == WpsInfo.PBC && !TextUtils.isEmpty(config.wps.pin)) { - Log.e(TAG, "Expected empty pin for PBC."); - return null; - } - - byte[] peerAddress = null; - try { - peerAddress = NativeUtil.macAddressToByteArray(config.deviceAddress); - } catch (Exception e) { - Log.e(TAG, "Could not parse peer mac address.", e); - return null; - } - - int provisionMethod = wpsInfoToConfigMethod(config.wps.setup); - if (provisionMethod == RESULT_NOT_VALID) { - Log.e(TAG, "Invalid WPS config method: " + config.wps.setup); - return null; - } - // NOTE: preSelectedPin cannot be null, otherwise hal would crash. - String preSelectedPin = TextUtils.isEmpty(config.wps.pin) ? "" : config.wps.pin; - boolean persistent = (config.netId == WifiP2pGroup.NETWORK_ID_PERSISTENT); - - if (config.groupOwnerIntent < 0 || config.groupOwnerIntent > 15) { - Log.e(TAG, "Invalid group owner intent: " + config.groupOwnerIntent); - return null; - } - - SupplicantResult<String> result = new SupplicantResult( - "connect(" + config.deviceAddress + ")"); - try { - mISupplicantP2pIface.connect( - peerAddress, provisionMethod, preSelectedPin, joinExistingGroup, - persistent, config.groupOwnerIntent, - (SupplicantStatus status, String generatedPin) -> { - result.setResult(status, generatedPin); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.getResult(); - } - } - - /** - * Cancel an ongoing P2P group formation and joining-a-group related - * operation. This operation unauthorizes the specific peer device (if any - * had been authorized to start group formation), stops P2P find (if in - * progress), stops pending operations for join-a-group, and removes the - * P2P group interface (if one was used) that is in the WPS provisioning - * step. If the WPS provisioning step has been completed, the group is not - * terminated. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean cancelConnect() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("cancelConnect")) return false; - SupplicantResult<Void> result = new SupplicantResult("cancelConnect()"); - try { - result.setResult(mISupplicantP2pIface.cancelConnect()); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Send P2P provision discovery request to the specified peer. The - * parameters for this command are the P2P device address of the peer and the - * desired configuration method. - * - * @param config Config class describing peer setup. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean provisionDiscovery(WifiP2pConfig config) { - if (config == null) return false; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("provisionDiscovery")) return false; - - int targetMethod = wpsInfoToConfigMethod(config.wps.setup); - if (targetMethod == RESULT_NOT_VALID) { - Log.e(TAG, "Unrecognized WPS configuration method: " + config.wps.setup); - return false; - } - if (targetMethod == ISupplicantP2pIface.WpsProvisionMethod.DISPLAY) { - // We are doing display, so provision discovery is keypad. - targetMethod = ISupplicantP2pIface.WpsProvisionMethod.KEYPAD; - } else if (targetMethod == ISupplicantP2pIface.WpsProvisionMethod.KEYPAD) { - // We are doing keypad, so provision discovery is display. - targetMethod = ISupplicantP2pIface.WpsProvisionMethod.DISPLAY; - } - - if (config.deviceAddress == null) { - Log.e(TAG, "Cannot parse null mac address."); - return false; - } - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(config.deviceAddress); - } catch (Exception e) { - Log.e(TAG, "Could not parse peer mac address.", e); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "provisionDiscovery(" + config.deviceAddress + ", " + config.wps.setup + ")"); - try { - result.setResult(mISupplicantP2pIface.provisionDiscovery(macAddress, targetMethod)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Invite a device to a persistent group. - * If the peer device is the group owner of the persistent group, the peer - * parameter is not needed. Otherwise it is used to specify which - * device to invite. |goDeviceAddress| parameter may be used to override - * the group owner device address for Invitation Request should it not be - * known for some reason (this should not be needed in most cases). - * - * @param group Group object to use. - * @param peerAddress MAC address of the device to invite. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean invite(WifiP2pGroup group, String peerAddress) { - if (TextUtils.isEmpty(peerAddress)) return false; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("invite")) return false; - if (group == null) { - Log.e(TAG, "Cannot invite to null group."); - return false; - } - - if (group.getOwner() == null) { - Log.e(TAG, "Cannot invite to group with null owner."); - return false; - } - - if (group.getOwner().deviceAddress == null) { - Log.e(TAG, "Group owner has no mac address."); - return false; - } - - byte[] ownerMacAddress = null; - try { - ownerMacAddress = NativeUtil.macAddressToByteArray(group.getOwner().deviceAddress); - } catch (Exception e) { - Log.e(TAG, "Group owner mac address parse error.", e); - return false; - } - - if (peerAddress == null) { - Log.e(TAG, "Cannot parse peer mac address."); - return false; - } - - byte[] peerMacAddress; - try { - peerMacAddress = NativeUtil.macAddressToByteArray(peerAddress); - } catch (Exception e) { - Log.e(TAG, "Peer mac address parse error.", e); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "invite(" + group.getInterface() + ", " + group.getOwner().deviceAddress - + ", " + peerAddress + ")"); - try { - result.setResult(mISupplicantP2pIface.invite( - group.getInterface(), ownerMacAddress, peerMacAddress)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Reject connection attempt from a peer (specified with a device - * address). This is a mechanism to reject a pending group owner negotiation - * with a peer and request to automatically block any further connection or - * discovery of the peer. - * - * @param peerAddress MAC address of the device to reject. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean reject(String peerAddress) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("reject")) return false; - - if (peerAddress == null) { - Log.e(TAG, "Cannot parse rejected peer's mac address."); - return false; - } - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(peerAddress); - } catch (Exception e) { - Log.e(TAG, "Could not parse peer mac address.", e); - return false; - } - - SupplicantResult<Void> result = - new SupplicantResult("reject(" + peerAddress + ")"); - try { - result.setResult(mISupplicantP2pIface.reject(macAddress)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Gets the MAC address of the device. - * - * @return MAC address of the device. - */ - public String getDeviceAddress() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("getDeviceAddress")) return null; - SupplicantResult<String> result = new SupplicantResult("getDeviceAddress()"); - try { - mISupplicantP2pIface.getDeviceAddress((SupplicantStatus status, byte[] address) -> { - String parsedAddress = null; - try { - parsedAddress = NativeUtil.macAddressFromByteArray(address); - } catch (Exception e) { - Log.e(TAG, "Could not process reported address.", e); - } - result.setResult(status, parsedAddress); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - return null; - } - - return result.getResult(); - } - } - - - /** - * Gets the operational SSID of the device. - * - * @param address MAC address of the peer. - * - * @return SSID of the device. - */ - public String getSsid(String address) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("getSsid")) return null; - - if (address == null) { - Log.e(TAG, "Cannot parse peer mac address."); - return null; - } - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(address); - } catch (Exception e) { - Log.e(TAG, "Could not parse mac address.", e); - return null; - } - - SupplicantResult<String> result = - new SupplicantResult("getSsid(" + address + ")"); - try { - mISupplicantP2pIface.getSsid( - macAddress, (SupplicantStatus status, ArrayList<Byte> ssid) -> { - String ssidString = null; - if (ssid != null) { - try { - ssidString = NativeUtil.removeEnclosingQuotes( - NativeUtil.encodeSsid(ssid)); - } catch (Exception e) { - Log.e(TAG, "Could not encode SSID.", e); - } - } - result.setResult(status, ssidString); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - return null; - } - - return result.getResult(); - } - } - - - /** - * Reinvoke a device from a persistent group. - * - * @param networkId Used to specify the persistent group. - * @param peerAddress MAC address of the device to reinvoke. - * - * @return true, if operation was successful. - */ - public boolean reinvoke(int networkId, String peerAddress) { - if (TextUtils.isEmpty(peerAddress) || networkId < 0) return false; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("reinvoke")) return false; - if (peerAddress == null) { - Log.e(TAG, "Cannot parse peer mac address."); - return false; - } - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(peerAddress); - } catch (Exception e) { - Log.e(TAG, "Could not parse mac address.", e); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "reinvoke(" + networkId + ", " + peerAddress + ")"); - try { - result.setResult(mISupplicantP2pIface.reinvoke(networkId, macAddress)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Set up a P2P group owner manually (i.e., without group owner - * negotiation with a specific peer). This is also known as autonomous - * group owner. - * - * @param networkId Used to specify the restart of a persistent group. - * @param isPersistent Used to request a persistent group to be formed. - * - * @return true, if operation was successful. - */ - public boolean groupAdd(int networkId, boolean isPersistent) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("groupAdd")) return false; - SupplicantResult<Void> result = - new SupplicantResult("groupAdd(" + networkId + ", " + isPersistent + ")"); - try { - result.setResult(mISupplicantP2pIface.addGroup(isPersistent, networkId)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - /** - * Set up a P2P group as Group Owner or join a group with a configuration. - * - * @param networkName SSID of the group to be formed - * @param passphrase passphrase of the group to be formed - * @param isPersistent Used to request a persistent group to be formed. - * @param freq prefered frequencty or band of the group to be formed - * @param peerAddress peerAddress Group Owner MAC address, only applied for Group Client. - * If the MAC is "00:00:00:00:00:00", the device will try to find a peer - * whose SSID matches ssid. - * @param join join a group or create a group - * - * @return true, if operation was successful. - */ - public boolean groupAdd(String networkName, String passphrase, - boolean isPersistent, int freq, String peerAddress, boolean join) { - synchronized (mLock) { - android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface ifaceV12 = - getSupplicantP2pIfaceAndLogFailureV1_2("groupAdd_1_2"); - if (ifaceV12 == null) return false; - - java.util.ArrayList<Byte> ssid = NativeUtil.decodeSsid("\"" + networkName + "\""); - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(peerAddress); - } catch (Exception e) { - Log.e(TAG, "Could not parse mac address.", e); - return false; - } - - SupplicantResult<Void> result = - new SupplicantResult("groupAdd(" + networkName + ", " - + (TextUtils.isEmpty(passphrase) ? "<Empty>" : "<Non-Empty>") - + ", " + isPersistent + ", " + freq - + ", " + peerAddress + ", " + join + ")"); - try { - result.setResult(ifaceV12.addGroup_1_2( - ssid, passphrase, isPersistent, freq, macAddress, join)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - /** - * Set up a P2P group owner manually. - * This is a helper method that invokes groupAdd(networkId, isPersistent) internally. - * - * @param isPersistent Used to request a persistent group to be formed. - * - * @return true, if operation was successful. - */ - public boolean groupAdd(boolean isPersistent) { - // Supplicant expects networkId to be -1 if not supplied. - return groupAdd(-1, isPersistent); - } - - - /** - * Terminate a P2P group. If a new virtual network interface was used for - * the group, it must also be removed. The network interface name of the - * group interface is used as a parameter for this command. - * - * @param groupName Group interface name to use. - * - * @return true, if operation was successful. - */ - public boolean groupRemove(String groupName) { - if (TextUtils.isEmpty(groupName)) return false; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("groupRemove")) return false; - SupplicantResult<Void> result = new SupplicantResult("groupRemove(" + groupName + ")"); - try { - result.setResult(mISupplicantP2pIface.removeGroup(groupName)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Gets the capability of the group which the device is a - * member of. - * - * @param peerAddress MAC address of the peer. - * - * @return combination of |GroupCapabilityMask| values. - */ - public int getGroupCapability(String peerAddress) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("getGroupCapability")) { - return RESULT_NOT_VALID; - } - - if (peerAddress == null) { - Log.e(TAG, "Cannot parse peer mac address."); - return RESULT_NOT_VALID; - } - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(peerAddress); - } catch (Exception e) { - Log.e(TAG, "Could not parse group address.", e); - return RESULT_NOT_VALID; - } - - SupplicantResult<Integer> capability = new SupplicantResult( - "getGroupCapability(" + peerAddress + ")"); - try { - mISupplicantP2pIface.getGroupCapability( - macAddress, (SupplicantStatus status, int cap) -> { - capability.setResult(status, cap); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - if (!capability.isSuccess()) { - return RESULT_NOT_VALID; - } - - return capability.getResult(); - } - } - - - /** - * Configure Extended Listen Timing. - * - * If enabled, listen state must be entered every |intervalInMillis| for at - * least |periodInMillis|. Both values have acceptable range of 1-65535 - * (with interval obviously having to be larger than or equal to duration). - * If the P2P module is not idle at the time the Extended Listen Timing - * timeout occurs, the Listen State operation must be skipped. - * - * @param enable Enables or disables listening. - * @param periodInMillis Period in milliseconds. - * @param intervalInMillis Interval in milliseconds. - * - * @return true, if operation was successful. - */ - public boolean configureExtListen(boolean enable, int periodInMillis, int intervalInMillis) { - if (enable && intervalInMillis < periodInMillis) { - return false; - } - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("configureExtListen")) return false; - - // If listening is disabled, wpa supplicant expects zeroes. - if (!enable) { - periodInMillis = 0; - intervalInMillis = 0; - } - - // Verify that the integers are not negative. Leave actual parameter validation to - // supplicant. - if (periodInMillis < 0 || intervalInMillis < 0) { - Log.e(TAG, "Invalid parameters supplied to configureExtListen: " + periodInMillis - + ", " + intervalInMillis); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "configureExtListen(" + periodInMillis + ", " + intervalInMillis + ")"); - try { - result.setResult( - mISupplicantP2pIface.configureExtListen(periodInMillis, intervalInMillis)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Set P2P Listen channel and operating chanel. - * - * @param listenChannel Wifi channel. eg, 1, 6, 11. - * @param operatingChannel Wifi channel. eg, 1, 6, 11. - * - * @return true, if operation was successful. - */ - public boolean setListenChannel(int listenChannel, int operatingChannel) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setListenChannel")) return false; - - if (listenChannel >= 1 && listenChannel <= 11) { - SupplicantResult<Void> result = new SupplicantResult( - "setListenChannel(" + listenChannel + ", " + DEFAULT_OPERATING_CLASS + ")"); - try { - result.setResult(mISupplicantP2pIface.setListenChannel( - listenChannel, DEFAULT_OPERATING_CLASS)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - if (!result.isSuccess()) { - return false; - } - } else if (listenChannel != 0) { - // listenChannel == 0 does not set any listen channel. - return false; - } - - if (operatingChannel >= 0 && operatingChannel <= 165) { - ArrayList<ISupplicantP2pIface.FreqRange> ranges = new ArrayList<>(); - // operatingChannel == 0 enables all freqs. - if (operatingChannel >= 1 && operatingChannel <= 165) { - int freq = (operatingChannel <= 14 ? 2407 : 5000) + operatingChannel * 5; - ISupplicantP2pIface.FreqRange range1 = new ISupplicantP2pIface.FreqRange(); - range1.min = 1000; - range1.max = freq - 5; - ISupplicantP2pIface.FreqRange range2 = new ISupplicantP2pIface.FreqRange(); - range2.min = freq + 5; - range2.max = 6000; - ranges.add(range1); - ranges.add(range2); - } - SupplicantResult<Void> result = new SupplicantResult( - "setDisallowedFrequencies(" + ranges + ")"); - try { - result.setResult(mISupplicantP2pIface.setDisallowedFrequencies(ranges)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - return false; - } - } - - - /** - * This command can be used to add a upnp/bonjour service. - * - * @param servInfo List of service queries. - * - * @return true, if operation was successful. - */ - public boolean serviceAdd(WifiP2pServiceInfo servInfo) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("serviceAdd")) return false; - - if (servInfo == null) { - Log.e(TAG, "Null service info passed."); - return false; - } - - for (String s : servInfo.getSupplicantQueryList()) { - if (s == null) { - Log.e(TAG, "Invalid service description (null)."); - return false; - } - - String[] data = s.split(" "); - if (data.length < 3) { - Log.e(TAG, "Service specification invalid: " + s); - return false; - } - - SupplicantResult<Void> result = null; - try { - if ("upnp".equals(data[0])) { - int version = 0; - try { - version = Integer.parseInt(data[1], 16); - } catch (NumberFormatException e) { - Log.e(TAG, "UPnP Service specification invalid: " + s, e); - return false; - } - - result = new SupplicantResult( - "addUpnpService(" + data[1] + ", " + data[2] + ")"); - result.setResult(mISupplicantP2pIface.addUpnpService(version, data[2])); - } else if ("bonjour".equals(data[0])) { - if (data[1] != null && data[2] != null) { - ArrayList<Byte> request = null; - ArrayList<Byte> response = null; - try { - request = NativeUtil.byteArrayToArrayList( - NativeUtil.hexStringToByteArray(data[1])); - response = NativeUtil.byteArrayToArrayList( - NativeUtil.hexStringToByteArray(data[2])); - } catch (Exception e) { - Log.e(TAG, "Invalid bonjour service description."); - return false; - } - result = new SupplicantResult( - "addBonjourService(" + data[1] + ", " + data[2] + ")"); - result.setResult( - mISupplicantP2pIface.addBonjourService(request, response)); - } - } else { - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - if (result == null || !result.isSuccess()) return false; - } - - return true; - } - } - - - /** - * This command can be used to remove a upnp/bonjour service. - * - * @param servInfo List of service queries. - * - * @return true, if operation was successful. - */ - public boolean serviceRemove(WifiP2pServiceInfo servInfo) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("serviceRemove")) return false; - - if (servInfo == null) { - Log.e(TAG, "Null service info passed."); - return false; - } - - for (String s : servInfo.getSupplicantQueryList()) { - if (s == null) { - Log.e(TAG, "Invalid service description (null)."); - return false; - } - - String[] data = s.split(" "); - if (data.length < 3) { - Log.e(TAG, "Service specification invalid: " + s); - return false; - } - - SupplicantResult<Void> result = null; - try { - if ("upnp".equals(data[0])) { - int version = 0; - try { - version = Integer.parseInt(data[1], 16); - } catch (NumberFormatException e) { - Log.e(TAG, "UPnP Service specification invalid: " + s, e); - return false; - } - result = new SupplicantResult( - "removeUpnpService(" + data[1] + ", " + data[2] + ")"); - result.setResult(mISupplicantP2pIface.removeUpnpService(version, data[2])); - } else if ("bonjour".equals(data[0])) { - if (data[1] != null) { - ArrayList<Byte> request = null; - try { - request = NativeUtil.byteArrayToArrayList( - NativeUtil.hexStringToByteArray(data[1])); - } catch (Exception e) { - Log.e(TAG, "Invalid bonjour service description."); - return false; - } - result = new SupplicantResult("removeBonjourService(" + data[1] + ")"); - result.setResult(mISupplicantP2pIface.removeBonjourService(request)); - } - } else { - Log.e(TAG, "Unknown / unsupported P2P service requested: " + data[0]); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - if (result == null || !result.isSuccess()) return false; - } - - return true; - } - } - - - /** - * Schedule a P2P service discovery request. The parameters for this command - * are the device address of the peer device (or 00:00:00:00:00:00 for - * wildcard query that is sent to every discovered P2P peer that supports - * service discovery) and P2P Service Query TLV(s) as hexdump. - * - * @param peerAddress MAC address of the device to discover. - * @param query Hex dump of the query data. - * @return identifier Identifier for the request. Can be used to cancel the - * request. - */ - public String requestServiceDiscovery(String peerAddress, String query) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("requestServiceDiscovery")) return null; - - if (peerAddress == null) { - Log.e(TAG, "Cannot parse peer mac address."); - return null; - } - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(peerAddress); - } catch (Exception e) { - Log.e(TAG, "Could not process peer MAC address.", e); - return null; - } - - if (query == null) { - Log.e(TAG, "Cannot parse service discovery query: " + query); - return null; - } - ArrayList<Byte> binQuery = null; - try { - binQuery = NativeUtil.byteArrayToArrayList(NativeUtil.hexStringToByteArray(query)); - } catch (Exception e) { - Log.e(TAG, "Could not parse service query.", e); - return null; - } - - SupplicantResult<Long> result = new SupplicantResult( - "requestServiceDiscovery(" + peerAddress + ", " + query + ")"); - try { - mISupplicantP2pIface.requestServiceDiscovery( - macAddress, binQuery, - (SupplicantStatus status, long identifier) -> { - result.setResult(status, new Long(identifier)); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - Long value = result.getResult(); - if (value == null) return null; - return value.toString(); - } - } - - - /** - * Cancel a previous service discovery request. - * - * @param identifier Identifier for the request to cancel. - * @return true, if operation was successful. - */ - public boolean cancelServiceDiscovery(String identifier) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("cancelServiceDiscovery")) return false; - if (identifier == null) { - Log.e(TAG, "cancelServiceDiscovery requires a valid tag."); - return false; - } - - long id = 0; - try { - id = Long.parseLong(identifier); - } catch (NumberFormatException e) { - Log.e(TAG, "Service discovery identifier invalid: " + identifier, e); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "cancelServiceDiscovery(" + identifier + ")"); - try { - result.setResult(mISupplicantP2pIface.cancelServiceDiscovery(id)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Send driver command to set Miracast mode. - * - * @param mode Mode of Miracast. - * @return true, if operation was successful. - */ - public boolean setMiracastMode(int mode) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setMiracastMode")) return false; - byte targetMode = ISupplicantP2pIface.MiracastMode.DISABLED; - - switch (mode) { - case WifiP2pManager.MIRACAST_SOURCE: - targetMode = ISupplicantP2pIface.MiracastMode.SOURCE; - break; - - case WifiP2pManager.MIRACAST_SINK: - targetMode = ISupplicantP2pIface.MiracastMode.SINK; - break; - } - - SupplicantResult<Void> result = new SupplicantResult( - "setMiracastMode(" + mode + ")"); - try { - result.setResult(mISupplicantP2pIface.setMiracastMode(targetMode)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Initiate WPS Push Button setup. - * The PBC operation requires that a button is also pressed at the - * AP/Registrar at about the same time (2 minute window). - * - * @param groupIfName Group interface name to use. - * @param bssid BSSID of the AP. Use empty bssid to indicate wildcard. - * @return true, if operation was successful. - */ - public boolean startWpsPbc(String groupIfName, String bssid) { - if (TextUtils.isEmpty(groupIfName)) { - Log.e(TAG, "Group name required when requesting WPS PBC. Got (" + groupIfName + ")"); - return false; - } - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("startWpsPbc")) return false; - // Null values should be fine, since bssid can be empty. - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(bssid); - } catch (Exception e) { - Log.e(TAG, "Could not parse BSSID.", e); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "startWpsPbc(" + groupIfName + ", " + bssid + ")"); - try { - result.setResult(mISupplicantP2pIface.startWpsPbc(groupIfName, macAddress)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Initiate WPS Pin Keypad setup. - * - * @param groupIfName Group interface name to use. - * @param pin 8 digit pin to be used. - * @return true, if operation was successful. - */ - public boolean startWpsPinKeypad(String groupIfName, String pin) { - if (TextUtils.isEmpty(groupIfName) || TextUtils.isEmpty(pin)) return false; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("startWpsPinKeypad")) return false; - if (groupIfName == null) { - Log.e(TAG, "Group name required when requesting WPS KEYPAD."); - return false; - } - if (pin == null) { - Log.e(TAG, "PIN required when requesting WPS KEYPAD."); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "startWpsPinKeypad(" + groupIfName + ", " + pin + ")"); - try { - result.setResult(mISupplicantP2pIface.startWpsPinKeypad(groupIfName, pin)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Initiate WPS Pin Display setup. - * - * @param groupIfName Group interface name to use. - * @param bssid BSSID of the AP. Use empty bssid to indicate wildcard. - * @return generated pin if operation was successful, null otherwise. - */ - public String startWpsPinDisplay(String groupIfName, String bssid) { - if (TextUtils.isEmpty(groupIfName)) return null; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("startWpsPinDisplay")) return null; - if (groupIfName == null) { - Log.e(TAG, "Group name required when requesting WPS KEYPAD."); - return null; - } - - // Null values should be fine, since bssid can be empty. - byte[] macAddress = null; - try { - macAddress = NativeUtil.macAddressToByteArray(bssid); - } catch (Exception e) { - Log.e(TAG, "Could not parse BSSID.", e); - return null; - } - - SupplicantResult<String> result = new SupplicantResult( - "startWpsPinDisplay(" + groupIfName + ", " + bssid + ")"); - try { - mISupplicantP2pIface.startWpsPinDisplay( - groupIfName, macAddress, - (SupplicantStatus status, String generatedPin) -> { - result.setResult(status, generatedPin); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.getResult(); - } - } - - - /** - * Cancel any ongoing WPS operations. - * - * @param groupIfName Group interface name to use. - * @return true, if operation was successful. - */ - public boolean cancelWps(String groupIfName) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("cancelWps")) return false; - if (groupIfName == null) { - Log.e(TAG, "Group name required when requesting WPS KEYPAD."); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "cancelWps(" + groupIfName + ")"); - try { - result.setResult(mISupplicantP2pIface.cancelWps(groupIfName)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Enable/Disable Wifi Display. - * - * @param enable true to enable, false to disable. - * @return true, if operation was successful. - */ - public boolean enableWfd(boolean enable) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("enableWfd")) return false; - - SupplicantResult<Void> result = new SupplicantResult( - "enableWfd(" + enable + ")"); - try { - result.setResult(mISupplicantP2pIface.enableWfd(enable)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Set Wifi Display device info. - * - * @param info WFD device info as described in section 5.1.2 of WFD technical - * specification v1.0.0. - * @return true, if operation was successful. - */ - public boolean setWfdDeviceInfo(String info) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setWfdDeviceInfo")) return false; - - if (info == null) { - Log.e(TAG, "Cannot parse null WFD info string."); - return false; - } - byte[] wfdInfo = null; - try { - wfdInfo = NativeUtil.hexStringToByteArray(info); - } catch (Exception e) { - Log.e(TAG, "Could not parse WFD Device Info string."); - return false; - } - - SupplicantResult<Void> result = new SupplicantResult( - "setWfdDeviceInfo(" + info + ")"); - try { - result.setResult(mISupplicantP2pIface.setWfdDeviceInfo(wfdInfo)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - /** - * Remove network with provided id. - * - * @param networkId Id of the network to lookup. - * @return true, if operation was successful. - */ - public boolean removeNetwork(int networkId) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("removeNetwork")) return false; - - SupplicantResult<Void> result = new SupplicantResult( - "removeNetwork(" + networkId + ")"); - try { - result.setResult(mISupplicantP2pIface.removeNetwork(networkId)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - /** - * List the networks saved in wpa_supplicant. - * - * @return List of network ids. - */ - private List<Integer> listNetworks() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("listNetworks")) return null; - SupplicantResult<ArrayList> result = new SupplicantResult("listNetworks()"); - try { - mISupplicantP2pIface.listNetworks( - (SupplicantStatus status, ArrayList<Integer> networkIds) -> { - result.setResult(status, networkIds); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.getResult(); - } - } - - /** - * Get the supplicant P2p network object for the specified network ID. - * - * @param networkId Id of the network to lookup. - * @return ISupplicantP2pNetwork instance on success, null on failure. - */ - private ISupplicantP2pNetwork getNetwork(int networkId) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("getNetwork")) return null; - SupplicantResult<ISupplicantNetwork> result = - new SupplicantResult("getNetwork(" + networkId + ")"); - try { - mISupplicantP2pIface.getNetwork( - networkId, - (SupplicantStatus status, ISupplicantNetwork network) -> { - result.setResult(status, network); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - if (result.getResult() == null) { - Log.e(TAG, "getNetwork got null network"); - return null; - } - return getP2pNetworkMockable(result.getResult()); - } - } - - /** - * Get the persistent group list from wpa_supplicant's p2p mgmt interface - * - * @param groups WifiP2pGroupList to store persistent groups in - * @return true, if list has been modified. - */ - public boolean loadGroups(WifiP2pGroupList groups) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("loadGroups")) return false; - List<Integer> networkIds = listNetworks(); - if (networkIds == null || networkIds.isEmpty()) { - return false; - } - for (Integer networkId : networkIds) { - ISupplicantP2pNetwork network = getNetwork(networkId); - if (network == null) { - Log.e(TAG, "Failed to retrieve network object for " + networkId); - continue; - } - SupplicantResult<Boolean> resultIsCurrent = - new SupplicantResult("isCurrent(" + networkId + ")"); - try { - network.isCurrent( - (SupplicantStatus status, boolean isCurrent) -> { - resultIsCurrent.setResult(status, isCurrent); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - /** Skip the current network, if we're somehow getting networks from the p2p GO - interface, instead of p2p mgmt interface*/ - if (!resultIsCurrent.isSuccess() || resultIsCurrent.getResult()) { - Log.i(TAG, "Skipping current network"); - continue; - } - - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(networkId); - - // Now get the ssid, bssid and other flags for this network. - SupplicantResult<ArrayList> resultSsid = - new SupplicantResult("getSsid(" + networkId + ")"); - try { - network.getSsid( - (SupplicantStatus status, ArrayList<Byte> ssid) -> { - resultSsid.setResult(status, ssid); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - if (resultSsid.isSuccess() && resultSsid.getResult() != null - && !resultSsid.getResult().isEmpty()) { - group.setNetworkName(NativeUtil.removeEnclosingQuotes( - NativeUtil.encodeSsid(resultSsid.getResult()))); - } - - SupplicantResult<byte[]> resultBssid = - new SupplicantResult("getBssid(" + networkId + ")"); - try { - network.getBssid( - (SupplicantStatus status, byte[] bssid) -> { - resultBssid.setResult(status, bssid); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - if (resultBssid.isSuccess() && !ArrayUtils.isEmpty(resultBssid.getResult())) { - WifiP2pDevice device = new WifiP2pDevice(); - device.deviceAddress = - NativeUtil.macAddressFromByteArray(resultBssid.getResult()); - group.setOwner(device); - } - - SupplicantResult<Boolean> resultIsGo = - new SupplicantResult("isGo(" + networkId + ")"); - try { - network.isGo( - (SupplicantStatus status, boolean isGo) -> { - resultIsGo.setResult(status, isGo); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - if (resultIsGo.isSuccess()) { - group.setIsGroupOwner(resultIsGo.getResult()); - } - groups.add(group); - } - } - return true; - } - - /** - * Set WPS device name. - * - * @param name String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsDeviceName(String name) { - if (name == null) { - return false; - } - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setWpsDeviceName")) return false; - SupplicantResult<Void> result = new SupplicantResult( - "setWpsDeviceName(" + name + ")"); - try { - result.setResult(mISupplicantP2pIface.setWpsDeviceName(name)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - /** - * Set WPS device type. - * - * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg> - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsDeviceType(String typeStr) { - try { - Matcher match = WPS_DEVICE_TYPE_PATTERN.matcher(typeStr); - if (!match.find() || match.groupCount() != 3) { - Log.e(TAG, "Malformed WPS device type " + typeStr); - return false; - } - short categ = Short.parseShort(match.group(1)); - byte[] oui = NativeUtil.hexStringToByteArray(match.group(2)); - short subCateg = Short.parseShort(match.group(3)); - - byte[] bytes = new byte[8]; - ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); - byteBuffer.putShort(categ); - byteBuffer.put(oui); - byteBuffer.putShort(subCateg); - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setWpsDeviceType")) return false; - SupplicantResult<Void> result = new SupplicantResult( - "setWpsDeviceType(" + typeStr + ")"); - try { - result.setResult(mISupplicantP2pIface.setWpsDeviceType(bytes)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + typeStr, e); - return false; - } - } - - /** - * Set WPS config methods - * - * @param configMethodsStr List of config methods. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setWpsConfigMethods(String configMethodsStr) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setWpsConfigMethods")) return false; - SupplicantResult<Void> result = - new SupplicantResult("setWpsConfigMethods(" + configMethodsStr + ")"); - short configMethodsMask = 0; - String[] configMethodsStrArr = configMethodsStr.split("\\s+"); - for (int i = 0; i < configMethodsStrArr.length; i++) { - configMethodsMask |= stringToWpsConfigMethod(configMethodsStrArr[i]); - } - try { - result.setResult(mISupplicantP2pIface.setWpsConfigMethods(configMethodsMask)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - /** - * Get NFC handover request message. - * - * @return select message if created successfully, null otherwise. - */ - public String getNfcHandoverRequest() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("getNfcHandoverRequest")) return null; - SupplicantResult<ArrayList> result = new SupplicantResult( - "getNfcHandoverRequest()"); - try { - mISupplicantP2pIface.createNfcHandoverRequestMessage( - (SupplicantStatus status, ArrayList<Byte> message) -> { - result.setResult(status, message); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - if (!result.isSuccess()) { - return null; - - } - return NativeUtil.hexStringFromByteArray( - NativeUtil.byteArrayFromArrayList(result.getResult())); - } - } - - /** - * Get NFC handover select message. - * - * @return select message if created successfully, null otherwise. - */ - public String getNfcHandoverSelect() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("getNfcHandoverSelect")) return null; - SupplicantResult<ArrayList> result = new SupplicantResult( - "getNfcHandoverSelect()"); - try { - mISupplicantP2pIface.createNfcHandoverSelectMessage( - (SupplicantStatus status, ArrayList<Byte> message) -> { - result.setResult(status, message); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - if (!result.isSuccess()) { - return null; - - } - return NativeUtil.hexStringFromByteArray( - NativeUtil.byteArrayFromArrayList(result.getResult())); - } - } - - /** - * Report NFC handover select message. - * - * @return true if reported successfully, false otherwise. - */ - public boolean initiatorReportNfcHandover(String selectMessage) { - if (selectMessage == null) return false; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("initiatorReportNfcHandover")) return false; - SupplicantResult<Void> result = new SupplicantResult( - "initiatorReportNfcHandover(" + selectMessage + ")"); - try { - result.setResult(mISupplicantP2pIface.reportNfcHandoverInitiation( - NativeUtil.byteArrayToArrayList(NativeUtil.hexStringToByteArray( - selectMessage)))); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + selectMessage, e); - return false; - } - return result.isSuccess(); - } - } - - /** - * Report NFC handover request message. - * - * @return true if reported successfully, false otherwise. - */ - public boolean responderReportNfcHandover(String requestMessage) { - if (requestMessage == null) return false; - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("responderReportNfcHandover")) return false; - SupplicantResult<Void> result = new SupplicantResult( - "responderReportNfcHandover(" + requestMessage + ")"); - try { - result.setResult(mISupplicantP2pIface.reportNfcHandoverResponse( - NativeUtil.byteArrayToArrayList(NativeUtil.hexStringToByteArray( - requestMessage)))); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + requestMessage, e); - return false; - } - return result.isSuccess(); - } - } - - /** - * Set the client list for the provided network. - * - * @param networkId Id of the network. - * @param clientListStr Space separated list of clients. - * @return true, if operation was successful. - */ - public boolean setClientList(int networkId, String clientListStr) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("setClientList")) return false; - if (TextUtils.isEmpty(clientListStr)) { - Log.e(TAG, "Invalid client list"); - return false; - } - ISupplicantP2pNetwork network = getNetwork(networkId); - if (network == null) { - Log.e(TAG, "Invalid network id "); - return false; - } - SupplicantResult<Void> result = new SupplicantResult( - "setClientList(" + networkId + ", " + clientListStr + ")"); - try { - ArrayList<byte[]> clients = new ArrayList<>(); - for (String clientStr : Arrays.asList(clientListStr.split("\\s+"))) { - clients.add(NativeUtil.macAddressToByteArray(clientStr)); - } - result.setResult(network.setClientList(clients)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Illegal argument " + clientListStr, e); - return false; - } - return result.isSuccess(); - } - } - - /** - * Set the client list for the provided network. - * - * @param networkId Id of the network. - * @return Space separated list of clients if successfull, null otherwise. - */ - public String getClientList(int networkId) { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("getClientList")) return null; - ISupplicantP2pNetwork network = getNetwork(networkId); - if (network == null) { - Log.e(TAG, "Invalid network id "); - return null; - } - SupplicantResult<ArrayList> result = new SupplicantResult( - "getClientList(" + networkId + ")"); - try { - network.getClientList( - (SupplicantStatus status, ArrayList<byte[]> clients) -> { - result.setResult(status, clients); - }); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - if (!result.isSuccess()) { - return null; - } - ArrayList<byte[]> clients = result.getResult(); - return clients.stream() - .map(NativeUtil::macAddressFromByteArray) - .collect(Collectors.joining(" ")); - } - } - - /** - * Persist the current configurations to disk. - * - * @return true, if operation was successful. - */ - public boolean saveConfig() { - synchronized (mLock) { - if (!checkSupplicantP2pIfaceAndLogFailure("saveConfig")) return false; - SupplicantResult<Void> result = new SupplicantResult("saveConfig()"); - try { - result.setResult(mISupplicantP2pIface.saveConfig()); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - return result.isSuccess(); - } - } - - - /** - * Enable/Disable P2P MAC randomization. - * - * @param enable true to enable, false to disable. - * @return true, if operation was successful. - */ - public boolean setMacRandomization(boolean enable) { - synchronized (mLock) { - android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface ifaceV12 = - getSupplicantP2pIfaceAndLogFailureV1_2("setMacRandomization"); - if (ifaceV12 == null) return false; - - SupplicantResult<Void> result = new SupplicantResult( - "setMacRandomization(" + enable + ")"); - try { - result.setResult(ifaceV12.setMacRandomization(enable)); - } catch (RemoteException e) { - Log.e(TAG, "ISupplicantP2pIface exception: " + e); - supplicantServiceDiedHandler(); - } - - return result.isSuccess(); - } - } - - - /** - * Converts the Wps config method string to the equivalent enum value. - */ - private static short stringToWpsConfigMethod(String configMethod) { - switch (configMethod) { - case "usba": - return WpsConfigMethods.USBA; - case "ethernet": - return WpsConfigMethods.ETHERNET; - case "label": - return WpsConfigMethods.LABEL; - case "display": - return WpsConfigMethods.DISPLAY; - case "int_nfc_token": - return WpsConfigMethods.INT_NFC_TOKEN; - case "ext_nfc_token": - return WpsConfigMethods.EXT_NFC_TOKEN; - case "nfc_interface": - return WpsConfigMethods.NFC_INTERFACE; - case "push_button": - return WpsConfigMethods.PUSHBUTTON; - case "keypad": - return WpsConfigMethods.KEYPAD; - case "virtual_push_button": - return WpsConfigMethods.VIRT_PUSHBUTTON; - case "physical_push_button": - return WpsConfigMethods.PHY_PUSHBUTTON; - case "p2ps": - return WpsConfigMethods.P2PS; - case "virtual_display": - return WpsConfigMethods.VIRT_DISPLAY; - case "physical_display": - return WpsConfigMethods.PHY_DISPLAY; - default: - throw new IllegalArgumentException( - "Invalid WPS config method: " + configMethod); - } - } - - /** Container class allowing propagation of status and/or value - * from callbacks. - * - * Primary purpose is to allow callback lambdas to provide results - * to parent methods. - */ - private static class SupplicantResult<E> { - private String mMethodName; - private SupplicantStatus mStatus; - private E mValue; - - SupplicantResult(String methodName) { - mMethodName = methodName; - mStatus = null; - mValue = null; - logd("entering " + mMethodName); - } - - public void setResult(SupplicantStatus status, E value) { - logCompletion(mMethodName, status); - logd("leaving " + mMethodName + " with result = " + value); - mStatus = status; - mValue = value; - } - - public void setResult(SupplicantStatus status) { - logCompletion(mMethodName, status); - logd("leaving " + mMethodName); - mStatus = status; - } - - public boolean isSuccess() { - return (mStatus != null - && (mStatus.code == SupplicantStatusCode.SUCCESS - || mStatus.code == SupplicantStatusCode.FAILURE_IFACE_EXISTS)); - } - - public E getResult() { - return (isSuccess() ? mValue : null); - } - } -} diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pMetrics.java b/service/java/com/android/server/wifi/p2p/WifiP2pMetrics.java deleted file mode 100644 index 085a837fa..000000000 --- a/service/java/com/android/server/wifi/p2p/WifiP2pMetrics.java +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.p2p; - -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pGroupList; -import android.util.Log; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.proto.nano.WifiMetricsProto.GroupEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiP2pStats; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.List; - -/** - * Provides storage for wireless connectivity P2p metrics, as they are generated. - * Metrics logged by this class include: - * Aggregated connection stats (num of connections, num of failures, ...) - * Discrete connection event stats (time, duration, failure codes, ...) - */ -public class WifiP2pMetrics { - private static final String TAG = "WifiP2pMetrics"; - private static final boolean DBG = false; - - private static final int MAX_CONNECTION_EVENTS = 256; - private static final int MAX_GROUP_EVENTS = 256; - - private Clock mClock; - private final Object mLock = new Object(); - - /** - * Metrics are stored within an instance of the WifiP2pStats proto during runtime, - * The P2pConnectionEvent and GroupEvent metrics are stored during runtime in member - * lists of this WifiP2pMetrics class, with the final WifiLog proto being pieced - * together at dump-time - */ - private final WifiP2pStats mWifiP2pStatsProto = - new WifiP2pStats(); - - /** - * Connection information that gets logged for every P2P connection attempt. - */ - private final List<P2pConnectionEvent> mConnectionEventList = - new ArrayList<>(); - - /** - * The latest started (but un-ended) connection attempt - */ - private P2pConnectionEvent mCurrentConnectionEvent; - - /** - * The latest started (but un-ended) connection attempt start time - */ - private long mCurrentConnectionEventStartTime; - - /** - * Group Session information that gets logged for every formed group. - */ - private final List<GroupEvent> mGroupEventList = - new ArrayList<>(); - - /** - * The latest started (but un-ended) group - */ - private GroupEvent mCurrentGroupEvent; - - /** - * The latest started (but un-ended) group start time - */ - private long mCurrentGroupEventStartTime; - - /** - * The latest started (but un-ended) group idle start time. - * The group is idle if there is no connected client. - */ - private long mCurrentGroupEventIdleStartTime; - - /** - * The current number of persistent groups. - * This should be persisted after a dump. - */ - private int mNumPersistentGroup; - - public WifiP2pMetrics(Clock clock) { - mClock = clock; - - mNumPersistentGroup = 0; - } - - /** - * Clear all WifiP2pMetrics, except for currentConnectionEvent. - */ - public void clear() { - synchronized (mLock) { - mConnectionEventList.clear(); - if (mCurrentConnectionEvent != null) { - mConnectionEventList.add(mCurrentConnectionEvent); - } - mGroupEventList.clear(); - if (mCurrentGroupEvent != null) { - mGroupEventList.add(mCurrentGroupEvent); - } - mWifiP2pStatsProto.clear(); - } - } - - /** - * Put all metrics that were being tracked separately into mWifiP2pStatsProto - */ - public WifiP2pStats consolidateProto() { - synchronized (mLock) { - mWifiP2pStatsProto.numPersistentGroup = mNumPersistentGroup; - int connectionEventCount = mConnectionEventList.size(); - if (mCurrentConnectionEvent != null) { - connectionEventCount--; - } - mWifiP2pStatsProto.connectionEvent = - new P2pConnectionEvent[connectionEventCount]; - for (int i = 0; i < connectionEventCount; i++) { - mWifiP2pStatsProto.connectionEvent[i] = mConnectionEventList.get(i); - } - - int groupEventCount = mGroupEventList.size(); - if (mCurrentGroupEvent != null) { - groupEventCount--; - } - mWifiP2pStatsProto.groupEvent = - new GroupEvent[groupEventCount]; - for (int i = 0; i < groupEventCount; i++) { - mWifiP2pStatsProto.groupEvent[i] = mGroupEventList.get(i); - } - return mWifiP2pStatsProto; - } - } - - /** - * Dump all WifiP2pMetrics. Collects some metrics at this time. - * - * @param pw PrintWriter for writing dump to - */ - public void dump(PrintWriter pw) { - synchronized (mLock) { - pw.println("WifiP2pMetrics:"); - pw.println("mConnectionEvents:"); - for (P2pConnectionEvent event : mConnectionEventList) { - StringBuilder sb = new StringBuilder(); - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(event.startTimeMillis); - sb.append("startTime="); - sb.append(event.startTimeMillis == 0 ? " <null>" : - String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); - sb.append(", connectionType="); - switch (event.connectionType) { - case P2pConnectionEvent.CONNECTION_FRESH: - sb.append("FRESH"); - break; - case P2pConnectionEvent.CONNECTION_REINVOKE: - sb.append("REINVOKE"); - break; - case P2pConnectionEvent.CONNECTION_LOCAL: - sb.append("LOCAL"); - break; - case P2pConnectionEvent.CONNECTION_FAST: - sb.append("FAST"); - break; - default: - sb.append("UNKNOWN"); - break; - } - sb.append(", wpsMethod="); - switch (event.wpsMethod) { - case P2pConnectionEvent.WPS_NA: - sb.append("NA"); - break; - case P2pConnectionEvent.WPS_PBC: - sb.append("PBC"); - break; - case P2pConnectionEvent.WPS_DISPLAY: - sb.append("DISPLAY"); - break; - case P2pConnectionEvent.WPS_KEYPAD: - sb.append("KEYPAD"); - break; - case P2pConnectionEvent.WPS_LABEL: - sb.append("LABLE"); - break; - default: - sb.append("UNKNOWN"); - break; - } - sb.append(", durationTakenToConnectMillis="); - sb.append(event.durationTakenToConnectMillis); - sb.append(", connectivityLevelFailureCode="); - switch (event.connectivityLevelFailureCode) { - case P2pConnectionEvent.CLF_NONE: - sb.append("NONE"); - break; - case P2pConnectionEvent.CLF_TIMEOUT: - sb.append("TIMEOUT"); - break; - case P2pConnectionEvent.CLF_CANCEL: - sb.append("CANCEL"); - break; - case P2pConnectionEvent.CLF_PROV_DISC_FAIL: - sb.append("PROV_DISC_FAIL"); - break; - case P2pConnectionEvent.CLF_INVITATION_FAIL: - sb.append("INVITATION_FAIL"); - break; - case P2pConnectionEvent.CLF_USER_REJECT: - sb.append("USER_REJECT"); - break; - case P2pConnectionEvent.CLF_NEW_CONNECTION_ATTEMPT: - sb.append("NEW_CONNECTION_ATTEMPT"); - break; - case P2pConnectionEvent.CLF_UNKNOWN: - default: - sb.append("UNKNOWN"); - break; - } - - if (event == mCurrentConnectionEvent) { - sb.append(" CURRENTLY OPEN EVENT"); - } - pw.println(sb.toString()); - } - pw.println("mGroupEvents:"); - for (GroupEvent event : mGroupEventList) { - StringBuilder sb = new StringBuilder(); - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(event.startTimeMillis); - sb.append("netId="); - sb.append(event.netId); - sb.append(", startTime="); - sb.append(event.startTimeMillis == 0 ? " <null>" : - String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); - sb.append(", channelFrequency="); - sb.append(event.channelFrequency); - sb.append(", groupRole="); - switch (event.groupRole) { - case GroupEvent.GROUP_CLIENT: - sb.append("GroupClient"); - break; - case GroupEvent.GROUP_OWNER: - default: - sb.append("GroupOwner"); - break; - } - sb.append(", numConnectedClients="); - sb.append(event.numConnectedClients); - sb.append(", numCumulativeClients="); - sb.append(event.numCumulativeClients); - sb.append(", sessionDurationMillis="); - sb.append(event.sessionDurationMillis); - sb.append(", idleDurationMillis="); - sb.append(event.idleDurationMillis); - - if (event == mCurrentGroupEvent) { - sb.append(" CURRENTLY OPEN EVENT"); - } - pw.println(sb.toString()); - } - pw.println("mWifiP2pStatsProto.numPersistentGroup=" - + mNumPersistentGroup); - pw.println("mWifiP2pStatsProto.numTotalPeerScans=" - + mWifiP2pStatsProto.numTotalPeerScans); - pw.println("mWifiP2pStatsProto.numTotalServiceScans=" - + mWifiP2pStatsProto.numTotalServiceScans); - } - } - - /** Increment total number of peer scans */ - public void incrementPeerScans() { - synchronized (mLock) { - mWifiP2pStatsProto.numTotalPeerScans++; - } - } - - /** Increment total number of service scans */ - public void incrementServiceScans() { - synchronized (mLock) { - mWifiP2pStatsProto.numTotalServiceScans++; - } - } - - /** Set the number of saved persistent group */ - public void updatePersistentGroup(WifiP2pGroupList groups) { - synchronized (mLock) { - final Collection<WifiP2pGroup> list = groups.getGroupList(); - mNumPersistentGroup = list.size(); - } - } - - /** - * Create a new connection event. Call when p2p attmpts to make a new connection to - * another peer. If there is a current 'un-ended' connection event, it will be ended with - * P2pConnectionEvent.CLF_NEW_CONNNECTION_ATTEMPT. - * - * @param connectionType indicate this connection is fresh or reinvoke. - * @param config configuration used for this connection. - */ - public void startConnectionEvent(int connectionType, WifiP2pConfig config) { - synchronized (mLock) { - // handle overlapping connection event first. - if (mCurrentConnectionEvent != null) { - endConnectionEvent(P2pConnectionEvent.CLF_NEW_CONNECTION_ATTEMPT); - } - - while (mConnectionEventList.size() >= MAX_CONNECTION_EVENTS) { - mConnectionEventList.remove(0); - } - mCurrentConnectionEventStartTime = mClock.getElapsedSinceBootMillis(); - - mCurrentConnectionEvent = new P2pConnectionEvent(); - mCurrentConnectionEvent.startTimeMillis = mClock.getWallClockMillis(); - mCurrentConnectionEvent.connectionType = connectionType; - if (config != null) { - mCurrentConnectionEvent.wpsMethod = config.wps.setup; - } - - mConnectionEventList.add(mCurrentConnectionEvent); - } - } - - /** - * End a Connection event record. Call when p2p connection attempt succeeds or fails. - * If a Connection event has not been started when .end is called, - * a new one is created with zero duration. - * - * @param failure indicate the failure with WifiMetricsProto.P2pConnectionEvent.CLF_X. - */ - public void endConnectionEvent(int failure) { - synchronized (mLock) { - if (mCurrentConnectionEvent == null) { - // Reinvoking a group with invitation will be handled in supplicant. - // There won't be a connection starting event in framework. - // THe framework only get the connection ending event in GroupStarted state. - startConnectionEvent(P2pConnectionEvent.CONNECTION_REINVOKE, null); - } - - mCurrentConnectionEvent.durationTakenToConnectMillis = (int) - (mClock.getElapsedSinceBootMillis() - - mCurrentConnectionEventStartTime); - mCurrentConnectionEvent.connectivityLevelFailureCode = failure; - - mCurrentConnectionEvent = null; - } - } - - /** - * Create a new group event. - * - * @param group the information of started group. - */ - public void startGroupEvent(WifiP2pGroup group) { - if (group == null) { - if (DBG) Log.d(TAG, "Cannot start group event due to null group"); - return; - } - synchronized (mLock) { - // handle overlapping group event first. - if (mCurrentGroupEvent != null) { - if (DBG) Log.d(TAG, "Overlapping group event!"); - endGroupEvent(); - } - - while (mGroupEventList.size() >= MAX_GROUP_EVENTS) { - mGroupEventList.remove(0); - } - mCurrentGroupEventStartTime = mClock.getElapsedSinceBootMillis(); - if (group.getClientList().size() == 0) { - mCurrentGroupEventIdleStartTime = mClock.getElapsedSinceBootMillis(); - } else { - mCurrentGroupEventIdleStartTime = 0; - } - - mCurrentGroupEvent = new GroupEvent(); - mCurrentGroupEvent.netId = group.getNetworkId(); - mCurrentGroupEvent.startTimeMillis = mClock.getWallClockMillis(); - mCurrentGroupEvent.numConnectedClients = group.getClientList().size(); - mCurrentGroupEvent.channelFrequency = group.getFrequency(); - mCurrentGroupEvent.groupRole = group.isGroupOwner() - ? GroupEvent.GROUP_OWNER - : GroupEvent.GROUP_CLIENT; - mGroupEventList.add(mCurrentGroupEvent); - } - } - - /** - * Update the information of started group. - */ - public void updateGroupEvent(WifiP2pGroup group) { - if (group == null) { - if (DBG) Log.d(TAG, "Cannot update group event due to null group."); - return; - } - synchronized (mLock) { - if (mCurrentGroupEvent == null) { - Log.w(TAG, "Cannot update group event due to no current group."); - return; - } - - if (mCurrentGroupEvent.netId != group.getNetworkId()) { - Log.w(TAG, "Updating group id " + group.getNetworkId() - + " is different from current group id " + mCurrentGroupEvent.netId - + "."); - return; - } - - int delta = group.getClientList().size() - mCurrentGroupEvent.numConnectedClients; - mCurrentGroupEvent.numConnectedClients = group.getClientList().size(); - if (delta > 0) { - mCurrentGroupEvent.numCumulativeClients += delta; - } - - // if new client comes during idle period, cumulate idle duration and reset idle timer. - // if the last client disconnected during non-idle period, start idle timer. - if (mCurrentGroupEventIdleStartTime > 0) { - if (group.getClientList().size() > 0) { - mCurrentGroupEvent.idleDurationMillis += - (mClock.getElapsedSinceBootMillis() - - mCurrentGroupEventIdleStartTime); - mCurrentGroupEventIdleStartTime = 0; - } - } else { - if (group.getClientList().size() == 0) { - mCurrentGroupEventIdleStartTime = mClock.getElapsedSinceBootMillis(); - } - } - } - } - - /** - * End a group event. - */ - public void endGroupEvent() { - synchronized (mLock) { - if (mCurrentGroupEvent != null) { - mCurrentGroupEvent.sessionDurationMillis = (int) - (mClock.getElapsedSinceBootMillis() - - mCurrentGroupEventStartTime); - if (mCurrentGroupEventIdleStartTime > 0) { - mCurrentGroupEvent.idleDurationMillis += - (mClock.getElapsedSinceBootMillis() - - mCurrentGroupEventIdleStartTime); - mCurrentGroupEventIdleStartTime = 0; - } - } else { - Log.e(TAG, "No current group!"); - } - mCurrentGroupEvent = null; - } - } - - /* Log Metrics */ -} diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java b/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java deleted file mode 100644 index cbf33b487..000000000 --- a/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (C) 2008 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.server.wifi.p2p; - -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pProvDiscEvent; -import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; -import android.os.Handler; -import android.os.Message; -import android.util.ArraySet; -import android.util.Log; -import android.util.SparseArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Protocol; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Listens for events from the wpa_supplicant, and passes them on - * to the {@link WifiP2pServiceImpl} for handling. - * - * @hide - */ -public class WifiP2pMonitor { - private static final String TAG = "WifiP2pMonitor"; - - /* Supplicant events reported to a state machine */ - private static final int BASE = Protocol.BASE_WIFI_MONITOR; - - /* Connection to supplicant established */ - public static final int SUP_CONNECTION_EVENT = BASE + 1; - /* Connection to supplicant lost */ - public static final int SUP_DISCONNECTION_EVENT = BASE + 2; - - /* P2P events */ - public static final int P2P_DEVICE_FOUND_EVENT = BASE + 21; - public static final int P2P_DEVICE_LOST_EVENT = BASE + 22; - public static final int P2P_GO_NEGOTIATION_REQUEST_EVENT = BASE + 23; - public static final int P2P_GO_NEGOTIATION_SUCCESS_EVENT = BASE + 25; - public static final int P2P_GO_NEGOTIATION_FAILURE_EVENT = BASE + 26; - public static final int P2P_GROUP_FORMATION_SUCCESS_EVENT = BASE + 27; - public static final int P2P_GROUP_FORMATION_FAILURE_EVENT = BASE + 28; - public static final int P2P_GROUP_STARTED_EVENT = BASE + 29; - public static final int P2P_GROUP_REMOVED_EVENT = BASE + 30; - public static final int P2P_INVITATION_RECEIVED_EVENT = BASE + 31; - public static final int P2P_INVITATION_RESULT_EVENT = BASE + 32; - public static final int P2P_PROV_DISC_PBC_REQ_EVENT = BASE + 33; - public static final int P2P_PROV_DISC_PBC_RSP_EVENT = BASE + 34; - public static final int P2P_PROV_DISC_ENTER_PIN_EVENT = BASE + 35; - public static final int P2P_PROV_DISC_SHOW_PIN_EVENT = BASE + 36; - public static final int P2P_FIND_STOPPED_EVENT = BASE + 37; - public static final int P2P_SERV_DISC_RESP_EVENT = BASE + 38; - public static final int P2P_PROV_DISC_FAILURE_EVENT = BASE + 39; - - /* hostap events */ - public static final int AP_STA_DISCONNECTED_EVENT = BASE + 41; - public static final int AP_STA_CONNECTED_EVENT = BASE + 42; - - - private final WifiInjector mWifiInjector; - private boolean mVerboseLoggingEnabled = false; - private boolean mConnected = false; - - public WifiP2pMonitor(WifiInjector wifiInjector) { - mWifiInjector = wifiInjector; - } - - /** - * Enable verbose logging for all sub modules. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = verbose > 0; - } - - private final Map<String, SparseArray<Set<Handler>>> mHandlerMap = new HashMap<>(); - - /** - * Registers a callback handler for the provided event. - */ - public synchronized void registerHandler(String iface, int what, Handler handler) { - SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); - if (ifaceHandlers == null) { - ifaceHandlers = new SparseArray<>(); - mHandlerMap.put(iface, ifaceHandlers); - } - Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what); - if (ifaceWhatHandlers == null) { - ifaceWhatHandlers = new ArraySet<>(); - ifaceHandlers.put(what, ifaceWhatHandlers); - } - ifaceWhatHandlers.add(handler); - } - - private final Map<String, Boolean> mMonitoringMap = new HashMap<>(); - private boolean isMonitoring(String iface) { - Boolean val = mMonitoringMap.get(iface); - if (val == null) { - return false; - } else { - return val.booleanValue(); - } - } - - /** - * Enable/Disable monitoring for the provided iface. - * - * @param iface Name of the iface. - * @param enabled true to enable, false to disable. - */ - @VisibleForTesting - public void setMonitoring(String iface, boolean enabled) { - mMonitoringMap.put(iface, enabled); - } - - private void setMonitoringNone() { - for (String iface : mMonitoringMap.keySet()) { - setMonitoring(iface, false); - } - } - - /** - * Start Monitoring for wpa_supplicant events. - * - * @param iface Name of iface. - * TODO: Add unit tests for these once we remove the legacy code. - */ - public synchronized void startMonitoring(String iface) { - setMonitoring(iface, true); - broadcastSupplicantConnectionEvent(iface); - } - - /** - * Stop Monitoring for wpa_supplicant events. - * - * @param iface Name of iface. - * TODO: Add unit tests for these once we remove the legacy code. - */ - public synchronized void stopMonitoring(String iface) { - if (mVerboseLoggingEnabled) Log.d(TAG, "stopMonitoring(" + iface + ")"); - setMonitoring(iface, true); - broadcastSupplicantDisconnectionEvent(iface); - setMonitoring(iface, false); - } - - /** - * Stop Monitoring for wpa_supplicant events. - * - * TODO: Add unit tests for these once we remove the legacy code. - */ - public synchronized void stopAllMonitoring() { - mConnected = false; - setMonitoringNone(); - } - - /** - * Similar functions to Handler#sendMessage that send the message to the registered handler - * for the given interface and message what. - * All of these should be called with the WifiMonitor class lock - */ - private void sendMessage(String iface, int what) { - sendMessage(iface, Message.obtain(null, what)); - } - - private void sendMessage(String iface, int what, Object obj) { - sendMessage(iface, Message.obtain(null, what, obj)); - } - - private void sendMessage(String iface, int what, int arg1) { - sendMessage(iface, Message.obtain(null, what, arg1, 0)); - } - - private void sendMessage(String iface, int what, int arg1, int arg2) { - sendMessage(iface, Message.obtain(null, what, arg1, arg2)); - } - - private void sendMessage(String iface, int what, int arg1, int arg2, Object obj) { - sendMessage(iface, Message.obtain(null, what, arg1, arg2, obj)); - } - - private void sendMessage(String iface, Message message) { - SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); - if (iface != null && ifaceHandlers != null) { - if (isMonitoring(iface)) { - Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(message.what); - if (ifaceWhatHandlers != null) { - for (Handler handler : ifaceWhatHandlers) { - if (handler != null) { - sendMessage(handler, Message.obtain(message)); - } - } - } - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Dropping event because (" + iface + ") is stopped"); - } - } - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Sending to all monitors because there's no matching iface"); - } - for (Map.Entry<String, SparseArray<Set<Handler>>> entry : mHandlerMap.entrySet()) { - if (isMonitoring(entry.getKey())) { - Set<Handler> ifaceWhatHandlers = entry.getValue().get(message.what); - for (Handler handler : ifaceWhatHandlers) { - if (handler != null) { - sendMessage(handler, Message.obtain(message)); - } - } - } - } - } - - message.recycle(); - } - - private void sendMessage(Handler handler, Message message) { - message.setTarget(handler); - message.sendToTarget(); - } - - /** - * Broadcast the connection to wpa_supplicant event to all the handlers registered for - * this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastSupplicantConnectionEvent(String iface) { - sendMessage(iface, SUP_CONNECTION_EVENT); - } - - /** - * Broadcast the loss of connection to wpa_supplicant event to all the handlers registered for - * this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastSupplicantDisconnectionEvent(String iface) { - sendMessage(iface, SUP_DISCONNECTION_EVENT); - } - - /** - * Broadcast new p2p device discovered event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param device Device that has been discovered during recent scan. - */ - public void broadcastP2pDeviceFound(String iface, WifiP2pDevice device) { - if (device != null) { - sendMessage(iface, P2P_DEVICE_FOUND_EVENT, device); - } - } - - /** - * Broadcast p2p device lost event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param device Device that has been lost in recent scan. - */ - public void broadcastP2pDeviceLost(String iface, WifiP2pDevice device) { - if (device != null) { - sendMessage(iface, P2P_DEVICE_LOST_EVENT, device); - } - } - - /** - * Broadcast scan termination event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastP2pFindStopped(String iface) { - sendMessage(iface, P2P_FIND_STOPPED_EVENT); - } - - /** - * Broadcast group owner negotiation request event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param config P2p configuration. - */ - public void broadcastP2pGoNegotiationRequest(String iface, WifiP2pConfig config) { - if (config != null) { - sendMessage(iface, P2P_GO_NEGOTIATION_REQUEST_EVENT, config); - } - } - - /** - * Broadcast group owner negotiation success event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastP2pGoNegotiationSuccess(String iface) { - sendMessage(iface, P2P_GO_NEGOTIATION_SUCCESS_EVENT); - } - - /** - * Broadcast group owner negotiation failure event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param reason Failure reason. - */ - public void broadcastP2pGoNegotiationFailure(String iface, P2pStatus reason) { - sendMessage(iface, P2P_GO_NEGOTIATION_FAILURE_EVENT, reason); - } - - /** - * Broadcast group formation success event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastP2pGroupFormationSuccess(String iface) { - sendMessage(iface, P2P_GROUP_FORMATION_SUCCESS_EVENT); - } - - /** - * Broadcast group formation failure event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param reason Failure reason. - */ - public void broadcastP2pGroupFormationFailure(String iface, String reason) { - P2pStatus err = P2pStatus.UNKNOWN; - if (reason.equals("FREQ_CONFLICT")) { - err = P2pStatus.NO_COMMON_CHANNEL; - } - sendMessage(iface, P2P_GROUP_FORMATION_FAILURE_EVENT, err); - } - - /** - * Broadcast group started event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param group Started group. - */ - public void broadcastP2pGroupStarted(String iface, WifiP2pGroup group) { - if (group != null) { - sendMessage(iface, P2P_GROUP_STARTED_EVENT, group); - } - } - - /** - * Broadcast group removed event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param group Removed group. - */ - public void broadcastP2pGroupRemoved(String iface, WifiP2pGroup group) { - if (group != null) { - sendMessage(iface, P2P_GROUP_REMOVED_EVENT, group); - } - } - - /** - * Broadcast invitation received event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param group Group to which invitation has been received. - */ - public void broadcastP2pInvitationReceived(String iface, WifiP2pGroup group) { - if (group != null) { - sendMessage(iface, P2P_INVITATION_RECEIVED_EVENT, group); - } - } - - /** - * Broadcast invitation result event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param result Result of invitation. - */ - public void broadcastP2pInvitationResult(String iface, P2pStatus result) { - sendMessage(iface, P2P_INVITATION_RESULT_EVENT, result); - } - - /** - * Broadcast PB discovery request event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param event Provision discovery request event. - */ - public void broadcastP2pProvisionDiscoveryPbcRequest(String iface, WifiP2pProvDiscEvent event) { - if (event != null) { - sendMessage(iface, P2P_PROV_DISC_PBC_REQ_EVENT, event); - } - } - - /** - * Broadcast PB discovery response event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param event Provision discovery response event. - */ - public void broadcastP2pProvisionDiscoveryPbcResponse( - String iface, WifiP2pProvDiscEvent event) { - if (event != null) { - sendMessage(iface, P2P_PROV_DISC_PBC_RSP_EVENT, event); - } - } - - /** - * Broadcast PIN discovery request event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param event Provision discovery request event. - */ - public void broadcastP2pProvisionDiscoveryEnterPin(String iface, WifiP2pProvDiscEvent event) { - if (event != null) { - sendMessage(iface, P2P_PROV_DISC_ENTER_PIN_EVENT, event); - } - } - - /** - * Broadcast PIN discovery response event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param event Provision discovery response event. - */ - public void broadcastP2pProvisionDiscoveryShowPin(String iface, WifiP2pProvDiscEvent event) { - if (event != null) { - sendMessage(iface, P2P_PROV_DISC_SHOW_PIN_EVENT, event); - } - } - - /** - * Broadcast P2P discovery failure event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastP2pProvisionDiscoveryFailure(String iface) { - sendMessage(iface, P2P_PROV_DISC_FAILURE_EVENT); - } - - /** - * Broadcast service discovery response event to all handlers registered for this event. - * - * @param iface Name of iface on which this occurred. - * @param services List of discovered services. - */ - public void broadcastP2pServiceDiscoveryResponse( - String iface, List<WifiP2pServiceResponse> services) { - sendMessage(iface, P2P_SERV_DISC_RESP_EVENT, services); - } - - /** - * Broadcast AP STA connection event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastP2pApStaConnected(String iface, WifiP2pDevice device) { - sendMessage(iface, AP_STA_CONNECTED_EVENT, device); - } - - /** - * Broadcast AP STA disconnection event. - * - * @param iface Name of iface on which this occurred. - */ - public void broadcastP2pApStaDisconnected(String iface, WifiP2pDevice device) { - sendMessage(iface, AP_STA_DISCONNECTED_EVENT, device); - } -} diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java deleted file mode 100644 index 300b7a122..000000000 --- a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java +++ /dev/null @@ -1,868 +0,0 @@ -/* - * Copyright (C) 2008 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.server.wifi.p2p; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.hardware.wifi.V1_0.IWifiP2pIface; -import android.hardware.wifi.V1_0.IfaceType; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pGroupList; -import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; -import android.os.Handler; -import android.text.TextUtils; -import android.util.Log; - -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.PropertyService; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.WifiVendorHal; - -import java.util.Set; - -/** - * Native calls for bring up/shut down of the supplicant daemon and for - * sending requests to the supplicant daemon - * - * {@hide} - */ -public class WifiP2pNative { - private static final String TAG = "WifiP2pNative"; - private boolean mVerboseLoggingEnabled = false; - private final SupplicantP2pIfaceHal mSupplicantP2pIfaceHal; - private final WifiInjector mWifiInjector; - private final HalDeviceManager mHalDeviceManager; - private final PropertyService mPropertyService; - private final WifiVendorHal mWifiVendorHal; - private IWifiP2pIface mIWifiP2pIface; - private InterfaceAvailableListenerInternal mInterfaceAvailableListener; - private InterfaceDestroyedListenerInternal mInterfaceDestroyedListener; - - // Internal callback registered to HalDeviceManager. - private class InterfaceAvailableListenerInternal implements - HalDeviceManager.InterfaceAvailableForRequestListener { - private final HalDeviceManager.InterfaceAvailableForRequestListener mExternalListener; - - InterfaceAvailableListenerInternal( - HalDeviceManager.InterfaceAvailableForRequestListener externalListener) { - mExternalListener = externalListener; - } - - @Override - public void onAvailabilityChanged(boolean isAvailable) { - Log.d(TAG, "P2P InterfaceAvailableListener " + isAvailable); - // We need another level of abstraction here. When a P2P interface is created, - // we should mask the availability change callback from WifiP2pService. - // This is because when the P2P interface is created, we'll get a callback - // indicating that we can no longer create a new P2P interface. We don't need to - // propagate this internal state to WifiP2pServiceImpl. - if (mIWifiP2pIface != null && !isAvailable) { - Log.i(TAG, "Masking interface non-availability callback because " - + "we created a P2P iface"); - return; - } - mExternalListener.onAvailabilityChanged(isAvailable); - } - } - - // Internal callback registered to HalDeviceManager. - private class InterfaceDestroyedListenerInternal implements - HalDeviceManager.InterfaceDestroyedListener { - private final HalDeviceManager.InterfaceDestroyedListener mExternalListener; - private boolean mValid; - - InterfaceDestroyedListenerInternal( - HalDeviceManager.InterfaceDestroyedListener externalListener) { - mExternalListener = externalListener; - mValid = true; - } - - public void teardownAndInvalidate(@Nullable String ifaceName) { - if (!TextUtils.isEmpty(ifaceName)) { - mSupplicantP2pIfaceHal.teardownIface(ifaceName); - } - mIWifiP2pIface = null; - mValid = false; - } - - @Override - public void onDestroyed(String ifaceName) { - Log.d(TAG, "P2P InterfaceDestroyedListener " + ifaceName); - if (!mValid) { - Log.d(TAG, "Ignoring stale interface destroyed listener"); - return; - } - teardownAndInvalidate(ifaceName); - mExternalListener.onDestroyed(ifaceName); - } - } - - public WifiP2pNative(WifiInjector wifiInjector, WifiVendorHal wifiVendorHal, - SupplicantP2pIfaceHal p2pIfaceHal, HalDeviceManager halDeviceManager, - PropertyService propertyService) { - mWifiInjector = wifiInjector; - mWifiVendorHal = wifiVendorHal; - mSupplicantP2pIfaceHal = p2pIfaceHal; - mHalDeviceManager = halDeviceManager; - mPropertyService = propertyService; - } - - /** - * Enable verbose logging for all sub modules. - */ - public void enableVerboseLogging(int verbose) { - mVerboseLoggingEnabled = verbose > 0; - SupplicantP2pIfaceHal.enableVerboseLogging(verbose); - } - - private static final int CONNECT_TO_SUPPLICANT_SAMPLING_INTERVAL_MS = 100; - private static final int CONNECT_TO_SUPPLICANT_MAX_SAMPLES = 50; - /** - * This method is called to wait for establishing connection to wpa_supplicant. - * - * @return true if connection is established, false otherwise. - */ - private boolean waitForSupplicantConnection() { - // Start initialization if not already started. - if (!mSupplicantP2pIfaceHal.isInitializationStarted() - && !mSupplicantP2pIfaceHal.initialize()) { - return false; - } - int connectTries = 0; - while (connectTries++ < CONNECT_TO_SUPPLICANT_MAX_SAMPLES) { - // Check if the initialization is complete. - if (mSupplicantP2pIfaceHal.isInitializationComplete()) { - return true; - } - try { - Thread.sleep(CONNECT_TO_SUPPLICANT_SAMPLING_INTERVAL_MS); - } catch (InterruptedException ignore) { - } - } - return false; - } - - /** - * Close supplicant connection. - */ - public void closeSupplicantConnection() { - // Nothing to do for HIDL. - } - - /** - * Returns whether HAL (HIDL) is supported on this device or not. - */ - public boolean isHalInterfaceSupported() { - return mHalDeviceManager.isSupported(); - } - - private static final String P2P_IFACE_NAME = "p2p0"; - private static final String P2P_INTERFACE_PROPERTY = "wifi.direct.interface"; - /** - * Helper function to handle creation of P2P iface. - * For devices which do not the support the HAL, this will bypass HalDeviceManager & - * teardown any existing iface. - */ - private String createP2pIface(Handler handler) { - if (mHalDeviceManager.isSupported()) { - mIWifiP2pIface = mHalDeviceManager - .createP2pIface(mInterfaceDestroyedListener, handler); - if (mIWifiP2pIface == null) { - Log.e(TAG, "Failed to create P2p iface in HalDeviceManager"); - return null; - } - String ifaceName = HalDeviceManager.getName(mIWifiP2pIface); - if (TextUtils.isEmpty(ifaceName)) { - Log.e(TAG, "Failed to get p2p iface name"); - teardownInterface(); - return null; - } - return ifaceName; - } else { - Log.i(TAG, "Vendor Hal is not supported, ignoring createP2pIface."); - return mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); - } - } - - /** - * Register for an interface available callbacks from HalDeviceManager. - * - * @param listener callback to be invoked when the interface is available/not available. - */ - public void registerInterfaceAvailableListener( - @NonNull HalDeviceManager.InterfaceAvailableForRequestListener listener, - Handler handler) { - mInterfaceAvailableListener = new InterfaceAvailableListenerInternal(listener); - // The interface available callbacks are cleared on every HAL stop, so need to - // re-register these callbacks on every start. - mHalDeviceManager.registerStatusListener(() -> { - if (mHalDeviceManager.isStarted()) { - Log.i(TAG, "Registering for interface available listener"); - mHalDeviceManager.registerInterfaceAvailableForRequestListener( - IfaceType.P2P, mInterfaceAvailableListener, handler); - } - }, handler); - if (mHalDeviceManager.isStarted()) { - mHalDeviceManager.registerInterfaceAvailableForRequestListener( - IfaceType.P2P, mInterfaceAvailableListener, handler); - } - } - - /** - * Setup Interface for P2p mode. - * - * @param destroyedListener Listener to be invoked when the interface is destroyed. - * @param handler Handler to be used for invoking the destroyedListener. - */ - public String setupInterface( - @NonNull HalDeviceManager.InterfaceDestroyedListener destroyedListener, - Handler handler) { - Log.d(TAG, "Setup P2P interface"); - if (mIWifiP2pIface == null) { - mInterfaceDestroyedListener = - new InterfaceDestroyedListenerInternal(destroyedListener); - String ifaceName = createP2pIface(handler); - if (ifaceName == null) { - Log.e(TAG, "Failed to create P2p iface"); - return null; - } - if (!waitForSupplicantConnection()) { - Log.e(TAG, "Failed to connect to supplicant"); - teardownInterface(); - return null; - } - if (!mSupplicantP2pIfaceHal.setupIface(ifaceName)) { - Log.e(TAG, "Failed to setup P2p iface in supplicant"); - teardownInterface(); - return null; - } - Log.i(TAG, "P2P interface setup completed"); - return ifaceName; - } else { - Log.i(TAG, "P2P interface is already existed"); - return mHalDeviceManager.isSupported() - ? HalDeviceManager.getName(mIWifiP2pIface) - : mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); - } - } - - /** - * Teardown P2p interface. - */ - public void teardownInterface() { - Log.d(TAG, "Teardown P2P interface"); - if (mHalDeviceManager.isSupported()) { - if (mIWifiP2pIface != null) { - String ifaceName = HalDeviceManager.getName(mIWifiP2pIface); - mHalDeviceManager.removeIface(mIWifiP2pIface); - mInterfaceDestroyedListener.teardownAndInvalidate(ifaceName); - Log.i(TAG, "P2P interface teardown completed"); - } - } else { - Log.i(TAG, "HAL (HIDL) is not supported. Destroy listener for the interface."); - String ifaceName = mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); - mInterfaceDestroyedListener.teardownAndInvalidate(ifaceName); - } - } - - /** - * Set WPS device name. - * - * @param name String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setDeviceName(String name) { - return mSupplicantP2pIfaceHal.setWpsDeviceName(name); - } - - /** - * Populate list of available networks or update existing list. - * - * @return true, if list has been modified. - */ - public boolean p2pListNetworks(WifiP2pGroupList groups) { - return mSupplicantP2pIfaceHal.loadGroups(groups); - } - - /** - * Initiate WPS Push Button setup. - * The PBC operation requires that a button is also pressed at the - * AP/Registrar at about the same time (2 minute window). - * - * @param iface Group interface name to use. - * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard. - * @return true, if operation was successful. - */ - public boolean startWpsPbc(String iface, String bssid) { - return mSupplicantP2pIfaceHal.startWpsPbc(iface, bssid); - } - - /** - * Initiate WPS Pin Keypad setup. - * - * @param iface Group interface name to use. - * @param pin 8 digit pin to be used. - * @return true, if operation was successful. - */ - public boolean startWpsPinKeypad(String iface, String pin) { - return mSupplicantP2pIfaceHal.startWpsPinKeypad(iface, pin); - } - - /** - * Initiate WPS Pin Display setup. - * - * @param iface Group interface name to use. - * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard. - * @return generated pin if operation was successful, null otherwise. - */ - public String startWpsPinDisplay(String iface, String bssid) { - return mSupplicantP2pIfaceHal.startWpsPinDisplay(iface, bssid); - } - - /** - * Remove network with provided id. - * - * @param netId Id of the network to lookup. - * @return true, if operation was successful. - */ - public boolean removeP2pNetwork(int netId) { - return mSupplicantP2pIfaceHal.removeNetwork(netId); - } - - /** - * Set WPS device name. - * - * @param name String to be set. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setP2pDeviceName(String name) { - return mSupplicantP2pIfaceHal.setWpsDeviceName(name); - } - - /** - * Set WPS device type. - * - * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg> - * @return true if request is sent successfully, false otherwise. - */ - public boolean setP2pDeviceType(String type) { - return mSupplicantP2pIfaceHal.setWpsDeviceType(type); - } - - /** - * Set WPS config methods - * - * @param cfg List of config methods. - * @return true if request is sent successfully, false otherwise. - */ - public boolean setConfigMethods(String cfg) { - return mSupplicantP2pIfaceHal.setWpsConfigMethods(cfg); - } - - /** - * Set the postfix to be used for P2P SSID's. - * - * @param postfix String to be appended to SSID. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean setP2pSsidPostfix(String postfix) { - return mSupplicantP2pIfaceHal.setSsidPostfix(postfix); - } - - /** - * Set the Maximum idle time in seconds for P2P groups. - * This value controls how long a P2P group is maintained after there - * is no other members in the group. As a group owner, this means no - * associated stations in the group. As a P2P client, this means no - * group owner seen in scan results. - * - * @param iface Group interface name to use. - * @param time Timeout value in seconds. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean setP2pGroupIdle(String iface, int time) { - return mSupplicantP2pIfaceHal.setGroupIdle(iface, time); - } - - /** - * Turn on/off power save mode for the interface. - * - * @param iface Group interface name to use. - * @param enabled Indicate if power save is to be turned on/off. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean setP2pPowerSave(String iface, boolean enabled) { - return mSupplicantP2pIfaceHal.setPowerSave(iface, enabled); - } - - /** - * Enable/Disable Wifi Display. - * - * @param enable true to enable, false to disable. - * @return true, if operation was successful. - */ - public boolean setWfdEnable(boolean enable) { - return mSupplicantP2pIfaceHal.enableWfd(enable); - } - - /** - * Set Wifi Display device info. - * - * @param hex WFD device info as described in section 5.1.2 of WFD technical - * specification v1.0.0. - * @return true, if operation was successful. - */ - public boolean setWfdDeviceInfo(String hex) { - return mSupplicantP2pIfaceHal.setWfdDeviceInfo(hex); - } - - /** - * Initiate a P2P service discovery indefinitely. - * Will trigger {@link WifiP2pMonitor#P2P_DEVICE_FOUND_EVENT} on finding devices. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pFind() { - return p2pFind(0); - } - - /** - * Initiate a P2P service discovery with a (optional) timeout. - * - * @param timeout Max time to be spent is peforming discovery. - * Set to 0 to indefinely continue discovery untill and explicit - * |stopFind| is sent. - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pFind(int timeout) { - return mSupplicantP2pIfaceHal.find(timeout); - } - - /** - * Stop an ongoing P2P service discovery. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pStopFind() { - return mSupplicantP2pIfaceHal.stopFind(); - } - - /** - * Configure Extended Listen Timing. - * - * If enabled, listen state must be entered every |intervalInMillis| for at - * least |periodInMillis|. Both values have acceptable range of 1-65535 - * (with interval obviously having to be larger than or equal to duration). - * If the P2P module is not idle at the time the Extended Listen Timing - * timeout occurs, the Listen State operation must be skipped. - * - * @param enable Enables or disables listening. - * @param period Period in milliseconds. - * @param interval Interval in milliseconds. - * - * @return true, if operation was successful. - */ - public boolean p2pExtListen(boolean enable, int period, int interval) { - return mSupplicantP2pIfaceHal.configureExtListen(enable, period, interval); - } - - /** - * Set P2P Listen channel. - * - * When specifying a social channel on the 2.4 GHz band (1/6/11) there is no - * need to specify the operating class since it defaults to 81. When - * specifying a social channel on the 60 GHz band (2), specify the 60 GHz - * operating class (180). - * - * @param lc Wifi channel. eg, 1, 6, 11. - * @param oc Operating Class indicates the channel set of the AP - * indicated by this BSSID - * - * @return true, if operation was successful. - */ - public boolean p2pSetChannel(int lc, int oc) { - return mSupplicantP2pIfaceHal.setListenChannel(lc, oc); - } - - /** - * Flush P2P peer table and state. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pFlush() { - return mSupplicantP2pIfaceHal.flush(); - } - - /** - * Start P2P group formation with a discovered P2P peer. This includes - * optional group owner negotiation, group interface setup, provisioning, - * and establishing data connection. - * - * @param config Configuration to use to connect to remote device. - * @param joinExistingGroup Indicates that this is a command to join an - * existing group as a client. It skips the group owner negotiation - * part. This must send a Provision Discovery Request message to the - * target group owner before associating for WPS provisioning. - * - * @return String containing generated pin, if selected provision method - * uses PIN. - */ - public String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) { - return mSupplicantP2pIfaceHal.connect(config, joinExistingGroup); - } - - /** - * Cancel an ongoing P2P group formation and joining-a-group related - * operation. This operation unauthorizes the specific peer device (if any - * had been authorized to start group formation), stops P2P find (if in - * progress), stops pending operations for join-a-group, and removes the - * P2P group interface (if one was used) that is in the WPS provisioning - * step. If the WPS provisioning step has been completed, the group is not - * terminated. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pCancelConnect() { - return mSupplicantP2pIfaceHal.cancelConnect(); - } - - /** - * Send P2P provision discovery request to the specified peer. The - * parameters for this command are the P2P device address of the peer and the - * desired configuration method. - * - * @param config Config class describing peer setup. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pProvisionDiscovery(WifiP2pConfig config) { - return mSupplicantP2pIfaceHal.provisionDiscovery(config); - } - - /** - * Set up a P2P group owner manually. - * This is a helper method that invokes groupAdd(networkId, isPersistent) internally. - * - * @param persistent Used to request a persistent group to be formed. - * - * @return true, if operation was successful. - */ - public boolean p2pGroupAdd(boolean persistent) { - return mSupplicantP2pIfaceHal.groupAdd(persistent); - } - - /** - * Set up a P2P group owner manually (i.e., without group owner - * negotiation with a specific peer). This is also known as autonomous - * group owner. - * - * @param netId Used to specify the restart of a persistent group. - * - * @return true, if operation was successful. - */ - public boolean p2pGroupAdd(int netId) { - return mSupplicantP2pIfaceHal.groupAdd(netId, true); - } - - /** - * Set up a P2P group as Group Owner or join a group with a configuration. - * - * @param config Used to specify config for setting up a P2P group - * - * @return true, if operation was successful. - */ - public boolean p2pGroupAdd(WifiP2pConfig config, boolean join) { - int freq = 0; - switch (config.groupOwnerBand) { - case WifiP2pConfig.GROUP_OWNER_BAND_2GHZ: - freq = 2; - break; - case WifiP2pConfig.GROUP_OWNER_BAND_5GHZ: - freq = 5; - break; - // treat it as frequency. - default: - freq = config.groupOwnerBand; - } - abortWifiRunningScanIfNeeded(join); - return mSupplicantP2pIfaceHal.groupAdd( - config.networkName, - config.passphrase, - (config.netId == WifiP2pGroup.NETWORK_ID_PERSISTENT), - freq, config.deviceAddress, join); - } - - private void abortWifiRunningScanIfNeeded(boolean isJoin) { - if (!isJoin) return; - - WifiNl80211Manager wifiCondManager = mWifiInjector.getWifiCondManager(); - WifiNative wifiNative = mWifiInjector.getWifiNative(); - Set<String> wifiClientInterfaces = wifiNative.getClientInterfaceNames(); - - for (String interfaceName: wifiClientInterfaces) { - wifiCondManager.abortScan(interfaceName); - } - } - - /** - * Terminate a P2P group. If a new virtual network interface was used for - * the group, it must also be removed. The network interface name of the - * group interface is used as a parameter for this command. - * - * @param iface Group interface name to use. - * @return true, if operation was successful. - */ - public boolean p2pGroupRemove(String iface) { - return mSupplicantP2pIfaceHal.groupRemove(iface); - } - - /** - * Reject connection attempt from a peer (specified with a device - * address). This is a mechanism to reject a pending group owner negotiation - * with a peer and request to automatically block any further connection or - * discovery of the peer. - * - * @param deviceAddress MAC address of the device to reject. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pReject(String deviceAddress) { - return mSupplicantP2pIfaceHal.reject(deviceAddress); - } - - /** - * Invite a device to a persistent group. - * If the peer device is the group owner of the persistent group, the peer - * parameter is not needed. Otherwise it is used to specify which - * device to invite. |goDeviceAddress| parameter may be used to override - * the group owner device address for Invitation Request should it not be - * known for some reason (this should not be needed in most cases). - * - * @param group Group object to use. - * @param deviceAddress MAC address of the device to invite. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) { - return mSupplicantP2pIfaceHal.invite(group, deviceAddress); - } - - /** - * Reinvoke a device from a persistent group. - * - * @param netId Used to specify the persistent group. - * @param deviceAddress MAC address of the device to reinvoke. - * - * @return true, if operation was successful. - */ - public boolean p2pReinvoke(int netId, String deviceAddress) { - return mSupplicantP2pIfaceHal.reinvoke(netId, deviceAddress); - } - - /** - * Gets the operational SSID of the device. - * - * @param deviceAddress MAC address of the peer. - * - * @return SSID of the device. - */ - public String p2pGetSsid(String deviceAddress) { - return mSupplicantP2pIfaceHal.getSsid(deviceAddress); - } - - /** - * Gets the MAC address of the device. - * - * @return MAC address of the device. - */ - public String p2pGetDeviceAddress() { - return mSupplicantP2pIfaceHal.getDeviceAddress(); - } - - /** - * Gets the capability of the group which the device is a - * member of. - * - * @param deviceAddress MAC address of the peer. - * - * @return combination of |GroupCapabilityMask| values. - */ - public int getGroupCapability(String deviceAddress) { - return mSupplicantP2pIfaceHal.getGroupCapability(deviceAddress); - } - - /** - * This command can be used to add a upnp/bonjour service. - * - * @param servInfo List of service queries. - * - * @return true, if operation was successful. - */ - public boolean p2pServiceAdd(WifiP2pServiceInfo servInfo) { - return mSupplicantP2pIfaceHal.serviceAdd(servInfo); - } - - /** - * This command can be used to remove a upnp/bonjour service. - * - * @param servInfo List of service queries. - * - * @return true, if operation was successful. - */ - public boolean p2pServiceDel(WifiP2pServiceInfo servInfo) { - return mSupplicantP2pIfaceHal.serviceRemove(servInfo); - } - - /** - * This command can be used to flush all services from the - * device. - * - * @return boolean value indicating whether operation was successful. - */ - public boolean p2pServiceFlush() { - return mSupplicantP2pIfaceHal.serviceFlush(); - } - - /** - * Schedule a P2P service discovery request. The parameters for this command - * are the device address of the peer device (or 00:00:00:00:00:00 for - * wildcard query that is sent to every discovered P2P peer that supports - * service discovery) and P2P Service Query TLV(s) as hexdump. - * - * @param addr MAC address of the device to discover. - * @param query Hex dump of the query data. - * @return identifier Identifier for the request. Can be used to cancel the - * request. - */ - public String p2pServDiscReq(String addr, String query) { - return mSupplicantP2pIfaceHal.requestServiceDiscovery(addr, query); - } - - /** - * Cancel a previous service discovery request. - * - * @param id Identifier for the request to cancel. - * @return true, if operation was successful. - */ - public boolean p2pServDiscCancelReq(String id) { - return mSupplicantP2pIfaceHal.cancelServiceDiscovery(id); - } - - /** - * Send driver command to set Miracast mode. - * - * @param mode Mode of Miracast. - * 0 = disabled - * 1 = operating as source - * 2 = operating as sink - */ - public void setMiracastMode(int mode) { - mSupplicantP2pIfaceHal.setMiracastMode(mode); - } - - /** - * Get NFC handover request message. - * - * @return select message if created successfully, null otherwise. - */ - public String getNfcHandoverRequest() { - return mSupplicantP2pIfaceHal.getNfcHandoverRequest(); - } - - /** - * Get NFC handover select message. - * - * @return select message if created successfully, null otherwise. - */ - public String getNfcHandoverSelect() { - return mSupplicantP2pIfaceHal.getNfcHandoverSelect(); - } - - /** - * Report NFC handover select message. - * - * @return true if reported successfully, false otherwise. - */ - public boolean initiatorReportNfcHandover(String selectMessage) { - return mSupplicantP2pIfaceHal.initiatorReportNfcHandover(selectMessage); - } - - /** - * Report NFC handover request message. - * - * @return true if reported successfully, false otherwise. - */ - public boolean responderReportNfcHandover(String requestMessage) { - return mSupplicantP2pIfaceHal.responderReportNfcHandover(requestMessage); - } - - /** - * Set the client list for the provided network. - * - * @param netId Id of the network. - * @return Space separated list of clients if successfull, null otherwise. - */ - public String getP2pClientList(int netId) { - return mSupplicantP2pIfaceHal.getClientList(netId); - } - - /** - * Set the client list for the provided network. - * - * @param netId Id of the network. - * @param list Space separated list of clients. - * @return true, if operation was successful. - */ - public boolean setP2pClientList(int netId, String list) { - return mSupplicantP2pIfaceHal.setClientList(netId, list); - } - - /** - * Save the current configuration to p2p_supplicant.conf. - * - * @return true on success, false otherwise. - */ - public boolean saveConfig() { - return mSupplicantP2pIfaceHal.saveConfig(); - } - - /** - * Enable/Disable MAC randomization. - * - * @param enable true to enable, false to disable. - * @return true, if operation was successful. - */ - public boolean setMacRandomization(boolean enable) { - return mSupplicantP2pIfaceHal.setMacRandomization(enable); - } - - /** - * Get the supported features - * - * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - public long getSupportedFeatureSet(@NonNull String ifaceName) { - return mWifiVendorHal.getSupportedFeatureSet(ifaceName); - } -} diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pService.java b/service/java/com/android/server/wifi/p2p/WifiP2pService.java deleted file mode 100644 index 2b536b0cd..000000000 --- a/service/java/com/android/server/wifi/p2p/WifiP2pService.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2011 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.server.wifi.p2p; - -import android.content.Context; -import android.util.Log; - -import com.android.server.SystemService; -import com.android.server.wifi.WifiContext; -import com.android.server.wifi.WifiInjector; - -/** - * Wifi P2p Service class, instantiates P2p service - * Overrides onStart() and onBootPhase() methods in - * the super class. - */ -public final class WifiP2pService extends SystemService { - - private static final String TAG = "WifiP2pService"; - final WifiP2pServiceImpl mImpl; - - public WifiP2pService(Context contextBase) { - super(new WifiContext(contextBase)); - mImpl = new WifiP2pServiceImpl(getContext(), WifiInjector.getInstance()); - } - - @Override - public void onStart() { - Log.i(TAG, "Registering " + Context.WIFI_P2P_SERVICE); - publishBinderService(Context.WIFI_P2P_SERVICE, mImpl); - } - - @Override - public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { - mImpl.connectivityServiceReady(); - } - } -} diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java deleted file mode 100644 index eb2a89c4e..000000000 --- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java +++ /dev/null @@ -1,4415 +0,0 @@ -/* - * Copyright (C) 2011 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.server.wifi.p2p; - -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_DEVICE_NAME; -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_PENDING_FACTORY_RESET; -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; - -import android.annotation.Nullable; -import android.app.AlertDialog; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.location.LocationManager; -import android.net.ConnectivityManager; -import android.net.DhcpResultsParcelable; -import android.net.InetAddresses; -import android.net.LinkProperties; -import android.net.NetworkInfo; -import android.net.NetworkStack; -import android.net.TetheringManager; -import android.net.ip.IIpClient; -import android.net.ip.IpClientCallbacks; -import android.net.ip.IpClientUtil; -import android.net.shared.ProvisioningConfiguration; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WpsInfo; -import android.net.wifi.p2p.IWifiP2pManager; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pDeviceList; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pGroupList; -import android.net.wifi.p2p.WifiP2pGroupList.GroupDeleteListener; -import android.net.wifi.p2p.WifiP2pInfo; -import android.net.wifi.p2p.WifiP2pManager; -import android.net.wifi.p2p.WifiP2pProvDiscEvent; -import android.net.wifi.p2p.WifiP2pWfdInfo; -import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; -import android.net.wifi.p2p.nsd.WifiP2pServiceRequest; -import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.Log; -import android.util.SparseArray; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.widget.EditText; -import android.widget.TextView; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; -import com.android.internal.util.Protocol; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import com.android.server.wifi.FrameworkFacade; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiLog; -import com.android.server.wifi.WifiSettingsConfigStore; -import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.WifiAsyncChannel; -import com.android.server.wifi.util.WifiHandler; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * WifiP2pService includes a state machine to perform Wi-Fi p2p operations. Applications - * communicate with this service to issue device discovery and connectivity requests - * through the WifiP2pManager interface. The state machine communicates with the wifi - * driver through wpa_supplicant and handles the event responses through WifiMonitor. - * - * Note that the term Wifi when used without a p2p suffix refers to the client mode - * of Wifi operation - * @hide - */ -public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { - private static final String TAG = "WifiP2pService"; - private boolean mVerboseLoggingEnabled = false; - private static final String NETWORKTYPE = "WIFI_P2P"; - @VisibleForTesting - static final int DEFAULT_GROUP_OWNER_INTENT = 6; - - private Context mContext; - - NetdWrapper mNetdWrapper; - private IIpClient mIpClient; - private int mIpClientStartIndex = 0; - private DhcpResultsParcelable mDhcpResultsParcelable; - - private P2pStateMachine mP2pStateMachine; - private AsyncChannel mReplyChannel = new WifiAsyncChannel(TAG); - private AsyncChannel mWifiChannel; - private LocationManager mLocationManager; - private WifiInjector mWifiInjector; - private WifiPermissionsUtil mWifiPermissionsUtil; - private FrameworkFacade mFrameworkFacade; - private WifiSettingsConfigStore mSettingsConfigStore; - private WifiP2pMetrics mWifiP2pMetrics; - - private static final Boolean JOIN_GROUP = true; - private static final Boolean FORM_GROUP = false; - - private static final Boolean RELOAD = true; - private static final Boolean NO_RELOAD = false; - - private static final String[] RECEIVER_PERMISSIONS_FOR_BROADCAST = { - android.Manifest.permission.ACCESS_FINE_LOCATION, - android.Manifest.permission.ACCESS_WIFI_STATE - }; - - private static final String[] RECEIVER_PERMISSIONS_FOR_BROADCAST_LOCATION_OFF = { - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.ACCESS_FINE_LOCATION, - android.Manifest.permission.ACCESS_WIFI_STATE - }; - - // Maximum number of bytes allowed for a network name, i.e. SSID. - private static final int MAX_NETWORK_NAME_BYTES = 32; - // Minimum number of bytes for a network name, i.e. DIRECT-xy. - private static final int MIN_NETWORK_NAME_BYTES = 9; - - // Two minutes comes from the wpa_supplicant setting - private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000; - private static int sGroupCreatingTimeoutIndex = 0; - - private static final int DISABLE_P2P_WAIT_TIME_MS = 5 * 1000; - private static int sDisableP2pTimeoutIndex = 0; - - // Set a two minute discover timeout to avoid STA scans from being blocked - private static final int DISCOVER_TIMEOUT_S = 120; - - // Idle time after a peer is gone when the group is torn down - private static final int GROUP_IDLE_TIME_S = 10; - - private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE; - - // Delayed message to timeout group creation - public static final int GROUP_CREATING_TIMED_OUT = BASE + 1; - - // User accepted a peer request - private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 2; - // User rejected a peer request - private static final int PEER_CONNECTION_USER_REJECT = BASE + 3; - // User wants to disconnect wifi in favour of p2p - private static final int DROP_WIFI_USER_ACCEPT = BASE + 4; - // User wants to keep his wifi connection and drop p2p - private static final int DROP_WIFI_USER_REJECT = BASE + 5; - // Delayed message to timeout p2p disable - public static final int DISABLE_P2P_TIMED_OUT = BASE + 6; - // User confirm a peer request - public static final int PEER_CONNECTION_USER_CONFIRM = BASE + 7; - - // Commands to the ClientModeImpl - public static final int P2P_CONNECTION_CHANGED = BASE + 11; - - // These commands are used to temporarily disconnect wifi when we detect - // a frequency conflict which would make it impossible to have with p2p - // and wifi active at the same time. - // If the user chooses to disable wifi temporarily, we keep wifi disconnected - // until the p2p connection is done and terminated at which point we will - // bring back wifi up - // DISCONNECT_WIFI_REQUEST - // msg.arg1 = 1 enables temporary disconnect and 0 disables it. - public static final int DISCONNECT_WIFI_REQUEST = BASE + 12; - public static final int DISCONNECT_WIFI_RESPONSE = BASE + 13; - - public static final int SET_MIRACAST_MODE = BASE + 14; - - // During dhcp (and perhaps other times) we can't afford to drop packets - // but Discovery will switch our channel enough we will. - // msg.arg1 = ENABLED for blocking, DISABLED for resumed. - // msg.arg2 = msg to send when blocked - // msg.obj = StateMachine to send to when blocked - public static final int BLOCK_DISCOVERY = BASE + 15; - public static final int ENABLE_P2P = BASE + 16; - public static final int DISABLE_P2P = BASE + 17; - public static final int REMOVE_CLIENT_INFO = BASE + 18; - - // Messages for interaction with IpClient. - private static final int IPC_PRE_DHCP_ACTION = BASE + 30; - private static final int IPC_POST_DHCP_ACTION = BASE + 31; - private static final int IPC_DHCP_RESULTS = BASE + 32; - private static final int IPC_PROVISIONING_SUCCESS = BASE + 33; - private static final int IPC_PROVISIONING_FAILURE = BASE + 34; - - private static final int GROUP_OWNER_TETHER_READY = BASE + 35; - - public static final int ENABLED = 1; - public static final int DISABLED = 0; - - private final boolean mP2pSupported; - - private final WifiP2pDevice mThisDevice = new WifiP2pDevice(); - - // When a group has been explicitly created by an app, we persist the group - // even after all clients have been disconnected until an explicit remove - // is invoked - private boolean mAutonomousGroup; - - // Invitation to join an existing p2p group - private boolean mJoinExistingGroup; - - // Track whether we are in p2p discovery. This is used to avoid sending duplicate - // broadcasts - private boolean mDiscoveryStarted; - - // Track whether servcice/peer discovery is blocked in favor of other wifi actions - // (notably dhcp) - private boolean mDiscoveryBlocked; - - // remember if we were in a scan when it had to be stopped - private boolean mDiscoveryPostponed = false; - - private NetworkInfo.DetailedState mDetailedState; - - private boolean mTemporarilyDisconnectedWifi = false; - - // The transaction Id of service discovery request - private byte mServiceTransactionId = 0; - - // Service discovery request ID of wpa_supplicant. - // null means it's not set yet. - private String mServiceDiscReqId; - - // clients(application) information list - private HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<Messenger, ClientInfo>(); - - // clients(application) channel list - private Map<IBinder, Messenger> mClientChannelList = new HashMap<IBinder, Messenger>(); - - // The empty device address set by wpa_supplicant. - private static final String EMPTY_DEVICE_ADDRESS = "00:00:00:00:00:00"; - - // An anonymized device address. This is used instead of the own device MAC to prevent the - // latter from leaking to apps - private static final String ANONYMIZED_DEVICE_ADDRESS = "02:00:00:00:00:00"; - - /** - * Error code definition. - * see the Table.8 in the WiFi Direct specification for the detail. - */ - public enum P2pStatus { - // Success - SUCCESS, - - // The target device is currently unavailable - INFORMATION_IS_CURRENTLY_UNAVAILABLE, - - // Protocol error - INCOMPATIBLE_PARAMETERS, - - // The target device reached the limit of the number of the connectable device. - // For example, device limit or group limit is set - LIMIT_REACHED, - - // Protocol error - INVALID_PARAMETER, - - // Unable to accommodate request - UNABLE_TO_ACCOMMODATE_REQUEST, - - // Previous protocol error, or disruptive behavior - PREVIOUS_PROTOCOL_ERROR, - - // There is no common channels the both devices can use - NO_COMMON_CHANNEL, - - // Unknown p2p group. For example, Device A tries to invoke the previous persistent group, - // but device B has removed the specified credential already - UNKNOWN_P2P_GROUP, - - // Both p2p devices indicated an intent of 15 in group owner negotiation - BOTH_GO_INTENT_15, - - // Incompatible provisioning method - INCOMPATIBLE_PROVISIONING_METHOD, - - // Rejected by user - REJECTED_BY_USER, - - // Unknown error - UNKNOWN; - - /** - * Returns P2p status corresponding to a given error value - * @param error integer error value - * @return P2pStatus enum for value - */ - public static P2pStatus valueOf(int error) { - switch(error) { - case 0 : - return SUCCESS; - case 1: - return INFORMATION_IS_CURRENTLY_UNAVAILABLE; - case 2: - return INCOMPATIBLE_PARAMETERS; - case 3: - return LIMIT_REACHED; - case 4: - return INVALID_PARAMETER; - case 5: - return UNABLE_TO_ACCOMMODATE_REQUEST; - case 6: - return PREVIOUS_PROTOCOL_ERROR; - case 7: - return NO_COMMON_CHANNEL; - case 8: - return UNKNOWN_P2P_GROUP; - case 9: - return BOTH_GO_INTENT_15; - case 10: - return INCOMPATIBLE_PROVISIONING_METHOD; - case 11: - return REJECTED_BY_USER; - default: - return UNKNOWN; - } - } - } - - /** - * Handles client connections - */ - private class ClientHandler extends WifiHandler { - - ClientHandler(String tag, android.os.Looper looper) { - super(tag, looper); - } - - @Override - public void handleMessage(Message msg) { - super.handleMessage(msg); - switch (msg.what) { - case WifiP2pManager.SET_DEVICE_NAME: - case WifiP2pManager.SET_WFD_INFO: - case WifiP2pManager.DISCOVER_PEERS: - case WifiP2pManager.STOP_DISCOVERY: - case WifiP2pManager.CONNECT: - case WifiP2pManager.CANCEL_CONNECT: - case WifiP2pManager.CREATE_GROUP: - case WifiP2pManager.REMOVE_GROUP: - case WifiP2pManager.START_LISTEN: - case WifiP2pManager.STOP_LISTEN: - case WifiP2pManager.SET_CHANNEL: - case WifiP2pManager.START_WPS: - case WifiP2pManager.ADD_LOCAL_SERVICE: - case WifiP2pManager.REMOVE_LOCAL_SERVICE: - case WifiP2pManager.CLEAR_LOCAL_SERVICES: - case WifiP2pManager.DISCOVER_SERVICES: - case WifiP2pManager.ADD_SERVICE_REQUEST: - case WifiP2pManager.REMOVE_SERVICE_REQUEST: - case WifiP2pManager.CLEAR_SERVICE_REQUESTS: - case WifiP2pManager.REQUEST_PEERS: - case WifiP2pManager.REQUEST_CONNECTION_INFO: - case WifiP2pManager.REQUEST_GROUP_INFO: - case WifiP2pManager.DELETE_PERSISTENT_GROUP: - case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO: - case WifiP2pManager.FACTORY_RESET: - case WifiP2pManager.SET_ONGOING_PEER_CONFIG: - case WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG: - case WifiP2pManager.REQUEST_P2P_STATE: - case WifiP2pManager.REQUEST_DISCOVERY_STATE: - case WifiP2pManager.REQUEST_NETWORK_INFO: - case WifiP2pManager.UPDATE_CHANNEL_INFO: - case WifiP2pManager.REQUEST_DEVICE_INFO: - mP2pStateMachine.sendMessage(Message.obtain(msg)); - break; - default: - Log.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg); - break; - } - } - } - private ClientHandler mClientHandler; - - private NetworkInfo makeNetworkInfo() { - final NetworkInfo info = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, - 0, NETWORKTYPE, ""); - if (mDetailedState != NetworkInfo.DetailedState.IDLE) { - info.setDetailedState(mDetailedState, null, null); - } - return info; - } - - /** - * Provide a way for unit tests to set valid log object in the WifiHandler - * @param log WifiLog object to assign to the clientHandler - */ - @VisibleForTesting - void setWifiHandlerLogForTest(WifiLog log) { - mClientHandler.setWifiLog(log); - - } - - /** - * Provide a way for unit tests to set valid log object in the WifiAsyncChannel - * @param log WifiLog object to assign to the mReplyChannel - */ - @VisibleForTesting - void setWifiLogForReplyChannel(WifiLog log) { - ((WifiAsyncChannel) mReplyChannel).setWifiLog(log); - } - - private class DeathHandlerData { - DeathHandlerData(DeathRecipient dr, Messenger m) { - mDeathRecipient = dr; - mMessenger = m; - } - - @Override - public String toString() { - return "deathRecipient=" + mDeathRecipient + ", messenger=" + mMessenger; - } - - DeathRecipient mDeathRecipient; - Messenger mMessenger; - } - private Object mLock = new Object(); - private final Map<IBinder, DeathHandlerData> mDeathDataByBinder = new HashMap<>(); - - public WifiP2pServiceImpl(Context context, WifiInjector wifiInjector) { - mContext = context; - mWifiInjector = wifiInjector; - mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); - mFrameworkFacade = mWifiInjector.getFrameworkFacade(); - mSettingsConfigStore = mWifiInjector.getSettingsConfigStore(); - mWifiP2pMetrics = mWifiInjector.getWifiP2pMetrics(); - - mDetailedState = NetworkInfo.DetailedState.IDLE; - - mP2pSupported = mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_DIRECT); - - HandlerThread wifiP2pThread = mWifiInjector.getWifiP2pServiceHandlerThread(); - mClientHandler = new ClientHandler(TAG, wifiP2pThread.getLooper()); - mP2pStateMachine = new P2pStateMachine(TAG, wifiP2pThread.getLooper(), mP2pSupported); - mP2pStateMachine.start(); - } - - /** - * Obtains the service interface for Managements services - */ - public void connectivityServiceReady() { - mNetdWrapper = mWifiInjector.makeNetdWrapper(); - } - - private void enforceAccessPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, - "WifiP2pService"); - } - - private void enforceChangePermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, - "WifiP2pService"); - } - - private boolean checkAnyPermissionOf(String... permissions) { - for (String permission : permissions) { - if (mContext.checkCallingOrSelfPermission(permission) - == PackageManager.PERMISSION_GRANTED) { - return true; - } - } - return false; - } - - private void enforceAnyPermissionOf(String... permissions) { - if (!checkAnyPermissionOf(permissions)) { - throw new SecurityException("Requires one of the following permissions: " - + String.join(", ", permissions) + "."); - } - } - - private void enforceNetworkStackOrLocationHardwarePermission() { - enforceAnyPermissionOf( - android.Manifest.permission.LOCATION_HARDWARE, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private void stopIpClient() { - // Invalidate all previous start requests - mIpClientStartIndex++; - if (mIpClient != null) { - try { - mIpClient.stop(); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - mIpClient = null; - } - mDhcpResultsParcelable = null; - } - - private void startIpClient(String ifname, Handler smHandler) { - stopIpClient(); - mIpClientStartIndex++; - IpClientUtil.makeIpClient(mContext, ifname, new IpClientCallbacksImpl( - mIpClientStartIndex, smHandler)); - } - - private class IpClientCallbacksImpl extends IpClientCallbacks { - private final int mStartIndex; - private final Handler mHandler; - - private IpClientCallbacksImpl(int startIndex, Handler handler) { - mStartIndex = startIndex; - mHandler = handler; - } - - @Override - public void onIpClientCreated(IIpClient ipClient) { - mHandler.post(() -> { - if (mIpClientStartIndex != mStartIndex) { - // This start request is obsolete - return; - } - mIpClient = ipClient; - - final ProvisioningConfiguration config = - new ProvisioningConfiguration.Builder() - .withoutIpReachabilityMonitor() - .withPreDhcpAction(30 * 1000) - .withProvisioningTimeoutMs(36 * 1000) - .build(); - try { - mIpClient.startProvisioning(config.toStableParcelable()); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - }); - } - - @Override - public void onPreDhcpAction() { - mP2pStateMachine.sendMessage(IPC_PRE_DHCP_ACTION); - } - @Override - public void onPostDhcpAction() { - mP2pStateMachine.sendMessage(IPC_POST_DHCP_ACTION); - } - @Override - public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { - mP2pStateMachine.sendMessage(IPC_DHCP_RESULTS, dhcpResults); - } - @Override - public void onProvisioningSuccess(LinkProperties newLp) { - mP2pStateMachine.sendMessage(IPC_PROVISIONING_SUCCESS); - } - @Override - public void onProvisioningFailure(LinkProperties newLp) { - mP2pStateMachine.sendMessage(IPC_PROVISIONING_FAILURE); - } - } - - /** - * Get a reference to handler. This is used by a client to establish - * an AsyncChannel communication with WifiP2pService - */ - @Override - public Messenger getMessenger(final IBinder binder) { - enforceAccessPermission(); - enforceChangePermission(); - - synchronized (mLock) { - final Messenger messenger = new Messenger(mClientHandler); - if (mVerboseLoggingEnabled) { - Log.d(TAG, "getMessenger: uid=" + getCallingUid() + ", binder=" + binder - + ", messenger=" + messenger); - } - - IBinder.DeathRecipient dr = () -> { - if (mVerboseLoggingEnabled) Log.d(TAG, "binderDied: binder=" + binder); - close(binder); - }; - - try { - binder.linkToDeath(dr, 0); - mDeathDataByBinder.put(binder, new DeathHandlerData(dr, messenger)); - } catch (RemoteException e) { - Log.e(TAG, "Error on linkToDeath: e=" + e); - // fall-through here - won't clean up - } - mP2pStateMachine.sendMessage(ENABLE_P2P); - - return messenger; - } - } - - /** - * Get a reference to handler. This is used by a ClientModeImpl to establish - * an AsyncChannel communication with P2pStateMachine - * @hide - */ - @Override - public Messenger getP2pStateMachineMessenger() { - enforceNetworkStackOrLocationHardwarePermission(); - enforceAccessPermission(); - enforceChangePermission(); - return new Messenger(mP2pStateMachine.getHandler()); - } - - /** - * Clean-up the state and configuration requested by the closing app. Takes same action as - * when the app dies (binder death). - */ - @Override - public void close(IBinder binder) { - enforceAccessPermission(); - enforceChangePermission(); - - DeathHandlerData dhd; - synchronized (mLock) { - dhd = mDeathDataByBinder.get(binder); - if (dhd == null) { - Log.w(TAG, "close(): no death recipient for binder"); - return; - } - - mP2pStateMachine.sendMessage(REMOVE_CLIENT_INFO, 0, 0, binder); - binder.unlinkToDeath(dhd.mDeathRecipient, 0); - mDeathDataByBinder.remove(binder); - - // clean-up if there are no more clients registered - // TODO: what does the ClientModeImpl client do? It isn't tracked through here! - if (dhd.mMessenger != null && mDeathDataByBinder.isEmpty()) { - try { - dhd.mMessenger.send( - mClientHandler.obtainMessage(WifiP2pManager.STOP_DISCOVERY)); - dhd.mMessenger.send(mClientHandler.obtainMessage(WifiP2pManager.REMOVE_GROUP)); - } catch (RemoteException e) { - Log.e(TAG, "close: Failed sending clean-up commands: e=" + e); - } - mP2pStateMachine.sendMessage(DISABLE_P2P); - } - } - } - - /** This is used to provide information to drivers to optimize performance depending - * on the current mode of operation. - * 0 - disabled - * 1 - source operation - * 2 - sink operation - * - * As an example, the driver could reduce the channel dwell time during scanning - * when acting as a source or sink to minimize impact on miracast. - * @param int mode of operation - */ - @Override - public void setMiracastMode(int mode) { - checkConfigureWifiDisplayPermission(); - mP2pStateMachine.sendMessage(SET_MIRACAST_MODE, mode); - } - - @Override - public void checkConfigureWifiDisplayPermission() { - if (!getWfdPermission(Binder.getCallingUid())) { - throw new SecurityException("Wifi Display Permission denied for uid = " - + Binder.getCallingUid()); - } - } - - private boolean getWfdPermission(int uid) { - WifiPermissionsWrapper wifiPermissionsWrapper = mWifiInjector.getWifiPermissionsWrapper(); - return wifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.CONFIGURE_WIFI_DISPLAY, uid) - != PackageManager.PERMISSION_DENIED; - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump WifiP2pService from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - mP2pStateMachine.dump(fd, pw, args); - pw.println("mAutonomousGroup " + mAutonomousGroup); - pw.println("mJoinExistingGroup " + mJoinExistingGroup); - pw.println("mDiscoveryStarted " + mDiscoveryStarted); - pw.println("mDetailedState " + mDetailedState); - pw.println("mTemporarilyDisconnectedWifi " + mTemporarilyDisconnectedWifi); - pw.println("mServiceDiscReqId " + mServiceDiscReqId); - pw.println("mDeathDataByBinder " + mDeathDataByBinder); - pw.println("mClientInfoList " + mClientInfoList.size()); - pw.println(); - - final IIpClient ipClient = mIpClient; - if (ipClient != null) { - pw.println("mIpClient:"); - IpClientUtil.dumpIpClient(ipClient, fd, pw, args); - } - } - - /** - * Handles interaction with ClientModeImpl - */ - private class P2pStateMachine extends StateMachine { - - private DefaultState mDefaultState = new DefaultState(); - private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState(); - private P2pDisablingState mP2pDisablingState = new P2pDisablingState(); - private P2pDisabledState mP2pDisabledState = new P2pDisabledState(); - private P2pEnabledState mP2pEnabledState = new P2pEnabledState(); - // Inactive is when p2p is enabled with no connectivity - private InactiveState mInactiveState = new InactiveState(); - private GroupCreatingState mGroupCreatingState = new GroupCreatingState(); - private UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState = - new UserAuthorizingInviteRequestState(); - private UserAuthorizingNegotiationRequestState mUserAuthorizingNegotiationRequestState = - new UserAuthorizingNegotiationRequestState(); - private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState(); - private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState(); - private FrequencyConflictState mFrequencyConflictState = new FrequencyConflictState(); - - private GroupCreatedState mGroupCreatedState = new GroupCreatedState(); - private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState(); - private OngoingGroupRemovalState mOngoingGroupRemovalState = new OngoingGroupRemovalState(); - - private WifiP2pNative mWifiNative = mWifiInjector.getWifiP2pNative(); - private WifiP2pMonitor mWifiMonitor = mWifiInjector.getWifiP2pMonitor(); - private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); - private String mInterfaceName; - - // During a connection, supplicant can tell us that a device was lost. From a supplicant's - // perspective, the discovery stops during connection and it purges device since it does - // not get latest updates about the device without being in discovery state. - // From the framework perspective, the device is still there since we are connecting or - // connected to it. so we keep these devices in a separate list, so that they are removed - // when connection is cancelled or lost - private final WifiP2pDeviceList mPeersLostDuringConnection = new WifiP2pDeviceList(); - private final WifiP2pGroupList mGroups = new WifiP2pGroupList(null, - new GroupDeleteListener() { - @Override - public void onDeleteGroup(int netId) { - if (mVerboseLoggingEnabled) logd("called onDeleteGroup() netId=" + netId); - mWifiNative.removeP2pNetwork(netId); - mWifiNative.saveConfig(); - sendP2pPersistentGroupsChangedBroadcast(); - } - }); - private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo(); - private WifiP2pGroup mGroup; - // Is the HAL (HIDL) interface available for use. - private boolean mIsHalInterfaceAvailable = false; - // Is wifi on or off. - private boolean mIsWifiEnabled = false; - - // Saved WifiP2pConfig for an ongoing peer connection. This will never be null. - // The deviceAddress will be an empty string when the device is inactive - // or if it is connected without any ongoing join request - private WifiP2pConfig mSavedPeerConfig = new WifiP2pConfig(); - - P2pStateMachine(String name, Looper looper, boolean p2pSupported) { - super(name, looper); - - // CHECKSTYLE:OFF IndentationCheck - addState(mDefaultState); - addState(mP2pNotSupportedState, mDefaultState); - addState(mP2pDisablingState, mDefaultState); - addState(mP2pDisabledState, mDefaultState); - addState(mP2pEnabledState, mDefaultState); - addState(mInactiveState, mP2pEnabledState); - addState(mGroupCreatingState, mP2pEnabledState); - addState(mUserAuthorizingInviteRequestState, mGroupCreatingState); - addState(mUserAuthorizingNegotiationRequestState, mGroupCreatingState); - addState(mProvisionDiscoveryState, mGroupCreatingState); - addState(mGroupNegotiationState, mGroupCreatingState); - addState(mFrequencyConflictState, mGroupCreatingState); - addState(mGroupCreatedState, mP2pEnabledState); - addState(mUserAuthorizingJoinState, mGroupCreatedState); - addState(mOngoingGroupRemovalState, mGroupCreatedState); - // CHECKSTYLE:ON IndentationCheck - - if (p2pSupported) { - setInitialState(mP2pDisabledState); - } else { - setInitialState(mP2pNotSupportedState); - } - setLogRecSize(50); - setLogOnlyTransitions(true); - - if (p2pSupported) { - // Register for wifi on/off broadcasts - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - int wifistate = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN); - if (wifistate == WifiManager.WIFI_STATE_ENABLED) { - mIsWifiEnabled = true; - checkAndReEnableP2p(); - } else { - mIsWifiEnabled = false; - // Teardown P2P if it's up already. - sendMessage(DISABLE_P2P); - } - checkAndSendP2pStateChangedBroadcast(); - } - }, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); - // Register for location mode on/off broadcasts - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - /* if location mode is off, ongoing discovery should be stopped. - * possible ongoing discovery: - * - peer discovery - * - service discovery - * - group joining scan in native service - */ - if (!mWifiPermissionsUtil.isLocationModeEnabled()) { - sendMessage(WifiP2pManager.STOP_DISCOVERY); - } - } - }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); - // Register for tethering state - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mGroup == null) return; - if (!mGroup.isGroupOwner()) return; - if (TextUtils.isEmpty(mGroup.getInterface())) return; - - final ArrayList<String> interfaces = intent.getStringArrayListExtra( - TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY); - - if (interfaces.contains(mGroup.getInterface())) { - sendMessage(GROUP_OWNER_TETHER_READY); - } - } - }, new IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)); - // Register for interface availability from HalDeviceManager - mWifiNative.registerInterfaceAvailableListener((boolean isAvailable) -> { - mIsHalInterfaceAvailable = isAvailable; - checkAndSendP2pStateChangedBroadcast(); - }, getHandler()); - - mSettingsConfigStore.registerChangeListener( - WIFI_VERBOSE_LOGGING_ENABLED, - (key, newValue) -> enableVerboseLogging(newValue), - getHandler()); - } - } - - /** - * Enable verbose logging for all sub modules. - */ - private void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - mWifiNative.enableVerboseLogging(verbose ? 1 : 0); - mWifiMonitor.enableVerboseLogging(verbose ? 1 : 0); - } - - public void registerForWifiMonitorEvents() { - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.AP_STA_CONNECTED_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_DEVICE_LOST_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_FIND_STOPPED_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_GROUP_STARTED_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.SUP_CONNECTION_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, - WifiP2pMonitor.SUP_DISCONNECTION_EVENT, getHandler()); - - mWifiMonitor.startMonitoring(mInterfaceName); - } - - class DefaultState extends State { - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - if (mVerboseLoggingEnabled) { - logd("Full connection with ClientModeImpl established"); - } - mWifiChannel = (AsyncChannel) message.obj; - } else { - loge("Full connection failure, error = " + message.arg1); - mWifiChannel = null; - transitionTo(mP2pDisabledState); - } - break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { - loge("Send failed, client connection lost"); - } else { - loge("Client connection lost with reason: " + message.arg1); - } - mWifiChannel = null; - transitionTo(mP2pDisabledState); - break; - case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: - AsyncChannel ac = new WifiAsyncChannel(TAG); - ac.connect(mContext, getHandler(), message.replyTo); - break; - case BLOCK_DISCOVERY: - mDiscoveryBlocked = (message.arg1 == ENABLED ? true : false); - // always reset this - we went to a state that doesn't support discovery so - // it would have stopped regardless - mDiscoveryPostponed = false; - if (mDiscoveryBlocked && mWifiChannel != null) { - mWifiChannel.replyToMessage(message, message.arg2); - } - break; - case WifiP2pManager.DISCOVER_PEERS: - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.STOP_DISCOVERY: - replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.DISCOVER_SERVICES: - replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.CONNECT: - replyToMessage(message, WifiP2pManager.CONNECT_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.CANCEL_CONNECT: - replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.CREATE_GROUP: - replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.REMOVE_GROUP: - replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.ADD_LOCAL_SERVICE: - replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.REMOVE_LOCAL_SERVICE: - replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.CLEAR_LOCAL_SERVICES: - replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.ADD_SERVICE_REQUEST: - replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.REMOVE_SERVICE_REQUEST: - replyToMessage(message, - WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.CLEAR_SERVICE_REQUESTS: - replyToMessage(message, - WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.SET_DEVICE_NAME: - replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.DELETE_PERSISTENT_GROUP: - replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.SET_WFD_INFO: - if (!getWfdPermission(message.sendingUid)) { - replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, - WifiP2pManager.ERROR); - } else { - replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, - WifiP2pManager.BUSY); - } - break; - case WifiP2pManager.REQUEST_PEERS: - replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, - getPeers(getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid)); - break; - case WifiP2pManager.REQUEST_CONNECTION_INFO: - replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, - new WifiP2pInfo(mWifiP2pInfo)); - break; - case WifiP2pManager.REQUEST_GROUP_INFO: - if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( - getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid, false)) { - replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, null); - // remain at this state. - break; - } - replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, - maybeEraseOwnDeviceAddress(mGroup, message.sendingUid)); - break; - case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO: - if (!checkNetworkSettingsOrNetworkStackOrReadWifiCredentialPermission( - message.sendingUid)) { - loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," - + " or READ_WIFI_CREDENTIAL permission, uid = " - + message.sendingUid); - replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, - new WifiP2pGroupList()); - break; - } - replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, - new WifiP2pGroupList( - maybeEraseOwnDeviceAddress(mGroups, message.sendingUid), - null)); - break; - case WifiP2pManager.REQUEST_P2P_STATE: - replyToMessage(message, WifiP2pManager.RESPONSE_P2P_STATE, - (mIsWifiEnabled && isHalInterfaceAvailable()) - ? WifiP2pManager.WIFI_P2P_STATE_ENABLED - : WifiP2pManager.WIFI_P2P_STATE_DISABLED); - break; - case WifiP2pManager.REQUEST_DISCOVERY_STATE: - replyToMessage(message, WifiP2pManager.RESPONSE_DISCOVERY_STATE, - mDiscoveryStarted - ? WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED - : WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); - break; - case WifiP2pManager.REQUEST_NETWORK_INFO: - replyToMessage(message, WifiP2pManager.RESPONSE_NETWORK_INFO, - makeNetworkInfo()); - break; - case WifiP2pManager.START_WPS: - replyToMessage(message, WifiP2pManager.START_WPS_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.GET_HANDOVER_REQUEST: - case WifiP2pManager.GET_HANDOVER_SELECT: - replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, null); - break; - case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: - case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: - replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: - case WifiP2pMonitor.SUP_CONNECTION_EVENT: - case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: - case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: - case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT: - case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: - case WifiP2pMonitor.P2P_FIND_STOPPED_EVENT: - case WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT: - case PEER_CONNECTION_USER_ACCEPT: - case PEER_CONNECTION_USER_REJECT: - case DISCONNECT_WIFI_RESPONSE: - case DROP_WIFI_USER_ACCEPT: - case DROP_WIFI_USER_REJECT: - case GROUP_CREATING_TIMED_OUT: - case DISABLE_P2P_TIMED_OUT: - case IPC_PRE_DHCP_ACTION: - case IPC_POST_DHCP_ACTION: - case IPC_DHCP_RESULTS: - case IPC_PROVISIONING_SUCCESS: - case IPC_PROVISIONING_FAILURE: - case GROUP_OWNER_TETHER_READY: - case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: - case SET_MIRACAST_MODE: - case WifiP2pManager.START_LISTEN: - case WifiP2pManager.STOP_LISTEN: - case WifiP2pManager.SET_CHANNEL: - case ENABLE_P2P: - // Enable is lazy and has no response - break; - case DISABLE_P2P: - // If we end up handling in default, p2p is not enabled - break; - case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: - // unexpected group created, remove - if (message.obj == null) { - Log.e(TAG, "Illegal arguments"); - break; - } - mGroup = (WifiP2pGroup) message.obj; - loge("Unexpected group creation, remove " + mGroup); - mWifiNative.p2pGroupRemove(mGroup.getInterface()); - break; - case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: - // A group formation failure is always followed by - // a group removed event. Flushing things at group formation - // failure causes supplicant issues. Ignore right now. - break; - case WifiP2pManager.FACTORY_RESET: - if (factoryReset(message.sendingUid)) { - replyToMessage(message, WifiP2pManager.FACTORY_RESET_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.FACTORY_RESET_FAILED, - WifiP2pManager.ERROR); - } - break; - case WifiP2pManager.SET_ONGOING_PEER_CONFIG: - if (mWifiPermissionsUtil.checkNetworkStackPermission(message.sendingUid)) { - WifiP2pConfig peerConfig = (WifiP2pConfig) message.obj; - if (isConfigInvalid(peerConfig)) { - loge("Dropping set mSavedPeerConfig requeset" + peerConfig); - replyToMessage(message, - WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED); - } else { - logd("setSavedPeerConfig to " + peerConfig); - mSavedPeerConfig = peerConfig; - replyToMessage(message, - WifiP2pManager.SET_ONGOING_PEER_CONFIG_SUCCEEDED); - } - } else { - loge("Permission violation - no NETWORK_STACK permission," - + " uid = " + message.sendingUid); - replyToMessage(message, - WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED); - } - break; - case WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG: - if (mWifiPermissionsUtil.checkNetworkStackPermission(message.sendingUid)) { - replyToMessage(message, - WifiP2pManager.RESPONSE_ONGOING_PEER_CONFIG, mSavedPeerConfig); - } else { - loge("Permission violation - no NETWORK_STACK permission," - + " uid = " + message.sendingUid); - replyToMessage(message, - WifiP2pManager.RESPONSE_ONGOING_PEER_CONFIG, null); - } - break; - case WifiP2pManager.UPDATE_CHANNEL_INFO: - if (!(message.obj instanceof Bundle)) { - break; - } - Bundle bundle = (Bundle) message.obj; - String pkgName = bundle.getString(WifiP2pManager.CALLING_PACKAGE); - String featureId = bundle.getString(WifiP2pManager.CALLING_FEATURE_ID); - IBinder binder = bundle.getBinder(WifiP2pManager.CALLING_BINDER); - try { - mWifiPermissionsUtil.checkPackage(message.sendingUid, pkgName); - } catch (SecurityException se) { - loge("Unable to update calling package, " + se); - break; - } - if (binder != null && message.replyTo != null) { - mClientChannelList.put(binder, message.replyTo); - ClientInfo clientInfo = getClientInfo(message.replyTo, true); - clientInfo.mPackageName = pkgName; - clientInfo.mFeatureId = featureId; - } - break; - case WifiP2pManager.REQUEST_DEVICE_INFO: - if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( - getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid, false)) { - replyToMessage(message, WifiP2pManager.RESPONSE_DEVICE_INFO, null); - break; - } - replyToMessage(message, WifiP2pManager.RESPONSE_DEVICE_INFO, - maybeEraseOwnDeviceAddress(mThisDevice, message.sendingUid)); - break; - default: - loge("Unhandled message " + message); - return NOT_HANDLED; - } - return HANDLED; - } - } - - class P2pNotSupportedState extends State { - @Override - public boolean processMessage(Message message) { - switch (message.what) { - case WifiP2pManager.DISCOVER_PEERS: - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.STOP_DISCOVERY: - replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.DISCOVER_SERVICES: - replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.CONNECT: - replyToMessage(message, WifiP2pManager.CONNECT_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.CANCEL_CONNECT: - replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.CREATE_GROUP: - replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.REMOVE_GROUP: - replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.ADD_LOCAL_SERVICE: - replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.REMOVE_LOCAL_SERVICE: - replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.CLEAR_LOCAL_SERVICES: - replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.ADD_SERVICE_REQUEST: - replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.REMOVE_SERVICE_REQUEST: - replyToMessage(message, - WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.CLEAR_SERVICE_REQUESTS: - replyToMessage(message, - WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.SET_DEVICE_NAME: - replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.DELETE_PERSISTENT_GROUP: - replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.SET_WFD_INFO: - if (!getWfdPermission(message.sendingUid)) { - replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, - WifiP2pManager.ERROR); - } else { - replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - } - break; - case WifiP2pManager.START_WPS: - replyToMessage(message, WifiP2pManager.START_WPS_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.START_LISTEN: - replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.STOP_LISTEN: - replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - case WifiP2pManager.FACTORY_RESET: - replyToMessage(message, WifiP2pManager.FACTORY_RESET_FAILED, - WifiP2pManager.P2P_UNSUPPORTED); - break; - - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class P2pDisablingState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - sendMessageDelayed(obtainMessage(DISABLE_P2P_TIMED_OUT, - ++sDisableP2pTimeoutIndex, 0), DISABLE_P2P_WAIT_TIME_MS); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: - if (mVerboseLoggingEnabled) logd("p2p socket connection lost"); - transitionTo(mP2pDisabledState); - break; - case ENABLE_P2P: - case DISABLE_P2P: - case REMOVE_CLIENT_INFO: - deferMessage(message); - break; - case DISABLE_P2P_TIMED_OUT: - if (sDisableP2pTimeoutIndex == message.arg1) { - loge("P2p disable timed out"); - transitionTo(mP2pDisabledState); - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class P2pDisabledState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - mInterfaceName = null; // reset iface name on disable. - } - - private void setupInterfaceFeatures(String interfaceName) { - if (mContext.getResources().getBoolean( - R.bool.config_wifi_p2p_mac_randomization_supported)) { - Log.i(TAG, "Supported feature: P2P MAC randomization"); - mWifiNative.setMacRandomization(true); - } else { - mWifiNative.setMacRandomization(false); - } - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - case ENABLE_P2P: - if (!mIsWifiEnabled) { - Log.e(TAG, "Ignore P2P enable since wifi is " + mIsWifiEnabled); - break; - } - mInterfaceName = mWifiNative.setupInterface((String ifaceName) -> { - mIsHalInterfaceAvailable = false; - sendMessage(DISABLE_P2P); - checkAndSendP2pStateChangedBroadcast(); - }, getHandler()); - if (mInterfaceName == null) { - Log.e(TAG, "Failed to setup interface for P2P"); - break; - } - setupInterfaceFeatures(mInterfaceName); - try { - mNetdWrapper.setInterfaceUp(mInterfaceName); - } catch (IllegalStateException ie) { - loge("Unable to change interface settings: " + ie); - } - registerForWifiMonitorEvents(); - transitionTo(mInactiveState); - break; - case REMOVE_CLIENT_INFO: - if (!(message.obj instanceof IBinder)) { - loge("Invalid obj when REMOVE_CLIENT_INFO"); - break; - } - IBinder b = (IBinder) message.obj; - // client service info is clear before enter disable p2p, - // just need to remove it from list - Messenger m = mClientChannelList.remove(b); - ClientInfo clientInfo = mClientInfoList.remove(m); - if (clientInfo != null) { - logd("Remove client - " + clientInfo.mPackageName); - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class P2pEnabledState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - - if (isPendingFactoryReset()) { - factoryReset(Process.SYSTEM_UID); - } - - sendP2pConnectionChangedBroadcast(); - initializeP2pSettings(); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: - loge("Unexpected loss of p2p socket connection"); - transitionTo(mP2pDisabledState); - break; - case ENABLE_P2P: - // Nothing to do - break; - case DISABLE_P2P: - if (mPeers.clear()) { - sendPeersChangedBroadcast(); - } - if (mGroups.clear()) sendP2pPersistentGroupsChangedBroadcast(); - // clear services list for all clients since interface will teardown soon. - clearServicesForAllClients(); - mWifiMonitor.stopMonitoring(mInterfaceName); - mWifiNative.teardownInterface(); - transitionTo(mP2pDisablingState); - break; - case REMOVE_CLIENT_INFO: - if (!(message.obj instanceof IBinder)) { - break; - } - IBinder b = (IBinder) message.obj; - // clear client info and remove it from list - clearClientInfo(mClientChannelList.get(b)); - mClientChannelList.remove(b); - break; - case WifiP2pManager.SET_DEVICE_NAME: - { - if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( - message.sendingUid)) { - loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," - + " or OVERRIDE_WIFI_CONFIG permission, uid = " - + message.sendingUid); - replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, - WifiP2pManager.ERROR); - break; - } - WifiP2pDevice d = (WifiP2pDevice) message.obj; - if (d != null && setAndPersistDeviceName(d.deviceName)) { - if (mVerboseLoggingEnabled) logd("set device name " + d.deviceName); - replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, - WifiP2pManager.ERROR); - } - break; - } - case WifiP2pManager.SET_WFD_INFO: - { - WifiP2pWfdInfo d = (WifiP2pWfdInfo) message.obj; - if (!getWfdPermission(message.sendingUid)) { - replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, - WifiP2pManager.ERROR); - } else if (d != null && setWfdInfo(d)) { - replyToMessage(message, WifiP2pManager.SET_WFD_INFO_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, - WifiP2pManager.ERROR); - } - break; - } - case BLOCK_DISCOVERY: - boolean blocked = (message.arg1 == ENABLED ? true : false); - if (mDiscoveryBlocked == blocked) break; - mDiscoveryBlocked = blocked; - if (blocked && mDiscoveryStarted) { - mWifiNative.p2pStopFind(); - mDiscoveryPostponed = true; - } - if (!blocked && mDiscoveryPostponed) { - mDiscoveryPostponed = false; - mWifiNative.p2pFind(DISCOVER_TIMEOUT_S); - } - if (blocked && mWifiChannel != null) { - mWifiChannel.replyToMessage(message, message.arg2); - } - break; - case WifiP2pManager.DISCOVER_PEERS: - if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( - getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid, true)) { - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, - WifiP2pManager.ERROR); - // remain at this state. - break; - } - if (mDiscoveryBlocked) { - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, - WifiP2pManager.BUSY); - break; - } - // do not send service discovery request while normal find operation. - clearSupplicantServiceRequest(); - if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) { - mWifiP2pMetrics.incrementPeerScans(); - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED); - sendP2pDiscoveryChangedBroadcast(true); - } else { - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, - WifiP2pManager.ERROR); - } - break; - case WifiP2pMonitor.P2P_FIND_STOPPED_EVENT: - sendP2pDiscoveryChangedBroadcast(false); - break; - case WifiP2pManager.STOP_DISCOVERY: - if (mWifiNative.p2pStopFind()) { - replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, - WifiP2pManager.ERROR); - } - break; - case WifiP2pManager.DISCOVER_SERVICES: - if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( - getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid, true)) { - replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, - WifiP2pManager.ERROR); - // remain at this state. - break; - } - if (mDiscoveryBlocked) { - replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, - WifiP2pManager.BUSY); - break; - } - if (mVerboseLoggingEnabled) logd(getName() + " discover services"); - if (!updateSupplicantServiceRequest()) { - replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, - WifiP2pManager.NO_SERVICE_REQUESTS); - break; - } - if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) { - mWifiP2pMetrics.incrementServiceScans(); - replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, - WifiP2pManager.ERROR); - } - break; - case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - WifiP2pDevice device = (WifiP2pDevice) message.obj; - if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break; - mPeers.updateSupplicantDetails(device); - sendPeersChangedBroadcast(); - break; - case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - device = (WifiP2pDevice) message.obj; - // Gets current details for the one removed - device = mPeers.remove(device.deviceAddress); - if (device != null) { - sendPeersChangedBroadcast(); - } - break; - case WifiP2pManager.ADD_LOCAL_SERVICE: - if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( - getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid, false)) { - replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED); - // remain at this state. - break; - } - if (mVerboseLoggingEnabled) logd(getName() + " add service"); - WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo) message.obj; - if (addLocalService(message.replyTo, servInfo)) { - replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED); - } - break; - case WifiP2pManager.REMOVE_LOCAL_SERVICE: - if (mVerboseLoggingEnabled) logd(getName() + " remove service"); - servInfo = (WifiP2pServiceInfo) message.obj; - removeLocalService(message.replyTo, servInfo); - replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED); - break; - case WifiP2pManager.CLEAR_LOCAL_SERVICES: - if (mVerboseLoggingEnabled) logd(getName() + " clear service"); - clearLocalServices(message.replyTo); - replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED); - break; - case WifiP2pManager.ADD_SERVICE_REQUEST: - if (mVerboseLoggingEnabled) logd(getName() + " add service request"); - if (!addServiceRequest(message.replyTo, - (WifiP2pServiceRequest) message.obj)) { - replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED); - break; - } - replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED); - break; - case WifiP2pManager.REMOVE_SERVICE_REQUEST: - if (mVerboseLoggingEnabled) logd(getName() + " remove service request"); - removeServiceRequest(message.replyTo, (WifiP2pServiceRequest) message.obj); - replyToMessage(message, WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED); - break; - case WifiP2pManager.CLEAR_SERVICE_REQUESTS: - if (mVerboseLoggingEnabled) logd(getName() + " clear service request"); - clearServiceRequests(message.replyTo); - replyToMessage(message, WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED); - break; - case WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT: - if (mVerboseLoggingEnabled) logd(getName() + " receive service response"); - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - List<WifiP2pServiceResponse> sdRespList = - (List<WifiP2pServiceResponse>) message.obj; - for (WifiP2pServiceResponse resp : sdRespList) { - WifiP2pDevice dev = - mPeers.get(resp.getSrcDevice().deviceAddress); - resp.setSrcDevice(dev); - sendServiceResponse(resp); - } - break; - case WifiP2pManager.DELETE_PERSISTENT_GROUP: - if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( - message.sendingUid)) { - loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," - + " or OVERRIDE_WIFI_CONFIG permission, uid = " - + message.sendingUid); - replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, - WifiP2pManager.ERROR); - break; - } - if (mVerboseLoggingEnabled) logd(getName() + " delete persistent group"); - mGroups.remove(message.arg1); - mWifiP2pMetrics.updatePersistentGroup(mGroups); - replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED); - break; - case SET_MIRACAST_MODE: - mWifiNative.setMiracastMode(message.arg1); - break; - case WifiP2pManager.START_LISTEN: - if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( - message.sendingUid)) { - loge("Permission violation - no NETWORK_SETTING permission," - + " uid = " + message.sendingUid); - replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); - break; - } - if (mVerboseLoggingEnabled) logd(getName() + " start listen mode"); - mWifiNative.p2pFlush(); - if (mWifiNative.p2pExtListen(true, 500, 500)) { - replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); - } - break; - case WifiP2pManager.STOP_LISTEN: - if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( - message.sendingUid)) { - loge("Permission violation - no NETWORK_SETTING permission," - + " uid = " + message.sendingUid); - replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); - break; - } - if (mVerboseLoggingEnabled) logd(getName() + " stop listen mode"); - if (mWifiNative.p2pExtListen(false, 0, 0)) { - replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); - } - mWifiNative.p2pFlush(); - break; - case WifiP2pManager.SET_CHANNEL: - if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( - message.sendingUid)) { - loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," - + " or OVERRIDE_WIFI_CONFIG permission, uid = " - + message.sendingUid); - replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED, - WifiP2pManager.ERROR); - break; - } - Bundle p2pChannels = (Bundle) message.obj; - int lc = p2pChannels.getInt("lc", 0); - int oc = p2pChannels.getInt("oc", 0); - if (mVerboseLoggingEnabled) { - logd(getName() + " set listen and operating channel"); - } - if (mWifiNative.p2pSetChannel(lc, oc)) { - replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); - } - break; - case WifiP2pManager.GET_HANDOVER_REQUEST: - Bundle requestBundle = new Bundle(); - requestBundle.putString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE, - mWifiNative.getNfcHandoverRequest()); - replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, - requestBundle); - break; - case WifiP2pManager.GET_HANDOVER_SELECT: - Bundle selectBundle = new Bundle(); - selectBundle.putString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE, - mWifiNative.getNfcHandoverSelect()); - replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, - selectBundle); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - @Override - public void exit() { - sendP2pDiscoveryChangedBroadcast(false); - } - } - - class InactiveState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - mSavedPeerConfig.invalidate(); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - case WifiP2pManager.CONNECT: - if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( - getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid, false)) { - replyToMessage(message, WifiP2pManager.CONNECT_FAILED); - // remain at this state. - break; - } - if (mVerboseLoggingEnabled) logd(getName() + " sending connect"); - WifiP2pConfig config = (WifiP2pConfig) message.obj; - - boolean isConnectFailed = false; - if (isConfigValidAsGroup(config)) { - mAutonomousGroup = false; - mWifiNative.p2pStopFind(); - if (mWifiNative.p2pGroupAdd(config, true)) { - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_FAST, - config); - transitionTo(mGroupNegotiationState); - } else { - loge("Cannot join a group with config."); - isConnectFailed = true; - replyToMessage(message, WifiP2pManager.CONNECT_FAILED); - } - } else { - if (isConfigInvalid(config)) { - loge("Dropping connect request " + config); - isConnectFailed = true; - replyToMessage(message, WifiP2pManager.CONNECT_FAILED); - } else { - mAutonomousGroup = false; - mWifiNative.p2pStopFind(); - if (reinvokePersistentGroup(config)) { - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_REINVOKE, - config); - transitionTo(mGroupNegotiationState); - } else { - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_FRESH, - config); - transitionTo(mProvisionDiscoveryState); - } - } - } - - if (!isConnectFailed) { - mSavedPeerConfig = config; - mPeers.updateStatus(mSavedPeerConfig.deviceAddress, - WifiP2pDevice.INVITED); - sendPeersChangedBroadcast(); - replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); - } - break; - case WifiP2pManager.STOP_DISCOVERY: - if (mWifiNative.p2pStopFind()) { - // When discovery stops in inactive state, flush to clear - // state peer data - mWifiNative.p2pFlush(); - mServiceDiscReqId = null; - replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, - WifiP2pManager.ERROR); - } - break; - case WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT: - config = (WifiP2pConfig) message.obj; - if (isConfigInvalid(config)) { - loge("Dropping GO neg request " + config); - break; - } - mSavedPeerConfig = config; - mAutonomousGroup = false; - mJoinExistingGroup = false; - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_FRESH, - config); - transitionTo(mUserAuthorizingNegotiationRequestState); - break; - case WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT: - if (message.obj == null) { - Log.e(TAG, "Invalid argument(s)"); - break; - } - WifiP2pGroup group = (WifiP2pGroup) message.obj; - WifiP2pDevice owner = group.getOwner(); - if (owner == null) { - int id = group.getNetworkId(); - if (id < 0) { - loge("Ignored invitation from null owner"); - break; - } - - String addr = mGroups.getOwnerAddr(id); - if (addr != null) { - group.setOwner(new WifiP2pDevice(addr)); - owner = group.getOwner(); - } else { - loge("Ignored invitation from null owner"); - break; - } - } - config = new WifiP2pConfig(); - config.deviceAddress = group.getOwner().deviceAddress; - if (isConfigInvalid(config)) { - loge("Dropping invitation request " + config); - break; - } - mSavedPeerConfig = config; - - // Check if we have the owner in peer list and use appropriate - // wps method. Default is to use PBC. - if (owner != null && ((owner = mPeers.get(owner.deviceAddress)) != null)) { - if (owner.wpsPbcSupported()) { - mSavedPeerConfig.wps.setup = WpsInfo.PBC; - } else if (owner.wpsKeypadSupported()) { - mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; - } else if (owner.wpsDisplaySupported()) { - mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; - } - } - - mAutonomousGroup = false; - mJoinExistingGroup = true; - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_FRESH, - config); - transitionTo(mUserAuthorizingInviteRequestState); - break; - case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: - case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: - // We let the supplicant handle the provision discovery response - // and wait instead for the GO_NEGOTIATION_REQUEST_EVENT. - // Handling provision discovery and issuing a p2p_connect before - // group negotiation comes through causes issues - break; - case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; - WifiP2pDevice device = provDisc.device; - if (device == null) { - loge("Device entry is null"); - break; - } - mSavedPeerConfig = new WifiP2pConfig(); - mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; - mSavedPeerConfig.deviceAddress = device.deviceAddress; - mSavedPeerConfig.wps.pin = provDisc.pin; - - notifyP2pProvDiscShowPinRequest(provDisc.pin, device.deviceAddress); - mPeers.updateStatus(device.deviceAddress, WifiP2pDevice.INVITED); - sendPeersChangedBroadcast(); - transitionTo(mUserAuthorizingNegotiationRequestState); - break; - case WifiP2pManager.CREATE_GROUP: - if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( - getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid, false)) { - replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, - WifiP2pManager.ERROR); - // remain at this state. - break; - } - mAutonomousGroup = true; - int netId = message.arg1; - config = (WifiP2pConfig) message.obj; - boolean ret = false; - if (config != null) { - if (isConfigValidAsGroup(config)) { - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_FAST, - config); - ret = mWifiNative.p2pGroupAdd(config, false); - } else { - ret = false; - } - } else if (netId == WifiP2pGroup.NETWORK_ID_PERSISTENT) { - // check if the go persistent group is present. - netId = mGroups.getNetworkId(mThisDevice.deviceAddress); - if (netId != -1) { - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_REINVOKE, - null); - ret = mWifiNative.p2pGroupAdd(netId); - } else { - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_LOCAL, - null); - ret = mWifiNative.p2pGroupAdd(true); - } - } else { - mWifiP2pMetrics.startConnectionEvent( - P2pConnectionEvent.CONNECTION_LOCAL, - null); - ret = mWifiNative.p2pGroupAdd(false); - } - - if (ret) { - replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED); - transitionTo(mGroupNegotiationState); - } else { - replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, - WifiP2pManager.ERROR); - // remain at this state. - } - break; - case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: - if (message.obj == null) { - Log.e(TAG, "Invalid argument(s)"); - break; - } - mGroup = (WifiP2pGroup) message.obj; - if (mVerboseLoggingEnabled) logd(getName() + " group started"); - if (mGroup.isGroupOwner() - && EMPTY_DEVICE_ADDRESS.equals(mGroup.getOwner().deviceAddress)) { - // wpa_supplicant doesn't set own device address to go_dev_addr. - mGroup.getOwner().deviceAddress = mThisDevice.deviceAddress; - } - // We hit this scenario when a persistent group is reinvoked - if (mGroup.getNetworkId() == WifiP2pGroup.NETWORK_ID_PERSISTENT) { - mAutonomousGroup = false; - deferMessage(message); - transitionTo(mGroupNegotiationState); - } else { - loge("Unexpected group creation, remove " + mGroup); - mWifiNative.p2pGroupRemove(mGroup.getInterface()); - } - break; - case WifiP2pManager.START_LISTEN: - if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( - message.sendingUid)) { - loge("Permission violation - no NETWORK_SETTING permission," - + " uid = " + message.sendingUid); - replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); - break; - } - if (mVerboseLoggingEnabled) logd(getName() + " start listen mode"); - mWifiNative.p2pFlush(); - if (mWifiNative.p2pExtListen(true, 500, 500)) { - replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); - } - break; - case WifiP2pManager.STOP_LISTEN: - if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( - message.sendingUid)) { - loge("Permission violation - no NETWORK_SETTING permission," - + " uid = " + message.sendingUid); - replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); - break; - } - if (mVerboseLoggingEnabled) logd(getName() + " stop listen mode"); - if (mWifiNative.p2pExtListen(false, 0, 0)) { - replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); - } - mWifiNative.p2pFlush(); - break; - case WifiP2pManager.SET_CHANNEL: - if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( - message.sendingUid)) { - loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," - + " or OVERRIDE_WIFI_CONFIG permission, uid = " - + message.sendingUid); - replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED, - WifiP2pManager.ERROR); - break; - } - if (message.obj == null) { - Log.e(TAG, "Illegal arguments(s)"); - break; - } - Bundle p2pChannels = (Bundle) message.obj; - int lc = p2pChannels.getInt("lc", 0); - int oc = p2pChannels.getInt("oc", 0); - if (mVerboseLoggingEnabled) { - logd(getName() + " set listen and operating channel"); - } - if (mWifiNative.p2pSetChannel(lc, oc)) { - replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); - } - break; - case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: - String handoverSelect = null; - - if (message.obj != null) { - handoverSelect = ((Bundle) message.obj) - .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); - } - - if (handoverSelect != null - && mWifiNative.initiatorReportNfcHandover(handoverSelect)) { - replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); - transitionTo(mGroupCreatingState); - } else { - replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); - } - break; - case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: - String handoverRequest = null; - - if (message.obj != null) { - handoverRequest = ((Bundle) message.obj) - .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); - } - - if (handoverRequest != null - && mWifiNative.responderReportNfcHandover(handoverRequest)) { - replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); - transitionTo(mGroupCreatingState); - } else { - replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class GroupCreatingState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - sendMessageDelayed(obtainMessage(GROUP_CREATING_TIMED_OUT, - ++sGroupCreatingTimeoutIndex, 0), GROUP_CREATING_WAIT_TIME_MS); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - boolean ret = HANDLED; - switch (message.what) { - case GROUP_CREATING_TIMED_OUT: - if (sGroupCreatingTimeoutIndex == message.arg1) { - if (mVerboseLoggingEnabled) logd("Group negotiation timed out"); - mWifiP2pMetrics.endConnectionEvent( - P2pConnectionEvent.CLF_TIMEOUT); - handleGroupCreationFailure(); - transitionTo(mInactiveState); - } - break; - case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - WifiP2pDevice device = (WifiP2pDevice) message.obj; - if (!mSavedPeerConfig.deviceAddress.equals(device.deviceAddress)) { - if (mVerboseLoggingEnabled) { - logd("mSavedPeerConfig " + mSavedPeerConfig.deviceAddress - + "device " + device.deviceAddress); - } - // Do the regular device lost handling - ret = NOT_HANDLED; - break; - } - // Do nothing - if (mVerboseLoggingEnabled) logd("Add device to lost list " + device); - mPeersLostDuringConnection.updateSupplicantDetails(device); - break; - case WifiP2pManager.DISCOVER_PEERS: - // Discovery will break negotiation - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, - WifiP2pManager.BUSY); - break; - case WifiP2pManager.CANCEL_CONNECT: - // Do a supplicant p2p_cancel which only cancels an ongoing - // group negotiation. This will fail for a pending provision - // discovery or for a pending user action, but at the framework - // level, we always treat cancel as succeeded and enter - // an inactive state - mWifiNative.p2pCancelConnect(); - mWifiP2pMetrics.endConnectionEvent( - P2pConnectionEvent.CLF_CANCEL); - handleGroupCreationFailure(); - transitionTo(mInactiveState); - replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); - break; - case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: - // We hit this scenario when NFC handover is invoked. - mAutonomousGroup = false; - transitionTo(mGroupNegotiationState); - break; - default: - ret = NOT_HANDLED; - } - return ret; - } - } - - class UserAuthorizingNegotiationRequestState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - if (mSavedPeerConfig.wps.setup == WpsInfo.PBC - || TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) { - notifyInvitationReceived(); - } - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - boolean ret = HANDLED; - switch (message.what) { - case PEER_CONNECTION_USER_ACCEPT: - mWifiNative.p2pStopFind(); - p2pConnectWithPinDisplay(mSavedPeerConfig); - mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); - sendPeersChangedBroadcast(); - transitionTo(mGroupNegotiationState); - break; - case PEER_CONNECTION_USER_REJECT: - if (mVerboseLoggingEnabled) { - logd("User rejected negotiation " + mSavedPeerConfig); - } - transitionTo(mInactiveState); - break; - case PEER_CONNECTION_USER_CONFIRM: - mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; - mSavedPeerConfig.groupOwnerIntent = - selectGroupOwnerIntentIfNecessary(mSavedPeerConfig); - mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP); - transitionTo(mGroupNegotiationState); - break; - default: - return NOT_HANDLED; - } - return ret; - } - - @Override - public void exit() { - // TODO: dismiss dialog if not already done - } - } - - class UserAuthorizingInviteRequestState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - notifyInvitationReceived(); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - boolean ret = HANDLED; - switch (message.what) { - case PEER_CONNECTION_USER_ACCEPT: - mWifiNative.p2pStopFind(); - if (!reinvokePersistentGroup(mSavedPeerConfig)) { - // Do negotiation when persistence fails - p2pConnectWithPinDisplay(mSavedPeerConfig); - } - mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); - sendPeersChangedBroadcast(); - transitionTo(mGroupNegotiationState); - break; - case PEER_CONNECTION_USER_REJECT: - if (mVerboseLoggingEnabled) { - logd("User rejected invitation " + mSavedPeerConfig); - } - transitionTo(mInactiveState); - break; - default: - return NOT_HANDLED; - } - return ret; - } - - @Override - public void exit() { - // TODO: dismiss dialog if not already done - } - } - - class ProvisionDiscoveryState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - WifiP2pProvDiscEvent provDisc = null; - WifiP2pDevice device = null; - switch (message.what) { - case WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT: - if (message.obj == null) { - Log.e(TAG, "Invalid argument(s)"); - break; - } - provDisc = (WifiP2pProvDiscEvent) message.obj; - device = provDisc.device; - if (device != null - && !device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { - break; - } - if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) { - if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig); - p2pConnectWithPinDisplay(mSavedPeerConfig); - transitionTo(mGroupNegotiationState); - } - break; - case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - provDisc = (WifiP2pProvDiscEvent) message.obj; - device = provDisc.device; - if (device != null - && !device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { - break; - } - if (mSavedPeerConfig.wps.setup == WpsInfo.KEYPAD) { - if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig); - // we already have the pin - if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) { - p2pConnectWithPinDisplay(mSavedPeerConfig); - transitionTo(mGroupNegotiationState); - } else { - mJoinExistingGroup = false; - transitionTo(mUserAuthorizingNegotiationRequestState); - } - } - break; - case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - provDisc = (WifiP2pProvDiscEvent) message.obj; - device = provDisc.device; - if (device == null) { - Log.e(TAG, "Invalid device"); - break; - } - if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { - break; - } - if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) { - if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig); - mSavedPeerConfig.wps.pin = provDisc.pin; - p2pConnectWithPinDisplay(mSavedPeerConfig); - notifyInvitationSent(provDisc.pin, device.deviceAddress); - transitionTo(mGroupNegotiationState); - } - break; - case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: - loge("provision discovery failed"); - mWifiP2pMetrics.endConnectionEvent( - P2pConnectionEvent.CLF_PROV_DISC_FAIL); - handleGroupCreationFailure(); - transitionTo(mInactiveState); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class GroupNegotiationState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - // We ignore these right now, since we get a GROUP_STARTED notification - // afterwards - case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: - case WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT: - if (mVerboseLoggingEnabled) logd(getName() + " go success"); - break; - case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - mGroup = (WifiP2pGroup) message.obj; - if (mVerboseLoggingEnabled) logd(getName() + " group started"); - if (mGroup.isGroupOwner() - && EMPTY_DEVICE_ADDRESS.equals(mGroup.getOwner().deviceAddress)) { - // wpa_supplicant doesn't set own device address to go_dev_addr. - mGroup.getOwner().deviceAddress = mThisDevice.deviceAddress; - } - if (mGroup.getNetworkId() == WifiP2pGroup.NETWORK_ID_PERSISTENT) { - // update cache information and set network id to mGroup. - updatePersistentNetworks(RELOAD); - String devAddr = mGroup.getOwner().deviceAddress; - mGroup.setNetworkId(mGroups.getNetworkId(devAddr, - mGroup.getNetworkName())); - } - - if (mGroup.isGroupOwner()) { - // Setting an idle time out on GO causes issues with certain scenarios - // on clients where it can be off-channel for longer and with the power - // save modes used. - // TODO: Verify multi-channel scenarios and supplicant behavior are - // better before adding a time out in future - // Set group idle timeout of 10 sec, to avoid GO beaconing incase of any - // failure during 4-way Handshake. - if (!mAutonomousGroup) { - mWifiNative.setP2pGroupIdle(mGroup.getInterface(), - GROUP_IDLE_TIME_S); - } - // {@link com.android.server.connectivity.Tethering} listens to - // {@link WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION} - // events and takes over the DHCP server management automatically. - // Because tethering service introduces random IP range, P2P could not - // hard-coded group owner IP and needs to wait for tethering completion. - // As a result, P2P sends a unicast intent to tether service to trigger - // the whole flow before entering GroupCreatedState. - setWifiP2pInfoOnGroupFormation(null); - String tetheringServicePackage = findTetheringServicePackage(); - if (!TextUtils.isEmpty(tetheringServicePackage)) { - sendP2pTetherRequestBroadcast(tetheringServicePackage); - } else { - loge("No valid tethering service, remove " + mGroup); - mWifiNative.p2pGroupRemove(mGroup.getInterface()); - } - break; - } - - mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S); - startIpClient(mGroup.getInterface(), getHandler()); - WifiP2pDevice groupOwner = mGroup.getOwner(); - WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress); - if (peer != null) { - // update group owner details with peer details found at discovery - groupOwner.updateSupplicantDetails(peer); - mPeers.updateStatus(groupOwner.deviceAddress, - WifiP2pDevice.CONNECTED); - sendPeersChangedBroadcast(); - } else { - // A supplicant bug can lead to reporting an invalid - // group owner address (all zeroes) at times. Avoid a - // crash, but continue group creation since it is not - // essential. - logw("Unknown group owner " + groupOwner); - } - transitionTo(mGroupCreatedState); - break; - case GROUP_OWNER_TETHER_READY: - if (mGroup != null && mGroup.isGroupOwner()) { - Log.d(TAG, "tether " + mGroup.getInterface() + " ready"); - transitionTo(mGroupCreatedState); - } - break; - case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: - P2pStatus status = (P2pStatus) message.obj; - if (status == P2pStatus.NO_COMMON_CHANNEL) { - transitionTo(mFrequencyConflictState); - break; - } - // continue with group removal handling - case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: - if (mVerboseLoggingEnabled) logd(getName() + " go failure"); - mWifiP2pMetrics.endConnectionEvent( - P2pConnectionEvent.CLF_UNKNOWN); - handleGroupCreationFailure(); - transitionTo(mInactiveState); - break; - case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: - // A group formation failure is always followed by - // a group removed event. Flushing things at group formation - // failure causes supplicant issues. Ignore right now. - status = (P2pStatus) message.obj; - if (status == P2pStatus.NO_COMMON_CHANNEL) { - transitionTo(mFrequencyConflictState); - break; - } - break; - case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: - status = (P2pStatus) message.obj; - if (status == P2pStatus.SUCCESS) { - // invocation was succeeded. - // wait P2P_GROUP_STARTED_EVENT. - break; - } - loge("Invitation result " + status); - if (status == P2pStatus.UNKNOWN_P2P_GROUP) { - // target device has already removed the credential. - // So, remove this credential accordingly. - int netId = mSavedPeerConfig.netId; - if (netId >= 0) { - if (mVerboseLoggingEnabled) { - logd("Remove unknown client from the list"); - } - removeClientFromList(netId, mSavedPeerConfig.deviceAddress, true); - } - - // Reinvocation has failed, try group negotiation - mSavedPeerConfig.netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; - p2pConnectWithPinDisplay(mSavedPeerConfig); - } else if (status == P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE) { - - // Devices setting persistent_reconnect to 0 in wpa_supplicant - // always defer the invocation request and return - // "information is currently unavailable" error. - // So, try another way to connect for interoperability. - mSavedPeerConfig.netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; - p2pConnectWithPinDisplay(mSavedPeerConfig); - } else if (status == P2pStatus.NO_COMMON_CHANNEL) { - transitionTo(mFrequencyConflictState); - } else { - mWifiP2pMetrics.endConnectionEvent( - P2pConnectionEvent.CLF_INVITATION_FAIL); - handleGroupCreationFailure(); - transitionTo(mInactiveState); - } - break; - case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: - case WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT: - // Group owner needs to wait for tethering completion before - // moving to GroupCreatedState. If native layer reports STA event - // earlier, defer it. - if (mGroup != null && mGroup.isGroupOwner()) { - deferMessage(message); - break; - } - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class FrequencyConflictState extends State { - private AlertDialog mFrequencyConflictDialog; - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - notifyFrequencyConflict(); - } - - private void notifyFrequencyConflict() { - logd("Notify frequency conflict"); - Resources r = mContext.getResources(); - - AlertDialog dialog = new AlertDialog.Builder(mContext) - .setMessage(r.getString(R.string.wifi_p2p_frequency_conflict_message, - getDeviceName(mSavedPeerConfig.deviceAddress))) - .setPositiveButton(r.getString(R.string.dlg_ok), new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - sendMessage(DROP_WIFI_USER_ACCEPT); - } - }) - .setNegativeButton(r.getString(R.string.decline), new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - sendMessage(DROP_WIFI_USER_REJECT); - } - }) - .setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface arg0) { - sendMessage(DROP_WIFI_USER_REJECT); - } - }) - .create(); - dialog.setCanceledOnTouchOutside(false); - - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - dialog.getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); - dialog.show(); - mFrequencyConflictDialog = dialog; - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: - case WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT: - loge(getName() + "group sucess during freq conflict!"); - break; - case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: - loge(getName() + "group started after freq conflict, handle anyway"); - deferMessage(message); - transitionTo(mGroupNegotiationState); - break; - case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: - case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: - case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: - // Ignore failures since we retry again - break; - case DROP_WIFI_USER_REJECT: - // User rejected dropping wifi in favour of p2p - mWifiP2pMetrics.endConnectionEvent( - P2pConnectionEvent.CLF_USER_REJECT); - handleGroupCreationFailure(); - transitionTo(mInactiveState); - break; - case DROP_WIFI_USER_ACCEPT: - // User accepted dropping wifi in favour of p2p - if (mWifiChannel != null) { - mWifiChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST, 1); - } else { - loge("DROP_WIFI_USER_ACCEPT message received when WifiChannel is null"); - } - mTemporarilyDisconnectedWifi = true; - break; - case DISCONNECT_WIFI_RESPONSE: - // Got a response from ClientModeImpl, retry p2p - if (mVerboseLoggingEnabled) { - logd(getName() + "Wifi disconnected, retry p2p"); - } - transitionTo(mInactiveState); - sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - public void exit() { - if (mFrequencyConflictDialog != null) mFrequencyConflictDialog.dismiss(); - } - } - - class GroupCreatedState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - // Once connected, peer config details are invalid - mSavedPeerConfig.invalidate(); - mDetailedState = NetworkInfo.DetailedState.CONNECTED; - - updateThisDevice(WifiP2pDevice.CONNECTED); - - // DHCP server has already been started if I am a group owner - if (mGroup.isGroupOwner()) { - Inet4Address addr = getInterfaceAddress(mGroup.getInterface()); - if (addr != null) { - setWifiP2pInfoOnGroupFormation(addr.getHostAddress()); - Log.d(TAG, "Group owner address: " + addr.getHostAddress() - + " at " + mGroup.getInterface()); - } else { - mWifiNative.p2pGroupRemove(mGroup.getInterface()); - } - } - - // In case of a negotiation group, connection changed is sent - // after a client joins. For autonomous, send now - if (mAutonomousGroup) { - sendP2pConnectionChangedBroadcast(); - } - - mWifiP2pMetrics.endConnectionEvent( - P2pConnectionEvent.CLF_NONE); - mWifiP2pMetrics.startGroupEvent(mGroup); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - WifiP2pDevice device = null; - String deviceAddress = null; - switch (message.what) { - case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - device = (WifiP2pDevice) message.obj; - deviceAddress = device.deviceAddress; - // Clear timeout that was set when group was started. - mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); - if (deviceAddress != null) { - if (mPeers.get(deviceAddress) != null) { - mGroup.addClient(mPeers.get(deviceAddress)); - } else { - mGroup.addClient(deviceAddress); - } - mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED); - if (mVerboseLoggingEnabled) logd(getName() + " ap sta connected"); - sendPeersChangedBroadcast(); - mWifiP2pMetrics.updateGroupEvent(mGroup); - } else { - loge("Connect on null device address, ignore"); - } - sendP2pConnectionChangedBroadcast(); - break; - case WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - break; - } - device = (WifiP2pDevice) message.obj; - deviceAddress = device.deviceAddress; - if (deviceAddress != null) { - mPeers.updateStatus(deviceAddress, WifiP2pDevice.AVAILABLE); - if (mGroup.removeClient(deviceAddress)) { - if (mVerboseLoggingEnabled) logd("Removed client " + deviceAddress); - if (!mAutonomousGroup && mGroup.isClientListEmpty()) { - logd("Client list empty, remove non-persistent p2p group"); - mWifiNative.p2pGroupRemove(mGroup.getInterface()); - // We end up sending connection changed broadcast - // when this happens at exit() - } else { - // Notify when a client disconnects from group - sendP2pConnectionChangedBroadcast(); - } - mWifiP2pMetrics.updateGroupEvent(mGroup); - } else { - if (mVerboseLoggingEnabled) { - logd("Failed to remove client " + deviceAddress); - } - for (WifiP2pDevice c : mGroup.getClientList()) { - if (mVerboseLoggingEnabled) logd("client " + c.deviceAddress); - } - } - sendPeersChangedBroadcast(); - if (mVerboseLoggingEnabled) logd(getName() + " ap sta disconnected"); - } else { - loge("Disconnect on unknown device: " + device); - } - break; - case IPC_PRE_DHCP_ACTION: - mWifiNative.setP2pPowerSave(mGroup.getInterface(), false); - try { - mIpClient.completedPreDhcpAction(); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - break; - case IPC_POST_DHCP_ACTION: - mWifiNative.setP2pPowerSave(mGroup.getInterface(), true); - break; - case IPC_DHCP_RESULTS: - mDhcpResultsParcelable = (DhcpResultsParcelable) message.obj; - if (mDhcpResultsParcelable == null) { - break; - } - - if (mVerboseLoggingEnabled) { - logd("mDhcpResultsParcelable: " + mDhcpResultsParcelable); - } - setWifiP2pInfoOnGroupFormation(mDhcpResultsParcelable.serverAddress); - sendP2pConnectionChangedBroadcast(); - try { - final String ifname = mGroup.getInterface(); - if (mDhcpResultsParcelable != null) { - mNetdWrapper.addInterfaceToLocalNetwork( - ifname, - mDhcpResultsParcelable.baseConfiguration.getRoutes(ifname)); - } - } catch (Exception e) { - loge("Failed to add iface to local network " + e); - } - break; - case IPC_PROVISIONING_SUCCESS: - break; - case IPC_PROVISIONING_FAILURE: - loge("IP provisioning failed"); - mWifiNative.p2pGroupRemove(mGroup.getInterface()); - break; - case WifiP2pManager.REMOVE_GROUP: - if (mVerboseLoggingEnabled) logd(getName() + " remove group"); - if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) { - transitionTo(mOngoingGroupRemovalState); - replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); - } else { - handleGroupRemoved(); - transitionTo(mInactiveState); - replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, - WifiP2pManager.ERROR); - } - break; - case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: - // We do not listen to NETWORK_DISCONNECTION_EVENT for group removal - // handling since supplicant actually tries to reconnect after a temporary - // disconnect until group idle time out. Eventually, a group removal event - // will come when group has been removed. - // - // When there are connectivity issues during temporary disconnect, - // the application will also just remove the group. - // - // Treating network disconnection as group removal causes race conditions - // since supplicant would still maintain the group at that stage. - if (mVerboseLoggingEnabled) logd(getName() + " group removed"); - handleGroupRemoved(); - transitionTo(mInactiveState); - break; - case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: - if (message.obj == null) { - Log.e(TAG, "Illegal argument(s)"); - return NOT_HANDLED; - } - device = (WifiP2pDevice) message.obj; - if (!mGroup.contains(device)) { - // do the regular device lost handling - return NOT_HANDLED; - } - // Device loss for a connected device indicates - // it is not in discovery any more - if (mVerboseLoggingEnabled) logd("Add device to lost list " + device); - mPeersLostDuringConnection.updateSupplicantDetails(device); - return HANDLED; - case DISABLE_P2P: - sendMessage(WifiP2pManager.REMOVE_GROUP); - deferMessage(message); - break; - // This allows any client to join the GO during the - // WPS window - case WifiP2pManager.START_WPS: - WpsInfo wps = (WpsInfo) message.obj; - if (wps == null) { - replyToMessage(message, WifiP2pManager.START_WPS_FAILED); - break; - } - boolean ret = true; - if (wps.setup == WpsInfo.PBC) { - ret = mWifiNative.startWpsPbc(mGroup.getInterface(), null); - } else { - if (wps.pin == null) { - String pin = mWifiNative.startWpsPinDisplay( - mGroup.getInterface(), null); - try { - Integer.parseInt(pin); - notifyInvitationSent(pin, "any"); - } catch (NumberFormatException ignore) { - ret = false; - } - } else { - ret = mWifiNative.startWpsPinKeypad(mGroup.getInterface(), - wps.pin); - } - } - replyToMessage(message, ret ? WifiP2pManager.START_WPS_SUCCEEDED : - WifiP2pManager.START_WPS_FAILED); - break; - case WifiP2pManager.CONNECT: - if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( - getCallingPkgName(message.sendingUid, message.replyTo), - getCallingFeatureId(message.sendingUid, message.replyTo), - message.sendingUid, false)) { - replyToMessage(message, WifiP2pManager.CONNECT_FAILED); - // remain at this state. - break; - } - WifiP2pConfig config = (WifiP2pConfig) message.obj; - if (isConfigInvalid(config)) { - loge("Dropping connect request " + config); - replyToMessage(message, WifiP2pManager.CONNECT_FAILED); - break; - } - logd("Inviting device : " + config.deviceAddress); - mSavedPeerConfig = config; - if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) { - mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED); - sendPeersChangedBroadcast(); - replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.CONNECT_FAILED, - WifiP2pManager.ERROR); - } - // TODO: figure out updating the status to declined - // when invitation is rejected - break; - case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: - P2pStatus status = (P2pStatus) message.obj; - if (status == P2pStatus.SUCCESS) { - // invocation was succeeded. - break; - } - loge("Invitation result " + status); - if (status == P2pStatus.UNKNOWN_P2P_GROUP) { - // target device has already removed the credential. - // So, remove this credential accordingly. - int netId = mGroup.getNetworkId(); - if (netId >= 0) { - if (mVerboseLoggingEnabled) { - logd("Remove unknown client from the list"); - } - removeClientFromList(netId, mSavedPeerConfig.deviceAddress, false); - // try invitation. - sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig); - } - } - break; - case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: - case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: - case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: - WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; - mSavedPeerConfig = new WifiP2pConfig(); - if (provDisc != null && provDisc.device != null) { - mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress; - } - if (message.what == WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) { - mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; - } else if (message.what == WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) { - mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; - mSavedPeerConfig.wps.pin = provDisc.pin; - } else { - mSavedPeerConfig.wps.setup = WpsInfo.PBC; - } - - // According to section 3.2.3 in SPEC, only GO can handle group join. - // Multiple groups is not supported, ignore this discovery for GC. - if (mGroup.isGroupOwner()) { - transitionTo(mUserAuthorizingJoinState); - } else { - if (mVerboseLoggingEnabled) logd("Ignore provision discovery for GC"); - } - break; - case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: - loge("Duplicate group creation event notice, ignore"); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - public void exit() { - // The group is still there and handling incoming request, - // no need to update P2P connection information. - if (mGroup != null) return; - - mWifiP2pMetrics.endGroupEvent(); - updateThisDevice(WifiP2pDevice.AVAILABLE); - resetWifiP2pInfo(); - mDetailedState = NetworkInfo.DetailedState.DISCONNECTED; - sendP2pConnectionChangedBroadcast(); - } - } - - class UserAuthorizingJoinState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - notifyInvitationReceived(); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: - case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: - case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: - // Ignore more client requests - break; - case PEER_CONNECTION_USER_ACCEPT: - // Stop discovery to avoid failure due to channel switch - mWifiNative.p2pStopFind(); - if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) { - mWifiNative.startWpsPbc(mGroup.getInterface(), null); - } else { - mWifiNative.startWpsPinKeypad(mGroup.getInterface(), - mSavedPeerConfig.wps.pin); - } - transitionTo(mGroupCreatedState); - break; - case PEER_CONNECTION_USER_REJECT: - if (mVerboseLoggingEnabled) logd("User rejected incoming request"); - transitionTo(mGroupCreatedState); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - @Override - public void exit() { - // TODO: dismiss dialog if not already done - } - } - - class OngoingGroupRemovalState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) logd(getName()); - } - - @Override - public boolean processMessage(Message message) { - if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - switch (message.what) { - // Group removal ongoing. Multiple calls - // end up removing persisted network. Do nothing. - case WifiP2pManager.REMOVE_GROUP: - replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); - break; - // Parent state will transition out of this state - // when removal is complete - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - super.dump(fd, pw, args); - pw.println("mWifiP2pInfo " + mWifiP2pInfo); - pw.println("mGroup " + mGroup); - pw.println("mSavedPeerConfig " + mSavedPeerConfig); - pw.println("mGroups" + mGroups); - pw.println(); - } - - // Check & re-enable P2P if needed. - // P2P interface will be created if all of the below are true: - // a) Wifi is enabled. - // b) HAL (HIDL) interface is available. - // c) There is atleast 1 client app which invoked initialize(). - private void checkAndReEnableP2p() { - boolean isHalInterfaceAvailable = isHalInterfaceAvailable(); - Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled + ", P2P Interface availability=" - + isHalInterfaceAvailable + ", Number of clients=" - + mDeathDataByBinder.size()); - if (mIsWifiEnabled && isHalInterfaceAvailable - && !mDeathDataByBinder.isEmpty()) { - sendMessage(ENABLE_P2P); - } - } - - // Ignore judgement if the device do not support HAL (HIDL) interface - private boolean isHalInterfaceAvailable() { - return mWifiNative.isHalInterfaceSupported() ? mIsHalInterfaceAvailable : true; - } - - private void checkAndSendP2pStateChangedBroadcast() { - boolean isHalInterfaceAvailable = isHalInterfaceAvailable(); - Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled + ", P2P Interface availability=" - + isHalInterfaceAvailable); - sendP2pStateChangedBroadcast(mIsWifiEnabled && isHalInterfaceAvailable); - } - - private void sendP2pStateChangedBroadcast(boolean enabled) { - final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - if (enabled) { - intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, - WifiP2pManager.WIFI_P2P_STATE_ENABLED); - } else { - intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, - WifiP2pManager.WIFI_P2P_STATE_DISABLED); - } - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private void sendP2pDiscoveryChangedBroadcast(boolean started) { - if (mDiscoveryStarted == started) return; - mDiscoveryStarted = started; - - if (mVerboseLoggingEnabled) logd("discovery change broadcast " + started); - - final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, started - ? WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED : - WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private void sendBroadcastMultiplePermissions(Intent intent) { - Context context = mContext.createContextAsUser(UserHandle.ALL, 0); - String[] permissions = RECEIVER_PERMISSIONS_FOR_BROADCAST; - if (!mWifiPermissionsUtil.isLocationModeEnabled()) { - permissions = RECEIVER_PERMISSIONS_FOR_BROADCAST_LOCATION_OFF; - } - context.sendBroadcastWithMultiplePermissions( - intent, permissions); - } - - private void sendThisDeviceChangedBroadcast() { - final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, - eraseOwnDeviceAddress(mThisDevice)); - sendBroadcastMultiplePermissions(intent); - } - - private void sendPeersChangedBroadcast() { - final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); - intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, new WifiP2pDeviceList(mPeers)); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - sendBroadcastMultiplePermissions(intent); - } - - private void sendP2pConnectionChangedBroadcast() { - if (mVerboseLoggingEnabled) logd("sending p2p connection changed broadcast"); - Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo)); - intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo()); - intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup)); - sendBroadcastMultiplePermissions(intent); - if (mWifiChannel != null) { - mWifiChannel.sendMessage(WifiP2pServiceImpl.P2P_CONNECTION_CHANGED, - makeNetworkInfo()); - } else { - loge("sendP2pConnectionChangedBroadcast(): WifiChannel is null"); - } - } - - private boolean isPackageExisted(String pkgName) { - PackageManager pm = mContext.getPackageManager(); - try { - PackageInfo info = pm.getPackageInfo(pkgName, PackageManager.GET_META_DATA); - } catch (PackageManager.NameNotFoundException e) { - return false; - } - return true; - } - - private String findTetheringServicePackage() { - ArrayList<String> possiblePackageNames = new ArrayList<>(); - // AOSP - possiblePackageNames.add("com.android.networkstack.tethering"); - // mainline release - possiblePackageNames.add("com.google.android.networkstack.tethering"); - // Android Go - possiblePackageNames.add("com.android.networkstack.tethering.inprocess"); - - for (String pkgName: possiblePackageNames) { - if (isPackageExisted(pkgName)) { - Log.d(TAG, "Tethering service package: " + pkgName); - return pkgName; - } - } - Log.w(TAG, "Cannot find tethering service package!"); - return null; - } - - private void sendP2pTetherRequestBroadcast(String tetheringServicePackage) { - if (mVerboseLoggingEnabled) logd("sending p2p tether request broadcast"); - - Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); - intent.setPackage(tetheringServicePackage); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo)); - intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo()); - intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup)); - - sendBroadcastMultiplePermissions(intent); - } - - private void sendP2pPersistentGroupsChangedBroadcast() { - if (mVerboseLoggingEnabled) logd("sending p2p persistent groups changed broadcast"); - Intent intent = new Intent(WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - - private void addRowToDialog(ViewGroup group, int stringId, String value) { - Resources r = mContext.getResources(); - View row = LayoutInflater.from(mContext).cloneInContext(mContext) - .inflate(R.layout.wifi_p2p_dialog_row, group, false); - ((TextView) row.findViewById(R.id.name)).setText(r.getString(stringId)); - ((TextView) row.findViewById(R.id.value)).setText(value); - group.addView(row); - } - - private void notifyInvitationSent(String pin, String peerAddress) { - Resources r = mContext.getResources(); - - final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) - .inflate(R.layout.wifi_p2p_dialog, null); - - ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info); - addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress)); - addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin); - - AlertDialog dialog = new AlertDialog.Builder(mContext) - .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title)) - .setView(textEntryView) - .setPositiveButton(r.getString(R.string.ok), null) - .create(); - dialog.setCanceledOnTouchOutside(false); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - dialog.getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); - dialog.show(); - } - - private void notifyP2pProvDiscShowPinRequest(String pin, String peerAddress) { - Resources r = mContext.getResources(); - final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) - .inflate(R.layout.wifi_p2p_dialog, null); - - ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info); - addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress)); - addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin); - - AlertDialog dialog = new AlertDialog.Builder(mContext) - .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title)) - .setView(textEntryView) - .setPositiveButton(r.getString(R.string.accept), new OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - sendMessage(PEER_CONNECTION_USER_CONFIRM); - } - }) - .create(); - dialog.setCanceledOnTouchOutside(false); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - dialog.getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); - dialog.show(); - } - - private void notifyInvitationReceived() { - Resources r = mContext.getResources(); - final WpsInfo wps = mSavedPeerConfig.wps; - final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) - .inflate(R.layout.wifi_p2p_dialog, null); - - ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info); - addRowToDialog(group, R.string.wifi_p2p_from_message, getDeviceName( - mSavedPeerConfig.deviceAddress)); - - final EditText pin = (EditText) textEntryView.findViewById(R.id.wifi_p2p_wps_pin); - - AlertDialog dialog = new AlertDialog.Builder(mContext) - .setTitle(r.getString(R.string.wifi_p2p_invitation_to_connect_title)) - .setView(textEntryView) - .setPositiveButton(r.getString(R.string.accept), new OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if (wps.setup == WpsInfo.KEYPAD) { - mSavedPeerConfig.wps.pin = pin.getText().toString(); - } - if (mVerboseLoggingEnabled) { - logd(getName() + " accept invitation " + mSavedPeerConfig); - } - sendMessage(PEER_CONNECTION_USER_ACCEPT); - } - }) - .setNegativeButton(r.getString(R.string.decline), new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (mVerboseLoggingEnabled) logd(getName() + " ignore connect"); - sendMessage(PEER_CONNECTION_USER_REJECT); - } - }) - .setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface arg0) { - if (mVerboseLoggingEnabled) logd(getName() + " ignore connect"); - sendMessage(PEER_CONNECTION_USER_REJECT); - } - }) - .create(); - dialog.setCanceledOnTouchOutside(false); - - // make the enter pin area or the display pin area visible - switch (wps.setup) { - case WpsInfo.KEYPAD: - if (mVerboseLoggingEnabled) logd("Enter pin section visible"); - textEntryView.findViewById(R.id.enter_pin_section).setVisibility(View.VISIBLE); - break; - case WpsInfo.DISPLAY: - if (mVerboseLoggingEnabled) logd("Shown pin section visible"); - addRowToDialog(group, R.string.wifi_p2p_show_pin_message, wps.pin); - break; - default: - break; - } - - if ((r.getConfiguration().uiMode & Configuration.UI_MODE_TYPE_APPLIANCE) - == Configuration.UI_MODE_TYPE_APPLIANCE) { - // For appliance devices, add a key listener which accepts. - dialog.setOnKeyListener(new DialogInterface.OnKeyListener() { - - @Override - public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { - // TODO: make the actual key come from a config value. - if (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { - sendMessage(PEER_CONNECTION_USER_ACCEPT); - dialog.dismiss(); - return true; - } - return false; - } - }); - // TODO: add timeout for this dialog. - // TODO: update UI in appliance mode to tell user what to do. - } - - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - dialog.getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); - dialog.show(); - } - - /** - * This method unifies the persisent group list, cleans up unused - * networks and if required, updates corresponding broadcast receivers - * @param reload if true, reload the group list from scratch - * and send broadcast message with fresh list - */ - private void updatePersistentNetworks(boolean reload) { - if (reload) mGroups.clear(); - - // Save in all cases, including when reload was requested, but - // no network has been found. - if (mWifiNative.p2pListNetworks(mGroups) || reload) { - for (WifiP2pGroup group : mGroups.getGroupList()) { - if (group.getOwner() == null) { - Log.d(TAG, "group.getOwner() null"); - continue; - } - if (Objects.equals(mThisDevice.deviceAddress, group.getOwner().deviceAddress)) { - group.setOwner(mThisDevice); - } - } - mWifiNative.saveConfig(); - mWifiP2pMetrics.updatePersistentGroup(mGroups); - sendP2pPersistentGroupsChangedBroadcast(); - } - } - - /** - * A config is valid if it has a peer address that has already been - * discovered - * @param WifiP2pConfig config to be validated - * @return true if it is invalid, false otherwise - */ - private boolean isConfigInvalid(WifiP2pConfig config) { - if (config == null) return true; - if (TextUtils.isEmpty(config.deviceAddress)) return true; - if (mPeers.get(config.deviceAddress) == null) return true; - return false; - } - - /** - * Check the network name complies standard SSID naming rules. - * - * The network name of a group is also the broadcasting SSID, - * as a result, the network name must complies standard SSID naming - * rules. - */ - private boolean isValidNetworkName(String networkName) { - if (TextUtils.isEmpty(networkName)) return false; - - byte[] ssidBytes = networkName.getBytes(StandardCharsets.UTF_8); - if (ssidBytes.length < MIN_NETWORK_NAME_BYTES) return false; - if (ssidBytes.length > MAX_NETWORK_NAME_BYTES) return false; - - return true; - } - - /** - * A config is valid as a group if it has network name and passphrase. - * Supplicant can construct a group on the fly for creating a group with specified config - * or join a group without negotiation and WPS. - * @param WifiP2pConfig config to be validated - * @return true if it is valid, false otherwise - */ - private boolean isConfigValidAsGroup(WifiP2pConfig config) { - if (config == null) return false; - if (TextUtils.isEmpty(config.deviceAddress)) return false; - if (isValidNetworkName(config.networkName) - && !TextUtils.isEmpty(config.passphrase)) { - return true; - } - - return false; - } - - private WifiP2pDevice fetchCurrentDeviceDetails(WifiP2pConfig config) { - if (config == null) return null; - // Fetch & update group capability from supplicant on the device - int gc = mWifiNative.getGroupCapability(config.deviceAddress); - // TODO: The supplicant does not provide group capability changes as an event. - // Having it pushed as an event would avoid polling for this information right - // before a connection - mPeers.updateGroupCapability(config.deviceAddress, gc); - return mPeers.get(config.deviceAddress); - } - - /** - * Erase the MAC address of our interface if it is present in a given device, to prevent - * apps from having access to persistent identifiers. - * - * @param device a device possibly having the same physical address as the wlan interface. - * @return a copy of the input, possibly with the device address erased. - */ - private WifiP2pDevice eraseOwnDeviceAddress(WifiP2pDevice device) { - if (device == null) { - return null; - } - WifiP2pDevice result = new WifiP2pDevice(device); - if (device.deviceAddress != null - && mThisDevice.deviceAddress != null - && device.deviceAddress.length() > 0 - && mThisDevice.deviceAddress.equals(device.deviceAddress)) { - result.deviceAddress = ANONYMIZED_DEVICE_ADDRESS; - } - return result; - } - - /** - * Erase the MAC address of our interface if it is set as the device address for any of the - * devices in a group. - * - * @param group a p2p group containing p2p devices. - * @return a copy of the input, with any devices corresponding to our wlan interface having - * their device address erased. - */ - private WifiP2pGroup eraseOwnDeviceAddress(WifiP2pGroup group) { - if (group == null) { - return null; - } - - WifiP2pGroup result = new WifiP2pGroup(group); - - // Create copies of the clients so they're not shared with the original object. - for (WifiP2pDevice originalDevice : group.getClientList()) { - result.removeClient(originalDevice); - result.addClient(eraseOwnDeviceAddress(originalDevice)); - } - - WifiP2pDevice groupOwner = group.getOwner(); - result.setOwner(eraseOwnDeviceAddress(groupOwner)); - - return result; - } - - /** - * Erase the MAC address of our interface if it is present in a given device, to prevent - * apps from having access to persistent identifiers. If the requesting party holds the - * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. - * - * @param device a device possibly having the same physical address as the wlan interface. - * @param uid the user id of the app that requested the information. - * @return a copy of the input, possibly with the device address erased. - */ - private WifiP2pDevice maybeEraseOwnDeviceAddress(WifiP2pDevice device, int uid) { - if (device == null) { - return null; - } - if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { - // Calling app holds the LOCAL_MAC_ADDRESS permission, and is allowed to see this - // device's MAC. - return new WifiP2pDevice(device); - } else { - return eraseOwnDeviceAddress(device); - } - } - - /** - * Erase the MAC address of our interface if it is set as the device address for any of the - * devices in a group. If the requesting party holds the - * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. - * - * @param group a p2p group containing p2p devices. - * @param uid the user id of the app that requested the information. - * @return a copy of the input, with any devices corresponding to our wlan interface having - * their device address erased. If the requesting app holds the LOCAL_MAC_ADDRESS - * permission, this method returns a copy of the input. - */ - private WifiP2pGroup maybeEraseOwnDeviceAddress(WifiP2pGroup group, int uid) { - if (group == null) { - return null; - } - if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { - // Calling app holds the LOCAL_MAC_ADDRESS permission, and is allowed to see this - // device's MAC. - return new WifiP2pGroup(group); - } else { - return eraseOwnDeviceAddress(group); - } - } - - /** - * Erase the MAC address of our interface if it is set as the device address for any of the - * devices in a list of groups. If the requesting party holds the - * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. - * - * @param groupList a list of p2p groups containing p2p devices. - * @param uid the user id of the app that requested the information. - * @return a copy of the input, with any devices corresponding to our wlan interface having - * their device address erased. If the requesting app holds the LOCAL_MAC_ADDRESS - * permission, this method returns a copy of the input. - */ - private WifiP2pGroupList maybeEraseOwnDeviceAddress(WifiP2pGroupList groupList, int uid) { - if (groupList == null) { - return null; - } - WifiP2pGroupList result = new WifiP2pGroupList(); - for (WifiP2pGroup group : groupList.getGroupList()) { - result.add(maybeEraseOwnDeviceAddress(group, uid)); - } - return result; - } - - /** - * Start a p2p group negotiation and display pin if necessary - * @param config for the peer - */ - private void p2pConnectWithPinDisplay(WifiP2pConfig config) { - if (config == null) { - Log.e(TAG, "Illegal argument(s)"); - return; - } - WifiP2pDevice dev = fetchCurrentDeviceDetails(config); - if (dev == null) { - Log.e(TAG, "Invalid device"); - return; - } - config.groupOwnerIntent = selectGroupOwnerIntentIfNecessary(config); - String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner()); - try { - Integer.parseInt(pin); - notifyInvitationSent(pin, config.deviceAddress); - } catch (NumberFormatException ignore) { - // do nothing if p2pConnect did not return a pin - } - } - - /** - * Reinvoke a persistent group. - * - * @param config for the peer - * @return true on success, false on failure - */ - private boolean reinvokePersistentGroup(WifiP2pConfig config) { - if (config == null) { - Log.e(TAG, "Illegal argument(s)"); - return false; - } - WifiP2pDevice dev = fetchCurrentDeviceDetails(config); - if (dev == null) { - Log.e(TAG, "Invalid device"); - return false; - } - boolean join = dev.isGroupOwner(); - String ssid = mWifiNative.p2pGetSsid(dev.deviceAddress); - if (mVerboseLoggingEnabled) logd("target ssid is " + ssid + " join:" + join); - - if (join && dev.isGroupLimit()) { - if (mVerboseLoggingEnabled) logd("target device reaches group limit."); - - // if the target group has reached the limit, - // try group formation. - join = false; - } else if (join) { - int netId = mGroups.getNetworkId(dev.deviceAddress, ssid); - if (netId >= 0) { - // Skip WPS and start 4way handshake immediately. - if (!mWifiNative.p2pGroupAdd(netId)) { - return false; - } - return true; - } - } - - if (!join && dev.isDeviceLimit()) { - loge("target device reaches the device limit."); - return false; - } - - if (!join && dev.isInvitationCapable()) { - int netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; - if (config.netId >= 0) { - if (config.deviceAddress.equals(mGroups.getOwnerAddr(config.netId))) { - netId = config.netId; - } - } else { - netId = mGroups.getNetworkId(dev.deviceAddress); - } - if (netId < 0) { - netId = getNetworkIdFromClientList(dev.deviceAddress); - } - if (mVerboseLoggingEnabled) { - logd("netId related with " + dev.deviceAddress + " = " + netId); - } - if (netId >= 0) { - // Invoke the persistent group. - if (mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) { - // Save network id. It'll be used when an invitation - // result event is received. - config.netId = netId; - return true; - } else { - loge("p2pReinvoke() failed, update networks"); - updatePersistentNetworks(RELOAD); - return false; - } - } - } - return false; - } - - /** - * Return the network id of the group owner profile which has the p2p client with - * the specified device address in it's client list. - * If more than one persistent group of the same address is present in its client - * lists, return the first one. - * - * @param deviceAddress p2p device address. - * @return the network id. if not found, return -1. - */ - private int getNetworkIdFromClientList(String deviceAddress) { - if (deviceAddress == null) return -1; - - Collection<WifiP2pGroup> groups = mGroups.getGroupList(); - for (WifiP2pGroup group : groups) { - int netId = group.getNetworkId(); - String[] p2pClientList = getClientList(netId); - if (p2pClientList == null) continue; - for (String client : p2pClientList) { - if (deviceAddress.equalsIgnoreCase(client)) { - return netId; - } - } - } - return -1; - } - - /** - * Return p2p client list associated with the specified network id. - * @param netId network id. - * @return p2p client list. if not found, return null. - */ - private String[] getClientList(int netId) { - String p2pClients = mWifiNative.getP2pClientList(netId); - if (p2pClients == null) { - return null; - } - return p2pClients.split(" "); - } - - /** - * Remove the specified p2p client from the specified profile. - * @param netId network id of the profile. - * @param addr p2p client address to be removed. - * @param isRemovable if true, remove the specified profile if its client - * list becomes empty. - * @return whether removing the specified p2p client is successful or not. - */ - private boolean removeClientFromList(int netId, String addr, boolean isRemovable) { - StringBuilder modifiedClientList = new StringBuilder(); - String[] currentClientList = getClientList(netId); - boolean isClientRemoved = false; - if (currentClientList != null) { - for (String client : currentClientList) { - if (!client.equalsIgnoreCase(addr)) { - modifiedClientList.append(" "); - modifiedClientList.append(client); - } else { - isClientRemoved = true; - } - } - } - if (modifiedClientList.length() == 0 && isRemovable) { - // the client list is empty. so remove it. - if (mVerboseLoggingEnabled) logd("Remove unknown network"); - mGroups.remove(netId); - mWifiP2pMetrics.updatePersistentGroup(mGroups); - return true; - } - - if (!isClientRemoved) { - // specified p2p client is not found. already removed. - return false; - } - - if (mVerboseLoggingEnabled) logd("Modified client list: " + modifiedClientList); - if (modifiedClientList.length() == 0) { - modifiedClientList.append("\"\""); - } - mWifiNative.setP2pClientList(netId, modifiedClientList.toString()); - mWifiNative.saveConfig(); - return true; - } - - private Inet4Address getInterfaceAddress(String interfaceName) { - NetworkInterface iface; - try { - iface = NetworkInterface.getByName(interfaceName); - } catch (SocketException ex) { - Log.w(TAG, "Could not obtain address of network interface " - + interfaceName, ex); - return null; - } - Enumeration<InetAddress> addrs = iface.getInetAddresses(); - while (addrs.hasMoreElements()) { - InetAddress addr = addrs.nextElement(); - if (addr instanceof Inet4Address) { - return (Inet4Address) addr; - } - } - Log.w(TAG, "Could not obtain address of network interface " - + interfaceName + " because it had no IPv4 addresses."); - return null; - } - - private void setWifiP2pInfoOnGroupFormation(String serverAddress) { - InetAddress serverInetAddress = serverAddress == null - ? null - : InetAddresses.parseNumericAddress(serverAddress); - mWifiP2pInfo.groupFormed = true; - mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner(); - mWifiP2pInfo.groupOwnerAddress = serverInetAddress; - } - - private void resetWifiP2pInfo() { - mWifiP2pInfo.groupFormed = false; - mWifiP2pInfo.isGroupOwner = false; - mWifiP2pInfo.groupOwnerAddress = null; - } - - private String getDeviceName(String deviceAddress) { - WifiP2pDevice d = mPeers.get(deviceAddress); - if (d != null) { - return d.deviceName; - } - //Treat the address as name if there is no match - return deviceAddress; - } - - private String getPersistedDeviceName() { - String deviceName = mSettingsConfigStore.get(WIFI_P2P_DEVICE_NAME); - if (deviceName == null) { - // We use the 4 digits of the ANDROID_ID to have a friendly - // default that has low likelihood of collision with a peer - String id = mFrameworkFacade.getSecureStringSetting(mContext, - Settings.Secure.ANDROID_ID); - return "Android_" + id.substring(0, 4); - } - return deviceName; - } - - private boolean setAndPersistDeviceName(String devName) { - if (devName == null) return false; - - if (!mWifiNative.setDeviceName(devName)) { - loge("Failed to set device name " + devName); - return false; - } - - mThisDevice.deviceName = devName; - mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName); - - mSettingsConfigStore.put(WIFI_P2P_DEVICE_NAME, devName); - sendThisDeviceChangedBroadcast(); - return true; - } - - private boolean setWfdInfo(WifiP2pWfdInfo wfdInfo) { - boolean success; - - if (!wfdInfo.isEnabled()) { - success = mWifiNative.setWfdEnable(false); - } else { - success = - mWifiNative.setWfdEnable(true) - && mWifiNative.setWfdDeviceInfo(wfdInfo.getDeviceInfoHex()); - } - - if (!success) { - loge("Failed to set wfd properties"); - return false; - } - - mThisDevice.wfdInfo = wfdInfo; - sendThisDeviceChangedBroadcast(); - return true; - } - - private void initializeP2pSettings() { - mThisDevice.deviceName = getPersistedDeviceName(); - mThisDevice.primaryDeviceType = mContext.getResources().getString( - R.string.config_wifi_p2p_device_type); - - mWifiNative.setP2pDeviceName(mThisDevice.deviceName); - // DIRECT-XY-DEVICENAME (XY is randomly generated) - mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName); - mWifiNative.setP2pDeviceType(mThisDevice.primaryDeviceType); - // Supplicant defaults to using virtual display with display - // which refers to a remote display. Use physical_display - mWifiNative.setConfigMethods("virtual_push_button physical_display keypad"); - - mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress(); - updateThisDevice(WifiP2pDevice.AVAILABLE); - if (mVerboseLoggingEnabled) logd("DeviceAddress: " + mThisDevice.deviceAddress); - mWifiNative.p2pFlush(); - mWifiNative.p2pServiceFlush(); - mServiceTransactionId = 0; - mServiceDiscReqId = null; - - updatePersistentNetworks(RELOAD); - enableVerboseLogging(mSettingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED)); - } - - private void updateThisDevice(int status) { - mThisDevice.status = status; - sendThisDeviceChangedBroadcast(); - } - - private void handleGroupCreationFailure() { - resetWifiP2pInfo(); - mDetailedState = NetworkInfo.DetailedState.FAILED; - sendP2pConnectionChangedBroadcast(); - - // Remove only the peer we failed to connect to so that other devices discovered - // that have not timed out still remain in list for connection - boolean peersChanged = mPeers.remove(mPeersLostDuringConnection); - if (!TextUtils.isEmpty(mSavedPeerConfig.deviceAddress) - && mPeers.remove(mSavedPeerConfig.deviceAddress) != null) { - peersChanged = true; - } - if (peersChanged) { - sendPeersChangedBroadcast(); - } - - mPeersLostDuringConnection.clear(); - mServiceDiscReqId = null; - sendMessage(WifiP2pManager.DISCOVER_PEERS); - } - - private void handleGroupRemoved() { - if (mGroup.isGroupOwner()) { - // {@link com.android.server.connectivity.Tethering} listens to - // {@link WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION} - // events and takes over the DHCP server management automatically. - } else { - if (mVerboseLoggingEnabled) logd("stop IpClient"); - stopIpClient(); - try { - mNetdWrapper.removeInterfaceFromLocalNetwork(mGroup.getInterface()); - } catch (IllegalStateException e) { - loge("Failed to remove iface from local network " + e); - } - } - - try { - mNetdWrapper.clearInterfaceAddresses(mGroup.getInterface()); - } catch (Exception e) { - loge("Failed to clear addresses " + e); - } - - // Clear any timeout that was set. This is essential for devices - // that reuse the main p2p interface for a created group. - mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); - - boolean peersChanged = false; - // Remove only peers part of the group, so that other devices discovered - // that have not timed out still remain in list for connection - for (WifiP2pDevice d : mGroup.getClientList()) { - if (mPeers.remove(d)) peersChanged = true; - } - if (mPeers.remove(mGroup.getOwner())) peersChanged = true; - if (mPeers.remove(mPeersLostDuringConnection)) peersChanged = true; - if (peersChanged) { - sendPeersChangedBroadcast(); - } - - mGroup = null; - mPeersLostDuringConnection.clear(); - mServiceDiscReqId = null; - - if (mTemporarilyDisconnectedWifi) { - if (mWifiChannel != null) { - mWifiChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST, 0); - } else { - loge("handleGroupRemoved(): WifiChannel is null"); - } - mTemporarilyDisconnectedWifi = false; - } - } - - private void replyToMessage(Message msg, int what) { - // State machine initiated requests can have replyTo set to null - // indicating there are no recipients, we ignore those reply actions - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private void replyToMessage(Message msg, int what, int arg1) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - dstMsg.arg1 = arg1; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private void replyToMessage(Message msg, int what, Object obj) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - dstMsg.obj = obj; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private Message obtainMessage(Message srcMsg) { - // arg2 on the source message has a hash code that needs to - // be retained in replies see WifiP2pManager for details - Message msg = Message.obtain(); - msg.arg2 = srcMsg.arg2; - return msg; - } - - @Override - protected void logd(String s) { - Log.d(TAG, s); - } - - @Override - protected void loge(String s) { - Log.e(TAG, s); - } - - /** - * Update service discovery request to wpa_supplicant. - */ - private boolean updateSupplicantServiceRequest() { - clearSupplicantServiceRequest(); - - StringBuffer sb = new StringBuffer(); - for (ClientInfo c: mClientInfoList.values()) { - int key; - WifiP2pServiceRequest req; - for (int i = 0; i < c.mReqList.size(); i++) { - req = c.mReqList.valueAt(i); - if (req != null) { - sb.append(req.getSupplicantQuery()); - } - } - } - - if (sb.length() == 0) { - return false; - } - - mServiceDiscReqId = mWifiNative.p2pServDiscReq("00:00:00:00:00:00", sb.toString()); - if (mServiceDiscReqId == null) { - return false; - } - return true; - } - - /** - * Clear service discovery request in wpa_supplicant - */ - private void clearSupplicantServiceRequest() { - if (mServiceDiscReqId == null) return; - - mWifiNative.p2pServDiscCancelReq(mServiceDiscReqId); - mServiceDiscReqId = null; - } - - private boolean addServiceRequest(Messenger m, WifiP2pServiceRequest req) { - if (m == null || req == null) { - Log.e(TAG, "Illegal argument(s)"); - return false; - } - // TODO: We could track individual service adds separately and avoid - // having to do update all service requests on every new request - clearClientDeadChannels(); - - ClientInfo clientInfo = getClientInfo(m, false); - if (clientInfo == null) { - return false; - } - - ++mServiceTransactionId; - //The Wi-Fi p2p spec says transaction id should be non-zero - if (mServiceTransactionId == 0) ++mServiceTransactionId; - req.setTransactionId(mServiceTransactionId); - clientInfo.mReqList.put(mServiceTransactionId, req); - - if (mServiceDiscReqId == null) { - return true; - } - - return updateSupplicantServiceRequest(); - } - - private void removeServiceRequest(Messenger m, WifiP2pServiceRequest req) { - if (m == null || req == null) { - Log.e(TAG, "Illegal argument(s)"); - } - - ClientInfo clientInfo = getClientInfo(m, false); - if (clientInfo == null) { - return; - } - - // Application does not have transaction id information - // go through stored requests to remove - boolean removed = false; - for (int i = 0; i < clientInfo.mReqList.size(); i++) { - if (req.equals(clientInfo.mReqList.valueAt(i))) { - removed = true; - clientInfo.mReqList.removeAt(i); - break; - } - } - - if (!removed) return; - - if (mServiceDiscReqId == null) { - return; - } - - updateSupplicantServiceRequest(); - } - - private void clearServiceRequests(Messenger m) { - if (m == null) { - Log.e(TAG, "Illegal argument(s)"); - return; - } - - ClientInfo clientInfo = getClientInfo(m, false); - if (clientInfo == null) { - return; - } - - if (clientInfo.mReqList.size() == 0) { - return; - } - - clientInfo.mReqList.clear(); - - if (mServiceDiscReqId == null) { - return; - } - - updateSupplicantServiceRequest(); - } - - private boolean addLocalService(Messenger m, WifiP2pServiceInfo servInfo) { - if (m == null || servInfo == null) { - Log.e(TAG, "Illegal arguments"); - return false; - } - - clearClientDeadChannels(); - - ClientInfo clientInfo = getClientInfo(m, false); - - if (clientInfo == null) { - return false; - } - - if (!clientInfo.mServList.add(servInfo)) { - return false; - } - - if (!mWifiNative.p2pServiceAdd(servInfo)) { - clientInfo.mServList.remove(servInfo); - return false; - } - - return true; - } - - private void removeLocalService(Messenger m, WifiP2pServiceInfo servInfo) { - if (m == null || servInfo == null) { - Log.e(TAG, "Illegal arguments"); - return; - } - - ClientInfo clientInfo = getClientInfo(m, false); - if (clientInfo == null) { - return; - } - - mWifiNative.p2pServiceDel(servInfo); - clientInfo.mServList.remove(servInfo); - } - - private void clearLocalServices(Messenger m) { - if (m == null) { - Log.e(TAG, "Illegal argument(s)"); - return; - } - - ClientInfo clientInfo = getClientInfo(m, false); - if (clientInfo == null) { - return; - } - - for (WifiP2pServiceInfo servInfo: clientInfo.mServList) { - mWifiNative.p2pServiceDel(servInfo); - } - - clientInfo.mServList.clear(); - } - - private void clearClientInfo(Messenger m) { - // update wpa_supplicant service info - clearLocalServices(m); - clearServiceRequests(m); - // remove client from client list - ClientInfo clientInfo = mClientInfoList.remove(m); - if (clientInfo != null) { - logd("Client:" + clientInfo.mPackageName + " is removed"); - } - } - - /** - * Send the service response to the WifiP2pManager.Channel. - * @param WifiP2pServiceResponse response to service discovery - */ - private void sendServiceResponse(WifiP2pServiceResponse resp) { - if (resp == null) { - Log.e(TAG, "sendServiceResponse with null response"); - return; - } - for (ClientInfo c : mClientInfoList.values()) { - WifiP2pServiceRequest req = c.mReqList.get(resp.getTransactionId()); - if (req != null) { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.RESPONSE_SERVICE; - msg.arg1 = 0; - msg.arg2 = 0; - msg.obj = resp; - if (c.mMessenger == null) { - continue; - } - try { - c.mMessenger.send(msg); - } catch (RemoteException e) { - if (mVerboseLoggingEnabled) logd("detect dead channel"); - clearClientInfo(c.mMessenger); - return; - } - } - } - } - - /** - * We don't get notifications of clients that have gone away. - * We detect this actively when services are added and throw - * them away. - * - * TODO: This can be done better with full async channels. - */ - private void clearClientDeadChannels() { - ArrayList<Messenger> deadClients = new ArrayList<Messenger>(); - - for (ClientInfo c : mClientInfoList.values()) { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.PING; - msg.arg1 = 0; - msg.arg2 = 0; - msg.obj = null; - if (c.mMessenger == null) { - continue; - } - try { - c.mMessenger.send(msg); - } catch (RemoteException e) { - if (mVerboseLoggingEnabled) logd("detect dead channel"); - deadClients.add(c.mMessenger); - } - } - - for (Messenger m : deadClients) { - clearClientInfo(m); - } - } - - /** - * Return the specified ClientInfo. - * @param m Messenger - * @param createIfNotExist if true and the specified channel info does not exist, - * create new client info. - * @return the specified ClientInfo. - */ - private ClientInfo getClientInfo(Messenger m, boolean createIfNotExist) { - ClientInfo clientInfo = mClientInfoList.get(m); - - if (clientInfo == null && createIfNotExist) { - if (mVerboseLoggingEnabled) logd("add a new client"); - clientInfo = new ClientInfo(m); - mClientInfoList.put(m, clientInfo); - } - - return clientInfo; - } - - /** - * Enforces permissions on the caller who is requesting for P2p Peers - * @param pkgName Package name of the caller - * @param featureId Feature in the package of the caller - * @param uid of the caller - * @return WifiP2pDeviceList the peer list - */ - private WifiP2pDeviceList getPeers(String pkgName, @Nullable String featureId, int uid) { - // getPeers() is guaranteed to be invoked after Wifi Service is up - // This ensures getInstance() will return a non-null object now - if (mWifiPermissionsUtil.checkCanAccessWifiDirect(pkgName, featureId, uid, true)) { - return new WifiP2pDeviceList(mPeers); - } else { - return new WifiP2pDeviceList(); - } - } - - private void setPendingFactoryReset(boolean pending) { - mSettingsConfigStore.put(WIFI_P2P_PENDING_FACTORY_RESET, pending); - } - - private boolean isPendingFactoryReset() { - return mSettingsConfigStore.get(WIFI_P2P_PENDING_FACTORY_RESET); - } - - /** - * Enforces permissions on the caller who is requesting factory reset. - * @param pkg Bundle containing the calling package string. - * @param uid The caller uid. - */ - private boolean factoryReset(int uid) { - String pkgName = mContext.getPackageManager().getNameForUid(uid); - UserManager userManager = mWifiInjector.getUserManager(); - - if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) return false; - - if (userManager.hasUserRestrictionForUser( - UserManager.DISALLOW_NETWORK_RESET, UserHandle.getUserHandleForUid(uid)) - || userManager.hasUserRestrictionForUser( - UserManager.DISALLOW_CONFIG_WIFI, UserHandle.getUserHandleForUid(uid))) { - return false; - } - - Log.i(TAG, "factoryReset uid=" + uid + " pkg=" + pkgName); - - if (mInterfaceName != null) { - if (mWifiNative.p2pListNetworks(mGroups)) { - for (WifiP2pGroup group : mGroups.getGroupList()) { - mWifiNative.removeP2pNetwork(group.getNetworkId()); - } - } - // reload will save native config and broadcast changed event. - updatePersistentNetworks(true); - setPendingFactoryReset(false); - } else { - setPendingFactoryReset(true); - } - return true; - } - - /** - * Get calling package string from Client HashMap - * - * @param uid The uid of the caller package - * @param replyMessenger AsyncChannel handler in caller - */ - private String getCallingPkgName(int uid, Messenger replyMessenger) { - ClientInfo clientInfo = mClientInfoList.get(replyMessenger); - if (clientInfo != null) { - return clientInfo.mPackageName; - } - if (uid == Process.SYSTEM_UID) return mContext.getOpPackageName(); - return null; - } - - /** - * Get calling feature id from Client HashMap - * - * @param uid The uid of the caller - * @param replyMessenger AsyncChannel handler in caller - */ - private String getCallingFeatureId(int uid, Messenger replyMessenger) { - ClientInfo clientInfo = mClientInfoList.get(replyMessenger); - if (clientInfo != null) { - return clientInfo.mFeatureId; - } - if (uid == Process.SYSTEM_UID) return mContext.getAttributionTag(); - return null; - } - - /** - * Clear all of p2p local service request/response for all p2p clients - */ - private void clearServicesForAllClients() { - for (ClientInfo c : mClientInfoList.values()) { - clearLocalServices(c.mMessenger); - clearServiceRequests(c.mMessenger); - } - } - - private int selectGroupOwnerIntentIfNecessary(WifiP2pConfig config) { - int intent = config.groupOwnerIntent; - // return the legacy default value for invalid values. - if (intent != WifiP2pConfig.GROUP_OWNER_INTENT_AUTO) { - if (intent < WifiP2pConfig.GROUP_OWNER_INTENT_MIN - || intent > WifiP2pConfig.GROUP_OWNER_INTENT_MAX) { - intent = DEFAULT_GROUP_OWNER_INTENT; - } - return intent; - } - - WifiManager wifiManager = mContext.getSystemService(WifiManager.class); - - WifiInfo wifiInfo = wifiManager.getConnectionInfo(); - Log.d(TAG, "WifiInfo: " + wifiInfo); - int freq = wifiInfo.getFrequency(); - if (wifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID) { - intent = DEFAULT_GROUP_OWNER_INTENT + 1; - } else if (ScanResult.is24GHz(freq)) { - intent = WifiP2pConfig.GROUP_OWNER_INTENT_MIN; - } else if (ScanResult.is5GHz(freq)) { - // If both sides use the maximum, the negotiation would fail. - intent = WifiP2pConfig.GROUP_OWNER_INTENT_MAX - 1; - } else { - intent = DEFAULT_GROUP_OWNER_INTENT; - } - Log.i(TAG, "change GO intent value from " - + config.groupOwnerIntent + " to " + intent); - return intent; - } - - } - - /** - * Information about a particular client and we track the service discovery requests - * and the local services registered by the client. - */ - private class ClientInfo { - - // A reference to WifiP2pManager.Channel handler. - // The response of this request is notified to WifiP2pManager.Channel handler - private Messenger mMessenger; - private String mPackageName; - private @Nullable String mFeatureId; - - - // A service discovery request list. - private SparseArray<WifiP2pServiceRequest> mReqList; - - // A local service information list. - private List<WifiP2pServiceInfo> mServList; - - private ClientInfo(Messenger m) { - mMessenger = m; - mPackageName = null; - mFeatureId = null; - mReqList = new SparseArray(); - mServList = new ArrayList<WifiP2pServiceInfo>(); - } - } - - /** - * Check that the UID has one of the following permissions: - * {@link android.Manifest.permission.NETWORK_SETTINGS} - * {@link android.Manifest.permission.NETWORK_STACK} - * {@link android.Manifest.permission.OVERRIDE_WIFI_CONFIG} - * - * @param uid the UID to check - * @return whether the UID has any of the above permissions - */ - private boolean checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission(int uid) { - return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) - || mWifiPermissionsUtil.checkNetworkStackPermission(uid) - || mWifiPermissionsUtil.checkConfigOverridePermission(uid); - } - - /** - * Check that the UID has one of the following permissions: - * {@link android.Manifest.permission.NETWORK_SETTINGS} - * {@link android.Manifest.permission.NETWORK_STACK} - * {@link android.Manifest.permission.READ_WIFI_CREDENTIAL} - * - * @param uid the UID to check - * @return whether the UID has any of the above permissions - */ - private boolean checkNetworkSettingsOrNetworkStackOrReadWifiCredentialPermission(int uid) { - return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) - || mWifiPermissionsUtil.checkNetworkStackPermission(uid) - || mWifiPermissionsUtil.checkReadWifiCredentialPermission(uid); - } -} diff --git a/service/java/com/android/server/wifi/rtt/RttMetrics.java b/service/java/com/android/server/wifi/rtt/RttMetrics.java deleted file mode 100644 index c2ee4ddb5..000000000 --- a/service/java/com/android/server/wifi/rtt/RttMetrics.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.rtt; - -import static com.android.server.wifi.util.MetricsUtils.addValueToLinearHistogram; -import static com.android.server.wifi.util.MetricsUtils.addValueToLogHistogram; -import static com.android.server.wifi.util.MetricsUtils.linearHistogramToGenericBuckets; -import static com.android.server.wifi.util.MetricsUtils.logHistogramToGenericBuckets; - -import android.net.MacAddress; -import android.net.wifi.rtt.RangingRequest; -import android.net.wifi.rtt.RangingResult; -import android.net.wifi.rtt.ResponderConfig; -import android.os.WorkSource; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.MetricsUtils; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Wi-Fi RTT metric container/processor. - */ -public class RttMetrics { - private static final String TAG = "RttMetrics"; - private static final boolean VDBG = false; - /* package */ boolean mDbg = false; - - private final Object mLock = new Object(); - private final Clock mClock; - - // accumulated metrics data - - // Histogram: 7 buckets (i=0, ..., 6) of 1 slots in range 10^i -> 10^(i+1) - // Buckets: - // 1 -> 10 - // 10 -> 100 - // 100 -> 1000 - // 10^3 -> 10^4 - // 10^4 -> 10^5 - // 10^5 -> 10^6 - // 10^5 -> 10^7 (10^7 ms = 160 minutes) - private static final MetricsUtils.LogHistParms COUNT_LOG_HISTOGRAM = - new MetricsUtils.LogHistParms(0, 1, 10, 1, 7); - - // Histogram for ranging limits in discovery. Indicates the following 7 buckets (in meters): - // < 0 - // [0, 5) - // [5, 15) - // [15, 30) - // [30, 60) - // [60, 100) - // >= 100 - private static final int[] DISTANCE_MM_HISTOGRAM = - {0, 5 * 1000, 15 * 1000, 30 * 1000, 60 * 1000, 100 * 1000}; - // Histogram for duration for ap only measurement. Indicates 5 buckets with 1000 ms interval. - private static final int[] MEASUREMENT_DURATION_HISTOGRAM_AP = - {1 * 1000, 2 * 1000, 3 * 1000, 4 * 1000}; - - // Histogram for duration for measurement with aware. Indicates 5 buckets with 2000 ms interval. - private static final int[] MEASUREMENT_DURATION_HISTOGRAM_AWARE = - {2 * 1000, 4 * 1000, 6 * 1000, 8 * 1000}; - - private static final int PEER_AP = 0; - private static final int PEER_AWARE = 1; - - private int mNumStartRangingCalls = 0; - private SparseIntArray mOverallStatusHistogram = new SparseIntArray(); - private SparseIntArray mMeasurementDurationApOnlyHistogram = new SparseIntArray(); - private SparseIntArray mMeasurementDurationWithAwareHistogram = new SparseIntArray(); - private PerPeerTypeInfo[] mPerPeerTypeInfo; - - public RttMetrics(Clock clock) { - mClock = clock; - - mPerPeerTypeInfo = new PerPeerTypeInfo[2]; - mPerPeerTypeInfo[PEER_AP] = new PerPeerTypeInfo(); - mPerPeerTypeInfo[PEER_AWARE] = new PerPeerTypeInfo(); - } - - private class PerUidInfo { - public int numRequests; - public long lastRequestMs; - - @Override - public String toString() { - return "numRequests=" + numRequests + ", lastRequestMs=" + lastRequestMs; - } - } - - private class PerPeerTypeInfo { - public int numCalls; - public int numIndividualCalls; - public SparseArray<PerUidInfo> perUidInfo = new SparseArray<>(); - public SparseIntArray numRequestsHistogram = new SparseIntArray(); - public SparseIntArray requestGapHistogram = new SparseIntArray(); - public SparseIntArray statusHistogram = new SparseIntArray(); - public SparseIntArray measuredDistanceHistogram = new SparseIntArray(); - - @Override - public String toString() { - return "numCalls=" + numCalls + ", numIndividualCalls=" + numIndividualCalls - + ", perUidInfo=" + perUidInfo + ", numRequestsHistogram=" - + numRequestsHistogram + ", requestGapHistogram=" + requestGapHistogram - + ", statusHistogram=" + statusHistogram - + ", measuredDistanceHistogram=" + measuredDistanceHistogram; - } - } - - // metric recording API - - /** - * Record metrics for the range request. - */ - public void recordRequest(WorkSource ws, RangingRequest requests) { - mNumStartRangingCalls++; - - int numApRequests = 0; - int numAwareRequests = 0; - for (ResponderConfig request : requests.mRttPeers) { - if (request == null) { - continue; - } - if (request.responderType == ResponderConfig.RESPONDER_AWARE) { - numAwareRequests++; - } else if (request.responderType == ResponderConfig.RESPONDER_AP) { - numApRequests++; - } else { - if (mDbg) Log.d(TAG, "Unexpected Responder type: " + request.responderType); - } - } - - updatePeerInfoWithRequestInfo(mPerPeerTypeInfo[PEER_AP], ws, numApRequests); - updatePeerInfoWithRequestInfo(mPerPeerTypeInfo[PEER_AWARE], ws, numAwareRequests); - } - - /** - * Record metrics for the range results. - */ - public void recordResult(RangingRequest requests, List<RangingResult> results, - int measurementDuration) { - Map<MacAddress, ResponderConfig> requestEntries = new HashMap<>(); - for (ResponderConfig responder : requests.mRttPeers) { - requestEntries.put(responder.macAddress, responder); - } - if (results != null) { - boolean containsAwarePeer = false; - for (RangingResult result : results) { - if (result == null) { - continue; - } - ResponderConfig responder = requestEntries.remove(result.getMacAddress()); - if (responder == null) { - Log.e(TAG, - "recordResult: found a result which doesn't match any requests: " - + result); - continue; - } - - if (responder.responderType == ResponderConfig.RESPONDER_AP) { - updatePeerInfoWithResultInfo(mPerPeerTypeInfo[PEER_AP], result); - } else if (responder.responderType == ResponderConfig.RESPONDER_AWARE) { - containsAwarePeer = true; - updatePeerInfoWithResultInfo(mPerPeerTypeInfo[PEER_AWARE], result); - } else { - Log.e(TAG, "recordResult: unexpected peer type in responder: " + responder); - } - } - if (containsAwarePeer) { - addValueToLinearHistogram(measurementDuration, - mMeasurementDurationWithAwareHistogram, - MEASUREMENT_DURATION_HISTOGRAM_AWARE); - } else { - addValueToLinearHistogram(measurementDuration, - mMeasurementDurationApOnlyHistogram, - MEASUREMENT_DURATION_HISTOGRAM_AP); - } - } - - for (ResponderConfig responder : requestEntries.values()) { - PerPeerTypeInfo peerInfo; - if (responder.responderType == ResponderConfig.RESPONDER_AP) { - peerInfo = mPerPeerTypeInfo[PEER_AP]; - } else if (responder.responderType == ResponderConfig.RESPONDER_AWARE) { - peerInfo = mPerPeerTypeInfo[PEER_AWARE]; - } else { - Log.e(TAG, "recordResult: unexpected peer type in responder: " + responder); - continue; - } - peerInfo.statusHistogram.put(WifiMetricsProto.WifiRttLog.MISSING_RESULT, - peerInfo.statusHistogram.get(WifiMetricsProto.WifiRttLog.MISSING_RESULT) + 1); - } - } - - /** - * Record metrics for the overall ranging request status. - */ - public void recordOverallStatus(int status) { - mOverallStatusHistogram.put(status, mOverallStatusHistogram.get(status) + 1); - } - - private void updatePeerInfoWithRequestInfo(PerPeerTypeInfo peerInfo, WorkSource ws, - int numIndividualCalls) { - if (numIndividualCalls == 0) { - return; - } - - long nowMs = mClock.getElapsedSinceBootMillis(); - peerInfo.numCalls++; - peerInfo.numIndividualCalls += numIndividualCalls; - peerInfo.numRequestsHistogram.put(numIndividualCalls, - peerInfo.numRequestsHistogram.get(numIndividualCalls) + 1); - boolean recordedIntervals = false; - - for (int i = 0; i < ws.size(); ++i) { - int uid = ws.getUid(i); - - PerUidInfo perUidInfo = peerInfo.perUidInfo.get(uid); - if (perUidInfo == null) { - perUidInfo = new PerUidInfo(); - } - - perUidInfo.numRequests++; - - if (!recordedIntervals && perUidInfo.lastRequestMs != 0) { - recordedIntervals = true; // don't want to record twice - addValueToLogHistogram(nowMs - perUidInfo.lastRequestMs, - peerInfo.requestGapHistogram, COUNT_LOG_HISTOGRAM); - } - perUidInfo.lastRequestMs = nowMs; - - peerInfo.perUidInfo.put(uid, perUidInfo); - } - } - - private void updatePeerInfoWithResultInfo(PerPeerTypeInfo peerInfo, RangingResult result) { - int protoStatus = convertRttStatusTypeToProtoEnum(result.getStatus()); - peerInfo.statusHistogram.put(protoStatus, peerInfo.statusHistogram.get(protoStatus) + 1); - if (result.getStatus() != RangingResult.STATUS_SUCCESS) { - return; - } - addValueToLinearHistogram(result.getDistanceMm(), peerInfo.measuredDistanceHistogram, - DISTANCE_MM_HISTOGRAM); - } - - /** - * Consolidate all metrics into the proto. - */ - public WifiMetricsProto.WifiRttLog consolidateProto() { - WifiMetricsProto.WifiRttLog log = new WifiMetricsProto.WifiRttLog(); - log.rttToAp = new WifiMetricsProto.WifiRttLog.RttToPeerLog(); - log.rttToAware = new WifiMetricsProto.WifiRttLog.RttToPeerLog(); - synchronized (mLock) { - log.numRequests = mNumStartRangingCalls; - log.histogramOverallStatus = consolidateOverallStatus(mOverallStatusHistogram); - log.histogramMeasurementDurationApOnly = genericBucketsToRttBuckets( - linearHistogramToGenericBuckets(mMeasurementDurationApOnlyHistogram, - MEASUREMENT_DURATION_HISTOGRAM_AP)); - log.histogramMeasurementDurationWithAware = genericBucketsToRttBuckets( - linearHistogramToGenericBuckets(mMeasurementDurationWithAwareHistogram, - MEASUREMENT_DURATION_HISTOGRAM_AWARE)); - - consolidatePeerType(log.rttToAp, mPerPeerTypeInfo[PEER_AP]); - consolidatePeerType(log.rttToAware, mPerPeerTypeInfo[PEER_AWARE]); - } - return log; - } - - private WifiMetricsProto.WifiRttLog.RttOverallStatusHistogramBucket[] consolidateOverallStatus( - SparseIntArray histogram) { - WifiMetricsProto.WifiRttLog.RttOverallStatusHistogramBucket[] h = - new WifiMetricsProto.WifiRttLog.RttOverallStatusHistogramBucket[histogram.size()]; - for (int i = 0; i < histogram.size(); i++) { - h[i] = new WifiMetricsProto.WifiRttLog.RttOverallStatusHistogramBucket(); - h[i].statusType = histogram.keyAt(i); - h[i].count = histogram.valueAt(i); - } - return h; - } - - private void consolidatePeerType(WifiMetricsProto.WifiRttLog.RttToPeerLog peerLog, - PerPeerTypeInfo peerInfo) { - peerLog.numRequests = peerInfo.numCalls; - peerLog.numIndividualRequests = peerInfo.numIndividualCalls; - peerLog.numApps = peerInfo.perUidInfo.size(); - peerLog.histogramNumPeersPerRequest = consolidateNumPeersPerRequest( - peerInfo.numRequestsHistogram); - peerLog.histogramNumRequestsPerApp = consolidateNumRequestsPerApp(peerInfo.perUidInfo); - peerLog.histogramRequestIntervalMs = genericBucketsToRttBuckets( - logHistogramToGenericBuckets(peerInfo.requestGapHistogram, COUNT_LOG_HISTOGRAM)); - peerLog.histogramIndividualStatus = consolidateIndividualStatus(peerInfo.statusHistogram); - peerLog.histogramDistance = genericBucketsToRttBuckets( - linearHistogramToGenericBuckets(peerInfo.measuredDistanceHistogram, - DISTANCE_MM_HISTOGRAM)); - } - - private WifiMetricsProto.WifiRttLog.RttIndividualStatusHistogramBucket[] - consolidateIndividualStatus(SparseIntArray histogram) { - WifiMetricsProto.WifiRttLog.RttIndividualStatusHistogramBucket[] h = - new WifiMetricsProto.WifiRttLog.RttIndividualStatusHistogramBucket[histogram.size( - )]; - for (int i = 0; i < histogram.size(); i++) { - h[i] = new WifiMetricsProto.WifiRttLog.RttIndividualStatusHistogramBucket(); - h[i].statusType = histogram.keyAt(i); - h[i].count = histogram.valueAt(i); - } - return h; - } - - private WifiMetricsProto.WifiRttLog.HistogramBucket[] consolidateNumPeersPerRequest( - SparseIntArray data) { - WifiMetricsProto.WifiRttLog.HistogramBucket[] protoArray = - new WifiMetricsProto.WifiRttLog.HistogramBucket[data.size()]; - - for (int i = 0; i < data.size(); i++) { - protoArray[i] = new WifiMetricsProto.WifiRttLog.HistogramBucket(); - protoArray[i].start = data.keyAt(i); - protoArray[i].end = data.keyAt(i); - protoArray[i].count = data.valueAt(i); - } - - return protoArray; - } - - private WifiMetricsProto.WifiRttLog.HistogramBucket[] consolidateNumRequestsPerApp( - SparseArray<PerUidInfo> perUidInfos) { - SparseIntArray histogramNumRequestsPerUid = new SparseIntArray(); - for (int i = 0; i < perUidInfos.size(); i++) { - addValueToLogHistogram(perUidInfos.valueAt(i).numRequests, histogramNumRequestsPerUid, - COUNT_LOG_HISTOGRAM); - } - - return genericBucketsToRttBuckets(logHistogramToGenericBuckets( - histogramNumRequestsPerUid, COUNT_LOG_HISTOGRAM)); - } - - private WifiMetricsProto.WifiRttLog.HistogramBucket[] genericBucketsToRttBuckets( - MetricsUtils.GenericBucket[] genericHistogram) { - WifiMetricsProto.WifiRttLog.HistogramBucket[] histogram = - new WifiMetricsProto.WifiRttLog.HistogramBucket[genericHistogram.length]; - for (int i = 0; i < genericHistogram.length; i++) { - histogram[i] = new WifiMetricsProto.WifiRttLog.HistogramBucket(); - histogram[i].start = genericHistogram[i].start; - histogram[i].end = genericHistogram[i].end; - histogram[i].count = genericHistogram[i].count; - } - return histogram; - } - - /** - * Dump all RttMetrics to console (pw) - this method is never called to dump the serialized - * metrics (handled by parent WifiMetrics). - * - * @param fd unused - * @param pw PrintWriter for writing dump to - * @param args unused - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - synchronized (mLock) { - pw.println("RTT Metrics:"); - pw.println("mNumStartRangingCalls:" + mNumStartRangingCalls); - pw.println("mOverallStatusHistogram:" + mOverallStatusHistogram); - pw.println("mMeasurementDurationApOnlyHistogram" + mMeasurementDurationApOnlyHistogram); - pw.println("mMeasurementDurationWithAwareHistogram" - + mMeasurementDurationWithAwareHistogram); - pw.println("AP:" + mPerPeerTypeInfo[PEER_AP]); - pw.println("AWARE:" + mPerPeerTypeInfo[PEER_AWARE]); - } - } - - /** - * clear Wi-Fi RTT metrics - */ - public void clear() { - synchronized (mLock) { - mNumStartRangingCalls = 0; - mOverallStatusHistogram.clear(); - mPerPeerTypeInfo[PEER_AP] = new PerPeerTypeInfo(); - mPerPeerTypeInfo[PEER_AWARE] = new PerPeerTypeInfo(); - mMeasurementDurationApOnlyHistogram.clear(); - mMeasurementDurationWithAwareHistogram.clear(); - } - } - - /** - * Convert a HAL RttStatus enum to a Metrics proto enum RttIndividualStatusTypeEnum. - */ - public static int convertRttStatusTypeToProtoEnum(int rttStatusType) { - switch (rttStatusType) { - case RttNative.FRAMEWORK_RTT_STATUS_SUCCESS: - return WifiMetricsProto.WifiRttLog.SUCCESS; - case RttNative.FRAMEWORK_RTT_STATUS_FAILURE: - return WifiMetricsProto.WifiRttLog.FAILURE; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP: - return WifiMetricsProto.WifiRttLog.FAIL_NO_RSP; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_REJECTED: - return WifiMetricsProto.WifiRttLog.FAIL_REJECTED; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET: - return WifiMetricsProto.WifiRttLog.FAIL_NOT_SCHEDULED_YET; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT: - return WifiMetricsProto.WifiRttLog.FAIL_TM_TIMEOUT; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL: - return WifiMetricsProto.WifiRttLog.FAIL_AP_ON_DIFF_CHANNEL; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY: - return WifiMetricsProto.WifiRttLog.FAIL_NO_CAPABILITY; - case RttNative.FRAMEWORK_RTT_STATUS_ABORTED: - return WifiMetricsProto.WifiRttLog.ABORTED; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS: - return WifiMetricsProto.WifiRttLog.FAIL_INVALID_TS; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL: - return WifiMetricsProto.WifiRttLog.FAIL_PROTOCOL; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE: - return WifiMetricsProto.WifiRttLog.FAIL_SCHEDULE; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER: - return WifiMetricsProto.WifiRttLog.FAIL_BUSY_TRY_LATER; - case RttNative.FRAMEWORK_RTT_STATUS_INVALID_REQ: - return WifiMetricsProto.WifiRttLog.INVALID_REQ; - case RttNative.FRAMEWORK_RTT_STATUS_NO_WIFI: - return WifiMetricsProto.WifiRttLog.NO_WIFI; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE: - return WifiMetricsProto.WifiRttLog.FAIL_FTM_PARAM_OVERRIDE; - default: - Log.e(TAG, "Unrecognized RttStatus: " + rttStatusType); - return WifiMetricsProto.WifiRttLog.UNKNOWN; - } - } -} diff --git a/service/java/com/android/server/wifi/rtt/RttNative.java b/service/java/com/android/server/wifi/rtt/RttNative.java deleted file mode 100644 index 4b1524139..000000000 --- a/service/java/com/android/server/wifi/rtt/RttNative.java +++ /dev/null @@ -1,906 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.rtt; - -import android.annotation.IntDef; -import android.annotation.Nullable; -import android.hardware.wifi.V1_0.IWifiRttController; -import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback; -import android.hardware.wifi.V1_0.RttBw; -import android.hardware.wifi.V1_0.RttCapabilities; -import android.hardware.wifi.V1_0.RttConfig; -import android.hardware.wifi.V1_0.RttPeerType; -import android.hardware.wifi.V1_0.RttPreamble; -import android.hardware.wifi.V1_0.RttResult; -import android.hardware.wifi.V1_0.RttStatus; -import android.hardware.wifi.V1_0.RttType; -import android.hardware.wifi.V1_0.WifiChannelWidthInMhz; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.net.MacAddress; -import android.net.wifi.rtt.RangingRequest; -import android.net.wifi.rtt.RangingResult; -import android.net.wifi.rtt.ResponderConfig; -import android.net.wifi.rtt.ResponderLocation; -import android.os.Handler; -import android.os.RemoteException; -import android.util.Log; - -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.util.NativeUtil; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Objects; - -/** - * TBD - */ -public class RttNative { - private static final String TAG = "RttNative"; - private static final boolean VDBG = false; // STOPSHIP if true - /* package */ boolean mDbg = false; - - /** Unknown status */ - public static final int FRAMEWORK_RTT_STATUS_UNKNOWN = -1; - /** Success */ - public static final int FRAMEWORK_RTT_STATUS_SUCCESS = 0; - /** General failure status */ - public static final int FRAMEWORK_RTT_STATUS_FAILURE = 1; - /** Target STA does not respond to request */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_RSP = 2; - /** Request rejected. Applies to 2-sided RTT only */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_REJECTED = 3; - public static final int FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; - /** Timing measurement times out */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT = 5; - /** Target on different channel, cannot range */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; - /** Ranging not supported */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY = 7; - /** Request aborted for unknown reason */ - public static final int FRAMEWORK_RTT_STATUS_ABORTED = 8; - /** Invalid T1-T4 timestamp */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS = 9; - /** 11mc protocol failed */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL = 10; - /** Request could not be scheduled */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE = 11; - /** Responder cannot collaborate at time of request */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; - /** Bad request args */ - public static final int FRAMEWORK_RTT_STATUS_INVALID_REQ = 13; - /** WiFi not enabled. */ - public static final int FRAMEWORK_RTT_STATUS_NO_WIFI = 14; - /** Responder overrides param info, cannot range with new params */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; - - /** @hide */ - @IntDef(prefix = "FRAMEWORK_RTT_STATUS_", value = {FRAMEWORK_RTT_STATUS_UNKNOWN, - FRAMEWORK_RTT_STATUS_SUCCESS, FRAMEWORK_RTT_STATUS_FAILURE, - FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, FRAMEWORK_RTT_STATUS_FAIL_REJECTED, - FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, - FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, - FRAMEWORK_RTT_STATUS_ABORTED, FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, - FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, - FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, FRAMEWORK_RTT_STATUS_INVALID_REQ, - FRAMEWORK_RTT_STATUS_NO_WIFI, FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE}) - @Retention(RetentionPolicy.SOURCE) - public @interface FrameworkRttStatus {} - - - private final RttServiceImpl mRttService; - private final HalDeviceManager mHalDeviceManager; - - private Object mLock = new Object(); - - private volatile IWifiRttController mIWifiRttController; - private volatile Capabilities mRttCapabilities; - private final WifiRttControllerEventCallback mWifiRttControllerEventCallback; - private volatile android.hardware.wifi.V1_4.IWifiRttController mIWifiRttController14; - private final WifiRttControllerEventCallback14 mWifiRttControllerEventCallback14; - private static final int CONVERSION_US_TO_MS = 1_000; - - private final HalDeviceManager.InterfaceRttControllerLifecycleCallback mRttLifecycleCb = - new HalDeviceManager.InterfaceRttControllerLifecycleCallback() { - @Override - public void onNewRttController(IWifiRttController controller) { - if (mDbg) Log.d(TAG, "onNewRttController: controller=" + controller); - synchronized (mLock) { - mIWifiRttController = controller; - mIWifiRttController14 = getWifiRttControllerV1_4(); - - try { - if (mIWifiRttController14 != null) { - mIWifiRttController14.registerEventCallback_1_4( - mWifiRttControllerEventCallback14); - } else { - mIWifiRttController.registerEventCallback( - mWifiRttControllerEventCallback); - } - } catch (RemoteException e) { - Log.e(TAG, "onNewRttController: exception registering callback: " + e); - if (mIWifiRttController != null) { - mIWifiRttController = null; - mIWifiRttController14 = null; - mRttService.disable(); - } - return; - } - mRttService.enableIfPossible(); - updateRttCapabilities(); - } - } - - @Override - public void onRttControllerDestroyed() { - if (mDbg) Log.d(TAG, "onRttControllerDestroyed"); - synchronized (mLock) { - mIWifiRttController = null; - mIWifiRttController14 = null; - mRttCapabilities = null; - mRttService.disable(); - } - } - }; - - public RttNative(RttServiceImpl rttService, HalDeviceManager halDeviceManager) { - mRttService = rttService; - mHalDeviceManager = halDeviceManager; - mWifiRttControllerEventCallback = new WifiRttControllerEventCallback(); - mWifiRttControllerEventCallback14 = new WifiRttControllerEventCallback14(); - } - - /** - * Initialize the object - registering with the HAL device manager. - */ - public void start(Handler handler) { - synchronized (mLock) { - mHalDeviceManager.initialize(); - mHalDeviceManager.registerStatusListener(() -> { - if (VDBG) Log.d(TAG, "hdm.onStatusChanged"); - if (mHalDeviceManager.isStarted()) { - mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, - handler); - } - }, handler); - if (mHalDeviceManager.isStarted()) { - mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, handler); - } - } - } - - /** - * Returns true if Wi-Fi is ready for RTT requests, false otherwise. - */ - public boolean isReady() { - return mIWifiRttController != null; - } - - /** - * Returns the RTT capabilities. Will only be null when disabled (e.g. no STA interface - * available - not necessarily up). - */ - public @Nullable Capabilities getRttCapabilities() { - return mRttCapabilities; - } - - /** - * Updates the RTT capabilities. - */ - void updateRttCapabilities() { - if (mIWifiRttController == null) { - Log.e(TAG, "updateRttCapabilities: but a RTT controller is NULL!?"); - return; - } - if (mRttCapabilities != null) { - return; - } - if (mDbg) Log.v(TAG, "updateRttCapabilities"); - - synchronized (mLock) { - try { - if (mIWifiRttController14 != null) { - mIWifiRttController14.getCapabilities_1_4( - (status, capabilities14) -> { - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "updateRttCapabilities:" - + " error requesting capabilities " - + "-- code=" + status.code); - return; - } - if (mDbg) { - Log.v(TAG, "updateRttCapabilities: RTT capabilities=" - + capabilities14); - } - mRttCapabilities = new Capabilities(capabilities14); - }); - } else { - mIWifiRttController.getCapabilities( - (status, capabilities) -> { - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "updateRttCapabilities:" - + " error requesting capabilities " - + "-- code=" + status.code); - return; - } - if (mDbg) { - Log.v(TAG, "updateRttCapabilities: RTT capabilities=" - + capabilities); - } - mRttCapabilities = new Capabilities(capabilities); - }); - } - } catch (RemoteException e) { - Log.e(TAG, "updateRttCapabilities: exception requesting capabilities: " + e); - } - - if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) { - Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - " - + "ignored!?"); - } - } - } - - /** - * Issue a range request to the HAL. - * - * @param cmdId Command ID for the request. Will be used in the corresponding - * {@link WifiRttControllerEventCallback#onResults(int, ArrayList)}. - * @param request Range request. - * @param isCalledFromPrivilegedContext Indicates whether privileged APIs are permitted, - * initially: support for one-sided RTT. - * - * @return Success status: true for success, false for failure. - */ - public boolean rangeRequest(int cmdId, RangingRequest request, - boolean isCalledFromPrivilegedContext) { - if (mDbg) { - Log.v(TAG, - "rangeRequest: cmdId=" + cmdId + ", # of requests=" + request.mRttPeers.size()); - } - if (VDBG) Log.v(TAG, "rangeRequest: request=" + request); - synchronized (mLock) { - if (!isReady()) { - Log.e(TAG, "rangeRequest: RttController is null"); - return false; - } - updateRttCapabilities(); - - if (mIWifiRttController14 != null) { - return sendRangeRequest14(cmdId, request, isCalledFromPrivilegedContext); - } else { - return sendRangeRequest(cmdId, request, isCalledFromPrivilegedContext); - } - } - } - - private boolean sendRangeRequest(int cmdId, RangingRequest request, - boolean isCalledFromPrivilegedContext) { - ArrayList<RttConfig> rttConfig = convertRangingRequestToRttConfigs(request, - isCalledFromPrivilegedContext, mRttCapabilities); - if (rttConfig == null) { - Log.e(TAG, "sendRangeRequest: invalid request parameters"); - return false; - } - if (rttConfig.size() == 0) { - Log.e(TAG, "sendRangeRequest: all requests invalidated"); - mRttService.onRangingResults(cmdId, new ArrayList<>()); - return true; - } - - try { - WifiStatus status = mIWifiRttController.rangeRequest(cmdId, rttConfig); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "sendRangeRequest: cannot issue range request -- code=" + status.code); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "sendRangeRequest: exception issuing range request: " + e); - return false; - } - - return true; - } - - private boolean sendRangeRequest14(int cmdId, RangingRequest request, - boolean isCalledFromPrivilegedContext) { - ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfig = - convertRangingRequestToRttConfigs14(request, - isCalledFromPrivilegedContext, mRttCapabilities); - if (rttConfig == null) { - Log.e(TAG, "sendRangeRequest14: invalid request parameters"); - return false; - } - if (rttConfig.size() == 0) { - Log.e(TAG, "sendRangeRequest14: all requests invalidated"); - mRttService.onRangingResults(cmdId, new ArrayList<>()); - return true; - } - - try { - WifiStatus status = mIWifiRttController14.rangeRequest_1_4(cmdId, rttConfig); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "sendRangeRequest14: cannot issue range request -- code=" - + status.code); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "sendRangeRequest14: exception issuing range request: " + e); - return false; - } - - return true; - } - - /** - * Cancel an outstanding ranging request: no guarantees of execution - we will ignore any - * results which are returned for the canceled request. - * - * @param cmdId The cmdId issued with the original rangeRequest command. - * @param macAddresses A list of MAC addresses for which to cancel the operation. - * @return Success status: true for success, false for failure. - */ - public boolean rangeCancel(int cmdId, ArrayList<byte[]> macAddresses) { - if (mDbg) Log.v(TAG, "rangeCancel: cmdId=" + cmdId); - synchronized (mLock) { - if (!isReady()) { - Log.e(TAG, "rangeCancel: RttController is null"); - return false; - } - - try { - WifiStatus status = mIWifiRttController.rangeCancel(cmdId, macAddresses); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "rangeCancel: cannot issue range cancel -- code=" + status.code); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "rangeCancel: exception issuing range cancel: " + e); - return false; - } - - return true; - } - } - - private static ArrayList<RttConfig> convertRangingRequestToRttConfigs(RangingRequest request, - boolean isCalledFromPrivilegedContext, Capabilities cap) { - ArrayList<RttConfig> rttConfigs = new ArrayList<>(request.mRttPeers.size()); - - // Skipping any configurations which have an error (printing out a message). - // The caller will only get results for valid configurations. - for (ResponderConfig responder: request.mRttPeers) { - if (!isCalledFromPrivilegedContext) { - if (!responder.supports80211mc) { - Log.e(TAG, "Invalid responder: does not support 802.11mc"); - continue; - } - } - - RttConfig config = new RttConfig(); - - System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, - config.addr.length); - - try { - config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED; - if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) { - Log.w(TAG, "Device does not support one-sided RTT"); - continue; - } - - config.peer = halRttPeerTypeFromResponderType(responder.responderType); - config.channel.width = halChannelWidthFromResponderChannelWidth( - responder.channelWidth); - config.channel.centerFreq = responder.frequency; - config.channel.centerFreq0 = responder.centerFreq0; - config.channel.centerFreq1 = responder.centerFreq1; - config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth); - config.preamble = halRttPreambleFromResponderPreamble(responder.preamble); - validateBwAndPreambleCombination(config.bw, config.preamble); - - if (config.peer == RttPeerType.NAN) { - config.mustRequestLci = false; - config.mustRequestLcr = false; - config.burstPeriod = 0; - config.numBurst = 0; - config.numFramesPerBurst = 5; - config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT - config.numRetriesPerFtmr = 3; - config.burstDuration = 9; - } else { // AP + all non-NAN requests - config.mustRequestLci = true; - config.mustRequestLcr = true; - config.burstPeriod = 0; - config.numBurst = 0; - config.numFramesPerBurst = 8; - config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); - config.numRetriesPerFtmr = 3; - config.burstDuration = 9; - - if (cap != null) { // constrain parameters per device capabilities - config.mustRequestLci = config.mustRequestLci && cap.lciSupported; - config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; - config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap); - config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap); - } - } - } catch (IllegalArgumentException e) { - Log.e(TAG, "Invalid configuration: " + e.getMessage()); - continue; - } - - rttConfigs.add(config); - } - - return rttConfigs; - } - - private static void validateBwAndPreambleCombination(int bw, int preamble) { - if (bw <= RttBw.BW_20MHZ) { - return; - } - if (bw == RttBw.BW_40MHZ && preamble >= RttPreamble.HT) { - return; - } - if (bw >= RttBw.BW_80MHZ && preamble >= RttPreamble.VHT) { - return; - } - throw new IllegalArgumentException( - "bw and preamble combination is invalid, bw: " + bw + " preamble: " + preamble); - } - - private static ArrayList<android.hardware.wifi.V1_4.RttConfig> - convertRangingRequestToRttConfigs14( - RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap) { - ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfigs = - new ArrayList<>(request.mRttPeers.size()); - - // Skipping any configurations which have an error (printing out a message). - // The caller will only get results for valid configurations. - for (ResponderConfig responder: request.mRttPeers) { - if (!isCalledFromPrivilegedContext) { - if (!responder.supports80211mc) { - Log.e(TAG, "Invalid responder: does not support 802.11mc"); - continue; - } - } - - android.hardware.wifi.V1_4.RttConfig config = - new android.hardware.wifi.V1_4.RttConfig(); - - System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, - config.addr.length); - - try { - config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED; - if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) { - Log.w(TAG, "Device does not support one-sided RTT"); - continue; - } - - config.peer = halRttPeerTypeFromResponderType(responder.responderType); - config.channel.width = halChannelWidthFromResponderChannelWidth( - responder.channelWidth); - config.channel.centerFreq = responder.frequency; - config.channel.centerFreq0 = responder.centerFreq0; - config.channel.centerFreq1 = responder.centerFreq1; - config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth); - config.preamble = halRttPreamble14FromResponderPreamble(responder.preamble); - - if (config.peer == RttPeerType.NAN) { - config.mustRequestLci = false; - config.mustRequestLcr = false; - config.burstPeriod = 0; - config.numBurst = 0; - config.numFramesPerBurst = 5; - config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT - config.numRetriesPerFtmr = 3; - config.burstDuration = 9; - } else { // AP + all non-NAN requests - config.mustRequestLci = true; - config.mustRequestLcr = true; - config.burstPeriod = 0; - config.numBurst = 0; - config.numFramesPerBurst = 8; - config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); - config.numRetriesPerFtmr = 3; - config.burstDuration = 9; - - if (cap != null) { // constrain parameters per device capabilities - config.mustRequestLci = config.mustRequestLci && cap.lciSupported; - config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; - config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap); - config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap); - } - } - } catch (IllegalArgumentException e) { - Log.e(TAG, "Invalid configuration: " + e.getMessage()); - continue; - } - - rttConfigs.add(config); - } - - return rttConfigs; - } - - private static int halRttPeerTypeFromResponderType(int responderType) { - switch (responderType) { - case ResponderConfig.RESPONDER_AP: - return RttPeerType.AP; - case ResponderConfig.RESPONDER_STA: - return RttPeerType.STA; - case ResponderConfig.RESPONDER_P2P_GO: - return RttPeerType.P2P_GO; - case ResponderConfig.RESPONDER_P2P_CLIENT: - return RttPeerType.P2P_CLIENT; - case ResponderConfig.RESPONDER_AWARE: - return RttPeerType.NAN; - default: - throw new IllegalArgumentException( - "halRttPeerTypeFromResponderType: bad " + responderType); - } - } - - private static int halChannelWidthFromResponderChannelWidth(int responderChannelWidth) { - switch (responderChannelWidth) { - case ResponderConfig.CHANNEL_WIDTH_20MHZ: - return WifiChannelWidthInMhz.WIDTH_20; - case ResponderConfig.CHANNEL_WIDTH_40MHZ: - return WifiChannelWidthInMhz.WIDTH_40; - case ResponderConfig.CHANNEL_WIDTH_80MHZ: - return WifiChannelWidthInMhz.WIDTH_80; - case ResponderConfig.CHANNEL_WIDTH_160MHZ: - return WifiChannelWidthInMhz.WIDTH_160; - case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: - return WifiChannelWidthInMhz.WIDTH_80P80; - default: - throw new IllegalArgumentException( - "halChannelWidthFromResponderChannelWidth: bad " + responderChannelWidth); - } - } - - private static int halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth) { - switch (responderChannelWidth) { - case ResponderConfig.CHANNEL_WIDTH_20MHZ: - return RttBw.BW_20MHZ; - case ResponderConfig.CHANNEL_WIDTH_40MHZ: - return RttBw.BW_40MHZ; - case ResponderConfig.CHANNEL_WIDTH_80MHZ: - return RttBw.BW_80MHZ; - case ResponderConfig.CHANNEL_WIDTH_160MHZ: - case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: - return RttBw.BW_160MHZ; - default: - throw new IllegalArgumentException( - "halRttChannelBandwidthFromHalBandwidth: bad " + responderChannelWidth); - } - } - - private static int halRttPreambleFromResponderPreamble(int responderPreamble) { - switch (responderPreamble) { - case ResponderConfig.PREAMBLE_LEGACY: - return RttPreamble.LEGACY; - case ResponderConfig.PREAMBLE_HT: - return RttPreamble.HT; - case ResponderConfig.PREAMBLE_VHT: - return RttPreamble.VHT; - default: - throw new IllegalArgumentException( - "halRttPreambleFromResponderPreamble: bad " + responderPreamble); - } - } - - private static int halRttPreamble14FromResponderPreamble(int responderPreamble) { - switch (responderPreamble) { - case ResponderConfig.PREAMBLE_LEGACY: - return RttPreamble.LEGACY; - case ResponderConfig.PREAMBLE_HT: - return RttPreamble.HT; - case ResponderConfig.PREAMBLE_VHT: - return RttPreamble.VHT; - case ResponderConfig.PREAMBLE_HE: - return android.hardware.wifi.V1_4.RttPreamble.HE; - default: - throw new IllegalArgumentException( - "halRttPreamble14FromResponderPreamble: bad " + responderPreamble); - } - } - - /** - * Check to see whether the selected RTT channel bandwidth is supported by the device. - * If not supported: return the next lower bandwidth which is supported - * If none: throw an IllegalArgumentException. - * - * Note: the halRttChannelBandwidth is a single bit flag of the ones used in cap.bwSupport (HAL - * specifications). - */ - private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, - Capabilities cap) { - while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & cap.bwSupported) == 0)) { - halRttChannelBandwidth >>= 1; - } - - if (halRttChannelBandwidth != 0) { - return halRttChannelBandwidth; - } - - throw new IllegalArgumentException( - "RTT BW=" + halRttChannelBandwidth + ", not supported by device capabilities=" + cap - + " - and no supported alternative"); - } - - /** - * Check to see whether the selected RTT preamble is supported by the device. - * If not supported: return the next "lower" preamble which is supported - * If none: throw an IllegalArgumentException. - * - * Note: the halRttPreamble is a single bit flag of the ones used in cap.preambleSupport (HAL - * specifications). - */ - private static int halRttPreambleCapabilityLimiter(int halRttPreamble, Capabilities cap) { - while ((halRttPreamble != 0) && ((halRttPreamble & cap.preambleSupported) == 0)) { - halRttPreamble >>= 1; - } - - if (halRttPreamble != 0) { - return halRttPreamble; - } - - throw new IllegalArgumentException( - "RTT Preamble=" + halRttPreamble + ", not supported by device capabilities=" + cap - + " - and no supported alternative"); - } - - /** - * Check if HAL Interface 1.4 is running - * - * @return 1.4 IWifiRttController object if the device is running the 1.4 hal service, null - * otherwise - */ - private android.hardware.wifi.V1_4.IWifiRttController getWifiRttControllerV1_4() { - if (mIWifiRttController == null) { - return null; - } - return android.hardware.wifi.V1_4.IWifiRttController.castFrom(mIWifiRttController); - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("RttNative:"); - pw.println(" mHalDeviceManager: " + mHalDeviceManager); - pw.println(" mIWifiRttController: " + mIWifiRttController); - pw.println(" mRttCapabilities: " + mRttCapabilities); - } - - /** - * Callback for events on 1.0 WifiRttController - */ - private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub { - /** - * Callback from HAL with range results. - * - * @param cmdId Command ID specified in the original request - * {@link #rangeRequest(int, RangingRequest, boolean)}. - * @param halResults A list of range results. - */ - @Override - public void onResults(int cmdId, ArrayList<RttResult> halResults) { - // sanitize HAL results - if (halResults == null) { - halResults = new ArrayList<>(); - } - halResults.removeIf(Objects::isNull); - if (mDbg) { - Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + halResults.size()); - } - ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults(halResults); - mRttService.onRangingResults(cmdId, rangingResults); - } - } - - /** - * Callback for events on 1.4 WifiRttController - */ - private class WifiRttControllerEventCallback14 extends - android.hardware.wifi.V1_4.IWifiRttControllerEventCallback.Stub { - @Override - public void onResults(int cmdId, ArrayList<RttResult> halResults) { - // This callback is not supported on this version of the interface - return; - } - - @Override - public void onResults_1_4(int cmdId, - ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { - if (mDbg) { - Log.v(TAG, - "onResults_1_4: cmdId=" + cmdId + ", # of results=" + halResults.size()); - } - // sanitize HAL results - if (halResults == null) { - halResults = new ArrayList<>(); - } - halResults.removeIf(Objects::isNull); - ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults14(halResults); - mRttService.onRangingResults(cmdId, rangingResults); - } - } - - private ArrayList<RangingResult> convertHalResultsRangingResults( - ArrayList<RttResult> halResults) { - ArrayList<RangingResult> rangingResults = new ArrayList<>(); - for (RttResult rttResult : halResults) { - byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); - byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); - ResponderLocation responderLocation; - try { - responderLocation = new ResponderLocation(lci, lcr); - if (!responderLocation.isValid()) { - responderLocation = null; - } - } catch (Exception e) { - responderLocation = null; - Log.e(TAG, - "ResponderLocation: lci/lcr parser failed exception -- " + e); - } - if (rttResult.successNumber <= 1 - && rttResult.distanceSdInMm != 0) { - if (mDbg) { - Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " - + "samples!? result=" + rttResult); - } - rttResult.distanceSdInMm = 0; - } - rangingResults.add(new RangingResult( - convertHalStatusToFrameworkStatus(rttResult.status), - MacAddress.fromBytes(rttResult.addr), - rttResult.distanceInMm, rttResult.distanceSdInMm, - rttResult.rssi / -2, rttResult.numberPerBurstPeer, - rttResult.successNumber, lci, lcr, responderLocation, - rttResult.timeStampInUs / CONVERSION_US_TO_MS)); - } - return rangingResults; - } - - private ArrayList<RangingResult> convertHalResultsRangingResults14( - ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { - ArrayList<RangingResult> rangingResults = new ArrayList<>(); - for (android.hardware.wifi.V1_4.RttResult rttResult : halResults) { - byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); - byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); - ResponderLocation responderLocation; - try { - responderLocation = new ResponderLocation(lci, lcr); - if (!responderLocation.isValid()) { - responderLocation = null; - } - } catch (Exception e) { - responderLocation = null; - Log.e(TAG, - "ResponderLocation: lci/lcr parser failed exception -- " + e); - } - if (rttResult.successNumber <= 1 - && rttResult.distanceSdInMm != 0) { - if (mDbg) { - Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " - + "samples!? result=" + rttResult); - } - rttResult.distanceSdInMm = 0; - } - rangingResults.add(new RangingResult( - convertHalStatusToFrameworkStatus(rttResult.status), - MacAddress.fromBytes(rttResult.addr), - rttResult.distanceInMm, rttResult.distanceSdInMm, - rttResult.rssi / -2, rttResult.numberPerBurstPeer, - rttResult.successNumber, lci, lcr, responderLocation, - rttResult.timeStampInUs / CONVERSION_US_TO_MS)); - } - return rangingResults; - } - - private @FrameworkRttStatus int convertHalStatusToFrameworkStatus(int halStatus) { - switch (halStatus) { - case RttStatus.SUCCESS: - return FRAMEWORK_RTT_STATUS_SUCCESS; - case RttStatus.FAILURE: - return FRAMEWORK_RTT_STATUS_FAILURE; - case RttStatus.FAIL_NO_RSP: - return FRAMEWORK_RTT_STATUS_FAIL_NO_RSP; - case RttStatus.FAIL_REJECTED: - return FRAMEWORK_RTT_STATUS_FAIL_REJECTED; - case RttStatus.FAIL_NOT_SCHEDULED_YET: - return FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET; - case RttStatus.FAIL_TM_TIMEOUT: - return FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT; - case RttStatus.FAIL_AP_ON_DIFF_CHANNEL: - return FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; - case RttStatus.FAIL_NO_CAPABILITY: - return FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY; - case RttStatus.ABORTED: - return FRAMEWORK_RTT_STATUS_ABORTED; - case RttStatus.FAIL_INVALID_TS: - return FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS; - case RttStatus.FAIL_PROTOCOL: - return FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL; - case RttStatus.FAIL_SCHEDULE: - return FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE; - case RttStatus.FAIL_BUSY_TRY_LATER: - return FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER; - case RttStatus.INVALID_REQ: - return FRAMEWORK_RTT_STATUS_INVALID_REQ; - case RttStatus.NO_WIFI: - return FRAMEWORK_RTT_STATUS_NO_WIFI; - case RttStatus.FAIL_FTM_PARAM_OVERRIDE: - return FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; - default: - Log.e(TAG, "Unrecognized RttStatus: " + halStatus); - return FRAMEWORK_RTT_STATUS_UNKNOWN; - } - } - - /** - * Rtt capabilities inside framework - */ - public class Capabilities { - //1-sided rtt measurement is supported - public boolean oneSidedRttSupported; - //location configuration information supported - public boolean lciSupported; - //location civic records supported - public boolean lcrSupported; - //preamble supported, see bit mask definition above - public int preambleSupported; - //RTT bandwidth supported - public int bwSupported; - // Whether STA responder role is supported. - public boolean responderSupported; - //Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43. - public byte mcVersion; - //if ftm rtt data collection is supported. - public boolean rttFtmSupported; - - public Capabilities(RttCapabilities rttHalCapabilities) { - oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; - lciSupported = rttHalCapabilities.lciSupported; - lcrSupported = rttHalCapabilities.lcrSupported; - responderSupported = rttHalCapabilities.responderSupported; - preambleSupported = rttHalCapabilities.preambleSupport; - mcVersion = rttHalCapabilities.mcVersion; - bwSupported = rttHalCapabilities.bwSupport; - rttFtmSupported = rttHalCapabilities.rttFtmSupported; - } - - public Capabilities(android.hardware.wifi.V1_4.RttCapabilities rttHalCapabilities) { - oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; - lciSupported = rttHalCapabilities.lciSupported; - lcrSupported = rttHalCapabilities.lcrSupported; - responderSupported = rttHalCapabilities.responderSupported; - preambleSupported = rttHalCapabilities.preambleSupport; - mcVersion = rttHalCapabilities.mcVersion; - bwSupported = rttHalCapabilities.bwSupport; - rttFtmSupported = rttHalCapabilities.rttFtmSupported; - } - } -} diff --git a/service/java/com/android/server/wifi/rtt/RttService.java b/service/java/com/android/server/wifi/rtt/RttService.java deleted file mode 100644 index 17e455868..000000000 --- a/service/java/com/android/server/wifi/rtt/RttService.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.rtt; - -import android.content.Context; -import android.net.wifi.aware.WifiAwareManager; -import android.os.HandlerThread; -import android.util.Log; - -import com.android.server.SystemService; -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.WifiContext; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.util.WifiPermissionsUtil; - -/** - * TBD. - */ -public class RttService extends SystemService { - private static final String TAG = "RttService"; - private RttServiceImpl mImpl; - - public RttService(Context contextBase) { - super(new WifiContext(contextBase)); - mImpl = new RttServiceImpl(getContext()); - } - - @Override - public void onStart() { - Log.i(TAG, "Registering " + Context.WIFI_RTT_RANGING_SERVICE); - publishBinderService(Context.WIFI_RTT_RANGING_SERVICE, mImpl); - } - - @Override - public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { - Log.i(TAG, "Starting " + Context.WIFI_RTT_RANGING_SERVICE); - - WifiInjector wifiInjector = WifiInjector.getInstance(); - if (wifiInjector == null) { - Log.e(TAG, "onBootPhase(PHASE_SYSTEM_SERVICES_READY): NULL injector!"); - return; - } - - HalDeviceManager halDeviceManager = wifiInjector.getHalDeviceManager(); - HandlerThread handlerThread = wifiInjector.getRttHandlerThread(); - WifiPermissionsUtil wifiPermissionsUtil = wifiInjector.getWifiPermissionsUtil(); - RttMetrics rttMetrics = wifiInjector.getWifiMetrics().getRttMetrics(); - - WifiAwareManager awareManager = getContext().getSystemService(WifiAwareManager.class); - - RttNative rttNative = new RttNative(mImpl, halDeviceManager); - mImpl.start(handlerThread.getLooper(), wifiInjector.getClock(), awareManager, rttNative, - rttMetrics, wifiPermissionsUtil, wifiInjector.getSettingsConfigStore()); - } - } -} diff --git a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java deleted file mode 100644 index ca986d112..000000000 --- a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java +++ /dev/null @@ -1,1228 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.rtt; - -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; - -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; - -import android.annotation.NonNull; -import android.app.ActivityManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.net.MacAddress; -import android.net.wifi.aware.IWifiAwareMacAddressProvider; -import android.net.wifi.aware.WifiAwareManager; -import android.net.wifi.rtt.IRttCallback; -import android.net.wifi.rtt.IWifiRttManager; -import android.net.wifi.rtt.RangingRequest; -import android.net.wifi.rtt.RangingResult; -import android.net.wifi.rtt.RangingResultCallback; -import android.net.wifi.rtt.ResponderConfig; -import android.net.wifi.rtt.ResponderLocation; -import android.net.wifi.rtt.WifiRttManager; -import android.os.BasicShellCommandHandler; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.ParcelFileDescriptor; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.WorkSource; -import android.os.WorkSource.WorkChain; -import android.util.Log; -import android.util.SparseIntArray; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.WakeupMessage; -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiSettingsConfigStore; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.wifi.resources.R; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - -/** - * Implementation of the IWifiRttManager AIDL interface and of the RttService state manager. - */ -public class RttServiceImpl extends IWifiRttManager.Stub { - private static final String TAG = "RttServiceImpl"; - private static final boolean VDBG = false; // STOPSHIP if true - private boolean mDbg = false; - - private final Context mContext; - private final RttShellCommand mShellCommand; - private Clock mClock; - private WifiAwareManager mAwareManager; - private RttNative mRttNative; - private RttMetrics mRttMetrics; - private WifiPermissionsUtil mWifiPermissionsUtil; - private ActivityManager mActivityManager; - private PowerManager mPowerManager; - private int mBackgroundProcessExecGapMs; - private long mLastRequestTimestamp; - - private RttServiceSynchronized mRttServiceSynchronized; - - /* package */ static final String HAL_RANGING_TIMEOUT_TAG = TAG + " HAL Ranging Timeout"; - - @VisibleForTesting - public static final long HAL_RANGING_TIMEOUT_MS = 5_000; // 5 sec - @VisibleForTesting - public static final long HAL_AWARE_RANGING_TIMEOUT_MS = 10_000; // 10 sec - - // Default value for RTT background throttling interval. - private static final long DEFAULT_BACKGROUND_PROCESS_EXEC_GAP_MS = 1_800_000; // 30 min - - // arbitrary, larger than anything reasonable - /* package */ static final int MAX_QUEUED_PER_UID = 20; - - public RttServiceImpl(Context context) { - mContext = context; - mShellCommand = new RttShellCommand(); - mShellCommand.reset(); - } - - /* - * Shell command: adb shell cmd wifirtt ... - */ - - // If set to 0: normal behavior, if set to 1: do not allow any caller (including system - // callers) privileged API access - private static final String CONTROL_PARAM_OVERRIDE_ASSUME_NO_PRIVILEGE_NAME = - "override_assume_no_privilege"; - private static final int CONTROL_PARAM_OVERRIDE_ASSUME_NO_PRIVILEGE_DEFAULT = 0; - - private class RttShellCommand extends BasicShellCommandHandler { - private Map<String, Integer> mControlParams = new HashMap<>(); - - @Override - public int onCommand(String cmd) { - final int uid = Binder.getCallingUid(); - if (uid != 0) { - throw new SecurityException( - "Uid " + uid + " does not have access to wifirtt commands"); - } - - final PrintWriter pw = getErrPrintWriter(); - try { - if ("reset".equals(cmd)) { - reset(); - return 0; - } else if ("get".equals(cmd)) { - String name = getNextArgRequired(); - if (!mControlParams.containsKey(name)) { - pw.println("Unknown parameter name -- '" + name + "'"); - return -1; - } - getOutPrintWriter().println(mControlParams.get(name)); - return 0; - } else if ("set".equals(cmd)) { - String name = getNextArgRequired(); - String valueStr = getNextArgRequired(); - - if (!mControlParams.containsKey(name)) { - pw.println("Unknown parameter name -- '" + name + "'"); - return -1; - } - - try { - mControlParams.put(name, Integer.valueOf(valueStr)); - return 0; - } catch (NumberFormatException e) { - pw.println("Can't convert value to integer -- '" + valueStr + "'"); - return -1; - } - } else if ("get_capabilities".equals(cmd)) { - RttNative.Capabilities cap = - mRttNative.getRttCapabilities(); - JSONObject j = new JSONObject(); - if (cap != null) { - try { - j.put("rttOneSidedSupported", cap.oneSidedRttSupported); - j.put("rttFtmSupported", cap.rttFtmSupported); - j.put("lciSupported", cap.lciSupported); - j.put("lcrSupported", cap.lcrSupported); - j.put("responderSupported", cap.responderSupported); - j.put("mcVersion", cap.mcVersion); - } catch (JSONException e) { - Log.e(TAG, "onCommand: get_capabilities e=" + e); - } - } - getOutPrintWriter().println(j.toString()); - return 0; - } else { - handleDefaultCommands(cmd); - } - } catch (Exception e) { - pw.println("Exception: " + e); - } - return -1; - } - - @Override - public void onHelp() { - final PrintWriter pw = getOutPrintWriter(); - - pw.println("Wi-Fi RTT (wifirt) commands:"); - pw.println(" help"); - pw.println(" Print this help text."); - pw.println(" reset"); - pw.println(" Reset parameters to default values."); - pw.println(" get_capabilities: prints out the RTT capabilities as a JSON string"); - pw.println(" get <name>"); - pw.println(" Get the value of the control parameter."); - pw.println(" set <name> <value>"); - pw.println(" Set the value of the control parameter."); - pw.println(" Control parameters:"); - for (String name : mControlParams.keySet()) { - pw.println(" " + name); - } - pw.println(); - } - - public int getControlParam(String name) { - if (mControlParams.containsKey(name)) { - return mControlParams.get(name); - } - - Log.wtf(TAG, "getControlParam for unknown variable: " + name); - return 0; - } - - public void reset() { - mControlParams.put(CONTROL_PARAM_OVERRIDE_ASSUME_NO_PRIVILEGE_NAME, - CONTROL_PARAM_OVERRIDE_ASSUME_NO_PRIVILEGE_DEFAULT); - } - } - - /* - * INITIALIZATION - */ - - /** - * Initializes the RTT service (usually with objects from an injector). - * - * @param looper The looper on which to synchronize operations. - * @param clock A mockable clock. - * @param awareManager The Wi-Fi Aware service (binder) if supported on the system. - * @param rttNative The Native interface to the HAL. - * @param rttMetrics The Wi-Fi RTT metrics object. - * @param wifiPermissionsUtil Utility for permission checks. - * @param settingsConfigStore Used for retrieving verbose logging level. - */ - public void start(Looper looper, Clock clock, WifiAwareManager awareManager, - RttNative rttNative, RttMetrics rttMetrics, WifiPermissionsUtil wifiPermissionsUtil, - WifiSettingsConfigStore settingsConfigStore) { - mClock = clock; - mAwareManager = awareManager; - mRttNative = rttNative; - mRttMetrics = rttMetrics; - mWifiPermissionsUtil = wifiPermissionsUtil; - mRttServiceSynchronized = new RttServiceSynchronized(looper, rttNative); - mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - mPowerManager = mContext.getSystemService(PowerManager.class); - - mRttServiceSynchronized.mHandler.post(() -> { - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (mDbg) Log.v(TAG, "BroadcastReceiver: action=" + action); - - if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) { - if (mPowerManager.isDeviceIdleMode()) { - disable(); - } else { - enableIfPossible(); - } - } - } - }, intentFilter); - - settingsConfigStore.registerChangeListener( - WIFI_VERBOSE_LOGGING_ENABLED, - (key, newValue) -> enableVerboseLogging(newValue), - mRttServiceSynchronized.mHandler); - enableVerboseLogging(settingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED)); - - mBackgroundProcessExecGapMs = mContext.getResources().getInteger( - R.integer.config_wifiRttBackgroundExecGapMs); - - intentFilter = new IntentFilter(); - intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION); - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mDbg) Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent); - if (mWifiPermissionsUtil.isLocationModeEnabled()) { - enableIfPossible(); - } else { - disable(); - } - } - }, intentFilter); - - rttNative.start(mRttServiceSynchronized.mHandler); - }); - } - - private void enableVerboseLogging(boolean verbose) { - mDbg = verbose; - if (VDBG) { - mDbg = true; // just override - } - mRttNative.mDbg = mDbg; - mRttMetrics.mDbg = mDbg; - } - - /* - * ASYNCHRONOUS DOMAIN - can be called from different threads! - */ - - /** - * Proxy for the final native call of the parent class. Enables mocking of - * the function. - */ - public int getMockableCallingUid() { - return getCallingUid(); - } - - /** - * Enable the API if possible: broadcast notification & start launching any queued requests - * - * If possible: - * - RTT HAL is available - * - Not in Idle mode - * - Location Mode allows Wi-Fi based locationing - */ - public void enableIfPossible() { - boolean isAvailable = isAvailable(); - if (VDBG) Log.v(TAG, "enableIfPossible: isAvailable=" + isAvailable); - if (!isAvailable) { - return; - } - sendRttStateChangedBroadcast(true); - mRttServiceSynchronized.mHandler.post(() -> { - // queue should be empty at this point (but this call allows validation) - mRttServiceSynchronized.executeNextRangingRequestIfPossible(false); - }); - } - - /** - * Disable the API: - * - Clean-up (fail) pending requests - * - Broadcast notification - */ - public void disable() { - if (VDBG) Log.v(TAG, "disable"); - sendRttStateChangedBroadcast(false); - mRttServiceSynchronized.mHandler.post(() -> { - mRttServiceSynchronized.cleanUpOnDisable(); - }); - } - - @Override - public int handleShellCommand(@NonNull ParcelFileDescriptor in, - @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, - @NonNull String[] args) { - return mShellCommand.exec( - this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), - args); - } - - /** - * Binder interface API to indicate whether the API is currently available. This requires an - * immediate asynchronous response. - */ - @Override - public boolean isAvailable() { - long ident = Binder.clearCallingIdentity(); - try { - return mRttNative != null && mRttNative.isReady() && !mPowerManager.isDeviceIdleMode() - && mWifiPermissionsUtil.isLocationModeEnabled(); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - /** - * Binder interface API to start a ranging operation. Called on binder thread, operations needs - * to be posted to handler thread. - */ - @Override - public void startRanging(IBinder binder, String callingPackage, String callingFeatureId, - WorkSource workSource, RangingRequest request, IRttCallback callback) - throws RemoteException { - if (VDBG) { - Log.v(TAG, "startRanging: binder=" + binder + ", callingPackage=" + callingPackage - + ", workSource=" + workSource + ", request=" + request + ", callback=" - + callback); - } - // verify arguments - if (binder == null) { - throw new IllegalArgumentException("Binder must not be null"); - } - if (request == null || request.mRttPeers == null || request.mRttPeers.size() == 0) { - throw new IllegalArgumentException("Request must not be null or empty"); - } - for (ResponderConfig responder : request.mRttPeers) { - if (responder == null) { - throw new IllegalArgumentException("Request must not contain null Responders"); - } - } - if (callback == null) { - throw new IllegalArgumentException("Callback must not be null"); - } - request.enforceValidity(mAwareManager != null); - - if (!isAvailable()) { - try { - mRttMetrics.recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); - callback.onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); - } catch (RemoteException e) { - Log.e(TAG, "startRanging: disabled, callback failed -- " + e); - } - return; - } - - final int uid = getMockableCallingUid(); - - // permission checks - enforceAccessPermission(); - enforceChangePermission(); - mWifiPermissionsUtil.enforceFineLocationPermission(callingPackage, callingFeatureId, uid); - - final WorkSource ws; - if (workSource != null) { - enforceLocationHardware(); - // We only care about UIDs in the incoming worksources and not their associated - // tags. Clear names so that other operations involving wakesources become simpler. - ws = workSource.withoutNames(); - } else { - ws = null; - } - - boolean isCalledFromPrivilegedContext = - checkLocationHardware() && mShellCommand.getControlParam( - CONTROL_PARAM_OVERRIDE_ASSUME_NO_PRIVILEGE_NAME) == 0; - - // register for binder death - IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { - @Override - public void binderDied() { - if (mDbg) Log.v(TAG, "binderDied: uid=" + uid); - binder.unlinkToDeath(this, 0); - - mRttServiceSynchronized.mHandler.post(() -> { - mRttServiceSynchronized.cleanUpClientRequests(uid, null); - }); - } - }; - - try { - binder.linkToDeath(dr, 0); - } catch (RemoteException e) { - Log.e(TAG, "Error on linkToDeath - " + e); - return; - } - - mRttServiceSynchronized.mHandler.post(() -> { - WorkSource sourceToUse = ws; - if (ws == null || ws.isEmpty()) { - sourceToUse = new WorkSource(uid); - } - mRttServiceSynchronized.queueRangingRequest(uid, sourceToUse, binder, dr, - callingPackage, callingFeatureId, request, callback, - isCalledFromPrivilegedContext); - }); - } - - @Override - public void cancelRanging(WorkSource workSource) throws RemoteException { - if (VDBG) Log.v(TAG, "cancelRanging: workSource=" + workSource); - enforceLocationHardware(); - // We only care about UIDs in the incoming worksources and not their associated - // tags. Clear names so that other operations involving wakesources become simpler. - final WorkSource ws = (workSource != null) ? workSource.withoutNames() : null; - - if (ws == null || ws.isEmpty()) { - Log.e(TAG, "cancelRanging: invalid work-source -- " + ws); - return; - } - - mRttServiceSynchronized.mHandler.post(() -> { - mRttServiceSynchronized.cleanUpClientRequests(0, ws); - }); - } - - /** - * Called by HAL to report ranging results. Called on HAL thread - needs to post to local - * thread. - */ - public void onRangingResults(int cmdId, List<RangingResult> results) { - if (VDBG) Log.v(TAG, "onRangingResults: cmdId=" + cmdId); - mRttServiceSynchronized.mHandler.post(() -> { - mRttServiceSynchronized.onRangingResults(cmdId, results); - }); - } - - private void enforceAccessPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, TAG); - } - - private void enforceChangePermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, TAG); - } - - private void enforceLocationHardware() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.LOCATION_HARDWARE, - TAG); - } - - private boolean checkLocationHardware() { - return mContext.checkCallingOrSelfPermission(android.Manifest.permission.LOCATION_HARDWARE) - == PackageManager.PERMISSION_GRANTED; - } - - private void sendRttStateChangedBroadcast(boolean enabled) { - if (VDBG) Log.v(TAG, "sendRttStateChangedBroadcast: enabled=" + enabled); - final Intent intent = new Intent(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission( - android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump RttService from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); - return; - } - pw.println("Wi-Fi RTT Service"); - mRttServiceSynchronized.dump(fd, pw, args); - } - - /* - * SYNCHRONIZED DOMAIN - */ - - /** - * RTT service implementation - synchronized on a single thread. All commands should be posted - * to the exposed handler. - */ - private class RttServiceSynchronized { - public Handler mHandler; - - private RttNative mRttNative; - private int mNextCommandId = 1000; - private Map<Integer, RttRequesterInfo> mRttRequesterInfo = new HashMap<>(); - private List<RttRequestInfo> mRttRequestQueue = new LinkedList<>(); - private WakeupMessage mRangingTimeoutMessage = null; - - RttServiceSynchronized(Looper looper, RttNative rttNative) { - mRttNative = rttNative; - - mHandler = new Handler(looper); - mRangingTimeoutMessage = new WakeupMessage(mContext, mHandler, - HAL_RANGING_TIMEOUT_TAG, () -> { - timeoutRangingRequest(); - }); - } - - private void cancelRanging(RttRequestInfo rri) { - ArrayList<byte[]> macAddresses = new ArrayList<>(); - for (ResponderConfig peer : rri.request.mRttPeers) { - macAddresses.add(peer.macAddress.toByteArray()); - } - - mRttNative.rangeCancel(rri.cmdId, macAddresses); - } - - private void cleanUpOnDisable() { - if (VDBG) Log.v(TAG, "RttServiceSynchronized.cleanUpOnDisable"); - for (RttRequestInfo rri : mRttRequestQueue) { - try { - if (rri.dispatchedToNative) { - // may not be necessary in some cases (e.g. Wi-Fi disable may already clear - // up active RTT), but in other cases will be needed (doze disabling RTT - // but Wi-Fi still up). Doesn't hurt - worst case will fail. - cancelRanging(rri); - } - mRttMetrics.recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); - rri.callback.onRangingFailure( - RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); - } catch (RemoteException e) { - Log.e(TAG, "RttServiceSynchronized.startRanging: disabled, callback failed -- " - + e); - } - rri.binder.unlinkToDeath(rri.dr, 0); - } - mRttRequestQueue.clear(); - mRangingTimeoutMessage.cancel(); - } - - /** - * Remove entries related to the specified client and cancel any dispatched to HAL - * requests. Expected to provide either the UID or the WorkSource (the other will be 0 or - * null respectively). - * - * A workSource specification will be cleared from the requested workSource and the request - * cancelled only if there are no remaining uids in the work-source. - */ - private void cleanUpClientRequests(int uid, WorkSource workSource) { - if (VDBG) { - Log.v(TAG, "RttServiceSynchronized.cleanUpOnClientDeath: uid=" + uid - + ", workSource=" + workSource + ", mRttRequestQueue=" + mRttRequestQueue); - } - boolean dispatchedRequestAborted = false; - ListIterator<RttRequestInfo> it = mRttRequestQueue.listIterator(); - while (it.hasNext()) { - RttRequestInfo rri = it.next(); - - boolean match = rri.uid == uid; // original UID will never be 0 - if (rri.workSource != null && workSource != null) { - rri.workSource.remove(workSource); - if (rri.workSource.isEmpty()) { - match = true; - } - } - - if (match) { - if (!rri.dispatchedToNative) { - it.remove(); - rri.binder.unlinkToDeath(rri.dr, 0); - } else { - dispatchedRequestAborted = true; - Log.d(TAG, "Client death - cancelling RTT operation in progress: cmdId=" - + rri.cmdId); - mRangingTimeoutMessage.cancel(); - cancelRanging(rri); - } - } - } - - if (VDBG) { - Log.v(TAG, "RttServiceSynchronized.cleanUpOnClientDeath: uid=" + uid - + ", dispatchedRequestAborted=" + dispatchedRequestAborted - + ", after cleanup - mRttRequestQueue=" + mRttRequestQueue); - } - - if (dispatchedRequestAborted) { - executeNextRangingRequestIfPossible(true); - } - } - - private void timeoutRangingRequest() { - if (VDBG) { - Log.v(TAG, "RttServiceSynchronized.timeoutRangingRequest mRttRequestQueue=" - + mRttRequestQueue); - } - if (mRttRequestQueue.size() == 0) { - Log.w(TAG, "RttServiceSynchronized.timeoutRangingRequest: but nothing in queue!?"); - return; - } - RttRequestInfo rri = mRttRequestQueue.get(0); - if (!rri.dispatchedToNative) { - Log.w(TAG, "RttServiceSynchronized.timeoutRangingRequest: command not dispatched " - + "to native!?"); - return; - } - cancelRanging(rri); - try { - mRttMetrics.recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT); - rri.callback.onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - } catch (RemoteException e) { - Log.e(TAG, "RttServiceSynchronized.timeoutRangingRequest: callback failed: " + e); - } - executeNextRangingRequestIfPossible(true); - } - - private void queueRangingRequest(int uid, WorkSource workSource, IBinder binder, - IBinder.DeathRecipient dr, String callingPackage, String callingFeatureId, - RangingRequest request, IRttCallback callback, - boolean isCalledFromPrivilegedContext) { - mRttMetrics.recordRequest(workSource, request); - - if (isRequestorSpamming(workSource)) { - Log.w(TAG, - "Work source " + workSource + " is spamming, dropping request: " + request); - binder.unlinkToDeath(dr, 0); - try { - mRttMetrics.recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE); - callback.onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - } catch (RemoteException e) { - Log.e(TAG, "RttServiceSynchronized.queueRangingRequest: spamming, callback " - + "failed -- " + e); - } - return; - } - - RttRequestInfo newRequest = new RttRequestInfo(); - newRequest.uid = uid; - newRequest.workSource = workSource; - newRequest.binder = binder; - newRequest.dr = dr; - newRequest.callingPackage = callingPackage; - newRequest.callingFeatureId = callingFeatureId; - newRequest.request = request; - newRequest.callback = callback; - newRequest.isCalledFromPrivilegedContext = isCalledFromPrivilegedContext; - mRttRequestQueue.add(newRequest); - - if (VDBG) { - Log.v(TAG, "RttServiceSynchronized.queueRangingRequest: newRequest=" + newRequest); - } - - executeNextRangingRequestIfPossible(false); - } - - private boolean isRequestorSpamming(WorkSource ws) { - if (VDBG) Log.v(TAG, "isRequestorSpamming: ws" + ws); - - SparseIntArray counts = new SparseIntArray(); - - for (RttRequestInfo rri : mRttRequestQueue) { - for (int i = 0; i < rri.workSource.size(); ++i) { - int uid = rri.workSource.getUid(i); - counts.put(uid, counts.get(uid) + 1); - } - - final List<WorkChain> workChains = rri.workSource.getWorkChains(); - if (workChains != null) { - for (int i = 0; i < workChains.size(); ++i) { - final int uid = workChains.get(i).getAttributionUid(); - counts.put(uid, counts.get(uid) + 1); - } - } - } - - for (int i = 0; i < ws.size(); ++i) { - if (counts.get(ws.getUid(i)) < MAX_QUEUED_PER_UID) { - return false; - } - } - - final List<WorkChain> workChains = ws.getWorkChains(); - if (workChains != null) { - for (int i = 0; i < workChains.size(); ++i) { - final int uid = workChains.get(i).getAttributionUid(); - if (counts.get(uid) < MAX_QUEUED_PER_UID) { - return false; - } - } - } - - if (mDbg) { - Log.v(TAG, "isRequestorSpamming: ws=" + ws + ", someone is spamming: " + counts); - } - return true; - } - - private void executeNextRangingRequestIfPossible(boolean popFirst) { - if (VDBG) Log.v(TAG, "executeNextRangingRequestIfPossible: popFirst=" + popFirst); - - if (popFirst) { - if (mRttRequestQueue.size() == 0) { - Log.w(TAG, "executeNextRangingRequestIfPossible: pop requested - but empty " - + "queue!? Ignoring pop."); - } else { - RttRequestInfo topOfQueueRequest = mRttRequestQueue.remove(0); - topOfQueueRequest.binder.unlinkToDeath(topOfQueueRequest.dr, 0); - } - } - - if (mRttRequestQueue.size() == 0) { - if (VDBG) Log.v(TAG, "executeNextRangingRequestIfPossible: no requests pending"); - return; - } - - // if top of list is in progress then do nothing - RttRequestInfo nextRequest = mRttRequestQueue.get(0); - if (nextRequest.peerHandlesTranslated || nextRequest.dispatchedToNative) { - if (VDBG) { - Log.v(TAG, "executeNextRangingRequestIfPossible: called but a command is " - + "executing. topOfQueue=" + nextRequest); - } - return; - } - - startRanging(nextRequest); - } - - private void startRanging(RttRequestInfo nextRequest) { - if (VDBG) { - Log.v(TAG, "RttServiceSynchronized.startRanging: nextRequest=" + nextRequest); - } - - if (!isAvailable()) { - Log.d(TAG, "RttServiceSynchronized.startRanging: disabled"); - try { - mRttMetrics.recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); - nextRequest.callback.onRangingFailure( - RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); - } catch (RemoteException e) { - Log.e(TAG, "RttServiceSynchronized.startRanging: disabled, callback failed -- " - + e); - executeNextRangingRequestIfPossible(true); - return; - } - } - - if (processAwarePeerHandles(nextRequest)) { - if (VDBG) { - Log.v(TAG, "RttServiceSynchronized.startRanging: deferring due to PeerHandle " - + "Aware requests"); - } - return; - } - - if (!preExecThrottleCheck(nextRequest.workSource)) { - Log.w(TAG, "RttServiceSynchronized.startRanging: execution throttled - nextRequest=" - + nextRequest + ", mRttRequesterInfo=" + mRttRequesterInfo); - try { - mRttMetrics.recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE); - nextRequest.callback.onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - } catch (RemoteException e) { - Log.e(TAG, "RttServiceSynchronized.startRanging: throttled, callback failed -- " - + e); - } - executeNextRangingRequestIfPossible(true); - return; - } - - nextRequest.cmdId = mNextCommandId++; - mLastRequestTimestamp = mClock.getWallClockMillis(); - if (mRttNative.rangeRequest(nextRequest.cmdId, nextRequest.request, - nextRequest.isCalledFromPrivilegedContext)) { - long timeout = HAL_RANGING_TIMEOUT_MS; - for (ResponderConfig responderConfig : nextRequest.request.mRttPeers) { - if (responderConfig.responderType == ResponderConfig.RESPONDER_AWARE) { - timeout = HAL_AWARE_RANGING_TIMEOUT_MS; - break; - } - } - mRangingTimeoutMessage.schedule(mClock.getElapsedSinceBootMillis() + timeout); - } else { - Log.w(TAG, "RttServiceSynchronized.startRanging: native rangeRequest call failed"); - try { - mRttMetrics.recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE); - nextRequest.callback.onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - } catch (RemoteException e) { - Log.e(TAG, "RttServiceSynchronized.startRanging: HAL request failed, callback " - + "failed -- " + e); - } - executeNextRangingRequestIfPossible(true); - } - nextRequest.dispatchedToNative = true; - } - - /** - * Perform pre-execution throttling checks: - * - If all uids in ws are in background then check last execution and block if request is - * more frequent than permitted - * - If executing (i.e. permitted) then update execution time - * - * Returns true to permit execution, false to abort it. - */ - private boolean preExecThrottleCheck(WorkSource ws) { - if (VDBG) Log.v(TAG, "preExecThrottleCheck: ws=" + ws); - - // are all UIDs running in the background or is at least 1 in the foreground? - boolean allUidsInBackground = true; - for (int i = 0; i < ws.size(); ++i) { - int uidImportance = mActivityManager.getUidImportance(ws.getUid(i)); - if (VDBG) { - Log.v(TAG, "preExecThrottleCheck: uid=" + ws.getUid(i) + " -> importance=" - + uidImportance); - } - if (uidImportance <= IMPORTANCE_FOREGROUND_SERVICE) { - allUidsInBackground = false; - break; - } - } - - final List<WorkChain> workChains = ws.getWorkChains(); - if (allUidsInBackground && workChains != null) { - for (int i = 0; i < workChains.size(); ++i) { - final WorkChain wc = workChains.get(i); - int uidImportance = mActivityManager.getUidImportance(wc.getAttributionUid()); - if (VDBG) { - Log.v(TAG, "preExecThrottleCheck: workChain=" + wc + " -> importance=" - + uidImportance); - } - - if (uidImportance <= IMPORTANCE_FOREGROUND_SERVICE) { - allUidsInBackground = false; - break; - } - } - } - - // if all UIDs are in background then check timestamp since last execution and see if - // any is permitted (infrequent enough) - boolean allowExecution = false; - long mostRecentExecutionPermitted = - mClock.getElapsedSinceBootMillis() - mBackgroundProcessExecGapMs; - if (allUidsInBackground) { - for (int i = 0; i < ws.size(); ++i) { - RttRequesterInfo info = mRttRequesterInfo.get(ws.getUid(i)); - if (info == null || info.lastRangingExecuted < mostRecentExecutionPermitted) { - allowExecution = true; - break; - } - } - - if (workChains != null & !allowExecution) { - for (int i = 0; i < workChains.size(); ++i) { - final WorkChain wc = workChains.get(i); - RttRequesterInfo info = mRttRequesterInfo.get(wc.getAttributionUid()); - if (info == null - || info.lastRangingExecuted < mostRecentExecutionPermitted) { - allowExecution = true; - break; - } - } - } - } else { - allowExecution = true; - } - - // update exec time - if (allowExecution) { - for (int i = 0; i < ws.size(); ++i) { - RttRequesterInfo info = mRttRequesterInfo.get(ws.getUid(i)); - if (info == null) { - info = new RttRequesterInfo(); - mRttRequesterInfo.put(ws.getUid(i), info); - } - info.lastRangingExecuted = mClock.getElapsedSinceBootMillis(); - } - - if (workChains != null) { - for (int i = 0; i < workChains.size(); ++i) { - final WorkChain wc = workChains.get(i); - RttRequesterInfo info = mRttRequesterInfo.get(wc.getAttributionUid()); - if (info == null) { - info = new RttRequesterInfo(); - mRttRequesterInfo.put(wc.getAttributionUid(), info); - } - info.lastRangingExecuted = mClock.getElapsedSinceBootMillis(); - } - } - } - - return allowExecution; - } - - /** - * Check request for any PeerHandle Aware requests. If there are any: issue requests to - * translate the peer ID to a MAC address and abort current execution of the range request. - * The request will be re-attempted when response is received. - * - * In cases of failure: pop the current request and execute the next one. Failures: - * - Not able to connect to remote service (unlikely) - * - Request already processed: but we're missing information - * - * @return true if need to abort execution, false otherwise. - */ - private boolean processAwarePeerHandles(RttRequestInfo request) { - List<Integer> peerIdsNeedingTranslation = new ArrayList<>(); - for (ResponderConfig rttPeer : request.request.mRttPeers) { - if (rttPeer.peerHandle != null && rttPeer.macAddress == null) { - peerIdsNeedingTranslation.add(rttPeer.peerHandle.peerId); - } - } - - if (peerIdsNeedingTranslation.size() == 0) { - return false; - } - - if (request.peerHandlesTranslated) { - Log.w(TAG, "processAwarePeerHandles: request=" + request - + ": PeerHandles translated - but information still missing!?"); - try { - mRttMetrics.recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_AWARE_TRANSLATION_FAILURE); - request.callback.onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - } catch (RemoteException e) { - Log.e(TAG, "processAwarePeerHandles: onRangingResults failure -- " + e); - } - executeNextRangingRequestIfPossible(true); - return true; // an abort because we removed request and are executing next one - } - - request.peerHandlesTranslated = true; - mAwareManager.requestMacAddresses(request.uid, peerIdsNeedingTranslation, - new IWifiAwareMacAddressProvider.Stub() { - @Override - public void macAddress(Map peerIdToMacMap) { - // ASYNC DOMAIN - mHandler.post(() -> { - // BACK TO SYNC DOMAIN - processReceivedAwarePeerMacAddresses(request, peerIdToMacMap); - }); - } - }); - return true; // a deferral - } - - private void processReceivedAwarePeerMacAddresses(RttRequestInfo request, - Map<Integer, byte[]> peerIdToMacMap) { - if (VDBG) { - Log.v(TAG, "processReceivedAwarePeerMacAddresses: request=" + request - + ", peerIdToMacMap=" + peerIdToMacMap); - } - - RangingRequest.Builder newRequestBuilder = new RangingRequest.Builder(); - for (ResponderConfig rttPeer : request.request.mRttPeers) { - if (rttPeer.peerHandle != null && rttPeer.macAddress == null) { - byte[] mac = peerIdToMacMap.get(rttPeer.peerHandle.peerId); - if (mac == null || mac.length != 6) { - Log.e(TAG, "processReceivedAwarePeerMacAddresses: received an invalid MAC " - + "address for peerId=" + rttPeer.peerHandle.peerId); - continue; - } - newRequestBuilder.addResponder(new ResponderConfig( - MacAddress.fromBytes(mac), - rttPeer.peerHandle, rttPeer.responderType, rttPeer.supports80211mc, - rttPeer.channelWidth, rttPeer.frequency, rttPeer.centerFreq0, - rttPeer.centerFreq1, rttPeer.preamble)); - } else { - newRequestBuilder.addResponder(rttPeer); - } - } - request.request = newRequestBuilder.build(); - - // run request again - startRanging(request); - } - - private void onRangingResults(int cmdId, List<RangingResult> results) { - if (mRttRequestQueue.size() == 0) { - Log.e(TAG, "RttServiceSynchronized.onRangingResults: no current RTT request " - + "pending!?"); - return; - } - mRangingTimeoutMessage.cancel(); - RttRequestInfo topOfQueueRequest = mRttRequestQueue.get(0); - - if (VDBG) { - Log.v(TAG, "RttServiceSynchronized.onRangingResults: cmdId=" + cmdId - + ", topOfQueueRequest=" + topOfQueueRequest + ", results=" - + Arrays.toString(results.toArray())); - } - - if (topOfQueueRequest.cmdId != cmdId) { - Log.e(TAG, "RttServiceSynchronized.onRangingResults: cmdId=" + cmdId - + ", does not match pending RTT request cmdId=" + topOfQueueRequest.cmdId); - return; - } - - boolean permissionGranted = mWifiPermissionsUtil.checkCallersLocationPermission( - topOfQueueRequest.callingPackage, topOfQueueRequest.callingFeatureId, - topOfQueueRequest.uid, /* coarseForTargetSdkLessThanQ */ false, null) - && mWifiPermissionsUtil.isLocationModeEnabled(); - try { - if (permissionGranted) { - List<RangingResult> finalResults = postProcessResults(topOfQueueRequest.request, - results, topOfQueueRequest.isCalledFromPrivilegedContext); - mRttMetrics.recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - mRttMetrics.recordResult(topOfQueueRequest.request, results, - (int) (mClock.getWallClockMillis() - mLastRequestTimestamp)); - if (VDBG) { - Log.v(TAG, "RttServiceSynchronized.onRangingResults: finalResults=" - + finalResults); - } - topOfQueueRequest.callback.onRangingResults(finalResults); - } else { - Log.w(TAG, "RttServiceSynchronized.onRangingResults: location permission " - + "revoked - not forwarding results"); - mRttMetrics.recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING); - topOfQueueRequest.callback.onRangingFailure( - RangingResultCallback.STATUS_CODE_FAIL); - } - } catch (RemoteException e) { - Log.e(TAG, - "RttServiceSynchronized.onRangingResults: callback exception -- " + e); - } - - executeNextRangingRequestIfPossible(true); - } - - /* - * Post process the results: - * - For requests without results: add FAILED results - * - For Aware requests using PeerHandle: replace MAC address with PeerHandle - * - Effectively: throws away results which don't match requests - */ - private List<RangingResult> postProcessResults(RangingRequest request, - List<RangingResult> results, boolean isCalledFromPrivilegedContext) { - Map<MacAddress, RangingResult> resultEntries = new HashMap<>(); - for (RangingResult result : results) { - resultEntries.put(result.getMacAddress(), result); - } - - List<RangingResult> finalResults = new ArrayList<>(request.mRttPeers.size()); - - for (ResponderConfig peer : request.mRttPeers) { - RangingResult resultForRequest = resultEntries.get(peer.macAddress); - if (resultForRequest == null - || resultForRequest.getStatus() != RttNative.FRAMEWORK_RTT_STATUS_SUCCESS) { - if (mDbg) { - Log.v(TAG, "postProcessResults: missing=" + peer.macAddress); - } - - int errorCode = RangingResult.STATUS_FAIL; - if (!isCalledFromPrivilegedContext) { - if (!peer.supports80211mc) { - errorCode = RangingResult.STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC; - } - } - - if (peer.peerHandle == null) { - finalResults.add( - new RangingResult(errorCode, peer.macAddress, 0, 0, 0, 0, 0, null, - null, null, 0)); - } else { - finalResults.add( - new RangingResult(errorCode, peer.peerHandle, 0, 0, 0, 0, 0, null, - null, null, 0)); - } - } else { - int status = RangingResult.STATUS_SUCCESS; - - // Clear LCI and LCR data if the location data should not be retransmitted, - // has a retention expiration time, contains no useful data, or did not parse, - // or the caller is not in a privileged context. - byte[] lci = resultForRequest.getLci(); - byte[] lcr = resultForRequest.getLcr(); - ResponderLocation responderLocation = - resultForRequest.getUnverifiedResponderLocation(); - if (responderLocation == null || !isCalledFromPrivilegedContext) { - lci = null; - lcr = null; - } - // Create external result with external RangResultStatus, cleared LCI and LCR. - if (peer.peerHandle == null) { - finalResults.add(new RangingResult( - status, - peer.macAddress, - resultForRequest.getDistanceMm(), - resultForRequest.getDistanceStdDevMm(), - resultForRequest.getRssi(), - resultForRequest.getNumAttemptedMeasurements(), - resultForRequest.getNumSuccessfulMeasurements(), - lci, - lcr, - responderLocation, - resultForRequest.getRangingTimestampMillis())); - } else { - finalResults.add(new RangingResult( - status, - peer.peerHandle, - resultForRequest.getDistanceMm(), - resultForRequest.getDistanceStdDevMm(), - resultForRequest.getRssi(), - resultForRequest.getNumAttemptedMeasurements(), - resultForRequest.getNumSuccessfulMeasurements(), - lci, - lcr, - responderLocation, - resultForRequest.getRangingTimestampMillis())); - } - } - } - - return finalResults; - } - - // dump call (asynchronous most likely) - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(" mNextCommandId: " + mNextCommandId); - pw.println(" mRttRequesterInfo: " + mRttRequesterInfo); - pw.println(" mRttRequestQueue: " + mRttRequestQueue); - pw.println(" mRangingTimeoutMessage: " + mRangingTimeoutMessage); - mRttMetrics.dump(fd, pw, args); - mRttNative.dump(fd, pw, args); - } - } - - private static class RttRequestInfo { - public int uid; - public WorkSource workSource; - public IBinder binder; - public IBinder.DeathRecipient dr; - public String callingPackage; - public String callingFeatureId; - public RangingRequest request; - public IRttCallback callback; - public boolean isCalledFromPrivilegedContext; - - public int cmdId = 0; // uninitialized cmdId value - public boolean dispatchedToNative = false; - public boolean peerHandlesTranslated = false; - - @Override - public String toString() { - return new StringBuilder("RttRequestInfo: uid=").append(uid).append( - ", workSource=").append(workSource).append(", binder=").append(binder).append( - ", dr=").append(dr).append(", callingPackage=").append(callingPackage).append( - ", callingFeatureId=").append(callingFeatureId).append(", request=").append( - request.toString()).append(", callback=").append(callback).append( - ", cmdId=").append(cmdId).append(", peerHandlesTranslated=").append( - peerHandlesTranslated).append(", isCalledFromPrivilegedContext=").append( - isCalledFromPrivilegedContext).toString(); - } - } - - private static class RttRequesterInfo { - public long lastRangingExecuted; - - @Override - public String toString() { - return new StringBuilder("RttRequesterInfo: lastRangingExecuted=").append( - lastRangingExecuted).toString(); - } - } -} diff --git a/service/java/com/android/server/wifi/scanner/BackgroundScanScheduler.java b/service/java/com/android/server/wifi/scanner/BackgroundScanScheduler.java deleted file mode 100644 index 2749aedf3..000000000 --- a/service/java/com/android/server/wifi/scanner/BackgroundScanScheduler.java +++ /dev/null @@ -1,839 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiScanner.ScanSettings; -import android.util.ArraySet; -import android.util.Log; -import android.util.Pair; -import android.util.Rational; - -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Set; - -/** - * <p>This class takes a series of scan requests and formulates the best hardware level scanning - * schedule it can to try and satisfy requests. The hardware level accepts a series of buckets, - * where each bucket represents a set of channels and an interval to scan at. This - * scheduler operates as follows:</p> - * - * <p>Each new request is placed in the best predefined bucket. Once all requests have been added - * the last buckets (lower priority) are placed in the next best bucket until the number of buckets - * is less than the number supported by the hardware. - * - * <p>Finally, the scheduler creates a WifiNative.ScanSettings from the list of buckets which may be - * passed through the Wifi HAL.</p> - * - * <p>This class is not thread safe.</p> - */ -public class BackgroundScanScheduler { - - private static final String TAG = "BackgroundScanScheduler"; - private static final boolean DBG = false; - - public static final int DEFAULT_MAX_BUCKETS = 8; - // Max channels that can be specified per bucket - public static final int DEFAULT_MAX_CHANNELS_PER_BUCKET = 16; - // anecdotally, some chipsets will fail without explanation with a higher batch size, and - // there is apparently no way to retrieve the maximum batch size - public static final int DEFAULT_MAX_SCANS_TO_BATCH = 10; - public static final int DEFAULT_MAX_AP_PER_SCAN = 32; - - /** - * Value that all scan periods must be an integer multiple of - */ - private static final int PERIOD_MIN_GCD_MS = 10000; - /** - * Default period to use if no buckets are being scheduled - */ - private static final int DEFAULT_PERIOD_MS = 30000; - /** - * Scan report threshold percentage to assign to the schedule by default - * @see com.android.server.wifi.WifiNative.ScanSettings#report_threshold_percent - */ - private static final int DEFAULT_REPORT_THRESHOLD_PERCENTAGE = 100; - - /** - * List of predefined periods (in ms) that buckets can be scheduled at. Ordered by preference - * if there are not enough buckets for all periods. All periods MUST be an integer multiple of - * the next smallest bucket with the smallest bucket having a period of PERIOD_MIN_GCD_MS. - * This requirement allows scans to be scheduled more efficiently because scan requests with - * intersecting channels will result in those channels being scanned exactly once at the smaller - * period and no unnecessary scan being scheduled. If this was not the case and two requests - * had channel 5 with periods of 15 seconds and 25 seconds then channel 5 would be scanned - * 296 (3600/15 + 3600/25 - 3500/75) times an hour instead of 240 times an hour (3600/15) if - * the 25s scan is rescheduled at 30s. This is less important with higher periods as it has - * significantly less impact. Ranking could be done by favoring shorter or longer; however, - * this would result in straying further from the requested period and possibly power - * implications if the scan is scheduled at a significantly lower period. - * - * For example if the hardware only supports 2 buckets and scans are requested with periods of - * 40s, 20s and 10s then the two buckets scheduled will have periods 40s and 20s and the 10s - * scan will be placed in the 20s bucket. - * - * If there are special scan requests such as exponential back off, we always dedicate a bucket - * for each type. Regular scan requests will be packed into the remaining buckets. - */ - private static final int[] PREDEFINED_BUCKET_PERIODS = { - 3 * PERIOD_MIN_GCD_MS, // 30s - 12 * PERIOD_MIN_GCD_MS, // 120s - 48 * PERIOD_MIN_GCD_MS, // 480s - 1 * PERIOD_MIN_GCD_MS, // 10s - 6 * PERIOD_MIN_GCD_MS, // 60s - 192 * PERIOD_MIN_GCD_MS, // 1920s - 24 * PERIOD_MIN_GCD_MS, // 240s - 96 * PERIOD_MIN_GCD_MS, // 960s - 384 * PERIOD_MIN_GCD_MS, // 3840s - -1, // place holder for exponential back off scan - }; - - private static final int EXPONENTIAL_BACK_OFF_BUCKET_IDX = - (PREDEFINED_BUCKET_PERIODS.length - 1); - private static final int NUM_OF_REGULAR_BUCKETS = - (PREDEFINED_BUCKET_PERIODS.length - 1); - - /** - * This class is an intermediate representation for scheduling. This maintins the channel - * collection to be scanned by the bucket as settings are added to it. - */ - private class Bucket { - public int period; - public int bucketId; - private final List<ScanSettings> mScanSettingsList = new ArrayList<>(); - private final ChannelCollection mChannelCollection; - - Bucket(int period) { - this.period = period; - this.bucketId = 0; - mScanSettingsList.clear(); - mChannelCollection = mChannelHelper.createChannelCollection(); - } - - /** - * Copy constructor which populates the settings list from the original bucket object. - */ - Bucket(Bucket originalBucket) { - this(originalBucket.period); - for (ScanSettings settings : originalBucket.getSettingsList()) { - mScanSettingsList.add(settings); - } - } - - /** - * convert ChannelSpec to native representation - */ - private WifiNative.ChannelSettings createChannelSettings(int frequency) { - WifiNative.ChannelSettings channelSettings = new WifiNative.ChannelSettings(); - channelSettings.frequency = frequency; - return channelSettings; - } - - public boolean addSettings(ScanSettings scanSettings) { - mChannelCollection.addChannels(scanSettings); - return mScanSettingsList.add(scanSettings); - } - - public boolean removeSettings(ScanSettings scanSettings) { - if (mScanSettingsList.remove(scanSettings)) { - // It's difficult to handle settings removal from buckets in terms of - // maintaining the correct channel collection, so recreate the channel - // collection from the remaining elements. - updateChannelCollection(); - return true; - } - return false; - } - - public List<ScanSettings> getSettingsList() { - return mScanSettingsList; - } - - public void updateChannelCollection() { - mChannelCollection.clear(); - for (ScanSettings settings : mScanSettingsList) { - mChannelCollection.addChannels(settings); - } - } - - public ChannelCollection getChannelCollection() { - return mChannelCollection; - } - - /** - * convert the setting for this bucket to HAL representation - */ - public WifiNative.BucketSettings createBucketSettings(int bucketId, int maxChannels) { - this.bucketId = bucketId; - int reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; - int maxPeriodInMs = 0; - int stepCount = 0; - int bucketIndex = 0; - - for (int i = 0; i < mScanSettingsList.size(); ++i) { - WifiScanner.ScanSettings setting = mScanSettingsList.get(i); - int requestedReportEvents = setting.reportEvents; - if ((requestedReportEvents & WifiScanner.REPORT_EVENT_NO_BATCH) == 0) { - reportEvents &= ~WifiScanner.REPORT_EVENT_NO_BATCH; - } - if ((requestedReportEvents & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) != 0) { - reportEvents |= WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - } - if ((requestedReportEvents & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { - reportEvents |= WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; - } - // For the bucket allocated to exponential back off scan, the values of - // the exponential back off scan related parameters from the very first - // setting in the settings list will be used to configure this bucket. - // - if (i == 0 && setting.maxPeriodInMs != 0 - && setting.maxPeriodInMs != setting.periodInMs) { - // Align the starting period with one of the pre-defined regular - // scan periods. This will optimize the scan schedule when it has - // both exponential back off scan and regular scan(s). - bucketIndex = findBestRegularBucketIndex(setting.periodInMs, - NUM_OF_REGULAR_BUCKETS); - period = PREDEFINED_BUCKET_PERIODS[bucketIndex]; - maxPeriodInMs = (setting.maxPeriodInMs < period) - ? period - : setting.maxPeriodInMs; - stepCount = setting.stepCount; - } - } - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - bucketSettings.bucket = bucketId; - bucketSettings.report_events = reportEvents; - bucketSettings.period_ms = period; - bucketSettings.max_period_ms = maxPeriodInMs; - bucketSettings.step_count = stepCount; - mChannelCollection.fillBucketSettings(bucketSettings, maxChannels); - return bucketSettings; - } - } - - /** - * Maintains a list of buckets and the number that are active (non-null) - */ - private class BucketList { - // Comparator to sort the buckets in order of increasing time periods - private final Comparator<Bucket> mTimePeriodSortComparator = - new Comparator<Bucket>() { - public int compare(Bucket b1, Bucket b2) { - return b1.period - b2.period; - } - }; - private final Bucket[] mBuckets; - private int mActiveBucketCount = 0; - - BucketList() { - mBuckets = new Bucket[PREDEFINED_BUCKET_PERIODS.length]; - } - - public void clearAll() { - Arrays.fill(mBuckets, null); - mActiveBucketCount = 0; - } - - public void clear(int index) { - if (mBuckets[index] != null) { - --mActiveBucketCount; - mBuckets[index] = null; - } - } - - public Bucket getOrCreate(int index) { - Bucket bucket = mBuckets[index]; - if (bucket == null) { - ++mActiveBucketCount; - bucket = mBuckets[index] = new Bucket(PREDEFINED_BUCKET_PERIODS[index]); - } - return bucket; - } - - public boolean isActive(int index) { - return mBuckets[index] != null; - } - - public Bucket get(int index) { - return mBuckets[index]; - } - - public int size() { - return mBuckets.length; - } - - public int getActiveCount() { - return mActiveBucketCount; - } - - public int getActiveRegularBucketCount() { - if (isActive(EXPONENTIAL_BACK_OFF_BUCKET_IDX)) { - return mActiveBucketCount - 1; - } else { - return mActiveBucketCount; - } - } - - /** - * Returns the active regular buckets sorted by their increasing time periods. - */ - public List<Bucket> getSortedActiveRegularBucketList() { - ArrayList<Bucket> activeBuckets = new ArrayList<>(); - for (int i = 0; i < mBuckets.length; i++) { - if (mBuckets[i] != null && i != EXPONENTIAL_BACK_OFF_BUCKET_IDX) { - activeBuckets.add(mBuckets[i]); - } - } - Collections.sort(activeBuckets, mTimePeriodSortComparator); - return activeBuckets; - } - } - - private int mMaxBuckets = DEFAULT_MAX_BUCKETS; - private int mMaxChannelsPerBucket = DEFAULT_MAX_CHANNELS_PER_BUCKET; - private int mMaxBatch = DEFAULT_MAX_SCANS_TO_BATCH; - private int mMaxApPerScan = DEFAULT_MAX_AP_PER_SCAN; - - public int getMaxBuckets() { - return mMaxBuckets; - } - - public void setMaxBuckets(int maxBuckets) { - mMaxBuckets = maxBuckets; - } - - public int getMaxChannelsPerBucket() { - return mMaxChannelsPerBucket; - } - - // TODO: find a way to get max channels - public void setMaxChannelsPerBucket(int maxChannels) { - mMaxChannelsPerBucket = maxChannels; - } - - public int getMaxBatch() { - return mMaxBatch; - } - - // TODO: find a way to get max batch size - public void setMaxBatch(int maxBatch) { - mMaxBatch = maxBatch; - } - - public int getMaxApPerScan() { - return mMaxApPerScan; - } - - public void setMaxApPerScan(int maxApPerScan) { - mMaxApPerScan = maxApPerScan; - } - - private final BucketList mBuckets = new BucketList(); - private final ChannelHelper mChannelHelper; - private WifiNative.ScanSettings mSchedule; - // This keeps track of the settings to the max time period bucket to which it was scheduled. - private final Map<ScanSettings, Bucket> mSettingsToScheduledBucket = new HashMap<>(); - - public BackgroundScanScheduler(ChannelHelper channelHelper) { - mChannelHelper = channelHelper; - createSchedule(new ArrayList<Bucket>(), getMaxChannelsPerBucket()); - } - - /** - * Updates the schedule from the given set of requests. - */ - public void updateSchedule(@NonNull Collection<ScanSettings> requests) { - // create initial schedule - mBuckets.clearAll(); - for (ScanSettings request : requests) { - addScanToBuckets(request); - } - - compactBuckets(getMaxBuckets()); - - List<Bucket> bucketList = optimizeBuckets(); - - List<Bucket> fixedBucketList = - fixBuckets(bucketList, getMaxBuckets(), getMaxChannelsPerBucket()); - - createSchedule(fixedBucketList, getMaxChannelsPerBucket()); - } - - /** - * Retrieves the current scanning schedule. - */ - public @NonNull WifiNative.ScanSettings getSchedule() { - return mSchedule; - } - - /** - * Returns true if the given scan result should be reported to a listener with the given - * settings. - */ - public boolean shouldReportFullScanResultForSettings(@NonNull ScanResult result, - int bucketsScanned, @NonNull ScanSettings settings) { - return ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, - result, bucketsScanned, settings, getScheduledBucket(settings)); - } - - /** - * Returns a filtered version of the scan results from the chip that represents only the data - * requested in the settings. Will return null if the result should not be reported. - */ - public @Nullable ScanData[] filterResultsForSettings(@NonNull ScanData[] scanDatas, - @NonNull ScanSettings settings) { - return ScanScheduleUtil.filterResultsForSettings(mChannelHelper, scanDatas, settings, - getScheduledBucket(settings)); - } - - /** - * Retrieves the max time period bucket idx at which this setting was scheduled - */ - public int getScheduledBucket(ScanSettings settings) { - Bucket maxScheduledBucket = mSettingsToScheduledBucket.get(settings); - if (maxScheduledBucket != null) { - return maxScheduledBucket.bucketId; - } else { - Log.wtf(TAG, "No bucket found for settings"); - return -1; - } - } - - /** - * creates a schedule for the current buckets - */ - private void createSchedule(List<Bucket> bucketList, int maxChannelsPerBucket) { - WifiNative.ScanSettings schedule = new WifiNative.ScanSettings(); - schedule.num_buckets = bucketList.size(); - schedule.buckets = new WifiNative.BucketSettings[bucketList.size()]; - - schedule.max_ap_per_scan = 0; - schedule.report_threshold_num_scans = getMaxBatch(); - - // set all buckets in schedule - int bucketId = 0; - for (Bucket bucket : bucketList) { - schedule.buckets[bucketId] = - bucket.createBucketSettings(bucketId, maxChannelsPerBucket); - for (ScanSettings settings : bucket.getSettingsList()) { - // set APs per scan - if (settings.numBssidsPerScan > schedule.max_ap_per_scan) { - schedule.max_ap_per_scan = settings.numBssidsPerScan; - } - // set batching - if (settings.maxScansToCache != 0 - && settings.maxScansToCache < schedule.report_threshold_num_scans) { - schedule.report_threshold_num_scans = settings.maxScansToCache; - } - } - bucketId++; - } - - schedule.report_threshold_percent = DEFAULT_REPORT_THRESHOLD_PERCENTAGE; - - if (schedule.max_ap_per_scan == 0 || schedule.max_ap_per_scan > getMaxApPerScan()) { - schedule.max_ap_per_scan = getMaxApPerScan(); - } - - // update base period as gcd of periods - if (schedule.num_buckets > 0) { - int gcd = schedule.buckets[0].period_ms; - for (int b = 1; b < schedule.num_buckets; b++) { - gcd = Rational.gcd(schedule.buckets[b].period_ms, gcd); - } - - if (gcd < PERIOD_MIN_GCD_MS) { - Log.wtf(TAG, "found gcd less than min gcd"); - gcd = PERIOD_MIN_GCD_MS; - } - - schedule.base_period_ms = gcd; - } else { - schedule.base_period_ms = DEFAULT_PERIOD_MS; - } - - mSchedule = schedule; - } - - /** - * Add a scan to the most appropriate bucket, creating the bucket if necessary. - */ - private void addScanToBuckets(ScanSettings settings) { - int bucketIndex; - - if (settings.maxPeriodInMs != 0 && settings.maxPeriodInMs != settings.periodInMs) { - // exponential back off scan has a dedicated bucket - bucketIndex = EXPONENTIAL_BACK_OFF_BUCKET_IDX; - } else { - bucketIndex = findBestRegularBucketIndex(settings.periodInMs, NUM_OF_REGULAR_BUCKETS); - } - - mBuckets.getOrCreate(bucketIndex).addSettings(settings); - } - - /** - * find closest bucket period to the requested period in all predefined buckets - */ - private static int findBestRegularBucketIndex(int requestedPeriod, int maxNumBuckets) { - maxNumBuckets = Math.min(maxNumBuckets, NUM_OF_REGULAR_BUCKETS); - int index = -1; - int minDiff = Integer.MAX_VALUE; - for (int i = 0; i < maxNumBuckets; ++i) { - int diff = Math.abs(PREDEFINED_BUCKET_PERIODS[i] - requestedPeriod); - if (diff < minDiff) { - minDiff = diff; - index = i; - } - } - if (index == -1) { - Log.wtf(TAG, "Could not find best bucket for period " + requestedPeriod + " in " - + maxNumBuckets + " buckets"); - } - return index; - } - - /** - * Reduce the number of required buckets by reassigning lower priority buckets to the next - * closest period bucket. - */ - private void compactBuckets(int maxBuckets) { - int maxRegularBuckets = maxBuckets; - - // reserve one bucket for exponential back off scan if there is - // such request(s) - if (mBuckets.isActive(EXPONENTIAL_BACK_OFF_BUCKET_IDX)) { - maxRegularBuckets--; - } - for (int i = NUM_OF_REGULAR_BUCKETS - 1; - i >= 0 && mBuckets.getActiveRegularBucketCount() > maxRegularBuckets; --i) { - if (mBuckets.isActive(i)) { - for (ScanSettings scanRequest : mBuckets.get(i).getSettingsList()) { - int newBucketIndex = findBestRegularBucketIndex(scanRequest.periodInMs, i); - mBuckets.getOrCreate(newBucketIndex).addSettings(scanRequest); - } - mBuckets.clear(i); - } - } - } - - /** - * Clone the provided scan settings fields to a new ScanSettings object. - */ - private ScanSettings cloneScanSettings(ScanSettings originalSettings) { - ScanSettings settings = new ScanSettings(); - settings.band = originalSettings.band; - settings.channels = originalSettings.channels; - settings.periodInMs = originalSettings.periodInMs; - settings.reportEvents = originalSettings.reportEvents; - settings.numBssidsPerScan = originalSettings.numBssidsPerScan; - settings.maxScansToCache = originalSettings.maxScansToCache; - settings.maxPeriodInMs = originalSettings.maxPeriodInMs; - settings.stepCount = originalSettings.stepCount; - settings.isPnoScan = originalSettings.isPnoScan; - return settings; - } - - /** - * Creates a split scan setting that needs to be added back to the current bucket. - */ - private ScanSettings createCurrentBucketSplitSettings(ScanSettings originalSettings, - Set<Integer> currentBucketChannels) { - ScanSettings currentBucketSettings = cloneScanSettings(originalSettings); - // Let's create a new settings for the current bucket with the same flags, but the missing - // channels from the other bucket - currentBucketSettings.band = WifiScanner.WIFI_BAND_UNSPECIFIED; - currentBucketSettings.channels = new WifiScanner.ChannelSpec[currentBucketChannels.size()]; - int chanIdx = 0; - for (Integer channel : currentBucketChannels) { - currentBucketSettings.channels[chanIdx++] = new WifiScanner.ChannelSpec(channel); - } - return currentBucketSettings; - } - - /** - * Creates a split scan setting that needs to be added to the target lower time period bucket. - * The reportEvents field is modified to remove REPORT_EVENT_AFTER_EACH_SCAN because we - * need this flag only in the higher time period bucket. - */ - private ScanSettings createTargetBucketSplitSettings(ScanSettings originalSettings, - Set<Integer> targetBucketChannels) { - ScanSettings targetBucketSettings = cloneScanSettings(originalSettings); - // The new settings for the other bucket will have the channels that already in the that - // bucket. We'll need to do some migration of the |reportEvents| flags. - targetBucketSettings.band = WifiScanner.WIFI_BAND_UNSPECIFIED; - targetBucketSettings.channels = new WifiScanner.ChannelSpec[targetBucketChannels.size()]; - int chanIdx = 0; - for (Integer channel : targetBucketChannels) { - targetBucketSettings.channels[chanIdx++] = new WifiScanner.ChannelSpec(channel); - } - targetBucketSettings.reportEvents = - originalSettings.reportEvents - & (WifiScanner.REPORT_EVENT_NO_BATCH - | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT); - return targetBucketSettings; - } - - /** - * Split the scan settings into 2 so that they can be put into 2 separate buckets. - * @return The first scan setting needs to be added back to the current bucket - * The second scan setting needs to be added to the other bucket - */ - private Pair<ScanSettings, ScanSettings> createSplitSettings(ScanSettings originalSettings, - ChannelCollection targetBucketChannelCol) { - Set<Integer> currentBucketChannels = - targetBucketChannelCol.getMissingChannelsFromSettings(originalSettings); - Set<Integer> targetBucketChannels = - targetBucketChannelCol.getContainingChannelsFromSettings(originalSettings); - // Two Copy of the original settings - ScanSettings currentBucketSettings = - createCurrentBucketSplitSettings(originalSettings, currentBucketChannels); - ScanSettings targetBucketSettings = - createTargetBucketSplitSettings(originalSettings, targetBucketChannels); - return Pair.create(currentBucketSettings, targetBucketSettings); - } - - /** - * Try to merge the settings to lower buckets. - * Check if the channels in this settings is already covered by a lower time period - * bucket. If it's partially covered, the settings is split else the entire settings - * is moved to the lower time period bucket. - * This method updates the |mSettingsToScheduledBucket| mapping. - * @return Pair<wasMerged, remainingSplitSettings> - * wasMerged - boolean indicating whether the original setting was merged to lower time - * period buckets. - * remainingSplitSettings - Partial Scan Settings that need to be added back to the - * current bucket. - */ - private Pair<Boolean, ScanSettings> mergeSettingsToLowerBuckets(ScanSettings originalSettings, - Bucket currentBucket, ListIterator<Bucket> iterTargetBuckets) { - ScanSettings remainingSplitSettings = null; - boolean wasMerged = false; - Bucket maxScheduledBucket = currentBucket; - - while (iterTargetBuckets.hasPrevious()) { - Bucket targetBucket = iterTargetBuckets.previous(); - ChannelCollection targetBucketChannelCol = targetBucket.getChannelCollection(); - if (targetBucketChannelCol.containsSettings(originalSettings)) { - targetBucket.addSettings(originalSettings); - // Update the max scheduled bucket for this setting - maxScheduledBucket = targetBucket; - wasMerged = true; - } else if (targetBucketChannelCol.partiallyContainsSettings(originalSettings)) { - Pair<ScanSettings, ScanSettings> splitSettings; - if (remainingSplitSettings == null) { - splitSettings = createSplitSettings(originalSettings, targetBucketChannelCol); - } else { - splitSettings = - createSplitSettings(remainingSplitSettings, targetBucketChannelCol); - } - targetBucket.addSettings(splitSettings.second); - // Update the |remainingSplitSettings| to keep track of the remaining scan settings. - // The original settings could be split across multiple buckets. - remainingSplitSettings = splitSettings.first; - wasMerged = true; - } - } - // Update the settings to scheduled bucket mapping. This is needed for event - // reporting lookup - mSettingsToScheduledBucket.put(originalSettings, maxScheduledBucket); - - return Pair.create(wasMerged, remainingSplitSettings); - } - - /** - * Optimize all the active buckets by removing duplicate channels in the buckets. - * This method tries to go through the settings in all the buckets and checks if the same - * channels for the setting is already being scanned by another bucked with lower time period. - * If yes, move the setting to the lower time period bucket. If all the settings from a higher - * period has been moved out, that bucket can be removed. - * - * We're trying to avoid cases where we have the same channels being scanned in different - * buckets. This is to workaround the fact that the HAL implementations have a max number of - * cumulative channel across buckets (b/28022609). - */ - private List<Bucket> optimizeBuckets() { - mSettingsToScheduledBucket.clear(); - List<Bucket> sortedBuckets = mBuckets.getSortedActiveRegularBucketList(); - ListIterator<Bucket> iterBuckets = sortedBuckets.listIterator(); - // This is needed to keep track of split settings that need to be added back to the same - // bucket at the end of iterating thru all the settings. This has to be a separate temp list - // to prevent concurrent modification exceptions during iterations. - List<ScanSettings> currentBucketSplitSettingsList = new ArrayList<>(); - - // We need to go thru each setting starting from the lowest time period bucket and check - // if they're already contained in a lower time period bucket. If yes, delete the setting - // from the current bucket and move it to the other bucket. If the settings are only - // partially contained, split the settings into two and move the partial bucket back - // to the same bucket. Finally, if all the settings have been moved out, remove the current - // bucket altogether. - while (iterBuckets.hasNext()) { - Bucket currentBucket = iterBuckets.next(); - Iterator<ScanSettings> iterSettings = currentBucket.getSettingsList().iterator(); - - currentBucketSplitSettingsList.clear(); - - while (iterSettings.hasNext()) { - ScanSettings currentSettings = iterSettings.next(); - ListIterator<Bucket> iterTargetBuckets = - sortedBuckets.listIterator(iterBuckets.previousIndex()); - - Pair<Boolean, ScanSettings> mergeResult = - mergeSettingsToLowerBuckets( - currentSettings, currentBucket, iterTargetBuckets); - - boolean wasMerged = mergeResult.first.booleanValue(); - if (wasMerged) { - // Remove the original settings from the current bucket. - iterSettings.remove(); - ScanSettings remainingSplitSettings = mergeResult.second; - if (remainingSplitSettings != null) { - // Add back the remaining split settings to the current bucket. - currentBucketSplitSettingsList.add(remainingSplitSettings); - } - } - } - - for (ScanSettings splitSettings: currentBucketSplitSettingsList) { - currentBucket.addSettings(splitSettings); - } - if (currentBucket.getSettingsList().isEmpty()) { - iterBuckets.remove(); - } else { - // Update the channel collection to account for the removed settings - currentBucket.updateChannelCollection(); - } - } - - // Update the settings to scheduled bucket map for all exponential scans. - if (mBuckets.isActive(EXPONENTIAL_BACK_OFF_BUCKET_IDX)) { - Bucket exponentialBucket = mBuckets.get(EXPONENTIAL_BACK_OFF_BUCKET_IDX); - for (ScanSettings settings : exponentialBucket.getSettingsList()) { - mSettingsToScheduledBucket.put(settings, exponentialBucket); - } - sortedBuckets.add(exponentialBucket); - } - - return sortedBuckets; - } - - /** - * Partition the channel set into 2 or more based on the max channels that can be specified for - * each bucket. - */ - private List<Set<Integer>> partitionChannelSet(Set<Integer> originalChannelSet, - int maxChannelsPerBucket) { - ArrayList<Set<Integer>> channelSetList = new ArrayList(); - ArraySet<Integer> channelSet = new ArraySet<>(); - Iterator<Integer> iterChannels = originalChannelSet.iterator(); - - while (iterChannels.hasNext()) { - channelSet.add(iterChannels.next()); - if (channelSet.size() == maxChannelsPerBucket) { - channelSetList.add(channelSet); - channelSet = new ArraySet<>(); - } - } - // Add the last partial set if any - if (!channelSet.isEmpty()) { - channelSetList.add(channelSet); - } - return channelSetList; - } - - /** - * Creates a list of split buckets with the channel collection corrected to fit the - * max channel list size that can be specified. The original channel collection will be split - * into multiple buckets with the same scan settings. - * Note: This does not update the mSettingsToScheduledBucket map because this bucket is - * essentially a copy of the original bucket, so it should not affect the event reporting. - * This bucket results will come back the same time the original bucket results come back. - */ - private List<Bucket> createSplitBuckets(Bucket originalBucket, List<Set<Integer>> channelSets) { - List<Bucket> splitBucketList = new ArrayList<>(); - int channelSetIdx = 0; - - for (Set<Integer> channelSet : channelSets) { - Bucket splitBucket; - if (channelSetIdx == 0) { - // Need to keep the original bucket to keep track of the settings to scheduled - // bucket mapping. - splitBucket = originalBucket; - } else { - splitBucket = new Bucket(originalBucket); - } - ChannelCollection splitBucketChannelCollection = splitBucket.getChannelCollection(); - splitBucketChannelCollection.clear(); - for (Integer channel : channelSet) { - splitBucketChannelCollection.addChannel(channel); - } - channelSetIdx++; - splitBucketList.add(splitBucket); - } - return splitBucketList; - } - - /** - * Check if any of the buckets don't fit into the bucket specification and fix it. This - * creates duplicate buckets to fit all the channels. So, the channels to be scanned - * will be split across 2 (or more) buckets. - * TODO: If we reach the max number of buckets, then this fix will be skipped! - */ - private List<Bucket> fixBuckets(List<Bucket> originalBucketList, int maxBuckets, - int maxChannelsPerBucket) { - List<Bucket> fixedBucketList = new ArrayList<>(); - int totalNumBuckets = originalBucketList.size(); - - for (Bucket originalBucket : originalBucketList) { - ChannelCollection channelCollection = originalBucket.getChannelCollection(); - Set<Integer> channelSet = channelCollection.getChannelSet(); - if (channelSet.size() > maxChannelsPerBucket) { - List<Set<Integer>> channelSetList = - partitionChannelSet(channelSet, maxChannelsPerBucket); - int newTotalNumBuckets = totalNumBuckets + channelSetList.size() - 1; - if (newTotalNumBuckets <= maxBuckets) { - List<Bucket> splitBuckets = createSplitBuckets(originalBucket, channelSetList); - for (Bucket bucket : splitBuckets) { - fixedBucketList.add(bucket); - } - totalNumBuckets = newTotalNumBuckets; - } else { - fixedBucketList.add(originalBucket); - } - } else { - fixedBucketList.add(originalBucket); - } - } - return fixedBucketList; - } -} diff --git a/service/java/com/android/server/wifi/scanner/ChannelHelper.java b/service/java/com/android/server/wifi/scanner/ChannelHelper.java deleted file mode 100644 index a7e50a67c..000000000 --- a/service/java/com/android/server/wifi/scanner/ChannelHelper.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.scanner; - -import android.net.wifi.WifiScanner; -import android.util.ArraySet; - -import com.android.server.wifi.WifiNative; - -import java.util.Set; -import java.util.StringJoiner; - -/** - * ChannelHelper offers an abstraction for channel manipulation utilities allowing operation to be - * adjusted based on the amount of information known about the available channels. - */ -public abstract class ChannelHelper { - - // TODO: Currently this is simply an estimate and is used for both active and passive channels - // scans. Eventually it should be split between passive and active and perhaps retrieved - // from the driver. - /** - * The estimated period spent scanning each channel. This is used for estimating scan duration. - */ - public static final int SCAN_PERIOD_PER_CHANNEL_MS = 200; - - protected static final WifiScanner.ChannelSpec[] NO_CHANNELS = new WifiScanner.ChannelSpec[0]; - - /** - * Create a new collection that can be used to store channels - */ - public abstract ChannelCollection createChannelCollection(); - - /** - * Return true if the specified channel is expected for a scan with the given settings - */ - public abstract boolean settingsContainChannel(WifiScanner.ScanSettings settings, int channel); - - /** - * Get the channels that are available for scanning on the supplied band. - * This method may return empty if the information is not available. - * The channels will be returned in a 2d array, each row will represent channels within a - * {@link #WifiBandBasic}. - * For example, if band is WIFI_BAND_BOTH (for both 2.4GHz and 5GHz no DFS), - * the returned 2d array will be something like: - * [[2412, 2417, 2422],[5180, 5190, 5200, 5210,5220],[]] - * The first row is the 2.4GHz channels, second row is the 5GHz (no DFS channels), and the third - * row is empty (since the requested band does not include DFS channels). - */ - public abstract WifiScanner.ChannelSpec[][] getAvailableScanChannels(int band); - - /** - * Compares the channels / bands available from this helper with the channels / bands available - * from the other channel helper. - * - * @return true if the all the channels available from the other channel helper is also - * available in this helper. - */ - public abstract boolean satisfies(ChannelHelper otherChannelHelper); - - /** - * Estimates the duration that the chip will spend scanning with the given settings - */ - public abstract int estimateScanDuration(WifiScanner.ScanSettings settings); - - /** - * Update the channel information that this object has. The source of the update is - * implementation dependent and may result in no change. Warning the behavior of a - * ChannelCollection created using {@link #createChannelCollection createChannelCollection} is - * undefined after calling this method until the {@link ChannelColleciton#clear() clear} method - * is called on it. - */ - public void updateChannels() { - // default implementation does nothing - } - - /** - * Object that supports accumulation of channels and bands - */ - public abstract class ChannelCollection { - /** - * Add a channel to the collection - */ - public abstract void addChannel(int channel); - /** - * Add all channels in the band to the collection - */ - public abstract void addBand(int band); - /** - * @return true if the collection contains the supplied channel - */ - public abstract boolean containsChannel(int channel); - /** - * @return true if the collection contains all the channels of the supplied band - */ - public abstract boolean containsBand(int band); - /** - * @return true if the collection contains some of the channels of the supplied band - */ - public abstract boolean partiallyContainsBand(int band); - /** - * @return true if the collection contains no channels - */ - public abstract boolean isEmpty(); - /** - * @return true if the collection contains all available channels - */ - public abstract boolean isAllChannels(); - /** - * Remove all channels from the collection - */ - public abstract void clear(); - /** - * Retrieves a list of channels from the band which are missing in the channel collection. - */ - public abstract Set<Integer> getMissingChannelsFromBand(int band); - /** - * Retrieves a list of channels from the band which are contained in the channel collection. - */ - public abstract Set<Integer> getContainingChannelsFromBand(int band); - /** - * Gets a list of channels specified in the current channel collection. This will return - * an empty set if an entire Band if specified or if the list is empty. - */ - public abstract Set<Integer> getChannelSet(); - - /** - * Add all channels in the ScanSetting to the collection - */ - public void addChannels(WifiScanner.ScanSettings scanSettings) { - if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - for (int j = 0; j < scanSettings.channels.length; ++j) { - addChannel(scanSettings.channels[j].frequency); - } - } else { - addBand(scanSettings.band); - } - } - - /** - * Add all channels in the BucketSettings to the collection - */ - public void addChannels(WifiNative.BucketSettings bucketSettings) { - if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - for (int j = 0; j < bucketSettings.channels.length; ++j) { - addChannel(bucketSettings.channels[j].frequency); - } - } else { - addBand(bucketSettings.band); - } - } - - /** - * Checks if all channels in ScanSetting is in the collection - */ - public boolean containsSettings(WifiScanner.ScanSettings scanSettings) { - if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - for (int j = 0; j < scanSettings.channels.length; ++j) { - if (!containsChannel(scanSettings.channels[j].frequency)) { - return false; - } - } - return true; - } else { - return containsBand(scanSettings.band); - } - } - - /** - * Checks if at least some of the channels in ScanSetting is in the collection - */ - public boolean partiallyContainsSettings(WifiScanner.ScanSettings scanSettings) { - if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - for (int j = 0; j < scanSettings.channels.length; ++j) { - if (containsChannel(scanSettings.channels[j].frequency)) { - return true; - } - } - return false; - } else { - return partiallyContainsBand(scanSettings.band); - } - } - - /** - * Retrieves a list of missing channels in the collection from the provided settings. - */ - public Set<Integer> getMissingChannelsFromSettings(WifiScanner.ScanSettings scanSettings) { - if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - ArraySet<Integer> missingChannels = new ArraySet<>(); - for (int j = 0; j < scanSettings.channels.length; ++j) { - if (!containsChannel(scanSettings.channels[j].frequency)) { - missingChannels.add(scanSettings.channels[j].frequency); - } - } - return missingChannels; - } else { - return getMissingChannelsFromBand(scanSettings.band); - } - } - - /** - * Retrieves a list of containing channels in the collection from the provided settings. - */ - public Set<Integer> getContainingChannelsFromSettings( - WifiScanner.ScanSettings scanSettings) { - if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - ArraySet<Integer> containingChannels = new ArraySet<>(); - for (int j = 0; j < scanSettings.channels.length; ++j) { - if (containsChannel(scanSettings.channels[j].frequency)) { - containingChannels.add(scanSettings.channels[j].frequency); - } - } - return containingChannels; - } else { - return getContainingChannelsFromBand(scanSettings.band); - } - } - - /** - * Store the channels in this collection in the supplied BucketSettings. If maxChannels is - * exceeded or a band better describes the channels then a band is specified instead of a - * channel list. - */ - public abstract void fillBucketSettings(WifiNative.BucketSettings bucket, int maxChannels); - - /** - * Gets the list of channels scan. Will either be a collection of all channels or null - * if all channels should be scanned. - */ - public abstract Set<Integer> getScanFreqs(); - } - - - /* - * Utility methods for converting band/channels to strings - */ - - /** - * Create a string representation of the channels in the ScanSettings. - * If it contains a list of channels then the channels are returned, otherwise a string name of - * the band is returned. - */ - public static String toString(WifiScanner.ScanSettings scanSettings) { - if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - return toString(scanSettings.channels); - } else { - return bandToString(scanSettings.band); - } - } - - /** - * Create a string representation of the channels in the BucketSettings. - * If it contains a list of channels then the channels are returned, otherwise a string name of - * the band is returned. - */ - public static String toString(WifiNative.BucketSettings bucketSettings) { - if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - return toString(bucketSettings.channels, bucketSettings.num_channels); - } else { - return bandToString(bucketSettings.band); - } - } - - private static String toString(WifiScanner.ChannelSpec[] channels) { - if (channels == null) { - return "null"; - } - - StringBuilder sb = new StringBuilder(); - sb.append("["); - for (int c = 0; c < channels.length; c++) { - sb.append(channels[c].frequency); - if (c != channels.length - 1) { - sb.append(","); - } - } - sb.append("]"); - return sb.toString(); - } - - private static String toString(WifiNative.ChannelSettings[] channels, int numChannels) { - if (channels == null) { - return "null"; - } - - StringBuilder sb = new StringBuilder(); - sb.append("["); - for (int c = 0; c < numChannels; c++) { - sb.append(channels[c].frequency); - if (c != numChannels - 1) { - sb.append(","); - } - } - sb.append("]"); - return sb.toString(); - } - - /** - * Converts a WifiScanner.WIFI_BAND_* constant to a meaningful String - */ - public static String bandToString(int band) { - StringJoiner sj = new StringJoiner(" & "); - sj.setEmptyValue("unspecified"); - - if ((band & WifiScanner.WIFI_BAND_24_GHZ) != 0) { - sj.add("24Ghz"); - } - band &= ~WifiScanner.WIFI_BAND_24_GHZ; - - switch (band & WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS) { - case WifiScanner.WIFI_BAND_5_GHZ: - sj.add("5Ghz (no DFS)"); - break; - case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: - sj.add("5Ghz (DFS only)"); - break; - case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: - sj.add("5Ghz (DFS incl)"); - break; - } - band &= ~WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS; - - if ((band & WifiScanner.WIFI_BAND_6_GHZ) != 0) { - sj.add("6Ghz"); - } - band &= ~WifiScanner.WIFI_BAND_6_GHZ; - - if (band != 0) { - return "Invalid band"; - } - return sj.toString(); - } -} diff --git a/service/java/com/android/server/wifi/scanner/HalWifiScannerImpl.java b/service/java/com/android/server/wifi/scanner/HalWifiScannerImpl.java deleted file mode 100644 index 12f65958d..000000000 --- a/service/java/com/android/server/wifi/scanner/HalWifiScannerImpl.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import android.content.Context; -import android.net.wifi.WifiScanner; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiMonitor; -import com.android.server.wifi.WifiNative; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * WifiScanner implementation that takes advantage of the gscan HAL API - * The gscan API is used to perform background scans and wificond is used for oneshot scans. - * @see com.android.server.wifi.scanner.WifiScannerImpl for more details on each method. - */ -public class HalWifiScannerImpl extends WifiScannerImpl implements Handler.Callback { - private static final String TAG = "HalWifiScannerImpl"; - private static final boolean DBG = false; - - private final WifiNative mWifiNative; - private final ChannelHelper mChannelHelper; - private final WificondScannerImpl mWificondScannerDelegate; - - public HalWifiScannerImpl(Context context, String ifaceName, WifiNative wifiNative, - WifiMonitor wifiMonitor, Looper looper, Clock clock) { - super(ifaceName); - mWifiNative = wifiNative; - mChannelHelper = new WificondChannelHelper(wifiNative); - mWificondScannerDelegate = - new WificondScannerImpl(context, getIfaceName(), wifiNative, wifiMonitor, - mChannelHelper, looper, clock); - } - - @Override - public boolean handleMessage(Message msg) { - Log.w(TAG, "Unknown message received: " + msg.what); - return true; - } - - @Override - public void cleanup() { - mWificondScannerDelegate.cleanup(); - } - - @Override - public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { - return mWifiNative.getBgScanCapabilities( - getIfaceName(), capabilities); - } - - @Override - public ChannelHelper getChannelHelper() { - return mChannelHelper; - } - - public boolean startSingleScan(WifiNative.ScanSettings settings, - WifiNative.ScanEventHandler eventHandler) { - return mWificondScannerDelegate.startSingleScan(settings, eventHandler); - } - - @Override - public WifiScanner.ScanData getLatestSingleScanResults() { - return mWificondScannerDelegate.getLatestSingleScanResults(); - } - - @Override - public boolean startBatchedScan(WifiNative.ScanSettings settings, - WifiNative.ScanEventHandler eventHandler) { - if (settings == null || eventHandler == null) { - Log.w(TAG, "Invalid arguments for startBatched: settings=" + settings - + ",eventHandler=" + eventHandler); - return false; - } - return mWifiNative.startBgScan( - getIfaceName(), settings, eventHandler); - } - - @Override - public void stopBatchedScan() { - mWifiNative.stopBgScan(getIfaceName()); - } - - @Override - public void pauseBatchedScan() { - mWifiNative.pauseBgScan(getIfaceName()); - } - - @Override - public void restartBatchedScan() { - mWifiNative.restartBgScan(getIfaceName()); - } - - @Override - public WifiScanner.ScanData[] getLatestBatchedScanResults(boolean flush) { - return mWifiNative.getBgScanResults(getIfaceName()); - } - - @Override - public boolean setHwPnoList(WifiNative.PnoSettings settings, - WifiNative.PnoEventHandler eventHandler) { - return mWificondScannerDelegate.setHwPnoList(settings, eventHandler); - } - - @Override - public boolean resetHwPnoList() { - return mWificondScannerDelegate.resetHwPnoList(); - } - - @Override - public boolean isHwPnoSupported(boolean isConnectedPno) { - return mWificondScannerDelegate.isHwPnoSupported(isConnectedPno); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - mWificondScannerDelegate.dump(fd, pw, args); - } -} diff --git a/service/java/com/android/server/wifi/scanner/KnownBandsChannelHelper.java b/service/java/com/android/server/wifi/scanner/KnownBandsChannelHelper.java deleted file mode 100644 index 2de70d55e..000000000 --- a/service/java/com/android/server/wifi/scanner/KnownBandsChannelHelper.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.scanner; - -import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ; -import static android.net.wifi.WifiScanner.WIFI_BAND_5_GHZ; -import static android.net.wifi.WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY; -import static android.net.wifi.WifiScanner.WIFI_BAND_6_GHZ; -import static android.net.wifi.WifiScanner.WIFI_BAND_ALL; -import static android.net.wifi.WifiScanner.WIFI_BAND_COUNT; -import static android.net.wifi.WifiScanner.WIFI_BAND_INDEX_24_GHZ; -import static android.net.wifi.WifiScanner.WIFI_BAND_INDEX_5_GHZ; -import static android.net.wifi.WifiScanner.WIFI_BAND_INDEX_5_GHZ_DFS_ONLY; -import static android.net.wifi.WifiScanner.WIFI_BAND_INDEX_6_GHZ; -import static android.net.wifi.WifiScanner.WIFI_BAND_UNSPECIFIED; - -import android.net.wifi.ScanResult; -import android.net.wifi.WifiAnnotations.WifiBandBasic; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.WifiBandIndex; -import android.util.ArraySet; - -import com.android.server.wifi.WifiNative; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * ChannelHelper that offers channel manipulation utilities when the channels in a band are known. - * This allows more fine operations on channels than if band channels are not known. - */ -public class KnownBandsChannelHelper extends ChannelHelper { - // 5G low includes U-NII-1 and Japan 4.9G band - public static final int BAND_5_GHZ_LOW_END_FREQ = 5240; - // 5G middle includes U-NII-2A and U-NII-2C - public static final int BAND_5_GHZ_MID_END_FREQ = 5710; - // 5G high includes U-NII-3 - public static final int BAND_5_GHZ_HIGH_END_FREQ = ScanResult.BAND_5_GHZ_END_FREQ_MHZ; - // 6G low includes UNII-5 - public static final int BAND_6_GHZ_LOW_END_FREQ = 6425; - // 6G middle includes UNII-6 and UNII-7 - public static final int BAND_6_GHZ_MID_END_FREQ = 6875; - // 6G high includes UNII-8 - public static final int BAND_6_GHZ_HIGH_END_FREQ = ScanResult.BAND_6_GHZ_END_FREQ_MHZ; - - private WifiScanner.ChannelSpec[][] mBandsToChannels; - - protected void setBandChannels(int[] channels2G, int[] channels5G, int[] channelsDfs, - int[] channels6G) { - mBandsToChannels = new WifiScanner.ChannelSpec[WIFI_BAND_COUNT][]; - - if (channels2G.length != 0) { - mBandsToChannels[WIFI_BAND_INDEX_24_GHZ] = - new WifiScanner.ChannelSpec[channels2G.length]; - copyChannels(mBandsToChannels[WIFI_BAND_INDEX_24_GHZ], channels2G); - } else { - mBandsToChannels[WIFI_BAND_INDEX_24_GHZ] = NO_CHANNELS; - } - - if (channels5G.length != 0) { - mBandsToChannels[WIFI_BAND_INDEX_5_GHZ] = - new WifiScanner.ChannelSpec[channels5G.length]; - copyChannels(mBandsToChannels[WIFI_BAND_INDEX_5_GHZ], channels5G); - } else { - mBandsToChannels[WIFI_BAND_INDEX_5_GHZ] = NO_CHANNELS; - } - - if (channelsDfs.length != 0) { - mBandsToChannels[WIFI_BAND_INDEX_5_GHZ_DFS_ONLY] = - new WifiScanner.ChannelSpec[channelsDfs.length]; - copyChannels(mBandsToChannels[WIFI_BAND_INDEX_5_GHZ_DFS_ONLY], channelsDfs); - } else { - mBandsToChannels[WIFI_BAND_INDEX_5_GHZ_DFS_ONLY] = NO_CHANNELS; - } - - if (channels6G.length != 0) { - mBandsToChannels[WIFI_BAND_INDEX_6_GHZ] = - new WifiScanner.ChannelSpec[channels6G.length]; - copyChannels(mBandsToChannels[WIFI_BAND_INDEX_6_GHZ], channels6G); - } else { - mBandsToChannels[WIFI_BAND_INDEX_6_GHZ] = NO_CHANNELS; - } - } - - private static void copyChannels( - WifiScanner.ChannelSpec[] channelSpec, int[] channels) { - for (int i = 0; i < channels.length; i++) { - channelSpec[i] = new WifiScanner.ChannelSpec(channels[i]); - } - } - - @Override - public WifiScanner.ChannelSpec[][] getAvailableScanChannels(int band) { - if (band <= WIFI_BAND_UNSPECIFIED || band > WIFI_BAND_ALL) { - // Invalid value for band. - return null; - } - - WifiScanner.ChannelSpec[][] channels = new WifiScanner.ChannelSpec[WIFI_BAND_COUNT][]; - for (@WifiBandIndex int index = 0; index < WIFI_BAND_COUNT; index++) { - if ((band & (1 << index)) != 0) { - channels[index] = mBandsToChannels[index]; - } else { - channels[index] = NO_CHANNELS; - } - } - return channels; - } - - @Override - public boolean satisfies(ChannelHelper otherChannelHelper) { - if (!(otherChannelHelper instanceof KnownBandsChannelHelper)) return false; - KnownBandsChannelHelper otherKnownBandsChannelHelper = - (KnownBandsChannelHelper) otherChannelHelper; - // Compare all the channels in every band - for (@WifiBandIndex int i = 0; i < WIFI_BAND_COUNT; i++) { - Set<Integer> thisFrequencies = Arrays.stream(mBandsToChannels[i]) - .map(spec -> spec.frequency) - .collect(Collectors.toSet()); - Set<Integer> otherFrequencies = Arrays.stream( - otherKnownBandsChannelHelper.mBandsToChannels[i]) - .map(spec -> spec.frequency) - .collect(Collectors.toSet()); - if (!thisFrequencies.containsAll(otherFrequencies)) { - return false; - } - } - return true; - } - - @Override - public int estimateScanDuration(WifiScanner.ScanSettings settings) { - if (settings.band == WIFI_BAND_UNSPECIFIED) { - return settings.channels.length * SCAN_PERIOD_PER_CHANNEL_MS; - } else { - WifiScanner.ChannelSpec[][] channels = getAvailableScanChannels(settings.band); - int len = 0; - for (int i = 0; i < channels.length; ++i) { - len += channels[i].length; - } - return len * SCAN_PERIOD_PER_CHANNEL_MS; - } - } - - private boolean isDfsChannel(int frequency) { - for (WifiScanner.ChannelSpec dfsChannel : - mBandsToChannels[WIFI_BAND_INDEX_5_GHZ_DFS_ONLY]) { - if (frequency == dfsChannel.frequency) { - return true; - } - } - return false; - } - - // TODO this should be rewritten to be based on the input data instead of hardcoded ranges - private int getBandFromChannel(int frequency) { - if (ScanResult.is24GHz(frequency)) { - return WIFI_BAND_24_GHZ; - } else if (ScanResult.is5GHz(frequency)) { - if (isDfsChannel(frequency)) { - return WIFI_BAND_5_GHZ_DFS_ONLY; - } else { - return WIFI_BAND_5_GHZ; - } - } else if (ScanResult.is6GHz(frequency)) { - return WIFI_BAND_6_GHZ; - } else { - return WIFI_BAND_UNSPECIFIED; - } - } - - private @WifiBandIndex int getIndexForBand(@WifiBandBasic int band) { - switch (band) { - case WIFI_BAND_24_GHZ: - return WIFI_BAND_INDEX_24_GHZ; - case WIFI_BAND_5_GHZ: - return WIFI_BAND_INDEX_5_GHZ; - case WIFI_BAND_5_GHZ_DFS_ONLY: - return WIFI_BAND_INDEX_5_GHZ_DFS_ONLY; - case WIFI_BAND_6_GHZ: - return WIFI_BAND_INDEX_6_GHZ; - default: - return -1; - } - } - - @Override - public boolean settingsContainChannel(WifiScanner.ScanSettings settings, int channel) { - WifiScanner.ChannelSpec[] settingsChannels; - @WifiBandBasic int band; - // If band is not specified in settings, limit check on channels in settings - if (settings.band == WIFI_BAND_UNSPECIFIED) { - settingsChannels = settings.channels; - } else { - // Get the proper band for this channel - band = getBandFromChannel(channel); - // Check if this band is included in band specified in settings - if ((settings.band & band) == WIFI_BAND_UNSPECIFIED) { - return false; - } - - settingsChannels = mBandsToChannels[getIndexForBand(band)]; - } - // Now search for the channel - for (int i = 0; i < settingsChannels.length; ++i) { - if (settingsChannels[i].frequency == channel) { - return true; - } - } - return false; - } - - /** - * ChannelCollection that merges channels so that the optimal schedule will be generated. - * When the max channels value is satisfied this implementation will always create a channel - * list that includes no more than the added channels. - */ - public class KnownBandsChannelCollection extends ChannelCollection { - /** - * Stores all channels, including those that belong to added bands. - */ - private final ArraySet<Integer> mChannels = new ArraySet<Integer>(); - /** - * Contains only the bands that were explicitly added as bands. - */ - private int mExactBands = 0; - /** - * Contains all bands, including those that were added because an added channel was in that - * band. - */ - private int mAllBands = 0; - - @Override - public void addChannel(int frequency) { - mChannels.add(frequency); - mAllBands |= getBandFromChannel(frequency); - } - - @Override - public void addBand(int band) { - mExactBands |= band; - mAllBands |= band; - WifiScanner.ChannelSpec[][] bandChannels = getAvailableScanChannels(band); - for (int i = 0; i < bandChannels.length; ++i) { - for (int j = 0; j < bandChannels[i].length; ++j) { - mChannels.add(bandChannels[i][j].frequency); - } - } - } - - @Override - public boolean containsChannel(int channel) { - return mChannels.contains(channel); - } - - @Override - public boolean containsBand(int band) { - WifiScanner.ChannelSpec[][] bandChannels = getAvailableScanChannels(band); - for (int i = 0; i < bandChannels.length; ++i) { - for (int j = 0; j < bandChannels[i].length; ++j) { - if (!mChannels.contains(bandChannels[i][j].frequency)) { - return false; - } - } - } - return true; - } - - @Override - public boolean partiallyContainsBand(int band) { - WifiScanner.ChannelSpec[][] bandChannels = getAvailableScanChannels(band); - for (int i = 0; i < bandChannels.length; ++i) { - for (int j = 0; j < bandChannels[i].length; ++j) { - if (mChannels.contains(bandChannels[i][j].frequency)) { - return true; - } - } - } - return false; - } - - @Override - public boolean isEmpty() { - return mChannels.isEmpty(); - } - - @Override - public boolean isAllChannels() { - return containsBand(WIFI_BAND_ALL); - } - - @Override - public void clear() { - mAllBands = 0; - mExactBands = 0; - mChannels.clear(); - } - - @Override - public Set<Integer> getMissingChannelsFromBand(int band) { - ArraySet<Integer> missingChannels = new ArraySet<>(); - WifiScanner.ChannelSpec[][] bandChannels = getAvailableScanChannels(band); - for (int i = 0; i < bandChannels.length; ++i) { - for (int j = 0; j < bandChannels[i].length; ++j) { - if (!mChannels.contains(bandChannels[i][j].frequency)) { - missingChannels.add(bandChannels[i][j].frequency); - } - } - } - return missingChannels; - } - - @Override - public Set<Integer> getContainingChannelsFromBand(int band) { - ArraySet<Integer> containingChannels = new ArraySet<>(); - WifiScanner.ChannelSpec[][] bandChannels = getAvailableScanChannels(band); - for (int i = 0; i < bandChannels.length; ++i) { - for (int j = 0; j < bandChannels[i].length; ++j) { - if (mChannels.contains(bandChannels[i][j].frequency)) { - containingChannels.add(bandChannels[i][j].frequency); - } - } - } - return containingChannels; - } - - @Override - public Set<Integer> getChannelSet() { - if (!isEmpty() && mAllBands != mExactBands) { - return mChannels; - } else { - return new ArraySet<>(); - } - } - - @Override - public void fillBucketSettings(WifiNative.BucketSettings bucketSettings, int maxChannels) { - if ((mChannels.size() > maxChannels || mAllBands == mExactBands) - && mAllBands != 0) { - bucketSettings.band = mAllBands; - bucketSettings.num_channels = 0; - bucketSettings.channels = null; - } else { - bucketSettings.band = WIFI_BAND_UNSPECIFIED; - bucketSettings.num_channels = mChannels.size(); - bucketSettings.channels = new WifiNative.ChannelSettings[mChannels.size()]; - for (int i = 0; i < mChannels.size(); ++i) { - WifiNative.ChannelSettings channelSettings = new WifiNative.ChannelSettings(); - channelSettings.frequency = mChannels.valueAt(i); - bucketSettings.channels[i] = channelSettings; - } - } - } - - @Override - public Set<Integer> getScanFreqs() { - if (mExactBands == WIFI_BAND_ALL) { - return null; - } else { - return new ArraySet<Integer>(mChannels); - } - } - - public Set<Integer> getAllChannels() { - return new ArraySet<Integer>(mChannels); - } - } - - @Override - - public KnownBandsChannelCollection createChannelCollection() { - return new KnownBandsChannelCollection(); - } -} diff --git a/service/java/com/android/server/wifi/scanner/PresetKnownBandsChannelHelper.java b/service/java/com/android/server/wifi/scanner/PresetKnownBandsChannelHelper.java deleted file mode 100644 index e1ddd9182..000000000 --- a/service/java/com/android/server/wifi/scanner/PresetKnownBandsChannelHelper.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.scanner; - -/** - * KnownBandsChannelHelper that uses a supplied list of band to channels mappings. - */ -public class PresetKnownBandsChannelHelper extends KnownBandsChannelHelper { - public PresetKnownBandsChannelHelper(int[] channels2G, int[] channels5G, int[] channelsDfs, - int[] channels6G) { - setBandChannels(channels2G, channels5G, channelsDfs, channels6G); - } -} diff --git a/service/java/com/android/server/wifi/scanner/ScanScheduleUtil.java b/service/java/com/android/server/wifi/scanner/ScanScheduleUtil.java deleted file mode 100644 index ab127af13..000000000 --- a/service/java/com/android/server/wifi/scanner/ScanScheduleUtil.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import android.annotation.Nullable; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiScanner.ScanSettings; - -import com.android.server.wifi.WifiNative; - -import java.util.ArrayList; -import java.util.List; - -/** - * A class with utilities for dealing with scan schedules. - */ -public class ScanScheduleUtil { - - /** - * Compares two ChannelSettings for equality. - */ - public static boolean channelEquals(@Nullable WifiNative.ChannelSettings channel1, - @Nullable WifiNative.ChannelSettings channel2) { - if (channel1 == null || channel2 == null) return false; - if (channel1 == channel2) return true; - - if (channel1.frequency != channel2.frequency) return false; - if (channel1.dwell_time_ms != channel2.dwell_time_ms) return false; - return channel1.passive == channel2.passive; - } - - /** - * Compares two BucketSettings for equality. - */ - public static boolean bucketEquals(@Nullable WifiNative.BucketSettings bucket1, - @Nullable WifiNative.BucketSettings bucket2) { - if (bucket1 == null || bucket2 == null) return false; - if (bucket1 == bucket2) return true; - - if (bucket1.bucket != bucket2.bucket) return false; - if (bucket1.band != bucket2.band) return false; - if (bucket1.period_ms != bucket2.period_ms) return false; - if (bucket1.report_events != bucket2.report_events) return false; - if (bucket1.num_channels != bucket2.num_channels) return false; - for (int c = 0; c < bucket1.num_channels; c++) { - if (!channelEquals(bucket1.channels[c], bucket2.channels[c])) { - return false; - } - } - - return true; - } - - /** - * Compares two ScanSettings for equality. - */ - public static boolean scheduleEquals(@Nullable WifiNative.ScanSettings schedule1, - @Nullable WifiNative.ScanSettings schedule2) { - if (schedule1 == null || schedule2 == null) return false; - if (schedule1 == schedule2) return true; - - if (schedule1.base_period_ms != schedule2.base_period_ms) return false; - if (schedule1.max_ap_per_scan != schedule2.max_ap_per_scan) return false; - if (schedule1.report_threshold_percent != schedule2.report_threshold_percent) return false; - if (schedule1.report_threshold_num_scans != schedule2.report_threshold_num_scans) { - return false; - } - if (schedule1.num_buckets != schedule2.num_buckets) return false; - for (int b = 0; b < schedule1.num_buckets; b++) { - if (!bucketEquals(schedule1.buckets[b], schedule2.buckets[b])) { - return false; - } - } - - return true; - } - - /** - * Check if the specified bucket was scanned. If not all information is available then this - * method will return true. - * - * @param scheduledBucket Index of the bucket to check for, zero indexed, or -1 if any scan - * should be treated as scanning this bucket. - * @param bucketsScannedBitSet The bitset of all buckets scanned, 0 if unavailable - */ - private static boolean isBucketMaybeScanned(int scheduledBucket, int bucketsScannedBitSet) { - if (bucketsScannedBitSet == 0 || scheduledBucket < 0) { - return true; - } else { - return (bucketsScannedBitSet & (1 << scheduledBucket)) != 0; - } - } - - /** - * Check if the specified bucket was scanned. If not all information is available then this - * method will return false. - * - * @param scheduledBucket Index of the bucket to check for, zero indexed, or -1 if any scan - * should be treated as scanning this bucket. - * @param bucketsScannedBitSet The bitset of all buckets scanned, 0 if unavailable - */ - private static boolean isBucketDefinitlyScanned(int scheduledBucket, int bucketsScannedBitSet) { - if (scheduledBucket < 0) { - return true; - } else if (bucketsScannedBitSet == 0) { - return false; - } else { - return (bucketsScannedBitSet & (1 << scheduledBucket)) != 0; - } - } - - /** - * Returns true if the given scan result should be reported to a listener with the given - * settings. - */ - public static boolean shouldReportFullScanResultForSettings(ChannelHelper channelHelper, - ScanResult result, int bucketsScanned, ScanSettings settings, int scheduledBucket) { - if (isBucketMaybeScanned(scheduledBucket, bucketsScanned)) { - return channelHelper.settingsContainChannel(settings, result.frequency); - } else { - return false; - } - } - - /** - * Returns a filtered version of the scan results from the chip that represents only the data - * requested in the settings. Will return null if the result should not be reported. - * - * If a ScanData indicates that the bucket the settings were placed in was scanned then it - * will always be included (filtered to only include requested channels). If it indicates that - * the bucket was definitely not scanned then the scan data will not be reported. - * If it is not possible to determine if the settings bucket was scanned or not then a - * ScanData will be included if the scan was empty or there was at least one scan result that - * matches a requested channel (again the results will be filtered to only include requested - * channels. - */ - public static ScanData[] filterResultsForSettings(ChannelHelper channelHelper, - ScanData[] scanDatas, ScanSettings settings, int scheduledBucket) { - List<ScanData> filteredScanDatas = new ArrayList<>(scanDatas.length); - List<ScanResult> filteredResults = new ArrayList<>(); - for (ScanData scanData : scanDatas) { - // only report ScanData if the settings bucket could have been scanned - if (isBucketMaybeScanned(scheduledBucket, scanData.getBucketsScanned())) { - filteredResults.clear(); - for (ScanResult scanResult : scanData.getResults()) { - if (channelHelper.settingsContainChannel(settings, scanResult.frequency)) { - filteredResults.add(scanResult); - } - if (settings.numBssidsPerScan > 0 - && filteredResults.size() >= settings.numBssidsPerScan) { - break; - } - } - // will include scan results if the scan was empty, there was at least one - // one result that matched the scan request or we are sure that all the requested - // channels were scanned. - if (filteredResults.size() == scanData.getResults().length) { - filteredScanDatas.add(scanData); - } else if (filteredResults.size() > 0 || isBucketDefinitlyScanned(scheduledBucket, - scanData.getBucketsScanned())) { - filteredScanDatas.add(new ScanData(scanData.getId(), - scanData.getFlags(), - 0, - scanData.getBandScanned(), - filteredResults.toArray( - new ScanResult[filteredResults.size()]))); - } - } - } - if (filteredScanDatas.size() == 0) { - return null; - } else { - return filteredScanDatas.toArray(new ScanData[filteredScanDatas.size()]); - } - } -} diff --git a/service/java/com/android/server/wifi/scanner/WifiScannerImpl.java b/service/java/com/android/server/wifi/scanner/WifiScannerImpl.java deleted file mode 100644 index c99117fdb..000000000 --- a/service/java/com/android/server/wifi/scanner/WifiScannerImpl.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiScanner; -import android.os.Looper; -import android.text.TextUtils; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiMonitor; -import com.android.server.wifi.WifiNative; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Comparator; - -/** - * Defines the interface to the Wifi hardware required for the WifiScanner API - */ -public abstract class WifiScannerImpl { - - /** - * A factory that create a {@link com.android.server.wifi.scanner.WifiScannerImpl} - */ - public static interface WifiScannerImplFactory { - /** - * Create instance of {@link WifiScannerImpl}. - */ - WifiScannerImpl create(Context context, Looper looper, Clock clock, - @NonNull String ifaceName); - } - - /** - * Factory that create the implementation that is most appropriate for the system. - * This factory should only ever be used once. - */ - public static final WifiScannerImplFactory DEFAULT_FACTORY = new WifiScannerImplFactory() { - public WifiScannerImpl create(Context context, Looper looper, Clock clock, - @NonNull String ifaceName) { - WifiNative wifiNative = WifiInjector.getInstance().getWifiNative(); - WifiMonitor wifiMonitor = WifiInjector.getInstance().getWifiMonitor(); - if (TextUtils.isEmpty(ifaceName)) { - return null; - } - if (wifiNative.getBgScanCapabilities( - ifaceName, new WifiNative.ScanCapabilities())) { - return new HalWifiScannerImpl(context, ifaceName, wifiNative, wifiMonitor, - looper, clock); - } else { - return new WificondScannerImpl(context, ifaceName, wifiNative, wifiMonitor, - new WificondChannelHelper(wifiNative), looper, clock); - } - } - }; - - /** - * A comparator that implements the sort order that is expected for scan results - */ - protected static final Comparator<ScanResult> SCAN_RESULT_SORT_COMPARATOR = - new Comparator<ScanResult>() { - public int compare(ScanResult r1, ScanResult r2) { - return r2.level - r1.level; - } - }; - - private final String mIfaceName; - - WifiScannerImpl(@NonNull String ifaceName) { - mIfaceName = ifaceName; - } - - /** - * Get the interface name used by this instance of {@link WifiScannerImpl} - */ - public @NonNull String getIfaceName() { - return mIfaceName; - } - - /** - * Cleanup any ongoing operations. This may be called when the driver is unloaded. - * There is no expectation that failure events are returned for ongoing operations. - */ - public abstract void cleanup(); - - /** - * Get the supported scan capabilities. - * - * @param capabilities Object that will be filled with the supported capabilities if successful - * @return true if the scan capabilities were retrieved successfully - */ - public abstract boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities); - - /** - * Get a ChannelHelper that can be used to perform operations on scan channels - */ - public abstract ChannelHelper getChannelHelper(); - - /** - * Start a one time scan. This method should only be called when there is no scan going on - * (after a callback indicating that the previous scan succeeded/failed). - * @return if the scan paramaters are valid - * Note this may return true even if the parameters are not accepted by the chip because the - * scan may be scheduled async. - */ - public abstract boolean startSingleScan(WifiNative.ScanSettings settings, - WifiNative.ScanEventHandler eventHandler); - /** - * Get the scan results of the most recent single scan. This should be called immediately when - * the scan success callback is receieved. - */ - public abstract WifiScanner.ScanData getLatestSingleScanResults(); - - /** - * Start a background scan. Calling this method while a background scan is already in process - * will interrupt the previous scan settings and replace it with the new ones. - * @return if the scan paramaters are valid - * Note this may return true even if the parameters are not accepted by the chip because the - * scan may be scheduled async. - */ - public abstract boolean startBatchedScan(WifiNative.ScanSettings settings, - WifiNative.ScanEventHandler eventHandler); - /** - * Stop the currently active background scan - */ - public abstract void stopBatchedScan(); - - /** - * Pause the currently active background scan - */ - public abstract void pauseBatchedScan(); - - /** - * Restart the currently paused background scan - */ - public abstract void restartBatchedScan(); - - /** - * Get the latest cached scan results from the last scan event. This should be called - * immediately when the scan success callback is receieved. - */ - public abstract WifiScanner.ScanData[] getLatestBatchedScanResults(boolean flush); - - /** - * Set PNO list to start PNO background scan. - * @param settings PNO settings for this scan. - * @param eventHandler Event handler for notifying the scan results. - * @return true if success, false otherwise - */ - public abstract boolean setHwPnoList(WifiNative.PnoSettings settings, - WifiNative.PnoEventHandler eventHandler); - - /** - * Reset PNO list to terminate PNO background scan. - * @return true if success, false otherwise - */ - public abstract boolean resetHwPnoList(); - - /** - * This returns whether HW PNO is supported or not. - * @param isConnectedPno Whether this is connected PNO vs disconnected PNO. - * @return true if HW PNO is supported, false otherwise. - */ - public abstract boolean isHwPnoSupported(boolean isConnectedPno); - - protected abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args); -} diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningService.java b/service/java/com/android/server/wifi/scanner/WifiScanningService.java deleted file mode 100644 index 8ec0d15e2..000000000 --- a/service/java/com/android/server/wifi/scanner/WifiScanningService.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008 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.server.wifi.scanner; - -import android.content.Context; -import android.os.BatteryStatsManager; -import android.os.HandlerThread; -import android.util.Log; - -import com.android.server.SystemService; -import com.android.server.wifi.WifiContext; -import com.android.server.wifi.WifiInjector; - -/** - * Service implementing Wi-Fi scanning functionality. Delegates actual interface - * implementation to WifiScanningServiceImpl. - */ -public class WifiScanningService extends SystemService { - - static final String TAG = "WifiScanningService"; - private final WifiScanningServiceImpl mImpl; - private final HandlerThread mHandlerThread; - - public WifiScanningService(Context contextBase) { - super(new WifiContext(contextBase)); - Log.i(TAG, "Creating " + Context.WIFI_SCANNING_SERVICE); - mHandlerThread = new HandlerThread("WifiScanningService"); - mHandlerThread.start(); - mImpl = new WifiScanningServiceImpl(getContext(), mHandlerThread.getLooper(), - WifiScannerImpl.DEFAULT_FACTORY, - getContext().getSystemService(BatteryStatsManager.class), - WifiInjector.getInstance()); - } - - @Override - public void onStart() { - Log.i(TAG, "Publishing " + Context.WIFI_SCANNING_SERVICE); - publishBinderService(Context.WIFI_SCANNING_SERVICE, mImpl); - } - - @Override - public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { - Log.i(TAG, "Starting " + Context.WIFI_SCANNING_SERVICE); - mImpl.startService(); - } - } -} diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java deleted file mode 100644 index 716b206c3..000000000 --- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java +++ /dev/null @@ -1,2666 +0,0 @@ -/* - * Copyright (C) 2008 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.server.wifi.scanner; - -import static android.content.pm.PackageManager.PERMISSION_DENIED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.AlarmManager; -import android.content.Context; -import android.net.wifi.IWifiScanner; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiAnnotations; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ChannelSpec; -import android.net.wifi.WifiScanner.PnoSettings; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiScanner.ScanSettings; -import android.net.wifi.WifiScanner.WifiBand; -import android.os.BadParcelableException; -import android.os.BatteryStatsManager; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.os.WorkSource; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.LocalLog; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; -import com.android.internal.util.Protocol; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import com.android.server.wifi.ClientModeImpl; -import com.android.server.wifi.Clock; -import com.android.server.wifi.FrameworkFacade; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiLog; -import com.android.server.wifi.WifiMetrics; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.WifiThreadRunner; -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; -import com.android.server.wifi.util.ArrayUtils; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiHandler; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WorkSourceUtil; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class WifiScanningServiceImpl extends IWifiScanner.Stub { - - private static final String TAG = WifiScanningService.TAG; - private static final boolean DBG = false; - - private static final int UNKNOWN_PID = -1; - - private final LocalLog mLocalLog = new LocalLog(512); - - private WifiLog mLog; - - private void localLog(String message) { - mLocalLog.log(message); - } - - private void logw(String message) { - Log.w(TAG, message); - mLocalLog.log(message); - } - - private void loge(String message) { - Log.e(TAG, message); - mLocalLog.log(message); - } - - @Override - public Messenger getMessenger() { - if (mClientHandler != null) { - mLog.trace("getMessenger() uid=%").c(Binder.getCallingUid()).flush(); - return new Messenger(mClientHandler); - } - loge("WifiScanningServiceImpl trying to get messenger w/o initialization"); - return null; - } - - @Override - public Bundle getAvailableChannels(@WifiBand int band, String packageName, - @Nullable String attributionTag) { - int uid = Binder.getCallingUid(); - long ident = Binder.clearCallingIdentity(); - try { - enforcePermission(uid, packageName, attributionTag, false, false, false); - } finally { - Binder.restoreCallingIdentity(ident); - } - - ChannelSpec[][] channelSpecs = mWifiThreadRunner.call(() -> { - if (mChannelHelper == null) return new ChannelSpec[0][0]; - mChannelHelper.updateChannels(); - return mChannelHelper.getAvailableScanChannels(band); - }, new ChannelSpec[0][0]); - - ArrayList<Integer> list = new ArrayList<>(); - for (int i = 0; i < channelSpecs.length; i++) { - for (ChannelSpec channelSpec : channelSpecs[i]) { - list.add(channelSpec.frequency); - } - } - Bundle b = new Bundle(); - b.putIntegerArrayList(WifiScanner.GET_AVAILABLE_CHANNELS_EXTRA, list); - mLog.trace("getAvailableChannels uid=%").c(Binder.getCallingUid()).flush(); - return b; - } - - private void enforceNetworkStack(int uid) { - mContext.enforcePermission( - Manifest.permission.NETWORK_STACK, - UNKNOWN_PID, uid, - "NetworkStack"); - } - - // Helper method to check if the incoming message is for a privileged request. - private boolean isPrivilegedMessage(int msgWhat) { - return (msgWhat == WifiScanner.CMD_ENABLE - || msgWhat == WifiScanner.CMD_DISABLE - || msgWhat == WifiScanner.CMD_START_PNO_SCAN - || msgWhat == WifiScanner.CMD_STOP_PNO_SCAN - || msgWhat == WifiScanner.CMD_REGISTER_SCAN_LISTENER); - } - - // For non-privileged requests, retrieve the bundled package name for app-op & permission - // checks. - private String getPackageName(Message msg) { - if (!(msg.obj instanceof Bundle)) { - return null; - } - Bundle bundle = (Bundle) msg.obj; - return bundle.getString(WifiScanner.REQUEST_PACKAGE_NAME_KEY); - } - - // For non-privileged requests, retrieve the bundled attributionTag name for app-op & permission - // checks. - private String getAttributionTag(Message msg) { - if (!(msg.obj instanceof Bundle)) { - return null; - } - Bundle bundle = (Bundle) msg.obj; - return bundle.getString(WifiScanner.REQUEST_FEATURE_ID_KEY); - } - - - // Check if we should ignore location settings if this is a single scan request. - private boolean shouldIgnoreLocationSettingsForSingleScan(Message msg) { - if (msg.what != WifiScanner.CMD_START_SINGLE_SCAN) return false; - if (!(msg.obj instanceof Bundle)) return false; - Bundle bundle = (Bundle) msg.obj; - ScanSettings scanSettings = bundle.getParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY); - return scanSettings.ignoreLocationSettings; - } - - // Check if we should hide this request from app-ops if this is a single scan request. - private boolean shouldHideFromAppsForSingleScan(Message msg) { - if (msg.what != WifiScanner.CMD_START_SINGLE_SCAN) return false; - if (!(msg.obj instanceof Bundle)) return false; - Bundle bundle = (Bundle) msg.obj; - ScanSettings scanSettings = bundle.getParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY); - return scanSettings.hideFromAppOps; - } - - /** - * @see #enforcePermission(int, String, String, boolean, boolean, boolean) - */ - private void enforcePermission(int uid, Message msg) throws SecurityException { - enforcePermission(uid, getPackageName(msg), getAttributionTag(msg), - isPrivilegedMessage(msg.what), shouldIgnoreLocationSettingsForSingleScan(msg), - shouldHideFromAppsForSingleScan(msg)); - } - - /** - * Enforce the necessary client permissions for WifiScanner. - * If the client has NETWORK_STACK permission, then it can "always" send "any" request. - * If the client has only LOCATION_HARDWARE permission, then it can - * a) Only make scan related requests when location is turned on. - * b) Can never make one of the privileged requests. - * @param uid uid of the client - * @param packageName package name of the client - * @param attributionTag The feature in the package of the client - * @param isPrivilegedRequest whether we are checking for a privileged request - * @param shouldIgnoreLocationSettings override to ignore location settings - * @param shouldHideFromApps override to hide request from AppOps - */ - private void enforcePermission(int uid, String packageName, @Nullable String attributionTag, - boolean isPrivilegedRequest, boolean shouldIgnoreLocationSettings, - boolean shouldHideFromApps) { - try { - /** Wifi stack issued requests.*/ - enforceNetworkStack(uid); - } catch (SecurityException e) { - // System-app issued requests - if (isPrivilegedRequest) { - // Privileged message, only requests from clients with NETWORK_STACK allowed! - throw e; - } - mWifiPermissionsUtil.enforceCanAccessScanResultsForWifiScanner(packageName, - attributionTag, uid, shouldIgnoreLocationSettings, shouldHideFromApps); - } - } - - private class ClientHandler extends WifiHandler { - - ClientHandler(String tag, Looper looper) { - super(tag, looper); - } - - @Override - public void handleMessage(Message msg) { - super.handleMessage(msg); - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { - if (msg.replyTo == null) { - logw("msg.replyTo is null"); - return; - } - ExternalClientInfo client = (ExternalClientInfo) mClients.get(msg.replyTo); - if (client != null) { - logw("duplicate client connection: " + msg.sendingUid + ", messenger=" - + msg.replyTo); - client.mChannel.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, - AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED); - return; - } - - AsyncChannel ac = mFrameworkFacade.makeWifiAsyncChannel(TAG); - ac.connected(mContext, this, msg.replyTo); - - client = new ExternalClientInfo(msg.sendingUid, msg.replyTo, ac); - client.register(); - - ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, - AsyncChannel.STATUS_SUCCESSFUL); - localLog("client connected: " + client); - return; - } - case AsyncChannel.CMD_CHANNEL_DISCONNECT: { - ExternalClientInfo client = (ExternalClientInfo) mClients.get(msg.replyTo); - if (client != null) { - client.mChannel.disconnect(); - } - return; - } - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { - ExternalClientInfo client = (ExternalClientInfo) mClients.get(msg.replyTo); - if (client != null && msg.arg1 != AsyncChannel.STATUS_SEND_UNSUCCESSFUL - && msg.arg1 - != AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED) { - localLog("client disconnected: " + client + ", reason: " + msg.arg1); - client.cleanup(); - } - return; - } - } - - try { - enforcePermission(msg.sendingUid, msg); - } catch (SecurityException e) { - localLog("failed to authorize app: " + e); - replyFailed(msg, WifiScanner.REASON_NOT_AUTHORIZED, "Not authorized"); - return; - } - - // Since the CMD_GET_SCAN_RESULTS and CMD_GET_SINGLE_SCAN_RESULTS messages are - // sent from WifiScanner using |sendMessageSynchronously|, handle separately since - // the |msg.replyTo| field does not actually correspond to the Messenger that is - // registered for that client. - if (msg.what == WifiScanner.CMD_GET_SCAN_RESULTS) { - mBackgroundScanStateMachine.sendMessage(Message.obtain(msg)); - return; - } - if (msg.what == WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS) { - mSingleScanStateMachine.sendMessage(Message.obtain(msg)); - return; - } - - ClientInfo ci = mClients.get(msg.replyTo); - if (ci == null) { - loge("Could not find client info for message " + msg.replyTo + ", msg=" + msg); - replyFailed(msg, WifiScanner.REASON_INVALID_LISTENER, "Could not find listener"); - return; - } - - switch (msg.what) { - case WifiScanner.CMD_ENABLE: - Log.i(TAG, "Received a request to enable scanning, UID = " + msg.sendingUid); - setupScannerImpls(); - mBackgroundScanStateMachine.sendMessage(Message.obtain(msg)); - mSingleScanStateMachine.sendMessage(Message.obtain(msg)); - mPnoScanStateMachine.sendMessage(Message.obtain(msg)); - break; - case WifiScanner.CMD_DISABLE: - Log.i(TAG, "Received a request to disable scanning, UID = " + msg.sendingUid); - teardownScannerImpls(); - mBackgroundScanStateMachine.sendMessage(Message.obtain(msg)); - mSingleScanStateMachine.sendMessage(Message.obtain(msg)); - mPnoScanStateMachine.sendMessage(Message.obtain(msg)); - break; - case WifiScanner.CMD_START_BACKGROUND_SCAN: - case WifiScanner.CMD_STOP_BACKGROUND_SCAN: - mBackgroundScanStateMachine.sendMessage(Message.obtain(msg)); - break; - case WifiScanner.CMD_START_PNO_SCAN: - case WifiScanner.CMD_STOP_PNO_SCAN: - mPnoScanStateMachine.sendMessage(Message.obtain(msg)); - break; - case WifiScanner.CMD_START_SINGLE_SCAN: - case WifiScanner.CMD_STOP_SINGLE_SCAN: - mSingleScanStateMachine.sendMessage(Message.obtain(msg)); - break; - case WifiScanner.CMD_REGISTER_SCAN_LISTENER: - logScanRequest("registerScanListener", ci, msg.arg2, null, null, null); - mSingleScanListeners.addRequest(ci, msg.arg2, null, null); - replySucceeded(msg); - break; - case WifiScanner.CMD_DEREGISTER_SCAN_LISTENER: - logScanRequest("deregisterScanListener", ci, msg.arg2, null, null, null); - mSingleScanListeners.removeRequest(ci, msg.arg2); - break; - default: - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "Invalid request"); - break; - } - } - } - - private static final int BASE = Protocol.BASE_WIFI_SCANNER_SERVICE; - - private static final int CMD_SCAN_RESULTS_AVAILABLE = BASE + 0; - private static final int CMD_FULL_SCAN_RESULTS = BASE + 1; - private static final int CMD_SCAN_PAUSED = BASE + 8; - private static final int CMD_SCAN_RESTARTED = BASE + 9; - private static final int CMD_SCAN_FAILED = BASE + 10; - private static final int CMD_PNO_NETWORK_FOUND = BASE + 11; - private static final int CMD_PNO_SCAN_FAILED = BASE + 12; - - private final Context mContext; - private final Looper mLooper; - private final WifiThreadRunner mWifiThreadRunner; - private final WifiScannerImpl.WifiScannerImplFactory mScannerImplFactory; - private final ArrayMap<Messenger, ClientInfo> mClients; - private final Map<String, WifiScannerImpl> mScannerImpls; - - - private final RequestList<Void> mSingleScanListeners = new RequestList<>(); - - private ChannelHelper mChannelHelper; - private BackgroundScanScheduler mBackgroundScheduler; - private WifiNative.ScanSettings mPreviousSchedule; - - private WifiBackgroundScanStateMachine mBackgroundScanStateMachine; - private WifiSingleScanStateMachine mSingleScanStateMachine; - private WifiPnoScanStateMachine mPnoScanStateMachine; - private ClientHandler mClientHandler; - private final BatteryStatsManager mBatteryStats; - private final AlarmManager mAlarmManager; - private final WifiMetrics mWifiMetrics; - private final Clock mClock; - private final FrameworkFacade mFrameworkFacade; - private final WifiPermissionsUtil mWifiPermissionsUtil; - private final WifiNative mWifiNative; - - WifiScanningServiceImpl(Context context, Looper looper, - WifiScannerImpl.WifiScannerImplFactory scannerImplFactory, - BatteryStatsManager batteryStats, WifiInjector wifiInjector) { - mContext = context; - mLooper = looper; - mWifiThreadRunner = new WifiThreadRunner(new Handler(looper)); - mScannerImplFactory = scannerImplFactory; - mBatteryStats = batteryStats; - mClients = new ArrayMap<>(); - mScannerImpls = new ArrayMap<>(); - mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); - mWifiMetrics = wifiInjector.getWifiMetrics(); - mClock = wifiInjector.getClock(); - mLog = wifiInjector.makeLog(TAG); - mFrameworkFacade = wifiInjector.getFrameworkFacade(); - mWifiPermissionsUtil = wifiInjector.getWifiPermissionsUtil(); - mWifiNative = wifiInjector.getWifiNative(); - mPreviousSchedule = null; - } - - public void startService() { - mWifiThreadRunner.post(() -> { - mBackgroundScanStateMachine = new WifiBackgroundScanStateMachine(mLooper); - mSingleScanStateMachine = new WifiSingleScanStateMachine(mLooper); - mPnoScanStateMachine = new WifiPnoScanStateMachine(mLooper); - - mBackgroundScanStateMachine.start(); - mSingleScanStateMachine.start(); - mPnoScanStateMachine.start(); - - // Create client handler only after StateMachines are ready. - mClientHandler = new ClientHandler(TAG, mLooper); - }); - } - - /** - * Checks if all the channels provided by the new impl is already satisfied by an existing impl. - * - * Note: This only handles the cases where the 2 ifaces are on different chips with - * distinctly different bands supported on both. If there are cases where - * the 2 ifaces support overlapping bands, then we probably need to rework this. - * For example: wlan0 supports 2.4G only, wlan1 supports 2.4G + 5G + DFS. - * In the above example, we should teardown wlan0 impl when wlan1 impl is created - * because wlan1 impl can already handle all the supported bands. - * Ignoring this for now since we don't foresee this requirement in the near future. - */ - private boolean doesAnyExistingImplSatisfy(WifiScannerImpl newImpl) { - for (WifiScannerImpl existingImpl : mScannerImpls.values()) { - if (existingImpl.getChannelHelper().satisfies(newImpl.getChannelHelper())) { - return true; - } - } - return false; - } - - private void setupScannerImpls() { - Set<String> ifaceNames = mWifiNative.getClientInterfaceNames(); - if (ArrayUtils.isEmpty(ifaceNames)) { - loge("Failed to retrieve client interface names"); - return; - } - Set<String> ifaceNamesOfImplsAlreadySetup = mScannerImpls.keySet(); - if (ifaceNames.equals(ifaceNamesOfImplsAlreadySetup)) { - // Scanner Impls already exist for all ifaces (back to back CMD_ENABLE sent?). - Log.i(TAG, "scanner impls already exists"); - return; - } - // set of impls to teardown. - Set<String> ifaceNamesOfImplsToTeardown = new ArraySet<>(ifaceNamesOfImplsAlreadySetup); - ifaceNamesOfImplsToTeardown.removeAll(ifaceNames); - // set of impls to be considered for setup. - Set<String> ifaceNamesOfImplsToSetup = new ArraySet<>(ifaceNames); - ifaceNamesOfImplsToSetup.removeAll(ifaceNamesOfImplsAlreadySetup); - - for (String ifaceName : ifaceNamesOfImplsToTeardown) { - WifiScannerImpl impl = mScannerImpls.remove(ifaceName); - if (impl == null) continue; // should never happen - impl.cleanup(); - Log.i(TAG, "Removed an impl for " + ifaceName); - } - for (String ifaceName : ifaceNamesOfImplsToSetup) { - WifiScannerImpl impl = mScannerImplFactory.create(mContext, mLooper, mClock, ifaceName); - if (impl == null) { - loge("Failed to create scanner impl for " + ifaceName); - continue; - } - // If this new scanner impl does not offer any new bands to scan, then we should - // ignore it. - if (!doesAnyExistingImplSatisfy(impl)) { - mScannerImpls.put(ifaceName, impl); - Log.i(TAG, "Created a new impl for " + ifaceName); - } else { - Log.i(TAG, "All the channels on the new impl for iface " + ifaceName - + " are already satisfied by an existing impl. Skipping.."); - impl.cleanup(); // cleanup the impl before discarding. - } - } - } - - private void teardownScannerImpls() { - for (Map.Entry<String, WifiScannerImpl> entry : mScannerImpls.entrySet()) { - WifiScannerImpl impl = entry.getValue(); - String ifaceName = entry.getKey(); - if (impl == null) continue; // should never happen - impl.cleanup(); - Log.i(TAG, "Removed an impl for " + ifaceName); - } - mScannerImpls.clear(); - } - - /** - * Provide a way for unit tests to set valid log object in the WifiHandler - * @param log WifiLog object to assign to the clientHandler - */ - @VisibleForTesting - public void setWifiHandlerLogForTest(WifiLog log) { - mClientHandler.setWifiLog(log); - } - - private WorkSource computeWorkSource(ClientInfo ci, WorkSource requestedWorkSource) { - if (requestedWorkSource != null && !requestedWorkSource.isEmpty()) { - return requestedWorkSource.withoutNames(); - } - - if (ci.getUid() > 0) { - return new WorkSource(ci.getUid()); - } - - // We can't construct a sensible WorkSource because the one supplied to us was empty and - // we don't have a valid UID for the given client. - loge("Unable to compute workSource for client: " + ci + ", requested: " - + requestedWorkSource); - return new WorkSource(); - } - - private class RequestInfo<T> { - final ClientInfo clientInfo; - final int handlerId; - final WorkSource workSource; - final T settings; - - RequestInfo(ClientInfo clientInfo, int handlerId, WorkSource requestedWorkSource, - T settings) { - this.clientInfo = clientInfo; - this.handlerId = handlerId; - this.settings = settings; - this.workSource = computeWorkSource(clientInfo, requestedWorkSource); - } - - void reportEvent(int what, int arg1, Object obj) { - clientInfo.reportEvent(what, arg1, handlerId, obj); - } - } - - private class RequestList<T> extends ArrayList<RequestInfo<T>> { - void addRequest(ClientInfo ci, int handler, WorkSource reqworkSource, T settings) { - add(new RequestInfo<T>(ci, handler, reqworkSource, settings)); - } - - T removeRequest(ClientInfo ci, int handlerId) { - T removed = null; - Iterator<RequestInfo<T>> iter = iterator(); - while (iter.hasNext()) { - RequestInfo<T> entry = iter.next(); - if (entry.clientInfo == ci && entry.handlerId == handlerId) { - removed = entry.settings; - iter.remove(); - } - } - return removed; - } - - Collection<T> getAllSettings() { - ArrayList<T> settingsList = new ArrayList<>(); - Iterator<RequestInfo<T>> iter = iterator(); - while (iter.hasNext()) { - RequestInfo<T> entry = iter.next(); - settingsList.add(entry.settings); - } - return settingsList; - } - - Collection<T> getAllSettingsForClient(ClientInfo ci) { - ArrayList<T> settingsList = new ArrayList<>(); - Iterator<RequestInfo<T>> iter = iterator(); - while (iter.hasNext()) { - RequestInfo<T> entry = iter.next(); - if (entry.clientInfo == ci) { - settingsList.add(entry.settings); - } - } - return settingsList; - } - - void removeAllForClient(ClientInfo ci) { - Iterator<RequestInfo<T>> iter = iterator(); - while (iter.hasNext()) { - RequestInfo<T> entry = iter.next(); - if (entry.clientInfo == ci) { - iter.remove(); - } - } - } - - WorkSource createMergedWorkSource() { - WorkSource mergedSource = new WorkSource(); - for (RequestInfo<T> entry : this) { - mergedSource.add(entry.workSource); - } - return mergedSource; - } - } - - /** - * State machine that holds the state of single scans. Scans should only be active in the - * ScanningState. The pending scans and active scans maps are swapped when entering - * ScanningState. Any requests queued while scanning will be placed in the pending queue and - * executed after transitioning back to IdleState. - */ - class WifiSingleScanStateMachine extends StateMachine { - /** - * Maximum age of results that we return from our cache via - * {@link WifiScanner#getScanResults()}. - * This is currently set to 3 minutes to restore parity with the wpa_supplicant's scan - * result cache expiration policy. (See b/62253332 for details) - */ - @VisibleForTesting - public static final int CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS = 180 * 1000; - - private final DefaultState mDefaultState = new DefaultState(); - private final DriverStartedState mDriverStartedState = new DriverStartedState(); - private final IdleState mIdleState = new IdleState(); - private final ScanningState mScanningState = new ScanningState(); - - private WifiNative.ScanSettings mActiveScanSettings = null; - private RequestList<ScanSettings> mActiveScans = new RequestList<>(); - private RequestList<ScanSettings> mPendingScans = new RequestList<>(); - - // Scan results cached from the last full single scan request. - private final List<ScanResult> mCachedScanResults = new ArrayList<>(); - - // Tracks scan requests across multiple scanner impls. - private final ScannerImplsTracker mScannerImplsTracker; - - WifiSingleScanStateMachine(Looper looper) { - super("WifiSingleScanStateMachine", looper); - - mScannerImplsTracker = new ScannerImplsTracker(); - - setLogRecSize(128); - setLogOnlyTransitions(false); - - // CHECKSTYLE:OFF IndentationCheck - addState(mDefaultState); - addState(mDriverStartedState, mDefaultState); - addState(mIdleState, mDriverStartedState); - addState(mScanningState, mDriverStartedState); - // CHECKSTYLE:ON IndentationCheck - - setInitialState(mDefaultState); - } - - /** - * Tracks a single scan request across all the available scanner impls. - * - * a) Initiates the scan using the same ScanSettings across all the available impls. - * b) Waits for all the impls to report the status of the scan request (success or failure). - * c) Calculates a consolidated scan status and sends the results if successful. - * Note: If there are failures on some of the scanner impls, we ignore them since we will - * get some scan results from the other successful impls. We don't declare total scan - * failures, unless all the scanner impls fail. - */ - private final class ScannerImplsTracker { - private final class ScanEventHandler implements WifiNative.ScanEventHandler { - private final String mImplIfaceName; - ScanEventHandler(@NonNull String implIfaceName) { - mImplIfaceName = implIfaceName; - } - - /** - * Called to indicate a change in state for the current scan. - * Will dispatch a corresponding event to the state machine - */ - @Override - public void onScanStatus(int event) { - if (DBG) localLog("onScanStatus event received, event=" + event); - switch (event) { - case WifiNative.WIFI_SCAN_RESULTS_AVAILABLE: - case WifiNative.WIFI_SCAN_THRESHOLD_NUM_SCANS: - case WifiNative.WIFI_SCAN_THRESHOLD_PERCENT: - reportScanStatusForImpl(mImplIfaceName, STATUS_SUCCEEDED); - break; - case WifiNative.WIFI_SCAN_FAILED: - reportScanStatusForImpl(mImplIfaceName, STATUS_FAILED); - break; - default: - Log.e(TAG, "Unknown scan status event: " + event); - break; - } - } - - /** - * Called for each full scan result if requested - */ - @Override - public void onFullScanResult(ScanResult fullScanResult, int bucketsScanned) { - if (DBG) localLog("onFullScanResult received"); - reportFullScanResultForImpl(mImplIfaceName, fullScanResult, bucketsScanned); - } - - @Override - public void onScanPaused(ScanData[] scanData) { - // should not happen for single scan - Log.e(TAG, "Got scan paused for single scan"); - } - - @Override - public void onScanRestarted() { - // should not happen for single scan - Log.e(TAG, "Got scan restarted for single scan"); - } - } - - private static final int STATUS_PENDING = 0; - private static final int STATUS_SUCCEEDED = 1; - private static final int STATUS_FAILED = 2; - - // Tracks scan status per impl. - Map<String, Integer> mStatusPerImpl = new ArrayMap<>(); - - /** - * Triggers a new scan on all the available scanner impls. - * @return true if the scan succeeded on any of the impl, false otherwise. - */ - public boolean startSingleScan(WifiNative.ScanSettings scanSettings) { - mStatusPerImpl.clear(); - boolean anySuccess = false; - for (Map.Entry<String, WifiScannerImpl> entry : mScannerImpls.entrySet()) { - String ifaceName = entry.getKey(); - WifiScannerImpl impl = entry.getValue(); - boolean success = impl.startSingleScan( - scanSettings, new ScanEventHandler(ifaceName)); - if (!success) { - Log.e(TAG, "Failed to start single scan on " + ifaceName); - continue; - } - mStatusPerImpl.put(ifaceName, STATUS_PENDING); - anySuccess = true; - } - return anySuccess; - } - - /** - * Returns the latest scan results from all the available scanner impls. - * @return Consolidated list of scan results from all the impl. - */ - public @Nullable ScanData getLatestSingleScanResults() { - ScanData consolidatedScanData = null; - for (WifiScannerImpl impl : mScannerImpls.values()) { - ScanData scanData = impl.getLatestSingleScanResults(); - if (consolidatedScanData == null) { - consolidatedScanData = new ScanData(scanData); - } else { - consolidatedScanData.addResults(scanData.getResults()); - } - } - return consolidatedScanData; - } - - private void reportFullScanResultForImpl(@NonNull String implIfaceName, - ScanResult fullScanResult, int bucketsScanned) { - Integer status = mStatusPerImpl.get(implIfaceName); - if (status != null && status == STATUS_PENDING) { - sendMessage(CMD_FULL_SCAN_RESULTS, 0, bucketsScanned, fullScanResult); - } - } - - private int getConsolidatedStatus() { - boolean anyPending = mStatusPerImpl.values().stream() - .anyMatch(status -> status == STATUS_PENDING); - // at-least one impl status is still pending. - if (anyPending) return STATUS_PENDING; - - boolean anySuccess = mStatusPerImpl.values().stream() - .anyMatch(status -> status == STATUS_SUCCEEDED); - // one success is good enough to declare consolidated success. - if (anySuccess) { - return STATUS_SUCCEEDED; - } else { - // all failed. - return STATUS_FAILED; - } - } - - private void reportScanStatusForImpl(@NonNull String implIfaceName, int newStatus) { - Integer currentStatus = mStatusPerImpl.get(implIfaceName); - if (currentStatus != null && currentStatus == STATUS_PENDING) { - mStatusPerImpl.put(implIfaceName, newStatus); - } - // Now check if all the scanner impls scan status is available. - int consolidatedStatus = getConsolidatedStatus(); - if (consolidatedStatus == STATUS_SUCCEEDED) { - sendMessage(CMD_SCAN_RESULTS_AVAILABLE); - } else if (consolidatedStatus == STATUS_FAILED) { - sendMessage(CMD_SCAN_FAILED); - } - } - } - - class DefaultState extends State { - @Override - public void enter() { - mActiveScans.clear(); - mPendingScans.clear(); - } - @Override - public boolean processMessage(Message msg) { - switch (msg.what) { - case WifiScanner.CMD_ENABLE: - if (mScannerImpls.isEmpty()) { - loge("Failed to start single scan state machine because scanner impl" - + " is null"); - return HANDLED; - } - transitionTo(mIdleState); - return HANDLED; - case WifiScanner.CMD_DISABLE: - transitionTo(mDefaultState); - return HANDLED; - case WifiScanner.CMD_START_SINGLE_SCAN: - case WifiScanner.CMD_STOP_SINGLE_SCAN: - replyFailed(msg, WifiScanner.REASON_UNSPECIFIED, "not available"); - return HANDLED; - case CMD_SCAN_RESULTS_AVAILABLE: - if (DBG) localLog("ignored scan results available event"); - return HANDLED; - case CMD_FULL_SCAN_RESULTS: - if (DBG) localLog("ignored full scan result event"); - return HANDLED; - case WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS: - msg.obj = new WifiScanner.ParcelableScanResults( - filterCachedScanResultsByAge()); - replySucceeded(msg); - return HANDLED; - default: - return NOT_HANDLED; - } - } - - /** - * Filter out any scan results that are older than - * {@link #CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS}. - * - * @return Filtered list of scan results. - */ - private ScanResult[] filterCachedScanResultsByAge() { - // Using ScanResult.timestamp here to ensure that we use the same fields as - // WificondScannerImpl for filtering stale results. - long currentTimeInMillis = mClock.getElapsedSinceBootMillis(); - return mCachedScanResults.stream() - .filter(scanResult - -> ((currentTimeInMillis - (scanResult.timestamp / 1000)) - < CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS)) - .toArray(ScanResult[]::new); - } - } - - /** - * State representing when the driver is running. This state is not meant to be transitioned - * directly, but is instead intended as a parent state of ScanningState and IdleState - * to hold common functionality and handle cleaning up scans when the driver is shut down. - */ - class DriverStartedState extends State { - @Override - public void exit() { - // clear scan results when scan mode is not active - mCachedScanResults.clear(); - - mWifiMetrics.incrementScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED, - mPendingScans.size()); - sendOpFailedToAllAndClear(mPendingScans, WifiScanner.REASON_UNSPECIFIED, - "Scan was interrupted"); - } - - @Override - public boolean processMessage(Message msg) { - ClientInfo ci = mClients.get(msg.replyTo); - - switch (msg.what) { - case WifiScanner.CMD_ENABLE: - // Ignore if we're already in driver loaded state. - return HANDLED; - case WifiScanner.CMD_START_SINGLE_SCAN: - int handler = msg.arg2; - Bundle scanParams = (Bundle) msg.obj; - if (scanParams == null) { - logCallback("singleScanInvalidRequest", ci, handler, "null params"); - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "params null"); - return HANDLED; - } - ScanSettings scanSettings = null; - WorkSource workSource = null; - try { - scanSettings = - scanParams.getParcelable( - WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY); - workSource = - scanParams.getParcelable( - WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY); - } catch (BadParcelableException e) { - Log.e(TAG, "Failed to get parcelable params", e); - logCallback("singleScanInvalidRequest", ci, handler, - "bad parcel params"); - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, - "bad parcel params"); - return HANDLED; - } - if (validateScanRequest(ci, handler, scanSettings)) { - mWifiMetrics.incrementOneshotScanCount(); - if ((scanSettings.band & WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY) != 0) { - mWifiMetrics.incrementOneshotScanWithDfsCount(); - } - logScanRequest("addSingleScanRequest", ci, handler, workSource, - scanSettings, null); - replySucceeded(msg); - - // If there is an active scan that will fulfill the scan request then - // mark this request as an active scan, otherwise mark it pending. - // If were not currently scanning then try to start a scan. Otherwise - // this scan will be scheduled when transitioning back to IdleState - // after finishing the current scan. - if (getCurrentState() == mScanningState) { - if (activeScanSatisfies(scanSettings)) { - mActiveScans.addRequest(ci, handler, workSource, scanSettings); - } else { - mPendingScans.addRequest(ci, handler, workSource, scanSettings); - } - } else { - mPendingScans.addRequest(ci, handler, workSource, scanSettings); - tryToStartNewScan(); - } - } else { - logCallback("singleScanInvalidRequest", ci, handler, "bad request"); - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request"); - mWifiMetrics.incrementScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, 1); - } - return HANDLED; - case WifiScanner.CMD_STOP_SINGLE_SCAN: - removeSingleScanRequest(ci, msg.arg2); - return HANDLED; - default: - return NOT_HANDLED; - } - } - } - - class IdleState extends State { - @Override - public void enter() { - tryToStartNewScan(); - } - - @Override - public boolean processMessage(Message msg) { - return NOT_HANDLED; - } - } - - class ScanningState extends State { - private WorkSource mScanWorkSource; - - @Override - public void enter() { - mScanWorkSource = mActiveScans.createMergedWorkSource(); - mBatteryStats.reportWifiScanStartedFromSource(mScanWorkSource); - Pair<int[], String[]> uidsAndTags = - WorkSourceUtil.getUidsAndTagsForWs(mScanWorkSource); - WifiStatsLog.write(WifiStatsLog.WIFI_SCAN_STATE_CHANGED, - uidsAndTags.first, uidsAndTags.second, - WifiStatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON); - } - - @Override - public void exit() { - mActiveScanSettings = null; - mBatteryStats.reportWifiScanStoppedFromSource(mScanWorkSource); - Pair<int[], String[]> uidsAndTags = - WorkSourceUtil.getUidsAndTagsForWs(mScanWorkSource); - WifiStatsLog.write(WifiStatsLog.WIFI_SCAN_STATE_CHANGED, - uidsAndTags.first, uidsAndTags.second, - WifiStatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF); - - // if any scans are still active (never got results available then indicate failure) - mWifiMetrics.incrementScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_UNKNOWN, - mActiveScans.size()); - sendOpFailedToAllAndClear(mActiveScans, WifiScanner.REASON_UNSPECIFIED, - "Scan was interrupted"); - } - - @Override - public boolean processMessage(Message msg) { - switch (msg.what) { - case CMD_SCAN_RESULTS_AVAILABLE: - ScanData latestScanResults = - mScannerImplsTracker.getLatestSingleScanResults(); - if (latestScanResults != null) { - mWifiMetrics.incrementScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_SUCCESS, - mActiveScans.size()); - reportScanResults(latestScanResults); - mActiveScans.clear(); - } else { - Log.e(TAG, "latest scan results null unexpectedly"); - } - transitionTo(mIdleState); - return HANDLED; - case CMD_FULL_SCAN_RESULTS: - reportFullScanResult((ScanResult) msg.obj, /* bucketsScanned */ msg.arg2); - return HANDLED; - case CMD_SCAN_FAILED: - mWifiMetrics.incrementScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_UNKNOWN, mActiveScans.size()); - sendOpFailedToAllAndClear(mActiveScans, WifiScanner.REASON_UNSPECIFIED, - "Scan failed"); - transitionTo(mIdleState); - return HANDLED; - default: - return NOT_HANDLED; - } - } - } - - boolean validateScanType(@WifiAnnotations.ScanType int type) { - return (type == WifiScanner.SCAN_TYPE_LOW_LATENCY - || type == WifiScanner.SCAN_TYPE_LOW_POWER - || type == WifiScanner.SCAN_TYPE_HIGH_ACCURACY); - } - - boolean validateScanRequest(ClientInfo ci, int handler, ScanSettings settings) { - if (ci == null) { - Log.d(TAG, "Failing single scan request ClientInfo not found " + handler); - return false; - } - if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - if (settings.channels == null || settings.channels.length == 0) { - Log.d(TAG, "Failing single scan because channel list was empty"); - return false; - } - } - if (!validateScanType(settings.type)) { - Log.e(TAG, "Invalid scan type " + settings.type); - return false; - } - if (mContext.checkPermission( - Manifest.permission.NETWORK_STACK, UNKNOWN_PID, ci.getUid()) - == PERMISSION_DENIED) { - if (!ArrayUtils.isEmpty(settings.hiddenNetworks)) { - Log.e(TAG, "Failing single scan because app " + ci.getUid() - + " does not have permission to set hidden networks"); - return false; - } - if (settings.type != WifiScanner.SCAN_TYPE_LOW_LATENCY) { - Log.e(TAG, "Failing single scan because app " + ci.getUid() - + " does not have permission to set type"); - return false; - } - } - return true; - } - - // We can coalesce a LOW_POWER/LOW_LATENCY scan request into an ongoing HIGH_ACCURACY - // scan request. But, we can't coalesce a HIGH_ACCURACY scan request into an ongoing - // LOW_POWER/LOW_LATENCY scan request. - boolean activeScanTypeSatisfies(int requestScanType) { - switch(mActiveScanSettings.scanType) { - case WifiScanner.SCAN_TYPE_LOW_LATENCY: - case WifiScanner.SCAN_TYPE_LOW_POWER: - return requestScanType != WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - case WifiScanner.SCAN_TYPE_HIGH_ACCURACY: - return true; - default: - // This should never happen becuase we've validated the incoming type in - // |validateScanType|. - throw new IllegalArgumentException("Invalid scan type " - + mActiveScanSettings.scanType); - } - } - - // If there is a HIGH_ACCURACY scan request among the requests being merged, the merged - // scan type should be HIGH_ACCURACY. - int mergeScanTypes(int existingScanType, int newScanType) { - switch(existingScanType) { - case WifiScanner.SCAN_TYPE_LOW_LATENCY: - case WifiScanner.SCAN_TYPE_LOW_POWER: - return newScanType; - case WifiScanner.SCAN_TYPE_HIGH_ACCURACY: - return existingScanType; - default: - // This should never happen becuase we've validated the incoming type in - // |validateScanType|. - throw new IllegalArgumentException("Invalid scan type " + existingScanType); - } - } - - boolean activeScanSatisfies(ScanSettings settings) { - if (mActiveScanSettings == null) { - return false; - } - - if (!activeScanTypeSatisfies(settings.type)) { - return false; - } - - // there is always one bucket for a single scan - WifiNative.BucketSettings activeBucket = mActiveScanSettings.buckets[0]; - - // validate that all requested channels are being scanned - ChannelCollection activeChannels = mChannelHelper.createChannelCollection(); - activeChannels.addChannels(activeBucket); - if (!activeChannels.containsSettings(settings)) { - return false; - } - - // if the request is for a full scan, but there is no ongoing full scan - if ((settings.reportEvents & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0 - && (activeBucket.report_events & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) - == 0) { - return false; - } - - if (!ArrayUtils.isEmpty(settings.hiddenNetworks)) { - if (ArrayUtils.isEmpty(mActiveScanSettings.hiddenNetworks)) { - return false; - } - List<WifiNative.HiddenNetwork> activeHiddenNetworks = new ArrayList<>(); - for (WifiNative.HiddenNetwork hiddenNetwork : mActiveScanSettings.hiddenNetworks) { - activeHiddenNetworks.add(hiddenNetwork); - } - for (ScanSettings.HiddenNetwork hiddenNetwork : settings.hiddenNetworks) { - WifiNative.HiddenNetwork nativeHiddenNetwork = new WifiNative.HiddenNetwork(); - nativeHiddenNetwork.ssid = hiddenNetwork.ssid; - if (!activeHiddenNetworks.contains(nativeHiddenNetwork)) { - return false; - } - } - } - - return true; - } - - void removeSingleScanRequest(ClientInfo ci, int handler) { - if (ci != null) { - logScanRequest("removeSingleScanRequest", ci, handler, null, null, null); - mPendingScans.removeRequest(ci, handler); - mActiveScans.removeRequest(ci, handler); - } - } - - void removeSingleScanRequests(ClientInfo ci) { - if (ci != null) { - logScanRequest("removeSingleScanRequests", ci, -1, null, null, null); - mPendingScans.removeAllForClient(ci); - mActiveScans.removeAllForClient(ci); - } - } - - void tryToStartNewScan() { - if (mPendingScans.size() == 0) { // no pending requests - return; - } - mChannelHelper.updateChannels(); - // TODO move merging logic to a scheduler - WifiNative.ScanSettings settings = new WifiNative.ScanSettings(); - settings.num_buckets = 1; - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - bucketSettings.bucket = 0; - bucketSettings.period_ms = 0; - bucketSettings.report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - - ChannelCollection channels = mChannelHelper.createChannelCollection(); - List<WifiNative.HiddenNetwork> hiddenNetworkList = new ArrayList<>(); - for (RequestInfo<ScanSettings> entry : mPendingScans) { - settings.scanType = mergeScanTypes(settings.scanType, entry.settings.type); - channels.addChannels(entry.settings); - for (ScanSettings.HiddenNetwork srcNetwork : entry.settings.hiddenNetworks) { - WifiNative.HiddenNetwork hiddenNetwork = new WifiNative.HiddenNetwork(); - hiddenNetwork.ssid = srcNetwork.ssid; - hiddenNetworkList.add(hiddenNetwork); - } - if ((entry.settings.reportEvents & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) - != 0) { - bucketSettings.report_events |= WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; - } - } - if (hiddenNetworkList.size() > 0) { - settings.hiddenNetworks = new WifiNative.HiddenNetwork[hiddenNetworkList.size()]; - int numHiddenNetworks = 0; - for (WifiNative.HiddenNetwork hiddenNetwork : hiddenNetworkList) { - settings.hiddenNetworks[numHiddenNetworks++] = hiddenNetwork; - } - } - - channels.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - - settings.buckets = new WifiNative.BucketSettings[] {bucketSettings}; - if (mScannerImplsTracker.startSingleScan(settings)) { - // store the active scan settings - mActiveScanSettings = settings; - // swap pending and active scan requests - RequestList<ScanSettings> tmp = mActiveScans; - mActiveScans = mPendingScans; - mPendingScans = tmp; - // make sure that the pending list is clear - mPendingScans.clear(); - transitionTo(mScanningState); - } else { - mWifiMetrics.incrementScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_UNKNOWN, mPendingScans.size()); - // notify and cancel failed scans - sendOpFailedToAllAndClear(mPendingScans, WifiScanner.REASON_UNSPECIFIED, - "Failed to start single scan"); - } - } - - void sendOpFailedToAllAndClear(RequestList<?> clientHandlers, int reason, - String description) { - for (RequestInfo<?> entry : clientHandlers) { - logCallback("singleScanFailed", entry.clientInfo, entry.handlerId, - "reason=" + reason + ", " + description); - entry.reportEvent(WifiScanner.CMD_OP_FAILED, 0, - new WifiScanner.OperationResult(reason, description)); - } - clientHandlers.clear(); - } - - void reportFullScanResult(@NonNull ScanResult result, int bucketsScanned) { - for (RequestInfo<ScanSettings> entry : mActiveScans) { - if (ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, - result, bucketsScanned, entry.settings, -1)) { - entry.reportEvent(WifiScanner.CMD_FULL_SCAN_RESULT, 0, result); - } - } - - for (RequestInfo<Void> entry : mSingleScanListeners) { - entry.reportEvent(WifiScanner.CMD_FULL_SCAN_RESULT, 0, result); - } - } - - void reportScanResults(@NonNull ScanData results) { - if (results != null && results.getResults() != null) { - if (results.getResults().length > 0) { - mWifiMetrics.incrementNonEmptyScanResultCount(); - } else { - mWifiMetrics.incrementEmptyScanResultCount(); - } - } - ScanData[] allResults = new ScanData[] {results}; - for (RequestInfo<ScanSettings> entry : mActiveScans) { - ScanData[] resultsToDeliver = ScanScheduleUtil.filterResultsForSettings( - mChannelHelper, allResults, entry.settings, -1); - WifiScanner.ParcelableScanData parcelableResultsToDeliver = - new WifiScanner.ParcelableScanData(resultsToDeliver); - logCallback("singleScanResults", entry.clientInfo, entry.handlerId, - describeForLog(resultsToDeliver)); - entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, parcelableResultsToDeliver); - // make sure the handler is removed - entry.reportEvent(WifiScanner.CMD_SINGLE_SCAN_COMPLETED, 0, null); - } - - WifiScanner.ParcelableScanData parcelableAllResults = - new WifiScanner.ParcelableScanData(allResults); - for (RequestInfo<Void> entry : mSingleScanListeners) { - logCallback("singleScanResults", entry.clientInfo, entry.handlerId, - describeForLog(allResults)); - entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, parcelableAllResults); - } - - // Cache full band (with DFS or not) scan results. - if (WifiScanner.isFullBandScan(results.getBandScanned(), true)) { - mCachedScanResults.clear(); - mCachedScanResults.addAll(Arrays.asList(results.getResults())); - } - } - - List<ScanResult> getCachedScanResultsAsList() { - return mCachedScanResults; - } - } - - // TODO(b/71855918): Remove this bg scan state machine and its dependencies. - // Note: bgscan will not support multiple scanner impls (will pick any). - class WifiBackgroundScanStateMachine extends StateMachine { - - private final DefaultState mDefaultState = new DefaultState(); - private final StartedState mStartedState = new StartedState(); - private final PausedState mPausedState = new PausedState(); - - private final RequestList<ScanSettings> mActiveBackgroundScans = new RequestList<>(); - - private WifiScannerImpl mScannerImpl; - - WifiBackgroundScanStateMachine(Looper looper) { - super("WifiBackgroundScanStateMachine", looper); - - setLogRecSize(512); - setLogOnlyTransitions(false); - - // CHECKSTYLE:OFF IndentationCheck - addState(mDefaultState); - addState(mStartedState, mDefaultState); - addState(mPausedState, mDefaultState); - // CHECKSTYLE:ON IndentationCheck - - setInitialState(mDefaultState); - } - - public Collection<ScanSettings> getBackgroundScanSettings(ClientInfo ci) { - return mActiveBackgroundScans.getAllSettingsForClient(ci); - } - - public void removeBackgroundScanSettings(ClientInfo ci) { - mActiveBackgroundScans.removeAllForClient(ci); - updateSchedule(); - } - - private final class ScanEventHandler implements WifiNative.ScanEventHandler { - private final String mImplIfaceName; - - ScanEventHandler(@NonNull String implIfaceName) { - mImplIfaceName = implIfaceName; - } - - @Override - public void onScanStatus(int event) { - if (DBG) localLog("onScanStatus event received, event=" + event); - switch (event) { - case WifiNative.WIFI_SCAN_RESULTS_AVAILABLE: - case WifiNative.WIFI_SCAN_THRESHOLD_NUM_SCANS: - case WifiNative.WIFI_SCAN_THRESHOLD_PERCENT: - sendMessage(CMD_SCAN_RESULTS_AVAILABLE); - break; - case WifiNative.WIFI_SCAN_FAILED: - sendMessage(CMD_SCAN_FAILED); - break; - default: - Log.e(TAG, "Unknown scan status event: " + event); - break; - } - } - - @Override - public void onFullScanResult(ScanResult fullScanResult, int bucketsScanned) { - if (DBG) localLog("onFullScanResult received"); - sendMessage(CMD_FULL_SCAN_RESULTS, 0, bucketsScanned, fullScanResult); - } - - @Override - public void onScanPaused(ScanData[] scanData) { - if (DBG) localLog("onScanPaused received"); - sendMessage(CMD_SCAN_PAUSED, scanData); - } - - @Override - public void onScanRestarted() { - if (DBG) localLog("onScanRestarted received"); - sendMessage(CMD_SCAN_RESTARTED); - } - } - - class DefaultState extends State { - @Override - public void enter() { - if (DBG) localLog("DefaultState"); - mActiveBackgroundScans.clear(); - } - - @Override - public boolean processMessage(Message msg) { - switch (msg.what) { - case WifiScanner.CMD_ENABLE: - if (mScannerImpls.isEmpty()) { - loge("Failed to start bgscan scan state machine because scanner impl" - + " is null"); - return HANDLED; - } - // Pick any impl available and stick to it until disable. - mScannerImpl = mScannerImpls.entrySet().iterator().next().getValue(); - mChannelHelper = mScannerImpl.getChannelHelper(); - - mBackgroundScheduler = new BackgroundScanScheduler(mChannelHelper); - - WifiNative.ScanCapabilities capabilities = - new WifiNative.ScanCapabilities(); - if (!mScannerImpl.getScanCapabilities(capabilities)) { - loge("could not get scan capabilities"); - return HANDLED; - } - if (capabilities.max_scan_buckets <= 0) { - loge("invalid max buckets in scan capabilities " - + capabilities.max_scan_buckets); - return HANDLED; - } - mBackgroundScheduler.setMaxBuckets(capabilities.max_scan_buckets); - mBackgroundScheduler.setMaxApPerScan(capabilities.max_ap_cache_per_scan); - - Log.i(TAG, "wifi driver loaded with scan capabilities: " - + "max buckets=" + capabilities.max_scan_buckets); - - transitionTo(mStartedState); - return HANDLED; - case WifiScanner.CMD_DISABLE: - Log.i(TAG, "wifi driver unloaded"); - transitionTo(mDefaultState); - break; - case WifiScanner.CMD_START_BACKGROUND_SCAN: - case WifiScanner.CMD_STOP_BACKGROUND_SCAN: - case WifiScanner.CMD_START_SINGLE_SCAN: - case WifiScanner.CMD_STOP_SINGLE_SCAN: - case WifiScanner.CMD_GET_SCAN_RESULTS: - replyFailed(msg, WifiScanner.REASON_UNSPECIFIED, "not available"); - break; - - case CMD_SCAN_RESULTS_AVAILABLE: - if (DBG) localLog("ignored scan results available event"); - break; - - case CMD_FULL_SCAN_RESULTS: - if (DBG) localLog("ignored full scan result event"); - break; - - default: - break; - } - - return HANDLED; - } - } - - class StartedState extends State { - - @Override - public void enter() { - if (DBG) localLog("StartedState"); - if (mScannerImpl == null) { - // should never happen - Log.wtf(TAG, "Scanner impl unexpectedly null"); - transitionTo(mDefaultState); - } - } - - @Override - public void exit() { - sendBackgroundScanFailedToAllAndClear( - WifiScanner.REASON_UNSPECIFIED, "Scan was interrupted"); - mScannerImpl = null; // reset impl - } - - @Override - public boolean processMessage(Message msg) { - ClientInfo ci = mClients.get(msg.replyTo); - - switch (msg.what) { - case WifiScanner.CMD_ENABLE: - Log.e(TAG, "wifi driver loaded received while already loaded"); - // Ignore if we're already in driver loaded state. - return HANDLED; - case WifiScanner.CMD_DISABLE: - return NOT_HANDLED; - case WifiScanner.CMD_START_BACKGROUND_SCAN: { - mWifiMetrics.incrementBackgroundScanCount(); - Bundle scanParams = (Bundle) msg.obj; - if (scanParams == null) { - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "params null"); - return HANDLED; - } - ScanSettings scanSettings = null; - WorkSource workSource = null; - try { - scanSettings = - scanParams.getParcelable( - WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY); - workSource = - scanParams.getParcelable( - WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY); - } catch (BadParcelableException e) { - Log.e(TAG, "Failed to get parcelable params", e); - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, - "bad parcel params"); - return HANDLED; - } - if (addBackgroundScanRequest(ci, msg.arg2, scanSettings, workSource)) { - replySucceeded(msg); - } else { - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request"); - } - break; - } - case WifiScanner.CMD_STOP_BACKGROUND_SCAN: - removeBackgroundScanRequest(ci, msg.arg2); - break; - case WifiScanner.CMD_GET_SCAN_RESULTS: - reportScanResults(mScannerImpl.getLatestBatchedScanResults(true)); - replySucceeded(msg); - break; - case CMD_SCAN_RESULTS_AVAILABLE: - reportScanResults(mScannerImpl.getLatestBatchedScanResults(true)); - break; - case CMD_FULL_SCAN_RESULTS: - reportFullScanResult((ScanResult) msg.obj, /* bucketsScanned */ msg.arg2); - break; - case CMD_SCAN_PAUSED: - reportScanResults((ScanData[]) msg.obj); - transitionTo(mPausedState); - break; - case CMD_SCAN_FAILED: - Log.e(TAG, "WifiScanner background scan gave CMD_SCAN_FAILED"); - sendBackgroundScanFailedToAllAndClear( - WifiScanner.REASON_UNSPECIFIED, "Background Scan failed"); - break; - default: - return NOT_HANDLED; - } - - return HANDLED; - } - } - - class PausedState extends State { - @Override - public void enter() { - if (DBG) localLog("PausedState"); - } - - @Override - public boolean processMessage(Message msg) { - switch (msg.what) { - case CMD_SCAN_RESTARTED: - transitionTo(mStartedState); - break; - default: - deferMessage(msg); - break; - } - return HANDLED; - } - } - - private boolean addBackgroundScanRequest(ClientInfo ci, int handler, - ScanSettings settings, WorkSource workSource) { - // sanity check the input - if (ci == null) { - Log.d(TAG, "Failing scan request ClientInfo not found " + handler); - return false; - } - if (settings.periodInMs < WifiScanner.MIN_SCAN_PERIOD_MS) { - loge("Failing scan request because periodInMs is " + settings.periodInMs - + ", min scan period is: " + WifiScanner.MIN_SCAN_PERIOD_MS); - return false; - } - - if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED && settings.channels == null) { - loge("Channels was null with unspecified band"); - return false; - } - - if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED - && settings.channels.length == 0) { - loge("No channels specified"); - return false; - } - - int minSupportedPeriodMs = mChannelHelper.estimateScanDuration(settings); - if (settings.periodInMs < minSupportedPeriodMs) { - loge("Failing scan request because minSupportedPeriodMs is " - + minSupportedPeriodMs + " but the request wants " + settings.periodInMs); - return false; - } - - // check truncated binary exponential back off scan settings - if (settings.maxPeriodInMs != 0 && settings.maxPeriodInMs != settings.periodInMs) { - if (settings.maxPeriodInMs < settings.periodInMs) { - loge("Failing scan request because maxPeriodInMs is " + settings.maxPeriodInMs - + " but less than periodInMs " + settings.periodInMs); - return false; - } - if (settings.maxPeriodInMs > WifiScanner.MAX_SCAN_PERIOD_MS) { - loge("Failing scan request because maxSupportedPeriodMs is " - + WifiScanner.MAX_SCAN_PERIOD_MS + " but the request wants " - + settings.maxPeriodInMs); - return false; - } - if (settings.stepCount < 1) { - loge("Failing scan request because stepCount is " + settings.stepCount - + " which is less than 1"); - return false; - } - } - - logScanRequest("addBackgroundScanRequest", ci, handler, null, settings, null); - mActiveBackgroundScans.addRequest(ci, handler, workSource, settings); - - if (updateSchedule()) { - return true; - } else { - mActiveBackgroundScans.removeRequest(ci, handler); - localLog("Failing scan request because failed to reset scan"); - return false; - } - } - - private boolean updateSchedule() { - if (mChannelHelper == null || mBackgroundScheduler == null || mScannerImpl == null) { - loge("Failed to update schedule because WifiScanningService is not initialized"); - return false; - } - mChannelHelper.updateChannels(); - Collection<ScanSettings> settings = mActiveBackgroundScans.getAllSettings(); - - mBackgroundScheduler.updateSchedule(settings); - WifiNative.ScanSettings schedule = mBackgroundScheduler.getSchedule(); - - if (ScanScheduleUtil.scheduleEquals(mPreviousSchedule, schedule)) { - if (DBG) Log.d(TAG, "schedule updated with no change"); - return true; - } - - mPreviousSchedule = schedule; - - if (schedule.num_buckets == 0) { - mScannerImpl.stopBatchedScan(); - if (DBG) Log.d(TAG, "scan stopped"); - return true; - } else { - localLog("starting scan: " - + "base period=" + schedule.base_period_ms - + ", max ap per scan=" + schedule.max_ap_per_scan - + ", batched scans=" + schedule.report_threshold_num_scans); - for (int b = 0; b < schedule.num_buckets; b++) { - WifiNative.BucketSettings bucket = schedule.buckets[b]; - localLog("bucket " + bucket.bucket + " (" + bucket.period_ms + "ms)" - + "[" + bucket.report_events + "]: " - + ChannelHelper.toString(bucket)); - } - - if (mScannerImpl.startBatchedScan(schedule, - new ScanEventHandler(mScannerImpl.getIfaceName()))) { - if (DBG) { - Log.d(TAG, "scan restarted with " + schedule.num_buckets - + " bucket(s) and base period: " + schedule.base_period_ms); - } - return true; - } else { - mPreviousSchedule = null; - loge("error starting scan: " - + "base period=" + schedule.base_period_ms - + ", max ap per scan=" + schedule.max_ap_per_scan - + ", batched scans=" + schedule.report_threshold_num_scans); - for (int b = 0; b < schedule.num_buckets; b++) { - WifiNative.BucketSettings bucket = schedule.buckets[b]; - loge("bucket " + bucket.bucket + " (" + bucket.period_ms + "ms)" - + "[" + bucket.report_events + "]: " - + ChannelHelper.toString(bucket)); - } - return false; - } - } - } - - private void removeBackgroundScanRequest(ClientInfo ci, int handler) { - if (ci != null) { - ScanSettings settings = mActiveBackgroundScans.removeRequest(ci, handler); - logScanRequest("removeBackgroundScanRequest", ci, handler, null, settings, null); - updateSchedule(); - } - } - - private void reportFullScanResult(ScanResult result, int bucketsScanned) { - for (RequestInfo<ScanSettings> entry : mActiveBackgroundScans) { - ClientInfo ci = entry.clientInfo; - int handler = entry.handlerId; - ScanSettings settings = entry.settings; - if (mBackgroundScheduler.shouldReportFullScanResultForSettings( - result, bucketsScanned, settings)) { - ScanResult newResult = new ScanResult(result); - if (result.informationElements != null) { - newResult.informationElements = result.informationElements.clone(); - } - else { - newResult.informationElements = null; - } - ci.reportEvent(WifiScanner.CMD_FULL_SCAN_RESULT, 0, handler, newResult); - } - } - } - - private void reportScanResults(ScanData[] results) { - if (results == null) { - Log.d(TAG,"The results is null, nothing to report."); - return; - } - for (ScanData result : results) { - if (result != null && result.getResults() != null) { - if (result.getResults().length > 0) { - mWifiMetrics.incrementNonEmptyScanResultCount(); - } else { - mWifiMetrics.incrementEmptyScanResultCount(); - } - } - } - for (RequestInfo<ScanSettings> entry : mActiveBackgroundScans) { - ClientInfo ci = entry.clientInfo; - int handler = entry.handlerId; - ScanSettings settings = entry.settings; - ScanData[] resultsToDeliver = - mBackgroundScheduler.filterResultsForSettings(results, settings); - if (resultsToDeliver != null) { - logCallback("backgroundScanResults", ci, handler, - describeForLog(resultsToDeliver)); - WifiScanner.ParcelableScanData parcelableScanData = - new WifiScanner.ParcelableScanData(resultsToDeliver); - ci.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, handler, parcelableScanData); - } - } - } - - private void sendBackgroundScanFailedToAllAndClear(int reason, String description) { - for (RequestInfo<ScanSettings> entry : mActiveBackgroundScans) { - ClientInfo ci = entry.clientInfo; - int handler = entry.handlerId; - ci.reportEvent(WifiScanner.CMD_OP_FAILED, 0, handler, - new WifiScanner.OperationResult(reason, description)); - } - mActiveBackgroundScans.clear(); - } - } - - /** - * PNO scan state machine has 5 states: - * -Default State - * -Started State - * -Hw Pno Scan state - * -Single Scan state - * - * These are the main state transitions: - * 1. Start at |Default State| - * 2. Move to |Started State| when we get the |WIFI_SCAN_AVAILABLE| broadcast from WifiManager. - * 3. When a new PNO scan request comes in: - * a.1. Switch to |Hw Pno Scan state| when the device supports HW PNO - * (This could either be HAL based ePNO or wificond based PNO). - * a.2. In |Hw Pno Scan state| when PNO scan results are received, check if the result - * contains IE (information elements). If yes, send the results to the client, else - * switch to |Single Scan state| and send the result to the client when the scan result - * is obtained. - * - * Note: PNO scans only work for a single client today. We don't have support in HW to support - * multiple requests at the same time, so will need non-trivial changes to support (if at all - * possible) in WifiScanningService. - */ - class WifiPnoScanStateMachine extends StateMachine { - - private final DefaultState mDefaultState = new DefaultState(); - private final StartedState mStartedState = new StartedState(); - private final HwPnoScanState mHwPnoScanState = new HwPnoScanState(); - private final SingleScanState mSingleScanState = new SingleScanState(); - private InternalClientInfo mInternalClientInfo; - - private final RequestList<Pair<PnoSettings, ScanSettings>> mActivePnoScans = - new RequestList<>(); - // Tracks scan requests across multiple scanner impls. - private final ScannerImplsTracker mScannerImplsTracker; - - WifiPnoScanStateMachine(Looper looper) { - super("WifiPnoScanStateMachine", looper); - - mScannerImplsTracker = new ScannerImplsTracker(); - - setLogRecSize(256); - setLogOnlyTransitions(false); - - // CHECKSTYLE:OFF IndentationCheck - addState(mDefaultState); - addState(mStartedState, mDefaultState); - addState(mHwPnoScanState, mStartedState); - addState(mSingleScanState, mHwPnoScanState); - // CHECKSTYLE:ON IndentationCheck - - setInitialState(mDefaultState); - } - - public void removePnoSettings(ClientInfo ci) { - mActivePnoScans.removeAllForClient(ci); - transitionTo(mStartedState); - } - - /** - * Tracks a PNO scan request across all the available scanner impls. - * - * Note: If there are failures on some of the scanner impls, we ignore them since we can - * get a PNO match from the other successful impls. We don't declare total scan - * failures, unless all the scanner impls fail. - */ - private final class ScannerImplsTracker { - private final class PnoEventHandler implements WifiNative.PnoEventHandler { - private final String mImplIfaceName; - - PnoEventHandler(@NonNull String implIfaceName) { - mImplIfaceName = implIfaceName; - } - - @Override - public void onPnoNetworkFound(ScanResult[] results) { - if (DBG) localLog("onWifiPnoNetworkFound event received"); - reportPnoNetworkFoundForImpl(mImplIfaceName, results); - } - - @Override - public void onPnoScanFailed() { - if (DBG) localLog("onWifiPnoScanFailed event received"); - reportPnoScanFailedForImpl(mImplIfaceName); - } - } - - private static final int STATUS_PENDING = 0; - private static final int STATUS_FAILED = 2; - - // Tracks scan status per impl. - Map<String, Integer> mStatusPerImpl = new ArrayMap<>(); - - /** - * Triggers a new PNO with the specified settings on all the available scanner impls. - * @return true if the PNO succeeded on any of the impl, false otherwise. - */ - public boolean setHwPnoList(WifiNative.PnoSettings pnoSettings) { - mStatusPerImpl.clear(); - boolean anySuccess = false; - for (Map.Entry<String, WifiScannerImpl> entry : mScannerImpls.entrySet()) { - String ifaceName = entry.getKey(); - WifiScannerImpl impl = entry.getValue(); - boolean success = impl.setHwPnoList( - pnoSettings, new PnoEventHandler(ifaceName)); - if (!success) { - Log.e(TAG, "Failed to start pno on " + ifaceName); - continue; - } - mStatusPerImpl.put(ifaceName, STATUS_PENDING); - anySuccess = true; - } - return anySuccess; - } - - /** - * Resets any ongoing PNO on all the available scanner impls. - * @return true if the PNO stop succeeded on all of the impl, false otherwise. - */ - public boolean resetHwPnoList() { - boolean allSuccess = true; - for (String ifaceName : mStatusPerImpl.keySet()) { - WifiScannerImpl impl = mScannerImpls.get(ifaceName); - if (impl == null) continue; - boolean success = impl.resetHwPnoList(); - if (!success) { - Log.e(TAG, "Failed to stop pno on " + ifaceName); - allSuccess = false; - } - } - mStatusPerImpl.clear(); - return allSuccess; - } - - /** - * @return true if HW PNO is supported on all the available scanner impls, - * false otherwise. - */ - public boolean isHwPnoSupported(boolean isConnected) { - for (WifiScannerImpl impl : mScannerImpls.values()) { - if (!impl.isHwPnoSupported(isConnected)) { - return false; - } - } - return true; - } - - private void reportPnoNetworkFoundForImpl(@NonNull String implIfaceName, - ScanResult[] results) { - Integer status = mStatusPerImpl.get(implIfaceName); - if (status != null && status == STATUS_PENDING) { - sendMessage(CMD_PNO_NETWORK_FOUND, 0, 0, results); - } - } - - private int getConsolidatedStatus() { - boolean anyPending = mStatusPerImpl.values().stream() - .anyMatch(status -> status == STATUS_PENDING); - // at-least one impl status is still pending. - if (anyPending) { - return STATUS_PENDING; - } else { - // all failed. - return STATUS_FAILED; - } - } - - private void reportPnoScanFailedForImpl(@NonNull String implIfaceName) { - Integer currentStatus = mStatusPerImpl.get(implIfaceName); - if (currentStatus != null && currentStatus == STATUS_PENDING) { - mStatusPerImpl.put(implIfaceName, STATUS_FAILED); - } - // Now check if all the scanner impls scan status is available. - int consolidatedStatus = getConsolidatedStatus(); - if (consolidatedStatus == STATUS_FAILED) { - sendMessage(CMD_PNO_SCAN_FAILED); - } - } - } - - class DefaultState extends State { - @Override - public void enter() { - if (DBG) localLog("DefaultState"); - } - - @Override - public boolean processMessage(Message msg) { - switch (msg.what) { - case WifiScanner.CMD_ENABLE: - if (mScannerImpls.isEmpty()) { - loge("Failed to start pno scan state machine because scanner impl" - + " is null"); - return HANDLED; - } - transitionTo(mStartedState); - break; - case WifiScanner.CMD_DISABLE: - transitionTo(mDefaultState); - break; - case WifiScanner.CMD_START_PNO_SCAN: - case WifiScanner.CMD_STOP_PNO_SCAN: - replyFailed(msg, WifiScanner.REASON_UNSPECIFIED, "not available"); - break; - case CMD_PNO_NETWORK_FOUND: - case CMD_PNO_SCAN_FAILED: - case WifiScanner.CMD_SCAN_RESULT: - case WifiScanner.CMD_OP_FAILED: - loge("Unexpected message " + msg.what); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class StartedState extends State { - @Override - public void enter() { - if (DBG) localLog("StartedState"); - } - - @Override - public void exit() { - sendPnoScanFailedToAllAndClear( - WifiScanner.REASON_UNSPECIFIED, "Scan was interrupted"); - } - - @Override - public boolean processMessage(Message msg) { - ClientInfo ci = mClients.get(msg.replyTo); - switch (msg.what) { - case WifiScanner.CMD_ENABLE: - // Ignore if we're already in driver loaded state. - return HANDLED; - case WifiScanner.CMD_START_PNO_SCAN: - Bundle pnoParams = (Bundle) msg.obj; - if (pnoParams == null) { - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "params null"); - return HANDLED; - } - PnoSettings pnoSettings = null; - try { - pnoSettings = - pnoParams.getParcelable( - WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY); - } catch (BadParcelableException e) { - Log.e(TAG, "Failed to get parcelable params", e); - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, - "bad parcel params"); - return HANDLED; - } - if (mScannerImplsTracker.isHwPnoSupported(pnoSettings.isConnected)) { - deferMessage(msg); - transitionTo(mHwPnoScanState); - } else { - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "not supported"); - } - break; - case WifiScanner.CMD_STOP_PNO_SCAN: - replyFailed(msg, WifiScanner.REASON_UNSPECIFIED, "no scan running"); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class HwPnoScanState extends State { - @Override - public void enter() { - if (DBG) localLog("HwPnoScanState"); - } - - @Override - public void exit() { - // Reset PNO scan in ScannerImpl before we exit. - mScannerImplsTracker.resetHwPnoList(); - removeInternalClient(); - } - - @Override - public boolean processMessage(Message msg) { - ClientInfo ci = mClients.get(msg.replyTo); - switch (msg.what) { - case WifiScanner.CMD_START_PNO_SCAN: - Bundle pnoParams = (Bundle) msg.obj; - if (pnoParams == null) { - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "params null"); - return HANDLED; - } - PnoSettings pnoSettings = null; - ScanSettings scanSettings = null; - try { - pnoSettings = - pnoParams.getParcelable( - WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY); - scanSettings = - pnoParams.getParcelable( - WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY); - } catch (BadParcelableException e) { - Log.e(TAG, "Failed to get parcelable params", e); - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, - "bad parcel params"); - return HANDLED; - } - if (addHwPnoScanRequest(ci, msg.arg2, scanSettings, pnoSettings)) { - replySucceeded(msg); - } else { - replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request"); - transitionTo(mStartedState); - } - break; - case WifiScanner.CMD_STOP_PNO_SCAN: - removeHwPnoScanRequest(ci, msg.arg2); - transitionTo(mStartedState); - break; - case CMD_PNO_NETWORK_FOUND: - ScanResult[] scanResults = ((ScanResult[]) msg.obj); - if (isSingleScanNeeded(scanResults)) { - ScanSettings activeScanSettings = getScanSettings(); - if (activeScanSettings == null) { - sendPnoScanFailedToAllAndClear( - WifiScanner.REASON_UNSPECIFIED, - "couldn't retrieve setting"); - transitionTo(mStartedState); - } else { - addSingleScanRequest(activeScanSettings); - transitionTo(mSingleScanState); - } - } else { - reportPnoNetworkFound((ScanResult[]) msg.obj); - } - break; - case CMD_PNO_SCAN_FAILED: - sendPnoScanFailedToAllAndClear( - WifiScanner.REASON_UNSPECIFIED, "pno scan failed"); - transitionTo(mStartedState); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class SingleScanState extends State { - @Override - public void enter() { - if (DBG) localLog("SingleScanState"); - } - - @Override - public boolean processMessage(Message msg) { - ClientInfo ci = mClients.get(msg.replyTo); - switch (msg.what) { - case WifiScanner.CMD_SCAN_RESULT: - WifiScanner.ParcelableScanData parcelableScanData = - (WifiScanner.ParcelableScanData) msg.obj; - ScanData[] scanDatas = parcelableScanData.getResults(); - ScanData lastScanData = scanDatas[scanDatas.length - 1]; - reportPnoNetworkFound(lastScanData.getResults()); - transitionTo(mHwPnoScanState); - break; - case WifiScanner.CMD_OP_FAILED: - sendPnoScanFailedToAllAndClear( - WifiScanner.REASON_UNSPECIFIED, "single scan failed"); - transitionTo(mStartedState); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - private WifiNative.PnoSettings convertSettingsToPnoNative(ScanSettings scanSettings, - PnoSettings pnoSettings) { - WifiNative.PnoSettings nativePnoSetting = new WifiNative.PnoSettings(); - nativePnoSetting.periodInMs = scanSettings.periodInMs; - nativePnoSetting.min5GHzRssi = pnoSettings.min5GHzRssi; - nativePnoSetting.min24GHzRssi = pnoSettings.min24GHzRssi; - nativePnoSetting.min6GHzRssi = pnoSettings.min6GHzRssi; - nativePnoSetting.isConnected = pnoSettings.isConnected; - nativePnoSetting.networkList = - new WifiNative.PnoNetwork[pnoSettings.networkList.length]; - for (int i = 0; i < pnoSettings.networkList.length; i++) { - nativePnoSetting.networkList[i] = new WifiNative.PnoNetwork(); - nativePnoSetting.networkList[i].ssid = pnoSettings.networkList[i].ssid; - nativePnoSetting.networkList[i].flags = pnoSettings.networkList[i].flags; - nativePnoSetting.networkList[i].auth_bit_field = - pnoSettings.networkList[i].authBitField; - nativePnoSetting.networkList[i].frequencies = - pnoSettings.networkList[i].frequencies; - } - return nativePnoSetting; - } - - // Retrieve the only active scan settings. - private ScanSettings getScanSettings() { - for (Pair<PnoSettings, ScanSettings> settingsPair : mActivePnoScans.getAllSettings()) { - return settingsPair.second; - } - return null; - } - - private void removeInternalClient() { - if (mInternalClientInfo != null) { - mInternalClientInfo.cleanup(); - mInternalClientInfo = null; - } else { - Log.w(TAG, "No Internal client for PNO"); - } - } - - private void addInternalClient(ClientInfo ci) { - if (mInternalClientInfo == null) { - mInternalClientInfo = - new InternalClientInfo(ci.getUid(), new Messenger(this.getHandler())); - mInternalClientInfo.register(); - } else { - Log.w(TAG, "Internal client for PNO already exists"); - } - } - - private void addPnoScanRequest(ClientInfo ci, int handler, ScanSettings scanSettings, - PnoSettings pnoSettings) { - mActivePnoScans.addRequest(ci, handler, ClientModeImpl.WIFI_WORK_SOURCE, - Pair.create(pnoSettings, scanSettings)); - addInternalClient(ci); - } - - private Pair<PnoSettings, ScanSettings> removePnoScanRequest(ClientInfo ci, int handler) { - Pair<PnoSettings, ScanSettings> settings = mActivePnoScans.removeRequest(ci, handler); - return settings; - } - - private boolean addHwPnoScanRequest(ClientInfo ci, int handler, ScanSettings scanSettings, - PnoSettings pnoSettings) { - if (ci == null) { - Log.d(TAG, "Failing scan request ClientInfo not found " + handler); - return false; - } - if (!mActivePnoScans.isEmpty()) { - loge("Failing scan request because there is already an active scan"); - return false; - } - WifiNative.PnoSettings nativePnoSettings = - convertSettingsToPnoNative(scanSettings, pnoSettings); - if (!mScannerImplsTracker.setHwPnoList(nativePnoSettings)) { - return false; - } - logScanRequest("addHwPnoScanRequest", ci, handler, null, scanSettings, pnoSettings); - addPnoScanRequest(ci, handler, scanSettings, pnoSettings); - - return true; - } - - private void removeHwPnoScanRequest(ClientInfo ci, int handler) { - if (ci != null) { - Pair<PnoSettings, ScanSettings> settings = removePnoScanRequest(ci, handler); - logScanRequest("removeHwPnoScanRequest", ci, handler, null, - settings.second, settings.first); - } - } - - private void reportPnoNetworkFound(ScanResult[] results) { - WifiScanner.ParcelableScanResults parcelableScanResults = - new WifiScanner.ParcelableScanResults(results); - for (RequestInfo<Pair<PnoSettings, ScanSettings>> entry : mActivePnoScans) { - ClientInfo ci = entry.clientInfo; - int handler = entry.handlerId; - logCallback("pnoNetworkFound", ci, handler, describeForLog(results)); - ci.reportEvent( - WifiScanner.CMD_PNO_NETWORK_FOUND, 0, handler, parcelableScanResults); - } - } - - private void sendPnoScanFailedToAllAndClear(int reason, String description) { - for (RequestInfo<Pair<PnoSettings, ScanSettings>> entry : mActivePnoScans) { - ClientInfo ci = entry.clientInfo; - int handler = entry.handlerId; - ci.reportEvent(WifiScanner.CMD_OP_FAILED, 0, handler, - new WifiScanner.OperationResult(reason, description)); - } - mActivePnoScans.clear(); - } - - private void addSingleScanRequest(ScanSettings settings) { - if (DBG) localLog("Starting single scan"); - if (mInternalClientInfo != null) { - mInternalClientInfo.sendRequestToClientHandler( - WifiScanner.CMD_START_SINGLE_SCAN, settings, - ClientModeImpl.WIFI_WORK_SOURCE); - } - } - - /** - * Checks if IE are present in scan data, if no single scan is needed to report event to - * client - */ - private boolean isSingleScanNeeded(ScanResult[] scanResults) { - for (ScanResult scanResult : scanResults) { - if (scanResult.informationElements != null - && scanResult.informationElements.length > 0) { - return false; - } - } - return true; - } - } - - private abstract class ClientInfo { - private final int mUid; - private final WorkSource mWorkSource; - private boolean mScanWorkReported = false; - protected final Messenger mMessenger; - - ClientInfo(int uid, Messenger messenger) { - mUid = uid; - mMessenger = messenger; - mWorkSource = new WorkSource(uid); - } - - /** - * Register this client to main client map. - */ - public void register() { - mClients.put(mMessenger, this); - } - - /** - * Unregister this client from main client map. - */ - private void unregister() { - mClients.remove(mMessenger); - } - - public void cleanup() { - mSingleScanListeners.removeAllForClient(this); - mSingleScanStateMachine.removeSingleScanRequests(this); - mBackgroundScanStateMachine.removeBackgroundScanSettings(this); - unregister(); - localLog("Successfully stopped all requests for client " + this); - } - - public int getUid() { - return mUid; - } - - public void reportEvent(int what, int arg1, int arg2) { - reportEvent(what, arg1, arg2, null); - } - - // This has to be implemented by subclasses to report events back to clients. - public abstract void reportEvent(int what, int arg1, int arg2, Object obj); - - // TODO(b/27903217, 71530998): This is dead code. Should this be wired up ? - private void reportBatchedScanStart() { - if (mUid == 0) - return; - - int csph = getCsph(); - - mBatteryStats.reportWifiBatchedScanStartedFromSource(mWorkSource, csph); - } - - // TODO(b/27903217, 71530998): This is dead code. Should this be wired up ? - private void reportBatchedScanStop() { - if (mUid == 0) - return; - - mBatteryStats.reportWifiBatchedScanStoppedFromSource(mWorkSource); - } - - // TODO migrate batterystats to accept scan duration per hour instead of csph - private int getCsph() { - int totalScanDurationPerHour = 0; - Collection<ScanSettings> settingsList = - mBackgroundScanStateMachine.getBackgroundScanSettings(this); - for (ScanSettings settings : settingsList) { - int scanDurationMs = mChannelHelper.estimateScanDuration(settings); - int scans_per_Hour = settings.periodInMs == 0 ? 1 : (3600 * 1000) / - settings.periodInMs; - totalScanDurationPerHour += scanDurationMs * scans_per_Hour; - } - - return totalScanDurationPerHour / ChannelHelper.SCAN_PERIOD_PER_CHANNEL_MS; - } - - // TODO(b/27903217, 71530998): This is dead code. Should this be wired up ? - private void reportScanWorkUpdate() { - if (mScanWorkReported) { - reportBatchedScanStop(); - mScanWorkReported = false; - } - if (mBackgroundScanStateMachine.getBackgroundScanSettings(this).isEmpty()) { - reportBatchedScanStart(); - mScanWorkReported = true; - } - } - - @Override - public String toString() { - return "ClientInfo[uid=" + mUid + "," + mMessenger + "]"; - } - } - - /** - * This class is used to represent external clients to the WifiScanning Service. - */ - private class ExternalClientInfo extends ClientInfo { - private final AsyncChannel mChannel; - /** - * Indicates if the client is still connected - * If the client is no longer connected then messages to it will be silently dropped - */ - private boolean mDisconnected = false; - - ExternalClientInfo(int uid, Messenger messenger, AsyncChannel c) { - super(uid, messenger); - mChannel = c; - if (DBG) localLog("New client, channel: " + c); - } - - @Override - public void reportEvent(int what, int arg1, int arg2, Object obj) { - if (!mDisconnected) { - mChannel.sendMessage(what, arg1, arg2, obj); - } - } - - @Override - public void cleanup() { - mDisconnected = true; - mPnoScanStateMachine.removePnoSettings(this); - super.cleanup(); - } - } - - /** - * This class is used to represent internal clients to the WifiScanning Service. This is needed - * for communicating between State Machines. - * This leaves the onReportEvent method unimplemented, so that the clients have the freedom - * to handle the events as they need. - */ - private class InternalClientInfo extends ClientInfo { - private static final int INTERNAL_CLIENT_HANDLER = 0; - - /** - * The UID here is used to proxy the original external requester UID. - */ - InternalClientInfo(int requesterUid, Messenger messenger) { - super(requesterUid, messenger); - } - - @Override - public void reportEvent(int what, int arg1, int arg2, Object obj) { - Message message = Message.obtain(); - message.what = what; - message.arg1 = arg1; - message.arg2 = arg2; - message.obj = obj; - try { - mMessenger.send(message); - } catch (RemoteException e) { - loge("Failed to send message: " + what); - } - } - - /** - * Send a message to the client handler which should reroute the message to the appropriate - * state machine. - */ - public void sendRequestToClientHandler(int what, ScanSettings settings, - WorkSource workSource) { - Message msg = Message.obtain(); - msg.what = what; - msg.arg2 = INTERNAL_CLIENT_HANDLER; - if (settings != null) { - Bundle bundle = new Bundle(); - bundle.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings); - bundle.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource); - msg.obj = bundle; - } - msg.replyTo = mMessenger; - msg.sendingUid = getUid(); - mClientHandler.sendMessage(msg); - } - - /** - * Send a message to the client handler which should reroute the message to the appropriate - * state machine. - */ - public void sendRequestToClientHandler(int what) { - sendRequestToClientHandler(what, null, null); - } - - @Override - public String toString() { - return "InternalClientInfo[]"; - } - } - - void replySucceeded(Message msg) { - if (msg.replyTo != null) { - Message reply = Message.obtain(); - reply.what = WifiScanner.CMD_OP_SUCCEEDED; - reply.arg2 = msg.arg2; - if (msg.obj != null) { - reply.obj = msg.obj; - } - try { - msg.replyTo.send(reply); - mLog.trace("replySucceeded recvdMessage=%").c(msg.what).flush(); - } catch (RemoteException e) { - // There's not much we can do if reply can't be sent! - } - } else { - // locally generated message; doesn't need a reply! - } - } - - void replyFailed(Message msg, int reason, String description) { - if (msg.replyTo != null) { - Message reply = Message.obtain(); - reply.what = WifiScanner.CMD_OP_FAILED; - reply.arg2 = msg.arg2; - reply.obj = new WifiScanner.OperationResult(reason, description); - try { - msg.replyTo.send(reply); - mLog.trace("replyFailed recvdMessage=% reason=%") - .c(msg.what) - .c(reason) - .flush(); - } catch (RemoteException e) { - // There's not much we can do if reply can't be sent! - } - } else { - // locally generated message; doesn't need a reply! - } - } - - private static String toString(int uid, ScanSettings settings) { - StringBuilder sb = new StringBuilder(); - sb.append("ScanSettings[uid=").append(uid); - sb.append(", period=").append(settings.periodInMs); - sb.append(", report=").append(settings.reportEvents); - if (settings.reportEvents == WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL - && settings.numBssidsPerScan > 0 - && settings.maxScansToCache > 1) { - sb.append(", batch=").append(settings.maxScansToCache); - sb.append(", numAP=").append(settings.numBssidsPerScan); - } - sb.append(", ").append(ChannelHelper.toString(settings)); - sb.append("]"); - - return sb.toString(); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump WifiScanner from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid() - + " without permission " - + android.Manifest.permission.DUMP); - return; - } - pw.println("WifiScanningService - Log Begin ----"); - mLocalLog.dump(fd, pw, args); - pw.println("WifiScanningService - Log End ----"); - pw.println(); - pw.println("clients:"); - for (ClientInfo client : mClients.values()) { - pw.println(" " + client); - } - pw.println("listeners:"); - for (ClientInfo client : mClients.values()) { - Collection<ScanSettings> settingsList = - mBackgroundScanStateMachine.getBackgroundScanSettings(client); - for (ScanSettings settings : settingsList) { - pw.println(" " + toString(client.mUid, settings)); - } - } - if (mBackgroundScheduler != null) { - WifiNative.ScanSettings schedule = mBackgroundScheduler.getSchedule(); - if (schedule != null) { - pw.println("schedule:"); - pw.println(" base period: " + schedule.base_period_ms); - pw.println(" max ap per scan: " + schedule.max_ap_per_scan); - pw.println(" batched scans: " + schedule.report_threshold_num_scans); - pw.println(" buckets:"); - for (int b = 0; b < schedule.num_buckets; b++) { - WifiNative.BucketSettings bucket = schedule.buckets[b]; - pw.println(" bucket " + bucket.bucket + " (" + bucket.period_ms + "ms)[" - + bucket.report_events + "]: " - + ChannelHelper.toString(bucket)); - } - } - } - if (mPnoScanStateMachine != null) { - mPnoScanStateMachine.dump(fd, pw, args); - } - pw.println(); - - if (mSingleScanStateMachine != null) { - mSingleScanStateMachine.dump(fd, pw, args); - pw.println(); - pw.println("Latest scan results:"); - List<ScanResult> scanResults = mSingleScanStateMachine.getCachedScanResultsAsList(); - long nowMs = mClock.getElapsedSinceBootMillis(); - ScanResultUtil.dumpScanResults(pw, scanResults, nowMs); - pw.println(); - } - for (WifiScannerImpl impl : mScannerImpls.values()) { - impl.dump(fd, pw, args); - } - } - - void logScanRequest(String request, ClientInfo ci, int id, WorkSource workSource, - ScanSettings settings, PnoSettings pnoSettings) { - StringBuilder sb = new StringBuilder(); - sb.append(request) - .append(": ") - .append((ci == null) ? "ClientInfo[unknown]" : ci.toString()) - .append(",Id=") - .append(id); - if (workSource != null) { - sb.append(",").append(workSource); - } - if (settings != null) { - sb.append(", "); - describeTo(sb, settings); - } - if (pnoSettings != null) { - sb.append(", "); - describeTo(sb, pnoSettings); - } - localLog(sb.toString()); - } - - void logCallback(String callback, ClientInfo ci, int id, String extra) { - StringBuilder sb = new StringBuilder(); - sb.append(callback) - .append(": ") - .append((ci == null) ? "ClientInfo[unknown]" : ci.toString()) - .append(",Id=") - .append(id); - if (extra != null) { - sb.append(",").append(extra); - } - localLog(sb.toString()); - } - - static String describeForLog(ScanData[] results) { - StringBuilder sb = new StringBuilder(); - sb.append("results="); - for (int i = 0; i < results.length; ++i) { - if (i > 0) sb.append(";"); - sb.append(results[i].getResults().length); - } - return sb.toString(); - } - - static String describeForLog(ScanResult[] results) { - return "results=" + results.length; - } - - static String getScanTypeString(int type) { - switch(type) { - case WifiScanner.SCAN_TYPE_LOW_LATENCY: - return "LOW LATENCY"; - case WifiScanner.SCAN_TYPE_LOW_POWER: - return "LOW POWER"; - case WifiScanner.SCAN_TYPE_HIGH_ACCURACY: - return "HIGH ACCURACY"; - default: - // This should never happen becuase we've validated the incoming type in - // |validateScanType|. - throw new IllegalArgumentException("Invalid scan type " + type); - } - } - - static String describeTo(StringBuilder sb, ScanSettings scanSettings) { - sb.append("ScanSettings { ") - .append(" type:").append(getScanTypeString(scanSettings.type)) - .append(" band:").append(ChannelHelper.bandToString(scanSettings.band)) - .append(" ignoreLocationSettings:").append(scanSettings.ignoreLocationSettings) - .append(" period:").append(scanSettings.periodInMs) - .append(" reportEvents:").append(scanSettings.reportEvents) - .append(" numBssidsPerScan:").append(scanSettings.numBssidsPerScan) - .append(" maxScansToCache:").append(scanSettings.maxScansToCache) - .append(" channels:[ "); - if (scanSettings.channels != null) { - for (int i = 0; i < scanSettings.channels.length; i++) { - sb.append(scanSettings.channels[i].frequency) - .append(" "); - } - } - sb.append(" ] ") - .append(" } "); - return sb.toString(); - } - - static String describeTo(StringBuilder sb, PnoSettings pnoSettings) { - sb.append("PnoSettings { ") - .append(" min5GhzRssi:").append(pnoSettings.min5GHzRssi) - .append(" min24GhzRssi:").append(pnoSettings.min24GHzRssi) - .append(" min6GhzRssi:").append(pnoSettings.min6GHzRssi) - .append(" isConnected:").append(pnoSettings.isConnected) - .append(" networks:[ "); - if (pnoSettings.networkList != null) { - for (int i = 0; i < pnoSettings.networkList.length; i++) { - sb.append(pnoSettings.networkList[i].ssid).append(","); - } - } - sb.append(" ] ") - .append(" } "); - return sb.toString(); - } -} diff --git a/service/java/com/android/server/wifi/scanner/WificondChannelHelper.java b/service/java/com/android/server/wifi/scanner/WificondChannelHelper.java deleted file mode 100644 index b52ce7e8c..000000000 --- a/service/java/com/android/server/wifi/scanner/WificondChannelHelper.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.scanner; - -import android.net.wifi.WifiScanner; -import android.util.Log; - -import com.android.server.wifi.WifiNative; - -/** - * KnownBandsChannelHelper that uses band to channel mappings retrieved from wificond. - * Also supporting updating the channel list from the wificond on demand. - */ -public class WificondChannelHelper extends KnownBandsChannelHelper { - private static final String TAG = "WificondChannelHelper"; - - private final WifiNative mWifiNative; - - public WificondChannelHelper(WifiNative wifiNative) { - mWifiNative = wifiNative; - final int[] emptyFreqList = new int[0]; - setBandChannels(emptyFreqList, emptyFreqList, emptyFreqList, emptyFreqList); - updateChannels(); - } - - @Override - public void updateChannels() { - int[] channels24G = - mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ); - if (channels24G == null) Log.e(TAG, "Failed to get channels for 2.4GHz band"); - int[] channels5G = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ); - if (channels5G == null) Log.e(TAG, "Failed to get channels for 5GHz band"); - int[] channelsDfs = - mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY); - if (channelsDfs == null) Log.e(TAG, "Failed to get channels for 5GHz DFS only band"); - int[] channels6G = - mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ); - if (channels6G == null) Log.e(TAG, "Failed to get channels for 6GHz band"); - - if (channels24G == null || channels5G == null || channelsDfs == null - || channels6G == null) { - Log.e(TAG, "Failed to get all channels for band, not updating band channel lists"); - } else if (channels24G.length > 0 || channels5G.length > 0 || channelsDfs.length > 0 - || channels6G.length > 0) { - setBandChannels(channels24G, channels5G, channelsDfs, channels6G); - } else { - Log.e(TAG, "Got zero length for all channel lists"); - } - } -} diff --git a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java deleted file mode 100644 index 66e0cfbaa..000000000 --- a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import android.app.AlarmManager; -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.WifiBandIndex; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.ScanDetail; -import com.android.server.wifi.WifiMonitor; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; -import com.android.server.wifi.util.NativeUtil; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.annotation.concurrent.GuardedBy; - -/** - * Implementation of the WifiScanner HAL API that uses wificond to perform all scans - * @see com.android.server.wifi.scanner.WifiScannerImpl for more details on each method. - */ -public class WificondScannerImpl extends WifiScannerImpl implements Handler.Callback { - private static final String TAG = "WificondScannerImpl"; - private static final boolean DBG = false; - - public static final String TIMEOUT_ALARM_TAG = TAG + " Scan Timeout"; - // Max number of networks that can be specified to wificond per scan request - public static final int MAX_HIDDEN_NETWORK_IDS_PER_SCAN = 16; - - private static final int SCAN_BUFFER_CAPACITY = 10; - private static final int MAX_APS_PER_SCAN = 32; - private static final int MAX_SCAN_BUCKETS = 16; - - private final Context mContext; - private final WifiNative mWifiNative; - private final WifiMonitor mWifiMonitor; - private final AlarmManager mAlarmManager; - private final Handler mEventHandler; - private final ChannelHelper mChannelHelper; - private final Clock mClock; - - private final Object mSettingsLock = new Object(); - - private ArrayList<ScanDetail> mNativeScanResults; - private ArrayList<ScanDetail> mNativePnoScanResults; - private WifiScanner.ScanData mLatestSingleScanResult = - new WifiScanner.ScanData(0, 0, new ScanResult[0]); - - // Settings for the currently running single scan, null if no scan active - private LastScanSettings mLastScanSettings = null; - // Settings for the currently running pno scan, null if no scan active - private LastPnoScanSettings mLastPnoScanSettings = null; - - /** - * Duration to wait before timing out a scan. - * - * The expected behavior is that the hardware will return a failed scan if it does not - * complete, but timeout just in case it does not. - */ - private static final long SCAN_TIMEOUT_MS = 15000; - - @GuardedBy("mSettingsLock") - private AlarmManager.OnAlarmListener mScanTimeoutListener; - - public WificondScannerImpl(Context context, String ifaceName, WifiNative wifiNative, - WifiMonitor wifiMonitor, ChannelHelper channelHelper, - Looper looper, Clock clock) { - super(ifaceName); - mContext = context; - mWifiNative = wifiNative; - mWifiMonitor = wifiMonitor; - mChannelHelper = channelHelper; - mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); - mEventHandler = new Handler(looper, this); - mClock = clock; - - wifiMonitor.registerHandler(getIfaceName(), - WifiMonitor.SCAN_FAILED_EVENT, mEventHandler); - wifiMonitor.registerHandler(getIfaceName(), - WifiMonitor.PNO_SCAN_RESULTS_EVENT, mEventHandler); - wifiMonitor.registerHandler(getIfaceName(), - WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler); - } - - @Override - public void cleanup() { - synchronized (mSettingsLock) { - stopHwPnoScan(); - mLastScanSettings = null; // finally clear any active scan - mLastPnoScanSettings = null; // finally clear any active scan - mWifiMonitor.deregisterHandler(getIfaceName(), - WifiMonitor.SCAN_FAILED_EVENT, mEventHandler); - mWifiMonitor.deregisterHandler(getIfaceName(), - WifiMonitor.PNO_SCAN_RESULTS_EVENT, mEventHandler); - mWifiMonitor.deregisterHandler(getIfaceName(), - WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler); - } - } - - @Override - public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { - capabilities.max_scan_cache_size = Integer.MAX_VALUE; - capabilities.max_scan_buckets = MAX_SCAN_BUCKETS; - capabilities.max_ap_cache_per_scan = MAX_APS_PER_SCAN; - capabilities.max_rssi_sample_size = 8; - capabilities.max_scan_reporting_threshold = SCAN_BUFFER_CAPACITY; - return true; - } - - @Override - public ChannelHelper getChannelHelper() { - return mChannelHelper; - } - - @Override - public boolean startSingleScan(WifiNative.ScanSettings settings, - WifiNative.ScanEventHandler eventHandler) { - if (eventHandler == null || settings == null) { - Log.w(TAG, "Invalid arguments for startSingleScan: settings=" + settings - + ",eventHandler=" + eventHandler); - return false; - } - synchronized (mSettingsLock) { - if (mLastScanSettings != null) { - Log.w(TAG, "A single scan is already running"); - return false; - } - - ChannelCollection allFreqs = mChannelHelper.createChannelCollection(); - boolean reportFullResults = false; - - for (int i = 0; i < settings.num_buckets; ++i) { - WifiNative.BucketSettings bucketSettings = settings.buckets[i]; - if ((bucketSettings.report_events - & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { - reportFullResults = true; - } - allFreqs.addChannels(bucketSettings); - } - - List<String> hiddenNetworkSSIDSet = new ArrayList<>(); - if (settings.hiddenNetworks != null) { - int numHiddenNetworks = - Math.min(settings.hiddenNetworks.length, MAX_HIDDEN_NETWORK_IDS_PER_SCAN); - for (int i = 0; i < numHiddenNetworks; i++) { - hiddenNetworkSSIDSet.add(settings.hiddenNetworks[i].ssid); - } - } - mLastScanSettings = new LastScanSettings( - mClock.getElapsedSinceBootMillis(), - reportFullResults, allFreqs, eventHandler); - - boolean success = false; - Set<Integer> freqs; - if (!allFreqs.isEmpty()) { - freqs = allFreqs.getScanFreqs(); - success = mWifiNative.scan( - getIfaceName(), settings.scanType, freqs, hiddenNetworkSSIDSet); - if (!success) { - Log.e(TAG, "Failed to start scan, freqs=" + freqs); - } - } else { - // There is a scan request but no available channels could be scanned for. - // We regard it as a scan failure in this case. - Log.e(TAG, "Failed to start scan because there is no available channel to scan"); - } - if (success) { - if (DBG) { - Log.d(TAG, "Starting wifi scan for freqs=" + freqs); - } - - mScanTimeoutListener = new AlarmManager.OnAlarmListener() { - @Override public void onAlarm() { - handleScanTimeout(); - } - }; - - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + SCAN_TIMEOUT_MS, - TIMEOUT_ALARM_TAG, mScanTimeoutListener, mEventHandler); - } else { - // indicate scan failure async - mEventHandler.post(new Runnable() { - @Override public void run() { - reportScanFailure(); - } - }); - } - - return true; - } - } - - @Override - public WifiScanner.ScanData getLatestSingleScanResults() { - return mLatestSingleScanResult; - } - - @Override - public boolean startBatchedScan(WifiNative.ScanSettings settings, - WifiNative.ScanEventHandler eventHandler) { - Log.w(TAG, "startBatchedScan() is not supported"); - return false; - } - - @Override - public void stopBatchedScan() { - Log.w(TAG, "stopBatchedScan() is not supported"); - } - - @Override - public void pauseBatchedScan() { - Log.w(TAG, "pauseBatchedScan() is not supported"); - } - - @Override - public void restartBatchedScan() { - Log.w(TAG, "restartBatchedScan() is not supported"); - } - - private void handleScanTimeout() { - synchronized (mSettingsLock) { - Log.e(TAG, "Timed out waiting for scan result from wificond"); - reportScanFailure(); - mScanTimeoutListener = null; - } - } - - @Override - public boolean handleMessage(Message msg) { - switch(msg.what) { - case WifiMonitor.SCAN_FAILED_EVENT: - Log.w(TAG, "Scan failed"); - cancelScanTimeout(); - reportScanFailure(); - break; - case WifiMonitor.PNO_SCAN_RESULTS_EVENT: - pollLatestScanDataForPno(); - break; - case WifiMonitor.SCAN_RESULTS_EVENT: - cancelScanTimeout(); - pollLatestScanData(); - break; - default: - // ignore unknown event - } - return true; - } - - private void cancelScanTimeout() { - synchronized (mSettingsLock) { - if (mScanTimeoutListener != null) { - mAlarmManager.cancel(mScanTimeoutListener); - mScanTimeoutListener = null; - } - } - } - - private void reportScanFailure() { - synchronized (mSettingsLock) { - if (mLastScanSettings != null) { - if (mLastScanSettings.singleScanEventHandler != null) { - mLastScanSettings.singleScanEventHandler - .onScanStatus(WifiNative.WIFI_SCAN_FAILED); - } - mLastScanSettings = null; - } - } - } - - private void reportPnoScanFailure() { - synchronized (mSettingsLock) { - if (mLastPnoScanSettings != null) { - if (mLastPnoScanSettings.pnoScanEventHandler != null) { - mLastPnoScanSettings.pnoScanEventHandler.onPnoScanFailed(); - } - // Clean up PNO state, we don't want to continue PNO scanning. - mLastPnoScanSettings = null; - } - } - } - - private void pollLatestScanDataForPno() { - synchronized (mSettingsLock) { - if (mLastPnoScanSettings == null) { - // got a scan before we started scanning or after scan was canceled - return; - } - mNativePnoScanResults = mWifiNative.getPnoScanResults(getIfaceName()); - List<ScanResult> hwPnoScanResults = new ArrayList<>(); - int numFilteredScanResults = 0; - for (int i = 0; i < mNativePnoScanResults.size(); ++i) { - ScanResult result = mNativePnoScanResults.get(i).getScanResult(); - long timestamp_ms = result.timestamp / 1000; // convert us -> ms - if (timestamp_ms > mLastPnoScanSettings.startTime) { - hwPnoScanResults.add(result); - } else { - numFilteredScanResults++; - } - } - - if (numFilteredScanResults != 0) { - Log.d(TAG, "Filtering out " + numFilteredScanResults + " pno scan results."); - } - - if (mLastPnoScanSettings.pnoScanEventHandler != null) { - ScanResult[] pnoScanResultsArray = - hwPnoScanResults.toArray(new ScanResult[hwPnoScanResults.size()]); - mLastPnoScanSettings.pnoScanEventHandler.onPnoNetworkFound(pnoScanResultsArray); - } - } - } - - /** - * Return one of the WIFI_BAND_# values that was scanned for in this scan. - */ - private static int getBandScanned(ChannelCollection channelCollection) { - int bandScanned = WifiScanner.WIFI_BAND_UNSPECIFIED; - - for (@WifiBandIndex int i = 0; i < WifiScanner.WIFI_BAND_COUNT; i++) { - if (channelCollection.containsBand(1 << i)) { - bandScanned |= 1 << i; - } - } - return bandScanned; - } - - private void pollLatestScanData() { - synchronized (mSettingsLock) { - if (mLastScanSettings == null) { - // got a scan before we started scanning or after scan was canceled - return; - } - - mNativeScanResults = mWifiNative.getScanResults(getIfaceName()); - List<ScanResult> singleScanResults = new ArrayList<>(); - int numFilteredScanResults = 0; - for (int i = 0; i < mNativeScanResults.size(); ++i) { - ScanResult result = mNativeScanResults.get(i).getScanResult(); - long timestamp_ms = result.timestamp / 1000; // convert us -> ms - if (timestamp_ms > mLastScanSettings.startTime) { - if (mLastScanSettings.singleScanFreqs.containsChannel( - result.frequency)) { - singleScanResults.add(result); - } - } else { - numFilteredScanResults++; - } - } - if (numFilteredScanResults != 0) { - Log.d(TAG, "Filtering out " + numFilteredScanResults + " scan results."); - } - - if (mLastScanSettings.singleScanEventHandler != null) { - if (mLastScanSettings.reportSingleScanFullResults) { - for (ScanResult scanResult : singleScanResults) { - // ignore buckets scanned since there is only one bucket for a single scan - mLastScanSettings.singleScanEventHandler.onFullScanResult(scanResult, - /* bucketsScanned */ 0); - } - } - Collections.sort(singleScanResults, SCAN_RESULT_SORT_COMPARATOR); - mLatestSingleScanResult = new WifiScanner.ScanData(0, 0, 0, - getBandScanned(mLastScanSettings.singleScanFreqs), - singleScanResults.toArray(new ScanResult[singleScanResults.size()])); - mLastScanSettings.singleScanEventHandler - .onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - } - - mLastScanSettings = null; - } - } - - - @Override - public WifiScanner.ScanData[] getLatestBatchedScanResults(boolean flush) { - return null; - } - - private boolean startHwPnoScan(WifiNative.PnoSettings pnoSettings) { - return mWifiNative.startPnoScan(getIfaceName(), pnoSettings); - } - - private void stopHwPnoScan() { - mWifiNative.stopPnoScan(getIfaceName()); - } - - /** - * Hw Pno Scan is required only for disconnected PNO when the device supports it. - * @param isConnectedPno Whether this is connected PNO vs disconnected PNO. - * @return true if HW PNO scan is required, false otherwise. - */ - private boolean isHwPnoScanRequired(boolean isConnectedPno) { - return (!isConnectedPno - && mContext.getResources().getBoolean(R.bool.config_wifi_background_scan_support)); - } - - @Override - public boolean setHwPnoList(WifiNative.PnoSettings settings, - WifiNative.PnoEventHandler eventHandler) { - synchronized (mSettingsLock) { - if (mLastPnoScanSettings != null) { - Log.w(TAG, "Already running a PNO scan"); - return false; - } - if (!isHwPnoScanRequired(settings.isConnected)) { - return false; - } - - mLastPnoScanSettings = new LastPnoScanSettings( - mClock.getElapsedSinceBootMillis(), - settings.networkList, eventHandler); - - if (!startHwPnoScan(settings)) { - Log.e(TAG, "Failed to start PNO scan"); - reportPnoScanFailure(); - } - return true; - } - } - - @Override - public boolean resetHwPnoList() { - synchronized (mSettingsLock) { - if (mLastPnoScanSettings == null) { - Log.w(TAG, "No PNO scan running"); - return false; - } - mLastPnoScanSettings = null; - // For wificond based PNO, we stop the scan immediately when we reset pno list. - stopHwPnoScan(); - return true; - } - } - - @Override - public boolean isHwPnoSupported(boolean isConnectedPno) { - // Hw Pno Scan is supported only for disconnected PNO when the device supports it. - return isHwPnoScanRequired(isConnectedPno); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - synchronized (mSettingsLock) { - long nowMs = mClock.getElapsedSinceBootMillis(); - pw.println("Latest native scan results:"); - if (mNativeScanResults != null) { - List<ScanResult> scanResults = mNativeScanResults.stream().map(r -> { - return r.getScanResult(); - }).collect(Collectors.toList()); - ScanResultUtil.dumpScanResults(pw, scanResults, nowMs); - } - pw.println("Latest native pno scan results:"); - if (mNativePnoScanResults != null) { - List<ScanResult> pnoScanResults = mNativePnoScanResults.stream().map(r -> { - return r.getScanResult(); - }).collect(Collectors.toList()); - ScanResultUtil.dumpScanResults(pw, pnoScanResults, nowMs); - } - pw.println("Latest native scan results IEs:"); - if (mNativeScanResults != null) { - for (ScanDetail detail : mNativeScanResults) { - if (detail.getInformationElementRawData() != null) { - pw.println(NativeUtil.hexStringFromByteArray( - detail.getInformationElementRawData())); - } - } - } - pw.println(""); - } - } - - private static class LastScanSettings { - LastScanSettings(long startTime, - boolean reportSingleScanFullResults, - ChannelCollection singleScanFreqs, - WifiNative.ScanEventHandler singleScanEventHandler) { - this.startTime = startTime; - this.reportSingleScanFullResults = reportSingleScanFullResults; - this.singleScanFreqs = singleScanFreqs; - this.singleScanEventHandler = singleScanEventHandler; - } - - public long startTime; - public boolean reportSingleScanFullResults; - public ChannelCollection singleScanFreqs; - public WifiNative.ScanEventHandler singleScanEventHandler; - - } - - private static class LastPnoScanSettings { - LastPnoScanSettings(long startTime, - WifiNative.PnoNetwork[] pnoNetworkList, - WifiNative.PnoEventHandler pnoScanEventHandler) { - this.startTime = startTime; - this.pnoNetworkList = pnoNetworkList; - this.pnoScanEventHandler = pnoScanEventHandler; - } - - public long startTime; - public WifiNative.PnoNetwork[] pnoNetworkList; - public WifiNative.PnoEventHandler pnoScanEventHandler; - - } - -} diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java deleted file mode 100644 index 1e8cc24a0..000000000 --- a/service/java/com/android/server/wifi/util/ApConfigUtil.java +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.res.Resources; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApConfiguration.BandType; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiScanner; -import android.util.Log; -import android.util.SparseArray; - -import com.android.server.wifi.WifiNative; -import com.android.wifi.resources.R; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Random; - -/** - * Provide utility functions for updating soft AP related configuration. - */ -public class ApConfigUtil { - private static final String TAG = "ApConfigUtil"; - - public static final int DEFAULT_AP_BAND = SoftApConfiguration.BAND_2GHZ; - public static final int DEFAULT_AP_CHANNEL = 6; - public static final int HIGHEST_2G_AP_CHANNEL = 14; - - /* Return code for updateConfiguration. */ - public static final int SUCCESS = 0; - public static final int ERROR_NO_CHANNEL = 1; - public static final int ERROR_GENERIC = 2; - public static final int ERROR_UNSUPPORTED_CONFIGURATION = 3; - - /* Random number generator used for AP channel selection. */ - private static final Random sRandom = new Random(); - - /** - * Valid Global Operating classes in each wifi band - * Reference: Table E-4 in IEEE Std 802.11-2016. - */ - private static final SparseArray<int[]> sBandToOperatingClass = new SparseArray<>(); - static { - sBandToOperatingClass.append(SoftApConfiguration.BAND_2GHZ, new int[]{81, 82, 83, 84}); - sBandToOperatingClass.append(SoftApConfiguration.BAND_5GHZ, new int[]{115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130}); - sBandToOperatingClass.append(SoftApConfiguration.BAND_6GHZ, new int[]{131, 132, 133, 134, - 135, 136}); - } - - /** - * Helper function to get the band corresponding to the operating class. - * - * @param operatingClass Global operating class. - * @return band, -1 if no match. - * - */ - public static int getBandFromOperatingClass(int operatingClass) { - for (int i = 0; i < sBandToOperatingClass.size(); i++) { - int band = sBandToOperatingClass.keyAt(i); - int[] operatingClasses = sBandToOperatingClass.get(band); - - for (int j = 0; j < operatingClasses.length; j++) { - if (operatingClasses[j] == operatingClass) { - return band; - } - } - } - return -1; - } - - /** - * Convert band from SoftApConfiguration.BandType to WifiScanner.WifiBand - * @param band in SoftApConfiguration.BandType - * @return band in WifiScanner.WifiBand - */ - public static @WifiScanner.WifiBand int apConfig2wifiScannerBand(@BandType int band) { - switch(band) { - case SoftApConfiguration.BAND_2GHZ: - return WifiScanner.WIFI_BAND_24_GHZ; - case SoftApConfiguration.BAND_5GHZ: - return WifiScanner.WIFI_BAND_5_GHZ; - case SoftApConfiguration.BAND_6GHZ: - return WifiScanner.WIFI_BAND_6_GHZ; - default: - return WifiScanner.WIFI_BAND_UNSPECIFIED; - } - } - - /** - * Convert channel/band to frequency. - * Note: the utility does not perform any regulatory domain compliance. - * @param channel number to convert - * @param band of channel to convert - * @return center frequency in Mhz of the channel, -1 if no match - */ - public static int convertChannelToFrequency(int channel, @BandType int band) { - return ScanResult.convertChannelToFrequencyMhz(channel, - apConfig2wifiScannerBand(band)); - } - - /** - * Convert frequency to band. - * Note: the utility does not perform any regulatory domain compliance. - * @param frequency frequency to convert - * @return band, -1 if no match - */ - public static int convertFrequencyToBand(int frequency) { - if (ScanResult.is24GHz(frequency)) { - return SoftApConfiguration.BAND_2GHZ; - } else if (ScanResult.is5GHz(frequency)) { - return SoftApConfiguration.BAND_5GHZ; - } else if (ScanResult.is6GHz(frequency)) { - return SoftApConfiguration.BAND_6GHZ; - } - - return -1; - } - - /** - * Convert band from WifiConfiguration into SoftApConfiguration - * - * @param wifiConfigBand band encoded as WifiConfiguration.AP_BAND_xxxx - * @return band as encoded as SoftApConfiguration.BAND_xxx - */ - public static int convertWifiConfigBandToSoftApConfigBand(int wifiConfigBand) { - switch (wifiConfigBand) { - case WifiConfiguration.AP_BAND_2GHZ: - return SoftApConfiguration.BAND_2GHZ; - case WifiConfiguration.AP_BAND_5GHZ: - return SoftApConfiguration.BAND_5GHZ; - case WifiConfiguration.AP_BAND_ANY: - return SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ; - default: - return SoftApConfiguration.BAND_2GHZ; - } - } - - /** - * Checks if band is a valid combination of {link SoftApConfiguration#BandType} values - */ - public static boolean isBandValid(@BandType int band) { - return ((band != 0) && ((band & ~SoftApConfiguration.BAND_ANY) == 0)); - } - - /** - * Check if the band contains a certain sub-band - * - * @param band The combination of bands to validate - * @param testBand the test band to validate on - * @return true if band contains testBand, false otherwise - */ - public static boolean containsBand(@BandType int band, @BandType int testBand) { - return ((band & testBand) != 0); - } - - /** - * Checks if band contains multiple sub-bands - * @param band a combination of sub-bands - * @return true if band has multiple sub-bands, false otherwise - */ - public static boolean isMultiband(@BandType int band) { - return ((band & (band - 1)) != 0); - } - - /** - * Convert string to channel list - * Format of the list is a comma separated channel numbers, or range of channel numbers - * Example, "34-48, 149". - * @param channelString for a comma separated channel numbers, or range of channel numbers - * such as "34-48, 149" - * @return list of channel numbers - */ - public static List<Integer> convertStringToChannelList(String channelString) { - if (channelString == null) { - return null; - } - - List<Integer> channelList = new ArrayList<Integer>(); - - for (String channelRange : channelString.split(",")) { - try { - if (channelRange.contains("-")) { - String[] channels = channelRange.split("-"); - if (channels.length != 2) { - Log.e(TAG, "Unrecognized channel range, Length is " + channels.length); - continue; - } - int start = Integer.parseInt(channels[0].trim()); - int end = Integer.parseInt(channels[1].trim()); - if (start > end) { - Log.e(TAG, "Invalid channel range, from " + start + " to " + end); - continue; - } - - for (int channel = start; channel <= end; channel++) { - channelList.add(channel); - } - } else { - channelList.add(Integer.parseInt(channelRange.trim())); - } - } catch (NumberFormatException e) { - // Ignore malformed string - Log.e(TAG, "Malformed channel value detected: " + e); - continue; - } - } - return channelList; - } - - /** - * Get channel frequencies for band that are allowed by both regulatory and OEM configuration - * - * @param band to get channels for - * @param wifiNative reference used to get regulatory restrictionsimport java.util.Arrays; - * @param resources used to get OEM restrictions - * @return A list of frequencies that are allowed, null on error. - */ - public static List<Integer> getAvailableChannelFreqsForBand( - @BandType int band, WifiNative wifiNative, Resources resources) { - if (!isBandValid(band) || isMultiband(band)) { - return null; - } - - List<Integer> configuredList; - int scannerBand; - switch (band) { - case SoftApConfiguration.BAND_2GHZ: - configuredList = convertStringToChannelList(resources.getString( - R.string.config_wifiSoftap2gChannelList)); - scannerBand = WifiScanner.WIFI_BAND_24_GHZ; - break; - case SoftApConfiguration.BAND_5GHZ: - configuredList = convertStringToChannelList(resources.getString( - R.string.config_wifiSoftap5gChannelList)); - scannerBand = WifiScanner.WIFI_BAND_5_GHZ; - break; - case SoftApConfiguration.BAND_6GHZ: - configuredList = convertStringToChannelList(resources.getString( - R.string.config_wifiSoftap6gChannelList)); - scannerBand = WifiScanner.WIFI_BAND_6_GHZ; - break; - default: - return null; - } - - // Get the allowed list of channel frequencies in MHz - int[] regulatoryArray = wifiNative.getChannelsForBand(scannerBand); - List<Integer> regulatoryList = new ArrayList<Integer>(); - for (int freq : regulatoryArray) { - regulatoryList.add(freq); - } - - if (configuredList == null || configuredList.isEmpty()) { - return regulatoryList; - } - - List<Integer> filteredList = new ArrayList<Integer>(); - // Otherwise, filter the configured list - for (int channel : configuredList) { - int channelFreq = convertChannelToFrequency(channel, band); - - if (regulatoryList.contains(channelFreq)) { - filteredList.add(channelFreq); - } - } - return filteredList; - } - - /** - * Return a channel number for AP setup based on the frequency band. - * @param apBand one or combination of the values of SoftApConfiguration.BAND_*. - * @param wifiNative reference used to collect regulatory restrictions. - * @param resources the resources to use to get configured allowed channels. - * @return a valid channel frequency on success, -1 on failure. - */ - public static int chooseApChannel(int apBand, WifiNative wifiNative, Resources resources) { - if (!isBandValid(apBand)) { - Log.e(TAG, "Invalid band: " + apBand); - return -1; - } - - List<Integer> allowedFreqList = null; - - if ((apBand & SoftApConfiguration.BAND_6GHZ) != 0) { - allowedFreqList = getAvailableChannelFreqsForBand(SoftApConfiguration.BAND_6GHZ, - wifiNative, resources); - if (allowedFreqList != null && allowedFreqList.size() > 0) { - return allowedFreqList.get(sRandom.nextInt(allowedFreqList.size())).intValue(); - } - } - - if ((apBand & SoftApConfiguration.BAND_5GHZ) != 0) { - allowedFreqList = getAvailableChannelFreqsForBand(SoftApConfiguration.BAND_5GHZ, - wifiNative, resources); - if (allowedFreqList != null && allowedFreqList.size() > 0) { - return allowedFreqList.get(sRandom.nextInt(allowedFreqList.size())).intValue(); - } - } - - if ((apBand & SoftApConfiguration.BAND_2GHZ) != 0) { - allowedFreqList = getAvailableChannelFreqsForBand(SoftApConfiguration.BAND_2GHZ, - wifiNative, resources); - if (allowedFreqList != null && allowedFreqList.size() > 0) { - return allowedFreqList.get(sRandom.nextInt(allowedFreqList.size())).intValue(); - } - } - - // If the default AP band is allowed, just use the default channel - if (containsBand(apBand, DEFAULT_AP_BAND)) { - Log.e(TAG, "Allowed channel list not specified, selecting default channel"); - /* Use default channel. */ - return convertChannelToFrequency(DEFAULT_AP_CHANNEL, - DEFAULT_AP_BAND); - } - - Log.e(TAG, "No available channels"); - return -1; - } - - /** - * Update AP band and channel based on the provided country code and band. - * This will also set - * @param wifiNative reference to WifiNative - * @param resources the resources to use to get configured allowed channels. - * @param countryCode country code - * @param config configuration to update - * @return an integer result code - */ - public static int updateApChannelConfig(WifiNative wifiNative, - Resources resources, - String countryCode, - SoftApConfiguration.Builder configBuilder, - SoftApConfiguration config, - boolean acsEnabled) { - /* Use default band and channel for device without HAL. */ - if (!wifiNative.isHalStarted()) { - configBuilder.setChannel(DEFAULT_AP_CHANNEL, DEFAULT_AP_BAND); - return SUCCESS; - } - - /* Country code is mandatory for 5GHz band. */ - if (config.getBand() == SoftApConfiguration.BAND_5GHZ - && countryCode == null) { - Log.e(TAG, "5GHz band is not allowed without country code"); - return ERROR_GENERIC; - } - - /* Select a channel if it is not specified and ACS is not enabled */ - if ((config.getChannel() == 0) && !acsEnabled) { - int freq = chooseApChannel(config.getBand(), wifiNative, resources); - if (freq == -1) { - /* We're not able to get channel from wificond. */ - Log.e(TAG, "Failed to get available channel."); - return ERROR_NO_CHANNEL; - } - configBuilder.setChannel( - ScanResult.convertFrequencyMhzToChannel(freq), convertFrequencyToBand(freq)); - } - - return SUCCESS; - } - - /** - * Helper function for converting WifiConfiguration to SoftApConfiguration. - * - * Only Support None and WPA2 configuration conversion. - * Note that WifiConfiguration only Supports 2GHz, 5GHz, 2GHz+5GHz bands, - * so conversion is limited to these bands. - * - * @param wifiConfig the WifiConfiguration which need to convert. - * @return the SoftApConfiguration if wifiConfig is valid, null otherwise. - */ - @Nullable - public static SoftApConfiguration fromWifiConfiguration( - @NonNull WifiConfiguration wifiConfig) { - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - try { - configBuilder.setSsid(wifiConfig.SSID); - if (wifiConfig.getAuthType() == WifiConfiguration.KeyMgmt.WPA2_PSK) { - configBuilder.setPassphrase(wifiConfig.preSharedKey, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - } - configBuilder.setHiddenSsid(wifiConfig.hiddenSSID); - - int band; - switch (wifiConfig.apBand) { - case WifiConfiguration.AP_BAND_2GHZ: - band = SoftApConfiguration.BAND_2GHZ; - break; - case WifiConfiguration.AP_BAND_5GHZ: - band = SoftApConfiguration.BAND_5GHZ; - break; - default: - // WifiConfiguration.AP_BAND_ANY means only 2GHz and 5GHz bands - band = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ; - break; - } - if (wifiConfig.apChannel == 0) { - configBuilder.setBand(band); - } else { - configBuilder.setChannel(wifiConfig.apChannel, band); - } - } catch (IllegalArgumentException iae) { - Log.e(TAG, "Invalid WifiConfiguration" + iae); - return null; - } catch (IllegalStateException ise) { - Log.e(TAG, "Invalid WifiConfiguration" + ise); - return null; - } - return configBuilder.build(); - } - - /** - * Helper function to creating SoftApCapability instance with initial field from resource file. - * - * @param context the caller context used to get value from resource file. - * @return SoftApCapability which updated the feature support or not from resource. - */ - @NonNull - public static SoftApCapability updateCapabilityFromResource(@NonNull Context context) { - long features = 0; - if (isAcsSupported(context)) { - Log.d(TAG, "Update Softap capability, add acs feature support"); - features |= SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD; - } - - if (isClientForceDisconnectSupported(context)) { - Log.d(TAG, "Update Softap capability, add client control feature support"); - features |= SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT; - } - - if (isWpa3SaeSupported(context)) { - Log.d(TAG, "Update Softap capability, add SAE feature support"); - features |= SoftApCapability.SOFTAP_FEATURE_WPA3_SAE; - } - SoftApCapability capability = new SoftApCapability(features); - int hardwareSupportedMaxClient = context.getResources().getInteger( - R.integer.config_wifiHardwareSoftapMaxClientCount); - if (hardwareSupportedMaxClient > 0) { - Log.d(TAG, "Update Softap capability, max client = " + hardwareSupportedMaxClient); - capability.setMaxSupportedClients(hardwareSupportedMaxClient); - } - - return capability; - } - - /** - * Helper function to get hal support client force disconnect or not. - * - * @param context the caller context used to get value from resource file. - * @return true if supported, false otherwise. - */ - public static boolean isClientForceDisconnectSupported(@NonNull Context context) { - return context.getResources().getBoolean( - R.bool.config_wifiSofapClientForceDisconnectSupported); - } - - /** - * Helper function to get SAE support or not. - * - * @param context the caller context used to get value from resource file. - * @return true if supported, false otherwise. - */ - public static boolean isWpa3SaeSupported(@NonNull Context context) { - return context.getResources().getBoolean( - R.bool.config_wifi_softap_sae_supported); - } - - /** - * Helper function to get ACS support or not. - * - * @param context the caller context used to get value from resource file. - * @return true if supported, false otherwise. - */ - public static boolean isAcsSupported(@NonNull Context context) { - return context.getResources().getBoolean( - R.bool.config_wifi_softap_acs_supported); - } - - /** - * Helper function for comparing two SoftApConfiguration. - * - * @param currentConfig the original configuration. - * @param newConfig the new configuration which plan to apply. - * @return true if the difference between the two configurations requires a restart to apply, - * false otherwise. - */ - public static boolean checkConfigurationChangeNeedToRestart( - SoftApConfiguration currentConfig, SoftApConfiguration newConfig) { - return !Objects.equals(currentConfig.getSsid(), newConfig.getSsid()) - || !Objects.equals(currentConfig.getBssid(), newConfig.getBssid()) - || currentConfig.getSecurityType() != newConfig.getSecurityType() - || !Objects.equals(currentConfig.getPassphrase(), newConfig.getPassphrase()) - || currentConfig.isHiddenSsid() != newConfig.isHiddenSsid() - || currentConfig.getBand() != newConfig.getBand() - || currentConfig.getChannel() != newConfig.getChannel(); - } - - - /** - * Helper function for checking all of the configuration are supported or not. - * - * @param config target configuration want to check. - * @param capability the capability which indicate feature support or not. - * @return true if supported, false otherwise. - */ - public static boolean checkSupportAllConfiguration(SoftApConfiguration config, - SoftApCapability capability) { - if (!capability.areFeaturesSupported( - SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT) - && (config.getMaxNumberOfClients() != 0 || config.isClientControlByUserEnabled() - || config.getBlockedClientList().size() != 0)) { - Log.d(TAG, "Error, Client control requires HAL support"); - return false; - } - - if (!capability.areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE) - && (config.getSecurityType() - == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION - || config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)) { - Log.d(TAG, "Error, SAE requires HAL support"); - return false; - } - return true; - } -} diff --git a/service/java/com/android/server/wifi/util/ArrayUtils.java b/service/java/com/android/server/wifi/util/ArrayUtils.java deleted file mode 100644 index 330abc025..000000000 --- a/service/java/com/android/server/wifi/util/ArrayUtils.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.annotation.Nullable; - -import java.util.Collection; -import java.util.Objects; - -/** - * Copied over from frameworks/base/core/java/com/android/internal/util/ArrayUtils.java - */ -public class ArrayUtils { - private ArrayUtils() { /* cannot be instantiated */ } - - /** - * Checks if the beginnings of two byte arrays are equal. - * - * @param array1 the first byte array - * @param array2 the second byte array - * @param length the number of bytes to check - * @return true if they're equal, false otherwise - */ - public static boolean equals(byte[] array1, byte[] array2, int length) { - if (length < 0) { - throw new IllegalArgumentException(); - } - - if (array1 == array2) { - return true; - } - if (array1 == null || array2 == null || array1.length < length || array2.length < length) { - return false; - } - for (int i = 0; i < length; i++) { - if (array1[i] != array2[i]) { - return false; - } - } - return true; - } - - /** - * Checks if given array is null or has zero elements. - */ - public static boolean isEmpty(@Nullable Collection<?> array) { - return array == null || array.isEmpty(); - } - - /** - * Checks if given array is null or has zero elements. - */ - public static <T> boolean isEmpty(@Nullable T[] array) { - return array == null || array.length == 0; - } - - /** - * Checks if given array is null or has zero elements. - */ - public static boolean isEmpty(@Nullable int[] array) { - return array == null || array.length == 0; - } - - /** - * Checks if given array is null or has zero elements. - */ - public static boolean isEmpty(@Nullable long[] array) { - return array == null || array.length == 0; - } - - /** - * Checks if given array is null or has zero elements. - */ - public static boolean isEmpty(@Nullable byte[] array) { - return array == null || array.length == 0; - } - - /** - * Checks if given array is null or has zero elements. - */ - public static boolean isEmpty(@Nullable boolean[] array) { - return array == null || array.length == 0; - } - - /** - * Length of the given array or 0 if it's null. - */ - public static int size(@Nullable Object[] array) { - return array == null ? 0 : array.length; - } - - /** - * Length of the given collection or 0 if it's null. - */ - public static int size(@Nullable Collection<?> collection) { - return collection == null ? 0 : collection.size(); - } - - /** - * Checks that value is present as at least one of the elements of the array. - * - * @param array the array to check in - * @param value the value to check for - * @return true if the value is present in the array - */ - public static <T> boolean contains(@Nullable T[] array, T value) { - return indexOf(array, value) != -1; - } - - /** - * Checks that value is present as at least one of the elements of the array. - * - * @param array the array to check in - * @param value the value to check for - * @return true if the value is present in the array - */ - public static boolean contains(@Nullable int[] array, int value) { - if (array == null) return false; - for (int element : array) { - if (element == value) { - return true; - } - } - return false; - } - - /** - * Checks that value is present as at least one of the elements of the array. - * - * @param array the array to check in - * @param value the value to check for - * @return true if the value is present in the array - */ - public static boolean contains(@Nullable long[] array, long value) { - if (array == null) return false; - for (long element : array) { - if (element == value) { - return true; - } - } - return false; - } - - /** - * Checks that value is present as at least one of the elements of the array. - * - * @param array the array to check in - * @param value the value to check for - * @return true if the value is present in the array - */ - public static boolean contains(@Nullable char[] array, char value) { - if (array == null) return false; - for (char element : array) { - if (element == value) { - return true; - } - } - return false; - } - - /** - * Return first index of {@code value} in {@code array}, or {@code -1} if - * not found. - */ - public static <T> int indexOf(@Nullable T[] array, T value) { - if (array == null) return -1; - for (int i = 0; i < array.length; i++) { - if (Objects.equals(array[i], value)) return i; - } - return -1; - } -} - diff --git a/service/java/com/android/server/wifi/util/BitMask.java b/service/java/com/android/server/wifi/util/BitMask.java deleted file mode 100644 index a6a82fd49..000000000 --- a/service/java/com/android/server/wifi/util/BitMask.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.util; - -/** - * Helper for translating bit-flags packed into an int - */ -public class BitMask { - public int value; - - public BitMask(int value) { - this.value = value; - } - - /** - * Clears the specifed bit, returning true if it was set - * - * @param maskBit to test and clear - * @return true if and only if the mask was originally set in value - */ - public boolean testAndClear(int maskBit) { - boolean ans = (value & maskBit) != 0; - value &= ~maskBit; - return ans; - } -} diff --git a/service/java/com/android/server/wifi/util/ByteArrayRingBuffer.java b/service/java/com/android/server/wifi/util/ByteArrayRingBuffer.java deleted file mode 100644 index 4341feeb3..000000000 --- a/service/java/com/android/server/wifi/util/ByteArrayRingBuffer.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import java.util.ArrayList; - -/** - * A ring buffer where each element of the ring is itself a byte array. - */ -public class ByteArrayRingBuffer { - private ArrayList<byte[]> mArrayList; - private int mMaxBytes; - private int mBytesUsed; - - /** - * Creates a ring buffer that holds at most |maxBytes| of data. The overhead for each element - * is not included in this limit. - * @param maxBytes upper bound on the amount of data to hold - */ - public ByteArrayRingBuffer(int maxBytes) { - if (maxBytes < 1) { - throw new IllegalArgumentException(); - } - mArrayList = new ArrayList<byte[]>(); - mMaxBytes = maxBytes; - mBytesUsed = 0; - } - - /** - * Adds |newData| to the ring buffer. Removes existing entries to make room, if necessary. - * Existing entries are removed in FIFO order. - * <p><b>Note:</b> will fail if |newData| itself exceeds the size limit for this buffer. - * Will first remove all existing entries in this case. (This guarantees that the ring buffer - * always represents a contiguous sequence of data.) - * @param newData data to be added to the ring - * @return true if the data was added - */ - public boolean appendBuffer(byte[] newData) { - pruneToSize(mMaxBytes - newData.length); - if (mBytesUsed + newData.length > mMaxBytes) { - return false; - } - - mArrayList.add(newData); - mBytesUsed += newData.length; - return true; - } - - /** - * Returns the |i|-th element of the ring. The element retains its position in the ring. - * @param i - * @return the requested element - */ - public byte[] getBuffer(int i) { - return mArrayList.get(i); - } - - /** - * Returns the number of elements present in the ring. - * @return the number of elements present - */ - public int getNumBuffers() { - return mArrayList.size(); - } - - /** - * Resize the buffer, removing existing data if necessary. - * @param maxBytes upper bound on the amount of data to hold - */ - public void resize(int maxBytes) { - pruneToSize(maxBytes); - mMaxBytes = maxBytes; - } - - private void pruneToSize(int sizeBytes) { - int newBytesUsed = mBytesUsed; - int i = 0; - while (i < mArrayList.size() && newBytesUsed > sizeBytes) { - newBytesUsed -= mArrayList.get(i).length; - i++; - } - mArrayList.subList(0, i).clear(); - mBytesUsed = newBytesUsed; - } -} diff --git a/service/java/com/android/server/wifi/util/EncryptedData.java b/service/java/com/android/server/wifi/util/EncryptedData.java deleted file mode 100644 index baec20426..000000000 --- a/service/java/com/android/server/wifi/util/EncryptedData.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import com.android.internal.util.Preconditions; - -import java.util.Arrays; -import java.util.Objects; - -/** - * A class to store data created by {@link WifiConfigStoreEncryptionUtil}. - */ -public class EncryptedData { - private final byte[] mEncryptedData; - private final byte[] mIv; - - public EncryptedData(byte[] encryptedData, byte[] iv) { - Preconditions.checkNotNull(encryptedData); - Preconditions.checkNotNull(iv); - mEncryptedData = encryptedData; - mIv = iv; - } - - public byte[] getEncryptedData() { - return mEncryptedData; - } - - public byte[] getIv() { - return mIv; - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof EncryptedData)) return false; - EncryptedData otherEncryptedData = (EncryptedData) other; - return Arrays.equals(this.mEncryptedData, otherEncryptedData.mEncryptedData) - && Arrays.equals(this.mIv, otherEncryptedData.mIv); - } - - @Override - public int hashCode() { - return Objects.hash(Arrays.hashCode(mEncryptedData), Arrays.hashCode(mIv)); - } -} diff --git a/service/java/com/android/server/wifi/util/Environment.java b/service/java/com/android/server/wifi/util/Environment.java deleted file mode 100644 index a423d55e6..000000000 --- a/service/java/com/android/server/wifi/util/Environment.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.content.ApexEnvironment; -import android.content.pm.ApplicationInfo; -import android.os.UserHandle; - -import java.io.File; - -/** - * Provides access to environment variables. - * - * Note: @hide methods copied from android.os.Environment - */ -public class Environment { - /** - * Wifi apex name. - */ - private static final String WIFI_APEX_NAME = "com.android.wifi"; - - /** - * The path where the Wifi apex is mounted. - * Current value = "/apex/com.android.wifi" - */ - private static final String WIFI_APEX_PATH = - new File("/apex", WIFI_APEX_NAME).getAbsolutePath(); - - /** - * Wifi shared folder. - */ - public static File getWifiSharedDirectory() { - return ApexEnvironment.getApexEnvironment(WIFI_APEX_NAME).getDeviceProtectedDataDir(); - } - - /** - * Wifi user specific folder. - */ - public static File getWifiUserDirectory(int userId) { - return ApexEnvironment.getApexEnvironment(WIFI_APEX_NAME) - .getCredentialProtectedDataDirForUser(UserHandle.of(userId)); - } - - /** - * Returns true if the app is in the Wifi apex, false otherwise. - * Checks if the app's path starts with "/apex/com.android.wifi". - */ - public static boolean isAppInWifiApex(ApplicationInfo appInfo) { - return appInfo.sourceDir.startsWith(WIFI_APEX_PATH); - } -} diff --git a/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java b/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java deleted file mode 100644 index 225e68ac4..000000000 --- a/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.util; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import com.android.internal.util.Preconditions; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Holds a list of external app-provided binder callback objects and tracks the death - * of the callback object. - * @param <T> Callback object type. - */ -public class ExternalCallbackTracker<T> { - private static final String TAG = "WifiExternalCallbackTracker"; - - /* Limit on number of registered callbacks to track and prevent potential memory leak */ - private static final int NUM_CALLBACKS_WARN_LIMIT = 10; - private static final int NUM_CALLBACKS_WTF_LIMIT = 20; - - /** - * Container for storing info about each external callback and tracks it's death. - */ - private static class ExternalCallbackHolder<T> implements IBinder.DeathRecipient { - private final IBinder mBinder; - private final T mCallbackObject; - private final DeathCallback mDeathCallback; - - /** - * Callback to be invoked on death of the app hosting the binder. - */ - public interface DeathCallback { - /** - * Called when the corresponding app has died. - */ - void onDeath(); - } - - private ExternalCallbackHolder(@NonNull IBinder binder, @NonNull T callbackObject, - @NonNull DeathCallback deathCallback) { - mBinder = Preconditions.checkNotNull(binder); - mCallbackObject = Preconditions.checkNotNull(callbackObject); - mDeathCallback = Preconditions.checkNotNull(deathCallback); - } - - /** - * Static method to create a new {@link ExternalCallbackHolder} object and register for - * death notification of the associated binder. - * @return an instance of {@link ExternalCallbackHolder} if there are no failures, otherwise - * null. - */ - public static <T> ExternalCallbackHolder<T> createAndLinkToDeath( - @NonNull IBinder binder, @NonNull T callbackObject, - @NonNull DeathCallback deathCallback) { - ExternalCallbackHolder<T> externalCallback = - new ExternalCallbackHolder<>(binder, callbackObject, deathCallback); - try { - binder.linkToDeath(externalCallback, 0); - } catch (RemoteException e) { - Log.e(TAG, "Error on linkToDeath - " + e); - return null; - } - return externalCallback; - } - - /** - * Unlinks this object from binder death. - */ - public void reset() { - mBinder.unlinkToDeath(this, 0); - } - - /** - * Retrieve the callback object. - */ - public T getCallback() { - return mCallbackObject; - } - - /** - * App hosting the binder has died. - */ - @Override - public void binderDied() { - mDeathCallback.onDeath(); - Log.d(TAG, "Binder died " + mBinder); - } - } - - private final Map<Integer, ExternalCallbackHolder<T>> mCallbacks; - private final Handler mHandler; - - public ExternalCallbackTracker(Handler handler) { - mHandler = handler; - mCallbacks = new HashMap<>(); - } - - /** - * Add a callback object to tracker. - * @return true on success, false on failure. - */ - public boolean add(@NonNull IBinder binder, @NonNull T callbackObject, int callbackIdentifier) { - ExternalCallbackHolder<T> externalCallback = ExternalCallbackHolder.createAndLinkToDeath( - binder, callbackObject, () -> { - mHandler.post(() -> { - Log.d(TAG, "Remove external callback on death " + callbackIdentifier); - remove(callbackIdentifier); - }); - }); - if (externalCallback == null) return false; - if (mCallbacks.containsKey(callbackIdentifier)) { - Log.d(TAG, "Replacing callback " + callbackIdentifier); - remove(callbackIdentifier); - } - mCallbacks.put(callbackIdentifier, externalCallback); - if (mCallbacks.size() > NUM_CALLBACKS_WTF_LIMIT) { - Log.wtf(TAG, "Too many callbacks: " + mCallbacks.size()); - } else if (mCallbacks.size() > NUM_CALLBACKS_WARN_LIMIT) { - Log.w(TAG, "Too many callbacks: " + mCallbacks.size()); - } - return true; - } - - /** - * Remove a callback object to tracker. - * @return Removed object instance on success, null on failure. - */ - public @Nullable T remove(int callbackIdentifier) { - ExternalCallbackHolder<T> externalCallback = mCallbacks.remove(callbackIdentifier); - if (externalCallback == null) { - Log.w(TAG, "Unknown external callback " + callbackIdentifier); - return null; - } - externalCallback.reset(); - return externalCallback.getCallback(); - } - - /** - * Retrieve all the callback objects in the tracker. - */ - public List<T> getCallbacks() { - List<T> callbacks = new ArrayList<>(); - for (ExternalCallbackHolder<T> externalCallback : mCallbacks.values()) { - callbacks.add(externalCallback.getCallback()); - } - return callbacks; - } - - /** - * Retrieve the number of callback objects in the tracker. - */ - public int getNumCallbacks() { - return mCallbacks.size(); - } - - /** - * Remove all callbacks registered. - */ - public void clear() { - for (ExternalCallbackHolder<T> externalCallback : mCallbacks.values()) { - externalCallback.reset(); - } - mCallbacks.clear(); - } -} diff --git a/service/java/com/android/server/wifi/util/FileUtils.java b/service/java/com/android/server/wifi/util/FileUtils.java deleted file mode 100644 index fb8214246..000000000 --- a/service/java/com/android/server/wifi/util/FileUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -/** - * Utility methods useful for working with files. - * - * Note: @hide methods copied from android.os.FileUtils - */ -public final class FileUtils { - private static final String TAG = "FileUtils"; - - /** - * Change the mode of a file. - * - * @param path path of the file - * @param mode to apply through {@code chmod} - * @return 0 on success, otherwise errno. - */ - public static int chmod(String path, int mode) { - try { - Os.chmod(path, mode); - return 0; - } catch (ErrnoException e) { - Log.w(TAG, "Failed to chmod(" + path + ", " + mode + "): ", e); - return e.errno; - } - } - - /** - * Writes the bytes given in {@code content} to the file whose absolute path - * is {@code filename}. - */ - public static void bytesToFile(String filename, byte[] content) throws IOException { - try (FileOutputStream fos = new FileOutputStream(filename)) { - fos.write(content); - } - } - - /** - * Writes string to file. Basically same as "echo -n $string > $filename" - * - * @param filename - * @param string - * @throws IOException - */ - public static void stringToFile(String filename, String string) throws IOException { - bytesToFile(filename, string.getBytes(StandardCharsets.UTF_8)); - } -} diff --git a/service/java/com/android/server/wifi/util/FrameParser.java b/service/java/com/android/server/wifi/util/FrameParser.java deleted file mode 100644 index c48ca8e2e..000000000 --- a/service/java/com/android/server/wifi/util/FrameParser.java +++ /dev/null @@ -1,1018 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import android.util.Log; - -import com.android.server.wifi.WifiLoggerHal; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.HashSet; -import java.util.Set; - -/** - * This class parses the raw bytes of a network frame, and stores the parsed information in its - * public fields. - */ -public class FrameParser { - /** - * Note: When adding constants derived from network protocol specifications, please encode - * these constants the same way as the relevant specification, for ease of comparison. - */ - - private static final String TAG = "FrameParser"; - - /* These fields hold the information parsed from this frame. */ - public String mMostSpecificProtocolString = "N/A"; - public String mTypeString = "N/A"; - public String mResultString = "N/A"; - - /** - * Parses the contents of a given network frame. - * - * @param frameType The type of the frame, as defined in - * {@link com.android.server.wifi.WifiLoggerHal}. - * @param frameBytes The raw bytes of the frame to be parsed. - */ - public FrameParser(byte frameType, byte[] frameBytes) { - try { - ByteBuffer frameBuffer = ByteBuffer.wrap(frameBytes); - frameBuffer.order(ByteOrder.BIG_ENDIAN); - if (frameType == WifiLoggerHal.FRAME_TYPE_ETHERNET_II) { - parseEthernetFrame(frameBuffer); - } else if (frameType == WifiLoggerHal.FRAME_TYPE_80211_MGMT) { - parseManagementFrame(frameBuffer); - } - } catch (BufferUnderflowException | IllegalArgumentException e) { - Log.e(TAG, "Dissection aborted mid-frame: " + e); - } - } - - /** - * Read one byte into a form that can easily be compared against, or output as, an integer - * in the range (0, 255). - */ - private static short getUnsignedByte(ByteBuffer data) { - return (short) (data.get() & 0x00ff); - } - /** - * Read two bytes into a form that can easily be compared against, or output as, an integer - * in the range (0, 65535). - */ - private static int getUnsignedShort(ByteBuffer data) { - return (data.getShort() & 0xffff); - } - - private static final int ETHERNET_SRC_MAC_ADDR_LEN = 6; - private static final int ETHERNET_DST_MAC_ADDR_LEN = 6; - private static final short ETHERTYPE_IP_V4 = (short) 0x0800; - private static final short ETHERTYPE_ARP = (short) 0x0806; - private static final short ETHERTYPE_IP_V6 = (short) 0x86dd; - private static final short ETHERTYPE_EAPOL = (short) 0x888e; - - private void parseEthernetFrame(ByteBuffer data) { - mMostSpecificProtocolString = "Ethernet"; - data.position(data.position() + ETHERNET_SRC_MAC_ADDR_LEN + ETHERNET_DST_MAC_ADDR_LEN); - short etherType = data.getShort(); - switch (etherType) { - case ETHERTYPE_IP_V4: - parseIpv4Packet(data); - return; - case ETHERTYPE_ARP: - parseArpPacket(data); - return; - case ETHERTYPE_IP_V6: - parseIpv6Packet(data); - return; - case ETHERTYPE_EAPOL: - parseEapolPacket(data); - return; - default: - return; - } - } - - private static final byte IP_V4_VERSION_BYTE_MASK = (byte) 0b11110000; - private static final byte IP_V4_IHL_BYTE_MASK = (byte) 0b00001111; - private static final byte IP_V4_ADDR_LEN = 4; - private static final byte IP_V4_DSCP_AND_ECN_LEN = 1; - private static final byte IP_V4_TOTAL_LEN_LEN = 2; - private static final byte IP_V4_ID_LEN = 2; - private static final byte IP_V4_FLAGS_AND_FRAG_OFFSET_LEN = 2; - private static final byte IP_V4_TTL_LEN = 1; - private static final byte IP_V4_HEADER_CHECKSUM_LEN = 2; - private static final byte IP_V4_SRC_ADDR_LEN = 4; - private static final byte IP_V4_DST_ADDR_LEN = 4; - private static final byte IP_PROTO_ICMP = 1; - private static final byte IP_PROTO_TCP = 6; - private static final byte IP_PROTO_UDP = 17; - private static final byte BYTES_PER_QUAD = 4; - - private void parseIpv4Packet(ByteBuffer data) { - mMostSpecificProtocolString = "IPv4"; - data.mark(); - byte versionAndHeaderLen = data.get(); - int version = (versionAndHeaderLen & IP_V4_VERSION_BYTE_MASK) >> 4; - if (version != 4) { - Log.e(TAG, "IPv4 header: Unrecognized protocol version " + version); - return; - } - - data.position(data.position() + IP_V4_DSCP_AND_ECN_LEN + IP_V4_TOTAL_LEN_LEN - + IP_V4_ID_LEN + IP_V4_FLAGS_AND_FRAG_OFFSET_LEN + IP_V4_TTL_LEN); - short protocolNumber = getUnsignedByte(data); - data.position(data.position() + IP_V4_HEADER_CHECKSUM_LEN + IP_V4_SRC_ADDR_LEN - + IP_V4_DST_ADDR_LEN); - - int headerLen = (versionAndHeaderLen & IP_V4_IHL_BYTE_MASK) * BYTES_PER_QUAD; - data.reset(); // back to start of IPv4 header - data.position(data.position() + headerLen); - - switch (protocolNumber) { - case IP_PROTO_ICMP: - parseIcmpPacket(data); - break; - case IP_PROTO_TCP: - parseTcpPacket(data); - break; - case IP_PROTO_UDP: - parseUdpPacket(data); - break; - default: - break; - } - } - - private static final byte TCP_SRC_PORT_LEN = 2; - private static final int HTTPS_PORT = 443; - private static final Set<Integer> HTTP_PORTS = new HashSet<>(); - static { - HTTP_PORTS.add(80); - HTTP_PORTS.add(3128); - HTTP_PORTS.add(3132); - HTTP_PORTS.add(5985); - HTTP_PORTS.add(8080); - HTTP_PORTS.add(8088); - HTTP_PORTS.add(11371); - HTTP_PORTS.add(1900); - HTTP_PORTS.add(2869); - HTTP_PORTS.add(2710); - } - - private void parseTcpPacket(ByteBuffer data) { - mMostSpecificProtocolString = "TCP"; - data.position(data.position() + TCP_SRC_PORT_LEN); - int dstPort = getUnsignedShort(data); - - if (dstPort == HTTPS_PORT) { - mTypeString = "HTTPS"; - } else if (HTTP_PORTS.contains(dstPort)) { - mTypeString = "HTTP"; - } - } - - private static final byte UDP_PORT_BOOTPS = 67; - private static final byte UDP_PORT_BOOTPC = 68; - private static final byte UDP_PORT_NTP = 123; - private static final byte UDP_CHECKSUM_LEN = 2; - - private void parseUdpPacket(ByteBuffer data) { - mMostSpecificProtocolString = "UDP"; - int srcPort = getUnsignedShort(data); - int dstPort = getUnsignedShort(data); - int length = getUnsignedShort(data); - - data.position(data.position() + UDP_CHECKSUM_LEN); - if ((srcPort == UDP_PORT_BOOTPC && dstPort == UDP_PORT_BOOTPS) - || (srcPort == UDP_PORT_BOOTPS && dstPort == UDP_PORT_BOOTPC)) { - parseDhcpPacket(data); - return; - } - if (srcPort == UDP_PORT_NTP || dstPort == UDP_PORT_NTP) { - mMostSpecificProtocolString = "NTP"; - return; - } - } - - private static final byte BOOTP_OPCODE_LEN = 1; - private static final byte BOOTP_HWTYPE_LEN = 1; - private static final byte BOOTP_HWADDR_LEN_LEN = 1; - private static final byte BOOTP_HOPCOUNT_LEN = 1; - private static final byte BOOTP_TRANSACTION_ID_LEN = 4; - private static final byte BOOTP_ELAPSED_SECONDS_LEN = 2; - private static final byte BOOTP_FLAGS_LEN = 2; - private static final byte BOOTP_CLIENT_HWADDR_LEN = 16; - private static final byte BOOTP_SERVER_HOSTNAME_LEN = 64; - private static final short BOOTP_BOOT_FILENAME_LEN = 128; - private static final byte BOOTP_MAGIC_COOKIE_LEN = 4; - private static final short DHCP_OPTION_TAG_PAD = 0; - private static final short DHCP_OPTION_TAG_MESSAGE_TYPE = 53; - private static final short DHCP_OPTION_TAG_END = 255; - - private void parseDhcpPacket(ByteBuffer data) { - mMostSpecificProtocolString = "DHCP"; - data.position(data.position() + BOOTP_OPCODE_LEN + BOOTP_HWTYPE_LEN + BOOTP_HWADDR_LEN_LEN - + BOOTP_HOPCOUNT_LEN + BOOTP_TRANSACTION_ID_LEN + BOOTP_ELAPSED_SECONDS_LEN - + BOOTP_FLAGS_LEN + IP_V4_ADDR_LEN * 4 + BOOTP_CLIENT_HWADDR_LEN - + BOOTP_SERVER_HOSTNAME_LEN + BOOTP_BOOT_FILENAME_LEN + BOOTP_MAGIC_COOKIE_LEN); - while (data.remaining() > 0) { - short dhcpOptionTag = getUnsignedByte(data); - if (dhcpOptionTag == DHCP_OPTION_TAG_PAD) { - continue; - } - if (dhcpOptionTag == DHCP_OPTION_TAG_END) { - break; - } - short dhcpOptionLen = getUnsignedByte(data); - switch (dhcpOptionTag) { - case DHCP_OPTION_TAG_MESSAGE_TYPE: - if (dhcpOptionLen != 1) { - Log.e(TAG, "DHCP option len: " + dhcpOptionLen + " (expected |1|)"); - return; - } - mTypeString = decodeDhcpMessageType(getUnsignedByte(data)); - return; - default: - data.position(data.position() + dhcpOptionLen); - } - } - } - - private static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1; - private static final byte DHCP_MESSAGE_TYPE_OFFER = 2; - private static final byte DHCP_MESSAGE_TYPE_REQUEST = 3; - private static final byte DHCP_MESSAGE_TYPE_DECLINE = 4; - private static final byte DHCP_MESSAGE_TYPE_ACK = 5; - private static final byte DHCP_MESSAGE_TYPE_NAK = 6; - private static final byte DHCP_MESSAGE_TYPE_RELEASE = 7; - private static final byte DHCP_MESSAGE_TYPE_INFORM = 8; - - private static String decodeDhcpMessageType(short messageType) { - switch (messageType) { - case DHCP_MESSAGE_TYPE_DISCOVER: - return "Discover"; - case DHCP_MESSAGE_TYPE_OFFER: - return "Offer"; - case DHCP_MESSAGE_TYPE_REQUEST: - return "Request"; - case DHCP_MESSAGE_TYPE_DECLINE: - return "Decline"; - case DHCP_MESSAGE_TYPE_ACK: - return "Ack"; - case DHCP_MESSAGE_TYPE_NAK: - return "Nak"; - case DHCP_MESSAGE_TYPE_RELEASE: - return "Release"; - case DHCP_MESSAGE_TYPE_INFORM: - return "Inform"; - default: - return "Unknown type " + messageType; - } - } - - private static final byte ICMP_TYPE_ECHO_REPLY = 0; - private static final byte ICMP_TYPE_DEST_UNREACHABLE = 3; - private static final byte ICMP_TYPE_REDIRECT = 5; - private static final byte ICMP_TYPE_ECHO_REQUEST = 8; - - private void parseIcmpPacket(ByteBuffer data) { - mMostSpecificProtocolString = "ICMP"; - short messageType = getUnsignedByte(data); - switch (messageType) { - case ICMP_TYPE_ECHO_REPLY: - mTypeString = "Echo Reply"; - return; - case ICMP_TYPE_DEST_UNREACHABLE: - mTypeString = "Destination Unreachable"; - return; - case ICMP_TYPE_REDIRECT: - mTypeString = "Redirect"; - return; - case ICMP_TYPE_ECHO_REQUEST: - mTypeString = "Echo Request"; - return; - default: - mTypeString = "Type " + messageType; - return; - } - } - - private static final byte ARP_HWTYPE_LEN = 2; - private static final byte ARP_PROTOTYPE_LEN = 2; - private static final byte ARP_HWADDR_LEN_LEN = 1; - private static final byte ARP_PROTOADDR_LEN_LEN = 1; - private static final byte ARP_OPCODE_REQUEST = 1; - private static final byte ARP_OPCODE_REPLY = 2; - - private void parseArpPacket(ByteBuffer data) { - mMostSpecificProtocolString = "ARP"; - data.position(data.position() + ARP_HWTYPE_LEN + ARP_PROTOTYPE_LEN + ARP_HWADDR_LEN_LEN - + ARP_PROTOADDR_LEN_LEN); - int opCode = getUnsignedShort(data); - switch (opCode) { - case ARP_OPCODE_REQUEST: - mTypeString = "Request"; - break; - case ARP_OPCODE_REPLY: - mTypeString = "Reply"; - break; - default: - mTypeString = "Operation " + opCode; - } - } - - private static final byte IP_V6_PAYLOAD_LENGTH_LEN = 2; - private static final byte IP_V6_HOP_LIMIT_LEN = 1; - private static final byte IP_V6_ADDR_LEN = 16; - private static final byte IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION = 0; - private static final byte IP_V6_HEADER_TYPE_ICMP_V6 = 58; - private static final byte BYTES_PER_OCT = 8; - - private void parseIpv6Packet(ByteBuffer data) { - mMostSpecificProtocolString = "IPv6"; - int versionClassAndLabel = data.getInt(); - int version = (versionClassAndLabel & 0xf0000000) >> 28; - if (version != 6) { - Log.e(TAG, "IPv6 header: invalid IP version " + version); - return; - } - data.position(data.position() + IP_V6_PAYLOAD_LENGTH_LEN); - - short nextHeaderType = getUnsignedByte(data); - data.position(data.position() + IP_V6_HOP_LIMIT_LEN + IP_V6_ADDR_LEN * 2); - while (nextHeaderType == IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION) { - int thisHeaderLen; - data.mark(); - nextHeaderType = getUnsignedByte(data); - thisHeaderLen = (getUnsignedByte(data) + 1) * BYTES_PER_OCT; - data.reset(); // back to start of this header - data.position(data.position() + thisHeaderLen); - } - switch (nextHeaderType) { - case IP_V6_HEADER_TYPE_ICMP_V6: - parseIcmpV6Packet(data); - return; - default: - mTypeString = "Option/Protocol " + nextHeaderType; - return; - } - } - - private static final short ICMP_V6_TYPE_ECHO_REQUEST = 128; - private static final short ICMP_V6_TYPE_ECHO_REPLY = 129; - private static final short ICMP_V6_TYPE_ROUTER_SOLICITATION = 133; - private static final short ICMP_V6_TYPE_ROUTER_ADVERTISEMENT = 134; - private static final short ICMP_V6_TYPE_NEIGHBOR_SOLICITATION = 135; - private static final short ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT = 136; - private static final short ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY = 143; - - private void parseIcmpV6Packet(ByteBuffer data) { - mMostSpecificProtocolString = "ICMPv6"; - short icmpV6Type = getUnsignedByte(data); - switch (icmpV6Type) { - case ICMP_V6_TYPE_ECHO_REQUEST: - mTypeString = "Echo Request"; - return; - case ICMP_V6_TYPE_ECHO_REPLY: - mTypeString = "Echo Reply"; - return; - case ICMP_V6_TYPE_ROUTER_SOLICITATION: - mTypeString = "Router Solicitation"; - return; - case ICMP_V6_TYPE_ROUTER_ADVERTISEMENT: - mTypeString = "Router Advertisement"; - return; - case ICMP_V6_TYPE_NEIGHBOR_SOLICITATION: - mTypeString = "Neighbor Solicitation"; - return; - case ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT: - mTypeString = "Neighbor Advertisement"; - return; - case ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY: - mTypeString = "MLDv2 report"; - return; - default: - mTypeString = "Type " + icmpV6Type; - return; - } - } - - private static final byte EAPOL_TYPE_KEY = 3; - private static final byte EAPOL_KEY_DESCRIPTOR_RSN_KEY = 2; - private static final byte EAPOL_LENGTH_LEN = 2; - private static final short WPA_KEY_INFO_FLAG_PAIRWISE = (short) 1 << 3; // bit 4 - private static final short WPA_KEY_INFO_FLAG_INSTALL = (short) 1 << 6; // bit 7 - private static final short WPA_KEY_INFO_FLAG_MIC = (short) 1 << 8; // bit 9 - private static final byte WPA_KEYLEN_LEN = 2; - private static final byte WPA_REPLAY_COUNTER_LEN = 8; - private static final byte WPA_KEY_NONCE_LEN = 32; - private static final byte WPA_KEY_IV_LEN = 16; - private static final byte WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN = 8; - private static final byte WPA_KEY_IDENTIFIER_LEN = 8; - private static final byte WPA_KEY_MIC_LEN = 16; - - private void parseEapolPacket(ByteBuffer data) { - mMostSpecificProtocolString = "EAPOL"; - short eapolVersion = getUnsignedByte(data); - if (eapolVersion < 1 || eapolVersion > 2) { - Log.e(TAG, "Unrecognized EAPOL version " + eapolVersion); - return; - } - - short eapolType = getUnsignedByte(data); - if (eapolType != EAPOL_TYPE_KEY) { - Log.e(TAG, "Unrecognized EAPOL type " + eapolType); - return; - } - - data.position(data.position() + EAPOL_LENGTH_LEN); - short eapolKeyDescriptorType = getUnsignedByte(data); - if (eapolKeyDescriptorType != EAPOL_KEY_DESCRIPTOR_RSN_KEY) { - Log.e(TAG, "Unrecognized key descriptor " + eapolKeyDescriptorType); - return; - } - - short wpaKeyInfo = data.getShort(); - if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_PAIRWISE) == 0) { - mTypeString = "Group Key"; - } else { - mTypeString = "Pairwise Key"; - } - - // See goo.gl/tu8AQC for details. - if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_MIC) == 0) { - mTypeString += " message 1/4"; - return; - } - - if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_INSTALL) != 0) { - mTypeString += " message 3/4"; - return; - } - - data.position(data.position() + WPA_KEYLEN_LEN + WPA_REPLAY_COUNTER_LEN - + WPA_KEY_NONCE_LEN + WPA_KEY_IV_LEN + WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN - + WPA_KEY_IDENTIFIER_LEN + WPA_KEY_MIC_LEN); - int wpaKeyDataLen = getUnsignedShort(data); - if (wpaKeyDataLen > 0) { - mTypeString += " message 2/4"; - } else { - mTypeString += " message 4/4"; - } - } - - private static final byte IEEE_80211_FRAME_TYPE_MGMT = 0b00; - // Per 802.11-2016 Table 9-1 - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ASSOC_REQ = 0b0000; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ASSOC_RESP = 0b0001; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_REASSOC_REQ = 0b0010; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_REASSOC_RESP = 0b0011; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_PROBE_REQ = 0b0100; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_PROBE_RESP = 0b0101; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_TIMING_AD = 0b0110; - // 0b0111 reserved - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_BEACON = 0b1000; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ATIM = 0b1001; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_DISASSOC = 0b1010; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_AUTH = 0b1011; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_DEAUTH = 0b1100; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ACTION = 0b1101; - private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ACTION_NO_ACK = 0b1110; - // 0b1111 reserved - - private static final byte IEEE_80211_FRAME_FLAG_ORDER = (byte) (1 << 7); // bit 8 - private static final byte IEEE_80211_DURATION_LEN = 2; - private static final byte IEEE_80211_ADDR1_LEN = 6; - private static final byte IEEE_80211_ADDR2_LEN = 6; - private static final byte IEEE_80211_ADDR3_LEN = 6; - private static final byte IEEE_80211_SEQUENCE_CONTROL_LEN = 2; - private static final byte IEEE_80211_HT_CONTROL_LEN = 4; - - private static byte parseIeee80211FrameCtrlVersion(byte b) { - return (byte) (b & 0b00000011); - } - private static byte parseIeee80211FrameCtrlType(byte b) { - return (byte) ((b & 0b00001100) >> 2); - } - private static byte parseIeee80211FrameCtrlSubtype(byte b) { - return (byte) ((b & 0b11110000) >> 4); - } - private void parseManagementFrame(ByteBuffer data) { // 802.11-2012 Sec 8.3.3.1 - data.order(ByteOrder.LITTLE_ENDIAN); - - mMostSpecificProtocolString = "802.11 Mgmt"; - byte frameControlVersionTypeSubtype = data.get(); - byte ieee80211Version = parseIeee80211FrameCtrlVersion(frameControlVersionTypeSubtype); - if (ieee80211Version != 0) { - Log.e(TAG, "Unrecognized 802.11 version " + ieee80211Version); - return; - } - - byte ieee80211FrameType = parseIeee80211FrameCtrlType(frameControlVersionTypeSubtype); - if (ieee80211FrameType != IEEE_80211_FRAME_TYPE_MGMT) { - Log.e(TAG, "Unexpected frame type " + ieee80211FrameType); - return; - } - - byte frameControlFlags = data.get(); - - data.position(data.position() + IEEE_80211_DURATION_LEN + IEEE_80211_ADDR1_LEN - + IEEE_80211_ADDR2_LEN + IEEE_80211_ADDR3_LEN + IEEE_80211_SEQUENCE_CONTROL_LEN); - - if ((frameControlFlags & IEEE_80211_FRAME_FLAG_ORDER) != 0) { - // Per 802.11-2012 Sec 8.2.4.1.10. - data.position(data.position() + IEEE_80211_HT_CONTROL_LEN); - } - - byte ieee80211FrameSubtype = parseIeee80211FrameCtrlSubtype(frameControlVersionTypeSubtype); - switch (ieee80211FrameSubtype) { - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ASSOC_REQ: - mTypeString = "Association Request"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ASSOC_RESP: - mTypeString = "Association Response"; - parseAssociationResponse(data); - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_REASSOC_REQ: - mTypeString = "Reassociation Request"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_REASSOC_RESP: - mTypeString = "Reassociation Response"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_PROBE_REQ: - mTypeString = "Probe Request"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_PROBE_RESP: - mTypeString = "Probe Response"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_TIMING_AD: - mTypeString = "Timing Advertisement"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_BEACON: - mTypeString = "Beacon"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ATIM: - mTypeString = "ATIM"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_DISASSOC: - mTypeString = "Disassociation"; - parseDisassociationFrame(data); - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_AUTH: - mTypeString = "Authentication"; - parseAuthenticationFrame(data); - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_DEAUTH: - mTypeString = "Deauthentication"; - parseDeauthenticationFrame(data); - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ACTION: - mTypeString = "Action"; - return; - case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ACTION_NO_ACK: - mTypeString = "Action No Ack"; - return; - case 0b0111: - case 0b1111: - mTypeString = "Reserved"; - return; - default: - mTypeString = "Unexpected subtype " + ieee80211FrameSubtype; - return; - } - } - - // Per 802.11-2012 Secs 8.3.3.6 and 8.4.1. - private static final byte IEEE_80211_CAPABILITY_INFO_LEN = 2; - private void parseAssociationResponse(ByteBuffer data) { - data.position(data.position() + IEEE_80211_CAPABILITY_INFO_LEN); - short resultCode = data.getShort(); - mResultString = String.format( - "%d: %s", resultCode, decodeIeee80211StatusCode(resultCode)); - } - - // Per 802.11-2016 Sec 9.3.3.5 - private void parseDisassociationFrame(ByteBuffer data) { - short reasonCode = data.getShort(); - mResultString = String.format("%d: %s", reasonCode, decodeIeee80211ReasonCode(reasonCode)); - } - - // Per 802.11-2012 Secs 8.3.3.11 and 8.4.1. - private static final short IEEE_80211_AUTH_ALG_OPEN = 0; - private static final short IEEE_80211_AUTH_ALG_SHARED_KEY = 1; - private static final short IEEE_80211_AUTH_ALG_FAST_BSS_TRANSITION = 2; - private static final short IEEE_80211_AUTH_ALG_SIMUL_AUTH_OF_EQUALS = 3; - private void parseAuthenticationFrame(ByteBuffer data) { - short algorithm = data.getShort(); - short sequenceNum = data.getShort(); - boolean hasResultCode = false; - switch (algorithm) { - case IEEE_80211_AUTH_ALG_OPEN: - case IEEE_80211_AUTH_ALG_SHARED_KEY: - if (sequenceNum == 2) { - hasResultCode = true; - } - break; - case IEEE_80211_AUTH_ALG_FAST_BSS_TRANSITION: - if (sequenceNum == 2 || sequenceNum == 4) { - hasResultCode = true; - } - break; - case IEEE_80211_AUTH_ALG_SIMUL_AUTH_OF_EQUALS: - hasResultCode = true; - break; - default: - // Ignore unknown algorithm -- don't know which frames would have result codes. - } - - if (hasResultCode) { - short resultCode = data.getShort(); - mResultString = String.format( - "%d: %s", resultCode, decodeIeee80211StatusCode(resultCode)); - } - } - - // Per 802.11-2016 Sec 9.3.3.13 - private void parseDeauthenticationFrame(ByteBuffer data) { - short reasonCode = data.getShort(); - mResultString = String.format("%d: %s", reasonCode, decodeIeee80211ReasonCode(reasonCode)); - } - - // Per 802.11-2016 Table 9-45 - private String decodeIeee80211ReasonCode(short reasonCode) { - switch (reasonCode) { - case 0: - return "Reserved"; - case 1: - return "Unspecified reason"; - case 2: - return "Previous authentication no longer valid"; - case 3: - return "Deauthenticated because sending STA is leaving (or has left) IBSS or ESS"; - case 4: - return "Disassociated due to inactivity"; - case 5: - return "Disassociated because AP is unable to handle all currently associated STAs"; - case 6: - return "Class 2 frame received from nonauthenticated STA"; - case 7: - return "Class 3 frame received from nonassociated STA"; - case 8: - return "Disassociated because sending STA is leaving (or has left) BSS"; - case 9: - return "STA requesting (re)association is not authenticated with responding STA"; - case 10: - return "Disassociated because the information in the Power Capability element is " - + "unacceptable"; - case 11: - return "Disassociated because the information in the Supported Channels element " - + "is unacceptable"; - case 12: - return "Disassociated due to BSS transition management"; - case 13: - return "Invalid element, i.e., an element defined in this standard for which the " - + "content does not meet the specifications in Clause 9"; - case 14: - return "Message integrity code (MIC) failure"; - case 15: - return "4-way handshake timeout"; - case 16: - return "Group key handshake timeout"; - case 17: - return "Element in 4-way handshake different from (Re)Association Request/Probe " - + "Response/Beacon frame"; - case 18: - return "Invalid group cipher"; - case 19: - return "Invalid pairwise cipher"; - case 20: - return "Invalid AKMP"; - case 21: - return "Unsupported RSNE version"; - case 22: - return "Invalid RSNE capabilities"; - case 23: - return "IEEE 802.1X authentication failed"; - case 24: - return "Cipher suite rejected because of the security policy"; - case 25: - return "TDLS direct-link teardown due to TDLS peer STA unreachable via the TDLS " - + "direct link"; - case 26: - return "TDLS direct-link teardown for unspecified reason"; - case 27: - return "Disassociated because session terminated by SSP request"; - case 28: - return "Disassociated because of lack of SSP roaming agreement"; - case 29: - return "Requested service rejected because of SSP cipher suite or AKM requirement"; - case 30: - return "Requested service not authorized in this location"; - case 31: - return "TS deleted because QoS AP lacks sufficient bandwidth for this QoS STA due" - + " to a change in BSS service characteristics or operational mode (e.g.," - + " an HT BSS change from 40 MHz channel to 20 MHz channel)"; - case 32: - return "Disassociated for unspecified, QoS-related reason"; - case 33: - return "Disassociated because QoS AP lacks sufficient bandwidth for this QoS STA"; - case 34: - return "Disassociated because excessive number of frames need to be acknowledged," - + " but are not acknowledged due to AP transmissions and/or poor channel " - + "conditions"; - case 35: - return "Disassociated because STA is transmitting outside the limits of its TXOPs"; - case 36: - return "Requesting STA is leaving the BSS (or resetting)"; - case 37: - return "Requesting STA is no longer using the stream or session"; - case 38: - return "Requesting STA received frames using a mechanism for which a setup has " - + "not been completed"; - case 39: - return "Requested from peer STA due to timeout"; - case 40: - case 41: - case 42: - case 43: - case 44: - return "<unspecified>"; - case 45: - return "Peer STA does not support the requested cipher suite"; - case 46: - return "In a DLS Teardown frame: The teardown was initiated by the DLS peer. In a" - + " Disassociation frame: Disassociated because authorized access limit " - + "reached"; - case 47: - return "In a DLS Teardown frame: The teardown was initiated by the AP. In a " - + "Disassociation frame: Disassociated due to external service " - + "requirements"; - case 48: - return "Invalid FT Action frame count"; - case 49: - return "Invalid pairwise master key identifier (PMKID)"; - case 50: - return "Invalid MDE"; - case 51: - return "Invalid FTE"; - case 52: - return "Mesh peering canceled for unknown reasons"; - case 53: - return "The mesh STA has reached the supported maximum number of peer mesh STAs"; - case 54: - return "The received information violates the Mesh Configuration policy " - + "configured in the mesh STA profile"; - case 55: - return "The mesh STA has received a Mesh Peering Close frame requesting to close " - + "the mesh peering."; - case 56: - return "The mesh STA has resent dot11MeshMaxRetries Mesh Peering Open frames, " - + "without receiving a Mesh Peering Confirm frame."; - case 57: - return "The confirmTimer for the mesh peering instance times out."; - case 58: - return "The mesh STA fails to unwrap the GTK or the values in the wrapped " - + "contents do not match"; - case 59: - return "The mesh STA receives inconsistent information about the mesh parameters " - + "between mesh peering Management frames"; - case 60: - return "The mesh STA fails the authenticated mesh peering exchange because due to" - + " failure in selecting either the pairwise ciphersuite or group " - + "ciphersuite"; - case 61: - return "The mesh STA does not have proxy information for this external " - + "destination."; - case 62: - return "The mesh STA does not have forwarding information for this destination."; - case 63: - return "The mesh STA determines that the link to the next hop of an active path " - + "in its forwarding information is no longer usable."; - case 64: - return "The Deauthentication frame was sent because the MAC address of the STA " - + "already exists in the mesh BSS. See 11.3.6."; - case 65: - return "The mesh STA performs channel switch to meet regulatory requirements."; - case 66: - return "The mesh STA performs channel switching with unspecified reason."; - default: - return "Reserved"; - } - } - - // Per 802.11-2012 Table 8-37. - private String decodeIeee80211StatusCode(short statusCode) { - switch (statusCode) { - case 0: - return "Success"; - case 1: - return "Unspecified failure"; - case 2: - return "TDLS wakeup schedule rejected; alternative provided"; - case 3: - return "TDLS wakeup schedule rejected"; - case 4: - return "Reserved"; - case 5: - return "Security disabled"; - case 6: - return "Unacceptable lifetime"; - case 7: - return "Not in same BSS"; - case 8: - case 9: - return "Reserved"; - case 10: - return "Capabilities mismatch"; - case 11: - return "Reassociation denied; could not confirm association exists"; - case 12: - return "Association denied for reasons outside standard"; - case 13: - return "Unsupported authentication algorithm"; - case 14: - return "Authentication sequence number of of sequence"; - case 15: - return "Authentication challenge failure"; - case 16: - return "Authentication timeout"; - case 17: - return "Association denied; too many STAs"; - case 18: - return "Association denied; must support BSSBasicRateSet"; - case 19: - return "Association denied; must support short preamble"; - case 20: - return "Association denied; must support PBCC"; - case 21: - return "Association denied; must support channel agility"; - case 22: - return "Association rejected; must support spectrum management"; - case 23: - return "Association rejected; unacceptable power capability"; - case 24: - return "Association rejected; unacceptable supported channels"; - case 25: - return "Association denied; must support short slot time"; - case 26: - return "Association denied; must support DSSS-OFDM"; - case 27: - return "Association denied; must support HT"; - case 28: - return "R0 keyholder unreachable (802.11r)"; - case 29: - return "Association denied; must support PCO transition time"; - case 30: - return "Refused temporarily"; - case 31: - return "Robust management frame policy violation"; - case 32: - return "Unspecified QoS failure"; - case 33: - return "Association denied; insufficient bandwidth for QoS"; - case 34: - return "Association denied; poor channel"; - case 35: - return "Association denied; must support QoS"; - case 36: - return "Reserved"; - case 37: - return "Declined"; - case 38: - return "Invalid parameters"; - case 39: - return "TS cannot be honored; changes suggested"; - case 40: - return "Invalid element"; - case 41: - return "Invalid group cipher"; - case 42: - return "Invalid pairwise cipher"; - case 43: - return "Invalid auth/key mgmt proto (AKMP)"; - case 44: - return "Unsupported RSNE version"; - case 45: - return "Invalid RSNE capabilities"; - case 46: - return "Cipher suite rejected by policy"; - case 47: - return "TS cannot be honored now; try again later"; - case 48: - return "Direct link rejected by policy"; - case 49: - return "Destination STA not in BSS"; - case 50: - return "Destination STA not configured for QoS"; - case 51: - return "Association denied; listen interval too large"; - case 52: - return "Invalid fast transition action frame count"; - case 53: - return "Invalid PMKID"; - case 54: - return "Invalid MDE"; - case 55: - return "Invalid FTE"; - case 56: - return "Unsupported TCLAS"; - case 57: - return "Requested TCLAS exceeds resources"; - case 58: - return "TS cannot be honored; try another BSS"; - case 59: - return "GAS Advertisement not supported"; - case 60: - return "No outstanding GAS request"; - case 61: - return "No query response from GAS server"; - case 62: - return "GAS query timeout"; - case 63: - return "GAS response too large"; - case 64: - return "Home network does not support request"; - case 65: - return "Advertisement server unreachable"; - case 66: - return "Reserved"; - case 67: - return "Rejected for SSP permissions"; - case 68: - return "Authentication required"; - case 69: - case 70: - case 71: - return "Reserved"; - case 72: - return "Invalid RSNE contents"; - case 73: - return "U-APSD coexistence unsupported"; - case 74: - return "Requested U-APSD coex mode unsupported"; - case 75: - return "Requested parameter unsupported with U-APSD coex"; - case 76: - return "Auth rejected; anti-clogging token required"; - case 77: - return "Auth rejected; offered group is not supported"; - case 78: - return "Cannot find alternative TBTT"; - case 79: - return "Transmission failure"; - case 80: - return "Requested TCLAS not supported"; - case 81: - return "TCLAS resources exhausted"; - case 82: - return "Rejected with suggested BSS transition"; - case 83: - return "Reserved"; - case 84: - case 85: - case 86: - case 87: - case 88: - case 89: - case 90: - case 91: - return "<unspecified>"; - case 92: - return "Refused due to external reason"; - case 93: - return "Refused; AP out of memory"; - case 94: - return "Refused; emergency services not supported"; - case 95: - return "GAS query response outstanding"; - case 96: - case 97: - case 98: - case 99: - return "Reserved"; - case 100: - return "Failed; reservation conflict"; - case 101: - return "Failed; exceeded MAF limit"; - case 102: - return "Failed; exceeded MCCA track limit"; - default: - return "Reserved"; - } - } -} diff --git a/service/java/com/android/server/wifi/util/GeneralUtil.java b/service/java/com/android/server/wifi/util/GeneralUtil.java deleted file mode 100644 index 80d745cc9..000000000 --- a/service/java/com/android/server/wifi/util/GeneralUtil.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.util; - -/** - * Class for general helper methods and objects for Wifi Framework code. - * @hide - */ -public class GeneralUtil { - - /** - * Class which can be used to fetch an object out of a lambda. Fetching an object - * out of a local scope with HIDL is a common operation (although usually it can - * and should be avoided). - * - * @param <E> Inner object type. - */ - public static final class Mutable<E> { - public E value; - - public Mutable() { - value = null; - } - - public Mutable(E value) { - this.value = value; - } - } -} diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java deleted file mode 100644 index a94c15f8b..000000000 --- a/service/java/com/android/server/wifi/util/InformationElementUtil.java +++ /dev/null @@ -1,1643 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.util; - -import android.net.wifi.ScanResult; -import android.net.wifi.ScanResult.InformationElement; -import android.net.wifi.WifiAnnotations.Cipher; -import android.net.wifi.WifiAnnotations.KeyMgmt; -import android.net.wifi.WifiAnnotations.Protocol; -import android.net.wifi.WifiScanner; -import android.net.wifi.nl80211.NativeScanResult; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.util.Log; - -import com.android.server.wifi.ByteBufferReader; -import com.android.server.wifi.MboOceConstants; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.List; - -public class InformationElementUtil { - private static final String TAG = "InformationElementUtil"; - private static final boolean DBG = false; - public static InformationElement[] parseInformationElements(byte[] bytes) { - if (bytes == null) { - return new InformationElement[0]; - } - ByteBuffer data = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN); - - ArrayList<InformationElement> infoElements = new ArrayList<>(); - boolean found_ssid = false; - while (data.remaining() > 1) { - int eid = data.get() & Constants.BYTE_MASK; - int eidExt = 0; - int elementLength = data.get() & Constants.BYTE_MASK; - - if (elementLength > data.remaining() || (eid == InformationElement.EID_SSID - && found_ssid)) { - // APs often pad the data with bytes that happen to match that of the EID_SSID - // marker. This is not due to a known issue for APs to incorrectly send the SSID - // name multiple times. - break; - } - if (eid == InformationElement.EID_SSID) { - found_ssid = true; - } else if (eid == InformationElement.EID_EXTENSION_PRESENT) { - if (elementLength == 0) { - // Malformed IE, skipping - break; - } - eidExt = data.get() & Constants.BYTE_MASK; - elementLength--; - } - - InformationElement ie = new InformationElement(); - ie.id = eid; - ie.idExt = eidExt; - ie.bytes = new byte[elementLength]; - data.get(ie.bytes); - infoElements.add(ie); - } - return infoElements.toArray(new InformationElement[infoElements.size()]); - } - - /** - * Parse and retrieve the Roaming Consortium Information Element from the list of IEs. - * - * @param ies List of IEs to retrieve from - * @return {@link RoamingConsortium} - */ - public static RoamingConsortium getRoamingConsortiumIE(InformationElement[] ies) { - RoamingConsortium roamingConsortium = new RoamingConsortium(); - if (ies != null) { - for (InformationElement ie : ies) { - if (ie.id == InformationElement.EID_ROAMING_CONSORTIUM) { - try { - roamingConsortium.from(ie); - } catch (RuntimeException e) { - Log.e(TAG, "Failed to parse Roaming Consortium IE: " + e.getMessage()); - } - } - } - } - return roamingConsortium; - } - - /** - * Parse and retrieve the Hotspot 2.0 Vendor Specific Information Element from the list of IEs. - * - * @param ies List of IEs to retrieve from - * @return {@link Vsa} - */ - public static Vsa getHS2VendorSpecificIE(InformationElement[] ies) { - Vsa vsa = new Vsa(); - if (ies != null) { - for (InformationElement ie : ies) { - if (ie.id == InformationElement.EID_VSA) { - try { - vsa.from(ie); - } catch (RuntimeException e) { - Log.e(TAG, "Failed to parse Vendor Specific IE: " + e.getMessage()); - } - } - } - } - return vsa; - } - - /** - * Parse and retrieve the Interworking information element from the list of IEs. - * - * @param ies List of IEs to retrieve from - * @return {@link Interworking} - */ - public static Interworking getInterworkingIE(InformationElement[] ies) { - Interworking interworking = new Interworking(); - if (ies != null) { - for (InformationElement ie : ies) { - if (ie.id == InformationElement.EID_INTERWORKING) { - try { - interworking.from(ie); - } catch (RuntimeException e) { - Log.e(TAG, "Failed to parse Interworking IE: " + e.getMessage()); - } - } - } - } - return interworking; - } - - public static class BssLoad { - public static final int INVALID = -1; - public static final int MAX_CHANNEL_UTILIZATION = 255; - public static final int MIN_CHANNEL_UTILIZATION = 0; - public static final int CHANNEL_UTILIZATION_SCALE = 256; - public int stationCount = INVALID; - public int channelUtilization = INVALID; - public int capacity = INVALID; - - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_BSS_LOAD) { - throw new IllegalArgumentException("Element id is not BSS_LOAD, : " + ie.id); - } - if (ie.bytes.length != 5) { - throw new IllegalArgumentException("BSS Load element length is not 5: " - + ie.bytes.length); - } - ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - stationCount = data.getShort() & Constants.SHORT_MASK; - channelUtilization = data.get() & Constants.BYTE_MASK; - capacity = data.getShort() & Constants.SHORT_MASK; - } - } - - public static class HtOperation { - private static final int HT_OPERATION_IE_LEN = 22; - private boolean mPresent = false; - private int mSecondChannelOffset = 0; - - /** - * returns if HT Operation IE present in the message. - */ - public boolean isPresent() { - return mPresent; - } - - /** - * Returns channel width if it is 20 or 40MHz - * Results will be invalid if channel width greater than 40MHz - * So caller should only call this method if VHT Operation IE is not present, - * or if VhtOperation.getChannelWidth() returns ScanResult.UNSPECIFIED. - */ - public int getChannelWidth() { - if (mSecondChannelOffset != 0) { - return ScanResult.CHANNEL_WIDTH_40MHZ; - } else { - return ScanResult.CHANNEL_WIDTH_20MHZ; - } - } - - /** - * Returns channel Center frequency (for 20/40 MHz channels only) - * Results will be invalid for larger channel width, - * So, caller should only call this method if VHT Operation IE is not present, - * or if VhtOperation.getChannelWidth() returns ScanResult.UNSPECIFIED. - */ - public int getCenterFreq0(int primaryFrequency) { - if (mSecondChannelOffset != 0) { - //40 MHz - if (mSecondChannelOffset == 1) { - return primaryFrequency + 10; - } else if (mSecondChannelOffset == 3) { - return primaryFrequency - 10; - } else { - Log.e("HtOperation", "Error on secondChannelOffset: " + mSecondChannelOffset); - return 0; - } - } else { - //20 MHz - return primaryFrequency; - } - } - - /** - * Parse the HT Operation IE to read the fields of interest. - */ - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_HT_OPERATION) { - throw new IllegalArgumentException("Element id is not HT_OPERATION, : " + ie.id); - } - if (ie.bytes.length < HT_OPERATION_IE_LEN) { - throw new IllegalArgumentException("Invalid HT_OPERATION len: " + ie.bytes.length); - } - mPresent = true; - mSecondChannelOffset = ie.bytes[1] & 0x3; - } - } - - public static class VhtOperation { - private static final int VHT_OPERATION_IE_LEN = 5; - private boolean mPresent = false; - private int mChannelMode = 0; - private int mCenterFreqIndex1 = 0; - private int mCenterFreqIndex2 = 0; - - /** - * returns if VHT Operation IE present in the message. - */ - public boolean isPresent() { - return mPresent; - } - - /** - * Returns channel width if it is above 40MHz, - * otherwise, returns {@link ScanResult.UNSPECIFIED} to indicate that - * channel width should be obtained from the HT Operation IE via - * HtOperation.getChannelWidth(). - */ - public int getChannelWidth() { - if (mChannelMode == 0) { - // 20 or 40MHz - return ScanResult.UNSPECIFIED; - } else if (mCenterFreqIndex2 == 0) { - // No secondary channel - return ScanResult.CHANNEL_WIDTH_80MHZ; - } else if (Math.abs(mCenterFreqIndex2 - mCenterFreqIndex1) == 8) { - // Primary and secondary channels adjacent - return ScanResult.CHANNEL_WIDTH_160MHZ; - } else { - // Primary and secondary channels not adjacent - return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; - } - } - - /** - * Returns center frequency of primary channel (if channel width greater than 40MHz), - * otherwise, it returns zero to indicate that center frequency should be obtained from - * the HT Operation IE via HtOperation.getCenterFreq0(). - */ - public int getCenterFreq0() { - if (mCenterFreqIndex1 == 0 || mChannelMode == 0) { - return 0; - } else { - return ScanResult.convertChannelToFrequencyMhz(mCenterFreqIndex1, - WifiScanner.WIFI_BAND_5_GHZ); - } - } - - /** - * Returns center frequency of secondary channel if exists (channel width greater than - * 40MHz), otherwise, it returns zero. - * Note that the secondary channel center frequency only applies to 80+80 or 160 MHz - * channels. - */ - public int getCenterFreq1() { - if (mCenterFreqIndex2 == 0 || mChannelMode == 0) { - return 0; - } else { - return ScanResult.convertChannelToFrequencyMhz(mCenterFreqIndex2, - WifiScanner.WIFI_BAND_5_GHZ); - } - } - - /** - * Parse the VHT Operation IE to read the fields of interest. - */ - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_VHT_OPERATION) { - throw new IllegalArgumentException("Element id is not VHT_OPERATION, : " + ie.id); - } - if (ie.bytes.length < VHT_OPERATION_IE_LEN) { - throw new IllegalArgumentException("Invalid VHT_OPERATION len: " + ie.bytes.length); - } - mPresent = true; - mChannelMode = ie.bytes[0] & Constants.BYTE_MASK; - mCenterFreqIndex1 = ie.bytes[1] & Constants.BYTE_MASK; - mCenterFreqIndex2 = ie.bytes[2] & Constants.BYTE_MASK; - } - } - - /** - * HeOperation: represents the HE Operation IE - */ - public static class HeOperation { - - private static final int HE_OPERATION_BASIC_LENGTH = 6; - private static final int VHT_OPERATION_INFO_PRESENT_MASK = 0x40; - private static final int HE_6GHZ_INFO_PRESENT_MASK = 0x02; - private static final int HE_6GHZ_CH_WIDTH_MASK = 0x03; - private static final int CO_HOSTED_BSS_PRESENT_MASK = 0x80; - private static final int VHT_OPERATION_INFO_START_INDEX = 6; - private static final int HE_BW_80_80_160 = 3; - - private boolean mPresent = false; - private boolean mVhtInfoPresent = false; - private boolean m6GhzInfoPresent = false; - private int mChannelWidth; - private int mPrimaryChannel; - private int mCenterFreqSeg0; - private int mCenterFreqSeg1; - private InformationElement mVhtInfo = null; - - /** - * Returns whether the HE Information Element is present. - */ - public boolean isPresent() { - return mPresent; - } - - /** - * Returns whether VHT Information field is present. - */ - public boolean isVhtInfoPresent() { - return mVhtInfoPresent; - } - - /** - * Returns the VHT Information Element if it exists - * otherwise, return null. - */ - public InformationElement getVhtInfoElement() { - return mVhtInfo; - } - - /** - * Returns whether the 6GHz information field is present. - */ - public boolean is6GhzInfoPresent() { - return m6GhzInfoPresent; - } - - /** - * Returns the Channel BW - * Only applicable to 6GHz band - */ - public int getChannelWidth() { - if (!m6GhzInfoPresent) { - return ScanResult.UNSPECIFIED; - } else if (mChannelWidth == 0) { - return ScanResult.CHANNEL_WIDTH_20MHZ; - } else if (mChannelWidth == 1) { - return ScanResult.CHANNEL_WIDTH_40MHZ; - } else if (mChannelWidth == 2) { - return ScanResult.CHANNEL_WIDTH_80MHZ; - } else if (Math.abs(mCenterFreqSeg1 - mCenterFreqSeg0) == 8) { - return ScanResult.CHANNEL_WIDTH_160MHZ; - } else { - return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; - } - } - - /** - * Returns the primary channel frequency - * Only applicable for 6GHz channels - */ - public int getPrimaryFreq() { - return ScanResult.convertChannelToFrequencyMhz(mPrimaryChannel, - WifiScanner.WIFI_BAND_6_GHZ); - } - - /** - * Returns the center frequency for the primary channel - * Only applicable to 6GHz channels - */ - public int getCenterFreq0() { - if (m6GhzInfoPresent) { - if (mCenterFreqSeg0 == 0) { - return 0; - } else { - return ScanResult.convertChannelToFrequencyMhz(mCenterFreqSeg0, - WifiScanner.WIFI_BAND_6_GHZ); - } - } else { - return 0; - } - } - - /** - * Returns the center frequency for the secondary channel - * Only applicable to 6GHz channels - */ - public int getCenterFreq1() { - if (m6GhzInfoPresent) { - if (mCenterFreqSeg1 == 0) { - return 0; - } else { - return ScanResult.convertChannelToFrequencyMhz(mCenterFreqSeg1, - WifiScanner.WIFI_BAND_6_GHZ); - } - } else { - return 0; - } - } - - /** Parse HE Operation IE */ - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_EXTENSION_PRESENT - || ie.idExt != InformationElement.EID_EXT_HE_OPERATION) { - throw new IllegalArgumentException("Element id is not HE_OPERATION"); - } - - // Make sure the byte array length is at least the fixed size - if (ie.bytes.length < HE_OPERATION_BASIC_LENGTH) { - if (DBG) { - Log.w(TAG, "Invalid HE_OPERATION len: " + ie.bytes.length); - } - // Skipping parsing of the IE - return; - } - - mVhtInfoPresent = (ie.bytes[1] & VHT_OPERATION_INFO_PRESENT_MASK) != 0; - m6GhzInfoPresent = (ie.bytes[2] & HE_6GHZ_INFO_PRESENT_MASK) != 0; - boolean coHostedBssPresent = (ie.bytes[1] & CO_HOSTED_BSS_PRESENT_MASK) != 0; - int expectedLen = HE_OPERATION_BASIC_LENGTH + (mVhtInfoPresent ? 3 : 0) - + (coHostedBssPresent ? 1 : 0) + (m6GhzInfoPresent ? 5 : 0); - - // Make sure the byte array length is at least fitting the known parameters - if (ie.bytes.length < expectedLen) { - if (DBG) { - Log.w(TAG, "Invalid HE_OPERATION len: " + ie.bytes.length); - } - // Skipping parsing of the IE - return; - } - - // Passed all checks, IE is ready for decoding - mPresent = true; - - if (mVhtInfoPresent) { - mVhtInfo = new InformationElement(); - mVhtInfo.id = InformationElement.EID_VHT_OPERATION; - mVhtInfo.bytes = new byte[5]; - System.arraycopy(ie.bytes, VHT_OPERATION_INFO_START_INDEX, mVhtInfo.bytes, 0, 3); - } - - if (m6GhzInfoPresent) { - int startIndx = VHT_OPERATION_INFO_START_INDEX + (mVhtInfoPresent ? 3 : 0) - + (coHostedBssPresent ? 1 : 0); - - mChannelWidth = ie.bytes[startIndx + 1] & HE_6GHZ_CH_WIDTH_MASK; - mPrimaryChannel = ie.bytes[startIndx] & Constants.BYTE_MASK; - mCenterFreqSeg0 = ie.bytes[startIndx + 2] & Constants.BYTE_MASK; - mCenterFreqSeg1 = ie.bytes[startIndx + 3] & Constants.BYTE_MASK; - } - } - } - - /** - * HtCapabilities: represents the HT Capabilities IE - */ - public static class HtCapabilities { - private int mMaxNumberSpatialStreams = 1; - private boolean mPresent = false; - /** Returns whether HT Capabilities IE is present */ - public boolean isPresent() { - return mPresent; - } - /** - * Returns max number of spatial streams if HT Capabilities IE is found and parsed, - * or 1 otherwise - */ - public int getMaxNumberSpatialStreams() { - return mMaxNumberSpatialStreams; - } - - /** Parse HT Capabilities IE */ - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_HT_CAPABILITIES) { - throw new IllegalArgumentException("Element id is not HT_CAPABILITIES: " + ie.id); - } - if (ie.bytes.length < 26) { - if (DBG) { - Log.w(TAG, "Invalid HtCapabilities len: " + ie.bytes.length); - } - return; - } - int stream1 = ie.bytes[3] & Constants.BYTE_MASK; - int stream2 = ie.bytes[4] & Constants.BYTE_MASK; - int stream3 = ie.bytes[5] & Constants.BYTE_MASK; - int stream4 = ie.bytes[6] & Constants.BYTE_MASK; - if (DBG) { - Log.d(TAG, "HT Rx MCS set4: " + Integer.toHexString(stream4)); - Log.d(TAG, "HT Rx MCS set3: " + Integer.toHexString(stream3)); - Log.d(TAG, "HT Rx MCS set2: " + Integer.toHexString(stream2)); - Log.d(TAG, "HT Rx MCS set1: " + Integer.toHexString(stream1)); - } - mMaxNumberSpatialStreams = (stream4 > 0) ? 4 : - ((stream3 > 0) ? 3 : - ((stream2 > 0) ? 2 : 1)); - mPresent = true; - } - } - - /** - * VhtCapabilities: represents the VHT Capabilities IE - */ - public static class VhtCapabilities { - private int mMaxNumberSpatialStreams = 1; - private boolean mPresent = false; - /** Returns whether VHT Capabilities IE is present */ - public boolean isPresent() { - return mPresent; - } - /** - * Returns max number of spatial streams if VHT Capabilities IE is found and parsed, - * or 1 otherwise - */ - public int getMaxNumberSpatialStreams() { - return mMaxNumberSpatialStreams; - } - /** Parse VHT Capabilities IE */ - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_VHT_CAPABILITIES) { - throw new IllegalArgumentException("Element id is not VHT_CAPABILITIES: " + ie.id); - } - if (ie.bytes.length < 12) { - if (DBG) { - Log.w(TAG, "Invalid VHT_CAPABILITIES len: " + ie.bytes.length); - } - return; - } - int mcsMap = ((ie.bytes[5] & Constants.BYTE_MASK) << 8) - + (ie.bytes[4] & Constants.BYTE_MASK); - mMaxNumberSpatialStreams = parseMaxNumberSpatialStreamsFromMcsMap(mcsMap); - mPresent = true; - } - } - - /** - * HeCapabilities: represents the HE Capabilities IE - */ - public static class HeCapabilities { - private int mMaxNumberSpatialStreams = 1; - private boolean mPresent = false; - /** Returns whether HE Capabilities IE is present */ - public boolean isPresent() { - return mPresent; - } - /** - * Returns max number of spatial streams if HE Capabilities IE is found and parsed, - * or 1 otherwise - */ - public int getMaxNumberSpatialStreams() { - return mMaxNumberSpatialStreams; - } - /** Parse HE Capabilities IE */ - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_EXTENSION_PRESENT - || ie.idExt != InformationElement.EID_EXT_HE_CAPABILITIES) { - throw new IllegalArgumentException("Element id is not HE_CAPABILITIES: " + ie.id); - } - if (ie.bytes.length < 21) { - if (DBG) { - Log.w(TAG, "Invalid HE_CAPABILITIES len: " + ie.bytes.length); - } - return; - } - int mcsMap = ((ie.bytes[18] & Constants.BYTE_MASK) << 8) - + (ie.bytes[17] & Constants.BYTE_MASK); - mMaxNumberSpatialStreams = parseMaxNumberSpatialStreamsFromMcsMap(mcsMap); - mPresent = true; - } - } - - private static int parseMaxNumberSpatialStreamsFromMcsMap(int mcsMap) { - int maxNumberSpatialStreams = 1; - for (int i = 8; i >= 1; --i) { - int streamMap = mcsMapToStreamMap(mcsMap, i); - // 3 means unsupported - if (streamMap != 3) { - maxNumberSpatialStreams = i; - break; - } - } - if (DBG) { - for (int i = 8; i >= 1; --i) { - int streamMap = mcsMapToStreamMap(mcsMap, i); - Log.d(TAG, "Rx MCS set " + i + " : " + streamMap); - } - } - return maxNumberSpatialStreams; - } - - private static int mcsMapToStreamMap(int mcsMap, int i) { - return (mcsMap >> ((i - 1) * 2)) & 0x3; - } - - public static class Interworking { - public NetworkDetail.Ant ant = null; - public boolean internet = false; - public long hessid = 0L; - - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_INTERWORKING) { - throw new IllegalArgumentException("Element id is not INTERWORKING, : " + ie.id); - } - ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - int anOptions = data.get() & Constants.BYTE_MASK; - ant = NetworkDetail.Ant.values()[anOptions & 0x0f]; - internet = (anOptions & 0x10) != 0; - // There are only three possible lengths for the Interworking IE: - // Len 1: Access Network Options only - // Len 3: Access Network Options & Venue Info - // Len 7: Access Network Options & HESSID - // Len 9: Access Network Options, Venue Info, & HESSID - if (ie.bytes.length != 1 - && ie.bytes.length != 3 - && ie.bytes.length != 7 - && ie.bytes.length != 9) { - throw new IllegalArgumentException( - "Bad Interworking element length: " + ie.bytes.length); - } - - if (ie.bytes.length == 3 || ie.bytes.length == 9) { - int venueInfo = (int) ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, 2); - } - - if (ie.bytes.length == 7 || ie.bytes.length == 9) { - hessid = ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, 6); - } - } - } - - public static class RoamingConsortium { - public int anqpOICount = 0; - - private long[] roamingConsortiums = null; - - public long[] getRoamingConsortiums() { - return roamingConsortiums; - } - - public void from(InformationElement ie) { - if (ie.id != InformationElement.EID_ROAMING_CONSORTIUM) { - throw new IllegalArgumentException("Element id is not ROAMING_CONSORTIUM, : " - + ie.id); - } - ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - anqpOICount = data.get() & Constants.BYTE_MASK; - - int oi12Length = data.get() & Constants.BYTE_MASK; - int oi1Length = oi12Length & Constants.NIBBLE_MASK; - int oi2Length = (oi12Length >>> 4) & Constants.NIBBLE_MASK; - int oi3Length = ie.bytes.length - 2 - oi1Length - oi2Length; - int oiCount = 0; - if (oi1Length > 0) { - oiCount++; - if (oi2Length > 0) { - oiCount++; - if (oi3Length > 0) { - oiCount++; - } - } - } - roamingConsortiums = new long[oiCount]; - if (oi1Length > 0 && roamingConsortiums.length > 0) { - roamingConsortiums[0] = - ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, oi1Length); - } - if (oi2Length > 0 && roamingConsortiums.length > 1) { - roamingConsortiums[1] = - ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, oi2Length); - } - if (oi3Length > 0 && roamingConsortiums.length > 2) { - roamingConsortiums[2] = - ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, oi3Length); - } - } - } - - public static class Vsa { - private static final int ANQP_DOMAIN_ID_PRESENT_BIT = 0x04; - private static final int ANQP_PPS_MO_ID_BIT = 0x02; - private static final int OUI_WFA_ALLIANCE = 0x506F9a; - private static final int OUI_TYPE_HS20 = 0x10; - private static final int OUI_TYPE_MBO_OCE = 0x16; - - public NetworkDetail.HSRelease hsRelease = null; - public int anqpDomainID = 0; // No domain ID treated the same as a 0; unique info per AP. - - public boolean IsMboCapable = false; - public boolean IsMboApCellularDataAware = false; - public boolean IsOceCapable = false; - public int mboAssociationDisallowedReasonCode = - MboOceConstants.MBO_OCE_ATTRIBUTE_NOT_PRESENT; - - private void parseVsaMboOce(InformationElement ie) { - ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - - // skip WFA OUI and type parsing as parseVsaMboOce() is called after identifying - // MBO-OCE OUI type. - data.getInt(); - - while (data.remaining() > 1) { - int attrId = data.get() & Constants.BYTE_MASK; - int attrLen = data.get() & Constants.BYTE_MASK; - - if ((attrLen == 0) || (attrLen > data.remaining())) { - return; - } - byte[] attrBytes = new byte[attrLen]; - data.get(attrBytes); - switch (attrId) { - case MboOceConstants.MBO_OCE_AID_MBO_AP_CAPABILITY_INDICATION: - IsMboCapable = true; - IsMboApCellularDataAware = (attrBytes[0] - & MboOceConstants.MBO_AP_CAP_IND_ATTR_CELL_DATA_AWARE) != 0; - break; - case MboOceConstants.MBO_OCE_AID_ASSOCIATION_DISALLOWED: - mboAssociationDisallowedReasonCode = attrBytes[0] & Constants.BYTE_MASK; - break; - case MboOceConstants.MBO_OCE_AID_OCE_AP_CAPABILITY_INDICATION: - IsOceCapable = true; - break; - default: - break; - } - } - if (DBG) { - Log.e(TAG, ":parseMboOce MBO: " + IsMboCapable + " cellDataAware: " - + IsMboApCellularDataAware + " AssocDisAllowRC: " - + mboAssociationDisallowedReasonCode + " :OCE: " + IsOceCapable); - } - } - - private void parseVsaHs20(InformationElement ie) { - ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - if (ie.bytes.length >= 5) { - // skip WFA OUI and type parsing as parseVsaHs20() is called after identifying - // HS20 OUI type. - data.getInt(); - - int hsConf = data.get() & Constants.BYTE_MASK; - switch ((hsConf >> 4) & Constants.NIBBLE_MASK) { - case 0: - hsRelease = NetworkDetail.HSRelease.R1; - break; - case 1: - hsRelease = NetworkDetail.HSRelease.R2; - break; - case 2: - hsRelease = NetworkDetail.HSRelease.R3; - break; - default: - hsRelease = NetworkDetail.HSRelease.Unknown; - break; - } - if ((hsConf & ANQP_DOMAIN_ID_PRESENT_BIT) != 0) { - // According to Hotspot 2.0 Specification v3.0 section 3.1.1 HS2.0 Indication - // element, the size of the element is 5 bytes, and 2 bytes are optionally added - // for each optional field; ANQP PPS MO ID and ANQP Domain ID present. - int expectedSize = 7; - if ((hsConf & ANQP_PPS_MO_ID_BIT) != 0) { - expectedSize += 2; - if (ie.bytes.length < expectedSize) { - throw new IllegalArgumentException( - "HS20 indication element too short: " + ie.bytes.length); - } - data.getShort(); // Skip 2 bytes - } - if (ie.bytes.length < expectedSize) { - throw new IllegalArgumentException( - "HS20 indication element too short: " + ie.bytes.length); - } - anqpDomainID = data.getShort() & Constants.SHORT_MASK; - } - } - } - - /** - * Parse the vendor specific information element to build - * InformationElemmentUtil.vsa object. - * - * @param ie -- Information Element - */ - public void from(InformationElement ie) { - if (ie.bytes.length < 3) { - if (DBG) { - Log.w(TAG, "Invalid vendor specific element len: " + ie.bytes.length); - } - return; - } - - int oui = (((ie.bytes[0] & Constants.BYTE_MASK) << 16) - | ((ie.bytes[1] & Constants.BYTE_MASK) << 8) - | ((ie.bytes[2] & Constants.BYTE_MASK))); - - if (oui == OUI_WFA_ALLIANCE && ie.bytes.length >= 4) { - int ouiType = ie.bytes[3]; - switch (ouiType) { - case OUI_TYPE_HS20: - parseVsaHs20(ie); - break; - case OUI_TYPE_MBO_OCE: - parseVsaMboOce(ie); - break; - default: - break; - } - } - } - } - - /** - * This IE contained a bit field indicating the capabilities being advertised by the STA. - * The size of the bit field (number of bytes) is indicated by the |Length| field in the IE. - * - * Refer to Section 8.4.2.29 in IEEE 802.11-2012 Spec for capability associated with each - * bit. - * - * Here is the wire format of this IE: - * | Element ID | Length | Capabilities | - * 1 1 n - */ - public static class ExtendedCapabilities { - private static final int RTT_RESP_ENABLE_BIT = 70; - private static final int SSID_UTF8_BIT = 48; - - public BitSet capabilitiesBitSet; - - /** - * @return true if SSID should be interpreted using UTF-8 encoding - */ - public boolean isStrictUtf8() { - return capabilitiesBitSet.get(SSID_UTF8_BIT); - } - - /** - * @return true if 802.11 MC RTT Response is enabled - */ - public boolean is80211McRTTResponder() { - return capabilitiesBitSet.get(RTT_RESP_ENABLE_BIT); - } - - public ExtendedCapabilities() { - capabilitiesBitSet = new BitSet(); - } - - public ExtendedCapabilities(ExtendedCapabilities other) { - capabilitiesBitSet = other.capabilitiesBitSet; - } - - /** - * Parse an ExtendedCapabilities from the IE containing raw bytes. - * - * @param ie The Information element data - */ - public void from(InformationElement ie) { - capabilitiesBitSet = BitSet.valueOf(ie.bytes); - } - } - - /** - * parse beacon to build the capabilities - * - * This class is used to build the capabilities string of the scan results coming - * from HAL. It parses the ieee beacon's capability field, WPA and RSNE IE as per spec, - * and builds the ScanResult.capabilities String in a way that mirrors the values returned - * by wpa_supplicant. - */ - public static class Capabilities { - private static final int WPA_VENDOR_OUI_TYPE_ONE = 0x01f25000; - private static final int WPS_VENDOR_OUI_TYPE = 0x04f25000; - private static final short WPA_VENDOR_OUI_VERSION = 0x0001; - private static final int OWE_VENDOR_OUI_TYPE = 0x1c9a6f50; - private static final short RSNE_VERSION = 0x0001; - - private static final int WPA_AKM_EAP = 0x01f25000; - private static final int WPA_AKM_PSK = 0x02f25000; - - private static final int RSN_AKM_EAP = 0x01ac0f00; - private static final int RSN_AKM_PSK = 0x02ac0f00; - private static final int RSN_AKM_FT_EAP = 0x03ac0f00; - private static final int RSN_AKM_FT_PSK = 0x04ac0f00; - private static final int RSN_AKM_EAP_SHA256 = 0x05ac0f00; - private static final int RSN_AKM_PSK_SHA256 = 0x06ac0f00; - private static final int RSN_AKM_SAE = 0x08ac0f00; - private static final int RSN_AKM_FT_SAE = 0x09ac0f00; - private static final int RSN_AKM_OWE = 0x12ac0f00; - private static final int RSN_AKM_EAP_SUITE_B_192 = 0x0cac0f00; - private static final int RSN_OSEN = 0x019a6f50; - private static final int RSN_AKM_EAP_FILS_SHA256 = 0x0eac0f00; - private static final int RSN_AKM_EAP_FILS_SHA384 = 0x0fac0f00; - - private static final int WPA_CIPHER_NONE = 0x00f25000; - private static final int WPA_CIPHER_TKIP = 0x02f25000; - private static final int WPA_CIPHER_CCMP = 0x04f25000; - - private static final int RSN_CIPHER_NONE = 0x00ac0f00; - private static final int RSN_CIPHER_TKIP = 0x02ac0f00; - private static final int RSN_CIPHER_CCMP = 0x04ac0f00; - private static final int RSN_CIPHER_NO_GROUP_ADDRESSED = 0x07ac0f00; - private static final int RSN_CIPHER_GCMP_256 = 0x09ac0f00; - - public List<Integer> protocol; - public List<List<Integer>> keyManagement; - public List<List<Integer>> pairwiseCipher; - public List<Integer> groupCipher; - public boolean isESS; - public boolean isIBSS; - public boolean isPrivacy; - public boolean isWPS; - - public Capabilities() { - } - - // RSNE format (size unit: byte) - // - // | Element ID | Length | Version | Group Data Cipher Suite | - // 1 1 2 4 - // | Pairwise Cipher Suite Count | Pairwise Cipher Suite List | - // 2 4 * m - // | AKM Suite Count | AKM Suite List | RSN Capabilities | - // 2 4 * n 2 - // | PMKID Count | PMKID List | Group Management Cipher Suite | - // 2 16 * s 4 - // - // Note: InformationElement.bytes has 'Element ID' and 'Length' - // stripped off already - private void parseRsnElement(InformationElement ie) { - ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - - try { - // version - if (buf.getShort() != RSNE_VERSION) { - // incorrect version - return; - } - - // found the RSNE IE, hence start building the capability string - protocol.add(ScanResult.PROTOCOL_RSN); - - // group data cipher suite - groupCipher.add(parseRsnCipher(buf.getInt())); - - // pairwise cipher suite count - short cipherCount = buf.getShort(); - ArrayList<Integer> rsnPairwiseCipher = new ArrayList<>(); - // pairwise cipher suite list - for (int i = 0; i < cipherCount; i++) { - rsnPairwiseCipher.add(parseRsnCipher(buf.getInt())); - } - pairwiseCipher.add(rsnPairwiseCipher); - - // AKM - // AKM suite count - short akmCount = buf.getShort(); - ArrayList<Integer> rsnKeyManagement = new ArrayList<>(); - - for (int i = 0; i < akmCount; i++) { - int akm = buf.getInt(); - switch (akm) { - case RSN_AKM_EAP: - rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP); - break; - case RSN_AKM_PSK: - rsnKeyManagement.add(ScanResult.KEY_MGMT_PSK); - break; - case RSN_AKM_FT_EAP: - rsnKeyManagement.add(ScanResult.KEY_MGMT_FT_EAP); - break; - case RSN_AKM_FT_PSK: - rsnKeyManagement.add(ScanResult.KEY_MGMT_FT_PSK); - break; - case RSN_AKM_EAP_SHA256: - rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP_SHA256); - break; - case RSN_AKM_PSK_SHA256: - rsnKeyManagement.add(ScanResult.KEY_MGMT_PSK_SHA256); - break; - case RSN_AKM_SAE: - rsnKeyManagement.add(ScanResult.KEY_MGMT_SAE); - break; - case RSN_AKM_FT_SAE: - rsnKeyManagement.add(ScanResult.KEY_MGMT_FT_SAE); - break; - case RSN_AKM_OWE: - rsnKeyManagement.add(ScanResult.KEY_MGMT_OWE); - break; - case RSN_AKM_EAP_SUITE_B_192: - rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP_SUITE_B_192); - break; - case RSN_OSEN: - rsnKeyManagement.add(ScanResult.KEY_MGMT_OSEN); - break; - case RSN_AKM_EAP_FILS_SHA256: - rsnKeyManagement.add(ScanResult.KEY_MGMT_FILS_SHA256); - break; - case RSN_AKM_EAP_FILS_SHA384: - rsnKeyManagement.add(ScanResult.KEY_MGMT_FILS_SHA384); - break; - default: - // do nothing - break; - } - } - // Default AKM - if (rsnKeyManagement.isEmpty()) { - rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP); - } - keyManagement.add(rsnKeyManagement); - } catch (BufferUnderflowException e) { - Log.e("IE_Capabilities", "Couldn't parse RSNE, buffer underflow"); - } - } - - private static @Cipher int parseWpaCipher(int cipher) { - switch (cipher) { - case WPA_CIPHER_NONE: - return ScanResult.CIPHER_NONE; - case WPA_CIPHER_TKIP: - return ScanResult.CIPHER_TKIP; - case WPA_CIPHER_CCMP: - return ScanResult.CIPHER_CCMP; - default: - Log.w("IE_Capabilities", "Unknown WPA cipher suite: " - + Integer.toHexString(cipher)); - return ScanResult.CIPHER_NONE; - } - } - - private static @Cipher int parseRsnCipher(int cipher) { - switch (cipher) { - case RSN_CIPHER_NONE: - return ScanResult.CIPHER_NONE; - case RSN_CIPHER_TKIP: - return ScanResult.CIPHER_TKIP; - case RSN_CIPHER_CCMP: - return ScanResult.CIPHER_CCMP; - case RSN_CIPHER_GCMP_256: - return ScanResult.CIPHER_GCMP_256; - case RSN_CIPHER_NO_GROUP_ADDRESSED: - return ScanResult.CIPHER_NO_GROUP_ADDRESSED; - default: - Log.w("IE_Capabilities", "Unknown RSN cipher suite: " - + Integer.toHexString(cipher)); - return ScanResult.CIPHER_NONE; - } - } - - private static boolean isWpsElement(InformationElement ie) { - ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - try { - // WPS OUI and type - return (buf.getInt() == WPS_VENDOR_OUI_TYPE); - } catch (BufferUnderflowException e) { - Log.e("IE_Capabilities", "Couldn't parse VSA IE, buffer underflow"); - return false; - } - } - - private static boolean isWpaOneElement(InformationElement ie) { - ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - - try { - // WPA OUI and type - return (buf.getInt() == WPA_VENDOR_OUI_TYPE_ONE); - } catch (BufferUnderflowException e) { - Log.e("IE_Capabilities", "Couldn't parse VSA IE, buffer underflow"); - return false; - } - } - - // WPA type 1 format (size unit: byte) - // - // | Element ID | Length | OUI | Type | Version | - // 1 1 3 1 2 - // | Group Data Cipher Suite | - // 4 - // | Pairwise Cipher Suite Count | Pairwise Cipher Suite List | - // 2 4 * m - // | AKM Suite Count | AKM Suite List | - // 2 4 * n - // - // Note: InformationElement.bytes has 'Element ID' and 'Length' - // stripped off already - // - private void parseWpaOneElement(InformationElement ie) { - ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - - try { - // skip WPA OUI and type parsing. isWpaOneElement() should have - // been called for verification before we reach here. - buf.getInt(); - - // version - if (buf.getShort() != WPA_VENDOR_OUI_VERSION) { - // incorrect version - return; - } - - // start building the string - protocol.add(ScanResult.PROTOCOL_WPA); - - // group data cipher suite - groupCipher.add(parseWpaCipher(buf.getInt())); - - // pairwise cipher suite count - short cipherCount = buf.getShort(); - ArrayList<Integer> wpaPairwiseCipher = new ArrayList<>(); - // pairwise chipher suite list - for (int i = 0; i < cipherCount; i++) { - wpaPairwiseCipher.add(parseWpaCipher(buf.getInt())); - } - pairwiseCipher.add(wpaPairwiseCipher); - - // AKM - // AKM suite count - short akmCount = buf.getShort(); - ArrayList<Integer> wpaKeyManagement = new ArrayList<>(); - - // AKM suite list - for (int i = 0; i < akmCount; i++) { - int akm = buf.getInt(); - switch (akm) { - case WPA_AKM_EAP: - wpaKeyManagement.add(ScanResult.KEY_MGMT_EAP); - break; - case WPA_AKM_PSK: - wpaKeyManagement.add(ScanResult.KEY_MGMT_PSK); - break; - default: - // do nothing - break; - } - } - // Default AKM - if (wpaKeyManagement.isEmpty()) { - wpaKeyManagement.add(ScanResult.KEY_MGMT_EAP); - } - keyManagement.add(wpaKeyManagement); - } catch (BufferUnderflowException e) { - Log.e("IE_Capabilities", "Couldn't parse type 1 WPA, buffer underflow"); - } - } - - /** - * Parse the Information Element and the 16-bit Capability Information field - * to build the InformationElemmentUtil.capabilities object. - * - * @param ies -- Information Element array - * @param beaconCap -- 16-bit Beacon Capability Information field - * @param isOweSupported -- Boolean flag to indicate if OWE is supported by the device - */ - - public void from(InformationElement[] ies, int beaconCap, boolean isOweSupported) { - protocol = new ArrayList<>(); - keyManagement = new ArrayList<>(); - groupCipher = new ArrayList<>(); - pairwiseCipher = new ArrayList<>(); - - if (ies == null) { - return; - } - isESS = (beaconCap & NativeScanResult.BSS_CAPABILITY_ESS) != 0; - isIBSS = (beaconCap & NativeScanResult.BSS_CAPABILITY_IBSS) != 0; - isPrivacy = (beaconCap & NativeScanResult.BSS_CAPABILITY_PRIVACY) != 0; - for (InformationElement ie : ies) { - WifiNl80211Manager.OemSecurityType oemSecurityType = - WifiNl80211Manager.parseOemSecurityTypeElement( - ie.id, ie.idExt, ie.bytes); - if (oemSecurityType != null - && oemSecurityType.protocol != ScanResult.PROTOCOL_NONE) { - protocol.add(oemSecurityType.protocol); - keyManagement.add(oemSecurityType.keyManagement); - pairwiseCipher.add(oemSecurityType.pairwiseCipher); - groupCipher.add(oemSecurityType.groupCipher); - } - - if (ie.id == InformationElement.EID_RSN) { - parseRsnElement(ie); - } - - if (ie.id == InformationElement.EID_VSA) { - if (isWpaOneElement(ie)) { - parseWpaOneElement(ie); - } - if (isWpsElement(ie)) { - // TODO(b/62134557): parse WPS IE to provide finer granularity information. - isWPS = true; - } - if (isOweSupported && isOweElement(ie)) { - /* From RFC 8110: Once the client and AP have finished 802.11 association, - they then complete the Diffie-Hellman key exchange and create a Pairwise - Master Key (PMK) and its associated identifier, PMKID [IEEE802.11]. - Upon completion of 802.11 association, the AP initiates the 4-way - handshake to the client using the PMK generated above. The 4-way - handshake generates a Key-Encrypting Key (KEK), a Key-Confirmation - Key (KCK), and a Message Integrity Code (MIC) to use for protection - of the frames that define the 4-way handshake. - - We check if OWE is supported here because we are adding the OWE - capabilities to the Open BSS. Non-supporting devices need to see this - open network and ignore this element. Supporting devices need to hide - the Open BSS of OWE in transition mode and connect to the Hidden one. - */ - protocol.add(ScanResult.PROTOCOL_RSN); - groupCipher.add(ScanResult.CIPHER_CCMP); - ArrayList<Integer> owePairwiseCipher = new ArrayList<>(); - owePairwiseCipher.add(ScanResult.CIPHER_CCMP); - pairwiseCipher.add(owePairwiseCipher); - ArrayList<Integer> oweKeyManagement = new ArrayList<>(); - oweKeyManagement.add(ScanResult.KEY_MGMT_OWE_TRANSITION); - keyManagement.add(oweKeyManagement); - } - } - } - } - - private static boolean isOweElement(InformationElement ie) { - ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - try { - // OWE OUI and type - return (buf.getInt() == OWE_VENDOR_OUI_TYPE); - } catch (BufferUnderflowException e) { - Log.e("IE_Capabilities", "Couldn't parse VSA IE, buffer underflow"); - return false; - } - } - - private String protocolToString(@Protocol int protocol) { - switch (protocol) { - case ScanResult.PROTOCOL_NONE: - return "None"; - case ScanResult.PROTOCOL_WPA: - return "WPA"; - case ScanResult.PROTOCOL_RSN: - return "RSN"; - case ScanResult.PROTOCOL_OSEN: - return "OSEN"; - case ScanResult.PROTOCOL_WAPI: - return "WAPI"; - default: - return "?"; - } - } - - private String keyManagementToString(@KeyMgmt int akm) { - switch (akm) { - case ScanResult.KEY_MGMT_NONE: - return "None"; - case ScanResult.KEY_MGMT_PSK: - return "PSK"; - case ScanResult.KEY_MGMT_EAP: - return "EAP"; - case ScanResult.KEY_MGMT_FT_EAP: - return "FT/EAP"; - case ScanResult.KEY_MGMT_FT_PSK: - return "FT/PSK"; - case ScanResult.KEY_MGMT_EAP_SHA256: - return "EAP-SHA256"; - case ScanResult.KEY_MGMT_PSK_SHA256: - return "PSK-SHA256"; - case ScanResult.KEY_MGMT_OWE: - return "OWE"; - case ScanResult.KEY_MGMT_OWE_TRANSITION: - return "OWE_TRANSITION"; - case ScanResult.KEY_MGMT_SAE: - return "SAE"; - case ScanResult.KEY_MGMT_FT_SAE: - return "FT/SAE"; - case ScanResult.KEY_MGMT_EAP_SUITE_B_192: - return "EAP_SUITE_B_192"; - case ScanResult.KEY_MGMT_OSEN: - return "OSEN"; - case ScanResult.KEY_MGMT_WAPI_PSK: - return "WAPI-PSK"; - case ScanResult.KEY_MGMT_WAPI_CERT: - return "WAPI-CERT"; - case ScanResult.KEY_MGMT_FILS_SHA256: - return "EAP-FILS-SHA256"; - case ScanResult.KEY_MGMT_FILS_SHA384: - return "EAP-FILS-SHA384"; - default: - return "?"; - } - } - - private String cipherToString(@Cipher int cipher) { - switch (cipher) { - case ScanResult.CIPHER_NONE: - return "None"; - case ScanResult.CIPHER_CCMP: - return "CCMP"; - case ScanResult.CIPHER_GCMP_256: - return "GCMP-256"; - case ScanResult.CIPHER_TKIP: - return "TKIP"; - case ScanResult.CIPHER_SMS4: - return "SMS4"; - default: - return "?"; - } - } - - /** - * Build the ScanResult.capabilities String. - * - * @return security string that mirrors what wpa_supplicant generates - */ - public String generateCapabilitiesString() { - StringBuilder capabilities = new StringBuilder(); - // private Beacon without an RSNE or WPA IE, hence WEP0 - boolean isWEP = (protocol.isEmpty()) && isPrivacy; - - if (isWEP) { - capabilities.append("[WEP]"); - } - for (int i = 0; i < protocol.size(); i++) { - String capability = generateCapabilitiesStringPerProtocol(i); - // add duplicate capabilities for WPA2 for backward compatibility: - // duplicate "RSN" entries as "WPA2" - String capWpa2 = generateWPA2CapabilitiesString(capability, i); - capabilities.append(capWpa2); - capabilities.append(capability); - } - if (isESS) { - capabilities.append("[ESS]"); - } - if (isIBSS) { - capabilities.append("[IBSS]"); - } - if (isWPS) { - capabilities.append("[WPS]"); - } - - return capabilities.toString(); - } - - /** - * Build the Capability String for one protocol - * @param index: index number of the protocol - * @return security string for one protocol - */ - private String generateCapabilitiesStringPerProtocol(int index) { - StringBuilder capability = new StringBuilder(); - capability.append("[").append(protocolToString(protocol.get(index))); - - if (index < keyManagement.size()) { - for (int j = 0; j < keyManagement.get(index).size(); j++) { - capability.append((j == 0) ? "-" : "+").append( - keyManagementToString(keyManagement.get(index).get(j))); - } - } - if (index < pairwiseCipher.size()) { - for (int j = 0; j < pairwiseCipher.get(index).size(); j++) { - capability.append((j == 0) ? "-" : "+").append( - cipherToString(pairwiseCipher.get(index).get(j))); - } - } - capability.append("]"); - return capability.toString(); - } - - /** - * Build the duplicate Capability String for WPA2 - * @param cap: original capability String - * @param index: index number of the protocol - * @return security string for WPA2, empty String if protocol is not WPA2 - */ - private String generateWPA2CapabilitiesString(String cap, int index) { - StringBuilder capWpa2 = new StringBuilder(); - // if not WPA2, return empty String - if (cap.contains("EAP_SUITE_B_192") - || (!cap.contains("RSN-EAP") && !cap.contains("RSN-FT/EAP") - && !cap.contains("RSN-PSK") && !cap.contains("RSN-FT/PSK"))) { - return ""; - } - capWpa2.append("[").append("WPA2"); - if (index < keyManagement.size()) { - for (int j = 0; j < keyManagement.get(index).size(); j++) { - capWpa2.append((j == 0) ? "-" : "+").append( - keyManagementToString(keyManagement.get(index).get(j))); - // WPA3/WPA2 transition mode - if (cap.contains("SAE")) { - break; - } - } - } - if (index < pairwiseCipher.size()) { - for (int j = 0; j < pairwiseCipher.get(index).size(); j++) { - capWpa2.append((j == 0) ? "-" : "+").append( - cipherToString(pairwiseCipher.get(index).get(j))); - } - } - capWpa2.append("]"); - return capWpa2.toString(); - } - } - - - /** - * Parser for the Traffic Indication Map (TIM) Information Element (EID 5). This element will - * only be present in scan results that are derived from a Beacon Frame, not from the more - * plentiful probe responses. Call 'isValid()' after parsing, to ensure the results are correct. - */ - public static class TrafficIndicationMap { - private static final int MAX_TIM_LENGTH = 254; - private boolean mValid = false; - public int mLength = 0; - public int mDtimCount = -1; - //Negative DTIM Period means no TIM element was given this frame. - public int mDtimPeriod = -1; - public int mBitmapControl = 0; - - /** - * Is this a valid TIM information element. - */ - public boolean isValid() { - return mValid; - } - - // Traffic Indication Map format (size unit: byte) - // - //| ElementID | Length | DTIM Count | DTIM Period | BitmapControl | Partial Virtual Bitmap | - // 1 1 1 1 1 1 - 251 - // - // Note: InformationElement.bytes has 'Element ID' and 'Length' - // stripped off already - // - public void from(InformationElement ie) { - mValid = false; - if (ie == null || ie.bytes == null) return; - mLength = ie.bytes.length; - ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - try { - mDtimCount = data.get() & Constants.BYTE_MASK; - mDtimPeriod = data.get() & Constants.BYTE_MASK; - mBitmapControl = data.get() & Constants.BYTE_MASK; - //A valid TIM element must have atleast one more byte - data.get(); - } catch (BufferUnderflowException e) { - return; - } - if (mLength <= MAX_TIM_LENGTH && mDtimPeriod > 0) { - mValid = true; - } - } - } - - /** - * This util class determines the 802.11 standard (a/b/g/n/ac/ax) being used - */ - public static class WifiMode { - public static final int MODE_UNDEFINED = 0; // Unknown/undefined - public static final int MODE_11A = 1; // 802.11a - public static final int MODE_11B = 2; // 802.11b - public static final int MODE_11G = 3; // 802.11g - public static final int MODE_11N = 4; // 802.11n - public static final int MODE_11AC = 5; // 802.11ac - public static final int MODE_11AX = 6; // 802.11ax - //<TODO> add support for 802.11ad and be more selective instead of defaulting to 11A - - /** - * Use frequency, max supported rate, and the existence of HE, VHT, HT & ERP fields in scan - * scan result to determine the 802.11 Wifi standard being used. - */ - public static int determineMode(int frequency, int maxRate, boolean foundHe, - boolean foundVht, boolean foundHt, boolean foundErp) { - if (foundHe) { - return MODE_11AX; - } else if (!ScanResult.is24GHz(frequency) && foundVht) { - // Do not include subset of VHT on 2.4 GHz vendor extension - // in consideration for reporting VHT. - return MODE_11AC; - } else if (foundHt) { - return MODE_11N; - } else if (foundErp) { - return MODE_11G; - } else if (ScanResult.is24GHz(frequency)) { - if (maxRate < 24000000) { - return MODE_11B; - } else { - return MODE_11G; - } - } else { - return MODE_11A; - } - } - - /** - * Map the wifiMode integer to its type, and output as String MODE_11<A/B/G/N/AC> - */ - public static String toString(int mode) { - switch(mode) { - case MODE_11A: - return "MODE_11A"; - case MODE_11B: - return "MODE_11B"; - case MODE_11G: - return "MODE_11G"; - case MODE_11N: - return "MODE_11N"; - case MODE_11AC: - return "MODE_11AC"; - case MODE_11AX: - return "MODE_11AX"; - default: - return "MODE_UNDEFINED"; - } - } - } - - /** - * Parser for both the Supported Rates & Extended Supported Rates Information Elements - */ - public static class SupportedRates { - public static final int MASK = 0x7F; // 0111 1111 - public boolean mValid = false; - public ArrayList<Integer> mRates; - - public SupportedRates() { - mRates = new ArrayList<Integer>(); - } - - /** - * Is this a valid Supported Rates information element. - */ - public boolean isValid() { - return mValid; - } - - /** - * get the Rate in bits/s from associated byteval - */ - public static int getRateFromByte(int byteVal) { - byteVal &= MASK; - switch(byteVal) { - case 2: - return 1000000; - case 4: - return 2000000; - case 11: - return 5500000; - case 12: - return 6000000; - case 18: - return 9000000; - case 22: - return 11000000; - case 24: - return 12000000; - case 36: - return 18000000; - case 44: - return 22000000; - case 48: - return 24000000; - case 66: - return 33000000; - case 72: - return 36000000; - case 96: - return 48000000; - case 108: - return 54000000; - default: - //ERROR UNKNOWN RATE - return -1; - } - } - - // Supported Rates format (size unit: byte) - // - //| ElementID | Length | Supported Rates [7 Little Endian Info bits - 1 Flag bit] - // 1 1 1 - 8 - // - // Note: InformationElement.bytes has 'Element ID' and 'Length' - // stripped off already - // - public void from(InformationElement ie) { - mValid = false; - if (ie == null || ie.bytes == null || ie.bytes.length > 8 || ie.bytes.length < 1) { - return; - } - ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); - try { - for (int i = 0; i < ie.bytes.length; i++) { - int rate = getRateFromByte(data.get()); - if (rate > 0) { - mRates.add(rate); - } else { - return; - } - } - } catch (BufferUnderflowException e) { - return; - } - mValid = true; - return; - } - - /** - * Lists the rates in a human readable string - */ - public String toString() { - StringBuilder sbuf = new StringBuilder(); - for (Integer rate : mRates) { - sbuf.append(String.format("%.1f", (double) rate / 1000000) + ", "); - } - return sbuf.toString(); - } - } -} diff --git a/service/java/com/android/server/wifi/util/IntCounter.java b/service/java/com/android/server/wifi/util/IntCounter.java deleted file mode 100644 index 40be9380c..000000000 --- a/service/java/com/android/server/wifi/util/IntCounter.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.util.SparseIntArray; - -import com.android.server.wifi.proto.nano.WifiMetricsProto.Int32Count; - -import java.lang.reflect.Array; -import java.util.Iterator; - -/** - * Utility class for counting occurrences of int keys using an int counter. - * Note: this class can also be used for counting occurrences of enum values. Just define a new - * Protobuf message, and call {@link #toProto(Class, ProtobufConverter)} with a - * {@link ProtobufConverter} that populates your custom Protobuf message type. - */ -public class IntCounter extends SparseIntArray implements Iterable<IntCounter.KeyCount> { - - /** - * A class to represent the number of occurrences for an int key. - */ - public static class KeyCount { - public int key; - public int count; - - public KeyCount(int key, int count) { - this.key = key; - this.count = count; - } - } - - /** - * Calls to {@link #add(int, int)}/{@link #increment(int)} for all keys < keyLowerBound are - * instead attributed to keyLowerBound. - */ - public final int keyLowerBound; - /** - * Calls to {@link #add(int, int)}/{@link #increment(int)} for all keys > keyUpperBound are - * instead attributed to keyUpperBound. - */ - public final int keyUpperBound; - - public IntCounter() { - this(Integer.MIN_VALUE, Integer.MAX_VALUE); - } - - /** - * Clamps keys to the range between keyLowerBound and keyUpperBound. See {@link #keyLowerBound} - * and {@link #keyUpperBound}. - */ - public IntCounter(int keyLowerBound, int keyUpperBound) { - this.keyLowerBound = keyLowerBound; - this.keyUpperBound = keyUpperBound; - } - - /** - * Increments the count of a key by 1. - */ - public void increment(int key) { - add(key, 1); - } - - /** - * Increments the count of a key by <code>count</code>. - */ - public void add(int key, int count) { - key = Math.max(keyLowerBound, Math.min(key, keyUpperBound)); - int curCount = get(key); // returns 0 if key not found - put(key, curCount + count); - } - - /** - * Iterates over all (key, count) pairs. - */ - @Override - public Iterator<KeyCount> iterator() { - return new Iterator<KeyCount>() { - private int mIndex = 0; - - @Override - public boolean hasNext() { - return mIndex < size(); - } - - @Override - public KeyCount next() { - KeyCount kc = new KeyCount(keyAt(mIndex), valueAt(mIndex)); - mIndex++; - return kc; - } - }; - } - - /** - * Converter function that converts a single (key, count) pair to a Protobuf object. - * @param <T> the type of the Protobuf output. - */ - public interface ProtobufConverter<T> { - /** - * Converter function that converts a single (key, count) pair to a Protobuf object. - * @param key the key that we are counting occurrences for - * @param count the number of occurrences for this key - * @return the Protobuf output - */ - T convert(int key, int count); - } - - /** - * Converts this object to a custom Protobuf representation. - * @param protoClass the class object for the Protobuf type. - * @param converter a conversion function. - * @param <T> the type of the Protobuf output. - * @return an array of Protobuf representation of buckets generated by the converter function. - */ - public <T> T[] toProto(Class<T> protoClass, ProtobufConverter<T> converter) { - @SuppressWarnings("unchecked") - T[] output = (T[]) Array.newInstance(protoClass, size()); - int i = 0; - for (KeyCount kc : this) { - output[i] = converter.convert(kc.key, kc.count); - i++; - } - return output; - } - - /** - * Converts this object to a standard Protobuf representation. - */ - public Int32Count[] toProto() { - return toProto(Int32Count.class, (key, count) -> { - Int32Count entry = new Int32Count(); - entry.key = key; - entry.count = count; - return entry; - }); - } -} diff --git a/service/java/com/android/server/wifi/util/IntHistogram.java b/service/java/com/android/server/wifi/util/IntHistogram.java deleted file mode 100644 index 8e8700a8c..000000000 --- a/service/java/com/android/server/wifi/util/IntHistogram.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.annotation.NonNull; -import android.util.SparseIntArray; - -import com.android.server.wifi.proto.nano.WifiMetricsProto.HistogramBucketInt32; - -import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.Iterator; - - -/** - * A histogram that stores the counts of values that fall within buckets, where buckets contain - * the count for a range of values. This implementation is backed by a SparseIntArray, meaning - * values are stored as int and counts are stored as int. - */ -public class IntHistogram implements Iterable<IntHistogram.Bucket> { - /* - * Definitions: - * - value: what you would like to count - * - count: the number of occurrences of values that fall within a bucket - * - key: mBuckets maps key => count, 0 <= key <= mBucketBoundaries.length, keys can be - * uninitialized for buckets that were never incremented - * - bucketIndex: the index of the initialized buckets, 0 <= bucketIndex < mBucket.size(), - * all indices in this range are initialized. - */ - private SparseIntArray mBuckets; - private final int[] mBucketBoundaries; - - /** - * A bucket in the histogram, for the range [start, end). - * An exception to this is when {@link Bucket#end} == Integer.MAX_VALUE, when the range will be - * [start, end]. - */ - public static class Bucket { - public int start; - public int end; - public int count; - - public Bucket(int start, int end, int count) { - this.start = start; - this.end = end; - this.count = count; - } - } - - /** - * Constructs a histogram given the boundary values of buckets, as an int[]. - * @param bucketBoundaries The boundary values that separate each bucket. The number of - * buckets is bucketBoundaries.length + 1, where the buckets are: - * - < bucketBoundaries[0] - * - [bucketBoundaries[0], bucketBoundaries[1]) - * ... - * - >= bucketBoundaries[bucketBoundaries.length() - 1] - * This array must be non-null, non-empty, and strictly monotonically - * increasing i.e. a[i] < a[i+1]. - */ - public IntHistogram(@NonNull int[] bucketBoundaries) { - if (bucketBoundaries == null || bucketBoundaries.length == 0) { - throw new IllegalArgumentException("bucketBoundaries must be non-null and non-empty!"); - } - for (int i = 0; i < bucketBoundaries.length - 1; i++) { - int cur = bucketBoundaries[i]; - int next = bucketBoundaries[i + 1]; - if (cur >= next) { - throw new IllegalArgumentException(String.format( - "bucketBoundaries values must be strictly monotonically increasing, but " - + "value %d at index %d is greater or equal to " - + "value %d at index %d!", - cur, i, next, i + 1)); - } - } - mBucketBoundaries = bucketBoundaries.clone(); - mBuckets = new SparseIntArray(); - } - - /** - * Resets this histogram to the initial state. - */ - public void clear() { - mBuckets.clear(); - } - - /** - * Returns the number of non-empty buckets, where an empty bucket is a bucket that was never - * added to. - */ - public int numNonEmptyBuckets() { - return mBuckets.size(); - } - - /** - * Returns the maximum number of possible buckets (dictated by the number of bucket boundaries). - */ - public int numTotalBuckets() { - return mBucketBoundaries.length + 1; - } - - /** - * Gets the nth non-empty bucket, where 0 <= n < {@link #numNonEmptyBuckets()} - */ - public Bucket getBucketByIndex(int bucketIndex) { - int bucketKey = mBuckets.keyAt(bucketIndex); - int start = bucketKey == 0 - ? Integer.MIN_VALUE : mBucketBoundaries[bucketKey - 1]; - int end = bucketKey == mBucketBoundaries.length - ? Integer.MAX_VALUE : mBucketBoundaries[bucketKey]; - int count = mBuckets.valueAt(bucketIndex); - return new Bucket(start, end, count); - } - - /** - * Increments the count of the bucket that this value falls into by 1. - */ - public void increment(int value) { - add(value, 1); - } - - /** - * Increments the count of the bucket that this value falls into by <code>count</code>. - */ - public void add(int value, int count) { - int bucketKey = getBucketKey(value); - int curBucketValue = mBuckets.get(bucketKey); - mBuckets.put(bucketKey, curBucketValue + count); - } - - - /** - * Computes the inverse of the cumulative probability distribution for the histogram. - * - * This is the value v such that the probability of a randomly selected datum being - * less than or equal to v is the provided probability. The answer is constrained to - * lie in the interval [minimum..maximum]. - */ - public double quantileFunction(double probability, int minimum, int maximum) { - if (minimum > maximum) { - throw new IllegalArgumentException("bad bounds"); - } - if (probability < 0.0 || probability > 1.0) { - throw new IllegalArgumentException("bad roll, try again"); - } - long sum = 0; - for (Bucket bucket : this) { - sum += bucket.count; - } - final double target = sum * probability; - double partialSum = 0.0; - Bucket hitBucket = null; - for (Bucket bucket : this) { - if (partialSum + bucket.count >= target) { - hitBucket = bucket; - break; - } - partialSum += bucket.count; - } - if (hitBucket == null) { - // No data at all; assume uniform between given limits - return minimum + probability * (maximum - minimum); - } - double highValue = Math.min(hitBucket.end, maximum); - double value = Math.max(hitBucket.start, minimum); - if (value >= highValue - 1.0 || hitBucket.count == 0) return Math.min(value, highValue); - // interpolate to estimate the value - value += (highValue - value) * (target - partialSum) / hitBucket.count; - return Math.min(Math.max(value, minimum), maximum); - } - - /** - * Given a value, returns the key of the bucket where it should fall into. - */ - private int getBucketKey(int value) { - // this passes unit tests, so don't worry about it too much - int insertionIndex = Arrays.binarySearch(mBucketBoundaries, value); - return Math.abs(insertionIndex + 1); - } - - /** - * Returns a human-readable string representation of the contents of this histogram, suitable - * for dump(). - */ - @Override - public String toString() { - if (mBuckets.size() <= 0) { - return "{}"; - } - - StringBuilder sb = new StringBuilder(); - sb.append('{'); - for (int bucketIndex = 0; bucketIndex < mBuckets.size(); ++bucketIndex) { - if (bucketIndex > 0) { - sb.append(", "); - } - int bucketKey = mBuckets.keyAt(bucketIndex); - sb.append('['); - if (bucketKey == 0) { - sb.append("Integer.MIN_VALUE"); - } else { - sb.append(mBucketBoundaries[bucketKey - 1]); - } - sb.append(','); - if (bucketKey == mBucketBoundaries.length) { - sb.append("Integer.MAX_VALUE]"); - } else { - sb.append(mBucketBoundaries[bucketKey]).append(')'); - } - sb.append('=').append(mBuckets.valueAt(bucketIndex)); - } - sb.append('}'); - return sb.toString(); - } - - /** - * Iterates over initialized buckets. - */ - @Override - public Iterator<Bucket> iterator() { - return new Iterator<Bucket>() { - private int mBucketIndex = 0; - - @Override - public boolean hasNext() { - return mBucketIndex < mBuckets.size(); - } - - @Override - public Bucket next() { - Bucket bucket = getBucketByIndex(mBucketIndex); - mBucketIndex++; - return bucket; - } - }; - } - - /** - * For backwards compatibility, can specify a conversion function that converts a bucket in this - * histogram to a specified Protobuf type, used by {@link #toProto(Class, ProtobufConverter)}. - * Note that for all new histograms, the standard Protobuf representation type is - * {@link HistogramBucketInt32[]}, which can be generated using {@link #toProto()}. - * @param <T> The type to convert to. - */ - public interface ProtobufConverter<T> { - /** - * Conversion function. - * @param start start of the range of a bucket. - * @param end end of the range of a bucket. - * @param count count of values in this bucket. - * @return A Protobuf representation of this bucket. - */ - T convert(int start, int end, int count); - } - - /** - * Converts this histogram to a Protobuf representation. See {@link ProtobufConverter} - * @param protoClass the class object for the Protobuf type. - * @param converter a conversion function. - * @param <T> the type of the Protobuf output. - * @return an array of Protobuf representation of buckets generated by the converter function. - */ - public <T> T[] toProto(Class<T> protoClass, ProtobufConverter<T> converter) { - @SuppressWarnings("unchecked") - T[] output = (T[]) Array.newInstance(protoClass, mBuckets.size()); - int i = 0; - for (Bucket bucket : this) { - output[i] = converter.convert(bucket.start, bucket.end, bucket.count); - i++; - } - return output; - } - - /** - * Converts this histogram to a standard Protobuf representation. - */ - public HistogramBucketInt32[] toProto() { - return toProto(HistogramBucketInt32.class, (start, end, count) -> { - HistogramBucketInt32 hb = new HistogramBucketInt32(); - hb.start = start; - hb.end = end; - hb.count = count; - return hb; - }); - } -} diff --git a/service/java/com/android/server/wifi/util/IpConfigStore.java b/service/java/com/android/server/wifi/util/IpConfigStore.java deleted file mode 100644 index e12f75f37..000000000 --- a/service/java/com/android/server/wifi/util/IpConfigStore.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2014 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.server.wifi.util; - -import android.annotation.Nullable; -import android.net.InetAddresses; -import android.net.IpConfiguration; -import android.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.ProxyInfo; -import android.net.RouteInfo; -import android.net.StaticIpConfiguration; -import android.net.Uri; -import android.util.ArrayMap; -import android.util.Log; -import android.util.SparseArray; - -import java.io.DataInputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -/** - * Note: @hide class copied from com.android.server.net. - */ -public class IpConfigStore { - private static final String TAG = "IpConfigStore"; - private static final boolean DBG = false; - - /* IP and proxy configuration keys */ - protected static final String ID_KEY = "id"; - protected static final String IP_ASSIGNMENT_KEY = "ipAssignment"; - protected static final String LINK_ADDRESS_KEY = "linkAddress"; - protected static final String GATEWAY_KEY = "gateway"; - protected static final String DNS_KEY = "dns"; - protected static final String PROXY_SETTINGS_KEY = "proxySettings"; - protected static final String PROXY_HOST_KEY = "proxyHost"; - protected static final String PROXY_PORT_KEY = "proxyPort"; - protected static final String PROXY_PAC_FILE = "proxyPac"; - protected static final String EXCLUSION_LIST_KEY = "exclusionList"; - protected static final String EOS = "eos"; - - /** - * Parses Ip configuration data from the bytestream provided. - */ - public static SparseArray<IpConfiguration> readIpAndProxyConfigurations( - InputStream inputStream) { - ArrayMap<String, IpConfiguration> networks = readIpConfigurations(inputStream); - if (networks == null) { - return null; - } - - SparseArray<IpConfiguration> networksById = new SparseArray<>(); - for (int i = 0; i < networks.size(); i++) { - int id = Integer.valueOf(networks.keyAt(i)); - networksById.put(id, networks.valueAt(i)); - } - - return networksById; - } - - /** Returns a map of network identity token and {@link IpConfiguration}. */ - public static ArrayMap<String, IpConfiguration> readIpConfigurations( - InputStream inputStream) { - ArrayMap<String, IpConfiguration> networks = new ArrayMap<>(); - DataInputStream in = null; - try { - in = new DataInputStream(inputStream); - - int version = in.readInt(); - if (version != 3 && version != 2 && version != 1) { - loge("Bad version on IP configuration file, ignore read"); - return null; - } - - while (true) { - String uniqueToken = null; - // Default is DHCP with no proxy - IpAssignment ipAssignment = IpAssignment.DHCP; - ProxySettings proxySettings = ProxySettings.NONE; - StaticIpConfiguration.Builder staticIPBuilder = new StaticIpConfiguration.Builder(); - List<InetAddress> dnsServerAddresses = new ArrayList<>(); - String proxyHost = null; - String pacFileUrl = null; - int proxyPort = -1; - String exclusionList = null; - String key; - - do { - key = in.readUTF(); - try { - if (key.equals(ID_KEY)) { - if (version < 3) { - int id = in.readInt(); - uniqueToken = String.valueOf(id); - } else { - uniqueToken = in.readUTF(); - } - } else if (key.equals(IP_ASSIGNMENT_KEY)) { - ipAssignment = IpAssignment.valueOf(in.readUTF()); - } else if (key.equals(LINK_ADDRESS_KEY)) { - LinkAddress linkAddr = new LinkAddress( - InetAddresses.parseNumericAddress(in.readUTF()), in.readInt()); - if (linkAddr.getAddress() instanceof Inet4Address) { - staticIPBuilder.setIpAddress(linkAddr); - } - } else if (key.equals(GATEWAY_KEY)) { - LinkAddress dest = null; - InetAddress gateway = null; - if (version == 1) { - // only supported default gateways - leave the dest/prefix empty - gateway = InetAddresses.parseNumericAddress(in.readUTF()); - staticIPBuilder.setGateway(gateway); - } else { - if (in.readInt() == 1) { - dest = new LinkAddress( - InetAddresses.parseNumericAddress(in.readUTF()), - in.readInt()); - } - if (in.readInt() == 1) { - gateway = InetAddresses.parseNumericAddress(in.readUTF()); - } - RouteInfo route = new RouteInfo( - dest == null ? null : new IpPrefix( - dest.getAddress(), dest.getPrefixLength()), - gateway, null, RouteInfo.RTN_UNICAST); - if (route.isDefaultRoute() - && route.getDestination().getAddress() - instanceof Inet4Address) { - staticIPBuilder.setGateway(gateway); - } else { - loge("Non-IPv4 default or duplicate route: " + route); - } - } - } else if (key.equals(DNS_KEY)) { - dnsServerAddresses.add(InetAddresses.parseNumericAddress(in.readUTF())); - } else if (key.equals(PROXY_SETTINGS_KEY)) { - proxySettings = ProxySettings.valueOf(in.readUTF()); - } else if (key.equals(PROXY_HOST_KEY)) { - proxyHost = in.readUTF(); - } else if (key.equals(PROXY_PORT_KEY)) { - proxyPort = in.readInt(); - } else if (key.equals(PROXY_PAC_FILE)) { - pacFileUrl = in.readUTF(); - } else if (key.equals(EXCLUSION_LIST_KEY)) { - exclusionList = in.readUTF(); - } else if (key.equals(EOS)) { - break; - } else { - loge("Ignore unknown key " + key + "while reading"); - } - } catch (IllegalArgumentException e) { - loge("Ignore invalid address while reading" + e); - } - } while (true); - - staticIPBuilder.setDnsServers(dnsServerAddresses); - StaticIpConfiguration staticIpConfiguration = staticIPBuilder.build(); - if (uniqueToken != null) { - IpConfiguration config = new IpConfiguration(); - networks.put(uniqueToken, config); - - switch (ipAssignment) { - case STATIC: - config.setStaticIpConfiguration(staticIpConfiguration); - config.setIpAssignment(ipAssignment); - break; - case DHCP: - config.setIpAssignment(ipAssignment); - break; - case UNASSIGNED: - loge("BUG: Found UNASSIGNED IP on file, use DHCP"); - config.setIpAssignment(IpAssignment.DHCP); - break; - default: - loge("Ignore invalid ip assignment while reading."); - config.setIpAssignment(IpAssignment.UNASSIGNED); - break; - } - - switch (proxySettings) { - case STATIC: - ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy( - proxyHost, proxyPort, - parseProxyExclusionListString(exclusionList)); - config.setProxySettings(proxySettings); - config.setHttpProxy(proxyInfo); - break; - case PAC: - ProxyInfo proxyPacProperties = - ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl)); - config.setProxySettings(proxySettings); - config.setHttpProxy(proxyPacProperties); - break; - case NONE: - config.setProxySettings(proxySettings); - break; - case UNASSIGNED: - loge("BUG: Found UNASSIGNED proxy on file, use NONE"); - config.setProxySettings(ProxySettings.NONE); - break; - default: - loge("Ignore invalid proxy settings while reading"); - config.setProxySettings(ProxySettings.UNASSIGNED); - break; - } - } else { - if (DBG) log("Missing id while parsing configuration"); - } - } - } catch (EOFException ignore) { - } catch (IOException e) { - loge("Error parsing configuration: " + e); - } finally { - if (in != null) { - try { - in.close(); - } catch (Exception e) { } - } - } - - return networks; - } - - private static List<String> parseProxyExclusionListString( - @Nullable String exclusionListString) { - if (exclusionListString == null) { - return Collections.emptyList(); - } else { - return Arrays.asList(exclusionListString.toLowerCase(Locale.ROOT).split(",")); - } - } - - protected static void loge(String s) { - Log.e(TAG, s); - } - - protected static void log(String s) { - Log.d(TAG, s); - } -} diff --git a/service/java/com/android/server/wifi/util/KalmanFilter.java b/service/java/com/android/server/wifi/util/KalmanFilter.java deleted file mode 100644 index b961ed809..000000000 --- a/service/java/com/android/server/wifi/util/KalmanFilter.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.util; - -/** - * Utility providiing a basic Kalman filter - * - * For background, see https://en.wikipedia.org/wiki/Kalman_filter - */ -public class KalmanFilter { - public Matrix mF; // stateTransition - public Matrix mQ; // processNoiseCovariance - public Matrix mH; // observationModel - public Matrix mR; // observationNoiseCovariance - public Matrix mP; // aPosterioriErrorCovariance - public Matrix mx; // stateEstimate - - /** - * Performs the prediction phase of the filter, using the state estimate to produce - * a new estimate for the current timestep. - */ - public void predict() { - mx = mF.dot(mx); - mP = mF.dot(mP).dotTranspose(mF).plus(mQ); - } - - /** - * Updates the state estimate to incorporate the new observation z. - */ - public void update(Matrix z) { - Matrix y = z.minus(mH.dot(mx)); - Matrix tS = mH.dot(mP).dotTranspose(mH).plus(mR); - Matrix tK = mP.dotTranspose(mH).dot(tS.inverse()); - mx = mx.plus(tK.dot(y)); - mP = mP.minus(tK.dot(mH).dot(mP)); - } - - @Override - public String toString() { - return "{F: " + mF - + " Q: " + mQ - + " H: " + mH - + " R: " + mR - + " P: " + mP - + " x: " + mx - + "}"; - } -} diff --git a/service/java/com/android/server/wifi/util/KeyValueListParser.java b/service/java/com/android/server/wifi/util/KeyValueListParser.java deleted file mode 100644 index ffbad6475..000000000 --- a/service/java/com/android/server/wifi/util/KeyValueListParser.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.util; - -import android.text.TextUtils; -import android.util.ArrayMap; - -import java.io.PrintWriter; -import java.time.Duration; -import java.time.format.DateTimeParseException; - -/** - * Parses a list of key=value pairs, separated by some delimiter, and puts the results in - * an internal Map. Values can be then queried by key, or if not found, a default value - * can be used. - * - * Note: @hide class copied from android.util (with ProtoStream dependency stripped out) - */ -public class KeyValueListParser { - private final ArrayMap<String, String> mValues = new ArrayMap<>(); - private final TextUtils.StringSplitter mSplitter; - - /** - * Constructs a new KeyValueListParser. This can be reused for different strings - * by calling {@link #setString(String)}. - * @param delim The delimiter that separates key=value pairs. - */ - public KeyValueListParser(char delim) { - mSplitter = new TextUtils.SimpleStringSplitter(delim); - } - - /** - * Resets the parser with a new string to parse. The string is expected to be in the following - * format: - * <pre>key1=value,key2=value,key3=value</pre> - * - * where the delimiter is a comma. - * - * @param str the string to parse. - * @throws IllegalArgumentException if the string is malformed. - */ - public void setString(String str) throws IllegalArgumentException { - mValues.clear(); - if (str != null) { - mSplitter.setString(str); - for (String pair : mSplitter) { - int sep = pair.indexOf('='); - if (sep < 0) { - mValues.clear(); - throw new IllegalArgumentException( - "'" + pair + "' in '" + str + "' is not a valid key-value pair"); - } - mValues.put(pair.substring(0, sep).trim(), pair.substring(sep + 1).trim()); - } - } - } - - /** - * Get the value for key as an int. - * @param key The key to lookup. - * @param def The value to return if the key was not found, or the value was not a long. - * @return the int value associated with the key. - */ - public int getInt(String key, int def) { - String value = mValues.get(key); - if (value != null) { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - // fallthrough - } - } - return def; - } - - /** - * Get the value for key as a long. - * @param key The key to lookup. - * @param def The value to return if the key was not found, or the value was not a long. - * @return the long value associated with the key. - */ - public long getLong(String key, long def) { - String value = mValues.get(key); - if (value != null) { - try { - return Long.parseLong(value); - } catch (NumberFormatException e) { - // fallthrough - } - } - return def; - } - - /** - * Get the value for key as a float. - * @param key The key to lookup. - * @param def The value to return if the key was not found, or the value was not a float. - * @return the float value associated with the key. - */ - public float getFloat(String key, float def) { - String value = mValues.get(key); - if (value != null) { - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { - // fallthrough - } - } - return def; - } - - /** - * Get the value for key as a string. - * @param key The key to lookup. - * @param def The value to return if the key was not found. - * @return the string value associated with the key. - */ - public String getString(String key, String def) { - String value = mValues.get(key); - if (value != null) { - return value; - } - return def; - } - - /** - * Get the value for key as a boolean. - * @param key The key to lookup. - * @param def The value to return if the key was not found. - * @return the string value associated with the key. - */ - public boolean getBoolean(String key, boolean def) { - String value = mValues.get(key); - if (value != null) { - try { - return Boolean.parseBoolean(value); - } catch (NumberFormatException e) { - // fallthrough - } - } - return def; - } - - /** - * Get the value for key as an integer array. - * - * The value should be encoded as "0:1:2:3:4" - * - * @param key The key to lookup. - * @param def The value to return if the key was not found. - * @return the int[] value associated with the key. - */ - public int[] getIntArray(String key, int[] def) { - String value = mValues.get(key); - if (value != null) { - try { - String[] parts = value.split(":"); - if (parts.length > 0) { - int[] ret = new int[parts.length]; - for (int i = 0; i < parts.length; i++) { - ret[i] = Integer.parseInt(parts[i]); - } - return ret; - } - } catch (NumberFormatException e) { - // fallthrough - } - } - return def; - } - - /** - * @return the number of keys. - */ - public int size() { - return mValues.size(); - } - - /** - * @return the key at {@code index}. Use with {@link #size()} to enumerate all key-value pairs. - */ - public String keyAt(int index) { - return mValues.keyAt(index); - } - - /** - * {@hide} - * Parse a duration in millis based on java.time.Duration or just a number (millis) - */ - public long getDurationMillis(String key, long def) { - String value = mValues.get(key); - if (value != null) { - try { - if (value.startsWith("P") || value.startsWith("p")) { - return Duration.parse(value).toMillis(); - } else { - return Long.parseLong(value); - } - } catch (NumberFormatException | DateTimeParseException e) { - // fallthrough - } - } - return def; - } - - /** Represents an integer config value. */ - public static class IntValue { - private final String mKey; - private final int mDefaultValue; - private int mValue; - - /** Constructor, initialize with a config key and a default value. */ - public IntValue(String key, int defaultValue) { - mKey = key; - mDefaultValue = defaultValue; - mValue = mDefaultValue; - } - - /** Read a value from {@link KeyValueListParser} */ - public void parse(KeyValueListParser parser) { - mValue = parser.getInt(mKey, mDefaultValue); - } - - /** Return the config key. */ - public String getKey() { - return mKey; - } - - /** Return the default value. */ - public int getDefaultValue() { - return mDefaultValue; - } - - /** Return the actual config value. */ - public int getValue() { - return mValue; - } - - /** Overwrites with a value. */ - public void setValue(int value) { - mValue = value; - } - - /** Used for dumpsys */ - public void dump(PrintWriter pw, String prefix) { - pw.print(prefix); - pw.print(mKey); - pw.print("="); - pw.print(mValue); - pw.println(); - } - } - - /** Represents an long config value. */ - public static class LongValue { - private final String mKey; - private final long mDefaultValue; - private long mValue; - - /** Constructor, initialize with a config key and a default value. */ - public LongValue(String key, long defaultValue) { - mKey = key; - mDefaultValue = defaultValue; - mValue = mDefaultValue; - } - - /** Read a value from {@link KeyValueListParser} */ - public void parse(KeyValueListParser parser) { - mValue = parser.getLong(mKey, mDefaultValue); - } - - /** Return the config key. */ - public String getKey() { - return mKey; - } - - /** Return the default value. */ - public long getDefaultValue() { - return mDefaultValue; - } - - /** Return the actual config value. */ - public long getValue() { - return mValue; - } - - /** Overwrites with a value. */ - public void setValue(long value) { - mValue = value; - } - - /** Used for dumpsys */ - public void dump(PrintWriter pw, String prefix) { - pw.print(prefix); - pw.print(mKey); - pw.print("="); - pw.print(mValue); - pw.println(); - } - } - - /** Represents an string config value. */ - public static class StringValue { - private final String mKey; - private final String mDefaultValue; - private String mValue; - - /** Constructor, initialize with a config key and a default value. */ - public StringValue(String key, String defaultValue) { - mKey = key; - mDefaultValue = defaultValue; - mValue = mDefaultValue; - } - - /** Read a value from {@link KeyValueListParser} */ - public void parse(KeyValueListParser parser) { - mValue = parser.getString(mKey, mDefaultValue); - } - - /** Return the config key. */ - public String getKey() { - return mKey; - } - - /** Return the default value. */ - public String getDefaultValue() { - return mDefaultValue; - } - - /** Return the actual config value. */ - public String getValue() { - return mValue; - } - - /** Overwrites with a value. */ - public void setValue(String value) { - mValue = value; - } - - /** Used for dumpsys */ - public void dump(PrintWriter pw, String prefix) { - pw.print(prefix); - pw.print(mKey); - pw.print("="); - pw.print(mValue); - pw.println(); - } - } - - /** Represents an float config value. */ - public static class FloatValue { - private final String mKey; - private final float mDefaultValue; - private float mValue; - - /** Constructor, initialize with a config key and a default value. */ - public FloatValue(String key, float defaultValue) { - mKey = key; - mDefaultValue = defaultValue; - mValue = mDefaultValue; - } - - /** Read a value from {@link KeyValueListParser} */ - public void parse(KeyValueListParser parser) { - mValue = parser.getFloat(mKey, mDefaultValue); - } - - /** Return the config key. */ - public String getKey() { - return mKey; - } - - /** Return the default value. */ - public float getDefaultValue() { - return mDefaultValue; - } - - /** Return the actual config value. */ - public float getValue() { - return mValue; - } - - /** Overwrites with a value. */ - public void setValue(float value) { - mValue = value; - } - - /** Used for dumpsys */ - public void dump(PrintWriter pw, String prefix) { - pw.print(prefix); - pw.print(mKey); - pw.print("="); - pw.print(mValue); - pw.println(); - } - } -} diff --git a/service/java/com/android/server/wifi/util/LruConnectionTracker.java b/service/java/com/android/server/wifi/util/LruConnectionTracker.java deleted file mode 100644 index 256728884..000000000 --- a/service/java/com/android/server/wifi/util/LruConnectionTracker.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi.util; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.wifi.WifiConfiguration; - -import com.android.server.wifi.ScanResultMatchInfo; -import com.android.wifi.resources.R; - -/** - * Create a lru list to store the network connection order. sorted by most recently connected - * first. - */ -public class LruConnectionTracker { - private final LruList<ScanResultMatchInfo> mList; - private final Context mContext; - public LruConnectionTracker(int size, Context context) { - mList = new LruList<>(size); - mContext = context; - } - /** - * Check if a WifiConfiguration is in the most recently connected list. - */ - public boolean isMostRecentlyConnected(@NonNull WifiConfiguration config) { - return getAgeIndexOfNetwork(config) < mContext.getResources() - .getInteger(R.integer.config_wifiMaxPnoSsidCount); - } - - /** - * Add a WifiConfiguration into the most recently connected list. - */ - public void addNetwork(@NonNull WifiConfiguration config) { - mList.add(ScanResultMatchInfo.fromWifiConfiguration(config)); - } - - /** - * Remove a network from the list. - */ - public void removeNetwork(@NonNull WifiConfiguration config) { - mList.remove(ScanResultMatchInfo.fromWifiConfiguration(config)); - } - - /** - * Get the index of the input config inside the MostRecentlyConnectNetworkList. - * If input config is in the list will return index number, - * otherwise return {@code Integer.MAX_VALUE} - */ - public int getAgeIndexOfNetwork(@NonNull WifiConfiguration config) { - int index = mList.indexOf(ScanResultMatchInfo.fromWifiConfiguration(config)); - // Not in the most recently connected list will return the MAX_INT - if (index < 0) { - return Integer.MAX_VALUE; - } - return index; - } -} diff --git a/service/java/com/android/server/wifi/util/LruList.java b/service/java/com/android/server/wifi/util/LruList.java deleted file mode 100644 index 69ed85112..000000000 --- a/service/java/com/android/server/wifi/util/LruList.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi.util; - -import android.annotation.NonNull; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -/** - * Utility class for keeping a reletively small List of values, sorted by most recently added - * first. - * @param <E> - */ -public class LruList<E> { - private int mSize; - private LinkedList<E> mLinkedList; - - /** - * Creates a new LruList capped by maxSize. - * @param maxSize max allowed size of the LruList - */ - public LruList(int maxSize) { - mSize = maxSize; - mLinkedList = new LinkedList<E>(); - } - - /** - * Add an entry. If the entry already exists then it will be moved to the front. Otherwise, - * a new entry will be added. - * If this operation makes the LruList exceed the max allowed size, then the least recently - * added entry will be removed. - * @param entry - */ - public void add(@NonNull E entry) { - if (entry == null) { - return; - } - int index = mLinkedList.indexOf(entry); - if (index >= 0) { - mLinkedList.remove(index); - } - mLinkedList.addFirst(entry); - while (mLinkedList.size() > mSize) { - mLinkedList.removeLast(); - } - } - - /** - * Remove an entry from list. - */ - public void remove(@NonNull E entry) { - if (entry == null) { - return; - } - int index = mLinkedList.indexOf(entry); - if (index < 0) { - return; - } - mLinkedList.remove(index); - } - - /** - * Returns the list of entries sorted by most recently added entries first. - * @return - */ - public @NonNull List<E> getEntries() { - return new ArrayList<E>(mLinkedList); - } - - /** - * Gets the number of entries in this LruList. - */ - public int size() { - return mLinkedList.size(); - } - - /** - * Get the index in the list of the input entry. - * If not in the list will return -1. - * If in the list, smaller index is more recently added. - */ - public int indexOf(E entry) { - return mLinkedList.indexOf(entry); - } -} diff --git a/service/java/com/android/server/wifi/util/Matrix.java b/service/java/com/android/server/wifi/util/Matrix.java deleted file mode 100644 index afd9de6ea..000000000 --- a/service/java/com/android/server/wifi/util/Matrix.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.util; - -/** - * Utility for doing basic matix calculations - */ -public class Matrix { - public final int n; - public final int m; - public final double[] mem; - - /** - * Creates a new matrix, initialized to zeros - * - * @param rows - number of rows (n) - * @param cols - number of columns (m) - */ - public Matrix(int rows, int cols) { - n = rows; - m = cols; - mem = new double[rows * cols]; - } - - /** - * Creates a new matrix using the provided array of values - * <p> - * Values are in row-major order. - * - * @param stride is the number of columns. - * @param values is the array of values. - * @throws IllegalArgumentException if length of values array not a multiple of stride - */ - public Matrix(int stride, double[] values) { - n = (values.length + stride - 1) / stride; - m = stride; - mem = values; - if (mem.length != n * m) throw new IllegalArgumentException(); - } - - /** - * Creates a new matrix duplicating the given one - * - * @param that is the source Matrix. - */ - public Matrix(Matrix that) { - n = that.n; - m = that.m; - mem = new double[that.mem.length]; - for (int i = 0; i < mem.length; i++) { - mem[i] = that.mem[i]; - } - } - - /** - * Gets the matrix coefficient from row i, column j - * - * @param i row number - * @param j column number - * @return Coefficient at i,j - * @throws IndexOutOfBoundsException if an index is out of bounds - */ - public double get(int i, int j) { - if (!(0 <= i && i < n && 0 <= j && j < m)) throw new IndexOutOfBoundsException(); - return mem[i * m + j]; - } - - /** - * Store a matrix coefficient in row i, column j - * - * @param i row number - * @param j column number - * @param v Coefficient to store at i,j - * @throws IndexOutOfBoundsException if an index is out of bounds - */ - public void put(int i, int j, double v) { - if (!(0 <= i && i < n && 0 <= j && j < m)) throw new IndexOutOfBoundsException(); - mem[i * m + j] = v; - } - - /** - * Forms the sum of two matrices, this and that - * - * @param that is the other matrix - * @return newly allocated matrix representing the sum of this and that - * @throws IllegalArgumentException if shapes differ - */ - public Matrix plus(Matrix that) { - return plus(that, new Matrix(n, m)); - - } - - /** - * Forms the sum of two matrices, this and that - * - * @param that is the other matrix - * @param result is space to hold the result - * @return result, filled with the matrix sum - * @throws IllegalArgumentException if shapes differ - */ - public Matrix plus(Matrix that, Matrix result) { - if (!(this.n == that.n && this.m == that.m && this.n == result.n && this.m == result.m)) { - throw new IllegalArgumentException(); - } - for (int i = 0; i < mem.length; i++) { - result.mem[i] = this.mem[i] + that.mem[i]; - } - return result; - } - - /** - * Forms the difference of two matrices, this and that - * - * @param that is the other matrix - * @return newly allocated matrix representing the difference of this and that - * @throws IllegalArgumentException if shapes differ - */ - public Matrix minus(Matrix that) { - return minus(that, new Matrix(n, m)); - } - - /** - * Forms the difference of two matrices, this and that - * - * @param that is the other matrix - * @param result is space to hold the result - * @return result, filled with the matrix difference - * @throws IllegalArgumentException if shapes differ - */ - public Matrix minus(Matrix that, Matrix result) { - if (!(this.n == that.n && this.m == that.m && this.n == result.n && this.m == result.m)) { - throw new IllegalArgumentException(); - } - for (int i = 0; i < mem.length; i++) { - result.mem[i] = this.mem[i] - that.mem[i]; - } - return result; - } - - /** - * Forms a scalar product - * - * @param scalar is the value to multiply by - * @return newly allocated matrix representing the product this and scalar - */ - public Matrix times(double scalar) { - return times(scalar, new Matrix(n, m)); - } - - /** - * Forms a scalar product - * - * @param scalar is the value to multiply by - * @param result is space to hold the result - * @return result, filled with the matrix difference - * @throws IllegalArgumentException if shapes differ - */ - public Matrix times(double scalar, Matrix result) { - if (!(this.n == result.n && this.m == result.m)) { - throw new IllegalArgumentException(); - } - for (int i = 0; i < mem.length; i++) { - result.mem[i] = this.mem[i] * scalar; - } - return result; - } - - /** - * Forms the matrix product of two matrices, this and that - * - * @param that is the other matrix - * @return newly allocated matrix representing the matrix product of this and that - * @throws IllegalArgumentException if shapes are not conformant - */ - public Matrix dot(Matrix that) { - return dot(that, new Matrix(this.n, that.m)); - } - - /** - * Forms the matrix product of two matrices, this and that - * <p> - * Caller supplies an object to contain the result, as well as scratch space - * - * @param that is the other matrix - * @param result is space to hold the result - * @return result, filled with the matrix product - * @throws IllegalArgumentException if shapes are not conformant - */ - public Matrix dot(Matrix that, Matrix result) { - if (!(this.n == result.n && this.m == that.n && that.m == result.m)) { - throw new IllegalArgumentException(); - } - for (int i = 0; i < n; i++) { - for (int j = 0; j < that.m; j++) { - double s = 0.0; - for (int k = 0; k < m; k++) { - s += this.get(i, k) * that.get(k, j); - } - result.put(i, j, s); - } - } - return result; - } - - /** - * Forms the matrix transpose - * - * @return newly allocated transpose matrix - */ - public Matrix transpose() { - return transpose(new Matrix(m, n)); - } - - /** - * Forms the matrix transpose - * <p> - * Caller supplies an object to contain the result - * - * @param result is space to hold the result - * @return result, filled with the matrix transpose - * @throws IllegalArgumentException if result shape is wrong - */ - public Matrix transpose(Matrix result) { - if (!(this.n == result.m && this.m == result.n)) throw new IllegalArgumentException(); - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - result.put(j, i, get(i, j)); - } - } - return result; - } - - /** - * Forms the inverse of a square matrix - * - * @return newly allocated matrix representing the matrix inverse - * @throws ArithmeticException if the matrix is not invertible - */ - public Matrix inverse() { - return inverse(new Matrix(n, m), new Matrix(n, 2 * m)); - } - - /** - * Forms the inverse of a square matrix - * - * @param result is space to hold the result - * @param scratch is workspace of dimension n by 2*n - * @return result, filled with the matrix inverse - * @throws ArithmeticException if the matrix is not invertible - * @throws IllegalArgumentException if shape of scratch or result is wrong - */ - public Matrix inverse(Matrix result, Matrix scratch) { - if (!(n == m && n == result.n && m == result.m && n == scratch.n && 2 * m == scratch.m)) { - throw new IllegalArgumentException(); - } - - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - scratch.put(i, j, get(i, j)); - scratch.put(i, m + j, i == j ? 1.0 : 0.0); - } - } - - for (int i = 0; i < n; i++) { - int ibest = i; - double vbest = Math.abs(scratch.get(ibest, ibest)); - for (int ii = i + 1; ii < n; ii++) { - double v = Math.abs(scratch.get(ii, i)); - if (v > vbest) { - ibest = ii; - vbest = v; - } - } - if (ibest != i) { - for (int j = 0; j < scratch.m; j++) { - double t = scratch.get(i, j); - scratch.put(i, j, scratch.get(ibest, j)); - scratch.put(ibest, j, t); - } - } - double d = scratch.get(i, i); - if (d == 0.0) throw new ArithmeticException("Singular matrix"); - for (int j = 0; j < scratch.m; j++) { - scratch.put(i, j, scratch.get(i, j) / d); - } - for (int ii = i + 1; ii < n; ii++) { - d = scratch.get(ii, i); - for (int j = 0; j < scratch.m; j++) { - scratch.put(ii, j, scratch.get(ii, j) - d * scratch.get(i, j)); - } - } - } - for (int i = n - 1; i >= 0; i--) { - for (int ii = 0; ii < i; ii++) { - double d = scratch.get(ii, i); - for (int j = 0; j < scratch.m; j++) { - scratch.put(ii, j, scratch.get(ii, j) - d * scratch.get(i, j)); - } - } - } - for (int i = 0; i < result.n; i++) { - for (int j = 0; j < result.m; j++) { - result.put(i, j, scratch.get(i, m + j)); - } - } - return result; - } - /** - * Forms the matrix product with the transpose of a second matrix - * - * @param that is the other matrix - * @return newly allocated matrix representing the matrix product of this and that.transpose() - * @throws IllegalArgumentException if shapes are not conformant - */ - public Matrix dotTranspose(Matrix that) { - return dotTranspose(that, new Matrix(this.n, that.n)); - } - - /** - * Forms the matrix product with the transpose of a second matrix - * <p> - * Caller supplies an object to contain the result, as well as scratch space - * - * @param that is the other matrix - * @param result is space to hold the result - * @return result, filled with the matrix product of this and that.transpose() - * @throws IllegalArgumentException if shapes are not conformant - */ - public Matrix dotTranspose(Matrix that, Matrix result) { - if (!(this.n == result.n && this.m == that.m && that.n == result.m)) { - throw new IllegalArgumentException(); - } - for (int i = 0; i < n; i++) { - for (int j = 0; j < that.n; j++) { - double s = 0.0; - for (int k = 0; k < m; k++) { - s += this.get(i, k) * that.get(j, k); - } - result.put(i, j, s); - } - } - return result; - } - - /** - * Tests for equality - */ - @Override - public boolean equals(Object that) { - if (this == that) return true; - if (!(that instanceof Matrix)) return false; - Matrix other = (Matrix) that; - if (n != other.n) return false; - if (m != other.m) return false; - for (int i = 0; i < mem.length; i++) { - if (mem[i] != other.mem[i]) return false; - } - return true; - } - - /** - * Calculates a hash code - */ - @Override - public int hashCode() { - int h = n * 101 + m; - for (int i = 0; i < mem.length; i++) { - h = h * 37 + Double.hashCode(mem[i]); - } - return h; - } - - /** - * Makes a string representation - * - * @return string like "[a, b; c, d]" - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(n * m * 8); - sb.append("["); - for (int i = 0; i < mem.length; i++) { - if (i > 0) sb.append(i % m == 0 ? "; " : ", "); - sb.append(mem[i]); - } - sb.append("]"); - return sb.toString(); - } - -} diff --git a/service/java/com/android/server/wifi/util/MetricsUtils.java b/service/java/com/android/server/wifi/util/MetricsUtils.java deleted file mode 100644 index 4c87aa237..000000000 --- a/service/java/com/android/server/wifi/util/MetricsUtils.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.util; - -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; -import android.util.SparseIntArray; - -import com.android.server.wifi.BssidBlocklistMonitor; -import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason; - -/** - * Utilities for Metrics collections. - */ -public class MetricsUtils { - /** - * A generic bucket containing a start, end, and count. The utility classes will convert to - * such a generic bucket which can then be copied into the specific bucket of the proto. - */ - public static class GenericBucket { - public long start; - public long end; - public int count; - } - - /** - * Specifies a ~log histogram consisting of two levels of buckets - a set of N big buckets: - * - * Buckets starts at: B + P * M^i, where i=0, ... , N-1 (N big buckets) - * Each big bucket is divided into S sub-buckets - * - * Each (big) bucket is M times bigger than the previous one. - * - * The buckets are then: - * #0: B + P * M^0 with S buckets each of width (P*M^1-P*M^0)/S - * #1: B + P * M^1 with S buckets each of width (P*M^2-P*M^1)/S - * ... - * #N-1: B + P * M^(N-1) with S buckets each of width (P*M^N-P*M^(N-1))/S - */ - public static class LogHistParms { - public LogHistParms(int b, int p, int m, int s, int n) { - this.b = b; - this.p = p; - this.m = m; - this.s = s; - this.n = n; - - // derived values - mLog = Math.log(m); - bb = new double[n]; - sbw = new double[n]; - bb[0] = b + p; - sbw[0] = p * (m - 1.0) / (double) s; - for (int i = 1; i < n; ++i) { - bb[i] = m * (bb[i - 1] - b) + b; - sbw[i] = m * sbw[i - 1]; - } - } - - // spec - public int b; - public int p; - public int m; - public int s; - public int n; - - // derived - public double mLog; - public double[] bb; // bucket base - public double[] sbw; // sub-bucket width - } - - /** - * Adds the input value to the log histogram based on the histogram parameters. - */ - public static int addValueToLogHistogram(long x, SparseIntArray histogram, LogHistParms hp) { - double logArg = (double) (x - hp.b) / (double) hp.p; - int bigBucketIndex = -1; - if (logArg > 0) { - bigBucketIndex = (int) (Math.log(logArg) / hp.mLog); - } - int subBucketIndex; - if (bigBucketIndex < 0) { - bigBucketIndex = 0; - subBucketIndex = 0; - } else if (bigBucketIndex >= hp.n) { - bigBucketIndex = hp.n - 1; - subBucketIndex = hp.s - 1; - } else { - subBucketIndex = (int) ((x - hp.bb[bigBucketIndex]) / hp.sbw[bigBucketIndex]); - if (subBucketIndex >= hp.s) { // probably a rounding error so move to next big bucket - bigBucketIndex++; - if (bigBucketIndex >= hp.n) { - bigBucketIndex = hp.n - 1; - subBucketIndex = hp.s - 1; - } else { - subBucketIndex = (int) ((x - hp.bb[bigBucketIndex]) / hp.sbw[bigBucketIndex]); - } - } - } - int key = bigBucketIndex * hp.s + subBucketIndex; - - // note that get() returns 0 if index not there already - int newValue = histogram.get(key) + 1; - histogram.put(key, newValue); - - return newValue; - } - - /** - * Converts the log histogram (with the specified histogram parameters) to an array of generic - * histogram buckets. - */ - public static GenericBucket[] logHistogramToGenericBuckets(SparseIntArray histogram, - LogHistParms hp) { - GenericBucket[] protoArray = new GenericBucket[histogram.size()]; - for (int i = 0; i < histogram.size(); ++i) { - int key = histogram.keyAt(i); - - protoArray[i] = new GenericBucket(); - protoArray[i].start = (long) (hp.bb[key / hp.s] + hp.sbw[key / hp.s] * (key % hp.s)); - protoArray[i].end = (long) (protoArray[i].start + hp.sbw[key / hp.s]); - protoArray[i].count = histogram.valueAt(i); - } - - return protoArray; - } - - /** - * Adds the input value to the histogram based on the lineaer histogram parameters. - * - * The 'int[] hp' contains a list of bucket limits. The number of buckets is hp.length() + 1 - * where buckets are: - * - < hp[0] - * - [hp[0], hp[1]) - * ... - * - >= hp[hp.length() - 1] - */ - public static int addValueToLinearHistogram(int x, SparseIntArray histogram, int[] hp) { - int bucket = 0; - for (int limit : hp) { - if (x >= limit) { - bucket++; - continue; - } - break; - } - - // note that get() returns 0 if index not there already - int newValue = histogram.get(bucket) + 1; - histogram.put(bucket, newValue); - - return newValue; - } - - /** - * Converts the histogram (with the specified linear histogram parameters) to an array of - * generic histogram buckets. - */ - public static GenericBucket[] linearHistogramToGenericBuckets(SparseIntArray histogram, - int[] linearHistParams) { - GenericBucket[] protoArray = new GenericBucket[histogram.size()]; - for (int i = 0; i < histogram.size(); ++i) { - int bucket = histogram.keyAt(i); - - protoArray[i] = new GenericBucket(); - if (bucket == 0) { - protoArray[i].start = Integer.MIN_VALUE; - protoArray[i].end = linearHistParams[0]; - } else if (bucket != linearHistParams.length) { - protoArray[i].start = linearHistParams[bucket - 1]; - protoArray[i].end = linearHistParams[bucket]; - } else { - protoArray[i].start = linearHistParams[linearHistParams.length - 1]; - protoArray[i].end = Integer.MAX_VALUE; - } - protoArray[i].count = histogram.valueAt(i); - } - - return protoArray; - } - - /** - * Converts NetworkSelectionStatus.NetworkSelectionDisableReason to - * WifiMetricsProto.NetworkDisableReason.DisableReason - */ - public static int convertNetworkSelectionDisableReasonToWifiProtoEnum(int reason) { - switch (reason) { - case NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION: - return NetworkDisableReason.REASON_ASSOCIATION_REJECTION; - case NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE: - return NetworkDisableReason.REASON_AUTHENTICATION_FAILURE; - case NetworkSelectionStatus.DISABLED_DHCP_FAILURE: - return NetworkDisableReason.REASON_DHCP_FAILURE; - case NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY: - case NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT: - return NetworkDisableReason.REASON_NETWORK_VALIDATION_FAILURE; - case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS: - return NetworkDisableReason.REASON_AUTHENTICATION_NO_CREDENTIALS; - case NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD: - return NetworkDisableReason.REASON_WRONG_PASSWORD; - case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION: - return NetworkDisableReason.REASON_AUTHENTICATION_NO_SUBSCRIPTION; - default: - return NetworkDisableReason.REASON_UNKNOWN; - } - } - - /** - * Converts BssidBlocklistMonitor.FailureReason to - * WifiMetricsProto.NetworkDisableReason.DisableReason - */ - public static int convertBssidBlocklistReasonToWifiProtoEnum(int reason) { - switch (reason) { - case BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA: - return NetworkDisableReason.REASON_AP_UNABLE_TO_HANDLE_NEW_STA; - case BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE: - return NetworkDisableReason.REASON_NETWORK_VALIDATION_FAILURE; - case BssidBlocklistMonitor.REASON_WRONG_PASSWORD: - return NetworkDisableReason.REASON_WRONG_PASSWORD; - case BssidBlocklistMonitor.REASON_EAP_FAILURE: - return NetworkDisableReason.REASON_EAP_FAILURE; - case BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION: - return NetworkDisableReason.REASON_ASSOCIATION_REJECTION; - case BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT: - return NetworkDisableReason.REASON_ASSOCIATION_TIMEOUT; - case BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE: - return NetworkDisableReason.REASON_AUTHENTICATION_FAILURE; - case BssidBlocklistMonitor.REASON_DHCP_FAILURE: - return NetworkDisableReason.REASON_DHCP_FAILURE; - case BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT: - return NetworkDisableReason.REASON_ABNORMAL_DISCONNECT; - case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE: - return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_MBO_OCE; - case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT: - return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT; - case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE: - return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE; - default: - return NetworkDisableReason.REASON_UNKNOWN; - } - } -} diff --git a/service/java/com/android/server/wifi/util/MissingCounterTimerLockList.java b/service/java/com/android/server/wifi/util/MissingCounterTimerLockList.java deleted file mode 100644 index efcbc596f..000000000 --- a/service/java/com/android/server/wifi/util/MissingCounterTimerLockList.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi.util; - -import android.annotation.NonNull; - -import com.android.server.wifi.Clock; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Utility class for Lock list which control by a missing counter which will trigger a timer when - * reach the threshold. When timer expires, object will be unlocked. Before unlocked, if object - * present again, will reset both counter and timer. - * @param <E> - */ -public class MissingCounterTimerLockList<E> { - private final int mConsecutiveMissingCountToTriggerTimer; - private final Clock mClock; - private final Map<E, LockListEntry> mEntries; - - /** - * Create a new MissingCounterTimerLockList. - * @param consecutiveCount missing count threshold. - * @param clock system clock. - */ - public MissingCounterTimerLockList(int consecutiveCount, Clock clock) { - mConsecutiveMissingCountToTriggerTimer = consecutiveCount; - mClock = clock; - mEntries = new HashMap<>(); - } - - /** - * Update a set of object to check if object present or not. - * @param entrySet set of objects. - */ - public void update(@NonNull Set<E> entrySet) { - if (entrySet == null) { - return; - } - for (Map.Entry<E, LockListEntry> mapEntry : mEntries.entrySet()) { - if (mapEntry.getValue().isExpired()) { - continue; - } - if (entrySet.contains(mapEntry.getKey())) { - mapEntry.getValue().onPresent(); - } else { - mapEntry.getValue().onAbsent(); - } - } - } - - /** - * Add a object to lock with timer duration - * @param entry object to lock. - * @param duration duration of the timer. - */ - public void add(@NonNull E entry, long duration) { - if (entry == null) { - return; - } - mEntries.put(entry, new LockListEntry(duration)); - } - - /** - * Remove an object from the lock list. - * @param entry object to remove. - * @return true if lock list contains this element, otherwise false. - */ - public boolean remove(@NonNull E entry) { - return mEntries.remove(entry) != null; - } - - /** - * Check if an object is in lock list and still locked. - * @param entry object to check. - * @return true if the object is in the list and locking, otherwise false. - */ - public boolean isLocked(@NonNull E entry) { - if (entry == null) { - return false; - } - LockListEntry blockTimer = mEntries.get(entry); - return blockTimer != null && !blockTimer.isExpired(); - } - - /** - * Return the size of the lock list - */ - public int size() { - return mEntries.size(); - } - - /** - * Clear the whole lock list. - */ - public void clear() { - mEntries.clear(); - } - - class LockListEntry { - private final long mExpiryMs; - private long mStartTimeStamp; - private int mCount; - - LockListEntry(long expiryMs) { - mCount = mConsecutiveMissingCountToTriggerTimer; - mExpiryMs = expiryMs; - mStartTimeStamp = mClock.getWallClockMillis(); - } - - void onPresent() { - if (isExpired()) { - return; - } - mCount = mConsecutiveMissingCountToTriggerTimer; - mStartTimeStamp = mClock.getWallClockMillis(); - } - - void onAbsent() { - if (mCount == 0) { - // Timer already triggered - return; - } - mCount--; - if (mCount > 0) { - // Don't need to trigger timer - return; - } - mStartTimeStamp = mClock.getWallClockMillis(); - } - - boolean isExpired() { - return mCount == 0 && mStartTimeStamp + mExpiryMs < mClock.getWallClockMillis(); - } - } -} diff --git a/service/java/com/android/server/wifi/util/NativeUtil.java b/service/java/com/android/server/wifi/util/NativeUtil.java deleted file mode 100644 index bcc426c48..000000000 --- a/service/java/com/android/server/wifi/util/NativeUtil.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.util; - -import android.net.wifi.util.HexEncoding; -import android.text.TextUtils; - -import com.android.server.wifi.ByteBufferReader; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Provide utility functions for native interfacing modules. - */ -public class NativeUtil { - private static final String ANY_MAC_STR = "any"; - public static final byte[] ANY_MAC_BYTES = {0, 0, 0, 0, 0, 0}; - private static final int MAC_LENGTH = 6; - private static final int MAC_OUI_LENGTH = 3; - private static final int MAC_STR_LENGTH = MAC_LENGTH * 2 + 5; - private static final int SSID_BYTES_MAX_LEN = 32; - - /** - * Convert the string to byte array list. - * - * @return the UTF_8 char byte values of str, as an ArrayList. - * @throws IllegalArgumentException if a null or unencodable string is sent. - */ - public static ArrayList<Byte> stringToByteArrayList(String str) { - if (str == null) { - throw new IllegalArgumentException("null string"); - } - // Ensure that the provided string is UTF_8 encoded. - CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder(); - try { - ByteBuffer encoded = encoder.encode(CharBuffer.wrap(str)); - byte[] byteArray = new byte[encoded.remaining()]; - encoded.get(byteArray); - return byteArrayToArrayList(byteArray); - } catch (CharacterCodingException cce) { - throw new IllegalArgumentException("cannot be utf-8 encoded", cce); - } - } - - /** - * Convert the byte array list to string. - * - * @return the string decoded from UTF_8 byte values in byteArrayList. - * @throws IllegalArgumentException if a null byte array list is sent. - */ - public static String stringFromByteArrayList(ArrayList<Byte> byteArrayList) { - if (byteArrayList == null) { - throw new IllegalArgumentException("null byte array list"); - } - byte[] byteArray = new byte[byteArrayList.size()]; - int i = 0; - for (Byte b : byteArrayList) { - byteArray[i] = b; - i++; - } - return new String(byteArray, StandardCharsets.UTF_8); - } - - /** - * Convert the string to byte array. - * - * @return the UTF_8 char byte values of str, as an Array. - * @throws IllegalArgumentException if a null string is sent. - */ - public static byte[] stringToByteArray(String str) { - if (str == null) { - throw new IllegalArgumentException("null string"); - } - return str.getBytes(StandardCharsets.UTF_8); - } - - /** - * Convert the byte array list to string. - * - * @return the string decoded from UTF_8 byte values in byteArray. - * @throws IllegalArgumentException if a null byte array is sent. - */ - public static String stringFromByteArray(byte[] byteArray) { - if (byteArray == null) { - throw new IllegalArgumentException("null byte array"); - } - return new String(byteArray); - } - - /** - * Converts a mac address string to an array of Bytes. - * - * @param macStr string of format: "XX:XX:XX:XX:XX:XX" or "XXXXXXXXXXXX", where X is any - * hexadecimal digit. - * Passing null, empty string or "any" is the same as 00:00:00:00:00:00 - * @throws IllegalArgumentException for various malformed inputs. - */ - public static byte[] macAddressToByteArray(String macStr) { - if (TextUtils.isEmpty(macStr) || ANY_MAC_STR.equals(macStr)) return ANY_MAC_BYTES; - String cleanMac = macStr.replace(":", ""); - if (cleanMac.length() != MAC_LENGTH * 2) { - throw new IllegalArgumentException("invalid mac string length: " + cleanMac); - } - return HexEncoding.decode(cleanMac.toCharArray(), false); - } - - /** - * Converts an array of 6 bytes to a HexEncoded String with format: "XX:XX:XX:XX:XX:XX", where X - * is any hexadecimal digit. - * - * @param macArray byte array of mac values, must have length 6 - * @throws IllegalArgumentException for malformed inputs. - */ - public static String macAddressFromByteArray(byte[] macArray) { - if (macArray == null) { - throw new IllegalArgumentException("null mac bytes"); - } - if (macArray.length != MAC_LENGTH) { - throw new IllegalArgumentException("invalid macArray length: " + macArray.length); - } - StringBuilder sb = new StringBuilder(MAC_STR_LENGTH); - for (int i = 0; i < macArray.length; i++) { - if (i != 0) sb.append(":"); - sb.append(new String(HexEncoding.encode(macArray, i, 1))); - } - return sb.toString().toLowerCase(); - } - - /** - * Converts a mac address OUI string to an array of Bytes. - * - * @param macStr string of format: "XX:XX:XX" or "XXXXXX", where X is any hexadecimal digit. - * @throws IllegalArgumentException for various malformed inputs. - */ - public static byte[] macAddressOuiToByteArray(String macStr) { - if (macStr == null) { - throw new IllegalArgumentException("null mac string"); - } - String cleanMac = macStr.replace(":", ""); - if (cleanMac.length() != MAC_OUI_LENGTH * 2) { - throw new IllegalArgumentException("invalid mac oui string length: " + cleanMac); - } - return HexEncoding.decode(cleanMac.toCharArray(), false); - } - - /** - * Converts an array of 6 bytes to a long representing the MAC address. - * - * @param macArray byte array of mac values, must have length 6 - * @return Long value of the mac address. - * @throws IllegalArgumentException for malformed inputs. - */ - public static Long macAddressToLong(byte[] macArray) { - if (macArray == null) { - throw new IllegalArgumentException("null mac bytes"); - } - if (macArray.length != MAC_LENGTH) { - throw new IllegalArgumentException("invalid macArray length: " + macArray.length); - } - try { - return ByteBufferReader.readInteger( - ByteBuffer.wrap(macArray), ByteOrder.BIG_ENDIAN, macArray.length); - } catch (BufferUnderflowException | IllegalArgumentException e) { - throw new IllegalArgumentException("invalid macArray"); - } - } - - /** - * Remove enclosing quotes from the provided string. - * - * @param quotedStr String to be unquoted. - * @return String without the enclosing quotes. - */ - public static String removeEnclosingQuotes(String quotedStr) { - int length = quotedStr.length(); - if ((length >= 2) - && (quotedStr.charAt(0) == '"') && (quotedStr.charAt(length - 1) == '"')) { - return quotedStr.substring(1, length - 1); - } - return quotedStr; - } - - /** - * Add enclosing quotes to the provided string. - * - * @param str String to be quoted. - * @return String with the enclosing quotes. - */ - public static String addEnclosingQuotes(String str) { - return "\"" + str + "\""; - } - - /** - * Converts an string to an arraylist of UTF_8 byte values. - * These forms are acceptable: - * a) UTF-8 String encapsulated in quotes, or - * b) Hex string with no delimiters. - * - * @param str String to be converted. - * @throws IllegalArgumentException for null string. - */ - public static ArrayList<Byte> hexOrQuotedStringToBytes(String str) { - if (str == null) { - throw new IllegalArgumentException("null string"); - } - int length = str.length(); - if ((length > 1) && (str.charAt(0) == '"') && (str.charAt(length - 1) == '"')) { - str = str.substring(1, str.length() - 1); - return stringToByteArrayList(str); - } else { - return byteArrayToArrayList(hexStringToByteArray(str)); - } - } - - /** - * Converts an ArrayList<Byte> of UTF_8 byte values to string. - * The string will either be: - * a) UTF-8 String encapsulated in quotes (if all the bytes are UTF-8 encodeable and non null), - * or - * b) Hex string with no delimiters. - * - * @param bytes List of bytes for ssid. - * @throws IllegalArgumentException for null bytes. - */ - public static String bytesToHexOrQuotedString(ArrayList<Byte> bytes) { - if (bytes == null) { - throw new IllegalArgumentException("null ssid bytes"); - } - byte[] byteArray = byteArrayFromArrayList(bytes); - // Check for 0's in the byte stream in which case we cannot convert this into a string. - if (!bytes.contains(Byte.valueOf((byte) 0))) { - CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder(); - try { - CharBuffer decoded = decoder.decode(ByteBuffer.wrap(byteArray)); - return "\"" + decoded.toString() + "\""; - } catch (CharacterCodingException cce) { - } - } - return hexStringFromByteArray(byteArray); - } - - /** - * Converts an ssid string to an arraylist of UTF_8 byte values. - * These forms are acceptable: - * a) UTF-8 String encapsulated in quotes, or - * b) Hex string with no delimiters. - * - * @param ssidStr String to be converted. - * @throws IllegalArgumentException for null string. - */ - public static ArrayList<Byte> decodeSsid(String ssidStr) { - ArrayList<Byte> ssidBytes = hexOrQuotedStringToBytes(ssidStr); - if (ssidBytes.size() > SSID_BYTES_MAX_LEN) { - throw new IllegalArgumentException("ssid bytes size out of range: " + ssidBytes.size()); - } - return ssidBytes; - } - - /** - * Converts an ArrayList<Byte> of UTF_8 byte values to ssid string. - * The string will either be: - * a) UTF-8 String encapsulated in quotes (if all the bytes are UTF-8 encodeable and non null), - * or - * b) Hex string with no delimiters. - * - * @param ssidBytes List of bytes for ssid. - * @throws IllegalArgumentException for null bytes. - */ - public static String encodeSsid(ArrayList<Byte> ssidBytes) { - if (ssidBytes.size() > SSID_BYTES_MAX_LEN) { - throw new IllegalArgumentException("ssid bytes size out of range: " + ssidBytes.size()); - } - return bytesToHexOrQuotedString(ssidBytes); - } - - /** - * Convert from an array of primitive bytes to an array list of Byte. - */ - public static ArrayList<Byte> byteArrayToArrayList(byte[] bytes) { - ArrayList<Byte> byteList = new ArrayList<>(); - for (Byte b : bytes) { - byteList.add(b); - } - return byteList; - } - - /** - * Convert from an array list of Byte to an array of primitive bytes. - */ - public static byte[] byteArrayFromArrayList(ArrayList<Byte> bytes) { - byte[] byteArray = new byte[bytes.size()]; - int i = 0; - for (Byte b : bytes) { - byteArray[i++] = b; - } - return byteArray; - } - - /** - * Converts a hex string to byte array. - * - * @param hexStr String to be converted. - * @throws IllegalArgumentException for null string. - */ - public static byte[] hexStringToByteArray(String hexStr) { - if (hexStr == null) { - throw new IllegalArgumentException("null hex string"); - } - return HexEncoding.decode(hexStr.toCharArray(), false); - } - - /** - * Converts a byte array to hex string. - * - * @param bytes List of bytes for ssid. - * @throws IllegalArgumentException for null bytes. - */ - public static String hexStringFromByteArray(byte[] bytes) { - if (bytes == null) { - throw new IllegalArgumentException("null hex bytes"); - } - return new String(HexEncoding.encode(bytes)).toLowerCase(); - } - - /** - * Converts an 8 byte array to a WPS device type string - * { 0, 1, 2, -1, 4, 5, 6, 7 } --> "1-02FF0405-1543"; - */ - public static String wpsDevTypeStringFromByteArray(byte[] devType) { - byte[] a = devType; - int x = ((a[0] & 0xFF) << 8) | (a[1] & 0xFF); - String y = new String(HexEncoding.encode(Arrays.copyOfRange(devType, 2, 6))); - int z = ((a[6] & 0xFF) << 8) | (a[7] & 0xFF); - return String.format("%d-%s-%d", x, y, z); - } -} diff --git a/service/java/com/android/server/wifi/util/NetdWrapper.java b/service/java/com/android/server/wifi/util/NetdWrapper.java deleted file mode 100644 index 686fca60f..000000000 --- a/service/java/com/android/server/wifi/util/NetdWrapper.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.content.Context; -import android.net.INetd; -import android.net.INetdUnsolicitedEventListener; -import android.net.InetAddresses; -import android.net.InterfaceConfiguration; -import android.net.InterfaceConfigurationParcel; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.RouteInfo; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.text.TextUtils; -import android.util.Log; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * This is a simple wrapper over INetd calls used by wifi stack. - * - * Based on {@link com.android.server.NetworkManagementService} - */ -public class NetdWrapper { - private static final String TAG = "NetdWrapper"; - static final boolean MODIFY_OPERATION_ADD = true; - static final boolean MODIFY_OPERATION_REMOVE = false; - - private final INetd mNetdService; - private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener; - private final Handler mHandler; - private final Set<NetdEventObserver> mObservers = new HashSet<>(); - - /** - * Observer for iface events. - */ - public interface NetdEventObserver { - /** - * Interface configuration status has changed. - * - * @param iface The interface. - * @param up True if the interface has been enabled. - */ - void interfaceStatusChanged(String iface, boolean up); - /** - * Interface physical-layer link state has changed. For Ethernet, - * this method is invoked when the cable is plugged in or unplugged. - * - * @param iface The interface. - * @param up True if the physical link-layer connection signal is valid. - */ - void interfaceLinkStateChanged(String iface, boolean up); - } - - private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub { - @Override - public void onInterfaceClassActivityChanged(boolean isActive, - int label, long timestamp, int uid) throws RemoteException { - // Unused. - } - - @Override - public void onQuotaLimitReached(String alertName, String ifName) - throws RemoteException { - // Unused. - } - - @Override - public void onInterfaceDnsServerInfo(String ifName, - long lifetime, String[] servers) throws RemoteException { - // Unused. - } - - @Override - public void onInterfaceAddressUpdated(String addr, - String ifName, int flags, int scope) throws RemoteException { - // Unused. - } - - @Override - public void onInterfaceAddressRemoved(String addr, - String ifName, int flags, int scope) throws RemoteException { - // Unused. - } - - @Override - public void onInterfaceAdded(String ifName) throws RemoteException { - // Unused. - } - - @Override - public void onInterfaceRemoved(String ifName) throws RemoteException { - // Unused. - } - - @Override - public void onInterfaceChanged(String ifName, boolean up) - throws RemoteException { - mHandler.post(() -> notifyInterfaceStatusChanged(ifName, up)); - } - - @Override - public void onInterfaceLinkStateChanged(String ifName, boolean up) - throws RemoteException { - mHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up)); - } - - @Override - public void onRouteChanged(boolean updated, - String route, String gateway, String ifName) throws RemoteException { - // Unused. - } - - @Override - public void onStrictCleartextDetected(int uid, String hex) throws RemoteException { - // Unused. - } - - @Override - public int getInterfaceVersion() { - return INetdUnsolicitedEventListener.VERSION; - } - - @Override - public String getInterfaceHash() { - return INetdUnsolicitedEventListener.HASH; - } - } - - public NetdWrapper(Context context, Handler handler) { - mNetdService = INetd.Stub.asInterface( - (IBinder) context.getSystemService(Context.NETD_SERVICE)); - mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener(); - mHandler = handler; - - try { - mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Failed to set Netd unsolicited event listener " + e); - } - } - - private void modifyInterfaceInNetwork(boolean add, int netId, String iface) { - try { - if (add) { - mNetdService.networkAddInterface(netId, iface); - } else { - mNetdService.networkRemoveInterface(netId, iface); - } - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - private void modifyRoute(boolean add, int netId, RouteInfo route) { - final String ifName = route.getInterface(); - final String dst = route.getDestination().toString(); - final String nextHop; - - switch (route.getType()) { - case RouteInfo.RTN_UNICAST: - if (route.hasGateway()) { - nextHop = route.getGateway().getHostAddress(); - } else { - nextHop = INetd.NEXTHOP_NONE; - } - break; - case RouteInfo.RTN_UNREACHABLE: - nextHop = INetd.NEXTHOP_UNREACHABLE; - break; - case RouteInfo.RTN_THROW: - nextHop = INetd.NEXTHOP_THROW; - break; - default: - nextHop = INetd.NEXTHOP_NONE; - break; - } - try { - if (add) { - mNetdService.networkAddRoute(netId, ifName, dst, nextHop); - } else { - mNetdService.networkRemoveRoute(netId, ifName, dst, nextHop); - } - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * Add iface to local network. - */ - public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) { - modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface); - - for (RouteInfo route : routes) { - if (!route.isDefaultRoute()) { - modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route); - } - } - - // IPv6 link local should be activated always. - modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, - new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RouteInfo.RTN_UNICAST)); - } - - /** - * Remove iface from local network. - */ - public void removeInterfaceFromLocalNetwork(String iface) { - modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface); - } - - /** - * Clear iface addresses. - */ - public void clearInterfaceAddresses(String iface) { - try { - mNetdService.interfaceClearAddrs(iface); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * Enable IPv6 on iface. - */ - public void enableIpv6(String iface) { - try { - mNetdService.interfaceSetEnableIPv6(iface, true); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * Disable IPv6 on iface. - */ - public void disableIpv6(String iface) { - try { - mNetdService.interfaceSetEnableIPv6(iface, false); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * Convert InterfaceConfiguration to InterfaceConfigurationParcel with given ifname. - */ - private static InterfaceConfigurationParcel toStableParcel(InterfaceConfiguration cfg, - String iface) { - InterfaceConfigurationParcel cfgParcel = new InterfaceConfigurationParcel(); - cfgParcel.ifName = iface; - String hwAddr = cfg.getHardwareAddress(); - if (!TextUtils.isEmpty(hwAddr)) { - cfgParcel.hwAddr = hwAddr; - } else { - cfgParcel.hwAddr = ""; - } - cfgParcel.ipv4Addr = cfg.getLinkAddress().getAddress().getHostAddress(); - cfgParcel.prefixLength = cfg.getLinkAddress().getPrefixLength(); - ArrayList<String> flags = new ArrayList<>(); - for (String flag : cfg.getFlags()) { - flags.add(flag); - } - cfgParcel.flags = flags.toArray(new String[0]); - - return cfgParcel; - } - - /** - * Construct InterfaceConfiguration from InterfaceConfigurationParcel. - */ - private static InterfaceConfiguration fromStableParcel(InterfaceConfigurationParcel p) { - InterfaceConfiguration cfg = new InterfaceConfiguration(); - cfg.setHardwareAddress(p.hwAddr); - - final InetAddress addr = InetAddresses.parseNumericAddress(p.ipv4Addr); - cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength)); - for (String flag : p.flags) { - cfg.setFlag(flag); - } - return cfg; - } - - private InterfaceConfiguration getInterfaceConfig(String iface) { - final InterfaceConfigurationParcel result; - try { - result = mNetdService.interfaceGetCfg(iface); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - - try { - final InterfaceConfiguration cfg = fromStableParcel(result); - return cfg; - } catch (IllegalArgumentException iae) { - throw new IllegalStateException("Invalid InterfaceConfigurationParcel", iae); - } - } - - private void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { - LinkAddress linkAddr = cfg.getLinkAddress(); - if (linkAddr == null || linkAddr.getAddress() == null) { - throw new IllegalStateException("Null LinkAddress given"); - } - final InterfaceConfigurationParcel cfgParcel = toStableParcel(cfg, iface); - - try { - mNetdService.interfaceSetCfg(cfgParcel); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * List all tethered interfaces. - */ - public String[] listTetheredInterfaces() { - try { - return mNetdService.tetherInterfaceList(); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * Register a new netd event observer. - */ - public void registerObserver(NetdEventObserver observer) { - mObservers.add(observer); - } - - /** - * Unregister a new netd event observer. - */ - public void unregisterObserver(NetdEventObserver observer) { - mObservers.remove(observer); - } - - /** - * Set iface down. - */ - public void setInterfaceDown(String iface) { - final InterfaceConfiguration ifcg = getInterfaceConfig(iface); - ifcg.setInterfaceDown(); - setInterfaceConfig(iface, ifcg); - } - - /** - * Set iface up. - */ - public void setInterfaceUp(String iface) { - final InterfaceConfiguration ifcg = getInterfaceConfig(iface); - ifcg.setInterfaceUp(); - setInterfaceConfig(iface, ifcg); - } - - /** - * Returns whether iface is up. - */ - public boolean isInterfaceUp(String iface) { - final InterfaceConfiguration ifcg = getInterfaceConfig(iface); - return ifcg.isUp(); - } - - /** - * Set iface link address. - */ - public void setInterfaceLinkAddress(String iface, LinkAddress linkAddress) { - final InterfaceConfiguration ifcg = getInterfaceConfig(iface); - ifcg.setLinkAddress(linkAddress); - ifcg.setInterfaceUp(); - setInterfaceConfig(iface, ifcg); - } - - /** - * Set iface IPv6 privacy extensions. - */ - public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { - try { - mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * Start tethering. - */ - public void startTethering(String[] dhcpRange) { - // an odd number of addrs will fail - try { - mNetdService.tetherStart(dhcpRange); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * Stop tethering. - */ - public void stopTethering() { - try { - mNetdService.tetherStop(); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - /** - * Add tethering on iface. - */ - public void tetherInterface(String iface) { - try { - mNetdService.tetherInterfaceAdd(iface); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - List<RouteInfo> routes = new ArrayList<>(); - // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it - // suitable to use as a route destination. - LinkAddress dest = getInterfaceConfig(iface).getLinkAddress(); - RouteInfo route = new RouteInfo( - new IpPrefix(dest.getAddress(), dest.getPrefixLength()), - null, null, RouteInfo.RTN_UNICAST); - routes.add(route); - addInterfaceToLocalNetwork(iface, routes); - } - - /** - * Remove tethering on iface. - */ - public void untetherInterface(String iface) { - try { - mNetdService.tetherInterfaceRemove(iface); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } finally { - removeInterfaceFromLocalNetwork(iface); - } - } - - /** - * Returns whether tethering has been started. - */ - public boolean isTetheringStarted() { - try { - final boolean isEnabled = mNetdService.tetherIsEnabled(); - return isEnabled; - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - - /** - * Notify our observers of an interface status change - */ - private void notifyInterfaceStatusChanged(String iface, boolean up) { - for (NetdEventObserver observer : mObservers) { - observer.interfaceStatusChanged(iface, up); - } - } - - /** - * Notify our observers of an interface link state change - * (typically, an Ethernet cable has been plugged-in or unplugged). - */ - private void notifyInterfaceLinkStateChanged(String iface, boolean up) { - for (NetdEventObserver observer : mObservers) { - observer.interfaceLinkStateChanged(iface, up); - } - } -} - diff --git a/service/java/com/android/server/wifi/util/ObjectCounter.java b/service/java/com/android/server/wifi/util/ObjectCounter.java deleted file mode 100644 index 78fe94a0b..000000000 --- a/service/java/com/android/server/wifi/util/ObjectCounter.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.util.ArrayMap; - -import java.lang.reflect.Array; -import java.util.Iterator; -import java.util.Map; - -/** - * Counts occurrences of keys of type K, where K is a custom key class. This is most commonly used - * for counting occurrences of composite keys. - * @param <K> Custom key type K must override {@link Object#hashCode()}, - * {@link Object#equals(Object)}, and {@link Object#toString()}. These methods can be auto-generated - * by IntelliJ by right clicking inside your class and clicking "Generate...". - */ -public class ObjectCounter<K> implements Iterable<Map.Entry<K, Integer>> { - private ArrayMap<K, Integer> mCounter; - - public ObjectCounter() { - mCounter = new ArrayMap<>(); - } - - /** - * Removes all keys and counts from this counter. - */ - public void clear() { - mCounter.clear(); - } - - /** - * Returns the number of keys in this counter. - */ - public int size() { - return mCounter.size(); - } - - /** - * Gets the number of occurrences of a key - */ - public int getCount(K key) { - return mCounter.getOrDefault(key, 0); - } - - /** - * Increments the count of a key by 1. - */ - public void increment(K key) { - add(key, 1); - } - - /** - * Increments the count of a key by <code>count</code>. - */ - public void add(K key, int count) { - int curCount = getCount(key); - mCounter.put(key, curCount + count); - } - - /** - * Returns a string representation of this counter object suitable for dump(). Note that the - * type K must have an overridden implementation of {@link Object#toString()}. - */ - @Override - public String toString() { - return mCounter.toString(); - } - - /** - * Iterates over all (key, count) pairs. - */ - @Override - public Iterator<Map.Entry<K, Integer>> iterator() { - return mCounter.entrySet().iterator(); - } - - /** - * Converter function that converts a single (key, count) pair to a Protobuf object. - * @param <I> The type of the key. - * @param <O> The type of the Protobuf output. - */ - public interface ProtobufConverter<I, O> { - /** - * Converter function that converts a single (key, count) pair to a Protobuf object. - * @param key the key that we are counting occurrences for - * @param count the number of occurrences for this key - * @return the Protobuf output - */ - O convert(I key, int count); - } - - /** - * Converts this object to a custom Protobuf representation. - * @param protoClass the class object for the Protobuf type. - * @param converter a conversion function. - * @param <T> the type of the Protobuf output. - * @return an array of Protobuf representation of buckets generated by the converter function. - */ - public <T> T[] toProto(Class<T> protoClass, ProtobufConverter<K, T> converter) { - @SuppressWarnings("unchecked") - T[] output = (T[]) Array.newInstance(protoClass, size()); - int i = 0; - for (Map.Entry<K, Integer> entry : this) { - output[i] = converter.convert(entry.getKey(), entry.getValue()); - i++; - } - return output; - } -} diff --git a/service/java/com/android/server/wifi/util/RssiUtil.java b/service/java/com/android/server/wifi/util/RssiUtil.java deleted file mode 100644 index 134970af5..000000000 --- a/service/java/com/android/server/wifi/util/RssiUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.annotation.NonNull; -import android.content.Context; - -import com.android.wifi.resources.R; - -/** Utilities for computations involving RSSI. */ -public class RssiUtil { - private RssiUtil() {} - - /** Calculate RSSI level from RSSI using overlaid RSSI level thresholds. */ - public static int calculateSignalLevel(Context context, int rssi) { - int[] thresholds = getRssiLevelThresholds(context); - - for (int level = 0; level < thresholds.length; level++) { - if (rssi < thresholds[level]) { - return level; - } - } - return thresholds.length; - } - - @NonNull - private static int[] getRssiLevelThresholds(Context context) { - // getIntArray() will never return null, it will throw instead - return context.getResources().getIntArray(R.array.config_wifiRssiLevelThresholds); - } -} diff --git a/service/java/com/android/server/wifi/util/ScanResultUtil.java b/service/java/com/android/server/wifi/util/ScanResultUtil.java deleted file mode 100644 index 4085045b5..000000000 --- a/service/java/com/android/server/wifi/util/ScanResultUtil.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.ScanDetail; -import com.android.server.wifi.hotspot2.NetworkDetail; - -import java.io.PrintWriter; -import java.util.List; -/** - * Scan result utility for any {@link ScanResult} related operations. - * Currently contains: - * > Helper method for converting a ScanResult to a ScanDetail. - * Only fields that are supported in ScanResult are copied. - * > Helper methods to identify the encryption of a ScanResult. - */ -public class ScanResultUtil { - private ScanResultUtil() { /* not constructable */ } - - /** - * This method should only be used when the informationElements field in the provided scan - * result is filled in with the IEs from the beacon. - */ - public static ScanDetail toScanDetail(ScanResult scanResult) { - NetworkDetail networkDetail = new NetworkDetail(scanResult.BSSID, - scanResult.informationElements, scanResult.anqpLines, scanResult.frequency); - return new ScanDetail(scanResult, networkDetail); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to a PSK network or not. - * This checks if the provided capabilities string contains PSK encryption type or not. - */ - public static boolean isScanResultForPskNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("PSK"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to a WAPI-PSK network or not. - * This checks if the provided capabilities string contains PSK encryption type or not. - */ - public static boolean isScanResultForWapiPskNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("WAPI-PSK"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to a WAPI-CERT - * network or not. - * This checks if the provided capabilities string contains PSK encryption type or not. - */ - public static boolean isScanResultForWapiCertNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("WAPI-CERT"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to a EAP network or not. - * This checks if the provided capabilities string contains EAP encryption type or not. - */ - public static boolean isScanResultForEapNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("EAP"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to a EAP network or not. - * This checks if the provided capabilities string contains EAP encryption type or not. - */ - public static boolean isScanResultForEapSuiteBNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("SUITE-B-192"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to a WEP network or not. - * This checks if the provided capabilities string contains WEP encryption type or not. - */ - public static boolean isScanResultForWepNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("WEP"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to OWE network. - * This checks if the provided capabilities string contains OWE or not. - */ - public static boolean isScanResultForOweNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("OWE"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to OWE transition network. - * This checks if the provided capabilities string contains OWE_TRANSITION or not. - */ - public static boolean isScanResultForOweTransitionNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("OWE_TRANSITION"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to SAE network. - * This checks if the provided capabilities string contains SAE or not. - */ - public static boolean isScanResultForSaeNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("SAE"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to PSK-SAE transition - * network. This checks if the provided capabilities string contains both PSK and SAE or not. - */ - public static boolean isScanResultForPskSaeTransitionNetwork(ScanResult scanResult) { - return scanResult.capabilities.contains("PSK") && scanResult.capabilities.contains("SAE"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to FILS SHA256 network. - * This checks if the provided capabilities string contains FILS-SHA256 or not. - */ - public static boolean isScanResultForFilsSha256Network(ScanResult scanResult) { - return scanResult.capabilities.contains("FILS-SHA256"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to FILS SHA384 network. - * This checks if the provided capabilities string contains FILS-SHA384 or not. - */ - public static boolean isScanResultForFilsSha384Network(ScanResult scanResult) { - return scanResult.capabilities.contains("FILS-SHA384"); - } - - /** - * Helper method to check if the provided |scanResult| corresponds to an open network or not. - * This checks if the provided capabilities string does not contain either of WEP, PSK, SAE - * or EAP encryption types or not. - */ - public static boolean isScanResultForOpenNetwork(ScanResult scanResult) { - return (!(isScanResultForWepNetwork(scanResult) || isScanResultForPskNetwork(scanResult) - || isScanResultForEapNetwork(scanResult) || isScanResultForSaeNetwork(scanResult) - || isScanResultForWapiPskNetwork(scanResult) - || isScanResultForWapiCertNetwork(scanResult) - || isScanResultForEapSuiteBNetwork(scanResult))); - } - - /** - * Helper method to quote the SSID in Scan result to use for comparing/filling SSID stored in - * WifiConfiguration object. - */ - @VisibleForTesting - public static String createQuotedSSID(String ssid) { - return "\"" + ssid + "\""; - } - - /** - * Creates a network configuration object using the provided |scanResult|. - * This is used to create ephemeral network configurations. - */ - public static WifiConfiguration createNetworkFromScanResult(ScanResult scanResult) { - WifiConfiguration config = new WifiConfiguration(); - config.SSID = createQuotedSSID(scanResult.SSID); - setAllowedKeyManagementFromScanResult(scanResult, config); - return config; - } - - /** - * Sets the {@link WifiConfiguration#allowedKeyManagement} field on the given - * {@link WifiConfiguration} based on its corresponding {@link ScanResult}. - */ - public static void setAllowedKeyManagementFromScanResult(ScanResult scanResult, - WifiConfiguration config) { - if (isScanResultForSaeNetwork(scanResult)) { - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); - } else if (isScanResultForWapiPskNetwork(scanResult)) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK); - } else if (isScanResultForWapiCertNetwork(scanResult)) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT); - } else if (isScanResultForPskNetwork(scanResult)) { - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); - } else if (isScanResultForEapSuiteBNetwork(scanResult)) { - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); - } else if (isScanResultForEapNetwork(scanResult)) { - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); - } else if (isScanResultForWepNetwork(scanResult)) { - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP); - } else if (isScanResultForOweNetwork(scanResult)) { - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE); - } else { - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); - } - } - - /** - * Dump the provided scan results list to |pw|. - */ - public static void dumpScanResults(PrintWriter pw, List<ScanResult> scanResults, long nowMs) { - if (scanResults != null && scanResults.size() != 0) { - pw.println(" BSSID Frequency RSSI Age(sec) SSID " - + " Flags"); - for (ScanResult r : scanResults) { - long timeStampMs = r.timestamp / 1000; - String age; - if (timeStampMs <= 0) { - age = "___?___"; - } else if (nowMs < timeStampMs) { - age = " 0.000"; - } else if (timeStampMs < nowMs - 1000000) { - age = ">1000.0"; - } else { - age = String.format("%3.3f", (nowMs - timeStampMs) / 1000.0); - } - String ssid = r.SSID == null ? "" : r.SSID; - String rssiInfo = ""; - if (ArrayUtils.size(r.radioChainInfos) == 1) { - rssiInfo = String.format("%5d(%1d:%3d) ", r.level, - r.radioChainInfos[0].id, r.radioChainInfos[0].level); - } else if (ArrayUtils.size(r.radioChainInfos) == 2) { - rssiInfo = String.format("%5d(%1d:%3d/%1d:%3d)", r.level, - r.radioChainInfos[0].id, r.radioChainInfos[0].level, - r.radioChainInfos[1].id, r.radioChainInfos[1].level); - } else { - rssiInfo = String.format("%9d ", r.level); - } - if ((r.flags & ScanResult.FLAG_PASSPOINT_NETWORK) - == ScanResult.FLAG_PASSPOINT_NETWORK) { - r.capabilities += "[PASSPOINT]"; - } - pw.printf(" %17s %9d %18s %7s %-32s %s\n", - r.BSSID, - r.frequency, - rssiInfo, - age, - String.format("%1.32s", ssid), - r.capabilities); - } - } - } - - /** - * Check if ScarResult list is valid. - */ - public static boolean validateScanResultList(List<ScanResult> scanResults) { - if (scanResults == null || scanResults.isEmpty()) { - return false; - } - for (ScanResult scanResult : scanResults) { - if (!validate(scanResult)) { - return false; - } - } - return true; - } - - private static boolean validate(ScanResult scanResult) { - return scanResult != null && scanResult.SSID != null - && scanResult.capabilities != null && scanResult.BSSID != null; - } -} diff --git a/service/java/com/android/server/wifi/util/SettingsMigrationDataHolder.java b/service/java/com/android/server/wifi/util/SettingsMigrationDataHolder.java deleted file mode 100644 index cdd0391be..000000000 --- a/service/java/com/android/server/wifi/util/SettingsMigrationDataHolder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi.util; - -import android.annotation.Nullable; -import android.content.Context; -import android.net.wifi.WifiMigration; - -/** - * Holder for storing the migration settings data retrieved from - * {@link android.net.wifi.WifiMigration#loadFromSettings(Context)} to avoid invoking the method - * multiple times. - */ -public class SettingsMigrationDataHolder { - private final Context mContext; - private WifiMigration.SettingsMigrationData mData = null; - private boolean mRetrieved = false; - - public SettingsMigrationDataHolder(Context context) { - mContext = context; - } - - private void retrieveDataIfNecessary() { - if (mRetrieved) return; - mData = WifiMigration.loadFromSettings(mContext); - mRetrieved = true; - } - - /** - * Retrieve the cached data returned from {@link WifiMigration#loadFromSettings(Context)}. - */ - @Nullable - public WifiMigration.SettingsMigrationData retrieveData() { - retrieveDataIfNecessary(); - return mData; - } -} diff --git a/service/java/com/android/server/wifi/util/StringUtil.java b/service/java/com/android/server/wifi/util/StringUtil.java deleted file mode 100644 index 813b85b95..000000000 --- a/service/java/com/android/server/wifi/util/StringUtil.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -/** Basic string utilities */ -public class StringUtil { - static final byte ASCII_PRINTABLE_MIN = ' '; - static final byte ASCII_PRINTABLE_MAX = '~'; - - /** Returns true if-and-only-if |byteArray| can be safely printed as ASCII. */ - public static boolean isAsciiPrintable(byte[] byteArray) { - if (byteArray == null) { - return true; - } - - for (byte b : byteArray) { - switch (b) { - // Control characters which actually are printable. Fall-throughs are deliberate. - case 0x07: // bell ('\a' not recognized in Java) - case '\f': // form feed - case '\n': // new line - case '\t': // horizontal tab - case 0x0b: // vertical tab ('\v' not recognized in Java) - continue; - } - - if (b < ASCII_PRINTABLE_MIN || b > ASCII_PRINTABLE_MAX) { - return false; - } - } - - return true; - } -} diff --git a/service/java/com/android/server/wifi/util/TimedQuotaManager.java b/service/java/com/android/server/wifi/util/TimedQuotaManager.java deleted file mode 100644 index bf78e9bc8..000000000 --- a/service/java/com/android/server/wifi/util/TimedQuotaManager.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import com.android.server.wifi.Clock; - -/** - * Manages a quota that is reset at the beginning of each new time period. - */ -public class TimedQuotaManager { - private final Clock mClock; - - private final long mQuota; - private final long mPeriodMillis; - private final long mStartTimeMillis; - - /** - * The number of elapsed periods between {@link #mStartTimeMillis} and the time of the last call - * to {@link #requestQuota()}. - */ - private long mLastPeriod; - /** How much quota has been consumed in the current period. */ - private long mConsumedQuota; - - /** - * Constructor. - * @param clock Clock instance. - * @param quota the maximum quota for a given period. - * @param periodMillis the quota will be reset at the beginning of each new period. - */ - public TimedQuotaManager(Clock clock, long quota, long periodMillis) { - mClock = clock; - mQuota = quota; - mPeriodMillis = periodMillis; - mStartTimeMillis = clock.getElapsedSinceBootMillis(); - mLastPeriod = 0; - mConsumedQuota = 0; - } - - /** - * Requests one quota. If there is sufficient remaining quota for the current period, - * returns true and consumes one quota. Otherwise, returns false. - */ - public boolean requestQuota() { - long currentPeriod = getCurrentPeriod(); - if (mLastPeriod < currentPeriod) { - mLastPeriod = currentPeriod; - mConsumedQuota = 0; - } - if (mConsumedQuota < mQuota) { - mConsumedQuota++; - return true; - } - return false; - } - - private long getCurrentPeriod() { - return (mClock.getElapsedSinceBootMillis() - mStartTimeMillis) / mPeriodMillis; - } - - @Override - public String toString() { - return "TimedQuotaManager{" - + "mQuota=" + mQuota - + ", mPeriodMillis=" + mPeriodMillis - + ", mStartTimeMillis=" + mStartTimeMillis - + ", mLastPeriod=" + mLastPeriod - + ", mConsumedQuota=" + mConsumedQuota - + '}'; - } -} diff --git a/service/java/com/android/server/wifi/util/WifiAsyncChannel.java b/service/java/com/android/server/wifi/util/WifiAsyncChannel.java deleted file mode 100644 index 4526d68a4..000000000 --- a/service/java/com/android/server/wifi/util/WifiAsyncChannel.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import android.annotation.NonNull; -import android.os.Message; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiLog; - -/** - * This class subclasses AsyncChannel and adds logging - * to the sendMessage() API - */ -public class WifiAsyncChannel extends AsyncChannel { - private static final String LOG_TAG = "WifiAsyncChannel"; - private WifiLog mLog; - private String mTag; - /** - * AsyncChannelWithLogging constructor - */ - public WifiAsyncChannel(String serviceTag) { - mTag = LOG_TAG + "." + serviceTag; - } - - @NonNull - private WifiLog getOrInitLog() { - // Lazy initization of mLog - if (mLog == null) { - mLog = WifiInjector.getInstance().makeLog(mTag); - } - return mLog; - } - - /** - * Send a message to the destination handler. - * - * @param msg - */ - @Override - public void sendMessage(Message msg) { - getOrInitLog().trace("sendMessage message=%") - .c(msg.what) - .flush(); - super.sendMessage(msg); - } - - /** - * Reply to srcMsg - * - * @param srcMsg - * @param dstMsg - */ - @Override - public void replyToMessage(Message srcMsg, Message dstMsg) { - getOrInitLog() - .trace("replyToMessage recvdMessage=% sendingUid=% sentMessage=%") - .c(srcMsg.what) - .c(srcMsg.sendingUid) - .c(dstMsg.what) - .flush(); - super.replyToMessage(srcMsg, dstMsg); - } - - /** - * Send the Message synchronously. - * - * @param msg to send - * @return reply message or null if an error. - */ - @Override - public Message sendMessageSynchronously(Message msg) { - getOrInitLog().trace("sendMessageSynchronously.send message=%") - .c(msg.what) - .flush(); - Message replyMessage = super.sendMessageSynchronously(msg); - if (replyMessage != null) { - getOrInitLog().trace("sendMessageSynchronously.recv message=% sendingUid=%") - .c(replyMessage.what) - .c(replyMessage.sendingUid) - .flush(); - } - return replyMessage; - } - - @VisibleForTesting - public void setWifiLog(WifiLog log) { - mLog = log; - } -} diff --git a/service/java/com/android/server/wifi/util/WifiConfigStoreEncryptionUtil.java b/service/java/com/android/server/wifi/util/WifiConfigStoreEncryptionUtil.java deleted file mode 100644 index ded3450c4..000000000 --- a/service/java/com/android/server/wifi/util/WifiConfigStoreEncryptionUtil.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Process; -import android.security.keystore.AndroidKeyStoreProvider; -import android.security.keystore.KeyGenParameterSpec; -import android.security.keystore.KeyProperties; -import android.text.TextUtils; -import android.util.Log; - -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.ProviderException; -import java.security.UnrecoverableEntryException; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.KeyGenerator; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.spec.GCMParameterSpec; - -/** - * Tools to help encrypt/decrypt - */ -public class WifiConfigStoreEncryptionUtil { - private static final String TAG = "WifiConfigStoreEncryptionUtil"; - - private static final String ALIAS_SUFFIX = ".data-encryption-key"; - private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; - private static final int GCM_TAG_LENGTH = 128; - private static final int KEY_LENGTH = 256; - private static final String KEY_STORE = "AndroidKeyStore"; - - private final String mDataFileName; - - /** - * Construct a new util to help {@link com.android.server.wifi.WifiConfigStore.StoreData} - * modules to encrypt/decrypt credential data written/read from this config store file. - * - * @param dataFileName The full path of the data file. - * @throws NullPointerException When data file is empty string. - */ - public WifiConfigStoreEncryptionUtil(@NonNull String dataFileName) { - if (TextUtils.isEmpty(dataFileName)) { - throw new NullPointerException("dataFileName must not be null or the empty " - + "string"); - } - mDataFileName = dataFileName; - } - - private String getKeyAlias() { - return mDataFileName + ALIAS_SUFFIX; - } - - /** - * Encrypt the provided data blob. - * - * @param data Data blob to be encrypted. - * @return Instance of {@link EncryptedData} containing the encrypted info. - */ - public @Nullable EncryptedData encrypt(byte[] data) { - EncryptedData encryptedData = null; - try { - Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - SecretKey secretKeyReference = getOrCreateSecretKey(getKeyAlias()); - if (secretKeyReference != null) { - cipher.init(Cipher.ENCRYPT_MODE, secretKeyReference); - encryptedData = new EncryptedData(cipher.doFinal(data), cipher.getIV()); - } else { - reportException(new Exception("secretKeyReference is null."), - "secretKeyReference is null."); - } - } catch (NoSuchAlgorithmException e) { - reportException(e, "encrypt could not find the algorithm: " + CIPHER_ALGORITHM); - } catch (NoSuchPaddingException e) { - reportException(e, "encrypt had a padding exception"); - } catch (InvalidKeyException e) { - reportException(e, "encrypt received an invalid key"); - } catch (BadPaddingException e) { - reportException(e, "encrypt had a padding problem"); - } catch (IllegalBlockSizeException e) { - reportException(e, "encrypt had an illegal block size"); - } - return encryptedData; - } - - /** - * Decrypt the original data blob from the provided {@link EncryptedData}. - * - * @param encryptedData Instance of {@link EncryptedData} containing the encrypted info. - * @return Original data blob that was encrypted. - */ - public @Nullable byte[] decrypt(@NonNull EncryptedData encryptedData) { - byte[] decryptedData = null; - try { - Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, encryptedData.getIv()); - SecretKey secretKeyReference = getOrCreateSecretKey(getKeyAlias()); - if (secretKeyReference != null) { - cipher.init(Cipher.DECRYPT_MODE, secretKeyReference, spec); - decryptedData = cipher.doFinal(encryptedData.getEncryptedData()); - } - } catch (NoSuchAlgorithmException e) { - reportException(e, "decrypt could not find cipher algorithm " + CIPHER_ALGORITHM); - } catch (NoSuchPaddingException e) { - reportException(e, "decrypt could not find padding algorithm"); - } catch (IllegalBlockSizeException e) { - reportException(e, "decrypt had a illegal block size"); - } catch (BadPaddingException e) { - reportException(e, "decrypt had bad padding"); - } catch (InvalidKeyException e) { - reportException(e, "decrypt had an invalid key"); - } catch (InvalidAlgorithmParameterException e) { - reportException(e, "decrypt had an invalid algorithm parameter"); - } - return decryptedData; - } - - private SecretKey getOrCreateSecretKey(String keyAlias) { - SecretKey secretKey = null; - try { - KeyStore keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(Process.WIFI_UID); - if (keyStore.containsAlias(keyAlias)) { // The key exists in key store. Get the key. - KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore - .getEntry(keyAlias, null); - if (secretKeyEntry != null) { - secretKey = secretKeyEntry.getSecretKey(); - } else { - reportException(new Exception("keystore contains the alias and the secret key " - + "entry was null"), - "keystore contains the alias and the secret key entry was null"); - } - } else { // The key does not exist in key store. Create the key and store it. - KeyGenerator keyGenerator = KeyGenerator - .getInstance(KeyProperties.KEY_ALGORITHM_AES, KEY_STORE); - - KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(keyAlias, - KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) - .setBlockModes(KeyProperties.BLOCK_MODE_GCM) - .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) - .setKeySize(KEY_LENGTH) - .setUid(Process.WIFI_UID) - .build(); - - keyGenerator.init(keyGenParameterSpec); - secretKey = keyGenerator.generateKey(); - } - } catch (InvalidAlgorithmParameterException e) { - reportException(e, "getOrCreateSecretKey had an invalid algorithm parameter"); - } catch (KeyStoreException e) { - reportException(e, "getOrCreateSecretKey cannot find the keystore: " + KEY_STORE); - } catch (NoSuchAlgorithmException e) { - reportException(e, "getOrCreateSecretKey cannot find algorithm"); - } catch (NoSuchProviderException e) { - reportException(e, "getOrCreateSecretKey cannot find crypto provider"); - } catch (UnrecoverableEntryException e) { - reportException(e, "getOrCreateSecretKey had an unrecoverable entry exception."); - } catch (ProviderException e) { - reportException(e, "getOrCreateSecretKey had a provider exception."); - } - return secretKey; - } - - private void reportException(Exception exception, String error) { - Log.wtf(TAG, "An irrecoverable key store error was encountered: " + error, exception); - } - -} diff --git a/service/java/com/android/server/wifi/util/WifiHandler.java b/service/java/com/android/server/wifi/util/WifiHandler.java deleted file mode 100644 index 51802b138..000000000 --- a/service/java/com/android/server/wifi/util/WifiHandler.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import android.annotation.NonNull; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiLog; - -/** - * This class subclasses Handler to log incoming messages - */ -public class WifiHandler extends Handler { - private static final String LOG_TAG = "WifiHandler"; - private WifiLog mLog; - private String mTag; - - public WifiHandler(String tag, Looper looper) { - super(looper); - mTag = LOG_TAG + "." + tag; - } - - @NonNull - private WifiLog getOrInitLog() { - // Lazy initialization of mLog - if (mLog == null) { - mLog = WifiInjector.getInstance().makeLog(mTag); - } - return mLog; - } - - @Override - public void handleMessage(Message msg) { - getOrInitLog().trace("Received message=% sendingUid=%") - .c(msg.what) - .c(msg.sendingUid) - .flush(); - } - - /** - * @hide - */ - @VisibleForTesting - public void setWifiLog(WifiLog wifiLog) { - // TODO WifiInjector should be passed as a variable in the constructor - // b/33308811 tracks removing lazy initializations of mLog - mLog = wifiLog; - } -} diff --git a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java deleted file mode 100644 index ebe7ea481..000000000 --- a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import android.Manifest; -import android.annotation.Nullable; -import android.app.AppOpsManager; -import android.app.admin.DevicePolicyManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.net.NetworkStack; -import android.os.Binder; -import android.os.Build; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.util.EventLog; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; -import com.android.server.wifi.FrameworkFacade; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiLog; - -/** - * A wifi permissions utility assessing permissions - * for getting scan results by a package. - */ -public class WifiPermissionsUtil { - private static final String TAG = "WifiPermissionsUtil"; - private final WifiPermissionsWrapper mWifiPermissionsWrapper; - private final Context mContext; - private final FrameworkFacade mFrameworkFacade; - private final AppOpsManager mAppOps; - private final UserManager mUserManager; - private final Object mLock = new Object(); - @GuardedBy("mLock") - private LocationManager mLocationManager; - private WifiLog mLog; - - public WifiPermissionsUtil(WifiPermissionsWrapper wifiPermissionsWrapper, - Context context, UserManager userManager, WifiInjector wifiInjector) { - mWifiPermissionsWrapper = wifiPermissionsWrapper; - mContext = context; - mFrameworkFacade = wifiInjector.getFrameworkFacade(); - mUserManager = userManager; - mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); - mLog = wifiInjector.makeLog(TAG); - } - - /** - * Checks if the app has the permission to override Wi-Fi network configuration or not. - * - * @param uid uid of the app. - * @return true if the app does have the permission, false otherwise. - */ - public boolean checkConfigOverridePermission(int uid) { - int permission = mWifiPermissionsWrapper.getOverrideWifiConfigPermission(uid); - return permission == PackageManager.PERMISSION_GRANTED; - } - - /** - * Check and enforce Coarse or Fine Location permission (depending on target SDK). - * - * @param pkgName PackageName of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - */ - public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid) { - if (!checkCallersLocationPermission(pkgName, featureId, - uid, /* coarseForTargetSdkLessThanQ */ true, null)) { - throw new SecurityException( - "UID " + uid + " does not have Coarse/Fine Location permission"); - } - } - - /** - * Checks whether than the target SDK of the package is less than the specified version code. - */ - public boolean isTargetSdkLessThan(String packageName, int versionCode, int callingUid) { - long ident = Binder.clearCallingIdentity(); - try { - if (mContext.getPackageManager().getApplicationInfoAsUser( - packageName, 0, - UserHandle.getUserHandleForUid(callingUid)).targetSdkVersion - < versionCode) { - return true; - } - } catch (PackageManager.NameNotFoundException e) { - // In case of exception, assume unknown app (more strict checking) - // Note: This case will never happen since checkPackage is - // called to verify validity before checking App's version. - } finally { - Binder.restoreCallingIdentity(ident); - } - return false; - } - - /** - * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION or - * android.Manifest.permission.ACCESS_FINE_LOCATION (depending on config/targetSDK leve) - * and a corresponding app op is allowed for this package and uid. - * - * @param pkgName PackageName of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param coarseForTargetSdkLessThanQ If true and the targetSDK < Q then will check for COARSE - * else (false or targetSDK >= Q) then will check for FINE - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - */ - public boolean checkCallersLocationPermission(String pkgName, @Nullable String featureId, - int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message) { - boolean isTargetSdkLessThanQ = isTargetSdkLessThan(pkgName, Build.VERSION_CODES.Q, uid); - - String permissionType = Manifest.permission.ACCESS_FINE_LOCATION; - if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { - // Having FINE permission implies having COARSE permission (but not the reverse) - permissionType = Manifest.permission.ACCESS_COARSE_LOCATION; - } - if (mWifiPermissionsWrapper.getUidPermission(permissionType, uid) - == PackageManager.PERMISSION_DENIED) { - return false; - } - - // Always checking FINE - even if will not enforce. This will record the request for FINE - // so that a location request by the app is surfaced to the user. - boolean isFineLocationAllowed = noteAppOpAllowed( - AppOpsManager.OPSTR_FINE_LOCATION, pkgName, featureId, uid, message); - if (isFineLocationAllowed) { - return true; - } - if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { - return noteAppOpAllowed(AppOpsManager.OPSTR_COARSE_LOCATION, pkgName, featureId, uid, - message); - } - return false; - } - - /** - * Check and enforce Fine Location permission. - * - * @param pkgName PackageName of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - */ - public void enforceFineLocationPermission(String pkgName, @Nullable String featureId, - int uid) { - if (!checkCallersFineLocationPermission(pkgName, featureId, uid, false)) { - throw new SecurityException("UID " + uid + " does not have Fine Location permission"); - } - } - - /** - * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION - * and a corresponding app op is allowed for this package and uid. - * - * @param pkgName PackageName of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param hideFromAppOps True to invoke {@link AppOpsManager#checkOp(int, int, String)}, false - * to invoke {@link AppOpsManager#noteOp(String, int, String, String, - * String)}. - */ - private boolean checkCallersFineLocationPermission(String pkgName, @Nullable String featureId, - int uid, boolean hideFromAppOps) { - // Having FINE permission implies having COARSE permission (but not the reverse) - if (mWifiPermissionsWrapper.getUidPermission( - Manifest.permission.ACCESS_FINE_LOCATION, uid) - == PackageManager.PERMISSION_DENIED) { - return false; - } - if (hideFromAppOps) { - // Don't note the operation, just check if the app is allowed to perform the operation. - return checkAppOpAllowed(AppOpsManager.OPSTR_FINE_LOCATION, pkgName, uid); - } else { - return noteAppOpAllowed(AppOpsManager.OPSTR_FINE_LOCATION, pkgName, featureId, uid, - null); - } - } - - /** - * Checks that calling process has android.Manifest.permission.LOCATION_HARDWARE. - * - * @param uid The uid of the package - */ - private boolean checkCallersHardwareLocationPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission(Manifest.permission.LOCATION_HARDWARE, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * API to determine if the caller has permissions to get scan results. Throws SecurityException - * if the caller has no permission. - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - */ - public void enforceCanAccessScanResults(String pkgName, @Nullable String featureId, int uid, - @Nullable String message) - throws SecurityException { - checkPackage(uid, pkgName); - - // Apps with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD, NETWORK_MANAGED_PROVISIONING, - // NETWORK_STACK & MAINLINE_NETWORK_STACK, RADIO_SCAN_WITHOUT_LOCATION are granted a bypass. - if (checkNetworkSettingsPermission(uid) || checkNetworkSetupWizardPermission(uid) - || checkNetworkManagedProvisioningPermission(uid) - || checkNetworkStackPermission(uid) || checkMainlineNetworkStackPermission(uid) - || checkScanWithoutLocationPermission(uid)) { - return; - } - - // Location mode must be enabled - if (!isLocationModeEnabled()) { - // Location mode is disabled, scan results cannot be returned - throw new SecurityException("Location mode is disabled for the device"); - } - - // Check if the calling Uid has CAN_READ_PEER_MAC_ADDRESS permission. - boolean canCallingUidAccessLocation = checkCallerHasPeersMacAddressPermission(uid); - // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to - // location information. - boolean canAppPackageUseLocation = checkCallersLocationPermission(pkgName, featureId, - uid, /* coarseForTargetSdkLessThanQ */ true, message); - - // If neither caller or app has location access, there is no need to check - // any other permissions. Deny access to scan results. - if (!canCallingUidAccessLocation && !canAppPackageUseLocation) { - throw new SecurityException("UID " + uid + " has no location permission"); - } - // Check if Wifi Scan request is an operation allowed for this App. - if (!isScanAllowedbyApps(pkgName, featureId, uid)) { - throw new SecurityException("UID " + uid + " has no wifi scan permission"); - } - // If the User or profile is current, permission is granted - // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission. - if (!isCurrentProfile(uid) && !checkInteractAcrossUsersFull(uid)) { - throw new SecurityException("UID " + uid + " profile not permitted"); - } - } - - /** - * API to determine if the caller has permissions to get scan results. Throws SecurityException - * if the caller has no permission. - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param ignoreLocationSettings Whether this request can bypass location settings. - * @param hideFromAppOps Whether to note the request in app-ops logging or not. - * - * Note: This is to be used for checking permissions in the internal WifiScanner API surface - * for requests coming from system apps. - */ - public void enforceCanAccessScanResultsForWifiScanner(String pkgName, - @Nullable String featureId, int uid, boolean ignoreLocationSettings, - boolean hideFromAppOps) throws SecurityException { - checkPackage(uid, pkgName); - - // Location mode must be enabled - if (!isLocationModeEnabled()) { - if (ignoreLocationSettings) { - mLog.w("Request from " + pkgName + " violated location settings"); - } else { - // Location mode is disabled, scan results cannot be returned - throw new SecurityException("Location mode is disabled for the device"); - } - } - // LocationAccess by App: caller must have fine & hardware Location permission to have - // access to location information. - if (!checkCallersFineLocationPermission(pkgName, featureId, uid, hideFromAppOps) - || !checkCallersHardwareLocationPermission(uid)) { - throw new SecurityException("UID " + uid + " has no location permission"); - } - // Check if Wifi Scan request is an operation allowed for this App. - if (!isScanAllowedbyApps(pkgName, featureId, uid)) { - throw new SecurityException("UID " + uid + " has no wifi scan permission"); - } - } - - /** - * - * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION - * and a corresponding app op is allowed for this package and uid - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param needLocationModeEnabled indicates location mode must be enabled. - * - * @return true if caller has permission, false otherwise - */ - public boolean checkCanAccessWifiDirect(String pkgName, @Nullable String featureId, int uid, - boolean needLocationModeEnabled) { - try { - checkPackage(uid, pkgName); - } catch (SecurityException se) { - Log.e(TAG, "Package check exception - " + se); - return false; - } - - // Apps with NETWORK_SETTINGS are granted a bypass. - if (checkNetworkSettingsPermission(uid)) { - return true; - } - - // Location mode must be enabled if needed. - if (needLocationModeEnabled && !isLocationModeEnabled()) { - Log.e(TAG, "Location mode is disabled for the device"); - return false; - } - - // LocationAccess by App: caller must have Fine Location permission to have access to - // location information. - if (!checkCallersLocationPermission(pkgName, featureId, uid, - /* coarseForTargetSdkLessThanQ */ false, null)) { - Log.e(TAG, "UID " + uid + " has no location permission"); - return false; - } - return true; - } - - /** - * API to check to validate if a package name belongs to a UID. Throws SecurityException - * if pkgName does not belongs to a UID - * - * @param pkgName package name of the application requesting access - * @param uid The uid of the package - * - */ - public void checkPackage(int uid, String pkgName) throws SecurityException { - if (pkgName == null) { - throw new SecurityException("Checking UID " + uid + " but Package Name is Null"); - } - mAppOps.checkPackage(uid, pkgName); - } - - /** - * Returns true if the caller holds PEERS_MAC_ADDRESS permission. - */ - private boolean checkCallerHasPeersMacAddressPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.PEERS_MAC_ADDRESS, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if Wifi scan operation is allowed for this caller - * and package. - */ - private boolean isScanAllowedbyApps(String pkgName, @Nullable String featureId, int uid) { - return noteAppOpAllowed(AppOpsManager.OPSTR_WIFI_SCAN, pkgName, featureId, uid, null); - } - - /** - * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL. - */ - private boolean checkInteractAcrossUsersFull(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the calling user is the current one or a profile of the - * current user. - */ - private boolean isCurrentProfile(int uid) { - UserHandle currentUser = UserHandle.of(mWifiPermissionsWrapper.getCurrentUser()); - UserHandle callingUser = UserHandle.getUserHandleForUid(uid); - return currentUser.equals(callingUser) - || mUserManager.isSameProfileGroup(currentUser, callingUser); - } - - private boolean noteAppOpAllowed(String op, String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - return mAppOps.noteOp(op, uid, pkgName, featureId, message) == AppOpsManager.MODE_ALLOWED; - } - - private boolean checkAppOpAllowed(String op, String pkgName, int uid) { - return mAppOps.unsafeCheckOp(op, uid, pkgName) == AppOpsManager.MODE_ALLOWED; - } - - private boolean retrieveLocationManagerIfNecessary() { - // This is going to be accessed by multiple threads. - synchronized (mLock) { - if (mLocationManager == null) { - mLocationManager = - (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); - } - } - return mLocationManager != null; - } - - /** - * Retrieves a handle to LocationManager (if not already done) and check if location is enabled. - */ - public boolean isLocationModeEnabled() { - if (!retrieveLocationManagerIfNecessary()) return false; - try { - return mLocationManager.isLocationEnabledForUser(UserHandle.of( - mWifiPermissionsWrapper.getCurrentUser())); - } catch (Exception e) { - Log.e(TAG, "Failure to get location mode via API, falling back to settings", e); - return mFrameworkFacade.getIntegerSetting( - mContext, Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) - == Settings.Secure.LOCATION_MODE_ON; - } - } - - /** - * Returns true if the |uid| holds NETWORK_SETTINGS permission. - */ - public boolean checkNetworkSettingsPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_SETTINGS, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds RADIO_SCAN_WITHOUT_LOCATION permission. - */ - public boolean checkScanWithoutLocationPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.RADIO_SCAN_WITHOUT_LOCATION, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds LOCAL_MAC_ADDRESS permission. - */ - public boolean checkLocalMacAddressPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.LOCAL_MAC_ADDRESS, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_SETUP_WIZARD permission. - */ - public boolean checkNetworkSetupWizardPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_SETUP_WIZARD, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_STACK permission. - */ - public boolean checkNetworkStackPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_STACK, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds MAINLINE_NETWORK_STACK permission. - */ - public boolean checkMainlineNetworkStackPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_MANAGED_PROVISIONING permission. - */ - public boolean checkNetworkManagedProvisioningPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_CARRIER_PROVISIONING permission. - */ - public boolean checkNetworkCarrierProvisioningPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_CARRIER_PROVISIONING, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds READ_WIFI_CREDENTIAL permission. - */ - public boolean checkReadWifiCredentialPermission(int uid) { - return mWifiPermissionsWrapper.getUidPermission( - android.Manifest.permission.READ_WIFI_CREDENTIAL, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |callingUid|/\callingPackage| holds SYSTEM_ALERT_WINDOW permission. - */ - public boolean checkSystemAlertWindowPermission(int callingUid, String callingPackage) { - final int mode = mAppOps.noteOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, callingUid, - callingPackage, null, null); - if (mode == AppOpsManager.MODE_DEFAULT) { - return mWifiPermissionsWrapper.getUidPermission( - Manifest.permission.SYSTEM_ALERT_WINDOW, callingUid) - == PackageManager.PERMISSION_GRANTED; - } - return mode == AppOpsManager.MODE_ALLOWED; - } - - private static DevicePolicyManager retrieveDevicePolicyManagerFromContext(Context context) { - DevicePolicyManager devicePolicyManager = - context.getSystemService(DevicePolicyManager.class); - if (devicePolicyManager == null - && context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_DEVICE_ADMIN)) { - Log.w(TAG, "Error retrieving DPM service"); - } - return devicePolicyManager; - } - - private DevicePolicyManager retrieveDevicePolicyManagerFromUserContext(int uid) { - Context userContext = null; - try { - userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0, - UserHandle.getUserHandleForUid(uid)); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Unknown package name"); - return null; - } - if (userContext == null) { - Log.e(TAG, "Unable to retrieve user context for " + uid); - return null; - } - return retrieveDevicePolicyManagerFromContext(userContext); - } - - /** - * Returns true if the |callingUid|/\callingPackage| is the device owner. - */ - public boolean isDeviceOwner(int uid, @Nullable String packageName) { - // Cannot determine if the app is DO/PO if packageName is null. So, will return false to be - // safe. - if (packageName == null) { - Log.e(TAG, "isDeviceOwner: packageName is null, returning false"); - return false; - } - DevicePolicyManager devicePolicyManager = - retrieveDevicePolicyManagerFromContext(mContext); - if (devicePolicyManager == null) return false; - long ident = Binder.clearCallingIdentity(); - UserHandle deviceOwnerUser = null; - ComponentName deviceOwnerComponent = null; - try { - deviceOwnerUser = devicePolicyManager.getDeviceOwnerUser(); - deviceOwnerComponent = devicePolicyManager.getDeviceOwnerComponentOnAnyUser(); - } finally { - Binder.restoreCallingIdentity(ident); - } - // no device owner - if (deviceOwnerUser == null || deviceOwnerComponent == null) return false; - return deviceOwnerUser.equals(UserHandle.getUserHandleForUid(uid)) - && deviceOwnerComponent.getPackageName().equals(packageName); - } - - /** - * Returns true if the |callingUid|/\callingPackage| is the profile owner. - */ - public boolean isProfileOwner(int uid, @Nullable String packageName) { - // Cannot determine if the app is DO/PO if packageName is null. So, will return false to be - // safe. - if (packageName == null) { - Log.e(TAG, "isProfileOwner: packageName is null, returning false"); - return false; - } - DevicePolicyManager devicePolicyManager = - retrieveDevicePolicyManagerFromUserContext(uid); - if (devicePolicyManager == null) return false; - return devicePolicyManager.isProfileOwnerApp(packageName); - } - - /** - * Check if the given UID belongs to the current foreground user. This is - * used to prevent apps running in background users from modifying network - * configurations. - * <p> - * UIDs belonging to system internals (such as SystemUI) are always allowed, - * since they always run as {@link UserHandle#USER_SYSTEM}. - * - * @param uid uid of the app. - * @return true if the given UID belongs to the current foreground user, - * otherwise false. - */ - public boolean doesUidBelongToCurrentUser(int uid) { - if (uid == android.os.Process.SYSTEM_UID - // UIDs with the NETWORK_SETTINGS permission are always allowed since they are - // acting on behalf of the user. - || checkNetworkSettingsPermission(uid)) { - return true; - } - boolean isCurrentProfile = isCurrentProfile(uid); - if (!isCurrentProfile) { - // Fix for b/174749461 - EventLog.writeEvent(0x534e4554, "174749461", -1, - "Non foreground user trying to modify wifi configuration"); - } - return isCurrentProfile; - } -} diff --git a/service/java/com/android/server/wifi/util/WifiPermissionsWrapper.java b/service/java/com/android/server/wifi/util/WifiPermissionsWrapper.java deleted file mode 100644 index 52ea1c0f1..000000000 --- a/service/java/com/android/server/wifi/util/WifiPermissionsWrapper.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import android.Manifest; -import android.app.ActivityManager; -import android.content.Context; - -/** - * A wifi permissions dependency class to wrap around external - * calls to static methods that enable testing. - */ -public class WifiPermissionsWrapper { - private static final String TAG = "WifiPermissionsWrapper"; - private final Context mContext; - - public WifiPermissionsWrapper(Context context) { - mContext = context; - } - - public int getCurrentUser() { - return ActivityManager.getCurrentUser(); - } - - /** - * Determine if a UID has a permission. - * @param permissionType permission string - * @param uid to get permission for - * @return Permissions setting - */ - public int getUidPermission(String permissionType, int uid) { - // We don't care about pid, pass in -1 - return mContext.checkPermission(permissionType, -1, uid); - } - - /** - * Determines if the caller has the override wifi config permission. - * - * @param uid to check the permission for - * @return int representation of success or denied - */ - public int getOverrideWifiConfigPermission(int uid) { - return getUidPermission(android.Manifest.permission.OVERRIDE_WIFI_CONFIG, uid); - } - - /** - * Determines if the caller has local mac address permission. - * - * @param uid to check the permission for - * @return int representation of success or denied - */ - public int getLocalMacAddressPermission(int uid) { - return getUidPermission(Manifest.permission.LOCAL_MAC_ADDRESS, uid); - } -} diff --git a/service/java/com/android/server/wifi/util/WorkSourceUtil.java b/service/java/com/android/server/wifi/util/WorkSourceUtil.java deleted file mode 100644 index 54852fb8a..000000000 --- a/service/java/com/android/server/wifi/util/WorkSourceUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.util; - -import android.os.WorkSource; -import android.util.Pair; - -import java.util.ArrayList; -import java.util.List; - -/** - * Class for general helper methods for WorkSource operations. - */ -public class WorkSourceUtil { - - /** - * Retrieve an array of uids & tags within the worksource. - */ - public static Pair<int[], String[]> getUidsAndTagsForWs(WorkSource ws) { - List<Integer> uids = new ArrayList<>(); - List<String> tags = new ArrayList<>(); - - for (int i = 0; i < ws.size(); i++) { - uids.add(ws.getUid(i)); - tags.add(ws.getPackageName(i)); - } - - final List<WorkSource.WorkChain> workChains = ws.getWorkChains(); - if (workChains != null) { - for (int i = 0; i < workChains.size(); ++i) { - final WorkSource.WorkChain workChain = workChains.get(i); - uids.add(workChain.getAttributionUid()); - tags.add(workChain.getAttributionTag()); - } - } - return Pair.create( - uids.stream().mapToInt(Integer::intValue).toArray(), - tags.toArray(new String[0])); - } - - -} diff --git a/service/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java deleted file mode 100644 index eb204e73d..000000000 --- a/service/java/com/android/server/wifi/util/XmlUtil.java +++ /dev/null @@ -1,1448 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.InetAddresses; -import android.net.IpConfiguration; -import android.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; -import android.net.LinkAddress; -import android.net.MacAddress; -import android.net.ProxyInfo; -import android.net.RouteInfo; -import android.net.StaticIpConfiguration; -import android.net.Uri; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; -import android.net.wifi.WifiEnterpriseConfig; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -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.Locale; - -/** - * Utils for manipulating XML data. This is essentially a wrapper over XmlUtils provided by core. - * The utility provides methods to write/parse section headers and write/parse values. - * This utility is designed for formatting the XML into the following format: - * <Document Header> - * <Section 1 Header> - * <Value 1> - * <Value 2> - * ... - * <Sub Section 1 Header> - * <Value 1> - * <Value 2> - * ... - * </Sub Section 1 Header> - * </Section 1 Header> - * </Document Header> - * - * Note: These utility methods are meant to be used for: - * 1. Backup/restore wifi network data to/from cloud. - * 2. Persisting wifi network data to/from disk. - */ -public class XmlUtil { - private static final String TAG = "WifiXmlUtil"; - - /** - * Ensure that the XML stream is at a start tag or the end of document. - * - * @throws XmlPullParserException if parsing errors occur. - */ - private static void gotoStartTag(XmlPullParser in) - throws XmlPullParserException, IOException { - int type = in.getEventType(); - while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { - type = in.next(); - } - } - - /** - * Ensure that the XML stream is at an end tag or the end of document. - * - * @throws XmlPullParserException if parsing errors occur. - */ - private static void gotoEndTag(XmlPullParser in) - throws XmlPullParserException, IOException { - int type = in.getEventType(); - while (type != XmlPullParser.END_TAG && type != XmlPullParser.END_DOCUMENT) { - type = in.next(); - } - } - - /** - * Start processing the XML stream at the document header. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param headerName expected name for the start tag. - * @throws XmlPullParserException if parsing errors occur. - */ - public static void gotoDocumentStart(XmlPullParser in, String headerName) - throws XmlPullParserException, IOException { - XmlUtilHelper.beginDocument(in, headerName); - } - - /** - * Move the XML stream to the next section header or indicate if there are no more sections. - * The provided outerDepth is used to find sub sections within that depth. - * - * Use this to move across sections if the ordering of sections are variable. The returned name - * can be used to decide what section is next. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param headerName An array of one string, used to return the name of the next section. - * @param outerDepth Find section within this depth. - * @return {@code true} if a next section is found, {@code false} if there are no more sections. - * @throws XmlPullParserException if parsing errors occur. - */ - public static boolean gotoNextSectionOrEnd( - XmlPullParser in, String[] headerName, int outerDepth) - throws XmlPullParserException, IOException { - if (XmlUtilHelper.nextElementWithin(in, outerDepth)) { - headerName[0] = in.getName(); - return true; - } - return false; - } - - /** - * Move the XML stream to the next section header or indicate if there are no more sections. - * If a section, exists ensure that the name matches the provided name. - * The provided outerDepth is used to find sub sections within that depth. - * - * Use this to move across repeated sections until the end. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param expectedName expected name for the section header. - * @param outerDepth Find section within this depth. - * @return {@code true} if a next section is found, {@code false} if there are no more sections. - * @throws XmlPullParserException if the section header name does not match |expectedName|, - * or if parsing errors occur. - */ - public static boolean gotoNextSectionWithNameOrEnd( - XmlPullParser in, String expectedName, int outerDepth) - throws XmlPullParserException, IOException { - String[] headerName = new String[1]; - if (gotoNextSectionOrEnd(in, headerName, outerDepth)) { - if (headerName[0].equals(expectedName)) { - return true; - } - throw new XmlPullParserException( - "Next section name does not match expected name: " + expectedName); - } - return false; - } - - /** - * Move the XML stream to the next section header and ensure that the name matches the provided - * name. - * The provided outerDepth is used to find sub sections within that depth. - * - * Use this to move across sections if the ordering of sections are fixed. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param expectedName expected name for the section header. - * @param outerDepth Find section within this depth. - * @throws XmlPullParserException if the section header name does not match |expectedName|, - * there are no more sections or if parsing errors occur. - */ - public static void gotoNextSectionWithName( - XmlPullParser in, String expectedName, int outerDepth) - throws XmlPullParserException, IOException { - if (!gotoNextSectionWithNameOrEnd(in, expectedName, outerDepth)) { - throw new XmlPullParserException("Section not found. Expected: " + expectedName); - } - } - - /** - * Checks if the stream is at the end of a section of values. This moves the stream to next tag - * and checks if it finds an end tag at the specified depth. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param sectionDepth depth of the start tag of this section. Used to match the end tag. - * @return {@code true} if a end tag at the provided depth is found, {@code false} otherwise - * @throws XmlPullParserException if parsing errors occur. - */ - public static boolean isNextSectionEnd(XmlPullParser in, int sectionDepth) - throws XmlPullParserException, IOException { - return !XmlUtilHelper.nextElementWithin(in, sectionDepth); - } - - /** - * Read the current value in the XML stream using core XmlUtils and stores the retrieved - * value name in the string provided. This method reads the value contained in current start - * tag. - * Note: Because there could be genuine null values being read from the XML, this method raises - * an exception to indicate errors. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param valueName An array of one string, used to return the name attribute - * of the value's tag. - * @return value retrieved from the XML stream. - * @throws XmlPullParserException if parsing errors occur. - */ - public static Object readCurrentValue(XmlPullParser in, String[] valueName) - throws XmlPullParserException, IOException { - Object value = XmlUtilHelper.readValueXml(in, valueName); - // XmlUtils.readValue does not always move the stream to the end of the tag. So, move - // it to the end tag before returning from here. - gotoEndTag(in); - return value; - } - - /** - * Read the next value in the XML stream using core XmlUtils and ensure that it matches the - * provided name. This method moves the stream to the next start tag and reads the value - * contained in it. - * Note: Because there could be genuine null values being read from the XML, this method raises - * an exception to indicate errors. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @return value retrieved from the XML stream. - * @throws XmlPullParserException if the value read does not match |expectedName|, - * or if parsing errors occur. - */ - public static Object readNextValueWithName(XmlPullParser in, String expectedName) - throws XmlPullParserException, IOException { - String[] valueName = new String[1]; - XmlUtilHelper.nextElement(in); - Object value = readCurrentValue(in, valueName); - if (valueName[0].equals(expectedName)) { - return value; - } - throw new XmlPullParserException( - "Value not found. Expected: " + expectedName + ", but got: " + valueName[0]); - } - - /** - * Write the XML document start with the provided document header name. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param headerName name for the start tag. - */ - public static void writeDocumentStart(XmlSerializer out, String headerName) - throws IOException { - out.startDocument(null, true); - out.startTag(null, headerName); - } - - /** - * Write the XML document end with the provided document header name. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param headerName name for the end tag. - */ - public static void writeDocumentEnd(XmlSerializer out, String headerName) - throws IOException { - out.endTag(null, headerName); - out.endDocument(); - } - - /** - * Write a section start header tag with the provided section name. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param headerName name for the start tag. - */ - public static void writeNextSectionStart(XmlSerializer out, String headerName) - throws IOException { - out.startTag(null, headerName); - } - - /** - * Write a section end header tag with the provided section name. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param headerName name for the end tag. - */ - public static void writeNextSectionEnd(XmlSerializer out, String headerName) - throws IOException { - out.endTag(null, headerName); - } - - /** - * Write the value with the provided name in the XML stream using core XmlUtils. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param name name of the value. - * @param value value to be written. - */ - public static void writeNextValue(XmlSerializer out, String name, Object value) - throws XmlPullParserException, IOException { - XmlUtilHelper.writeValueXml(value, name, out); - } - - /** - * Utility class to serialize and deserialize {@link WifiConfiguration} object to XML & - * vice versa. - * This is used by both {@link com.android.server.wifi.WifiConfigStore} & - * {@link com.android.server.wifi.WifiBackupRestore} modules. - * The |writeConfigurationToXml| has 2 versions, one for backup and one for config store. - * There is only 1 version of |parseXmlToConfiguration| for both backup & config store. - * The parse method is written so that any element added/deleted in future revisions can - * be easily handled. - */ - public static class WifiConfigurationXmlUtil { - /** - * List of XML tags corresponding to WifiConfiguration object elements. - */ - public static final String XML_TAG_SSID = "SSID"; - public static final String XML_TAG_BSSID = "BSSID"; - public static final String XML_TAG_CONFIG_KEY = "ConfigKey"; - public static final String XML_TAG_PRE_SHARED_KEY = "PreSharedKey"; - public static final String XML_TAG_WEP_KEYS = "WEPKeys"; - public static final String XML_TAG_WEP_TX_KEY_INDEX = "WEPTxKeyIndex"; - public static final String XML_TAG_HIDDEN_SSID = "HiddenSSID"; - public static final String XML_TAG_REQUIRE_PMF = "RequirePMF"; - public static final String XML_TAG_ALLOWED_KEY_MGMT = "AllowedKeyMgmt"; - public static final String XML_TAG_ALLOWED_PROTOCOLS = "AllowedProtocols"; - public static final String XML_TAG_ALLOWED_AUTH_ALGOS = "AllowedAuthAlgos"; - public static final String XML_TAG_ALLOWED_GROUP_CIPHERS = "AllowedGroupCiphers"; - public static final String XML_TAG_ALLOWED_PAIRWISE_CIPHERS = "AllowedPairwiseCiphers"; - public static final String XML_TAG_ALLOWED_GROUP_MGMT_CIPHERS = "AllowedGroupMgmtCiphers"; - public static final String XML_TAG_ALLOWED_SUITE_B_CIPHERS = "AllowedSuiteBCiphers"; - public static final String XML_TAG_SHARED = "Shared"; - public static final String XML_TAG_STATUS = "Status"; - public static final String XML_TAG_FQDN = "FQDN"; - public static final String XML_TAG_PROVIDER_FRIENDLY_NAME = "ProviderFriendlyName"; - public static final String XML_TAG_LINKED_NETWORKS_LIST = "LinkedNetworksList"; - public static final String XML_TAG_DEFAULT_GW_MAC_ADDRESS = "DefaultGwMacAddress"; - public static final String XML_TAG_VALIDATED_INTERNET_ACCESS = "ValidatedInternetAccess"; - public static final String XML_TAG_NO_INTERNET_ACCESS_EXPECTED = "NoInternetAccessExpected"; - public static final String XML_TAG_METERED_HINT = "MeteredHint"; - public static final String XML_TAG_METERED_OVERRIDE = "MeteredOverride"; - public static final String XML_TAG_USE_EXTERNAL_SCORES = "UseExternalScores"; - public static final String XML_TAG_CREATOR_UID = "CreatorUid"; - public static final String XML_TAG_CREATOR_NAME = "CreatorName"; - public static final String XML_TAG_LAST_UPDATE_UID = "LastUpdateUid"; - public static final String XML_TAG_LAST_UPDATE_NAME = "LastUpdateName"; - public static final String XML_TAG_LAST_CONNECT_UID = "LastConnectUid"; - public static final String XML_TAG_IS_LEGACY_PASSPOINT_CONFIG = "IsLegacyPasspointConfig"; - public static final String XML_TAG_ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs"; - public static final String XML_TAG_RANDOMIZED_MAC_ADDRESS = "RandomizedMacAddress"; - public static final String XML_TAG_MAC_RANDOMIZATION_SETTING = "MacRandomizationSetting"; - public static final String XML_TAG_CARRIER_ID = "CarrierId"; - public static final String XML_TAG_IS_AUTO_JOIN = "AutoJoinEnabled"; - public static final String XML_TAG_IS_TRUSTED = "Trusted"; - private static final String XML_TAG_IS_MOST_RECENTLY_CONNECTED = "IsMostRecentlyConnected"; - - /** - * Write WepKeys to the XML stream. - * WepKeys array is intialized in WifiConfiguration constructor, but all of the elements - * are set to null. User may chose to set any one of the key elements in WifiConfiguration. - * XmlUtils serialization doesn't handle this array of nulls well . - * So, write empty strings if some of the keys are not initialized and null if all of - * the elements are empty. - */ - private static void writeWepKeysToXml(XmlSerializer out, String[] wepKeys) - throws XmlPullParserException, IOException { - String[] wepKeysToWrite = new String[wepKeys.length]; - boolean hasWepKey = false; - for (int i = 0; i < wepKeys.length; i++) { - if (wepKeys[i] == null) { - wepKeysToWrite[i] = new String(); - } else { - wepKeysToWrite[i] = wepKeys[i]; - hasWepKey = true; - } - } - if (hasWepKey) { - XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeysToWrite); - } else { - XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, null); - } - } - - /** - * Write preshared key to the XML stream. - * - * If encryptionUtil is null or if encryption fails for some reason, the pre-shared - * key is stored in plaintext, else the encrypted psk is stored. - */ - private static void writePreSharedKeyToXml( - XmlSerializer out, String preSharedKey, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - EncryptedData encryptedData = null; - if (encryptionUtil != null) { - if (preSharedKey != null) { - encryptedData = encryptionUtil.encrypt(preSharedKey.getBytes()); - if (encryptedData == null) { - // We silently fail encryption failures! - Log.wtf(TAG, "Encryption of preSharedKey failed"); - } - } - } - if (encryptedData != null) { - XmlUtil.writeNextSectionStart(out, XML_TAG_PRE_SHARED_KEY); - EncryptedDataXmlUtil.writeToXml(out, encryptedData); - XmlUtil.writeNextSectionEnd(out, XML_TAG_PRE_SHARED_KEY); - } else { - XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, preSharedKey); - } - } - - /** - * Write the Configuration data elements that are common for backup & config store to the - * XML stream. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param configuration WifiConfiguration object to be serialized. - * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. Backup/restore stores - * keys unencrypted. - */ - public static void writeCommonElementsToXml( - XmlSerializer out, WifiConfiguration configuration, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.getKey()); - XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID); - writePreSharedKeyToXml(out, configuration.preSharedKey, encryptionUtil); - writeWepKeysToXml(out, configuration.wepKeys); - XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex); - XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID); - XmlUtil.writeNextValue(out, XML_TAG_REQUIRE_PMF, configuration.requirePmf); - XmlUtil.writeNextValue( - out, XML_TAG_ALLOWED_KEY_MGMT, - configuration.allowedKeyManagement.toByteArray()); - XmlUtil.writeNextValue( - out, XML_TAG_ALLOWED_PROTOCOLS, - configuration.allowedProtocols.toByteArray()); - XmlUtil.writeNextValue( - out, XML_TAG_ALLOWED_AUTH_ALGOS, - configuration.allowedAuthAlgorithms.toByteArray()); - XmlUtil.writeNextValue( - out, XML_TAG_ALLOWED_GROUP_CIPHERS, - configuration.allowedGroupCiphers.toByteArray()); - XmlUtil.writeNextValue( - out, XML_TAG_ALLOWED_PAIRWISE_CIPHERS, - configuration.allowedPairwiseCiphers.toByteArray()); - XmlUtil.writeNextValue( - out, XML_TAG_ALLOWED_GROUP_MGMT_CIPHERS, - configuration.allowedGroupManagementCiphers.toByteArray()); - XmlUtil.writeNextValue( - out, XML_TAG_ALLOWED_SUITE_B_CIPHERS, - configuration.allowedSuiteBCiphers.toByteArray()); - XmlUtil.writeNextValue(out, XML_TAG_SHARED, configuration.shared); - XmlUtil.writeNextValue(out, XML_TAG_IS_AUTO_JOIN, configuration.allowAutojoin); - } - - /** - * Write the Configuration data elements for backup from the provided Configuration to the - * XML stream. - * Note: This is a subset of the elements serialized for config store. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param configuration WifiConfiguration object to be serialized. - */ - public static void writeToXmlForBackup(XmlSerializer out, WifiConfiguration configuration) - throws XmlPullParserException, IOException { - writeCommonElementsToXml(out, configuration, null); - XmlUtil.writeNextValue(out, XML_TAG_METERED_OVERRIDE, configuration.meteredOverride); - } - - /** - * Write the Configuration data elements for config store from the provided Configuration - * to the XML stream. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param configuration WifiConfiguration object to be serialized. - * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. - */ - public static void writeToXmlForConfigStore( - XmlSerializer out, WifiConfiguration configuration, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - writeCommonElementsToXml(out, configuration, encryptionUtil); - XmlUtil.writeNextValue(out, XML_TAG_IS_TRUSTED, configuration.trusted); - XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID); - XmlUtil.writeNextValue(out, XML_TAG_STATUS, configuration.status); - XmlUtil.writeNextValue(out, XML_TAG_FQDN, configuration.FQDN); - XmlUtil.writeNextValue( - out, XML_TAG_PROVIDER_FRIENDLY_NAME, configuration.providerFriendlyName); - XmlUtil.writeNextValue( - out, XML_TAG_LINKED_NETWORKS_LIST, configuration.linkedConfigurations); - XmlUtil.writeNextValue( - out, XML_TAG_DEFAULT_GW_MAC_ADDRESS, configuration.defaultGwMacAddress); - XmlUtil.writeNextValue( - out, XML_TAG_VALIDATED_INTERNET_ACCESS, configuration.validatedInternetAccess); - XmlUtil.writeNextValue( - out, XML_TAG_NO_INTERNET_ACCESS_EXPECTED, - configuration.noInternetAccessExpected); - XmlUtil.writeNextValue(out, XML_TAG_METERED_HINT, configuration.meteredHint); - XmlUtil.writeNextValue(out, XML_TAG_METERED_OVERRIDE, configuration.meteredOverride); - XmlUtil.writeNextValue( - out, XML_TAG_USE_EXTERNAL_SCORES, configuration.useExternalScores); - XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, configuration.creatorUid); - XmlUtil.writeNextValue(out, XML_TAG_CREATOR_NAME, configuration.creatorName); - XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_UID, configuration.lastUpdateUid); - XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_NAME, configuration.lastUpdateName); - XmlUtil.writeNextValue(out, XML_TAG_LAST_CONNECT_UID, configuration.lastConnectUid); - XmlUtil.writeNextValue( - out, XML_TAG_IS_LEGACY_PASSPOINT_CONFIG, - configuration.isLegacyPasspointConfig); - XmlUtil.writeNextValue( - out, XML_TAG_ROAMING_CONSORTIUM_OIS, configuration.roamingConsortiumIds); - XmlUtil.writeNextValue(out, XML_TAG_RANDOMIZED_MAC_ADDRESS, - configuration.getRandomizedMacAddress().toString()); - XmlUtil.writeNextValue(out, XML_TAG_MAC_RANDOMIZATION_SETTING, - configuration.macRandomizationSetting); - XmlUtil.writeNextValue(out, XML_TAG_CARRIER_ID, configuration.carrierId); - XmlUtil.writeNextValue(out, XML_TAG_IS_MOST_RECENTLY_CONNECTED, - configuration.isMostRecentlyConnected); - } - - /** - * Populate wepKeys array elements only if they were non-empty in the backup data. - * - * @throws XmlPullParserException if parsing errors occur. - */ - private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) - throws XmlPullParserException, IOException { - String[] wepKeysInData = (String[]) value; - if (wepKeysInData == null) { - return; - } - if (wepKeysInData.length != wepKeys.length) { - throw new XmlPullParserException( - "Invalid Wep Keys length: " + wepKeysInData.length); - } - for (int i = 0; i < wepKeys.length; i++) { - if (wepKeysInData[i].isEmpty()) { - wepKeys[i] = null; - } else { - wepKeys[i] = wepKeysInData[i]; - } - } - } - - /** - * Parses the configuration data elements from the provided XML stream to a - * WifiConfiguration object. - * Note: This is used for parsing both backup data and config store data. Looping through - * the tags make it easy to add or remove elements in the future versions if needed. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @param shouldExpectEncryptedCredentials Whether to expect encrypted credentials or not. - * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. - * @return Pair<Config key, WifiConfiguration object> if parsing is successful, - * null otherwise. - */ - public static Pair<String, WifiConfiguration> parseFromXml( - XmlPullParser in, int outerTagDepth, boolean shouldExpectEncryptedCredentials, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - WifiConfiguration configuration = new WifiConfiguration(); - String configKeyInData = null; - boolean macRandomizationSettingExists = false; - - // Loop through and parse out all the elements from the stream within this section. - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - if (in.getAttributeValue(null, "name") != null) { - // Value elements. - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_CONFIG_KEY: - configKeyInData = (String) value; - break; - case XML_TAG_SSID: - configuration.SSID = (String) value; - break; - case XML_TAG_BSSID: - configuration.BSSID = (String) value; - break; - case XML_TAG_PRE_SHARED_KEY: - configuration.preSharedKey = (String) value; - break; - case XML_TAG_WEP_KEYS: - populateWepKeysFromXmlValue(value, configuration.wepKeys); - break; - case XML_TAG_WEP_TX_KEY_INDEX: - configuration.wepTxKeyIndex = (int) value; - break; - case XML_TAG_HIDDEN_SSID: - configuration.hiddenSSID = (boolean) value; - break; - case XML_TAG_REQUIRE_PMF: - configuration.requirePmf = (boolean) value; - break; - case XML_TAG_ALLOWED_KEY_MGMT: - byte[] allowedKeyMgmt = (byte[]) value; - configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); - break; - case XML_TAG_ALLOWED_PROTOCOLS: - byte[] allowedProtocols = (byte[]) value; - configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); - break; - case XML_TAG_ALLOWED_AUTH_ALGOS: - byte[] allowedAuthAlgorithms = (byte[]) value; - configuration.allowedAuthAlgorithms = BitSet.valueOf( - allowedAuthAlgorithms); - break; - case XML_TAG_ALLOWED_GROUP_CIPHERS: - byte[] allowedGroupCiphers = (byte[]) value; - configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers); - break; - case XML_TAG_ALLOWED_PAIRWISE_CIPHERS: - byte[] allowedPairwiseCiphers = (byte[]) value; - configuration.allowedPairwiseCiphers = - BitSet.valueOf(allowedPairwiseCiphers); - break; - case XML_TAG_ALLOWED_GROUP_MGMT_CIPHERS: - byte[] allowedGroupMgmtCiphers = (byte[]) value; - configuration.allowedGroupManagementCiphers = - BitSet.valueOf(allowedGroupMgmtCiphers); - break; - case XML_TAG_ALLOWED_SUITE_B_CIPHERS: - byte[] allowedSuiteBCiphers = (byte[]) value; - configuration.allowedSuiteBCiphers = - BitSet.valueOf(allowedSuiteBCiphers); - break; - case XML_TAG_SHARED: - configuration.shared = (boolean) value; - break; - case XML_TAG_STATUS: - int status = (int) value; - // Any network which was CURRENT before reboot needs - // to be restored to ENABLED. - if (status == WifiConfiguration.Status.CURRENT) { - status = WifiConfiguration.Status.ENABLED; - } - configuration.status = status; - break; - case XML_TAG_FQDN: - configuration.FQDN = (String) value; - break; - case XML_TAG_PROVIDER_FRIENDLY_NAME: - configuration.providerFriendlyName = (String) value; - break; - case XML_TAG_LINKED_NETWORKS_LIST: - configuration.linkedConfigurations = (HashMap<String, Integer>) value; - break; - case XML_TAG_DEFAULT_GW_MAC_ADDRESS: - configuration.defaultGwMacAddress = (String) value; - break; - case XML_TAG_VALIDATED_INTERNET_ACCESS: - configuration.validatedInternetAccess = (boolean) value; - break; - case XML_TAG_NO_INTERNET_ACCESS_EXPECTED: - configuration.noInternetAccessExpected = (boolean) value; - break; - case XML_TAG_METERED_HINT: - configuration.meteredHint = (boolean) value; - break; - case XML_TAG_METERED_OVERRIDE: - configuration.meteredOverride = (int) value; - break; - case XML_TAG_USE_EXTERNAL_SCORES: - configuration.useExternalScores = (boolean) value; - break; - case XML_TAG_CREATOR_UID: - configuration.creatorUid = (int) value; - break; - case XML_TAG_CREATOR_NAME: - configuration.creatorName = (String) value; - break; - case XML_TAG_LAST_UPDATE_UID: - configuration.lastUpdateUid = (int) value; - break; - case XML_TAG_LAST_UPDATE_NAME: - configuration.lastUpdateName = (String) value; - break; - case XML_TAG_LAST_CONNECT_UID: - configuration.lastConnectUid = (int) value; - break; - case XML_TAG_IS_LEGACY_PASSPOINT_CONFIG: - configuration.isLegacyPasspointConfig = (boolean) value; - break; - case XML_TAG_ROAMING_CONSORTIUM_OIS: - configuration.roamingConsortiumIds = (long[]) value; - break; - case XML_TAG_RANDOMIZED_MAC_ADDRESS: - configuration.setRandomizedMacAddress( - MacAddress.fromString((String) value)); - break; - case XML_TAG_MAC_RANDOMIZATION_SETTING: - configuration.macRandomizationSetting = (int) value; - macRandomizationSettingExists = true; - break; - case XML_TAG_CARRIER_ID: - configuration.carrierId = (int) value; - break; - case XML_TAG_IS_AUTO_JOIN: - configuration.allowAutojoin = (boolean) value; - break; - case XML_TAG_IS_TRUSTED: - configuration.trusted = (boolean) value; - break; - case XML_TAG_IS_MOST_RECENTLY_CONNECTED: - configuration.isMostRecentlyConnected = (boolean) value; - break; - default: - Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); - break; - } - } else { - String tagName = in.getName(); - if (tagName == null) { - throw new XmlPullParserException("Unexpected null tag found"); - } - switch (tagName) { - case XML_TAG_PRE_SHARED_KEY: - if (!shouldExpectEncryptedCredentials || encryptionUtil == null) { - throw new XmlPullParserException( - "Encrypted preSharedKey section not expected"); - } - EncryptedData encryptedData = - EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); - byte[] preSharedKeyBytes = encryptionUtil.decrypt(encryptedData); - if (preSharedKeyBytes == null) { - Log.wtf(TAG, "Decryption of preSharedKey failed"); - } else { - configuration.preSharedKey = new String(preSharedKeyBytes); - } - break; - default: - Log.w(TAG, "Ignoring unknown tag found: " + tagName); - break; - } - } - } - if (!macRandomizationSettingExists) { - configuration.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - } - return Pair.create(configKeyInData, configuration); - } - } - - /** - * Utility class to serialize and deseriaize {@link IpConfiguration} object to XML & vice versa. - * This is used by both {@link com.android.server.wifi.WifiConfigStore} & - * {@link com.android.server.wifi.WifiBackupRestore} modules. - */ - public static class IpConfigurationXmlUtil { - - /** - * List of XML tags corresponding to IpConfiguration object elements. - */ - public static final String XML_TAG_IP_ASSIGNMENT = "IpAssignment"; - public static final String XML_TAG_LINK_ADDRESS = "LinkAddress"; - public static final String XML_TAG_LINK_PREFIX_LENGTH = "LinkPrefixLength"; - public static final String XML_TAG_GATEWAY_ADDRESS = "GatewayAddress"; - public static final String XML_TAG_DNS_SERVER_ADDRESSES = "DNSServers"; - public static final String XML_TAG_PROXY_SETTINGS = "ProxySettings"; - public static final String XML_TAG_PROXY_HOST = "ProxyHost"; - public static final String XML_TAG_PROXY_PORT = "ProxyPort"; - public static final String XML_TAG_PROXY_PAC_FILE = "ProxyPac"; - public static final String XML_TAG_PROXY_EXCLUSION_LIST = "ProxyExclusionList"; - - private static List<String> parseProxyExclusionListString( - @Nullable String exclusionListString) { - if (exclusionListString == null) { - return Collections.emptyList(); - } else { - return Arrays.asList(exclusionListString.toLowerCase(Locale.ROOT).split(",")); - } - } - - private static String generateProxyExclusionListString(@NonNull String[] exclusionList) { - return TextUtils.join(",", exclusionList); - } - - /** - * Write the static IP configuration data elements to XML stream. - */ - private static void writeStaticIpConfigurationToXml( - XmlSerializer out, StaticIpConfiguration staticIpConfiguration) - throws XmlPullParserException, IOException { - if (staticIpConfiguration.getIpAddress() != null) { - XmlUtil.writeNextValue( - out, XML_TAG_LINK_ADDRESS, - staticIpConfiguration.getIpAddress().getAddress().getHostAddress()); - XmlUtil.writeNextValue( - out, XML_TAG_LINK_PREFIX_LENGTH, - staticIpConfiguration.getIpAddress().getPrefixLength()); - } else { - XmlUtil.writeNextValue( - out, XML_TAG_LINK_ADDRESS, null); - XmlUtil.writeNextValue( - out, XML_TAG_LINK_PREFIX_LENGTH, null); - } - if (staticIpConfiguration.getGateway() != null) { - XmlUtil.writeNextValue( - out, XML_TAG_GATEWAY_ADDRESS, - staticIpConfiguration.getGateway().getHostAddress()); - } else { - XmlUtil.writeNextValue( - out, XML_TAG_GATEWAY_ADDRESS, null); - - } - // Create a string array of DNS server addresses - String[] dnsServers = new String[staticIpConfiguration.getDnsServers().size()]; - int dnsServerIdx = 0; - for (InetAddress inetAddr : staticIpConfiguration.getDnsServers()) { - dnsServers[dnsServerIdx++] = inetAddr.getHostAddress(); - } - XmlUtil.writeNextValue( - out, XML_TAG_DNS_SERVER_ADDRESSES, dnsServers); - } - - /** - * Write the IP configuration data elements from the provided Configuration to the XML - * stream. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param ipConfiguration IpConfiguration object to be serialized. - */ - public static void writeToXml(XmlSerializer out, IpConfiguration ipConfiguration) - throws XmlPullParserException, IOException { - // Write IP assignment settings - XmlUtil.writeNextValue(out, XML_TAG_IP_ASSIGNMENT, - ipConfiguration.getIpAssignment().toString()); - switch (ipConfiguration.getIpAssignment()) { - case STATIC: - writeStaticIpConfigurationToXml( - out, ipConfiguration.getStaticIpConfiguration()); - break; - case DHCP: - case UNASSIGNED: - break; - default: - Log.w(TAG, "Ignoring unknown ip assignment type: " - + ipConfiguration.getIpAssignment()); - break; - } - - // Write proxy settings - XmlUtil.writeNextValue( - out, XML_TAG_PROXY_SETTINGS, - ipConfiguration.getProxySettings().toString()); - switch (ipConfiguration.getProxySettings()) { - case STATIC: - XmlUtil.writeNextValue( - out, XML_TAG_PROXY_HOST, - ipConfiguration.getHttpProxy().getHost()); - XmlUtil.writeNextValue( - out, XML_TAG_PROXY_PORT, - ipConfiguration.getHttpProxy().getPort()); - XmlUtil.writeNextValue( - out, XML_TAG_PROXY_EXCLUSION_LIST, - generateProxyExclusionListString( - ipConfiguration.getHttpProxy().getExclusionList())); - break; - case PAC: - XmlUtil.writeNextValue( - out, XML_TAG_PROXY_PAC_FILE, - ipConfiguration.getHttpProxy().getPacFileUrl().toString()); - break; - case NONE: - case UNASSIGNED: - break; - default: - Log.w(TAG, "Ignoring unknown proxy settings type: " - + ipConfiguration.getProxySettings()); - break; - } - } - - /** - * Parse out the static IP configuration from the XML stream. - */ - private static StaticIpConfiguration parseStaticIpConfigurationFromXml(XmlPullParser in) - throws XmlPullParserException, IOException { - StaticIpConfiguration.Builder builder = new StaticIpConfiguration.Builder(); - - String linkAddressString = - (String) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_ADDRESS); - Integer linkPrefixLength = - (Integer) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_PREFIX_LENGTH); - if (linkAddressString != null && linkPrefixLength != null) { - LinkAddress linkAddress = new LinkAddress( - InetAddresses.parseNumericAddress(linkAddressString), - linkPrefixLength); - if (linkAddress.getAddress() instanceof Inet4Address) { - builder.setIpAddress(linkAddress); - } else { - Log.w(TAG, "Non-IPv4 address: " + linkAddress); - } - } - String gatewayAddressString = - (String) XmlUtil.readNextValueWithName(in, XML_TAG_GATEWAY_ADDRESS); - if (gatewayAddressString != null) { - InetAddress gateway = - InetAddresses.parseNumericAddress(gatewayAddressString); - RouteInfo route = new RouteInfo(null, gateway, null, RouteInfo.RTN_UNICAST); - if (route.isDefaultRoute() - && route.getDestination().getAddress() instanceof Inet4Address) { - builder.setGateway(gateway); - } else { - Log.w(TAG, "Non-IPv4 default route: " + route); - } - } - String[] dnsServerAddressesString = - (String[]) XmlUtil.readNextValueWithName(in, XML_TAG_DNS_SERVER_ADDRESSES); - if (dnsServerAddressesString != null) { - List<InetAddress> dnsServerAddresses = new ArrayList<>(); - for (String dnsServerAddressString : dnsServerAddressesString) { - InetAddress dnsServerAddress = - InetAddresses.parseNumericAddress(dnsServerAddressString); - dnsServerAddresses.add(dnsServerAddress); - } - builder.setDnsServers(dnsServerAddresses); - } - return builder.build(); - } - - /** - * Parses the IP configuration data elements from the provided XML stream to an - * IpConfiguration object. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @return IpConfiguration object if parsing is successful, null otherwise. - */ - public static IpConfiguration parseFromXml(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - IpConfiguration ipConfiguration = new IpConfiguration(); - - // Parse out the IP assignment info first. - String ipAssignmentString = - (String) XmlUtil.readNextValueWithName(in, XML_TAG_IP_ASSIGNMENT); - IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); - ipConfiguration.setIpAssignment(ipAssignment); - switch (ipAssignment) { - case STATIC: - ipConfiguration.setStaticIpConfiguration(parseStaticIpConfigurationFromXml(in)); - break; - case DHCP: - case UNASSIGNED: - break; - default: - Log.w(TAG, "Ignoring unknown ip assignment type: " + ipAssignment); - break; - } - - // Parse out the proxy settings next. - String proxySettingsString = - (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_SETTINGS); - ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); - ipConfiguration.setProxySettings(proxySettings); - switch (proxySettings) { - case STATIC: - String proxyHost = - (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_HOST); - int proxyPort = - (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PORT); - String proxyExclusionList = - (String) XmlUtil.readNextValueWithName( - in, XML_TAG_PROXY_EXCLUSION_LIST); - ipConfiguration.setHttpProxy( - ProxyInfo.buildDirectProxy( - proxyHost, proxyPort, - parseProxyExclusionListString(proxyExclusionList))); - break; - case PAC: - String proxyPacFile = - (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PAC_FILE); - ipConfiguration.setHttpProxy( - ProxyInfo.buildPacProxy(Uri.parse(proxyPacFile))); - break; - case NONE: - case UNASSIGNED: - break; - default: - Log.w(TAG, "Ignoring unknown proxy settings type: " + proxySettings); - break; - } - return ipConfiguration; - } - } - - /** - * Utility class to serialize and deseriaize {@link NetworkSelectionStatus} object to XML & - * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module. - */ - public static class NetworkSelectionStatusXmlUtil { - - /** - * List of XML tags corresponding to NetworkSelectionStatus object elements. - */ - public static final String XML_TAG_SELECTION_STATUS = "SelectionStatus"; - public static final String XML_TAG_DISABLE_REASON = "DisableReason"; - public static final String XML_TAG_CONNECT_CHOICE = "ConnectChoice"; - public static final String XML_TAG_HAS_EVER_CONNECTED = "HasEverConnected"; - - /** - * Write the NetworkSelectionStatus data elements from the provided status to the XML - * stream. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param selectionStatus NetworkSelectionStatus object to be serialized. - */ - public static void writeToXml(XmlSerializer out, NetworkSelectionStatus selectionStatus) - throws XmlPullParserException, IOException { - XmlUtil.writeNextValue( - out, XML_TAG_SELECTION_STATUS, selectionStatus.getNetworkStatusString()); - XmlUtil.writeNextValue( - out, XML_TAG_DISABLE_REASON, - selectionStatus.getNetworkSelectionDisableReasonString()); - XmlUtil.writeNextValue(out, XML_TAG_CONNECT_CHOICE, selectionStatus.getConnectChoice()); - XmlUtil.writeNextValue( - out, XML_TAG_HAS_EVER_CONNECTED, selectionStatus.hasEverConnected()); - } - - /** - * Parses the NetworkSelectionStatus data elements from the provided XML stream to a - * NetworkSelectionStatus object. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @return NetworkSelectionStatus object if parsing is successful, null otherwise. - */ - public static NetworkSelectionStatus parseFromXml(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - NetworkSelectionStatus selectionStatus = new NetworkSelectionStatus(); - String statusString = ""; - String disableReasonString = ""; - - // Loop through and parse out all the elements from the stream within this section. - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_SELECTION_STATUS: - statusString = (String) value; - break; - case XML_TAG_DISABLE_REASON: - disableReasonString = (String) value; - break; - case XML_TAG_CONNECT_CHOICE: - selectionStatus.setConnectChoice((String) value); - break; - case XML_TAG_HAS_EVER_CONNECTED: - selectionStatus.setHasEverConnected((boolean) value); - break; - default: - Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); - break; - } - } - // Now figure out the network selection status codes from |selectionStatusString| & - // |disableReasonString|. - int status = - Arrays.asList(NetworkSelectionStatus.QUALITY_NETWORK_SELECTION_STATUS) - .indexOf(statusString); - int disableReason = - NetworkSelectionStatus.getDisableReasonByString(disableReasonString); - - // If either of the above codes are invalid or if the network was temporarily disabled - // (blacklisted), restore the status as enabled. We don't want to persist blacklists - // across reboots. - if (status == -1 || disableReason == -1 || - status == NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED) { - status = NetworkSelectionStatus.NETWORK_SELECTION_ENABLED; - disableReason = NetworkSelectionStatus.DISABLED_NONE; - } - selectionStatus.setNetworkSelectionStatus(status); - selectionStatus.setNetworkSelectionDisableReason(disableReason); - return selectionStatus; - } - } - - /** - * Utility class to serialize and deseriaize {@link WifiEnterpriseConfig} object to XML & - * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module. - */ - public static class WifiEnterpriseConfigXmlUtil { - - /** - * List of XML tags corresponding to WifiEnterpriseConfig object elements. - */ - public static final String XML_TAG_IDENTITY = "Identity"; - public static final String XML_TAG_ANON_IDENTITY = "AnonIdentity"; - public static final String XML_TAG_PASSWORD = "Password"; - public static final String XML_TAG_CLIENT_CERT = "ClientCert"; - public static final String XML_TAG_CA_CERT = "CaCert"; - public static final String XML_TAG_SUBJECT_MATCH = "SubjectMatch"; - public static final String XML_TAG_ENGINE = "Engine"; - public static final String XML_TAG_ENGINE_ID = "EngineId"; - public static final String XML_TAG_PRIVATE_KEY_ID = "PrivateKeyId"; - public static final String XML_TAG_ALT_SUBJECT_MATCH = "AltSubjectMatch"; - public static final String XML_TAG_DOM_SUFFIX_MATCH = "DomSuffixMatch"; - public static final String XML_TAG_CA_PATH = "CaPath"; - public static final String XML_TAG_EAP_METHOD = "EapMethod"; - public static final String XML_TAG_PHASE2_METHOD = "Phase2Method"; - public static final String XML_TAG_PLMN = "PLMN"; - public static final String XML_TAG_REALM = "Realm"; - public static final String XML_TAG_OCSP = "Ocsp"; - public static final String XML_TAG_WAPI_CERT_SUITE = "WapiCertSuite"; - - /** - * Write password key to the XML stream. - * - * If encryptionUtil is null or if encryption fails for some reason, the password is stored - * in plaintext, else the encrypted psk is stored. - */ - private static void writePasswordToXml( - XmlSerializer out, String password, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - EncryptedData encryptedData = null; - if (encryptionUtil != null) { - if (password != null) { - encryptedData = encryptionUtil.encrypt(password.getBytes()); - if (encryptedData == null) { - // We silently fail encryption failures! - Log.wtf(TAG, "Encryption of password failed"); - } - } - } - if (encryptedData != null) { - XmlUtil.writeNextSectionStart(out, XML_TAG_PASSWORD); - EncryptedDataXmlUtil.writeToXml(out, encryptedData); - XmlUtil.writeNextSectionEnd(out, XML_TAG_PASSWORD); - } else { - XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, password); - } - } - - /** - * Write the WifiEnterpriseConfig data elements from the provided config to the XML - * stream. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param enterpriseConfig WifiEnterpriseConfig object to be serialized. - * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. - */ - public static void writeToXml(XmlSerializer out, WifiEnterpriseConfig enterpriseConfig, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - XmlUtil.writeNextValue(out, XML_TAG_IDENTITY, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_ANON_IDENTITY, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY)); - writePasswordToXml( - out, enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY), - encryptionUtil); - XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CERT, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_CA_CERT, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_SUBJECT_MATCH, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_ENGINE, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_ENGINE_ID, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_PRIVATE_KEY_ID, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_ALT_SUBJECT_MATCH, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_DOM_SUFFIX_MATCH, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_CA_PATH, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_EAP_METHOD, enterpriseConfig.getEapMethod()); - XmlUtil.writeNextValue(out, XML_TAG_PHASE2_METHOD, enterpriseConfig.getPhase2Method()); - XmlUtil.writeNextValue(out, XML_TAG_PLMN, enterpriseConfig.getPlmn()); - XmlUtil.writeNextValue(out, XML_TAG_REALM, enterpriseConfig.getRealm()); - XmlUtil.writeNextValue(out, XML_TAG_OCSP, enterpriseConfig.getOcsp()); - XmlUtil.writeNextValue(out, - XML_TAG_WAPI_CERT_SUITE, enterpriseConfig.getWapiCertSuite()); - } - - /** - * Parses the data elements from the provided XML stream to a WifiEnterpriseConfig object. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @param shouldExpectEncryptedCredentials Whether to expect encrypted credentials or not. - * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. - * @return WifiEnterpriseConfig object if parsing is successful, null otherwise. - */ - public static WifiEnterpriseConfig parseFromXml(XmlPullParser in, int outerTagDepth, - boolean shouldExpectEncryptedCredentials, - @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); - - // Loop through and parse out all the elements from the stream within this section. - while (XmlUtilHelper.nextElementWithin(in, outerTagDepth)) { - if (in.getAttributeValue(null, "name") != null) { - // Value elements. - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_IDENTITY: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.IDENTITY_KEY, (String) value); - break; - case XML_TAG_ANON_IDENTITY: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.ANON_IDENTITY_KEY, (String) value); - break; - case XML_TAG_PASSWORD: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.PASSWORD_KEY, (String) value); - if (shouldExpectEncryptedCredentials - && !TextUtils.isEmpty(enterpriseConfig.getFieldValue( - WifiEnterpriseConfig.PASSWORD_KEY))) { - // Indicates that encryption of password failed when it was last - // written. - Log.e(TAG, "password value not expected"); - } - break; - case XML_TAG_CLIENT_CERT: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.CLIENT_CERT_KEY, (String) value); - break; - case XML_TAG_CA_CERT: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.CA_CERT_KEY, (String) value); - break; - case XML_TAG_SUBJECT_MATCH: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.SUBJECT_MATCH_KEY, (String) value); - break; - case XML_TAG_ENGINE: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.ENGINE_KEY, (String) value); - break; - case XML_TAG_ENGINE_ID: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.ENGINE_ID_KEY, (String) value); - break; - case XML_TAG_PRIVATE_KEY_ID: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, (String) value); - break; - case XML_TAG_ALT_SUBJECT_MATCH: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, (String) value); - break; - case XML_TAG_DOM_SUFFIX_MATCH: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, (String) value); - break; - case XML_TAG_CA_PATH: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.CA_PATH_KEY, (String) value); - break; - case XML_TAG_OCSP: - enterpriseConfig.setOcsp((int) value); - break; - case XML_TAG_EAP_METHOD: - enterpriseConfig.setEapMethod((int) value); - break; - case XML_TAG_PHASE2_METHOD: - enterpriseConfig.setPhase2Method((int) value); - break; - case XML_TAG_PLMN: - enterpriseConfig.setPlmn((String) value); - break; - case XML_TAG_REALM: - enterpriseConfig.setRealm((String) value); - break; - case XML_TAG_WAPI_CERT_SUITE: - enterpriseConfig.setWapiCertSuite((String) value); - break; - default: - Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); - break; - } - } else { - String tagName = in.getName(); - if (tagName == null) { - throw new XmlPullParserException("Unexpected null tag found"); - } - switch (tagName) { - case XML_TAG_PASSWORD: - if (!shouldExpectEncryptedCredentials || encryptionUtil == null) { - throw new XmlPullParserException( - "encrypted password section not expected"); - } - EncryptedData encryptedData = - EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); - byte[] passwordBytes = encryptionUtil.decrypt(encryptedData); - if (passwordBytes == null) { - Log.wtf(TAG, "Decryption of password failed"); - } else { - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.PASSWORD_KEY, - new String(passwordBytes)); - } - break; - default: - Log.w(TAG, "Ignoring unknown tag name found: " + tagName); - break; - } - } - } - return enterpriseConfig; - } - } - - /** - * Utility class to serialize and deseriaize {@link EncryptedData} object to XML & - * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module. - */ - public static class EncryptedDataXmlUtil { - /** - * List of XML tags corresponding to EncryptedData object elements. - */ - private static final String XML_TAG_ENCRYPTED_DATA = "EncryptedData"; - private static final String XML_TAG_IV = "IV"; - - /** - * Write the NetworkSelectionStatus data elements from the provided status to the XML - * stream. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param encryptedData EncryptedData object to be serialized. - */ - public static void writeToXml(XmlSerializer out, EncryptedData encryptedData) - throws XmlPullParserException, IOException { - XmlUtil.writeNextValue( - out, XML_TAG_ENCRYPTED_DATA, encryptedData.getEncryptedData()); - XmlUtil.writeNextValue(out, XML_TAG_IV, encryptedData.getIv()); - } - - /** - * Parses the EncryptedData data elements from the provided XML stream to a - * EncryptedData object. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @return EncryptedData object if parsing is successful, null otherwise. - */ - public static EncryptedData parseFromXml(XmlPullParser in, int outerTagDepth) - throws XmlPullParserException, IOException { - byte[] encryptedData = null; - byte[] iv = null; - - // Loop through and parse out all the elements from the stream within this section. - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_ENCRYPTED_DATA: - encryptedData = (byte[]) value; - break; - case XML_TAG_IV: - iv = (byte[]) value; - break; - default: - Log.e(TAG, "Unknown value name found: " + valueName[0]); - break; - } - } - return new EncryptedData(encryptedData, iv); - } - } - - public static boolean nextElementWithin(XmlPullParser parser, int outerDepth) - throws IOException, XmlPullParserException { - return XmlUtilHelper.nextElementWithin(parser, outerDepth); - } - - /** - * Utility class to serialize and deseriaize {@link SoftApConfiguration} object to XML - * & vice versa. This is used by both {@link com.android.server.wifi.SoftApStore} modules. - */ - public static class SoftApConfigurationXmlUtil { - /** - * List of XML tags corresponding to SoftApConfiguration object elements. - */ - public static final String XML_TAG_CLIENT_MACADDRESS = "ClientMacAddress"; - - /** - * Parses the client list from the provided XML stream to a ArrayList object. - * - * @param in XmlPullParser instance pointing to the XML stream. - * @param outerTagDepth depth of the outer tag in the XML document. - * @return ArrayList object if parsing is successful, null otherwise. - */ - public static List<MacAddress> parseClientListFromXml(XmlPullParser in, - int outerTagDepth) throws XmlPullParserException, IOException, - IllegalArgumentException { - List<MacAddress> clientList = new ArrayList<>(); - // Loop through and parse out all the elements from the stream within this section. - while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_CLIENT_MACADDRESS: - MacAddress client = MacAddress.fromString((String) value); - clientList.add(client); - break; - default: - Log.e(TAG, "Unknown value name found: " + valueName[0]); - break; - } - } - return clientList; - } - - /** - * Write the SoftApConfiguration client control list data elements - * from the provided list to the XML stream. - * - * @param out XmlSerializer instance pointing to the XML stream. - * @param clientList Client list object to be serialized. - */ - public static void writeClientListToXml(XmlSerializer out, List<MacAddress> clientList) - throws XmlPullParserException, IOException { - for (MacAddress mac: clientList) { - XmlUtil.writeNextValue(out, XML_TAG_CLIENT_MACADDRESS, mac.toString()); - } - } - } -} - diff --git a/service/java/com/android/server/wifi/util/XmlUtilHelper.java b/service/java/com/android/server/wifi/util/XmlUtilHelper.java deleted file mode 100644 index 8ca536956..000000000 --- a/service/java/com/android/server/wifi/util/XmlUtilHelper.java +++ /dev/null @@ -1,1776 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi.util; - -import android.compat.annotation.UnsupportedAppUsage; -import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Base64; -import android.util.Xml; - -import com.android.internal.util.FastXmlSerializer; - -import android.net.wifi.util.HexEncoding; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.ProtocolException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Copied from {@link com.android.internal.util.XmlUtils}. - * Changed to use {@link android.net.wifi.util.HexEncoding} instead of - * {@link libcore.util.HexEncoding}. - * Should only be used by {@link XmlUtil}. - */ -/* package private */ class XmlUtilHelper { - - private static final String STRING_ARRAY_SEPARATOR = ":"; - - @UnsupportedAppUsage - public static void skipCurrentTag(XmlPullParser parser) - throws XmlPullParserException, IOException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - } - } - - public static final int - convertValueToList(CharSequence value, String[] options, int defaultValue) - { - if (!TextUtils.isEmpty(value)) { - for (int i = 0; i < options.length; i++) { - if (value.equals(options[i])) - return i; - } - } - - return defaultValue; - } - - @UnsupportedAppUsage - public static final boolean - convertValueToBoolean(CharSequence value, boolean defaultValue) - { - boolean result = false; - - if (TextUtils.isEmpty(value)) { - return defaultValue; - } - - if (value.equals("1") - || value.equals("true") - || value.equals("TRUE")) - result = true; - - return result; - } - - @UnsupportedAppUsage - public static final int - convertValueToInt(CharSequence charSeq, int defaultValue) - { - if (TextUtils.isEmpty(charSeq)) { - return defaultValue; - } - - String nm = charSeq.toString(); - - // XXX This code is copied from Integer.decode() so we don't - // have to instantiate an Integer! - - int value; - int sign = 1; - int index = 0; - int len = nm.length(); - int base = 10; - - if ('-' == nm.charAt(0)) { - sign = -1; - index++; - } - - if ('0' == nm.charAt(index)) { - // Quick check for a zero by itself - if (index == (len - 1)) - return 0; - - char c = nm.charAt(index + 1); - - if ('x' == c || 'X' == c) { - index += 2; - base = 16; - } else { - index++; - base = 8; - } - } - else if ('#' == nm.charAt(index)) - { - index++; - base = 16; - } - - return Integer.parseInt(nm.substring(index), base) * sign; - } - - public static int convertValueToUnsignedInt(String value, int defaultValue) { - if (TextUtils.isEmpty(value)) { - return defaultValue; - } - - return parseUnsignedIntAttribute(value); - } - - public static int parseUnsignedIntAttribute(CharSequence charSeq) { - String value = charSeq.toString(); - - long bits; - int index = 0; - int len = value.length(); - int base = 10; - - if ('0' == value.charAt(index)) { - // Quick check for zero by itself - if (index == (len - 1)) - return 0; - - char c = value.charAt(index + 1); - - if ('x' == c || 'X' == c) { // check for hex - index += 2; - base = 16; - } else { // check for octal - index++; - base = 8; - } - } else if ('#' == value.charAt(index)) { - index++; - base = 16; - } - - return (int) Long.parseLong(value.substring(index), base); - } - - /** - * Flatten a Map into an output stream as XML. The map can later be - * read back with readMapXml(). - * - * @param val The map to be flattened. - * @param out Where to write the XML data. - * - * @see #writeMapXml(Map, String, XmlSerializer) - * @see #writeListXml - * @see #writeValueXml - * @see #readMapXml - */ - @UnsupportedAppUsage - public static final void writeMapXml(Map val, OutputStream out) - throws XmlPullParserException, IOException { - XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(out, StandardCharsets.UTF_8.name()); - serializer.startDocument(null, true); - serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); - writeMapXml(val, null, serializer); - serializer.endDocument(); - } - - /** - * Flatten a List into an output stream as XML. The list can later be - * read back with readListXml(). - * - * @param val The list to be flattened. - * @param out Where to write the XML data. - * - * @see #writeListXml(List, String, XmlSerializer) - * @see #writeMapXml - * @see #writeValueXml - * @see #readListXml - */ - public static final void writeListXml(List val, OutputStream out) - throws XmlPullParserException, IOException - { - XmlSerializer serializer = Xml.newSerializer(); - serializer.setOutput(out, StandardCharsets.UTF_8.name()); - serializer.startDocument(null, true); - serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); - writeListXml(val, null, serializer); - serializer.endDocument(); - } - - /** - * Flatten a Map into an XmlSerializer. The map can later be read back - * with readThisMapXml(). - * - * @param val The map to be flattened. - * @param name Name attribute to include with this list's tag, or null for - * none. - * @param out XmlSerializer to write the map into. - * - * @see #writeMapXml(Map, OutputStream) - * @see #writeListXml - * @see #writeValueXml - * @see #readMapXml - */ - public static final void writeMapXml(Map val, String name, XmlSerializer out) - throws XmlPullParserException, IOException { - writeMapXml(val, name, out, null); - } - - /** - * Flatten a Map into an XmlSerializer. The map can later be read back - * with readThisMapXml(). - * - * @param val The map to be flattened. - * @param name Name attribute to include with this list's tag, or null for - * none. - * @param out XmlSerializer to write the map into. - * @param callback Method to call when an Object type is not recognized. - * - * @see #writeMapXml(Map, OutputStream) - * @see #writeListXml - * @see #writeValueXml - * @see #readMapXml - * - * @hide - */ - public static final void writeMapXml(Map val, String name, XmlSerializer out, - WriteMapCallback callback) throws XmlPullParserException, IOException { - - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "map"); - if (name != null) { - out.attribute(null, "name", name); - } - - writeMapXml(val, out, callback); - - out.endTag(null, "map"); - } - - /** - * Flatten a Map into an XmlSerializer. The map can later be read back - * with readThisMapXml(). This method presumes that the start tag and - * name attribute have already been written and does not write an end tag. - * - * @param val The map to be flattened. - * @param out XmlSerializer to write the map into. - * - * @see #writeMapXml(Map, OutputStream) - * @see #writeListXml - * @see #writeValueXml - * @see #readMapXml - * - * @hide - */ - public static final void writeMapXml(Map val, XmlSerializer out, - WriteMapCallback callback) throws XmlPullParserException, IOException { - if (val == null) { - return; - } - - Set s = val.entrySet(); - Iterator i = s.iterator(); - - while (i.hasNext()) { - Map.Entry e = (Map.Entry)i.next(); - writeValueXml(e.getValue(), (String)e.getKey(), out, callback); - } - } - - /** - * Flatten a List into an XmlSerializer. The list can later be read back - * with readThisListXml(). - * - * @param val The list to be flattened. - * @param name Name attribute to include with this list's tag, or null for - * none. - * @param out XmlSerializer to write the list into. - * - * @see #writeListXml(List, OutputStream) - * @see #writeMapXml - * @see #writeValueXml - * @see #readListXml - */ - public static final void writeListXml(List val, String name, XmlSerializer out) - throws XmlPullParserException, IOException - { - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "list"); - if (name != null) { - out.attribute(null, "name", name); - } - - int N = val.size(); - int i=0; - while (i < N) { - writeValueXml(val.get(i), null, out); - i++; - } - - out.endTag(null, "list"); - } - - public static final void writeSetXml(Set val, String name, XmlSerializer out) - throws XmlPullParserException, IOException { - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "set"); - if (name != null) { - out.attribute(null, "name", name); - } - - for (Object v : val) { - writeValueXml(v, null, out); - } - - out.endTag(null, "set"); - } - - /** - * Flatten a byte[] into an XmlSerializer. The list can later be read back - * with readThisByteArrayXml(). - * - * @param val The byte array to be flattened. - * @param name Name attribute to include with this array's tag, or null for - * none. - * @param out XmlSerializer to write the array into. - * - * @see #writeMapXml - * @see #writeValueXml - */ - public static final void writeByteArrayXml(byte[] val, String name, - XmlSerializer out) - throws XmlPullParserException, IOException { - - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "byte-array"); - if (name != null) { - out.attribute(null, "name", name); - } - - final int N = val.length; - out.attribute(null, "num", Integer.toString(N)); - - out.text(HexEncoding.encodeToString(val).toLowerCase()); - - out.endTag(null, "byte-array"); - } - - /** - * Flatten an int[] into an XmlSerializer. The list can later be read back - * with readThisIntArrayXml(). - * - * @param val The int array to be flattened. - * @param name Name attribute to include with this array's tag, or null for - * none. - * @param out XmlSerializer to write the array into. - * - * @see #writeMapXml - * @see #writeValueXml - * @see #readThisIntArrayXml - */ - public static final void writeIntArrayXml(int[] val, String name, - XmlSerializer out) - throws XmlPullParserException, IOException { - - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "int-array"); - if (name != null) { - out.attribute(null, "name", name); - } - - final int N = val.length; - out.attribute(null, "num", Integer.toString(N)); - - for (int i=0; i<N; i++) { - out.startTag(null, "item"); - out.attribute(null, "value", Integer.toString(val[i])); - out.endTag(null, "item"); - } - - out.endTag(null, "int-array"); - } - - /** - * Flatten a long[] into an XmlSerializer. The list can later be read back - * with readThisLongArrayXml(). - * - * @param val The long array to be flattened. - * @param name Name attribute to include with this array's tag, or null for - * none. - * @param out XmlSerializer to write the array into. - * - * @see #writeMapXml - * @see #writeValueXml - * @see #readThisIntArrayXml - */ - public static final void writeLongArrayXml(long[] val, String name, XmlSerializer out) - throws XmlPullParserException, IOException { - - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "long-array"); - if (name != null) { - out.attribute(null, "name", name); - } - - final int N = val.length; - out.attribute(null, "num", Integer.toString(N)); - - for (int i=0; i<N; i++) { - out.startTag(null, "item"); - out.attribute(null, "value", Long.toString(val[i])); - out.endTag(null, "item"); - } - - out.endTag(null, "long-array"); - } - - /** - * Flatten a double[] into an XmlSerializer. The list can later be read back - * with readThisDoubleArrayXml(). - * - * @param val The double array to be flattened. - * @param name Name attribute to include with this array's tag, or null for - * none. - * @param out XmlSerializer to write the array into. - * - * @see #writeMapXml - * @see #writeValueXml - * @see #readThisIntArrayXml - */ - public static final void writeDoubleArrayXml(double[] val, String name, XmlSerializer out) - throws XmlPullParserException, IOException { - - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "double-array"); - if (name != null) { - out.attribute(null, "name", name); - } - - final int N = val.length; - out.attribute(null, "num", Integer.toString(N)); - - for (int i=0; i<N; i++) { - out.startTag(null, "item"); - out.attribute(null, "value", Double.toString(val[i])); - out.endTag(null, "item"); - } - - out.endTag(null, "double-array"); - } - - /** - * Flatten a String[] into an XmlSerializer. The list can later be read back - * with readThisStringArrayXml(). - * - * @param val The String array to be flattened. - * @param name Name attribute to include with this array's tag, or null for - * none. - * @param out XmlSerializer to write the array into. - * - * @see #writeMapXml - * @see #writeValueXml - * @see #readThisIntArrayXml - */ - public static final void writeStringArrayXml(String[] val, String name, XmlSerializer out) - throws XmlPullParserException, IOException { - - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "string-array"); - if (name != null) { - out.attribute(null, "name", name); - } - - final int N = val.length; - out.attribute(null, "num", Integer.toString(N)); - - for (int i=0; i<N; i++) { - out.startTag(null, "item"); - out.attribute(null, "value", val[i]); - out.endTag(null, "item"); - } - - out.endTag(null, "string-array"); - } - - /** - * Flatten a boolean[] into an XmlSerializer. The list can later be read back - * with readThisBooleanArrayXml(). - * - * @param val The boolean array to be flattened. - * @param name Name attribute to include with this array's tag, or null for - * none. - * @param out XmlSerializer to write the array into. - * - * @see #writeMapXml - * @see #writeValueXml - * @see #readThisIntArrayXml - */ - public static final void writeBooleanArrayXml(boolean[] val, String name, XmlSerializer out) - throws XmlPullParserException, IOException { - - if (val == null) { - out.startTag(null, "null"); - out.endTag(null, "null"); - return; - } - - out.startTag(null, "boolean-array"); - if (name != null) { - out.attribute(null, "name", name); - } - - final int N = val.length; - out.attribute(null, "num", Integer.toString(N)); - - for (int i=0; i<N; i++) { - out.startTag(null, "item"); - out.attribute(null, "value", Boolean.toString(val[i])); - out.endTag(null, "item"); - } - - out.endTag(null, "boolean-array"); - } - - /** - * Flatten an object's value into an XmlSerializer. The value can later - * be read back with readThisValueXml(). - * - * Currently supported value types are: null, String, Integer, Long, - * Float, Double Boolean, Map, List. - * - * @param v The object to be flattened. - * @param name Name attribute to include with this value's tag, or null - * for none. - * @param out XmlSerializer to write the object into. - * - * @see #writeMapXml - * @see #writeListXml - * @see #readValueXml - */ - public static final void writeValueXml(Object v, String name, XmlSerializer out) - throws XmlPullParserException, IOException { - writeValueXml(v, name, out, null); - } - - /** - * Flatten an object's value into an XmlSerializer. The value can later - * be read back with readThisValueXml(). - * - * Currently supported value types are: null, String, Integer, Long, - * Float, Double Boolean, Map, List. - * - * @param v The object to be flattened. - * @param name Name attribute to include with this value's tag, or null - * for none. - * @param out XmlSerializer to write the object into. - * @param callback Handler for Object types not recognized. - * - * @see #writeMapXml - * @see #writeListXml - * @see #readValueXml - */ - private static final void writeValueXml(Object v, String name, XmlSerializer out, - WriteMapCallback callback) throws XmlPullParserException, IOException { - String typeStr; - if (v == null) { - out.startTag(null, "null"); - if (name != null) { - out.attribute(null, "name", name); - } - out.endTag(null, "null"); - return; - } else if (v instanceof String) { - out.startTag(null, "string"); - if (name != null) { - out.attribute(null, "name", name); - } - out.text(v.toString()); - out.endTag(null, "string"); - return; - } else if (v instanceof Integer) { - typeStr = "int"; - } else if (v instanceof Long) { - typeStr = "long"; - } else if (v instanceof Float) { - typeStr = "float"; - } else if (v instanceof Double) { - typeStr = "double"; - } else if (v instanceof Boolean) { - typeStr = "boolean"; - } else if (v instanceof byte[]) { - writeByteArrayXml((byte[])v, name, out); - return; - } else if (v instanceof int[]) { - writeIntArrayXml((int[])v, name, out); - return; - } else if (v instanceof long[]) { - writeLongArrayXml((long[])v, name, out); - return; - } else if (v instanceof double[]) { - writeDoubleArrayXml((double[])v, name, out); - return; - } else if (v instanceof String[]) { - writeStringArrayXml((String[])v, name, out); - return; - } else if (v instanceof boolean[]) { - writeBooleanArrayXml((boolean[])v, name, out); - return; - } else if (v instanceof Map) { - writeMapXml((Map)v, name, out); - return; - } else if (v instanceof List) { - writeListXml((List) v, name, out); - return; - } else if (v instanceof Set) { - writeSetXml((Set) v, name, out); - return; - } else if (v instanceof CharSequence) { - // XXX This is to allow us to at least write something if - // we encounter styled text... but it means we will drop all - // of the styling information. :( - out.startTag(null, "string"); - if (name != null) { - out.attribute(null, "name", name); - } - out.text(v.toString()); - out.endTag(null, "string"); - return; - } else if (callback != null) { - callback.writeUnknownObject(v, name, out); - return; - } else { - throw new RuntimeException("writeValueXml: unable to write value " + v); - } - - out.startTag(null, typeStr); - if (name != null) { - out.attribute(null, "name", name); - } - out.attribute(null, "value", v.toString()); - out.endTag(null, typeStr); - } - - /** - * Read a HashMap from an InputStream containing XML. The stream can - * previously have been written by writeMapXml(). - * - * @param in The InputStream from which to read. - * - * @return HashMap The resulting map. - * - * @see #readListXml - * @see #readValueXml - * @see #readThisMapXml - * #see #writeMapXml - */ - @SuppressWarnings("unchecked") - @UnsupportedAppUsage - public static final HashMap<String, ?> readMapXml(InputStream in) - throws XmlPullParserException, IOException - { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(in, StandardCharsets.UTF_8.name()); - return (HashMap<String, ?>) readValueXml(parser, new String[1]); - } - - /** - * Read an ArrayList from an InputStream containing XML. The stream can - * previously have been written by writeListXml(). - * - * @param in The InputStream from which to read. - * - * @return ArrayList The resulting list. - * - * @see #readMapXml - * @see #readValueXml - * @see #readThisListXml - * @see #writeListXml - */ - public static final ArrayList readListXml(InputStream in) - throws XmlPullParserException, IOException - { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(in, StandardCharsets.UTF_8.name()); - return (ArrayList)readValueXml(parser, new String[1]); - } - - - /** - * Read a HashSet from an InputStream containing XML. The stream can - * previously have been written by writeSetXml(). - * - * @param in The InputStream from which to read. - * - * @return HashSet The resulting set. - * - * @throws XmlPullParserException - * @throws IOException - * - * @see #readValueXml - * @see #readThisSetXml - * @see #writeSetXml - */ - public static final HashSet readSetXml(InputStream in) - throws XmlPullParserException, IOException { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(in, null); - return (HashSet) readValueXml(parser, new String[1]); - } - - /** - * Read a HashMap object from an XmlPullParser. The XML data could - * previously have been generated by writeMapXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the map. - * - * @param parser The XmlPullParser from which to read the map data. - * @param endTag Name of the tag that will end the map, usually "map". - * @param name An array of one string, used to return the name attribute - * of the map's tag. - * - * @return HashMap The newly generated map. - * - * @see #readMapXml - */ - public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag, - String[] name) throws XmlPullParserException, IOException { - return readThisMapXml(parser, endTag, name, null); - } - - /** - * Read a HashMap object from an XmlPullParser. The XML data could - * previously have been generated by writeMapXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the map. - * - * @param parser The XmlPullParser from which to read the map data. - * @param endTag Name of the tag that will end the map, usually "map". - * @param name An array of one string, used to return the name attribute - * of the map's tag. - * - * @return HashMap The newly generated map. - * - * @see #readMapXml - * @hide - */ - public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag, - String[] name, ReadMapCallback callback) - throws XmlPullParserException, IOException - { - HashMap<String, Object> map = new HashMap<String, Object>(); - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - Object val = readThisValueXml(parser, name, callback, false); - map.put(name[0], val); - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return map; - } - throw new XmlPullParserException( - "Expected " + endTag + " end tag at: " + parser.getName()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException( - "Document ended before " + endTag + " end tag"); - } - - /** - * Like {@link #readThisMapXml}, but returns an ArrayMap instead of HashMap. - * @hide - */ - public static final ArrayMap<String, ?> readThisArrayMapXml(XmlPullParser parser, String endTag, - String[] name, ReadMapCallback callback) - throws XmlPullParserException, IOException - { - ArrayMap<String, Object> map = new ArrayMap<>(); - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - Object val = readThisValueXml(parser, name, callback, true); - map.put(name[0], val); - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return map; - } - throw new XmlPullParserException( - "Expected " + endTag + " end tag at: " + parser.getName()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException( - "Document ended before " + endTag + " end tag"); - } - - /** - * Read an ArrayList object from an XmlPullParser. The XML data could - * previously have been generated by writeListXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the list. - * - * @param parser The XmlPullParser from which to read the list data. - * @param endTag Name of the tag that will end the list, usually "list". - * @param name An array of one string, used to return the name attribute - * of the list's tag. - * - * @return HashMap The newly generated list. - * - * @see #readListXml - */ - public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, - String[] name) throws XmlPullParserException, IOException { - return readThisListXml(parser, endTag, name, null, false); - } - - /** - * Read an ArrayList object from an XmlPullParser. The XML data could - * previously have been generated by writeListXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the list. - * - * @param parser The XmlPullParser from which to read the list data. - * @param endTag Name of the tag that will end the list, usually "list". - * @param name An array of one string, used to return the name attribute - * of the list's tag. - * - * @return HashMap The newly generated list. - * - * @see #readListXml - */ - private static final ArrayList readThisListXml(XmlPullParser parser, String endTag, - String[] name, ReadMapCallback callback, boolean arrayMap) - throws XmlPullParserException, IOException { - ArrayList list = new ArrayList(); - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - Object val = readThisValueXml(parser, name, callback, arrayMap); - list.add(val); - //System.out.println("Adding to list: " + val); - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return list; - } - throw new XmlPullParserException( - "Expected " + endTag + " end tag at: " + parser.getName()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException( - "Document ended before " + endTag + " end tag"); - } - - /** - * Read a HashSet object from an XmlPullParser. The XML data could previously - * have been generated by writeSetXml(). The XmlPullParser must be positioned - * <em>after</em> the tag that begins the set. - * - * @param parser The XmlPullParser from which to read the set data. - * @param endTag Name of the tag that will end the set, usually "set". - * @param name An array of one string, used to return the name attribute - * of the set's tag. - * - * @return HashSet The newly generated set. - * - * @throws XmlPullParserException - * @throws IOException - * - * @see #readSetXml - */ - public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name) - throws XmlPullParserException, IOException { - return readThisSetXml(parser, endTag, name, null, false); - } - - /** - * Read a HashSet object from an XmlPullParser. The XML data could previously - * have been generated by writeSetXml(). The XmlPullParser must be positioned - * <em>after</em> the tag that begins the set. - * - * @param parser The XmlPullParser from which to read the set data. - * @param endTag Name of the tag that will end the set, usually "set". - * @param name An array of one string, used to return the name attribute - * of the set's tag. - * - * @return HashSet The newly generated set. - * - * @throws XmlPullParserException - * @throws IOException - * - * @see #readSetXml - * @hide - */ - private static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name, - ReadMapCallback callback, boolean arrayMap) - throws XmlPullParserException, IOException { - HashSet set = new HashSet(); - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - Object val = readThisValueXml(parser, name, callback, arrayMap); - set.add(val); - //System.out.println("Adding to set: " + val); - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return set; - } - throw new XmlPullParserException( - "Expected " + endTag + " end tag at: " + parser.getName()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException( - "Document ended before " + endTag + " end tag"); - } - - /** - * Read a byte[] object from an XmlPullParser. The XML data could - * previously have been generated by writeByteArrayXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the list. - * - * @param parser The XmlPullParser from which to read the list data. - * @param endTag Name of the tag that will end the list, usually "list". - * @param name An array of one string, used to return the name attribute - * of the list's tag. - * - * @return Returns a newly generated byte[]. - * - * @see #writeByteArrayXml - */ - public static final byte[] readThisByteArrayXml(XmlPullParser parser, - String endTag, String[] name) - throws XmlPullParserException, IOException { - - int num; - try { - num = Integer.parseInt(parser.getAttributeValue(null, "num")); - } catch (NullPointerException e) { - throw new XmlPullParserException( - "Need num attribute in byte-array"); - } catch (NumberFormatException e) { - throw new XmlPullParserException( - "Not a number in num attribute in byte-array"); - } - - // 0 len byte array does not have a text in the XML tag. So, initialize to 0 len array. - // For all other array lens, HexEncoding.decode() below overrides the array. - byte[] array = new byte[0]; - - int eventType = parser.getEventType(); - do { - if (eventType == parser.TEXT) { - if (num > 0) { - String values = parser.getText(); - if (values == null || values.length() != num * 2) { - throw new XmlPullParserException( - "Invalid value found in byte-array: " + values); - } - array = HexEncoding.decode(values); - } - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return array; - } else { - throw new XmlPullParserException( - "Expected " + endTag + " end tag at: " - + parser.getName()); - } - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException( - "Document ended before " + endTag + " end tag"); - } - - /** - * Read an int[] object from an XmlPullParser. The XML data could - * previously have been generated by writeIntArrayXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the list. - * - * @param parser The XmlPullParser from which to read the list data. - * @param endTag Name of the tag that will end the list, usually "list". - * @param name An array of one string, used to return the name attribute - * of the list's tag. - * - * @return Returns a newly generated int[]. - * - * @see #readListXml - */ - public static final int[] readThisIntArrayXml(XmlPullParser parser, - String endTag, String[] name) - throws XmlPullParserException, IOException { - - int num; - try { - num = Integer.parseInt(parser.getAttributeValue(null, "num")); - } catch (NullPointerException e) { - throw new XmlPullParserException( - "Need num attribute in int-array"); - } catch (NumberFormatException e) { - throw new XmlPullParserException( - "Not a number in num attribute in int-array"); - } - parser.next(); - - int[] array = new int[num]; - int i = 0; - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - if (parser.getName().equals("item")) { - try { - array[i] = Integer.parseInt( - parser.getAttributeValue(null, "value")); - } catch (NullPointerException e) { - throw new XmlPullParserException( - "Need value attribute in item"); - } catch (NumberFormatException e) { - throw new XmlPullParserException( - "Not a number in value attribute in item"); - } - } else { - throw new XmlPullParserException( - "Expected item tag at: " + parser.getName()); - } - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return array; - } else if (parser.getName().equals("item")) { - i++; - } else { - throw new XmlPullParserException( - "Expected " + endTag + " end tag at: " - + parser.getName()); - } - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException( - "Document ended before " + endTag + " end tag"); - } - - /** - * Read a long[] object from an XmlPullParser. The XML data could - * previously have been generated by writeLongArrayXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the list. - * - * @param parser The XmlPullParser from which to read the list data. - * @param endTag Name of the tag that will end the list, usually "list". - * @param name An array of one string, used to return the name attribute - * of the list's tag. - * - * @return Returns a newly generated long[]. - * - * @see #readListXml - */ - public static final long[] readThisLongArrayXml(XmlPullParser parser, - String endTag, String[] name) - throws XmlPullParserException, IOException { - - int num; - try { - num = Integer.parseInt(parser.getAttributeValue(null, "num")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need num attribute in long-array"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in num attribute in long-array"); - } - parser.next(); - - long[] array = new long[num]; - int i = 0; - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - if (parser.getName().equals("item")) { - try { - array[i] = Long.parseLong(parser.getAttributeValue(null, "value")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need value attribute in item"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in value attribute in item"); - } - } else { - throw new XmlPullParserException("Expected item tag at: " + parser.getName()); - } - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return array; - } else if (parser.getName().equals("item")) { - i++; - } else { - throw new XmlPullParserException("Expected " + endTag + " end tag at: " + - parser.getName()); - } - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException("Document ended before " + endTag + " end tag"); - } - - /** - * Read a double[] object from an XmlPullParser. The XML data could - * previously have been generated by writeDoubleArrayXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the list. - * - * @param parser The XmlPullParser from which to read the list data. - * @param endTag Name of the tag that will end the list, usually "double-array". - * @param name An array of one string, used to return the name attribute - * of the list's tag. - * - * @return Returns a newly generated double[]. - * - * @see #readListXml - */ - public static final double[] readThisDoubleArrayXml(XmlPullParser parser, String endTag, - String[] name) throws XmlPullParserException, IOException { - - int num; - try { - num = Integer.parseInt(parser.getAttributeValue(null, "num")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need num attribute in double-array"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in num attribute in double-array"); - } - parser.next(); - - double[] array = new double[num]; - int i = 0; - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - if (parser.getName().equals("item")) { - try { - array[i] = Double.parseDouble(parser.getAttributeValue(null, "value")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need value attribute in item"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in value attribute in item"); - } - } else { - throw new XmlPullParserException("Expected item tag at: " + parser.getName()); - } - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return array; - } else if (parser.getName().equals("item")) { - i++; - } else { - throw new XmlPullParserException("Expected " + endTag + " end tag at: " + - parser.getName()); - } - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException("Document ended before " + endTag + " end tag"); - } - - /** - * Read a String[] object from an XmlPullParser. The XML data could - * previously have been generated by writeStringArrayXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the list. - * - * @param parser The XmlPullParser from which to read the list data. - * @param endTag Name of the tag that will end the list, usually "string-array". - * @param name An array of one string, used to return the name attribute - * of the list's tag. - * - * @return Returns a newly generated String[]. - * - * @see #readListXml - */ - public static final String[] readThisStringArrayXml(XmlPullParser parser, String endTag, - String[] name) throws XmlPullParserException, IOException { - - int num; - try { - num = Integer.parseInt(parser.getAttributeValue(null, "num")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need num attribute in string-array"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in num attribute in string-array"); - } - parser.next(); - - String[] array = new String[num]; - int i = 0; - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - if (parser.getName().equals("item")) { - try { - array[i] = parser.getAttributeValue(null, "value"); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need value attribute in item"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in value attribute in item"); - } - } else { - throw new XmlPullParserException("Expected item tag at: " + parser.getName()); - } - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return array; - } else if (parser.getName().equals("item")) { - i++; - } else { - throw new XmlPullParserException("Expected " + endTag + " end tag at: " + - parser.getName()); - } - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException("Document ended before " + endTag + " end tag"); - } - - /** - * Read a boolean[] object from an XmlPullParser. The XML data could - * previously have been generated by writeBooleanArrayXml(). The XmlPullParser - * must be positioned <em>after</em> the tag that begins the list. - * - * @param parser The XmlPullParser from which to read the list data. - * @param endTag Name of the tag that will end the list, usually "string-array". - * @param name An array of one string, used to return the name attribute - * of the list's tag. - * - * @return Returns a newly generated boolean[]. - * - * @see #readListXml - */ - public static final boolean[] readThisBooleanArrayXml(XmlPullParser parser, String endTag, - String[] name) throws XmlPullParserException, IOException { - - int num; - try { - num = Integer.parseInt(parser.getAttributeValue(null, "num")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need num attribute in string-array"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in num attribute in string-array"); - } - parser.next(); - - boolean[] array = new boolean[num]; - int i = 0; - - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - if (parser.getName().equals("item")) { - try { - array[i] = Boolean.parseBoolean(parser.getAttributeValue(null, "value")); - } catch (NullPointerException e) { - throw new XmlPullParserException("Need value attribute in item"); - } catch (NumberFormatException e) { - throw new XmlPullParserException("Not a number in value attribute in item"); - } - } else { - throw new XmlPullParserException("Expected item tag at: " + parser.getName()); - } - } else if (eventType == parser.END_TAG) { - if (parser.getName().equals(endTag)) { - return array; - } else if (parser.getName().equals("item")) { - i++; - } else { - throw new XmlPullParserException("Expected " + endTag + " end tag at: " + - parser.getName()); - } - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException("Document ended before " + endTag + " end tag"); - } - - /** - * Read a flattened object from an XmlPullParser. The XML data could - * previously have been written with writeMapXml(), writeListXml(), or - * writeValueXml(). The XmlPullParser must be positioned <em>at</em> the - * tag that defines the value. - * - * @param parser The XmlPullParser from which to read the object. - * @param name An array of one string, used to return the name attribute - * of the value's tag. - * - * @return Object The newly generated value object. - * - * @see #readMapXml - * @see #readListXml - * @see #writeValueXml - */ - public static final Object readValueXml(XmlPullParser parser, String[] name) - throws XmlPullParserException, IOException - { - int eventType = parser.getEventType(); - do { - if (eventType == parser.START_TAG) { - return readThisValueXml(parser, name, null, false); - } else if (eventType == parser.END_TAG) { - throw new XmlPullParserException( - "Unexpected end tag at: " + parser.getName()); - } else if (eventType == parser.TEXT) { - throw new XmlPullParserException( - "Unexpected text: " + parser.getText()); - } - eventType = parser.next(); - } while (eventType != parser.END_DOCUMENT); - - throw new XmlPullParserException( - "Unexpected end of document"); - } - - private static final Object readThisValueXml(XmlPullParser parser, String[] name, - ReadMapCallback callback, boolean arrayMap) - throws XmlPullParserException, IOException { - final String valueName = parser.getAttributeValue(null, "name"); - final String tagName = parser.getName(); - - //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName); - - Object res; - - if (tagName.equals("null")) { - res = null; - } else if (tagName.equals("string")) { - String value = ""; - int eventType; - while ((eventType = parser.next()) != parser.END_DOCUMENT) { - if (eventType == parser.END_TAG) { - if (parser.getName().equals("string")) { - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + value); - return value; - } - throw new XmlPullParserException( - "Unexpected end tag in <string>: " + parser.getName()); - } else if (eventType == parser.TEXT) { - value += parser.getText(); - } else if (eventType == parser.START_TAG) { - throw new XmlPullParserException( - "Unexpected start tag in <string>: " + parser.getName()); - } - } - throw new XmlPullParserException( - "Unexpected end of document in <string>"); - } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) { - // all work already done by readThisPrimitiveValueXml - } else if (tagName.equals("byte-array")) { - res = readThisByteArrayXml(parser, "byte-array", name); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (tagName.equals("int-array")) { - res = readThisIntArrayXml(parser, "int-array", name); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (tagName.equals("long-array")) { - res = readThisLongArrayXml(parser, "long-array", name); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (tagName.equals("double-array")) { - res = readThisDoubleArrayXml(parser, "double-array", name); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (tagName.equals("string-array")) { - res = readThisStringArrayXml(parser, "string-array", name); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (tagName.equals("boolean-array")) { - res = readThisBooleanArrayXml(parser, "boolean-array", name); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (tagName.equals("map")) { - parser.next(); - res = arrayMap - ? readThisArrayMapXml(parser, "map", name, callback) - : readThisMapXml(parser, "map", name, callback); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (tagName.equals("list")) { - parser.next(); - res = readThisListXml(parser, "list", name, callback, arrayMap); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (tagName.equals("set")) { - parser.next(); - res = readThisSetXml(parser, "set", name, callback, arrayMap); - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } else if (callback != null) { - res = callback.readThisUnknownObjectXml(parser, tagName); - name[0] = valueName; - return res; - } else { - throw new XmlPullParserException("Unknown tag: " + tagName); - } - - // Skip through to end tag. - int eventType; - while ((eventType = parser.next()) != parser.END_DOCUMENT) { - if (eventType == parser.END_TAG) { - if (parser.getName().equals(tagName)) { - name[0] = valueName; - //System.out.println("Returning value for " + valueName + ": " + res); - return res; - } - throw new XmlPullParserException( - "Unexpected end tag in <" + tagName + ">: " + parser.getName()); - } else if (eventType == parser.TEXT) { - throw new XmlPullParserException( - "Unexpected text in <" + tagName + ">: " + parser.getName()); - } else if (eventType == parser.START_TAG) { - throw new XmlPullParserException( - "Unexpected start tag in <" + tagName + ">: " + parser.getName()); - } - } - throw new XmlPullParserException( - "Unexpected end of document in <" + tagName + ">"); - } - - private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName) - throws XmlPullParserException, IOException - { - try { - if (tagName.equals("int")) { - return Integer.parseInt(parser.getAttributeValue(null, "value")); - } else if (tagName.equals("long")) { - return Long.valueOf(parser.getAttributeValue(null, "value")); - } else if (tagName.equals("float")) { - return new Float(parser.getAttributeValue(null, "value")); - } else if (tagName.equals("double")) { - return new Double(parser.getAttributeValue(null, "value")); - } else if (tagName.equals("boolean")) { - return Boolean.valueOf(parser.getAttributeValue(null, "value")); - } else { - return null; - } - } catch (NullPointerException e) { - throw new XmlPullParserException("Need value attribute in <" + tagName + ">"); - } catch (NumberFormatException e) { - throw new XmlPullParserException( - "Not a number in value attribute in <" + tagName + ">"); - } - } - - @UnsupportedAppUsage - public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException - { - int type; - while ((type=parser.next()) != parser.START_TAG - && type != parser.END_DOCUMENT) { - ; - } - - if (type != parser.START_TAG) { - throw new XmlPullParserException("No start tag found"); - } - - if (!parser.getName().equals(firstElementName)) { - throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + - ", expected " + firstElementName); - } - } - - @UnsupportedAppUsage - public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException - { - int type; - while ((type=parser.next()) != parser.START_TAG - && type != parser.END_DOCUMENT) { - ; - } - } - - public static boolean nextElementWithin(XmlPullParser parser, int outerDepth) - throws IOException, XmlPullParserException { - for (;;) { - int type = parser.next(); - if (type == XmlPullParser.END_DOCUMENT - || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) { - return false; - } - if (type == XmlPullParser.START_TAG - && parser.getDepth() == outerDepth + 1) { - return true; - } - } - } - - public static int readIntAttribute(XmlPullParser in, String name, int defaultValue) { - final String value = in.getAttributeValue(null, name); - if (TextUtils.isEmpty(value)) { - return defaultValue; - } - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public static int readIntAttribute(XmlPullParser in, String name) throws IOException { - final String value = in.getAttributeValue(null, name); - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); - } - } - - public static void writeIntAttribute(XmlSerializer out, String name, int value) - throws IOException { - out.attribute(null, name, Integer.toString(value)); - } - - public static long readLongAttribute(XmlPullParser in, String name, long defaultValue) { - final String value = in.getAttributeValue(null, name); - if (TextUtils.isEmpty(value)) { - return defaultValue; - } - try { - return Long.parseLong(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public static long readLongAttribute(XmlPullParser in, String name) throws IOException { - final String value = in.getAttributeValue(null, name); - try { - return Long.parseLong(value); - } catch (NumberFormatException e) { - throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); - } - } - - public static void writeLongAttribute(XmlSerializer out, String name, long value) - throws IOException { - out.attribute(null, name, Long.toString(value)); - } - - public static float readFloatAttribute(XmlPullParser in, String name) throws IOException { - final String value = in.getAttributeValue(null, name); - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { - throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); - } - } - - public static void writeFloatAttribute(XmlSerializer out, String name, float value) - throws IOException { - out.attribute(null, name, Float.toString(value)); - } - - public static boolean readBooleanAttribute(XmlPullParser in, String name) { - final String value = in.getAttributeValue(null, name); - return Boolean.parseBoolean(value); - } - - public static boolean readBooleanAttribute(XmlPullParser in, String name, - boolean defaultValue) { - final String value = in.getAttributeValue(null, name); - if (TextUtils.isEmpty(value)) { - return defaultValue; - } else { - return Boolean.parseBoolean(value); - } - } - - public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value) - throws IOException { - out.attribute(null, name, Boolean.toString(value)); - } - - public static Uri readUriAttribute(XmlPullParser in, String name) { - final String value = in.getAttributeValue(null, name); - return (value != null) ? Uri.parse(value) : null; - } - - public static void writeUriAttribute(XmlSerializer out, String name, Uri value) - throws IOException { - if (value != null) { - out.attribute(null, name, value.toString()); - } - } - - public static String readStringAttribute(XmlPullParser in, String name) { - return in.getAttributeValue(null, name); - } - - public static void writeStringAttribute(XmlSerializer out, String name, CharSequence value) - throws IOException { - if (value != null) { - out.attribute(null, name, value.toString()); - } - } - - public static byte[] readByteArrayAttribute(XmlPullParser in, String name) { - final String value = in.getAttributeValue(null, name); - if (!TextUtils.isEmpty(value)) { - return Base64.decode(value, Base64.DEFAULT); - } else { - return null; - } - } - - public static void writeByteArrayAttribute(XmlSerializer out, String name, byte[] value) - throws IOException { - if (value != null) { - out.attribute(null, name, Base64.encodeToString(value, Base64.DEFAULT)); - } - } - - public static Bitmap readBitmapAttribute(XmlPullParser in, String name) { - final byte[] value = readByteArrayAttribute(in, name); - if (value != null) { - return BitmapFactory.decodeByteArray(value, 0, value.length); - } else { - return null; - } - } - - @Deprecated - public static void writeBitmapAttribute(XmlSerializer out, String name, Bitmap value) - throws IOException { - if (value != null) { - final ByteArrayOutputStream os = new ByteArrayOutputStream(); - value.compress(CompressFormat.PNG, 90, os); - writeByteArrayAttribute(out, name, os.toByteArray()); - } - } - - /** @hide */ - public interface WriteMapCallback { - /** - * Called from writeMapXml when an Object type is not recognized. The implementer - * must write out the entire element including start and end tags. - * - * @param v The object to be written out - * @param name The mapping key for v. Must be written into the "name" attribute of the - * start tag. - * @param out The XML output stream. - * @throws XmlPullParserException on unrecognized Object type. - * @throws IOException on XmlSerializer serialization errors. - * @hide - */ - public void writeUnknownObject(Object v, String name, XmlSerializer out) - throws XmlPullParserException, IOException; - } - - /** @hide */ - public interface ReadMapCallback { - /** - * Called from readThisMapXml when a START_TAG is not recognized. The input stream - * is positioned within the start tag so that attributes can be read using in.getAttribute. - * - * @param in the XML input stream - * @param tag the START_TAG that was not recognized. - * @return the Object parsed from the stream which will be put into the map. - * @throws XmlPullParserException if the START_TAG is not recognized. - * @throws IOException on XmlPullParser serialization errors. - * @hide - */ - public Object readThisUnknownObjectXml(XmlPullParser in, String tag) - throws XmlPullParserException, IOException; - } -} diff --git a/service/proguard.flags b/service/proguard.flags deleted file mode 100644 index d2d7866ad..000000000 --- a/service/proguard.flags +++ /dev/null @@ -1,5 +0,0 @@ -# Prevent proguard from stripping out any wifi-service. -# TODO: This could be optimized in the future to only keep the critical -# entry points and then let proguard strip out any unused code within -# the service. --keep class com.android.server.wifi.** { *; } diff --git a/service/proto/Android.bp b/service/proto/Android.bp deleted file mode 100644 index cb061d360..000000000 --- a/service/proto/Android.bp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2018 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. - -java_library { - name: "wifi-lite-protos", - proto: { - type: "lite", - }, - sdk_version: "system_current", - srcs: ["src/scorecard.proto"], -} - -java_library { - name: "wifi-nano-protos", - host_supported: true, - proto: { - type: "nano", - }, - srcs: [ - "src/metrics.proto", - ":system-messages-proto-src", - ], - sdk_version: "system_current", - // Pin java_version until jarjar is certified to support later versions. http://b/72703434 - java_version: "1.8", - target: { - host: { - static_libs: ["libprotobuf-java-nano"], - }, - }, -} diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto deleted file mode 100644 index 1c3b27872..000000000 --- a/service/proto/src/metrics.proto +++ /dev/null @@ -1,3422 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -syntax = "proto2"; - -package com_android_server_wifi; - -option java_package = "com.android.server.wifi.proto"; -option java_outer_classname = "WifiMetricsProto"; - -// The information about the Wifi events. -message WifiLog { - reserved 122; - - // Session information that gets logged for every Wifi connection. - repeated ConnectionEvent connection_event = 1; - - // Number of saved networks in the user profile. - optional int32 num_saved_networks = 2; - - // Number of open networks in the saved networks. - optional int32 num_open_networks = 3; - - // Number of legacy personal networks. - optional int32 num_legacy_personal_networks = 4; - - // Number of legacy enterprise networks. - optional int32 num_legacy_enterprise_networks = 5; - - // Does the user have location setting enabled. - optional bool is_location_enabled = 6; - - // Does the user have scanning enabled. - optional bool is_scanning_always_enabled = 7; - - // Number of times user toggled wifi using the settings menu. - optional int32 num_wifi_toggled_via_settings = 8; - - // Number of times user toggled wifi using the airplane menu. - optional int32 num_wifi_toggled_via_airplane = 9; - - // Number of networks added by the user. - optional int32 num_networks_added_by_user = 10; - - // Number of networks added by applications. - optional int32 num_networks_added_by_apps = 11; - - // Number scans that returned empty results. - optional int32 num_empty_scan_results = 12; - - // Number scans that returned at least one result. - optional int32 num_non_empty_scan_results = 13; - - // Number of single scans requests. - optional int32 num_oneshot_scans = 14; - - // Number of repeated background scans that were scheduled to the chip. - optional int32 num_background_scans = 15; - - // Error codes that a scan can result in. - enum ScanReturnCode { - - // Return Code is unknown. - SCAN_UNKNOWN = 0; - - // Scan was successful. - SCAN_SUCCESS = 1; - - // Scan was successfully started, but was interrupted. - SCAN_FAILURE_INTERRUPTED = 2; - - // Scan failed to start because of invalid configuration - // (bad channel, etc). - SCAN_FAILURE_INVALID_CONFIGURATION = 3; - - // Could not start a scan because wifi is disabled. - FAILURE_WIFI_DISABLED = 4; - - } - - // Mapping of error codes to the number of times that scans resulted - // in that error. - repeated ScanReturnEntry scan_return_entries = 16; - - message ScanReturnEntry { - - // Return code of the scan. - optional ScanReturnCode scan_return_code = 1; - - // Number of entries that were found in the scan. - optional int32 scan_results_count = 2; - } - - // State of the Wifi. - enum WifiState { - - // State is unknown. - WIFI_UNKNOWN = 0; - - // Wifi is disabled. - WIFI_DISABLED = 1; - - // Wifi is enabled. - WIFI_DISCONNECTED = 2; - - // Wifi is enabled and associated with an AP. - WIFI_ASSOCIATED = 3; - } - - // Mapping of system state to the number of times that scans were requested in - // that state - repeated WifiSystemStateEntry wifi_system_state_entries = 17; - - message WifiSystemStateEntry { - - // Current WiFi state. - optional WifiState wifi_state = 1; - - // Count of scans in state. - optional int32 wifi_state_count = 2; - - // Is screen on. - optional bool is_screen_on = 3; - } - - // Mapping of Error/Success codes to the number of background scans that resulted in it - repeated ScanReturnEntry background_scan_return_entries = 18; - - // Mapping of system state to the number of times that Background scans were requested in that - // state - repeated WifiSystemStateEntry background_scan_request_state = 19; - - // Total number of times the Watchdog of Last Resort triggered, resetting the wifi stack - optional int32 num_last_resort_watchdog_triggers = 20; - - // Total number of networks over bad association threshold when watchdog triggered - optional int32 num_last_resort_watchdog_bad_association_networks_total = 21; - - // Total number of networks over bad authentication threshold when watchdog triggered - optional int32 num_last_resort_watchdog_bad_authentication_networks_total = 22; - - // Total number of networks over bad dhcp threshold when watchdog triggered - optional int32 num_last_resort_watchdog_bad_dhcp_networks_total = 23; - - // Total number of networks over bad other threshold when watchdog triggered - optional int32 num_last_resort_watchdog_bad_other_networks_total = 24; - - // Total count of networks seen when watchdog triggered - optional int32 num_last_resort_watchdog_available_networks_total = 25; - - // Total count of triggers with atleast one bad association network - optional int32 num_last_resort_watchdog_triggers_with_bad_association = 26; - - // Total count of triggers with atleast one bad authentication network - optional int32 num_last_resort_watchdog_triggers_with_bad_authentication = 27; - - // Total count of triggers with atleast one bad dhcp network - optional int32 num_last_resort_watchdog_triggers_with_bad_dhcp = 28; - - // Total count of triggers with atleast one bad other network - optional int32 num_last_resort_watchdog_triggers_with_bad_other = 29; - - // Count of times connectivity watchdog confirmed pno is working - optional int32 num_connectivity_watchdog_pno_good = 30; - - // Count of times connectivity watchdog found pno not working - optional int32 num_connectivity_watchdog_pno_bad = 31; - - // Count of times connectivity watchdog confirmed background scan is working - optional int32 num_connectivity_watchdog_background_good = 32; - - // Count of times connectivity watchdog found background scan not working - optional int32 num_connectivity_watchdog_background_bad = 33; - - // The time duration represented by this wifi log, from start to end of capture - optional int32 record_duration_sec = 34; - - // Counts the occurrences of each individual RSSI poll level - repeated RssiPollCount rssi_poll_rssi_count = 35; - - // Total number of times WiFi connected immediately after a Last Resort Watchdog trigger, - // without new networks becoming available. - optional int32 num_last_resort_watchdog_successes = 36; - - // Total number of saved hidden networks - optional int32 num_hidden_networks = 37; - - // Total number of saved passpoint / hotspot 2.0 networks - optional int32 num_passpoint_networks = 38; - - // Total number of scan results - optional int32 num_total_scan_results = 39; - - // Total number of scan results for open networks - optional int32 num_open_network_scan_results = 40; - - // Total number of scan results for legacy personal networks - optional int32 num_legacy_personal_network_scan_results = 41; - - // Total number of scan results for legacy enterprise networks - optional int32 num_legacy_enterprise_network_scan_results = 42; - - // Total number of scan results for hidden networks - optional int32 num_hidden_network_scan_results = 43; - - // Total number of scan results for hotspot 2.0 r1 networks - optional int32 num_hotspot2_r1_network_scan_results = 44; - - // Total number of scan results for hotspot 2.0 r2 networks - optional int32 num_hotspot2_r2_network_scan_results = 45; - - // Total number of scans handled by framework (oneshot or otherwise) - optional int32 num_scans = 46; - - // Counts the occurrences of each alert reason. - repeated AlertReasonCount alert_reason_count = 47; - - // Counts the occurrences of each Wifi score - repeated WifiScoreCount wifi_score_count = 48; - - // Histogram of Soft AP Durations - repeated SoftApDurationBucket soft_ap_duration = 49; - - // Histogram of Soft AP ReturnCode - repeated SoftApReturnCodeCount soft_ap_return_code = 50; - - // Histogram of the delta between scan result RSSI and RSSI polls - repeated RssiPollCount rssi_poll_delta_count = 51; - - // List of events - repeated StaEvent sta_event_list = 52; - - // Total number of times WiFi HAL crashed. - optional int32 num_hal_crashes = 53; - - // Total number of times WiFicond crashed. - optional int32 num_wificond_crashes = 54; - - // Indicates the number of times an error was encountered in - // Wifi HAL on |WifiNative.setupInterfaceForClientMode|. - optional int32 num_setup_client_interface_failure_due_to_hal = 55; - - // Indicates the number of times an error was encountered in - // Wificond on |WifiNative.setupInterfaceForClientMode|. - optional int32 num_setup_client_interface_failure_due_to_wificond = 56; - - // Wi-Fi Aware metrics - optional WifiAwareLog wifi_aware_log = 57; - - // Number of saved Passpoint providers in user profile. - optional int32 num_passpoint_providers = 58; - - // Count of times Passpoint provider being installed. - optional int32 num_passpoint_provider_installation = 59; - - // Count of times Passpoint provivider is installed successfully. - optional int32 num_passpoint_provider_install_success = 60; - - // Count of times Passpoint provider is being uninstalled. - optional int32 num_passpoint_provider_uninstallation = 61; - - // Count of times Passpoint provider is uninstalled successfully. - optional int32 num_passpoint_provider_uninstall_success = 62; - - // Count of saved Passpoint providers device has ever connected to. - optional int32 num_passpoint_providers_successfully_connected = 63; - - // Histogram counting instances of scans with N many ScanResults with unique ssids - repeated NumConnectableNetworksBucket total_ssids_in_scan_histogram = 64; - - // Histogram counting instances of scans with N many ScanResults/bssids - repeated NumConnectableNetworksBucket total_bssids_in_scan_histogram = 65; - - // Histogram counting instances of scans with N many unique open ssids - repeated NumConnectableNetworksBucket available_open_ssids_in_scan_histogram = 66; - - // Histogram counting instances of scans with N many bssids for open networks - repeated NumConnectableNetworksBucket available_open_bssids_in_scan_histogram = 67; - - // Histogram counting instances of scans with N many unique ssids for saved networks - repeated NumConnectableNetworksBucket available_saved_ssids_in_scan_histogram = 68; - - // Histogram counting instances of scans with N many bssids for saved networks - repeated NumConnectableNetworksBucket available_saved_bssids_in_scan_histogram = 69; - - // Histogram counting instances of scans with N many unique SSIDs for open or saved networks - repeated NumConnectableNetworksBucket available_open_or_saved_ssids_in_scan_histogram = 70; - - // Histogram counting instances of scans with N many BSSIDs for open or saved networks - repeated NumConnectableNetworksBucket available_open_or_saved_bssids_in_scan_histogram = 71; - - // Histogram counting instances of scans with N many ScanResults matching unique saved passpoint providers - repeated NumConnectableNetworksBucket available_saved_passpoint_provider_profiles_in_scan_histogram = 72; - - // Histogram counting instances of scans with N many ScanResults BSSIDs matching a saved passpoint provider - repeated NumConnectableNetworksBucket available_saved_passpoint_provider_bssids_in_scan_histogram = 73; - - // Counts the number of AllSingleScanLister.onResult calls with a full band scan result - optional int32 full_band_all_single_scan_listener_results = 74; - - // Counts the number of AllSingleScanLister.onResult calls with a partial (channels) scan result - optional int32 partial_all_single_scan_listener_results = 75; - - // Pno scan metrics - optional PnoScanMetrics pno_scan_metrics = 76; - - // Histogram of "Connect to Network" notifications. - // The notification Action should be unset. - repeated ConnectToNetworkNotificationAndActionCount connect_to_network_notification_count = 77; - - // Histogram of "Connect to Network" notification user actions. - repeated ConnectToNetworkNotificationAndActionCount connect_to_network_notification_action_count = 78; - - // The number of SSIDs blacklisted from recommendation by the open network - // notification recommender - optional int32 open_network_recommender_blacklist_size = 79; - - // Is the available network notification feature turned on - optional bool is_wifi_networks_available_notification_on = 80; - - // Count of recommendation updates made by the open network notification - // recommender - optional int32 num_open_network_recommendation_updates = 81; - - // Count of connection attempts that were initiated unsuccessfully - optional int32 num_open_network_connect_message_failed_to_send = 82; - - // Histogram counting instances of scans with N many HotSpot 2.0 R1 APs - repeated NumConnectableNetworksBucket observed_hotspot_r1_aps_in_scan_histogram = 83; - - // Histogram counting instances of scans with N many HotSpot 2.0 R2 APs - repeated NumConnectableNetworksBucket observed_hotspot_r2_aps_in_scan_histogram = 84; - - // Histogram counting instances of scans with N many unique HotSpot 2.0 R1 ESS. - // Where ESS is defined as the (HESSID, ANQP Domain ID), (SSID, ANQP Domain ID) or - // (SSID, BSSID) tuple depending on AP configuration (in the above priority - // order). - repeated NumConnectableNetworksBucket observed_hotspot_r1_ess_in_scan_histogram = 85; - - // Histogram counting instances of scans with N many unique HotSpot 2.0 R2 ESS. - // Where ESS is defined as the (HESSID, ANQP Domain ID), (SSID, ANQP Domain ID) or - // (SSID, BSSID) tuple depending on AP configuration (in the above priority - // order). - repeated NumConnectableNetworksBucket observed_hotspot_r2_ess_in_scan_histogram = 86; - - // Histogram counting number of HotSpot 2.0 R1 APs per observed ESS in a scan - // (one value added per unique ESS - potentially multiple counts per single - // scan!) - repeated NumConnectableNetworksBucket observed_hotspot_r1_aps_per_ess_in_scan_histogram = 87; - - // Histogram counting number of HotSpot 2.0 R2 APs per observed ESS in a scan - // (one value added per unique ESS - potentially multiple counts per single - // scan!) - repeated NumConnectableNetworksBucket observed_hotspot_r2_aps_per_ess_in_scan_histogram = 88; - - // SoftAP event list tracking sessions and client counts in tethered mode - repeated SoftApConnectedClientsEvent soft_ap_connected_clients_events_tethered = 89; - - // SoftAP event list tracking sessions and client counts in local only mode - repeated SoftApConnectedClientsEvent soft_ap_connected_clients_events_local_only = 90; - - // WPS connection metrics - removed - reserved 91; - reserved "wps_metrics"; - - // Wifi power statistics - optional WifiPowerStats wifi_power_stats = 92; - - // Number of connectivity single scan requests. - optional int32 num_connectivity_oneshot_scans = 93; - - // WifiWake statistics - optional WifiWakeStats wifi_wake_stats = 94; - - // Histogram counting instances of scans with N many 802.11mc (RTT) supporting APs - repeated NumConnectableNetworksBucket observed_80211mc_supporting_aps_in_scan_histogram = 95; - - // Total number of times supplicant crashed. - optional int32 num_supplicant_crashes = 96; - - // Total number of times hostapd crashed. - optional int32 num_hostapd_crashes = 97; - - // Indicates the number of times an error was encountered in - // supplicant on |WifiNative.setupInterfaceForClientMode|. - optional int32 num_setup_client_interface_failure_due_to_supplicant = 98; - - // Indicates the number of times an error was encountered in - // Wifi HAL on |WifiNative.setupInterfaceForSoftApMode|. - optional int32 num_setup_soft_ap_interface_failure_due_to_hal = 99; - - // Indicates the number of times an error was encountered in - // Wifi HAL on |WifiNative.setupInterfaceForSoftApMode|. - optional int32 num_setup_soft_ap_interface_failure_due_to_wificond = 100; - - // Indicates the number of times an error was encountered in - // Wifi HAL on |WifiNative.setupInterfaceForSoftApMode|. - optional int32 num_setup_soft_ap_interface_failure_due_to_hostapd = 101; - - // Indicates the number of times we got an interface down in client mode. - optional int32 num_client_interface_down = 102; - - // Indicates the number of times we got an interface down in softap mode. - optional int32 num_soft_ap_interface_down = 103; - - // Indicates the number of scan requests from external apps. - optional int32 num_external_app_oneshot_scan_requests = 104; - - // Indicates the number of times a scan request from an external foreground app was throttled. - optional int32 num_external_foreground_app_oneshot_scan_requests_throttled = 105; - - // Indicates the number of times a scan request from an external background app was throttled. - optional int32 num_external_background_app_oneshot_scan_requests_throttled = 106; - - // WifiLastResortWatchdog time milliseconds delta between trigger and first connection success - optional int64 watchdog_trigger_to_connection_success_duration_ms = 107 [default = -1]; - - // The number of times wifi experienced failures after watchdog has already been triggered and is - // waiting for a connection success - optional int64 watchdog_total_connection_failure_count_after_trigger = 108; - - // Number of times DFS channel scans are requested in single scan requests. - optional int32 num_oneshot_has_dfs_channel_scans = 109; - - // Wi-Fi RTT metrics - optional WifiRttLog wifi_rtt_log = 110; - - // Flag which indicates if Connected MAC Randomization is enabled - optional bool is_mac_randomization_on = 111 [default = false]; - - // Number of radio mode changes to MCC (Multi channel concurrency). - optional int32 num_radio_mode_change_to_mcc = 112; - - // Number of radio mode changes to SCC (Single channel concurrency). - optional int32 num_radio_mode_change_to_scc = 113; - - // Number of radio mode changes to SBS (Single band simultaneous). - optional int32 num_radio_mode_change_to_sbs = 114; - - // Number of radio mode changes to DBS (Dual band simultaneous). - optional int32 num_radio_mode_change_to_dbs = 115; - - // Number of times the firmware picked a SoftAp channel not satisfying user band preference. - optional int32 num_soft_ap_user_band_preference_unsatisfied = 116; - - // Identifier for experimental scoring parameter settings. - optional string score_experiment_id = 117; - - // Data on wifi radio usage - optional WifiRadioUsage wifi_radio_usage = 118; - - // Stores settings values used for metrics testing. - optional ExperimentValues experiment_values = 119; - - // List of WifiIsUnusableEvents which get logged when we notice that WiFi is unusable. - // Collected only when WIFI_IS_UNUSABLE_EVENT_METRICS_ENABLED Settings is enabled. - repeated WifiIsUnusableEvent wifi_is_unusable_event_list = 120; - - // Counts the occurrences of each link speed (Mbps) level - // with rssi (dBm) and rssi^2 sums (dBm^2) - repeated LinkSpeedCount link_speed_counts = 121; - - // Hardware revision (EVT, DVT, PVT etc.) - optional string hardware_revision = 124; - - // Total wifi link layer usage data over the logging duration in ms. - optional WifiLinkLayerUsageStats wifi_link_layer_usage_stats = 125; - - // Multiple lists of timestamped link layer stats with labels to represent whether wifi is usable - repeated WifiUsabilityStats wifi_usability_stats_list = 126; - - // Counts the occurrences of each Wifi usability score provided by external app - repeated WifiUsabilityScoreCount wifi_usability_score_count = 127; - - // List of PNO scan stats, one element for each mobility state - repeated DeviceMobilityStatePnoScanStats mobility_state_pno_stats_list = 128; - - // Wifi p2p statistics - optional WifiP2pStats wifi_p2p_stats = 129; - - // Easy Connect (DPP) metrics - optional WifiDppLog wifi_dpp_log = 130; - - // Number of Enhanced Open (OWE) networks in the saved networks. - optional int32 num_enhanced_open_networks = 131; - - // Number of WPA3-Personal networks. - optional int32 num_wpa3_personal_networks = 132; - - // Number of WPA3-Enterprise networks. - optional int32 num_wpa3_enterprise_networks = 133; - - // Total number of scan results for Enhanced open networks - optional int32 num_enhanced_open_network_scan_results = 134; - - // Total number of scan results for WPA3-Personal networks - optional int32 num_wpa3_personal_network_scan_results = 135; - - // Total number of scan results for WPA3-Enterprise networks - optional int32 num_wpa3_enterprise_network_scan_results = 136; - - // WifiConfigStore read/write metrics. - optional WifiConfigStoreIO wifi_config_store_io = 137; - - // Total number of saved networks with mac randomization enabled. - optional int32 num_saved_networks_with_mac_randomization = 138; - - // Link Probe metrics - optional LinkProbeStats link_probe_stats = 139; - - // List of NetworkSelectionExperimentDecisions stats for each experiment - repeated NetworkSelectionExperimentDecisions network_selection_experiment_decisions_list = 140; - - // Network Request API surface metrics. - optional WifiNetworkRequestApiLog wifi_network_request_api_log = 141; - - // Network Suggestion API surface metrics. - optional WifiNetworkSuggestionApiLog wifi_network_suggestion_api_log = 142; - - // WifiLock statistics - optional WifiLockStats wifi_lock_stats = 143; - - // Stats on number of times Wi-Fi is turned on/off though the WifiManager#setWifiEnabled API - optional WifiToggleStats wifi_toggle_stats = 144; - - // Number of times WifiManager#addOrUpdateNetwork is called. - optional int32 num_add_or_update_network_calls = 145; - - // Number of times WifiManager#enableNetwork is called. - optional int32 num_enable_network_calls = 146; - - // Passpoint provison metrics - optional PasspointProvisionStats passpoint_provision_stats = 147; - - // Histogram of the EAP method type of all installed Passpoint profiles for R1 - repeated PasspointProfileTypeCount installed_passpoint_profile_type_for_r1 = 123; - - // Histogram of the EAP method type of all installed Passpoint profiles for R2 - repeated PasspointProfileTypeCount installed_passpoint_profile_type_for_r2 = 148; - - // Histogram of Tx link speed at 2G - repeated Int32Count tx_link_speed_count_2g = 149; - - // Histogram of Tx link speed at 5G low band - repeated Int32Count tx_link_speed_count_5g_low = 150; - - // Histogram of Tx link speed at 5G middle band - repeated Int32Count tx_link_speed_count_5g_mid = 151; - - // Histogram of Tx link speed at 5G high band - repeated Int32Count tx_link_speed_count_5g_high = 152; - - // Histogram of Rx link speed at 2G - repeated Int32Count rx_link_speed_count_2g = 153; - - // Histogram of Rx link speed at 5G low band - repeated Int32Count rx_link_speed_count_5g_low = 154; - - // Histogram of Rx link speed at 5G middle band - repeated Int32Count rx_link_speed_count_5g_mid = 155; - - // Histogram of Rx link speed at 5G high band - repeated Int32Count rx_link_speed_count_5g_high = 156; - - // Count of IP renewal failures. - optional int32 num_ip_renewal_failure = 157; - - // Metrics collected by health monitor - optional HealthMonitorMetrics health_monitor_metrics = 158; - - // Metrics related to the BssidBlocklistMonitor - optional BssidBlocklistStats bssid_blocklist_stats = 159; - - // Connection duration under various health conditions - optional ConnectionDurationStats connection_duration_stats = 160; - - // Number of WAPI-Personal saved networks. - optional int32 num_wapi_personal_networks = 161; - - // Number of WAPI-Enterprise saved networks. - optional int32 num_wapi_enterprise_networks = 162; - - // Total number of scan results for WAPI-Personal networks - optional int32 num_wapi_personal_network_scan_results = 163; - - // Total number of scan results for WAPI-Enterprise networks - optional int32 num_wapi_enterprise_network_scan_results = 164; - - // Is the external WiFi connected network scorer from OEM extension module turned on - optional bool is_external_wifi_scorer_on = 165 [default = false]; - - // Metrics related to Wi-Fi off - optional WifiOffMetrics wifi_off_metrics = 166; - - // Total number of scan results for MBO supported networks - optional int32 num_mbo_supported_network_scan_results = 167; - - // Total number of scan results for MBO cellular data aware networks - optional int32 num_mbo_cellular_data_aware_network_scan_results = 168; - - // Total number of scan results for OCE supported networks - optional int32 num_oce_supported_network_scan_results = 169; - - // Total number of scan results for FILS supported networks - optional int32 num_fils_supported_network_scan_results = 170; - - // Total number of bssids filtered from network selection due to mbo association - // disallowed indication - optional int32 num_bssid_filtered_due_to_mbo_assoc_disallow_ind = 171; - - // Total number of connection to network supporting MBO - optional int32 num_connect_to_network_supporting_mbo = 172; - - // Total number of connection to network supporting OCE - optional int32 num_connect_to_network_supporting_oce = 173; - - // Total number of scans triggered due to steering request from AP - optional int32 num_force_scan_due_to_steering_request = 174; - - // Total number of cellular switch requests from MBO supported AP - optional int32 num_mbo_cellular_switch_request = 175; - - // Total number of connect request to AP adding FILS AKM - optional int32 num_connect_request_with_fils_akm = 176; - - // Total number of successful L2 connection through FILS authentication - optional int32 num_l2_connection_through_fils_authentication = 177; - - // Metrics related to limitation in soft ap config - optional SoftApConfigLimitationMetrics soft_ap_config_limitation_metrics = 178; - - // WiFi channel utilization histogram of various RF bands - optional ChannelUtilizationHistogram channel_utilization_histogram = 179; - - // WiFi Tx and Rx throughput histogram at various RF bands - optional ThroughputMbpsHistogram throughput_mbps_histogram = 180; - - // Total number of steering requests which include MBO assoc retry delay - optional int32 num_steering_request_including_mbo_assoc_retry_delay = 181; - - // Total number of scan results from 11ax network - optional int32 num_11ax_network_scan_results = 182; - - // Total number of scan results from 6GHz band - optional int32 num_6g_network_scan_results = 183; - - // Initial partial scan stats - optional InitPartialScanStats init_partial_scan_stats = 184; - - // Total number of scan results for hotspot 2.0 r3 networks - optional int32 num_hotspot2_r3_network_scan_results = 185; - - // Histogram counting instances of scans with N many HotSpot 2.0 R3 APs - repeated NumConnectableNetworksBucket observed_hotspot_r3_aps_in_scan_histogram = 186; - - // Histogram counting number of HotSpot 2.0 R3 APs per observed ESS in a scan - // (one value added per unique ESS - potentially multiple counts per single - // scan!) - repeated NumConnectableNetworksBucket observed_hotspot_r3_aps_per_ess_in_scan_histogram = 187; - - // Histogram counting instances of scans with N many unique HotSpot 2.0 R3 ESS. - // Where ESS is defined as the (HESSID, ANQP Domain ID), (SSID, ANQP Domain ID) or - // (SSID, BSSID) tuple depending on AP configuration (in the above priority - // order). - repeated NumConnectableNetworksBucket observed_hotspot_r3_ess_in_scan_histogram = 188; - - // Total number of Passpoint providers with no Root CA in their profile. - optional int32 num_passpoint_provider_with_no_root_ca = 189; - - // Total number of Passpoint providers with self-signed root CA in their profile. - optional int32 num_passpoint_provider_with_self_signed_root_ca = 190; - - // Total number of Passpoint providers with subscription expiration date in their profile. - optional int32 num_passpoint_provider_with_subscription_expiration = 191; - - // List of user initiated actions - repeated UserActionEvent user_action_events = 192; - - // Does the user have wifi verbose logging enabled. - optional bool is_verbose_logging_enabled = 193; - - // Does the user have enhanced MAC randomization forced to on. - optional bool is_enhanced_mac_randomization_force_enabled = 194; - - // Metered stats for saved networks. - optional MeteredNetworkStats metered_network_stats_saved = 195; - - // Metered stats for suggestion networks. - optional MeteredNetworkStats metered_network_stats_suggestion = 196; - - // Does the user have wifi wake enabled. - optional bool is_wifi_wake_enabled = 197; - - // User reaction to the carrier or suggestion app approval UI. - optional UserReactionToApprovalUiEvent user_reaction_to_approval_ui_event = 198; - - // Number of connection with different BSSID between framework and firmware selection. - optional int32 num_bssid_different_selection_between_framework_and_firmware = 199; - - // Metrics about carrier wifi network. - optional CarrierWifiMetrics carrier_wifi_metrics = 200; - - // Long version code of wifi mainline module, 0 means not available. - optional int64 mainline_module_version = 201; - - // Histogram of Tx link speed at 6G low band - repeated Int32Count tx_link_speed_count_6g_low = 202; - - // Histogram of Tx link speed at 6G middle band - repeated Int32Count tx_link_speed_count_6g_mid = 203; - - // Histogram of Tx link speed at 6G high band - repeated Int32Count tx_link_speed_count_6g_high = 204; - - // Histogram of Rx link speed at 6G low band - repeated Int32Count rx_link_speed_count_6g_low = 205; - - // Histogram of Rx link speed at 6G middle band - repeated Int32Count rx_link_speed_count_6g_mid = 206; - - // Histogram of Rx link speed at 6G high band - repeated Int32Count rx_link_speed_count_6g_high = 207; -} - -// Information that gets logged for every WiFi connection. -message RouterFingerPrint { - - enum RoamType { - - // Type is unknown. - ROAM_TYPE_UNKNOWN = 0; - - // No roaming - usually happens on a single band (2.4 GHz) router. - ROAM_TYPE_NONE = 1; - - // Enterprise router. - ROAM_TYPE_ENTERPRISE = 2; - - // DBDC => Dual Band Dual Concurrent essentially a router that - // supports both 2.4 GHz and 5 GHz bands. - ROAM_TYPE_DBDC = 3; - } - - enum Auth { - - // Auth is unknown. - AUTH_UNKNOWN = 0; - - // No authentication. - AUTH_OPEN = 1; - - // If the router uses a personal authentication. - AUTH_PERSONAL = 2; - - // If the router is setup for enterprise authentication. - AUTH_ENTERPRISE = 3; - } - - enum RouterTechnology { - - // Router is unknown. - ROUTER_TECH_UNKNOWN = 0; - - // Router Channel A. - ROUTER_TECH_A = 1; - - // Router Channel B. - ROUTER_TECH_B = 2; - - // Router Channel G. - ROUTER_TECH_G = 3; - - // Router Channel N. - ROUTER_TECH_N = 4; - - // Router Channel AC. - ROUTER_TECH_AC = 5; - - // When the channel is not one of the above. - ROUTER_TECH_OTHER = 6; - - // Router Channel AX. - ROUTER_TECH_AX = 7; - } - - enum EapMethod { - - // No EAP method used - TYPE_EAP_UNKNOWN = 0; - - // EAP with Transport Layer Security - TYPE_EAP_TLS = 1; - - // EAP with Tunneled Transport Layer Security - TYPE_EAP_TTLS = 2; - - // EAP with Subscriber Identity Module [RFC-4186] - TYPE_EAP_SIM = 3; - - // EAP with Authentication and Key Agreement [RFC-4187] - TYPE_EAP_AKA = 4; - - // EAP with Authentication and Key Agreement Prime [RFC-5448] - TYPE_EAP_AKA_PRIME = 5; - - // Protected EAP - TYPE_EAP_PEAP = 6; - - // EAP for Hotspot 2.0 r2 OSEN - TYPE_EAP_UNAUTH_TLS = 7; - - // EAP with Password - TYPE_EAP_PWD = 8; - - // EAP with WAPI certifcate - TYPE_EAP_WAPI_CERT = 9; - } - - enum AuthPhase2Method { - - // No phase2 method - TYPE_PHASE2_NONE = 0; - - // Password Authentication Protocol - TYPE_PHASE2_PAP = 1; - - // Microsoft Challenge Handshake Authentication Protocol - TYPE_PHASE2_MSCHAP = 2; - - // Microsoft Challenge Handshake Authentication Protocol v2 - TYPE_PHASE2_MSCHAPV2 = 3; - - // Generic Token Card - TYPE_PHASE2_GTC = 4; - - // EAP-Subscriber Identity Module [RFC-4186] - TYPE_PHASE2_SIM = 5; - - // EAP-Authentication and Key Agreement [RFC-4187] - TYPE_PHASE2_AKA = 6; - - // EAP-Authentication and Key Agreement Prime [RFC-5448] - TYPE_PHASE2_AKA_PRIME = 7; - } - - enum OcspType { - // Do not use OCSP stapling - TYPE_OCSP_NONE = 0; - - // Try to use OCSP stapling, but not require response - TYPE_OCSP_REQUEST_CERT_STATUS = 1; - - // Require valid OCSP stapling response - TYPE_OCSP_REQUIRE_CERT_STATUS = 2; - - // Require valid OCSP stapling response for all not-trusted certificates - // in the server certificate chain - TYPE_OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS = 3; - } - - optional RoamType roam_type = 1; - - // Channel on which the connection takes place. - optional int32 channel_info = 2; - - // DTIM setting of the router. - optional int32 dtim = 3; - - // Authentication scheme of the router. - optional Auth authentication = 4; - - // If the router is hidden. - optional bool hidden = 5; - - // Channel information. - optional RouterTechnology router_technology = 6; - - // whether ipv6 is supported. - optional bool supports_ipv6 = 7; - - // If the router is a passpoint / hotspot 2.0 network - optional bool passpoint = 8; - - // EAP method used by the enterprise network - optional EapMethod eap_method = 9; - - // Phase 2 authentication method after setting up a secure channel - optional AuthPhase2Method auth_phase2_method = 10; - - // Online certificate status protocol stapling type - optional OcspType ocsp_type = 11; - - // PMK caching enablement - optional bool pmk_cache_enabled = 12; - - // Max Tx link speed (in Mbps) supported by current network (STA and AP) - optional int32 max_supported_tx_link_speed_mbps = 13; - - // Max Rx link speed (in Mbps) supported by current network (STA and AP) - optional int32 max_supported_rx_link_speed_mbps = 14; -} - -message ConnectionEvent { - - // Roam Type. - enum RoamType { - - // Type is unknown. - ROAM_UNKNOWN = 0; - - // No roaming. - ROAM_NONE = 1; - - // DBDC roaming. - ROAM_DBDC = 2; - - // Enterprise roaming. - ROAM_ENTERPRISE = 3; - - // User selected roaming. - ROAM_USER_SELECTED = 4; - - // Unrelated. - ROAM_UNRELATED = 5; - } - - // Connectivity Level Failure. - enum ConnectivityLevelFailure { - - // Failure is unknown. - HLF_UNKNOWN = 0; - - // No failure. - HLF_NONE = 1; - - // DHCP failure. - HLF_DHCP = 2; - - // No internet connection. - HLF_NO_INTERNET = 3; - - // No internet connection. - HLF_UNWANTED = 4; - } - - // Level 2 failure reason. - enum Level2FailureReason { - - // Unknown default - FAILURE_REASON_UNKNOWN = 0; - - // The reason code if there is no error during authentication. It could - // also imply that there no authentication in progress. - AUTH_FAILURE_NONE = 1; - - // The reason code if there was a timeout authenticating. - AUTH_FAILURE_TIMEOUT = 2; - - // The reason code if there was a wrong password while authenticating. - AUTH_FAILURE_WRONG_PSWD = 3; - - // The reason code if there was EAP failure while authenticating. - AUTH_FAILURE_EAP_FAILURE = 4; - - // The reason code if the AP can no longer accept new clients. - ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA = 5; - } - - // Entity that recommended connecting to this network. - enum ConnectionNominator { - // Unknown nominator - NOMINATOR_UNKNOWN = 0; - - // User selected network manually - NOMINATOR_MANUAL = 1; - - // Saved network - NOMINATOR_SAVED = 2; - - // Suggestion API - NOMINATOR_SUGGESTION = 3; - - // Passpoint - NOMINATOR_PASSPOINT = 4; - - // Carrier suggestion - NOMINATOR_CARRIER = 5; - - // External scorer - NOMINATOR_EXTERNAL_SCORED = 6; - - // Network Specifier - NOMINATOR_SPECIFIER = 7; - - // User connected choice override - NOMINATOR_SAVED_USER_CONNECT_CHOICE = 8; - - // Open Network Available Pop-up - NOMINATOR_OPEN_NETWORK_AVAILABLE = 9; - } - - enum NetworkType { - // Unknown network type - TYPE_UNKNOWN = 0; - - // WPA2 network - TYPE_WPA2 = 1; - - // WPA3 network - TYPE_WPA3 = 2; - - // Passpoint network - TYPE_PASSPOINT = 3; - - // EAP network, excluding passpoint - TYPE_EAP = 4; - - // OWE network - TYPE_OWE = 5; - - // Open network - TYPE_OPEN = 6; - - // WAPI network - TYPE_WAPI = 7; - } - - enum NetworkCreator { - // This network is created by an unknown app. - CREATOR_UNKNOWN = 0; - - // This network is created by the user. - CREATOR_USER = 1; - - // This network is created by a carrier app. - CREATOR_CARRIER = 2; - } - - // Start time of the connection, in milliseconds since Unix epoch (1970-01-01). - optional int64 start_time_millis = 1;// [(datapol.semantic_type) = ST_TIMESTAMP]; - - // Duration to connect. - optional int32 duration_taken_to_connect_millis = 2; - - // Router information. - optional RouterFingerPrint router_fingerprint = 3; - - // RSSI at the start of the connection. - optional int32 signal_strength = 4; - - // Roam Type. - optional RoamType roam_type = 5; - - // Result of the connection. - optional int32 connection_result = 6; - - // Reasons for level 2 failure (needs to be coordinated with wpa-supplicant). - optional int32 level_2_failure_code = 7; - - // Failures that happen at the connectivity layer. - optional ConnectivityLevelFailure connectivity_level_failure_code = 8; - - // Has bug report been taken. - optional bool automatic_bug_report_taken = 9; - - // Connection is using locally generated random MAC address. - optional bool use_randomized_mac = 10 [default = false]; - - // Who chose to connect. - optional ConnectionNominator connection_nominator = 11; - - // The currently running network selector when this connection event occurred. - optional int32 network_selector_experiment_id = 12; - - // Breakdown of level_2_failure_code with more detailed reason. - optional Level2FailureReason level_2_failure_reason = 13 - [default = FAILURE_REASON_UNKNOWN]; - - // Connection is using an aggressively generated random MAC address. - optional bool use_aggressive_mac = 14; - - // Number of BSSIDs for this network that were excluded from network selection. - optional int32 num_bssid_in_blocklist = 15; - - // The type of network for this connection. - optional NetworkType network_type = 16; - - // UID of the app that created this network. - optional NetworkCreator network_creator = 17; - - // Whether the screen is on when the connection event starts - optional bool screen_on = 18; - - // Number of consecutive connection failures with the same SSID at high RSSI - // before current connection event. Any connection failure at low RSSI in the - // middle won't break the streak count. The count is cleared after - // a network disconnection event. - optional int32 num_consecutive_connection_failure = 19 [default = -1]; - - // Indicates if the profile used for the connection was provisioned by Passpoint OSU server - optional bool is_osu_provisioned = 20; -} - -// Number of occurrences of a specific RSSI poll rssi value -message RssiPollCount { - // RSSI - optional int32 rssi = 1; - - // Number of RSSI polls with 'rssi' - optional int32 count = 2; - - // Beacon frequency of the channel in MHz - optional int32 frequency = 3; -} - -// Number of occurrences of a specific alert reason value -message AlertReasonCount { - // Alert reason - optional int32 reason = 1; - - // Number of alerts with |reason|. - optional int32 count = 2; -} - -// Counts the number of instances of a specific Wifi Score calculated by WifiScoreReport -message WifiScoreCount { - // Wifi Score - optional int32 score = 1; - - // Number of Wifi score reports with this score - optional int32 count = 2; -} - -// Counts the number of instances of a specific Wifi Usability Score -message WifiUsabilityScoreCount { - // Wifi Usability Score - optional int32 score = 1; - - // Number of Wifi score reports with this score - optional int32 count = 2; -} - -// Number of occurrences of a specific link speed (Mbps) -// and sum of rssi (dBm) and rssi^2 (dBm^2) -message LinkSpeedCount { - // Link speed (Mbps) - optional int32 link_speed_mbps = 1; - - // Number of RSSI polls with link_speed - optional int32 count = 2; - - // Sum of absolute values of rssi values (dBm) - optional int32 rssi_sum_dbm = 3; - - // Sum of squares of rssi values (dBm^2) - optional int64 rssi_sum_of_squares_dbm_sq = 4; -} - - -// Number of occurrences of Soft AP session durations -message SoftApDurationBucket { - // Bucket covers duration : [duration_sec, duration_sec + bucket_size_sec) - // The (inclusive) lower bound of Soft AP session duration represented by this bucket - optional int32 duration_sec = 1; - - // The size of this bucket - optional int32 bucket_size_sec = 2; - - // Number of soft AP session durations that fit into this bucket - optional int32 count = 3; -} - -// Number of occurrences of a soft AP session return code -message SoftApReturnCodeCount { - - enum SoftApStartResult { - - // SoftApManager return code unknown - SOFT_AP_RETURN_CODE_UNKNOWN = 0; - - // SoftAp started successfully - SOFT_AP_STARTED_SUCCESSFULLY = 1; - - // Catch all for failures with no specific failure reason - SOFT_AP_FAILED_GENERAL_ERROR = 2; - - // SoftAp failed to start due to NO_CHANNEL error - SOFT_AP_FAILED_NO_CHANNEL = 3; - - // SoftAp failed to start due to unsupported configuration error - SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION = 4; - } - - // Historical, no longer used for writing as of 01/2017. - optional int32 return_code = 1 [deprecated = true]; - - // Occurrences of this soft AP return code - optional int32 count = 2; - - // Result of attempt to start SoftAp - optional SoftApStartResult start_result = 3; -} - -message StaEvent { - message ConfigInfo { - // The set of key management protocols supported by this configuration. - optional uint32 allowed_key_management = 1 [default = 0]; - - // The set of security protocols supported by this configuration. - optional uint32 allowed_protocols = 2 [default = 0]; - - // The set of authentication protocols supported by this configuration. - optional uint32 allowed_auth_algorithms = 3 [default = 0]; - - // The set of pairwise ciphers for WPA supported by this configuration. - optional uint32 allowed_pairwise_ciphers = 4 [default = 0]; - - // The set of group ciphers supported by this configuration. - optional uint32 allowed_group_ciphers = 5; - - // Is this a 'hidden network' - optional bool hidden_ssid = 6; - - // Is this a Hotspot 2.0 / passpoint network - optional bool is_passpoint = 7; - - // Is this an 'ephemeral' network (Not in saved network list, recommended externally) - optional bool is_ephemeral = 8; - - // Has a successful connection ever been established using this WifiConfiguration - optional bool has_ever_connected = 9; - - // RSSI of the scan result candidate associated with this WifiConfiguration - optional int32 scan_rssi = 10 [default = -127]; - - // Frequency of the scan result candidate associated with this WifiConfiguration - optional int32 scan_freq = 11 [default = -1]; - } - - enum EventType { - // Default/Invalid event - TYPE_UNKNOWN = 0; - - // Supplicant Association Rejection event. Code contains the 802.11 - TYPE_ASSOCIATION_REJECTION_EVENT = 1; - - // Supplicant L2 event, - TYPE_AUTHENTICATION_FAILURE_EVENT = 2; - - // Supplicant L2 event - TYPE_NETWORK_CONNECTION_EVENT = 3; - - // Supplicant L2 event - TYPE_NETWORK_DISCONNECTION_EVENT = 4; - - // Supplicant L2 event - TYPE_SUPPLICANT_STATE_CHANGE_EVENT = 5; - - // Supplicant L2 event - TYPE_CMD_ASSOCIATED_BSSID = 6; - - // IP Manager successfully completed IP Provisioning - TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL = 7; - - // IP Manager failed to complete IP Provisioning - TYPE_CMD_IP_CONFIGURATION_LOST = 8; - - // IP Manager lost reachability to network neighbors - TYPE_CMD_IP_REACHABILITY_LOST = 9; - - // Indicator that Supplicant is targeting a BSSID for roam/connection - TYPE_CMD_TARGET_BSSID = 10; - - // Wifi framework is initiating a connection attempt - TYPE_CMD_START_CONNECT = 11; - - // Wifi framework is initiating a roaming connection attempt - TYPE_CMD_START_ROAM = 12; - - // SystemAPI connect() command, Settings App - TYPE_CONNECT_NETWORK = 13; - - // Network Agent has validated the internet connection (Captive Portal Check success, or user - // validation) - TYPE_NETWORK_AGENT_VALID_NETWORK = 14; - - // Framework initiated disconnect. Sometimes generated to give an extra reason for a disconnect - // Should typically be followed by a NETWORK_DISCONNECTION_EVENT with a local_gen = true - TYPE_FRAMEWORK_DISCONNECT = 15; - - // The NetworkAgent score for wifi has changed in a way that may impact - // connectivity - TYPE_SCORE_BREACH = 16; - - // Framework changed Sta interface MAC address - TYPE_MAC_CHANGE = 17; - - // Wifi is turned on - TYPE_WIFI_ENABLED = 18; - - // Wifi is turned off - TYPE_WIFI_DISABLED = 19; - - // The NetworkAgent Wifi usability score has changed in a way that may - // impact connectivity - TYPE_WIFI_USABILITY_SCORE_BREACH = 20; - - // Link probe was performed - TYPE_LINK_PROBE = 21; - } - - enum FrameworkDisconnectReason { - // default/none/unknown value - DISCONNECT_UNKNOWN = 0; - - // API DISCONNECT - DISCONNECT_API = 1; - - // Some framework internal reason (generic) - DISCONNECT_GENERIC = 2; - - // Network Agent network validation failed, user signaled network unwanted - DISCONNECT_UNWANTED = 3; - - // Roaming timed out - DISCONNECT_ROAM_WATCHDOG_TIMER = 4; - - // P2P service requested wifi disconnect - DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST = 5; - - // SIM was removed while using a SIM config - DISCONNECT_RESET_SIM_NETWORKS = 6; - } - - // Authentication Failure reasons as reported through the API. - enum AuthFailureReason { - // Unknown default - AUTH_FAILURE_UNKNOWN = 0; - - // The reason code if there is no error during authentication. It could also imply that there no - // authentication in progress, - AUTH_FAILURE_NONE = 1; - - // The reason code if there was a timeout authenticating. - AUTH_FAILURE_TIMEOUT = 2; - - // The reason code if there was a wrong password while authenticating. - AUTH_FAILURE_WRONG_PSWD = 3; - - // The reason code if there was EAP failure while authenticating. - AUTH_FAILURE_EAP_FAILURE = 4; - } - - // What event was this - optional EventType type = 1; - - // 80211 death reason code, relevant to NETWORK_DISCONNECTION_EVENTs - optional int32 reason = 2 [default = -1]; - - // 80211 Association Status code, relevant to ASSOCIATION_REJECTION_EVENTs - optional int32 status = 3 [default = -1]; - - // Designates whether a NETWORK_DISCONNECT_EVENT was by the STA or AP - optional bool local_gen = 4 [default = false]; - - // Network information from the WifiConfiguration of a framework initiated connection attempt - optional ConfigInfo config_info = 5; - - // RSSI from the last rssi poll (Only valid for active connections) - optional int32 last_rssi = 6 [default = -127]; - - // Link speed from the last rssi poll (Only valid for active connections) - optional int32 last_link_speed = 7 [default = -1]; - - // Frequency from the last rssi poll (Only valid for active connections) - optional int32 last_freq = 8 [default = -1]; - - // Enum used to define bit positions in the supplicant_state_change_bitmask - // See {@code frameworks/base/wifi/java/android/net/wifi/SupplicantState.java} for documentation - enum SupplicantState { - STATE_DISCONNECTED = 0; - - STATE_INTERFACE_DISABLED = 1; - - STATE_INACTIVE = 2; - - STATE_SCANNING = 3; - - STATE_AUTHENTICATING = 4; - - STATE_ASSOCIATING = 5; - - STATE_ASSOCIATED = 6; - - STATE_FOUR_WAY_HANDSHAKE = 7; - - STATE_GROUP_HANDSHAKE = 8; - - STATE_COMPLETED = 9; - - STATE_DORMANT = 10; - - STATE_UNINITIALIZED = 11; - - STATE_INVALID = 12; - } - - // Bit mask of all supplicant state changes that occurred since the last event - optional uint32 supplicant_state_changes_bitmask = 9 [default = 0]; - - // The number of milliseconds that have elapsed since the device booted - optional int64 start_time_millis = 10 [default = 0]; - - optional FrameworkDisconnectReason framework_disconnect_reason = 11 [default = DISCONNECT_UNKNOWN]; - - // Flag which indicates if an association rejection event occurred due to a timeout - optional bool association_timed_out = 12 [default = false]; - - // Authentication failure reason, as reported by WifiManager (calculated from state & deauth code) - optional AuthFailureReason auth_failure_reason = 13 [default = AUTH_FAILURE_UNKNOWN]; - - // NetworkAgent score of connected wifi - optional int32 last_score = 14 [default = -1]; - - // NetworkAgent Wifi usability score of connected wifi - optional int32 last_wifi_usability_score = 15 [default = -1]; - - // Prediction horizon (in second) of Wifi usability score provided by external - // system app - optional int32 last_prediction_horizon_sec = 16 [default = -1]; - - // Only valid if event type == TYPE_LINK_PROBE. - // true if link probe succeeded, false otherwise. - optional bool link_probe_was_success = 17; - - // Only valid if event type == TYPE_LINK_PROBE and link_probe_was_success == true. - // Elapsed time, in milliseconds, of a successful link probe. - optional int32 link_probe_success_elapsed_time_ms = 18; - - // Only valid if event type == TYPE_LINK_PROBE and link_probe_was_success == false. - // Failure reason for an unsuccessful link probe. - optional LinkProbeStats.LinkProbeFailureReason link_probe_failure_reason = 19; - - // Number of bytes transmitted across mobile networks since device boot. - optional int64 mobile_tx_bytes = 20 [default = -1]; - - // // Number of bytes received across mobile networks since device boot. - optional int64 mobile_rx_bytes = 21 [default = -1]; - - // Number of bytes transmitted since device boot. - optional int64 total_tx_bytes = 22 [default = -1]; - - // Number of bytes received since device boot. - optional int64 total_rx_bytes = 23 [default = -1]; - - // Whether screen is on when the event happens - optional bool screen_on = 24; - - // Whether cellular data network is available - optional bool is_cellular_data_available = 25; - - //Whether Adaptive Connectivity is enabled - optional bool is_adaptive_connectivity_enabled = 26; -} - -// Wi-Fi Aware metrics -message WifiAwareLog { - // total number of unique apps that used Aware (measured on attach) - optional int32 num_apps = 1; - - // total number of unique apps that used an identity callback when attaching - optional int32 num_apps_using_identity_callback = 2; - - // maximum number of attaches for an app - optional int32 max_concurrent_attach_sessions_in_app = 3; - - // histogram of attach request results - repeated NanStatusHistogramBucket histogram_attach_session_status = 4; - - // maximum number of concurrent publish sessions in a single app - optional int32 max_concurrent_publish_in_app = 5; - - // maximum number of concurrent subscribe sessions in a single app - optional int32 max_concurrent_subscribe_in_app = 6; - - // maximum number of concurrent discovery (publish+subscribe) sessions in a single app - optional int32 max_concurrent_discovery_sessions_in_app = 7; - - // maximum number of concurrent publish sessions in the system - optional int32 max_concurrent_publish_in_system = 8; - - // maximum number of concurrent subscribe sessions in the system - optional int32 max_concurrent_subscribe_in_system = 9; - - // maximum number of concurrent discovery (publish+subscribe) sessions in the system - optional int32 max_concurrent_discovery_sessions_in_system = 10; - - // histogram of publish request results - repeated NanStatusHistogramBucket histogram_publish_status = 11; - - // histogram of subscribe request results - repeated NanStatusHistogramBucket histogram_subscribe_status = 12; - - // number of unique apps which experienced a discovery session creation failure due to lack of - // resources - optional int32 num_apps_with_discovery_session_failure_out_of_resources = 13; - - // histogram of create ndp request results - repeated NanStatusHistogramBucket histogram_request_ndp_status = 14; - - // histogram of create ndp out-of-band (OOB) request results - repeated NanStatusHistogramBucket histogram_request_ndp_oob_status = 15; - - // maximum number of concurrent active data-interfaces (NDI) in a single app - optional int32 max_concurrent_ndi_in_app = 19; - - // maximum number of concurrent active data-interfaces (NDI) in the system - optional int32 max_concurrent_ndi_in_system = 20; - - // maximum number of concurrent data-paths (NDP) in a single app - optional int32 max_concurrent_ndp_in_app = 21; - - // maximum number of concurrent data-paths (NDP) in the system - optional int32 max_concurrent_ndp_in_system = 22; - - // maximum number of concurrent secure data-paths (NDP) in a single app - optional int32 max_concurrent_secure_ndp_in_app = 23; - - // maximum number of concurrent secure data-paths (NDP) in the system - optional int32 max_concurrent_secure_ndp_in_system = 24; - - // maximum number of concurrent data-paths (NDP) per data-interface (NDI) - optional int32 max_concurrent_ndp_per_ndi = 25; - - // histogram of durations of Aware being available - repeated HistogramBucket histogram_aware_available_duration_ms = 26; - - // histogram of durations of Aware being enabled - repeated HistogramBucket histogram_aware_enabled_duration_ms = 27; - - // histogram of duration (in ms) of attach sessions - repeated HistogramBucket histogram_attach_duration_ms = 28; - - // histogram of duration (in ms) of publish sessions - repeated HistogramBucket histogram_publish_session_duration_ms = 29; - - // histogram of duration (in ms) of subscribe sessions - repeated HistogramBucket histogram_subscribe_session_duration_ms = 30; - - // histogram of duration (in ms) of data-paths (NDP) - repeated HistogramBucket histogram_ndp_session_duration_ms = 31; - - // histogram of usage (in MB) of data-paths (NDP) - repeated HistogramBucket histogram_ndp_session_data_usage_mb = 32; - - // histogram of usage (in MB) of data-path creation time (in ms) measured as request -> confirm - repeated HistogramBucket histogram_ndp_creation_time_ms = 33; - - // statistics for data-path (NDP) creation time (in ms) measured as request -> confirm: minimum - optional int64 ndp_creation_time_ms_min = 34; - - // statistics for data-path (NDP) creation time (in ms) measured as request -> confirm: maximum - optional int64 ndp_creation_time_ms_max = 35; - - // statistics for data-path (NDP) creation time (in ms) measured as request -> confirm: sum - optional int64 ndp_creation_time_ms_sum = 36; - - // statistics for data-path (NDP) creation time (in ms) measured as request -> confirm: sum of sq - optional int64 ndp_creation_time_ms_sum_of_sq = 37; - - // statistics for data-path (NDP) creation time (in ms) measured as request -> confirm: number of - // samples - optional int64 ndp_creation_time_ms_num_samples = 38; - - // total time within the logging window that aware was available - optional int64 available_time_ms = 39; - - // total time within the logging window that aware was enabled - optional int64 enabled_time_ms = 40; - - // maximum number of concurrent publish sessions enabling ranging in a single app - optional int32 max_concurrent_publish_with_ranging_in_app = 41; - - // maximum number of concurrent subscribe sessions specifying a geofence in a single app - optional int32 max_concurrent_subscribe_with_ranging_in_app = 42; - - // maximum number of concurrent publish sessions enabling ranging in the system - optional int32 max_concurrent_publish_with_ranging_in_system = 43; - - // maximum number of concurrent subscribe sessions specifying a geofence in the system - optional int32 max_concurrent_subscribe_with_ranging_in_system = 44; - - // histogram of subscribe session geofence minimum (only when specified) - repeated HistogramBucket histogram_subscribe_geofence_min = 45; - - // histogram of subscribe session geofence maximum (only when specified) - repeated HistogramBucket histogram_subscribe_geofence_max = 46; - - // total number of subscribe sessions which enabled ranging - optional int32 num_subscribes_with_ranging = 47; - - // total number of matches (service discovery indication) with ranging provided - optional int32 num_matches_with_ranging = 48; - - // total number of matches (service discovery indication) for service discovery with ranging - // enabled which did not trigger ranging - optional int32 num_matches_without_ranging_for_ranging_enabled_subscribes = 49; - - // Histogram bucket for Wi-Fi Aware logs. Range is [start, end) - message HistogramBucket { - // lower range of the bucket (inclusive) - optional int64 start = 1; - - // upper range of the bucket (exclusive) - optional int64 end = 2; - - // number of samples in the bucket - optional int32 count = 3; - } - - // Status of various NAN operations - enum NanStatusTypeEnum { - // constant to be used by proto - UNKNOWN = 0; - - // NAN operation succeeded - SUCCESS = 1; - - // NAN Discovery Engine/Host driver failures - INTERNAL_FAILURE = 2; - - // NAN OTA failures - PROTOCOL_FAILURE = 3; - - // The publish/subscribe discovery session id is invalid - INVALID_SESSION_ID = 4; - - // Out of resources to fufill request - NO_RESOURCES_AVAILABLE = 5; - - // Invalid arguments passed - INVALID_ARGS = 6; - - // Invalid peer id - INVALID_PEER_ID = 7; - - // Invalid NAN data-path (ndp) id - INVALID_NDP_ID = 8; - - // Attempting to enable NAN when not available, e.g. wifi is disabled - NAN_NOT_ALLOWED = 9; - - // Over the air ACK not received - NO_OTA_ACK = 10; - - // Attempting to enable NAN when already enabled - ALREADY_ENABLED = 11; - - // Can't queue tx followup message foor transmission - FOLLOWUP_TX_QUEUE_FULL = 12; - - // Unsupported concurrency of NAN and another feature - NAN disabled - UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 13; - - // Unknown NanStatusType - UNKNOWN_HAL_STATUS = 14; - } - - // Histogram bucket for Wi-Fi Aware (NAN) status. - message NanStatusHistogramBucket { - // status type defining the bucket - optional NanStatusTypeEnum nan_status_type = 1; - - // number of samples in the bucket - optional int32 count = 2; - } -} - -// Data point used to build 'Number of Connectable Network' histograms -message NumConnectableNetworksBucket { - // Number of connectable networks seen in a scan result - optional int32 num_connectable_networks = 1 [default = 0]; - - // Number of scan results with num_connectable_networks - optional int32 count = 2 [default = 0]; -} - -// Pno scan metrics -// Here "Pno Scan" refers to the session of offloaded scans, these metrics count the result of a -// single session, and not the individual scans within that session. -message PnoScanMetrics { - // Total number of attempts to offload pno scans - optional int32 num_pno_scan_attempts = 1; - - // Total number of pno scans failed - optional int32 num_pno_scan_failed = 2; - - // Number of pno scans started successfully over offload - optional int32 num_pno_scan_started_over_offload = 3; - - // Number of pno scans failed over offload - optional int32 num_pno_scan_failed_over_offload = 4; - - // Total number of pno scans that found any network - optional int32 num_pno_found_network_events = 5; -} - -// Number of occurrences for a particular "Connect to Network" Notification or -// notification Action. -message ConnectToNetworkNotificationAndActionCount { - - // "Connect to Network" notifications - enum Notification { - - // Default - NOTIFICATION_UNKNOWN = 0; - - // Initial notification with a recommended network. - NOTIFICATION_RECOMMEND_NETWORK = 1; - - // Notification when connecting to the recommended network. - NOTIFICATION_CONNECTING_TO_NETWORK = 2; - - // Notification when successfully connected to the network. - NOTIFICATION_CONNECTED_TO_NETWORK = 3; - - // Notification when failed to connect to network. - NOTIFICATION_FAILED_TO_CONNECT = 4; - } - - // "Connect to Network" notification actions - enum Action { - - // Default - ACTION_UNKNOWN = 0; - - // User dismissed the "Connect to Network" notification. - ACTION_USER_DISMISSED_NOTIFICATION = 1; - - // User tapped action button to connect to recommended network. - ACTION_CONNECT_TO_NETWORK = 2; - - // User tapped action button to open Wi-Fi Settings. - ACTION_PICK_WIFI_NETWORK = 3; - - // User tapped "Failed to connect" notification to open Wi-Fi Settings. - ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE = 4; - } - - // Recommenders of the "Connect to Network" notification - enum Recommender { - - // Default. - RECOMMENDER_UNKNOWN = 0; - - // Open Network Available recommender. - RECOMMENDER_OPEN = 1; - } - - // Notification Type. - optional Notification notification = 1; - - // Action Type. - optional Action action = 2; - - // Recommender Type. - optional Recommender recommender = 3; - - // Occurrences of this action. - optional int32 count = 4; -} - -// SoftAP event tracking sessions and client counts -message SoftApConnectedClientsEvent { - - // Soft AP event Types - enum SoftApEventType { - - // Soft AP is Up and ready for use - SOFT_AP_UP = 0; - - // Soft AP is Down - SOFT_AP_DOWN = 1; - - // Number of connected soft AP clients has changed - NUM_CLIENTS_CHANGED = 2; - } - - // Soft AP channel bandwidth types - enum ChannelBandwidth { - - BANDWIDTH_INVALID = 0; - - BANDWIDTH_20_NOHT = 1; - - BANDWIDTH_20 = 2; - - BANDWIDTH_40 = 3; - - BANDWIDTH_80 = 4; - - BANDWIDTH_80P80 = 5; - - BANDWIDTH_160 = 6; - } - - // Type of event being recorded - optional SoftApEventType event_type = 1; - - // Time passed since last boot in milliseconds - optional int64 time_stamp_millis = 2; - - // Number of connected clients if event_type is NUM_CLIENTS_CHANGED, otherwise zero. - optional int32 num_connected_clients = 3; - - // Channel frequency used for Soft AP - optional int32 channel_frequency = 4; - - // Channel bandwidth used for Soft AP - optional ChannelBandwidth channel_bandwidth = 5; - - // Maximum number of client setting in SoftApConfiguration - optional int32 max_num_clients_setting_in_softap_configuration = 6; - - // Maximum number of client setting in SoftApCapability - optional int32 max_num_clients_setting_in_softap_capability = 7; - - // Auto shutdown timeout setting in SoftApConfiguration - optional int64 shutdown_timeout_setting_in_softap_configuration = 8; - - // Framework default auto shutdown timeout setting - optional int64 default_shutdown_timeout_setting = 9; - - // Indicates if user enabled the client_control - optional bool client_control_is_enabled = 10; -} - -// Power stats for Wifi -message WifiPowerStats { - - // Duration of log (ms) - optional int64 logging_duration_ms = 1; - - // Energy consumed by wifi (mAh) - optional double energy_consumed_mah = 2; - - // Amount of time wifi is in idle (ms) - optional int64 idle_time_ms = 3; - - // Amount of time wifi is in rx (ms) - optional int64 rx_time_ms = 4; - - // Amount of time wifi is in tx (ms) - optional int64 tx_time_ms = 5; - - // Amount of time kernel is active because of wifi data (ms) - optional int64 wifi_kernel_active_time_ms = 6; - - // Number of packets sent (tx) - optional int64 num_packets_tx = 7; - - // Number of bytes sent (tx) - optional int64 num_bytes_tx = 8; - - // Number of packets received (rx) - optional int64 num_packets_rx = 9; - - // Number of bytes sent (rx) - optional int64 num_bytes_rx = 10; - - // Amount of time wifi is in sleep (ms) - optional int64 sleep_time_ms = 11; - - // Amount of time wifi is scanning (ms) - optional int64 scan_time_ms = 12; - - // Actual monitored rail energy consumed by wifi (mAh) - optional double monitored_rail_energy_consumed_mah = 13; -} - -// Metrics for Wifi Wake -message WifiWakeStats { - // An individual session for Wifi Wake - message Session { - // A Wifi Wake lifecycle event - message Event { - // Elapsed time in milliseconds since start of session. - optional int64 elapsed_time_millis = 1; - - // Number of scans that have occurred since start of session. - optional int32 elapsed_scans = 2; - } - - // Start time of session in milliseconds. - optional int64 start_time_millis = 1; - - // The number of networks the lock was provided with at start. - optional int32 locked_networks_at_start = 2; - - // The number of networks in the lock at the time of the initialize event. Only valid if - // initialize_event is recorded. - optional int32 locked_networks_at_initialize = 6; - - // Event for fully initializing the WakeupLock (i.e. WakeupLock is "locked"). - optional Event initialize_event = 7; - - // Event for unlocking the WakeupLock. Does not occur if lock was initialized with 0 networks. - optional Event unlock_event = 3; - - // Event for triggering wakeup. - optional Event wakeup_event = 4; - - // Event for WifiWake reset event. This event marks the end of a session. - optional Event reset_event = 5; - } - - // Total number of sessions for Wifi Wake. - optional int32 num_sessions = 1; - - // Session information for every Wifi Wake session (up to a maximum of 10). - repeated Session sessions = 2; - - // Number of ignored calls to start (due to WakeupController already being active). - optional int32 num_ignored_starts = 3; - - // Number of Wifi Wake sessions that have recorded wakeup events. - optional int32 num_wakeups = 4; -} - -// Metrics for Wi-Fi RTT -message WifiRttLog { - // Number of RTT request API calls - optional int32 num_requests = 1; - - // Histogram of RTT operation overall status - repeated RttOverallStatusHistogramBucket histogram_overall_status = 2; - - // RTT to Access Points metrics - optional RttToPeerLog rtt_to_ap = 3; - - // RTT to Wi-Fi Aware peers metrics - optional RttToPeerLog rtt_to_aware = 4; - - // Histogram of how long a measurement with only AP take. - repeated HistogramBucket histogram_measurement_duration_ap_only = 5; - - // Histogram of how long a measurement with aware peer included take. - repeated HistogramBucket histogram_measurement_duration_with_aware = 6; - - // Metrics for a RTT to Peer (peer = AP or Wi-Fi Aware) - message RttToPeerLog { - // Total number of API calls - optional int32 num_requests = 1; - - // Total number of individual requests - optional int32 num_individual_requests = 2; - - // Total number of apps which requested RTT - optional int32 num_apps = 3; - - // Histogram of total number of RTT requests by an app (WifiRttManager#startRanging) - repeated HistogramBucket histogram_num_requests_per_app = 4; - - // Histogram of number of peers in a single RTT request (RangingRequest entries) - repeated HistogramBucket histogram_num_peers_per_request = 5; - - // Histogram of status of individual RTT operations (RangingResult entries) - repeated RttIndividualStatusHistogramBucket histogram_individual_status = 6; - - // Histogram of measured distances (RangingResult entries) - repeated HistogramBucket histogram_distance = 7; - - // Histogram of interval of RTT requests by an app (WifiRttManager#startRanging) - repeated HistogramBucket histogram_request_interval_ms = 8; - } - - // Histogram bucket for Wi-Fi RTT logs. Range is [start, end) - message HistogramBucket { - // lower range of the bucket (inclusive) - optional int64 start = 1; - - // upper range of the bucket (exclusive) - optional int64 end = 2; - - // number of samples in the bucket - optional int32 count = 3; - } - - // Status codes for overall RTT operation - enum RttOverallStatusTypeEnum { - // constant to be used by proto - OVERALL_UNKNOWN = 0; - - // RTT operation succeeded (individual results may still fail) - OVERALL_SUCCESS = 1; - - // RTT operation failed (unspecified reason) - OVERALL_FAIL = 2; - - // RTT operation failed since RTT was not available (e.g. Airplane mode) - OVERALL_RTT_NOT_AVAILABLE = 3; - - // RTT operation timed-out: didn't receive response from HAL in expected time - OVERALL_TIMEOUT = 4; - - // RTT operation aborted since the app is spamming the service - OVERALL_THROTTLE = 5; - - // RTT request to HAL received immediate failure - OVERALL_HAL_FAILURE = 6; - - // RTT to Wi-Fi Aware peer using PeerHandle failed to get a MAC address translation - OVERALL_AWARE_TRANSLATION_FAILURE = 7; - - // RTT operation failed due to missing Location permission (post execution) - OVERALL_LOCATION_PERMISSION_MISSING = 8; - } - - // Status codes for individual RTT operation - enum RttIndividualStatusTypeEnum { - // constant to be used by proto - UNKNOWN = 0; - - // RTT operation succeeded - SUCCESS = 1; - - // RTT failure: generic reason (no further information) - FAILURE = 2; - - // Target STA does not respond to request - FAIL_NO_RSP = 3; - - // Request rejected. Applies to 2-sided RTT only - FAIL_REJECTED = 4; - - // Operation not scheduled - FAIL_NOT_SCHEDULED_YET = 5; - - // Timing measurement times out - FAIL_TM_TIMEOUT = 6; - - // Target on different channel, cannot range - FAIL_AP_ON_DIFF_CHANNEL = 7; - - // Ranging not supported - FAIL_NO_CAPABILITY = 8; - - // Request aborted for unknown reason - ABORTED = 9; - - // Invalid T1-T4 timestamp - FAIL_INVALID_TS = 10; - - // 11mc protocol failed - FAIL_PROTOCOL = 11; - - // Request could not be scheduled - FAIL_SCHEDULE = 12; - - // Responder cannot collaborate at time of request - FAIL_BUSY_TRY_LATER = 13; - - // Bad request args - INVALID_REQ = 14; - - // WiFi not enabled - NO_WIFI = 15; - - // Responder overrides param info, cannot range with new params - FAIL_FTM_PARAM_OVERRIDE = 16; - - // HAL did not provide a result to a framework request - MISSING_RESULT = 17; - } - - // Histogram bucket for Wi-Fi RTT overall operation status - message RttOverallStatusHistogramBucket { - // status type defining the bucket - optional RttOverallStatusTypeEnum status_type = 1; - - // number of samples in the bucket - optional int32 count = 2; - } - - // Histogram bucket for Wi-Fi RTT individual operation status - message RttIndividualStatusHistogramBucket { - // status type defining the bucket - optional RttIndividualStatusTypeEnum status_type = 1; - - // number of samples in the bucket - optional int32 count = 2; - } -} - -// Usage data for the wifi radio while device is running on battery. -message WifiRadioUsage { - // Duration of log (ms) - optional int64 logging_duration_ms = 1; - - // Total time for which the radio is awake due to scan. - optional int64 scan_time_ms = 2; -} - -message ExperimentValues { - // Indicates if we are logging WifiIsUnusableEvent in metrics - optional bool wifi_is_unusable_logging_enabled = 1; - - // Minimum number of txBad to trigger a data stall - optional int32 wifi_data_stall_min_tx_bad = 2; - - // Minimum number of txSuccess to trigger a data stall - // when rxSuccess is 0 - optional int32 wifi_data_stall_min_tx_success_without_rx = 3; - - // Indicates if we are logging LinkSpeedCount in metrics - optional bool link_speed_counts_logging_enabled = 4; - - // Duration for evaluating Wifi condition to trigger a data stall - // measured in milliseconds - optional int32 data_stall_duration_ms = 5; - - // Threshold of Tx throughput below which to trigger a data stall - // measured in Kbps - optional int32 data_stall_tx_tput_thr_kbps = 6; - - // Threshold of Rx throughput below which to trigger a data stall - // measured in Kbps - optional int32 data_stall_rx_tput_thr_kbps = 7; - - // Threshold of Tx packet error rate above which to trigger a data stall - // in percentage - optional int32 data_stall_tx_per_thr = 8; - - // Threshold of CCA level above which to trigger a data stall in percentage - optional int32 data_stall_cca_level_thr = 9; - - // Health monitor RSSI poll valid time in ms - optional int32 health_monitor_rssi_poll_valid_time_ms = 10; -} - -message BssidBlocklistStats { - // Distributions of number of blocked BSSIDs filtered out from network selection. - repeated Int32Count network_selection_filtered_bssid_count = 1; - - // If this is enabled, then network connections in high movement state will be skipped unless - // we find a candidate BSSID with similar RSSI in 2 scans sufficiently far apart. - optional bool high_movement_multiple_scans_feature_enabled = 2; - - // Number of times connection is skipped in the high movement state - // only relevant if high_movement_multiple_scans_feature_enabled=true - optional int32 num_high_movement_connection_skipped = 3; - - // Number of times connection is initiated in the high movement state - // only relevant if high_movement_multiple_scans_feature_enabled=true - optional int32 num_high_movement_connection_started = 4; -} - -message WifiIsUnusableEvent { - enum TriggerType { - // Default/Invalid event - TYPE_UNKNOWN = 0; - - // There is a data stall from tx failures - TYPE_DATA_STALL_BAD_TX = 1; - - // There is a data stall from rx failures - TYPE_DATA_STALL_TX_WITHOUT_RX = 2; - - // There is a data stall from both tx and rx failures - TYPE_DATA_STALL_BOTH = 3; - - // Firmware generated an alert - TYPE_FIRMWARE_ALERT = 4; - - // IP Manager lost reachability to network neighbors - TYPE_IP_REACHABILITY_LOST = 5; - } - - // What event triggered WifiIsUnusableEvent. - optional TriggerType type = 1; - - // The timestamp at which this event occurred. - // Measured in milliseconds that have elapsed since the device booted. - optional int64 start_time_millis = 2; - - // NetworkAgent score of connected wifi. - // Defaults to -1 if the score was never set. - optional int32 last_score = 3 [default = -1]; - - // Delta of successfully transmitted (ACKed) unicast data packets - // between the last two WifiLinkLayerStats. - optional int64 tx_success_delta = 4; - - // Delta of transmitted unicast data retry packets - // between the last two WifiLinkLayerStats. - optional int64 tx_retries_delta = 5; - - // Delta of lost (not ACKed) transmitted unicast data packets - // between the last two WifiLinkLayerStats. - optional int64 tx_bad_delta = 6; - - // Delta of received unicast data packets - // between the last two WifiLinkLayerStats. - optional int64 rx_success_delta = 7; - - // Time in millisecond between the last two WifiLinkLayerStats. - optional int64 packet_update_time_delta = 8; - - // The timestamp at which the last WifiLinkLayerStats was updated. - // Measured in milliseconds that have elapsed since the device booted. - optional int64 last_link_layer_stats_update_time = 9; - - // Firmware alert code. Only valid when the event was triggered by a firmware alert, otherwise -1. - optional int32 firmware_alert_code = 10 [default = -1]; - - // NetworkAgent wifi usability score of connected wifi. - // Defaults to -1 if the score was never set. - optional int32 last_wifi_usability_score = 11 [default = -1]; - - // Prediction horizon (in second) of Wifi usability score provided by external - // system app - optional int32 last_prediction_horizon_sec = 12 [default = -1]; - - // Whether screen status is on when WifiIsUnusableEvent happens. - optional bool screen_on = 13 [default = false]; - - // Number of bytes transmitted across mobile networks since device boot. - optional int64 mobile_tx_bytes = 14 [default = -1]; - - // // Number of bytes received across mobile networks since device boot. - optional int64 mobile_rx_bytes = 15 [default = -1]; - - // Number of bytes transmitted since device boot. - optional int64 total_tx_bytes = 16 [default = -1]; - - // Number of bytes received since device boot. - optional int64 total_rx_bytes = 17 [default = -1]; -} - -message PasspointProfileTypeCount { - enum EapMethod { - // Unknown Type - TYPE_UNKNOWN = 0; - - // EAP_TLS (13) - TYPE_EAP_TLS = 1; - - // EAP_TTLS (21) - TYPE_EAP_TTLS = 2; - - // EAP_SIM (18) - TYPE_EAP_SIM = 3; - - // EAP_AKA (23) - TYPE_EAP_AKA = 4; - - // EAP_AKA_PRIME (50) - TYPE_EAP_AKA_PRIME = 5; - } - - // Eap method type set in Passpoint profile - optional EapMethod eap_method_type = 1; - - // Num of installed Passpoint profile with same eap method - optional int32 count = 2; -} - -message WifiLinkLayerUsageStats { - // Total logging duration in ms. - optional int64 logging_duration_ms = 1; - - // Total time the wifi radio is on in ms over the logging duration. - optional int64 radio_on_time_ms = 2; - - // Total time the wifi radio is doing tx in ms over the logging duration. - optional int64 radio_tx_time_ms = 3; - - // Total time the wifi radio is doing rx in ms over the logging duration. - optional int64 radio_rx_time_ms = 4; - - // Total time the wifi radio is scanning in ms over the logging duration. - optional int64 radio_scan_time_ms = 5; - - // Total time the wifi radio spent doing nan scans in ms over the logging duration. - optional int64 radio_nan_scan_time_ms = 6; - - // Total time the wifi radio spent doing background scans in ms over the logging duration. - optional int64 radio_background_scan_time_ms = 7; - - // Total time the wifi radio spent doing roam scans in ms over the logging duration. - optional int64 radio_roam_scan_time_ms = 8; - - // Total time the wifi radio spent doing pno scans in ms over the logging duration. - optional int64 radio_pno_scan_time_ms = 9; - - // Total time the wifi radio spent doing hotspot 2.0 scans and GAS exchange - // in ms over the logging duration. - optional int64 radio_hs20_scan_time_ms = 10; -} - -message WifiUsabilityStatsEntry { - // Status codes for link probe status - enum LinkProbeStatus { - // Link probe status is unknown - PROBE_STATUS_UNKNOWN = 0; - - // Link probe is not triggered - PROBE_STATUS_NO_PROBE = 1; - - // Link probe is triggered and the result is success - PROBE_STATUS_SUCCESS = 2; - - // Link probe is triggered and the result is failure - PROBE_STATUS_FAILURE = 3; - } - - // Codes for cellular data network type - enum CellularDataNetworkType { - // Unknown network - NETWORK_TYPE_UNKNOWN = 0; - - // GSM network - NETWORK_TYPE_GSM = 1; - - // CDMA network - NETWORK_TYPE_CDMA = 2; - - // CDMA EVDO network - NETWORK_TYPE_EVDO_0 = 3; - - // WCDMA network - NETWORK_TYPE_UMTS = 4; - - // TDSCDMA network - NETWORK_TYPE_TD_SCDMA = 5; - - // LTE network - NETWORK_TYPE_LTE = 6; - - // NR network - NETWORK_TYPE_NR = 7; - } - - // Absolute milliseconds from device boot when these stats were sampled - optional int64 time_stamp_ms = 1; - - // The RSSI at the sample time - optional int32 rssi = 2; - - // Link speed at the sample time in Mbps - optional int32 link_speed_mbps = 3; - - // The total number of tx success counted from the last radio chip reset - optional int64 total_tx_success = 4; - - // The total number of MPDU data packet retries counted from the last radio chip reset - optional int64 total_tx_retries = 5; - - // The total number of tx bad counted from the last radio chip reset - optional int64 total_tx_bad = 6; - - // The total number of rx success counted from the last radio chip reset - optional int64 total_rx_success = 7; - - // The total time the wifi radio is on in ms counted from the last radio chip reset - optional int64 total_radio_on_time_ms = 8; - - // The total time the wifi radio is doing tx in ms counted from the last radio chip reset - optional int64 total_radio_tx_time_ms = 9; - - // The total time the wifi radio is doing rx in ms counted from the last radio chip reset - optional int64 total_radio_rx_time_ms = 10; - - // The total time spent on all types of scans in ms counted from the last radio chip reset - optional int64 total_scan_time_ms = 11; - - // The total time spent on nan scans in ms counted from the last radio chip reset - optional int64 total_nan_scan_time_ms = 12; - - // The total time spent on background scans in ms counted from the last radio chip reset - optional int64 total_background_scan_time_ms = 13; - - // The total time spent on roam scans in ms counted from the last radio chip reset - optional int64 total_roam_scan_time_ms = 14; - - // The total time spent on pno scans in ms counted from the last radio chip reset - optional int64 total_pno_scan_time_ms = 15; - - // The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio - // chip reset - optional int64 total_hotspot_2_scan_time_ms = 16; - - // Internal framework Wifi score - optional int32 wifi_score = 17; - - // Wifi usability score provided by external system app - optional int32 wifi_usability_score = 18; - - // Sequence number from external system app to framework - optional int32 seq_num_to_framework = 19; - - // The total time CCA is on busy status on the current frequency in ms - // counted from the last radio chip reset - optional int64 total_cca_busy_freq_time_ms = 20; - - // The total radio on time of the current frequency from the last radio - // chip reset - optional int64 total_radio_on_freq_time_ms = 21; - - // The total number of beacons received from the last radio chip reset - optional int64 total_beacon_rx = 22; - - // Prediction horizon (in second) of Wifi usability score provided by external - // system app - optional int32 prediction_horizon_sec = 23; - - // The link probe status since last stats update - optional LinkProbeStatus probe_status_since_last_update = 24; - - // The elapsed time of the most recent link probe since last stats update; - optional int32 probe_elapsed_time_since_last_update_ms = 25; - - // The MCS rate of the most recent link probe since last stats update - optional int32 probe_mcs_rate_since_last_update = 26; - - // Rx link speed at the sample time in Mbps - optional int32 rx_link_speed_mbps = 27; - - // Sequence number generated by framework - optional int32 seq_num_inside_framework = 28; - - // Whether current entry is for the same BSSID on the same frequency compared - // to last entry - optional bool is_same_bssid_and_freq = 29; - - // Cellular data network type currently in use on the device for data transmission - optional CellularDataNetworkType cellular_data_network_type = 30; - - // Cellular signal strength in dBm, NR: CsiRsrp, LTE: Rsrp, WCDMA/TDSCDMA: Rscp, - // CDMA: Rssi, EVDO: Rssi, GSM: Rssi - optional int32 cellular_signal_strength_dbm = 31; - - // Cellular signal strength in dB, NR: CsiSinr, LTE: Rsrq, WCDMA: EcNo, TDSCDMA: invalid, - // CDMA: Ecio, EVDO: SNR, GSM: invalid */ - optional int32 cellular_signal_strength_db = 32; - - // Whether the primary registered cell of current entry is same as that of previous entry - optional bool is_same_registered_cell = 33; - - // The device mobility state - optional DeviceMobilityStatePnoScanStats.DeviceMobilityState - device_mobility_state = 34; -} - -message WifiUsabilityStats { - enum Label { - // Default label - LABEL_UNKNOWN = 0; - - // Wifi is usable - LABEL_GOOD = 1; - - // Wifi is unusable - LABEL_BAD = 2; - } - - enum UsabilityStatsTriggerType { - // Default/Invalid event - TYPE_UNKNOWN = 0; - - // There is a data stall from tx failures - TYPE_DATA_STALL_BAD_TX = 1; - - // There is a data stall from rx failures - TYPE_DATA_STALL_TX_WITHOUT_RX = 2; - - // There is a data stall from both tx and rx failures - TYPE_DATA_STALL_BOTH = 3; - - // Firmware generated an alert - TYPE_FIRMWARE_ALERT = 4; - - // IP Manager lost reachability to network neighbors - TYPE_IP_REACHABILITY_LOST = 5; - } - - // The current wifi usability state - optional Label label = 1; - - // The list of timestamped wifi usability stats - repeated WifiUsabilityStatsEntry stats = 2; - - // What event triggered WifiUsabilityStats. - optional UsabilityStatsTriggerType trigger_type = 3; - - // Firmware alert code. Only valid when the stats was triggered by a firmware - // alert, otherwise -1. - optional int32 firmware_alert_code = 4 [default = -1]; - - // Absolute milliseconds from device boot when these stats were sampled - optional int64 time_stamp_ms = 5; -} - -message DeviceMobilityStatePnoScanStats { - // see WifiManager.DEVICE_MOBILITY_STATE_* constants - enum DeviceMobilityState { - // Unknown mobility - UNKNOWN = 0; - - // High movement - HIGH_MVMT = 1; - - // Low movement - LOW_MVMT = 2; - - // Stationary - STATIONARY = 3; - } - - // The device mobility state - optional DeviceMobilityState device_mobility_state = 1; - - // The number of times that this state was entered - optional int32 num_times_entered_state = 2; - - // The total duration elapsed while in this mobility state, in ms - optional int64 total_duration_ms = 3; - - // the total duration elapsed while in this mobility state with PNO scans running, in ms - optional int64 pno_duration_ms = 4; -} - -// The information about the Wifi P2p events. -message WifiP2pStats { - - // Group event list tracking sessions and client counts in tethered mode. - repeated GroupEvent group_event = 1; - - // Session information that gets logged for every Wifi P2p connection. - repeated P2pConnectionEvent connection_event = 2; - - // Number of persistent group in the user profile. - optional int32 num_persistent_group = 3; - - // Number of peer scan. - optional int32 num_total_peer_scans = 4; - - // Number of service scan. - optional int32 num_total_service_scans = 5; -} - -message P2pConnectionEvent { - - enum ConnectionType { - - // fresh new connection. - CONNECTION_FRESH = 0; - - // reinvoke a group. - CONNECTION_REINVOKE = 1; - - // create a group with the current device as the group owner locally. - CONNECTION_LOCAL = 2; - - // create a group or join a group with config. - CONNECTION_FAST = 3; - } - - enum ConnectivityLevelFailure { - - // Failure is unknown. - CLF_UNKNOWN = 0; - - // No failure. - CLF_NONE = 1; - - // Timeout for current connecting request. - CLF_TIMEOUT = 2; - - // The connecting request is canceled by the user. - CLF_CANCEL = 3; - - // Provision discovery failure, e.g. no pin code, timeout, rejected by the peer. - CLF_PROV_DISC_FAIL = 4; - - // Invitation failure, e.g. rejected by the peer. - CLF_INVITATION_FAIL = 5; - - // Incoming request is rejected by the user. - CLF_USER_REJECT = 6; - - // New connection request is issued before ending previous connecting request. - CLF_NEW_CONNECTION_ATTEMPT = 7; - } - - // WPS method. - enum WpsMethod { - // WPS is skipped for Group Reinvoke. - WPS_NA = -1; - - // Push button configuration. - WPS_PBC = 0; - - // Display pin method configuration - pin is generated and displayed on device. - WPS_DISPLAY = 1; - - // Keypad pin method configuration - pin is entered on device. - WPS_KEYPAD = 2; - - // Label pin method configuration - pin is labelled on device. - WPS_LABEL = 3; - } - - // Start time of the connection. - optional int64 start_time_millis = 1; - - // Type of the connection. - optional ConnectionType connection_type = 2; - - // WPS method. - optional WpsMethod wps_method = 3 [default = WPS_NA]; - - // Duration to connect. - optional int32 duration_taken_to_connect_millis = 4; - - // Failures that happen at the connectivity layer. - optional ConnectivityLevelFailure connectivity_level_failure_code = 5; -} - -// GroupEvent tracking group information from GroupStarted to GroupRemoved. -message GroupEvent { - - enum GroupRole { - - GROUP_OWNER = 0; - - GROUP_CLIENT = 1; - } - - // The ID of network in supplicant for this group. - optional int32 net_id = 1; - - // Start time of the group. - optional int64 start_time_millis = 2; - - // Channel frequency used for Group. - optional int32 channel_frequency = 3; - - // Is group owner or group client. - optional GroupRole group_role = 5; - - // Number of connected clients. - optional int32 num_connected_clients = 6; - - // Cumulative number of connected clients. - optional int32 num_cumulative_clients = 7; - - // The session duration. - optional int32 session_duration_millis = 8; - - // The idle duration. A group without any client is in idle. - optional int32 idle_duration_millis = 9; -} - -// Easy Connect (DPP) -message WifiDppLog { - reserved 6; - - // Number of Configurator-Initiator requests - optional int32 num_dpp_configurator_initiator_requests = 1; - - // Number of Enrollee-Initiator requests - optional int32 num_dpp_enrollee_initiator_requests = 2; - - // Easy Connect (DPP) Enrollee success - optional int32 num_dpp_enrollee_success = 3; - - // Easy Connect (DPP) Configurator success code bucket - repeated DppConfiguratorSuccessStatusHistogramBucket dpp_configurator_success_code = 4; - - // Easy Connect (DPP) failure code bucket - repeated DppFailureStatusHistogramBucket dpp_failure_code = 5; - - // Easy Connect (DPP) operation time bucket - repeated HistogramBucketInt32 dpp_operation_time = 7; - - // Number of Enrollee-Responder peer devices supporting DPP protocol version 1 - optional int32 num_dpp_r1_capable_enrollee_responder_devices = 8; - - // Number of Enrollee-Responder peer devices supporting DPP protocol version 2 - optional int32 num_dpp_r2_capable_enrollee_responder_devices = 9; - - // Number of Enrollee-Responder incompatible configurations found in DPP R2 compatibility check. - optional int32 num_dpp_r2_enrollee_responder_incompatible_configuration = 10; - - // Histogram bucket for Wi-Fi DPP configurator success - message DppConfiguratorSuccessStatusHistogramBucket { - // status type defining the bucket - optional DppConfiguratorSuccessCode dpp_status_type = 1; - - // number of samples in the bucket - optional int32 count = 2; - } - - // Histogram bucket for Wi-Fi DPP failures - message DppFailureStatusHistogramBucket { - // status type defining the bucket - optional DppFailureCode dpp_status_type = 1; - - // number of samples in the bucket - optional int32 count = 2; - } - - enum DppConfiguratorSuccessCode { - // Unknown success code - EASY_CONNECT_EVENT_SUCCESS_UNKNOWN = 0; - - // Easy Connect Configurator success event: Configuration sent to enrollee - EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 1; - - // Easy Connect Configurator success event: Configuration applied by enrollee - EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED = 2; - } - - enum DppFailureCode { - // Unknown failure - EASY_CONNECT_EVENT_FAILURE_UNKNOWN = 0; - - // Easy Connect Failure event: Scanned QR code is either not a Easy Connect URI, or the Easy - // Connect URI has errors. - EASY_CONNECT_EVENT_FAILURE_INVALID_URI = 1; - - // Easy Connect Failure event: Bootstrapping/Authentication initialization process failure. - EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION = 2; - - // Easy Connect Failure event: Both devices are implementing the same role and are - // incompatible. - EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE = 3; - - // Easy Connect Failure event: Configuration process has failed due to malformed message. - EASY_CONNECT_EVENT_FAILURE_CONFIGURATION = 4; - - // Easy Connect Failure event: Easy Connect request while in another Easy Connect exchange. - EASY_CONNECT_EVENT_FAILURE_BUSY = 5; - - // Easy Connect Failure event: No response from the peer. - EASY_CONNECT_EVENT_FAILURE_TIMEOUT = 6; - - // Easy Connect Failure event: General protocol failure. - EASY_CONNECT_EVENT_FAILURE_GENERIC = 7; - - // Easy Connect Failure event: Feature or option is not supported. - EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED = 8; - - // Easy Connect Failure event: Invalid network provided to Easy Connect configurator. - // Network must either be WPA3-Personal (SAE) or WPA2-Personal (PSK). - EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = 9; - - // Easy Connect R2 Failure event: Enrollee cannot find the network. - EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK = 10; - - // Easy Connect R2 Failure event: Enrollee failed to authenticate with the network. - EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION = 11; - - // Easy Connect R2 Failure event: Enrollee rejected the configuration. - EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = 12; - } -} - -// WifiConfigStore read/write metrics. -message WifiConfigStoreIO { - // Histogram of config store read durations. - repeated DurationBucket read_durations = 1; - - // Histogram of config store write durations. - repeated DurationBucket write_durations = 2; - - // Total Number of instances of write/read duration in this duration bucket. - message DurationBucket { - // Bucket covers duration : [range_start_ms, range_end_ms) - // The (inclusive) lower bound of read/write duration represented by this bucket - optional int32 range_start_ms = 1; - - // The (exclusive) upper bound of read/write duration represented by this bucket - optional int32 range_end_ms = 2; - - // Number of read/write durations that fit into this bucket - optional int32 count = 3; - } -} - -// Histogram bucket counting with int32. Range is [start, end) -message HistogramBucketInt32 { - // lower range of the bucket (inclusive) - optional int32 start = 1; - - // upper range of the bucket (exclusive) - optional int32 end = 2; - - // number of samples in the bucket - optional int32 count = 3; -} - -// Counts occurrences of a int32 key -message Int32Count { - // the key - optional int32 key = 1; - - // the count - optional int32 count = 2; -} - -message LinkProbeStats { - enum LinkProbeFailureReason { - // unknown reason - LINK_PROBE_FAILURE_REASON_UNKNOWN = 0; - - // Specified MCS rate when it is unsupported by the driver. - LINK_PROBE_FAILURE_REASON_MCS_UNSUPPORTED = 1; - - // Driver reported that no ACK was received for the transmitted probe. - LINK_PROBE_FAILURE_REASON_NO_ACK = 2; - - // Driver failed to report on the status of the transmitted probe within the timeout. - LINK_PROBE_FAILURE_REASON_TIMEOUT = 3; - - // An existing link probe is in progress. - LINK_PROBE_FAILURE_REASON_ALREADY_STARTED = 4; - } - - // Counts the number of failures for each failure reason. - message LinkProbeFailureReasonCount { - // The failure reason. - optional LinkProbeFailureReason failure_reason = 1; - - // The number of occurrences for this failure reason. - optional int32 count = 2; - } - - // Counts the number of link probes for each experiment. - message ExperimentProbeCounts { - // The experiment ID. - optional string experiment_id = 1; - - // The number of link probes triggered for this experiment. - optional int32 probe_count = 2; - } - - // Counts the occurrences of RSSI values when a link probe succeeds. - repeated Int32Count success_rssi_counts = 1; - - // Counts the occurrences of RSSI values when a link probe fails. - repeated Int32Count failure_rssi_counts = 2; - - // Counts the occurrences of Link Speed values when a link probe succeeds. - repeated Int32Count success_link_speed_counts = 3; - - // Counts the occurrences of Link Speed values when a link probe fails. - repeated Int32Count failure_link_speed_counts = 4; - - // Histogram for the number of seconds since the last TX success when a link probe succeeds. - repeated HistogramBucketInt32 success_seconds_since_last_tx_success_histogram = 5; - - // Histogram for the number of seconds since the last TX success when a link probe fails. - repeated HistogramBucketInt32 failure_seconds_since_last_tx_success_histogram = 6; - - // Histogram for the elapsed time of successful link probes, in ms. - repeated HistogramBucketInt32 success_elapsed_time_ms_histogram = 7; - - // Counts the occurrences of error codes for failed link probes. - repeated LinkProbeFailureReasonCount failure_reason_counts = 8; - - // Counts the number of link probes for each experiment. - repeated ExperimentProbeCounts experiment_probe_counts = 9; -} - -// Stores the decisions that were made by a experiment when compared against another experiment -message NetworkSelectionExperimentDecisions { - // the id of one experiment - optional int32 experiment1_id = 1; - - // the id of the other experiment - optional int32 experiment2_id = 2; - - // Counts occurrences of the number of network choices there were when experiment1 makes the - // same network selection as experiment2. - // The keys are the number of network choices, and the values are the number of occurrences of - // this number of network choices when exp1 and exp2 make the same network selection. - repeated Int32Count same_selection_num_choices_counter = 3; - - // Counts occurrences of the number of network choices there were when experiment1 makes the - // same network selection as experiment2. - // The keys are the number of network choices, and the values are the number of occurrences of - // this number of network choices when exp1 and exp2 make different network selections. - // Note that it is possible for the network selection to be different even when there only exists - // a single network choice, since choosing not to connect to that network is a valid choice. - repeated Int32Count different_selection_num_choices_counter = 4; -} - -// NetworkRequest API metrics. -message WifiNetworkRequestApiLog { - // Number of requests via this API surface. - optional int32 num_request = 1; - - // Histogram of requests via this API surface to number of networks matched in scan results. - repeated HistogramBucketInt32 network_match_size_histogram = 2; - - // Number of successful network connection from this API. - optional int32 num_connect_success = 3; - - // Number of requests via this API surface that bypassed user approval. - optional int32 num_user_approval_bypass = 4; - - // Number of requests via this API surface that was rejected by the user. - optional int32 num_user_reject = 5; - - // Number of unique apps using this API surface. - optional int32 num_apps = 6; -} - -// NetworkSuggestion API metrics. -message WifiNetworkSuggestionApiLog { - enum SuggestionAppTypeCode { - // UNKNOWN type suggestion app. - TYPE_UNKNOWN = 0; - // Suggestion app with carrier privilege. - TYPE_CARRIER_PRIVILEGED = 1; - // Suggestion app with network provisioning permission(NETWORK_CARRIER_PROVISIONING). - TYPE_NETWORK_PROVISIONING = 2; - // Suggestion app without special privilege. - TYPE_NON_PRIVILEGED = 3; - } - - message SuggestionAppCount { - // Suggestion app type. - optional SuggestionAppTypeCode app_type = 1; - // Num of app in this type. - optional int32 count = 2; - } - - // Number of modifications to their suggestions by apps. - optional int32 num_modification = 1; - - // Number of successful network connection from app suggestions. - optional int32 num_connect_success = 2; - - // Number of network connection failures from app suggestions. - optional int32 num_connect_failure = 3; - - // Histogram for size of the network lists provided by various apps on the device. - repeated HistogramBucketInt32 network_list_size_histogram = 4; - - // Count of app using suggestion API with different privilege. - repeated SuggestionAppCount app_count_per_type = 5; - - // Number of user revoke app's permission from settings or disallowed from UI. - optional int32 user_revoke_app_suggestion_permission = 6; -} - -// WifiLock metrics -message WifiLockStats { - // Amount of time wifi is actively in HIGH_PERF mode (ms) - // This means the lock takes effect and the device takes the actions required for this mode - optional int64 high_perf_active_time_ms = 1; - - // Amount of time wifi is actively in LOW_LATENCY mode (ms) - // This means the lock takes effect and the device takes the actions required for this mode - optional int64 low_latency_active_time_ms = 2; - - // Histogram of HIGH_PERF lock acquisition duration (seconds) - // Note that acquiring the lock does not necessarily mean that device is actively in that mode - repeated HistogramBucketInt32 high_perf_lock_acq_duration_sec_histogram = 3; - - // Histogram of LOW_LATENCY lock acquisition duration (seconds) - // Note that acquiring the lock does not necessarily mean that device is actively in that mode - repeated HistogramBucketInt32 low_latency_lock_acq_duration_sec_histogram = 4; - - // Histogram of HIGH_PERF active session duration (seconds) - // This means the lock takes effect and the device takes the actions required for this mode - repeated HistogramBucketInt32 high_perf_active_session_duration_sec_histogram = 5; - - // Histogram of LOW_LATENCY active session duration (seconds) - // This means the lock takes effect and the device takes the actions required for this mode - repeated HistogramBucketInt32 low_latency_active_session_duration_sec_histogram = 6; -} - -// Stats on number of times Wi-Fi is turned on/off though the WifiManager#setWifiEnabled API -message WifiToggleStats { - // Number of time Wi-Fi is turned on by privileged apps - optional int32 num_toggle_on_privileged = 1; - - // Number of time Wi-Fi is turned off by privileged apps - optional int32 num_toggle_off_privileged = 2; - - // Number of time Wi-Fi is turned on by normal apps - optional int32 num_toggle_on_normal = 3; - - // Number of time Wi-Fi is turned off by normal apps - optional int32 num_toggle_off_normal = 4; -} - -// Information about the Passpoint provision metrics. -message PasspointProvisionStats { - enum ProvisionFailureCode { - // provisioning failure for unknown reason. - OSU_FAILURE_UNKNOWN = 0; - - // The reason code for Provisioning Failure due to connection failure to OSU AP. - OSU_FAILURE_AP_CONNECTION = 1; - - // The reason code for invalid server URL address. - OSU_FAILURE_SERVER_URL_INVALID = 2; - - // The reason code for provisioning failure due to connection failure to the server. - OSU_FAILURE_SERVER_CONNECTION = 3; - - // The reason code for provisioning failure due to invalid server certificate. - OSU_FAILURE_SERVER_VALIDATION = 4; - - // The reason code for provisioning failure due to invalid service provider. - OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION = 5; - - // The reason code for provisioning failure when a provisioning flow is aborted. - OSU_FAILURE_PROVISIONING_ABORTED = 6; - - // The reason code for provisioning failure when a provisioning flow is not possible. - OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7; - - // The reason code for provisioning failure due to invalid web url format for an OSU web page. - OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU = 8; - - // The reason code for provisioning failure when a command received is not the expected command - // type. - OSU_FAILURE_UNEXPECTED_COMMAND_TYPE = 9; - - // The reason code for provisioning failure when a SOAP message is not the expected message - // type. - OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE = 10; - - // The reason code for provisioning failure when a SOAP message exchange fails. - OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11; - - // The reason code for provisioning failure when a redirect listener fails to start. - OSU_FAILURE_START_REDIRECT_LISTENER = 12; - - // The reason code for provisioning failure when a redirect listener timed out to receive a HTTP - // redirect response. - OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER = 13; - - // The reason code for provisioning failure when there is no OSU activity to listen to intent. - OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14; - - // The reason code for provisioning failure when the status of a SOAP message is not the - // expected message status. - OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15; - - // The reason code for provisioning failure when there is no PPS MO. - OSU_FAILURE_NO_PPS_MO = 16; - - // The reason code for provisioning failure when there is no AAAServerTrustRoot node in a PPS - // MO. - OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE = 17; - - // The reason code for provisioning failure when there is no TrustRoot node for remediation - // server in a PPS MO. - OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE = 18; - - // The reason code for provisioning failure when there is no TrustRoot node for policy server in - // a PPS MO. - OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE = 19; - - // The reason code for provisioning failure when failing to retrieve trust root certificates - // used for validating server certificate for AAA, Remediation and Policy server. - OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES = 20; - - // The reason code for provisioning failure when there is no trust root certificate for AAA - // server. - OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE = 21; - - // The reason code for provisioning failure when a {@link PasspointConfiguration} is failed to - // install. - OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION = 22; - - // The reason code for provisioning failure when an {@link OsuProvider} is not found for - // provisioning. - OSU_FAILURE_OSU_PROVIDER_NOT_FOUND = 23; - } - - // Number of passpoint provisioning success - optional int32 num_provision_success = 1; - - // Count for passpoint provisioning failure - repeated ProvisionFailureCount provision_failure_count = 2; - - // Number of occurrences of a specific passpoint provision failure code - message ProvisionFailureCount { - // Failure code - optional ProvisionFailureCode failure_code = 1; - - // Number of failure for the failure_code. - optional int32 count = 2; - } -} - -// Counts number of networks on the device that are metered. -message MeteredNetworkStats { - // Number of networks that are set or detected as metered. - optional int32 num_metered = 1 [default = 0]; - - // Number of networks that are set or detected as unmetered. - optional int32 num_unmetered = 2; - - // Number of networks that have meteredOverride set to metered. - optional int32 num_override_metered = 3; - - // Number of networks that have meteredOverride set to unmetered. - optional int32 num_override_unmetered = 4; -} - -// An event capturing user action on wifi -message UserActionEvent { - enum EventType { - // The default and unused event - EVENT_UNKNOWN = 0; - // User forgets the network - EVENT_FORGET_WIFI = 1; - // User manually triggers disconnect - EVENT_DISCONNECT_WIFI = 2; - // User changes the metered setting to "metered" - EVENT_CONFIGURE_METERED_STATUS_METERED = 3; - // User changes the metered setting to "unmetered" - EVENT_CONFIGURE_METERED_STATUS_UNMETERED = 4; - // User changes the mac randomization setting to use random MAC - EVENT_CONFIGURE_MAC_RANDOMIZATION_ON = 5; - // User changes the mac randomization setting to use factory MAC - EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF = 6; - // User sets auto-connect to on - EVENT_CONFIGURE_AUTO_CONNECT_ON = 7; - // User sets auto-connect to off - EVENT_CONFIGURE_AUTO_CONNECT_OFF = 8; - // User toggles wifi on - EVENT_TOGGLE_WIFI_ON = 9; - // User toggles wifi off - EVENT_TOGGLE_WIFI_OFF = 10; - // User manually connects to a network - EVENT_MANUAL_CONNECT = 11; - // User changes the metered setting to "detect automatically" - EVENT_CONFIGURE_METERED_STATUS_AUTO = 12; - // User adds a new network or updates configurations for an existing network. - EVENT_ADD_OR_UPDATE_NETWORK = 13; - // User sets the adaptive connectivity to on - EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_ON = 14; - // User sets the adaptive connectivity to off - EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_OFF = 15; - } - - // The type of user action - optional EventType event_type = 1; - - // The start time of the event in milliseconds since boot. - optional int64 start_time_millis = 2; - - // Additional information on the target network for the action. This is not applicable and will - // be null for some actions such as EVENT_TOGGLE_WIFI_ON. - optional TargetNetworkInfo target_network_info = 3; - - // Information about the currently connected network. - optional WifiStatus wifi_status = 4; - - // Reasons why the network applicable for this user action is disabled. - // Normally this should be referring to the currently connected network. - // For a manual connection, this is referring to the user selected networks. - optional NetworkDisableReason network_disable_reason = 5; -} - -message WifiStatus { - // Wifi is connected. - optional bool is_connected = 1; - - // Wifi is validated - optional bool is_validated = 2; - - // The last observed RSSI - optional sint32 last_rssi = 3; - - // Estimated TX - optional int32 estimated_tx_kbps = 4; - - // Estimated RX - optional int32 estimated_rx_kbps = 5; - - // There is another candidate with better score, but user connect choice is preventing the switch. - optional bool is_stuck_due_to_user_connect_choice = 6; -} - -// Additional information on a network -message TargetNetworkInfo { - // Whether the network is an ephemeral network. - optional bool is_ephemeral = 1; - - // Whether the target is a passpoint network. - optional bool is_passpoint = 2; -} - -// Reasons why a configuration or BSSID is disabled. -message NetworkDisableReason { - enum DisableReason { - // Default value, should not be used. - REASON_UNKNOWN = 0; - // AP unable to accept more clients, a special kind of association rejection failure. - REASON_AP_UNABLE_TO_HANDLE_NEW_STA = 1; - // No internet - REASON_NETWORK_VALIDATION_FAILURE = 2; - // Password is incorrect, a special kind of authentication failure. - REASON_WRONG_PASSWORD = 3; - // Incorrect EAP credentials. - REASON_EAP_FAILURE = 4; - // Other association rejection failures. - REASON_ASSOCIATION_REJECTION = 5; - // Associated timeout failures. - REASON_ASSOCIATION_TIMEOUT = 6; - // Other authentication failures. - REASON_AUTHENTICATION_FAILURE = 7; - // DHCP failures. - REASON_DHCP_FAILURE = 8; - // Device disconnected shortly after connection. - REASON_ABNORMAL_DISCONNECT = 9; - // AP initiated disconnect for a given duration. - REASON_FRAMEWORK_DISCONNECT_MBO_OCE = 10; - // Avoid connecting to the failed AP when trying to reconnect on other available candidates. - REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT = 11; - // The connected scorer has disconnected this network. - REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE = 12; - // The network is disabled due to absence of user credentials - REASON_AUTHENTICATION_NO_CREDENTIALS = 13; - // The network is disabled because service is not subscribed, a special kind of EAP failure. - REASON_AUTHENTICATION_NO_SUBSCRIPTION = 14; - // User disabled auto-join for this network. - REASON_AUTO_JOIN_DISABLED = 15; - } - - // The reason for disabling a network. - optional DisableReason disable_reason = 1; - - // The configuration is temporarily disabled. - optional bool config_temporarily_disabled = 2; - - // The configuration is disabled until the user manually re-enables it. - optional bool config_permanently_disabled = 3; - - // Reasons why 1 or more BSSIDs are temporarily disabled. - repeated DisableReason bssid_disable_reasons = 4; -} - -// Number of networks with a large change of connection/disconnection -// failure rate or high failure rate at high RSSI -message HealthMonitorFailureStats { - // Number of networks with a large change of (or high) association rejection rate - optional int32 cnt_assoc_rejection = 1; - // Number of networks with a large change of (or high) association timeout rate - optional int32 cnt_assoc_timeout = 2; - // Number of networks with a large change of (or high) auth failure rate - optional int32 cnt_auth_failure = 3; - // Number of networks with a large change of (or high) connection failure rate - optional int32 cnt_connection_failure = 4; - // Number of networks with a large change of (or high) nonlocal disconnection rate - optional int32 cnt_disconnection_nonlocal = 5; - // Number of networks with a large change of (or high) short disconnection rate - optional int32 cnt_short_connection_nonlocal = 6; -} - -// Metrics collected by health monitor -message HealthMonitorMetrics { - // Number of networks with a large increase (compared to stats of previous build) of - // connection/disconnection failure rate - optional HealthMonitorFailureStats failure_stats_increase = 1; - // Number of networks with a large decrease (compared to stats of previous build) of - // connection/disconnection failure rate - optional HealthMonitorFailureStats failure_stats_decrease = 2; - // Number of networks with high connection/disconnection failure rate for - // current build but without sufficient connection attempts for previous build - optional HealthMonitorFailureStats failure_stats_high = 3; - // Number of networks with sufficient connection attempts for current build - // but without suffcient connection attempts for previous build - optional int32 num_network_sufficient_recent_stats_only = 4; - // Number of networks with sufficient connection attempts for both current and previous builds - optional int32 num_network_sufficient_recent_prev_stats = 5; -} - -// Connection duration statistics collected under various health conditions -// while Wifi link layer stats report are on -message ConnectionDurationStats { - // Total time with sufficient Wifi throughput and with cellular data on - optional int32 total_time_sufficient_throughput_ms = 1; - // Total time with insufficient Wifi throughput and with cellular data on - optional int32 total_time_insufficient_throughput_ms = 2; - // Total time with cellular data off - optional int32 total_time_cellular_data_off_ms = 3; -} - -// Wi-Fi off metrics -// Keeps track of Wi-Fi off stats -message WifiOffMetrics { - // Total number of Wi-Fi off - optional int32 num_wifi_off = 1; - - // Total number of Wi-Fi off with deferring - optional int32 num_wifi_off_deferring = 2; - - // Total number of Wi-Fi off deferring timeout - optional int32 num_wifi_off_deferring_timeout = 3; - - // Histogram of wifi off deferring time - repeated Int32Count wifi_off_deferring_time_histogram = 4; -} - -// SoftAp Config Limitation Metrics -message SoftApConfigLimitationMetrics { - // Total number of softap security configuration reset to default because - // hardware limitation when restore configuration from cloud - optional int32 num_security_type_reset_to_default = 1; - - // Total number of softap max client setting reset to default because - // hardware limitation when restore configuration from cloud - optional int32 num_max_client_setting_reset_to_default = 2; - - // Total number of softap client control by user reset to default because - // hardware limitation when restore configuration from cloud - optional int32 num_client_control_by_user_reset_to_default = 3; - - // Histogram of max client count when client connection fail because - // setting limitation - repeated Int32Count max_client_setting_when_reach_histogram = 4; -} - -// Channel utilization histogram -// The valid utilization range is between 0 and 255 corresponding to -// utilization ratio between 0 and 1 -message ChannelUtilizationHistogram { - // Histogram at 2G - repeated HistogramBucketInt32 utilization_2g = 1; - // Histogram above 2G - repeated HistogramBucketInt32 utilization_above_2g = 2; -} - -// Throughput histogram -message ThroughputMbpsHistogram { - // Tx histogram at 2G - repeated HistogramBucketInt32 tx_2g = 1; - // Tx histogram above 2G - repeated HistogramBucketInt32 tx_above_2g = 2; - // Rx histogram at 2G - repeated HistogramBucketInt32 rx_2g = 3; - // Rx histogram above 2G - repeated HistogramBucketInt32 rx_above_2g = 4; -} - -// Initial Partial Scan stats -message InitPartialScanStats { - // Total number of partial scans - optional int32 num_scans = 1; - - // Number of instances a partial scan results in finding a network - optional int32 num_success_scans = 2; - - // Number of instances a patial scan does not result in finding a network - // and a follow up full scan finds a network. - optional int32 num_failure_scans = 3; - - // Histogram of number of channels used in a successful partial scan - repeated HistogramBucketInt32 successful_scan_channel_count_histogram = 4; - - // Histogram of number of channels used in a failed partial scan - repeated HistogramBucketInt32 failed_scan_channel_count_histogram = 5; -} - -// User reaction to the carrier IMSI protection exemption UI -message UserReactionToApprovalUiEvent { - enum UserActionCode { - // UNKNOWN user action. - ACTION_UNKNOWN = 0; - // Action user allowed. - ACTION_ALLOWED = 1; - // Action user disallowed. - ACTION_DISALLOWED = 2; - // Action user dismiss. - ACTION_DISMISS = 3; - } - message UserReaction { - // User action to the UI. - optional UserActionCode user_action = 1; - // Is UI a dialog or notification. - optional bool is_dialog = 2; - } - - // Event of user reaction to the app approval UI. - repeated UserReaction user_approval_app_ui_reaction = 1; - - // Event of user reaction to the carrier approval UI. - repeated UserReaction user_approval_carrier_ui_reaction = 2; -} - -message CarrierWifiMetrics { - // Number of successful network connection using Carrier ID - optional int32 num_connection_success = 1; - // Number of failed authentication from network connection using Carrier ID - optional int32 num_connection_auth_failure = 2; - optional int32 num_connection_non_auth_failure = 3; -} diff --git a/service/proto/src/scorecard.proto b/service/proto/src/scorecard.proto deleted file mode 100644 index d351c5666..000000000 --- a/service/proto/src/scorecard.proto +++ /dev/null @@ -1,191 +0,0 @@ -// -// Copyright (C) 2018 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. -// - -syntax = "proto2"; - -package com_android_server_wifi; - -option java_package = "com.android.server.wifi.proto"; -option java_outer_classname = "WifiScoreCardProto"; - -message NetworkList { - optional int64 start_time_millis = 1; // Start of collection period - optional int64 end_time_millis = 2; // End of collection period - // A collection of network descriptions - repeated Network networks = 3; -}; - -// Describes a network, consisting of a collection of access points that share -// the same SSID, the same security type, and (hopefully) the same L3 subnet. -// This message is not stored in the MemoryStore. It is used to package -// the access points of a network together in dumpsys output or similar. -// For this purpose, the network_config_id and network_agent_id may be useful -// for cross-referencing with other parts of the bug report. Neither of these -// are meaningful across reboots. -message Network { - optional string ssid = 1; // The SSID (not stored) - optional SecurityType security_type = 2; // Wireless security type - repeated AccessPoint access_points = 3; // The list of related APs - optional int32 network_config_id = 4; // The networkId of WifiConfiguration - optional int32 network_agent_id = 5; // Latest NetworkAgent netId - optional NetworkStats network_stats = 6; // Network stats of current SSID -}; - -// Describes an access point (single BSSID) -// -// Beyond the BSSID, a concise id is assigned to track references -// among APs. These ids are local to the device, but unique among all APs -// known to the device. The BSSID itself is not stored in persistent storage. -message AccessPoint { - optional int32 id = 1; // Concise id - optional bytes bssid = 2; // BSSID of the access point (not stored) - optional SecurityType security_type = 6; // Wireless security type - reserved 3; - repeated Signal event_stats = 4; // Statistics taken at specific events - reserved 5; -}; - -// Describes the IEEE 802.11 security type -enum SecurityType { - OPEN = 0; // Open - no encryption - WEP = 1; // Should not be used - PSK = 2; // WPA2 - EAP = 3; // Extensible Authentication Protocol - SAE = 4; // WPA3 - EAP_SUITE_B = 5; - OWE = 6; // Opportunistic Wireless Encryption -}; - -// Records statistics gathered at various points in the life-cycle of -// a connection, e.g., at disconnections of various flavors. May be -// further split out by frequency. -// -message Signal { - optional Event event = 1; // Type of the event - optional int32 frequency = 2; // Frequency (MHz) - optional UnivariateStatistic rssi = 3; // Signal strength (dBm) of beacons - optional UnivariateStatistic linkspeed = 4; // Link speed (Mbits/sec) - optional UnivariateStatistic elapsed_ms = 5; // Milliseconds since connection attempt -}; - -// Statistics about a real value -message UnivariateStatistic { - // Short-term statistics (for current collection period) - optional int64 count = 1; // Number of events - optional double sum = 2; // Sum of values - optional double sum_of_squares = 3; // Sum of squares of values - optional double min_value = 4; // Minimum value during period - optional double max_value = 5; // Maximum value during period - - // Long-term statistics - // These are accumulated over a longer time span, and are aged so that - // more recent measurements get a higher weight. - optional double historical_mean = 6; // Long-term average - optional double historical_variance = 7; // Long-term variance - - // Arranged by increasing value - repeated HistogramBucket buckets = 8; -}; - -message HistogramBucket { - // Lower bound (inclusive) for values falling in this bucket. - // Compact signed encoding used here, because rssi values are negative. - // The upper bound is not stored explicitly. - optional sint64 low = 1; - // Number of occurences for this value or bucket. - optional int64 number = 2; -} - -// Events where statistics may be collected -enum Event { - SIGNAL_POLL = 1; - SCAN_BEFORE_SUCCESSFUL_CONNECTION = 2; - FIRST_POLL_AFTER_CONNECTION = 3; - IP_CONFIGURATION_SUCCESS = 4; - SCAN_BEFORE_FAILED_CONNECTION = 5; - CONNECTION_FAILURE = 6; - IP_REACHABILITY_LOST = 7; - LAST_POLL_BEFORE_ROAM = 8; - ROAM_SUCCESS = 9; - WIFI_DISABLED = 10; - ROAM_FAILURE = 11; - LAST_POLL_BEFORE_SWITCH = 12; - VALIDATION_SUCCESS = 13; - DISCONNECTION = 14; - CONNECTION_ATTEMPT = 15; - VALIDATION_FAILURE = 16; -}; - -message SystemInfoStats { - // Current software build information - optional SoftwareBuildInfo curr_software_build_info = 1; - // Previous software build information - optional SoftwareBuildInfo prev_software_build_info = 2; - // Most recent WiFi scan time - optional int64 last_scan_time_ms = 3; - // Number of access points found in most recent WiFi scan at 2G - optional int32 num_bssid_last_scan_2g = 4; - // Number of access points found in most recent WiFi scan above 2G - optional int32 num_bssid_last_scan_above_2g = 5; -} - -message SoftwareBuildInfo { - // Android OS build version - optional string os_build_version = 1; - // WiFi stack APK version, 0 means not available. - optional int64 wifi_stack_version = 2; - // WiFi driver version - optional string wifi_driver_version = 3; - // WiFi firmware version - optional string wifi_firmware_version = 4; -} - -message NetworkStats { - optional int32 id = 1; // Concise id - // The most recent connection stats with current SW build that may be collected over days - optional ConnectionStats recent_stats = 2; - // Accumulated connection stats with current SW build - optional ConnectionStats stats_curr_build = 3; - // Accumulated connection stats with previous SW build - optional ConnectionStats stats_prev_build = 4; - // List of frequencies observed for this network from scan results, sorted by most recent first. - repeated int32 frequencies = 5; - -}; - -message ConnectionStats { - // Number of connection attempts at high RSSI - optional int32 num_connection_attempt = 1; - // Number of connection failures at high RSSI - // Does not include wrong password but does include DHCP - optional int32 num_connection_failure = 2; - // Total connection duration in seconds - optional int32 connection_duration_sec = 3; - // Number of association rejections at high RSSI - optional int32 num_association_rejection = 4; - // Number of association timeouts at high RSSI - optional int32 num_association_timeout = 5; - // Number of authentication failures (excluding wrong password) at high RSSI - optional int32 num_authentication_failure = 6; - // Number of short connections caused by nonlocal disconnection at high RSSI - // or at high Tx speed with a recent RSSI poll - optional int32 num_short_connection_nonlocal = 7; - // Number of non-locally generated disconnections at high RSSI or Tx speed - // with a recent RSSI poll - optional int32 num_disconnection_nonlocal = 8; - // Number of disconnections with a recent RSSI poll - optional int32 num_disconnection = 9; -} diff --git a/service/res/drawable/ic_wifi_settings.xml b/service/res/drawable/ic_wifi_settings.xml deleted file mode 100644 index c678ad4dd..000000000 --- a/service/res/drawable/ic_wifi_settings.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 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. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - - <path - android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> - <path - android:fillColor="#000000" - android:pathData="M12.584,15.93c0.026-0.194,0.044-0.397,0.044-0.608c0-0.211-0.018-0.405-0.044-0.608l1.304-1.022 -c0.115-0.088,0.15-0.256,0.071-0.397l-1.234-2.133c-0.071-0.132-0.238-0.185-0.379-0.132l-1.533,0.617 -c-0.317-0.247-0.67-0.449-1.04-0.608L9.535,9.4c-0.018-0.132-0.141-0.247-0.3-0.247H6.768c-0.15,0-0.282,0.115-0.3,0.256 -L6.23,11.048c-0.379,0.159-0.723,0.361-1.04,0.608l-1.533-0.617c-0.141-0.053-0.3,0-0.379,0.132l-1.234,2.133 -c-0.079,0.132-0.044,0.3,0.07,0.397l1.304,1.022c-0.026,0.194-0.044,0.405-0.044,0.608s0.018,0.405,0.044,0.608l-1.304,1.022 -c-0.115,0.088-0.15,0.256-0.07,0.397l1.234,2.133c0.07,0.132,0.238,0.185,0.379,0.132l1.533-0.617 -c0.317,0.247,0.67,0.449,1.04,0.608l0.238,1.639c0.018,0.15,0.15,0.256,0.3,0.256h2.467c0.159,0,0.282-0.115,0.3-0.256 -l0.238-1.639c0.379-0.15,0.723-0.361,1.04-0.608l1.533,0.617c0.141,0.053,0.3,0,0.379-0.132l1.234-2.133 -c0.071-0.132,0.044-0.3-0.07-0.397L12.584,15.93z -M8.002,17.481c-1.19,0-2.159-0.969-2.159-2.159s0.969-2.159,2.159-2.159 -s2.159,0.969,2.159,2.159C10.161,16.512,9.191,17.481,8.002,17.481z" /> - <path - android:fillColor="#000000" - android:pathData="M16.003,12.026l5.995-7.474c-0.229-0.172-2.537-2.06-6-2.06s-5.771,1.889-6,2.06l5.995,7.469l0.005,0.01L16.003,12.026z" /> -</vector>
\ No newline at end of file diff --git a/service/res/drawable/stat_notify_wifi_in_range.xml b/service/res/drawable/stat_notify_wifi_in_range.xml deleted file mode 100644 index a271ca522..000000000 --- a/service/res/drawable/stat_notify_wifi_in_range.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- -Copyright (C) 2014 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. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="26.0dp" - android:height="24.0dp" - android:viewportWidth="26.0" - android:viewportHeight="24.0"> - <path - android:fillColor="#4DFFFFFF" - android:pathData="M19.1,14l-3.4,0l0,-1.5c0,-1.8 0.8,-2.8 1.5,-3.4C18.1,8.3 19.200001,8 20.6,8c1.2,0 2.3,0.3 3.1,0.8l1.9,-2.3C25.1,6.1 20.299999,2.1 13,2.1S0.9,6.1 0.4,6.5L13,22l0,0l0,0l0,0l0,0l6.5,-8.1L19.1,14z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M19.5,17.799999c0,-0.8 0.1,-1.3 0.2,-1.6c0.2,-0.3 0.5,-0.7 1.1,-1.2c0.4,-0.4 0.7,-0.8 1,-1.1s0.4,-0.8 0.4,-1.2c0,-0.5 -0.1,-0.9 -0.4,-1.2c-0.3,-0.3 -0.7,-0.4 -1.2,-0.4c-0.4,0 -0.8,0.1 -1.1,0.3c-0.3,0.2 -0.4,0.6 -0.4,1.1l-1.9,0c0,-1 0.3,-1.7 1,-2.2c0.6,-0.5 1.5,-0.8 2.5,-0.8c1.1,0 2,0.3 2.6,0.8c0.6,0.5 0.9,1.3 0.9,2.3c0,0.7 -0.2,1.3 -0.6,1.8c-0.4,0.6 -0.9,1.1 -1.5,1.6c-0.3,0.3 -0.5,0.5 -0.6,0.7c-0.1,0.2 -0.1,0.6 -0.1,1L19.5,17.700001zM21.4,21l-1.9,0l0,-1.8l1.9,0L21.4,21z"/> -</vector> diff --git a/service/res/layout/wifi_p2p_dialog.xml b/service/res/layout/wifi_p2p_dialog.xml deleted file mode 100644 index 86dcbfab3..000000000 --- a/service/res/layout/wifi_p2p_dialog.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 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. ---> - -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <LinearLayout android:id="@+id/info" - style="@style/wifi_section" /> - - <LinearLayout android:id="@+id/enter_pin_section" - style="@style/wifi_section" - android:visibility="gone"> - - <LinearLayout - style="@style/wifi_item"> - <TextView - android:text="@string/wifi_p2p_enter_pin_message" - style="@style/wifi_item_label" /> - - <EditText android:id="@+id/wifi_p2p_wps_pin" - android:singleLine="true" - android:maxLines="8" - android:inputType="number" - style="@style/wifi_item_content" /> - </LinearLayout> - </LinearLayout> - </LinearLayout> - -</ScrollView> diff --git a/service/res/layout/wifi_p2p_dialog_row.xml b/service/res/layout/wifi_p2p_dialog_row.xml deleted file mode 100644 index 2c88b1082..000000000 --- a/service/res/layout/wifi_p2p_dialog_row.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2010 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. ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - style="@style/wifi_item"> - <TextView - style="@style/wifi_item_label" - android:id="@+id/name" /> - - <TextView - android:id="@+id/value" - style="@style/wifi_item_content" - android:textStyle="bold" - android:textAlignment="viewStart" /> -</LinearLayout> diff --git a/service/res/values-af/strings.xml b/service/res/values-af/strings.xml deleted file mode 100644 index ff81fd344..000000000 --- a/service/res/values-af/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Stelsel-Wi-Fi-hulpbronne"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Koppel aan oop Wi-Fi-netwerk"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Koppel tans aan Wi-Fi-netwerk"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Aan Wi-Fi-netwerk gekoppel"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Kon nie aan Wi-Fi-netwerk koppel nie"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tik om alle netwerke te sien"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Koppel"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Alle netwerke"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Netwerkstatus"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Netwerkwaarskuwings"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Netwerk is beskikbaar"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Laat voorgestelde Wi‑Fi-netwerke toe?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Netwerke wat deur <xliff:g id="NAME">%s</xliff:g> voorgestel is. Toestel sal dalk outomaties koppel."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Laat toe"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nee, dankie"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Koppel aan <xliff:g id="CARRIERNAME">%s</xliff:g>-Wi‑Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Hierdie netwerke ontvang \'n SIM-ID wat gebruik kan word om toestelligging na te spoor"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Koppel"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Moenie koppel nie"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Bevestig verbinding?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"As jy koppel, kan <xliff:g id="CARRIERNAME">%s</xliff:g> se Wi‑Fi-netwerke toegang kry tot \'n unieke ID wat met jou SIM geassosieer word, of dit deel. Dit kan dit vir hulle moontlik maak om jou toestel se ligging na te spoor."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Koppel"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Moenie koppel nie"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi sal outomaties aanskakel"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Wanneer jy naby \'n gestoorde hoëgehaltenetwerk is"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Moenie weer aanskakel nie"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi is outomaties aangeskakel"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Jy is naby \'n gestoorde netwerk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Kon nie aan Wi-Fikoppel nie"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" het \'n swak internetverbinding."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Laat verbinding toe?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Program %1$s wil aan Wi-Fi-netwerk %2$s koppel"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"\'n Program"</string> - <string name="accept" msgid="5931271886782610829">"Aanvaar"</string> - <string name="decline" msgid="6874256900873707640">"Weier"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Uitnodiging gestuur"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Uitnodiging om te koppel"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Van:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Aan:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Voer die vereiste PIN in:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Die tablet sal tydelik van Wi-Fi ontkoppel terwyl dit aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gekoppel is"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Jou Android TV-toestel sal tydelik van Wi-Fi ontkoppel terwyl dit aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gekoppel is"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Die foon sal tydelik van Wi-Fi ontkoppel terwyl dit aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gekoppel is"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Kan nie aan <xliff:g id="SSID">%1$s</xliff:g> koppel nie"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tik om privaatheidinstellings te verander en herprobeer"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Verander privaatheidinstelling?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> moet jou toestel se MAC-adres, \'n unieke identifiseerder, gebruik om te koppel. Jou privaatheidinstelling vir hierdie netwerk gebruik tans \'n verewekansigde identifiseerder. \n\nHierdie verandering kan dit vir toestelle in die omtrek moontlik maak om jou toestel se ligging na te spoor."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Verander instelling"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Instelling is opgedateer. Probeer weer koppel"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Kan nie privaatheidinstelling verander nie"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Kon nie netwerk kry nie"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-stawingsfout 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-stawingsfout 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-stawingsfout 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-stawingsfout 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-stawingsfout 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-stawingsfout 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-stawingsfout 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Warmkol is afgeskakel"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Geen toestelle is gekoppel nie. Tik om te wysig."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi is ontkoppel"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Sit \'n <xliff:g id="CARRIER_NAME">%2$s</xliff:g>-SIM in om aan <xliff:g id="SSID">%1$s</xliff:g> te koppel"</string> -</resources> diff --git a/service/res/values-am/strings.xml b/service/res/values-am/strings.xml deleted file mode 100644 index 64c045ec5..000000000 --- a/service/res/values-am/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"የስርዓት Wi-Fi መርጃዎች"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"ከክፍት የWi‑Fi አውታረ መረብ ጋር ያገናኙ"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"ከWi‑Fi አውታረ መረብ ጋር በመገናኘት ላይ"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"ከWi‑Fi አውታረ መረብ ጋር ተገናኝቷል"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"ከWi‑Fi አውታረ መረብ ጋር መገናኘት አልተቻለም"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"ሁሉንም አውታረ መረቦችን ለማየት መታ ያድርጉ"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"አገናኝ"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"ሁሉም አውታረ መረቦች"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"የአውታረ መረብ ሁኔታ"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"የአውታረ መረብ ማንቂያዎች"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"አውታረ መረብ ይገኛል"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"የተጠቆሙ የWi‑Fi አውታረ መረቦች ይፈቀዱ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"በ<xliff:g id="NAME">%s</xliff:g> የተጠቆሙ አውታረ መረቦች። መሣሪያ በራስ-ሰር ሊገናኝ ይችላል።"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ፍቀድ"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"አይ፣ አመሰግናለሁ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"ከ<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi ጋር ይገናኙ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"እነዚህ አውታረ መረቦች የመሣሪያ አካባቢን ለመከታተል ሥራ ላይ ሊውል የሚችል የሲም መታወቂያ ተቀብለዋል።"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"አገናኝ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"አታገናኝ"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ግንኙነት ይረጋገጥ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ከተገናኙ የ<xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi አውትረ መረቦች ከእርስዎ ሲም ጋር የተጎዳኘ ልዩ መታወቂያ ሊደርሱ ወይም ሊያጋሩ ይችላሉ። ይህ የመሣሪያዎ አካባቢ ክትትል እንዲደረግበት ሊያስችል ይችላል።"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"አገናኝ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"አታገናኝ"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi በራስ-ሰር ይበራል"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"ከፍተኛ ጥራት ያለው የተቀመጠ አውታረ መረብ አቅራቢያ ሲሆኑ"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"መልሰህ አታብራ"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi በራስ-ሰር በርቷል"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"ከተቀመጠ አውታረ መረብ አቅራቢያ ነዎት፦ <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ወደ Wi-Fi ለማያያዝ አልተቻለም"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ደካማ የበይነመረብ ግንኙነት ኣለው፡፡"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"ግንኙነት ይፈቀድ?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"መተግበሪያ %1$s ወደ Wifi Network %2$s መገናኘት ይፈልጋል"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"አንድ መተግበሪያ"</string> - <string name="accept" msgid="5931271886782610829">"ተቀበል"</string> - <string name="decline" msgid="6874256900873707640">"ውድቅ አድርግ"</string> - <string name="ok" msgid="4215387532539340948">"እሺ"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ግብዣ ተልኳል"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"ለማገናኘት ግብዣ"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"ከ፦"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"ለ፦"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"የሚፈለገውን ፒን ተይብ፦"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"ፒን፦"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ጡባዊው ከ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ጋር ተገናኝቶ ባለበት ጊዜ በጊዜያዊነት ከWi-Fi ጋር ይላቀቃል"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"ወደ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ተገናኝቶ ሳለ የእርስዎ Android TV መሣሪያ ለጊዜው ከ Wi-Fi ግንኙነቱ ይቋረጣል"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ስልኩ ከ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ጋር ተገናኝቶ ባለበት ጊዜ በጊዜያዊነት ከWi-Fi ጋር ያለው ግንኙነት ይቋረጣል"</string> - <string name="dlg_ok" msgid="3250085870426030310">"እሺ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"ከ<xliff:g id="SSID">%1$s</xliff:g> ጋር መገናኘት አልተቻለም"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"የግላዊነት ቅንብሮችን ለመቀየር መታ ያድርጉ እና ዳግም ይሞክሩ"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"የግላዊነት ቅንብር ይቀየር?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"ለማገናኘት፣ <xliff:g id="SSID">%1$s</xliff:g> የእርስዎን መሣሪያ MAC አድራሻ፣ ልዩ ለይቶ ማወቂያ ለመጠቀም ይፈልጋል። አሁን ላይ፣ ለዚህ አውታረ መረብ የእርስዎ የግላዊነት ቅንብር በዘፈቀደ የተደረገ ለይቶ ማወቂያን ይጠቀማል። \n\nይህ የመሣሪያዎ አካባቢ አቅራቢያ ባሉ መሣሪያዎች ክትትል እንዲደረግበት ሊያደርገው ይችላል።"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ቅንብሮችን ለውጥ"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ቅንብር ተዘምኗል። እንደገና ለማገናኘት ይሞክሩ።"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"የግላዊነት ቅንብርን መቀየር አይቻልም"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"አውታረ መረብ አልተገኘም"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>፦ የEAP ማረጋገጥ ስህተት 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>፦ የEAP ማረጋገጥ ስህተት 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>፦ የEAP ማረጋገጥ ስህተት 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>፦ የEAP ማረጋገጥ ስህተት 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>፦ የEAP ማረጋገጥ ስህተት 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>፦ የEAP ማረጋገጥ ስህተት 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>፦ የEAP ማረጋገጥ ስህተት 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"መገናኛ ነጥብ ጠፍቷል"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"ምንም መሣሪያ አልተገናኘም። ለመቀየር መታ ያድርጉ።"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"የWifi ግንኙነት ተቋርጧል"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"ክ<xliff:g id="SSID">%1$s</xliff:g> ጋር ለመገናኘት የ<xliff:g id="CARRIER_NAME">%2$s</xliff:g> ሲም ያስገቡ"</string> -</resources> diff --git a/service/res/values-ar/strings.xml b/service/res/values-ar/strings.xml deleted file mode 100644 index 0ca426644..000000000 --- a/service/res/values-ar/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"مصادر شبكة Wi-Fi للنظام"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"الاتصال بشبكة Wi-Fi المفتوحة"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"جارٍ الاتصال بشبكة Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"تم الاتصال بشبكة Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"تعذَّر الاتصال بشبكة Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"انقر للاطلاع على جميع الشبكات"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"اتصال"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"جميع الشبكات"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"حالة الشبكة"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"تنبيهات الشبكة"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"الشبكة متوفرة"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"هل تريد السماح لشبكات Wi‑Fi المقترحة؟"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"شبكات <xliff:g id="NAME">%s</xliff:g> المقترحة - قد يتم توصيل الجهاز تلقائيًا."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"سماح"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"لا، شكرًا"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"هل تريد ربط <xliff:g id="CARRIERNAME">%s</xliff:g> بشبكة Wi-Fi؟"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"تتلقّى هذه الشبكات رقم تعريف لشريحة SIM يمكن استخدامه لتتبُّع الموقع الجغرافي للجهاز."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ربط"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"عدم الاتصال"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"هل تريد تأكيد الاتصال بالشبكة؟"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"في حال اتصال بالشبكة، يمكن لشبكات Wi‑Fi من <xliff:g id="CARRIERNAME">%s</xliff:g> الوصول إلى المعرّف الفريد المرتبط بشريحة SIM أو مشاركته. قد يسمح هذا بتتبُّع الموقع الجغرافي لجهازك."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"اتصال"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"عدم الاتصال"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"سيتم تفعيل شبكة Wi-Fi تلقائيًا."</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"عندما تكون بالقرب من شبكة محفوظة عالية الجودة"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"عدم إعادة التشغيل"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"تم تفعيل شبكة Wi-Fi تلقائيًا."</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"أنت قريب من شبكة محفوظة: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>."</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"تعذر الاتصال بـ Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" تحتوي على اتصال إنترنت ضعيف."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"هل تريد السماح بالاتصال؟"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"يريد تطبيق %1$s الاتصال بشبكة Wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"تطبيق"</string> - <string name="accept" msgid="5931271886782610829">"قبول"</string> - <string name="decline" msgid="6874256900873707640">"رفض"</string> - <string name="ok" msgid="4215387532539340948">"حسنًا"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"تم إرسال الدعوة"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"دعوة للاتصال"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"من:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"إلى:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"اكتب رمز PIN المطلوب:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"رقم التعريف الشخصي:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"سيتم قطع اتصال الجهاز اللوحي مؤقتًا بشبكة Wi-Fi في الوقت الذي يكون فيه متصلاً بـ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"سيتم قطع اتصال جهاز Android TV بشبكة Wi-Fi مؤقتًا أثناء اتصاله بجهاز<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"سيتم قطع اتصال الهاتف مؤقتًا بشبكة Wi-Fi في الوقت الذي يكون فيه متصلاً بـ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"حسنًا"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"يتعذّر الاتصال بـ <xliff:g id="SSID">%1$s</xliff:g>."</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"انقر لتغيير إعدادات الخصوصية وإعادة المحاولة."</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"هل تريد تغيير إعداد الخصوصية؟"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"للاتصال، تحتاج خدمة <xliff:g id="SSID">%1$s</xliff:g> إلى استخدام عنوان MAC الخاص بجهازك ومعرّف فريد. يستخدم إعداد الخصوصية لهذه الشبكة حاليًا معرّفًا عشوائيًا. \n\nقد يسمح هذا التغيير للأجهزة القريبة بتتبع الموقع الجغرافي لجهازك."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"تغيير الإعداد"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"تم تعديل الإعداد. حاوِل إعادة الاتصال."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"لا يمكن تغيير إعداد الخصوصية."</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"لم يتم العثور على الشبكة."</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : خطأ في مصادقة EAP رقم 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : خطأ في مصادقة EAP رقم 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : خطأ في مصادقة EAP رقم 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : خطأ في مصادقة EAP رقم 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : خطأ في مصادقة EAP رقم 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : خطأ في مصادقة EAP رقم 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : خطأ في مصادقة EAP رقم 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"تم إيقاف نقطة الاتصال."</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"ما مِن أجهزة متصلة. انقر للتعديل."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"تم قطع اتصال Wi-Fi."</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"للاتصال بشبكة <xliff:g id="SSID">%1$s</xliff:g>، عليك إدخال شريحة SIM من <xliff:g id="CARRIER_NAME">%2$s</xliff:g>."</string> -</resources> diff --git a/service/res/values-as/strings.xml b/service/res/values-as/strings.xml deleted file mode 100644 index a38a860c5..000000000 --- a/service/res/values-as/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"ছিষ্টেম ৱাই-ফাইৰ উৎসসমূহ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"পাছৱৰ্ড অবিহনে সংযোগ কৰিবপৰা ৱাই-ফাই নেটৱর্কৰ সৈতে সংযোগ কৰক"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"ৱাই-ফাই নেটৱৰ্কৰ সৈতে সংযোগ কৰি থকা হৈছে"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"ৱাই-ফাই নেটৱৰ্কৰ সৈতে সংযোগ কৰা হ’ল"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"ৱাই-ফাই নেটৱৰ্কৰ সৈতে সংযোগ কৰিবপৰা নগ\'ল"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"সকলো নেটৱৰ্ক চাবলৈ টিপক"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"সংযোগ কৰক"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"সকলো নেটৱৰ্ক"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"নেটৱৰ্কৰ স্থিতি"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"নেটৱৰ্ক সম্পৰ্কীয় সতৰ্কবাণী"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"নেটৱৰ্ক উপলব্ধ"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"পৰামর্শ হিচাপে পোৱা নেটৱর্কবোৰক অনুমতি দিবনে?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>এ পৰামর্শ হিচাপে দিয়া নেটৱর্কবোৰ। ডিভাইচটো স্বয়ংক্ৰিয়ভাৱে সংযোগ হ\'ব পাৰে।"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"অনুমতি দিয়ক"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"নালাগে, ধন্যবাদ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> ৱাই-ফাইৰ সৈতে সংযোগ কৰিবনে?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"এই নেটৱৰ্কটোৱে এটা ছিম আইডি পায়, যিটো ডিভাইচৰ অৱস্থান ট্ৰেক কৰিবলৈ ব্যৱহাৰ কৰিব পাৰি"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"সংযোগ কৰক"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"সংযোগ নকৰিব"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"সংযোগ নিশ্চিত কৰিবনে?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"আপুনি যদি সংযোগ কৰে, <xliff:g id="CARRIERNAME">%s</xliff:g>ৰ ৱাই-ফাই নেটৱৰ্কসমূহে আপোনাৰ ছিমৰ সৈতে জড়িত এটা সুকীয়া আইডি এক্সেছ কৰিব অথবা সেইটো শ্বেয়াৰ কৰিব পাৰে। এইটোৱে আপোনাৰ ডিভাইচটোৰ অৱস্থান ট্ৰেক কৰাৰ অনুমতি দিব পাৰে।"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"সংযোগ কৰক"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"সংযোগ নকৰিব"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"ৱাই-ফাই স্বয়ংক্ৰিয়ভাৱে অন হ\'ব"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"যেতিয়া আপুনি ছেভ কৰি থোৱা উচ্চ মানৰ নেটৱৰ্কৰ কাষত থাকে"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"পুনৰাই অন নকৰিব"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"ৱাই-ফাই স্বয়ংক্ৰিয়ভাৱে অন কৰা হ’ল"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"আপুনি ছেভ কৰি থোৱা নেটৱৰ্ক এটাৰ কাষত আছে: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ৱাই-ফাইৰ লগত সংযোগ কৰিব পৰা নগ\'ল"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ইণ্টাৰনেট সংযোগ যথেষ্ট দুর্বল।"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"সংযোগ কৰাৰ অনুমতি দিবনে?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s এপ্লিকেশ্বনটোৱে ৱাই-ফাই নেটৱৰ্ক %2$sৰ সৈতে সংযুক্ত হ\'ব বিচাৰিছে"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"এপ্লিকেশ্বন"</string> - <string name="accept" msgid="5931271886782610829">"স্বীকাৰ কৰক"</string> - <string name="decline" msgid="6874256900873707640">"প্ৰত্যাখ্যান কৰক"</string> - <string name="ok" msgid="4215387532539340948">"ঠিক আছে"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"আমন্ত্ৰণ পঠোৱা হ’ল"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"সংযোগ হ\'বলৈ আমন্ত্ৰণ"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"প্ৰেৰক:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"প্ৰতি:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"প্ৰয়োজনীয় পিন নম্বৰটো লিখক:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"পিন:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"টি.ভি.টো <xliff:g id="DEVICE_NAME">%1$s</xliff:g> লৈ সংযোগ হৈ থকাৰ অৱস্থাত অস্থায়ীভাৱে ৱাই-ফাইৰ পৰা সংযোগ বিচ্ছিন্ন হ\'ব"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"আপোনাৰ Android TV ডিভাইচটো <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ লগত সংযোগ হ’লে অস্থায়ীভাৱে ৱাই-ফাইৰ পৰা সংযোগ বিচ্ছিন্ন হ’ব"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ফ\'নটো <xliff:g id="DEVICE_NAME">%1$s</xliff:g> লৈ সংযোগ হ\'লে ৱাই-ফাইৰ পৰা কিছু সময়ৰ বাবে সংযোগ স্বীকাৰ বিচ্ছিন্ন হ\'ব"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ঠিক আছে"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g>ৰ সৈতে সংযোগ কৰিব নোৱাৰি"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"গোপনীয়তাৰ ছেটিংসমূহ সলনি কৰিবলৈ আৰু পুনৰ চেষ্টা কৰিবলৈ টিপক"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"গোপনীয়তাৰ ছেটিংটো সলনি কৰিবনে?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"সংযোগ কৰিবলৈ <xliff:g id="SSID">%1$s</xliff:g>এ আপোনাৰ ডিভাইচৰ MAC ঠিকনাটো, এটা সুকীয়া চিনাক্তকাৰী ব্যৱহাৰ কৰিব লাগে। বৰ্তমান, এই নেটৱৰ্কটোৰ বাবে আপোনাৰ গোপনীয়তাৰ ছেটিঙে এটা যাদৃচ্ছিক চিনাক্তকাৰী ব্যৱহাৰ কৰে। \n\nএই সালসলনিয়ে নিকটৱৰ্তী ডিভাইচসমূহক আপোনাৰ ডিভাইচটোৰ অৱস্থান ট্ৰেক কৰাৰ অনুমতি দিব পাৰে।"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ছেটিংটো সলনি কৰক"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ছেটিংটো আপডে’ট হ’ল। পুনৰ সংযোগ কৰিবলৈ চেষ্টা কৰক।"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"গোপনীয়তাৰ ছেটিংটো সলনি কৰিব নোৱাৰি"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"নেটৱৰ্ক বিচাৰ পোৱা নগ’ল"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : ইএপি বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ সম্পর্কীয় আসোঁৱাহ 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : ইএপি বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ সম্পর্কীয় আসোঁৱাহ 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : ইএপি বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ সম্পর্কীয় আসোঁৱাহ 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : ইএপি বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ সম্পর্কীয় আসোঁৱাহ 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : ইএপি বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ সম্পর্কীয় আসোঁৱাহ 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : ইএপি বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ সম্পর্কীয় আসোঁৱাহ 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : ইএপি বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ সম্পর্কীয় আসোঁৱাহ 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"হটস্পট অফ কৰা হ’ল"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"কোনো ডিভাইচ সংযোগ কৰা হোৱা নাই। সংশোধন কৰিবলৈ টিপক।"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"ৱাই-ফাই সংযোগ বিচ্ছিন্ন হৈছে"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g>ৰ সৈতে সংযোগ কৰিবলৈ এখন <xliff:g id="CARRIER_NAME">%2$s</xliff:g> ছিম ভৰাওক"</string> -</resources> diff --git a/service/res/values-az/strings.xml b/service/res/values-az/strings.xml deleted file mode 100644 index ae0455e02..000000000 --- a/service/res/values-az/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistem Wi-Fi Resursları"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Açıq Wi‑Fi şəbəkəsinə qoşulun"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi şəbəkəsinə qoşulur"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi şəbəkəsinə qoşuldu"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi şəbəkəsinə qoşulmaq mümkün deyil"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Bütün şəbəkələri görmək üçün klikləyin"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Qoşulun"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Bütün şəbəkələr"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Şəbəkə statusu"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Şəbəkə siqnalları"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Şəbəkə əlçatandır"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Təklif edilən Wi‑Fi şəbəkələrinə icazə verilsin?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> təklif edilən şəbəkə. Cihaz avtomatik qoşula bilər."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"İcazə verin"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Xeyr, təşəkkürlər"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi şəbəkəsinə qoşulsun?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Bu şəbəkələr cihaz məkanını izləmək üçün istifadə edilə biləcək SIM ID qəbul edir"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Qoşun"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Qoşulmayın"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Bağlantı təsdiq edilsin?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Qoşulsanız, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi şəbəkələri SIM kartınızla əlaqəli unikal ID\'ə daxil ola və ya onu paylaşa bilər. Bu, cihazınızın məkanının izlənilməsinə icazə verə bilər."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Qoşulun"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Qoşulmayın"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi avtomatik olaraq aktiv ediləcək"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Yadda saxlanmış yüksək keyfiyyətli şəbəkələr yaxınlıqda olduqda"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Yenidən aktiv etməyin"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi avtomatik aktiv edildi"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Yadda saxlanmış şəbəkəyə yaxınsınız: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi\'a qoşulmaq alınmadı"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" zəif internet əlaqəsi var"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Bağlantıya icazə verilsin?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Proqram %1$s Wifi Şəbəkəsinə qoşulmaq istəyir %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Tətbiq"</string> - <string name="accept" msgid="5931271886782610829">"Qəbul edin"</string> - <string name="decline" msgid="6874256900873707640">"İmtina edin"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Dəvətnamə göndərildi"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Qoşulmaq üçün dəvət"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Kimdən:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kimə:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Tələb olunan PİN kodu daxil edin:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PİN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Bu planşet <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına qoşulan zaman Wi-Fi şəbəkəsindən müvəqqəti ayrılmış olacaq"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına qoşularkən Wi-Fi bağlantısı müvəqqəti olaraq kəsiləcək."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Bu telefon <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına qoşulan zaman Wi-Fi şəbəkəsindən müvəqqəti ayrılmış olacaq"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> şəbəkəsinə qoşulmaq mümkün deyil"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Toxunaraq məxfilik ayarını dəyişin və yenidən cəhd edin"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Məxfilik ayarı dəyişdirilsin?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Qoşulmaq üçün <xliff:g id="SSID">%1$s</xliff:g> unikal identifikator olan cihazınızın MAC ünvanını istifadə etməlidir. Daha doğrusu, bu şəbəkə üçün məxfilik ayarınız təsadüfi identifikator istifadə edir. \n\nBu dəyişiklik yaxın cihazların cihazınızın məkanını izləməsinə imkan verə bilər."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Ayarı dəyişin"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Ayar güncəlləndi. Yenidən qoşulmağa çalışın."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Məxfilik ayarını dəyişmək mümkün deyil"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Şəbəkə tapılmadı"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP doğrulama xətası 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP doğrulama xətası 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP doğrulama xətası 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP doğrulama xətası 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP doğrulama xətası 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP doğrulama xətası 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP doğrulama xətası 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot deaktiv edilib"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Heç bir cihaz qoşulmayıb. Dəyişiklik etmək üçün toxunun."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi‑Fi bağlantısı kəsildi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> şəbəkəsinə qoşulmaq üçün <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM kartı daxil edin"</string> -</resources> diff --git a/service/res/values-b+sr+Latn/strings.xml b/service/res/values-b+sr+Latn/strings.xml deleted file mode 100644 index 634f9a743..000000000 --- a/service/res/values-b+sr+Latn/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistemski WiFi resursi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Povežite se sa otvorenom Wi‑Fi mrežom"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Povezuje se sa WiFi mrežom..."</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Povezali ste se sa Wi‑Fi mrežom"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Povezivanje sa Wi‑Fi mrežom nije uspelo"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Dodirnite da biste videli sve mreže"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Poveži"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Sve mreže"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Status mreže"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Obaveštenja u vezi sa mrežom"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Mreža je dostupna"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Želite da dozvolite predložene Wi‑Fi mreže?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mreže koje predlaže <xliff:g id="NAME">%s</xliff:g>. Uređaj će se možda povezati automatski."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Dozvoli"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, hvala"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Želite da se povežete na WiFi mrežu <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ove mreže dobijaju ID SIM kartice koji može da se koristi za praćenje lokacije uređaja"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Poveži"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne povezuj"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Želite li da potvrdite povezivanje?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ako se povežete, Wi‑Fi mreže operatera <xliff:g id="CARRIERNAME">%s</xliff:g> mogu da pristupaju jedinstvenom ID-u povezanom sa SIM karticom ili da ga dele. To može da omogući praćenje lokacije uređaja."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Poveži"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ne povezuj"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi će se automatski uključiti"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kada ste u blizini sačuvane mreže visokog kvaliteta"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ne uključuj ponovo"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi je automatski uključen"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"U blizini ste sačuvane mreže: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nije moguće povezati sa WiFi mrežom"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ima lošu internet vezu."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Želite li da dozvolite povezivanje?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikacija %1$s želi da se poveže na WiFi mrežu %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikacija"</string> - <string name="accept" msgid="5931271886782610829">"Prihvati"</string> - <string name="decline" msgid="6874256900873707640">"Odbij"</string> - <string name="ok" msgid="4215387532539340948">"Potvrdi"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Pozivnica je poslata"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Pozivnica za povezivanje"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Od:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kome:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Unesite potrebni PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet će privremeno prekinuti vezu sa WiFi-em dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV uređaj će privremeno prekinuti vezu sa WiFi mrežom dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon će privremeno prekinuti vezu sa WiFi-em dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Potvrdi"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Povezivanje na mrežu <xliff:g id="SSID">%1$s</xliff:g> nije uspelo"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Dodirnite da biste promenili podešavanja privatnosti i probali ponovo"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Želite li da promenite podešavanja privatnosti?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> treba da se poveže pomoću MAC adrese uređaja, jedinstvenog identifikatora. Podešavanje privatnosti za ovu mrežu trenutno koristi nasumični identifikator. \n\nOva izmena može da omogući uređajima u blizini da prate lokaciju uređaja."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Promeni podešavanje"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Podešavanje je ažurirano. Probajte ponovo da se povežete."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Promena podešavanja privatnosti nije uspela"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Mreža nije pronađena"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška pri potvrdi identiteta 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška pri potvrdi identiteta 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška pri potvrdi identiteta 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška pri potvrdi identiteta 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška pri potvrdi identiteta 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška pri potvrdi identiteta 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška pri potvrdi identiteta 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot je isključen"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nijedan uređaj nije povezan. Dodirnite da biste izmenili."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"WiFi veza je prekinuta"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Da biste se povezali na mrežu <xliff:g id="SSID">%1$s</xliff:g>, stavite <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM karticu"</string> -</resources> diff --git a/service/res/values-be/strings.xml b/service/res/values-be/strings.xml deleted file mode 100644 index 76e9c0219..000000000 --- a/service/res/values-be/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Сістэмныя рэсурсы Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Падключыцеся да адкрытай сеткі Wi-Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Падключэнне да сеткі Wi‑Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Выканана падключэнне да адкрытай сеткі Wi‑Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Не атрымалася падключыцца да адкрытай сеткі Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Дакраніцеся, каб убачыць усе сеткі"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Падключыцца"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Усе сеткі"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Стан сеткі"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Абвесткі сеткі"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Сетка даступная"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Дазволіць падключэнне да прапанаваных сетак Wi‑Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Праграма \"<xliff:g id="NAME">%s</xliff:g>\" прапанавала сеткі. Прылада можа падключыцца да ніх аўтаматычна."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Дазволіць"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Не, дзякуй"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Падключыцца да Wi-Fi аператара \"<xliff:g id="CARRIERNAME">%s</xliff:g>\"?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Гэтыя сеткі атрымліваюць ідэнтыфікатар SIM-карты, які можа выкарыстоўвацца для адсочвання месцазнаходжання прылады"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Падключыцца"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не падключацца"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Пацвердзіць падключэнне?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Калі вы падключыцеся, сеткі Wi‑Fi аператара \"<xliff:g id="CARRIERNAME">%s</xliff:g>\" змогуць атрымаць доступ да ўнікальнага ідэнтыфікатара, звязанага з вашай SIM-картай, ці абагуліць яго. Можа ўзнікнуць магчымасць адсочваць месцазнаходжанне вашай прылады."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Падключыцца"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Не падключацца"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi уключыцца аўтаматычна"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Побач з захаванай сеткай з высакаякасным сігналам"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Не ўключаць зноў"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi уключыўся аўтаматычна"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Вы знаходзіцеся побач з захаванай сеткай: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Немагчыма падключыцца да Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" дрэннае падключэнне да Інтэрнэту."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Дазволіць падключэнне?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Праграма %1$s хоча падключыцца да сеткі Wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Праграма"</string> - <string name="accept" msgid="5931271886782610829">"Прыняць"</string> - <string name="decline" msgid="6874256900873707640">"Адхіліць"</string> - <string name="ok" msgid="4215387532539340948">"ОК"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Запрашэнне адпраўлена"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Запрашэнне далучыцца"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Ад:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Каму:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Увядзіце патрэбны PIN-код:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-код"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Тэлефон будзе часова адключаны ад сеткі Wi-Fi, пакуль ён падлучаны да прылады <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Прылада Android TV будзе часова адключана ад сеткі Wi-Fi, пакуль яна падключана да прылады \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\""</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Тэлефон будзе часова адключаны ад Wi-Fi, пакуль ён падлучаны да прылады <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ОК"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Не ўдалося падключыцца да сеткі \"<xliff:g id="SSID">%1$s</xliff:g>\""</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Націсніце, каб змяніць налады прыватнасці, і паўтарыце спробу"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Змяніць наладу прыватнасці?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Для падключэння да сеткі \"<xliff:g id="SSID">%1$s</xliff:g>\" неабходна ўвесці ўнікальны ідэнтыфікатар – MAC-адрас вашай прылады. Цяпер у наладах прыватнасці гэтай сеткі выкарыстоўваецца выпадковы ідэнтыфікатар. \n\nПасля яго змянення прылады паблізу змогуць адсочваць месцазнаходжанне вашай прылады."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Змяніць наладу"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Налады абноўлены. Паспрабуйце падключыцца яшчэ раз."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Не ўдалося змяніць наладу прыватнасці"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Сетка не знойдзена"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : памылка аўтэнтыфікацыі EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : памылка аўтэнтыфікацыі EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : памылка аўтэнтыфікацыі EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : памылка аўтэнтыфікацыі EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : памылка аўтэнтыфікацыі EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : памылка аўтэнтыфікацыі EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : памылка аўтэнтыфікацыі EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Хот-спот выключаны"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Няма падключаных прылад. Націсніце, каб змяніць налады."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi выключаны"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Каб падключыцца да сеткі \"<xliff:g id="SSID">%1$s</xliff:g>\", устаўце SIM-карту аператара \"<xliff:g id="CARRIER_NAME">%2$s</xliff:g>\""</string> -</resources> diff --git a/service/res/values-bg/strings.xml b/service/res/values-bg/strings.xml deleted file mode 100644 index d849753b4..000000000 --- a/service/res/values-bg/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Системни Wi-Fi ресурси"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Свързване с отворена Wi‑Fi мрежа"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Установява се връзка с Wi-Fi мрежата"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Установихте връзка с Wi-Fi мрежата"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Не можа да се установи връзка с Wi‑Fi мрежата"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Докоснете, за да видите всички мрежи"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Свързване"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Всички мрежи"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Състояние на мрежата"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Сигнали за мрежата"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Налице е мрежа"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Да се разрешат ли предложените Wi‑Fi мрежи?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Предложени от <xliff:g id="NAME">%s</xliff:g> мрежи. Устройството може да се свърже автоматично."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Разрешаване"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Не, благодаря"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Искате ли да се свържете с Wi-Fi от <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Тези мрежи получават идентификатор за SIM карта, който може да се използва за проследяване на местоположението на устройството"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Свързване"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Без свързване"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Потвърждавате ли връзката?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ако се свържете, Wi-Fi мрежите на <xliff:g id="CARRIERNAME">%s</xliff:g> може да имат достъп или да споделят уникален идентификатор, свързан със SIM картата ви. Това може да позволи проследяването на местоположението на устройството ви."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Свързване"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Без свързване"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi ще се включи автоматично"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Когато сте в района на запазена мрежа с високо качество"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Без повторно включване"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi-Fi се включи автоматично"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Намирате се в района на запазена мрежа: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Не можа да се свърже с Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" има лоша връзка с интернет."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Да се разреши ли връзката?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Приложението %1$s иска да се свърже с Wi-Fi мрежата „%2$s“"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Приложение"</string> - <string name="accept" msgid="5931271886782610829">"Приемам"</string> - <string name="decline" msgid="6874256900873707640">"Отхвърлям"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Поканата е изпратена"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Покана за свързване"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"От:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"До:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Въведете задължителния ПИН:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"ПИН:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Таблетът временно ще прекъсне връзката с Wi-Fi, докато е свързан с/ъс <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Wi-Fi връзката на устройството ви с Android TV временно ще бъде прекратена, докато то е свързано към <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Телефонът временно ще прекрати връзката с Wi-Fi, докато е свързан с/ъс <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Не може да се установи връзка с(ъс) <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Докоснете, за да промените настройките за поверителност, и опитайте отново"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Да се промени ли настройката за поверителност?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"За да установи връзка, <xliff:g id="SSID">%1$s</xliff:g> трябва да използва MAC адреса (уникален идентификатор) на устройството ви. Понастоящем в настройката ви за поверителност за тази мрежа се използва рандомизиран идентификатор. \n\nТази промяна може да даде възможност на устройствата в близост да проследяват местоположението на устройството ви."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Промяна на настройката"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Настройката е актуализирана. Опитайте отново да установите връзка."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Настройката за поверителност не може да се промени"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Мрежата не е намерена"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> – Грешка при удостоверяването на EAP: 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> – Грешка при удостоверяването на EAP: 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> – Грешка при удостоверяването на EAP: 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> – Грешка при удостоверяването на EAP: 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> – Грешка при удостоверяването на EAP: 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> – Грешка при удостоверяването на EAP: 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> – Грешка при удостоверяването на EAP: 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Точката за достъп е изключена"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Няма свързани устройства. Докоснете за промяна."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Няма връзка с Wi-Fi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"За да се свържете с(ъс) <xliff:g id="SSID">%1$s</xliff:g>, поставете SIM карта от <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-bn/strings.xml b/service/res/values-bn/strings.xml deleted file mode 100644 index 2ca2fa95a..000000000 --- a/service/res/values-bn/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"সিস্টেম ওয়াই-ফাই-এর রিসোর্স"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"উন্মুক্ত ওয়াই-ফাই নেটওয়ার্কে সংযোগ করুন"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"ওয়াই-ফাই নেটওয়ার্কে কানেক্ট করা হচ্ছে"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"উন্মুক্ত ওয়াই-ফাই নেটওয়ার্কে সংযুক্ত করা হয়েছে"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"ওয়াই-ফাই নেটওয়ার্কে সংযোগ করা গেল না"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"সমস্ত নেটওয়ার্ক দেখতে ট্যাপ করুন"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"সংযুক্ত করুন"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"সব নেটওয়ার্ক"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"নেটওয়ার্কের স্থিতি"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"নেটওয়ার্ক সক্রান্ত অ্যালার্ট"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"নেটওয়ার্ক পাওয়া যাচ্ছে"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"সাজেস্ট করা ওয়াই-ফাই নেটওয়ার্কে কানেক্ট করার অনুমতি দিতে চান?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>-এর সাজেস্ট করা নেটওয়ার্ক। ডিভাইস নিজে থেকে কানেক্ট হতে পারে।"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"অনুমতি দিন"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"না থাক"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> ওয়াই-ফাইতে কানেক্ট করবেন?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"এই নেটওয়ার্কগুলির কাছে একটি সিম আইডি থাকে যা ব্যবহার করে এই নেটওয়ার্কের সাথে যুক্ত থাকা ডিভাইসের লোকেশন ট্র্যাক করা যেত পারে"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"কানেক্ট করুন"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"কানেক্ট করবেন না"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"কানেকশন কনফার্ম করতে চান?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"আপনি কানেক্ট করলে, <xliff:g id="CARRIERNAME">%s</xliff:g> ওয়াই-ফাই নেটওয়ার্ক আপনার সিমের সাথে সম্পর্কযুক্ত একটি অনন্য আইডি অ্যাক্সেস বা শেয়ার করতে পারে। এর ফলে আপনার ডিভাইসের লোকেশন ট্র্যাক করা যেতে পারে।"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"কানেক্ট করুন"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"কানেক্ট করবেন না"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"ওয়াই-ফাই অটোমেটিক চালু হবে"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"যখন আপনি একটি উচ্চ মানের সংরক্ষিত নেটওয়ার্ক কাছাকাছি থাকেন"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"আবার চালু করবেন না"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"ওয়াই-ফাই নিজে থেকে চালু করা হয়েছে"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"আপনি একটি সেভ করা নেটওয়ার্কের কাছেই আছেন: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ওয়াই-ফাই এর সাথে সংযোগ করা যায়নি"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ইন্টারনেট কানেকশন ভাল নেই।"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"সংযোগের অনুমতি দেবেন?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"অ্যাপ্লিকেশান %1$s ওয়াই ফাই নেটওয়ার্ক %2$s এর সাথে সংযোগ করতে চায়"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"একটি অ্যাপ্লিকেশান"</string> - <string name="accept" msgid="5931271886782610829">"গ্রহণ করুন"</string> - <string name="decline" msgid="6874256900873707640">"অস্বীকার করুন"</string> - <string name="ok" msgid="4215387532539340948">"ঠিক আছে"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"আমন্ত্রণ পাঠানো হয়েছে"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"সংযুক্ত হওয়ার আমন্ত্রণ"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"থেকে:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"প্রাপক:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"প্রয়োজনীয় পিনটি লিখুন:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"পিন:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ট্যাবলেটটি যখন <xliff:g id="DEVICE_NAME">%1$s</xliff:g> এ সংযুক্ত হবে তখন এটি ওয়াই-ফাই থেকে সাময়িকভাবে সংযোগ বিচ্ছিন্ন হবে"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>-এ কানেক্ট থাকা অবস্থায় আপনার Android TV ডিভাইস সাময়িকভাবে ওয়াই-ফাই থেকে ডিসকানেক্ট হয়ে যাবে"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ফোনটি যখন <xliff:g id="DEVICE_NAME">%1$s</xliff:g> এ সংযুক্ত হবে তখন এটি ওয়াই-ফাই থেকে সাময়িকভাবে সংযোগ বিচ্ছিন্ন হবে"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ঠিক আছে"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g>-এর সাথে কানেক্ট করা যাচ্ছে না"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"গোপনীয়তা সেটিংস পরিবর্তন করতে এবং আবার চেষ্টা করতে ট্যাপ করুন"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"গোপনীয়তা সেটিংস পরিবর্তন করবেন?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"কানেক্ট করার জন্য, একটি অনন্য শনাক্তকারী হিসেবে <xliff:g id="SSID">%1$s</xliff:g> আপনার ডিভাইসের MAC অ্যাড্রেস ব্যবহার করবে। আপনার গোপনীয়তা সেটিংস এখন এই নেটওয়ার্কের জন্য একটি র্যান্ডামাইজ করা শনাক্তকারী ব্যবহার করে। \n\nএই পরিবর্তনটি আশেপাশের ডিভাইসগুলিকে আপনার ডিভাইসের লোকেশন ট্র্যাক করার অনুমতি দিতে পারে।"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"সেটিং পরিবর্তন করুন"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"সেটিং আপডেট করা হয়েছে। আবার কানেক্ট করার চেষ্টা করুন।"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"গোপনীয়তা সেটিংস পরিবর্তন করা যাবে না"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"নেটওয়ার্ক পাওয়া যায়নি"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP যাচাইকরণের সমস্যা 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP যাচাইকরণের সমস্যা 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP যাচাইকরণের সমস্যা 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP যাচাইকরণের সমস্যা 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP যাচাইকরণের সমস্যা 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP যাচাইকরণের সমস্যা 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP যাচাইকরণের সমস্যা 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"হটস্পট বন্ধ করা আছে"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"কোনও ডিভাইস কানেক্ট করা নেই। পরিবর্তন করতে ট্যাপ করুন।"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"ওয়াই-ফাই ডিসকানেক্ট হয়েছে"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g>-এ কানেক্ট করার জন্য <xliff:g id="CARRIER_NAME">%2$s</xliff:g>-এর সিম কার্ড যোগ করুন"</string> -</resources> diff --git a/service/res/values-bs/strings.xml b/service/res/values-bs/strings.xml deleted file mode 100644 index 1afb4a27f..000000000 --- a/service/res/values-bs/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistemski Wi-Fi resursi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Povežite se na otvorenu Wi‑Fi mrežu"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Povezivanje na WiFi mrežu"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Povezani ste s WiFi mrežom"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Nije se moguće povezati s WiFi mrežom"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Dodirnite da vidite sve mreže"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Povežite se"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Sve mreže"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Status mreže"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Mrežna upozorenja"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Mreža je dostupna"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Dozvoliti predložene WiFi mreže?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mreže koje predlaže <xliff:g id="NAME">%s</xliff:g>. Uređaj će se možda povezati automatski."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Dozvoli"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, hvala"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Povezati se s WiFi mrežom operatera <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ove mreže primaju ID SIM-a koji se može koristiti za praćenje lokacije uređaja"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Poveži"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nemoj se povezati"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Potvrditi povezivanje?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ako se povežete, Wi-Fi mreže mobilnog operatera <xliff:g id="CARRIERNAME">%s</xliff:g> mogu pristupiti jedinstvenom ID-u koji je povezan s vašom SIM karticom ili ga podijeliti. Na taj način možete dozvoliti da se prati lokacija vašeg uređaja."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Poveži se"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Nemoj se povezati"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"WiFi će se uključiti automatski"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kada ste u blizini sačuvane mreže visokog kvaliteta"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Nemoj ponovo uključiti"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi veza se automatski uključila"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"U blizini ste sačuvane mreže: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Problem prilikom spajanja na WiFi mrežu"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ima lošu internetsku vezu."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Želite li dozvoliti povezivanje?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikacija %1$s se želi povezati s WiFi mrežom %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikacija"</string> - <string name="accept" msgid="5931271886782610829">"Prihvati"</string> - <string name="decline" msgid="6874256900873707640">"Odbijte"</string> - <string name="ok" msgid="4215387532539340948">"Uredu"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Pozivnica poslana"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Pozivnica za povezivanje"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Od:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Prima:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Unesite potrebni PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet će privremeno prekinuti WiFi vezu dok bude povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Povezanost Android TV uređaja i WiFi mreže će se privremeno prekinuti dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon će privremeno prekinuti WiFi vezu dok bude povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Uredu"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Nije se moguće povezati s mrežom <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Dodirnite da promijenite postavke privatnosti i pokušajte ponovo"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Promijeniti postavku privatnosti?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Za povezivanje <xliff:g id="SSID">%1$s</xliff:g> treba koristiti vašu MAC adresu, koja je jedinstveni identifikator. Vaša postavka privatnosti za ovu mrežu trenutno koristi nasumično odabrani identifikator. \n\nNa taj način se uređajima u blizini može dozvoliti da prate lokaciju vašeg uređaja."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Promijeni postavku"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Postavka je ažurirana. Pokušajte se ponovo povezati."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nije moguće promijeniti postavku privatnosti"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Mreža nije pronađena"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška autentifikacije 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška autentifikacije 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška autentifikacije 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška autentifikacije 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška autentifikacije 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška autentifikacije 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška autentifikacije 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Pristupna tačka je isključena"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nema povezanih uređaja. Dodirnite da izmijenite."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"WiFi nije povezan"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Da se povežete s mrežom <xliff:g id="SSID">%1$s</xliff:g>, umetnite SIM karticu mobilnog operatera <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-ca/strings.xml b/service/res/values-ca/strings.xml deleted file mode 100644 index 84ec8989b..000000000 --- a/service/res/values-ca/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Recursos del sistema Wi‑Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Connecta\'t a una xarxa Wi-Fi oberta"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"S\'està connectant a una xarxa Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"S\'ha connectat a la xarxa Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"No s\'ha pogut connectar a una xarxa Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Toca per veure totes les xarxes"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Connecta"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Totes les xarxes"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Estat de la xarxa"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertes de xarxa"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Hi ha una xarxa disponible"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Vols permetre les xarxes Wi‑Fi suggerides?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Xarxes suggerides de l\'aplicació <xliff:g id="NAME">%s</xliff:g>. El dispositiu pot connectar-se automàticament."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permet"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, gràcies"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vols connectar-te a la Wi‑Fi de l\'operador <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Aquestes xarxes reben un identificador de SIM que es pot utilitzar per fer el seguiment de la ubicació del dispositiu"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connecta"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"No et connectis"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vols confirmar la connexió?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si et connectes, les xarxes Wi‑Fi de l\'operador <xliff:g id="CARRIERNAME">%s</xliff:g> poden compartir un identificador únic associat a la teva SIM o bé accedir-hi. Això pot permetre que es faci un seguiment de la ubicació del teu dispositiu."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Connecta"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"No connectis"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"La Wi-Fi s\'activarà automàticament"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Quan siguis a prop d\'una xarxa de qualitat desada"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"No tornis a activar"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"La Wi‑Fi s\'ha activat automàticament"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Ets a prop d\'una xarxa desada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"No s\'ha pogut connectar a la Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" té una mala connexió a Internet."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Vols permetre la connexió?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"L\'aplicació %1$s vol connectar-se a la xarxa Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Una aplicació"</string> - <string name="accept" msgid="5931271886782610829">"Accepta"</string> - <string name="decline" msgid="6874256900873707640">"Rebutja"</string> - <string name="ok" msgid="4215387532539340948">"D\'acord"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"S\'ha enviat la invitació"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitació per connectar"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Per a:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Introdueix el PIN sol·licitat:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"La tauleta es desconnectarà temporalment de la Wi-Fi mentre estigui connectada a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"El dispositiu Android TV es desconnectarà temporalment de la Wi‑Fi mentre estigui connectat a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"El telèfon es desconnectarà temporalment de la Wi-Fi mentre estigui connectat a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"D\'acord"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"No es pot connectar a <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Toca per canviar la configuració de privadesa i torna-ho a provar"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Vols canviar l\'opció de configuració de privadesa?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Per connectar-se, <xliff:g id="SSID">%1$s</xliff:g> necessita utilitzar l\'adreça MAC del teu dispositiu, un identificador únic. Actualment, la configuració de privadesa d\'aquesta xarxa utilitza un identificador aleatori. \n\nAquest canvi pot permetre que altres dispositius propers facin un seguiment de la ubicació del teu dispositiu."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Canvia l\'opció de configuració"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"La configuració s\'ha actualitzat. Torna a provar de connectar-te."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"No es pot canviar l\'opció de configuració de privadesa"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"No s\'ha trobat la xarxa"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: error d\'autenticació EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: error d\'autenticació EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: error d\'autenticació EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: error d\'autenticació EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: error d\'autenticació EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: error d\'autenticació EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: error d\'autenticació EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"S\'ha desactivat el punt d\'accés Wi‑Fi"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"No hi ha cap dispositiu connectat. Toca per modificar."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"La Wi‑Fi està desconnectada"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Per connectar-te a <xliff:g id="SSID">%1$s</xliff:g>, insereix una SIM de l\'operador<xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-cs/strings.xml b/service/res/values-cs/strings.xml deleted file mode 100644 index dcc7b9fdd..000000000 --- a/service/res/values-cs/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Systémové zdroje Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Připojení k otevřené síti Wi-Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Připojování k síti Wi-Fi..."</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Připojeno k síti Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Připojení k síti Wi-Fi se nezdařilo"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Klepnutím zobrazíte všechny sítě"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Připojit"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Všechny sítě"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Stav sítě"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Síťová upozornění"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"K dispozici je síť"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Povolit navrhované sítě Wi-Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Sítě navrhované aplikací <xliff:g id="NAME">%s</xliff:g>. Zařízení se může připojovat automaticky."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Povolit"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, díky"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Připojit k Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Tyto sítě dostávají identifikátor SIM karty, pomocí něhož lze sledovat polohu zařízení"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Připojit"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nepřipojovat"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Potvrdit připojení?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Pokud se připojíte, sítě Wi-Fi operátora <xliff:g id="CARRIERNAME">%s</xliff:g> mohou získat přístup k jedinečnému ID přidruženému k vaší SIM kartě. Může to umožnit sledování polohy zařízení."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Připojit"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Nepřipojovat"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi se zapne automaticky"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Když budete v dosahu kvalitní uložené sítě"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Znovu nezapínat"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Automaticky se zapnulo připojení Wi-Fi"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Jste v dosahu uložené sítě: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Připojení k síti Wi-Fi se nezdařilo"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" má pomalé připojení k internetu."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Povolit připojení?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikace %1$s se chce připojit k síti Wi-Fi %2$s."</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikace"</string> - <string name="accept" msgid="5931271886782610829">"Přijmout"</string> - <string name="decline" msgid="6874256900873707640">"Odmítnout"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Pozvánka odeslána."</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Pozvánka k připojení"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Od:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Komu:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Zadejte požadovaný kód PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet se při připojení k zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> dočasně odpojí od sítě Wi-Fi"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Zatímco bude zařízení Android TV připojeno k zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, dočasně se odpojí od sítě Wi-Fi."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon se při připojení k zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> dočasně odpojí od sítě Wi-Fi"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"K síti <xliff:g id="SSID">%1$s</xliff:g> se nelze připojit"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Klepnutím změníte nastavení ochrany soukromí a budete opakovat pokus"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Změnit nastavení ochrany soukromí?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"K připojení potřebuje síť <xliff:g id="SSID">%1$s</xliff:g> použít adresu MAC vašeho zařízení – jedinečný identifikátor. V současné době vaše nastavení ochrany soukromí pro tuto síť používá náhodný identifikátor. \n\nTato změna může zařízením v okolí umožnit sledovat polohu vašeho zařízení."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Změnit nastavení"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Nastavení bylo aktualizováno. Zkuste se připojit znovu."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nastavení ochrany soukromí se nepodařilo změnit"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Síť nebyla nalezena"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: Chyba ověření EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: Chyba ověření EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: Chyba ověření EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: Chyba ověření EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: Chyba ověření EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: Chyba ověření EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: Chyba ověření EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot je vypnutý"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Žádná připojená zařízení Upravíte klepnutím."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Síť Wi-Fi je odpojena"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Chcete-li se připojit k síti <xliff:g id="SSID">%1$s</xliff:g>, vložte SIM kartu operátora <xliff:g id="CARRIER_NAME">%2$s</xliff:g>."</string> -</resources> diff --git a/service/res/values-da/strings.xml b/service/res/values-da/strings.xml deleted file mode 100644 index 6f388ee6a..000000000 --- a/service/res/values-da/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Ressourcer for systemets Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Opret forbindelse til et åbent Wi-Fi-netværk"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Opretter forbindelse til Wi-Fi-netværket"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Forbundet til Wi-Fi-netværket"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Der kan ikke oprettes forbindelse til Wi-Fi-netværket"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tryk for at se alle netværk"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Opret forbindelse"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Alle netværk"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Netværksstatus"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Netværksunderretninger"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Tilgængeligt netværk"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Vil du tillade foreslåede Wi‑Fi-netværk?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Netværk foreslået af <xliff:g id="NAME">%s</xliff:g>. Enheden opretter muligvis forbindelse automatisk."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Tillad"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nej tak"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Opret forbindelse til <xliff:g id="CARRIERNAME">%s</xliff:g>-Wi-Fi"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Disse netværk kræver et SIM-id, der kan bruges til at spore enhedens placering"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Opret forbindelse"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Opret ikke forbindelse"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vil du bekræfte forbindelsen?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Hvis du opretter forbindelse, kan Wi-Fi-netværk fra <xliff:g id="CARRIERNAME">%s</xliff:g> få adgang til eller dele et unikt id, der er knyttet til dit SIM-kort. Derved kan din enheds placering muligvis spores."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Opret forbindelse"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Opret ikke forbindelse"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi aktiveres automatisk"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Når du er i nærheden af et gemt netværk af høj kvalitet"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Aktivér ikke igen"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi blev automatisk aktiveret"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Du er i nærheden af et gemt netværk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Kunne ikke oprette forbindelse til Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" har en dårlig internetforbindelse."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Vil du tillade denne forbindelse?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Applikationen %1$s vil gerne have forbindelse til Wi-Fi-netværk %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"En applikation"</string> - <string name="accept" msgid="5931271886782610829">"Accepter"</string> - <string name="decline" msgid="6874256900873707640">"Afvis"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitationen er sendt"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitation til forbindelse"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Fra:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Til:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Skriv den påkrævede pinkode:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"Pinkode:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Wi-Fi-forbindelse til tabletten vil midlertidigt blive afbrudt, når den er tilsluttet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Wi-Fi-forbindelsen til din Android TV-enhed bliver midlertidigt afbrudt, når den er tilsluttet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefonens Wi-Fi-forbindelse vil midlertidigt blive afbrudt, når den er tilsluttet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Der kan ikke oprettes forbindelse til <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tryk for at ændre privatlivsindstillingerne, og prøv igen"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Vil du ændre privatlivsindstillingen?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> skal bruge din enheds MAC-adresse (som er et unikt id), for at oprette forbindelse. I øjeblikket bruges et tilfældigt id i henhold til dine privatlivsindstillinger for dette netværk. \n\nDenne ændring kan gøre det muligt for enheder i nærheden spore din enheds placering."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Skift indstilling"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Indstillingen blev opdateret. Prøv at oprette forbindelse igen."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Privatlivsindstillingen kan ikke ændres"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Netværket blev ikke fundet"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-godkendelsesfejl 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-godkendelsesfejl 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-godkendelsesfejl 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-godkendelsesfejl 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-godkendelsesfejl 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-godkendelsesfejl 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-godkendelsesfejl 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot er slået fra"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Der er ikke tilsluttet nogen enheder. Tryk for at ændre."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi-forbindelsen er afbrudt"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Indsæt et SIM-kort fra <xliff:g id="CARRIER_NAME">%2$s</xliff:g> for at oprette forbindelse til <xliff:g id="SSID">%1$s</xliff:g>."</string> -</resources> diff --git a/service/res/values-de/strings.xml b/service/res/values-de/strings.xml deleted file mode 100644 index ad695ce07..000000000 --- a/service/res/values-de/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"System-WLAN-Ressourcen"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Mit offenem WLAN verbinden"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Verbindung zu WLAN wird hergestellt"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Mit WLAN verbunden"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"WLAN-Verbindung konnte nicht hergestellt werden"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tippen, um alle Netzwerke zu sehen"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Verbinden"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Alle Netzwerke"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Netzwerkstatus"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Netzwerkwarnungen"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Netzwerk verfügbar"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Vorgeschlagene WLANs zulassen?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Von <xliff:g id="NAME">%s</xliff:g> vorgeschlagene Netzwerke. Gerät verbindet sich möglicherweise automatisch."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Zulassen"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nein danke"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Mit <xliff:g id="CARRIERNAME">%s</xliff:g>-WLAN verbinden?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Diese Netzwerke empfangen eine SIM-ID, mit der der Gerätestandort erfasst werden kann"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Verbinden"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nicht verbinden"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Verbindung bestätigen?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Wenn du eine Verbindung herstellst, können die WLANs von <xliff:g id="CARRIERNAME">%s</xliff:g> möglicherweise eine eindeutige ID abrufen oder teilen, die deiner SIM zugewiesen ist. Damit lässt sich unter Umständen der Standort deines Geräts ermitteln."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Verbinden"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Nicht verbinden"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"WLAN wird automatisch aktiviert"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Wenn du in der Nähe eines sicheren gespeicherten Netzwerks bist"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Nicht wieder aktivieren"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"WLAN automatisch aktiviert"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Du bist in der Nähe eines gespeicherten Netzwerks: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Es konnte keine WLAN-Verbindung hergestellt werden."</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" hat eine schlechte Internetverbindung."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Verbindung zulassen?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Die App \"%1$s\" möchte eine Verbindung zum WLAN %2$s herstellen."</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Eine App"</string> - <string name="accept" msgid="5931271886782610829">"Akzeptieren"</string> - <string name="decline" msgid="6874256900873707640">"Ablehnen"</string> - <string name="ok" msgid="4215387532539340948">"Ok"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Einladung gesendet"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Einladung zum Aufbau einer Verbindung"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Von:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"An:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Gib die PIN ein:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Das Tablet wird vorübergehend vom WLAN getrennt, während eine Verbindung mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> besteht."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Das Android TV-Gerät wird vorübergehend vom WLAN getrennt, während es mit \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" verbunden ist."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Das Telefon wird vorübergehend vom WLAN getrennt, während eine Verbindung mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> hergestellt wird."</string> - <string name="dlg_ok" msgid="3250085870426030310">"Ok"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Verbindung zu <xliff:g id="SSID">%1$s</xliff:g> nicht möglich"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tippe, um die Datenschutzeinstellung zu ändern und es noch einmal zu versuchen"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Datenschutzeinstellung ändern?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Wenn du eine Verbindung herstellen möchtest, muss <xliff:g id="SSID">%1$s</xliff:g> die MAC-Adresse deines Geräts verwenden; die MAC-Adresse ist eine Kennung, mit der das Gerät eindeutig identifiziert werden kann. In deiner Datenschutzeinstellung für dieses Netzwerk wird momentan eine zufällige Kennung genutzt. \n\nDurch diese Änderung können andere Geräte in der Nähe den Standort deines Geräts möglicherweise verfolgen."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Einstellung ändern"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Einstellung aktualisiert. Versuch noch einmal, eine Verbindung herzustellen."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Datenschutzeinstellung kann nicht geändert werden"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Netzwerk nicht gefunden"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-Authentifizierungsfehler 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-Authentifizierungsfehler 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-Authentifizierungsfehler 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-Authentifizierungsfehler 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-Authentifizierungsfehler 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-Authentifizierungsfehler 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-Authentifizierungsfehler 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot ist deaktiviert"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Keine Geräte verbunden. Tippen, um Einstellungen zu ändern."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"WLAN nicht verbunden"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Lege eine SIM-Karte von <xliff:g id="CARRIER_NAME">%2$s</xliff:g> ein, um eine Verbindung mit <xliff:g id="SSID">%1$s</xliff:g> herzustellen"</string> -</resources> diff --git a/service/res/values-el/strings.xml b/service/res/values-el/strings.xml deleted file mode 100644 index 83bdbfe5c..000000000 --- a/service/res/values-el/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Πόροι Wi-Fi συστήματος"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Σύνδεση σε ανοιχτό δίκτυο Wi‑Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Σύνδεση σε δίκτυο Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Ολοκληρώθηκε η σύνδεση στο δίκτυο Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Δεν ήταν δυνατή η σύνδεση σε δίκτυο Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Πατήστε για να δείτε όλα τα δίκτυα"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Σύνδεση"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Όλα τα δίκτυα"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Κατάσταση δικτύου"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Ειδοποιήσεις δικτύου"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Το δίκτυο είναι διαθέσιμο"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Να επιτρέπονται προτεινόμενα δίκτυα Wi‑Fi;"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Προτεινόμενα δίκτυα <xliff:g id="NAME">%s</xliff:g>. Η συσκευή μπορεί να συνδεθεί αυτόματα."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Αποδοχή"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Όχι, ευχαριστώ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Σύνδεση στο Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>;"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Αυτά τα δίκτυα λαμβάνουν ένα αναγνωριστικό SIM που μπορεί να χρησιμοποιηθεί για την παρακολούθηση της τοποθεσίας της συσκευής."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Σύνδεση"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Να μην γίνει σύνδεση."</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Επιβεβαίωση της σύνδεσης;"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Εάν συνδεθείτε, τα δίκτυα Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> ενδέχεται να έχουν πρόσβαση ή να μοιράζονται ένα μοναδικό αναγνωριστικό που σχετίζεται με την κάρτα σας SIM. Αυτό μπορεί να επιτρέψει την παρακολούθηση της τοποθεσίας της συσκευής σας."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Σύνδεση"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Να μην γίνει σύνδεση."</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Το Wi‑Fi θα ενεργοποιηθεί αυτόματα"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Όταν βρίσκεστε κοντά σε αποθηκευμένο δίκτυο υψηλής ποιότητας"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Να μην ενεργοποιηθεί ξανά"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Το Wi‑Fi ενεργοποιήθηκε αυτόματα"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Βρίσκεστε κοντά σε αποθηκευμένο δίκτυο: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Δεν είναι δυνατή η σύνδεση στο Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" έχει κακή σύνδεση Διαδικτύου."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Να επιτρέπεται η σύνδεση;"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Η εφαρμογή %1$s θα ήθελε να συνδεθεί με το δίκτυο Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Μια εφαρμογή"</string> - <string name="accept" msgid="5931271886782610829">"Αποδοχή"</string> - <string name="decline" msgid="6874256900873707640">"Απόρριψη"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Η πρόσκληση στάλθηκε"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Πρόσκληση για σύνδεση"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Από:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Προς:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Πληκτρολογήστε τον απαιτούμενο κωδικό PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Το tablet θα αποσυνδεθεί προσωρινά από το δίκτυο Wi-Fi ενώ συνδέεται στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Η συσκευή σας Android TV θα αποσυνδεθεί προσωρινά από το δίκτυο Wi-Fi, ενόσω είναι συνδεδεμένη στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Το τηλέφωνο θα αποσυνδεθεί προσωρινά από το δίκτυο Wi-Fi ενώ συνδέεται στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ΟΚ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Δεν είναι δυνατή η σύνδεση με <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Πατήστε για αλλαγή των ρυθμίσεων απορρήτου και δοκιμάστε ξανά"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Αλλαγή της ρύθμισης απορρήτου;"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Για να συνδεθεί, το <xliff:g id="SSID">%1$s</xliff:g> θα πρέπει να χρησιμοποιήσει τη διεύθυνση MAC σας, η οποία είναι ένα μοναδικό αναγνωριστικό. Αυτήν τη στιγμή, η ρύθμιση απορρήτου σας για αυτό το δίκτυο χρησιμοποιεί ένα τυχαίο αναγνωριστικό. \n\nΑυτή η αλλαγή μπορεί να επιτρέψει την παρακολούθηση της τοποθεσίας της συσκευής σας από συσκευές σε κοντινή απόσταση."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Αλλαγή ρύθμισης"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Η ρύθμιση ενημερώθηκε. Δοκιμάστε να συνδεθείτε ξανά."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Δεν είναι δυνατή η αλλαγή της ρύθμισης απορρήτου"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Δεν βρέθηκε δίκτυο"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Σφάλμα ελέγχου ταυτότητας EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Σφάλμα ελέγχου ταυτότητας EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Σφάλμα ελέγχου ταυτότητας EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Σφάλμα ελέγχου ταυτότητας EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Σφάλμα ελέγχου ταυτότητας EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Σφάλμα ελέγχου ταυτότητας EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Σφάλμα ελέγχου ταυτότητας EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Το σημείο πρόσβασης Wi-Fi απενεργοποιήθηκε."</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Δεν υπάρχουν συνδεδεμένες συσκευές. Πατήστε για τροποποίηση."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Το Wi-Fi αποσυνδέθηκε."</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Για να συνδεθείτε στο <xliff:g id="SSID">%1$s</xliff:g>, τοποθετήστε μια κάρτα SIM <xliff:g id="CARRIER_NAME">%2$s</xliff:g>."</string> -</resources> diff --git a/service/res/values-en-rAU/strings.xml b/service/res/values-en-rAU/strings.xml deleted file mode 100644 index 43d5ce869..000000000 --- a/service/res/values-en-rAU/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"System Wi-Fi resources"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Connect to open Wi‑Fi network"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Connecting to Wi‑Fi network"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Connected to Wi‑Fi network"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Could not connect to Wi‑Fi network"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tap to see all networks"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Connect"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"All networks"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Network status"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Network alerts"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Network available"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Allow suggested Wi‑Fi networks?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Allow"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, thanks"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connect to <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"These networks receive a SIM ID that can be used to track device location"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connect"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Don\'t connect"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirm connection?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"If you connect, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi networks may access or share a unique ID associated with your SIM. This may allow your device\'s location to be tracked."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Connect"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Don\'t connect"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi will turn on automatically"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"When you\'re near a high‑quality saved network"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Don\'t turn back on"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi turned on automatically"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"You\'re near a saved network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Couldn\'t connect to Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" has a poor Internet connection."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Allow connection?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Application %1$s would like to connect to Wi-Fi Network %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"An application"</string> - <string name="accept" msgid="5931271886782610829">"Accept"</string> - <string name="decline" msgid="6874256900873707640">"Decline"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitation sent"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitation to connect"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"From:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"To:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Type the required PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"The tablet will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Your Android TV device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"The phone will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Can\'t connect to <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tap to change privacy settings and retry"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Change privacy setting?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"To connect, <xliff:g id="SSID">%1$s</xliff:g> needs to use your device MAC address, a unique identifier. Currently, your privacy setting for this network uses a randomised identifier. \n\nThis change may allow your device\'s location to be tracked by nearby devices."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Change setting"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Setting updated. Try connecting again."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Can\'t change privacy setting"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Network not found"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot turned off"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"No devices connected. Tap to modify."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi‑Fi disconnected"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"To connect to <xliff:g id="SSID">%1$s</xliff:g>, insert a <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM"</string> -</resources> diff --git a/service/res/values-en-rCA/strings.xml b/service/res/values-en-rCA/strings.xml deleted file mode 100644 index 43d5ce869..000000000 --- a/service/res/values-en-rCA/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"System Wi-Fi resources"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Connect to open Wi‑Fi network"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Connecting to Wi‑Fi network"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Connected to Wi‑Fi network"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Could not connect to Wi‑Fi network"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tap to see all networks"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Connect"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"All networks"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Network status"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Network alerts"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Network available"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Allow suggested Wi‑Fi networks?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Allow"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, thanks"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connect to <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"These networks receive a SIM ID that can be used to track device location"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connect"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Don\'t connect"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirm connection?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"If you connect, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi networks may access or share a unique ID associated with your SIM. This may allow your device\'s location to be tracked."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Connect"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Don\'t connect"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi will turn on automatically"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"When you\'re near a high‑quality saved network"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Don\'t turn back on"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi turned on automatically"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"You\'re near a saved network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Couldn\'t connect to Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" has a poor Internet connection."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Allow connection?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Application %1$s would like to connect to Wi-Fi Network %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"An application"</string> - <string name="accept" msgid="5931271886782610829">"Accept"</string> - <string name="decline" msgid="6874256900873707640">"Decline"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitation sent"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitation to connect"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"From:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"To:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Type the required PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"The tablet will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Your Android TV device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"The phone will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Can\'t connect to <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tap to change privacy settings and retry"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Change privacy setting?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"To connect, <xliff:g id="SSID">%1$s</xliff:g> needs to use your device MAC address, a unique identifier. Currently, your privacy setting for this network uses a randomised identifier. \n\nThis change may allow your device\'s location to be tracked by nearby devices."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Change setting"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Setting updated. Try connecting again."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Can\'t change privacy setting"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Network not found"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot turned off"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"No devices connected. Tap to modify."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi‑Fi disconnected"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"To connect to <xliff:g id="SSID">%1$s</xliff:g>, insert a <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM"</string> -</resources> diff --git a/service/res/values-en-rGB/strings.xml b/service/res/values-en-rGB/strings.xml deleted file mode 100644 index 43d5ce869..000000000 --- a/service/res/values-en-rGB/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"System Wi-Fi resources"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Connect to open Wi‑Fi network"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Connecting to Wi‑Fi network"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Connected to Wi‑Fi network"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Could not connect to Wi‑Fi network"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tap to see all networks"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Connect"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"All networks"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Network status"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Network alerts"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Network available"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Allow suggested Wi‑Fi networks?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Allow"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, thanks"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connect to <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"These networks receive a SIM ID that can be used to track device location"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connect"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Don\'t connect"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirm connection?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"If you connect, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi networks may access or share a unique ID associated with your SIM. This may allow your device\'s location to be tracked."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Connect"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Don\'t connect"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi will turn on automatically"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"When you\'re near a high‑quality saved network"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Don\'t turn back on"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi turned on automatically"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"You\'re near a saved network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Couldn\'t connect to Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" has a poor Internet connection."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Allow connection?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Application %1$s would like to connect to Wi-Fi Network %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"An application"</string> - <string name="accept" msgid="5931271886782610829">"Accept"</string> - <string name="decline" msgid="6874256900873707640">"Decline"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitation sent"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitation to connect"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"From:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"To:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Type the required PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"The tablet will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Your Android TV device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"The phone will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Can\'t connect to <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tap to change privacy settings and retry"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Change privacy setting?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"To connect, <xliff:g id="SSID">%1$s</xliff:g> needs to use your device MAC address, a unique identifier. Currently, your privacy setting for this network uses a randomised identifier. \n\nThis change may allow your device\'s location to be tracked by nearby devices."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Change setting"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Setting updated. Try connecting again."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Can\'t change privacy setting"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Network not found"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot turned off"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"No devices connected. Tap to modify."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi‑Fi disconnected"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"To connect to <xliff:g id="SSID">%1$s</xliff:g>, insert a <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM"</string> -</resources> diff --git a/service/res/values-en-rIN/strings.xml b/service/res/values-en-rIN/strings.xml deleted file mode 100644 index 43d5ce869..000000000 --- a/service/res/values-en-rIN/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"System Wi-Fi resources"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Connect to open Wi‑Fi network"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Connecting to Wi‑Fi network"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Connected to Wi‑Fi network"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Could not connect to Wi‑Fi network"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tap to see all networks"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Connect"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"All networks"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Network status"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Network alerts"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Network available"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Allow suggested Wi‑Fi networks?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Allow"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, thanks"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connect to <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"These networks receive a SIM ID that can be used to track device location"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connect"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Don\'t connect"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirm connection?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"If you connect, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi networks may access or share a unique ID associated with your SIM. This may allow your device\'s location to be tracked."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Connect"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Don\'t connect"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi will turn on automatically"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"When you\'re near a high‑quality saved network"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Don\'t turn back on"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi turned on automatically"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"You\'re near a saved network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Couldn\'t connect to Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" has a poor Internet connection."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Allow connection?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Application %1$s would like to connect to Wi-Fi Network %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"An application"</string> - <string name="accept" msgid="5931271886782610829">"Accept"</string> - <string name="decline" msgid="6874256900873707640">"Decline"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitation sent"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitation to connect"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"From:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"To:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Type the required PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"The tablet will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Your Android TV device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"The phone will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Can\'t connect to <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tap to change privacy settings and retry"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Change privacy setting?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"To connect, <xliff:g id="SSID">%1$s</xliff:g> needs to use your device MAC address, a unique identifier. Currently, your privacy setting for this network uses a randomised identifier. \n\nThis change may allow your device\'s location to be tracked by nearby devices."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Change setting"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Setting updated. Try connecting again."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Can\'t change privacy setting"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Network not found"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot turned off"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"No devices connected. Tap to modify."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi‑Fi disconnected"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"To connect to <xliff:g id="SSID">%1$s</xliff:g>, insert a <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM"</string> -</resources> diff --git a/service/res/values-es-rUS/strings.xml b/service/res/values-es-rUS/strings.xml deleted file mode 100644 index a512dc40d..000000000 --- a/service/res/values-es-rUS/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Recursos Wi‑Fi del sistema"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Conéctate a una red Wi-Fi abierta"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Estableciendo conexión con la red Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Se conectó a la red Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"No fue posible conectarse a la red Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Presiona para ver todas las redes"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Conectar"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Todas las redes"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Estado de la red"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertas de red"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Red disponible"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"¿Quieres permitir las redes Wi‑Fi sugeridas?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> sugirió redes. Es posible que el dispositivo se conecte automáticamente."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, gracias"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"¿Quieres conectarte a la red Wi-Fi de <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Estas redes reciben un ID de SIM que puede usarse para realizar el seguimiento de la ubicación del dispositivo"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"No conectar"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"¿Confirmar conexión?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si te conectas, las redes de Wi-Fi de <xliff:g id="CARRIERNAME">%s</xliff:g> podrán acceder o compartir un ID único asociado con tu SIM. Esto podría permitir que se realice el seguimiento de la ubicación del dispositivo."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"No conectar"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Se activará la conexión Wi-Fi automáticamente"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Cuando estés cerca de una red guardada de alta calidad"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"No volver a activar"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Se activó el Wi-Fi automáticamente"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Estás cerca de una red guardada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"No se pudo conectar a la red Wi-Fi."</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" tiene una mala conexión a Internet."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"¿Permitir la conexión?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"La aplicación %1$s quiere conectarse a la red Wi-Fi %2$s."</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Una aplicación"</string> - <string name="accept" msgid="5931271886782610829">"Aceptar"</string> - <string name="decline" msgid="6874256900873707640">"Rechazar"</string> - <string name="ok" msgid="4215387532539340948">"Aceptar"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Se envió la invitación."</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitación para conectarse"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Para:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Escribe el PIN solicitado:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"La tablet se desconectará temporalmente de la red Wi-Fi mientras esté conectada a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Se desconectará temporalmente el dispositivo Android TV de la red Wi-Fi mientras esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"El dispositivo se desconectará temporalmente de la red Wi-Fi mientras esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="dlg_ok" msgid="3250085870426030310">"Aceptar"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"No se puede establecer conexión con <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Presiona para cambiar la configuración de privacidad y volver a intentarlo"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"¿Quieres cambiar la configuración de privacidad?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Para conectarse, <xliff:g id="SSID">%1$s</xliff:g> necesita usar la dirección MAC (un identificador único) de tu dispositivo. Actualmente, tu configuración de privacidad para esta red usa un identificador aleatorio. \n\nEste cambio podría permitir que dispositivos cercanos registren la ubicación del tuyo."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Cambiar configuración"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Se actualizó la configuración. Intenta conectarte de nuevo."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"No se puede cambiar la configuración de privacidad"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"No se encontró ninguna red"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: Error de autenticación de EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: Error de autenticación de EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: Error de autenticación de EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: Error de autenticación de EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: Error de autenticación de EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: Error de autenticación de EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: Error de autenticación de EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Se desactivó el hotspot"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"No hay dispositivos conectados. Presiona para modificar la configuración."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Sin conexión Wi-Fi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Para conectarte a <xliff:g id="SSID">%1$s</xliff:g>, inserta una SIM de <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-es/strings.xml b/service/res/values-es/strings.xml deleted file mode 100644 index 4695bd075..000000000 --- a/service/res/values-es/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Recursos Wi‑Fi del sistema"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Conectarse a una red Wi-Fi abierta"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Estableciendo conexión con la red Wi‑Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Conectado a la red Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"No se ha podido conectar a la red Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Toca para ver todas las redes"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Conectarse"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Todas las redes"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Estado de la red"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertas de la red"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Red disponible"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"¿Permitir sugerencias de redes Wi‑Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> te ha sugerido alguna red. El dispositivo puede que se conecte automáticamente."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, gracias"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"¿Conectarse a la red Wi‑Fi de <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Estas redes reciben un ID de SIM con el que se puede rastrear la ubicación del dispositivo"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"No conectar"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"¿Confirmar conexión?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si te conectas, es posible que la red Wi‑Fi de <xliff:g id="CARRIERNAME">%s</xliff:g> obtenga o comparta un ID único asociado a tu SIM, lo que puede permitir que se rastree la ubicación de tu dispositivo."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"No conectar"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"La conexión Wi‑Fi se activará automáticamente"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Cuando estés cerca de una red de alta calidad guardada"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"No volver a activar"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi activada automáticamente"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Estás cerca de una red guardada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"No se ha podido establecer conexión con la red Wi-Fi."</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" tiene una mala conexión a Internet."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"¿Permitir la conexión?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"La aplicación %1$s quiere establecer conexión con la red Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Una aplicación"</string> - <string name="accept" msgid="5931271886782610829">"Aceptar"</string> - <string name="decline" msgid="6874256900873707640">"Rechazar"</string> - <string name="ok" msgid="4215387532539340948">"Aceptar"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitación enviada"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitación para conectarse"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Para:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Escribe el PIN solicitado:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"El tablet se desconectará temporalmente de la red Wi-Fi mientras esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Mientras el dispositivo Android TV esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, se desconectará temporalmente de la red Wi‑Fi"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"El teléfono se desconectará temporalmente de la red Wi-Fi mientras está conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="dlg_ok" msgid="3250085870426030310">"Aceptar"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"No se puede conectar a <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Toca para cambiar los ajustes de privacidad y vuelve a intentarlo"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"¿Quieres cambiar el ajuste de privacidad?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Para conectarse, <xliff:g id="SSID">%1$s</xliff:g> necesita la dirección MAC de tu dispositivo, que es un identificador único; no obstante, ahora el ajuste de privacidad que has configurado para usar en esta red utiliza un identificador aleatorio. \n\nEs posible que este cambio permita que los dispositivos cercanos registren la ubicación de tu dispositivo."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Cambiar ajuste"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Se ha cambiado el ajuste. Prueba a conectarte de nuevo."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"No se ha podido cambiar el ajuste de privacidad"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"No se ha encontrado la red"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: error de autenticación de EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: error de autenticación de EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: error de autenticación de EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: error de autenticación de EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: error de autenticación de EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: error de autenticación de EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: error de autenticación de EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Punto de acceso desactivado"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"No hay dispositivos conectados. Toca para modificar este ajuste."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi‑Fi desconectado"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Para conectarte a <xliff:g id="SSID">%1$s</xliff:g>, inserta una tarjeta SIM de <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-et/strings.xml b/service/res/values-et/strings.xml deleted file mode 100644 index 00713b6d2..000000000 --- a/service/res/values-et/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Süsteemi WiFi-ressursid"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Looge ühendus avatud WiFi-võrguga"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"WiFi-võrguga ühendamine"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Ühendatud WiFi-võrguga"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"WiFi-võrguga ei õnnestunud ühendust luua"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Puudutage kõikide võrkude nägemiseks"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Ühenda"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Kõik võrgud"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Võrgu olek"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Võrguteavitused"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Võrk on saadaval"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Kas lubada soovitatud WiFi-võrgud?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Rakenduse <xliff:g id="NAME">%s</xliff:g> soovitatud võrgud. Seade võib automaatselt ühenduse luua."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Luba"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Tänan, ei"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Kas luua ühendus operaatori <xliff:g id="CARRIERNAME">%s</xliff:g> WiFi-võrguga?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Need võrgud saavad SIM-i ID, mida saab kasutada seadme asukoha jälgimiseks."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Ühenda"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ära ühenda"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Kas soovite ühenduse kinnitada?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Kui loote ühenduse, võivad operaatori <xliff:g id="CARRIERNAME">%s</xliff:g> WiFi-võrgud teie SIM-kaardiga seotud kordumatule ID-le juurde pääseda või seda jagada. See võib võimaldada seadme asukohta jälgida."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Ühenda"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ära ühenda"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"WiFi lülitub sisse automaatselt"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kui olete kvaliteetse salvestatud võrgu läheduses"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ära lülita tagasi sisse"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"WiFi lülitati automaatselt sisse"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Teie lähedal on salvestatud võrk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Ei saanud WiFi-ga ühendust"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" on halb Interneti-ühendus."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Kas lubada ühendus?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Rakendus %1$s soovib luua ühenduse WiFi-võrguga %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Rakendus"</string> - <string name="accept" msgid="5931271886782610829">"Nõustu"</string> - <string name="decline" msgid="6874256900873707640">"Keeldu"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Kutse on saadetud"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Kutse ühendamiseks"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Saatja:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Saaja:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Sisestage nõutav PIN-kood:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-kood:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tahvelarvuti ühendus WiFi-ga katkestatakse ajutiselt, kui see on ühendatud seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ühendamisel katkestatakse ajutiselt Android TV seadme ühendus WiFi-võrguga."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefoni ühendus WiFi-ga katkestatakse ajutiselt, kui see on ühendatud seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Võrguga <xliff:g id="SSID">%1$s</xliff:g> ei õnnestu ühendada"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Puudutage privaatsusseadete muutmiseks ja uuesti proovimiseks"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Kas muuta privaatsusseadet?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Ühendamiseks peab <xliff:g id="SSID">%1$s</xliff:g> kasutama teie seadme MAC-aadressi, mis on teie kordumatu ID. Praegu kasutab teie privaatsusseade selle võrgu puhul juhuslikku ID-d. \n\nSee muudatus võib võimaldada läheduses asuvatel seadmetel jälgida teie seadme asukohta."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Muuda seadet"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Seadet värskendati. Proovige uuesti ühendada."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Privaatsusseadet ei saa muuta"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Võrku ei leitud"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentimise viga 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentimise viga 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentimise viga 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentimise viga 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentimise viga 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentimise viga 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentimise viga 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Kuumkoht lülitati välja"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Ükski seade pole ühendatud. Puudutage muutmiseks."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"WiFi-ühendus on katkestatud"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Võrguga <xliff:g id="SSID">%1$s</xliff:g> ühendamiseks sisestage operaatori <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM-kaart"</string> -</resources> diff --git a/service/res/values-eu/strings.xml b/service/res/values-eu/strings.xml deleted file mode 100644 index ccb1d3328..000000000 --- a/service/res/values-eu/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistemaren wifi-baliabideak"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Konektatu wifi-sare irekira"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi sarera konektatzen"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wifi-sare irekira konektatuta"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Ezin izan da konektatu wifi-sare irekira"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Sakatu hau sare guztiak ikusteko"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Konektatu"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Sare guztiak"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Sarearen egoera"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Sarearen alertak"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Sare bat erabilgarri dago"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Iradokitako wifi-sareak baimendu nahi dituzu?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> aplikazioak sare batzuk iradoki ditu. Baliteke gailua automatikoki konektatzea."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Baimendu"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ez, eskerrik asko"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> operadorearen wifi-sarera konektatu nahi duzu?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Sare hauek SIM ID bat jasotzen dute, gailuaren kokapenaren jarraipena egin ahal izateko"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Konektatu"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ez konektatu"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Konexioa berretsi nahi duzu?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Konektatzen bazara, baliteke <xliff:g id="CARRIERNAME">%s</xliff:g> operadorearen wifi-sareek zure SIM txartelarekin lotutako ID esklusiboa atzitzea edo partekatzea. Horrela, baliteke zure gailuaren kokapenaren jarraipena egiteko aukera izatea."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Konektatu"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ez konektatu"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi konexioa automatikoki aktibatuko da"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Gordeta daukazun kalitate handiko sare batetik gertu zaudenean"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ez aktibatu berriro"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Automatikoki aktibatu da Wi‑Fi konexioa"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Gordetako sare honetatik gertu zaude: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Ezin izan da wifi-sarera konektatu"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" SSIDak Interneteko konexio txarra du."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Konektatzeko baimena eman nahi diozu?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s aplikazioak %2$s wifi-sarera konektatu nahi du"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikazio bat"</string> - <string name="accept" msgid="5931271886782610829">"Onartu"</string> - <string name="decline" msgid="6874256900873707640">"Baztertu"</string> - <string name="ok" msgid="4215387532539340948">"Ados"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Gonbidapena bidali da"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Konektatzeko gonbidapena"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Igorlea:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Hartzaileak:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Idatzi beharrezko PINa:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PINa:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tableta wifi-saretik deskonektatuko da <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailura konektatuta dagoen bitartean"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV gailua wifi-saretik deskonektatuko da aldi batez <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailura konektatuta dagoen bitartean"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefonoa wifi-saretik deskonektatuko da <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailura konektatuta dagoen bitartean"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Ados"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Ezin da konektatu <xliff:g id="SSID">%1$s</xliff:g> sarera"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Sakatu hau pribatutasun-ezarpenak aldatzeko, eta saiatu berriro"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Pribatutasun-ezarpena aldatu nahi duzu?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Konektatzeko, <xliff:g id="SSID">%1$s</xliff:g> sareak gailuaren MAC helbidea (identifikatzaile esklusiboa) behar du. Sarearen uneko pribatutasun-ezarpenen arabera, ausazko identifikatzaile bat erabiltzen da. \n\nAldaketa honekin, baliteke inguruko gailuek zure gailuaren kokapenaren jarraipena egin ahal izatea."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Aldatu ezarpena"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Eguneratu da ezarpena. Saiatu berriro konektatzen."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Ezin da aldatu pribatutasun-ezarpena"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Ez da aurkitu sarea"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP metodoaren autentifikazio-errorea 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP metodoaren autentifikazio-errorea 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP metodoaren autentifikazio-errorea 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP metodoaren autentifikazio-errorea 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP metodoaren autentifikazio-errorea 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP metodoaren autentifikazio-errorea 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP metodoaren autentifikazio-errorea 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Wifi-gunea desaktibatu egin da"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Ez dago gailurik konektatuta. Sakatu aldatzeko."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Deskonektatu egin da wifia"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> sarera konektatzeko, sartu <xliff:g id="CARRIER_NAME">%2$s</xliff:g> operadorearen SIM txartel bat"</string> -</resources> diff --git a/service/res/values-fa/strings.xml b/service/res/values-fa/strings.xml deleted file mode 100644 index 739b5c4ff..000000000 --- a/service/res/values-fa/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"منابع Wi-Fi سیستم"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"اتصال به شبکه Wi‑Fi باز"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"درحال اتصال به شبکه Wi‑Fi..."</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"به شبکه Wi‑Fi متصل شد"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"به شبکه Wi-Fi متصل نشد"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"برای دیدن همه شبکهها ضربه بزنید"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"اتصال"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"همه شبکهها"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"وضعیت شبکه"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"هشدارهای شبکه"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"شبکه دردسترس است"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"شبکههای Wi‑Fi پیشنهادی مجاز شود؟"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"شبکههای پیشنهادی <xliff:g id="NAME">%s</xliff:g>. ممکن است دستگاه بهطور خودکار متصل شود."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"مجاز"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"نه متشکرم"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"به Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> متصل میشوید؟"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"این شبکهها شناسه سیمکارتی دریافت میکنند که میتوان از آن برای ردیابی مکان دستگاه استفاده کرد"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"اتصال"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"متصل نشود"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"اتصال را تأیید میکنید؟"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"اگر متصل شوید، شبکههای Wi‑Fi <xliff:g id="CARRIERNAME">%s</xliff:g> میتوانند به شناسه یکتای مربوط به سیمکارتتان دسترسی پیدا کنند و از آن بهصورت مشترک استفاده کنند. این کار ممکن است ردیابی مکان دستگاه را مجاز کند."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"اتصال"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"متصل نشود"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi بهطور خودکار روشن خواهد شد"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"وقتی نزدیک شبکه ذخیرهشده با کیفیت بالا هستید"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"دوباره روشن نشود"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi بهصورت خودکار روشن شد"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"نزدیک شبکه ذخیرهشدهای هستید: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"اتصال به Wi-Fi ممکن نیست"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" اتصال اینترنتی ضعیفی دارد."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"اتصال مجاز است؟"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"برنامه %1$s میخواهد به شبکه Wifi %2$s وصل شود"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"برنامه"</string> - <string name="accept" msgid="5931271886782610829">"پذیرفتن"</string> - <string name="decline" msgid="6874256900873707640">"نپذیرفتن"</string> - <string name="ok" msgid="4215387532539340948">"تأیید"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"دعوتنامه ارسال شد"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"دعوتنامه برای اتصال"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"از:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"به:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"پین لازم را تایپ کنید:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"پین:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"در حین اتصال به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ارتباط این رایانه لوحی با Wi-Fi موقتاً قطع خواهد شد."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"وقتی دستگاه Android TV به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> متصل است، اتصال آن به Wi-Fi موقتاً قطع میشود"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"این گوشی بهطور موقت از Wi-Fi قطع خواهد شد، در حالی که به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> وصل است"</string> - <string name="dlg_ok" msgid="3250085870426030310">"تأیید"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"اتصال به <xliff:g id="SSID">%1$s</xliff:g> امکانپذیر نیست"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"برای تغییر تنظیم حریمخصوصی ضربه بزنید و دوباره امتحان کنید"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"تنظیم حریمخصوصی تغییر کند؟"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"برای اتصال، <xliff:g id="SSID">%1$s</xliff:g> باید از نشانی MAC دستگاهتان که شناسهای منحصربهفرد است استفاده کند. درحالحاضر، تنظیم حریمخصوصی شما برای این شبکه از شناسه تصادفی استفاده میکند. \n\nاین تغییر ممکن است به دستگاههای اطراف امکان دهد مکان دستگاهتان را ردیابی کنند."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"تغییر تنظیم"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"تنظیم بهروزرسانی شد. دوباره متصل شوید."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"تنظیم حریمخصوصی تغییر نکرد"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"شبکهای پیدا نشد"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۰ اصالتسنجی EAP"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۱ اصالتسنجی EAP"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۲ اصالتسنجی EAP"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۳ اصالتسنجی EAP"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۴ اصالتسنجی EAP"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۵ اصالتسنجی EAP"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۶ اصالتسنجی EAP"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"نقطه اتصال خاموش شد"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"هیچ دستگاهی متصل نیست. برای اصلاح ضربه بزنید."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi قطع شد."</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"برای متصل شدن به <xliff:g id="SSID">%1$s</xliff:g>، یک سیمکارت <xliff:g id="CARRIER_NAME">%2$s</xliff:g> در دستگاه قرار دهید"</string> -</resources> diff --git a/service/res/values-fi/strings.xml b/service/res/values-fi/strings.xml deleted file mode 100644 index 8efc7df40..000000000 --- a/service/res/values-fi/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Järjestelmän Wi-Fi-resurssit"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Yhdistä avoimeen Wi‑Fi-verkkoon"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Yhdistetään Wi-Fi-verkkoon"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Yhdistetty Wi-Fi-verkkoon"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi-verkkoon yhdistäminen epäonnistui"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Napauta, niin näet kaikki verkot."</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Yhdistä"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Kaikki verkot"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Verkon tila"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Verkkoilmoitukset"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Verkko käytettävissä"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Sallitaanko ehdotetut Wi-Fi-verkot?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ehdotti verkkoja. Laite voi muodostaa yhteyden automaattisesti."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Salli"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ei kiitos"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Yhdistetäänkö Wi-Fi-verkkoon (<xliff:g id="CARRIERNAME">%s</xliff:g>)?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Nämä verkot saavat SIM-tunnuksen, jolla voidaan seurata laitteen sijaintia."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Yhdistä"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Älä yhdistä"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vahvistetaanko yhteys?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Jos muodostat yhteyden, Wi-Fi-verkot (<xliff:g id="CARRIERNAME">%s</xliff:g>) voivat nähdä tai jakaa yksilöllisen tunnuksen, joka liittyy SIM-korttiisi. Tämän kautta laitteesi sijaintia voidaan seurata."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Yhdistä"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Älä yhdistä"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi käynnistyy automaattisesti"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kun olet lähellä laadukasta tallennettua verkkoa"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Älä käynnistä uudelleen"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi otettiin käyttöön automaattisesti"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Olet lähellä tallennettua verkkoa: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi-yhteyden muodostaminen epäonnistui"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" : huono internetyhteys."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Sallitaanko yhteys?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Sovellus %1$s yrittää yhdistää Wi-Fi-verkkoon %2$s."</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Sovellus"</string> - <string name="accept" msgid="5931271886782610829">"Hyväksy"</string> - <string name="decline" msgid="6874256900873707640">"Hylkää"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Kutsu lähetetty."</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Yhdistämiskutsu"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Lähde:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kohde:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Kirjoita pyydetty PIN-koodi:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-koodi:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet-laitteen yhteys Wi-Fi-verkkoon katkaistaan väliaikaisesti tabletin ollessa yhdistettynä laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV ‑laitteen Wi-Fi-yhteys katkeaa tilapäisesti, kun siihen on yhdistetty <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Puhelimen yhteys Wi-Fi-verkkoon katkaistaan väliaikaisesti puhelimen ollessa yhdistettynä laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Verkkoon <xliff:g id="SSID">%1$s</xliff:g> ei saada yhteyttä"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Napauta muuttaaksesi yksityisyysasetusta ja yritä uudelleen"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Muutetaanko yksityisyysasetus?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Yhteyden muodostaminen edellyttää, että <xliff:g id="SSID">%1$s</xliff:g> voi käyttää MAC-osoitetta eli yksilöllistä tunnistetta. Tällä hetkellä verkon yksityisyysasetuksesi käyttää satunnaistettua tunnistetta. \n\nTämä muutos voi sallia lähellä olevien laitteiden seurata laitteesi sijaintia."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Muuta asetusta"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Asetus päivitetty. Yritä muodostaa yhteys uudelleen."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Yksityisyysasetusta ei voi muuttaa"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Verkkoa ei löydy"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-todennusvirhe 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-todennusvirhe 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-todennusvirhe 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-todennusvirhe 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-todennusvirhe 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-todennusvirhe 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-todennusvirhe 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot pois päältä"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Ei liitettyjä laitteita. Muokkaa napauttamalla."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Ei Wi-Fi-yhteyttä"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Aseta SIM-kortti (<xliff:g id="CARRIER_NAME">%2$s</xliff:g>), jotta <xliff:g id="SSID">%1$s</xliff:g> voidaan yhdistää"</string> -</resources> diff --git a/service/res/values-fr-rCA/strings.xml b/service/res/values-fr-rCA/strings.xml deleted file mode 100644 index 938c2d5ca..000000000 --- a/service/res/values-fr-rCA/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Ressources Wi-Fi du système"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Connectez-vous pour ouvrir un réseau Wi-Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Connexion au réseau Wi-Fi en cours…"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Connecté au réseau Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Impossible de se connecter au réseau Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Touchez pour afficher tous les réseaux"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Connexion"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Tous les réseaux"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"État du réseau"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertes réseau"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Réseau accessible"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Autoriser les suggestions de réseaux Wi‑Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Réseaux suggérés par <xliff:g id="NAME">%s</xliff:g>. L\'appareil peut s\'y connecter automatiquement."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Autoriser"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Non merci"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connexion au Wi-Fi de <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ces réseaux reçoivent un identifiant SIM qui peut être utilisé pour faire le suivi de la position de l\'appareil"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connecter"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne pas se connecter"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmer la connexion?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si vous vous connectez, les réseaux Wi-Fi de <xliff:g id="CARRIERNAME">%s</xliff:g> pourront accéder à un identifiant unique associé à votre module SIM ou partager cet identifiant. Cela pourrait permettre à d\'autres appareils de faire le suivi de la position de votre appareil."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Se connecter"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ne pas se connecter"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Le Wi-Fi s\'activera automatiquement"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Lorsque vous êtes près d\'un réseau enregistré de haute qualité"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ne pas réactiver"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi-Fi activé automatiquement"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Vous êtes à proximité d\'un réseau enregistré : <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Impossible de se connecter au Wi-Fi."</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" dispose d\'une connexion Internet faible."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Autoriser la connexion?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"L\'application %1$s souhaite se connecter au réseau Wi-Fi %2$s."</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Une application"</string> - <string name="accept" msgid="5931271886782610829">"Accepter"</string> - <string name="decline" msgid="6874256900873707640">"Refuser"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitation envoyée"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitation à se connecter"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De :"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"À :"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Saisissez le NIP requis :"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"NIP :"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"La tablette sera déconnectée du réseau Wi-Fi tant qu\'elle sera connectée à l\'appareil \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Votre appareil Android TV se déconnectera temporairement du Wi-Fi lors de sa connexion à l\'appareil <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Le téléphone sera déconnecté du réseau Wi-Fi tant qu\'il sera connecté à l\'appareil <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Impossible de se connecter à <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Touchez pour modifier les paramètres de confidentialité et réessayer"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Modifier le paramètre de confidentialité?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Pour autoriser la connexion, le réseau <xliff:g id="SSID">%1$s</xliff:g> a besoin d\'utiliser l\'adresse MAC de votre appareil, un identifiant unique. En ce moment, votre paramètre de confidentialité pour ce réseau utilise un identifiant aléatoire. \n\nIl se peut que ce changement permette à des appareils à proximité de suivre la position de votre appareil."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Modifier le paramètre"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Paramètre mis à jour. Réessayez de vous connecter."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Impossible de modifier les paramètres de confidentialité"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Réseau introuvable"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Point d\'accès sans fil désactivé"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Aucun appareil n\'est connecté. Touchez pour effectuer une modification."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi déconnecté"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Pour vous connecter à <xliff:g id="SSID">%1$s</xliff:g>, insérez une carte SIM de <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-fr/strings.xml b/service/res/values-fr/strings.xml deleted file mode 100644 index 6949a3327..000000000 --- a/service/res/values-fr/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Ressources Wi-Fi du système"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Connexion à un réseau Wi-Fi ouvert"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Connexion au réseau Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Connecté au réseau Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Impossible de se connecter au réseau Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Appuyer pour afficher tous les réseaux"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Se connecter"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Tous les réseaux"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"État du réseau"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertes réseau"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Réseau disponible"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Autoriser les suggestions de réseaux Wi‑Fi ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Réseaux suggérés par <xliff:g id="NAME">%s</xliff:g>. L\'appareil pourra se connecter automatiquement."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Autoriser"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Non, merci"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Se connecter au Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ces réseaux reçoivent un ID de SIM qui peut être utilisé pour suivre la position de l\'appareil"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Se connecter"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne pas connecter"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmer la connexion ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si vous établissez la connexion, les réseaux Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> peuvent accéder à un identifiant unique associé à votre carte SIM ou le partager. Suite à cette connexion, la position de votre appareil peut également d\'être suivie."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Connecter"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ne pas connecter"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Le Wi-Fi sera activé automatiquement"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Lorsque vous êtes à proximité d\'un réseau enregistré de haute qualité"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ne pas réactiver"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi-Fi activé automatiquement"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Vous vous trouvez à proximité d\'un réseau enregistré : <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Impossible de se connecter au Wi-Fi."</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" dispose d\'une mauvaise connexion Internet."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Autoriser la connexion ?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"L\'application %1$s souhaite se connecter au réseau Wi-Fi %2$s."</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Une application"</string> - <string name="accept" msgid="5931271886782610829">"Accepter"</string> - <string name="decline" msgid="6874256900873707640">"Refuser"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitation envoyée"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitation à se connecter"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De :"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"À :"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Saisissez le code PIN requis :"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"Code :"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"La tablette sera déconnectée du réseau Wi-Fi tant qu\'elle sera connectée à l\'appareil \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Votre appareil Android TV se déconnectera temporairement du Wi-Fi lors de sa connexion à l\'appareil <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Le téléphone sera déconnecté du réseau Wi-Fi tant qu\'il sera connecté à l\'appareil <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Impossible de se connecter à <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Appuyez pour modifier les paramètres de confidentialité, puis réessayez"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Modifier le paramètre de confidentialité ?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Pour se connecter, <xliff:g id="SSID">%1$s</xliff:g> doit utiliser l\'adresse MAC de votre appareil, un identifiant unique. À l\'heure actuelle, votre paramètre de confidentialité pour ce réseau utilise un identifiant aléatoire. \n\nCela risque de permettre à des appareils à proximité d\'effectuer le suivi de votre position."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Modifier le paramètre"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Paramètre mis à jour. Essayez de vous reconnecter."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Impossible de modifier le paramètre de confidentialité"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Réseau introuvable"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : erreur d\'authentification EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Point d\'accès désactivé"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Aucun appareil connecté. Appuyez pour modifier."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi déconnecté"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Pour vous connecter au réseau <xliff:g id="SSID">%1$s</xliff:g>, insérez une carte SIM <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-gl/strings.xml b/service/res/values-gl/strings.xml deleted file mode 100644 index 45cb1e440..000000000 --- a/service/res/values-gl/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Recursos wifi do sistema"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Conéctate a unha rede wifi aberta"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Conectándose á rede wifi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Conectouse á rede wifi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Non se puido conectar á rede wifi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Toca para ver todas as redes"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Conectarse"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Todas as redes"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Estado da rede"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertas de rede"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"A rede está dispoñible"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Queres permitir as redes wifi suxeridas?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Redes suxeridas de <xliff:g id="NAME">%s</xliff:g>. O dispositivo pode conectarse automaticamente."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Non, grazas"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Quéreste conectar á rede wifi de <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Estas redes reciben un código SIM que se pode usar para facer un seguimento da localización do dispositivo"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Non conectar"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Queres confirmar a conexión?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Se te conectas, as redes wifi de <xliff:g id="CARRIERNAME">%s</xliff:g> poden acceder a un código exclusivo asociado coa túa SIM ou ben compartilo. Deste xeito, pódese facer un seguimento da localización do teu dispositivo."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Non conectar"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"A wifi activarase automaticamente"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Cando esteas preto dunha rede gardada de alta calidade"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Non volver activar"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Activouse a wifi automaticamente"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Estás preto dunha rede gardada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Non se puido conectar á wifi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ten unha mala conexión a Internet."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Queres permitir a conexión?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"A aplicación %1$s quere conectarse á rede wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Unha aplicación"</string> - <string name="accept" msgid="5931271886782610829">"Aceptar"</string> - <string name="decline" msgid="6874256900873707640">"Rexeitar"</string> - <string name="ok" msgid="4215387532539340948">"Aceptar"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitación enviada"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitación para conectarse"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Para:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Escribe o PIN obrigatorio:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"A tableta desconectarase temporalmente da wifi mentres está conectada a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"O dispositivo Android TV desconectarase temporalmente da wifi mentres estea conectado a: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"O teléfono desconectarase temporalmente da wifi mentres está conectado con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Aceptar"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Non se puido establecer conexión co <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Toca para cambiar a configuración de privacidade e tentalo de novo"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Queres cambiar a configuración de privacidade?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Para conectarse, <xliff:g id="SSID">%1$s</xliff:g> ten que usar o enderezo MAC do teu dispositivo, un identificador único. A configuración de privacidade desta rede usa actualmente un identificador aleatorio. \n\nCon este cambio, os dispositivos próximos poden facer un seguimento da localización do teu dispositivo."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Cambiar configuración"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Actualizouse a opción de configuración. Proba a conectarte de novo."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Non se puido cambiar a configuración de privacidade"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Non se atopou ningunha rede"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: produciuse un erro (32760) de autenticación de EAP"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: produciuse un erro (32761) de autenticación de EAP"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: produciuse un erro (32762) de autenticación de EAP"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: produciuse un erro (32763) de autenticación de EAP"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: produciuse un erro (32764) de autenticación de EAP"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: produciuse un erro (32765) de autenticación de EAP"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: produciuse un erro (32766) de autenticación de EAP"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"A zona wifi esta desactivada"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Non hai ningún dispositivo conectado. Toca para modificalo."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Desconectouse a wifi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Para conectarte a <xliff:g id="SSID">%1$s</xliff:g>, introduce unha tarxeta SIM de <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-gu/strings.xml b/service/res/values-gu/strings.xml deleted file mode 100644 index facd8427a..000000000 --- a/service/res/values-gu/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"સિસ્ટમ વાઇ-ફાઇના સાધનો"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"ખુલ્લા વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરો"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"કનેક્ટ કરી રહ્યાં છીએ તે વાઇ-ફાઇ નેટવર્ક"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કર્યુ"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરી શકાયું નથી"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"બધા નેટવર્ક જોવા ટૅપ કરો"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"કનેક્ટ કરો"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"બધા નેટવર્કો"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"નેટવર્ક સ્થિતિ"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"નેટવર્ક ચેતવણીઓ"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"નેટવર્ક ઉપલબ્ધ છે"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"સૂચવેલા વાઇ-ફાઇ નેટવર્કને મંજૂરી આપીએ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> સૂચવેલા નેટવર્ક. ડિવાઇસ ઑટોમૅટિક રીતે કનેક્ટ થાય તેમ બની શકે છે."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"મંજૂરી આપો"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ના, આભાર"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> વાઇ-ફાઇ સાથે કનેક્ટ કરીએ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"આ બધા નેટવર્કને સિમ ID મળે છે કે જેનો ઉપયોગ ડિવાઇસના સ્થાનને ટ્રૅક કરવા માટે થઈ શકે છે"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"કનેક્ટ કરો"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"કનેક્ટ કરશો નહીં"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"કનેક્શનને કન્ફર્મ કરીએ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"જો તમે કનેક્ટ કરો છો, તો <xliff:g id="CARRIERNAME">%s</xliff:g> વાઇ-ફાઇ નેટવર્ક, તમારા SIM સાથે સંકળાયેલા અજોડ IDને ઍક્સેસ અથવા શેર કરી શકે છે. આમ કરવાથી તમારા ડિવાઇસનું સ્થાન ટ્રૅક કરવાની મંજૂરી આપવામાં આવી શકે છે."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"કનેક્ટ કરો"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"કનેક્ટ કરશો નહીં"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"વાઇ-ફાઇ ઑટોમૅટિક રીતે ચાલુ થઈ જશે"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"જ્યારે તમે એક ઉચ્ચ ક્વૉલિટીવાળા સાચવેલ નેટવર્કની નજીક હોવ"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"પાછું ચાલુ કરશો નહીં"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"વાઇ-ફાઇ ઑટોમૅટિક રીતે ચાલુ થયું"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"તમે એક સાચવેલ નેટવર્કની નજીકમાં છો: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"વાઇ-ફાઇ સાથે કનેક્ટ કરી શકાયું નથી"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" આમનું ઇન્ટરનેટ કનેક્શન નબળું છે."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"કનેક્શનની મંજૂરી આપીએ?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s ઍપ્લિકેશન Wifi નેટવર્ક %2$s થી કનેક્ટ થવા માગે છે"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ઍપ્લિકેશન"</string> - <string name="accept" msgid="5931271886782610829">"સ્વીકારો"</string> - <string name="decline" msgid="6874256900873707640">"નકારો"</string> - <string name="ok" msgid="4215387532539340948">"ઓકે"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"આમંત્રણ મોકલ્યું"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"કનેક્ટ થવા માટે આમંત્રણ"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"મોકલનાર:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"પ્રતિ:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"આવશ્યક પિન લખો:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"પિન:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ટેબ્લેટ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> થી કનેક્ટ હોય તે વખતે વાઇ-ફાઇ થી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"તમારું Android TV ડિવાઇસ, <xliff:g id="DEVICE_NAME">%1$s</xliff:g>થી કનેક્ટ હોય તે વખતે વાઇ-ફાઇથી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ફોન <xliff:g id="DEVICE_NAME">%1$s</xliff:g> થી કનેક્ટ હોય તે વખતે વાઇ-ફાઇ થી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ઓકે"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> સાથે કનેક્ટ કરી શકાતું નથી"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"પ્રાઇવસી સેટિંગ બદલવા અને ફરી પ્રયાસ કરવા ટૅપ કરો"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"પ્રાઇવસી સેટિંગ બદલીએ?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"કનેક્ટ કરવા માટે, <xliff:g id="SSID">%1$s</xliff:g>ને વિશિષ્ટ ઓળખકર્તા એવા તમારા ડિવાઇસના MAC ઍડ્રેસનો ઉપયોગ કરવો જરૂરી છે. હાલમાં, આ નેટવર્ક માટે તમારું પ્રાઇવસી સેટિંગ રેન્ડમ કરેલા ઓળખકર્તાનો ઉપયોગ કરે છે. \n\nઆ ફેરફારથી, તમારા ડિવાઇસનું સ્થાન ટ્રૅક કરવાની મંજૂરી નજીકના કોઈ ડિવાઇસ દ્વારા મેળવવામાં આવી શકે છે."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"સેટિંગ બદલો"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"સેટિંગ અપડેટ કર્યું. ફરીથી કનેક્ટ કરવાનો પ્રયાસ કરો."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"પ્રાઇવસી સેટિંગ બદલી શકાતું નથી"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"નેટવર્ક મળ્યું નથી"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP પ્રમાણીકરણમાં ભૂલ 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP પ્રમાણીકરણમાં ભૂલ 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP પ્રમાણીકરણમાં ભૂલ 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP પ્રમાણીકરણમાં ભૂલ 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP પ્રમાણીકરણમાં ભૂલ 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP પ્રમાણીકરણમાં ભૂલ 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP પ્રમાણીકરણમાં ભૂલ 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"હૉટસ્પૉટ બંધ કર્યું"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"કોઈ ડિવાઇસ કનેક્ટ કરેલું નથી. ફેરફાર કરવા માટે ટૅપ કરો."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"વાઇ-ફાઇ ડિસ્કનેક્ટ થયું"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> સાથે કનેક્ટ કરવા માટે, <xliff:g id="CARRIER_NAME">%2$s</xliff:g>નું સિમ કાર્ડ દાખલ કરો"</string> -</resources> diff --git a/service/res/values-hi/strings.xml b/service/res/values-hi/strings.xml deleted file mode 100644 index dabcd3e1c..000000000 --- a/service/res/values-hi/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"सिस्टम के वाई-फ़ाई के संसाधन"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"खुले वाई-फ़ाई नेटवर्क से कनेक्ट करें"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"वाई-फ़ाई नेटवर्क से जोड़ा जा रहा है"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"वाई-फ़ाई नेटवर्क से कनेक्ट हो गया है"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"वाई-फ़ाई नेटवर्क से कनेक्ट नहीं हो सका"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"सभी नेटवर्क देखने के लिए यहां पर टैप करें"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"कनेक्ट करें"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"सभी नेटवर्क"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"नेटवर्क की स्थिति"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"नेटवर्क संबंधी सूचनाएं"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"नेटवर्क उपलब्ध है"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"सुझाए गए वाई-फ़ाई नेटवर्क को अनुमति देना चाहते हैं?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> के सुझाए गए नेटवर्क. डिवाइस अपने आप कनेक्ट हो सकता है."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"अनुमति दें"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"रहने दें"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> वाई-फ़ाई से कनेक्ट करना चाहते हैं?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"इन नेटवर्क को एक सिम आईडी दिया जाता है जिसका इस्तेमाल डिवाइस की जगह की जानकारी का पता लगाने के लिए किया जा सकता है"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"कनेक्ट करें"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"कनेक्ट न करें"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"कनेक्शन की पुष्टि करना चाहते हैं?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"अगर आप कनेक्ट करते हैं, तो <xliff:g id="CARRIERNAME">%s</xliff:g> वाई-फ़ाई नेटवर्क आपकी सिम से जुड़े हुए विशेष आईडी को ऐक्सेस या शेयर कर सकता है. इससे आपके डिवाइस की जगह की जानकारी का पता लगा सकते हैं."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"कनेक्ट करें"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"कनेक्ट न करें"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"वाई-फ़ाई अपने आप चालू हो जाएगा"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"जब आप किसी अच्छी क्वालिटी वाले सेव किए गए नेटवर्क के पास हों"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"वापस चालू न करें"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"वाई-फ़ाई अपने आप चालू हो गया है"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"आप एक सेव किए गए नेटवर्क के पास हैं: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"वाई-फ़ाई से कनेक्ट नहीं हो सका"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" के पास एक कमज़ोर इंटरनेट कनेक्शन है."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"कनेक्शन की अनुमति दें?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s ऐप्लिकेशन %2$s वाई-फ़ाई नेटवर्क से कनेक्ट करना चाहता है"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ऐप्लिकेशन"</string> - <string name="accept" msgid="5931271886782610829">"स्वीकार करें"</string> - <string name="decline" msgid="6874256900873707640">"अस्वीकार करें"</string> - <string name="ok" msgid="4215387532539340948">"ठीक है"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"आमंत्रण भेजा गया"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"कनेक्ट करने का आमंत्रण"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"प्रेषक:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"प्रति:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"आवश्यक पिन लिखें:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"पिन:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहने पर टैबलेट वाई-फ़ाई से अस्थायी रूप से डिसकनेक्ट हो जाएगा"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>से कनेक्ट रहने के दौरान आपका Android TV डिवाइस, Wi-Fi से अस्थायी रूप से डिसकनेक्ट हो जाएगा."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"फ़ोन <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहते समय वाई-फ़ाई से अस्थायी रूप से डिसकनेक्ट हो जाएगा"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ठीक है"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> से कनेक्ट नहीं किया जा सकता"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"निजता सेटिंग बदलने के लिए टैप करें और फिर से कोशिश करें"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"निजता सेटिंग बदलना चाहते हैं?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"कनेक्ट करने के लिए, <xliff:g id="SSID">%1$s</xliff:g> को आपके डिवाइस के एमएसी (मैक) पते का इस्तेमाल करने की ज़रूरत पड़ेगी. यह एक खास पहचानकर्ता होता है. फ़िलहाल, इस नेटवर्क के लिए आपकी निजता सेटिंग, किसी भी क्रम में लगाए गए पहचानकर्ता का इस्तेमाल करती है. \n\nइस बदलाव से, आपके डिवाइस की जगह की जानकारी को आस-पास के डिवाइस ट्रैक कर सकते हैं."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"सेटिंग बदलें"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"सेटिंग अपडेट की गई. फिर से कनेक्ट करने की कोशिश करें."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"निजता सेटिंग नहीं बदली जा सकती"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"नेटवर्क नहीं मिला"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP authentication error 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"हॉटस्पॉट बंद किया गया"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"कोई भी डिवाइस जुड़ा नहीं है. बदलाव करने के लिए टैप करें."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"वाई-फ़ाई डिसकनेक्ट हो गया"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> से कनेक्ट करने के लिए, <xliff:g id="CARRIER_NAME">%2$s</xliff:g> का सिम डालें"</string> -</resources> diff --git a/service/res/values-hr/strings.xml b/service/res/values-hr/strings.xml deleted file mode 100644 index 1c5fa897a..000000000 --- a/service/res/values-hr/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Wi-Fi resursi sustava"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Povezivanje s otvorenom Wi‑Fi mrežom"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Povezivanje s Wi-Fi mrežom"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Povezano s Wi-Fi mrežom"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Nije uspjelo povezivanje s Wi-Fi mrežom"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Dodirnite za prikaz svih mreža"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Poveži"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Sve mreže"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Mrežni status"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Mrežna upozorenja"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Mreža je dostupna"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Želite li dopustiti predložene Wi‑Fi mreže?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mreže koje predlaže aplikacija <xliff:g id="NAME">%s</xliff:g>. Uređaji se mogu povezati automatski."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Dopusti"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, hvala"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Želite li se povezati s Wi-Fijem mobilnog operatera <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ove mreže primaju ID SIM-a koji se može upotrijebiti za praćenje lokacije uređaja"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Poveži"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nemoj povezati"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Želite li potvrditi povezivanje?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ako se povežete, Wifi mreže operatera <xliff:g id="CARRIERNAME">%s</xliff:g> mogu pristupiti jedinstvenom ID-ju povezanom s vašim SIM-om ili ga podijeliti. To može omogućiti praćenje lokacije vašeg uređaja."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Poveži"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Nemoj povezati"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi će se uključiti automatski"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kada ste u blizini spremljene mreže visoke kvalitete"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Više ne uključuj"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi je uključen automatski"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Nalazite se u blizini spremljene mreže: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Ne može se spojiti na Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ima lošu internetsku vezu."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Dopustiti povezivanje?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikacija %1$s traži povezivanje s Wi-Fi mrežom %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikacija"</string> - <string name="accept" msgid="5931271886782610829">"Prihvaćam"</string> - <string name="decline" msgid="6874256900873707640">"Odbaci"</string> - <string name="ok" msgid="4215387532539340948">"U redu"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Pozivnica je poslana"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Pozivnica za povezivanje"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Šalje:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Prima:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Upišite potreban PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet će se privremeno isključiti s Wi-Fija dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV uređaj privremeno će prekinuti vezu s Wi-Fijem dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon će se privremeno isključiti s Wi-Fija dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"U redu"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Povezivanje s mrežom <xliff:g id="SSID">%1$s</xliff:g> nije uspjelo"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Dodirnite da biste promijenili postavke privatnosti i pokušajte ponovo"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Želite li promijeniti postavku privatnosti?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Da biste se povezali, <xliff:g id="SSID">%1$s</xliff:g> treba upotrijebiti MAC adresu, jedinstveni identifikator vašeg uređaja. Vaša postavka privatnosti za tu mrežu trenutačno upotrebljava nasumični identifikator. \n\nTo može omogućiti uređajima u blizini da prate lokaciju vašeg uređaja."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Promijenite postavku"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Postavka je ažurirana. Pokušajte se ponovo povezati."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Promjena postavke privatnosti nije uspjela"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Mreža nije pronađena"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP pogreška autentifikacije 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP pogreška autentifikacije 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP pogreška autentifikacije 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP pogreška autentifikacije 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP pogreška autentifikacije 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP pogreška autentifikacije 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP pogreška autentifikacije 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Žarišna točka je isključena"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nije povezan nijedan uređaj. Dodirnite za prilagodbu."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi je isključen"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Da biste se povezali s mrežom <xliff:g id="SSID">%1$s</xliff:g> umetnite SIM mobilnog operatera <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-hu/strings.xml b/service/res/values-hu/strings.xml deleted file mode 100644 index a8e562be4..000000000 --- a/service/res/values-hu/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"A rendszer Wi-Fi-erőforrásai"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Nyílt Wi-Fi-hálózathoz kapcsolódhat"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Csatlakozás Wi-Fi hálózathoz…"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Sikeres kapcsolódás a Wi-Fi-hálózathoz"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Nem sikerült kapcsolódni a Wi‑Fi-hálózathoz"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Koppintással megjelenítheti az összes hálózatot"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Kapcsolódás"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Összes hálózat"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Hálózati állapot"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Hálózati értesítések"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Van elérhető hálózat"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Engedélyezi a javasolt Wi-Fi-hálózatokat?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"A(z) <xliff:g id="NAME">%s</xliff:g> hálózatokat javasolt. Az eszköz automatikusan csatlakozhat hozzájuk."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Engedélyezés"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nem, köszönöm"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Csatlakozni szeretne a(z) <xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi-hálózathoz?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ezek a hálózatok SIM-azonosítót kapnak, amely felhasználható az eszköz helyadatainak követésére"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Csatlakozás"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne csatlakozzon"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Biztosan csatlakozik?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ha csatlakozik, a(z) <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi-hálózatai hozzáférhetnek a SIM-hez társított egyedi azonosítóhoz, amelyet meg is oszthatnak. Ez lehetővé teheti eszköze helyadatainak követését."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Csatlakozás"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ne csatlakozzon"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"A Wi-Fi automatikusan bekapcsol"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Amikor jó minőségű mentett hálózat közelében tartózkodik"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ne kapcsolódjon vissza"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi automatikusan bekapcsolva"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Ön a következő mentett hálózat közelében tartózkodik: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nem sikerült csatlakozni a Wi-Fi hálózathoz"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" rossz internetkapcsolattal rendelkezik."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Engedélyezi a csatlakozást?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"A(z) %1$s alkalmazás szeretne csatlakozni a következő Wi-Fi hálózathoz: %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Egy alkalmazás"</string> - <string name="accept" msgid="5931271886782610829">"Elfogadás"</string> - <string name="decline" msgid="6874256900873707640">"Elutasítás"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Meghívó elküldve"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Meghívó csatlakozásra"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Feladó:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Címzett:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Adja meg a szükséges PIN kódot:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-kód:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"A táblagép ideiglenesen lecsatlakozik a Wi-Fi hálózatról, míg a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközhöz csatlakozik"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Az Android TV eszköz ideiglenesen bontja a Wi-Fi-kapcsolatot arra az időre, amíg a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközhöz csatlakozik"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"A telefon ideiglenesen kilép a Wi-Fi hálózatról, míg a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközhöz csatlakozik."</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Nem lehet csatlakozni a következőhöz: <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Koppintson az adatvédelmi beállítások módosításához, majd próbálja újra"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Módosítja az adatvédelmi beállítást?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"A kapcsolódáshoz a(z) <xliff:g id="SSID">%1$s</xliff:g> számára szükséges az eszköz egyedi azonosítójaként szolgáló MAC-cím használata. Jelenleg az adatvédelmi beállításnak megfelelően a rendszer ehhez a hálózathoz véletlenszerű azonosítót használ. \n\nEz a módosítás lehetővé teheti, hogy más közeli eszközök megfigyelhessék az Ön eszközének helyzetét."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Beállítás módosítása"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Beállítás frissítve. Próbáljon ismét csatlakozni."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nem lehet módosítani az adatvédelmi beállítást"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"A hálózat nem található"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP hitelesítési hiba 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP hitelesítési hiba 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP hitelesítési hiba 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP hitelesítési hiba 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP hitelesítési hiba 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP hitelesítési hiba 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP hitelesítési hiba 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot kikapcsolva"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nincsenek csatlakoztatott eszközök. Koppintson a módosításhoz."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Nincs Wi-Fi-kapcsolat"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"A(z) <xliff:g id="SSID">%1$s</xliff:g> csatlakoztatásához helyezzen be <xliff:g id="CARRIER_NAME">%2$s</xliff:g> szolgáltatóhoz tartozó SIM-kártyát"</string> -</resources> diff --git a/service/res/values-hy/strings.xml b/service/res/values-hy/strings.xml deleted file mode 100644 index 3e60ba0c7..000000000 --- a/service/res/values-hy/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Համակարգի Wi-Fi ռեսուրսներ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Միացեք բաց Wi‑Fi ցանցին"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Միացում Wi‑Fi ցանցին"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Միացել է Wi‑Fi ցանցին"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Չհաջողվեց միանալ Wi‑Fi ցանցին"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Հպեք՝ բոլոր ցանցերը տեսնելու համար"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Միանալ"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Բոլոր ցանցերը"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Ցանցի կարգավիճակ"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Ցանցային զգուշացումներ"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Ցանցը հասանելի է"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Թույլատրե՞լ առաջարկվող Wi‑Fi ցանցերի օգտագործումը"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> հավելվածի առաջարկվող ցանցեր: Սարքը կարող է ավտոմատ միանալ:"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Թույլատրել"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ոչ, շնորհակալություն"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Միանա՞լ <xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi ցանցին"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Այս ցանցերը ստանում են SIM քարտի ID, որը կարող է օգտագործվել սարքի տեղադրությունը հետագծելու համար։"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Միանալ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Չմիանալ"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Հաստատե՞լ միացումը"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Միանալու դեպքում <xliff:g id="CARRIERNAME">%s</xliff:g>-ի Wi‑Fi ցանցերը կարող են ստանալ ձեր SIM քարտի հետ կապված եզակի ID-ն կամ կիսվել դրանով։ Դա հնարավորություն կտա հետագծել ձեր սարքի տեղադրությունը։"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Միանալ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Չմիանալ"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi-ն ավտոմատ կմիանա"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Լավ ազդանշանով պահված ցանցի տարածքում գտնվելիս"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Նորից չմիացնել"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi-ը միացել է ավտոմատ կերպով"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Դուք գտնվում եք պահված ցանցի մոտակայքում՝ <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Չհաջողվեց միանալ Wi-Fi-ին"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ինտերնետային կապը թույլ է:"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Թույլատրե՞լ կապը:"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s հավելվածը ցանկանում է միանալ %2$s Wifi ցանցին"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Հավելված"</string> - <string name="accept" msgid="5931271886782610829">"Ընդունել"</string> - <string name="decline" msgid="6874256900873707640">"Մերժել"</string> - <string name="ok" msgid="4215387532539340948">"Լավ"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Հրավերն ուղարկված է"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Միացման հրավեր"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Ուղարկող`"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Ում`"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Մուտքագրեք պահանջվող PIN-ը:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-ը՝"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Գրասալիկը ժամանակավորապես կանջատվի Wi-Fi-ից, քանի դեռ այն կապակցված է <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ին"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Ձեր Android TV սարքը ժամանակավորապես կանջատվի Wi-Fi-ից, քանի դեռ այն միացված է <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ին"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Հեռախոսը ժամանակավորապես կանջատվի Wi-Fi-ից, քանի դեռ այն միացված է <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ին"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Եղավ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Չհաջողվեց միանալ <xliff:g id="SSID">%1$s</xliff:g> սարքին"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Հպեք՝ գաղտնիության կարգավորումները փոփոխելու և նորից փորձելու համար։"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Փոխե՞լ գաղտնիության կարգավորումը"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Միանալու համար <xliff:g id="SSID">%1$s</xliff:g> ցանցը պետք է օգտագործի ձեր սարքի MAC հասցեն (եզակի նույնացուցիչը)։ Ներկայումս այս ցանցի ձեր գաղտնիության կարգավորումն օգտագործում է պատահական նույնացուցիչ։ \n\nՄոտակայքում գտնվող սարքերը կկարողանան հետագծել ձեր սարքի տեղադրությունը։"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Փոխել կարգավորումը"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Կարգավորումը թարմացվեց։ Փորձեք նորից միանալ։"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Չհաջողվեց փոփոխել գաղտնիության կարգավորումները"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Ցանցը չի գտնվել"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP նույնականացման սխալ 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP նույնականացման սխալ 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP նույնականացման սխալ 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP նույնականացման սխալ 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP նույնականացման սխալ 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP նույնականացման սխալ 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP նույնականացման սխալ 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Թեժ կետն անջատված է"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Կապված սարքեր չկան։ Հպեք՝ փոփոխելու համար։"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi-ն անջատված է"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> ցանցին միանալու համար տեղադրեք <xliff:g id="CARRIER_NAME">%2$s</xliff:g> օպերատորի SIM քարտը"</string> -</resources> diff --git a/service/res/values-in/strings.xml b/service/res/values-in/strings.xml deleted file mode 100644 index 70fd8af48..000000000 --- a/service/res/values-in/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Resource Wi-Fi Sistem"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Hubungkan ke jaringan Wi-Fi terbuka"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Menghubungkan ke jaringan Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Terhubung ke jaringan Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Tidak dapat menghubungkan ke jaringan Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Ketuk untuk melihat semua jaringan"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Hubungkan"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Semua jaringan"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Status jaringan"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Notifikasi jaringan"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Jaringan tersedia"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Izinkan jaringan Wi-Fi yang disarankan?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Jaringan yang disarankan <xliff:g id="NAME">%s</xliff:g>. Perangkat dapat terhubung secara otomatis."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Izinkan"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Lain kali"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Hubungkan ke Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Jaringan ini menerima ID SIM yang dapat digunakan untuk melacak lokasi perangkat"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Hubungkan"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Jangan hubungkan"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Konfirmasi koneksi?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Jika Anda menghubungkan, jaringan Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> mungkin mengakses atau membagikan ID unik terkait dengan SIM Anda. Ini memungkinkan lokasi perangkat Anda untuk dilacak."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Ikuti"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Jangan hubungkan"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi akan aktif otomatis"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Saat berada di dekat jaringan berkualitas tinggi yang tersimpan"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Jangan aktifkan kembali"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi diaktifkan otomatis"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Anda berada di dekat jaringan yang tersimpan: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Tidak dapat tersambung ke Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" memiliki koneksi internet yang buruk."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Izinkan hubungan?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikasi %1$s ingin tersambung ke Jaringan Wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikasi"</string> - <string name="accept" msgid="5931271886782610829">"Terima"</string> - <string name="decline" msgid="6874256900873707640">"Tolak"</string> - <string name="ok" msgid="4215387532539340948">"Oke"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Undangan terkirim"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Undangan untuk terhubung"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Dari:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kepada:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Ketik PIN yang diminta:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Sambungan tablet akan diputuskan dari Wi-Fi untuk sementara saat tersambung dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Perangkat Android TV akan memutuskan hubungan sementara dari Wi-Fi saat terhubung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Ponsel akan terputus sementara dari Wi-Fi saat tersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Oke"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Tidak dapat terhubung ke <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Ketuk untuk mengubah setelan privasi dan coba lagi"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Ubah setelan privasi?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Untuk terhubung, <xliff:g id="SSID">%1$s</xliff:g> perlu menggunakan alamat MAC perangkat, yaitu ID unik. Saat ini, setelan privasi untuk jaringan ini menggunakan ID yang diacak. \n\nPerubahan ini memungkinkan lokasi perangkat dilacak oleh perangkat di sekitar."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Ganti setelan"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Setelan diperbarui. Coba hubungkan lagi."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Tidak dapat mengubah setelan privasi"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Jaringan tidak ditemukan"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Error autentikasi EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Error autentikasi EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Error autentikasi EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Error autentikasi EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Error autentikasi EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Error autentikasi EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Error autentikasi EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot dinonaktifkan"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Tidak ada perangkat yang terhubung. Ketuk untuk mengubah."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi tidak tersambung"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Untuk terhubung ke <xliff:g id="SSID">%1$s</xliff:g>, masukkan SIM <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-is/strings.xml b/service/res/values-is/strings.xml deleted file mode 100644 index c60e883b2..000000000 --- a/service/res/values-is/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Kerfistilföng fyrir Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Tengjast opnu Wi-Fi neti"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Tengist við Wi-Fi net"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Tengt við Wi‑Fi net"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Ekki hægt að tengjast Wi-Fi neti"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Ýttu til að sjá öll netkerfi"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Tengjast"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Öll netkerfi"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Staða netkerfis"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Viðvaranir netkerfis"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Net í boði"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Leyfa ráðlögð Wi‑Fi net?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> kom með tillögur að netkerfum. Tækið gæti tengst sjálfkrafa."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Leyfa"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nei, takk"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Tengjast við <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Þessi net fá SIM-auðkenni sem hægt er að nota til að rekja staðsetningu tækisins"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Tengja"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ekki tengjast"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Staðfesta tengingu?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ef þú tengist geta Wi-Fi net <xliff:g id="CARRIERNAME">%s</xliff:g> fengið aðgang að eða deilt einkvæmu auðkenni sem er tengt SIM-kortinu þínu. Með þessu er hugsanlega hægt að rekja staðsetningu tækisins þíns."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Tengjast"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ekki tengjast"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Kveikt verður sjálfkrafa á Wi‑Fi"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Þegar þú ert nálægt vistuðu hágæðaneti"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ekki kveikja aftur"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Sjálfkrafa kveikt á Wi-Fi"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Þú ert nálægt vistuðu neti: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Ekki var hægt að tengjast Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" er með lélegt netsamband."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Leyfa tengingu?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Forritið %1$s vill tengjast Wi-Fi netinu %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Forrit"</string> - <string name="accept" msgid="5931271886782610829">"Samþykkja"</string> - <string name="decline" msgid="6874256900873707640">"Hafna"</string> - <string name="ok" msgid="4215387532539340948">"Í lagi"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Boðið var sent"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Boð um tengingu"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Frá:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Til:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Sláðu inn PIN-númerið sem er krafist:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-númer:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Wi-Fi tengingu spjaldtölvunnar verður tímabundið slitið á meðan hún er tengd við <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV mun tímabundið aftengjast Wi-Fi á meðan það er tengt við <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Síminn mun tímabundið aftengjast Wi-Fi á meðan hann er tengdur við <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Í lagi"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Ekki hægt að tengjast <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Ýttu til að breyta persónuverndarstillingum og reyna aftur"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Viltu breyta persónuverndarstillingunni?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Til að tengjast þarf <xliff:g id="SSID">%1$s</xliff:g> að nota MAC-vistfang tækisins, sem er einkvæmt auðkenni þess. Núverandi persónuverndarstillingar þínar fyrir þetta net nota auðkenni sem valið er af handahófi. \n\nÞessi breyting getur gert nálægum tækjum kleift að rekja staðsetningu tækisins."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Breyta stillingu"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Stilling uppfærð. Reyndu aftur að tengja."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Ekki er hægt að breyta persónuverndarstillingu"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Netið fannst ekki"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-auðkenningarvilla 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-auðkenningarvilla 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-auðkenningarvilla 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-auðkenningarvilla 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-auðkenningarvilla 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-auðkenningarvilla 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-auðkenningarvilla 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Slökkt á heitum reit"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Engin tæki eru tengd. Ýttu til að breyta."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi ótengt"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Til að tengjast <xliff:g id="SSID">%1$s</xliff:g> skaltu setja inn SIM-kort frá <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-it/strings.xml b/service/res/values-it/strings.xml deleted file mode 100644 index f675f7e89..000000000 --- a/service/res/values-it/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Risorse Wi-Fi sistema"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Stabilisci la connessione per aprire la rete Wi‑Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Connessione alla rete Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Connessione alla rete Wi-Fi stabilita"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Impossibile connettersi alla rete Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tocca per vedere tutte le reti"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Connetti"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Tutte le reti"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Stato della rete"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Avvisi di rete"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Rete disponibile"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Vuoi consentire le reti Wi-Fi suggerite?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ha suggerito delle reti. Il dispositivo potrebbe collegarsi automaticamente."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Consenti"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, grazie"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vuoi connetterti alla rete Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Queste reti ricevono un ID SIM che può essere usato per monitorare la posizione del dispositivo"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connetti"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Non connettere"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confermi la connessione?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Se esegui la connessione, le reti Wi-Fi di <xliff:g id="CARRIERNAME">%s</xliff:g> potranno accedere o condividere un ID univoco associato alla tua SIM. Questa azione potrebbe consentire il monitoraggio della posizione del tuo dispositivo."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Connetti"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Non connettere"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Il Wi‑Fi verrà attivato automaticamente"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Quando ti trovi nell\'area di una rete salvata di alta qualità"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Non riattivare"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi attivato automaticamente"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Ti trovi nell\'area di copertura di una rete salvata: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Impossibile connettersi alla rete Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ha una connessione Internet debole."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Consentire la connessione?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"L\'applicazione %1$s vorrebbe connettersi alla rete Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Un\'applicazione"</string> - <string name="accept" msgid="5931271886782610829">"Accetto"</string> - <string name="decline" msgid="6874256900873707640">"Rifiuto"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invito inviato"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invito a connettersi"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Da:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"A:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Inserisci il PIN richiesto:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Il tablet verrà momentaneamente scollegato dalla rete Wi-Fi durante il collegamento a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Il dispositivo Android TV verrà scollegato temporaneamente dalla rete Wi-Fi mentre è connesso a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Il telefono verrà momentaneamente scollegato dalla rete Wi-Fi durante il collegamento a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Impossibile connettersi alla rete <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tocca per cambiare le impostazioni sulla privacy e riprova"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Vuoi cambiare l\'impostazione sulla privacy?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Per la connessione, la rete <xliff:g id="SSID">%1$s</xliff:g> deve usare l\'indirizzo MAC del dispositivo, ossia un identificatore univoco. L\'impostazione sulla privacy attuale relativa a questa rete prevede l\'uso di un identificatore casuale. \n\nQuesta modifica potrebbe consentire il monitoraggio della posizione del tuo dispositivo da parte di dispositivi nelle vicinanze."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Cambia l\'impostazione"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Impostazione aggiornata. Prova a ricollegarti."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Impossibile cambiare l\'impostazione sulla privacy"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Rete non trovata"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: errore di autenticazione EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: errore di autenticazione EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: errore di autenticazione EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: errore di autenticazione EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: errore di autenticazione EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: errore di autenticazione EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: errore di autenticazione EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot disattivato"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nessun dispositivo connesso. Tocca per modificare."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Rete Wi-Fi scollegata"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Per connetterti alla rete <xliff:g id="SSID">%1$s</xliff:g>, inserisci una SIM <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-iw/strings.xml b/service/res/values-iw/strings.xml deleted file mode 100644 index ad8fc46d9..000000000 --- a/service/res/values-iw/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"משאבי Wi-Fi של המערכת"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"התחברות לרשת Wi‑Fi פתוחה"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"התחברות לרשת Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"מחובר לרשת Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"לא ניתן היה להתחבר לרשת Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"יש להקיש כדי לראות את כל הרשתות"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"התחבר"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"כל הרשתות"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"סטטוס הרשת"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"התראות רשת"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"יש רשת זמינה"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"לאפשר הצעות לרשתות Wi-Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"הצעות לרשתות <xliff:g id="NAME">%s</xliff:g>. ייתכן שחיבור המכשיר ייעשה באופן אוטומטי."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"אישור"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"לא תודה"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"האם להתחבר ל-Wi-Fi של <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"רשתות אלה מקבלות מזהה SIM שיכול לשמש למעקב אחר מיקום של מכשיר"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"חיבור"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"אין להתחבר"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"לאשר את ההתחברות?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"אם תתבצע התחברות, ייתכן שרשתות Wi‑Fi של <xliff:g id="CARRIERNAME">%s</xliff:g> יקבלו גישה או ישתפו מזהה ייחודי שמשויך לכרטיס ה-SUM שלך. בעקבות זאת, ייתכן שניתן יהיה לעקוב אחר מיקום המכשיר שלך."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"התחברות"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"אין להתחבר"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"ה-Wi-Fi יופעל אוטומטית"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"כשתימצאו בקרבת רשת באיכות גבוהה ששמרתם"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"אל תפעיל שוב"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"רשת Wi‑Fi הופעלה אוטומטית"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"המיקום הנוכחי שלך הוא בקרבת הרשת השמורה: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"אין אפשרות להתחבר ל-Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" בעל חיבור גרוע לאינטרנט."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"האם להתיר את החיבור?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"האפליקציה %1$s מנסה להתחבר אל רשת ה-Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"אפליקציה"</string> - <string name="accept" msgid="5931271886782610829">"קבל"</string> - <string name="decline" msgid="6874256900873707640">"דחה"</string> - <string name="ok" msgid="4215387532539340948">"אישור"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ההזמנה נשלחה"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"הזמנה להתחבר"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"מאת:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"אל:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"הקלד את קוד הגישה הנדרש."</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"קוד גישה:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"הטאבלט יתנתק מרשת ה-Wi-Fi באופן זמני בשעה שהוא מחובר אל <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"מכשיר ה-Android TV יתנתק מרשת ה-Wi-Fi באופן זמני בשעה שהוא מחובר אל <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"הטלפון יתנתק מרשת ה-Wi-Fi באופן זמני בשעה שהוא מחובר אל <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"אישור"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"לא ניתן להתחבר אל <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"יש להקיש כדי לשנות את הגדרות הפרטיות ולנסות שוב"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"לשנות את הגדרות הפרטיות?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"כדי לחבר, עליך לאפשר ל-<xliff:g id="SSID">%1$s</xliff:g> להשתמש בכתובת ה-MAC של המכשיר, מזהה ייחודי. הגדרת הפרטיות לרשת זו משתמשת כרגע במזהה רנדומלי. \n\nשינוי זה עשוי לאפשר למכשירים בקרבת מקום לעקוב אחר מיקום המכשיר שלך."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"שינוי ההגדרות"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ההגדרה עודכנה. אפשר לנסות שוב להתחבר."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"לא ניתן לשנות את הגדרות הפרטיות"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"הרשת לא נמצאה"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32760 באימות EAP"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32761 באימות EAP"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32762 באימות EAP"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32763 באימות EAP"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32764 באימות EAP"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32765 באימות EAP"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32766 באימות EAP"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"נקודת האינטרנט (hotspot) נכבתה"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"אין מכשירים מחוברים. יש להקיש כדי לשנות."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi מנותק"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"יש להכניס SIM של <xliff:g id="CARRIER_NAME">%2$s</xliff:g> כדי להתחבר אל <xliff:g id="SSID">%1$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-ja/strings.xml b/service/res/values-ja/strings.xml deleted file mode 100644 index e494dbd8c..000000000 --- a/service/res/values-ja/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"システム Wi-Fi リソース"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Wi-Fi オープン ネットワークに接続"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi-Fi ネットワークに接続中"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi-Fi ネットワークに接続しました"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi ネットワークに接続できませんでした"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"すべてのネットワークを表示するにはタップします"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"接続"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"すべてのネットワーク"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ネットワークのステータス"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ネットワーク通知"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"ネットワークを利用できます"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Wi‑Fi ネットワーク候補を許可しますか?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> からのネットワーク候補に、デバイスが自動的に接続される可能性があります。"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"許可"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"許可しない"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> のWi-Fi に接続しますか?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"これらのネットワークは SIM ID を受信します。この ID を使ってデバイスの位置情報が追跡される可能性があります"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"接続"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"接続しない"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"接続を確認しますか?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"接続すると、<xliff:g id="CARRIERNAME">%s</xliff:g> の Wi‑Fi ネットワークが、SIM に関連付けられている一意の ID にアクセスしたりその ID を共有したりする可能性があります。これにより、デバイスの位置情報が追跡される可能性もあります。"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"接続"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"接続しない"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi は自動的にオンになります"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"高品質の保存済みネットワークの検出時"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"再度オンにしない"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi が自動的に ON になりました"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"保存済みネットワーク「<xliff:g id="NETWORK_SSID">%1$s</xliff:g>」の近くにいます"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fiに接続できませんでした"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" はインターネット接続に問題があります。"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"接続を許可しますか?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"アプリ%1$sがWi-Fiネットワーク%2$sへの接続を希望しています"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"アプリ"</string> - <string name="accept" msgid="5931271886782610829">"同意する"</string> - <string name="decline" msgid="6874256900873707640">"同意しない"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"招待状を送信しました"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"接続への招待"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"From:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"To:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"必要なPINを入力してください:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"タブレットが<xliff:g id="DEVICE_NAME">%1$s</xliff:g>に接続されている間は一時的にWi-Fi接続が切断されます"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV デバイスが <xliff:g id="DEVICE_NAME">%1$s</xliff:g> に接続されている間は一時的に Wi-Fi 接続が解除されます"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"モバイル デバイスが<xliff:g id="DEVICE_NAME">%1$s</xliff:g>に接続されている間は一時的にWi-Fi接続が解除されます。"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> に接続できません"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"タップしてプライバシー設定を変更し、もう一度お試しください"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"プライバシー設定を変更しますか?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> は接続のために、あなたのデバイスの MAC アドレス(固有の識別番号)を使用する必要があります。現在、このネットワークのプライバシー設定では、ランダム ID を使用しています。\n\nこの変更により、付近のデバイスがあなたのデバイスの位置情報を追跡できるようになる可能性があります。"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"設定を変更"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"設定を更新しました。もう一度接続してみてください。"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"プライバシー設定を変更できません"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ネットワークが見つかりません"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP 認証エラー 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP 認証エラー 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP 認証エラー 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP 認証エラー 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP 認証エラー 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP 認証エラー 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP 認証エラー 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"アクセス ポイントが OFF になりました"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"デバイスは接続されていません。タップすると変更できます。"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi が切断されました"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> に接続するには、<xliff:g id="CARRIER_NAME">%2$s</xliff:g> の SIM を挿入します"</string> -</resources> diff --git a/service/res/values-ka/strings.xml b/service/res/values-ka/strings.xml deleted file mode 100644 index 7e12bcc7f..000000000 --- a/service/res/values-ka/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"სისტემის Wi-Fi რესურსები"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"დაუკავშირდით ღია Wi‑Fi ქსელს"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"მიმდინარეობს Wi‑Fi ქსელთან დაკავშირება"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi ქსელთან დაკავშირება წარმატებით მოხერხდა"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi ქსელთან დაკავშირება ვერ მოხერხდა"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"შეეხეთ ყველა ქსელის სანახავად"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"დაკავშირება"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"ყველა ქსელი"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ქსელის სტატუსი"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ქსელის გაფრთხილებები"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"ქსელი ხელმისაწვდომია"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"გსურთ, დაუშვათ შემოთავაზებული Wi‑Fi ქსელები?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> შემოთავაზებული ქსელები. მოწყობილობა შეიძლება ავტომატურად დაუკავშირდეს."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"დაშვება"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"არა, გმადლობთ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"დაუკავშირდებით <xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi-ს?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ეს ქსელები მიიღებს SIM-ის ID-ს, რომლის მეშვეობითაც შესაძლებელია მოწყობილობის მდებარეობაზე თვალის დევნება."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"დაკავშირება"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"არ დაუკავშირდეს"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"გსურთ, დაადასტუროთ დაკავშირება?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"დაკავშირების შემთხვევაში, <xliff:g id="CARRIERNAME">%s</xliff:g>-ის Wi‑Fi ქსელებმა შეიძლება წვდომა იქონიოს ან გააზიაროს უნიკალური ID, რომელიც თქვენს SIM-ბარათთან არის ასოცირებული. ამ ცვლილებამ შესაძლოა თქვენი მოწყობილობის მდებარეობა აღნუსხვადი გახადოს."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"დაკავშირება"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"არ დაუკავშირდეს"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi ავტომატურად ჩაირთვება"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"როცა შენახულ მაღალხარისხიან ქსელებთან ახლოს იმყოფებით"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"ხელახლა ნუ ჩართავ"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi ავტომატურად ჩაირთო"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"თქვენ შენახული ქსელის მახლობლად ხართ: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi-თან დაკავშირება ვერ მოხერხდა"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ცუდი ინტერნეტ-კავშირი."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"გსურთ კავშირის დაშვება?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"განაცხადს %1$s სურს დაუკავშირდეს Wifi ქსელს %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"აპლიკაცია"</string> - <string name="accept" msgid="5931271886782610829">"მიღება"</string> - <string name="decline" msgid="6874256900873707640">"უარყოფა"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"მოწვევა გაგზავნილია"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"მოწვევა დასაკავშირებლად"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"გამგზავნი:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"მიმღები:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"შეიყვანეთ საჭირო PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"პინ-კოდი:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ტაბლეტი დროებით გაითიშება Wi-Fi-დან, სანამ მიერთებულია <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ზე"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"თქვენი Android TV მოწყობილობა დროებით გაითიშება Wi-Fi-დან, სანამ ის <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-თან იქნება დაკავშირებული"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ტელეფონი დროებით გაითიშება Wi-Fi-დან, სანამ მიერთებულია <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ზე"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g>-თან დაკავშირება ვერ ხერხდება"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"შეეხეთ კონფიდენციალურობის პარამეტრების შესაცვლელად და ცადეთ ხელახლა"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"შეიცვალოს კონფიდენციალურობის პარამეტრი?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"დასაკავშირებლად <xliff:g id="SSID">%1$s</xliff:g> საჭიროებს თქვენი მოწყობილობის MAC მისამართის, უნიკალური იდენტიფიკატორის, გამოყენებას. ამჟამად თქვენი კონფიდენციალურობის პარამეტრი ამ ქსელისთვის შემთხვევით იდენტიფიკატორს იყენებს. \n\nამ ცვლილებამ შიძლება თქვენი მოწყობილობის მდებარეობა ახლომახლო მოწყობილობებისთვის ხილული გახადოს."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"პარამეტრის შეცვლა"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"პარამეტრი განახლდა. ცადეთ ხელახლა დაკავშირება."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"კონფიდენციალურობის პარამეტრის შეცვლა ვერ ხერხდება"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ქსელი ვერ მოიძებნა"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ავთენტიკაციის შეცდომა 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ავთენტიკაციის შეცდომა 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ავთენტიკაციის შეცდომა 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ავთენტიკაციის შეცდომა 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ავთენტიკაციის შეცდომა 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ავთენტიკაციის შეცდომა 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ავთენტიკაციის შეცდომა 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"უსადენო ქსელი გამორთულია"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"დაკავშირებული მოწყობილობები არ არის. შეეხეთ შესაცვლელად."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi ქსელთან კავშირი გაწყდა."</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g>-თან დასაკავშირებლად მოათავსეთ <xliff:g id="CARRIER_NAME">%2$s</xliff:g>-ის SIM-ბარათი"</string> -</resources> diff --git a/service/res/values-kk/strings.xml b/service/res/values-kk/strings.xml deleted file mode 100644 index 0b7a57338..000000000 --- a/service/res/values-kk/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Жүйенің Wi-Fi ресурстары"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Ашық Wi‑Fi желісіне қосылу"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi желісіне қосылуда"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi желісіне қосылды"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi желісіне қосылмады"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Барлық желілерді көру үшін түртіңіз"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Қосылу"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Барлық желілер"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Желі күйі"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Желі дабылдары"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Желі қолжетімді"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Ұсынылған Wi‑Fi желілеріне рұқсат беру керек пе?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ұсынған желілер. Құрылғы автоматты түрде қосылуы мүмкін."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Рұқсат беру"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Жоқ, рақмет"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> қызметі Wi‑Fi желісімен байланыстырылсын ба?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Бұл желілер SIM идентификаторын алады, оны құрылғының орналасқан жерін бақылау үшін қолдануға болады."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Байланыстыру"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Қосылмау"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Қосылымды растайсыз ба?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Егер қосылсаңыз, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi желілері SIM картаңызға байланыстырылған бірегей идентификаторды пайдалана немесе бөлісе алады. Оның көмегімен құрылғыңыздың орнын қадағалауға болады."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Қосу"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Қосылмау"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi автоматты түрде қосылады"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Сақталған жоғары сапалы желіге жақын болғанда"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Қайта қоспау"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi автоматты түрде қосылды"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Сақталған желінің маңайындасыз: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi желісіне қосыла алмады"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" интернет байланысы нашар."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Қосылуға рұқсат ету керек пе?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s қолданбасы %2$s Wi-Fi желісіне қосылғысы келеді"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Қолданба"</string> - <string name="accept" msgid="5931271886782610829">"Қабылдау"</string> - <string name="decline" msgid="6874256900873707640">"Бас тарту"</string> - <string name="ok" msgid="4215387532539340948">"Жарайды"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Шақыру жіберілді"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Жалғау үшін шақыру"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Кімнен:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Кімге:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Өтінілген PIN кодты теру:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Планшет <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысына қосылғанша Wi-Fi байланысынан уақытша ажыратылады"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысына қосулы тұрғанда, Android TV құрылғысы Wi-Fi желісінен уақытша ажырайды."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысына жалғанып тұрғанда телефон уақытша Wi-Fi байланысынан ажыратылады"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Жарайды"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> құрылғысына қосылмайды."</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Құпиялылық параметрін өзгерту үшін түртіп, әрекетті қайталаңыз."</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Құпиялылық параметрі өзгертілсін бе?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Қосылу үшін <xliff:g id="SSID">%1$s</xliff:g> құрылғыңыздың MAC мекенжайын, бірегей идентификаторын қажет етеді. Қазір желінің құпиялылық параметрі еркін идентификаторды пайдаланады. \n\nБұл өзгеріс маңайдағы құрылғыларға құрылғыңыздың орнын қадағалауға мүмкіндік береді."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Параметрді өзгерту"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Параметр жаңартылды. Қайта қосылып көріңіз."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Құпиялылық параметрі өзгертілмейді."</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Желі табылмады"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация қатесі 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация қатесі 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация қатесі 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация қатесі 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация қатесі 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация қатесі 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация қатесі 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Хотспот өшірілді"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Ешқандай құрылғы қосылмаған. Өзгерту үшін түртіңіз."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi ажыратылған."</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> желісіне қосылу үшін <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM картасын салыңыз."</string> -</resources> diff --git a/service/res/values-km/strings.xml b/service/res/values-km/strings.xml deleted file mode 100644 index 3a0c18b16..000000000 --- a/service/res/values-km/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"ធនធាន Wi-Fi របស់ប្រព័ន្ធ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"ភ្ជាប់ទៅបណ្តាញ Wi‑Fi ចំហ"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"កំពុងភ្ជាប់ទៅបណ្តាញ Wi‑Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"បានភ្ជាប់ទៅបណ្តាញ Wi‑Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"មិនអាចភ្ជាប់ទៅបណ្តាញ Wi‑Fi បានទេ"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"ចុចដើម្បីមើលបណ្តាញទាំងអស់"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"ភ្ជាប់"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"បណ្ដាញទាំងអស់"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ស្ថានភាពបណ្តាញ"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ការជូនដំណឹងអំពីបណ្តាញ"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"មានបណ្តាញ"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"អនុញ្ញាតឱ្យភ្ជាប់បណ្ដាញ Wi‑Fi ដែលបានណែនាំ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"បណ្ដាញដែលបានណែនាំរបស់ <xliff:g id="NAME">%s</xliff:g> ។ ឧបករណ៍អាចភ្ជាប់ដោយស្វ័យប្រវត្តិ។"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"អនុញ្ញាត"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ទេ អរគុណ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"ភ្ជាប់ Wi-Fi របស់ <xliff:g id="CARRIERNAME">%s</xliff:g> ឬ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"បណ្ដាញទាំងនេះទទួលបានលេខសម្គាល់ស៊ីម ដែលអាចប្រើដើម្បីតាមដានទីតាំងឧបករណ៍"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ភ្ជាប់"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"កុំភ្ជាប់"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"បញ្ជាក់ការតភ្ជាប់ដែរទេ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ប្រសិនបើអ្នកភ្ជាប់ នោះបណ្ដាញ Wi-Fi របស់ <xliff:g id="CARRIERNAME">%s</xliff:g> អាចចូលប្រើ ឬចែករំលែកលេខសម្គាល់ពិសេសដែលភ្ជាប់ជាមួយស៊ីមរបស់អ្នក។ សកម្មភាពនេះអាចអនុញ្ញាតឱ្យមានការតាមដានទីតាំងឧបករណ៍របស់អ្នក។"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"ភ្ជាប់"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"កុំភ្ជាប់"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi នឹងបើកដោយស្វ័យប្រវត្តិ"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"នៅពេលដែលអ្នកនៅជិតបណ្តាញគុណភាពខ្ពស់ដែលបានរក្សាទុក"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"កុំបើកឡើងវិញ"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi បានបើកដោយស្វ័យប្រវត្តិ"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"អ្នកនៅជិតបណ្តាញដែលបានរក្សាទុក៖ <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"មិនអាចតភ្ជាប់វ៉ាយហ្វាយ"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" មានការតភ្ជាប់អ៊ីនធឺណិតមិនល្អ។"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"អនុញ្ញាតភ្ជាប់?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"កម្មវិធី %1$s ចង់ភ្ជាប់ទៅបណ្តាញ Wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"កម្មវិធី"</string> - <string name="accept" msgid="5931271886782610829">"ទទួល"</string> - <string name="decline" msgid="6874256900873707640">"បដិសេធ"</string> - <string name="ok" msgid="4215387532539340948">"យល់ព្រម"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"បានផ្ញើលិខិតអញ្ជើញ"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"អញ្ជើញឲ្យភ្ជាប់"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"ពី៖"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"ទៅ៖"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"បញ្ចូលកូដ PIN ដែលទាមទារ៖"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"កូដ PIN ៖"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"កុំព្យូទ័របន្ទះនឹងផ្ដាច់ជាបណ្ដោះអាសន្នពីវ៉ាយហ្វាយ ខណៈដែលវាភ្ជាប់ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"ឧបករណ៍ Android TV របស់អ្នកនឹងផ្ដាច់ពី Wi-Fi ជាបណ្តោះអាសន្ន នៅពេលឧបករណ៍នេះភ្ជាប់ជាមួយ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ទូរស័ព្ទនឹងផ្ដាច់ពីវ៉ាយហ្វាយខណៈដែលវាត្រូវបានតភ្ជាប់ទៅ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"យល់ព្រម"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"មិនអាចភ្ជាប់ជាមួយ <xliff:g id="SSID">%1$s</xliff:g> បានទេ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"ចុច ដើម្បីប្ដូរការកំណត់ឯកជនភាព រួចព្យាយាមម្ដងទៀត"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"ប្ដូរការកំណត់ឯកជនភាពឬ?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"ដើម្បីភ្ជាប់ <xliff:g id="SSID">%1$s</xliff:g> ត្រូវការប្រើអាសយដ្ឋាន MAC របស់ឧបករណ៍អ្នក ដែលជាព័ត៌មានសម្គាល់ពិសេស។ បច្ចុប្បន្ន ការកំណត់ឯកជនភាពរបស់អ្នកសម្រាប់បណ្ដាញនេះប្រើព័ត៌មានសម្គាល់ចៃដន្យ។ \n\nការផ្លាស់ប្ដូរនេះអាចអនុញ្ញាតឱ្យឧបករណ៍នៅជិតតាមដានទីតាំងឧបករណ៍របស់អ្នក។"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ប្ដូរការកំណត់"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"បានធ្វើបច្ចុប្បន្នភាពការកំណត់។ សូមសាកល្បងភ្ជាប់ម្ដងទៀត។"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"មិនអាចប្ដូរការកំណត់ឯកជនភាពបានទេ"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"រកមិនឃើញបណ្ដាញទេ"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : បញ្ហាក្នុងការផ្ទៀងផ្ទាត់ EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : បញ្ហាក្នុងការផ្ទៀងផ្ទាត់ EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : បញ្ហាក្នុងការផ្ទៀងផ្ទាត់ EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : បញ្ហាក្នុងការផ្ទៀងផ្ទាត់ EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : បញ្ហាក្នុងការផ្ទៀងផ្ទាត់ EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : បញ្ហាក្នុងការផ្ទៀងផ្ទាត់ EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : បញ្ហាក្នុងការផ្ទៀងផ្ទាត់ EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"បានបិទហតស្ប៉ត"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"មិនមានឧបករណ៍ដែលបានភ្ជាប់ទេ។ សូមចុច ដើម្បីកែ។"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"បានផ្តាច់ Wi-Fi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"ដើម្បីភ្ជាប់ <xliff:g id="SSID">%1$s</xliff:g> សូមបញ្ចូលស៊ីម <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-kn/strings.xml b/service/res/values-kn/strings.xml deleted file mode 100644 index a31341719..000000000 --- a/service/res/values-kn/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"ಸಿಸ್ಟಂ ವೈ-ಫೈ ಮೂಲಗಳು"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಿಸಿ"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗುತ್ತಿದೆ"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"ಎಲ್ಲಾ ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ನೋಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"ಸಂಪರ್ಕಿಸಿ"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"ಎಲ್ಲಾ ನೆಟ್ವರ್ಕ್ಗಳು"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ನೆಟ್ವರ್ಕ್ ಸ್ಥಿತಿ"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ನೆಟ್ವರ್ಕ್ ಎಚ್ಚರಿಕೆಗಳು"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿದೆ"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"ಸೂಚಿಸಿರುವ ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ಅನುಮತಿಸುವುದೇ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ಸೂಚಿಸಿರುವ ನೆಟ್ವರ್ಕ್ಗಳು. ಸಾಧನಗಳು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಗೊಳ್ಳಬಹುದು."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ಅನುಮತಿಸಿ"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ಬೇಡ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> ವೈ-ಫೈ ಗೆ ಕನೆಕ್ಟ್ ಮಾಡುವುದೇ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಬಳಸಬಹುದಾದ SIM ಐಡಿಯನ್ನು ಈ ನೆಟ್ವರ್ಕ್ಗಳು ಸ್ವೀಕರಿಸುತ್ತವೆ"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ಕನೆಕ್ಟ್ ಮಾಡಿ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ಕನೆಕ್ಟ್ ಮಾಡಬೇಡಿ"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ಕನೆಕ್ಷನ್ ಅನ್ನು ಖಚಿತಪಡಿಸಬೇಕೇ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ನೀವು ಕನೆಕ್ಟ್ ಮಾಡಿದರೆ, <xliff:g id="CARRIERNAME">%s</xliff:g> ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ನಿಮ್ಮ SIM ಗೆ ಸಂಬಂಧಿಸಿದ ಅನನ್ಯ ಐಡಿಗೆ ಪ್ರವೇಶ ಪಡೆಯಬಹುದು ಅಥವಾ ಅದನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು. ನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಇದು ಅವಕಾಶ ನೀಡಬಹುದು."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"ಕನೆಕ್ಟ್ ಮಾಡಿ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"ಕನೆಕ್ಟ್ ಮಾಡಬೇಡಿ"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"ವೈ‑ಫೈ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಆಗುತ್ತದೆ"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"ನೀವು ಉಳಿಸಿದ ಅಧಿಕ ಗುಣಮಟ್ಟದ ನೆಟ್ವರ್ಕ್ ಸಮೀಪದಲ್ಲಿದ್ದಾಗ"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"ಮತ್ತೆ ಆನ್ ಮಾಡಲು ಹಿಂತಿರುಗಬೇಡಿ"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"ವೈ-ಫೈ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಆಗಿದೆ"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"ನೀವು ಉಳಿಸಿದ ನೆಟ್ವರ್ಕ್ನ ಸಮೀಪವಿರುವಿರಿ: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ವೈ-ಫೈ ಗೆ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ದುರ್ಬಲ ಇಂಟರ್ನೆಟ್ ಕನೆಕ್ಷನ್ ಅನ್ನು ಹೊಂದಿದೆ."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"ಸಂಪರ್ಕವನ್ನು ಅನುಮತಿಸುವುದೇ?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%2$s ವೈಫೈ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಿಸಲು %1$s ಅಪ್ಲಿಕೇಶನ್ ಬಯಸುತ್ತದೆ"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ಅಪ್ಲಿಕೇಶನ್"</string> - <string name="accept" msgid="5931271886782610829">"ಸ್ವೀಕರಿಸಿ"</string> - <string name="decline" msgid="6874256900873707640">"ನಿರಾಕರಿಸಿ"</string> - <string name="ok" msgid="4215387532539340948">"ಸರಿ"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ಆಹ್ವಾನವನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"ಸಂಪರ್ಕಗೊಳ್ಳಲು ಆಹ್ವಾನ"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"ಇಂದ:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"ಗೆ:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"ಅಗತ್ಯವಿರುವ ಪಿನ್ ಟೈಪ್ ಮಾಡಿ:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"ಪಿನ್:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ಟ್ಯಾಬ್ಲೆಟ್ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಾಗ ಅದನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ವೈ-ಫೈ ನಿಂದ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗುತ್ತದೆ"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"ನಿಮ್ಮ Android TV ಸಾಧನವು <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಾಗ, ವೈ-ಫೈ ನಿಂದ ತಾತ್ಕಾಲಿಕವಾಗಿ ಸಂಪರ್ಕ ಕಡಿದುಕೊಳ್ಳುತ್ತದೆ"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ಫೋನ್ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಾಗ ವೈ-ಫೈ ನಿಂದ ಅದು ತಾತ್ಕಾಲಿಕವಾಗಿ ಸಂಪರ್ಕ ಕಡಿತಗೊಳ್ಳುತ್ತದೆ"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ಸರಿ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"ಗೌಪ್ಯತೆ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಮರುಪ್ರಯತ್ನಿಸಿ"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"ಗೌಪ್ಯತೆ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸಬೇಕೆ?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"ಕನೆಕ್ಟ್ ಮಾಡಲು, <xliff:g id="SSID">%1$s</xliff:g> ಗೆ ನಿಮ್ಮ ಸಾಧನದ ಅನನ್ಯ ಗುರುತಿಸುವಿಕೆಯಾದ MAC ವಿಳಾಸವನ್ನು ಬಳಸುವ ಅಗತ್ಯವಿದೆ. ಪ್ರಸ್ತುತವಾಗಿ, ಈ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಬಂಧಿಸಿದ ಗೌಪ್ಯತೆಯ ಸೆಟ್ಟಿಂಗ್ \'ಯಾದೃಚ್ಛಿಕ\' ಗುರುತಿಸುವಿಕೆಯನ್ನು ಬಳಸುತ್ತದೆ. \n\nನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಸಮೀಪದಲ್ಲಿನ ಸಾಧನಗಳಿಗೆ ಈ ಬದಲಾವಣೆಯು ಅನುಮತಿಸಬಹುದು."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ಸೆಟ್ಟಿಂಗ್ ಬದಲಾಯಿಸಿ"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲಾಗಿದೆ. ಪುನಃ ಕನೆಕ್ಟ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"ಗೌಪ್ಯತೆ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ನೆಟ್ವರ್ಕ್ ಕಂಡುಬಂದಿಲ್ಲ"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ಪ್ರಮಾಣೀಕರಣ ದೋಷ 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ಪ್ರಮಾಣೀಕರಣ ದೋಷ 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ಪ್ರಮಾಣೀಕರಣ ದೋಷ 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ಪ್ರಮಾಣೀಕರಣ ದೋಷ 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ಪ್ರಮಾಣೀಕರಣ ದೋಷ 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ಪ್ರಮಾಣೀಕರಣ ದೋಷ 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ಪ್ರಮಾಣೀಕರಣ ದೋಷ 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ಹಾಟ್ಸ್ಪಾಟ್ ಅನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"ಯಾವುದೇ ಸಾಧನಗಳನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಿಲ್ಲ. ಮಾರ್ಪಡಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"ವೈ-ಫೈ ಕನೆಕ್ಷನ್ ಕಡಿತಗೊಂಡಿದೆ."</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು, <xliff:g id="CARRIER_NAME">%2$s</xliff:g> ಸಿಮ್ ಅನ್ನು ಸೇರಿಸಿ"</string> -</resources> diff --git a/service/res/values-ko/strings.xml b/service/res/values-ko/strings.xml deleted file mode 100644 index 4fbca69bc..000000000 --- a/service/res/values-ko/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"시스템 Wi-Fi 리소스"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"공개 Wi‑Fi 네트워크에 연결"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi-Fi 네트워크에 연결 중"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi 네트워크에 연결됨"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi 네트워크에 연결할 수 없음"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"모든 네트워크를 보려면 탭하세요."</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"연결"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"모든 네트워크"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"네트워크 상태"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"네트워크 알림"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"네트워크 사용 가능"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"제안된 Wi‑Fi 네트워크를 허용하시겠습니까?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>에서 네트워크를 제안했습니다. 기기가 자동으로 연결될 수 있습니다."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"허용"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"허용 안함"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi에 연결하시겠습니까?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"이 네트워크는 기기 위치 추적에 사용할 수 있는 SIM ID를 수신합니다."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"연결"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"연결 안 함"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"연결하시겠습니까?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"연결하면 <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi 네트워크에서 SIM과 연결된 고유 ID에 액세스하거나 고유 ID를 공유할 수 있습니다. 이 경우 내 기기의 위치를 추적할 수도 있습니다."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"연결"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"연결 안 함"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi가 자동으로 사용 설정됨"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"저장된 고품질 네트워크가 가까이 있는 경우"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"다시 사용 설정하지 않음"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi가 자동으로 사용 설정됨"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"주변에 저장된 네트워크(<xliff:g id="NETWORK_SSID">%1$s</xliff:g>)가 있습니다"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi에 연결할 수 없습니다"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" 인터넷 연결 상태가 좋지 않습니다."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"연결을 허용하시겠습니까?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s 애플리케이션에서 %2$s Wi-Fi 네트워크에 연결하려고 합니다."</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"앱"</string> - <string name="accept" msgid="5931271886782610829">"동의"</string> - <string name="decline" msgid="6874256900873707640">"거부"</string> - <string name="ok" msgid="4215387532539340948">"확인"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"초대장을 보냈습니다."</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"연결하도록 초대"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"보낸사람:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"수신:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"필수 PIN 입력:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 연결되어 있는 동안 일시적으로 태블릿의 Wi-Fi 연결이 해제됩니다."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 연결되어 있는 동안 Android TV 기기의 Wi-Fi 연결이 일시적으로 해제됩니다."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 연결되어 있는 동안 일시적으로 휴대전화의 Wi-Fi 연결이 해제됩니다."</string> - <string name="dlg_ok" msgid="3250085870426030310">"확인"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g>에 연결할 수 없습니다."</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"탭하여 개인정보 보호 설정을 변경하고 다시 시도하세요."</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"개인정보 보호 설정을 변경하시겠습니까?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"연결하려면 <xliff:g id="SSID">%1$s</xliff:g>에서 기기의 고유 식별자인 MAC 주소를 사용해야 합니다. 현재 이 네트워크의 개인정보 보호 설정에서는 무작위 식별자를 사용합니다. \n\n변경할 경우 근처 기기가 내 기기의 위치 정보를 추적할 수도 있습니다."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"설정 변경"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"설정이 업데이트되었습니다. 다시 연결해 보세요."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"개인정보 보호 설정을 변경할 수 없습니다."</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"네트워크를 찾을 수 없습니다."</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 인증 오류 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 인증 오류 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 인증 오류 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 인증 오류 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 인증 오류 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 인증 오류 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 인증 오류 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"핫스팟이 사용 중지됨"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"연결된 기기가 없습니다. 수정하려면 탭하세요."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi 연결이 끊어졌습니다."</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g>에 연결하려면 <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM을 삽입하세요."</string> -</resources> diff --git a/service/res/values-ky/strings.xml b/service/res/values-ky/strings.xml deleted file mode 100644 index 4f3aaba94..000000000 --- a/service/res/values-ky/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Тутумдун Wi-Fi ресурстары"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Ачык Wi‑Fi тармагына туташуу"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi тармагына туташууда"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Ачык Wi‑Fi тармагына туташты"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi-Fi тармагына туташпай калды"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Бардык тармактарды көрүү үчүн басыңыз"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Туташуу"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Бардык тармактар"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Тармактын абалы"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Тармактын эскертүүлөрү"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Жеткиликтүү тармактар"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Сунушталган Wi‑Fi тармактарына туташасызбы?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> сунуштаган тармактар. Түзмөк автоматтык түрдө туташышы мүмкүн."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Уруксат берүү"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Жок, рахмат"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi тармагына туташтырылсынбы?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Бул тармактарга SIM-картанын идентификатору берилип, анын жардамы менен түзмөктүн жайгашкан жерин аныктоого болот"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Туташуу"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Туташпасын"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Туташууну ырастайсызбы?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Туташсаңыз, <xliff:g id="CARRIERNAME">%s</xliff:g> операторунун Wi‑Fi тармактары SIM картаңызга байланышкан өзгөчө идентификаторго мүмкүнчүлүк алып, аны башкалар менен бөлүшө алат. Ушуну менен, түзмөгүңүздүн жайгашкан жерин аныктай аласыз."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Туташуу"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Туташпасын"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi автоматтык түрдө күйөт"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Байланыш сигналы күчтүү тармактарга жакындаганда"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Өзү кайра күйбөйт"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi автоматтык түрдө күйгүзүлдү"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Сакталган тармактын жанындасыз: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi менен туташуу түзүлбөдү"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" хотспотунун интернет байланышы начар."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Туташууга уруксатпы?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s колдонмосу %2$s Wifi тармагына туташкысы келет"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Колдонмо"</string> - <string name="accept" msgid="5931271886782610829">"Кабыл алуу"</string> - <string name="decline" msgid="6874256900873707640">"Баш тартуу"</string> - <string name="ok" msgid="4215387532539340948">"Жарайт"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Чакыруу жөнөтүлдү"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Туташууга чакыруу"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Жөнөтүүчү:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Алуучу:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Талап кылынган PIN\'ди териңиз:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Планшет <xliff:g id="DEVICE_NAME">%1$s</xliff:g> менен байланышып турганда, Wi-Fi\'дан убактылуу ажыратылат"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүнө туташып турганда убактылуу Wi-Fi\'дан ажыратылат"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Телефон <xliff:g id="DEVICE_NAME">%1$s</xliff:g> менен байланышып турганда, Wi-Fi\'дан убактылуу ажыратылат"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Жарайт"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> менен туташпай жатат"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Купуялык жөндөөлөрүн өзгөртүү үчүн таптап, кайталап көрүңүз"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Купуялык жөндөөлөрүн өзгөртөсүзбү?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Туташуу үчүн <xliff:g id="SSID">%1$s</xliff:g> MAC дарегиңизди – уникалдуу идентификаторду колдонушу керек. Учурда бул тармактын купуялык жөндөөсү башаламан иретте түзүлгөн идентификаторду колдонууда. \n\nУшуну менен түзмөгүңүздүн жайгашкан жерине жакын жердеги түзмөктөр көз сала алышат."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Жөндөөнү өзгөртүү"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Жөндөө жаңырды. Кайра туташып көрүңүз."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Купуялык жөндөөлөрүн өзгөртүүгө болбойт"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Тармак табылган жок"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация катасы 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация катасы 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация катасы 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация катасы 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация катасы 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация катасы 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP аутентификация катасы 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Байланыш түйүнү өчүрүлдү"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Туташып турган түзмөктөр жок. Өзгөртүү үчүн таптап коюңуз."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi‑Fi туташуусу жок"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> тармагына туташуу үчүн <xliff:g id="CARRIER_NAME">%2$s</xliff:g> байланыш операторунун SIM-картасын салыңыз"</string> -</resources> diff --git a/service/res/values-lo/strings.xml b/service/res/values-lo/strings.xml deleted file mode 100644 index dbe5efb41..000000000 --- a/service/res/values-lo/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"ແຫຼ່ງຂໍ້ມູນ Wi-Fi ລະບົບ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ແບບເປີດ"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"ກຳລັງເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ແລ້ວ"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"ບໍ່ສາມາດເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ໄດ້"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"ແຕະເພື່ອເບິ່ງເຄືອຂ່າຍທັງໝົດ"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"ເຊື່ອມຕໍ່"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"ເຄືອຂ່າຍທັງໝົດ"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ສະຖານະເຄືອຂ່າຍ"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ແຈ້ງເຕືອນເຄືອຂ່າຍ"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"ມີເຄືອຂ່າຍທີ່ສາມາດໃຊ້ໄດ້"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"ອະນຸຍາດເຄືອຂ່າຍ Wi‑Fi ທີ່ແນະນຳບໍ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"ເຄືອຂ່າຍ <xliff:g id="NAME">%s</xliff:g> ທີ່ແນະນຳ. ອຸປະກອນອາດເຊື່ອມຕໍ່ເອງໂດຍອັດຕະໂນມັດ."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ອະນຸຍາດ"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ບໍ່, ຂອບໃຈ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"ເຊື່ອມຕໍ່ກັບ Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> ບໍ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ເຄືອຂ່າຍເຫຼົ່ານີ້ຈະໄດ້ຮັບ ID ຊິມທີ່ສາມາດໃຊ້ເພື່ອຕິດຕາມສະຖານທີ່ຂອງອຸປະກອນໄດ້"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ເຊື່ອມຕໍ່"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ຢ່າເຊື່ອມຕໍ່"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ຢືນຢັນການເຊື່ອມຕໍ່ບໍ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ຫາກທ່ານເຊື່ອມຕໍ່, ເຄືອຂ່າຍ Wi-Fi ຂອງ <xliff:g id="CARRIERNAME">%s</xliff:g> ຈະສາມາດເຂົ້າເຖິງ ແລະ ແບ່ງປັນ unique ID ທີ່ເຊື່ອມໂຍງກັບຊິມຂອງທ່ານໄດ້. ນີ້ອາດເຮັດໃຫ້ສາມາດຕິດຕາມສະຖານທີ່ຂອງອຸປະກອນທ່ານໄດ້."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"ເຊື່ອມຕໍ່"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"ຢ່າເຊື່ອມຕໍ່"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"ຈະມີການເປີດໃຊ້ Wi‑Fi ອັດຕະໂນມັດ"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"ເມື່ອທ່ານຢູ່ໃກ້ເຄືອຂ່າຍຄຸນນະພາບສູງທີ່ບັນທຶກໄວ້"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"ບໍ່ຕ້ອງເປີດໃຊ້ຄືນໃໝ່"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"ເປີດໃຊ້ Wi‑Fi ອັດຕະໂນມັດແລ້ວ"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"ທ່ານຢູ່ໃກ້ເຄືອຂ່າຍທີ່ບັນທຶກໄວ້: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ບໍ່ສາມາດເຊື່ອມຕໍ່ Wi-Fi ໄດ້"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດທີ່ຊ້າ."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"ອະນຸຍາດການເຊື່ອມຕໍ່ຫຼືບໍ່?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"ແອັບພລິເຄຊັນ %1$s ຢາກຈະເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍ Wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ແອັບພລິເຄຊັນ"</string> - <string name="accept" msgid="5931271886782610829">"ຍອມຮັບ"</string> - <string name="decline" msgid="6874256900873707640">"ປະຕິເສດ"</string> - <string name="ok" msgid="4215387532539340948">"ຕົກລົງ"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ການເຊື້ອເຊີນຖືກສົ່ງໄປແລ້ວ"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"ການເຊີນຊວນເພື່ອເຊື່ອມຕໍ່"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"ຈາກ:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"ຈາກ:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"ພິມລະຫັດ PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ແທັບເລັດຈະຖືກຕັດການເຊື່ອມຕໍ່ຈາກ Wi-Fi ເປັນການຊົ່ວຄາວ ໃນຂະນະທີ່ມັນເຊື່ອມຕໍ່ກັບ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຢູ່."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"ອຸປະກອນ Android TV ຂອງທ່ານຈະຕັດການເຊື່ອມຕໍ່ຈາກ Wi-Fi ເປັນການຊົ່ວຄາວໃນລະຫວ່າງທີ່ມັນເຊື່ອມຕໍ່ຫາ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ໂທລະສັບຈະຖືກຢຸດການເຊື່ອມຕໍ່ຊົ່ວຄາວຈາກ Wi-Fi ໃນຂະນະທີ່ມັນເຊື່ອມຕໍ່ກັບ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ຕົກລົງ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"ບໍ່ສາມາດເຊື່ອມຕໍ່ຫາ <xliff:g id="SSID">%1$s</xliff:g> ໄດ້"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"ແຕະເພື່ອປ່ຽນການຕັ້ງຄ່າຄວາມເປັນສ່ວນຕົວແລ້ວລອງໃໝ່"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"ປ່ຽນການຕັ້ງຄ່າຄວາມເປັນສ່ວນຕົວບໍ?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"ເພື່ອເຊື່ອມຕໍ່, <xliff:g id="SSID">%1$s</xliff:g> ຈຳເປັນຕ້ອງໃຊ້ທີ່ຢູ່ MAC ອຸປະກອນຂອງທ່ານ, ເຊິ່ງເປັນຕົວລະບຸແບບບໍ່ຊ້ຳກັນ. ຕອນນີ້, ການຕັ້ງຄ່າຄວາມເປັນສ່ວນຕົວຂອງທ່ານສຳລັບເຄືອຂ່າຍນີ້ໃຊ້ຕົວລະບຸແບບສຸ່ມຢູ່. \n\nການປ່ຽນແປງນີ້ອາດຈະເຮັດໃຫ້ອຸປະກອນໃກ້ຄຽງສາມາດຕິດຕາມສະຖານທີ່ຂອງອຸປະກອນທ່ານໄດ້."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ປ່ຽນການຕັ້ງຄ່າ"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ອັບເດດການຕັ້ງຄ່າແລ້ວ ກະລຸນາລອງເຊື່ອມຕໍ່ໃໝ່."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"ບໍ່ສາມາດປ່ຽນການຕັ້ງຄ່າຄວາມເປັນສ່ວນຕົວໄດ້"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ບໍ່ພົບເຄືອຂ່າຍ"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : ການພິສູດຢືນຢັນ EAP ຜິດພາດ 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : ການພິສູດຢືນຢັນ EAP ຜິດພາດ 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : ການພິສູດຢືນຢັນ EAP ຜິດພາດ 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : ການພິສູດຢືນຢັນ EAP ຜິດພາດ 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : ການພິສູດຢືນຢັນ EAP ຜິດພາດ 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : ການພິສູດຢືນຢັນ EAP ຜິດພາດ 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : ການພິສູດຢືນຢັນ EAP ຜິດພາດ 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ປິດຮັອດສະປອດແລ້ວ"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"ບໍ່ມີອຸປະກອນເຊື່ອມຕໍ່. ແຕະເພື່ອແກ້ໄຂ."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"ຕັດການເຊື່ອມຕໍ່ Wi-Fi ແລ້ວ"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"ເພື່ອເຊື່ອມຕໍ່ຫາ <xliff:g id="SSID">%1$s</xliff:g>, ກະລຸນາໃສ່ຊິມ <xliff:g id="CARRIER_NAME">%2$s</xliff:g> ກ່ອນ"</string> -</resources> diff --git a/service/res/values-lt/strings.xml b/service/res/values-lt/strings.xml deleted file mode 100644 index 3d6a667f2..000000000 --- a/service/res/values-lt/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistemos „Wi‑Fi“ šaltiniai"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Prisijunkite prie atviro „Wi‑Fi“ tinklo"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Jungiamasi prie „Wi-Fi“ tinklo"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Prisijungta prie „Wi-Fi“ tinklo"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Nepavyko prisijungti prie „Wi‑Fi“ tinklo"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Palieskite, jei norite matyti visus tinklus"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Prisijungti"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Visi tinklai"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Tinklo būsena"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Tinklo įspėjimai"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Tinklas pasiekiamas"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Leisti siūlomus „Wi‑Fi“ tinklus?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"„<xliff:g id="NAME">%s</xliff:g>“ siūlomi tinklai. Įrenginys gali prisijungti automatiškai."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Leisti"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, ačiū"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Prisijungti prie „<xliff:g id="CARRIERNAME">%s</xliff:g>“ „Wi-Fi“?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Šie tinklai gauna SIM kortelės ID, kurį galima naudoti įrenginio vietovei stebėti"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Prisijungti"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nesprisijungti"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Patvirtinti prijungimą?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Prisijungus „<xliff:g id="CARRIERNAME">%s</xliff:g>“ teikiami „Wi‑Fi“ tinklai gali pasiekti ar bendrinti su jūsų SIM susietą unikalų ID. Gali būti, kad jūsų įrenginio vieta bus stebima."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Prisijungti"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Nesprisijungti"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"„Wi‑Fi“ bus įjungtas automatiškai"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kai būsite netoli išsaugoto aukštos kokybės tinklo"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Neįjunkite vėl"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"„Wi‑Fi“ įjungtas automatiškai"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Esate netoli išsaugoto tinklo: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nepavyko prisijungti prie „Wi-Fi“"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" turi prastą interneto ryšį."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Leisti prisijungti?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Programa „%1$s“ nori prisijungti prie „Wi-Fi“ tinklo „%2$s“"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Programa"</string> - <string name="accept" msgid="5931271886782610829">"Sutikti"</string> - <string name="decline" msgid="6874256900873707640">"Atmesti"</string> - <string name="ok" msgid="4215387532539340948">"Gerai"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Pakvietimas išsiųstas"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Pakvietimas prisijungti"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Nuo:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Skirta:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Įveskite reikiamą PIN kodą:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN kodas:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Planšetinis kompiuteris bus laikinai atjungtas nuo „Wi-Fi“, kol jis prijungtas prie „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"„Android TV“ įrenginys bus laikinai atjungtas nuo „Wi-Fi“, kol bus prijungtas prie „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefonas bus laikinai atjungtas nuo „Wi-Fi“, kol bus prijungtas prie „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Gerai"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Nepavyksta prisijungti prie „<xliff:g id="SSID">%1$s</xliff:g>“"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Palieskite, kad pakeistumėte privatumo nustatymus, ir bandykite dar kartą"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Keisti privatumo nustatymą?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Kad galėtų prisijungti, <xliff:g id="SSID">%1$s</xliff:g> reikia jūsų įrenginio MAC adreso, unikaliojo identifikatoriaus. Šiuo metu šio tinklo privatumo nustatymas naudoja atsitiktinio parinkimo identifikatorių. \n\nGali būti, kad atlikus šį pakeitimą įrenginio vietovę galės stebėti netoliese esantys įrenginiai."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Keisti nustatymą"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Nustatymas atnaujintas. Bandykite prisijungti dar kartą."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nepavyko pakeisti privatumo nustatymo"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Tinklas nerastas"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> – EAP autentifikavimo klaida: 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> – EAP autentifikavimo klaida: 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> – EAP autentifikavimo klaida: 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> – EAP autentifikavimo klaida: 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> – EAP autentifikavimo klaida: 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> – EAP autentifikavimo klaida: 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> – EAP autentifikavimo klaida: 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Viešosios interneto prieigos taškas išjungtas"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nėra jokių prijungtų įrenginių. Palieskite, kad pakeistumėte."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"„Wi-Fi“ atjungtas"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Jei norite prisijungti prie „<xliff:g id="SSID">%1$s</xliff:g>“, įdėkite „<xliff:g id="CARRIER_NAME">%2$s</xliff:g>“ SIM kortelę"</string> -</resources> diff --git a/service/res/values-lv/strings.xml b/service/res/values-lv/strings.xml deleted file mode 100644 index c8d186589..000000000 --- a/service/res/values-lv/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistēmas Wi-Fi resursi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Savienojuma izveide ar atvērtu Wi-Fi tīklu"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Savienojuma izveide ar Wi-Fi tīklu"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Ir izveidots savienojums ar Wi-Fi tīklu"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Nevarēja izveidot savienojumu ar Wi‑Fi tīklu"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Pieskarieties, lai skatītu visus tīklus"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Izveidot savienojumu"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Visi tīkli"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Tīkla statuss"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Tīkla brīdinājumi"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Tīkls ir pieejams"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Vai atļaut ieteiktos Wi‑Fi tīklus?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Lietotnes <xliff:g id="NAME">%s</xliff:g> ieteiktie tīkli. Ierīcē var tikt automātiski izveidots savienojums."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Atļaut"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nē, paldies"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vai izveidot savienojumu ar <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Šie tīkli saņem SIM ID, ko var izmantot, lai izsekotu ierīces atrašanās vietu."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Izveidot savienojumu"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Neizveidot savienojumu"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vai apstiprināt savienojumu?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ja izveidosiet savienojumu, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi tīkli varēs piekļūt unikālajam ID, kas saistīts ar jūsu SIM, vai kopīgot to. Tādējādi varēs tikt izsekota jūsu ierīces atrašanās vieta."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Izveidot savienojumu"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Neizveidot savienojumu"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi tiks automātiski ieslēgts"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kad atrodaties saglabāta augstas kvalitātes tīkla tuvumā"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Neieslēgt atkārtoti"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi-Fi tika ieslēgts automātiski"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Jūs atrodaties saglabāta tīkla tuvumā: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>."</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nevarēja izveidot savienojumu ar Wi-Fi."</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ir slikts interneta savienojums."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Vai atļaut savienojumu?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Lietotne %1$s vēlas izveidot savienojumu ar Wi-Fi tīklu %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Lietojumprogramma"</string> - <string name="accept" msgid="5931271886782610829">"Piekrist"</string> - <string name="decline" msgid="6874256900873707640">"Noraidīt"</string> - <string name="ok" msgid="4215387532539340948">"Labi"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Ielūgums ir nosūtīts."</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Ielūgums izveidot savienojumu"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"No:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kam:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Ierakstiet pieprasīto PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Planšetdators tiks īslaicīgi atvienots no Wi-Fi tīkla, kamēr būs izveidots savienojums ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV ierīce tiks īslaicīgi atvienota no Wi-Fi tīkla, kamēr ir izveidots savienojums ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Tālrunis tiks īslaicīgi atvienots no Wi-Fi tīkla, kamēr būs izveidots savienojums ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="dlg_ok" msgid="3250085870426030310">"Labi"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Nevar izveidot savienojumu ar: <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Pieskarieties, lai mainītu konfidencialitātes iestatījumus un mēģinātu vēlreiz"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Vai mainīt konfidencialitātes iestatījumu?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Lai varētu izveidot savienojumu, <xliff:g id="SSID">%1$s</xliff:g> vēlas izmantot jūsu ierīces MAC adresi, unikālu identifikatoru. Šobrīd šī tīkla konfidencialitātes iestatījumam tiek izmantots nejauši atlasīts identifikators. \n\nTādējādi tuvumā esošās ierīces var izsekot jūsu ierīces atrašanās vietu."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Mainīt iestatījumu"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Iestatījums atjaunināts. Mēģiniet izveidot savienojumu vēlreiz."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nevar mainīt konfidencialitātes iestatījumu"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Tīkls nav atrasts"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentificēšanas kļūda 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentificēšanas kļūda 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentificēšanas kļūda 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentificēšanas kļūda 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentificēšanas kļūda 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentificēšanas kļūda 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP autentificēšanas kļūda 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Tīklājs ir izslēgts"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nav pievienota neviena ierīce. Pieskarieties, lai mainītu iestatījumus."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi savienojums ir pārtraukts."</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Lai izveidotu savienojumu ar tīklu <xliff:g id="SSID">%1$s</xliff:g>, ievietojiet operatora <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM karti."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-af/strings.xml b/service/res/values-mcc310-mnc004-af/strings.xml deleted file mode 100644 index a739f55ca..000000000 --- a/service/res/values-mcc310-mnc004-af/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Jy kan nie van buite Verizon se dekkingsgebied aan Verizon Wi-F Access koppel nie."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Jy is nie op Verizon Wi-Fi Access ingeteken nie. Bel ons asseblief by 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Daar is \'n probleem met jou Verizon Wi-Fi Access-rekening. Bel ons asseblief by 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Jy is reeds aan Verizon Wi-Fi Access gekoppel."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Kan jou nie aan Verizon Wi-Fi Access koppel nie. Bel ons asseblief by 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Daar is \'n probleem met jou Verizon Wi-Fi Access-rekening. Bel ons asseblief by 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access is nie in jou ligging beskikbaar nie. Probeer later weer of probeer van \'n ander ligging af."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-am/strings.xml b/service/res/values-mcc310-mnc004-am/strings.xml deleted file mode 100644 index a4058d3b8..000000000 --- a/service/res/values-mcc310-mnc004-am/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> ፦ የVerizon ሽፋን ካለው አካባቢ ውጭ ሆነው ከVerizon Wi-Fi Access ጋር መገናኘት አይችሉም።"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> ፦ ለVerizon Wi-Fi Access ደንበኝነት አልተመዘገቡም። እባክዎ 800-922-0204 ላይ ይደውሉልን።"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> ፦ የእርስዎ Verizon Wi-Fi Access መለያ ጋር ችግር አለበት። እባክዎ 800-922-0204 ላይ ይደውሉልን።"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> ፦ አስቀድመው ከVerizon Wi-Fi Access ጋር ተገናኝተዋል።"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> ፦ እርስዎን ከVerizon Wi-Fi Access ጋር ማገናኘት ላይ ችግር አለ። እባክዎ 800-922-0204 ላይ ይደውሉልን።"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> ፦ የእርስዎ Verizon Wi-Fi Access መለያ ጋር ችግር አለበት። እባክዎ 800-922-0204 ላይ ይደውሉልን።"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ከእርስዎ አካባቢ የሚገኝ አይደለም። በኋላ ላይ እንደገና ይሞክሩ ወይም ከተለየ አካባቢ ይሞክሩ።"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ar/strings.xml b/service/res/values-mcc310-mnc004-ar/strings.xml deleted file mode 100644 index 2baecb4a4..000000000 --- a/service/res/values-mcc310-mnc004-ar/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : لا يمكنك الاتصال بشبكة Verizon Wi-Fi Access من خارج نطاق تغطية Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : لم تشترك في Verizon Wi-Fi Access. يُرجى الاتصال بالرقم 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : حدثت مشكلة في حسابك على Verizon Wi-Fi Access. يُرجى الاتصال بالرقم 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : سبق واتصلت بشبكة Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : حدثت مشكلة أثناء اتصالك بشبكة Verizon Wi-Fi Access. يُرجى الاتصال بالرقم 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : حدثت مشكلة في حسابك على Verizon Wi-Fi Access. يُرجى الاتصال بالرقم 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access غير متاح في موقعك الجغرافية. يُرجى إعادة المحاولة لاحقًا أو المحاولة من موقع جغرافي مختلف."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-as/strings.xml b/service/res/values-mcc310-mnc004-as/strings.xml deleted file mode 100644 index 3382d827d..000000000 --- a/service/res/values-mcc310-mnc004-as/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : আপুনি Verizon কভাৰেজ ক্ষেত্ৰৰ বাহিৰৰ পৰা Verizon Wi-Fi Accessৰ সৈতে সংযোগ কৰিব নোৱাৰে।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : আপুনি Verizon Wi-Fi Access ছাবস্ক্ৰাইব কৰা নাই। অনুগ্ৰহ কৰি ৮০০-৯২২-০২০৪ নম্বৰটোত আমালৈ কল কৰক।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : আপোনাৰ Verizon Wi-Fi Access একাউণ্টটোত কিবা সমস্যা আছে। অনুগ্ৰহ কৰি ৮০০-৯২২-০২০৪ নম্বৰটোত আমালৈ কল কৰক।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : আপুনি ইতিমধ্যে Verizon Wi-Fi Accessৰ সৈতে সংযুক্ত হৈ আছে।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : আপোনাক Verizon Wi-Fi Accessৰ সৈতে সংযোগ কৰাত এটা সমস্যা হৈছে। অনুগ্ৰহ কৰি ৮০০-৯২২-০২০৪ নম্বৰটোত আমালৈ কল কৰক।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : আপোনাৰ Verizon Wi-Fi Access একাউণ্টটোত কিবা সমস্যা আছে। অনুগ্ৰহ কৰি ৮০০-৯২২-০২০৪ নম্বৰটোত আমালৈ কল কৰক।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access আপোনাৰ অৱস্থানৰ পৰা উপলব্ধ নহয়। পাছত পুনৰ চেষ্টা কৰক অথবা এটা বেলেগ অৱস্থানৰ পৰা চেষ্টা কৰক।"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-az/strings.xml b/service/res/values-mcc310-mnc004-az/strings.xml deleted file mode 100644 index 31497db2b..000000000 --- a/service/res/values-mcc310-mnc004-az/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon əhatə dairəsindən kənarda Verizon Wi-Fi Access\'ə qoşula bilməzsiniz."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ə abunə olmamısınız. 800-922-0204 nömrəsini yığaraq bizə zəng edin."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access hesabınız ilə bağlı problem var. 800-922-0204 nömrəsini yığaraq bizə zəng edin."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Artıq Verizon Wi-Fi Access\'ə qoşulmusunuz."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Sizi Verizon Wi-Fi Access\'ə qoşmaqla bağlı problem var. 800-922-0204 nömrəsini yığaraq bizə zəng edin."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access hesabınız ilə bağlı problem var. 800-922-0204 nömrəsini yığaraq bizə zəng edin."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access məkanınızdan əlçatan deyil. Sonra cəhd edin, ya da fərqli məkandan yoxlayın."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-b+sr+Latn/strings.xml b/service/res/values-mcc310-mnc004-b+sr+Latn/strings.xml deleted file mode 100644 index 5ab12b1f7..000000000 --- a/service/res/values-mcc310-mnc004-b+sr+Latn/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Ne možete da se povežete na Verizon WiFi Access van oblasti koju Verizon pokriva."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Niste pretplaćeni na Verizon WiFi Access. Pozovite nas na 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon WiFi Access nalogom. Pozovite nas na 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Već ste povezani na Verizon WiFi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Postoji problem pri povezivanju na Verizon WiFi Access. Pozovite nas na 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon WiFi Access nalogom. Pozovite nas na 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon WiFi Access nije dostupan sa vaše lokacije. Probajte ponovo kasnije ili probajte sa neke druge lokacije."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-be/strings.xml b/service/res/values-mcc310-mnc004-be/strings.xml deleted file mode 100644 index 0eb819785..000000000 --- a/service/res/values-mcc310-mnc004-be/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : вы не можаце падключыцца да Verizon Wi-Fi Access, калі не знаходзіцеся ў зоне пакрыцця Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : вы не падпісаны на Verizon Wi-Fi Access. Выклікайце нас па нумары 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : ёсць праблема з вашым уліковым запісам Verizon Wi-Fi Access. Выклікайце нас па нумары 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : вы ўжо падключаны да Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : ёсць праблема з падключэннем да Verizon Wi-Fi Access. Выклікайце нас па нумары 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : ёсць праблема з вашым уліковым запісам Verizon Wi-Fi Access. Выклікайце нас па нумары 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : з месца, дзе вы знаходзіцеся, няма доступу да Verizon Wi-Fi Access. Паўтарыце спробу пазней або змяніце месцазнаходжанне."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-bg/strings.xml b/service/res/values-mcc310-mnc004-bg/strings.xml deleted file mode 100644 index ba0bacca2..000000000 --- a/service/res/values-mcc310-mnc004-bg/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: Не можете да се свържете с Verizon Wi-Fi Access извън района на покритие на Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Нямате абонамент за Verizon Wi-Fi Access. Моля, обадете ни се на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: Възникна проблем с профила ви във Verizon Wi-Fi Access. Моля, обадете ни се на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: Вече сте установили връзка с Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Възникна проблем при свързването с Verizon Wi-Fi Access. Моля, обадете ни се на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: Възникна проблем с профила ви във Verizon Wi-Fi Access. Моля, обадете ни се на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access не се предлага за местоположението ви. Опитайте отново по-късно или от друго местоположение."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-bn/strings.xml b/service/res/values-mcc310-mnc004-bn/strings.xml deleted file mode 100644 index 62fb5c13e..000000000 --- a/service/res/values-mcc310-mnc004-bn/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon কভারেজ এলাকার বাইরে আপনি Verizon Wi-Fi Access-এর সাথে কানেক্ট করতে পারবেন না।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : আপনি Verizon Wi-Fi Access সাবস্ক্রাইব করেননি। ৮০০-৯২২-০২০৪ নম্বরে যোগাযোগ করুন।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : আপনার Verizon Wi-Fi Access অ্যাকাউন্ট নিয়ে কোনও সমস্যা হয়েছে। ৮০০-৯২২-০২০৪ নম্বরে যোগাযোগ করুন।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : আপনি আগে থেকে Verizon Wi-Fi Access-এর সাথে কানেক্ট করেছেন।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : আপনার Verizon Wi-Fi Access-এর সাথে কানেক্ট করতে কোনও সমস্যা হয়েছে। ৮০০-৯২২-০২০৪ নম্বরে যোগাযোগ করুন।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : আপনার Verizon Wi-Fi Access অ্যাকাউন্ট নিয়ে কোনও সমস্যা হয়েছে। ৮০০-৯২২-০২০৪ নম্বরে যোগাযোগ করুন।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : আপনার লোকেশনে Verizon Wi-Fi Access উপলভ্য নেই। পরে আবার চেষ্টা করুন বা অন্য লোকেশন থেকে চেষ্টা করুন।"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-bs/strings.xml b/service/res/values-mcc310-mnc004-bs/strings.xml deleted file mode 100644 index 8e13ce195..000000000 --- a/service/res/values-mcc310-mnc004-bs/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Ne možete se povezati s WiFi pristupom Verizonu izvan područja pokrivenosti Verizona."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Niste pretplaćeni na WiFi pristup Verizonu. Pozovite nas na broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema s vašim računom za WiFi pristup Verizonu. Pozovite nas na broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Već ste povezani s WiFi pristupom Verizonu."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema pri povezivanju s WiFi pristupom Verizonu. Pozovite nas na broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema s vašim računom za WiFi pristup Verizonu. Pozovite nas na broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : WiFi pristup Verizonu nije dostupan s vaše lokacije. Pokušajte ponovo kasnije ili pokušajte s druge lokacije."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ca/strings.xml b/service/res/values-mcc310-mnc004-ca/strings.xml deleted file mode 100644 index d976a524d..000000000 --- a/service/res/values-mcc310-mnc004-ca/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: no et pots connectar a Verizon Wi‑Fi Access des de fora de l\'àrea de cobertura de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: no estàs subscrit a Verizon Wi‑Fi Access. Truca\'ns al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: hi ha un problema amb el teu compte de Verizon Wi‑Fi Access. Truca\'ns al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: ja estàs connectat a Verizon Wi‑Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: hi ha un problema en connectar-te a Verizon Wi‑Fi Access. Truca\'ns al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: hi ha un problema amb el teu compte de Verizon Wi‑Fi Access. Truca\'ns al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi‑Fi Access no està disponible des de la teva ubicació. Torna-ho a provar més tard o bé des d\'una altra ubicació."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-cs/strings.xml b/service/res/values-mcc310-mnc004-cs/strings.xml deleted file mode 100644 index 9cb55473c..000000000 --- a/service/res/values-mcc310-mnc004-cs/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: K síti Verizon Wi-Fi Access se nelze připojit mimo dosah pokrytí společnosti Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Síť Verizon Wi-Fi Access nemáte předplacenou. Zavolejte nám na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: U vašeho účtu Verizon Wi-Fi Access došlo k problému. Zavolejte nám na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: K síti Verizon Wi-Fi Access jste už připojeni."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Při připojování k síti Verizon Wi-Fi Access došlo k problému. Zavolejte nám na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: U vašeho účtu Verizon Wi-Fi Access došlo k problému. Zavolejte nám na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access ve vaší oblasti není k dispozici. Zkuste to později nebo z jiného místa."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-da/strings.xml b/service/res/values-mcc310-mnc004-da/strings.xml deleted file mode 100644 index dc5b8a209..000000000 --- a/service/res/values-mcc310-mnc004-da/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Du kan ikke oprette forbindelse til Verizon Wi-Fi Access uden for Verizons dækningsområde."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Du abonnerer ikke på Verizon Wi-Fi Access. Ring til os på telefonnummer 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Der er et problem med din Verizon Wi-Fi Access-konto. Ring til os på telefonnummer 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Du har allerede oprettet forbindelse til Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Du kan ikke oprette forbindelse til Verizon Wi-Fi Access. Ring til os på telefonnummer 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Der er et problem med din Verizon Wi-Fi Access-konto. Ring til os på telefonnummer 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access er ikke tilgængeligt i dit område. Prøv igen senere eller fra en anden placering."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-de/strings.xml b/service/res/values-mcc310-mnc004-de/strings.xml deleted file mode 100644 index 7dc92942f..000000000 --- a/service/res/values-mcc310-mnc004-de/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Eine Verbindung mit Verizon Wi-Fi Access ist außerhalb der Abdeckung von Verizon nicht möglich."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Du bist nicht bei Verizon Wi-Fi Access angemeldet. Bitte ruf uns unter 800-922-0204 an."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Es gibt ein Problem mit deinem Verizon Wi-Fi Access-Konto. Bitte ruf uns unter 800-922-0204 an."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Du bist bereits mit Verizon Wi-Fi Access verbunden."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Es kann keine Verbindung zu Verizon Wi-Fi Access hergestellt werden. Bitte ruf uns unter 800-922-0204 an."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Es gibt ein Problem mit deinem Verizon Wi-Fi Access-Konto. Bitte ruf uns unter 800-922-0204 an."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ist an deinem Standort nicht verfügbar. Du kannst es später noch einmal oder von einem anderen Standort aus versuchen."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-el/strings.xml b/service/res/values-mcc310-mnc004-el/strings.xml deleted file mode 100644 index 6e02508c3..000000000 --- a/service/res/values-mcc310-mnc004-el/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Δεν μπορείτε να συνδεθείτε στο Verizon Wi-Fi Access εκτός της περιοχής κάλυψης της Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Δεν έχετε εγγραφεί στο Verizon Wi-Fi Access. Καλέστε μας στον αριθμό 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Υπάρχει πρόβλημα με τον λογαριασμό σας Verizon Wi-Fi Access. Καλέστε μας στον αριθμό 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Έχετε συνδεθεί ήδη με το Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Υπάρχει πρόβλημα με τη σύνδεση στο Verizon Wi-Fi Access. Καλέστε μας στον αριθμό 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Υπάρχει πρόβλημα με τον λογαριασμό σας Verizon Wi-Fi Access. Καλέστε μας στον αριθμό 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Το Verizon Wi-Fi Access δεν είναι διαθέσιμο από την τοποθεσία σας. Δοκιμάστε ξανά αργότερα ή δοκιμάστε από διαφορετική τοποθεσία."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-en-rAU/strings.xml b/service/res/values-mcc310-mnc004-en-rAU/strings.xml deleted file mode 100644 index 7777f42e0..000000000 --- a/service/res/values-mcc310-mnc004-en-rAU/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : You can’t connect to Verizon Wi-Fi access from outside the Verizon coverage area."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi access is not available from your location. Try again later or try from a different location."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-en-rCA/strings.xml b/service/res/values-mcc310-mnc004-en-rCA/strings.xml deleted file mode 100644 index 7777f42e0..000000000 --- a/service/res/values-mcc310-mnc004-en-rCA/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : You can’t connect to Verizon Wi-Fi access from outside the Verizon coverage area."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi access is not available from your location. Try again later or try from a different location."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-en-rGB/strings.xml b/service/res/values-mcc310-mnc004-en-rGB/strings.xml deleted file mode 100644 index 7777f42e0..000000000 --- a/service/res/values-mcc310-mnc004-en-rGB/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : You can’t connect to Verizon Wi-Fi access from outside the Verizon coverage area."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi access is not available from your location. Try again later or try from a different location."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-en-rIN/strings.xml b/service/res/values-mcc310-mnc004-en-rIN/strings.xml deleted file mode 100644 index 7777f42e0..000000000 --- a/service/res/values-mcc310-mnc004-en-rIN/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : You can’t connect to Verizon Wi-Fi access from outside the Verizon coverage area."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi access is not available from your location. Try again later or try from a different location."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-es-rUS/strings.xml b/service/res/values-mcc310-mnc004-es-rUS/strings.xml deleted file mode 100644 index 5452ff2ea..000000000 --- a/service/res/values-mcc310-mnc004-es-rUS/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : No te puedes conectar a Verizon Wi-Fi Access si te encuentras fuera del área de cobertura de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : No te suscribiste a Verizon Wi-Fi Access. Comunícate con nosotros al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Hay un problema con tu cuenta de Verizon Wi-Fi Access. Comunícate con nosotros al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Ya te conectaste a Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Se produjo un error al conectarte a Verizon Wi-Fi Access. Comunícate con nosotros al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Hay un problema con tu cuenta de Verizon Wi-Fi Access. Comunícate con nosotros al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access no está disponible en tu ubicación. Vuelve a intentarlo más tarde o en una ubicación diferente."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-es/strings.xml b/service/res/values-mcc310-mnc004-es/strings.xml deleted file mode 100644 index bb549ee3f..000000000 --- a/service/res/values-mcc310-mnc004-es/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: no puedes conectarte a Verizon Wi‑Fi Access si no estás en el área de cobertura de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: no tienes una suscripción a Verizon Wi‑Fi Access. Llámanos al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: hay un problema con tu cuenta de Verizon Wi‑Fi Access. Llámanos al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: ya te has conectado a Verizon Wi‑Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: no se ha podido conectar a Verizon Wi‑Fi Access. Llámanos al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: hay un problema con tu cuenta de Verizon Wi‑Fi Access. Llámanos al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi‑Fi Access no está disponible en tu ubicación. Inténtalo de nuevo más tarde o cuando estés en otro sitio."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-et/strings.xml b/service/res/values-mcc310-mnc004-et/strings.xml deleted file mode 100644 index a30df836f..000000000 --- a/service/res/values-mcc310-mnc004-et/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: te ei saa väljaspool Verizoni leviala Verizon Wi-Fi Accessiga ühendust luua."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: te ei ole Verizon Wi-Fi Accessi tellinud. Helistage meile numbril 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: teie Verizon Wi-Fi Accessi kontoga on probleem. Helistage meile numbril 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: olete Verizon Wi-Fi Accessiga juba ühendatud."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: teie ja Verizon Wi-Fi Accessi vahelise ühenduse loomisel on probleem. Helistage meile numbril 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: teie Verizon Wi-Fi Accessi kontoga on probleem. Helistage meile numbril 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access ei ole teie asukohas saadaval. Proovige hiljem või mõnes teises asukohas uuesti."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-eu/strings.xml b/service/res/values-mcc310-mnc004-eu/strings.xml deleted file mode 100644 index 071d5f3d6..000000000 --- a/service/res/values-mcc310-mnc004-eu/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: ezin zara konektatu Verizon Wi-Fi Access zerbitzura Verizon-en estaldura-eremutik kanpo bazaude."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: ez zaude harpidetuta Verizon Wi-Fi Access zerbitzura. Dei iezaguzu 800-922-0204 zenbakira."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: arazo bat dago Verizon Wi-Fi Access zerbitzuko kontuarekin. Dei iezaguzu 800-922-0204 zenbakira."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: dagoeneko konektatuta zaude Verizon Wi-Fi Access zerbitzura."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: arazo bat dago Verizon Wi-Fi Access zerbitzura konektatzeko. Dei iezaguzu 800-922-0204 zenbakira."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: arazo bat dago Verizon Wi-Fi Access zerbitzuko kontuarekin. Dei iezaguzu 800-922-0204 zenbakira."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access ez dago erabilgarri kokapen horretan. Saiatu berriro geroago edo beste kokapen batetik."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-fa/strings.xml b/service/res/values-mcc310-mnc004-fa/strings.xml deleted file mode 100644 index 643e63c7f..000000000 --- a/service/res/values-mcc310-mnc004-fa/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : خارج از منطقه تحت پوشش Verizon نمیتوانید به Verizon Wi-Fi Access متصل شوید."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : مشترک Verizon Wi-Fi Access نیستید. لطفاً ازطریق شماره ۰۲۰۴-۹۲۲-۸۰۰ با ما تماس بگیرید."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : مشکلی در حساب Verizon Wi-Fi Access وجود دارد. لطفاً ازطریق شماره ۰۲۰۴-۹۲۲-۸۰۰ با ما تماس بگیرید."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : در حالحاضر به Verizon Wi-Fi Access متصل هستید."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : هنگام اتصال به Verizon Wi-Fi Access مشکلی وجود دارد. لطفاً ازطریق شماره ۰۲۰۴-۹۲۲-۸۰۰ با ما تماس بگیرید."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : مشکلی در حساب Verizon Wi-Fi Access وجود دارد. لطفاً ازطریق شماره ۰۲۰۴-۹۲۲-۸۰۰ با ما تماس بگیرید."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access در مکان شما در دسترس نیست. بعداً دوباره تلاش کنید یا از مکان متفاوتی امتحان کنید."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-fi/strings.xml b/service/res/values-mcc310-mnc004-fi/strings.xml deleted file mode 100644 index 57e0c3882..000000000 --- a/service/res/values-mcc310-mnc004-fi/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizonin Wi-Fi‑yhteyttä ei voi muodostaa Verizonin kattavuusalueen ulkopuolelta."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Et ole tilannut Verizonin Wi-Fi‑yhteyttä. Soita meille: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi ‑tilisi kanssa on ongelma. Soita meille: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Olet jo yhteydessä Verizonin Wi-Fiin."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Ongelma yhdistettäessä Verizonin Wi-Fiin. Soita meille: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi ‑tilisi kanssa on ongelma. Soita meille: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi ei ole saatavilla sijainnissasi. Yritä uudelleen tai toisesta sijainnista."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-fr-rCA/strings.xml b/service/res/values-mcc310-mnc004-fr-rCA/strings.xml deleted file mode 100644 index 61e2e8056..000000000 --- a/service/res/values-mcc310-mnc004-fr-rCA/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Vous ne pouvez pas vous connecter à Verizon Wi-Fi Access en dehors de la zone de couverture de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Vous n\'êtes pas abonné à Verizon Wi-Fi Access. Veuillez nous appeler au 1 800 922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Il y a un problème avec votre compte Verizon Wi-Fi Access. Veuillez nous appeler au 1 800 922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Vous êtes déjà connecté à Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Il y a un problème de connexion à Verizon Wi-Fi Access. Veuillez nous appeler au 1 800 922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Il y a un problème avec votre compte Verizon Wi-Fi Access. Veuillez nous appeler au 1 800 922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access n\'est pas proposé dans votre région. Réessayez plus tard ou essayez à partir d\'une région différente."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-fr/strings.xml b/service/res/values-mcc310-mnc004-fr/strings.xml deleted file mode 100644 index 7b41f7c33..000000000 --- a/service/res/values-mcc310-mnc004-fr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : vous ne pouvez pas vous connecter à Verizon Wi-Fi Access si vous ne vous trouvez pas dans une zone couverte par le réseau Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : vous n\'avez pas d\'abonnement à Verizon Wi-Fi Access. Veuillez nous appeler au 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : un problème lié à votre compte Verizon Wi-Fi Access a été détecté. Veuillez nous appeler au 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : votre connexion à Verizon Wi-Fi Access est déjà active."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : un problème est survenu lors de votre connexion à Verizon Wi-Fi Access. Veuillez nous appeler au 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : un problème lié à votre compte Verizon Wi-Fi Access a été détecté. Veuillez nous appeler au 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : le service Verizon Wi-Fi Access n\'est pas disponible dans votre région. Veuillez réessayer plus tard ou depuis un autre lieu."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-gl/strings.xml b/service/res/values-mcc310-mnc004-gl/strings.xml deleted file mode 100644 index 7f2e8a829..000000000 --- a/service/res/values-mcc310-mnc004-gl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: non podes conectar con Verizon Wi-Fi Access desde fóra da área de cobertura de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: non tes subscrición a Verizon Wi-Fi Access. Chámanos ao número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: houbo un problema coa túa conta de Verizon Wi-Fi Access. Chámanos ao número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: xa estableciches conexión con Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: houbo un problema ao conectar con Verizon Wi-Fi Access. Chámanos ao número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: houbo un problema coa túa conta de Verizon Wi-Fi Access. Chámanos ao número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access non está dispoñible desde a túa localización. Téntao de novo máis tarde ou proba desde unha localización diferente."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-gu/strings.xml b/service/res/values-mcc310-mnc004-gu/strings.xml deleted file mode 100644 index 8c892adff..000000000 --- a/service/res/values-mcc310-mnc004-gu/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : તમે Verizon કવરેજ વિસ્તારની બહારથી Verizon વાઇ-ફાઇ ઍક્સેસ સાથે કનેક્ટ થઈ શકતાં નથી."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : તમે Verizon વાઇ-ફાઇ ઍક્સેસને સબ્સ્ક્રાઇબ કરેલું નથી. કૃપા કરીને અમને 800-922-0204 પર કૉલ કરો."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : તમારા વાઇ-ફાઇ ઍક્સેસ એકાઉન્ટમાં કોઈ સમસ્યા છે. કૃપા કરીને અમને 800-922-0204 પર કૉલ કરો."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : તમે પહેલેથી Verizon વાઇ-ફાઇ ઍક્સેસ સાથે કનેક્ટ કરેલું છે."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : તમને Verizon વાઇ-ફાઇ ઍક્સેસ સાથે કનેક્ટ કરવામાં કોઈ સમસ્યા આવે છે. કૃપા કરીને અમને 800-922-0204 પર કૉલ કરો."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : તમારા વાઇ-ફાઇ ઍક્સેસ એકાઉન્ટમાં કોઈ સમસ્યા છે. કૃપા કરીને અમને 800-922-0204 પર કૉલ કરો."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : તમારા સ્થળેથી Verizon વાઇ-ફાઇ ઍક્સેસ ઉપલબ્ધ નથી. પછીથી અથવા કોઈ અલગ સ્થળેથી પ્રયાસ કરો."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-hi/strings.xml b/service/res/values-mcc310-mnc004-hi/strings.xml deleted file mode 100644 index 7764c578f..000000000 --- a/service/res/values-mcc310-mnc004-hi/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : आप Verizon के कवरेज एरिया के बाहर Verizon Wi-Fi Access से कनेक्ट नहीं हो सकते."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : आपने Verizon Wi-Fi Access की सदस्यता नहीं ली है. कृपया 800-922-0204 पर कॉल करके हमसे संपर्क करें."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : आपके Verizon Wi-Fi Access खाते में कोई समस्या है. कृपया 800-922-0204 पर कॉल करके हमसे संपर्क करें."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : आप पहले ही Verizon Wi-Fi Access से कनेक्ट हैं."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : आपको Verizon Wi-Fi Access से कनेक्ट करने में कोई समस्या हुई है. कृपया 800-922-0204 पर कॉल करके हमसे संपर्क करें."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : आपके Verizon Wi-Fi Access खाते में कोई समस्या है. कृपया 800-922-0204 पर कॉल करके हमसे संपर्क करें."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : आपकी जगह पर Verizon Wi-Fi Access उपलब्ध नहीं है. कृपया थोड़ी देर में कोशिश करें या किसी दूसरी जगह से कोशिश करें."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-hr/strings.xml b/service/res/values-mcc310-mnc004-hr/strings.xml deleted file mode 100644 index b1b207565..000000000 --- a/service/res/values-mcc310-mnc004-hr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : ne možete se povezati s Wi-Fi pristupom Verizonu izvan područja pokrivenosti Verizona."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : niste pretplaćeni na Wi-Fi pristup Verizonu. Nazovite nas na telefonski broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : postoji problem s vašim računom za Wi-Fi pristup Verizonu. Nazovite nas na telefonski broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : već ste povezani s Wi-Fi pristupom Verizonu."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : postoji problem s povezivanjem s Wi-Fi pristupom Verizonu. Nazovite nas na telefonski broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : postoji problem s vašim računom za Wi-Fi pristup Verizonu. Nazovite nas na telefonski broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Wi-Fi pristup Verizonu nije dostupan s vaše lokacije. Pokušajte ponovno kasnije ili s druge lokacije."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-hu/strings.xml b/service/res/values-mcc310-mnc004-hu/strings.xml deleted file mode 100644 index 21c7cc073..000000000 --- a/service/res/values-mcc310-mnc004-hu/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: Nem kapcsolódhat a Verizon Wi-Fi-hozzáférési szolgáltatásához a Verizon lefedettségi területén kívülről."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Nem fizetett elő a Verizon Wi-Fi-hozzáférési szolgáltatására. Hívjon minket a következő telefonszámon: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: Valami gond van Verizon Wi-Fi-hozzáférési fiókjával. Hívjon minket a következő telefonszámon: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: Már kapcsolódott a Verizon Wi-Fi-hozzáférési szolgáltatásához."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Valami probléma történt a Verizon Wi-Fi-hozzáférési szolgáltatásához való kapcsolódás során. Hívjon minket a következő telefonszámon: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: Valami gond van Verizon Wi-Fi-hozzáférési fiókjával. Hívjon minket a következő telefonszámon: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: A Verizon Wi-Fi-hozzáférési szolgáltatása nem áll rendelkezésre az Ön tartózkodási helyén. Próbálja újra, vagy próbáljon meg máshol csatlakozni."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-hy/strings.xml b/service/res/values-mcc310-mnc004-hy/strings.xml deleted file mode 100644 index 6a98ac36b..000000000 --- a/service/res/values-mcc310-mnc004-hy/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> – Դուք չեք կարող միանալ Verizon Wi-Fi Access-ին, երբ Verizon-ի ծածկույթից դուրս եք։"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> – Դուք բաժանորդագրված չեք Verizon Wi-Fi Access-ին։ Զանգեք մեզ 800-922-0204 հեռախոսահամարով։"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> – Ձեր Verizon Wi-Fi Access հաշվի հետ կապված խնդիր կա։ Զանգեք մեզ 800-922-0204 հեռախոսահամարով։"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> – Դուք արդեն միացած եք Verizon Wi-Fi Access-ին։"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> – Verizon Wi-Fi Access-ին միանալու հետ կապված խնդիր կա։ Զանգեք մեզ 800-922-0204 հեռախոսահամարով։"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> – Ձեր Verizon Wi-Fi Access հաշվի հետ կապված խնդիր կա։ Զանգեք մեզ 800-922-0204 հեռախոսահամարով։"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> – Verizon Wi-Fi Access-ը հասանելի չէ ձեր գտնվելու վայրից։ Փորձեք ավելի ուշ կամ մեկ այլ վայրից։"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-in/strings.xml b/service/res/values-mcc310-mnc004-in/strings.xml deleted file mode 100644 index 24d9a5c07..000000000 --- a/service/res/values-mcc310-mnc004-in/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Anda tidak dapat terhubung ke Akses Wi-Fi Verizon dari luar area cakupan Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Anda tidak berlangganan Akses Wi-Fi Verizon. Harap hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Ada masalah dengan akun Akses Wi-Fi Verizon Anda. Harap hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Anda sudah terhubung ke Akses Wi-Fi Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Terjadi masalah saat menghubungkan ke Akses Wi-Fi Verizon Anda. Harap hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Ada masalah dengan akun Akses Wi-Fi Verizon Anda. Harap hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Akses Wi-Fi Verizon tidak tersedia di lokasi Anda. Coba lagi nanti atau coba dari lokasi yang berbeda."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-is/strings.xml b/service/res/values-mcc310-mnc004-is/strings.xml deleted file mode 100644 index b09092e1c..000000000 --- a/service/res/values-mcc310-mnc004-is/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Ekki er hægt að tengjast Verizon Wi-Fi Access utan þjónustusvæðis Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Þú ert ekki áskrifandi að Verizon Wi-Fi Access. Hringdu í okkur í síma 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Vandamál kom upp í tengslum við Verizon Wi-Fi Access reikninginn þinn. Hringdu í okkur í síma 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Þú ert nú þegar tengd(ur) við Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Vandamál kom upp við að tengja þig við Verizon Wi-Fi Access. Hringdu í okkur í síma 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Vandamál kom upp í tengslum við Verizon Wi-Fi Access reikninginn þinn. Hringdu í okkur í síma 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access er ekki í boði þar sem þú ert. Reyndu aftur síðar eða á öðrum stað."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-it/strings.xml b/service/res/values-mcc310-mnc004-it/strings.xml deleted file mode 100644 index aadc15d6c..000000000 --- a/service/res/values-mcc310-mnc004-it/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: non puoi connetterti a Verizon Wi-Fi Access se sei fuori dell\'area di copertura Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: non hai un abbonamento a Verizon Wi-Fi Access. Chiamaci al numero 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: si è verificato un problema con il tuo account Verizon Wi-Fi Access. Chiamaci al numero 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: connessione a Verizon Wi-Fi Access già stabilita."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: si è verificato un problema di connessione a Verizon Wi-Fi Access. Chiamaci al numero 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: si è verificato un problema con il tuo account Verizon Wi-Fi Access. Chiamaci al numero 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access non è disponibile dalla tua posizione. Riprova più tardi o prova da un\'altra posizione."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-iw/strings.xml b/service/res/values-mcc310-mnc004-iw/strings.xml deleted file mode 100644 index 5dab7b8e4..000000000 --- a/service/res/values-mcc310-mnc004-iw/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : לא ניתן להתחבר לגישת Wi-Fi של Verizon מחוץ לאזור הכיסוי של Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : לא נרשמת לגישת Wi-Fi של Verizon. עליך להתקשר אלינו למספר 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : יש בעיה עם החשבון שלך לגישת Wi-Fi של Verizon. עליך להתקשר אלינו למספר 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : כבר יש לך חיבור לגישת Wi-Fi של Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : יש בעיה בהתחברות לגישת Wi-Fi של Verizon. עליך להתקשר אלינו למספר 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : יש בעיה עם החשבון שלך לגישת Wi-Fi של Verizon. עליך להתקשר אלינו למספר 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : גישת Wi-Fi של Verizon לא זמינה מהמיקום שלך. אפשר לנסות שוב מאוחר יותר או לנסות ממיקום אחר."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ja/strings.xml b/service/res/values-mcc310-mnc004-ja/strings.xml deleted file mode 100644 index 0a27df759..000000000 --- a/service/res/values-mcc310-mnc004-ja/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon のサービスエリア外から Verizon Wi-Fi Access に接続することはできません。"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access に登録されていません。800-922-0204 までお電話でお問い合わせください。"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: お使いの Verizon Wi-Fi Access アカウントに問題があります。800-922-0204 までお電話でお問い合わせください。"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access にすでに接続しています。"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access への接続中に問題が発生しました。800-922-0204 までお電話でお問い合わせください。"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: お使いの Verizon Wi-Fi Access アカウントに問題があります。800-922-0204 までお電話でお問い合わせください。"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: 現在地では Verizon Wi-Fi Access はご利用いただけません。しばらくしてからもう一度お試しいただくか、場所を変えてお試しください。"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ka/strings.xml b/service/res/values-mcc310-mnc004-ka/strings.xml deleted file mode 100644 index b601efb9e..000000000 --- a/service/res/values-mcc310-mnc004-ka/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access-ს ვერ დაუკავშირდებით Verizon-ის დაფარვის ზონის გარეთ."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access გამოწერილი არ გაქვთ. გთხოვთ, დაგვირეკოთ ტელეფონზე 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: თქვენს Verizon Wi-Fi Access ანგარიშთან დაკავშირებით პრობლემა წარმოიშვა. გთხოვთ, დაგვირეკოთ ტელეფონზე 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: თქვენ უკვე დაკავშირებული ხართ Verizon Wi-Fi Access-თან."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access-თან დაკავშირებისას პრობლემა წარმოიშვა. გთხოვთ, დაგვირეკოთ ტელეფონზე 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: თქვენს Verizon Wi-Fi Access ანგარიშთან დაკავშირებით პრობლემა წარმოიშვა. გთხოვთ, დაგვირეკოთ ტელეფონზე 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access თქვენი მდებარეობიდან მიუწვდომელია. ცადეთ მოგვიანებით ან ცადეთ სხვა მდებარეობიდან."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-kk/strings.xml b/service/res/values-mcc310-mnc004-kk/strings.xml deleted file mode 100644 index 660fd679c..000000000 --- a/service/res/values-mcc310-mnc004-kk/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қызметіне Verizon қызмет көрсету аясынан тыс жерден қосыла алмайсыз."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қызметіне жазылған жоқсыз. Бізге 800-922-0204 нөмірі арқылы хабарласыңыз."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access есептік жазбасына қатысты мәселе шықты. Бізге 800-922-0204 нөмірі арқылы хабарласыңыз."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қызметіне әлдеқашан қосылғансыз."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қызметіне қосылу кезінде мәселе шықты. Бізге 800-922-0204 нөмірі арқылы хабарласыңыз."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access есептік жазбасына қатысты мәселе шықты. Бізге 800-922-0204 нөмірі арқылы хабарласыңыз."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қазіргі орналасқан жеріңізде жұмыс істемейді. Әрекетті кейінірек немесе басқа жерден қайталап көріңіз."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-km/strings.xml b/service/res/values-mcc310-mnc004-km/strings.xml deleted file mode 100644 index e29a0e3ca..000000000 --- a/service/res/values-mcc310-mnc004-km/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>៖ អ្នកមិនអាចភ្ជាប់ទៅការចូលប្រើ Wi-Fi របស់ Verizon ពីក្រៅតំបន់គ្រប់ដណ្ដប់របស់ Verizon បានទេ។"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>៖ អ្នកមិនបានជាវការចូលប្រើ Wi-Fi របស់ Verizon ទេ។ សូមហៅទូរសព្ទមកយើងតាមរយៈលេខ 800-922-0204។"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>៖ មានបញ្ហាជាមួយគណនីចូលប្រើ Wi-Fi របស់ Verizon របស់អ្នក។ សូមហៅទូរសព្ទមកយើងតាមរយៈលេខ 800-922-0204។"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>៖ អ្នកបានភ្ជាប់ទៅការចូលប្រើ Wi-Fi របស់ Verizon រួចហើយ។"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>៖ មានបញ្ហាក្នុងការភ្ជាប់អ្នកទៅការចូលប្រើ Wi-Fi របស់ Verizon។ សូមហៅទូរសព្ទមកយើងតាមរយៈលេខ 800-922-0204។"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>៖ មានបញ្ហាជាមួយគណនីចូលប្រើ Wi-Fi របស់ Verizon របស់អ្នក។ សូមហៅទូរសព្ទមកយើងតាមរយៈលេខ 800-922-0204។"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>៖ មិនអាចប្រើការចូលប្រើ Wi-Fi របស់ Verizon ពីទីតាំងរបស់អ្នកបានទេ។ សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ ឬសាកល្បងពីទីតាំងផ្សេង។"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-kn/strings.xml b/service/res/values-mcc310-mnc004-kn/strings.xml deleted file mode 100644 index fcda7bbfb..000000000 --- a/service/res/values-mcc310-mnc004-kn/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon ಕವರೇಜ್ ಪ್ರದೇಶದ ಹೊರಗಿನಿಂದ Verizon ವೈ-ಫೈ ಪ್ರವೇಶಕ್ಕೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ನಿಮಗೆ ಸಾಧ್ಯವಿಲ್ಲ."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : ನೀವು Verizon ವೈ-ಫೈ ಪ್ರವೇಶಕ್ಕೆ ಸಬ್ಸ್ಕ್ರೈಬ್ ಆಗಿಲ್ಲ. ನಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸಲು 800-922-0204 ಗೆ ಕರೆ ಮಾಡಿ."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : ನಿಮ್ಮ Verizon ವೈ-ಫೈ ಪ್ರವೇಶ ಖಾತೆಯಲ್ಲಿ ಸಮಸ್ಯೆಯಿದೆ. ನಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸಲು 800-922-0204 ಗೆ ಕರೆ ಮಾಡಿ."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : ನೀವು ಈಗಾಗಲೇ Verizon ವೈ-ಫೈ ಪ್ರವೇಶಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಿರುವಿರಿ."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon ವೈ-ಫೈ ಪ್ರವೇಶಕ್ಕೆ ನಿಮ್ಮನ್ನು ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗುತ್ತಿದೆ. ನಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸಲು 800-922-0204 ಗೆ ಕರೆ ಮಾಡಿ."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : ನಿಮ್ಮ Verizon ವೈ-ಫೈ ಪ್ರವೇಶ ಖಾತೆಯಲ್ಲಿ ಸಮಸ್ಯೆಯಿದೆ. ನಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸಲು 800-922-0204 ಗೆ ಕರೆ ಮಾಡಿ."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : ನಿಮ್ಮ ಸ್ಥಳದಿಂದ Verizon ವೈ-ಫೈ ಪ್ರವೇಶ ಲಭ್ಯವಿಲ್ಲ. ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ ಅಥವಾ ಬೇರೊಂದು ಸ್ಥಳದಿಂದ ಪ್ರಯತ್ನಿಸಿ."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ko/strings.xml b/service/res/values-mcc310-mnc004-ko/strings.xml deleted file mode 100644 index 6aa3855e3..000000000 --- a/service/res/values-mcc310-mnc004-ko/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon 서비스 지역 외부에서는 Verizon Wi-Fi Access에 연결할 수 없습니다."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access를 구독 중이 아닙니다. 800-922-0204번으로 문의하세요."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access 계정에 문제가 있습니다. 800-922-0204번으로 문의하세요."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: 이미 Verizon Wi-Fi Access에 연결되어 있습니다."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access에 연결하는 중에 문제가 발생했습니다. 800-922-0204번으로 문의하세요."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access 계정에 문제가 있습니다. 800-922-0204번으로 문의하세요."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: 해당 위치에서는 Verizon Wi-Fi Access를 이용할 수 없습니다. 나중에 다시 시도하거나 다른 장소에서 시도해 보세요."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ky/strings.xml b/service/res/values-mcc310-mnc004-ky/strings.xml deleted file mode 100644 index 913e93870..000000000 --- a/service/res/values-mcc310-mnc004-ky/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ке Verizon иштеген аймактан сырткары жерде туташа албайсыз."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ке катталган эмессиз. 800-922-0204 номерине телефон чалыңыз."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access аккаунтуңузда маселе келип чыкты. 800-922-0204 номерине телефон чалыңыз."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ке туташып турасыз."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ке туташууда маселе келип чыкты. 800-922-0204 номерине телефон чалыңыз."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access аккаунтуңузда маселе келип чыкты. 800-922-0204 номерине телефон чалыңыз."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access сиз жүргөн жерде жеткиликтүү эмес. Кийинчерээк же башка жерден кайталаңыз."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-lo/strings.xml b/service/res/values-mcc310-mnc004-lo/strings.xml deleted file mode 100644 index 0a9ede1dc..000000000 --- a/service/res/values-mcc310-mnc004-lo/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : ທ່ານບໍ່ສາມາດເຊື່ອມຕໍ່ຫາ Verizon Wi-Fi Access ຈາກນອກພື້ນທີ່ຄອບຄຸມ Verizon ໄດ້."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : ທ່ານບໍ່ໄດ້ສະໝັກໃຊ້ Verizon Wi-Fi Access. ກະລຸນາໂທຫາພວກເຮົາທີ່ເບີ 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : ເກີດບັນຫາກັບບັນຊີ Verizon Wi-Fi Access ຂອງທ່ານ. ກະລຸນາໂທຫາພວກເຮົາທີ່ເບີ 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : ທ່ານເຊື່ອມຕໍ່ຫາ Verizon Wi-Fi Access ຢູ່ກ່ອນແລ້ວ."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : ເກີດບັນຫາໃນການເຊື່ອມຕໍ່ທ່ານຫາ Verizon Wi-Fi Access. ກະລຸນາໂທຫາພວກເຮົາທີ່ເບີ 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : ເກີດບັນຫາກັບບັນຊີ Verizon Wi-Fi Access ຂອງທ່ານ. ກະລຸນາໂທຫາພວກເຮົາທີ່ເບີ 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : ບໍ່ສາມາດໃຊ້ Verizon Wi-Fi Access ຈາກສະຖານທີ່ຂອງທ່ານໄດ້. ກະລຸນາລອງໃໝ່ ຫຼື ລອງຈາກສະຖານທີ່ອື່ນ."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-lt/strings.xml b/service/res/values-mcc310-mnc004-lt/strings.xml deleted file mode 100644 index 6852c5289..000000000 --- a/service/res/values-mcc310-mnc004-lt/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: negalite prisijungti prie „Verizon“ „Wi-Fi“ prieigos taško būdami ne „Verizon“ aprėpties zonoje."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: neprenumeruojate „Verizon“ „Wi-Fi“ prieigos taško. Paskambinkite telefono numeriu 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: iškilo su „Verizon“ „Wi-Fi“ prieigos taško paskyra susijusi problema. Paskambinkite telefono numeriu 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: jau esate prisijungę prie „Verizon“ „Wi-Fi“ prieigos taško."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: prisijungiant prie „Verizon“ „Wi-Fi“ prieigos taško kilo problema. Paskambinkite telefono numeriu 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: iškilo su „Verizon“ „Wi-Fi“ prieigos taško paskyra susijusi problema. Paskambinkite telefono numeriu 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: „Verizon“ „Wi-Fi“ prieigos taškas nepasiekiamas iš jūsų vietovės. Vėliau bandykite dar kartą arba pabandykite iš kitos vietovės."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-lv/strings.xml b/service/res/values-mcc310-mnc004-lv/strings.xml deleted file mode 100644 index acf8ea54c..000000000 --- a/service/res/values-mcc310-mnc004-lv/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: lai izveidotu savienojumu ar pakalpojumu Verizon Wi-Fi Access, ir jābūt Verizon pārklājuma zonā."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: jums nav Verizon Wi-Fi Access abonementa. Lūdzu, zvaniet mums uz numuru 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: radusies problēma ar jūsu Verizon Wi-Fi Access kontu. Lūdzu, zvaniet mums uz numuru 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: savienojums ar Verizon Wi-Fi Access jau ir izveidots."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: veidojot savienojumu ar pakalpojumu Verizon Wi-Fi Access, radās problēma. Lūdzu, zvaniet mums uz numuru 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: radusies problēma ar jūsu Verizon Wi-Fi Access kontu. Lūdzu, zvaniet mums uz numuru 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: jūsu atrašanās vietā pakalpojums Verizon Wi-Fi Access nav pieejams. Vēlāk mēģiniet vēlreiz, vai arī mēģiniet izveidot savienojumu no citas atrašanās vietas."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-mk/strings.xml b/service/res/values-mcc310-mnc004-mk/strings.xml deleted file mode 100644 index 0bae4f25b..000000000 --- a/service/res/values-mcc310-mnc004-mk/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: не може да се поврзете на Verizon Wi-Fi Access надвор од областа на покривање на Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: не сте претплатени на Verizon Wi-Fi Access. Контактирајте со нас на 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: проблем со вашата сметка на Verizon Wi-Fi Access. Контактирајте со нас на 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: веќе сте поврзани на Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: наидовме на проблем при обидот да ве поврземе на Verizon Wi-Fi Access. Контактирајте со нас на 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: проблем со вашата сметка на Verizon Wi-Fi Access. Контактирајте со нас на 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access не е достапна од вашата локација. Обидете повторно подоцна или обидете се од друга локација."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ml/strings.xml b/service/res/values-mcc310-mnc004-ml/strings.xml deleted file mode 100644 index 20f2d365c..000000000 --- a/service/res/values-mcc310-mnc004-ml/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon കവറേജ് ഏരിയയ്ക്ക് പുറത്ത് നിന്ന് നിങ്ങൾക്ക് Verizon വൈഫൈ ആക്സസിലേക്ക് കണക്റ്റ് ചെയ്യാനാകില്ല."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon വൈഫൈ ആക്സസിലേക്ക് നിങ്ങൾ സബ്സ്ക്രൈബ് ചെയ്തിട്ടില്ല. ഞങ്ങളുടെ 800-922-0204 എന്ന നമ്പറിൽ വിളിക്കുക."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : നിങ്ങളുടെ Verizon വൈഫൈ ആക്സസ് അക്കൗണ്ടുമായി ബന്ധപ്പെട്ട് ഒരു പ്രശ്നമുണ്ട്. ഞങ്ങളുടെ 800-922-0204 എന്ന നമ്പറിൽ വിളിക്കുക."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : നിങ്ങൾ മുമ്പേ തന്നെ Verizon വൈഫൈ ആക്സസിലേക്ക് കണക്റ്റ് ചെയ്തിട്ടുണ്ട്."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon വൈഫൈ ആക്സസ് അക്കൗണ്ടിലേക്ക് നിങ്ങളെ കണക്റ്റ് ചെയ്യുന്നതിൽ ഒരു പ്രശ്നമുണ്ട്. ഞങ്ങളുടെ 800-922-0204 എന്ന നമ്പറിൽ വിളിക്കുക."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : നിങ്ങളുടെ Verizon വൈഫൈ ആക്സസ് അക്കൗണ്ടുമായി ബന്ധപ്പെട്ട് ഒരു പ്രശ്നമുണ്ട്. ഞങ്ങളുടെ 800-922-0204 എന്ന നമ്പറിൽ വിളിക്കുക."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon വൈഫൈ ആക്സസ് നിങ്ങളുടെ ലൊക്കേഷനില് ലഭ്യമല്ല. മറ്റൊരു ലൊക്കേഷനിൽ നിന്ന് പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-mn/strings.xml b/service/res/values-mcc310-mnc004-mn/strings.xml deleted file mode 100644 index 76d92ec91..000000000 --- a/service/res/values-mcc310-mnc004-mn/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Та Verizon-ы хамрах бүсийн гаднаас Verizon Wi-Fi хандалтад холбогдох боломжгүй."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Та Verizon Wi-Fi хандалтад бүртгүүлээгүй байна. 800-922-0204 дугаар луу залгаж, бидэнтэй холбогдоно уу."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Таны Verizon Wi-Fi хандалтын бүртгэлтэй холбоотой асуудал гарлаа. 800-922-0204 дугаар луу залгаж, бидэнтэй холбогдоно уу."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Та Verizon Wi-Fi хандалтад хэдийн холбогдсон байна."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Таныг Verizon Wi-Fi хандалтад холбоход асуудал гарлаа. 800-922-0204 дугаар луу залгаж, бидэнтэй холбогдоно уу."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Таны Verizon Wi-Fi хандалтын бүртгэлтэй холбоотой асуудал гарлаа. 800-922-0204 дугаар луу залгаж, бидэнтэй холбогдоно уу."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi хандалт нь таны байршлаас боломжгүй байна. Дараа дахин оролдох эсвэл өөр байршлаас оролдоно уу."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-mr/strings.xml b/service/res/values-mcc310-mnc004-mr/strings.xml deleted file mode 100644 index 5c7404a99..000000000 --- a/service/res/values-mcc310-mnc004-mr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : तुम्ही व्हेरिझॉन कव्हरेज क्षेत्राच्या बाहेरून व्हेरिझॉन वाय-फाय अॅक्सेस शी कनेक्ट करू शकत नाही."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : तुम्ही व्हेरिझॉन वाय-फाय अॅक्सेस चे सदस्यत्व घेतलेले नाही. कृपया आम्हाला ८००-९२२-०२०४ वर कॉल करा."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : तुमच्या व्हेरिझॉन वाय-फाय अॅक्सेस खात्यामध्ये समस्या आहे. कृपया आम्हाला ८००-९२२-०२०४ वर कॉल करा."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : तुम्ही आधीपासून व्हेरिझॉन वाय-फाय अॅक्सेस शी कनेक्ट केलेले आहे."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : तुम्हाला व्हेरिझॉन वाय-फाय अॅक्सेस शी कनेक्ट करण्यात समस्या आहे. कृपया आम्हाला ८००-९२२-०२०४ वर कॉल करा."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : तुमच्या व्हेरिझॉन वाय-फाय अॅक्सेस खात्यामध्ये समस्या आहे. कृपया आम्हाला ८००-९२२-०२०४ वर कॉल करा."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : तुमच्या स्थानावरून व्हेरिझॉन वाय-फाय अॅक्सेस उपलब्ध नाही. नंतर पुन्हा प्रयत्न करा किंवा वेगळ्या स्थानावरून प्रयत्न करा."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ms/strings.xml b/service/res/values-mcc310-mnc004-ms/strings.xml deleted file mode 100644 index ce765e088..000000000 --- a/service/res/values-mcc310-mnc004-ms/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Anda tidak boleh menyambung ke Verizon Wi-Fi Access dari luar kawasan liputan Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Anda tidak melanggan Verizon Wi-Fi Access. Sila hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Terdapat masalah dengan akaun Verizon Wi-Fi Access anda. Sila hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Anda sudah disambungkan ke Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Terdapat masalah semasa menyambungkan anda ke Verizon Wi-Fi Access. Sila hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Terdapat masalah dengan akaun Verizon Wi-Fi Access anda. Sila hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access tidak tersedia dari lokasi anda. Cuba lagi nanti atau cuba dari lokasi lain."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-my/strings.xml b/service/res/values-mcc310-mnc004-my/strings.xml deleted file mode 100644 index a367ce5bf..000000000 --- a/service/res/values-mcc310-mnc004-my/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> - Verizon ဝန်ဆောင်မှုမရှိသည့်နေရာမှနေ၍ Verizon Wi-Fi Access သို့ ချိတ်ဆက်၍မရပါ။"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> - သင်သည် Verizon Wi-Fi Access သို့ စာရင်းသွင်းမထားပါ။ ၈၀၀-၉၂၂-၀၂၀၄ ကို ခေါ်ပါ။"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> - သင့် Verizon Wi-Fi Access အကောင့်တွင် ပြဿနာရှိနေသည်။ ၈၀၀-၉၂၂-၀၂၀၄ ကို ခေါ်ပါ။"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> - သင်သည် Verizon Wi-Fi Access သို့ ချိတ်ဆက်ထားပြီးဖြစ်သည်။"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> - Verizon Wi-Fi Access သို့ ချိတ်ဆက်ရာတွင် ပြဿနာရှိနေသည်။ ၈၀၀-၉၂၂-၀၂၀၄ ကို ခေါ်ပါ။"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> - သင့် Verizon Wi-Fi Access အကောင့်တွင် ပြဿနာရှိနေသည်။ ၈၀၀-၉၂၂-၀၂၀၄ ကို ခေါ်ပါ။"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> - သင့်တည်နေရာတွင် Verizon Wi-Fi Access မရနိုင်ပါ။ နောက်မှထပ်စမ်းကြည့်ပါ သို့မဟုတ် အခြားတည်နေရာမှနေ၍ စမ်းကြည့်ပါ။"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-nb/strings.xml b/service/res/values-mcc310-mnc004-nb/strings.xml deleted file mode 100644 index 85c0d6ebb..000000000 --- a/service/res/values-mcc310-mnc004-nb/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Du kan ikke koble til Verizon Wi-Fi Access fra utenfor Verizons dekningsområde."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Du abonnerer ikke på Verizon Wi-Fi Access. Ring oss på 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Det har oppstått et problem med Verizon Wi-Fi Access-kontoen din. Ring oss på 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Du er allerede koblet til Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Det har oppstått et problem med å koble deg til Verizon Wi-Fi Access. Ring oss på 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Det har oppstått et problem med Verizon Wi-Fi Access-kontoen din. Ring oss på 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access er ikke tilgjengelig fra der du er. Prøv igjen senere, eller prøv fra et annet sted."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ne/strings.xml b/service/res/values-mcc310-mnc004-ne/strings.xml deleted file mode 100644 index 51694fb1d..000000000 --- a/service/res/values-mcc310-mnc004-ne/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईं Verizon कभरेज क्षेत्र बाहिरबाट Verizon Wi-Fi Access मा जोडिन सक्नुहुन्न।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईंले Verizon Wi-Fi Access को सदस्यता लिनुभएको छैन। कृपया 800-922-0204 मा फोन गर्नुहोस्।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईंको Verizon Wi-Fi Access खातामा कुनै समस्या छ। कृपया 800-922-0204 मा फोन गर्नुहोस्।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईं अहिले Verizon Wi-Fi Access मा नै जोडिनुभएको छ।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईंलाई Verizon Wi-Fi Access मा जोड्ने क्रममा कुनै समस्या भयो। कृपया 800-922-0204 मा फोन गर्नुहोस्।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईंको Verizon Wi-Fi Access खातामा कुनै समस्या छ। कृपया 800-922-0204 मा फोन गर्नुहोस्।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईं रहेको स्थानमा Verizon Wi-Fi Access उपलब्ध छैन। पछि फेरि प्रयास गर्नुहोस् वा अर्को स्थानमा गएर जोडिने प्रयास गर्नुहोस्।"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-nl/strings.xml b/service/res/values-mcc310-mnc004-nl/strings.xml deleted file mode 100644 index 993fdc822..000000000 --- a/service/res/values-mcc310-mnc004-nl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: Je kunt buiten het dekkingsgebied van Verizon geen verbinding maken met Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Je hebt geen abonnement op Verizon Wi-Fi Access. Bel ons op 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: Er is een probleem met je Verizon Wi-Fi Access-account. Bel ons op 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: Je hebt al verbinding met Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Er is een probleem bij het maken van verbinding met Verizon Wi-Fi Access. Bel ons op 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: Er is een probleem met je Verizon Wi-Fi Access-account. Bel ons op 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access is niet beschikbaar op jouw locatie. Probeer het later opnieuw of ga naar een andere locatie."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-or/strings.xml b/service/res/values-mcc310-mnc004-or/strings.xml deleted file mode 100644 index e608ebc7e..000000000 --- a/service/res/values-mcc310-mnc004-or/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣ Verizon କଭରେଜ୍ କ୍ଷେତ୍ର ବାହାରେ Verizon Wi-Fi Access ସହ ସଂଯୋଗ କରିପାରିବେ ନାହିଁ।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣ Verizon Wi-Fi Accessର ସଦସ୍ୟତା ନେଇ ନାହାଁନ୍ତି। ଦୟାକରି 800-922-0204ରେ ଆମକୁ କଲ୍ କରନ୍ତୁ।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣଙ୍କ Verizon Wi-Fi Access ଆକାଉଣ୍ଟରେ ଏକ ସମସ୍ୟା ହୋଇଛି। ଦୟାକରି 800-922-0204ରେ ଆମକୁ କଲ୍ କରନ୍ତୁ।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣ ପୂର୍ବରୁ Verizon Wi-Fi Access ସହ ସଂଯୋଗ କରିସାରିଛନ୍ତି।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣଙ୍କୁ Verizon Wi-Fi Access ସହ ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଦୟାକରି 800-922-0204ରେ ଆମକୁ କଲ୍ କରନ୍ତୁ।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣଙ୍କ Verizon Wi-Fi Access ଆକାଉଣ୍ଟରେ ଏକ ସମସ୍ୟା ହୋଇଛି। ଦୟାକରି 800-922-0204ରେ ଆମକୁ କଲ୍ କରନ୍ତୁ।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ଆପଣଙ୍କ ଲୋକେସନରେ ଉପଲବ୍ଧ ନାହିଁ। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ କିମ୍ବା ଏକ ଭିନ୍ନ ଲୋକେସନରୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-pa/strings.xml b/service/res/values-mcc310-mnc004-pa/strings.xml deleted file mode 100644 index 56260be4d..000000000 --- a/service/res/values-mcc310-mnc004-pa/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਸੀਂ Verizon ਕਵਰੇਜ ਖੇਤਰ ਤੋਂ ਬਾਹਰ Verizon Wi-Fi Access ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਸੀਂ Verizon Wi-Fi Access ਲਈ ਗਾਹਕੀ ਨਹੀਂ ਲਈ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ 800-922-0204 \'ਤੇ ਕਾਲ ਕਰੋ।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਹਾਡੇ Verizon Wi-Fi Access ਖਾਤੇ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ 800-922-0204 \'ਤੇ ਕਾਲ ਕਰੋ।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਸੀਂ ਪਹਿਲਾਂ ਤੋਂ ਹੀ Verizon Wi-Fi Access ਨਾਲ ਕਨੈਕਟ ਹੋ।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਹਾਨੂੰ Verizon Wi-Fi Access ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ 800-922-0204 \'ਤੇ ਕਾਲ ਕਰੋ।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਹਾਡੇ Verizon Wi-Fi Access ਖਾਤੇ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ 800-922-0204 \'ਤੇ ਕਾਲ ਕਰੋ।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਤੋਂ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜਾਂ ਕਿਸੇ ਹੋਰ ਟਿਕਾਣੇ ਤੋਂ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-pl/strings.xml b/service/res/values-mcc310-mnc004-pl/strings.xml deleted file mode 100644 index 0321a08ee..000000000 --- a/service/res/values-mcc310-mnc004-pl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : nie możesz połączyć się z Wi-Fi Verizon poza obszarem obsługiwanym przez Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : nie subskrybujesz Wi-Fi Verizon. Zadzwoń pod numer +1 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : wystąpił problem z Twoim kontem Wi-Fi Verizon. Zadzwoń pod numer +1 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : już jesteś połączony z Wi-Fi Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : wystąpił problem z połączeniem z Wi-Fi Verizon. Zadzwoń pod numer +1 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : wystąpił problem z Twoim kontem Wi-Fi Verizon. Zadzwoń pod numer +1 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Wi-Fi Verizon jest niedostępne w Twojej lokalizacji. Spróbuj ponownie później lub z innej lokalizacji."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-pt-rBR/strings.xml b/service/res/values-mcc310-mnc004-pt-rBR/strings.xml deleted file mode 100644 index 540f81d80..000000000 --- a/service/res/values-mcc310-mnc004-pt-rBR/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: não é possível se conectar ao Verizon Wi-Fi Access fora da área de cobertura."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: você não se inscreveu no Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema com sua conta do Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: você já se conectou ao Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema na conexão com o Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema com sua conta do Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: o Verizon Wi-Fi Access não está disponível neste local. Tente novamente mais tarde ou de um local diferente."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-pt-rPT/strings.xml b/service/res/values-mcc310-mnc004-pt-rPT/strings.xml deleted file mode 100644 index abe379522..000000000 --- a/service/res/values-mcc310-mnc004-pt-rPT/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: não é possível estabelecer ligação ao ponto de acesso Wi-Fi da Verizon fora da área de cobertura da Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: não possui uma subscrição do ponto de acesso Wi-Fi da Verizon. Contacte-nos através do número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: existe um problema com a sua conta do ponto de acesso Wi-Fi da Verizon. Contacte-nos através do número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: já tem ligação ao ponto de acesso Wi-Fi da Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: ocorreu um problema ao estabelecer ligação ao ponto de acesso Wi-Fi da Verizon. Contacte-nos através do número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: existe um problema com a sua conta do ponto de acesso Wi-Fi da Verizon. Contacte-nos através do número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: o ponto de acesso Wi-Fi da Verizon não está disponível a partir da sua localização. Tente novamente mais tarde ou experimente a partir de uma localização diferente."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-pt/strings.xml b/service/res/values-mcc310-mnc004-pt/strings.xml deleted file mode 100644 index 540f81d80..000000000 --- a/service/res/values-mcc310-mnc004-pt/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: não é possível se conectar ao Verizon Wi-Fi Access fora da área de cobertura."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: você não se inscreveu no Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema com sua conta do Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: você já se conectou ao Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema na conexão com o Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema com sua conta do Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: o Verizon Wi-Fi Access não está disponível neste local. Tente novamente mais tarde ou de um local diferente."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ro/strings.xml b/service/res/values-mcc310-mnc004-ro/strings.xml deleted file mode 100644 index e663bd6df..000000000 --- a/service/res/values-mcc310-mnc004-ro/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : nu vă puteți conecta la Verizon Wi-Fi Access în afara ariei de acoperire Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : nu v-ați abonat la Verizon Wi-Fi Access. Apelați-ne la 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : există o problemă legată de contul dvs. Verizon Wi-Fi Access. Apelați-ne la 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : v-ați conectat deja la Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : există o problemă legată de conectarea la Verizon Wi-Fi Access. Apelați-ne la 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : există o problemă legată de contul dvs. Verizon Wi-Fi Access. Apelați-ne la 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access nu este disponibil în locația dvs. Încercați din nou mai târziu sau încercați dintr-o altă locație."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ru/strings.xml b/service/res/values-mcc310-mnc004-ru/strings.xml deleted file mode 100644 index 9ae888a81..000000000 --- a/service/res/values-mcc310-mnc004-ru/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: вы не можете подключиться к сервису Verizon Wi-Fi Access вне зоны покрытия Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: вы не подписаны на сервис Verizon Wi-Fi Access. Позвоните нам по номеру 800 922-02-04."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: возникла проблема с вашим аккаунтом Verizon Wi-Fi Access. Позвоните нам по номеру 800 922-02-04."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: вы уже подключены к сервису Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: не удалось подключиться к сервису Verizon Wi-Fi Access. Позвоните нам по номеру 800 922-02-04."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: возникла проблема с вашим аккаунтом Verizon Wi-Fi Access. Позвоните нам по номеру 800 922-02-04."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: сервис Verizon Wi-Fi Access недоступен там, где вы находитесь. Повторите попытку позже или в другом месте."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-si/strings.xml b/service/res/values-mcc310-mnc004-si/strings.xml deleted file mode 100644 index 73d4f76e4..000000000 --- a/service/res/values-mcc310-mnc004-si/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon ආවරණ ප්රදේශයට පිටතින් ඔබට Verizon Wi-Fi ප්රවේශය වෙත සම්බන්ධ විය නොහැකිය."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබ Verizon Wi-Fi ප්රවේශය වෙත දායක වී නැත. කරුණාකර 800-922-0204 අංකයෙන් අපට අමතන්න."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබේ Verizon Wi-Fi ප්රවේශ ගිණුම හා ගැටලුවක් තිබේ. කරුණාකර 800-922-0204 අංකයෙන් අපට අමතන්න."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබ දැනටමත් Verizon Wi-Fi ප්රවේශය වෙත සම්බන්ධ වී ඇත."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබව Verizon Wi-Fi ප්රවේශය වෙත සම්බන්ධ කිරීමේ ගැටලුවක් තිබේ. කරුණාකර 800-922-0204 අංකයෙන් අපට අමතන්න."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබේ Verizon Wi-Fi ප්රවේශ ගිණුම හා ගැටලුවක් තිබේ. කරුණාකර 800-922-0204 අංකයෙන් අපට අමතන්න."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi ප්රවේශය ඔබේ ස්ථානය වෙතින් ලබා ගත නොහැකිය. පසුව නැවත උත්සාහ කරන්න නැතහොත් වෙනත් ස්ථානයකින් උත්සාහ කරන්න."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-sk/strings.xml b/service/res/values-mcc310-mnc004-sk/strings.xml deleted file mode 100644 index e6a8cc11a..000000000 --- a/service/res/values-mcc310-mnc004-sk/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : K službe Verizon Wi-Fi Access sa nemôžete pripojiť mimo oblasti, v ktorej Verizon poskytuje služby."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Službu Verizon Wi-Fi Access neodoberáte. Zavolajte na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Vyskytol sa problém s vaším účtom Verizon Wi-Fi Access. Zavolajte na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : K službe Verizon Wi-Fi Access ste sa už pripojili."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Pri pripájaní vášho účtu k službe Verizon Wi-Fi Access sa vyskytol problém. Zavolajte na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Vyskytol sa problém s vaším účtom Verizon Wi-Fi Access. Zavolajte na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access nie je k dispozícii vo vašej oblasti. Skúste to znova alebo pokus zopakujte v inej oblasti."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-sl/strings.xml b/service/res/values-mcc310-mnc004-sl/strings.xml deleted file mode 100644 index 4a23593b7..000000000 --- a/service/res/values-mcc310-mnc004-sl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: Povezave s storitvijo Verizon Wi-Fi Access ni mogoče vzpostaviti zunaj območja, ki ga pokriva operater Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Niste naročeni na storitev Verizon Wi-Fi Access. Pokličite nas na 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: Prišlo je do težave z vašim računom za storitev Verizon Wi-Fi Access. Pokličite nas na 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: Povezava s storitvijo Verizon Wi-Fi Access je že vzpostavljena."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Prišlo je do težave pri povezovanju s storitvijo Verizon Wi-Fi Access. Pokličite nas na 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: Prišlo je do težave z vašim računom za storitev Verizon Wi-Fi Access. Pokličite nas na 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Storitev Verizon Wi-Fi Access ni na voljo na vaši lokaciji. Poskusite znova pozneje ali z druge lokacije."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-sq/strings.xml b/service/res/values-mcc310-mnc004-sq/strings.xml deleted file mode 100644 index abf416fec..000000000 --- a/service/res/values-mcc310-mnc004-sq/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Nuk mund të lidhesh me Verizon Wi-Fi Access nga jashtë zonës së mbulimit të Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Nuk je abonuar në Verizon Wi-Fi Access. Na telefono në 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Ka një problem me llogarinë tënde të Verizon Wi-Fi Access. Na telefono në 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Je lidhur tashmë me Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Ka një problem gjatë lidhjes sate me Verizon Wi-Fi Access. Na telefono në 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Ka një problem me llogarinë tënde të Verizon Wi-Fi Access. Na telefono në 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access nuk ofrohet nga vendndodhja jote. Provo përsëri më vonë ose provo nga një vendndodhje tjetër."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-sr/strings.xml b/service/res/values-mcc310-mnc004-sr/strings.xml deleted file mode 100644 index 176e51bb0..000000000 --- a/service/res/values-mcc310-mnc004-sr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Не можете да се повежете на Verizon WiFi Access ван области коју Verizon покрива."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Нисте претплаћени на Verizon WiFi Access. Позовите нас на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon WiFi Access налогом. Позовите нас на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Већ сте повезани на Verizon WiFi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Постоји проблем при повезивању на Verizon WiFi Access. Позовите нас на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon WiFi Access налогом. Позовите нас на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon WiFi Access није доступан са ваше локације. Пробајте поново касније или пробајте са неке друге локације."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-sv/strings.xml b/service/res/values-mcc310-mnc004-sv/strings.xml deleted file mode 100644 index 1b315536c..000000000 --- a/service/res/values-mcc310-mnc004-sv/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Det går inte att ansluta till Verizon Wi-Fi Access om du befinner dig utanför Verizons täckningsområde."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Du prenumererar inte på Verizon Wi-Fi Access. Ring oss på 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Ett fel har uppstått i Verizon Wi-Fi Access-kontot. Ring oss på 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Du är redan ansluten till Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Det gick inte att ansluta till Verizon Wi-Fi Access. Ring oss på 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Ett fel har uppstått i Verizon Wi-Fi Access-kontot. Ring oss på 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access är inte tillgängligt där du befinner dig. Försök igen senare eller anslut från en annan plats."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-sw/strings.xml b/service/res/values-mcc310-mnc004-sw/strings.xml deleted file mode 100644 index e4b6d1990..000000000 --- a/service/res/values-mcc310-mnc004-sw/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Huwezi kuunganisha kwenye Ufikiaji wa Wi-Fi ya Verizon ukiwa nje ya eneo la mtandao wa Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Hujajisajili kwenye Ufikiaji wa Wi-Fi ya Verizon. Tafadhali tupigie kwa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Kuna hitilafu ya Akaunti yako ya Ufikiaji wa Wi-Fi ya Verizon. Tafadhali tupigie kwa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Tayari umeunganisha kwenye Ufikiaji wa Wi-Fi ya Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Kuna hitilafu ya kuunganisha kwenye Ufikiaji wa Wi-Fi ya Verizon. Tafadhali tupigie kwa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Kuna hitilafu ya Akaunti yako ya Ufikiaji wa Wi-Fi ya Verizon. Tafadhali tupigie kwa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Ufikiaji wa Wi-Fi ya Verizon haupatikani katika eneo lako. Jaribu tena baadaye au ujaribu ukiwa katika eneo tofauti."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ta/strings.xml b/service/res/values-mcc310-mnc004-ta/strings.xml deleted file mode 100644 index 9dacf26ee..000000000 --- a/service/res/values-mcc310-mnc004-ta/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon கவரேஜ் பகுதியைத் தாண்டி Verizon வைஃபை Accessஸுடன் இணைக்க முடியாது."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : நீங்கள் Verizon வைஃபை Accessஸிற்கு சந்தா செய்யவில்லை. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் Verizon வைஃபை Access கணக்கில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon வைஃபை Accessஸுடன் ஏற்கெனவே இணைப்பில் உள்ளீர்கள்."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon வைஃபை Accessஸுடன் இணைப்பதில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் Verizon வைஃபை Access கணக்கில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் பகுதிக்கு Verizon வைஃபை Access சேவை கிடைக்கவில்லை. மீண்டும் முயலவும் அல்லது வேறு இருப்பிடத்தில் இருந்து முயலவும்."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-te/strings.xml b/service/res/values-mcc310-mnc004-te/strings.xml deleted file mode 100644 index e7afb2b9b..000000000 --- a/service/res/values-mcc310-mnc004-te/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : మీరు Verizon కవరేజీ ప్రాంతానికి వెలుపల నుండి Verizon Wi-Fi యాక్సెస్కు కనెక్ట్ చేయలేరు."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : మీరు Verizon Wi-Fi యాక్సెస్కు సభ్యత్వం పొందలేదు. 800-922-0204 నంబర్ వద్ద దయచేసి మాకు కాల్ చేయండి."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : మీ Verizon Wi-Fi యాక్సెస్ ఖాతాలో సమస్య ఉంది. 800-922-0204 నంబర్ వద్ద దయచేసి మాకు కాల్ చేయండి."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : మీరు ఇప్పటికే Verizon Wi-Fi యాక్సెస్కు కనెక్ట్ చేయబడ్డారు."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi యాక్సెస్కు మిమ్మల్ని కనెక్ట్ చేయడంలో సమస్య ఉంది. 800-922-0204 నంబర్ వద్ద దయచేసి మాకు కాల్ చేయండి."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : మీ Verizon Wi-Fi యాక్సెస్ ఖాతాలో సమస్య ఉంది. 800-922-0204 నంబర్ వద్ద దయచేసి మాకు కాల్ చేయండి."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : మీ లొకేషన్ వద్ద Verizon Wi-Fi యాక్సెస్ అందుబాటులో లేదు. తర్వాత మళ్లీ ప్రయత్నించండి లేదా వేరే లొకేషన్ నుండి ప్రయత్నించండి."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-th/strings.xml b/service/res/values-mcc310-mnc004-th/strings.xml deleted file mode 100644 index 6f6367278..000000000 --- a/service/res/values-mcc310-mnc004-th/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : คุณเชื่อมต่อกับ Verizon Wi-Fi Access จากนอกพื้นที่ให้บริการของ Verizon ไม่ได้"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : คุณไม่ได้สมัครใช้บริการ Verizon Wi-Fi Access โปรดโทรหาเราที่ 800-922-0204"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : บัญชี Verizon Wi-Fi Access ของคุณมีปัญหา โปรดโทรหาเราที่ 800-922-0204"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : คุณเชื่อมต่อกับ Verizon Wi-Fi Access แล้ว"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : มีปัญหาในการเชื่อมต่อคุณกับ Verizon Wi-Fi Access โปรดโทรหาเราที่ 800-922-0204"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : บัญชี Verizon Wi-Fi Access ของคุณมีปัญหา โปรดโทรหาเราที่ 800-922-0204"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ไม่พร้อมให้บริการจากตำแหน่งของคุณ โปรดลองอีกครั้งในภายหลังหรือลองจากตำแหน่งอื่น"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-tl/strings.xml b/service/res/values-mcc310-mnc004-tl/strings.xml deleted file mode 100644 index 8dfee2fda..000000000 --- a/service/res/values-mcc310-mnc004-tl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Hindi ka puwedeng kumonekta sa Verizon Wi-Fi Access mula sa labas ng lugar na saklaw ng Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Hindi ka naka-subscribe sa Verizon Wi-Fi Access. Pakitawagan kami sa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : May problema sa iyong Verizon Wi-Fi Access account. Pakitawagan kami sa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Nakakonekta ka na sa Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : May problema sa pagkonekta sa iyo sa Verizon Wi-Fi Access. Pakitawagan kami sa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : May problema sa iyong Verizon Wi-Fi Access account. Pakitawagan kami sa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Hindi available sa iyong lokasyon ang Verizon Wi-Fi Access. Subukan ulit sa ibang pagkakataon o subukan mula sa ibang lokasyon."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-tr/strings.xml b/service/res/values-mcc310-mnc004-tr/strings.xml deleted file mode 100644 index a2ce4ad23..000000000 --- a/service/res/values-mcc310-mnc004-tr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon\'ın kapsama alanının dışından Verizon Wi-Fi Access\'e bağlanamazsınız."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access abonesi değilsiniz. Bize ulaşmak için lütfen 800-922-0204 numaralı telefonu arayın."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access hesabınızla ilgili bir sorun var. Bize ulaşmak için lütfen 800-922-0204 numaralı telefonu arayın."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access\'e zaten bağlısınız."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access\'e bağlanırken bir sorun oluştu. Bize ulaşmak için lütfen 800-922-0204 numaralı telefonu arayın."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access hesabınızla ilgili bir sorun var. Bize ulaşmak için lütfen 800-922-0204 numaralı telefonu arayın."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access bulunduğunuz konumdan kullanılamıyor. Daha sonra tekrar deneyin veya farklı bir konumdan bağlanmaya çalışın."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-uk/strings.xml b/service/res/values-mcc310-mnc004-uk/strings.xml deleted file mode 100644 index 69e45dcfd..000000000 --- a/service/res/values-mcc310-mnc004-uk/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>: не можна підключитися до Verizon Wi-Fi Access за межами зони покриття."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>: у вас немає підписки на Verizon Wi-Fi Access. Зателефонуйте нам на номер 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>: виникла проблема з вашим обліковим записом Verizon Wi-Fi Access. Зателефонуйте нам на номер 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>: пристрій уже підключено до Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>: не вдалося підключитися до Verizon Wi-Fi Access. Зателефонуйте нам на номер 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>: виникла проблема з вашим обліковим записом Verizon Wi-Fi Access. Зателефонуйте нам на номер 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>: сервіс Verizon Wi-Fi Access недоступний за вашим розташуванням. Повторіть спробу пізніше або змініть місцезнаходження."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-ur/strings.xml b/service/res/values-mcc310-mnc004-ur/strings.xml deleted file mode 100644 index 94b890abb..000000000 --- a/service/res/values-mcc310-mnc004-ur/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : آپ Verizon کوریج علاقہ کے باہر سے Verizon Wi-Fi رسائی کے لیے منسلک نہیں کر سکتے ہیں۔"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : آپ Verizon Wi-Fi رسائی کے رکن نہیں ہیں۔ براہ کرم ہمیں 0204-922-800 پر کال کریں۔"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : آپ کے Verizon Wi-Fi رسائی اکاؤنٹ کے ساتھ ایک مسئلہ ہے۔ براہ کرم ہمیں 0204-922-800 پر کال کریں۔"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : آپ پہلے سے ہی Verizon Wi-Fi رسائی سے منسلک ہیں۔"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : آپ کو Verizon Wi-Fi رسائی سے منسلک ہونے میں ایک مسئلہ ہے۔ براہ کرم ہمیں 0204-922-800 پر کال کریں۔"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : آپ کے Verizon Wi-Fi رسائی اکاؤنٹ کے ساتھ ایک مسئلہ ہے۔ براہ کرم ہمیں 0204-922-800 پر کال کریں۔"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi رسائی آپ کے مقام سے دستیاب نہیں ہے۔ بعد میں دوبارہ کوشش کریں یا دوسرے مقام سے کوشش کر کے دیکھیں۔"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-uz/strings.xml b/service/res/values-mcc310-mnc004-uz/strings.xml deleted file mode 100644 index a6aa16cfb..000000000 --- a/service/res/values-mcc310-mnc004-uz/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon qamrovidan tashqarida Verizon Wi-Fi Access xizmatiga ulana olmaysiz."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access xizmatiga obuna boʻlmagansiz. 800-922-0204 raqamiga telefon qiling."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access hisobingiz bilan muammo bor. 800-922-0204 raqamiga telefon qiling."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Allaqachon Verizon Wi-Fi Access xizmatiga ulangansiz."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access xizmatiga ulanishda muammo chiqdi. 800-922-0204 raqamiga telefon qiling."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access hisobingiz bilan muammo bor. 800-922-0204 raqamiga telefon qiling."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access siz turgan joyda ishlamaydi. Keyinroq qayta urining yoki boshqa joydan urining."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-vi/strings.xml b/service/res/values-mcc310-mnc004-vi/strings.xml deleted file mode 100644 index 042a11343..000000000 --- a/service/res/values-mcc310-mnc004-vi/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Bạn không thể kết nối với dịch vụ Truy cập Wi-Fi của Verizon từ bên ngoài khu vực phủ sóng của Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Bạn chưa đăng ký dịch vụ Truy cập Wi-Fi của Verizon. Vui lòng gọi cho chúng tôi theo số 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Đã xảy ra sự cố với tài khoản Truy cập Wi-Fi của Verizon mà bạn có. Vui lòng gọi cho chúng tôi theo số 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Bạn đã kết nối với dịch vụ Truy cập Wi-Fi của Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Đã xảy ra sự cố khi kết nối bạn với dịch vụ Truy cập Wi-Fi của Verizon. Vui lòng gọi cho chúng tôi theo số 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Đã xảy ra sự cố với tài khoản Truy cập Wi-Fi của Verizon mà bạn có. Vui lòng gọi cho chúng tôi theo số 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Không có dịch vụ Truy cập Wi-Fi của Verizon tại vị trí của bạn. Hãy thử lại sau hoặc thử ở một vị trí khác."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-zh-rCN/strings.xml b/service/res/values-mcc310-mnc004-zh-rCN/strings.xml deleted file mode 100644 index db62e8a27..000000000 --- a/service/res/values-mcc310-mnc004-zh-rCN/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>:您无法从 Verizon 覆盖区域外的地点连接到 Verizon WLAN Access。"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>:您没有订阅 Verizon WLAN Access。请拨打 800-922-0204 与我们联系。"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>:您的 Verizon WLAN Access 帐号出现问题。请拨打 800-922-0204 与我们联系。"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>:您已连接到 Verizon WLAN Access。"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>:将您连接到 Verizon WLAN Access 时出现问题。请拨打 800-922-0204 与我们联系。"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>:您的 Verizon WLAN Access 帐号出现问题。请拨打 800-922-0204 与我们联系。"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>:Verizon WLAN Access 在您所在的地点无法使用。请稍后重试,或换个地点再试一次。"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-zh-rHK/strings.xml b/service/res/values-mcc310-mnc004-zh-rHK/strings.xml deleted file mode 100644 index f7d8f344e..000000000 --- a/service/res/values-mcc310-mnc004-zh-rHK/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>:無法從 Verizon 訊號覆蓋範圍外的地點連線至 Verizon Wi-Fi Access。"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>:您未訂閱 Verizon Wi-Fi Access。請致電 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>:您的 Verizon Wi-Fi Access 帳戶發生問題。請致電 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>:您已連線至 Verizon Wi-Fi Access。"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>:連線至 Verizon Wi-Fi Access 時發生問題。請致電 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>:您的 Verizon Wi-Fi Access 帳戶發生問題。請致電 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>:您目前的所在地點無法使用 Verizon Wi-Fi Access,請稍後再試。您亦可換個地點,然後再試一次。"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-zh-rTW/strings.xml b/service/res/values-mcc310-mnc004-zh-rTW/strings.xml deleted file mode 100644 index 1927bc40d..000000000 --- a/service/res/values-mcc310-mnc004-zh-rTW/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g>:無法在 Verizon 訊號涵蓋範圍之外的地點連線至 Verizon Wi-Fi Access。"</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g>:你並未訂閱 Verizon Wi-Fi Access。請撥打 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g>:你的 Verizon Wi-Fi Access 帳戶發生問題。請撥打 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g>:你已連線至 Verizon Wi-Fi Access。"</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g>:連線至 Verizon Wi-Fi Access 時發生問題。請撥打 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g>:你的 Verizon Wi-Fi Access 帳戶發生問題。請撥打 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g>:你目前的所在地點無法使用 Verizon Wi-Fi Access,請稍後再試。你也可以換個地點,然後再試一次。"</string> -</resources> diff --git a/service/res/values-mcc310-mnc004-zu/strings.xml b/service/res/values-mcc310-mnc004-zu/strings.xml deleted file mode 100644 index 952acbd12..000000000 --- a/service/res/values-mcc310-mnc004-zu/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Awukwazi ukuxhuma kukufinyelela kwi-Verizon Wi-Fi kusuka ngaphandle kwendawo yokufakwa ye-Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Awubhalisele ukufinyelela kwi-Verizon Wi-Fi. Sicela usishayele ucingo ku-800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Kukhona inkinga nge-akhawunti yakho yokufinyelela kwi-Wi-Fi. Sicela usishayele ucingo ku-800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Usuxhumeke kakade kukufinyelela kwi-Verizon Wi-Fi."</string> - <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Kukhona inkinga yokukuxhuma kukufinyelela kwi-Verizon Wi-Fi. Sicela usishayele ucingo ku-800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Kukhona inkinga nge-akhawunti yakho yokufinyelela kwi-Wi-Fi. Sicela usishayele ucingo ku-800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Ukufinyelela kwi-Verizon Wi-Fi akutholakali kusuka endaweni yakho. Zama futhi ngemuva kwesikhathi noma zama indawo ehlukile."</string> -</resources> diff --git a/service/res/values-mcc310-mnc004/strings.xml b/service/res/values-mcc310-mnc004/strings.xml deleted file mode 100644 index af976d472..000000000 --- a/service/res/values-mcc310-mnc004/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2020 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. ---> - -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- A notification is shown when eap failure happens. It should be overridden by carrier-specific overlays. --> - <string name="wifi_eap_error_message_code_32760"><xliff:g id="ssid">%1$s</xliff:g> : You can\u2019t connect to Verizon Wi-Fi Access from outside the Verizon coverage area.</string> - <string name="wifi_eap_error_message_code_32761"><xliff:g id="ssid">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi Access. Please call us at 800-922-0204.</string> - <string name="wifi_eap_error_message_code_32762"><xliff:g id="ssid">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi Access account. Please call us at 800-922-0204.</string> - <string name="wifi_eap_error_message_code_32763"><xliff:g id="ssid">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi Access.</string> - <string name="wifi_eap_error_message_code_32764"><xliff:g id="ssid">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi Access. Please call us at 800-922-0204.</string> - <string name="wifi_eap_error_message_code_32765"><xliff:g id="ssid">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi Access account. Please call us at 800-922-0204.</string> - <string name="wifi_eap_error_message_code_32766"><xliff:g id="ssid">%1$s</xliff:g> : Verizon Wi-Fi Access is not available from your location. Try again later or try from a different location.</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-af/strings.xml b/service/res/values-mcc311-mnc480-af/strings.xml deleted file mode 100644 index 7d2e6c850..000000000 --- a/service/res/values-mcc311-mnc480-af/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Jy kan nie van buite Verizon se dekkingsgebied aan Verizon Wi-F Access koppel nie."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Jy is nie op Verizon Wi-Fi Access ingeteken nie. Bel ons asseblief by 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Daar is \'n probleem met jou Verizon Wi-Fi Access-rekening. Bel ons asseblief by 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Jy is reeds aan Verizon Wi-Fi Access gekoppel."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Kan jou nie aan Verizon Wi-Fi Access koppel nie. Bel ons asseblief by 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Daar is \'n probleem met jou Verizon Wi-Fi Access-rekening. Bel ons asseblief by 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access is nie in jou ligging beskikbaar nie. Probeer later weer of probeer van \'n ander ligging af."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-am/strings.xml b/service/res/values-mcc311-mnc480-am/strings.xml deleted file mode 100644 index d56be2f94..000000000 --- a/service/res/values-mcc311-mnc480-am/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> ፦ የVerizon ሽፋን ካለው አካባቢ ውጭ ሆነው ከVerizon Wi-Fi Access ጋር መገናኘት አይችሉም።"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> ፦ ለVerizon Wi-Fi Access ደንበኝነት አልተመዘገቡም። እባክዎ 800-922-0204 ላይ ይደውሉልን።"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> ፦ የእርስዎ Verizon Wi-Fi Access መለያ ጋር ችግር አለበት። እባክዎ 800-922-0204 ላይ ይደውሉልን።"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> ፦ አስቀድመው ከVerizon Wi-Fi Access ጋር ተገናኝተዋል።"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> ፦ እርስዎን ከVerizon Wi-Fi Access ጋር ማገናኘት ላይ ችግር አለ። እባክዎ 800-922-0204 ላይ ይደውሉልን።"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> ፦ የእርስዎ Verizon Wi-Fi Access መለያ ጋር ችግር አለበት። እባክዎ 800-922-0204 ላይ ይደውሉልን።"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ከእርስዎ አካባቢ የሚገኝ አይደለም። በኋላ ላይ እንደገና ይሞክሩ ወይም ከተለየ አካባቢ ይሞክሩ።"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ar/strings.xml b/service/res/values-mcc311-mnc480-ar/strings.xml deleted file mode 100644 index a397eb2f2..000000000 --- a/service/res/values-mcc311-mnc480-ar/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : لا يمكنك الاتصال بشبكة Verizon Wi-Fi Access من خارج نطاق تغطية Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : لم تشترك في Verizon Wi-Fi Access. يُرجى الاتصال بالرقم 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : حدثت مشكلة في حسابك على Verizon Wi-Fi Access. يُرجى الاتصال بالرقم 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : سبق واتصلت بشبكة Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : حدثت مشكلة أثناء اتصالك بشبكة Verizon Wi-Fi Access. يُرجى الاتصال بالرقم 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : حدثت مشكلة في حسابك على Verizon Wi-Fi Access. يُرجى الاتصال بالرقم 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access غير متاح في موقعك الجغرافية. يُرجى إعادة المحاولة لاحقًا أو المحاولة من موقع جغرافي مختلف."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-as/strings.xml b/service/res/values-mcc311-mnc480-as/strings.xml deleted file mode 100644 index 9dabc29ce..000000000 --- a/service/res/values-mcc311-mnc480-as/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : আপুনি Verizon কভাৰেজ ক্ষেত্ৰৰ বাহিৰৰ পৰা Verizon Wi-Fi Accessৰ সৈতে সংযোগ কৰিব নোৱাৰে।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : আপুনি Verizon Wi-Fi Access ছাবস্ক্ৰাইব কৰা নাই। অনুগ্ৰহ কৰি ৮০০-৯২২-০২০৪ নম্বৰটোত আমালৈ কল কৰক।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : আপোনাৰ Verizon Wi-Fi Access একাউণ্টটোত কিবা সমস্যা আছে। অনুগ্ৰহ কৰি ৮০০-৯২২-০২০৪ নম্বৰটোত আমালৈ কল কৰক।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : আপুনি ইতিমধ্যে Verizon Wi-Fi Accessৰ সৈতে সংযুক্ত হৈ আছে।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : আপোনাক Verizon Wi-Fi Accessৰ সৈতে সংযোগ কৰাত এটা সমস্যা হৈছে। অনুগ্ৰহ কৰি ৮০০-৯২২-০২০৪ নম্বৰটোত আমালৈ কল কৰক।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : আপোনাৰ Verizon Wi-Fi Access একাউণ্টটোত কিবা সমস্যা আছে। অনুগ্ৰহ কৰি ৮০০-৯২২-০২০৪ নম্বৰটোত আমালৈ কল কৰক।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access আপোনাৰ অৱস্থানৰ পৰা উপলব্ধ নহয়। পাছত পুনৰ চেষ্টা কৰক অথবা এটা বেলেগ অৱস্থানৰ পৰা চেষ্টা কৰক।"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-az/strings.xml b/service/res/values-mcc311-mnc480-az/strings.xml deleted file mode 100644 index 6075e8110..000000000 --- a/service/res/values-mcc311-mnc480-az/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon əhatə dairəsindən kənarda Verizon Wi-Fi Access\'ə qoşula bilməzsiniz."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ə abunə olmamısınız. 800-922-0204 nömrəsini yığaraq bizə zəng edin."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access hesabınız ilə bağlı problem var. 800-922-0204 nömrəsini yığaraq bizə zəng edin."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Artıq Verizon Wi-Fi Access\'ə qoşulmusunuz."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Sizi Verizon Wi-Fi Access\'ə qoşmaqla bağlı problem var. 800-922-0204 nömrəsini yığaraq bizə zəng edin."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access hesabınız ilə bağlı problem var. 800-922-0204 nömrəsini yığaraq bizə zəng edin."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access məkanınızdan əlçatan deyil. Sonra cəhd edin, ya da fərqli məkandan yoxlayın."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-b+sr+Latn/strings.xml b/service/res/values-mcc311-mnc480-b+sr+Latn/strings.xml deleted file mode 100644 index 712334ed5..000000000 --- a/service/res/values-mcc311-mnc480-b+sr+Latn/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Ne možete da se povežete na Verizon WiFi Access van oblasti koju Verizon pokriva."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Niste pretplaćeni na Verizon WiFi Access. Pozovite nas na 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon WiFi Access nalogom. Pozovite nas na 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Već ste povezani na Verizon WiFi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Postoji problem pri povezivanju na Verizon WiFi Access. Pozovite nas na 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon WiFi Access nalogom. Pozovite nas na 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon WiFi Access nije dostupan sa vaše lokacije. Probajte ponovo kasnije ili probajte sa neke druge lokacije."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-be/strings.xml b/service/res/values-mcc311-mnc480-be/strings.xml deleted file mode 100644 index 7a46b6243..000000000 --- a/service/res/values-mcc311-mnc480-be/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : вы не можаце падключыцца да Verizon Wi-Fi Access, калі не знаходзіцеся ў зоне пакрыцця Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : вы не падпісаны на Verizon Wi-Fi Access. Выклікайце нас па нумары 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : ёсць праблема з вашым уліковым запісам Verizon Wi-Fi Access. Выклікайце нас па нумары 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : вы ўжо падключаны да Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : ёсць праблема з падключэннем да Verizon Wi-Fi Access. Выклікайце нас па нумары 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : ёсць праблема з вашым уліковым запісам Verizon Wi-Fi Access. Выклікайце нас па нумары 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : з месца, дзе вы знаходзіцеся, няма доступу да Verizon Wi-Fi Access. Паўтарыце спробу пазней або змяніце месцазнаходжанне."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-bg/strings.xml b/service/res/values-mcc311-mnc480-bg/strings.xml deleted file mode 100644 index f9882ef2b..000000000 --- a/service/res/values-mcc311-mnc480-bg/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: Не можете да се свържете с Verizon Wi-Fi Access извън района на покритие на Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Нямате абонамент за Verizon Wi-Fi Access. Моля, обадете ни се на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: Възникна проблем с профила ви във Verizon Wi-Fi Access. Моля, обадете ни се на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: Вече сте установили връзка с Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Възникна проблем при свързването с Verizon Wi-Fi Access. Моля, обадете ни се на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: Възникна проблем с профила ви във Verizon Wi-Fi Access. Моля, обадете ни се на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access не се предлага за местоположението ви. Опитайте отново по-късно или от друго местоположение."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-bn/strings.xml b/service/res/values-mcc311-mnc480-bn/strings.xml deleted file mode 100644 index c3310f3f3..000000000 --- a/service/res/values-mcc311-mnc480-bn/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon কভারেজ এলাকার বাইরে আপনি Verizon Wi-Fi Access-এর সাথে কানেক্ট করতে পারবেন না।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : আপনি Verizon Wi-Fi Access সাবস্ক্রাইব করেননি। ৮০০-৯২২-০২০৪ নম্বরে যোগাযোগ করুন।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : আপনার Verizon Wi-Fi Access অ্যাকাউন্ট নিয়ে কোনও সমস্যা হয়েছে। ৮০০-৯২২-০২০৪ নম্বরে যোগাযোগ করুন।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : আপনি আগে থেকে Verizon Wi-Fi Access-এর সাথে কানেক্ট করেছেন।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : আপনার Verizon Wi-Fi Access-এর সাথে কানেক্ট করতে কোনও সমস্যা হয়েছে। ৮০০-৯২২-০২০৪ নম্বরে যোগাযোগ করুন।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : আপনার Verizon Wi-Fi Access অ্যাকাউন্ট নিয়ে কোনও সমস্যা হয়েছে। ৮০০-৯২২-০২০৪ নম্বরে যোগাযোগ করুন।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : আপনার লোকেশনে Verizon Wi-Fi Access উপলভ্য নেই। পরে আবার চেষ্টা করুন বা অন্য লোকেশন থেকে চেষ্টা করুন।"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-bs/strings.xml b/service/res/values-mcc311-mnc480-bs/strings.xml deleted file mode 100644 index 87006e398..000000000 --- a/service/res/values-mcc311-mnc480-bs/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Ne možete se povezati s WiFi pristupom Verizonu izvan područja pokrivenosti Verizona."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Niste pretplaćeni na WiFi pristup Verizonu. Pozovite nas na broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema s vašim računom za WiFi pristup Verizonu. Pozovite nas na broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Već ste povezani s WiFi pristupom Verizonu."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema pri povezivanju s WiFi pristupom Verizonu. Pozovite nas na broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema s vašim računom za WiFi pristup Verizonu. Pozovite nas na broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : WiFi pristup Verizonu nije dostupan s vaše lokacije. Pokušajte ponovo kasnije ili pokušajte s druge lokacije."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ca/strings.xml b/service/res/values-mcc311-mnc480-ca/strings.xml deleted file mode 100644 index 91e3d7d17..000000000 --- a/service/res/values-mcc311-mnc480-ca/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: no et pots connectar a Verizon Wi‑Fi Access des de fora de l\'àrea de cobertura de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: no estàs subscrit a Verizon Wi‑Fi Access. Truca\'ns al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: hi ha un problema amb el teu compte de Verizon Wi‑Fi Access. Truca\'ns al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: ja estàs connectat a Verizon Wi‑Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: hi ha un problema en connectar-te a Verizon Wi‑Fi Access. Truca\'ns al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: hi ha un problema amb el teu compte de Verizon Wi‑Fi Access. Truca\'ns al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi‑Fi Access no està disponible des de la teva ubicació. Torna-ho a provar més tard o bé des d\'una altra ubicació."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-cs/strings.xml b/service/res/values-mcc311-mnc480-cs/strings.xml deleted file mode 100644 index e65785fba..000000000 --- a/service/res/values-mcc311-mnc480-cs/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: K síti Verizon Wi-Fi Access se nelze připojit mimo dosah pokrytí společnosti Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Síť Verizon Wi-Fi Access nemáte předplacenou. Zavolejte nám na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: U vašeho účtu Verizon Wi-Fi Access došlo k problému. Zavolejte nám na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: K síti Verizon Wi-Fi Access jste už připojeni."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Při připojování k síti Verizon Wi-Fi Access došlo k problému. Zavolejte nám na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: U vašeho účtu Verizon Wi-Fi Access došlo k problému. Zavolejte nám na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access ve vaší oblasti není k dispozici. Zkuste to později nebo z jiného místa."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-da/strings.xml b/service/res/values-mcc311-mnc480-da/strings.xml deleted file mode 100644 index ebe1a683d..000000000 --- a/service/res/values-mcc311-mnc480-da/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Du kan ikke oprette forbindelse til Verizon Wi-Fi Access uden for Verizons dækningsområde."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Du abonnerer ikke på Verizon Wi-Fi Access. Ring til os på telefonnummer 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Der er et problem med din Verizon Wi-Fi Access-konto. Ring til os på telefonnummer 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Du har allerede oprettet forbindelse til Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Du kan ikke oprette forbindelse til Verizon Wi-Fi Access. Ring til os på telefonnummer 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Der er et problem med din Verizon Wi-Fi Access-konto. Ring til os på telefonnummer 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access er ikke tilgængeligt i dit område. Prøv igen senere eller fra en anden placering."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-de/strings.xml b/service/res/values-mcc311-mnc480-de/strings.xml deleted file mode 100644 index 0b474548e..000000000 --- a/service/res/values-mcc311-mnc480-de/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Eine Verbindung mit Verizon Wi-Fi Access ist außerhalb der Abdeckung von Verizon nicht möglich."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Du bist nicht bei Verizon Wi-Fi Access angemeldet. Bitte ruf uns unter 800-922-0204 an."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Es gibt ein Problem mit deinem Verizon Wi-Fi Access-Konto. Bitte ruf uns unter 800-922-0204 an."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Du bist bereits mit Verizon Wi-Fi Access verbunden."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Es kann keine Verbindung zu Verizon Wi-Fi Access hergestellt werden. Bitte ruf uns unter 800-922-0204 an."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Es gibt ein Problem mit deinem Verizon Wi-Fi Access-Konto. Bitte ruf uns unter 800-922-0204 an."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ist an deinem Standort nicht verfügbar. Du kannst es später noch einmal oder von einem anderen Standort aus versuchen."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-el/strings.xml b/service/res/values-mcc311-mnc480-el/strings.xml deleted file mode 100644 index ca5526e17..000000000 --- a/service/res/values-mcc311-mnc480-el/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Δεν μπορείτε να συνδεθείτε στο Verizon Wi-Fi Access εκτός της περιοχής κάλυψης της Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Δεν έχετε εγγραφεί στο Verizon Wi-Fi Access. Καλέστε μας στον αριθμό 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Υπάρχει πρόβλημα με τον λογαριασμό σας Verizon Wi-Fi Access. Καλέστε μας στον αριθμό 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Έχετε συνδεθεί ήδη με το Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Υπάρχει πρόβλημα με τη σύνδεση στο Verizon Wi-Fi Access. Καλέστε μας στον αριθμό 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Υπάρχει πρόβλημα με τον λογαριασμό σας Verizon Wi-Fi Access. Καλέστε μας στον αριθμό 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Το Verizon Wi-Fi Access δεν είναι διαθέσιμο από την τοποθεσία σας. Δοκιμάστε ξανά αργότερα ή δοκιμάστε από διαφορετική τοποθεσία."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-en-rAU/strings.xml b/service/res/values-mcc311-mnc480-en-rAU/strings.xml deleted file mode 100644 index 56422c148..000000000 --- a/service/res/values-mcc311-mnc480-en-rAU/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : You can’t connect to Verizon Wi-Fi access from outside the Verizon coverage area."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi access is not available from your location. Try again later or try from a different location."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-en-rCA/strings.xml b/service/res/values-mcc311-mnc480-en-rCA/strings.xml deleted file mode 100644 index 56422c148..000000000 --- a/service/res/values-mcc311-mnc480-en-rCA/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : You can’t connect to Verizon Wi-Fi access from outside the Verizon coverage area."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi access is not available from your location. Try again later or try from a different location."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-en-rGB/strings.xml b/service/res/values-mcc311-mnc480-en-rGB/strings.xml deleted file mode 100644 index 56422c148..000000000 --- a/service/res/values-mcc311-mnc480-en-rGB/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : You can’t connect to Verizon Wi-Fi access from outside the Verizon coverage area."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi access is not available from your location. Try again later or try from a different location."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-en-rIN/strings.xml b/service/res/values-mcc311-mnc480-en-rIN/strings.xml deleted file mode 100644 index 56422c148..000000000 --- a/service/res/values-mcc311-mnc480-en-rIN/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : You can’t connect to Verizon Wi-Fi access from outside the Verizon coverage area."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi access. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi access account. Please call us on 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi access is not available from your location. Try again later or try from a different location."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-es-rUS/strings.xml b/service/res/values-mcc311-mnc480-es-rUS/strings.xml deleted file mode 100644 index 2f97d6eba..000000000 --- a/service/res/values-mcc311-mnc480-es-rUS/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : No te puedes conectar a Verizon Wi-Fi Access si te encuentras fuera del área de cobertura de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : No te suscribiste a Verizon Wi-Fi Access. Comunícate con nosotros al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Hay un problema con tu cuenta de Verizon Wi-Fi Access. Comunícate con nosotros al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Ya te conectaste a Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Se produjo un error al conectarte a Verizon Wi-Fi Access. Comunícate con nosotros al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Hay un problema con tu cuenta de Verizon Wi-Fi Access. Comunícate con nosotros al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access no está disponible en tu ubicación. Vuelve a intentarlo más tarde o en una ubicación diferente."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-es/strings.xml b/service/res/values-mcc311-mnc480-es/strings.xml deleted file mode 100644 index f813163e1..000000000 --- a/service/res/values-mcc311-mnc480-es/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: no puedes conectarte a Verizon Wi‑Fi Access si no estás en el área de cobertura de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: no tienes una suscripción a Verizon Wi‑Fi Access. Llámanos al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: hay un problema con tu cuenta de Verizon Wi‑Fi Access. Llámanos al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: ya te has conectado a Verizon Wi‑Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: no se ha podido conectar a Verizon Wi‑Fi Access. Llámanos al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: hay un problema con tu cuenta de Verizon Wi‑Fi Access. Llámanos al 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi‑Fi Access no está disponible en tu ubicación. Inténtalo de nuevo más tarde o cuando estés en otro sitio."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-et/strings.xml b/service/res/values-mcc311-mnc480-et/strings.xml deleted file mode 100644 index 7621693db..000000000 --- a/service/res/values-mcc311-mnc480-et/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: te ei saa väljaspool Verizoni leviala Verizon Wi-Fi Accessiga ühendust luua."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: te ei ole Verizon Wi-Fi Accessi tellinud. Helistage meile numbril 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: teie Verizon Wi-Fi Accessi kontoga on probleem. Helistage meile numbril 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: olete Verizon Wi-Fi Accessiga juba ühendatud."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: teie ja Verizon Wi-Fi Accessi vahelise ühenduse loomisel on probleem. Helistage meile numbril 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: teie Verizon Wi-Fi Accessi kontoga on probleem. Helistage meile numbril 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access ei ole teie asukohas saadaval. Proovige hiljem või mõnes teises asukohas uuesti."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-eu/strings.xml b/service/res/values-mcc311-mnc480-eu/strings.xml deleted file mode 100644 index 90b04a694..000000000 --- a/service/res/values-mcc311-mnc480-eu/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: ezin zara konektatu Verizon Wi-Fi Access zerbitzura Verizon-en estaldura-eremutik kanpo bazaude."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: ez zaude harpidetuta Verizon Wi-Fi Access zerbitzura. Dei iezaguzu 800-922-0204 zenbakira."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: arazo bat dago Verizon Wi-Fi Access zerbitzuko kontuarekin. Dei iezaguzu 800-922-0204 zenbakira."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: dagoeneko konektatuta zaude Verizon Wi-Fi Access zerbitzura."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: arazo bat dago Verizon Wi-Fi Access zerbitzura konektatzeko. Dei iezaguzu 800-922-0204 zenbakira."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: arazo bat dago Verizon Wi-Fi Access zerbitzuko kontuarekin. Dei iezaguzu 800-922-0204 zenbakira."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access ez dago erabilgarri kokapen horretan. Saiatu berriro geroago edo beste kokapen batetik."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-fa/strings.xml b/service/res/values-mcc311-mnc480-fa/strings.xml deleted file mode 100644 index 4f210152f..000000000 --- a/service/res/values-mcc311-mnc480-fa/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : خارج از منطقه تحت پوشش Verizon نمیتوانید به Verizon Wi-Fi Access متصل شوید."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : مشترک Verizon Wi-Fi Access نیستید. لطفاً ازطریق شماره ۰۲۰۴-۹۲۲-۸۰۰ با ما تماس بگیرید."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : مشکلی در حساب Verizon Wi-Fi Access وجود دارد. لطفاً ازطریق شماره ۰۲۰۴-۹۲۲-۸۰۰ با ما تماس بگیرید."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : در حالحاضر به Verizon Wi-Fi Access متصل هستید."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : هنگام اتصال به Verizon Wi-Fi Access مشکلی وجود دارد. لطفاً ازطریق شماره ۰۲۰۴-۹۲۲-۸۰۰ با ما تماس بگیرید."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : مشکلی در حساب Verizon Wi-Fi Access وجود دارد. لطفاً ازطریق شماره ۰۲۰۴-۹۲۲-۸۰۰ با ما تماس بگیرید."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access در مکان شما در دسترس نیست. بعداً دوباره تلاش کنید یا از مکان متفاوتی امتحان کنید."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-fi/strings.xml b/service/res/values-mcc311-mnc480-fi/strings.xml deleted file mode 100644 index abc2d1769..000000000 --- a/service/res/values-mcc311-mnc480-fi/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizonin Wi-Fi‑yhteyttä ei voi muodostaa Verizonin kattavuusalueen ulkopuolelta."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Et ole tilannut Verizonin Wi-Fi‑yhteyttä. Soita meille: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi ‑tilisi kanssa on ongelma. Soita meille: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Olet jo yhteydessä Verizonin Wi-Fiin."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Ongelma yhdistettäessä Verizonin Wi-Fiin. Soita meille: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi ‑tilisi kanssa on ongelma. Soita meille: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi ei ole saatavilla sijainnissasi. Yritä uudelleen tai toisesta sijainnista."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-fr-rCA/strings.xml b/service/res/values-mcc311-mnc480-fr-rCA/strings.xml deleted file mode 100644 index 1d06c5068..000000000 --- a/service/res/values-mcc311-mnc480-fr-rCA/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Vous ne pouvez pas vous connecter à Verizon Wi-Fi Access en dehors de la zone de couverture de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Vous n\'êtes pas abonné à Verizon Wi-Fi Access. Veuillez nous appeler au 1 800 922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Il y a un problème avec votre compte Verizon Wi-Fi Access. Veuillez nous appeler au 1 800 922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Vous êtes déjà connecté à Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Il y a un problème de connexion à Verizon Wi-Fi Access. Veuillez nous appeler au 1 800 922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Il y a un problème avec votre compte Verizon Wi-Fi Access. Veuillez nous appeler au 1 800 922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access n\'est pas proposé dans votre région. Réessayez plus tard ou essayez à partir d\'une région différente."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-fr/strings.xml b/service/res/values-mcc311-mnc480-fr/strings.xml deleted file mode 100644 index 0e55a4f75..000000000 --- a/service/res/values-mcc311-mnc480-fr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : vous ne pouvez pas vous connecter à Verizon Wi-Fi Access si vous ne vous trouvez pas dans une zone couverte par le réseau Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : vous n\'avez pas d\'abonnement à Verizon Wi-Fi Access. Veuillez nous appeler au 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : un problème lié à votre compte Verizon Wi-Fi Access a été détecté. Veuillez nous appeler au 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : votre connexion à Verizon Wi-Fi Access est déjà active."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : un problème est survenu lors de votre connexion à Verizon Wi-Fi Access. Veuillez nous appeler au 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : un problème lié à votre compte Verizon Wi-Fi Access a été détecté. Veuillez nous appeler au 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : le service Verizon Wi-Fi Access n\'est pas disponible dans votre région. Veuillez réessayer plus tard ou depuis un autre lieu."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-gl/strings.xml b/service/res/values-mcc311-mnc480-gl/strings.xml deleted file mode 100644 index a51f1c354..000000000 --- a/service/res/values-mcc311-mnc480-gl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: non podes conectar con Verizon Wi-Fi Access desde fóra da área de cobertura de Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: non tes subscrición a Verizon Wi-Fi Access. Chámanos ao número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: houbo un problema coa túa conta de Verizon Wi-Fi Access. Chámanos ao número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: xa estableciches conexión con Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: houbo un problema ao conectar con Verizon Wi-Fi Access. Chámanos ao número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: houbo un problema coa túa conta de Verizon Wi-Fi Access. Chámanos ao número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access non está dispoñible desde a túa localización. Téntao de novo máis tarde ou proba desde unha localización diferente."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-gu/strings.xml b/service/res/values-mcc311-mnc480-gu/strings.xml deleted file mode 100644 index e22deb9ad..000000000 --- a/service/res/values-mcc311-mnc480-gu/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : તમે Verizon કવરેજ વિસ્તારની બહારથી Verizon વાઇ-ફાઇ ઍક્સેસ સાથે કનેક્ટ થઈ શકતાં નથી."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : તમે Verizon વાઇ-ફાઇ ઍક્સેસને સબ્સ્ક્રાઇબ કરેલું નથી. કૃપા કરીને અમને 800-922-0204 પર કૉલ કરો."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : તમારા વાઇ-ફાઇ ઍક્સેસ એકાઉન્ટમાં કોઈ સમસ્યા છે. કૃપા કરીને અમને 800-922-0204 પર કૉલ કરો."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : તમે પહેલેથી Verizon વાઇ-ફાઇ ઍક્સેસ સાથે કનેક્ટ કરેલું છે."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : તમને Verizon વાઇ-ફાઇ ઍક્સેસ સાથે કનેક્ટ કરવામાં કોઈ સમસ્યા આવે છે. કૃપા કરીને અમને 800-922-0204 પર કૉલ કરો."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : તમારા વાઇ-ફાઇ ઍક્સેસ એકાઉન્ટમાં કોઈ સમસ્યા છે. કૃપા કરીને અમને 800-922-0204 પર કૉલ કરો."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : તમારા સ્થળેથી Verizon વાઇ-ફાઇ ઍક્સેસ ઉપલબ્ધ નથી. પછીથી અથવા કોઈ અલગ સ્થળેથી પ્રયાસ કરો."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-hi/strings.xml b/service/res/values-mcc311-mnc480-hi/strings.xml deleted file mode 100644 index 8d4b47c97..000000000 --- a/service/res/values-mcc311-mnc480-hi/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : आप Verizon के कवरेज एरिया के बाहर Verizon Wi-Fi Access से कनेक्ट नहीं हो सकते."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : आपने Verizon Wi-Fi Access की सदस्यता नहीं ली है. कृपया 800-922-0204 पर कॉल करके हमसे संपर्क करें."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : आपके Verizon Wi-Fi Access खाते में कोई समस्या है. कृपया 800-922-0204 पर कॉल करके हमसे संपर्क करें."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : आप पहले ही Verizon Wi-Fi Access से कनेक्ट हैं."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : आपको Verizon Wi-Fi Access से कनेक्ट करने में कोई समस्या हुई है. कृपया 800-922-0204 पर कॉल करके हमसे संपर्क करें."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : आपके Verizon Wi-Fi Access खाते में कोई समस्या है. कृपया 800-922-0204 पर कॉल करके हमसे संपर्क करें."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : आपकी जगह पर Verizon Wi-Fi Access उपलब्ध नहीं है. कृपया थोड़ी देर में कोशिश करें या किसी दूसरी जगह से कोशिश करें."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-hr/strings.xml b/service/res/values-mcc311-mnc480-hr/strings.xml deleted file mode 100644 index fbc231b50..000000000 --- a/service/res/values-mcc311-mnc480-hr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : ne možete se povezati s Wi-Fi pristupom Verizonu izvan područja pokrivenosti Verizona."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : niste pretplaćeni na Wi-Fi pristup Verizonu. Nazovite nas na telefonski broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : postoji problem s vašim računom za Wi-Fi pristup Verizonu. Nazovite nas na telefonski broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : već ste povezani s Wi-Fi pristupom Verizonu."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : postoji problem s povezivanjem s Wi-Fi pristupom Verizonu. Nazovite nas na telefonski broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : postoji problem s vašim računom za Wi-Fi pristup Verizonu. Nazovite nas na telefonski broj 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Wi-Fi pristup Verizonu nije dostupan s vaše lokacije. Pokušajte ponovno kasnije ili s druge lokacije."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-hu/strings.xml b/service/res/values-mcc311-mnc480-hu/strings.xml deleted file mode 100644 index eada54e1a..000000000 --- a/service/res/values-mcc311-mnc480-hu/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: Nem kapcsolódhat a Verizon Wi-Fi-hozzáférési szolgáltatásához a Verizon lefedettségi területén kívülről."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Nem fizetett elő a Verizon Wi-Fi-hozzáférési szolgáltatására. Hívjon minket a következő telefonszámon: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: Valami gond van Verizon Wi-Fi-hozzáférési fiókjával. Hívjon minket a következő telefonszámon: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: Már kapcsolódott a Verizon Wi-Fi-hozzáférési szolgáltatásához."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Valami probléma történt a Verizon Wi-Fi-hozzáférési szolgáltatásához való kapcsolódás során. Hívjon minket a következő telefonszámon: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: Valami gond van Verizon Wi-Fi-hozzáférési fiókjával. Hívjon minket a következő telefonszámon: 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: A Verizon Wi-Fi-hozzáférési szolgáltatása nem áll rendelkezésre az Ön tartózkodási helyén. Próbálja újra, vagy próbáljon meg máshol csatlakozni."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-hy/strings.xml b/service/res/values-mcc311-mnc480-hy/strings.xml deleted file mode 100644 index f9bfdc2c8..000000000 --- a/service/res/values-mcc311-mnc480-hy/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> – Դուք չեք կարող միանալ Verizon Wi-Fi Access-ին, երբ Verizon-ի ծածկույթից դուրս եք։"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> – Դուք բաժանորդագրված չեք Verizon Wi-Fi Access-ին։ Զանգեք մեզ 800-922-0204 հեռախոսահամարով։"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> – Ձեր Verizon Wi-Fi Access հաշվի հետ կապված խնդիր կա։ Զանգեք մեզ 800-922-0204 հեռախոսահամարով։"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> – Դուք արդեն միացած եք Verizon Wi-Fi Access-ին։"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> – Verizon Wi-Fi Access-ին միանալու հետ կապված խնդիր կա։ Զանգեք մեզ 800-922-0204 հեռախոսահամարով։"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> – Ձեր Verizon Wi-Fi Access հաշվի հետ կապված խնդիր կա։ Զանգեք մեզ 800-922-0204 հեռախոսահամարով։"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> – Verizon Wi-Fi Access-ը հասանելի չէ ձեր գտնվելու վայրից։ Փորձեք ավելի ուշ կամ մեկ այլ վայրից։"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-in/strings.xml b/service/res/values-mcc311-mnc480-in/strings.xml deleted file mode 100644 index 9e2669fc8..000000000 --- a/service/res/values-mcc311-mnc480-in/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Anda tidak dapat terhubung ke Akses Wi-Fi Verizon dari luar area cakupan Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Anda tidak berlangganan Akses Wi-Fi Verizon. Harap hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Ada masalah dengan akun Akses Wi-Fi Verizon Anda. Harap hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Anda sudah terhubung ke Akses Wi-Fi Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Terjadi masalah saat menghubungkan ke Akses Wi-Fi Verizon Anda. Harap hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Ada masalah dengan akun Akses Wi-Fi Verizon Anda. Harap hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Akses Wi-Fi Verizon tidak tersedia di lokasi Anda. Coba lagi nanti atau coba dari lokasi yang berbeda."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-is/strings.xml b/service/res/values-mcc311-mnc480-is/strings.xml deleted file mode 100644 index 12581f838..000000000 --- a/service/res/values-mcc311-mnc480-is/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Ekki er hægt að tengjast Verizon Wi-Fi Access utan þjónustusvæðis Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Þú ert ekki áskrifandi að Verizon Wi-Fi Access. Hringdu í okkur í síma 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Vandamál kom upp í tengslum við Verizon Wi-Fi Access reikninginn þinn. Hringdu í okkur í síma 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Þú ert nú þegar tengd(ur) við Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Vandamál kom upp við að tengja þig við Verizon Wi-Fi Access. Hringdu í okkur í síma 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Vandamál kom upp í tengslum við Verizon Wi-Fi Access reikninginn þinn. Hringdu í okkur í síma 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access er ekki í boði þar sem þú ert. Reyndu aftur síðar eða á öðrum stað."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-it/strings.xml b/service/res/values-mcc311-mnc480-it/strings.xml deleted file mode 100644 index 09a4976dd..000000000 --- a/service/res/values-mcc311-mnc480-it/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: non puoi connetterti a Verizon Wi-Fi Access se sei fuori dell\'area di copertura Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: non hai un abbonamento a Verizon Wi-Fi Access. Chiamaci al numero 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: si è verificato un problema con il tuo account Verizon Wi-Fi Access. Chiamaci al numero 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: connessione a Verizon Wi-Fi Access già stabilita."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: si è verificato un problema di connessione a Verizon Wi-Fi Access. Chiamaci al numero 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: si è verificato un problema con il tuo account Verizon Wi-Fi Access. Chiamaci al numero 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access non è disponibile dalla tua posizione. Riprova più tardi o prova da un\'altra posizione."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-iw/strings.xml b/service/res/values-mcc311-mnc480-iw/strings.xml deleted file mode 100644 index 985e97a9d..000000000 --- a/service/res/values-mcc311-mnc480-iw/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : לא ניתן להתחבר לגישת Wi-Fi של Verizon מחוץ לאזור הכיסוי של Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : לא נרשמת לגישת Wi-Fi של Verizon. עליך להתקשר אלינו למספר 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : יש בעיה עם החשבון שלך לגישת Wi-Fi של Verizon. עליך להתקשר אלינו למספר 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : כבר יש לך חיבור לגישת Wi-Fi של Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : יש בעיה בהתחברות לגישת Wi-Fi של Verizon. עליך להתקשר אלינו למספר 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : יש בעיה עם החשבון שלך לגישת Wi-Fi של Verizon. עליך להתקשר אלינו למספר 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : גישת Wi-Fi של Verizon לא זמינה מהמיקום שלך. אפשר לנסות שוב מאוחר יותר או לנסות ממיקום אחר."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ja/strings.xml b/service/res/values-mcc311-mnc480-ja/strings.xml deleted file mode 100644 index 2fc19bd5b..000000000 --- a/service/res/values-mcc311-mnc480-ja/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon のサービスエリア外から Verizon Wi-Fi Access に接続することはできません。"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access に登録されていません。800-922-0204 までお電話でお問い合わせください。"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: お使いの Verizon Wi-Fi Access アカウントに問題があります。800-922-0204 までお電話でお問い合わせください。"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access にすでに接続しています。"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access への接続中に問題が発生しました。800-922-0204 までお電話でお問い合わせください。"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: お使いの Verizon Wi-Fi Access アカウントに問題があります。800-922-0204 までお電話でお問い合わせください。"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: 現在地では Verizon Wi-Fi Access はご利用いただけません。しばらくしてからもう一度お試しいただくか、場所を変えてお試しください。"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ka/strings.xml b/service/res/values-mcc311-mnc480-ka/strings.xml deleted file mode 100644 index 7dff68f5f..000000000 --- a/service/res/values-mcc311-mnc480-ka/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access-ს ვერ დაუკავშირდებით Verizon-ის დაფარვის ზონის გარეთ."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access გამოწერილი არ გაქვთ. გთხოვთ, დაგვირეკოთ ტელეფონზე 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: თქვენს Verizon Wi-Fi Access ანგარიშთან დაკავშირებით პრობლემა წარმოიშვა. გთხოვთ, დაგვირეკოთ ტელეფონზე 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: თქვენ უკვე დაკავშირებული ხართ Verizon Wi-Fi Access-თან."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access-თან დაკავშირებისას პრობლემა წარმოიშვა. გთხოვთ, დაგვირეკოთ ტელეფონზე 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: თქვენს Verizon Wi-Fi Access ანგარიშთან დაკავშირებით პრობლემა წარმოიშვა. გთხოვთ, დაგვირეკოთ ტელეფონზე 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access თქვენი მდებარეობიდან მიუწვდომელია. ცადეთ მოგვიანებით ან ცადეთ სხვა მდებარეობიდან."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-kk/strings.xml b/service/res/values-mcc311-mnc480-kk/strings.xml deleted file mode 100644 index 069ec93f9..000000000 --- a/service/res/values-mcc311-mnc480-kk/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қызметіне Verizon қызмет көрсету аясынан тыс жерден қосыла алмайсыз."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қызметіне жазылған жоқсыз. Бізге 800-922-0204 нөмірі арқылы хабарласыңыз."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access есептік жазбасына қатысты мәселе шықты. Бізге 800-922-0204 нөмірі арқылы хабарласыңыз."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қызметіне әлдеқашан қосылғансыз."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қызметіне қосылу кезінде мәселе шықты. Бізге 800-922-0204 нөмірі арқылы хабарласыңыз."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access есептік жазбасына қатысты мәселе шықты. Бізге 800-922-0204 нөмірі арқылы хабарласыңыз."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access қазіргі орналасқан жеріңізде жұмыс істемейді. Әрекетті кейінірек немесе басқа жерден қайталап көріңіз."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-km/strings.xml b/service/res/values-mcc311-mnc480-km/strings.xml deleted file mode 100644 index 329e87a6d..000000000 --- a/service/res/values-mcc311-mnc480-km/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>៖ អ្នកមិនអាចភ្ជាប់ទៅការចូលប្រើ Wi-Fi របស់ Verizon ពីក្រៅតំបន់គ្រប់ដណ្ដប់របស់ Verizon បានទេ។"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>៖ អ្នកមិនបានជាវការចូលប្រើ Wi-Fi របស់ Verizon ទេ។ សូមហៅទូរសព្ទមកយើងតាមរយៈលេខ 800-922-0204។"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>៖ មានបញ្ហាជាមួយគណនីចូលប្រើ Wi-Fi របស់ Verizon របស់អ្នក។ សូមហៅទូរសព្ទមកយើងតាមរយៈលេខ 800-922-0204។"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>៖ អ្នកបានភ្ជាប់ទៅការចូលប្រើ Wi-Fi របស់ Verizon រួចហើយ។"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>៖ មានបញ្ហាក្នុងការភ្ជាប់អ្នកទៅការចូលប្រើ Wi-Fi របស់ Verizon។ សូមហៅទូរសព្ទមកយើងតាមរយៈលេខ 800-922-0204។"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>៖ មានបញ្ហាជាមួយគណនីចូលប្រើ Wi-Fi របស់ Verizon របស់អ្នក។ សូមហៅទូរសព្ទមកយើងតាមរយៈលេខ 800-922-0204។"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>៖ មិនអាចប្រើការចូលប្រើ Wi-Fi របស់ Verizon ពីទីតាំងរបស់អ្នកបានទេ។ សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ ឬសាកល្បងពីទីតាំងផ្សេង។"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-kn/strings.xml b/service/res/values-mcc311-mnc480-kn/strings.xml deleted file mode 100644 index 5e3084780..000000000 --- a/service/res/values-mcc311-mnc480-kn/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon ಕವರೇಜ್ ಪ್ರದೇಶದ ಹೊರಗಿನಿಂದ Verizon ವೈ-ಫೈ ಪ್ರವೇಶಕ್ಕೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ನಿಮಗೆ ಸಾಧ್ಯವಿಲ್ಲ."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : ನೀವು Verizon ವೈ-ಫೈ ಪ್ರವೇಶಕ್ಕೆ ಸಬ್ಸ್ಕ್ರೈಬ್ ಆಗಿಲ್ಲ. ನಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸಲು 800-922-0204 ಗೆ ಕರೆ ಮಾಡಿ."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : ನಿಮ್ಮ Verizon ವೈ-ಫೈ ಪ್ರವೇಶ ಖಾತೆಯಲ್ಲಿ ಸಮಸ್ಯೆಯಿದೆ. ನಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸಲು 800-922-0204 ಗೆ ಕರೆ ಮಾಡಿ."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : ನೀವು ಈಗಾಗಲೇ Verizon ವೈ-ಫೈ ಪ್ರವೇಶಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಿರುವಿರಿ."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon ವೈ-ಫೈ ಪ್ರವೇಶಕ್ಕೆ ನಿಮ್ಮನ್ನು ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗುತ್ತಿದೆ. ನಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸಲು 800-922-0204 ಗೆ ಕರೆ ಮಾಡಿ."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : ನಿಮ್ಮ Verizon ವೈ-ಫೈ ಪ್ರವೇಶ ಖಾತೆಯಲ್ಲಿ ಸಮಸ್ಯೆಯಿದೆ. ನಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸಲು 800-922-0204 ಗೆ ಕರೆ ಮಾಡಿ."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : ನಿಮ್ಮ ಸ್ಥಳದಿಂದ Verizon ವೈ-ಫೈ ಪ್ರವೇಶ ಲಭ್ಯವಿಲ್ಲ. ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ ಅಥವಾ ಬೇರೊಂದು ಸ್ಥಳದಿಂದ ಪ್ರಯತ್ನಿಸಿ."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ko/strings.xml b/service/res/values-mcc311-mnc480-ko/strings.xml deleted file mode 100644 index b097a058f..000000000 --- a/service/res/values-mcc311-mnc480-ko/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon 서비스 지역 외부에서는 Verizon Wi-Fi Access에 연결할 수 없습니다."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access를 구독 중이 아닙니다. 800-922-0204번으로 문의하세요."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access 계정에 문제가 있습니다. 800-922-0204번으로 문의하세요."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: 이미 Verizon Wi-Fi Access에 연결되어 있습니다."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access에 연결하는 중에 문제가 발생했습니다. 800-922-0204번으로 문의하세요."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access 계정에 문제가 있습니다. 800-922-0204번으로 문의하세요."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: 해당 위치에서는 Verizon Wi-Fi Access를 이용할 수 없습니다. 나중에 다시 시도하거나 다른 장소에서 시도해 보세요."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ky/strings.xml b/service/res/values-mcc311-mnc480-ky/strings.xml deleted file mode 100644 index 0faa5c8c3..000000000 --- a/service/res/values-mcc311-mnc480-ky/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ке Verizon иштеген аймактан сырткары жерде туташа албайсыз."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ке катталган эмессиз. 800-922-0204 номерине телефон чалыңыз."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access аккаунтуңузда маселе келип чыкты. 800-922-0204 номерине телефон чалыңыз."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ке туташып турасыз."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access\'ке туташууда маселе келип чыкты. 800-922-0204 номерине телефон чалыңыз."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access аккаунтуңузда маселе келип чыкты. 800-922-0204 номерине телефон чалыңыз."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access сиз жүргөн жерде жеткиликтүү эмес. Кийинчерээк же башка жерден кайталаңыз."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-lo/strings.xml b/service/res/values-mcc311-mnc480-lo/strings.xml deleted file mode 100644 index 6680df540..000000000 --- a/service/res/values-mcc311-mnc480-lo/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : ທ່ານບໍ່ສາມາດເຊື່ອມຕໍ່ຫາ Verizon Wi-Fi Access ຈາກນອກພື້ນທີ່ຄອບຄຸມ Verizon ໄດ້."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : ທ່ານບໍ່ໄດ້ສະໝັກໃຊ້ Verizon Wi-Fi Access. ກະລຸນາໂທຫາພວກເຮົາທີ່ເບີ 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : ເກີດບັນຫາກັບບັນຊີ Verizon Wi-Fi Access ຂອງທ່ານ. ກະລຸນາໂທຫາພວກເຮົາທີ່ເບີ 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : ທ່ານເຊື່ອມຕໍ່ຫາ Verizon Wi-Fi Access ຢູ່ກ່ອນແລ້ວ."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : ເກີດບັນຫາໃນການເຊື່ອມຕໍ່ທ່ານຫາ Verizon Wi-Fi Access. ກະລຸນາໂທຫາພວກເຮົາທີ່ເບີ 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : ເກີດບັນຫາກັບບັນຊີ Verizon Wi-Fi Access ຂອງທ່ານ. ກະລຸນາໂທຫາພວກເຮົາທີ່ເບີ 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : ບໍ່ສາມາດໃຊ້ Verizon Wi-Fi Access ຈາກສະຖານທີ່ຂອງທ່ານໄດ້. ກະລຸນາລອງໃໝ່ ຫຼື ລອງຈາກສະຖານທີ່ອື່ນ."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-lt/strings.xml b/service/res/values-mcc311-mnc480-lt/strings.xml deleted file mode 100644 index 3c5f9f300..000000000 --- a/service/res/values-mcc311-mnc480-lt/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: negalite prisijungti prie „Verizon“ „Wi-Fi“ prieigos taško būdami ne „Verizon“ aprėpties zonoje."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: neprenumeruojate „Verizon“ „Wi-Fi“ prieigos taško. Paskambinkite telefono numeriu 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: iškilo su „Verizon“ „Wi-Fi“ prieigos taško paskyra susijusi problema. Paskambinkite telefono numeriu 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: jau esate prisijungę prie „Verizon“ „Wi-Fi“ prieigos taško."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: prisijungiant prie „Verizon“ „Wi-Fi“ prieigos taško kilo problema. Paskambinkite telefono numeriu 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: iškilo su „Verizon“ „Wi-Fi“ prieigos taško paskyra susijusi problema. Paskambinkite telefono numeriu 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: „Verizon“ „Wi-Fi“ prieigos taškas nepasiekiamas iš jūsų vietovės. Vėliau bandykite dar kartą arba pabandykite iš kitos vietovės."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-lv/strings.xml b/service/res/values-mcc311-mnc480-lv/strings.xml deleted file mode 100644 index 12197086f..000000000 --- a/service/res/values-mcc311-mnc480-lv/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: lai izveidotu savienojumu ar pakalpojumu Verizon Wi-Fi Access, ir jābūt Verizon pārklājuma zonā."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: jums nav Verizon Wi-Fi Access abonementa. Lūdzu, zvaniet mums uz numuru 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: radusies problēma ar jūsu Verizon Wi-Fi Access kontu. Lūdzu, zvaniet mums uz numuru 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: savienojums ar Verizon Wi-Fi Access jau ir izveidots."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: veidojot savienojumu ar pakalpojumu Verizon Wi-Fi Access, radās problēma. Lūdzu, zvaniet mums uz numuru 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: radusies problēma ar jūsu Verizon Wi-Fi Access kontu. Lūdzu, zvaniet mums uz numuru 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: jūsu atrašanās vietā pakalpojums Verizon Wi-Fi Access nav pieejams. Vēlāk mēģiniet vēlreiz, vai arī mēģiniet izveidot savienojumu no citas atrašanās vietas."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-mk/strings.xml b/service/res/values-mcc311-mnc480-mk/strings.xml deleted file mode 100644 index 3f3375632..000000000 --- a/service/res/values-mcc311-mnc480-mk/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: не може да се поврзете на Verizon Wi-Fi Access надвор од областа на покривање на Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: не сте претплатени на Verizon Wi-Fi Access. Контактирајте со нас на 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: проблем со вашата сметка на Verizon Wi-Fi Access. Контактирајте со нас на 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: веќе сте поврзани на Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: наидовме на проблем при обидот да ве поврземе на Verizon Wi-Fi Access. Контактирајте со нас на 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: проблем со вашата сметка на Verizon Wi-Fi Access. Контактирајте со нас на 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access не е достапна од вашата локација. Обидете повторно подоцна или обидете се од друга локација."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ml/strings.xml b/service/res/values-mcc311-mnc480-ml/strings.xml deleted file mode 100644 index f978b3c6e..000000000 --- a/service/res/values-mcc311-mnc480-ml/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon കവറേജ് ഏരിയയ്ക്ക് പുറത്ത് നിന്ന് നിങ്ങൾക്ക് Verizon വൈഫൈ ആക്സസിലേക്ക് കണക്റ്റ് ചെയ്യാനാകില്ല."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon വൈഫൈ ആക്സസിലേക്ക് നിങ്ങൾ സബ്സ്ക്രൈബ് ചെയ്തിട്ടില്ല. ഞങ്ങളുടെ 800-922-0204 എന്ന നമ്പറിൽ വിളിക്കുക."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : നിങ്ങളുടെ Verizon വൈഫൈ ആക്സസ് അക്കൗണ്ടുമായി ബന്ധപ്പെട്ട് ഒരു പ്രശ്നമുണ്ട്. ഞങ്ങളുടെ 800-922-0204 എന്ന നമ്പറിൽ വിളിക്കുക."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : നിങ്ങൾ മുമ്പേ തന്നെ Verizon വൈഫൈ ആക്സസിലേക്ക് കണക്റ്റ് ചെയ്തിട്ടുണ്ട്."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon വൈഫൈ ആക്സസ് അക്കൗണ്ടിലേക്ക് നിങ്ങളെ കണക്റ്റ് ചെയ്യുന്നതിൽ ഒരു പ്രശ്നമുണ്ട്. ഞങ്ങളുടെ 800-922-0204 എന്ന നമ്പറിൽ വിളിക്കുക."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : നിങ്ങളുടെ Verizon വൈഫൈ ആക്സസ് അക്കൗണ്ടുമായി ബന്ധപ്പെട്ട് ഒരു പ്രശ്നമുണ്ട്. ഞങ്ങളുടെ 800-922-0204 എന്ന നമ്പറിൽ വിളിക്കുക."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon വൈഫൈ ആക്സസ് നിങ്ങളുടെ ലൊക്കേഷനില് ലഭ്യമല്ല. മറ്റൊരു ലൊക്കേഷനിൽ നിന്ന് പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-mn/strings.xml b/service/res/values-mcc311-mnc480-mn/strings.xml deleted file mode 100644 index f8fa830a8..000000000 --- a/service/res/values-mcc311-mnc480-mn/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Та Verizon-ы хамрах бүсийн гаднаас Verizon Wi-Fi хандалтад холбогдох боломжгүй."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Та Verizon Wi-Fi хандалтад бүртгүүлээгүй байна. 800-922-0204 дугаар луу залгаж, бидэнтэй холбогдоно уу."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Таны Verizon Wi-Fi хандалтын бүртгэлтэй холбоотой асуудал гарлаа. 800-922-0204 дугаар луу залгаж, бидэнтэй холбогдоно уу."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Та Verizon Wi-Fi хандалтад хэдийн холбогдсон байна."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Таныг Verizon Wi-Fi хандалтад холбоход асуудал гарлаа. 800-922-0204 дугаар луу залгаж, бидэнтэй холбогдоно уу."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Таны Verizon Wi-Fi хандалтын бүртгэлтэй холбоотой асуудал гарлаа. 800-922-0204 дугаар луу залгаж, бидэнтэй холбогдоно уу."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi хандалт нь таны байршлаас боломжгүй байна. Дараа дахин оролдох эсвэл өөр байршлаас оролдоно уу."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-mr/strings.xml b/service/res/values-mcc311-mnc480-mr/strings.xml deleted file mode 100644 index 032b179f5..000000000 --- a/service/res/values-mcc311-mnc480-mr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : तुम्ही व्हेरिझॉन कव्हरेज क्षेत्राच्या बाहेरून व्हेरिझॉन वाय-फाय अॅक्सेस शी कनेक्ट करू शकत नाही."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : तुम्ही व्हेरिझॉन वाय-फाय अॅक्सेस चे सदस्यत्व घेतलेले नाही. कृपया आम्हाला ८००-९२२-०२०४ वर कॉल करा."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : तुमच्या व्हेरिझॉन वाय-फाय अॅक्सेस खात्यामध्ये समस्या आहे. कृपया आम्हाला ८००-९२२-०२०४ वर कॉल करा."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : तुम्ही आधीपासून व्हेरिझॉन वाय-फाय अॅक्सेस शी कनेक्ट केलेले आहे."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : तुम्हाला व्हेरिझॉन वाय-फाय अॅक्सेस शी कनेक्ट करण्यात समस्या आहे. कृपया आम्हाला ८००-९२२-०२०४ वर कॉल करा."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : तुमच्या व्हेरिझॉन वाय-फाय अॅक्सेस खात्यामध्ये समस्या आहे. कृपया आम्हाला ८००-९२२-०२०४ वर कॉल करा."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : तुमच्या स्थानावरून व्हेरिझॉन वाय-फाय अॅक्सेस उपलब्ध नाही. नंतर पुन्हा प्रयत्न करा किंवा वेगळ्या स्थानावरून प्रयत्न करा."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ms/strings.xml b/service/res/values-mcc311-mnc480-ms/strings.xml deleted file mode 100644 index 2c99d6b0e..000000000 --- a/service/res/values-mcc311-mnc480-ms/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Anda tidak boleh menyambung ke Verizon Wi-Fi Access dari luar kawasan liputan Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Anda tidak melanggan Verizon Wi-Fi Access. Sila hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Terdapat masalah dengan akaun Verizon Wi-Fi Access anda. Sila hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Anda sudah disambungkan ke Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Terdapat masalah semasa menyambungkan anda ke Verizon Wi-Fi Access. Sila hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Terdapat masalah dengan akaun Verizon Wi-Fi Access anda. Sila hubungi kami di 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access tidak tersedia dari lokasi anda. Cuba lagi nanti atau cuba dari lokasi lain."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-my/strings.xml b/service/res/values-mcc311-mnc480-my/strings.xml deleted file mode 100644 index f1708a372..000000000 --- a/service/res/values-mcc311-mnc480-my/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> - Verizon ဝန်ဆောင်မှုမရှိသည့်နေရာမှနေ၍ Verizon Wi-Fi Access သို့ ချိတ်ဆက်၍မရပါ။"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> - သင်သည် Verizon Wi-Fi Access သို့ စာရင်းသွင်းမထားပါ။ ၈၀၀-၉၂၂-၀၂၀၄ ကို ခေါ်ပါ။"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> - သင့် Verizon Wi-Fi Access အကောင့်တွင် ပြဿနာရှိနေသည်။ ၈၀၀-၉၂၂-၀၂၀၄ ကို ခေါ်ပါ။"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> - သင်သည် Verizon Wi-Fi Access သို့ ချိတ်ဆက်ထားပြီးဖြစ်သည်။"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> - Verizon Wi-Fi Access သို့ ချိတ်ဆက်ရာတွင် ပြဿနာရှိနေသည်။ ၈၀၀-၉၂၂-၀၂၀၄ ကို ခေါ်ပါ။"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> - သင့် Verizon Wi-Fi Access အကောင့်တွင် ပြဿနာရှိနေသည်။ ၈၀၀-၉၂၂-၀၂၀၄ ကို ခေါ်ပါ။"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> - သင့်တည်နေရာတွင် Verizon Wi-Fi Access မရနိုင်ပါ။ နောက်မှထပ်စမ်းကြည့်ပါ သို့မဟုတ် အခြားတည်နေရာမှနေ၍ စမ်းကြည့်ပါ။"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-nb/strings.xml b/service/res/values-mcc311-mnc480-nb/strings.xml deleted file mode 100644 index 4f25a26d8..000000000 --- a/service/res/values-mcc311-mnc480-nb/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Du kan ikke koble til Verizon Wi-Fi Access fra utenfor Verizons dekningsområde."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Du abonnerer ikke på Verizon Wi-Fi Access. Ring oss på 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Det har oppstått et problem med Verizon Wi-Fi Access-kontoen din. Ring oss på 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Du er allerede koblet til Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Det har oppstått et problem med å koble deg til Verizon Wi-Fi Access. Ring oss på 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Det har oppstått et problem med Verizon Wi-Fi Access-kontoen din. Ring oss på 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access er ikke tilgjengelig fra der du er. Prøv igjen senere, eller prøv fra et annet sted."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ne/strings.xml b/service/res/values-mcc311-mnc480-ne/strings.xml deleted file mode 100644 index bbd5aca90..000000000 --- a/service/res/values-mcc311-mnc480-ne/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईं Verizon कभरेज क्षेत्र बाहिरबाट Verizon Wi-Fi Access मा जोडिन सक्नुहुन्न।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईंले Verizon Wi-Fi Access को सदस्यता लिनुभएको छैन। कृपया 800-922-0204 मा फोन गर्नुहोस्।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईंको Verizon Wi-Fi Access खातामा कुनै समस्या छ। कृपया 800-922-0204 मा फोन गर्नुहोस्।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईं अहिले Verizon Wi-Fi Access मा नै जोडिनुभएको छ।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईंलाई Verizon Wi-Fi Access मा जोड्ने क्रममा कुनै समस्या भयो। कृपया 800-922-0204 मा फोन गर्नुहोस्।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईंको Verizon Wi-Fi Access खातामा कुनै समस्या छ। कृपया 800-922-0204 मा फोन गर्नुहोस्।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : तपाईं रहेको स्थानमा Verizon Wi-Fi Access उपलब्ध छैन। पछि फेरि प्रयास गर्नुहोस् वा अर्को स्थानमा गएर जोडिने प्रयास गर्नुहोस्।"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-nl/strings.xml b/service/res/values-mcc311-mnc480-nl/strings.xml deleted file mode 100644 index f1f4cbca4..000000000 --- a/service/res/values-mcc311-mnc480-nl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: Je kunt buiten het dekkingsgebied van Verizon geen verbinding maken met Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Je hebt geen abonnement op Verizon Wi-Fi Access. Bel ons op 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: Er is een probleem met je Verizon Wi-Fi Access-account. Bel ons op 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: Je hebt al verbinding met Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Er is een probleem bij het maken van verbinding met Verizon Wi-Fi Access. Bel ons op 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: Er is een probleem met je Verizon Wi-Fi Access-account. Bel ons op 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access is niet beschikbaar op jouw locatie. Probeer het later opnieuw of ga naar een andere locatie."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-or/strings.xml b/service/res/values-mcc311-mnc480-or/strings.xml deleted file mode 100644 index 5937ca3a6..000000000 --- a/service/res/values-mcc311-mnc480-or/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣ Verizon କଭରେଜ୍ କ୍ଷେତ୍ର ବାହାରେ Verizon Wi-Fi Access ସହ ସଂଯୋଗ କରିପାରିବେ ନାହିଁ।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣ Verizon Wi-Fi Accessର ସଦସ୍ୟତା ନେଇ ନାହାଁନ୍ତି। ଦୟାକରି 800-922-0204ରେ ଆମକୁ କଲ୍ କରନ୍ତୁ।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣଙ୍କ Verizon Wi-Fi Access ଆକାଉଣ୍ଟରେ ଏକ ସମସ୍ୟା ହୋଇଛି। ଦୟାକରି 800-922-0204ରେ ଆମକୁ କଲ୍ କରନ୍ତୁ।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣ ପୂର୍ବରୁ Verizon Wi-Fi Access ସହ ସଂଯୋଗ କରିସାରିଛନ୍ତି।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣଙ୍କୁ Verizon Wi-Fi Access ସହ ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଦୟାକରି 800-922-0204ରେ ଆମକୁ କଲ୍ କରନ୍ତୁ।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : ଆପଣଙ୍କ Verizon Wi-Fi Access ଆକାଉଣ୍ଟରେ ଏକ ସମସ୍ୟା ହୋଇଛି। ଦୟାକରି 800-922-0204ରେ ଆମକୁ କଲ୍ କରନ୍ତୁ।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ଆପଣଙ୍କ ଲୋକେସନରେ ଉପଲବ୍ଧ ନାହିଁ। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ କିମ୍ବା ଏକ ଭିନ୍ନ ଲୋକେସନରୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-pa/strings.xml b/service/res/values-mcc311-mnc480-pa/strings.xml deleted file mode 100644 index 646b870a8..000000000 --- a/service/res/values-mcc311-mnc480-pa/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਸੀਂ Verizon ਕਵਰੇਜ ਖੇਤਰ ਤੋਂ ਬਾਹਰ Verizon Wi-Fi Access ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਸੀਂ Verizon Wi-Fi Access ਲਈ ਗਾਹਕੀ ਨਹੀਂ ਲਈ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ 800-922-0204 \'ਤੇ ਕਾਲ ਕਰੋ।"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਹਾਡੇ Verizon Wi-Fi Access ਖਾਤੇ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ 800-922-0204 \'ਤੇ ਕਾਲ ਕਰੋ।"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਸੀਂ ਪਹਿਲਾਂ ਤੋਂ ਹੀ Verizon Wi-Fi Access ਨਾਲ ਕਨੈਕਟ ਹੋ।"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਹਾਨੂੰ Verizon Wi-Fi Access ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ 800-922-0204 \'ਤੇ ਕਾਲ ਕਰੋ।"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : ਤੁਹਾਡੇ Verizon Wi-Fi Access ਖਾਤੇ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ 800-922-0204 \'ਤੇ ਕਾਲ ਕਰੋ।"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਤੋਂ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜਾਂ ਕਿਸੇ ਹੋਰ ਟਿਕਾਣੇ ਤੋਂ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-pl/strings.xml b/service/res/values-mcc311-mnc480-pl/strings.xml deleted file mode 100644 index b8ebab502..000000000 --- a/service/res/values-mcc311-mnc480-pl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : nie możesz połączyć się z Wi-Fi Verizon poza obszarem obsługiwanym przez Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : nie subskrybujesz Wi-Fi Verizon. Zadzwoń pod numer +1 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : wystąpił problem z Twoim kontem Wi-Fi Verizon. Zadzwoń pod numer +1 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : już jesteś połączony z Wi-Fi Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : wystąpił problem z połączeniem z Wi-Fi Verizon. Zadzwoń pod numer +1 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : wystąpił problem z Twoim kontem Wi-Fi Verizon. Zadzwoń pod numer +1 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Wi-Fi Verizon jest niedostępne w Twojej lokalizacji. Spróbuj ponownie później lub z innej lokalizacji."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-pt-rBR/strings.xml b/service/res/values-mcc311-mnc480-pt-rBR/strings.xml deleted file mode 100644 index 4fab5ce63..000000000 --- a/service/res/values-mcc311-mnc480-pt-rBR/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: não é possível se conectar ao Verizon Wi-Fi Access fora da área de cobertura."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: você não se inscreveu no Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema com sua conta do Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: você já se conectou ao Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema na conexão com o Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema com sua conta do Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: o Verizon Wi-Fi Access não está disponível neste local. Tente novamente mais tarde ou de um local diferente."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-pt-rPT/strings.xml b/service/res/values-mcc311-mnc480-pt-rPT/strings.xml deleted file mode 100644 index bc1f6f433..000000000 --- a/service/res/values-mcc311-mnc480-pt-rPT/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: não é possível estabelecer ligação ao ponto de acesso Wi-Fi da Verizon fora da área de cobertura da Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: não possui uma subscrição do ponto de acesso Wi-Fi da Verizon. Contacte-nos através do número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: existe um problema com a sua conta do ponto de acesso Wi-Fi da Verizon. Contacte-nos através do número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: já tem ligação ao ponto de acesso Wi-Fi da Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: ocorreu um problema ao estabelecer ligação ao ponto de acesso Wi-Fi da Verizon. Contacte-nos através do número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: existe um problema com a sua conta do ponto de acesso Wi-Fi da Verizon. Contacte-nos através do número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: o ponto de acesso Wi-Fi da Verizon não está disponível a partir da sua localização. Tente novamente mais tarde ou experimente a partir de uma localização diferente."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-pt/strings.xml b/service/res/values-mcc311-mnc480-pt/strings.xml deleted file mode 100644 index 4fab5ce63..000000000 --- a/service/res/values-mcc311-mnc480-pt/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: não é possível se conectar ao Verizon Wi-Fi Access fora da área de cobertura."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: você não se inscreveu no Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema com sua conta do Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: você já se conectou ao Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema na conexão com o Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: há um problema com sua conta do Verizon Wi-Fi Access. Entre em contato pelo número 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: o Verizon Wi-Fi Access não está disponível neste local. Tente novamente mais tarde ou de um local diferente."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ro/strings.xml b/service/res/values-mcc311-mnc480-ro/strings.xml deleted file mode 100644 index 8f0b4574d..000000000 --- a/service/res/values-mcc311-mnc480-ro/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : nu vă puteți conecta la Verizon Wi-Fi Access în afara ariei de acoperire Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : nu v-ați abonat la Verizon Wi-Fi Access. Apelați-ne la 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : există o problemă legată de contul dvs. Verizon Wi-Fi Access. Apelați-ne la 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : v-ați conectat deja la Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : există o problemă legată de conectarea la Verizon Wi-Fi Access. Apelați-ne la 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : există o problemă legată de contul dvs. Verizon Wi-Fi Access. Apelați-ne la 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access nu este disponibil în locația dvs. Încercați din nou mai târziu sau încercați dintr-o altă locație."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ru/strings.xml b/service/res/values-mcc311-mnc480-ru/strings.xml deleted file mode 100644 index 56e51cbc8..000000000 --- a/service/res/values-mcc311-mnc480-ru/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: вы не можете подключиться к сервису Verizon Wi-Fi Access вне зоны покрытия Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: вы не подписаны на сервис Verizon Wi-Fi Access. Позвоните нам по номеру 800 922-02-04."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: возникла проблема с вашим аккаунтом Verizon Wi-Fi Access. Позвоните нам по номеру 800 922-02-04."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: вы уже подключены к сервису Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: не удалось подключиться к сервису Verizon Wi-Fi Access. Позвоните нам по номеру 800 922-02-04."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: возникла проблема с вашим аккаунтом Verizon Wi-Fi Access. Позвоните нам по номеру 800 922-02-04."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: сервис Verizon Wi-Fi Access недоступен там, где вы находитесь. Повторите попытку позже или в другом месте."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-si/strings.xml b/service/res/values-mcc311-mnc480-si/strings.xml deleted file mode 100644 index 3bba7e498..000000000 --- a/service/res/values-mcc311-mnc480-si/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon ආවරණ ප්රදේශයට පිටතින් ඔබට Verizon Wi-Fi ප්රවේශය වෙත සම්බන්ධ විය නොහැකිය."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබ Verizon Wi-Fi ප්රවේශය වෙත දායක වී නැත. කරුණාකර 800-922-0204 අංකයෙන් අපට අමතන්න."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබේ Verizon Wi-Fi ප්රවේශ ගිණුම හා ගැටලුවක් තිබේ. කරුණාකර 800-922-0204 අංකයෙන් අපට අමතන්න."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබ දැනටමත් Verizon Wi-Fi ප්රවේශය වෙත සම්බන්ධ වී ඇත."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබව Verizon Wi-Fi ප්රවේශය වෙත සම්බන්ධ කිරීමේ ගැටලුවක් තිබේ. කරුණාකර 800-922-0204 අංකයෙන් අපට අමතන්න."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : ඔබේ Verizon Wi-Fi ප්රවේශ ගිණුම හා ගැටලුවක් තිබේ. කරුණාකර 800-922-0204 අංකයෙන් අපට අමතන්න."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi ප්රවේශය ඔබේ ස්ථානය වෙතින් ලබා ගත නොහැකිය. පසුව නැවත උත්සාහ කරන්න නැතහොත් වෙනත් ස්ථානයකින් උත්සාහ කරන්න."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-sk/strings.xml b/service/res/values-mcc311-mnc480-sk/strings.xml deleted file mode 100644 index faefbc9dc..000000000 --- a/service/res/values-mcc311-mnc480-sk/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : K službe Verizon Wi-Fi Access sa nemôžete pripojiť mimo oblasti, v ktorej Verizon poskytuje služby."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Službu Verizon Wi-Fi Access neodoberáte. Zavolajte na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Vyskytol sa problém s vaším účtom Verizon Wi-Fi Access. Zavolajte na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : K službe Verizon Wi-Fi Access ste sa už pripojili."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Pri pripájaní vášho účtu k službe Verizon Wi-Fi Access sa vyskytol problém. Zavolajte na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Vyskytol sa problém s vaším účtom Verizon Wi-Fi Access. Zavolajte na číslo 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access nie je k dispozícii vo vašej oblasti. Skúste to znova alebo pokus zopakujte v inej oblasti."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-sl/strings.xml b/service/res/values-mcc311-mnc480-sl/strings.xml deleted file mode 100644 index 9975c367c..000000000 --- a/service/res/values-mcc311-mnc480-sl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: Povezave s storitvijo Verizon Wi-Fi Access ni mogoče vzpostaviti zunaj območja, ki ga pokriva operater Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Niste naročeni na storitev Verizon Wi-Fi Access. Pokličite nas na 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: Prišlo je do težave z vašim računom za storitev Verizon Wi-Fi Access. Pokličite nas na 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: Povezava s storitvijo Verizon Wi-Fi Access je že vzpostavljena."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Prišlo je do težave pri povezovanju s storitvijo Verizon Wi-Fi Access. Pokličite nas na 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: Prišlo je do težave z vašim računom za storitev Verizon Wi-Fi Access. Pokličite nas na 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Storitev Verizon Wi-Fi Access ni na voljo na vaši lokaciji. Poskusite znova pozneje ali z druge lokacije."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-sq/strings.xml b/service/res/values-mcc311-mnc480-sq/strings.xml deleted file mode 100644 index 77953eb83..000000000 --- a/service/res/values-mcc311-mnc480-sq/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Nuk mund të lidhesh me Verizon Wi-Fi Access nga jashtë zonës së mbulimit të Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Nuk je abonuar në Verizon Wi-Fi Access. Na telefono në 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Ka një problem me llogarinë tënde të Verizon Wi-Fi Access. Na telefono në 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Je lidhur tashmë me Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Ka një problem gjatë lidhjes sate me Verizon Wi-Fi Access. Na telefono në 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Ka një problem me llogarinë tënde të Verizon Wi-Fi Access. Na telefono në 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access nuk ofrohet nga vendndodhja jote. Provo përsëri më vonë ose provo nga një vendndodhje tjetër."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-sr/strings.xml b/service/res/values-mcc311-mnc480-sr/strings.xml deleted file mode 100644 index 05b637a8a..000000000 --- a/service/res/values-mcc311-mnc480-sr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Не можете да се повежете на Verizon WiFi Access ван области коју Verizon покрива."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Нисте претплаћени на Verizon WiFi Access. Позовите нас на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon WiFi Access налогом. Позовите нас на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Већ сте повезани на Verizon WiFi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Постоји проблем при повезивању на Verizon WiFi Access. Позовите нас на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon WiFi Access налогом. Позовите нас на 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon WiFi Access није доступан са ваше локације. Пробајте поново касније или пробајте са неке друге локације."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-sv/strings.xml b/service/res/values-mcc311-mnc480-sv/strings.xml deleted file mode 100644 index 58de1f233..000000000 --- a/service/res/values-mcc311-mnc480-sv/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Det går inte att ansluta till Verizon Wi-Fi Access om du befinner dig utanför Verizons täckningsområde."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Du prenumererar inte på Verizon Wi-Fi Access. Ring oss på 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Ett fel har uppstått i Verizon Wi-Fi Access-kontot. Ring oss på 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Du är redan ansluten till Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Det gick inte att ansluta till Verizon Wi-Fi Access. Ring oss på 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Ett fel har uppstått i Verizon Wi-Fi Access-kontot. Ring oss på 800 922 0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access är inte tillgängligt där du befinner dig. Försök igen senare eller anslut från en annan plats."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-sw/strings.xml b/service/res/values-mcc311-mnc480-sw/strings.xml deleted file mode 100644 index 176085c4a..000000000 --- a/service/res/values-mcc311-mnc480-sw/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Huwezi kuunganisha kwenye Ufikiaji wa Wi-Fi ya Verizon ukiwa nje ya eneo la mtandao wa Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Hujajisajili kwenye Ufikiaji wa Wi-Fi ya Verizon. Tafadhali tupigie kwa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Kuna hitilafu ya Akaunti yako ya Ufikiaji wa Wi-Fi ya Verizon. Tafadhali tupigie kwa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Tayari umeunganisha kwenye Ufikiaji wa Wi-Fi ya Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Kuna hitilafu ya kuunganisha kwenye Ufikiaji wa Wi-Fi ya Verizon. Tafadhali tupigie kwa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Kuna hitilafu ya Akaunti yako ya Ufikiaji wa Wi-Fi ya Verizon. Tafadhali tupigie kwa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Ufikiaji wa Wi-Fi ya Verizon haupatikani katika eneo lako. Jaribu tena baadaye au ujaribu ukiwa katika eneo tofauti."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ta/strings.xml b/service/res/values-mcc311-mnc480-ta/strings.xml deleted file mode 100644 index 79239efdd..000000000 --- a/service/res/values-mcc311-mnc480-ta/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon கவரேஜ் பகுதியைத் தாண்டி Verizon வைஃபை Accessஸுடன் இணைக்க முடியாது."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : நீங்கள் Verizon வைஃபை Accessஸிற்கு சந்தா செய்யவில்லை. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் Verizon வைஃபை Access கணக்கில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon வைஃபை Accessஸுடன் ஏற்கெனவே இணைப்பில் உள்ளீர்கள்."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon வைஃபை Accessஸுடன் இணைப்பதில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் Verizon வைஃபை Access கணக்கில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் பகுதிக்கு Verizon வைஃபை Access சேவை கிடைக்கவில்லை. மீண்டும் முயலவும் அல்லது வேறு இருப்பிடத்தில் இருந்து முயலவும்."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-te/strings.xml b/service/res/values-mcc311-mnc480-te/strings.xml deleted file mode 100644 index 01f5250b6..000000000 --- a/service/res/values-mcc311-mnc480-te/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : మీరు Verizon కవరేజీ ప్రాంతానికి వెలుపల నుండి Verizon Wi-Fi యాక్సెస్కు కనెక్ట్ చేయలేరు."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : మీరు Verizon Wi-Fi యాక్సెస్కు సభ్యత్వం పొందలేదు. 800-922-0204 నంబర్ వద్ద దయచేసి మాకు కాల్ చేయండి."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : మీ Verizon Wi-Fi యాక్సెస్ ఖాతాలో సమస్య ఉంది. 800-922-0204 నంబర్ వద్ద దయచేసి మాకు కాల్ చేయండి."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : మీరు ఇప్పటికే Verizon Wi-Fi యాక్సెస్కు కనెక్ట్ చేయబడ్డారు."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi యాక్సెస్కు మిమ్మల్ని కనెక్ట్ చేయడంలో సమస్య ఉంది. 800-922-0204 నంబర్ వద్ద దయచేసి మాకు కాల్ చేయండి."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : మీ Verizon Wi-Fi యాక్సెస్ ఖాతాలో సమస్య ఉంది. 800-922-0204 నంబర్ వద్ద దయచేసి మాకు కాల్ చేయండి."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : మీ లొకేషన్ వద్ద Verizon Wi-Fi యాక్సెస్ అందుబాటులో లేదు. తర్వాత మళ్లీ ప్రయత్నించండి లేదా వేరే లొకేషన్ నుండి ప్రయత్నించండి."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-th/strings.xml b/service/res/values-mcc311-mnc480-th/strings.xml deleted file mode 100644 index aec60e692..000000000 --- a/service/res/values-mcc311-mnc480-th/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : คุณเชื่อมต่อกับ Verizon Wi-Fi Access จากนอกพื้นที่ให้บริการของ Verizon ไม่ได้"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : คุณไม่ได้สมัครใช้บริการ Verizon Wi-Fi Access โปรดโทรหาเราที่ 800-922-0204"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : บัญชี Verizon Wi-Fi Access ของคุณมีปัญหา โปรดโทรหาเราที่ 800-922-0204"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : คุณเชื่อมต่อกับ Verizon Wi-Fi Access แล้ว"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : มีปัญหาในการเชื่อมต่อคุณกับ Verizon Wi-Fi Access โปรดโทรหาเราที่ 800-922-0204"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : บัญชี Verizon Wi-Fi Access ของคุณมีปัญหา โปรดโทรหาเราที่ 800-922-0204"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access ไม่พร้อมให้บริการจากตำแหน่งของคุณ โปรดลองอีกครั้งในภายหลังหรือลองจากตำแหน่งอื่น"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-tl/strings.xml b/service/res/values-mcc311-mnc480-tl/strings.xml deleted file mode 100644 index 564638a61..000000000 --- a/service/res/values-mcc311-mnc480-tl/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Hindi ka puwedeng kumonekta sa Verizon Wi-Fi Access mula sa labas ng lugar na saklaw ng Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Hindi ka naka-subscribe sa Verizon Wi-Fi Access. Pakitawagan kami sa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : May problema sa iyong Verizon Wi-Fi Access account. Pakitawagan kami sa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Nakakonekta ka na sa Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : May problema sa pagkonekta sa iyo sa Verizon Wi-Fi Access. Pakitawagan kami sa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : May problema sa iyong Verizon Wi-Fi Access account. Pakitawagan kami sa 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Hindi available sa iyong lokasyon ang Verizon Wi-Fi Access. Subukan ulit sa ibang pagkakataon o subukan mula sa ibang lokasyon."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-tr/strings.xml b/service/res/values-mcc311-mnc480-tr/strings.xml deleted file mode 100644 index c6d9ff23f..000000000 --- a/service/res/values-mcc311-mnc480-tr/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon\'ın kapsama alanının dışından Verizon Wi-Fi Access\'e bağlanamazsınız."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access abonesi değilsiniz. Bize ulaşmak için lütfen 800-922-0204 numaralı telefonu arayın."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access hesabınızla ilgili bir sorun var. Bize ulaşmak için lütfen 800-922-0204 numaralı telefonu arayın."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access\'e zaten bağlısınız."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access\'e bağlanırken bir sorun oluştu. Bize ulaşmak için lütfen 800-922-0204 numaralı telefonu arayın."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access hesabınızla ilgili bir sorun var. Bize ulaşmak için lütfen 800-922-0204 numaralı telefonu arayın."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: Verizon Wi-Fi Access bulunduğunuz konumdan kullanılamıyor. Daha sonra tekrar deneyin veya farklı bir konumdan bağlanmaya çalışın."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-uk/strings.xml b/service/res/values-mcc311-mnc480-uk/strings.xml deleted file mode 100644 index 6aa2a5081..000000000 --- a/service/res/values-mcc311-mnc480-uk/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>: не можна підключитися до Verizon Wi-Fi Access за межами зони покриття."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>: у вас немає підписки на Verizon Wi-Fi Access. Зателефонуйте нам на номер 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>: виникла проблема з вашим обліковим записом Verizon Wi-Fi Access. Зателефонуйте нам на номер 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>: пристрій уже підключено до Verizon Wi-Fi Access."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>: не вдалося підключитися до Verizon Wi-Fi Access. Зателефонуйте нам на номер 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>: виникла проблема з вашим обліковим записом Verizon Wi-Fi Access. Зателефонуйте нам на номер 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>: сервіс Verizon Wi-Fi Access недоступний за вашим розташуванням. Повторіть спробу пізніше або змініть місцезнаходження."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-ur/strings.xml b/service/res/values-mcc311-mnc480-ur/strings.xml deleted file mode 100644 index 730c2fd8b..000000000 --- a/service/res/values-mcc311-mnc480-ur/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : آپ Verizon کوریج علاقہ کے باہر سے Verizon Wi-Fi رسائی کے لیے منسلک نہیں کر سکتے ہیں۔"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : آپ Verizon Wi-Fi رسائی کے رکن نہیں ہیں۔ براہ کرم ہمیں 0204-922-800 پر کال کریں۔"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : آپ کے Verizon Wi-Fi رسائی اکاؤنٹ کے ساتھ ایک مسئلہ ہے۔ براہ کرم ہمیں 0204-922-800 پر کال کریں۔"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : آپ پہلے سے ہی Verizon Wi-Fi رسائی سے منسلک ہیں۔"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : آپ کو Verizon Wi-Fi رسائی سے منسلک ہونے میں ایک مسئلہ ہے۔ براہ کرم ہمیں 0204-922-800 پر کال کریں۔"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : آپ کے Verizon Wi-Fi رسائی اکاؤنٹ کے ساتھ ایک مسئلہ ہے۔ براہ کرم ہمیں 0204-922-800 پر کال کریں۔"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi رسائی آپ کے مقام سے دستیاب نہیں ہے۔ بعد میں دوبارہ کوشش کریں یا دوسرے مقام سے کوشش کر کے دیکھیں۔"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-uz/strings.xml b/service/res/values-mcc311-mnc480-uz/strings.xml deleted file mode 100644 index 83125d05a..000000000 --- a/service/res/values-mcc311-mnc480-uz/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon qamrovidan tashqarida Verizon Wi-Fi Access xizmatiga ulana olmaysiz."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access xizmatiga obuna boʻlmagansiz. 800-922-0204 raqamiga telefon qiling."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access hisobingiz bilan muammo bor. 800-922-0204 raqamiga telefon qiling."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Allaqachon Verizon Wi-Fi Access xizmatiga ulangansiz."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access xizmatiga ulanishda muammo chiqdi. 800-922-0204 raqamiga telefon qiling."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access hisobingiz bilan muammo bor. 800-922-0204 raqamiga telefon qiling."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access siz turgan joyda ishlamaydi. Keyinroq qayta urining yoki boshqa joydan urining."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-vi/strings.xml b/service/res/values-mcc311-mnc480-vi/strings.xml deleted file mode 100644 index 4c4c9dad3..000000000 --- a/service/res/values-mcc311-mnc480-vi/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Bạn không thể kết nối với dịch vụ Truy cập Wi-Fi của Verizon từ bên ngoài khu vực phủ sóng của Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Bạn chưa đăng ký dịch vụ Truy cập Wi-Fi của Verizon. Vui lòng gọi cho chúng tôi theo số 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Đã xảy ra sự cố với tài khoản Truy cập Wi-Fi của Verizon mà bạn có. Vui lòng gọi cho chúng tôi theo số 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Bạn đã kết nối với dịch vụ Truy cập Wi-Fi của Verizon."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Đã xảy ra sự cố khi kết nối bạn với dịch vụ Truy cập Wi-Fi của Verizon. Vui lòng gọi cho chúng tôi theo số 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Đã xảy ra sự cố với tài khoản Truy cập Wi-Fi của Verizon mà bạn có. Vui lòng gọi cho chúng tôi theo số 800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Không có dịch vụ Truy cập Wi-Fi của Verizon tại vị trí của bạn. Hãy thử lại sau hoặc thử ở một vị trí khác."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-zh-rCN/strings.xml b/service/res/values-mcc311-mnc480-zh-rCN/strings.xml deleted file mode 100644 index 711ef643f..000000000 --- a/service/res/values-mcc311-mnc480-zh-rCN/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>:您无法从 Verizon 覆盖区域外的地点连接到 Verizon WLAN Access。"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>:您没有订阅 Verizon WLAN Access。请拨打 800-922-0204 与我们联系。"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>:您的 Verizon WLAN Access 帐号出现问题。请拨打 800-922-0204 与我们联系。"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>:您已连接到 Verizon WLAN Access。"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>:将您连接到 Verizon WLAN Access 时出现问题。请拨打 800-922-0204 与我们联系。"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>:您的 Verizon WLAN Access 帐号出现问题。请拨打 800-922-0204 与我们联系。"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>:Verizon WLAN Access 在您所在的地点无法使用。请稍后重试,或换个地点再试一次。"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-zh-rHK/strings.xml b/service/res/values-mcc311-mnc480-zh-rHK/strings.xml deleted file mode 100644 index 7a4daf14b..000000000 --- a/service/res/values-mcc311-mnc480-zh-rHK/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>:無法從 Verizon 訊號覆蓋範圍外的地點連線至 Verizon Wi-Fi Access。"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>:您未訂閱 Verizon Wi-Fi Access。請致電 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>:您的 Verizon Wi-Fi Access 帳戶發生問題。請致電 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>:您已連線至 Verizon Wi-Fi Access。"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>:連線至 Verizon Wi-Fi Access 時發生問題。請致電 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>:您的 Verizon Wi-Fi Access 帳戶發生問題。請致電 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>:您目前的所在地點無法使用 Verizon Wi-Fi Access,請稍後再試。您亦可換個地點,然後再試一次。"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-zh-rTW/strings.xml b/service/res/values-mcc311-mnc480-zh-rTW/strings.xml deleted file mode 100644 index 087407536..000000000 --- a/service/res/values-mcc311-mnc480-zh-rTW/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g>:無法在 Verizon 訊號涵蓋範圍之外的地點連線至 Verizon Wi-Fi Access。"</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g>:你並未訂閱 Verizon Wi-Fi Access。請撥打 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g>:你的 Verizon Wi-Fi Access 帳戶發生問題。請撥打 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g>:你已連線至 Verizon Wi-Fi Access。"</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g>:連線至 Verizon Wi-Fi Access 時發生問題。請撥打 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g>:你的 Verizon Wi-Fi Access 帳戶發生問題。請撥打 800-922-0204 與我們聯絡。"</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g>:你目前的所在地點無法使用 Verizon Wi-Fi Access,請稍後再試。你也可以換個地點,然後再試一次。"</string> -</resources> diff --git a/service/res/values-mcc311-mnc480-zu/strings.xml b/service/res/values-mcc311-mnc480-zu/strings.xml deleted file mode 100644 index 78a0f8309..000000000 --- a/service/res/values-mcc311-mnc480-zu/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2020 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Awukwazi ukuxhuma kukufinyelela kwi-Verizon Wi-Fi kusuka ngaphandle kwendawo yokufakwa ye-Verizon."</string> - <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Awubhalisele ukufinyelela kwi-Verizon Wi-Fi. Sicela usishayele ucingo ku-800-922-0204."</string> - <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Kukhona inkinga nge-akhawunti yakho yokufinyelela kwi-Wi-Fi. Sicela usishayele ucingo ku-800-922-0204."</string> - <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Usuxhumeke kakade kukufinyelela kwi-Verizon Wi-Fi."</string> - <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Kukhona inkinga yokukuxhuma kukufinyelela kwi-Verizon Wi-Fi. Sicela usishayele ucingo ku-800-922-0204."</string> - <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Kukhona inkinga nge-akhawunti yakho yokufinyelela kwi-Wi-Fi. Sicela usishayele ucingo ku-800-922-0204."</string> - <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Ukufinyelela kwi-Verizon Wi-Fi akutholakali kusuka endaweni yakho. Zama futhi ngemuva kwesikhathi noma zama indawo ehlukile."</string> -</resources> diff --git a/service/res/values-mcc311-mnc480/strings.xml b/service/res/values-mcc311-mnc480/strings.xml deleted file mode 100644 index af976d472..000000000 --- a/service/res/values-mcc311-mnc480/strings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2020 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. ---> - -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- A notification is shown when eap failure happens. It should be overridden by carrier-specific overlays. --> - <string name="wifi_eap_error_message_code_32760"><xliff:g id="ssid">%1$s</xliff:g> : You can\u2019t connect to Verizon Wi-Fi Access from outside the Verizon coverage area.</string> - <string name="wifi_eap_error_message_code_32761"><xliff:g id="ssid">%1$s</xliff:g> : You are not subscribed to Verizon Wi-Fi Access. Please call us at 800-922-0204.</string> - <string name="wifi_eap_error_message_code_32762"><xliff:g id="ssid">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi Access account. Please call us at 800-922-0204.</string> - <string name="wifi_eap_error_message_code_32763"><xliff:g id="ssid">%1$s</xliff:g> : You are already connected to Verizon Wi-Fi Access.</string> - <string name="wifi_eap_error_message_code_32764"><xliff:g id="ssid">%1$s</xliff:g> : There is a problem connecting you to Verizon Wi-Fi Access. Please call us at 800-922-0204.</string> - <string name="wifi_eap_error_message_code_32765"><xliff:g id="ssid">%1$s</xliff:g> : There is a problem with your Verizon Wi-Fi Access account. Please call us at 800-922-0204.</string> - <string name="wifi_eap_error_message_code_32766"><xliff:g id="ssid">%1$s</xliff:g> : Verizon Wi-Fi Access is not available from your location. Try again later or try from a different location.</string> -</resources> diff --git a/service/res/values-mk/strings.xml b/service/res/values-mk/strings.xml deleted file mode 100644 index 836a82303..000000000 --- a/service/res/values-mk/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Системски ресусрси на Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Поврзете се на отворена Wi‑Fi-мрежа"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Поврзување со Wi-Fi мрежа"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Се поврзавте на Wi‑Fi-мрежа"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Не може да се поврзе на Wi‑Fi-мрежа"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Допрете за да ги видите сите мрежи"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Поврзете се"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Сите мрежи"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Статус на мрежа"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Известувања на мрежа"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Има достапна мрежа"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Да се дозволат предложените Wi‑Fi мрежи?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Предложени мрежи од <xliff:g id="NAME">%s</xliff:g>. Уредот може да се поврзе автоматски."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Дозволи"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Не, фала"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Да се поврзе на Wi-Fi на <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Мреживе примаат уникатен ID на SIM што може да се користи за следење на локацијата на уредот"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Поврзи"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не поврзувај"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Да се потврди врската?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ако се поврзете, Wi‑Fi мрежите на <xliff:g id="CARRIERNAME">%s</xliff:g> може да имаат пристап до уникатен ID поврзан со вашата SIM-картичка или да го споделуваат. Ова може да овозможи следење на локацијата на вашиот уред."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Поврзи"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Не поврзувај"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi ќе се вклучи автоматски"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Кога сте во близина на зачувана мрежа со висок квалитет"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Не вклучувај повторно"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi се вклучи автоматски"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Близу сте до зачувана мрежа: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Не може да се поврзе на Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" има слаба интернет-врска."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Дозволете поврзување?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Апликацијата %1$s сака да се поврзе со Wifi-мрежата %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Апликација"</string> - <string name="accept" msgid="5931271886782610829">"Прифати"</string> - <string name="decline" msgid="6874256900873707640">"Одбиј"</string> - <string name="ok" msgid="4215387532539340948">"Во ред"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Поканата е испратена"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Покана да се поврзе"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Од:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"До:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Внеси го бараниот PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Таблетот привремено ќе се исклучи од Wi-Fi, додека да се приклучи на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Привремено ќе се прекине врската на вашиот уред Android TV со Wi-Fi додека е поврзан со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Телефонот привремено ќе се исклучи од Wi-Fi додека е приклучен на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Во ред"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Не може да се поврзе на „<xliff:g id="SSID">%1$s</xliff:g>“"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Допрете за да ги промените поставките за приватност и обидете се повторно"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Да се променат поставките за приватност?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"За да се поврзе, <xliff:g id="SSID">%1$s</xliff:g> треба да ја користи MAC-адресата на вашиот уред, којашто е уникатен идентификатор. Поставките за приватност за мрежава користат рандомизиран идентификатор во моментов. \n\nПроменава може да им дозволи на уредите во близина да ја следат локацијата на вашиот уред."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Променете ги поставките"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Поставките се ажурирани. Обидете се да се поврзете повторно."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Не може да се променат поставките за приватност"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Не е пронајдена мрежа"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: грешка 32760 при проверката со EAP"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: грешка 32761 при проверката со EAP"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: грешка 32762 при проверката со EAP"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: грешка 32763 при проверката со EAP"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: грешка 32764 при проверката со EAP"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: грешка 32765 при проверката со EAP"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: грешка 32766 при проверката со EAP"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Точката на пристап е исклучена"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Нема поврзани уреди. Допрете за да измените."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi е исклучено"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"За да се поврзете на <xliff:g id="SSID">%1$s</xliff:g>, вметнете SIM-картичка на <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-ml/strings.xml b/service/res/values-ml/strings.xml deleted file mode 100644 index 648d76044..000000000 --- a/service/res/values-ml/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"സിസ്റ്റം വെെഫെെ ഉറവിടങ്ങൾ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"ലഭ്യമായ വൈഫൈ നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്യുക"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"വൈഫൈ നെറ്റ്വർക്കിലേക്ക് കണക്റ്റ് ചെയ്യുന്നു"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"വൈഫൈ നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്തു"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"വൈ-ഫൈ നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"എല്ലാ നെറ്റ്വർക്കുകളും കാണാൻ ടാപ്പുചെയ്യുക"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"കണക്റ്റുചെയ്യുക"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"എല്ലാ നെറ്റ്വർക്കുകളും"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"നെറ്റ്വർക്ക് നില"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"നെറ്റ്വർക്ക് അലേർട്ടുകൾ"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"നെറ്റ്വർക്ക് ലഭ്യമല്ല"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"നിർദ്ദേശിച്ച വെെഫെെ നെറ്റ്വർക്കുകൾ അനുവദിക്കണോ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> നിർദ്ദേശിച്ച നെറ്റ്വർക്കുകൾ. ഉപകരണം സ്വയമേവ കണക്റ്റ് ചെയ്തേക്കാം."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"അനുവദിക്കുക"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"വേണ്ട"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> വൈഫൈയിൽ കണക്റ്റ് ചെയ്യണോ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ഉപകരണ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ ഉപയോഗിക്കാവുന്ന സിം ഐഡി ഈ നെറ്റ്വർക്കുകൾക്ക് ലഭിക്കും"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"കണക്റ്റ് ചെയ്യുക"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"കണക്റ്റ് ചെയ്യരുത്"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"കണക്ഷൻ സ്ഥിരീകരിക്കണോ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"നിങ്ങൾ കണക്റ്റ് ചെയ്യുകയാണെങ്കിൽ, സിമ്മുമായി ബന്ധപ്പെട്ട തനത് ഐഡി <xliff:g id="CARRIERNAME">%s</xliff:g> വൈഫൈ നെറ്റ്വർക്കുകൾ ആക്സസ് ചെയ്യുകയോ പങ്കിടുകയോ ചെയ്തേക്കാം. നിങ്ങളുടെ ഉപകരണ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ ഇത് അനുവദിച്ചേക്കാം."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"കണക്റ്റ് ചെയ്യുക"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"കണക്റ്റ് ചെയ്യരുത്"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"വൈഫൈ സ്വമേധയാ ഓണാകും"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"നിങ്ങൾ ഉയർന്ന നിലവാരമുള്ള സംരക്ഷിക്കപ്പെട്ട നെറ്റ്വർക്കിനരികിലെത്തുമ്പോൾ"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"തിരികെ ഓണാക്കരുത്"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"വൈഫൈ സ്വമേധയാ ഓണായി"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"നിങ്ങൾ സംരക്ഷിച്ചിട്ടുള്ള ഒരു നെറ്റ്വർക്കിന് സമീപമാണ്: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi-ലേക്ക് കണക്റ്റുചെയ്യാൻ കഴിഞ്ഞില്ല"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" എന്നതിന്റെ ഇന്റർനെറ്റ് കണക്ഷൻ മോശമാണ്."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"കണക്ഷൻ അനുവദിക്കണോ?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"അപ്ലിക്കേഷൻ %1$s Wifi നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്യാൻ താൽപ്പര്യപ്പെടുന്നു %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ഒരു അപ്ലിക്കേഷൻ"</string> - <string name="accept" msgid="5931271886782610829">"അംഗീകരിക്കുക"</string> - <string name="decline" msgid="6874256900873707640">"നിരസിക്കുക"</string> - <string name="ok" msgid="4215387532539340948">"ശരി"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ക്ഷണം അയച്ചു"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"കണക്റ്റുചെയ്യാനുള്ള ക്ഷണം"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"അയച്ചത്:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"ടു:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"ആവശ്യമായ പിൻ ടൈപ്പുചെയ്യുക:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"പിൻ:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ടാബ്ലെറ്റ് <xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിൽ കണക്റ്റുചെയ്തിരിക്കുമ്പോൾ അത് താൽക്കാലികമായി Wi-Fi-യിൽ നിന്നും വിച്ഛേദിക്കപ്പെടും."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"നിങ്ങളുടെ Android TV <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ഉപകരണവുമായി കണക്റ്റ് ചെയ്തിരിക്കുമ്പോൾ അത് താൽക്കാലികമായി വൈഫൈയിൽ നിന്ന് വിച്ഛേദിക്കും"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തിരിക്കുമ്പോൾ ഫോൺ Wi-Fi-യിൽ നിന്ന് താൽക്കാലികമായി വിച്ഛേദിക്കും"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ശരി"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g>-ലേക്ക് കണക്റ്റ് ചെയ്യാനാവുന്നില്ല"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"സ്വകാര്യതാ ക്രമീകരണം മാറ്റാൻ ടാപ്പ് ചെയ്യുക, വീണ്ടും ശ്രമിക്കുക"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"സ്വകാര്യതാ ക്രമീകരണം മാറ്റണോ?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"കണക്റ്റ് ചെയ്യാൻ, തനത് ഐഡന്റിഫയറായ MAC വിലാസം <xliff:g id="SSID">%1$s</xliff:g> ഉപയോഗിക്കിക്കേണ്ടതുണ്ട്. നിലവിൽ, ക്രമരഹിതമാക്കിയ ഐഡന്റിഫയർ ആണ് ഈ നെറ്റ്വർക്കിന്റെ സ്വകാര്യതാ ക്രമീകരണം ഉപയോഗിക്കുന്നത്. \n\nനിങ്ങളുടെ ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ സമീപത്തുള്ള ഉപകരണങ്ങളെ ഈ മാറ്റം അനുവദിച്ചേക്കാം."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ക്രമീകരണം മാറ്റുക"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ക്രമീകരണം അപ്ഡേറ്റ് ചെയ്തു. വീണ്ടും കണക്റ്റ് ചെയ്യാൻ ശ്രമിക്കുക."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"സ്വകാര്യതാ ക്രമീകരണം മാറ്റാനാവില്ല"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"നെറ്റ്വർക്ക് കണ്ടെത്തിയില്ല"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP പരിശോധിച്ചുറപ്പിക്കുന്നതിലെ പ്രശ്നം 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP പരിശോധിച്ചുറപ്പിക്കുന്നതിലെ പ്രശ്നം 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP പരിശോധിച്ചുറപ്പിക്കുന്നതിലെ പ്രശ്നം 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP പരിശോധിച്ചുറപ്പിക്കുന്നതിലെ പ്രശ്നം 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP പരിശോധിച്ചുറപ്പിക്കുന്നതിലെ പ്രശ്നം 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP പരിശോധിച്ചുറപ്പിക്കുന്നതിലെ പ്രശ്നം 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP പരിശോധിച്ചുറപ്പിക്കുന്നതിലെ പ്രശ്നം 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ഹോട്ട്സ്പോട്ട് ഓഫാക്കി"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"ഉപകരണങ്ങളൊന്നും കണക്റ്റ് ചെയ്തിട്ടില്ല. പരിഷ്കരിക്കാൻ ടാപ്പ് ചെയ്യുക."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"വൈഫൈ വിച്ഛേദിച്ചു"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> എന്നതിലേക്ക് കണക്റ്റ് ചെയ്യാൻ <xliff:g id="CARRIER_NAME">%2$s</xliff:g> സിം ഇടുക"</string> -</resources> diff --git a/service/res/values-mn/strings.xml b/service/res/values-mn/strings.xml deleted file mode 100644 index 691c9d154..000000000 --- a/service/res/values-mn/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Wi-Fi нөөцийн систем"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Нээлттэй Wi‑Fi сүлжээнд холбогдох"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi сүлжээнд холбогдож байна"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi сүлжээнд холбогдлоо"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi сүлжээнд холбогдож чадсангүй"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Бүх сүлжээг харахын тулд товшино уу"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Холбогдох"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Бүх сүлжээ"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Сүлжээний төлөв"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Сүлжээний сануулга"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Сүлжээ боломжтой"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Санал болгосон Wi‑Fi сүлжээг зөвшөөрөх үү?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> сүлжээ санал болголоо. Төхөөрөмж автоматаар холбогдож магадгүй."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Зөвшөөрөх"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Үгүй, баярлалаа"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g>-н Wi‑Fi-д холбоогдох уу?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Эдгээр сүлжээ нь төхөөрөмжийн байршлыг тандахад ашиглах боломжтой SIM ID-г хүлээн авдаг"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Холбогдох"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Битгий холбогд"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Холболтыг баталгаажуулах уу?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Хэрэв та холбогдвол <xliff:g id="CARRIERNAME">%s</xliff:g>-н Wi‑Fi сүлжээ нь таны SIM-тэй холбоотой цор ганц дугаарт хандаж эсвэл түүнийг хуваалцаж болзошгүй. Энэ нь таны төхөөрөмжийн байршлыг тандахыг зөвшөөрч болзошгүй."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Холбогдох"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Битгий холбогд"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi автоматаар асна"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Таныг хадгалсан, өндөр чанартай сүлжээний ойролцоо байх үед"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Буцааж асаахгүй"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi-г автоматаар асаасан"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Та дараах хадгалсан сүлжээтэй ойрхон байна: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi-д холбогдож чадсангүй"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" Интернет холболт муу байна."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Холболтыг зөвшөөрөх үү?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Програм %1$s нь Wifi сүлжээ %2$s-тай холбох хүсэлтэй байна"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Аппликейшн"</string> - <string name="accept" msgid="5931271886782610829">"Зөвшөөрөх"</string> - <string name="decline" msgid="6874256900873707640">"Татгалзах"</string> - <string name="ok" msgid="4215387532539340948">"ОК"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Урилга илгээгдсэн"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Холбох урилга"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Хэнээс:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Хэнд:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Шаардлагатай PIN-г бичнэ үү:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Таблет <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-тэй холбогдох үедээ түр зуур Wi-Fi-с салах болно."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Таны Android TV төхөөрөмж <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-д холбогдсон үед Wi-Fi-с түр хугацаанд сална"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Утас <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-тай холбогдох үедээ түр зуур Wi-Fi-с салах болно."</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g>-д холбогдож чадсангүй"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Нууцлалын тохиргоог өөрчлөхийн тулд товшоод, дахин оролдоно уу"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Нууцлалын тохиргоог өөрчлөх үү?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Холбогдохын тулд <xliff:g id="SSID">%1$s</xliff:g> нь таны төхөөрөмжийн өвөрмөц таниулбар болох MAC хаягийг ашиглах хэрэгтэй байна. Одоогоор энэ сүлжээнд зориулсан таны нууцлалын тохиргоо нь санамсаргүй сонгосон таниулбарыг ашиглаж байна. \n\nЭнэ нь ойролцоох төхөөрөмжүүдэд таны төхөөрөмжийн байршлыг тандахыг зөвшөөрч болзошгүй."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Тохиргоог өөрчлөх"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Тохиргоог шинэчиллээ. Дахин холбогдохыг оролдоно уу."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Нууцлалын тохиргоог өөрчлөх боломжгүй байна"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Сүлжээ олдсонгүй"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP нотолгооны алдаа 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP нотолгооны алдаа 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP нотолгооны алдаа 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP нотолгооны алдаа 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP нотолгооны алдаа 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP нотолгооны алдаа 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP нотолгооны алдаа 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Сүлжээний цэгийг унтраасан"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Ямар ч төхөөрөмж холбогдоогүй байна. Өөрчлөхийн тулд товшино уу."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wifi-г салгалаа"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g>-д холбогдохын тулд <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM-г хийнэ үү"</string> -</resources> diff --git a/service/res/values-mr/strings.xml b/service/res/values-mr/strings.xml deleted file mode 100644 index 361222732..000000000 --- a/service/res/values-mr/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"सिस्टम वाय-फाय स्रोत"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"खुल्या वाय-फाय नेटवर्कशी कनेक्ट करा"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"वाय-फाय नेटवर्कशी कनेक्ट करत आहे"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"वाय-फाय नेटवर्कशी कनेक्ट केले"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"वाय-फाय नेटवर्कशी कनेक्ट करू शकत नाही"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"सर्व नेटवर्क पाहण्यासाठी टॅप करा"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"कनेक्ट करा"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"सर्व नेटवर्क"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"नेटवर्क स्थिती"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"नेटवर्क सूचना"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"नेटवर्क उपलब्ध"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"सुचवलेल्या वाय-फाय नेटवर्कना अनुमती द्यायची का?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> सुचवलेली नेटवर्क. डिव्हाइस आपोआप कनेक्ट होऊ शकते."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"अनुमती द्या"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"नाही, नको"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> वाय-फायशी कनेक्ट करायचे आहे का?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"या नेटवर्कना एक सिम आयडी मिळतो जो डिव्हाइस स्थानाचा माग ठेवण्यासाठी वापरला जाऊ शकतो"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"कनेक्ट करा"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"कनेक्ट करू नका"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"कनेक्शन निश्चित करायचे आहे का?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"तुम्ही कनेक्ट केल्यास, <xliff:g id="CARRIERNAME">%s</xliff:g> वाय-फाय नेटवर्क तुमच्या सिम शी संबंधित एक युनिक आयडी अॅक्सेस किंवा शेअर करू शकतात. यामुळे तुमच्या डिव्हाइस स्थानाचा मागोवा घेतला जाऊ शकतो."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"कनेक्ट करा"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"कनेक्ट करू नका"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"वाय-फाय आपोआप सुरू होईल"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"तुम्ही जेव्हा सेव्ह केलेल्या उच्च दर्जाच्या नेटवर्कजवळ असाल तेव्हा"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"पुन्हा सुरू करू नका"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"वाय-फाय आपोआप सुरू झाले"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"तुम्ही या सेव्ह केलेल्या नेटवर्कजवळ आहात: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"वाय-फाय ला कनेक्ट करू शकलो नाही"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" इंटरनेट कनेक्शन खराब आहे."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"कनेक्शनला अनुमती द्यायची?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s ॲप्लिकेशन %2$s वायफाय नेटवर्कशी कनेक्ट करू इच्छित आहे"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ॲप्लिकेशन"</string> - <string name="accept" msgid="5931271886782610829">"स्वीकार करा"</string> - <string name="decline" msgid="6874256900873707640">"नकार द्या"</string> - <string name="ok" msgid="4215387532539340948">"ठीक आहे"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"आमंत्रण पाठविले"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"कनेक्ट करण्यासाठी आमंत्रण"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"प्रेषक:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"प्रति:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"आवश्यक पिन टाइप करा:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"पिन:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"टॅबलेट <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ला कनेक्ट केलेले असताना तात्पुरते वाय-फाय वरून डिस्कनेक्ट होईल"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>शी तुमचे Android TV डिव्हाइस कनेक्ट केलेले असताना ते वाय-फाय वरून तात्पुरते डिस्कनेक्ट केले जाईल"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> वर फोन कनेक्ट केलेला असताना तो वाय-फाय वरून तात्पुरता डिस्कनेक्ट केला जाईल"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ठीक"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> शी कनेक्ट करता आले नाही"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"गोपनीयता सेटिंग्ज बदलण्यासाठी टॅप करा आणि पुन्हा प्रयत्न करा"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"गोपनीयता सेटिंग्ज बदलायची आहे का?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"कनेक्ट करण्यासाठी, <xliff:g id="SSID">%1$s</xliff:g> ला तुमच्या डिव्हाइसचा MAC अॅड्रेस, एक युनिक आयडेंटिफायर वापरणे आवश्यक आहे. सध्या, या नेटवर्कसाठी तुमचे गोपनीयता सेटिंग रँडम आयडेंटिफायर वापरते. \n\nया बदलामुळे जवळपासच्या डिव्हाइसद्वारे तुमच्या डिव्हाइसचे स्थान ट्रॅक करता येऊ शकते."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"सेटिंग बदला"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"सेटिंग अपडेट केले. पुन्हा कनेक्ट करण्याचा प्रयत्न करा."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"गोपनीयता सेटिंग्ज बदलू शकत नाही"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"नेटवर्क मिळाला नाही आहे"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ऑथेंटिकेशन एरर ३२७६०"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ऑथेंटिकेशन एरर ३२७६१"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ऑथेंटिकेशन एरर ३२७६२"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ऑथेंटिकेशन एरर ३२७६३"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ऑथेंटिकेशन एरर ३२७६४"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ऑथेंटिकेशन एरर ३२७६५"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ऑथेंटिकेशन एरर ३२७६६"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"हॉटस्पॉट बंद आहे"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"कोणतीही डिव्हाइस कनेक्ट केलेली नाहीत. सुधारित करण्यासाठी टॅप करा."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"वाय-फाय डिस्कनेक्ट झाले"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> शी कनेक्ट करण्यासाठी, एक <xliff:g id="CARRIER_NAME">%2$s</xliff:g> सिम घाला"</string> -</resources> diff --git a/service/res/values-ms/strings.xml b/service/res/values-ms/strings.xml deleted file mode 100644 index 0ecdb4fb1..000000000 --- a/service/res/values-ms/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sumber Wi-Fi Sistem"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Sambung ke rangkaian Wi-Fi terbuka"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Menyambung ke rangkaian Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Disambungkan ke rangkaian Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Tidak dapat menyambung ke rangkaian Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Ketik untuk melihat semua rangkaian"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Sambung"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Semua rangkaian"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Status rangkaian"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Makluman rangkaian"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Rangkaian tersedia"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Benarkan rangkaian Wi-Fi yang dicadangkan?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Rangkaian yang dicadangkan oleh <xliff:g id="NAME">%s</xliff:g>. Peranti mungkin disambungkan secara automatik."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Benarkan"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Tidak perlu"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Sambung ke Wi‑Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Rangkaian ini menerima ID SIM yang boleh digunakan untuk menjejaki lokasi peranti"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Sambung"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Jangan sambung"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Sahkan sambungan?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Jika anda bersambung, rangkaian Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> mungkin mengakses atau berkongsi ID unik yang dikaitkan dengan SIM anda. Hal ini mungkin membenarkan lokasi peranti anda dijejaki."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Sambung"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Jangan sambung"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi akan dihidupkan secara automatik"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Apabila anda berada berdekatan dengan rangkaian disimpan yang berkualiti tinggi"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Jangan hidupkan kembali"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi dihidupkan secara automatik"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Anda berada berdekatan rangkaian yang disimpan: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Tidak boleh menyambung kepada Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" mempunyai sambungan internet yang kurang baik."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Benarkan sambungan?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikasi %1$s ingin menyambung ke Rangkaian Wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Satu aplikasi"</string> - <string name="accept" msgid="5931271886782610829">"Terima"</string> - <string name="decline" msgid="6874256900873707640">"Tolak"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Jemputan dihantar"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Jemputan untuk menyambung"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Daripada:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kepada:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Taipkan PIN yang diperlukan:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Sambungan tablet ke Wi-Fi akan diputuskan buat sementara waktu semasa tablet bersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Peranti Android TV anda akan diputuskan sambungan daripada Wi-Fi untuk sementara waktu semasa peranti ini disambungkan ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Sambungan telefon ke Wi-Fi akan diputuskan buat sementara waktu semasa telefon bersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Tidak dapat menyambung ke <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Ketik untuk menukar tetapan privasi, kemudian cuba semula"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Tukar tetapan privasi?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Untuk menyambung, <xliff:g id="SSID">%1$s</xliff:g> perlu menggunakan alamat MAC peranti anda, iaitu pengecam unik. Pada masa ini, tetapan privasi anda untuk rangkaian ini menggunakan pengecam terawak. \n\nPerubahan ini mungkin membenarkan lokasi peranti anda dijejaki oleh peranti yang berdekatan."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Tukar tetapan"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Tetapan dikemas kini. Cuba sambung lagi."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Tidak boleh menukar tetapan privasi"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Rangkaian tidak ditemukan"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Ralat pengesahan EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Ralat pengesahan EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Ralat pengesahan EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Ralat pengesahan EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Ralat pengesahan EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Ralat pengesahan EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Ralat pengesahan EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Tempat liputan dimatikan."</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Tiada peranti disambungkan. Ketik untuk mengubah suai."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi diputuskan sambungannya"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Untuk menyambung kepada <xliff:g id="SSID">%1$s</xliff:g>, masukkan SIM <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-my/strings.xml b/service/res/values-my/strings.xml deleted file mode 100644 index d88c369d4..000000000 --- a/service/res/values-my/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Wi-Fi စနစ် အရင်းအမြစ်များ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"အများသုံး Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပါ"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်နေသည်"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပြီးပါပြီ"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်၍ မရပါ"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"ကွန်ရက်အားလုံးကို ကြည့်ရန် တို့ပါ"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"ချိတ်ဆက်ရန်"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"ကွန်ရက်အားလုံး"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ကွန်ရက် အခြေအနေ"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ကွန်ရက် သတိပေးချက်များ"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"ကွန်ရက်ချိတ်ဆက်မှု ရရှိနိုင်ပါသည်"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"အကြံပြုထားသည့် Wi‑Fi ကွန်ရက်များ ခွင့်ပြုမလား။"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> သည် ကွန်ရက်များကို အကြံပြုထားသည်။ စက်သည် အလိုအလျောက် ချိတ်ဆက်နိုင်သည်။"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ခွင့်ပြုရန်"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"မလိုပါ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi သို့ ချိတ်ဆက်မလား။"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ဤကွန်ရက်များက စက်တည်နေရာကို ခြေရာခံရန် အသုံးပြုနိုင်သည့် SIM ID တစ်ခုကို ရရှိပါသည်"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ချိတ်ဆက်ပါ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"မချိတ်ဆက်ပါနှင့်"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ချိတ်ဆက်မှု အတည်ပြုမလား။"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"သင်ချိတ်ဆက်ပါက <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi ကွန်ရက်များက သင့်ဆင်းမ်ကတ်နှင့် ဆက်စပ်နေသည့် သီးသန့် ID ကို သုံးခြင်း သို့မဟုတ် မျှဝေခြင်းတို့ ပြုလုပ်နိုင်သည်။ ၎င်းက သင့်စက်၏တည်နေရာကို ခြေရာခံခွင့် ပြုနိုင်သည်။"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"ချိတ်ဆက်ပါ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"မချိတ်ဆက်ပါနှင့်"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi ကို အလိုအလျောက် ပြန်ဖွင့်ပေးလိမ့်ပါမည်"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"သိမ်းဆည်းထားသည့် အရည်အသွေးမြင့်ကွန်ရက်များအနီးသို့ ရောက်ရှိသည့်အခါ"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"ပြန်မဖွင့်ပါနှင့်"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi ကို အလိုအလျောက် ဖွင့်ထားသည်"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"သင်သည် သိမ်းထားသည့် ကွန်ရက်အနီးတွင် ရှိသည်− <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ဝိုင်ဖိုင်ကိုချိတ်ဆက်မရပါ"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" အင်တာနက် ဆက်သွယ်မှု ကောင်းကောင်းမရှိပါ"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"ချိတ်ဆက်မှုကို ခွင့်ပြုမလား?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"အပလီကေးရှင်း %1$s သည် ဝိုင်ဖိုင်ကွန်ရက် %2$s ကိုချိတ်ဆက်လိုသည်"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"အပလီကေးရှင်း"</string> - <string name="accept" msgid="5931271886782610829">"လက်ခံရန်"</string> - <string name="decline" msgid="6874256900873707640">"လက်မခံပါ"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ဖိတ်ကြားချက် ပို့ပြီး"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"ချိတ်ဆက်ရန် ဖိတ်ကြားချက်"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"မှ၊"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"သို့:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"လိုအပ်သော ပင် နံပါတ် ရိုက်ရန်:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"ပင် နံပါတ်:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> နှင့် ဆက်သွယ်ထားစဉ် တက်ဘလက်ဟာ Wi-Fi နှင့် ဆက်သွယ်မှု ရပ်ဆိုင်းထားမှာ ဖြစ်ပါတယ်"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"သင်၏ Android TV စက်ပစ္စည်းသည် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားသည့်အခါ Wi-Fi မှနေ၍ ယာယီ ချိတ်ဆက်မှုဖြုတ်သွားပါမည်။"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို ဆက်သွယ်ထားစဉ် ဖုန်းအား ဝိုင်ဖိုင်မှ ဆက်သွယ်မှု ရပ်ဆိုင်းထားပါမည်"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> နှင့် ချိတ်ဆက်၍မရပါ။"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"ကိုယ်ရေးလုံခြုံမှုဆက်တင်ကို ပြောင်းရန် တို့ပြီးနောက် ပြန်စမ်းကြည့်ပါ"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"ကိုယ်ရေးလုံခြုံမှုဆက်တင်ကို ပြောင်းမလား။"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"ချိတ်ဆက်ရန်အတွက် <xliff:g id="SSID">%1$s</xliff:g> သည် သင့်စက်၏ သီးသန့်သတ်မှတ်မှုစနစ် ဖြစ်သည့် MAC လိပ်စာကို အသုံးပြုရန်လိုသည်။ လက်ရှိတွင် ဤကွန်ရက်အတွက် သင်၏ကိုယ်ရေးလုံခြုံမှုဆက်တင်က ကျပန်းသတ်မှတ်မှုစနစ်ကို အသုံးပြုပါသည်။ \n\nဤအပြောင်းအလဲက သင့်စက်၏တည်နေရာကို ခြေရာခံရန် အနီးတစ်ဝိုက်ရှိ စက်များအား ခွင့်ပြုနိုင်သည်။"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ဆက်တင် ပြောင်းရန်"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ဆက်တင် အပ်ဒိတ်လုပ်ပြီးပြီ။ ထပ်ချိတ်ဆက်ကြည့်ပါ။"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"ကိုယ်ရေးလုံခြုံမှုဆက်တင်ကို ပြောင်းလဲ၍မရပါ"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ကွန်ရက်ကို ရှာမတွေ့ပါ"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> - EAP အထောက်အထားစိစစ်ခြင်း အမှား 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> - EAP အထောက်အထားစိစစ်ခြင်း အမှား 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> - EAP အထောက်အထားစိစစ်ခြင်း အမှား 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> - EAP အထောက်အထားစိစစ်ခြင်း အမှား 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> - EAP အထောက်အထားစိစစ်ခြင်း အမှား 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> - EAP အထောက်အထားစိစစ်ခြင်း အမှား 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> - EAP အထောက်အထားစိစစ်ခြင်း အမှား 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ဟော့စပေါ့ ပိတ်ထားသည်"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"ချိတ်ဆက်ထားသောစက် မရှိပါ။ ပြင်ဆင်ရန် တို့ပါ။"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi ချိတ်ဆက်မှု မရှိပါ"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> နှင့် ချိတ်ဆက်ရန် <xliff:g id="CARRIER_NAME">%2$s</xliff:g> ဆင်းမ်ကတ် ထည့်ပါ။"</string> -</resources> diff --git a/service/res/values-nb/strings.xml b/service/res/values-nb/strings.xml deleted file mode 100644 index 898d50a9d..000000000 --- a/service/res/values-nb/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Systemets Wi-Fi-ressurser"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Koble til et åpent Wi‑Fi-nettverk"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Kobler til Wi-Fi-nettverket"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Koblet til Wi-Fi-nettverk"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Kunne ikke koble til Wi-Fi-nettverket"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Trykk for å se alle nettverkene"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Koble til"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Alle nettverk"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Nettverksstatus"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Nettverksvarsler"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Nettverk er tilgjengelig"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Vil du tillate foreslåtte Wi-Fi nettverk?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>-foreslåtte nettverk. Enheten kan koble til automatisk."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Tillat"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nei takk"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vil du koble til <xliff:g id="CARRIERNAME">%s</xliff:g>-Wi-Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Disse nettverkene mottar en SIM-ID som kan brukes til å spore enhetsposisjonen"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Koble til"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ikke koble til"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vil du bekrefte tilkoblingen?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Hvis du kobler til, kan <xliff:g id="CARRIERNAME">%s</xliff:g>-Wi‑Fi-nettverk få tilgang til eller dele en unik ID som er knyttet til SIM-kortet ditt. Dette gjør at enhetens posisjon kan spores."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Koble til"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ikke koble til"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi slås på automatisk"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Når du er i nærheten av et lagret nettverk av høy kvalitet"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ikke slå på igjen"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi er slått på automatisk"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Du er i nærheten av et lagret nettverk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Kan ikke koble til Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" har en dårlig internettilkobling."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Vil du tillat tilkoblingen?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Appen %1$s vil koble til Wi-Fi-nettverket %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"En app"</string> - <string name="accept" msgid="5931271886782610829">"Godta"</string> - <string name="decline" msgid="6874256900873707640">"Avslå"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitasjonen er sendt"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitasjon for tilkobling"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Fra:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Til:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Skriv inn påkrevd PIN-kode:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Nettbrettet frakobles Wi-Fi midlertidig mens den er tilkoblet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV-enheten din blir midlertidig koblet fra Wi-Fi mens den er koblet til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefonen frakobles Wi-Fi midlertidig mens den er tilkoblet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Kan ikke koble til <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Trykk for å endre personverninnstillingene og prøve på nytt"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Vil du endre personverninnstillingen?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"For å koble til må <xliff:g id="SSID">%1$s</xliff:g> bruke enhetens MAC-adresse, en unik identifikator. For øyeblikket bruker personverninnstillingene dine for dette nettverket en tilfeldig valgt identifikator. \n\nDenne endringen gjør at enhetens posisjon kan spores av enheter i nærheten."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Endre innstillingen"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Innstillingen er oppdatert. Prøv å koble til igjen."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Kan ikke endre personverninnstillingen"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Fant ikke nettverket"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-autentiseringsfeil 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-autentiseringsfeil 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-autentiseringsfeil 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-autentiseringsfeil 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-autentiseringsfeil 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-autentiseringsfeil 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP-autentiseringsfeil 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Wi-Fi-sonen er slått av"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Ingen enheter er koblet til. Trykk for å endre."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi er frakoblet"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"For å koble til <xliff:g id="SSID">%1$s</xliff:g>, sett inn et <xliff:g id="CARRIER_NAME">%2$s</xliff:g>-SIM-kort"</string> -</resources> diff --git a/service/res/values-ne/strings.xml b/service/res/values-ne/strings.xml deleted file mode 100644 index 9b2aec5be..000000000 --- a/service/res/values-ne/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"प्रणालीको Wi-Fi का स्रोतहरू"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"खुला Wi‑Fi नेटवर्कमा जडान गर्नुहोस्"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi नेटवर्कमा जडान गर्दै"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi नेटवर्कमा जडान गरियो"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi नेटवर्कमा जडान गर्न सकिएन"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"सबै नेटवर्कहरू हेर्न ट्याप गर्नुहोस्"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"जडान गर्नुहोस्"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"सबै नेटवर्कहरू"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"नेटवर्कको स्थिति"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"नेटवर्कका अलर्टहरू"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"नेटवर्क उपलब्ध छ"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"सिफारिस गरिएका Wi‑Fi नेटवर्कहरूलाई अनुमति दिनुहोस्?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ले सिफारिस गरेका नेटवर्कहरू। यन्त्र स्वतः जडान हुन सक्छ।"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"अनुमति दिनुहोस्"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"पर्दैन, धन्यवाद"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi मा कनेक्ट गर्ने हो?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"यी नेटवर्कहरूलाई यन्त्रको स्थान पहिल्याउन प्रयोग गर्न मिल्ने एउटा अद्वितीय SIM कार्ड ID उपलब्ध गराइन्छ"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"कनेक्ट गर्नुहोस्"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"नजोड्नुहोस्"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"जोडिने हो?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"तपाईं जोडिनुभयो भने <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi नेटवर्कहरूले तपाईंको SIM सँग सम्बद्ध अद्वित्तीय ID प्रयोग गर्न वा उक्त ID आदान प्रदान गर्न सक्छ। उक्त ID प्रयोग गरी तपाईंको यन्त्रको स्थान पहिल्याउन सकिन्छ।"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"जोड्नुहोस्"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"नजोड्नुहोस्"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi स्वतः सक्रिय हुनेछ"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"तपाईं कुनै सुरक्षित गरिएको उच्च गुणस्तरीय नेटवर्कको नजिक हुनुभएको अवस्थामा"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"फेरि सक्रिय नगर्नुहोला"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi स्वतः सक्रिय गरियो"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"तपाईं कुनै सुरक्षित गरिएको नेटवर्क नजिकै हुनुहुन्छ: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"वाइ-फाइसँग जडान गर्न सकेन"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" खराब इन्टरनेट जडान रहेको छ।"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"जडान अनुमति दिने हो?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"एप %1$s Wifi सञ्जाल %2$s मा जडान गर्न चाहन्छ"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"एउटा एप"</string> - <string name="accept" msgid="5931271886782610829">"स्वीकार्नुहोस्"</string> - <string name="decline" msgid="6874256900873707640">"अस्वीकार गर्नुहोस्"</string> - <string name="ok" msgid="4215387532539340948">"ठिक छ"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"निमन्त्रणा पठाइएको"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"जडानमा निमन्त्रणा"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"बाट:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"प्रापक:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"आवश्यक PIN टाइप गर्नुहोस्:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"यो <xliff:g id="DEVICE_NAME">%1$s</xliff:g>सँग जोडिएको बेला ट्याब्लेट अस्थायी रूपमा वाइ-फाइबाट विच्छेद गरिने छ।"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"तपाईंको Android टिभी यन्त्र <xliff:g id="DEVICE_NAME">%1$s</xliff:g> मा जोडिएको बेला यो केही समयका लागि Wi-Fi बाट विच्छेद हुने छ।"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"जब यो <xliff:g id="DEVICE_NAME">%1$s</xliff:g> सँग जडित हुन्छ, फोन अस्थायी रूपमा वाइ-फाइबाट विच्छेद हुने छ"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ठिक छ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> मा जडान गर्न सकिएन"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"गोपनीयता सेटिङ परिवर्तन गर्न ट्याप गरेर फेरि प्रयास गर्नुहोस्"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"गोपनीयतासम्बन्धी सेटिङ परिवर्तन गर्ने हो?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"जोड्नका लागि <xliff:g id="SSID">%1$s</xliff:g> ले तपाईंको यन्त्रको MAC ठेगाना अर्थात् एउटा अद्वितीय पहिचानकर्ता प्रयोग गर्नु पर्ने हुन्छ। हाल, यो नेटवर्कमा लागू हुने तपाईंको गोपनीयतासम्बन्धी सेटिङले अनियमित पहिचानकर्ताको प्रयोग गर्छ। \n\nयो परिवर्तन गर्नाले वरपरका यन्त्रहरूलाई तपाईंको यन्त्रको स्थान ट्र्याक गर्न दिने सम्भावना हुन्छ।"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"सेटिङ परिवर्तन गर्नुहोस्"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"सेटिङ अद्यावधिक गरियो। फेरि जोडी हेर्नुहोस्।"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"गोपनीयता सेटिङ परिवर्तन गर्न सकिँदैन"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"नेटवर्क फेला परेन"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP प्रमाणीकरणसम्बन्धी त्रुटि ३२७६०"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP प्रमाणीकरणसम्बन्धी त्रुटि ३२७६१"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP प्रमाणीकरणसम्बन्धी त्रुटि ३२७६२"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP प्रमाणीकरणसम्बन्धी त्रुटि ३२७६३"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP प्रमाणीकरणसम्बन्धी त्रुटि ३२७६४"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP प्रमाणीकरणसम्बन्धी त्रुटि ३२७६५"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP प्रमाणीकरणसम्बन्धी त्रुटि ३२७६६"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"हटस्पट निष्क्रिय पारिएको छ"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"कुनै यन्त्र जोडिएको छैन। परिमार्जन गर्न ट्याप गर्नुहोस्।"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi विच्छेद गरियो।"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> मा जोडिन <xliff:g id="CARRIER_NAME">%2$s</xliff:g> को SIM सम्मिलित गर्नुहोस्"</string> -</resources> diff --git a/service/res/values-nl/strings.xml b/service/res/values-nl/strings.xml deleted file mode 100644 index 1baa7ff8a..000000000 --- a/service/res/values-nl/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Wifi-bronnen systeem"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Verbinding maken met een open wifi-netwerk"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Verbinden met wifi-netwerk"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Verbonden met een wifi-netwerk"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Kan geen verbinding maken met het wifi-netwerk"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tik om alle netwerken te bekijken"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Verbinding maken"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Alle netwerken"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Netwerkstatus"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Netwerkmeldingen"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Netwerk beschikbaar"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Voorgestelde wifi-netwerken toestaan?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> heeft netwerken voorgesteld. Apparaat kan automatisch verbinding maken."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Toestaan"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nee, bedankt"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Verbinding maken met wifi van <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Deze netwerken ontvangen een simkaart-ID die kan worden gebruikt om de apparaatlocatie bij te houden"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Verbinding maken"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Geen verbinding maken"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Verbinding bevestigen?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Als je verbinding maakt, hebben de wifi-netwerken van <xliff:g id="CARRIERNAME">%s</xliff:g> mogelijk toegang tot de unieke ID die aan je simkaart is gekoppeld of kunnen ze deze delen. Op deze manier kan de locatie van je apparaat worden bijgehouden."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Verbinding maken"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Geen verbinding maken"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wifi wordt automatisch ingeschakeld"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Wanneer je in de buurt van een opgeslagen netwerk van hoge kwaliteit bent"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Niet weer inschakelen"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wifi automatisch ingeschakeld"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Je bent in de buurt van een opgeslagen netwerk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Kan geen verbinding maken met wifi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" heeft een slechte internetverbinding."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Verbinding toestaan?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"App %1$s wil verbinding maken met wifi-netwerk %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Een app"</string> - <string name="accept" msgid="5931271886782610829">"Accepteren"</string> - <string name="decline" msgid="6874256900873707640">"Weigeren"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Uitnodiging verzonden"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Uitnodiging om te koppelen"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Van:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Naar:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Voer de gewenste pincode in:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"Pincode"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"De verbinding met het wifi-netwerk wordt tijdelijk uitgeschakeld terwijl de telefoon is verbonden met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"De verbinding met het wifi-netwerk wordt tijdelijk uitgeschakeld terwijl het Android TV-apparaat is verbonden met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"De verbinding met het wifi-netwerk wordt tijdelijk uitgeschakeld terwijl de telefoon verbonden is met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Kan niet verbinden met <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tik om de privacyinstellingen aan te passen en probeer het opnieuw"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Privacyinstelling wijzigen?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> moet het MAC-adres van je apparaat gebruiken om verbinding te maken. Dat is een unieke ID. Vanwege je privacyinstelling voor dit netwerk wordt op dit moment een willekeurige ID gebruikt. \n\nDoor deze wijziging kan de locatie van je apparaat worden bijgehouden door apparaten in de buurt."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Instelling wijzigen"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Instelling geüpdatet. Probeer opnieuw verbinding te maken."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Wijzigen van privacyinstelling is mislukt"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Netwerk niet gevonden"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-verificatiefout 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-verificatiefout 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-verificatiefout 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-verificatiefout 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-verificatiefout 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-verificatiefout 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-verificatiefout 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot uitgeschakeld"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Geen apparaten gekoppeld. Tik om te wijzigen."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wifi-verbinding verbroken"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Plaats een simkaart van <xliff:g id="CARRIER_NAME">%2$s</xliff:g> om verbinding te maken met <xliff:g id="SSID">%1$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-or/strings.xml b/service/res/values-or/strings.xml deleted file mode 100644 index c1150ae70..000000000 --- a/service/res/values-or/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"ସିଷ୍ଟମ୍ ୱାଇ-ଫାଇ ରିସୋର୍ସ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"ୱାଇ‑ଫାଇ ନେଟୱର୍କ ଖୋଲିବାକୁ କନେକ୍ଟ କରନ୍ତୁ"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କ ସହିତ କନେକ୍ଟ ହେଉଛି"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କରେ କନେକ୍ଟ ହୋଇଛି"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କରେ କନେକ୍ଟ କରିହେଲା ନାହିଁ"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"ସମସ୍ତ ନେଟ୍ୱର୍କ ଦେଖିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"କନେକ୍ଟ କରନ୍ତୁ"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"ସମସ୍ତ ନେଟ୍ୱର୍କ"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ନେଟୱର୍କ ସ୍ଥିତି"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ନେଟୱର୍କ ଅଲର୍ଟ"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"ନେଟ୍ୱର୍କ ଉପଲବ୍ଧ ଅଛି"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"ପ୍ରସ୍ତାବିତ ୱାଇ-ଫାଇ ନେଟ୍ୱାର୍କଗୁଡ଼ିକୁ ଅନୁମତି ଦେବେ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ପ୍ରସ୍ତାବିତ ନେଟ୍ୱାର୍କଗୁଡ଼ିକ। ଡିଭାଇସ୍ ହୁଏତ ସ୍ୱଚାଳିତ ଭାବେ ସଂଯୋଗ ହୋଇପାରେ।"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ଅନୁମତି ଦିଅନ୍ତୁ"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ନାହିଁ, ଥାଉ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> ୱାଇ-ଫାଇ ସହ ସଂଯୋଗ କରିବେ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ଏହି ନେଟୱାର୍କଗୁଡ଼ିକ ଏକ SIM ID ପ୍ରାପ୍ତ କରେ ଯାହା ଡିଭାଇସର ଲୋକେସନ୍ ଟ୍ରାକ୍ କରିବାରେ ବ୍ୟବହାର କରାଯାଇପାରିବ"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ସଂଯୋଗ କରନ୍ତୁ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ସଂଯୋଗ କରନ୍ତୁ ନାହିଁ"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ସଂଯୋଗ ସୁନିଶ୍ଚିତ କରିବେ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ଯଦି ଆପଣ ସଂଯୋଗ କରିବେ, ତେବେ <xliff:g id="CARRIERNAME">%s</xliff:g> ୱାଇ-ଫାଇ ନେଟୱାର୍କଗୁଡ଼ିକ ଆପଣଙ୍କ SIM ସମ୍ବନ୍ଧିତ ଏକ ସ୍ଵତନ୍ତ୍ର ID ଆକ୍ସେସ୍ କିମ୍ବା ସେୟାର୍ କରିପାରେ। ଏହା ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନ୍ ଟ୍ରାକ୍ କରିବାକୁ ଅନୁମତି ଦେଇପାରେ।"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"ସଂଯୋଗ କରନ୍ତୁ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"ସଂଯୋଗ କରନ୍ତୁ ନାହିଁ"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"ୱାଇ-ଫାଇ ସ୍ୱଚାଳିତ ଭାବେ ଅନ୍ ହେବ"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"ଆପଣ ଏକ ଉଚ୍ଚ-କ୍ୱାଲିଟୀ ବିଶିଷ୍ଟ ସେଭ୍ କରାଯାଇଥିବା ନେଟ୍ୱର୍କ ପାଖରେ ଥିବା ସମୟରେ"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"ପୁଣି ଅନ୍ କରନ୍ତୁ ନାହିଁ"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"ୱାଇ-ଫାଇ ସ୍ୱଚାଳିତ ଭାବେ ଅନ୍ ହେଲା"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"ସେଭ୍ ହୋଇଥିବା ନେଟ୍ୱର୍କ ନିକଟରେ ଆପଣ ଅଛନ୍ତି: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ୱାଇ-ଫାଇ ସହ ସଂଯୋଗ ହୋଇପାରିଲା ନାହିଁ"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ଏହାର ଦୁର୍ବଳ ଇଣ୍ଟରନେଟ୍ ସଂଯୋଗ ରହିଛି।"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"ସଂଯୋଗର ଅନୁମତି ଦେବେ?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"ଆପ୍ଲିକେଶନ୍ %1$s %2$s ୱାଇ-ଫାଇ ନେଟୱର୍କକୁ ସଂଯୋଗ କରିବାକୁ ଚାହେଁ"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ଏକ ଅନୁପ୍ରୟୋଗ"</string> - <string name="accept" msgid="5931271886782610829">"ସ୍ୱୀକାର କରନ୍ତୁ"</string> - <string name="decline" msgid="6874256900873707640">"ପ୍ରତ୍ୟାଖ୍ୟାନ"</string> - <string name="ok" msgid="4215387532539340948">"ଠିକ୍ ଅଛି"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ନିମନ୍ତ୍ରଣ ପଠାଗଲା"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"ସଂଯୁକ୍ତ ହେବାକୁ ନିମନ୍ତ୍ରଣ"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"ପ୍ରେରକ:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"ପ୍ରାପ୍ତେଷୁ:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"ଆବଶ୍ୟକ PIN ଟାଇପ୍ କରନ୍ତୁ:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ ସଂଯୁକ୍ତ ହୋଇଥିବାବେଳେ, ୱାଇ-ଫାଇଠାରୁ ଟାବଲେଟ୍ଟି ଅସ୍ଥାୟୀ ଭାବେ ବିଚ୍ଛିନ୍ନ ହେବ"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ ସଂଯୋଗ ହେଉଥିବା ସମୟରେ ୱାଇ-ଫାଇରୁ ଅସ୍ଥାୟୀ ଭାବେ ବିଚ୍ଛିନ୍ନ ହେବ"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ ସଂଯୋଗ ଥିବାବେଳେ ଫୋନ୍ଟି ୱାଇ-ଫାଇରୁ ଅସ୍ଥାୟୀ ଭାବରେ ବିଚ୍ଛିନ୍ନ ହେବ"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ଠିକ୍ ଅଛି"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> ସହିତ ସଂଯୋଗ କରାଯାଇପାରିବ ନାହିଁ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"ଗୋପନୀୟତା ସେଟିଂସ୍ ବଦଳେଇବାକୁ ଟାପ୍ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"ଗୋପନୀୟତା ସେଟିଂ ବଦଳେଇବେ?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"ସଂଯୋଗ କରିବାକୁ <xliff:g id="SSID">%1$s</xliff:g> ଆପଣଙ୍କ ଡିଭାଇସର ଏକ ସ୍ୱତନ୍ତ୍ର ଚିହ୍ନଟକାରୀ ଭାବେ MAC ଠିକଣା ଆବଶ୍ୟକ କରେ। ବର୍ତ୍ତମାନ, ଏହି ନେଟୱାର୍କ ପାଇଁ ଆପଣଙ୍କ ଗୋପନୀୟତା ସେଟିଂ ଏକ ରେଣ୍ଡମାଇଜ୍ ଚିହ୍ନଟକାରୀ ବ୍ୟବହାର କରେ। \n\nଏହି ପରିବର୍ତ୍ତନ ଫଳରେ ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକୁ ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନକୁ ଟ୍ରାକ୍ କରିବାକୁ ଅନୁମତି ଦେଇପାରେ।"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ସେଟିଂକୁ ବଦଳାନ୍ତୁ"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ସେଟିଂକୁ ଅପଡେଟ୍ କରାଯାଇଛି। ପୁଣି ସଂଯୋଗ କରିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"ଗୋପନୀୟତା ସେଟିଂ ବଦଳିପାରିବ ନାହିଁ"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ନେଟ୍ୱାର୍କ ମିଳିଲା ନାହିଁ"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ପ୍ରମାଣିକତାରେ ତ୍ରୁଟି 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ପ୍ରମାଣିକତାରେ ତ୍ରୁଟି 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ପ୍ରମାଣିକତାରେ ତ୍ରୁଟି 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ପ୍ରମାଣିକତାରେ ତ୍ରୁଟି 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ପ୍ରମାଣିକତାରେ ତ୍ରୁଟି 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ପ୍ରମାଣିକତାରେ ତ୍ରୁଟି 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ପ୍ରମାଣିକତାରେ ତ୍ରୁଟି 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ହଟସ୍ପଟ୍ ବନ୍ଦ କରାଯାଇଛି"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"କୌଣସି ଡିଭାଇସ୍ ସଂଯୁକ୍ତ ନାହିଁ। ପରିବର୍ତ୍ତନ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"ୱାଇ-ଫାଇ ସଂଯୋଗ ବିଚ୍ଛିନ୍ନ ହୋଇଛି"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g>କୁ ସଂଯୋଗ କରିବା ପାଇଁ ଏକ <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM ଭର୍ତ୍ତି କରନ୍ତୁ"</string> -</resources> diff --git a/service/res/values-pa/strings.xml b/service/res/values-pa/strings.xml deleted file mode 100644 index e4e7c77e5..000000000 --- a/service/res/values-pa/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"ਸਿਸਟਮ ਵਾਈ-ਫਾਈ ਸਰੋਤ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"ਖੁੱਲ੍ਹੇ ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੋਵੋ"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"ਸਾਰੇ ਨੈੱਟਵਰਕਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"ਕਨੈਕਟ ਕਰੋ"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"ਸਾਰੇ ਨੈੱਟਵਰਕ"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ਨੈੱਟਵਰਕ ਅਵਸਥਾ"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ਨੈੱਟਵਰਕ ਸੁਚੇਤਨਾਵਾਂ"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਹੈ"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"ਕੀ ਸੁਝਾਏ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਵਰਤਣੇ ਹਨ?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ਦੇ ਸੁਝਾਏ ਨੈੱਟਵਰਕ। ਸ਼ਾਇਦ ਡੀਵਾਈਸ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਹੋਵੇ।"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ਵਰਤਣ ਦਿਓ"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ਨਹੀਂ ਧੰਨਵਾਦ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"ਕੀ <xliff:g id="CARRIERNAME">%s</xliff:g> ਵਾਈ-ਫਾਈ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਹੈ?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ਇਹ ਨੈੱਟਵਰਕ ਇੱਕ ਸਿਮ ਆਈਡੀ ਪ੍ਰਾਪਤ ਕਰਦੇ ਹਨ ਜਿਨ੍ਹਾਂ ਨੂੰ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਨੂੰ ਟਰੈਕ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ਕਨੈਕਟ ਕਰੋ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ਕਨੈਕਟ ਨਾ ਕਰੋ"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ਕੀ ਕਨੈਕਸ਼ਨ ਦੀ ਤਸਦੀਕ ਕਰਨੀ ਹੈ?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ਜੇ ਤੁਸੀਂ ਕਨੈਕਟ ਕਰਦੇ ਹੋ, ਤਾਂ <xliff:g id="CARRIERNAME">%s</xliff:g> ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੁਹਾਡੇ ਸਿਮ ਨਾਲ ਸੰਬੰਧਿਤ ਵਿਲੱਖਣ ਆਈਡੀ ਤੱਕ ਪਹੁੰਚ ਜਾਂ ਉਸ ਨੂੰ ਸਾਂਝਾ ਕਰ ਸਕਦੇ ਹਨ। ਇਸ ਨਾਲ ਸ਼ਾਇਦ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਟਿਕਾਣਾ ਟਰੈਕ ਕੀਤਾ ਜਾ ਸਕੇ।"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"ਕਨੈਕਟ ਕਰੋ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"ਕਨੈਕਟ ਨਾ ਕਰੋ"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"ਵਾਈ‑ਫਾਈ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਚੱਲ ਪਵੇਗਾ"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"ਜਦੋਂ ਤੁਸੀਂ ਕਿਸੇ ਰੱਖਿਅਤ ਕੀਤੇ ਉੱਚ-ਗੁਣਵੱਤਾ ਵਾਲੇ ਨੈੱਟਵਰਕ ਦੇ ਨੇੜੇ ਹੋਵੋ"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"ਵਾਪਸ ਚਾਲੂ ਨਾ ਕਰੋ"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"ਵਾਈ‑ਫਾਈ ਨੂੰ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"ਤੁਸੀਂ ਕਿਸੇ ਰੱਖਿਅਤ ਕੀਤੇ ਨੈੱਟਵਰਕ ਦੇ ਨੇੜੇ ਹੋ: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ਵਾਈ-ਫਾਈ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਹੋ ਸਕਿਆ"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ਇਸਦਾ ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਖਰਾਬ ਹੈ।"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"ਕੀ ਕਨੈਕਸ਼ਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"ਐਪਲੀਕੇਸ਼ਨ %1$s ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ %2$s ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦੀ ਹੈ"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ"</string> - <string name="accept" msgid="5931271886782610829">"ਸਵੀਕਾਰ ਕਰੋ"</string> - <string name="decline" msgid="6874256900873707640">"ਅਸਵੀਕਾਰ ਕਰੋ"</string> - <string name="ok" msgid="4215387532539340948">"ਠੀਕ ਹੈ"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ਸੱਦਾ ਭੇਜਿਆ"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"ਕਨੈਕਟ ਕਰਨ ਲਈ ਸੱਦਾ"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"ਇਸ ਤੋਂ:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"ਵੱਲ:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"ਲੋੜੀਂਦਾ ਪਿੰਨ ਟਾਈਪ ਕਰੋ:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"ਪਿੰਨ:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ਟੈਬਲੈੱਟ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ ਵਾਈ-ਫਾਈ ਤੋਂ ਅਸਥਾਈ ਤੌਰ ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਵੇਗਾ"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"ਤੁਹਾਡਾ Android TV ਡੀਵਾਈਸ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ \'ਤੇ ਵਾਈ-ਫਾਈ ਤੋਂ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਵੇਗਾ"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ਫ਼ੋਨ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ ਵਾਈ-ਫਾਈ ਤੋਂ ਅਸਥਾਈ ਤੌਰ ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਏਗਾ"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ਠੀਕ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"ਪਰਦੇਦਾਰੀ ਸੈਟਿੰਗਾਂ ਬਦਲਣ ਲਈ ਟੈਪ ਕਰਕੇ ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"ਕੀ ਪਰਦੇਦਾਰੀ ਸੈਟਿੰਗ ਬਦਲਣੀ ਹੈ?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"ਕਨੈਕਟ ਕਰਨ ਲਈ, <xliff:g id="SSID">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ MAC ਪਤਾ ਵਰਤਣ ਦੀ ਲੋੜ ਹੈ, ਜੋ ਕਿ ਇੱਕ ਵਿਲੱਖਣ ਪਛਾਣਕਰਤਾ ਹੁੰਦਾ ਹੈ। ਇਸ ਵੇਲੇ, ਇਸ ਨੈੱਟਵਰਕ ਲਈ ਤੁਹਾਡੀ ਪਰਦੇਦਾਰੀ ਸੈਟਿੰਗ ਇੱਕ ਬੇਤਰਤੀਬੇ ਪਛਾਣਕਰਤਾ ਦੀ ਵਰਤੋਂ ਕਰਦੀ ਹੈ। \n\nਇਸ ਤਬਦੀਲੀ ਨਾਲ ਸ਼ਾਇਦ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਨੂੰ ਟਰੈਕ ਕਰ ਸਕਣ।"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ਸੈਟਿੰਗ ਬਦਲੋ"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ਸੈਟਿੰਗ ਅੱਪਡੇਟ ਕੀਤੀ ਗਈ। ਦੁਬਾਰਾ ਕਨੈਕਟ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"ਪਰਦੇਦਾਰੀ ਸੈਟਿੰਗ ਨਹੀਂ ਬਦਲ ਸਕਦੇ"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ਨੈੱਟਵਰਕ ਨਹੀਂ ਮਿਲਿਆ"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ਪ੍ਰਮਾਣੀਕਰਨ ਗੜਬੜ 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ਪ੍ਰਮਾਣੀਕਰਨ ਗੜਬੜ 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ਪ੍ਰਮਾਣੀਕਰਨ ਗੜਬੜ 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ਪ੍ਰਮਾਣੀਕਰਨ ਗੜਬੜ 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ਪ੍ਰਮਾਣੀਕਰਨ ਗੜਬੜ 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ਪ੍ਰਮਾਣੀਕਰਨ ਗੜਬੜ 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ਪ੍ਰਮਾਣੀਕਰਨ ਗੜਬੜ 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ਹੌਟਸਪੌਟ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"ਕੋਈ ਕਨੈਕਟ ਕੀਤੇ ਹੋਏ ਡੀਵਾਈਸ ਨਹੀਂ। ਸੋਧਣ ਲਈ ਟੈਪ ਕਰੋ।"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"ਵਾਈ-ਫਾਈ ਡਿਸਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਲਈ, <xliff:g id="CARRIER_NAME">%2$s</xliff:g> ਦਾ ਸਿਮ ਪਾਓ"</string> -</resources> diff --git a/service/res/values-pl/strings.xml b/service/res/values-pl/strings.xml deleted file mode 100644 index 468495de2..000000000 --- a/service/res/values-pl/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Zasoby systemowej sieci Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Połącz się z otwartą siecią Wi-Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Łączę z siecią Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Połączono z siecią Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Nie udało się połączyć z siecią Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Kliknij, by zobaczyć wszystkie sieci"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Połącz"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Wszystkie sieci"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Stan sieci"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alerty dotyczące sieci"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Sieć dostępna"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Zezwalać na sugerowane sieci Wi‑Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Sugerowane sieci: <xliff:g id="NAME">%s</xliff:g>. Urządzenie może łączyć się automatycznie."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Zezwól"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nie, dziękuję"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Połączyć z Wi-Fi operatora <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Te sieci otrzymują identyfikator SIM, który można wykorzystać do śledzenia lokalizacji urządzenia"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Połącz"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nie łącz"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Potwierdzić połączenie?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Jeśli się połączysz, sieci Wi-Fi operatora <xliff:g id="CARRIERNAME">%s</xliff:g> będą mogły korzystać z unikalnego identyfikatora powiązanego z Twoją kartą SIM oraz go udostępniać. To może pozwolić na monitorowanie lokalizacji Twojego urządzenia."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Połącz"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Nie łącz"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi włączy się automatycznie"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Gdy znajdziesz się w pobliżu zapisanej sieci o mocnym sygnale"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Nie włączaj ponownie"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi włączone automatycznie"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Jesteś w pobliżu zapisanej sieci: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nie można połączyć się z siecią Wi-Fi."</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ma powolne połączenie internetowe."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Zezwolić na połączenie?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikacja %1$s chce połączyć się z siecią Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikacja"</string> - <string name="accept" msgid="5931271886782610829">"Akceptuj"</string> - <string name="decline" msgid="6874256900873707640">"Odrzuć"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Wysłano zaproszenie"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Zaproszenie do połączenia"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Od:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Do:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Wpisz wymagany kod PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"Kod PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Na czas połączenia z <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tablet zostanie tymczasowo odłączony od Wi-Fi"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Urządzenie z Androidem TV zostanie odłączone od sieci Wi-Fi na czas połączenia z urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Na czas połączenia z <xliff:g id="DEVICE_NAME">%1$s</xliff:g> telefon zostanie tymczasowo odłączony od Wi-Fi"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Nie można połączyć się z siecią <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Kliknij, by zmienić ustawienia prywatności, i spróbuj jeszcze raz"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Zmienić ustawienie prywatności?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Aby nawiązać połączenie, sieć <xliff:g id="SSID">%1$s</xliff:g> musi użyć adresu MAC Twojego urządzenia, który jest jego unikalnym identyfikatorem. Obecnie ustawienia prywatności w tej sieci używają randomizowanego identyfikatora. \n\nUrządzenia w pobliżu mogą w ten sposób zyskać możliwość monitorowania lokalizacji Twojego urządzenia."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Zmień ustawienie"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Zaktualizowano ustawienie. Spróbuj połączyć się ponownie."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nie można zmienić ustawienia prywatności"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Nie znaleziono sieci"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: błąd uwierzytelniania EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: błąd uwierzytelniania EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: błąd uwierzytelniania EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: błąd uwierzytelniania EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: błąd uwierzytelniania EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : błąd uwierzytelniania EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: błąd uwierzytelniania EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot jest wyłączony"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Brak połączonych urządzeń. Kliknij, by zmodyfikować."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi rozłączone"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Aby połączyć się z siecią <xliff:g id="SSID">%1$s</xliff:g>, włóż kartę SIM operatora <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-pt-rBR/strings.xml b/service/res/values-pt-rBR/strings.xml deleted file mode 100644 index c5cef5636..000000000 --- a/service/res/values-pt-rBR/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Recursos do Wi-Fi do sistema"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Conectar a uma rede Wi‑Fi aberta"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Conectando-se à rede Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Conectado a uma rede Wi‑Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Não foi possível conectar-se à rede Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Toque para ver todas as redes"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Conectar"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Todas as redes"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Status de rede"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertas de rede"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Rede disponível"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Permitir redes Wi-Fi sugeridas?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Redes sugeridas pelo app <xliff:g id="NAME">%s</xliff:g>. O dispositivo pode se conectar automaticamente."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Não"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Conectar à rede Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Essas redes recebem um ID de chip que pode ser usado para monitorar o local do dispositivo"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Não conectar"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmar a conexão?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Se você fizer a conexão, as redes Wi-Fi da <xliff:g id="CARRIERNAME">%s</xliff:g> poderão acessar ou compartilhar o código exclusivo associado ao seu chip. Isso talvez permita que o local do dispositivo seja monitorado."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Não conectar"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"O Wi‑Fi será ativado automaticamente"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Quando você estiver perto de uma rede salva de alta qualidade"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Não ativar novamente"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi ativado automaticamente"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Você está perto de uma rede salva: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Não foi possível se conectar a redes Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" tem uma conexão de baixa qualidade com a Internet."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Permitir conexão?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"O app %1$s deseja se conectar à rede Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Um app"</string> - <string name="accept" msgid="5931271886782610829">"Aceitar"</string> - <string name="decline" msgid="6874256900873707640">"Recusar"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Convite enviado"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Convite para se conectar"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Para:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Digite o PIN obrigatório:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"O tablet desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"O dispositivo Android TV desconectará o Wi-Fi temporariamente enquanto estiver conectado ao <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"O telefone desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Não foi possível se conectar à rede <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Toque para mudar as configurações de privacidade e tentar novamente"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Mudar configuração de privacidade?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Para se conectar, <xliff:g id="SSID">%1$s</xliff:g> precisa usar o endereço MAC do seu dispositivo, um identificador exclusivo. Atualmente, sua configuração de privacidade para esta rede usa um identificador aleatório. \n\nEssa mudança pode permitir que o local do dispositivo seja monitorado por dispositivos próximos."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Mudar configuração"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Configuração atualizada. Tente conectar novamente."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Não foi possível mudar as configurações de privacidade"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Rede não encontrada"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Ponto de acesso desativado"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Não há dispositivos conectados. Toque para modificar."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi desconectado"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Para se conectar a <xliff:g id="SSID">%1$s</xliff:g>, insira um chip da <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-pt-rPT/strings.xml b/service/res/values-pt-rPT/strings.xml deleted file mode 100644 index e051c21ed..000000000 --- a/service/res/values-pt-rPT/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Recursos de Wi-Fi do sistema"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Ligar à rede Wi-Fi aberta"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"A ligar à rede Wi-Fi…"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Ligado à rede Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Não foi possível ligar à rede Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Toque para ver todas as redes"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Ligar"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Todas as redes"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Estado da rede"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertas da rede"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Rede disponível"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Permitir redes Wi-Fi sugeridas?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Redes sugeridas por <xliff:g id="NAME">%s</xliff:g>. O dispositivo pode estabelecer ligação automaticamente."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Não, obrigado"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Pretende estabelecer ligação à rede Wi-Fi do operador <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Estas redes recebem um ID do SIM que pode ser utilizado para monitorizar a localização dos dispositivos."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Ligar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Não ligar"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Pretende confirmar a ligação?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Caso proceda à ligação, as redes Wi-Fi do operador <xliff:g id="CARRIERNAME">%s</xliff:g> podem partilhar ou aceder a um ID exclusivo associado ao seu SIM. Esta ação pode permitir que a localização do seu dispositivo seja monitorizada."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Ligar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Não ligar"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"O Wi‑Fi será ativado automaticamente"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Quando estiver próximo de uma rede de alta qualidade guardada."</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Não reativar"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi ativado automaticamente"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Está perto de uma rede guardada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>."</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Não foi possível ligar a Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" tem uma ligação à internet fraca."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Permitir ligação?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"A app %1$s pretende estabelecer ligação à rede Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Uma app"</string> - <string name="accept" msgid="5931271886782610829">"Aceitar"</string> - <string name="decline" msgid="6874256900873707640">"Recusar"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Convite enviado"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Convite para se ligar"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Para:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Introduza o PIN solicitado:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"O tablet sera temporariamente desligado da rede Wi-Fi enquanto estiver ligado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"O seu dispositivo Android TV irá desligar-se temporariamente da rede Wi-Fi enquanto está ligado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"O telemóvel irá desligar-se temporariamente da rede Wi-Fi enquanto está ligado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Não é possível ligar a <xliff:g id="SSID">%1$s</xliff:g>."</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Toque para alterar as definições de privacidade e tente novamente."</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Pretende alterar a definição de privacidade?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Para associar, o <xliff:g id="SSID">%1$s</xliff:g> tem de utilizar o endereço MAC do seu dispositivo, um identificador único. Atualmente, a sua definição de privacidade para esta rede utiliza um identificador aleatorizado. \n\nEsta alteração pode permitir que a localização do seu dispositivo seja monitorizada por dispositivos próximos."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Alterar definição"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Definição atualizada. Experimente estabelecer ligação novamente."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Não é possível alterar a definição de privacidade."</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Rede não encontrada."</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Zona Wi-Fi desativada"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nenhum dispositivo ligado. Toque para modificar."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi desligado"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Para estabelecer ligação a <xliff:g id="SSID">%1$s</xliff:g>, insira um SIM do operador <xliff:g id="CARRIER_NAME">%2$s</xliff:g>."</string> -</resources> diff --git a/service/res/values-pt/strings.xml b/service/res/values-pt/strings.xml deleted file mode 100644 index c5cef5636..000000000 --- a/service/res/values-pt/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Recursos do Wi-Fi do sistema"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Conectar a uma rede Wi‑Fi aberta"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Conectando-se à rede Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Conectado a uma rede Wi‑Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Não foi possível conectar-se à rede Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Toque para ver todas as redes"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Conectar"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Todas as redes"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Status de rede"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alertas de rede"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Rede disponível"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Permitir redes Wi-Fi sugeridas?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Redes sugeridas pelo app <xliff:g id="NAME">%s</xliff:g>. O dispositivo pode se conectar automaticamente."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Não"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Conectar à rede Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Essas redes recebem um ID de chip que pode ser usado para monitorar o local do dispositivo"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Não conectar"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmar a conexão?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Se você fizer a conexão, as redes Wi-Fi da <xliff:g id="CARRIERNAME">%s</xliff:g> poderão acessar ou compartilhar o código exclusivo associado ao seu chip. Isso talvez permita que o local do dispositivo seja monitorado."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Conectar"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Não conectar"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"O Wi‑Fi será ativado automaticamente"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Quando você estiver perto de uma rede salva de alta qualidade"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Não ativar novamente"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi ativado automaticamente"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Você está perto de uma rede salva: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Não foi possível se conectar a redes Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" tem uma conexão de baixa qualidade com a Internet."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Permitir conexão?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"O app %1$s deseja se conectar à rede Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Um app"</string> - <string name="accept" msgid="5931271886782610829">"Aceitar"</string> - <string name="decline" msgid="6874256900873707640">"Recusar"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Convite enviado"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Convite para se conectar"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Para:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Digite o PIN obrigatório:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"O tablet desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"O dispositivo Android TV desconectará o Wi-Fi temporariamente enquanto estiver conectado ao <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"O telefone desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Não foi possível se conectar à rede <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Toque para mudar as configurações de privacidade e tentar novamente"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Mudar configuração de privacidade?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Para se conectar, <xliff:g id="SSID">%1$s</xliff:g> precisa usar o endereço MAC do seu dispositivo, um identificador exclusivo. Atualmente, sua configuração de privacidade para esta rede usa um identificador aleatório. \n\nEssa mudança pode permitir que o local do dispositivo seja monitorado por dispositivos próximos."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Mudar configuração"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Configuração atualizada. Tente conectar novamente."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Não foi possível mudar as configurações de privacidade"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Rede não encontrada"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: erro de autenticação EAP nº 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Ponto de acesso desativado"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Não há dispositivos conectados. Toque para modificar."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi desconectado"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Para se conectar a <xliff:g id="SSID">%1$s</xliff:g>, insira um chip da <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-ro/strings.xml b/service/res/values-ro/strings.xml deleted file mode 100644 index b6ee6bee4..000000000 --- a/service/res/values-ro/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Resurse Wi-Fi pentru sistem"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Conectați-vă la o rețea Wi‑Fi deschisă"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Se conectează la rețeaua Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"S-a realizat conexiunea la rețeaua Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Nu s-a putut stabili conexiunea la rețeaua Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Atingeți pentru a vedea toate rețelele"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Conectați-vă"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Toate rețelele"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Starea rețelei"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Alerte privind rețeaua"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Rețea disponibilă"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Permiteți rețelele Wi-Fi sugerate?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> a sugerat rețele. Dispozitivul se poate conecta automat."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permiteți"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nu, mulțumesc"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vă conectați la rețeaua Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Aceste rețele primesc un cod SIM care se poate folosi pentru a urmări locația dispozitivului"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectați"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nu conectați"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmați conexiunea?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Dacă vă conectați, rețelele Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> pot să acceseze sau să trimită un ID unic asociat profilului dvs. SIM. Astfel, locația dispozitivului poate fi urmărită."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Conectați"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Nu conectați"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi se va activa automat"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Când vă aflați lângă o rețea salvată, de înaltă calitate"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Nu reactivați"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi-Fi s-a activat automat"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Vă aflați lângă o rețea salvată: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nu se poate conecta la Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" are o conexiune la internet slabă."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Permiteți conectarea?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplicația %1$s dorește să se conecteze la rețeaua Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"O aplicație"</string> - <string name="accept" msgid="5931271886782610829">"Acceptați"</string> - <string name="decline" msgid="6874256900873707640">"Refuzați"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Invitația a fost trimisă."</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Invitație pentru conectare"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"De la:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Către:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Introduceți codul PIN necesar:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"Cod PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tableta se va deconecta temporar de la rețeaua Wi-Fi cât timp este conectată la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Dispozitivul Android TV se va deconecta temporar de la rețeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefonul se va deconecta temporar de la rețeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Nu se poate conecta la <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Atingeți pentru a modifica setările de confidențialitate și a încerca din nou"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Modificați setările de confidențialitate?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Pentru a se conecta, <xliff:g id="SSID">%1$s</xliff:g> trebuie să folosească adresa MAC a dispozitivului, un identificator unic. Momentan, setarea de confidențialitate pentru această rețea folosește un identificator aleatoriu. \n\nAceastă modificare poate permite ca locația dispozitivului să fie urmărită de dispozitivele din apropiere."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Modificați setarea"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Setarea a fost actualizată. Încercați să vă conectați din nou."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nu puteți modifica setarea de confidențialitate"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Rețeaua nu a fost găsită"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : eroare de autentificare EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : eroare de autentificare EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : eroare de autentificare EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : eroare de autentificare EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : eroare de autentificare EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : eroare de autentificare EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : eroare de autentificare EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspotul a fost dezactivat"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Niciun dispozitiv conectat. Atingeți pentru a modifica."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Rețea Wi-Fi deconectată"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Pentru a vă conecta la <xliff:g id="SSID">%1$s</xliff:g>, introduceți un SIM <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-ru/strings.xml b/service/res/values-ru/strings.xml deleted file mode 100644 index 266ee0dfa..000000000 --- a/service/res/values-ru/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Системные ресурсы Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Подключитесь к открытой сети Wi‑Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Идет подключение к сети Wi-Fi…"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Подключено к сети Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Не удалось подключиться к сети Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Нажмите, чтобы увидеть список сетей"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Подключиться"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Все сети"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Статус сети"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Оповещения сети"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Сеть доступна"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Подключаться к предложенным сетям Wi‑Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Приложение \"<xliff:g id="NAME">%s</xliff:g>\" рекомендует сети, к которым устройство может подключаться автоматически."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Разрешить"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Нет, спасибо"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Подключиться к сети Wi-Fi оператора \"<xliff:g id="CARRIERNAME">%s</xliff:g>\"?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Этим сетям будет передан идентификатор SIM-карты, с помощью которого можно отслеживать местоположение устройства."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Подключиться"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не подключаться"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Подтвердите подключение"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Если вы установите подключение, Wi‑Fi-сети оператора \"<xliff:g id="CARRIERNAME">%s</xliff:g>\" смогут получать доступ к уникальному идентификатору, связанному с вашей SIM-картой, или делиться им. Это позволит отслеживать местоположение устройства."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Подключиться"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Не подключаться"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi включится автоматически"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Когда вы будете в зоне действия сохраненной сети с хорошим сигналом."</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Не включать снова"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi включен автоматически"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Вы находитесь в зоне действия сохраненной сети <xliff:g id="NETWORK_SSID">%1$s</xliff:g>."</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Не удалось подключиться к сети Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" – плохое интернет-соединение."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Разрешить подключение?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Приложение \"%1$s\" запрашивает доступ на подключение к сети Wi-Fi (%2$s)"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Приложение"</string> - <string name="accept" msgid="5931271886782610829">"Принять"</string> - <string name="decline" msgid="6874256900873707640">"Отклонить"</string> - <string name="ok" msgid="4215387532539340948">"ОК"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Приглашение отправлено"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Приглашение к подключению"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"От:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Кому:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Введите PIN-код:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-код:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"При подключении к устройству <xliff:g id="DEVICE_NAME">%1$s</xliff:g> планшетный ПК будет временно отключаться от сети Wi-Fi"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"При подключении к устройству <xliff:g id="DEVICE_NAME">%1$s</xliff:g> устройство Android TV будет временно отключаться от сети Wi-Fi."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"При подключении к устройству <xliff:g id="DEVICE_NAME">%1$s</xliff:g> телефон будет временно отключаться от сети Wi-Fi"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ОК"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Не удалось подключиться к устройству \"<xliff:g id="SSID">%1$s</xliff:g>\""</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Нажмите, чтобы изменить настройки конфиденциальности и повторить попытку."</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Изменить настройки конфиденциальности?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Для подключения сети <xliff:g id="SSID">%1$s</xliff:g> необходим MAC-адрес вашего устройства (уникальный идентификатор). Сейчас ваша настройка конфиденциальности для этой сети использует случайный идентификатор. \n\nЭто изменение может привести к тому, что устройства поблизости смогут отслеживать ваше местоположение."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Изменить настройки"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Настройки сохранены. Попробуйте подключиться ещё раз."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Не удается изменить настройки конфиденциальности."</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Сеть не найдена."</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Ошибка аутентификации EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Ошибка аутентификации EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Ошибка аутентификации EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Ошибка аутентификации EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Ошибка аутентификации EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Ошибка аутентификации EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Ошибка аутентификации EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Точка доступа отключена"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Нет подключенных устройств. Нажмите, чтобы внести изменения."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Нет подключения к Wi-Fi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Чтобы подключиться к сети \"<xliff:g id="SSID">%1$s</xliff:g>\", вставьте SIM-карту оператора \"<xliff:g id="CARRIER_NAME">%2$s</xliff:g>\"."</string> -</resources> diff --git a/service/res/values-si/strings.xml b/service/res/values-si/strings.xml deleted file mode 100644 index 959f31c59..000000000 --- a/service/res/values-si/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"පද්ධති Wi-Fi සම්පත්"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"විවෘත Wi-Fi ජාලය වෙත සම්බන්ධ වෙන්න"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi-Fi ජාලයට සම්බන්ධ වෙමින්"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi-Fi ජාලයක් වෙත සම්බන්ධ විය"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi-Fi ජාලයක් වෙත සම්බන්ධ විය නොහැකි විය"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"සියලු ජාල බැලීමට තට්ටු කරන්න"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"සම්බන්ධ කරන්න"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"සියලු ජාල"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"ජාල තත්ත්වය"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"ජාල ඇඟවීම්"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"ජාලය ලබා ගැනීමට හැකිය"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"යෝජිත Wi-Fi ජාල ඉඩ දෙන්නද?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> යෝජිත ජාල. උපාංගය ස්වයංක්රියව සම්බන්ධ වනු ඇත."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ඉඩ දෙන්න"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"එපා, ස්තූතියි"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi වෙත සබඳින්නද?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"උපාංග ස්ථානය නිරීක්ෂණය කිරීමට භාවිත කළ හැකි SIM ID එකක් මෙම ජාලවලට ලැබේ"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"සම්බන්ධ කරන්න"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"සම්බන්ධ නොකරන්න"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"නිවැරදි කිරීම තහවුරු කරන්නද?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ඔබ සම්බන්ධ වුවහොත්, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi ජාල ඔබේ SIM එක හා සම්බන්ධිත අනන්ය ID එකකට ප්රවේශ වීමට හෝ එය බෙදා ගැනීමට හැකිය. මෙය ඔබේ උපාංගයෙහි ස්ථානය නිරීක්ෂණය කිරීමට ඉඩ දිය හැකිය."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"සම්බන්ධ කරන්න"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"සම්බන්ධ නොකරන්න"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi ස්වයංක්රියව ක්රියාත්මක වනු ඇත"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"ඔබ උසස් තත්ත්වයේ සුරැකි ජාලයක් අවට සිටින විට"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"නැවත ක්රියාත්මක නොකරන්න"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi ස්වයංක්රියව ක්රියාත්මක කරන ලදි"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"ඔබ සුරැකි ජාලයක් අවට සිටී: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi වෙත සම්බන්ධ විය නොහැක"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" වෙත දුර්වල අන්තර්ජාල සම්බන්ධතාවයක් ඇත."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"සම්බන්ධතාවයට ඉඩ දෙන්නද?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"යෙදුම් %1$s ක් WiFi ජාලය %2$s වෙත සම්බන්ධ කිරීමට කැමතියි"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"යෙදුම"</string> - <string name="accept" msgid="5931271886782610829">"පිළිගන්න"</string> - <string name="decline" msgid="6874256900873707640">"ප්රතික්ෂේප කරන්න"</string> - <string name="ok" msgid="4215387532539340948">"හරි"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ආරාධනාව යවන ලදි"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"සම්බන්ධතාවයට ඇරයුමකි"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"වෙතින්:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"වෙත:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"අවශ්ය PIN එක ටයිප් කරන්න:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ටැබ්ලටය <xliff:g id="DEVICE_NAME">%1$s</xliff:g> වෙත සම්බන්ධ වන අතරතුර එය Wi-Fi වලින් තාවකාලිකව විසන්ධි කෙරේ."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"ඔබගේ Android TV උපාංගය <xliff:g id="DEVICE_NAME">%1$s</xliff:g> වෙත සම්බන්ධ වී පවතින විට Wi-Fi වෙතින් එය තාවකාලිකව විසන්ධි වනු ඇත"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"දුරකථනය <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ට සම්බන්ධ වී පවතින විට Wi-Fi වලින් එය තාවකාලිකව විසන්ධි වෙයි."</string> - <string name="dlg_ok" msgid="3250085870426030310">"හරි"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> වෙත සම්බන්ධ විය නොහැකිය"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"රහස්යතා සැකසීම් වෙනස් කිරීමට තට්ටු කර යළි උත්සාහ කරන්න"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"රහස්යතා සැකසීම වෙනස් කරන්නද?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"සම්බන්ධ වීමට, <xliff:g id="SSID">%1$s</xliff:g> හට ඔබේ උපාංග MAC ලිපිනය, අනන්ය අනන්යකාරකයක් භාවිත කිරීමට අවශ්යය. දැනට, මෙම ජාලය සඳහා ඔබේ රහස්යතා සැකසීම සසම්භාවීකරණය කළ අනන්යකාරකයක් භාවිත කරයි. \n\nමෙය ඔබේ උපාංගයේ ස්ථානය අවට උපාංග මගින් නිරීක්ෂණය කිරීමට ඉඩ දිය හැකිය."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"සැකසීම වෙනස් කරන්න"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"සැකසීම යාවත්කාලීනයි. නැවත සබැඳීමට උත්සාහ කරන්න."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"රහස්යතා සැකසීම වෙනස් කළ නොහැකිය"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ජාලය හමු වූයේ නැත"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP සත්යාපනය කිරීමේ දෝෂය 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP සත්යාපනය කිරීමේ දෝෂය 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP සත්යාපනය කිරීමේ දෝෂය 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP සත්යාපනය කිරීමේ දෝෂය 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP සත්යාපනය කිරීමේ දෝෂය 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP සත්යාපනය කිරීමේ දෝෂය 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP සත්යාපනය කිරීමේ දෝෂය 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"හොට්ස්පොට් ක්රියා විරහිතයි"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"උපාංග කිසිවක් සම්බන්ධ කර නැත. වෙනස් කිරීමට තට්ටු කරන්න."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi‑Fi විසන්ධි විය"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> වෙත සම්බන්ධ වීමට, <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM එකක් ඇතුල් කරන්න"</string> -</resources> diff --git a/service/res/values-sk/strings.xml b/service/res/values-sk/strings.xml deleted file mode 100644 index db3478bf1..000000000 --- a/service/res/values-sk/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Zdroje systému Wi‑Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Pripojenie k otvorenej sieti Wi‑Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Pripája sa k sieti Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Pripojenie k sieti Wi‑Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"K sieti Wi‑Fi sa nepodarilo pripojiť"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Klepnutím zobrazíte všetky siete"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Pripojiť"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Všetky siete"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Stav siete"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Upozornenia týkajúce sa siete"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Sieť je k dispozícii"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Chcete povoliť navrhované siete Wi‑Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Siete navrhuje aplikácia <xliff:g id="NAME">%s</xliff:g>. Zariadenie sa môže pripájať automaticky."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Povoliť"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nie, ďakujem"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Chcete sa pripojiť k sieti Wi‑Fi operátora <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Tieto siete dostávajú jedinečný identifikátor SIM karty, pomocou ktorého je možné sledovať polohu zariadenia"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Pripojiť"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nepripojiť"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Chcete potvrdiť pripojenie?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Po pripojení môžu siete Wi‑Fi operátora <xliff:g id="CARRIERNAME">%s</xliff:g> pristupovať k jedinečnému identifikátoru spojenému s vašou SIM kartou alebo ho zdieľať. To umožňuje sledovať polohu vášho zariadenia."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Pripojiť"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Nepripojiť"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi sa zapne automaticky"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Keď budete v blízkosti kvalitnej uloženej siete"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Znova nezapínať"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Pripojenie Wi‑Fi sa zaplo automaticky"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Ste v blízkosti uloženej siete: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nepodarilo sa pripojiť k sieti Wi‑Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" má nekvalitné internetové pripojenie."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Povoliť pripojenie?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikácia %1$s sa chce pripojiť k sieti Wi‑Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikácia"</string> - <string name="accept" msgid="5931271886782610829">"Prijať"</string> - <string name="decline" msgid="6874256900873707640">"Odmietnuť"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Pozvánka bola odoslaná"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Pozvánka na pripojenie"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Od:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Komu:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Zadajte požadovaný kód PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet bude počas pripojenia k zariadeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> od siete Wi‑Fi dočasne odpojený."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Zariadenie Android TV sa počas pripojenia k zariadeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> dočasne odpojí od siete Wi‑Fi"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefón bude počas pripojenia k zariadeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> od siete Wi‑Fi dočasne odpojený."</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"K sieti <xliff:g id="SSID">%1$s</xliff:g> sa nedá pripojiť"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Klepnutím zmeňte nastavenia ochrany súkromia a skúste to znova"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Chcete zmeniť nastavenie ochrany súkromia?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> potrebuje na pripojenie jedinečný identifikátor, ktorým je adresa MAC vášho zariadenia. Vaše nastavenie ochrany súkromia pre túto sieť momentálne používa náhodný identifikátor. \n\nZariadenia v okolí tak budú môcť sledovať polohu vášho zariadenia."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Zmeniť nastavenie"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Nastavenie bolo aktualizované. Skúste sa znova pripojiť."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nastavenie ochrany súkromia sa nedá zmeniť"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Sieť nebola nájdená"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : chyba overenia EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : chyba overenia EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : chyba overenia EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : chyba overenia EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : chyba overenia EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : chyba overenia EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : chyba overenia EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot je vypnutý"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nie sú pripojené žiadne zariadenia. Klepnutím to môžete upraviť."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Sieť Wi‑Fi je odpojená"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Ak sa chcete pripojiť k sieti <xliff:g id="SSID">%1$s</xliff:g>, vložte SIM kartu operátora <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-sl/strings.xml b/service/res/values-sl/strings.xml deleted file mode 100644 index 990cddd22..000000000 --- a/service/res/values-sl/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistemska sredstva za Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Vzpostavite povezavo z odprtim omrežjem Wi‑Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Vzpostavljanje povezave z omrežjem Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Povezava z omrežjem Wi-Fi je vzpostavljena"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Povezave z omrežjem Wi-Fi ni bilo mogoče vzpostaviti"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Dotaknite se, če si želite ogledati vsa omrežja"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Vzpostavi povezavo"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Vsa omrežja"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Stanje omrežja"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Opozorila omrežja"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Omrežje je na voljo"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Želite dovoliti predlagana omrežja Wi-Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> – predlagana omrežja. Naprava se lahko poveže samodejno."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Dovoli"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, hvala"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Želite vzpostaviti povezavo z omrežjem Wi-Fi operaterja <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ta omrežja prejmejo ID kartice SIM, s katerim je mogoče spremljati lokacijo naprave."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Poveži"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne poveži"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Želite potrditi povezavo?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Če vzpostavite povezavo, lahko omrežja Wi-Fi operaterja <xliff:g id="CARRIERNAME">%s</xliff:g> dostopajo do enoličnega ID-ja, povezanega s kartico SIM, in ga delijo. To lahko omogoči spremljanje lokacije naprave."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Poveži"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ne poveži"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Povezava Wi‑Fi se bo samodejno vklopila"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Ko ste v bližini zanesljivega shranjenega omrežja"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ne vklopi znova"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi je bil vklopljen samodejno"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Ste v bližini shranjenega omrežja: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Z omrežjem Wi-Fi se ni mogoče povezati"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ima slabo internetno povezavo."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Ali dovolite vzpostavitev povezave?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikacija %1$s želi vzpostaviti povezavo z omrežjem Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikacija"</string> - <string name="accept" msgid="5931271886782610829">"Sprejmem"</string> - <string name="decline" msgid="6874256900873707640">"Zavrni"</string> - <string name="ok" msgid="4215387532539340948">"V redu"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Povabilo je poslano"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Povabilo za povezavo"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Od:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Za:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Vnesite zahtevano kodo PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablični računalnik bo začasno prekinil povezavo z Wi-Fi-jem, medtem ko je povezan z napravo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Naprava Android TV bo začasno prekinila povezavo z omrežjem Wi-Fi, medtem ko je povezana z napravo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon bo začasno prekinil povezavo z Wi-Fi-jem, ko je povezan z napravo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"V redu"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Povezava z omrežjem <xliff:g id="SSID">%1$s</xliff:g> ni mogoča"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Dotaknite se za spremembo nastavitev zasebnosti in poskusite znova"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Želite spremeniti nastavitev zasebnosti?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Za vzpostavitev povezave mora omrežje <xliff:g id="SSID">%1$s</xliff:g> uporabiti naslov MAC naprave, ki je enolični identifikator. Nastavitev zasebnosti za to omrežje trenutno uporablja naključno določen identifikator. \n\nTa sprememba lahko napravam v bližini omogoči spremljanje lokacije vaše naprave."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Spremeni nastavitev"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Nastavitev je posodobljena. Poskusite se znova povezati."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Nastavitve zasebnosti ni mogoče spremeniti"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Omrežja ni mogoče najti"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: Napaka 32760 pri preverjanju pristnosti EAP"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: Napaka 32761 pri preverjanju pristnosti EAP"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: Napaka 32762 pri preverjanju pristnosti EAP"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: Napaka 32763 pri preverjanju pristnosti EAP"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: Napaka 32764 pri preverjanju pristnosti EAP"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: Napaka 32765 pri preverjanju pristnosti EAP"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: Napaka 32766 pri preverjanju pristnosti EAP"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Dostopna točka je izklopljena"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nobena naprava ni povezana. Dotaknite se, da spremenite."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Povezava Wi-Fi je prekinjena"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Za povezavo z omrežjem <xliff:g id="SSID">%1$s</xliff:g> vstavite kartico SIM operaterja <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-sq/strings.xml b/service/res/values-sq/strings.xml deleted file mode 100644 index 1bee4985f..000000000 --- a/service/res/values-sq/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Burimet Wi-Fi të sistemit"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Lidhu me rrjetin e hapur Wi‑Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Po lidhet me rrjetin Wi‑Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Lidhur me rrjetin e hapur Wi‑Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Nuk mund të lidhet me rrjetin Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Trokit për të parë të gjitha rrjetet"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Lidhu"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Të gjitha rrjetet"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Statusi i rrjetit"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Sinjalizimet e rrjetit"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Ka rrjet të disponueshëm"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Të lejohen rrjetet e sugjeruara Wi‑Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Rrjet e sugjeruara të <xliff:g id="NAME">%s</xliff:g>. Pajisja mund të lidhet automatikisht."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Lejo"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Jo, faleminderit"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Do të lidhesh me Wi-Fi nga <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Këto rrjete marrin një ID karte SIM që mund të përdoret për të monitoruar vendndodhjen"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Lidh"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Mos u lidh"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Të konfirmohet lidhja?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Nëse lidhesh, rrjetet Wi-Fi të <xliff:g id="CARRIERNAME">%s</xliff:g> mund të kenë qasje ose mund të ndajnë një ID unike që lidhet me kartën tënde SIM. Kjo mund të lejojë monitorimin e vendndodhjes sate."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Lidhu"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Mos u lidh"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi do të aktivizohet automatikisht"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kur ndodhesh pranë një rrjeti të ruajtur me cilësi të lartë"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Mos e aktivizo përsëri"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi u aktivizua automatikisht"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Ndodhesh pranë një rrjeti të ruajtur: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nuk mund të lidhej me Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ka një lidhje të dobët interneti."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Të lejohet lidhja?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikacioni %1$s do të lidhet me rrjetin Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Një aplikacion"</string> - <string name="accept" msgid="5931271886782610829">"Prano"</string> - <string name="decline" msgid="6874256900873707640">"Refuzo"</string> - <string name="ok" msgid="4215387532539340948">"Në rregull"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Ftesa u dërgua"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Ftesë për t\'u lidhur"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Nga:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Për:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Shkruaj PIN-in e kërkuar:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-i:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tableti do të shkëputet përkohësisht nga Wi-Fi gjatë kohës së lidhjes me <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Pajisja jote Android TV do të shkëputet përkohësisht nga Wi-Fi ndërkohë që është e lidhur me <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefoni do të shkëputet përkohësisht nga Wi-Fi gjatë kohës së lidhjes me <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Në rregull"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Nuk mund të lidhet me <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Trokit për të ndryshuar cilësimet e privatësisë dhe provo përsëri"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Do ta ndryshosh cilësimin e privatësisë?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Për t\'u lidhur, <xliff:g id="SSID">%1$s</xliff:g> ka nevojë të përdorë adresën MAC të pajisjes sate, një identifikues unik. Aktualisht, cilësimi yt i privatësisë për këtë rrjet përdor një identifikues të rastësishëm. \n\nKy ndryshim mund të lejojë monitorimin e vendndodhjes së pajisjes sate nga pajisjet në afërsi."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Ndrysho cilësimin"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Cilësimi u përditësua. Provo të lidhesh përsëri."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Cilësimi i privatësisë nuk mund të ndryshohet"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Rrjeti nuk u gjet"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Gabimi i vërtetimit të EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Gabimi i vërtetimit të EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Gabimi i vërtetimit të EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Gabimi i vërtetimit të EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Gabimi i vërtetimit të EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Gabimi i vërtetimit të EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Gabimi i vërtetimit të EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Zona e qasjes për internet është çaktivizuar"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nuk ka pajisje të lidhura. Trokit për ta modifikuar."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi është i shkëputur"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Për t\'u lidhur me <xliff:g id="SSID">%1$s</xliff:g> fut një kartë SIM nga <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-sr/strings.xml b/service/res/values-sr/strings.xml deleted file mode 100644 index 74bf98238..000000000 --- a/service/res/values-sr/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Системски WiFi ресурси"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Повежите се са отвореном Wi‑Fi мрежом"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Повезује се са WiFi мрежом..."</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Повезали сте се са Wi‑Fi мрежом"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Повезивање са Wi‑Fi мрежом није успело"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Додирните да бисте видели све мреже"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Повежи"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Све мреже"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Статус мреже"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Обавештења у вези са мрежом"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Мрежа је доступна"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Желите да дозволите предложене Wi‑Fi мреже?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Мреже које предлаже <xliff:g id="NAME">%s</xliff:g>. Уређај ће се можда повезати аутоматски."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Дозволи"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Не, хвала"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Желите да се повежете на WiFi мрежу <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ове мреже добијају ИД SIM картице који може да се користи за праћење локације уређаја"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Повежи"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не повезуј"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Желите ли да потврдите повезивање?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ако се повежете, Wi‑Fi мреже оператера <xliff:g id="CARRIERNAME">%s</xliff:g> могу да приступају јединственом ИД-у повезаном са SIM картицом или да га деле. То може да омогући праћење локације уређаја."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Повежи"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Не повезуј"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi ће се аутоматски укључити"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Када сте у близини сачуване мреже високог квалитета"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Не укључуј поново"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi је аутоматски укључен"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"У близини сте сачуване мреже: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Није могуће повезати са WiFi мрежом"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" има лошу интернет везу."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Желите ли да дозволите повезивање?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Апликација %1$s жели да се повеже на WiFi мрежу %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Апликација"</string> - <string name="accept" msgid="5931271886782610829">"Прихвати"</string> - <string name="decline" msgid="6874256900873707640">"Одбиј"</string> - <string name="ok" msgid="4215387532539340948">"Потврди"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Позивница је послата"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Позивница за повезивање"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Од:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Коме:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Унесите потребни PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Таблет ће привремено прекинути везу са WiFi-ем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV уређај ће привремено прекинути везу са WiFi мрежом док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Телефон ће привремено прекинути везу са WiFi-ем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Потврди"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Повезивање на мрежу <xliff:g id="SSID">%1$s</xliff:g> није успело"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Додирните да бисте променили подешавања приватности и пробали поново"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Желите ли да промените подешавања приватности?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> треба да се повеже помоћу MAC адресе уређаја, јединственог идентификатора. Подешавање приватности за ову мрежу тренутно користи насумични идентификатор. \n\nОва измена може да омогући уређајима у близини да прате локацију уређаја."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Промени подешавање"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Подешавање је ажурирано. Пробајте поново да се повежете."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Промена подешавања приватности није успела"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Мрежа није пронађена"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP грешка при потврди идентитета 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP грешка при потврди идентитета 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP грешка при потврди идентитета 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP грешка при потврди идентитета 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP грешка при потврди идентитета 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP грешка при потврди идентитета 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP грешка при потврди идентитета 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Хотспот је искључен"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Ниједан уређај није повезан. Додирните да бисте изменили."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"WiFi веза је прекинута"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Да бисте се повезали на мрежу <xliff:g id="SSID">%1$s</xliff:g>, ставите <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM картицу"</string> -</resources> diff --git a/service/res/values-sv/strings.xml b/service/res/values-sv/strings.xml deleted file mode 100644 index 01fe1a832..000000000 --- a/service/res/values-sv/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Resurser för Wi-Fi-system"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Anslut till ett öppet Wi-Fi-nätverk"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Ansluter till Wi-Fi-nätverk"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Ansluten till Wi-Fi-nätverket"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Det gick inte att ansluta till Wi‑Fi-nätverket"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tryck för att visa alla nätverk"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Anslut"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Alla nätverk"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Nätverksstatus"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Nätverksvarningar"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Nätverk tillgängligt"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Vill du tillåta föreslagna Wi-Fi-nätverk?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Nätverk som föreslagits av <xliff:g id="NAME">%s</xliff:g>. Enheten kan anslutas automatiskt."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Tillåt"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nej tack"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vill du ansluta till Wi-Fi från <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Dessa nätverk får ett SIM-id som kan användas till att spåra enhetens plats"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Anslut"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Anslut inte"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vill du bekräfta anslutningen?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Om du ansluter kan Wi-Fi-nätverk från <xliff:g id="CARRIERNAME">%s</xliff:g> få åtkomst till eller dela ett unikt id som är kopplat till ditt SIM-kort. Detta kan göra det möjligt att spåra enhetens plats."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Anslut"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Anslut inte"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi aktiveras automatiskt"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"När du är i närheten av ett sparat nätverk av hög kvalitet"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Återaktivera inte"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi-Fi aktiverades automatiskt"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Du är i närheten av ett sparat nätverk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Det gick inte att ansluta till Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" har en dålig Internetanslutning."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Tillåt anslutning?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Appen %1$s vill ansluta till Wi-Fi-nätverket %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"En app"</string> - <string name="accept" msgid="5931271886782610829">"Godkänn"</string> - <string name="decline" msgid="6874256900873707640">"Avvisa"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Inbjudan har skickats"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Inbjudan om att ansluta"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Från:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Till:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Ange den obligatoriska PIN-koden:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-kod:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Surfplattans Wi-Fi-anslutning kommer tillfälligt att avbrytas när den är ansluten till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV-enheten kopplas tillfälligt från Wi-Fi medan den är ansluten till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Mobilen kommer tillfälligt att kopplas från Wi-Fi när den är ansluten till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Det gick inte att ansluta till <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Tryck för att ändra sekretessinställningar och försök igen"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Vill du ändra sekretessinställningar?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> måste använda enhetens MAC-adress (en unik identifierare) vid anslutningen. Just nu används en slumpgenererad identifierare enligt integritetsinställningarna för nätverket. \n\nDetta kan göra det möjligt för enheter i närheten att spåra enhetens plats."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Ändra inställning"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Inställningen har uppdaterats. Försök ansluta igen."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Det gick inte att ändra sekretessinställningen"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Nätverket hittades inte"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-autentiseringsfel 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-autentiseringsfel 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-autentiseringsfel 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-autentiseringsfel 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-autentiseringsfel 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-autentiseringsfel 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP-autentiseringsfel 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Surfzonen har inaktiverats"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Inga enheter har anslutits. Tryck för att ändra."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Ingen Wi-Fi-anslutning"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Sätt i ett SIM-kort från <xliff:g id="CARRIER_NAME">%2$s</xliff:g> om du vill ansluta till <xliff:g id="SSID">%1$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-sw/strings.xml b/service/res/values-sw/strings.xml deleted file mode 100644 index 5ab27d395..000000000 --- a/service/res/values-sw/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Nyenzo za Wi-Fi ya Mfumo"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Unganisha kwenye mtandao wa Wi‑Fi unaotumiwa na mtu yeyote"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Inaunganisha kwenye mtandao wa Wi‑Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Imeunganisha kwenye mtandao wa Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Imeshindwa kuunganisha kwenye mtandao wa Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Gusa ili uone mitandao yote"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Unganisha"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Mitandao yote"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Hali ya mtandao"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Arifa za mtandao"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Mtandao unapatikana"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Ungependa kuruhusu mitandao inayopendekezwa ya Wi-Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mitandao inayopendekezwa kwa ajili ya <xliff:g id="NAME">%s</xliff:g>. Huenda kifaa kikaunganisha kiotomatiki."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Ruhusu"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Hapana"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Ungependa kuunganisha kwenye Wi‑Fi ya <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Mitandao hii hupokea kitambulisho cha SIM kinachoweza kutumika ili kufuatilia mahali kifaa kilipo"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Unganisha"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Usiunganishe"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Ungependa kuthibitisha muunganisho?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ukiunganisha, huenda mitandao ya Wi-Fi ya <xliff:g id="CARRIERNAME">%s</xliff:g> ikafikia au kushiriki kitambulisho cha kipekee kinachohusishwa na SIM yako. Huenda hii ikaruhusu ufuatiliaji wa mahali kifaa chako kilipo."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Unganisha"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Usiunganishe"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi itawashwa kiotomatiki"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Unapokuwa karibu na mtandao uliohifadhiwa wenye ubora wa juu"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Usiwashe tena"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi imewashwa kiotomatiki"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Uko karibu na mtandao uliohifadhiwa: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Imeshindwa kuunganisha Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" inao muunganisho duni wa wavuti."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Ungepenga kuruhusu muunganisho?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Programu ya %1$s ingependa kuunganisha kwenye Mtandao wa Wifi wa %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Programu"</string> - <string name="accept" msgid="5931271886782610829">"Kubali"</string> - <string name="decline" msgid="6874256900873707640">"Kataa"</string> - <string name="ok" msgid="4215387532539340948">"Sawa"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Mwaliko umetumwa"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Mwaliko wa kuunganisha"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Kutoka:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kwa:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Charaza PIN inayohitajika:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Kompyuta ndogo itaukata muunganisho kwa muda kutoka kwenye Wi-Fi inapokuwa imeunganishwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Kifaa chako cha Android TV kitatenganishwa na Wi-Fi kwa muda wakati kimeunganishwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Simu itaukata muunganisho kwa muda kutoka kwenye Wi-Fi inapokuwa imeunganishwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Sawa"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Imeshindwa kuunganisha kwenye <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Gusa ili ubadilishe mipangilio ya faragha na ujaribu tena"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Ungependa kubadilisha mipangilio ya faragha?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Ili kuunganisha, <xliff:g id="SSID">%1$s</xliff:g> inahitaji kutumia anwani ya MAC ya kifaa chako, kitambulishi cha kipekee. Kwa sasa, mipangilio yako ya faragha ya mtandao huu inatumia kitambulishi kwa nasibu \n\nMabadiliko haya yanaweza kuruhusu vifaa vilivyo karibu nawe vifuatilie mahali kifaa chako kilipo."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Badilisha mipangilio"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Imesasisha mipangilio. Jaribu kuunganisha tena."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Imeshindwa kubadilisha mipangilio ya faragha"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Mtandao haupatikani"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Hitilafu ya 32760 ya uthibitishaji wa EAP"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Hitilafu ya 32761 ya uthibitishaji wa EAP"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Hitilafu ya 32762 ya uthibitishaji wa EAP"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Hitilafu ya 32763 ya uthibitishaji wa EAP"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Hitilafu ya 32764 ya uthibitishaji wa EAP"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Hitilafu ya 32765 ya uthibitishaji wa EAP"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Hitilafu ya 32766 ya uthibitishaji wa EAP"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Mtandaopepe umezimwa"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Hakuna vifaa vilivyounganishwa. Gusa ili ubadilishe."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi imeondolewa"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Ili uunganishe kwenye <xliff:g id="SSID">%1$s</xliff:g>, weka SIM ya <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-ta/strings.xml b/service/res/values-ta/strings.xml deleted file mode 100644 index 0fe47fea7..000000000 --- a/service/res/values-ta/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"சிஸ்டம் வைஃபை ஆதாரங்கள்"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"திறந்த வைஃபை நெட்வொர்க்குடன் இணைக்கவும்"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"வைஃபை நெட்வொர்க்குடன் இணைக்கிறது"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"வைஃபை நெட்வொர்க்குடன் இணைக்கப்பட்டது"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"வைஃபை நெட்வொர்க்குடன் இணைக்க முடியவில்லை"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"எல்லா நெட்வொர்க்குகளையும் பார்க்க, தட்டவும்"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"இணை"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"எல்லா நெட்வொர்க்குகளும்"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"நெட்வொர்க்கின் நிலை"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"நெட்வொர்க் விழிப்பூட்டல்கள்"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"நெட்வொர்க் உள்ளது"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"பரிந்துரைக்கப்பட்ட வைஃபை நெட்வொர்க்குகளை அனுமதிக்க வேண்டுமா?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> பரிந்துரைக்கும் நெட்வொர்க்குகள். சாதனம் தானாக இணைக்கப்படக்கூடும்."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"அனுமதி"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"வேண்டாம்"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> வைஃபையுடன் இணைக்கவா?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"சாதன இருப்பிடத்தைக் கண்காணிக்கப் பயன்படுத்தப்படும் சிம் ஐடியை இந்த நெட்வொர்க்குகள் பெறும்"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"இணை"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"இணைக்காதே"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"நிச்சயமாக இணைக்கவா?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"இணைத்தால், உங்கள் SIMமுடன் இணைக்கப்பட்டிருக்கும் தனிப்பட்ட ஐடியை <xliff:g id="CARRIERNAME">%s</xliff:g> வைஃபை நெட்வொர்க்குகள் அணுகக்கூடும் அல்லது பகிரக்கூடும். இதனால் உங்கள் சாதனத்தின் இருப்பிடத்தை டிராக் செய்ய அனுமதிக்கப்படலாம்."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"இணை"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"இணைக்காதே"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"வைஃபை தானாக ஆன் ஆகும்"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"சேமித்த, உயர்தர நெட்வொர்க்கிற்கு அருகில் இருக்கும்போது"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"மீண்டும் ஆன் செய்யாதே"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"வைஃபை தானாகவே ஆன் செய்யப்பட்டது"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> என்ற சேமிக்கப்பட்ட நெட்வொர்க் அருகில் உள்ளீர்கள்"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"வைஃபை உடன் இணைக்க முடியவில்லை"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" இணைய இணைப்பு மோசமாக உள்ளது."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"இணைப்பை அனுமதிக்கவா?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%2$s வைஃபை நெட்வொர்க்குடன், %1$s ஆப்ஸ் இணைக்க விரும்புகிறது"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ஒரு ஆப்ஸ்"</string> - <string name="accept" msgid="5931271886782610829">"ஏற்கிறேன்"</string> - <string name="decline" msgid="6874256900873707640">"நிராகரி"</string> - <string name="ok" msgid="4215387532539340948">"சரி"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"அழைப்பு அனுப்பப்பட்டது"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"இணைவதற்கான அழைப்பு"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"அனுப்புநர்:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"பெறுநர்:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"பின்வரும் அவசியமான பின்னை உள்ளிடவும்:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"பின்:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் டேப்லெட் இணைக்கப்படும்போது, வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"உங்கள் Android TV <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்துடன் இணைக்கப்பட்டிருக்கும் போது வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் மொபைல் இணைக்கப்படும்போது, வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்."</string> - <string name="dlg_ok" msgid="3250085870426030310">"சரி"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> உடன் இணைக்க முடியவில்லை"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"தனியுரிமை அமைப்புகளை மாற்ற தட்டி மீண்டும் முயலவும்"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"தனியுரிமை அமைப்பை மாற்றவா?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"இணைப்பதற்கு, தனித்துவமான அடையாளங்காட்டியான உங்கள் சாதன MAC முகவரியை <xliff:g id="SSID">%1$s</xliff:g> பயன்படுத்த வேண்டும். தற்போது, இந்த நெட்வொர்க்கிற்கான உங்கள் தனியுரிமை அமைப்பானது ரேண்டம் ஆக்கப்பட்ட அடையாளங்காட்டியைப் பயன்படுத்துகிறது. \n\nஇதனால் உங்கள் சாதனத்தின் இருப்பிடத்தை டிராக் செய்ய அருகில் இருக்கும் சாதனங்கள் அனுமதிக்கப்படக்கூடும்."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"அமைப்பை மாற்று"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"அமைப்பு புதுப்பிக்கப்பட்டது. மீண்டும் இணைக்க முயலவும்."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"தனியுரிமை அமைப்பை மாற்ற இயலவில்லை"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"நெட்வொர்க்கைக் கண்டறிய முடியவில்லை"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP அங்கீகரிப்புப் பிழை 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP அங்கீகரிப்புப் பிழை 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP அங்கீகரிப்புப் பிழை 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP அங்கீகரிப்புப் பிழை 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP அங்கீகரிப்புப் பிழை 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP அங்கீகரிப்புப் பிழை 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP அங்கீகரிப்புப் பிழை 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ஹாட்ஸ்பாட் முடக்கப்பட்டது"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"சாதனங்கள் எதுவும் இணைக்கப்படவில்லை. மாற்ற, தட்டவும்."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"வைஃபை துண்டிக்கப்பட்டது"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> இல் இணைக்க <xliff:g id="CARRIER_NAME">%2$s</xliff:g> சிம்மைச் செருகவும்"</string> -</resources> diff --git a/service/res/values-te/strings.xml b/service/res/values-te/strings.xml deleted file mode 100644 index fedd99034..000000000 --- a/service/res/values-te/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"సిస్టమ్ Wi-Fi వనరులు"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"బహిరంగ Wi‑Fi నెట్వర్క్కు కనెక్ట్ చేయండి"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi నెట్వర్క్కి కనెక్ట్ చేస్తోంది"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi నెట్వర్క్కు కనెక్ట్ చేయబడింది"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi నెట్వర్క్కు కనెక్ట్ చేయడం సాధ్యపడలేదు"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"అన్ని నెట్వర్క్లు చూడటానికి నొక్కండి"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"కనెక్ట్ చేయి"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"అన్ని నెట్వర్క్లు"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"నెట్వర్క్ స్థితి"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"నెట్వర్క్ హెచ్చరికలు"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"నెట్వర్క్ అందుబాటులో ఉంది"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"సూచించిన Wi‑Fi నెట్వర్క్లను అనుమతించాలా?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> సూచించిన నెట్వర్క్లు. పరికరం ఆటోమేటిక్గా కనెక్ట్ అవచ్చు."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"అనుమతించు"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"వద్దు"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fiకి కనెక్ట్ చేయాలా?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"పరికర లొకేషన్ను ట్రాక్ చేయడానికి ఉపయోగపడే SIM IDని ఈ నెట్వర్క్లు అందుకుంటాయి"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"కనెక్ట్ చేయి"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"కనెక్ట్ చేయవద్దు"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ఖచ్చితంగా కనెక్ట్ చేయాలా?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"<xliff:g id="CARRIERNAME">%s</xliff:g> నెట్వర్క్కు మీరు కనెక్ట్ చేస్తే, ఆ క్యారియర్ Wi‑Fi నెట్వర్క్లు మీ SIMకు అనుబంధితమైన ప్రత్యేక IDని యాక్సెస్ లేదా షేర్ చేయగలగవచ్చు. దీని వలన మీ పరికరం లొకేషన్ ట్రాక్ చేయబడవచ్చు."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"కనెక్ట్ చేయి"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"కనెక్ట్ చేయవద్దు"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi స్వయంచాలకంగా ఆన్ అవుతుంది"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"మీరు అధిక నాణ్యత గల సేవ్ చేసిన నెట్వర్క్కు సమీపంగా ఉన్నప్పుడు"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"తిరిగి ఆన్ చేయవద్దు"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi స్వయంచాలకంగా ఆన్ చేయబడింది"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"మీరు సేవ్ చేసిన నెట్వర్క్కి సమీపంలో ఉన్నారు: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fiకి కనెక్ట్ చేయడం సాధ్యపడలేదు"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" బలహీన ఇంటర్నెట్ కనెక్షన్ను కలిగి ఉంది."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"కనెక్షన్ని అనుమతించాలా?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s యాప్ %2$s Wifi నెట్వర్క్కు కనెక్ట్ చేయాలనుకుంటోంది"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ఒక యాప్"</string> - <string name="accept" msgid="5931271886782610829">"ఆమోదిస్తున్నాను"</string> - <string name="decline" msgid="6874256900873707640">"తిరస్కరిస్తున్నాను"</string> - <string name="ok" msgid="4215387532539340948">"సరే"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ఆహ్వానం పంపబడింది"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"కనెక్ట్ చేయడానికి ఆహ్వానం"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"వీరి నుండి:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"వీరికి:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"అవసరమైన పిన్ను టైప్ చేయండి:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"పిన్:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"టాబ్లెట్ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>కు కనెక్ట్ చేయబడినప్పుడు Wi-Fi నుండి తాత్కాలికంగా డిస్కనెక్ట్ చేయబడుతుంది"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"మీ Android TV పరికరం <xliff:g id="DEVICE_NAME">%1$s</xliff:g>కి కనెక్ట్ అయి ఉన్నప్పుడు తాత్కాలికంగా Wi-Fi నుండి డిస్కనెక్ట్ అవుతుంది"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"ఫోన్ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>కి కనెక్ట్ అయినప్పుడు అది Wi-Fi నుండి తాత్కాలికంగా డిస్కనెక్ట్ చేయబడుతుంది"</string> - <string name="dlg_ok" msgid="3250085870426030310">"సరే"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g>కు కనెక్ట్ చేయడం సాధ్యపడదు"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"మీ గోప్యతా సెట్టింగ్లను మార్చడానికి నొక్కి, మళ్లీ ప్రయత్నించండి"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"గోప్యతా సెట్టింగ్ను మార్చాలా?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"కనెక్ట్ చేయడానికి, <xliff:g id="SSID">%1$s</xliff:g> అనేది ప్రత్యేకమైన ఐడెంటిఫయర్ అయిన మీ పరికరం యొక్క MAC చిరునామాను ఉపయోగించాల్సి ఉంటుంది. ప్రస్తుతం, ఈ నెట్వర్క్ కోసం మీ గోప్యతా సెట్టింగ్ యాదృచ్ఛిక ఐడెంటిఫయర్ను ఉపయోగిస్తుంది. \n\nఈ మార్పు వలన మీ పరికర లొకేషన్ను ట్రాక్ చేయడానికి సమీప పరికరాలకు అనుమతి లభించవచ్చు."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"సెట్టింగ్ను మార్చండి"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"సెట్టింగ్ అప్డేట్ చేయబడింది. మళ్లీ కనెక్ట్ చేయడానికి ట్రై చేయండి."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"గోప్యతా సెట్టింగ్లను మార్చడం సాధ్యం కాదు"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"నెట్వర్క్ కనుగొనబడలేదు"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ప్రామాణీకరణ ఎర్రర్ 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ప్రామాణీకరణ ఎర్రర్ 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ప్రామాణీకరణ ఎర్రర్ 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ప్రామాణీకరణ ఎర్రర్ 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ప్రామాణీకరణ ఎర్రర్ 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ప్రామాణీకరణ ఎర్రర్ 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP ప్రామాణీకరణ ఎర్రర్ 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"హాట్స్పాట్ ఆఫ్ చేయబడింది"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"పరికరాలు ఏవీ కనెక్ట్ కాలేదు. మార్చడానికి నొక్కండి."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wifi డిస్కనెక్ట్ చేయబడింది"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g>కి కనెక్ట్ చేయడానికి, <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIMను చొప్పించండి"</string> -</resources> diff --git a/service/res/values-th/strings.xml b/service/res/values-th/strings.xml deleted file mode 100644 index b6a0691aa..000000000 --- a/service/res/values-th/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"ทรัพยากร Wi-Fi ของระบบ"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"เชื่อมต่อเครือข่าย Wi‑Fi แบบเปิด"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"กำลังเชื่อมต่อกับเครือข่าย Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"เชื่อมต่อเครือข่าย Wi-Fi แล้ว"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"ไม่สามารถเชื่อมต่อเครือข่าย Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"แตะเพื่อดูเครือข่ายทั้งหมด"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"เชื่อมต่อ"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"เครือข่ายทั้งหมด"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"สถานะเครือข่าย"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"การแจ้งเตือนเครือข่าย"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"มีเครือข่ายพร้อมใช้งาน"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"อนุญาตให้เชื่อมต่อเครือข่าย Wi-Fi ที่แนะนำไหม"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"เครือข่ายที่แนะนำโดย <xliff:g id="NAME">%s</xliff:g> และอุปกรณ์อาจเชื่อมต่อโดยอัตโนมัติ"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"อนุญาต"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ไม่เป็นไร"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"เชื่อมต่อกับ Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> ไหม"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"เครือข่ายเหล่านี้จะได้รับรหัส SIM ซึ่งใช้ติดตามตำแหน่งอุปกรณ์ได้"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"เชื่อมต่อ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ไม่เชื่อมต่อ"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ยืนยันการเชื่อมต่อใช่ไหม"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"หากเชื่อมต่อ เครือข่าย Wi-Fi ของ <xliff:g id="CARRIERNAME">%s</xliff:g> อาจเข้าถึงหรือแชร์รหัสที่ไม่ซ้ำกันซึ่งเชื่อมโยงกับซิมของคุณ และอาจอนุญาตให้มีการติดตามตำแหน่งอุปกรณ์ของคุณ"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"เชื่อมต่อ"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"ไม่เชื่อมต่อ"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi จะเปิดโดยอัตโนมัติ"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"เมื่อคุณอยู่ใกล้เครือข่ายคุณภาพสูงที่บันทึกไว้"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"ไม่ต้องเปิดอีกครั้ง"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"เปิด Wi‑Fi โดยอัตโนมัติแล้ว"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"คุณอยู่ใกล้เครือข่ายที่บันทึกไว้ ซึ่งก็คือ <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"ไม่สามารถเชื่อมต่อ WiFi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" มีสัญญาณอินเทอร์เน็ตไม่ดี"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"อนุญาตการเชื่อมต่อใช่ไหม"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"แอปพลิเคชัน %1$s ต้องการเชื่อมต่อเครือข่าย Wi-Fi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"แอปพลิเคชัน"</string> - <string name="accept" msgid="5931271886782610829">"ยอมรับ"</string> - <string name="decline" msgid="6874256900873707640">"ปฏิเสธ"</string> - <string name="ok" msgid="4215387532539340948">"ตกลง"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"ส่งข้อความเชิญแล้ว"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"ข้อความเชิญเพื่อเชื่อมต่อ"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"จาก:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"ถึง:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"พิมพ์ PIN ที่ต้องการ:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"แท็บเล็ตนี้จะยกเลิกการเชื่อมต่อกับ WiFi ชั่วคราวในขณะที่เชื่อมต่อกับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"อุปกรณ์ Android TV จะยกเลิกการเชื่อมต่อ Wi-Fi ชั่วคราวระหว่างที่เชื่อมต่อกับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"โทรศัพท์จะยกเลิกการเชื่อมต่อกับ WiFi ชั่วคราวในขณะที่เชื่อมต่อกับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ตกลง"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"เชื่อมต่อกับ <xliff:g id="SSID">%1$s</xliff:g> ไม่ได้"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"แตะเพื่อเปลี่ยนการตั้งค่าความเป็นส่วนตัวแล้วลองใหม่"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"เปลี่ยนการตั้งค่าความเป็นส่วนตัวใช่ไหม"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> ต้องเชื่อมต่อโดยใช้ที่อยู่ MAC ของอุปกรณ์ ซึ่งเป็นตัวระบุที่ไม่ซ้ำกัน การตั้งค่าความเป็นส่วนตัวในปัจจุบันของคุณสำหรับเครือข่ายนี้ใช้ตัวระบุแบบสุ่มอยู่ \n\nวิธีนี้อาจทำให้อุปกรณ์ใกล้เคียงติดตามตำแหน่งอุปกรณ์ของคุณได้"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"เปลี่ยนการตั้งค่า"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"อัปเดตการตั้งค่าแล้ว ลองเชื่อมต่ออีกครั้ง"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"เปลี่ยนการตั้งค่าความเป็นส่วนตัวไม่ได้"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"ไม่พบเครือข่าย"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : ข้อผิดพลาดในการตรวจสอบสิทธิ์ EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : ข้อผิดพลาดในการตรวจสอบสิทธิ์ EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : ข้อผิดพลาดในการตรวจสอบสิทธิ์ EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : ข้อผิดพลาดในการตรวจสอบสิทธิ์ EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : ข้อผิดพลาดในการตรวจสอบสิทธิ์ EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : ข้อผิดพลาดในการตรวจสอบสิทธิ์ EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : ข้อผิดพลาดในการตรวจสอบสิทธิ์ EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ปิดฮอตสปอตแล้ว"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"ไม่มีอุปกรณ์ที่เชื่อมต่อ แตะเพื่อแก้ไข"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"ไม่ได้เชื่อมต่อ Wi-Fi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"หากต้องการเชื่อมต่อกับ <xliff:g id="SSID">%1$s</xliff:g> ให้ใส่ซิมของ <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-tl/strings.xml b/service/res/values-tl/strings.xml deleted file mode 100644 index b26679db9..000000000 --- a/service/res/values-tl/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Mga Resource ng Wi-Fi ng System"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Kumonekta sa bukas na Wi‑Fi network"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Kumokonekta sa Wi‑Fi network"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Nakakonekta sa Wi‑Fi network"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Hindi makakonekta sa Wi‑Fi network"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"I-tap upang makita ang lahat ng network"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Kumonekta"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Lahat ng network"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Status ng network"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Mga alerto sa network"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Available ang network"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Payagan ang mga iminumungkahing Wi‑Fi network?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mga iminumungkahing network ng <xliff:g id="NAME">%s</xliff:g>. Posibleng awtomatikong kumonekta ang device."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Payagan"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Hindi, salamat na lang"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Kumonekta sa <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Tumatanggap ang mga network na ito ng SIM ID na magagamit sa pag-track sa lokasyon ng device"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Kumonekta"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Huwag kumonekta"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Kumpirmahin ang koneksyon?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Kung kokonekta ka, posibleng ma-access o maging kapareho ng mga Wi-Fi network ng <xliff:g id="CARRIERNAME">%s</xliff:g> ang natatanging ID na nauugnay sa iyong SIM. Baka mapahintulutan nito ang pagsubaybay sa lokasyon ng iyong device."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Ikonekta"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Huwag kumonekta"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Awtomatikong mag-o-on ang Wi‑Fi"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Kapag malapit ka sa naka-save na network na mataas ang kalidad"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Huwag i-on muli"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Awtomatikong na-on ang Wi‑Fi"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Malapit ka sa isang naka-save na network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Hindi makakonekta sa Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ay mayroong mahinang koneksyon sa internet."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Payagan ang kuneksyon?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Gustong kumonekta ng application na %1$s sa Wifi Network na %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Isang application"</string> - <string name="accept" msgid="5931271886782610829">"Tanggapin"</string> - <string name="decline" msgid="6874256900873707640">"Tanggihan"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Naipadala ang imbitasyon"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Imbitasyong kumonekta"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Mula kay:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kay:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"I-type ang kinakailangang PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Pansamantalang madidiskoneta ang tablet sa Wi-Fi habang nakakonekta ito sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Pansamantalang madidiskonekta sa Wi-Fi ang iyong Android TV device habang nakakonekta ito sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Pansamantalang madidiskoneta ang telepono sa Wi-Fi habang nakakonekta ito sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Hindi makakonekta sa <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"I-tap para baguhin ang mga setting ng privacy at subukan ulit"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Baguhin ang setting ng privacy?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Para kumonekta, kailangan ng <xliff:g id="SSID">%1$s</xliff:g> ang MAC address ng iyong device, na isang natatanging identifier. Sa kasalukuyan, gumagamit ng naka-randomize na identifier ang mga setting mo sa privacy para sa network na ito. \n\nDahil sa pagbabagong ito, baka mapahintulutan ang mga kalapit na device na subaybayan ang lokasyon ng iyong device."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Baguhin ang setting"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Na-update ang setting. Subukang kumonekta ulit."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Hindi puwedeng baguhin ang setting ng privacy"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Hindi nakita ang network"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Error sa pag-authenticate ng EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Error sa pag-authenticate ng EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Error sa pag-authenticate ng EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Error sa pag-authenticate ng EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Error sa pag-authenticate ng EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Error sa pag-authenticate ng EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Error sa pag-authenticate ng EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Naka-off ang hotspot"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Walang mga nakakonektang device. I-tap para baguhin."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Nadiskonekta ang Wi‑Fi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Para makakonekta sa <xliff:g id="SSID">%1$s</xliff:g>, maglagay ng <xliff:g id="CARRIER_NAME">%2$s</xliff:g> na SIM"</string> -</resources> diff --git a/service/res/values-tr/strings.xml b/service/res/values-tr/strings.xml deleted file mode 100644 index 16cf1a297..000000000 --- a/service/res/values-tr/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistem Kablosuz Bağlantı Kaynakları"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Açık kablosuz ağa bağlanın"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Kablosuz ağa bağlanıyor"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Kablosuz ağa bağlanıldı"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Kablosuz ağa bağlanamadı"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Tüm ağları görmek için dokunun"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Bağlan"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Tüm ağlar"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Ağ durumu"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Ağ uyarıları"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Ağ mevcut"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Önerilen kablosuz ağlara izin verilsin mi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> tarafından önerilen ağlar. Cihaz otomatik olarak bağlanabilir."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"İzin ver"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Hayır, teşekkürler"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> kablosuz ağına bağlanılsın mı?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Bu ağlar, cihazın konumunu izlemek için kullanılabilecek bir SIM kimliği alır"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Bağlan"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Bağlanma"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Bağlantı onaylansın mı?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Bağlanırsanız <xliff:g id="CARRIERNAME">%s</xliff:g> kablosuz ağları SIM\'inizle ilişkilendirilmiş benzersiz kimliğe erişebilir veya bunları paylaşabilir. Bu, cihazınızın konumunun izlenmesine olanak sağlayabilir."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Bağlan"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Bağlanma"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Kablosuz ağ otomatik olarak açılacak"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Daha önce kaydedilmiş yüksek kaliteli bir ağın yakınında olduğunuzda"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Tekrar açılmasın"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Kablosuz ağ otomatik olarak açıldı"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Kayıtlı bir ağın yakınındasınız: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Kablosuz bağlantısı kurulamadı"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" internet bağlantısı zayıf."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Bağlantıya izin verilsin mi?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s uygulaması %2$s Kablosuz Ağına bağlanmak istiyor"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Bir uygulama"</string> - <string name="accept" msgid="5931271886782610829">"Kabul et"</string> - <string name="decline" msgid="6874256900873707640">"Reddet"</string> - <string name="ok" msgid="4215387532539340948">"Tamam"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Davetiye gönderildi"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Bağlantı davetiyesi"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Gönderen:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Alıcı:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Gerekli PIN\'i yazın:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaza bağlıyken Kablosuz ağ bağlantısı geçici olarak kesilecektir"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV cihazınız <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaza bağlıyken kablosuz ağ bağlantısı geçici olarak kesilecek"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaza bağlıyken Kablosuz ağ bağlantısı geçici olarak kesilecektir"</string> - <string name="dlg_ok" msgid="3250085870426030310">"Tamam"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> ağına bağlanılamıyor"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Gizlilik ayarını değiştirip tekrar denemek için dokunun"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Gizlilik ayarı değiştirilsin mi?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> bağlanmak için benzersiz bir tanımlayıcı olan, cihazınızın MAC adresini kullanmaya ihtiyaç duyuyor. Bu ağa ait gizlilik ayarınız şu anda rastgele bir tanımlayıcı kullanıyor. \n\nBu değişiklik, cihazınızın konumunun etraftaki cihazlar tarafından izlenmesine olanak sağlayabilir."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Ayarı değiştir"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Ayar güncellendi. Tekrar bağlanmayı deneyin."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Gizlilik ayarı değiştirilemiyor"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Ağ bulunamadı"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP kimlik doğrulama hatası 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP kimlik doğrulama hatası 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP kimlik doğrulama hatası 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP kimlik doğrulama hatası 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP kimlik doğrulama hatası 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP kimlik doğrulama hatası 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP kimlik doğrulama hatası 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot kapatıldı"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Bağlı cihaz yok. Değiştirmek için dokunun."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Kablosuz bağlantı kesildi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> ağına bağlanmak için <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM\'ini takın"</string> -</resources> diff --git a/service/res/values-uk/strings.xml b/service/res/values-uk/strings.xml deleted file mode 100644 index e2b9e5129..000000000 --- a/service/res/values-uk/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Системні ресурси Wi-Fi"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Під’єднайтеся до відкритої мережі Wi-Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"З’єднання з мережею Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Під’єднано до мережі Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Не вдалося під’єднатися до мережі Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Торкніться, щоб побачити всі мережі"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Під’єднатися"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Усі мережі"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Статус мережі"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Сповіщення мережі"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Мережа доступна"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Дозволити пропоновані мережі Wi‑Fi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Мережі, пропоновані додатком <xliff:g id="NAME">%s</xliff:g>. Пристрій може підключитися автоматично."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Дозволити"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ні, дякую"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Підключитися до мережі Wi‑Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ці мережі отримують ідентифікатор SIM-карти, за допомогою якого можна відстежити місцезнаходження пристрою"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Підключитися"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не підключатися"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Підтвердити підключення?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Якщо ви під\'єднаєтеся, мережі Wi‑Fi оператора \"<xliff:g id="CARRIERNAME">%s</xliff:g>\" зможуть розкрити унікальний ідентифікатор вашої SIM-карти й відстежити місцезнаходження вашого пристрою."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Підключитися"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Не підключатися"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi вмикатиметься автоматично"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Коли ви поблизу збереженої мережі високої якості"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Не вмикати знову"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"З’єднання Wi-Fi увімкнулось автоматично"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Ви поблизу збереженої мережі: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Не вдалося під’єднатися до мережі Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" має погане з’єднання з Інтернетом."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Дозволити з’єднання?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Додаток %1$s хоче під’єднатися до мережі Wi-Fi \"%2$s\""</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Додаток"</string> - <string name="accept" msgid="5931271886782610829">"Прийняти"</string> - <string name="decline" msgid="6874256900873707640">"Відхилити"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Запрошення надіслано"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Запрошення під’єднатися"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Від:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Кому:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Введіть потрібний PIN-код:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN-код:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Під час з’єднання з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g> планшетний ПК тимчасово від’єднається від мережі Wi-Fi"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"На час підключення до пристрою <xliff:g id="DEVICE_NAME">%1$s</xliff:g> Android TV тимчасово відключиться від мережі Wi-Fi"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Під час з’єднання з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g> телефон тимчасово від’єднається від мережі Wi-Fi"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Не вдалося підключитися до мережі \"<xliff:g id="SSID">%1$s</xliff:g>\""</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Натисніть, щоб змінити налаштування конфіденційності й повторити спробу"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Змінити налаштування конфіденційності?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Щоб підключитись, <xliff:g id="SSID">%1$s</xliff:g> має використовувати унікальний ідентифікатор пристрою – його MAC-адресу. Згідно з налаштуваннями конфіденційності, ваша мережа зараз використовує випадкові ідентифікатори. \n\nПісля цієї зміни пристрої поруч зможуть відстежувати місцезнаходження вашого пристрою."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Змінити налаштування"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Налаштування оновлено. Спробуйте підключитися знову."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Не вдалося змінити налаштування конфіденційності"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Мережу не знайдено"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>: помилка автентифікації за протоколом EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>: помилка автентифікації за протоколом EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>: помилка автентифікації за протоколом EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>: помилка автентифікації за протоколом EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>: помилка автентифікації за протоколом EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>: помилка автентифікації за протоколом EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: помилка автентифікації за протоколом EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Точку доступу вимкнено"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Немає підключених пристроїв. Натисніть, щоб змінити."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Від\'єднано від мережі Wi-Fi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Щоб підключитися до мережі \"<xliff:g id="SSID">%1$s</xliff:g>\", вставте SIM-карту \"<xliff:g id="CARRIER_NAME">%2$s</xliff:g>\""</string> -</resources> diff --git a/service/res/values-ur/strings.xml b/service/res/values-ur/strings.xml deleted file mode 100644 index 0d506439a..000000000 --- a/service/res/values-ur/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Wi-Fi سسٹم کے وسائل"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"عوامی Wi‑Fi نیٹ ورک سے منسلک ہوں"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi نیٹ ورک سے منسلک ہو رہا ہے"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"عوامی Wi‑Fi نیٹ ورک سے منسلک ہو گيا"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi‑Fi نیٹ ورک سے منسلک نہیں ہو سکا"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"تمام نیٹ ورکس دیکھنے کیلئے تھپتھپائيں"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"منسلک کریں"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"سبھی نیٹ ورکس"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"نیٹ ورک اسٹیٹس"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"نیٹ ورک الرٹس"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"نیٹ ورک دستیاب ہے"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"تجویز کردہ Wi‑Fi نیٹ ورکس کو اجازت دیں؟"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> تجویز کردہ نیٹ ورکس۔ آلہ خودکار طور پر منسلک ہو سکتا ہے۔"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"اجازت ہیں"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"نہیں شکریہ"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi سے منسلک ہوں؟"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"یہ نیٹ ورکس ایک منفرد SIM ID موصول کرتے ہیں جسے آلہ کا مقام ٹریک کرنے کے لیے استعمال کیا جا سکتا ہے"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"منسلک کریں"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"منسلک نہ کریں"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"کنکشن کی تصدیق کریں؟"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"اگر آب منسلک ہیں، Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> نیٹ ورکس آپ کے SIM سے وابستہ ایک منفرد ID تک رسائی حاصل یا اشتراک کر سکتے ہیں۔ یہ آپ کے آلہ کے مقام کو ٹریک کیے جانے کی اجازت دے سکتا ہے۔"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"منسلک کریں"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"منسلک نہ کریں"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi از خود آن ہو جائے گا"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"جب آپ اعلی معیار کے محفوظ کردہ نیٹ ورک کے قریب ہوں"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"دوبارہ آن نہ کریں"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi-Fi خود کار طور پر آن ہو گیا"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"آپ ایک محفوظ نیٹ ورک کے قریب ہیں: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi سے مربوط نہیں ہو سکا"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" اس میں ایک کمزور انٹرنیٹ کنکشن ہے۔"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"کنکشن کی اجازت دیں؟"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"ایپلیکیشن %1$s Wifi نیٹ ورک %2$s سے منسلک ہونا چاہتی ہے"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"ایک ایپلیکیشن"</string> - <string name="accept" msgid="5931271886782610829">"قبول کریں"</string> - <string name="decline" msgid="6874256900873707640">"مسترد کریں"</string> - <string name="ok" msgid="4215387532539340948">"ٹھیک ہے"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"دعوت بھیج دی گئی"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"مربوط ہونے کی دعوت"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"منجانب:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"بنام:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"مطلوبہ PIN ٹائپ کریں:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"ٹیبلیٹ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> سے مربوط ہونے پر عارضی طور پر Wi-Fi سے منقطع ہو جائے گا"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"آپ کا Android TV آلہ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> سے منسلک ہونے پر عارضی طور پر Wi-Fi سے غیر منسلک ہو جائے گا"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"فون <xliff:g id="DEVICE_NAME">%1$s</xliff:g> سے مربوط رہنے کے وقت عارضی طور پر Wi-Fi سے منقطع ہوجائے گا"</string> - <string name="dlg_ok" msgid="3250085870426030310">"ٹھیک ہے"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> سے منسلک نہیں کر سکتے"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"رازداری کی ترتیبات تبدیل کرنے اور دوبارہ کوشش کرنے کے لیے تھپتھپائیں"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"رازداری کی ترتیب تبدیل کریں؟"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"منسلک کرنے کے ليے، <xliff:g id="SSID">%1$s</xliff:g> کو آپ کے آلہ کا MAC پتہ استعمال کرنے کی ضرورت ہے، ایک منفرد شناخت کار ہے۔ فی الحال، اس نیٹ ورک کے ليے آپ کی رازداری کی ترتیب بے ترتیب شناخت کار استعمال کرتی ہے۔ \n\nاس تبدیلی سے آپ کے آلے کے مقام کو قریبی آلات کے ذریعہ ٹریک کرنے کی اجازت دے سکتا ہے۔"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"ترتیب تبدیل کریں"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"ترتیبات اپ ڈیٹ کر دی گئی۔ دوبارہ منسلک کرنے کی کوشش کریں۔"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"رازداری کی ترتیب تبدیل نہیں ہو سکتی"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"نیٹ ورک نہیں ملا"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP توثیق کی خرابی 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP توثیق کی خرابی 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP توثیق کی خرابی 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP توثیق کی خرابی 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP توثیق کی خرابی 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP توثیق کی خرابی 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP توثیق کی خرابی 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"ہاٹ اسپاٹ کو آف کر دیا گیا"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"کوئی آلات منسلک نہیں ہیں۔ ترمیم کرنے کے لیے تھپتھپائیں۔"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wifi غیر منسلک ہو گیا"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> سے منسلک ہونے کے ليے <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM داخل کریں"</string> -</resources> diff --git a/service/res/values-uz/strings.xml b/service/res/values-uz/strings.xml deleted file mode 100644 index be52bd25a..000000000 --- a/service/res/values-uz/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Tizimdagi Wi-Fi tarmoq resurslari"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Ochiq Wi‑Fi tarmoqqa ulaning"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Wi‑Fi tarmoqqa ulanmoqda"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Wi‑Fi tarmoqqa ulanildi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Wi-Fi tarmoqqa ulanib bo‘lmadi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Barcha tarmoqlarni ko‘rish uchun bosing"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Ulanish"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Barcha tarmoqlar"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Tarmoq holati"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Tarmoqqa oid bildirgilar"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Tarmoq mavjud"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Tavsiya qilingan Wi‑Fi tarmoqlarga ruxsat berilsinmi?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> tavsiya qilgan tarmoqlar. Qurilma avtomatik ulanishi mumkin."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Ruxsat"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Kerak emas"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi tarmoqqa ulaning"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Bu tarmoqlar SIM identifikator oladi, bu orqali qurilma joylashuvini kuzatish mumkin"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Ulash"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ulanmasin"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Ulanish tasdiqlansinmi?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Agar ulansangiz, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi tarmoqlari SIM kartangizga aloqador unikal identifikatordan foydalanishi yoki ulashishi mumkin. Bu qurilmangiz joylashuvi kuzatilishiga ruxsat berishi mumkin."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Ulash"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ulanmasin"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi avtomatik ravishda yoqiladi"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Saqlangan tarmoqlar ichidan signali yaxshisi hududida ekaningizda"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Qayta yoqilmasin"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi avtomatik ravishda yoqildi"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Saqlangan tarmoq atrofidasiz: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Wi-Fi’ga ulana olmadi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" tezligi past Internetga ulangan."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Ulanishga ruxsat berilsinmi?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"%1$s ilovasi %2$s Wi-Fi tarmog‘iga ulanmoqchi"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Ilova"</string> - <string name="accept" msgid="5931271886782610829">"Qabul qilish"</string> - <string name="decline" msgid="6874256900873707640">"Rad etish"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"taklif jo‘natildi"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"ulanish taklifi"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Kimdan:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kimga:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"So‘ralgan PIN kodni kiriting:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN kod:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Planshet <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ga ulanganligi tufayli vaqtincha Wi-Fi tarmog‘idan uzildi."</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV qurilmangiz <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasiga ulangani uchun u vaqtincha Wi-Fi tarmoqdan uzildi."</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ga ulanganligi tufayli vaqtincha Wi-Fi tarmog‘idan uzildi."</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"<xliff:g id="SSID">%1$s</xliff:g> bilan aloqa oʻrnatilmadi"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Maxfiylik sozlamalarini oʻzgartirish uchun bosing va qayta urining"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Maxfiylik sozlamalari oʻzgartirilsinmi?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Ulanish uchun <xliff:g id="SSID">%1$s</xliff:g> qurilmangizning MAC manzilidan (unikal identifikator) foydalanishi lozim. Hozirda bu tarmoq uchun maxfiylik sozlamalari tasodifiy identifikatordan foydalanmoqda. \n\nBunday holda yaqin-atrofingizdagi qurilmalar qurilmangiz joylashuvini kuzatishi mumkin."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Sozlamani oʻzgartirish"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Sozlama yangilandi. Qaytadan ulaning."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Maxfiylik parametrini oʻzgartirib boʻlmadi"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Tarmoq topilmadi"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP haqiqiylikni tekshirishda xato: 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP haqiqiylikni tekshirishda xato: 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : haqiqiylikni tekshirishda xato: 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP haqiqiylikni tekshirishda xato: 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP haqiqiylikni tekshirishda xato: 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP haqiqiylikni tekshirishda xato: 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP haqiqiylikni tekshirishda xato: 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot oʻchirildi"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Hech qanday qurilma ulanmagan. Oʻzgartirish uchun tegining."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi uzildi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"<xliff:g id="SSID">%1$s</xliff:g> nomli tarmoqqa ulanish uchun <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM kartasini joylang"</string> -</resources> diff --git a/service/res/values-vi/strings.xml b/service/res/values-vi/strings.xml deleted file mode 100644 index d6e1ea354..000000000 --- a/service/res/values-vi/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Các tài nguyên Wi-Fi của hệ thống"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Kết nối với mạng Wi-Fi đang mở"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Đang kết nối với mạng Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Đã kết nối với mạng Wi-Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Không thể kết nối với mạng Wi‑Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Nhấn để xem tất cả các mạng"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Kết nối"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Tất cả các mạng"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Trạng thái mạng"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Cảnh báo mạng"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Có mạng"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Cho phép các mạng Wi‑Fi được đề xuất?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"Các mạng do <xliff:g id="NAME">%s</xliff:g> đề xuất. Thiết bị có thể kết nối tự động."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Cho phép"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Không, cảm ơn"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Kết nối với Wi-Fi của <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Các mạng này nhận được một mã nhận dạng SIM có thể dùng để theo dõi vị trí của thiết bị"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Kết nối"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Không kết nối"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Xác nhận kết nối?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Nếu bạn kết nối, các mạng Wi-Fi của <xliff:g id="CARRIERNAME">%s</xliff:g> có thể truy cập hoặc chia sẻ mã nhận dạng duy nhất liên kết với SIM của bạn. Từ đó, các mạng này có thể theo dõi vị trí thiết bị của bạn."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Kết nối"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Không kết nối"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi sẽ tự động bật"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Khi bạn ở gần mạng đã lưu chất lượng cao"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Không bật lại"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi-Fi đã tự động bật"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Bạn đang ở gần mạng đã lưu: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Không thể kết nối với Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" có kết nối internet kém."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Cho phép kết nối?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Ứng dụng %1$s muốn kết nối với Mạng Wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Ứng dụng"</string> - <string name="accept" msgid="5931271886782610829">"Đồng ý"</string> - <string name="decline" msgid="6874256900873707640">"Từ chối"</string> - <string name="ok" msgid="4215387532539340948">"OK"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Đã gửi thư mời"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Thư mời kết nối"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Người gửi:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Người nhận:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Nhập PIN bắt buộc:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"Mã PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Máy tính bảng sẽ tạm thời ngắt kết nối khỏi Wi-Fi trong khi máy tính bảng được kết nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Thiết bị Android TV sẽ tạm thời ngắt kết nối khỏi Wi-Fi trong khi kết nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Điện thoại sẽ tạm thời ngắt kết nối khỏi Wi-Fi trong khi điện thoại được kết nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"OK"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Không thể kết nối với <xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Nhấn để thay đổi các tùy chọn cài đặt quyền riêng tư rồi thử lại"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Thay đổi tùy chọn cài đặt quyền riêng tư?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Để kết nối, <xliff:g id="SSID">%1$s</xliff:g> cần phải dùng địa chỉ MAC (mã nhận dạng duy nhất) của thiết bị. Hiện tại, tùy chọn cài đặt quyền riêng tư của mạng này đang dùng mã nhận dạng ngẫu nhiên. \n\nVới sự thay đổi này, các thiết bị ở gần có thể theo dõi vị trí thiết bị của bạn."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Thay đổi tùy chọn cài đặt"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Đã cập nhật tùy chọn cài đặt. Hãy thử kết nối lại."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Không thể thay đổi tùy chọn cài đặt quyền riêng tư"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Không tìm thấy mạng"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Lỗi xác thực EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Lỗi xác thực EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Lỗi xác thực EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Lỗi xác thực EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Lỗi xác thực EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Lỗi xác thực EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Lỗi xác thực EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Đã tắt điểm phát sóng"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Chưa kết nối thiết bị nào. Hãy nhấn để chỉnh sửa."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Đã ngắt kết nối Wi-Fi"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Để kết nối với <xliff:g id="SSID">%1$s</xliff:g>, hãy lắp một thẻ SIM <xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values-zh-rCN/strings.xml b/service/res/values-zh-rCN/strings.xml deleted file mode 100644 index bf1eff811..000000000 --- a/service/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"系统 WLAN 资源"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"连接到开放的 WLAN 网络"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"正在连接到 WLAN 网络"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"已连接到 WLAN 网络"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"无法连接到 WLAN 网络"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"点按即可查看所有网络"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"连接"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"所有网络"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"网络状态"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"网络提醒"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"有可用的网络"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"是否允许系统连接到建议的 WLAN 网络?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>建议的网络。设备可能会自动连接到这些网络。"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"允许"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"不用了"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"要连接到<xliff:g id="CARRIERNAME">%s</xliff:g>的 WLAN 吗?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"这些网络会收到可用于跟踪设备位置的 SIM 卡 ID"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"连接"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"不连接"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"确认连接?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"如果您确认连接,<xliff:g id="CARRIERNAME">%s</xliff:g> WLAN 网络可获取或共享与您的 SIM 卡关联的唯一 ID。他人或许可以借此跟踪您的设备位置。"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"连接"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"不连接"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"WLAN 将自动开启"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"当您位于已保存的高品质网络信号范围内时"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"不要重新开启"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"已自动开启 WLAN 网络"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"您位于已保存的网络 (<xliff:g id="NETWORK_SSID">%1$s</xliff:g>) 信号范围内"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"无法连接到WLAN"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" 互联网连接状况不佳。"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"要允许连接吗?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"“%1$s”应用想要连接到 WLAN 网络“%2$s”"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"一款应用"</string> - <string name="accept" msgid="5931271886782610829">"接受"</string> - <string name="decline" msgid="6874256900873707640">"拒绝"</string> - <string name="ok" msgid="4215387532539340948">"确定"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"已发出邀请"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"连接邀请"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"发件人:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"收件人:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"输入所需的PIN码:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN 码:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"平板电脑连接到“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”时会暂时断开与WLAN的连接"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"当 Android TV 设备连接到 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 时,它会暂时断开 WLAN 连接"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"手机连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时会暂时断开与WLAN的连接。"</string> - <string name="dlg_ok" msgid="3250085870426030310">"确定"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"无法连接到“<xliff:g id="SSID">%1$s</xliff:g>”"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"点按以更改隐私设置并重试"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"要更改隐私设置吗?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"“<xliff:g id="SSID">%1$s</xliff:g>”需要使用您设备的 MAC 地址(一个唯一标识符)才能连接。目前,该网络的隐私设置使用的是随机标识符。\n\n这项变更可能会让附近的设备可以跟踪您设备的位置信息。"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"更改设置"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"设置已更新。请尝试重新连接。"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"无法更改隐私设置"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"未找到任何网络"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 身份验证错误 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 身份验证错误 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 身份验证错误 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 身份验证错误 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 身份验证错误 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 身份验证错误 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 身份验证错误 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"热点已关闭"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"未连接到任何设备。点按即可修改。"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"WLAN 连接已断开"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"要连接到“<xliff:g id="SSID">%1$s</xliff:g>”,请插入<xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM 卡"</string> -</resources> diff --git a/service/res/values-zh-rHK/strings.xml b/service/res/values-zh-rHK/strings.xml deleted file mode 100644 index d41d74e94..000000000 --- a/service/res/values-zh-rHK/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"系統 Wi-Fi 資源"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"連線至開放的 Wi-Fi 網絡"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"正在連線至 Wi-Fi 網絡"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"已連線至 Wi-Fi 網絡"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"無法連線至 Wi-Fi 網絡"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"輕按即可查看所有網絡"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"連線"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"所有網絡"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"網絡狀態"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"網絡通知"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"有可用的網絡"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"要允許連線至建議的 Wi-Fi 網絡嗎?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"「<xliff:g id="NAME">%s</xliff:g>」已建議網絡連線,裝置可能會自動連接網絡。"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"允許"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"不用了,謝謝"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"要連線至「<xliff:g id="CARRIERNAME">%s</xliff:g>」Wi-Fi 嗎?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"這些網絡會收到可追蹤裝置位置的 SIM 卡 ID"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"連接"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"不要連線"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"確定要連線嗎?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"連線後,「<xliff:g id="CARRIERNAME">%s</xliff:g>」的 Wi‑Fi 網絡就能存取或分享與 SIM 卡相關的獨有 ID,有心人或許可藉此追蹤您裝置的位置。"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"連線"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"不要連線"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi-Fi 將會自動開啟"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"當您位於已儲存的高品質網絡信號範圍內時"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"不要重新開啟"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"已自動開啟 Wi‑Fi"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"您附近有已儲存的網絡:<xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"無法連線至 Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" 互聯網連線欠佳。"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"允許連線?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"應用程式 %1$s 要求連線至 WiFi 網絡 %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"應用程式"</string> - <string name="accept" msgid="5931271886782610829">"接受"</string> - <string name="decline" msgid="6874256900873707640">"拒絕"</string> - <string name="ok" msgid="4215387532539340948">"確定"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"已發出邀請"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"連線邀請"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"寄件者:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"收件者:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"請輸入必要的 PIN 碼:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN 碼:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"平板電腦與 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 連線期間將暫時中斷 Wi-Fi 連線"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV 裝置與 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 連線期間,系統將暫時中斷 Wi-Fi 連線"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"手機與 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 連線期間將暫時中斷 Wi-Fi 連線"</string> - <string name="dlg_ok" msgid="3250085870426030310">"確定"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"無法連接「<xliff:g id="SSID">%1$s</xliff:g>」"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"輕按以更改私隱設定,然後重試"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"要更改私隱設定嗎?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"<xliff:g id="SSID">%1$s</xliff:g> 需要使用您裝置的 MAC 位址 (不重複的識別碼) 連接。此網絡的私隱設定目前使用隨機識別碼。\n\n此變更可能會令附近裝置能夠追蹤您裝置的位置。"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"更改設定"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"已更新設定,請嘗試重新連線。"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"無法更改私隱設定"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"找不到網絡"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 驗證錯誤 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 驗證錯誤 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 驗證錯誤 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 驗證錯誤 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 驗證錯誤 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 驗證錯誤 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : EAP 驗證錯誤 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"熱點已關閉"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"未連接到任何裝置,輕按即可修改。"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi 連線已中斷"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"插入「<xliff:g id="CARRIER_NAME">%2$s</xliff:g>」SIM 卡以連線至「<xliff:g id="SSID">%1$s</xliff:g>」"</string> -</resources> diff --git a/service/res/values-zh-rTW/strings.xml b/service/res/values-zh-rTW/strings.xml deleted file mode 100644 index 3bc93f13b..000000000 --- a/service/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"系統 Wi-Fi 資源"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"連線至開放的 Wi‑Fi 網路"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"正在連線至 Wi‑Fi 網路"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"已連線至 Wi-Fi 網路"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"無法連線至 Wi‑Fi 網路"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"輕觸即可查看所有網路"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"連線"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"所有網路"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"網路狀態"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"網路警示"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"有可用的網路"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"是否允許系統連線到建議的 Wi‑Fi 網路?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"「<xliff:g id="NAME">%s</xliff:g>」建議的網路。裝置可能會自動連線到這些網路。"</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"允許"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"不用了,謝謝"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"要連線至「<xliff:g id="CARRIERNAME">%s</xliff:g>」的 Wi-Fi 網路嗎?"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"這些網路會收到可用於追蹤裝置位置的 SIM 卡 ID"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"連線"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"不要連線"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"確定要連線嗎?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"連線後,「<xliff:g id="CARRIERNAME">%s</xliff:g>」的 Wi‑Fi 網路可能會存取或分享與 SIM 卡相關的唯一 ID,有心人士或許可藉此追蹤你的裝置所在位置。"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"連線"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"不要連線"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"Wi‑Fi 將自動開啟"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"當你位於已儲存的高品質網路範圍內時"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"不要重新開啟"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"已自動開啟 Wi‑Fi"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"你位於已儲存的網路範圍內:<xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"無法連線至 Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" 網際網路連線狀況不佳。"</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"允許連線?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"「%1$s」應用程式要求連線至 WiFi 網路 %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"應用程式"</string> - <string name="accept" msgid="5931271886782610829">"接受"</string> - <string name="decline" msgid="6874256900873707640">"拒絕"</string> - <string name="ok" msgid="4215387532539340948">"確定"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"邀請函已傳送"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"連線邀請"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"寄件者:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"收件者:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"請輸入必要的 PIN:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN 碼:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"平板電腦與 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 連線期間將暫時中斷 Wi-Fi 連線"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV 裝置與「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」連線期間將暫時中斷 Wi-Fi 連線"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"手機與 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 連線期間將暫時中斷 Wi-Fi 連線"</string> - <string name="dlg_ok" msgid="3250085870426030310">"確定"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"無法連線至「<xliff:g id="SSID">%1$s</xliff:g>」"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"輕觸即可變更隱私權設定並重試"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"要變更隱私權設定嗎?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"「<xliff:g id="SSID">%1$s</xliff:g>」要求使用裝置 MAC 位址 (即專屬 ID) 進行連線。你目前的網路隱私權設定使用的是隨機 ID,\n\n如果進行這項變更,附近的裝置或許可以追蹤你的裝置所在位置。"</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"變更設定"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"設定已更新,請再次嘗試連線。"</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"無法變更隱私權設定"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"找不到網路"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 驗證錯誤 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 驗證錯誤 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 驗證錯誤 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 驗證錯誤 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 驗證錯誤 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 驗證錯誤 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>:EAP 驗證錯誤 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"無線基地台已關閉"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"未連線到任何裝置,輕觸即可修改。"</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi 連線中斷"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"如要連線到「<xliff:g id="SSID">%1$s</xliff:g>」,請插入「<xliff:g id="CARRIER_NAME">%2$s</xliff:g>」的 SIM 卡"</string> -</resources> diff --git a/service/res/values-zu/strings.xml b/service/res/values-zu/strings.xml deleted file mode 100644 index ecc4a2553..000000000 --- a/service/res/values-zu/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2019 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Izinsiza ze-Wi-Fi yesistimu"</string> - <string name="wifi_available_title" msgid="2844963247498642107">"Xhuma kunethiwekhi evulekile ye-Wi‑Fi"</string> - <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Ixhumeka kunethiwekhi ye-Wi-Fi"</string> - <string name="wifi_available_title_connected" msgid="922603556292157664">"Kuxhumeke kunethiwekhi ye-Wi‑Fi"</string> - <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Ayikwazanga ukuxhumeka kunethiwekhi ye-Wi-Fi"</string> - <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Thepha ukuze ubone onke amanethiwekhi"</string> - <string name="wifi_available_action_connect" msgid="7989951293406720158">"Xhuma"</string> - <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Onke amanethiwekhi"</string> - <string name="notification_channel_network_status" msgid="7808526906954286713">"Isimo senethiwekhi"</string> - <string name="notification_channel_network_alerts" msgid="3638265846217667221">"Izexwayiso zenethiwekhi"</string> - <string name="notification_channel_network_available" msgid="7791052175212297403">"Inethiwekhi iyatholakala"</string> - <string name="wifi_suggestion_title" msgid="8724552631151189767">"Vumela amanethiwekhi e-Wi-Fi aphakanyisiwe?"</string> - <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> amanethiwekhi aphakanyisiwe. Idivayisi ingaxhumeka ngokuzenzakalela."</string> - <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Vumela"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Cha ngiyabonga"</string> - <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Xhuma ku-Wi-Fi ye-<xliff:g id="CARRIERNAME">%s</xliff:g>"</string> - <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Lama nethiwekhi athola i-SIM ID engasetshenziselwa ukulandelela indawo yedivayisi"</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Xhuma"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ungaxhumi"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Qinisekisa ukuxhuma?"</string> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Uma uxhuma, amanethiwekhi we-Wi-Fi ye-<xliff:g id="CARRIERNAME">%s</xliff:g> angase akwazi ukufinyelela ku-ID yakho ehlukile ehlobene ne-SIM yakho. Lokhu kungase kuvumele ukuthi indawo yedivayisi yakho ilandelelwe."</string> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"Xhuma"</string> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"Ungaxhumi"</string> - <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"I-Wi-Fi izovuleka ngokuzenzakalela"</string> - <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"Uma useduze kwenethiwekhi yekhwalithi ephezulu elondoloziwe"</string> - <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ungaphindi uvule"</string> - <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"I-Wi‑Fi ivuleke ngokuzenzakalela"</string> - <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Useduzane nenethiwekhi elondoloziwe: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> - <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Ayikwazanga ukuxhuma kwi-Wi-Fi"</string> - <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" inoxhumano oluphansi lwe-inthanethi."</string> - <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Vumela ukuxhumeka?"</string> - <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Uhlelo lokusebenza %1$s lungathanda ukuxhuma kunethiwekhi ye-Wifi %2$s"</string> - <string name="wifi_connect_default_application" msgid="6164721692891325243">"Uhlelo lokusebenza"</string> - <string name="accept" msgid="5931271886782610829">"Yamukela"</string> - <string name="decline" msgid="6874256900873707640">"Nqaba"</string> - <string name="ok" msgid="4215387532539340948">"KULUNGILE"</string> - <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Isimemo sithunyelwe"</string> - <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Isimemo kuya kokuqukethwe"</string> - <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Kusuka:"</string> - <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Ku:"</string> - <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Faka i-PIN edingekayo:"</string> - <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Ithebulethi izonqamuka okwesikhashana ku-Wi-Fi ngenkathi ixhumeke ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Idivayisi yakho ye-Android TV izonqamula okwesikhashana kusuka ku-Wi-Fi ngenkathi ixhumeke ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Ifoni izonqamuka okwesikhashana ku-Wi-Fi ngenkathi ixhumeke ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> - <string name="dlg_ok" msgid="3250085870426030310">"KULUNGILE"</string> - <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Ayikwazi ukuxhumeka ku-<xliff:g id="SSID">%1$s</xliff:g>"</string> - <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Thepha ukuze ushintshe izilungiselelo zobumfihlo uphinde uzame futhi"</string> - <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Shintsha isilungiselelo sobumfihlo?"</string> - <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"Ukuze uxhume, i-<xliff:g id="SSID">%1$s</xliff:g> idinga ukusebenzisa ikheli lakho ledivayisi ye-MAC, inkomba ehlukile. Okwamanje, izilungiselelo zemfihlo yakho ngale nethiwekhi zisebenzisa inkomba engahleliwe. \n\nLokhu kungavumela indawo yedivayisi yakho ukuthi ilandelelwe amadivayisi aseduze."</string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"Shintsha isilungiselelo"</string> - <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"Isilungiselelo sibuyekeziwe. Zama ukuxhuma futhi."</string> - <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"Ayikwazi ukushintsha isilungiselelo sobumfihlo"</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"Inethiwekhi ayitholiwe"</string> - <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"<xliff:g id="SSID">%1$s</xliff:g> : Iphutha lokugunyaza le-EAP 32760"</string> - <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"<xliff:g id="SSID">%1$s</xliff:g> : Iphutha lokugunyaza le-EAP 32761"</string> - <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"<xliff:g id="SSID">%1$s</xliff:g> : Iphutha lokugunyaza le-EAP 32762"</string> - <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"<xliff:g id="SSID">%1$s</xliff:g> : Iphutha lokugunyaza le-EAP 32763"</string> - <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"<xliff:g id="SSID">%1$s</xliff:g> : Iphutha lokugunyaza le-EAP 32764"</string> - <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"<xliff:g id="SSID">%1$s</xliff:g> : Iphutha lokugunyaza le-EAP 32765"</string> - <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g> : Iphutha lokugunyaza le-EAP 32766"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"I-Hotspot ivaliwe"</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Awekho amadivayisi axhunyiwe. Thepha ukuze ushintshe."</string> - <string name="wifi_sim_required_title" msgid="8362843050699015640">"I-Wi-Fi inqanyuliwe"</string> - <string name="wifi_sim_required_message" msgid="6085636103482409595">"Ukuze uxhumeke ku-<xliff:g id="SSID">%1$s</xliff:g> faka i-SIM ye-<xliff:g id="CARRIER_NAME">%2$s</xliff:g>"</string> -</resources> diff --git a/service/res/values/config.xml b/service/res/values/config.xml deleted file mode 100644 index 0264c3eae..000000000 --- a/service/res/values/config.xml +++ /dev/null @@ -1,467 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<!-- These resources are around just to allow their values to be customized - for different hardware and product builds. Do not translate. - - NOTE: The naming convention is "config_camelCaseValue". Some legacy - entries do not follow the convention, but all new entries should. --> - -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- boolean indicating whether the WiFi chipset has 5GHz band support. - Note: This config is replacing the config_wifi_dual_band_support - since more bands may now be supported (such as 6GHz), the naming dual_band - is no longer indicative, and a separate config now exists for each band --> - <bool translatable="false" name ="config_wifi5ghzSupport">false</bool> - - <!-- boolean indicating whether the WiFi chipset has 6GHz band support --> - <bool translatable="false" name ="config_wifi6ghzSupport">false</bool> - - <!-- Indicates that 11ax mode is supported on this device - Note that if this flag is set to true, then 11ax is assumed to be supported. - However, if it is left to the default value of false, the 11ax support will - be checked via NL80211 interface --> - <bool translatable="false" name="config_wifi11axSupportOverride">false</bool> - - <!-- Indicates whether to enable overriding the max number of spatial stream supported by the device - If true, config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideValue - will be used to override the max number of spatial stream supported by the device. - If false, it will be left to WifiCond to derive the value from NL80211 interface --> - <bool translatable="false" name="config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideEnable">true</bool> - <integer translatable="false" name="config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideValue">2</integer> - - <!-- Boolean indicating whether 802.11r Fast BSS Transition is enabled on this platform --> - <bool translatable="false" name="config_wifi_fast_bss_transition_enabled">false</bool> - - <!-- Device type information conforming to Annex B format in WiFi Direct specification. - The default represents a dual-mode smartphone --> - <string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string> - - <!-- Boolean indicating whether the wifi chipset supports background scanning mechanism. - This mechanism allows the host to remain in suspend state and the dongle to actively - scan and wake the host when a configured SSID is detected by the dongle. This chipset - capability can provide power savings when wifi needs to be always kept on. --> - <bool translatable="false" name="config_wifi_background_scan_support">false</bool> - - <!-- Boolean indicating whether or not to revert to default country code when cellular - radio is unable to find any MCC information to infer wifi country code from --> - <bool translatable="false" name="config_wifi_revert_country_code_on_cellular_loss">false</bool> - - <!-- Integer size limit, in KB, for a single WifiLogger ringbuffer, in default logging mode --> - <integer translatable="false" name="config_wifi_logger_ring_buffer_default_size_limit_kb">32</integer> - - <!-- Integer size limit, in KB, for a single WifiLogger ringbuffer, in verbose logging mode --> - <integer translatable="false" name="config_wifi_logger_ring_buffer_verbose_size_limit_kb">1024</integer> - - <!-- Array indicating wifi fatal firmware alert error code list from driver --> - <integer-array translatable="false" name="config_wifi_fatal_firmware_alert_error_code_list"> - <!-- Example: - <item>0</item> - <item>1</item> - <item>2</item> - --> - </integer-array> - - <!-- Boolean indicating whether or not wifi should turn off when emergency call is made --> - <bool translatable="false" name="config_wifi_turn_off_during_emergency_call">false</bool> - - <!-- Parameters for controlling network selection by the framework --> - - <!-- The ratio of the next two parameters is the multiplier that converts the estimated - throughput in Mbps to score points. --> - <integer translatable="false" name="config_wifiFrameworkThroughputBonusNumerator">120</integer> - <integer translatable="false" name="config_wifiFrameworkThroughputBonusDenominator">433</integer> - - <!-- Maximum contribution (in score points) due to the estimated throughput. --> - <integer translatable="false" name="config_wifiFrameworkThroughputBonusLimit">320</integer> - - <!-- The default values chosen here establish four non-overlapping categories: - saved, unmetered - unsaved, unmetered - saved, metered - unsaved, metered - These values can be reduced to allow overlapping between categories. --> - <integer translatable="false" name="config_wifiFrameworkSavedNetworkBonus">500</integer> - <integer translatable="false" name="config_wifiFrameworkUnmeteredNetworkBonus">1000</integer> - <!-- Integer specifying the minimum bonus for current network --> - <integer translatable="false" name="config_wifiFrameworkCurrentNetworkBonusMin">20</integer> - <!-- Integer specifying the percent bonus for current network. The percent is applied to - the sum of rssi base score and throughput score--> - <integer translatable="false" name="config_wifiFrameworkCurrentNetworkBonusPercent">20</integer> - <integer translatable="false" name="config_wifiFrameworkSecureNetworkBonus">40</integer> - - <!-- The duration in minutes to strongly favor the last-selected network over other options. --> - <integer translatable="false" name="config_wifiFrameworkLastSelectionMinutes">480</integer> - - <!-- Integer specifying the min packet Tx/Rx rates in packets per second to be considered - active traffic so that network selection and scan could be skipped--> - <integer translatable="false" name="config_wifiFrameworkMinPacketPerSecondActiveTraffic">16</integer> - <!-- Integer specifying the min packet Tx/Rx rates in packets per second to be considered - high traffic so that the device should stay on WiFi even if RSSI is very low --> - <integer translatable="false" name="config_wifiFrameworkMinPacketPerSecondHighTraffic">100</integer> - <!-- Integer parameters of the wifi to cellular handover feature - wifi should not stick to bad networks --> - <!-- Integer threshold for low network score, should be somewhat less than the entry threshhold --> - <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-80</integer> - <!-- Integer threshold, do not connect to APs with RSSI lower than the entry threshold --> - <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz">-77</integer> - <integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz">-70</integer> - <integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz">-57</integer> - <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz">-83</integer> - <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz">-80</integer> - <integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz">-73</integer> - <integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz">-60</integer> - <integer translatable="false" name="config_wifiFrameworkScoreBadRssiThreshold6ghz">-80</integer> - <integer translatable="false" name="config_wifiFrameworkScoreEntryRssiThreshold6ghz">-77</integer> - <integer translatable="false" name="config_wifiFrameworkScoreLowRssiThreshold6ghz">-70</integer> - <integer translatable="false" name="config_wifiFrameworkScoreGoodRssiThreshold6ghz">-57</integer> - - <!-- Integer delay in milliseconds before shutting down soft AP when there - are no connected devices. --> - <integer translatable="false" name="config_wifiFrameworkSoftApShutDownTimeoutMilliseconds">600000</integer> - - <!-- Integer indicating maximum hardware supported client number of soft ap --> - <integer translatable="false" name="config_wifiHardwareSoftapMaxClientCount">16</integer> - - <!-- boolean indicating whether or not to reset channel configuration during cloud configuration restore --> - <bool translatable="false" name ="config_wifiSoftapResetChannelConfig">true</bool> - - <!-- boolean indicating whether or not to reset hiddenSsid configuration during cloud configuration restore --> - <bool translatable="false" name ="config_wifiSoftapResetHiddenConfig">true</bool> - - <!-- boolean indicating whether or not to reset user control configuration during cloud configuration restore --> - <bool translatable="false" name ="config_wifiSoftapResetUserControlConfig">true</bool> - - <!-- boolean indicating whether or not to reset auto shotdown configuration during cloud configuration restore --> - <bool translatable="false" name ="config_wifiSoftapResetAutoShutdownTimerConfig">true</bool> - - <!-- boolean indicating whether or not to reset max client setting configuration during cloud configuration restore --> - <bool translatable="false" name ="config_wifiSoftapResetMaxClientSettingConfig">true</bool> - - <!-- List of allowed channels in 2GHz band for softap. If the device doesn't want to restrict - channels this should be empty. Values is a comma separated channel string and/or channel - range string like '1-6,11'. --> - <string translatable="false" name="config_wifiSoftap2gChannelList">1-11</string> - - <!-- List of allowed channels in 5GHz band for softap. If the device doesn't want to restrict - channels this should be empty. Values is a comma separated channel string and/or channel - range string like '36-48,149'. --> - <string translatable="false" name="config_wifiSoftap5gChannelList"></string> - - <!-- List of allowed channels in 6GHz band for softap. If the device doesn't want to restrict - channels this should be empty. Values is a comma separated channel string and/or channel - range string like '36-48,149'. --> - <string translatable="false" name="config_wifiSoftap6gChannelList"></string> - - <!-- Integer indicating associated full scan max num active channels --> - <integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_active_channels">6</integer> - - <!-- Integer delay in milliseconds before set wlan interface up during watchdog recovery --> - <integer translatable="false" name="config_wifi_framework_recovery_timeout_delay">2000</integer> - - <!-- Boolean indicating associated network selection is allowed --> - <bool translatable="false" name="config_wifi_framework_enable_associated_network_selection">true</bool> - - <!-- Integer duration after connection that a user-selected network is considered sufficient (milliseconds) --> - <integer translatable="false" name="config_wifiSufficientDurationAfterUserSelectionMilliseconds">60000</integer> - - <!-- Boolean indicating performing a partial initial scan is enabled --> - <bool translatable="false" name="config_wifiEnablePartialInitialScan">false</bool> - - <!-- Integer for maximum number of channels to use in initial partial scan. If equals to 0, means add all available channels for networks --> - <integer translatable="false" name="config_wifiInitialPartialScanChannelMaxCount">10</integer> - - <!-- Integer for maximum age for scan results used to identify channels for partial initial - scan in minutes --> - <integer translatable="false" name="config_wifiInitialPartialScanChannelCacheAgeMins">14400</integer> - - <!-- Boolean indicating whether single radio chain scan results are to be used for network selection --> - <bool translatable="false" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection">true</bool> - - <!-- Boolean indicating that wifi only link configuratios that have exact same credentials (i.e PSK) --> - <bool translatable="false" name="config_wifi_only_link_same_credential_configurations">true</bool> - - <!-- Boolean indicating whether framework needs to set the tx power limit for meeting SAR requirements --> - <bool translatable="false" name="config_wifi_framework_enable_sar_tx_power_limit">false</bool> - - <!-- Boolean indicating whether framework should use detection of softAP mode to set the tx - power limit for meeting SAR requirements --> - <bool translatable="false" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit">false</bool> - - <!-- Wifi Hal supports force client disconnect for softap --> - <bool translatable="false" name="config_wifiSofapClientForceDisconnectSupported">true</bool> - - <!-- Wifi driver supports Automatic channel selection (ACS) for softap --> - <bool translatable="false" name="config_wifi_softap_acs_supported">false</bool> - - <!-- Wifi driver supports WPA3 Simultaneous Authentication of Equals (WPA3-SAE) for softap --> - <bool translatable="false" name="config_wifi_softap_sae_supported">false</bool> - - <!-- Wifi driver supports IEEE80211AC for softap --> - <bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool> - - <!-- Wifi driver supports IEEE80211AX for softap --> - <bool translatable="false" name="config_wifiSoftapIeee80211axSupported">false</bool> - - <!-- Wifi driver supports IEEE80211AX single user beamformer for softap --> - <bool translatable="false" name="config_wifiSoftapHeSuBeamformerSupported">false</bool> - - <!-- Wifi driver supports IEEE80211AX single user beamformee for softap --> - <bool translatable="false" name="config_wifiSoftapHeSuBeamformeeSupported">false</bool> - - <!-- Wifi driver supports IEEE80211AX multiple user beamformer for softap --> - <bool translatable="false" name="config_wifiSoftapHeMuBeamformerSupported">false</bool> - - <!-- Wifi driver supports IEEE80211AX TWT (Target Wake Time) for softap --> - <bool translatable="false" name="config_wifiSoftapHeTwtSupported">false</bool> - - <!-- Wifi driver supports 6GHz band for softap --> - <bool translatable="false" name="config_wifiSoftap6ghzSupported">false</bool> - - <!-- Indicates that local-only hotspot should be brought up at 6GHz if possible. - This option is for automotive builds only (the one that have - PackageManager#FEATURE_AUTOMOTIVE) --> - <bool translatable="false" name="config_wifiLocalOnlyHotspot6ghz">false</bool> - - <!-- Indicates that local-only hotspot should be brought up at 5GHz if 6GHz is not enabled - or feasible. This option is for automotive builds only (the one that have - PackageManager#FEATURE_AUTOMOTIVE) --> - <bool translatable="false" name="config_wifi_local_only_hotspot_5ghz">false</bool> - - <!-- Indicates that connected MAC randomization is supported on this device --> - <bool translatable="false" name="config_wifi_connected_mac_randomization_supported">false</bool> - - <!-- Indicates that p2p MAC randomization is supported on this device --> - <bool translatable="false" name="config_wifi_p2p_mac_randomization_supported">false</bool> - - <!-- Indicates that AP mode MAC randomization is supported on this device --> - <bool translatable="false" name="config_wifi_ap_mac_randomization_supported">true</bool> - - <!-- list of SSIDs to enable aggressive MAC randomization on --> - <string-array translatable="false" name="config_wifi_aggressive_randomization_ssid_allowlist"> - <!-- SSIDs are expected in quoted format: - <item>\"SSID_1\"</item> - <item>\"SSID_2\"</item> - --> - </string-array> - - <!-- list of SSIDs to disable aggressive MAC randomization on. If a SSID is in both the - allowlist and blocklist, then aggressive MAC randomization will still be disabled. --> - <string-array translatable="false" name="config_wifi_aggressive_randomization_ssid_blocklist"> - <!-- SSIDs are expected in quoted format: - <item>\"SSID_1\"</item> - <item>\"SSID_2\"</item> - --> - </string-array> - - <!-- Indicates that wifi link probing is supported on this device --> - <bool translatable="false" name="config_wifi_link_probing_supported">false</bool> - - <!-- Configure wifi tcp buffersizes in the form: - rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max --> - <string name="config_wifi_tcp_buffers" translatable="false">524288,1048576,2097152,262144,524288,1048576</string> - - <!-- Do not translate. Default access point SSID used for tethering --> - <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string> - <!-- Do not translate. Default access point SSID used for local only hotspot --> - <string name="wifi_localhotspot_configure_ssid_default" translatable="false">AndroidShare</string> - - <!-- Indicates that a full bugreport should be triggered when wifi diagnostics detects an error on non-user (i.e debug) builds --> - <bool translatable="false" name="config_wifi_diagnostics_bugreport_enabled">false</bool> - - <!-- Indicates that wifi watchdog is enabled on this device --> - <bool translatable="false" name="config_wifi_watchdog_enabled">true</bool> - - <!-- - Controls the mapping between RSSI and RSSI levels. - - RSSI RSSI Level - (-infinity, thresholds[0]) 0 - [threshold[0], threshold[1]) 1 - [threshold[1], threshold[2]) 2 - ... ... - [threshold[len-2], threshold[len-1]) len-1 - [threshold[len-1], +infinity) len - - where: - [a, b) is the range of integers `n` such that a <= n < b - `threshold[i]` represents the i'th element of the config_wifiRssiLevelThresholds array - and `len` is the length of the config_wifiRssiLevelThresholds array. - --> - <integer-array translatable="false" name="config_wifiRssiLevelThresholds"> - <!-- RSSI RSSI Level --> - <item>-88</item> <!-- (-infinity, -88) 0 --> - <item>-77</item> <!-- [-88, -77) 1 --> - <item>-66</item> <!-- [-77, -66) 2 --> - <item>-55</item> <!-- [-66, -55) 3 --> - <!-- [-55, +infinity) 4 --> - </integer-array> - - <!-- Array describing scanning schedule in seconds when device is disconnected and screen is on --> - <integer-array translatable="false" name="config_wifiDisconnectedScanIntervalScheduleSec"> - <item>20</item> - <item>40</item> - <item>80</item> - <item>160</item> - </integer-array> - - <!-- Array describing scanning schedule in seconds when device is connected and screen is on --> - <integer-array translatable="false" name="config_wifiConnectedScanIntervalScheduleSec"> - <item>20</item> - <item>40</item> - <item>80</item> - <item>160</item> - </integer-array> - - <!-- Integer for minimum time between the last network selection and next high RSSI scan - in seconds when device is connected and screen is on --> - <integer translatable="false" name="config_wifiConnectedHighRssiScanMinimumWindowSizeSec"> 600 </integer> - - <!-- Array describing scanning schedule in seconds when device is connected and screen is on - and the connected network is the only saved network. - When this array is set to an empty array, the noraml connected scan schedule defined - in config_wifiConnectedScanIntervalScheduleSec will be used --> - <integer-array translatable="false" name="config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec"> - </integer-array> - - <!-- List of constants that indicate the number of consecutive failures per type needed to block a BSSID. - A blocked BSSID will not be considered in network selection and firmware roaming.--> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorApUnableToHandleNewStaThreshold"> 1 </integer> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorNetworkValidationFailureThreshold"> 1 </integer> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorWrongPasswordThreshold"> 1 </integer> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorEapFailureThreshold"> 1 </integer> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorAssociationRejectionThreshold"> 3 </integer> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorAssociationTimeoutThreshold"> 3 </integer> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorAuthenticationFailureThreshold"> 3 </integer> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorDhcpFailureThreshold"> 3 </integer> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorAbnormalDisconnectThreshold"> 3 </integer> - - <!-- Base duration to block a BSSID after consecutive failures happen. (default = 5 mins) - The blocklist duration is increased exponentially for a BSSID that consecutively gets added to the blocklist. - ie. 5/10/20/40/80/160/320/640 minutes - capped at 640 minutes because the default for - config_wifiBssidBlocklistMonitorFailureStreakCap is set to 7--> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorBaseBlockDurationMs"> 300000 </integer> - - <!-- Base duration to block a BSSID after the external connected scorer sets wifi as unusable. - The block duration is increased exponentially if the same BSSID is repeated marked as unusable. - ie. 0.5/1/2/4/8/16/32/64 minutes - capped at 64 minutes because the default for - config_wifiBssidBlocklistMonitorFailureStreakCap is set to 7. The block duration is reset to - the base value 3 hours after the latest connection to this BSSID. --> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs"> 30000 </integer> - - <!-- The failure streak is the number of times a BSSID consecutively gets blocked without ever - successfully connecting in between, and is used to calculate the exponentially growing blocklist time. - The config_wifiBssidBlocklistMonitorFailureStreakCap controls how many times the block duration - could exponentially grow when a BSSID keeps failing. - ie. A value of 0 means BSSIDs are always blocked for the flat base duration defined by - config_wifiBssidBlocklistMonitorBaseBlockDurationMs. --> - <integer translatable="false" name="config_wifiBssidBlocklistMonitorFailureStreakCap"> 7 </integer> - - <!-- If a non-locally generated disconnect happens within this time window after association, - then count it as a failure with reason code REASON_ABNORMAL_DISCONNECT (default = 30 seconds) --> - <integer translatable="false" name="config_wifiBssidBlocklistAbnormalDisconnectTimeWindowMs"> 30000 </integer> - - <!-- Indicates that hidden networks are to be scanned during scan only mode --> - <bool translatable="false" name="config_wifiScanHiddenNetworksScanOnlyMode">false</bool> - - <!-- Enable logging WifiIsUnusableEvent in metrics which gets triggered when wifi becomes unusable. --> - <bool translatable="false" name="config_wifiIsUnusableEventMetricsEnabled">true</bool> - - <!-- The minimum number of txBad the framework has to observe to trigger a wifi data stall. --> - <integer translatable="false" name="config_wifiDataStallMinTxBad">1</integer> - - <!-- The minimum number of txSuccess the framework has to observe - to trigger a wifi data stall when rxSuccess is 0. --> - <integer translatable="false" name="config_wifiDataStallMinTxSuccessWithoutRx">50</integer> - - <!-- Enable logging Wifi LinkSpeedCounts in metrics. --> - <bool translatable="false" name="config_wifiLinkSpeedMetricsEnabled">true</bool> - - <!-- Enable the PNO frequency culling optimization. --> - <bool translatable="false" name="config_wifiPnoFrequencyCullingEnabled">true</bool> - - <!-- Enable the PNO frequency culling optimization. --> - <bool translatable="false" name="config_wifiPnoRecencySortingEnabled">true</bool> - - <!-- Maximum number of SSIDs that can be PNO scanned concurrently--> - <integer translatable="false" name="config_wifiMaxPnoSsidCount">16</integer> - - <!-- Suspend optimization. --> - <bool translatable="false" name="config_wifiSuspendOptimizationsEnabled">true</bool> - - <!-- Network selection optimization at DEVICE_MOBILITY_STATE_HIGH_MVMT --> - <bool translatable="false" name="config_wifiHighMovementNetworkSelectionOptimizationEnabled">true</bool> - - <!-- Duration for the delayed scan used to verify access points are staying relatively stationary - to the device at high mobility state. (default = 10 seconds) --> - <integer translatable="false" name="config_wifiHighMovementNetworkSelectionOptimizationScanDelayMs">10000</integer> - - <!-- When config_wifiHighMovementNetworkSelectionOptimizationEnabled is true, BSSIDs with RSSI - from 2 consecutive scans that differ in either direction by more than this threshold will be - filtered out from network selection. (default = 10 dBs) --> - <integer translatable="false" name="config_wifiHighMovementNetworkSelectionOptimizationRssiDelta">10</integer> - - <!-- The interval in milliseconds at which wifi rtt ranging requests will be throttled when - they are coming from the background apps (default = 30 mins). --> - <integer translatable="false" name="config_wifiRttBackgroundExecGapMs">1800000</integer> - - <!-- Integer indicating the RSSI and link layer stats polling interval in milliseconds when device is connected and screen is on --> - <integer translatable="false" name="config_wifiPollRssiIntervalMilliseconds">3000</integer> - - <!-- Override channel utilization estimation with fixed value --> - <bool translatable="false" name="config_wifiChannelUtilizationOverrideEnabled">true</bool> - <!-- Integer values represent the channel utilization in different RF bands when - config_wifiChannelUtilizationOverridingEnabled is true. - They should be set to [0, 255] corresponding to utilization ratio between 0 and 1 --> - <integer translatable="false" name="config_wifiChannelUtilizationOverride2g">80</integer> - <integer translatable="false" name="config_wifiChannelUtilizationOverride5g">15</integer> - <integer translatable="false" name="config_wifiChannelUtilizationOverride6g">10</integer> - - <!-- Enable WPA2 to WPA3 auto-upgrade --> - <bool translatable="false" name="config_wifiSaeUpgradeEnabled">true</bool> - - <!-- Enable WPA2 to WPA3 auto-upgrade offload to capable Driver/Firmware --> - <bool translatable="false" name="config_wifiSaeUpgradeOffloadEnabled">false</bool> - - <!-- Number of self recoveries to be attempted per hour. Any fatal errors beyond this will - cause the wifi stack to turn wifi off and wait for user input. - Set to 0 to turn off recovery attempts and always turn off wifi on failures --> - <integer translatable="false" name="config_wifiMaxNativeFailureSelfRecoveryPerHour">2</integer> - <!-- Ignore the open saved network if from carrier provisioning app, there is a same open suggestion and a secure suggestion from same carrier available --> - <bool translatable="false" name="config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable">true</bool> - - <!-- Wifi driver Automatic channel selection (ACS) for softap to include DFS channels --> - <bool translatable="false" name="config_wifiSoftapAcsIncludeDfs">false</bool> - - <!-- Initial PNO scan interval, in milliseconds, when the device is moving (i.e. - WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN, WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT, or - WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT). - The scan interval backs off from this initial interval on subsequent scans. - This scan is performed when screen is off and disconnected. --> - <integer translatable="false" name="config_wifiMovingPnoScanIntervalMillis">20000</integer> - - <!-- Initial PNO scan interval, in milliseconds, when the device is stationary (i.e. - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY). - The scan interval backs off from this initial interval on subsequent scans. - This scan is performed when screen is off and disconnected. --> - <integer translatable="false" name="config_wifiStationaryPnoScanIntervalMillis">60000</integer> - - <!-- integer indicating additional disconnect delay (in ms) after IMS onLost() indication is received --> - <integer translatable="false" name="config_wifiDelayDisconnectOnImsLostMs">0</integer> - - <!-- Enable adding minimum confirmation duration when sending network score to connectivity service. --> - <bool translatable="false" name="config_wifiMinConfirmationDurationSendNetworkScoreEnabled">false</bool> -</resources> diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml deleted file mode 100644 index 60764ba6e..000000000 --- a/service/res/values/overlayable.xml +++ /dev/null @@ -1,235 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<!-- These values can be used to control wifi stack behavior/features on individual devices. - These can be overridden by OEM's by using an RRO overlay app. - See device/google/coral/rro_overlays/WifiOverlay/ for a sample overlay app. --> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <overlayable name="WifiCustomization"> - <!-- START VENDOR CUSTOMIZATION --> - <policy type="product|system|vendor"> - - <!-- Params from config.xml that can be overlayed --> - <item type="bool" name="config_wifi5ghzSupport" /> - <item type="bool" name="config_wifi6ghzSupport" /> - <item type="bool" name="config_wifi11axSupportOverride" /> - <item type="bool" name="config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideEnable" /> - <item type="integer" name="config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideValue" /> - <item type="bool" name="config_wifi_fast_bss_transition_enabled" /> - <item type="string" name="config_wifi_p2p_device_type" /> - <item type="bool" name="config_wifi_background_scan_support" /> - <item type="bool" name="config_wifi_revert_country_code_on_cellular_loss" /> - <item type="integer" name="config_wifi_logger_ring_buffer_default_size_limit_kb" /> - <item type="integer" name="config_wifi_logger_ring_buffer_verbose_size_limit_kb" /> - <item type="array" name="config_wifi_fatal_firmware_alert_error_code_list" /> - <item type="bool" name="config_wifi_turn_off_during_emergency_call" /> - <item type="integer" name="config_wifiFrameworkThroughputBonusNumerator" /> - <item type="integer" name="config_wifiFrameworkThroughputBonusDenominator" /> - <item type="integer" name="config_wifiFrameworkThroughputBonusLimit" /> - <item type="integer" name="config_wifiFrameworkSavedNetworkBonus" /> - <item type="integer" name="config_wifiFrameworkUnmeteredNetworkBonus" /> - <item type="integer" name="config_wifiFrameworkCurrentNetworkBonusMin" /> - <item type="integer" name="config_wifiFrameworkCurrentNetworkBonusPercent" /> - <item type="integer" name="config_wifiFrameworkSecureNetworkBonus" /> - <item type="integer" name="config_wifiFrameworkLastSelectionMinutes" /> - <item type="integer" name="config_wifiFrameworkMinPacketPerSecondActiveTraffic" /> - <item type="integer" name="config_wifiFrameworkMinPacketPerSecondHighTraffic" /> - <item type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz" /> - <item type="integer" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz" /> - <item type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz" /> - <item type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz" /> - <item type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz" /> - <item type="integer" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz" /> - <item type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz" /> - <item type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz" /> - <item type="integer" name="config_wifiFrameworkScoreBadRssiThreshold6ghz" /> - <item type="integer" name="config_wifiFrameworkScoreEntryRssiThreshold6ghz" /> - <item type="integer" name="config_wifiFrameworkScoreLowRssiThreshold6ghz" /> - <item type="integer" name="config_wifiFrameworkScoreGoodRssiThreshold6ghz" /> - <item type="integer" name="config_wifiFrameworkSoftApShutDownTimeoutMilliseconds" /> - <item type="bool" name="config_wifiSoftapResetChannelConfig" /> - <item type="bool" name="config_wifiSoftapResetHiddenConfig" /> - <item type="bool" name="config_wifiSoftapResetUserControlConfig" /> - <item type="bool" name="config_wifiSoftapResetAutoShutdownTimerConfig" /> - <item type="bool" name="config_wifiSoftapResetMaxClientSettingConfig" /> - <item type="string" name="config_wifiSoftap2gChannelList" /> - <item type="string" name="config_wifiSoftap5gChannelList" /> - <item type="string" name="config_wifiSoftap6gChannelList" /> - <item type="integer" name="config_wifi_framework_associated_partial_scan_max_num_active_channels" /> - <item type="integer" name="config_wifi_framework_recovery_timeout_delay" /> - <item type="bool" name="config_wifi_framework_enable_associated_network_selection" /> - <item type="integer" name="config_wifiSufficientDurationAfterUserSelectionMilliseconds" /> - <item type="bool" name="config_wifiEnablePartialInitialScan" /> - <item type="integer" name="config_wifiInitialPartialScanChannelMaxCount" /> - <item type="integer" name="config_wifiInitialPartialScanChannelCacheAgeMins" /> - <item type="bool" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection" /> - <item type="bool" name="config_wifi_only_link_same_credential_configurations" /> - <item type="bool" name="config_wifi_framework_enable_sar_tx_power_limit" /> - <item type="bool" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit" /> - <item type="bool" name="config_wifiSofapClientForceDisconnectSupported" /> - <item type="bool" name="config_wifi_softap_acs_supported" /> - <item type="bool" name="config_wifi_softap_sae_supported" /> - <item type="bool" name="config_wifi_softap_ieee80211ac_supported" /> - <item type="bool" name="config_wifiSoftapIeee80211axSupported" /> - <item type="bool" name="config_wifiSoftap6ghzSupported" /> - <item type="bool" name="config_wifiSoftapHeSuBeamformerSupported" /> - <item type="bool" name="config_wifiSoftapHeSuBeamformeeSupported" /> - <item type="bool" name="config_wifiSoftapHeMuBeamformerSupported" /> - <item type="bool" name="config_wifiSoftapHeTwtSupported" /> - <item type="bool" name="config_wifiLocalOnlyHotspot6ghz" /> - <item type="bool" name="config_wifi_local_only_hotspot_5ghz" /> - <item type="bool" name="config_wifi_connected_mac_randomization_supported" /> - <item type="bool" name="config_wifi_p2p_mac_randomization_supported" /> - <item type="bool" name="config_wifi_ap_mac_randomization_supported" /> - <item type="array" name="config_wifi_aggressive_randomization_ssid_allowlist" /> - <item type="array" name="config_wifi_aggressive_randomization_ssid_blocklist" /> - <item type="bool" name="config_wifi_link_probing_supported" /> - <item type="string" name="config_wifi_tcp_buffers" /> - <item type="string" name="wifi_tether_configure_ssid_default" /> - <item type="string" name="wifi_localhotspot_configure_ssid_default" /> - <item type="bool" name="config_wifi_diagnostics_bugreport_enabled" /> - <item type="bool" name="config_wifi_watchdog_enabled" /> - <item type="array" name="config_wifiRssiLevelThresholds" /> - <item type="array" name="config_wifiDisconnectedScanIntervalScheduleSec" /> - <item type="array" name="config_wifiConnectedScanIntervalScheduleSec" /> - <item type="array" name="config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec" /> - <item type="integer" name="config_wifiConnectedHighRssiScanMinimumWindowSizeSec" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorApUnableToHandleNewStaThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorNetworkValidationFailureThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorWrongPasswordThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorEapFailureThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorAssociationRejectionThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorAssociationTimeoutThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorAuthenticationFailureThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorDhcpFailureThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorAbnormalDisconnectThreshold" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorBaseBlockDurationMs" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs" /> - <item type="integer" name="config_wifiBssidBlocklistMonitorFailureStreakCap" /> - <item type="integer" name="config_wifiBssidBlocklistAbnormalDisconnectTimeWindowMs" /> - <item type="bool" name="config_wifiScanHiddenNetworksScanOnlyMode" /> - <item type="integer" name="config_wifiHardwareSoftapMaxClientCount" /> - <item type="bool" name="config_wifiIsUnusableEventMetricsEnabled" /> - <item type="integer" name="config_wifiDataStallMinTxBad" /> - <item type="integer" name="config_wifiDataStallMinTxSuccessWithoutRx" /> - <item type="bool" name="config_wifiLinkSpeedMetricsEnabled" /> - <item type="bool" name="config_wifiPnoFrequencyCullingEnabled" /> - <item type="bool" name="config_wifiPnoRecencySortingEnabled" /> - <item type="integer" name="config_wifiMaxPnoSsidCount" /> - <item type="bool" name="config_wifiSuspendOptimizationsEnabled" /> - <item type="bool" name="config_wifiHighMovementNetworkSelectionOptimizationEnabled" /> - <item type="integer" name="config_wifiHighMovementNetworkSelectionOptimizationScanDelayMs" /> - <item type="integer" name="config_wifiHighMovementNetworkSelectionOptimizationRssiDelta" /> - <item type="integer" name="config_wifiRttBackgroundExecGapMs" /> - <item type="integer" name="config_wifiPollRssiIntervalMilliseconds" /> - <item type="bool" name="config_wifiChannelUtilizationOverrideEnabled" /> - <item type="integer" name="config_wifiChannelUtilizationOverride2g" /> - <item type="integer" name="config_wifiChannelUtilizationOverride5g" /> - <item type="integer" name="config_wifiChannelUtilizationOverride6g" /> - <item type="bool" name="config_wifiSaeUpgradeEnabled" /> - <item type="bool" name="config_wifiSaeUpgradeOffloadEnabled" /> - <item type="integer" name="config_wifiMaxNativeFailureSelfRecoveryPerHour" /> - <item type="bool" name="config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable" /> - <item type="bool" name="config_wifiSoftapAcsIncludeDfs" /> - <item type="integer" name="config_wifiMovingPnoScanIntervalMillis" /> - <item type="integer" name="config_wifiStationaryPnoScanIntervalMillis" /> - <item type="integer" name="config_wifiDelayDisconnectOnImsLostMs" /> - <item type="bool" name="config_wifiMinConfirmationDurationSendNetworkScoreEnabled" /> - <!-- Params from config.xml that can be overlayed --> - - <!-- Params from strings.xml that can be overlayed --> - <item type="string" name="wifi_available_title" /> - <item type="string" name="wifi_available_title_connecting" /> - <item type="string" name="wifi_available_title_connected" /> - <item type="string" name="wifi_available_title_failed_to_connect" /> - <item type="string" name="wifi_available_content_failed_to_connect" /> - <item type="string" name="wifi_available_action_connect" /> - <item type="string" name="wifi_available_action_all_networks" /> - <item type="string" name="wifi_suggestion_title" /> - <item type="string" name="wifi_suggestion_content" /> - <item type="string" name="wifi_suggestion_action_allow_app" /> - <item type="string" name="wifi_suggestion_action_disallow_app" /> - <item type="string" name="wifi_suggestion_imsi_privacy_title" /> - <item type="string" name="wifi_suggestion_imsi_privacy_content" /> - <item type="string" name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" /> - <item type="string" name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" /> - <item type="string" name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" /> - <item type="string" name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" /> - <item type="string" name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" /> - <item type="string" name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" /> - <item type="string" name="wifi_wakeup_onboarding_title" /> - <item type="string" name="wifi_wakeup_onboarding_subtext" /> - <item type="string" name="wifi_wakeup_onboarding_action_disable" /> - <item type="string" name="wifi_wakeup_enabled_title" /> - <item type="string" name="wifi_wakeup_enabled_content" /> - <item type="string" name="wifi_watchdog_network_disabled" /> - <item type="string" name="wifi_watchdog_network_disabled_detailed" /> - <item type="string" name="wifi_connect_alert_title" /> - <item type="string" name="wifi_connect_alert_message" /> - <item type="string" name="wifi_connect_default_application" /> - <item type="string" name="accept" /> - <item type="string" name="decline" /> - <item type="string" name="ok" /> - <item type="string" name="wifi_p2p_invitation_sent_title" /> - <item type="string" name="wifi_p2p_invitation_to_connect_title" /> - <item type="string" name="wifi_p2p_from_message" /> - <item type="string" name="wifi_p2p_to_message" /> - <item type="string" name="wifi_p2p_enter_pin_message" /> - <item type="string" name="wifi_p2p_show_pin_message" /> - <item type="string" name="wifi_p2p_frequency_conflict_message" /> - <item type="string" name="dlg_ok" /> - <item type="string" name="wifi_cannot_connect_with_randomized_mac_title" /> - <item type="string" name="wifi_cannot_connect_with_randomized_mac_message" /> - <item type="string" name="wifi_disable_mac_randomization_dialog_title" /> - <item type="string" name="wifi_disable_mac_randomization_dialog_message" /> - <item type="string" name="wifi_disable_mac_randomization_dialog_confirm_text" /> - <item type="string" name="wifi_disable_mac_randomization_dialog_success" /> - <item type="string" name="wifi_disable_mac_randomization_dialog_failure" /> - <item type="string" name="wifi_disable_mac_randomization_dialog_network_not_found" /> - <item type="string" name="notification_channel_network_status" /> - <item type="string" name="notification_channel_network_alerts" /> - <item type="string" name="notification_channel_network_available" /> - <item type="string" name="wifi_eap_error_message_code_32760" /> - <item type="string" name="wifi_eap_error_message_code_32761" /> - <item type="string" name="wifi_eap_error_message_code_32762" /> - <item type="string" name="wifi_eap_error_message_code_32763" /> - <item type="string" name="wifi_eap_error_message_code_32764" /> - <item type="string" name="wifi_eap_error_message_code_32765" /> - <item type="string" name="wifi_eap_error_message_code_32766" /> - <item type="string" name="wifi_softap_auto_shutdown_timeout_expired_title" /> - <item type="string" name="wifi_softap_auto_shutdown_timeout_expired_summary" /> - <item type="string" name="wifi_sim_required_title" /> - <item type="string" name="wifi_sim_required_message" /> - <!-- Params from strings.xml that can be overlayed --> - - <!-- Params from styles.xml that can be overlayed --> - <item type="style" name="wifi_item" /> - <item type="style" name="wifi_item_label" /> - <item type="style" name="wifi_item_content" /> - <item type="style" name="wifi_section" /> - <!-- Params from styles.xml that can be overlayed --> - - <!-- Params from drawable/ that can be overlayed --> - <item type="drawable" name="stat_notify_wifi_in_range" /> - <item type="drawable" name="ic_wifi_settings" /> - <!-- Params from drawable/ that can be overlayed --> - - <!-- Params from layout/ that can be overlayed --> - <item type="layout" name="wifi_p2p_dialog" /> - <item type="layout" name="wifi_p2p_dialog_row" /> - <!-- Params from layout/ that can be overlayed --> - - </policy> - <!-- END VENDOR CUSTOMIZATION --> - </overlayable> -</resources> diff --git a/service/res/values/strings.xml b/service/res/values/strings.xml deleted file mode 100644 index ae3f1977b..000000000 --- a/service/res/values/strings.xml +++ /dev/null @@ -1,141 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- Official label of the wifi stack --> - <string name="wifiResourcesAppLabel" product="default">System Wi-Fi Resources</string> - <!-- Notification title for a nearby open wireless network.--> - <string name="wifi_available_title">Connect to open Wi\u2011Fi network</string> - <!-- Notification title when the system is connecting to the specified network. The network name is specified in the notification content. --> - <string name="wifi_available_title_connecting">Connecting to Wi\u2011Fi network</string> - <!-- Notification title when the system has connected to the network. The network name is specified in the notification content. --> - <string name="wifi_available_title_connected">Connected to Wi\u2011Fi network</string> - <!-- Notification title when the system failed to connect to the specified network. --> - <string name="wifi_available_title_failed_to_connect">Could not connect to Wi\u2011Fi network</string> - <!-- Notification content when the system failed to connect to the specified network. This informs the user that tapping on this notification will open the wifi picker. --> - <string name="wifi_available_content_failed_to_connect">Tap to see all networks</string> - <!-- Notification action name for connecting to the network specified in the notification body. --> - <string name="wifi_available_action_connect">Connect</string> - <!-- Notification action name for opening the wifi picker, showing the user all the nearby networks. --> - <string name="wifi_available_action_all_networks">All networks</string> - - <!-- Text shown when viewing channel settings for notifications related to network status --> - <string name="notification_channel_network_status">Network status</string> - <!-- Text shown when viewing channel settings for notifications related to network alerts --> - <string name="notification_channel_network_alerts">Network alerts</string> - <!-- Text shown when viewing the channel settings for notification about open nearby wireless networks. --> - <string name="notification_channel_network_available">Network available</string> - - <!-- Notification title for a connection to a app suggested wireless network.--> - <string name="wifi_suggestion_title">Allow suggested Wi\u2011Fi networks?</string> - <!-- Notification content for a connection to a app suggested wireless network.--> - <string name="wifi_suggestion_content"><xliff:g id="name" example="App123">%s</xliff:g> suggested networks. Device may connect automatically. </string> - <!-- Notification action for allowing app specified in the notification body.--> - <string name="wifi_suggestion_action_allow_app">Allow</string> - <!-- Notification action for disallowing app specified in the notification body.--> - <string name="wifi_suggestion_action_disallow_app">No thanks</string> - - <!-- Notification title for a connection to a SIM-based carrier network without IMSI privacy protection. --> - <string name="wifi_suggestion_imsi_privacy_title">Connect to <xliff:g id="carrierName" example="xxxMobile">%s</xliff:g> Wi\u2011Fi?</string> - <!-- Notification content for a connection to a SIM-based carrier network without IMSI privacy protection.--> - <string name="wifi_suggestion_imsi_privacy_content">These networks receive a SIM ID that can be used to track device location</string> - <!-- Notification action for allowing carrier specified in the notification body.--> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier">Connect</string> - <!-- Notification action for disallowing carrier specified in the notification body.--> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier">Don\u0027t connect</string> - <!-- Confirmation dialog title for a connection to a SIM-based carrier network without IMSI privacy protection. --> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title">Confirm connection?</string> - <!-- Confirmation dialog content for a connection to a SIM-based carrier network without IMSI privacy protection. --> - <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content">If you connect, <xliff:g id="carrierName" example="xxxMobile">%s</xliff:g> Wi\u2011Fi networks may access or share a unique ID associated with your SIM. This may allow your device\u0027s location to be tracked.</string> - <!-- Confirmation dialog action for allowing carrier specified in the dialog body --> - <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation">Connect</string> - <!-- Confirmation dialog action for disallowing carrier specified in the dialog body --> - <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation">Don\u0027t connect</string> - - - - <!--Notification title for Wi-Fi Wake onboarding. This is displayed the first time a user disables Wi-Fi with the feature enabled. --> - <string name="wifi_wakeup_onboarding_title">Wi\u2011Fi will turn on automatically</string> - <!--Notification subtext for Wi-Fi Wake onboarding.--> - <string name="wifi_wakeup_onboarding_subtext">When you\'re near a high quality saved network</string> - <!--Notification action to disable Wi-Fi Wake during onboarding.--> - <string name="wifi_wakeup_onboarding_action_disable">Don\'t turn back on</string> - <!--Notification title for when Wi-Fi Wake enables Wi-Fi.--> - <string name="wifi_wakeup_enabled_title">Wi\u2011Fi turned on automatically</string> - <!--Notification content for when Wi-Fi Wake enables Wi-Fi. %1$s is the SSID of the nearby saved network that triggered the wakeup. --> - <string name="wifi_wakeup_enabled_content">You\u0027re near a saved network: <xliff:g id="network_ssid">%1$s</xliff:g></string> - - <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems. This is the notification's title / ticker. --> - <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string> - <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems. The complete alert msg is: <hotspot name> + this string, i.e. "Linksys has a poor internet connection" --> - <string name="wifi_watchdog_network_disabled_detailed">\u0020has a poor internet connection.</string> - - <!-- A notification is shown the first time a connection is attempted on an app owned AP --> - <!-- title for this message --> - <string name="wifi_connect_alert_title">Allow connection?</string> - <!-- message explaining who is connecting to what --> - <string name="wifi_connect_alert_message">Application %1$s would like to connect to Wifi Network %2$s</string> - <!-- default application in case name can not be found --> - <string name="wifi_connect_default_application">An application</string> - - <string name="accept">Accept</string> - <string name="decline">Decline</string> - <string name="ok">OK</string> - - <string name="wifi_p2p_invitation_sent_title">Invitation sent</string> - <string name="wifi_p2p_invitation_to_connect_title">Invitation to connect</string> - - <string name="wifi_p2p_from_message">From: </string> - <string name="wifi_p2p_to_message">To: </string> - <string name="wifi_p2p_enter_pin_message">Type the required PIN: </string> - <string name="wifi_p2p_show_pin_message">PIN: </string> - - <string name="wifi_p2p_frequency_conflict_message" product="tablet">The tablet will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string> - <string name="wifi_p2p_frequency_conflict_message" product="tv">Your Android TV device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string> - <string name="wifi_p2p_frequency_conflict_message" product="default">The phone will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string> - <!-- Dialog ok button--> - <string name="dlg_ok">OK</string> - - <!-- Start of string constants used to inform the user that the current network may be failing to connect due to not supporting randomized MAC--> - <string name="wifi_cannot_connect_with_randomized_mac_title">Can\'t connect to <xliff:g id="ssid">%1$s</xliff:g></string> - <string name="wifi_cannot_connect_with_randomized_mac_message">Tap to change privacy settings and retry</string> - <string name="wifi_disable_mac_randomization_dialog_title">Change privacy setting?</string> - <string name="wifi_disable_mac_randomization_dialog_message"> To connect, <xliff:g id="ssid">%1$s</xliff:g> needs to use your device MAC address, a unique identifier. Currently, your privacy setting for this network uses a randomized identifier. - \n\nThis change may allow your device\'s location to be tracked by nearby devices. </string> - <string name="wifi_disable_mac_randomization_dialog_confirm_text">Change setting</string> - <string name="wifi_disable_mac_randomization_dialog_success">Setting updated. Try connecting again.</string> - <string name="wifi_disable_mac_randomization_dialog_failure">Can\'t change privacy setting</string> - <string name="wifi_disable_mac_randomization_dialog_network_not_found">Network not found</string> - <!-- End of string constants used to inform the user that the current network may be failing to connect due to not supporting randomized MAC--> - - <!-- A notification is shown when eap failure happens. It should be overridden by carrier-specific overlays. --> - <string name="wifi_eap_error_message_code_32760"><xliff:g id="ssid">%1$s</xliff:g> : EAP authentication error 32760</string> - <string name="wifi_eap_error_message_code_32761"><xliff:g id="ssid">%1$s</xliff:g> : EAP authentication error 32761</string> - <string name="wifi_eap_error_message_code_32762"><xliff:g id="ssid">%1$s</xliff:g> : EAP authentication error 32762</string> - <string name="wifi_eap_error_message_code_32763"><xliff:g id="ssid">%1$s</xliff:g> : EAP authentication error 32763</string> - <string name="wifi_eap_error_message_code_32764"><xliff:g id="ssid">%1$s</xliff:g> : EAP authentication error 32764</string> - <string name="wifi_eap_error_message_code_32765"><xliff:g id="ssid">%1$s</xliff:g> : EAP authentication error 32765</string> - <string name="wifi_eap_error_message_code_32766"><xliff:g id="ssid">%1$s</xliff:g> : EAP authentication error 32766</string> - - - <!-- A notification is shown when softap auto shutdown timeout expired. It should be overridden by carrier-specific overlays. --> - <string name="wifi_softap_auto_shutdown_timeout_expired_title">Hotspot turned off</string> - <string name="wifi_softap_auto_shutdown_timeout_expired_summary">No devices connected. Tap to modify.</string> - - <!-- A notification is shown when eap-sim/aka/aka' wifi network is disconnected due to sim removal --> - <string name="wifi_sim_required_title">Wi\u2011Fi disconnected</string> - <string name="wifi_sim_required_message">To connect to <xliff:g id="ssid">%1$s</xliff:g>, insert a <xliff:g id="carrier_name">%2$s</xliff:g> SIM</string> -</resources> diff --git a/service/res/values/styles.xml b/service/res/values/styles.xml deleted file mode 100644 index 1de17d635..000000000 --- a/service/res/values/styles.xml +++ /dev/null @@ -1,45 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> -<resources> - <!-- Wifi dialog styles --> - <style name="wifi_item"> - <item name="android:layout_width">200dip</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:layout_marginTop">8dip</item> - <item name="android:layout_marginStart">16dip</item> - <item name="android:layout_marginEnd">16dip</item> - <item name="android:orientation">vertical</item> - <item name="android:gravity">start</item> - </style> - - <style name="wifi_item_label"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:textSize">14sp</item> - </style> - - <style name="wifi_item_content"> - <item name="android:layout_width">match_parent</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:textSize">18sp</item> - </style> - - <style name="wifi_section"> - <item name="android:layout_width">match_parent</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:orientation">vertical</item> - </style> -</resources> diff --git a/service/resources-certs/com.android.wifi.resources.pk8 b/service/resources-certs/com.android.wifi.resources.pk8 Binary files differdeleted file mode 100644 index 50cca9098..000000000 --- a/service/resources-certs/com.android.wifi.resources.pk8 +++ /dev/null diff --git a/service/resources-certs/com.android.wifi.resources.x509.pem b/service/resources-certs/com.android.wifi.resources.x509.pem deleted file mode 100644 index c321be108..000000000 --- a/service/resources-certs/com.android.wifi.resources.x509.pem +++ /dev/null @@ -1,35 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGJzCCBA+gAwIBAgIUYJCfWCLIVw8RN9EmWeX78BvlReMwDQYJKoZIhvcNAQEL -BQAwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH -DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy -b2lkMR0wGwYDVQQDDBRTZXJ2aWNlV2lmaVJlc291cmNlczEiMCAGCSqGSIb3DQEJ -ARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAgFw0yMDAzMjUwMzA0MDFaGA80NzU4MDIx -OTAzMDQwMVowgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYw -FAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQL -DAdBbmRyb2lkMR0wGwYDVQQDDBRTZXJ2aWNlV2lmaVJlc291cmNlczEiMCAGCSqG -SIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAOqOCNZuwS5nIEg5wUPop40+WSAZEQ5SL/uSNU1dnGMSxkD5 -QqZQ3eWKlLSvP1FXtbQPTojXn2fa8w2P39dUAe33NXgpSHZVk18DMgeepNCAbynJ -fciqYCMjnT3G1scIZP8HCxAXsuoynqLSms7IyombgM4iePVKKKwRpe3F3BmWgjgz -RatW6C2CJLHc4KgCD53b4w9XHrQ8l3L1c3bgIwjaDSd0VxKIa41KtHHWp3LuvxX5 -4wz6tbBNW5ZMNDEfvF7CGmTCkdbMAYkWcJxZxA57E2tpxXd+2TnEDo6HL7Yq28jG -r8jN6U63zRsKHLMi+Dtyei0w1nBxtTf5KsWI7B5Cxavl+V+tCsnNfq5Gu+vjJnlL -0kpFcBixG/TPv7H+NgyO5D7joAyGSctfMkTPWdSRD/FNTs30yil+hxUIu4mFYtXO -+c6yIm11OBmGz1IoqetgbBhQiUwy+p8oqge2NtFDaIJ3dkd5cmNUF/EXI89aUhu0 -o/Vo2coUpR/cYZTgexfk2RKcH3RkuG69HXofrC9SGY0RI7GgmaG0e1inBjVrOydP -1XXJmF3DV8yy8NmkJklbljsGD52XuBC6VQ0eIh7cLKWjgMCJFFNkNgU0syZ3+bma -28FWvzJzd3ii5seWqePGgcrfdgjxblNzQEKWw0Me9Wn/S0OKOz/5OAM9Z7RDAgMB -AAGjUzBRMB0GA1UdDgQWBBQjYEU0cbWxEO42h68+ttN5+wDSITAfBgNVHSMEGDAW -gBQjYEU0cbWxEO42h68+ttN5+wDSITAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 -DQEBCwUAA4ICAQCatnV7MZsIQTPo3AbbvmSPfyFM4/ncRDao+hxxvDKwMMWw6O2r -uKPIbdj3xcH4vwvM2v3Kg+YCNrRgTTG23QHXNzHgXM75o1q7djGEiuOaZ6lwGh0G -KD0B1xnYVRKqpacoP7SJ2MLWpum1i6c12P3s4JLBIiU4OtHKOozai37YMFM1Iwla -QsGwgXyScRPs091aGe0G4eC0/10skHW0ASS4VUjbvqQE6opfMLdoMhuqAxTY8Nlz -51B2smf/w7AAU4dpOE5sgdctbWpMNovAZe8yxt3Wk48pFIYPwTRXM6wSXoqYzX23 -s/rJmuGzX3PKV5hVZazYetj5clK/HB4Y/Clf3bVaoOKKSUgtOT3KB732yHIfFJDl -vhqe5niRNf2Decy6aYJFw/IqMYM/3Fh4B1JcDFHzOq4Ta6yuvhqbXVdbM5dPzcgQ -CO640v20uQVMjpknnxdBu7QxLMYuAfeuJkoWnvRtjSwQHPisnCWfxu6ryBIN3Xg7 -HtiEv+CVrvyq2UGbKhCtk/Z50eOdyRTAldoP3AcGbakZHtKAuz/m9TlTYDCnh/tH -79soVqj2HMaM5XzslueGaERt149pr8uOhhK4NO+e1bc65Fw9ysHVrVn4pcaq8OGm -yPSAsaHXcskBG5CywWfPcBaSij/0+QLbddie1cyeCFxz0aDypNMH+SCgsA== ------END CERTIFICATE----- diff --git a/service/resources-certs/key.pem b/service/resources-certs/key.pem deleted file mode 100644 index 31acc3c89..000000000 --- a/service/resources-certs/key.pem +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDqjgjWbsEuZyBI -OcFD6KeNPlkgGREOUi/7kjVNXZxjEsZA+UKmUN3lipS0rz9RV7W0D06I159n2vMN -j9/XVAHt9zV4KUh2VZNfAzIHnqTQgG8pyX3IqmAjI509xtbHCGT/BwsQF7LqMp6i -0prOyMqJm4DOInj1SiisEaXtxdwZloI4M0WrVugtgiSx3OCoAg+d2+MPVx60PJdy -9XN24CMI2g0ndFcSiGuNSrRx1qdy7r8V+eMM+rWwTVuWTDQxH7xewhpkwpHWzAGJ -FnCcWcQOexNracV3ftk5xA6Ohy+2KtvIxq/IzelOt80bChyzIvg7cnotMNZwcbU3 -+SrFiOweQsWr5flfrQrJzX6uRrvr4yZ5S9JKRXAYsRv0z7+x/jYMjuQ+46AMhknL -XzJEz1nUkQ/xTU7N9MopfocVCLuJhWLVzvnOsiJtdTgZhs9SKKnrYGwYUIlMMvqf -KKoHtjbRQ2iCd3ZHeXJjVBfxFyPPWlIbtKP1aNnKFKUf3GGU4HsX5NkSnB90ZLhu -vR16H6wvUhmNESOxoJmhtHtYpwY1azsnT9V1yZhdw1fMsvDZpCZJW5Y7Bg+dl7gQ -ulUNHiIe3Cylo4DAiRRTZDYFNLMmd/m5mtvBVr8yc3d4oubHlqnjxoHK33YI8W5T -c0BClsNDHvVp/0tDijs/+TgDPWe0QwIDAQABAoICAQCXq2SXlGKiqNi9G2uXh/fg -Y3KqSMs4oXiZij+hWWjov5knJocsmJoD9gqWk8Ozy62ZU1SLNDLFq1UDbgdma9Ib -mIEgxEExE8EJ7T0KpFEa6hH3yWzmtxUXY84nxk3Xwdvc9Sb4LvroafcefmTQVhJx -zPYLVUs2AdAvA/JxwEHE4gguYykn1DiqRL+Jq7Qxr7N9dlRq9QDLt2qPUZxqQCEn -diiPXLF5MHGrmaT4/76jmTJC+aUSHYQjDsKse3Y8VbMu6wC6Kv63EI/ln3cOAxW9 -72PtTyX7UTESI27uRwhZGXmpaKD+jffRiRS96VoJlBFED5BlbHEdoMl3+kzoEtPq -uIA+8gdl0pXtQpzR340d6vqSU+THnqhR4OCyhZXRSJAqyBIlG7pWmNMnMJoARUIq -q3vJmiakgNGcFqFaddYL8dUdZiwBg37WIG40GUhEaSaPc9BYpX4mTxheWRqPUHuj -BUQpZA8qUZx4zlkJ8OpqCznU5wCPs6CRxB9+MXh7+Rk4l0aEir2yvQpkQuoH+qx8 -HzinDpj6B+PPDuHhQkVu7EZxq/hnl3RktHghT+qOH36Z4f6yx6+UqR724NcHC4zn -igS4JP1wq7egedPbr1v+GZWWa+/HIkUicy1gT2FxvlLAXiYBCQh9lQW80tPLREE5 -OC++g3Znn4BhAxC9Nf9MIQKCAQEA+A/Mq6etUdjEER0F22MMm2H5wca/x+VAPw03 -0PkpuWD6hEXIWEq5olowMAmsy99XDQmLhP4qnARNbVcqJ3/Ad8TDiPc9u4ofHvEI -r0BiB+90Y+MSydjtE2JCGqZ+7f1o9gv02Ym28ZNmF786oJKoCLTF7oarzuFSyiBL -V6dcE6zzkaMNpHj9U2boeI/vgdhUlLPZ3ES+o2FUCWvuuhfkj6NheCuyqhKiLTnW -1M3sLjSbxQKLkY0ebPK0I3l8pasBKRE34MUWRRc5sHQquvdv5YHRLHsL1Ti4zzTM -jPejMWsBHFdygA2EIz144PV0rLQAXURtu1fp864oRhMmQeIvqwKCAQEA8g+VDmyR -QJrhea199judCRvURxsFR9Cy6ZQpGdYpK9OQcHA1AGig4hCW2S1+ZIdJCOWvjdBQ -X2SbtM0tzjOkwqfsMjYubXcPMLB2tM8eOSPD/kOfDL4+G8wjGhDeua8loTOg3Jzl -MeSCDrPhO5gIzXDr+ysnMQblLrL36YJb+PTwMHgk1NdgCQ9PBa2BHbKpPiK3mMM0 -qQXz+zRublvB0uXYaNlUpgdL35fXo5ChKgrMvk9rOiozh/jE/SFTM1iRGU4WJUlN -KB1CxXR5Cn+lYeO8yF+aZO0a7lWq9R8i2bXsMReQIr+sOBE2cAZP+VP18chujSkP -DnAwoLVxmHXVyQKCAQAA9h6285lqXcq0vkYNiZ68425SX/DSV4MeO3Dh8HVG8KdH -5/VU0kVR6cOSDBeNWro9pLHTvCByJloeeF4DdS1LyYlweHTWyzw/pHOCKl+25Cix -Umn6OksA7jqPW+HWDktf2MAEL9JzsTyODwGtKaRZFEpIGGGGFb16ZxGjr1ReByeS -gu1Em+tvbVCtVvF4sVvyj5fikKmkfHYU60QrmHgcTmfMTW8N1bCnODgq7vlhXHbW -FqJv1/osNeyYzpm7EqSYgiaTSnBBqEti8bBQtTDL1Or4nyl2lBezReMdEMCjKmUA -tR4OfP7sHArh5FGlcbUmp2M9fKO9fAlP7DcTvkqtAoIBAQDp0hd/6Wud5n5rFSWZ -1xfoFpPFY9qD9pr8enwBUxhOF31sv1bTYD4YYUH147Y10WDBUW11JYadvweRbKkU -iFpdFexYzHGol9t6gtsH6RIey+elExjuLE6+d0BpC2a6Iu/MeZynvn6+5SakoSmu -cTv/h1bMNnETML/tjj9ftua045WonEWnu6wu1DTXHTSdxVkqhkqnK9kQdImrXIhX -3haqbA/RqC3WezHVeE162Fh1zhzcsMa5Vs6UR7+xbKF79c+jjARkXBxF5Y38Qngx -pf/RQTW4sHDpkQf0tZgAU+VMPCk9eq9mgZQQTMAzEkXqaCopNh1kCgdbQRAYDWz/ -gsPRAoIBAQCVVhnmVFI3+u0vFcnJsKScw/D/hUcv2czUje0Li7fz84lrT2sXiSfH -iFsvG9SwFsrSvTVcAy/agumE3nzsvymTQvdu7irVJczKw4lUdx22ZqdupqQRsUMR -2kx2fzPLUlG5eHnFUpyUDIVwPSfmjSv6MwF2ScWFLWyR0coPDgYz/EdUENDSXkzW -CCxbF7lH7jc60vOVqMH0HyFT+k5SOQDVWckzQzGLoMhKobv9FHijCnc/jdsAYkOx -+MMdUcFf1X4WjHb9U5be/YrhiOO4Ar41hEm2ezsrcreszr69Zv4Tw3BLpr/nkS37 -adx3U1hB9OzUKVm21xtowKxcrEsOpvR1 ------END PRIVATE KEY----- diff --git a/service/wifi.rc b/service/wifi.rc deleted file mode 100644 index eceee0ae0..000000000 --- a/service/wifi.rc +++ /dev/null @@ -1,101 +0,0 @@ -# -# Copyright (C) 2016 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. -# - -# These are needed for migration of data to wifi apex directory. -on post-fs-data - restorecon_recursive /data/misc/apexdata/com.android.wifi - -on property:sys.user.0.ce_available=true - restorecon_recursive /data/misc_ce/0/apexdata/com.android.wifi - -# Below are for kernel tracing related stuff. -on fs - setprop sys.wifitracing.started 0 - -on property:sys.boot_completed=1 && property:sys.wifitracing.started=0 - # Create trace buffer, and set basic configuration. - mkdir /sys/kernel/debug/tracing/instances/wifi 711 - restorecon_recursive /sys/kernel/debug/tracing/instances/wifi - write /sys/kernel/debug/tracing/instances/wifi/tracing_on 0 - write /sys/kernel/debug/tracing/instances/wifi/buffer_size_kb 1 - write /sys/kernel/debug/tracing/instances/wifi/trace_options disable_on_free - - mkdir /sys/kernel/tracing/instances/wifi 711 - restorecon_recursive /sys/kernel/tracing/instances/wifi - write /sys/kernel/tracing/instances/wifi/tracing_on 0 - write /sys/kernel/tracing/instances/wifi/buffer_size_kb 1 - write /sys/kernel/tracing/instances/wifi/trace_options disable_on_free - - # Enable cfg80211 events for connection and key management events. - # - Events are not actually logged until WifiService writes "1" to - # /sys/kernel/debug/tracing/instances/wifi/tracing_on. - # - WifiService is responsible for turning tracing off and on. - write /sys/kernel/debug/tracing/instances/wifi/events/cfg80211/cfg80211_gtk_rekey_notify/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/cfg80211/rdev_add_key/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/cfg80211/rdev_assoc/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/cfg80211/rdev_auth/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/cfg80211/rdev_connect/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/cfg80211/rdev_set_default_key/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/cfg80211/rdev_set_default_mgmt_key/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/cfg80211/rdev_set_rekey_data/enable 1 - - write /sys/kernel/tracing/instances/wifi/events/cfg80211/cfg80211_gtk_rekey_notify/enable 1 - write /sys/kernel/tracing/instances/wifi/events/cfg80211/rdev_add_key/enable 1 - write /sys/kernel/tracing/instances/wifi/events/cfg80211/rdev_assoc/enable 1 - write /sys/kernel/tracing/instances/wifi/events/cfg80211/rdev_auth/enable 1 - write /sys/kernel/tracing/instances/wifi/events/cfg80211/rdev_connect/enable 1 - write /sys/kernel/tracing/instances/wifi/events/cfg80211/rdev_set_default_key/enable 1 - write /sys/kernel/tracing/instances/wifi/events/cfg80211/rdev_set_default_mgmt_key/enable 1 - write /sys/kernel/tracing/instances/wifi/events/cfg80211/rdev_set_rekey_data/enable 1 - - # Enable datapath events for Wifi. - # - Events are not actually logged until WifiService writes "1" to - # /sys/kernel/debug/tracing/instances/wifi/tracing_on. - # - WifiService will ensure that tracing is turned back off, - # when a connection attempt ends (whether in success or failure) - write /sys/kernel/debug/tracing/instances/wifi/events/net/filter name==${wifi.interface:-wlan0} - write /sys/kernel/debug/tracing/instances/wifi/events/net/net_dev_queue/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/net/net_dev_xmit/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/net/netif_rx/enable 1 - write /sys/kernel/debug/tracing/instances/wifi/events/net/netif_receive_skb/enable 1 - - write /sys/kernel/tracing/instances/wifi/events/net/filter name==${wifi.interface:-wlan0} - write /sys/kernel/tracing/instances/wifi/events/net/net_dev_queue/enable 1 - write /sys/kernel/tracing/instances/wifi/events/net/net_dev_xmit/enable 1 - write /sys/kernel/tracing/instances/wifi/events/net/netif_rx/enable 1 - write /sys/kernel/tracing/instances/wifi/events/net/netif_receive_skb/enable 1 - - # Set DAC to allow system to enable/disable, and read wifi trace - # events. - chown system /sys/kernel/debug/tracing/instances/wifi/tracing_on - chown system /sys/kernel/debug/tracing/instances/wifi/free_buffer - chown system /sys/kernel/debug/tracing/instances/wifi/trace - chmod 200 /sys/kernel/debug/tracing/instances/wifi/tracing_on - chmod 400 /sys/kernel/debug/tracing/instances/wifi/free_buffer - chmod 600 /sys/kernel/debug/tracing/instances/wifi/trace - - chown system /sys/kernel/tracing/instances/wifi/tracing_on - chown system /sys/kernel/tracing/instances/wifi/free_buffer - chown system /sys/kernel/tracing/instances/wifi/trace - chmod 200 /sys/kernel/tracing/instances/wifi/tracing_on - chmod 400 /sys/kernel/tracing/instances/wifi/free_buffer - chmod 600 /sys/kernel/tracing/instances/wifi/trace - setprop sys.wifitracing.started 1 - -on property:sys.boot_completed=1 && property:wifi.interface=* && property:sys.wifitracing.started=1 - # Override default value. - write /sys/kernel/debug/tracing/instances/wifi/events/net/filter name==${wifi.interface} - write /sys/kernel/tracing/instances/wifi/events/net/filter name==${wifi.interface} diff --git a/tests/Android.bp b/tests/Android.bp deleted file mode 100644 index 67fea52b2..000000000 --- a/tests/Android.bp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2019 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. - -// Include subdirectory makefiles -// ============================================================ -subdirs = [ - "wifitests", - "mts", -] diff --git a/tests/mts/Android.bp b/tests/mts/Android.bp deleted file mode 100644 index 19b0eb1f7..000000000 --- a/tests/mts/Android.bp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2020 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. - -// Wifi MTS-only tests i.e. not part of CTS or GTS -// Used to test functionality that is only guaranteed to be implemented in the Wifi Mainline module, -// but is not required if the Wifi Mainline module is not present on the device. -android_test { - name: "MtsWifiTestCases", - defaults: ["cts_defaults"], - - libs: [ - "org.apache.http.legacy", - "android.test.base.stubs", - ], - - srcs: [ "src/**/*.java" ], - - static_libs: [ - // for ShellIdentityUtils, builds against test_current - "compatibility-device-util-axt", - "ctstestrunner-axt", - "ctstestserver", - "junit", - "junit-params", - "truth-prebuilt", - // for Wifi protos, builds against system_current - "wifi-nano-protos", - // for AndroidJUnit4 - "androidx.test.ext.junit", - "androidx.test.runner", - ], - - // need access to system_current and test_current, so needs to be platform_apis: true - platform_apis: true, - - test_suites: [ "mts" ], - test_config: "AndroidTest.xml", -} diff --git a/tests/mts/AndroidManifest.xml b/tests/mts/AndroidManifest.xml deleted file mode 100644 index b8b025dc2..000000000 --- a/tests/mts/AndroidManifest.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2020 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. - --> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="android.net.wifi.mts" - android:targetSandboxVersion="2"> - - <!-- Need DUMP permission to call `dumpsys wifi wifiMetricsProto` --> - <uses-permission android:name="android.permission.DUMP" /> - - <application android:usesCleartextTraffic="true"> - <uses-library android:name="android.test.runner" /> - <uses-library android:name="org.apache.http.legacy" android:required="false" /> - </application> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.net.wifi.mts" - android:label="MTS tests for android.net.wifi"> - <meta-data android:name="listener" - android:value="com.android.cts.runner.CtsTestRunListener" /> - </instrumentation> - -</manifest> - diff --git a/tests/mts/AndroidTest.xml b/tests/mts/AndroidTest.xml deleted file mode 100644 index ee5878600..000000000 --- a/tests/mts/AndroidTest.xml +++ /dev/null @@ -1,40 +0,0 @@ -<!-- - ~ Copyright (C) 2020 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. - --> -<configuration description="Test config for MtsWifiTestCases"> - <option name="test-suite-tag" value="cts" /> - <option name="config-descriptor:metadata" key="component" value="networking" /> - <option name="config-descriptor:metadata" key="parameter" value="instant_app" /> - <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> - <option name="config-descriptor:metadata" key="parameter" value="secondary_user" /> - <option name="not-shardable" value="true" /> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="test-file-name" value="MtsWifiTestCases.apk" /> - </target_preparer> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="android.net.wifi.mts" /> - <option name="runtime-hint" value="9m4s" /> - <option name="hidden-api-checks" value="false" /> - <option name="isolated-storage" value="false" /> - </test> - - <!-- Only run MtsWifiTestCases if the Wifi Mainline module is installed. If the Wifi Mainline - module is not installed, the device is not required to pass these test cases. --> - <object type="module_controller" - class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.google.android.wifi" /> - </object> -</configuration> diff --git a/tests/mts/src/android/net/wifi/mts/StreamReader.java b/tests/mts/src/android/net/wifi/mts/StreamReader.java deleted file mode 100644 index c0c35bbb5..000000000 --- a/tests/mts/src/android/net/wifi/mts/StreamReader.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2020 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 android.net.wifi.mts; - -import android.util.Log; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * Reads from the given BufferedReader and saves the output to a string. - */ -public class StreamReader extends Thread { - private static final String TAG = "ConnMetrics:" + StreamReader.class.getSimpleName(); - private BufferedReader mSource; - private String mOutput; - - public StreamReader(BufferedReader source) { - mSource = source; - } - - public String getOutput() { - if (mOutput == null) { - throw new IllegalStateException( - "Should call start and join before trying to get output"); - } - return mOutput; - } - - @Override - public void run() { - StringBuilder sb = new StringBuilder(); - String s; - try { - while ((s = mSource.readLine()) != null) { - sb.append(s); - sb.append("\n"); - } - } catch (IOException e) { - Log.e(TAG, "Error reading input", e); - } finally { - try { - mSource.close(); - } catch (IOException e) { - Log.e(TAG, "Error closing reader", e); - } - } - mOutput = sb.toString(); - } - - /** - * Runs the specified process command and returns the results of the input and error streams. - * - * @return The output of the input stream, or null if there was an exception. - */ - public static String runProcessCommand(String command) { - try { - Process process = Runtime.getRuntime().exec(command); - - BufferedReader stdInput = new BufferedReader( - new InputStreamReader(process.getInputStream())); - BufferedReader stdError = new BufferedReader( - new InputStreamReader(process.getErrorStream())); - StreamReader inputReader = new StreamReader(stdInput); - StreamReader errorReader = new StreamReader(stdError); - - inputReader.start(); - errorReader.start(); - - process.waitFor(); - try { - inputReader.join(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - Log.e(TAG, "Error joining thread", e); - } - try { - errorReader.join(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - Log.e(TAG, "Error joining thread", e); - } - - // Some commands will return some valid data while also printing a message in - // the error stream, so returning result of the input stream regardless of if - // there's a message in the error stream. - if (errorReader.getOutput().length() > 0) { - Log.e(TAG, errorReader.getOutput()); - } - return inputReader.getOutput(); - } catch (IOException e) { - Log.e(TAG, "Error running command", e); - return null; - } catch (InterruptedException e) { - Log.e(TAG, "Process was interrupted", e); - Thread.currentThread().interrupt(); - return null; - } - } -} diff --git a/tests/mts/src/android/net/wifi/mts/WifiDumpsysMetricsTest.java b/tests/mts/src/android/net/wifi/mts/WifiDumpsysMetricsTest.java deleted file mode 100644 index 7fc10ec84..000000000 --- a/tests/mts/src/android/net/wifi/mts/WifiDumpsysMetricsTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2020 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 android.net.wifi.mts; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import static org.junit.Assume.assumeTrue; - -import android.content.Context; -import android.util.Base64; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.platform.app.InstrumentationRegistry; - -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiLog; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -public class WifiDumpsysMetricsTest { - - private static final String WIFI_DUMP_PROTO_CMD = "/system/bin/dumpsys wifi wifiMetricsProto"; - - private static final String START_TAG = "WifiMetrics:\n"; - private static final String END_TAG = "\nEndWifiMetrics"; - - @Before - public void setUp() throws Exception { - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - assumeTrue(WifiFeature.isWifiSupported(context)); - } - - /** - * Test that Wifi dumps metrics in the expected format. - * - * Assumption: - * - Test device should have at least 1 saved network - */ - @Test - public void testWifiDumpMetrics() throws Exception { - // DO NOT run under shell identity. Shell has a lot more permissions. - // `dumpsys wifi wifiMetricsProto` should ONLY need `android.permission.DUMP` - String rawDumpOutput = StreamReader.runProcessCommand(WIFI_DUMP_PROTO_CMD); - - assertThat(rawDumpOutput).isNotNull(); - - int protoStart = rawDumpOutput.indexOf(START_TAG); - int protoEnd = rawDumpOutput.indexOf(END_TAG); - - assertWithMessage("Expected to find \"WifiMetrics:\", but instead found: " + rawDumpOutput) - .that(protoStart).isAtLeast(0); - assertWithMessage( - "Expected to find \"EndWifiMetrics\", but instead found: " + rawDumpOutput) - .that(protoEnd).isAtLeast(protoStart); - - String protoString = rawDumpOutput.substring(protoStart + START_TAG.length(), protoEnd); - byte[] protoBytes = Base64.decode(protoString, Base64.DEFAULT); - - WifiLog wifiLog = WifiLog.parseFrom(protoBytes); - - assertThat(wifiLog.numSavedNetworks).isAtLeast(1); - assertThat(wifiLog.numOpenNetworks).isAtLeast(0); - assertThat(wifiLog.numHiddenNetworks).isAtLeast(0); - assertThat(wifiLog.numWificondCrashes).isAtLeast(0); - assertThat(wifiLog.numSupplicantCrashes).isAtLeast(0); - } -} diff --git a/tests/mts/src/android/net/wifi/mts/WifiFeature.java b/tests/mts/src/android/net/wifi/mts/WifiFeature.java deleted file mode 100644 index 701f38453..000000000 --- a/tests/mts/src/android/net/wifi/mts/WifiFeature.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2020 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 android.net.wifi.mts; - -import android.content.Context; -import android.content.pm.PackageManager; - -public class WifiFeature { - static boolean isWifiSupported(Context context) { - PackageManager packageManager = context.getPackageManager(); - return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI); - } - - static boolean isP2pSupported(Context context) { - PackageManager packageManager = context.getPackageManager(); - return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT); - } -} diff --git a/tests/wifitests/Android.bp b/tests/wifitests/Android.bp deleted file mode 100644 index 6c48c3b60..000000000 --- a/tests/wifitests/Android.bp +++ /dev/null @@ -1,935 +0,0 @@ -// Copyright (C) 2015 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. - -// Make test APK -// ============================================================ -android_test { - name: "FrameworksWifiTests", - - srcs: [ "**/*.java" ], - - dxflags: ["--multi-dex"], - - java_version: "1.9", - - static_libs: [ - "androidx.test.rules", - "hamcrest-library", - "mockito-target-extended-minus-junit4", - "frameworks-base-testutils", - "truth-prebuilt", - - // Statically link wifi-service-pre-jarjar since we want to test the working copy of - // service-wifi, not the on-device copy. - // Use pre-jarjar version so that we can reference symbols before they are renamed. - // Then, the jarjar_rules here will perform the rename for the entire APK - // i.e. service-wifi + test code - "wifi-service-pre-jarjar", - ], - - jarjar_rules: ":wifi-jarjar-rules", - - sdk_version: "core_platform", // tests can use @CorePlatformApi's - libs: [ - // order matters: classes in framework-wifi are resolved before framework, meaning - // @hide APIs in framework-wifi are resolved before @SystemApi stubs in framework - "framework-wifi-pre-jarjar", - "framework", - - // if sdk_version="" this gets automatically included, but here we need to add manually. - "framework-res", - - "android.test.runner", - "android.test.base", - "android.test.mock", - // load the resources from the resources APK. - "ServiceWifiResources", - ], - - // These must be explicitly included because they are not normally accessible - // from apps. - jni_libs: [ - "libbase", - "libc++", - "ld-android", - "libdl_android", - "libcgrouprc", - "libcutils", - "libnativehelper", - "libprocessgroup", - "libutils", - "libvndksupport", - "libdexmakerjvmtiagent", - "libstaticjvmtiagent", - ], - compile_multilib: "both", - - min_sdk_version: "29", - privileged: true, - test_suites: [ - "device-tests", - "mts", - ], - - // For coverage - jacoco: { - exclude_filter: [ - ], - include_filter: [ - "com.android.server.wifi.ActiveModeManager", - "com.android.server.wifi.ActiveModeManager$*", - "com.android.server.wifi.ActiveModeManager.**", - "com.android.server.wifi.ActiveModeWarden", - "com.android.server.wifi.ActiveModeWarden$*", - "com.android.server.wifi.ActiveModeWarden.**", - "com.android.server.wifi.AggressiveConnectedScore", - "com.android.server.wifi.AggressiveConnectedScore$*", - "com.android.server.wifi.AggressiveConnectedScore.**", - "com.android.server.wifi.AvailableNetworkNotifier", - "com.android.server.wifi.AvailableNetworkNotifier$*", - "com.android.server.wifi.AvailableNetworkNotifier.**", - "com.android.server.wifi.BackupManagerProxy", - "com.android.server.wifi.BackupManagerProxy$*", - "com.android.server.wifi.BackupManagerProxy.**", - "com.android.server.wifi.BaseWifiDiagnostics", - "com.android.server.wifi.BaseWifiDiagnostics$*", - "com.android.server.wifi.BaseWifiDiagnostics.**", - "com.android.server.wifi.BaseWifiService", - "com.android.server.wifi.BaseWifiService$*", - "com.android.server.wifi.BaseWifiService.**", - "com.android.server.wifi.BssidBlocklistMonitor", - "com.android.server.wifi.BssidBlocklistMonitor$*", - "com.android.server.wifi.BssidBlocklistMonitor.**", - "com.android.server.wifi.BubbleFunScorer", - "com.android.server.wifi.BubbleFunScorer$*", - "com.android.server.wifi.BubbleFunScorer.**", - "com.android.server.wifi.BuildProperties", - "com.android.server.wifi.BuildProperties$*", - "com.android.server.wifi.BuildProperties.**", - "com.android.server.wifi.ByteBufferReader", - "com.android.server.wifi.ByteBufferReader$*", - "com.android.server.wifi.ByteBufferReader.**", - "com.android.server.wifi.ClientModeImpl", - "com.android.server.wifi.ClientModeImpl$*", - "com.android.server.wifi.ClientModeImpl.**", - "com.android.server.wifi.ClientModeManager", - "com.android.server.wifi.ClientModeManager$*", - "com.android.server.wifi.ClientModeManager.**", - "com.android.server.wifi.Clock", - "com.android.server.wifi.Clock$*", - "com.android.server.wifi.Clock.**", - "com.android.server.wifi.CompatibilityScorer", - "com.android.server.wifi.CompatibilityScorer$*", - "com.android.server.wifi.CompatibilityScorer.**", - "com.android.server.wifi.ConfigurationMap", - "com.android.server.wifi.ConfigurationMap$*", - "com.android.server.wifi.ConfigurationMap.**", - "com.android.server.wifi.ConnectToNetworkNotificationBuilder", - "com.android.server.wifi.ConnectToNetworkNotificationBuilder$*", - "com.android.server.wifi.ConnectToNetworkNotificationBuilder.**", - "com.android.server.wifi.ConnectedScore", - "com.android.server.wifi.ConnectedScore$*", - "com.android.server.wifi.ConnectedScore.**", - "com.android.server.wifi.ConnectionFailureNotificationBuilder", - "com.android.server.wifi.ConnectionFailureNotificationBuilder$*", - "com.android.server.wifi.ConnectionFailureNotificationBuilder.**", - "com.android.server.wifi.ConnectionFailureNotifier", - "com.android.server.wifi.ConnectionFailureNotifier$*", - "com.android.server.wifi.ConnectionFailureNotifier.**", - "com.android.server.wifi.DefaultModeManager", - "com.android.server.wifi.DefaultModeManager$*", - "com.android.server.wifi.DefaultModeManager.**", - "com.android.server.wifi.DeviceConfigFacade", - "com.android.server.wifi.DeviceConfigFacade$*", - "com.android.server.wifi.DeviceConfigFacade.**", - "com.android.server.wifi.DppManager", - "com.android.server.wifi.DppManager$*", - "com.android.server.wifi.DppManager.**", - "com.android.server.wifi.DppMetrics", - "com.android.server.wifi.DppMetrics$*", - "com.android.server.wifi.DppMetrics.**", - "com.android.server.wifi.DummyLogMessage", - "com.android.server.wifi.DummyLogMessage$*", - "com.android.server.wifi.DummyLogMessage.**", - "com.android.server.wifi.EapFailureNotifier", - "com.android.server.wifi.EapFailureNotifier$*", - "com.android.server.wifi.EapFailureNotifier.**", - "com.android.server.wifi.ExtendedWifiInfo", - "com.android.server.wifi.ExtendedWifiInfo$*", - "com.android.server.wifi.ExtendedWifiInfo.**", - "com.android.server.wifi.FakeWifiLog", - "com.android.server.wifi.FakeWifiLog$*", - "com.android.server.wifi.FakeWifiLog.**", - "com.android.server.wifi.FrameworkFacade", - "com.android.server.wifi.FrameworkFacade$*", - "com.android.server.wifi.FrameworkFacade.**", - "com.android.server.wifi.HalDeviceManager", - "com.android.server.wifi.HalDeviceManager$*", - "com.android.server.wifi.HalDeviceManager.**", - "com.android.server.wifi.HostapdHal", - "com.android.server.wifi.HostapdHal$*", - "com.android.server.wifi.HostapdHal.**", - "com.android.server.wifi.IMSIParameter", - "com.android.server.wifi.IMSIParameter$*", - "com.android.server.wifi.IMSIParameter.**", - "com.android.server.wifi.ImsiPrivacyProtectionExemptionStoreData", - "com.android.server.wifi.ImsiPrivacyProtectionExemptionStoreData$*", - "com.android.server.wifi.ImsiPrivacyProtectionExemptionStoreData.**", - "com.android.server.wifi.LastMileLogger", - "com.android.server.wifi.LastMileLogger$*", - "com.android.server.wifi.LastMileLogger.**", - "com.android.server.wifi.LinkProbeManager", - "com.android.server.wifi.LinkProbeManager$*", - "com.android.server.wifi.LinkProbeManager.**", - "com.android.server.wifi.LocalOnlyHotspotRequestInfo", - "com.android.server.wifi.LocalOnlyHotspotRequestInfo$*", - "com.android.server.wifi.LocalOnlyHotspotRequestInfo.**", - "com.android.server.wifi.LogcatLog", - "com.android.server.wifi.LogcatLog$*", - "com.android.server.wifi.LogcatLog.**", - "com.android.server.wifi.MacAddressUtil", - "com.android.server.wifi.MacAddressUtil$*", - "com.android.server.wifi.MacAddressUtil.**", - "com.android.server.wifi.MboOceConstants", - "com.android.server.wifi.MboOceConstants$*", - "com.android.server.wifi.MboOceConstants.**", - "com.android.server.wifi.MboOceController", - "com.android.server.wifi.MboOceController$*", - "com.android.server.wifi.MboOceController.**", - "com.android.server.wifi.MemoryStoreImpl", - "com.android.server.wifi.MemoryStoreImpl$*", - "com.android.server.wifi.MemoryStoreImpl.**", - "com.android.server.wifi.NetworkListSharedStoreData", - "com.android.server.wifi.NetworkListSharedStoreData$*", - "com.android.server.wifi.NetworkListSharedStoreData.**", - "com.android.server.wifi.NetworkListStoreData", - "com.android.server.wifi.NetworkListStoreData$*", - "com.android.server.wifi.NetworkListStoreData.**", - "com.android.server.wifi.NetworkListUserStoreData", - "com.android.server.wifi.NetworkListUserStoreData$*", - "com.android.server.wifi.NetworkListUserStoreData.**", - "com.android.server.wifi.NetworkRequestStoreData", - "com.android.server.wifi.NetworkRequestStoreData$*", - "com.android.server.wifi.NetworkRequestStoreData.**", - "com.android.server.wifi.NetworkSuggestionNominator", - "com.android.server.wifi.NetworkSuggestionNominator$*", - "com.android.server.wifi.NetworkSuggestionNominator.**", - "com.android.server.wifi.NetworkSuggestionStoreData", - "com.android.server.wifi.NetworkSuggestionStoreData$*", - "com.android.server.wifi.NetworkSuggestionStoreData.**", - "com.android.server.wifi.NetworkUpdateResult", - "com.android.server.wifi.NetworkUpdateResult$*", - "com.android.server.wifi.NetworkUpdateResult.**", - "com.android.server.wifi.OpenNetworkNotifier", - "com.android.server.wifi.OpenNetworkNotifier$*", - "com.android.server.wifi.OpenNetworkNotifier.**", - "com.android.server.wifi.PropertyService", - "com.android.server.wifi.PropertyService$*", - "com.android.server.wifi.PropertyService.**", - "com.android.server.wifi.RandomizedMacStoreData", - "com.android.server.wifi.RandomizedMacStoreData$*", - "com.android.server.wifi.RandomizedMacStoreData.**", - "com.android.server.wifi.SarInfo", - "com.android.server.wifi.SarInfo$*", - "com.android.server.wifi.SarInfo.**", - "com.android.server.wifi.SarManager", - "com.android.server.wifi.SarManager$*", - "com.android.server.wifi.SarManager.**", - "com.android.server.wifi.SavedNetworkNominator", - "com.android.server.wifi.SavedNetworkNominator$*", - "com.android.server.wifi.SavedNetworkNominator.**", - "com.android.server.wifi.ScanDetail", - "com.android.server.wifi.ScanDetail$*", - "com.android.server.wifi.ScanDetail.**", - "com.android.server.wifi.ScanDetailCache", - "com.android.server.wifi.ScanDetailCache$*", - "com.android.server.wifi.ScanDetailCache.**", - "com.android.server.wifi.ScanRequestProxy", - "com.android.server.wifi.ScanRequestProxy$*", - "com.android.server.wifi.ScanRequestProxy.**", - "com.android.server.wifi.ScanResultMatchInfo", - "com.android.server.wifi.ScanResultMatchInfo$*", - "com.android.server.wifi.ScanResultMatchInfo.**", - "com.android.server.wifi.ScoreCardBasedScorer", - "com.android.server.wifi.ScoreCardBasedScorer$*", - "com.android.server.wifi.ScoreCardBasedScorer.**", - "com.android.server.wifi.ScoredNetworkNominator", - "com.android.server.wifi.ScoredNetworkNominator$*", - "com.android.server.wifi.ScoredNetworkNominator.**", - "com.android.server.wifi.ScoringParams", - "com.android.server.wifi.ScoringParams$*", - "com.android.server.wifi.ScoringParams.**", - "com.android.server.wifi.SelfRecovery", - "com.android.server.wifi.SelfRecovery$*", - "com.android.server.wifi.SelfRecovery.**", - "com.android.server.wifi.SimRequiredNotifier", - "com.android.server.wifi.SimRequiredNotifier$*", - "com.android.server.wifi.SimRequiredNotifier.**", - "com.android.server.wifi.SoftApBackupRestore", - "com.android.server.wifi.SoftApBackupRestore$*", - "com.android.server.wifi.SoftApBackupRestore.**", - "com.android.server.wifi.SoftApManager", - "com.android.server.wifi.SoftApManager$*", - "com.android.server.wifi.SoftApManager.**", - "com.android.server.wifi.SoftApModeConfiguration", - "com.android.server.wifi.SoftApModeConfiguration$*", - "com.android.server.wifi.SoftApModeConfiguration.**", - "com.android.server.wifi.SoftApNotifier", - "com.android.server.wifi.SoftApNotifier$*", - "com.android.server.wifi.SoftApNotifier.**", - "com.android.server.wifi.SoftApStoreData", - "com.android.server.wifi.SoftApStoreData$*", - "com.android.server.wifi.SoftApStoreData.**", - "com.android.server.wifi.SsidSetStoreData", - "com.android.server.wifi.SsidSetStoreData$*", - "com.android.server.wifi.SsidSetStoreData.**", - "com.android.server.wifi.StateChangeResult", - "com.android.server.wifi.StateChangeResult$*", - "com.android.server.wifi.StateChangeResult.**", - "com.android.server.wifi.SupplicantStaIfaceCallbackImpl", - "com.android.server.wifi.SupplicantStaIfaceCallbackImpl$*", - "com.android.server.wifi.SupplicantStaIfaceCallbackImpl.**", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_1Impl", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_1Impl$*", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_1Impl.**", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_2Impl", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_2Impl$*", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_2Impl.**", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_3Impl", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_3Impl$*", - "com.android.server.wifi.SupplicantStaIfaceCallbackV1_3Impl.**", - "com.android.server.wifi.SupplicantStaIfaceHal", - "com.android.server.wifi.SupplicantStaIfaceHal$*", - "com.android.server.wifi.SupplicantStaIfaceHal.**", - "com.android.server.wifi.SupplicantStaNetworkHal", - "com.android.server.wifi.SupplicantStaNetworkHal$*", - "com.android.server.wifi.SupplicantStaNetworkHal.**", - "com.android.server.wifi.SupplicantStateTracker", - "com.android.server.wifi.SupplicantStateTracker$*", - "com.android.server.wifi.SupplicantStateTracker.**", - "com.android.server.wifi.SystemBuildProperties", - "com.android.server.wifi.SystemBuildProperties$*", - "com.android.server.wifi.SystemBuildProperties.**", - "com.android.server.wifi.SystemPropertyService", - "com.android.server.wifi.SystemPropertyService$*", - "com.android.server.wifi.SystemPropertyService.**", - "com.android.server.wifi.ThroughputPredictor", - "com.android.server.wifi.ThroughputPredictor$*", - "com.android.server.wifi.ThroughputPredictor.**", - "com.android.server.wifi.ThroughputScorer", - "com.android.server.wifi.ThroughputScorer$*", - "com.android.server.wifi.ThroughputScorer.**", - "com.android.server.wifi.UntrustedWifiNetworkFactory", - "com.android.server.wifi.UntrustedWifiNetworkFactory$*", - "com.android.server.wifi.UntrustedWifiNetworkFactory.**", - "com.android.server.wifi.VelocityBasedConnectedScore", - "com.android.server.wifi.VelocityBasedConnectedScore$*", - "com.android.server.wifi.VelocityBasedConnectedScore.**", - "com.android.server.wifi.WakeupConfigStoreData", - "com.android.server.wifi.WakeupConfigStoreData$*", - "com.android.server.wifi.WakeupConfigStoreData.**", - "com.android.server.wifi.WakeupController", - "com.android.server.wifi.WakeupController$*", - "com.android.server.wifi.WakeupController.**", - "com.android.server.wifi.WakeupEvaluator", - "com.android.server.wifi.WakeupEvaluator$*", - "com.android.server.wifi.WakeupEvaluator.**", - "com.android.server.wifi.WakeupLock", - "com.android.server.wifi.WakeupLock$*", - "com.android.server.wifi.WakeupLock.**", - "com.android.server.wifi.WakeupNotificationFactory", - "com.android.server.wifi.WakeupNotificationFactory$*", - "com.android.server.wifi.WakeupNotificationFactory.**", - "com.android.server.wifi.WakeupOnboarding", - "com.android.server.wifi.WakeupOnboarding$*", - "com.android.server.wifi.WakeupOnboarding.**", - "com.android.server.wifi.WifiApConfigStore", - "com.android.server.wifi.WifiApConfigStore$*", - "com.android.server.wifi.WifiApConfigStore.**", - "com.android.server.wifi.WifiBackupDataParser", - "com.android.server.wifi.WifiBackupDataParser$*", - "com.android.server.wifi.WifiBackupDataParser.**", - "com.android.server.wifi.WifiBackupDataV1Parser", - "com.android.server.wifi.WifiBackupDataV1Parser$*", - "com.android.server.wifi.WifiBackupDataV1Parser.**", - "com.android.server.wifi.WifiBackupRestore", - "com.android.server.wifi.WifiBackupRestore$*", - "com.android.server.wifi.WifiBackupRestore.**", - "com.android.server.wifi.WifiCandidates", - "com.android.server.wifi.WifiCandidates$*", - "com.android.server.wifi.WifiCandidates.**", - "com.android.server.wifi.WifiCarrierInfoManager", - "com.android.server.wifi.WifiCarrierInfoManager$*", - "com.android.server.wifi.WifiCarrierInfoManager.**", - "com.android.server.wifi.WifiChannelUtilization", - "com.android.server.wifi.WifiChannelUtilization$*", - "com.android.server.wifi.WifiChannelUtilization.**", - "com.android.server.wifi.WifiConfigManager", - "com.android.server.wifi.WifiConfigManager$*", - "com.android.server.wifi.WifiConfigManager.**", - "com.android.server.wifi.WifiConfigStore", - "com.android.server.wifi.WifiConfigStore$*", - "com.android.server.wifi.WifiConfigStore.**", - "com.android.server.wifi.WifiConfigurationUtil", - "com.android.server.wifi.WifiConfigurationUtil$*", - "com.android.server.wifi.WifiConfigurationUtil.**", - "com.android.server.wifi.WifiConnectivityHelper", - "com.android.server.wifi.WifiConnectivityHelper$*", - "com.android.server.wifi.WifiConnectivityHelper.**", - "com.android.server.wifi.WifiConnectivityManager", - "com.android.server.wifi.WifiConnectivityManager$*", - "com.android.server.wifi.WifiConnectivityManager.**", - "com.android.server.wifi.WifiContext", - "com.android.server.wifi.WifiContext$*", - "com.android.server.wifi.WifiContext.**", - "com.android.server.wifi.WifiCountryCode", - "com.android.server.wifi.WifiCountryCode$*", - "com.android.server.wifi.WifiCountryCode.**", - "com.android.server.wifi.WifiDataStall", - "com.android.server.wifi.WifiDataStall$*", - "com.android.server.wifi.WifiDataStall.**", - "com.android.server.wifi.WifiDiagnostics", - "com.android.server.wifi.WifiDiagnostics$*", - "com.android.server.wifi.WifiDiagnostics.**", - "com.android.server.wifi.WifiHealthMonitor", - "com.android.server.wifi.WifiHealthMonitor$*", - "com.android.server.wifi.WifiHealthMonitor.**", - "com.android.server.wifi.WifiInjector", - "com.android.server.wifi.WifiInjector$*", - "com.android.server.wifi.WifiInjector.**", - "com.android.server.wifi.WifiKeyStore", - "com.android.server.wifi.WifiKeyStore$*", - "com.android.server.wifi.WifiKeyStore.**", - "com.android.server.wifi.WifiLastResortWatchdog", - "com.android.server.wifi.WifiLastResortWatchdog$*", - "com.android.server.wifi.WifiLastResortWatchdog.**", - "com.android.server.wifi.WifiLinkLayerStats", - "com.android.server.wifi.WifiLinkLayerStats$*", - "com.android.server.wifi.WifiLinkLayerStats.**", - "com.android.server.wifi.WifiLockManager", - "com.android.server.wifi.WifiLockManager$*", - "com.android.server.wifi.WifiLockManager.**", - "com.android.server.wifi.WifiLog", - "com.android.server.wifi.WifiLog$*", - "com.android.server.wifi.WifiLog.**", - "com.android.server.wifi.WifiLoggerHal", - "com.android.server.wifi.WifiLoggerHal$*", - "com.android.server.wifi.WifiLoggerHal.**", - "com.android.server.wifi.WifiMetrics", - "com.android.server.wifi.WifiMetrics$*", - "com.android.server.wifi.WifiMetrics.**", - "com.android.server.wifi.WifiMonitor", - "com.android.server.wifi.WifiMonitor$*", - "com.android.server.wifi.WifiMonitor.**", - "com.android.server.wifi.WifiMulticastLockManager", - "com.android.server.wifi.WifiMulticastLockManager$*", - "com.android.server.wifi.WifiMulticastLockManager.**", - "com.android.server.wifi.WifiNative", - "com.android.server.wifi.WifiNative$*", - "com.android.server.wifi.WifiNative.**", - "com.android.server.wifi.WifiNetworkFactory", - "com.android.server.wifi.WifiNetworkFactory$*", - "com.android.server.wifi.WifiNetworkFactory.**", - "com.android.server.wifi.WifiNetworkScoreCache", - "com.android.server.wifi.WifiNetworkScoreCache$*", - "com.android.server.wifi.WifiNetworkScoreCache.**", - "com.android.server.wifi.WifiNetworkSelector", - "com.android.server.wifi.WifiNetworkSelector$*", - "com.android.server.wifi.WifiNetworkSelector.**", - "com.android.server.wifi.WifiNetworkSuggestionsManager", - "com.android.server.wifi.WifiNetworkSuggestionsManager$*", - "com.android.server.wifi.WifiNetworkSuggestionsManager.**", - "com.android.server.wifi.WifiPowerMetrics", - "com.android.server.wifi.WifiPowerMetrics$*", - "com.android.server.wifi.WifiPowerMetrics.**", - "com.android.server.wifi.WifiScanAlwaysAvailableSettingsCompatibility", - "com.android.server.wifi.WifiScanAlwaysAvailableSettingsCompatibility$*", - "com.android.server.wifi.WifiScanAlwaysAvailableSettingsCompatibility.**", - "com.android.server.wifi.WifiScoreCard", - "com.android.server.wifi.WifiScoreCard$*", - "com.android.server.wifi.WifiScoreCard.**", - "com.android.server.wifi.WifiScoreReport", - "com.android.server.wifi.WifiScoreReport$*", - "com.android.server.wifi.WifiScoreReport.**", - "com.android.server.wifi.WifiService", - "com.android.server.wifi.WifiService$*", - "com.android.server.wifi.WifiService.**", - "com.android.server.wifi.WifiServiceImpl", - "com.android.server.wifi.WifiServiceImpl$*", - "com.android.server.wifi.WifiServiceImpl.**", - "com.android.server.wifi.WifiSettingsConfigStore", - "com.android.server.wifi.WifiSettingsConfigStore$*", - "com.android.server.wifi.WifiSettingsConfigStore.**", - "com.android.server.wifi.WifiSettingsStore", - "com.android.server.wifi.WifiSettingsStore$*", - "com.android.server.wifi.WifiSettingsStore.**", - "com.android.server.wifi.WifiShellCommand", - "com.android.server.wifi.WifiShellCommand$*", - "com.android.server.wifi.WifiShellCommand.**", - "com.android.server.wifi.WifiStateTracker", - "com.android.server.wifi.WifiStateTracker$*", - "com.android.server.wifi.WifiStateTracker.**", - "com.android.server.wifi.WifiThreadRunner", - "com.android.server.wifi.WifiThreadRunner$*", - "com.android.server.wifi.WifiThreadRunner.**", - "com.android.server.wifi.WifiTrafficPoller", - "com.android.server.wifi.WifiTrafficPoller$*", - "com.android.server.wifi.WifiTrafficPoller.**", - "com.android.server.wifi.WifiVendorHal", - "com.android.server.wifi.WifiVendorHal$*", - "com.android.server.wifi.WifiVendorHal.**", - "com.android.server.wifi.WifiWakeMetrics", - "com.android.server.wifi.WifiWakeMetrics$*", - "com.android.server.wifi.WifiWakeMetrics.**", - "com.android.server.wifi.WlanWakeReasonAndCounts", - "com.android.server.wifi.WlanWakeReasonAndCounts$*", - "com.android.server.wifi.WlanWakeReasonAndCounts.**", - "com.android.server.wifi.WrongPasswordNotifier", - "com.android.server.wifi.WrongPasswordNotifier$*", - "com.android.server.wifi.WrongPasswordNotifier.**", - "com.android.server.wifi.aware.Capabilities", - "com.android.server.wifi.aware.Capabilities$*", - "com.android.server.wifi.aware.Capabilities.**", - "com.android.server.wifi.aware.WifiAwareClientState", - "com.android.server.wifi.aware.WifiAwareClientState$*", - "com.android.server.wifi.aware.WifiAwareClientState.**", - "com.android.server.wifi.aware.WifiAwareDataPathStateManager", - "com.android.server.wifi.aware.WifiAwareDataPathStateManager$*", - "com.android.server.wifi.aware.WifiAwareDataPathStateManager.**", - "com.android.server.wifi.aware.WifiAwareDiscoverySessionState", - "com.android.server.wifi.aware.WifiAwareDiscoverySessionState$*", - "com.android.server.wifi.aware.WifiAwareDiscoverySessionState.**", - "com.android.server.wifi.aware.WifiAwareMetrics", - "com.android.server.wifi.aware.WifiAwareMetrics$*", - "com.android.server.wifi.aware.WifiAwareMetrics.**", - "com.android.server.wifi.aware.WifiAwareNativeApi", - "com.android.server.wifi.aware.WifiAwareNativeApi$*", - "com.android.server.wifi.aware.WifiAwareNativeApi.**", - "com.android.server.wifi.aware.WifiAwareNativeCallback", - "com.android.server.wifi.aware.WifiAwareNativeCallback$*", - "com.android.server.wifi.aware.WifiAwareNativeCallback.**", - "com.android.server.wifi.aware.WifiAwareNativeManager", - "com.android.server.wifi.aware.WifiAwareNativeManager$*", - "com.android.server.wifi.aware.WifiAwareNativeManager.**", - "com.android.server.wifi.aware.WifiAwareService", - "com.android.server.wifi.aware.WifiAwareService$*", - "com.android.server.wifi.aware.WifiAwareService.**", - "com.android.server.wifi.aware.WifiAwareServiceImpl", - "com.android.server.wifi.aware.WifiAwareServiceImpl$*", - "com.android.server.wifi.aware.WifiAwareServiceImpl.**", - "com.android.server.wifi.aware.WifiAwareShellCommand", - "com.android.server.wifi.aware.WifiAwareShellCommand$*", - "com.android.server.wifi.aware.WifiAwareShellCommand.**", - "com.android.server.wifi.aware.WifiAwareStateManager", - "com.android.server.wifi.aware.WifiAwareStateManager$*", - "com.android.server.wifi.aware.WifiAwareStateManager.**", - "com.android.server.wifi.hotspot2.ANQPData", - "com.android.server.wifi.hotspot2.ANQPData$*", - "com.android.server.wifi.hotspot2.ANQPData.**", - "com.android.server.wifi.hotspot2.ANQPMatcher", - "com.android.server.wifi.hotspot2.ANQPMatcher$*", - "com.android.server.wifi.hotspot2.ANQPMatcher.**", - "com.android.server.wifi.hotspot2.ANQPNetworkKey", - "com.android.server.wifi.hotspot2.ANQPNetworkKey$*", - "com.android.server.wifi.hotspot2.ANQPNetworkKey.**", - "com.android.server.wifi.hotspot2.ANQPRequestManager", - "com.android.server.wifi.hotspot2.ANQPRequestManager$*", - "com.android.server.wifi.hotspot2.ANQPRequestManager.**", - "com.android.server.wifi.hotspot2.AnqpCache", - "com.android.server.wifi.hotspot2.AnqpCache$*", - "com.android.server.wifi.hotspot2.AnqpCache.**", - "com.android.server.wifi.hotspot2.AnqpEvent", - "com.android.server.wifi.hotspot2.AnqpEvent$*", - "com.android.server.wifi.hotspot2.AnqpEvent.**", - "com.android.server.wifi.hotspot2.DomainMatcher", - "com.android.server.wifi.hotspot2.DomainMatcher$*", - "com.android.server.wifi.hotspot2.DomainMatcher.**", - "com.android.server.wifi.hotspot2.IconEvent", - "com.android.server.wifi.hotspot2.IconEvent$*", - "com.android.server.wifi.hotspot2.IconEvent.**", - "com.android.server.wifi.hotspot2.LegacyPasspointConfig", - "com.android.server.wifi.hotspot2.LegacyPasspointConfig$*", - "com.android.server.wifi.hotspot2.LegacyPasspointConfig.**", - "com.android.server.wifi.hotspot2.NetworkDetail", - "com.android.server.wifi.hotspot2.NetworkDetail$*", - "com.android.server.wifi.hotspot2.NetworkDetail.**", - "com.android.server.wifi.hotspot2.OsuNetworkConnection", - "com.android.server.wifi.hotspot2.OsuNetworkConnection$*", - "com.android.server.wifi.hotspot2.OsuNetworkConnection.**", - "com.android.server.wifi.hotspot2.OsuServerConnection", - "com.android.server.wifi.hotspot2.OsuServerConnection$*", - "com.android.server.wifi.hotspot2.OsuServerConnection.**", - "com.android.server.wifi.hotspot2.PasspointConfigSharedStoreData", - "com.android.server.wifi.hotspot2.PasspointConfigSharedStoreData$*", - "com.android.server.wifi.hotspot2.PasspointConfigSharedStoreData.**", - "com.android.server.wifi.hotspot2.PasspointConfigUserStoreData", - "com.android.server.wifi.hotspot2.PasspointConfigUserStoreData$*", - "com.android.server.wifi.hotspot2.PasspointConfigUserStoreData.**", - "com.android.server.wifi.hotspot2.PasspointEventHandler", - "com.android.server.wifi.hotspot2.PasspointEventHandler$*", - "com.android.server.wifi.hotspot2.PasspointEventHandler.**", - "com.android.server.wifi.hotspot2.PasspointManager", - "com.android.server.wifi.hotspot2.PasspointManager$*", - "com.android.server.wifi.hotspot2.PasspointManager.**", - "com.android.server.wifi.hotspot2.PasspointMatch", - "com.android.server.wifi.hotspot2.PasspointMatch$*", - "com.android.server.wifi.hotspot2.PasspointMatch.**", - "com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper", - "com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper$*", - "com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper.**", - "com.android.server.wifi.hotspot2.PasspointObjectFactory", - "com.android.server.wifi.hotspot2.PasspointObjectFactory$*", - "com.android.server.wifi.hotspot2.PasspointObjectFactory.**", - "com.android.server.wifi.hotspot2.PasspointProvider", - "com.android.server.wifi.hotspot2.PasspointProvider$*", - "com.android.server.wifi.hotspot2.PasspointProvider.**", - "com.android.server.wifi.hotspot2.PasspointProvisioner", - "com.android.server.wifi.hotspot2.PasspointProvisioner$*", - "com.android.server.wifi.hotspot2.PasspointProvisioner.**", - "com.android.server.wifi.hotspot2.PasspointXmlUtils", - "com.android.server.wifi.hotspot2.PasspointXmlUtils$*", - "com.android.server.wifi.hotspot2.PasspointXmlUtils.**", - "com.android.server.wifi.hotspot2.ServiceProviderVerifier", - "com.android.server.wifi.hotspot2.ServiceProviderVerifier$*", - "com.android.server.wifi.hotspot2.ServiceProviderVerifier.**", - "com.android.server.wifi.hotspot2.SystemInfo", - "com.android.server.wifi.hotspot2.SystemInfo$*", - "com.android.server.wifi.hotspot2.SystemInfo.**", - "com.android.server.wifi.hotspot2.Utils", - "com.android.server.wifi.hotspot2.Utils$*", - "com.android.server.wifi.hotspot2.Utils.**", - "com.android.server.wifi.hotspot2.WfaCertBuilder", - "com.android.server.wifi.hotspot2.WfaCertBuilder$*", - "com.android.server.wifi.hotspot2.WfaCertBuilder.**", - "com.android.server.wifi.hotspot2.WfaKeyStore", - "com.android.server.wifi.hotspot2.WfaKeyStore$*", - "com.android.server.wifi.hotspot2.WfaKeyStore.**", - "com.android.server.wifi.hotspot2.WnmData", - "com.android.server.wifi.hotspot2.WnmData$*", - "com.android.server.wifi.hotspot2.WnmData.**", - "com.android.server.wifi.hotspot2.anqp.ANQPElement", - "com.android.server.wifi.hotspot2.anqp.ANQPElement$*", - "com.android.server.wifi.hotspot2.anqp.ANQPElement.**", - "com.android.server.wifi.hotspot2.anqp.ANQPParser", - "com.android.server.wifi.hotspot2.anqp.ANQPParser$*", - "com.android.server.wifi.hotspot2.anqp.ANQPParser.**", - "com.android.server.wifi.hotspot2.anqp.CellularNetwork", - "com.android.server.wifi.hotspot2.anqp.CellularNetwork$*", - "com.android.server.wifi.hotspot2.anqp.CellularNetwork.**", - "com.android.server.wifi.hotspot2.anqp.Constants", - "com.android.server.wifi.hotspot2.anqp.Constants$*", - "com.android.server.wifi.hotspot2.anqp.Constants.**", - "com.android.server.wifi.hotspot2.anqp.DomainNameElement", - "com.android.server.wifi.hotspot2.anqp.DomainNameElement$*", - "com.android.server.wifi.hotspot2.anqp.DomainNameElement.**", - "com.android.server.wifi.hotspot2.anqp.GenericBlobElement", - "com.android.server.wifi.hotspot2.anqp.GenericBlobElement$*", - "com.android.server.wifi.hotspot2.anqp.GenericBlobElement.**", - "com.android.server.wifi.hotspot2.anqp.HSConnectionCapabilityElement", - "com.android.server.wifi.hotspot2.anqp.HSConnectionCapabilityElement$*", - "com.android.server.wifi.hotspot2.anqp.HSConnectionCapabilityElement.**", - "com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement", - "com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement$*", - "com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement.**", - "com.android.server.wifi.hotspot2.anqp.HSIconFileElement", - "com.android.server.wifi.hotspot2.anqp.HSIconFileElement$*", - "com.android.server.wifi.hotspot2.anqp.HSIconFileElement.**", - "com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement", - "com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement$*", - "com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement.**", - "com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement", - "com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement$*", - "com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement.**", - "com.android.server.wifi.hotspot2.anqp.I18Name", - "com.android.server.wifi.hotspot2.anqp.I18Name$*", - "com.android.server.wifi.hotspot2.anqp.I18Name.**", - "com.android.server.wifi.hotspot2.anqp.IPAddressTypeAvailabilityElement", - "com.android.server.wifi.hotspot2.anqp.IPAddressTypeAvailabilityElement$*", - "com.android.server.wifi.hotspot2.anqp.IPAddressTypeAvailabilityElement.**", - "com.android.server.wifi.hotspot2.anqp.IconInfo", - "com.android.server.wifi.hotspot2.anqp.IconInfo$*", - "com.android.server.wifi.hotspot2.anqp.IconInfo.**", - "com.android.server.wifi.hotspot2.anqp.NAIRealmData", - "com.android.server.wifi.hotspot2.anqp.NAIRealmData$*", - "com.android.server.wifi.hotspot2.anqp.NAIRealmData.**", - "com.android.server.wifi.hotspot2.anqp.NAIRealmElement", - "com.android.server.wifi.hotspot2.anqp.NAIRealmElement$*", - "com.android.server.wifi.hotspot2.anqp.NAIRealmElement.**", - "com.android.server.wifi.hotspot2.anqp.OsuProviderInfo", - "com.android.server.wifi.hotspot2.anqp.OsuProviderInfo$*", - "com.android.server.wifi.hotspot2.anqp.OsuProviderInfo.**", - "com.android.server.wifi.hotspot2.anqp.ProtocolPortTuple", - "com.android.server.wifi.hotspot2.anqp.ProtocolPortTuple$*", - "com.android.server.wifi.hotspot2.anqp.ProtocolPortTuple.**", - "com.android.server.wifi.hotspot2.anqp.RawByteElement", - "com.android.server.wifi.hotspot2.anqp.RawByteElement$*", - "com.android.server.wifi.hotspot2.anqp.RawByteElement.**", - "com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement", - "com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement$*", - "com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement.**", - "com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement", - "com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement$*", - "com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement.**", - "com.android.server.wifi.hotspot2.anqp.VenueNameElement", - "com.android.server.wifi.hotspot2.anqp.VenueNameElement$*", - "com.android.server.wifi.hotspot2.anqp.VenueNameElement.**", - "com.android.server.wifi.hotspot2.anqp.eap.AuthParam", - "com.android.server.wifi.hotspot2.anqp.eap.AuthParam$*", - "com.android.server.wifi.hotspot2.anqp.eap.AuthParam.**", - "com.android.server.wifi.hotspot2.anqp.eap.CredentialType", - "com.android.server.wifi.hotspot2.anqp.eap.CredentialType$*", - "com.android.server.wifi.hotspot2.anqp.eap.CredentialType.**", - "com.android.server.wifi.hotspot2.anqp.eap.EAPMethod", - "com.android.server.wifi.hotspot2.anqp.eap.EAPMethod$*", - "com.android.server.wifi.hotspot2.anqp.eap.EAPMethod.**", - "com.android.server.wifi.hotspot2.anqp.eap.ExpandedEAPMethod", - "com.android.server.wifi.hotspot2.anqp.eap.ExpandedEAPMethod$*", - "com.android.server.wifi.hotspot2.anqp.eap.ExpandedEAPMethod.**", - "com.android.server.wifi.hotspot2.anqp.eap.InnerAuthEAP", - "com.android.server.wifi.hotspot2.anqp.eap.InnerAuthEAP$*", - "com.android.server.wifi.hotspot2.anqp.eap.InnerAuthEAP.**", - "com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth", - "com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth$*", - "com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth.**", - "com.android.server.wifi.hotspot2.anqp.eap.VendorSpecificAuth", - "com.android.server.wifi.hotspot2.anqp.eap.VendorSpecificAuth$*", - "com.android.server.wifi.hotspot2.anqp.eap.VendorSpecificAuth.**", - "com.android.server.wifi.hotspot2.omadm.DevDetailMo", - "com.android.server.wifi.hotspot2.omadm.DevDetailMo$*", - "com.android.server.wifi.hotspot2.omadm.DevDetailMo.**", - "com.android.server.wifi.hotspot2.omadm.DevInfoMo", - "com.android.server.wifi.hotspot2.omadm.DevInfoMo$*", - "com.android.server.wifi.hotspot2.omadm.DevInfoMo.**", - "com.android.server.wifi.hotspot2.omadm.MoSerializer", - "com.android.server.wifi.hotspot2.omadm.MoSerializer$*", - "com.android.server.wifi.hotspot2.omadm.MoSerializer.**", - "com.android.server.wifi.hotspot2.soap.ExchangeCompleteMessage", - "com.android.server.wifi.hotspot2.soap.ExchangeCompleteMessage$*", - "com.android.server.wifi.hotspot2.soap.ExchangeCompleteMessage.**", - "com.android.server.wifi.hotspot2.soap.HttpsServiceConnection", - "com.android.server.wifi.hotspot2.soap.HttpsServiceConnection$*", - "com.android.server.wifi.hotspot2.soap.HttpsServiceConnection.**", - "com.android.server.wifi.hotspot2.soap.HttpsTransport", - "com.android.server.wifi.hotspot2.soap.HttpsTransport$*", - "com.android.server.wifi.hotspot2.soap.HttpsTransport.**", - "com.android.server.wifi.hotspot2.soap.PostDevDataMessage", - "com.android.server.wifi.hotspot2.soap.PostDevDataMessage$*", - "com.android.server.wifi.hotspot2.soap.PostDevDataMessage.**", - "com.android.server.wifi.hotspot2.soap.PostDevDataResponse", - "com.android.server.wifi.hotspot2.soap.PostDevDataResponse$*", - "com.android.server.wifi.hotspot2.soap.PostDevDataResponse.**", - "com.android.server.wifi.hotspot2.soap.RedirectListener", - "com.android.server.wifi.hotspot2.soap.RedirectListener$*", - "com.android.server.wifi.hotspot2.soap.RedirectListener.**", - "com.android.server.wifi.hotspot2.soap.SoapParser", - "com.android.server.wifi.hotspot2.soap.SoapParser$*", - "com.android.server.wifi.hotspot2.soap.SoapParser.**", - "com.android.server.wifi.hotspot2.soap.SppConstants", - "com.android.server.wifi.hotspot2.soap.SppConstants$*", - "com.android.server.wifi.hotspot2.soap.SppConstants.**", - "com.android.server.wifi.hotspot2.soap.SppResponseMessage", - "com.android.server.wifi.hotspot2.soap.SppResponseMessage$*", - "com.android.server.wifi.hotspot2.soap.SppResponseMessage.**", - "com.android.server.wifi.hotspot2.soap.UpdateResponseMessage", - "com.android.server.wifi.hotspot2.soap.UpdateResponseMessage$*", - "com.android.server.wifi.hotspot2.soap.UpdateResponseMessage.**", - "com.android.server.wifi.hotspot2.soap.command.BrowserUri", - "com.android.server.wifi.hotspot2.soap.command.BrowserUri$*", - "com.android.server.wifi.hotspot2.soap.command.BrowserUri.**", - "com.android.server.wifi.hotspot2.soap.command.PpsMoData", - "com.android.server.wifi.hotspot2.soap.command.PpsMoData$*", - "com.android.server.wifi.hotspot2.soap.command.PpsMoData.**", - "com.android.server.wifi.hotspot2.soap.command.SppCommand", - "com.android.server.wifi.hotspot2.soap.command.SppCommand$*", - "com.android.server.wifi.hotspot2.soap.command.SppCommand.**", - "com.android.server.wifi.p2p.SupplicantP2pIfaceCallback", - "com.android.server.wifi.p2p.SupplicantP2pIfaceCallback$*", - "com.android.server.wifi.p2p.SupplicantP2pIfaceCallback.**", - "com.android.server.wifi.p2p.SupplicantP2pIfaceHal", - "com.android.server.wifi.p2p.SupplicantP2pIfaceHal$*", - "com.android.server.wifi.p2p.SupplicantP2pIfaceHal.**", - "com.android.server.wifi.p2p.WifiP2pMetrics", - "com.android.server.wifi.p2p.WifiP2pMetrics$*", - "com.android.server.wifi.p2p.WifiP2pMetrics.**", - "com.android.server.wifi.p2p.WifiP2pMonitor", - "com.android.server.wifi.p2p.WifiP2pMonitor$*", - "com.android.server.wifi.p2p.WifiP2pMonitor.**", - "com.android.server.wifi.p2p.WifiP2pNative", - "com.android.server.wifi.p2p.WifiP2pNative$*", - "com.android.server.wifi.p2p.WifiP2pNative.**", - "com.android.server.wifi.p2p.WifiP2pService", - "com.android.server.wifi.p2p.WifiP2pService$*", - "com.android.server.wifi.p2p.WifiP2pService.**", - "com.android.server.wifi.p2p.WifiP2pServiceImpl", - "com.android.server.wifi.p2p.WifiP2pServiceImpl$*", - "com.android.server.wifi.p2p.WifiP2pServiceImpl.**", - "com.android.server.wifi.rtt.RttMetrics", - "com.android.server.wifi.rtt.RttMetrics$*", - "com.android.server.wifi.rtt.RttMetrics.**", - "com.android.server.wifi.rtt.RttNative", - "com.android.server.wifi.rtt.RttNative$*", - "com.android.server.wifi.rtt.RttNative.**", - "com.android.server.wifi.rtt.RttService", - "com.android.server.wifi.rtt.RttService$*", - "com.android.server.wifi.rtt.RttService.**", - "com.android.server.wifi.rtt.RttServiceImpl", - "com.android.server.wifi.rtt.RttServiceImpl$*", - "com.android.server.wifi.rtt.RttServiceImpl.**", - "com.android.server.wifi.scanner.BackgroundScanScheduler", - "com.android.server.wifi.scanner.BackgroundScanScheduler$*", - "com.android.server.wifi.scanner.BackgroundScanScheduler.**", - "com.android.server.wifi.scanner.ChannelHelper", - "com.android.server.wifi.scanner.ChannelHelper$*", - "com.android.server.wifi.scanner.ChannelHelper.**", - "com.android.server.wifi.scanner.HalWifiScannerImpl", - "com.android.server.wifi.scanner.HalWifiScannerImpl$*", - "com.android.server.wifi.scanner.HalWifiScannerImpl.**", - "com.android.server.wifi.scanner.KnownBandsChannelHelper", - "com.android.server.wifi.scanner.KnownBandsChannelHelper$*", - "com.android.server.wifi.scanner.KnownBandsChannelHelper.**", - "com.android.server.wifi.scanner.PresetKnownBandsChannelHelper", - "com.android.server.wifi.scanner.PresetKnownBandsChannelHelper$*", - "com.android.server.wifi.scanner.PresetKnownBandsChannelHelper.**", - "com.android.server.wifi.scanner.ScanScheduleUtil", - "com.android.server.wifi.scanner.ScanScheduleUtil$*", - "com.android.server.wifi.scanner.ScanScheduleUtil.**", - "com.android.server.wifi.scanner.WifiScannerImpl", - "com.android.server.wifi.scanner.WifiScannerImpl$*", - "com.android.server.wifi.scanner.WifiScannerImpl.**", - "com.android.server.wifi.scanner.WifiScanningService", - "com.android.server.wifi.scanner.WifiScanningService$*", - "com.android.server.wifi.scanner.WifiScanningService.**", - "com.android.server.wifi.scanner.WifiScanningServiceImpl", - "com.android.server.wifi.scanner.WifiScanningServiceImpl$*", - "com.android.server.wifi.scanner.WifiScanningServiceImpl.**", - "com.android.server.wifi.scanner.WificondChannelHelper", - "com.android.server.wifi.scanner.WificondChannelHelper$*", - "com.android.server.wifi.scanner.WificondChannelHelper.**", - "com.android.server.wifi.scanner.WificondScannerImpl", - "com.android.server.wifi.scanner.WificondScannerImpl$*", - "com.android.server.wifi.scanner.WificondScannerImpl.**", - "com.android.server.wifi.util.ApConfigUtil", - "com.android.server.wifi.util.ApConfigUtil$*", - "com.android.server.wifi.util.ApConfigUtil.**", - "com.android.server.wifi.util.ArrayUtils", - "com.android.server.wifi.util.ArrayUtils$*", - "com.android.server.wifi.util.ArrayUtils.**", - "com.android.server.wifi.util.BitMask", - "com.android.server.wifi.util.BitMask$*", - "com.android.server.wifi.util.BitMask.**", - "com.android.server.wifi.util.ByteArrayRingBuffer", - "com.android.server.wifi.util.ByteArrayRingBuffer$*", - "com.android.server.wifi.util.ByteArrayRingBuffer.**", - "com.android.server.wifi.util.EncryptedData", - "com.android.server.wifi.util.EncryptedData$*", - "com.android.server.wifi.util.EncryptedData.**", - "com.android.server.wifi.util.Environment", - "com.android.server.wifi.util.Environment$*", - "com.android.server.wifi.util.Environment.**", - "com.android.server.wifi.util.ExternalCallbackTracker", - "com.android.server.wifi.util.ExternalCallbackTracker$*", - "com.android.server.wifi.util.ExternalCallbackTracker.**", - "com.android.server.wifi.util.FileUtils", - "com.android.server.wifi.util.FileUtils$*", - "com.android.server.wifi.util.FileUtils.**", - "com.android.server.wifi.util.FrameParser", - "com.android.server.wifi.util.FrameParser$*", - "com.android.server.wifi.util.FrameParser.**", - "com.android.server.wifi.util.GeneralUtil", - "com.android.server.wifi.util.GeneralUtil$*", - "com.android.server.wifi.util.GeneralUtil.**", - "com.android.server.wifi.util.InformationElementUtil", - "com.android.server.wifi.util.InformationElementUtil$*", - "com.android.server.wifi.util.InformationElementUtil.**", - "com.android.server.wifi.util.IntCounter", - "com.android.server.wifi.util.IntCounter$*", - "com.android.server.wifi.util.IntCounter.**", - "com.android.server.wifi.util.IntHistogram", - "com.android.server.wifi.util.IntHistogram$*", - "com.android.server.wifi.util.IntHistogram.**", - "com.android.server.wifi.util.IpConfigStore", - "com.android.server.wifi.util.IpConfigStore$*", - "com.android.server.wifi.util.IpConfigStore.**", - "com.android.server.wifi.util.KalmanFilter", - "com.android.server.wifi.util.KalmanFilter$*", - "com.android.server.wifi.util.KalmanFilter.**", - "com.android.server.wifi.util.KeyValueListParser", - "com.android.server.wifi.util.KeyValueListParser$*", - "com.android.server.wifi.util.KeyValueListParser.**", - "com.android.server.wifi.util.LruConnectionTracker", - "com.android.server.wifi.util.LruConnectionTracker$*", - "com.android.server.wifi.util.LruConnectionTracker.**", - "com.android.server.wifi.util.LruList", - "com.android.server.wifi.util.LruList$*", - "com.android.server.wifi.util.LruList.**", - "com.android.server.wifi.util.Matrix", - "com.android.server.wifi.util.Matrix$*", - "com.android.server.wifi.util.Matrix.**", - "com.android.server.wifi.util.MetricsUtils", - "com.android.server.wifi.util.MetricsUtils$*", - "com.android.server.wifi.util.MetricsUtils.**", - "com.android.server.wifi.util.MissingCounterTimerLockList", - "com.android.server.wifi.util.MissingCounterTimerLockList$*", - "com.android.server.wifi.util.MissingCounterTimerLockList.**", - "com.android.server.wifi.util.NativeUtil", - "com.android.server.wifi.util.NativeUtil$*", - "com.android.server.wifi.util.NativeUtil.**", - "com.android.server.wifi.util.NetdWrapper", - "com.android.server.wifi.util.NetdWrapper$*", - "com.android.server.wifi.util.NetdWrapper.**", - "com.android.server.wifi.util.ObjectCounter", - "com.android.server.wifi.util.ObjectCounter$*", - "com.android.server.wifi.util.ObjectCounter.**", - "com.android.server.wifi.util.RssiUtil", - "com.android.server.wifi.util.RssiUtil$*", - "com.android.server.wifi.util.RssiUtil.**", - "com.android.server.wifi.util.ScanResultUtil", - "com.android.server.wifi.util.ScanResultUtil$*", - "com.android.server.wifi.util.ScanResultUtil.**", - "com.android.server.wifi.util.SettingsMigrationDataHolder", - "com.android.server.wifi.util.SettingsMigrationDataHolder$*", - "com.android.server.wifi.util.SettingsMigrationDataHolder.**", - "com.android.server.wifi.util.StringUtil", - "com.android.server.wifi.util.StringUtil$*", - "com.android.server.wifi.util.StringUtil.**", - "com.android.server.wifi.util.TimedQuotaManager", - "com.android.server.wifi.util.TimedQuotaManager$*", - "com.android.server.wifi.util.TimedQuotaManager.**", - "com.android.server.wifi.util.WifiAsyncChannel", - "com.android.server.wifi.util.WifiAsyncChannel$*", - "com.android.server.wifi.util.WifiAsyncChannel.**", - "com.android.server.wifi.util.WifiConfigStoreEncryptionUtil", - "com.android.server.wifi.util.WifiConfigStoreEncryptionUtil$*", - "com.android.server.wifi.util.WifiConfigStoreEncryptionUtil.**", - "com.android.server.wifi.util.WifiHandler", - "com.android.server.wifi.util.WifiHandler$*", - "com.android.server.wifi.util.WifiHandler.**", - "com.android.server.wifi.util.WifiPermissionsUtil", - "com.android.server.wifi.util.WifiPermissionsUtil$*", - "com.android.server.wifi.util.WifiPermissionsUtil.**", - "com.android.server.wifi.util.WifiPermissionsWrapper", - "com.android.server.wifi.util.WifiPermissionsWrapper$*", - "com.android.server.wifi.util.WifiPermissionsWrapper.**", - "com.android.server.wifi.util.WorkSourceUtil", - "com.android.server.wifi.util.WorkSourceUtil$*", - "com.android.server.wifi.util.WorkSourceUtil.**", - "com.android.server.wifi.util.XmlUtil", - "com.android.server.wifi.util.XmlUtil$*", - "com.android.server.wifi.util.XmlUtil.**", - "com.android.server.wifi.util.XmlUtilHelper", - "com.android.server.wifi.util.XmlUtilHelper$*", - "com.android.server.wifi.util.XmlUtilHelper.**", - ], - }, -} diff --git a/tests/wifitests/AndroidManifest.xml b/tests/wifitests/AndroidManifest.xml deleted file mode 100644 index 31eaac900..000000000 --- a/tests/wifitests/AndroidManifest.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - ~ Copyright (C) 2015 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 - --> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.server.wifi.test"> - - <application - android:debuggable="true" - android:largeHeap="true"> - <uses-library android:name="android.test.runner" /> - <activity android:label="WifiTestDummyLabel" - android:name="WifiTestDummyName"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER"/> - </intent-filter> - </activity> - </application> - - <instrumentation android:name="com.android.server.wifi.CustomTestRunner" - android:targetPackage="com.android.server.wifi.test" - android:label="Frameworks Wifi Tests"> - </instrumentation> - - <uses-permission android:name="android.permission.READ_PHONE_STATE" /> - <uses-permission android:name="android.permission.INTERNET" /> - -</manifest> diff --git a/tests/wifitests/AndroidTest.xml b/tests/wifitests/AndroidTest.xml deleted file mode 100644 index f904a4436..000000000 --- a/tests/wifitests/AndroidTest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 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. ---> -<configuration description="Runs Frameworks Wifi Tests."> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="test-file-name" value="FrameworksWifiTests.apk" /> - </target_preparer> - - <option name="test-suite-tag" value="apct" /> - <option name="test-tag" value="FrameworksWifiTests" /> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="com.android.server.wifi.test" /> - <option name="runner" value="com.android.server.wifi.CustomTestRunner" /> - <option name="hidden-api-checks" value="false"/> - </test> - - <!-- Only run FrameworksWifiTests in MTS if the Wifi Mainline module is installed. --> - <object type="module_controller" - class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.google.android.wifi" /> - </object> -</configuration> diff --git a/tests/wifitests/README.md b/tests/wifitests/README.md deleted file mode 100644 index 8908fcd77..000000000 --- a/tests/wifitests/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Wifi Unit Tests -This package contains unit tests for the android wifi service based on the -[Android Testing Support Library](http://developer.android.com/tools/testing-support-library/index.html). -The test cases are built using the [JUnit](http://junit.org/) and [Mockito](http://mockito.org/) -libraries. - -## Running Tests -The easiest way to run tests is simply run - -``` -atest com.android.server.wifi -``` - -## Adding Tests -Tests can be added by adding classes to the src directory. JUnit4 style test cases can -be written by simply annotating test methods with `org.junit.Test`. - -## Debugging Tests -If you are trying to debug why tests are not doing what you expected, you can add android log -statements and use logcat to view them. The beginning and end of every tests is automatically logged -with the tag `TestRunner`. - -## Code Coverage -If you would like to collect code coverage information you can run the `coverage.sh` script located -in this directory. It will rebuild parts of your tree with coverage enabled and then run the tests, -similar to runtests.sh. If you have multiple devices connected to your machine make sure to set the -`ANDROID_SERIAL` environment variable before running the script. You must supply an output directory -for results. By default the results are generated as a set of HTML pages. For example, you can use -the following from the root out your source tree to generate results in the wifi_coverage directory - -``` -frameworks/opt/net/wifi/tests/wifitests/coverage.sh wifi_coverage -``` diff --git a/tests/wifitests/apex/Android.bp b/tests/wifitests/apex/Android.bp deleted file mode 100644 index 80acd49ca..000000000 --- a/tests/wifitests/apex/Android.bp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2019 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. - -// A test version of wifi apex. -// It has a version code that should beat a "real" APEX and enables end-to-end -// installation testing on devices with the latests real data. -apex_test { - name: "test_com.android.wifi", - visibility: [ - "//system/apex/tests", - ], - defaults: ["com.android.wifi-defaults"], - manifest: "test_apex_manifest.json", - file_contexts: ":com.android.wifi-file_contexts", - // Test APEX, should never be installed - installable: false, -} diff --git a/tests/wifitests/apex/test_apex_manifest.json b/tests/wifitests/apex/test_apex_manifest.json deleted file mode 100644 index 3272a0d90..000000000 --- a/tests/wifitests/apex/test_apex_manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "com.android.wifi", - "version": 2147483647 -} diff --git a/tests/wifitests/assets/r1.PerProviderSubscription.conf b/tests/wifitests/assets/r1.PerProviderSubscription.conf deleted file mode 100644 index 7cdc5973e..000000000 --- a/tests/wifitests/assets/r1.PerProviderSubscription.conf +++ /dev/null @@ -1,88 +0,0 @@ -tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0) -17:PerProviderSubscription(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)+ - 10:UpdateIdentifier=1:1 - 4:r1i2+ - 6:HomeSP+ - c:FriendlyName=8:TWC-WiFi - 4:FQDN=b:twcwifi.com - . - a:Credential+ - 10:UsernamePassword+ - 8:Username=7:tushar4 - 8:Password=d:cGFzc3dvcmQx - - 9:EAPMethod+ - 7:EAPType=2:21 - b:InnerMethod=a:MS-CHAP-V2 - . - . - 5:Realm=6:rr.com - . - . - 6:Cred01+ - 6:Policy+ - c:PolicyUpdate+ - e:UpdateInterval=a:4294967295 - c:UpdateMethod=13:SPP-ClientInitiated - b:Restriction=6:HomeSP - 3:URI=58:https://policy-server.r2-testbed-rks.wi-fi.org:9445/OnlineSignup/services/doAuthenticate - 10:UsernamePassword+ - 8:Username=a:osu_sta006 - 8:Password=10:b3N1X2FiYzEyMw== - . - 9:TrustRoot+ - 7:CertURL=3d:http://www.r2-testbed.wi-fi.org/policy-rootcert-networkfx.der - 15:CertSHA256Fingerprint=40:d9fb79e3247bb096e1efd549fc88cc0b8b520cedba7a9604686f5298b55adbfc - . - . - 1b:PreferredRoamingPartnerList+ - 4:RP01+ - 7:Country=2:US - 8:Priority=3:130 - a:FQDN_match=1d:ruckuswireless.com,exactMatch - . - . - . - 12:CredentialPriority=1:1 - 12:AAAServerTrustRoot+ - 3:TR1+ - 7:CertURL=2a:http://www.r2-testbed.wi-fi.org/cacert.der - 15:CertSHA256Fingerprint=40:5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647 - . - . - 12:SubscriptionUpdate+ - e:UpdateInterval=a:4294967295 - c:UpdateMethod=13:SPP-ClientInitiated - b:Restriction=6:HomeSP - 3:URI=5d:https://remediation-server.r2-testbed-rks.wi-fi.org:9445/OnlineSignup/services/doAuthenticate - 9:TrustRoot+ - 7:CertURL=43:http://www.r2-testbed.wi-fi.org/subscription-rootcert-networkfx.der - 15:CertSHA256Fingerprint=40:d9fb79e3247bb096e1efd549fc88cc0b8b520cedba7a9604686f5298b55adbfc - . - 10:UsernamePassword+ - 8:Username=a:osu_sta006 - 8:Password=10:b3N1X2FiYzEyMw== - . - . - 6:HomeSP+ - c:FriendlyName=e:Wi-Fi Alliance - 4:FQDN=9:wi-fi.org - . - 16:SubscriptionParameters+ - c:CreationDate=14:2016-01-10T23:04:58Z - . - a:Credential+ - c:CreationDate=14:2016-01-10T23:04:50Z - 5:Realm=9:wi-fi.org - 10:UsernamePassword+ - 8:Username=6:sta006 - 8:Password=8:YWJjMTIz - e:MachineManaged=5:false - 9:EAPMethod+ - 7:EAPType=2:21 - b:InnerMethod=a:MS-CHAP-V2 - . - . - . - . -. diff --git a/tests/wifitests/assets/r2-ttls-tree.xml b/tests/wifitests/assets/r2-ttls-tree.xml deleted file mode 100644 index 9dfdb0d44..000000000 --- a/tests/wifitests/assets/r2-ttls-tree.xml +++ /dev/null @@ -1,208 +0,0 @@ -<MgmtTree>
- <VerDTD>1.2</VerDTD>
- <Node>
- <NodeName>PerProviderSubscription</NodeName>
- <RTProperties>
- <Type>
- <DDFName>urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0</DDFName>
- </Type>
- </RTProperties>
- <Node>
- <NodeName>UpdateIdentifier</NodeName>
- <Value>1</Value>
- </Node>
- <Node>
- <NodeName>Cred01</NodeName>
- <Node>
- <NodeName>Policy</NodeName>
- <Node>
- <NodeName>PolicyUpdate</NodeName>
- <Node>
- <NodeName>UpdateInterval</NodeName>
- <Value>4294967295</Value>
- </Node>
- <Node>
- <NodeName>UpdateMethod</NodeName>
- <Value>SPP-ClientInitiated</Value>
- </Node>
- <Node>
- <NodeName>Restriction</NodeName>
- <Value>HomeSP</Value>
- </Node>
- <Node>
- <NodeName>URI</NodeName>
- <Value>
- https://policy-server.r2-testbed-rks.wi-fi.org:9445/OnlineSignup/services/doAuthenticate
- </Value>
- </Node>
- <Node>
- <NodeName>UsernamePassword</NodeName>
- <Node>
- <NodeName>Username</NodeName>
- <Value>osu_sta020</Value>
- </Node>
- <Node>
- <NodeName>Password</NodeName>
- <Value>b3N1X2FiYzEyMw==</Value>
- </Node>
- </Node>
- <Node>
- <NodeName>TrustRoot</NodeName>
- <Node>
- <NodeName>CertURL</NodeName>
- <Value>
- http://www.r2-testbed.wi-fi.org/policy-rootcert-networkfx.der
- </Value>
- </Node>
- <Node>
- <NodeName>CertSHA256Fingerprint</NodeName>
- <Value>
- d9fb79e3247bb096e1efd549fc88cc0b8b520cedba7a9604686f5298b55adbfc
- </Value>
- </Node>
- </Node>
- </Node>
- <Node>
- <NodeName>PreferredRoamingPartnerList</NodeName>
- <Node>
- <NodeName>RP01</NodeName>
- <Node>
- <NodeName>Country</NodeName>
- <Value>US</Value>
- </Node>
- <Node>
- <NodeName>Priority</NodeName>
- <Value>130</Value>
- </Node>
- <Node>
- <NodeName>FQDN_match</NodeName>
- <Value>ruckuswireless.com,exactMatch</Value>
- </Node>
- </Node>
- </Node>
- </Node>
- <Node>
- <NodeName>CredentialPriority</NodeName>
- <Value>1</Value>
- </Node>
- <Node>
- <NodeName>AAAServerTrustRoot</NodeName>
- <Node>
- <NodeName>TR1</NodeName>
- <Node>
- <NodeName>CertURL</NodeName>
- <Value>http://www.r2-testbed.wi-fi.org/cacert.der</Value>
- </Node>
- <Node>
- <NodeName>CertSHA256Fingerprint</NodeName>
- <Value>
- 5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647
- </Value>
- </Node>
- </Node>
- </Node>
- <Node>
- <NodeName>SubscriptionUpdate</NodeName>
- <Node>
- <NodeName>UpdateInterval</NodeName>
- <Value>4294967295</Value>
- </Node>
- <Node>
- <NodeName>UpdateMethod</NodeName>
- <Value>SPP-ClientInitiated</Value>
- </Node>
- <Node>
- <NodeName>Restriction</NodeName>
- <Value>HomeSP</Value>
- </Node>
- <Node>
- <NodeName>URI</NodeName>
- <Value>
- https://remediation-server.r2-testbed-rks.wi-fi.org:9445/OnlineSignup/services/doAuthenticate
- </Value>
- </Node>
- <Node>
- <NodeName>TrustRoot</NodeName>
- <Node>
- <NodeName>CertURL</NodeName>
- <Value>
- http://www.r2-testbed.wi-fi.org/subscription-rootcert-networkfx.der
- </Value>
- </Node>
- <Node>
- <NodeName>CertSHA256Fingerprint</NodeName>
- <Value>
- d9fb79e3247bb096e1efd549fc88cc0b8b520cedba7a9604686f5298b55adbfc
- </Value>
- </Node>
- </Node>
- <Node>
- <NodeName>UsernamePassword</NodeName>
- <Node>
- <NodeName>Username</NodeName>
- <Value>osu_sta020</Value>
- </Node>
- <Node>
- <NodeName>Password</NodeName>
- <Value>b3N1X2FiYzEyMw==</Value>
- </Node>
- </Node>
- </Node>
- <Node>
- <NodeName>HomeSP</NodeName>
- <Node>
- <NodeName>FriendlyName</NodeName>
- <Value>RK TTLS</Value>
- </Node>
- <Node>
- <NodeName>FQDN</NodeName>
- <Value>rk-ttls.org</Value>
- </Node>
- </Node>
- <Node>
- <NodeName>SubscriptionParameters</NodeName>
- <Node>
- <NodeName>CreationDate</NodeName>
- <Value>2016-01-21T23:08:03Z</Value>
- </Node>
- </Node>
- <Node>
- <NodeName>Credential</NodeName>
- <Node>
- <NodeName>CreationDate</NodeName>
- <Value>2016-01-21T23:07:56Z</Value>
- </Node>
- <Node>
- <NodeName>Realm</NodeName>
- <Value>wi-fi.org</Value>
- </Node>
- <Node>
- <NodeName>UsernamePassword</NodeName>
- <Node>
- <NodeName>Username</NodeName>
- <Value>sta020</Value>
- </Node>
- <Node>
- <NodeName>Password</NodeName>
- <Value>YWJjMTIz</Value>
- </Node>
- <Node>
- <NodeName>MachineManaged</NodeName>
- <Value>false</Value>
- </Node>
- <Node>
- <NodeName>EAPMethod</NodeName>
- <Node>
- <NodeName>EAPType</NodeName>
- <Value>21</Value>
- </Node>
- <Node>
- <NodeName>InnerMethod</NodeName>
- <Value>MS-CHAP-V2</Value>
- </Node>
- </Node>
- </Node>
- </Node>
- </Node>
- </Node>
-</MgmtTree>
diff --git a/tests/wifitests/assets/r2.PerProviderSubscription.conf b/tests/wifitests/assets/r2.PerProviderSubscription.conf deleted file mode 100644 index a011f97dd..000000000 --- a/tests/wifitests/assets/r2.PerProviderSubscription.conf +++ /dev/null @@ -1,92 +0,0 @@ -tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0) -8:MgmtTree+ - 17:PerProviderSubscription(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)+ - 10:UpdateIdentifier=1:1 - 6:Cred01+ - 6:Policy+ - c:PolicyUpdate+ - e:UpdateInterval=a:4294967295 - c:UpdateMethod=13:SPP-ClientInitiated - b:Restriction=6:HomeSP - 3:URI=58:https://policy-server.r2-testbed-rks.wi-fi.org:9445/OnlineSignup/services/doAuthenticate - 10:UsernamePassword+ - 8:Username=a:osu_sta015 - 8:Password=10:b3N1X2FiYzEyMw== - . - 9:TrustRoot+ - 7:CertURL=3d:http://www.r2-testbed.wi-fi.org/policy-rootcert-networkfx.der - 15:CertSHA256Fingerprint=40:d9fb79e3247bb096e1efd549fc88cc0b8b520cedba7a9604686f5298b55adbfc - . - . - 1b:PreferredRoamingPartnerList+ - 4:RP01+ - 7:Country=2:US - 8:Priority=3:130 - a:FQDN_match=1d:ruckuswireless.com,exactMatch - . - . - . - 12:CredentialPriority=1:1 - 12:AAAServerTrustRoot+ - 3:TR1+ - 7:CertURL=2a:http://www.r2-testbed.wi-fi.org/cacert.der - 15:CertSHA256Fingerprint=40:5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647 - . - . - 12:SubscriptionUpdate+ - e:UpdateInterval=a:4294967295 - c:UpdateMethod=13:SPP-ClientInitiated - b:Restriction=6:HomeSP - 3:URI=5d:https://remediation-server.r2-testbed-rks.wi-fi.org:9445/OnlineSignup/services/doAuthenticate - 9:TrustRoot+ - 7:CertURL=43:http://www.r2-testbed.wi-fi.org/subscription-rootcert-networkfx.der - 15:CertSHA256Fingerprint=40:d9fb79e3247bb096e1efd549fc88cc0b8b520cedba7a9604686f5298b55adbfc - . - 10:UsernamePassword+ - 8:Username=a:osu_sta015 - 8:Password=10:b3N1X2FiYzEyMw== - . - . - 6:HomeSP+ - c:FriendlyName=e:Wi-Fi Alliance - 4:FQDN=9:wi-fi.org - . - 16:SubscriptionParameters+ - c:CreationDate=14:2016-01-12T22:24:29Z - . - a:Credential+ - c:CreationDate=14:2016-01-12T22:24:21Z - 5:Realm=9:wi-fi.org - 10:UsernamePassword+ - 8:Username=6:sta015 - 8:Password=8:YWJjMTIz - e:MachineManaged=5:false - 9:EAPMethod+ - 7:EAPType=2:21 - b:InnerMethod=a:MS-CHAP-V2 - . - . - . - . - . - 17:PerProviderSubscription+ - 4:r1i2+ - 6:HomeSP+ - c:FriendlyName=8:TWC-WiFi - 4:FQDN=b:twcwifi.com - . - a:Credential+ - 10:UsernamePassword+ - 8:Username=7:tushar4 - 8:Password=d:cGFzc3dvcmQx - - 9:EAPMethod+ - 7:EAPType=2:21 - b:InnerMethod=a:MS-CHAP-V2 - . - . - 5:Realm=6:rr.com - . - . - . -. diff --git a/tests/wifitests/assets/ruckus.PerProviderSubscription.conf b/tests/wifitests/assets/ruckus.PerProviderSubscription.conf deleted file mode 100644 index 5a8b36a88..000000000 --- a/tests/wifitests/assets/ruckus.PerProviderSubscription.conf +++ /dev/null @@ -1,72 +0,0 @@ -tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0) -8:MgmtTree+ - 17:PerProviderSubscription(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)+ - 10:UpdateIdentifier=1:1 - 6:Cred01+ - 6:Policy+ - c:PolicyUpdate+ - e:UpdateInterval=a:4294967295 - c:UpdateMethod=13:SPP-ClientInitiated - b:Restriction=6:HomeSP - 3:URI=58:https://policy-server.r2-testbed-rks.wi-fi.org:9445/OnlineSignup/services/doAuthenticate - 10:UsernamePassword+ - 8:Username=a:osu_sta015 - 8:Password=10:b3N1X2FiYzEyMw== - . - 9:TrustRoot+ - 7:CertURL=3d:http://www.r2-testbed.wi-fi.org/policy-rootcert-networkfx.der - 15:CertSHA256Fingerprint=40:d9fb79e3247bb096e1efd549fc88cc0b8b520cedba7a9604686f5298b55adbfc - . - . - 1b:PreferredRoamingPartnerList+ - 4:RP01+ - 7:Country=2:US - 8:Priority=3:130 - a:FQDN_match=1d:ruckuswireless.com,exactMatch - . - . - . - 12:CredentialPriority=1:1 - 12:AAAServerTrustRoot+ - 3:TR1+ - 7:CertURL=2a:http://www.r2-testbed.wi-fi.org/cacert.der - 15:CertSHA256Fingerprint=40:5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647 - . - . - 12:SubscriptionUpdate+ - e:UpdateInterval=a:4294967295 - c:UpdateMethod=13:SPP-ClientInitiated - b:Restriction=6:HomeSP - 3:URI=5d:https://remediation-server.r2-testbed-rks.wi-fi.org:9445/OnlineSignup/services/doAuthenticate - 9:TrustRoot+ - 7:CertURL=43:http://www.r2-testbed.wi-fi.org/subscription-rootcert-networkfx.der - 15:CertSHA256Fingerprint=40:d9fb79e3247bb096e1efd549fc88cc0b8b520cedba7a9604686f5298b55adbfc - . - 10:UsernamePassword+ - 8:Username=a:osu_sta015 - 8:Password=10:b3N1X2FiYzEyMw== - . - . - 6:HomeSP+ - c:FriendlyName=e:Wi-Fi Alliance - 4:FQDN=9:wi-fi.org - . - 16:SubscriptionParameters+ - c:CreationDate=14:2016-01-12T22:24:29Z - . - a:Credential+ - c:CreationDate=14:2016-01-12T22:24:21Z - 5:Realm=9:wi-fi.org - 10:UsernamePassword+ - 8:Username=6:sta015 - 8:Password=8:YWJjMTIz - e:MachineManaged=5:false - 9:EAPMethod+ - 7:EAPType=2:21 - b:InnerMethod=a:MS-CHAP-V2 - . - . - . - . - . -. diff --git a/tests/wifitests/coverage.sh b/tests/wifitests/coverage.sh deleted file mode 100755 index b2b37c120..000000000 --- a/tests/wifitests/coverage.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/sh - -# A shell script to generate a coverage report for opt/net/wifi - -if [[ ! ($# == 1) ]]; then - echo "$0: usage: coverage.sh OUTPUT_DIR" - exit 1 -fi - -if [ -z $ANDROID_BUILD_TOP ]; then - echo "You need to source and lunch before you can use this script" - exit 1 -fi - -# Make the output directory and get its full name -OUTPUT_DIR="$1" -mkdir -p $OUTPUT_DIR || exit 1 -OUTPUT_DIR="`(cd $OUTPUT_DIR && pwd)`" -BUILD_OUT_DIR=$OUTPUT_DIR/out -echo "Output dir: $OUTPUT_DIR" - -cd "$(dirname $0)" #cd to directory containing this script - -echo "Checking jacoco patterns" -class_patterns_from_filenames () { - sed -e 's/[.]java$//' -e 's@/@.@g' | - while read x; do - printf ' "%s",\n' "$x" - printf ' "%s$*",\n' "$x" - printf ' "%s.**",\n' "$x" - done -} - -generate_new_bp () ( - sed -n -e p -e '/include_filter:/q' < Android.bp - (cd ../../service/java && find * -name \*.java) | - LC_ALL=C sort | - class_patterns_from_filenames - tail -n 3 Android.bp -) - -generate_new_bp > $OUTPUT_DIR/bp - -diff -u Android.bp $OUTPUT_DIR/bp || { - mv $OUTPUT_DIR/bp Android.bp - echo "Android.bp has been updated. Please review and check in the new version" - exit 1 -} -rm -f $OUTPUT_DIR/bp - -REMOTE_COVERAGE_OUTPUT_FILE=/data/data/com.android.server.wifi.test/files/coverage.ec -COVERAGE_OUTPUT_FILE=$OUTPUT_DIR/wifi_coverage.ec - -# Note - the $VARs in the following are expanded by the here-file redirection! -echo "Building for coverage report" -bash <<END_OF_BUILD_SCRIPT || { exit 1; } - cd $ANDROID_BUILD_TOP - source build/make/envsetup.sh - lunch ${TARGET_PRODUCT}-${TARGET_BUILD_VARIANT} - export OUT_DIR=${BUILD_OUT_DIR} - export EMMA_INSTRUMENT=true - export EMMA_INSTRUMENT_FRAMEWORK=false - export EMMA_INSTRUMENT_STATIC=true - export ANDROID_COMPILE_WITH_JACK=false - export SKIP_BOOT_JARS_CHECK=true - m FrameworksWifiTests jacoco-cli -END_OF_BUILD_SCRIPT - -APK_NAME="$(find $BUILD_OUT_DIR/target -name FrameworksWifiTests.apk)" -REPORTER_JAR="$(find $BUILD_OUT_DIR/host -name jacoco-cli.jar)" - -echo "Running tests and generating coverage report" - -set -e # fail early -set -x # print commands -test -f "$APK_NAME" -test -f "$REPORTER_JAR" - -adb root -adb wait-for-device - -adb shell rm -f $REMOTE_COVERAGE_OUTPUT_FILE - -adb install -r -g "$APK_NAME" - -adb shell am instrument -e coverage true --no-hidden-api-checks \ - -w 'com.android.server.wifi.test/com.android.server.wifi.CustomTestRunner' - -adb pull $REMOTE_COVERAGE_OUTPUT_FILE $COVERAGE_OUTPUT_FILE - -java -jar $REPORTER_JAR \ - report \ - --html $OUTPUT_DIR \ - --classfiles $BUILD_OUT_DIR/target/common/obj/APPS/FrameworksWifiTests_intermediates/jacoco-report-classes.jar \ - --sourcefiles $ANDROID_BUILD_TOP/frameworks/opt/net/wifi/service/java \ - --name wifi-coverage \ - $COVERAGE_OUTPUT_FILE -set +x - -echo Created report at file://$OUTPUT_DIR/index.html - diff --git a/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java b/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java deleted file mode 100644 index 8294bdb04..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java +++ /dev/null @@ -1,2320 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; -import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY; -import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY; -import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockingDetails; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Resources; -import android.location.LocationManager; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApConfiguration.Builder; -import android.net.wifi.SoftApInfo; -import android.net.wifi.WifiClient; -import android.net.wifi.WifiManager; -import android.os.BatteryStatsManager; -import android.os.test.TestLooper; -import android.util.Log; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiNative.InterfaceAvailableForRequestListener; -import com.android.server.wifi.util.GeneralUtil; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Unit tests for {@link com.android.server.wifi.ActiveModeWarden}. - */ -@SmallTest -public class ActiveModeWardenTest extends WifiBaseTest { - public static final String TAG = "WifiActiveModeWardenTest"; - - private static final String ENABLED_STATE_STRING = "EnabledState"; - private static final String DISABLED_STATE_STRING = "DisabledState"; - - private static final String WIFI_IFACE_NAME = "mockWlan"; - private static final int TEST_WIFI_RECOVERY_DELAY_MS = 2000; - private static final int TEST_AP_FREQUENCY = 2412; - private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; - - TestLooper mLooper; - @Mock WifiInjector mWifiInjector; - @Mock Context mContext; - @Mock Resources mResources; - @Mock WifiNative mWifiNative; - @Mock WifiApConfigStore mWifiApConfigStore; - @Mock ClientModeManager mClientModeManager; - @Mock SoftApManager mSoftApManager; - @Mock DefaultModeManager mDefaultModeManager; - @Mock BatteryStatsManager mBatteryStats; - @Mock SelfRecovery mSelfRecovery; - @Mock BaseWifiDiagnostics mWifiDiagnostics; - @Mock ScanRequestProxy mScanRequestProxy; - @Mock ClientModeImpl mClientModeImpl; - @Mock FrameworkFacade mFacade; - @Mock WifiSettingsStore mSettingsStore; - @Mock WifiPermissionsUtil mWifiPermissionsUtil; - @Mock SoftApCapability mSoftApCapability; - - ActiveModeManager.Listener mClientListener; - ActiveModeManager.Listener mSoftApListener; - WifiManager.SoftApCallback mSoftApManagerCallback; - SoftApModeConfiguration mSoftApConfig; - @Mock WifiManager.SoftApCallback mSoftApStateMachineCallback; - @Mock WifiManager.SoftApCallback mLohsStateMachineCallback; - WifiNative.StatusListener mWifiNativeStatusListener; - ActiveModeWarden mActiveModeWarden; - private SoftApInfo mTestSoftApInfo; - - final ArgumentCaptor<WifiNative.StatusListener> mStatusListenerCaptor = - ArgumentCaptor.forClass(WifiNative.StatusListener.class); - final ArgumentCaptor<InterfaceAvailableForRequestListener> mClientIfaceAvailableListener = - ArgumentCaptor.forClass(InterfaceAvailableForRequestListener.class); - final ArgumentCaptor<InterfaceAvailableForRequestListener> mSoftApIfaceAvailableListener = - ArgumentCaptor.forClass(InterfaceAvailableForRequestListener.class); - - /** - * Set up the test environment. - */ - @Before - public void setUp() throws Exception { - Log.d(TAG, "Setting up ..."); - - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - - when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy); - when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); - when(mContext.getResources()).thenReturn(mResources); - when(mSoftApManager.getRole()).thenReturn(ROLE_SOFTAP_TETHERED); - - when(mResources.getString(R.string.wifi_localhotspot_configure_ssid_default)) - .thenReturn("AndroidShare"); - when(mResources.getInteger(R.integer.config_wifi_framework_recovery_timeout_delay)) - .thenReturn(TEST_WIFI_RECOVERY_DELAY_MS); - when(mResources.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) - .thenReturn(false); - - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - - doAnswer(new Answer<ClientModeManager>() { - public ClientModeManager answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - mClientListener = (ClientModeManager.Listener) args[0]; - return mClientModeManager; - } - }).when(mWifiInjector).makeClientModeManager(any(ActiveModeManager.Listener.class)); - doAnswer(new Answer<SoftApManager>() { - public SoftApManager answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - mSoftApListener = (ActiveModeManager.Listener) args[0]; - mSoftApManagerCallback = (WifiManager.SoftApCallback) args[1]; - mSoftApConfig = (SoftApModeConfiguration) args[2]; - return mSoftApManager; - } - }).when(mWifiInjector).makeSoftApManager(any(ActiveModeManager.Listener.class), - any(WifiManager.SoftApCallback.class), any()); - - mActiveModeWarden = createActiveModeWarden(); - mActiveModeWarden.start(); - mLooper.dispatchAll(); - - verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); - mWifiNativeStatusListener = mStatusListenerCaptor.getValue(); - - verify(mWifiNative).registerClientInterfaceAvailabilityListener( - mClientIfaceAvailableListener.capture()); - verify(mWifiNative).registerSoftApInterfaceAvailabilityListener( - mSoftApIfaceAvailableListener.capture()); - - mActiveModeWarden.registerSoftApCallback(mSoftApStateMachineCallback); - mActiveModeWarden.registerLohsCallback(mLohsStateMachineCallback); - mTestSoftApInfo = new SoftApInfo(); - mTestSoftApInfo.setFrequency(TEST_AP_FREQUENCY); - mTestSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); - } - - private ActiveModeWarden createActiveModeWarden() { - ActiveModeWarden warden = new ActiveModeWarden( - mWifiInjector, - mLooper.getLooper(), - mWifiNative, - mDefaultModeManager, - mBatteryStats, - mWifiDiagnostics, - mContext, - mClientModeImpl, - mSettingsStore, - mFacade, - mWifiPermissionsUtil); - // SelfRecovery is created in WifiInjector after ActiveModeWarden, so getSelfRecovery() - // returns null when constructing ActiveModeWarden. - when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); - return warden; - } - - /** - * Clean up after tests - explicitly set tested object to null. - */ - @After - public void cleanUp() throws Exception { - mActiveModeWarden = null; - mLooper.dispatchAll(); - } - - /** - * Helper method to enter the EnabledState and set ClientModeManager in ConnectMode. - */ - private void enterClientModeActiveState() throws Exception { - String fromState = mActiveModeWarden.getCurrentMode(); - when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - mClientListener.onStarted(); - mLooper.dispatchAll(); - - assertInEnabledState(); - verify(mClientModeManager).start(); - verify(mClientModeManager).setRole(ROLE_CLIENT_PRIMARY); - verify(mScanRequestProxy).enableScanning(true, true); - if (fromState.equals(DISABLED_STATE_STRING)) { - verify(mBatteryStats).reportWifiOn(); - } - } - - /** - * Helper method to enter the EnabledState and set ClientModeManager in ScanOnlyMode. - */ - private void enterScanOnlyModeActiveState() throws Exception { - String fromState = mActiveModeWarden.getCurrentMode(); - when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - mClientListener.onStarted(); - mLooper.dispatchAll(); - - assertInEnabledState(); - verify(mClientModeManager).start(); - verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY); - verify(mScanRequestProxy).enableScanning(true, false); - if (fromState.equals(DISABLED_STATE_STRING)) { - verify(mBatteryStats).reportWifiOn(); - } - verify(mBatteryStats).reportWifiState(BatteryStatsManager.WIFI_STATE_OFF_SCANNING, null); - } - - private void enterSoftApActiveMode() throws Exception { - enterSoftApActiveMode( - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mSoftApCapability)); - } - - /** - * Helper method to activate SoftApManager. - * - * This method puts the test object into the correct state and verifies steps along the way. - */ - private void enterSoftApActiveMode(SoftApModeConfiguration softApConfig) throws Exception { - String fromState = mActiveModeWarden.getCurrentMode(); - int softApRole = softApConfig.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED - ? ROLE_SOFTAP_TETHERED : ROLE_SOFTAP_LOCAL_ONLY; - when(mSoftApManager.getRole()).thenReturn(softApRole); - mActiveModeWarden.startSoftAp(softApConfig); - mLooper.dispatchAll(); - mSoftApListener.onStarted(); - mLooper.dispatchAll(); - - assertInEnabledState(); - assertThat(softApConfig).isEqualTo(mSoftApConfig); - verify(mSoftApManager).start(); - verify(mSoftApManager).setRole(softApRole); - if (fromState.equals(DISABLED_STATE_STRING)) { - verify(mBatteryStats).reportWifiOn(); - } - } - - private void enterStaDisabledMode(boolean isSoftApModeManagerActive) { - String fromState = mActiveModeWarden.getCurrentMode(); - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - if (mClientListener != null) { - mClientListener.onStopped(); - mLooper.dispatchAll(); - } - - if (isSoftApModeManagerActive) { - assertInEnabledState(); - } else { - assertInDisabledState(); - } - if (fromState.equals(ENABLED_STATE_STRING)) { - verify(mScanRequestProxy).enableScanning(false, false); - } - } - - private void shutdownWifi() { - mActiveModeWarden.recoveryDisableWifi(); - mLooper.dispatchAll(); - } - - private void assertInEnabledState() { - assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(ENABLED_STATE_STRING); - } - - private void assertInDisabledState() { - assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(DISABLED_STATE_STRING); - } - - /** - * Emergency mode is a sub-mode within each main state (ScanOnly, Client, DisabledState). - */ - private void assertInEmergencyMode() { - assertThat(mActiveModeWarden.isInEmergencyMode()).isTrue(); - } - - /** - * Counts the number of times a void method was called on a mock. - * - * Void methods cannot be passed to Mockito.mockingDetails(). Thus we have to use method name - * matching instead. - */ - private static int getMethodInvocationCount(Object mock, String methodName) { - long count = mockingDetails(mock).getInvocations() - .stream() - .filter(invocation -> methodName.equals(invocation.getMethod().getName())) - .count(); - return (int) count; - } - - /** - * Counts the number of times a non-void method was called on a mock. - * - * For non-void methods, can pass the method call literal directly: - * e.g. getMethodInvocationCount(mock.method()); - */ - private static int getMethodInvocationCount(Object mockMethod) { - return mockingDetails(mockMethod).getInvocations().size(); - } - - private void assertWifiShutDown(Runnable r) { - assertWifiShutDown(r, 1); - } - - /** - * Asserts that the runnable r has shut down wifi properly. - * - * @param r runnable that will shut down wifi - * @param times expected number of times that <code>r</code> shut down wifi - */ - private void assertWifiShutDown(Runnable r, int times) { - // take snapshot of ActiveModeManagers - Collection<ActiveModeManager> activeModeManagers = - mActiveModeWarden.getActiveModeManagers(); - - List<Integer> expectedStopInvocationCounts = activeModeManagers - .stream() - .map(manager -> getMethodInvocationCount(manager, "stop") + times) - .collect(Collectors.toList()); - - r.run(); - - List<Integer> actualStopInvocationCounts = activeModeManagers - .stream() - .map(manager -> getMethodInvocationCount(manager, "stop")) - .collect(Collectors.toList()); - - String managerNames = activeModeManagers.stream() - .map(manager -> manager.getClass().getCanonicalName()) - .collect(Collectors.joining(", ", "[", "]")); - - assertThat(actualStopInvocationCounts) - .named(managerNames) - .isEqualTo(expectedStopInvocationCounts); - } - - private void assertEnteredEcmMode(Runnable r) { - assertEnteredEcmMode(r, 1); - } - - /** - * Asserts that the runnable r has entered ECM state properly. - * - * @param r runnable that will enter ECM - * @param times expected number of times that <code>r</code> shut down wifi - */ - private void assertEnteredEcmMode(Runnable r, int times) { - // take snapshot of ActiveModeManagers - Collection<ActiveModeManager> activeModeManagers = - mActiveModeWarden.getActiveModeManagers(); - - boolean disableWifiInEcm = mFacade.getConfigWiFiDisableInECBM(mContext); - - List<Integer> expectedStopInvocationCounts = activeModeManagers.stream() - .map(manager -> { - int initialCount = getMethodInvocationCount(manager, "stop"); - // carrier config enabled, all mode managers should have been shut down once - int count = disableWifiInEcm ? initialCount + times : initialCount; - if (manager instanceof SoftApManager) { - // expect SoftApManager.close() to be called - return count + times; - } else { - // don't expect other Managers close() to be called - return count; - } - }) - .collect(Collectors.toList()); - - r.run(); - - assertInEmergencyMode(); - - List<Integer> actualStopInvocationCounts = activeModeManagers.stream() - .map(manager -> getMethodInvocationCount(manager, "stop")) - .collect(Collectors.toList()); - - String managerNames = activeModeManagers.stream() - .map(manager -> manager.getClass().getCanonicalName()) - .collect(Collectors.joining(", ", "[", "]")); - - assertThat(actualStopInvocationCounts) - .named(managerNames) - .isEqualTo(expectedStopInvocationCounts); - } - - /** Test that after starting up, ActiveModeWarden is in the DisabledState State. */ - @Test - public void testDisabledStateAtStartup() { - assertInDisabledState(); - } - - /** - * Test that ActiveModeWarden properly enters the EnabledState (in ScanOnlyMode) from the - * DisabledState state. - */ - @Test - public void testEnterScanOnlyModeFromDisabled() throws Exception { - enterScanOnlyModeActiveState(); - } - - /** - * Test that ActiveModeWarden enables hidden network scanning in scan-only-mode - * if configured to do. - */ - @Test - public void testScanOnlyModeScanHiddenNetworks() throws Exception { - when(mResources.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) - .thenReturn(true); - - mActiveModeWarden = createActiveModeWarden(); - mActiveModeWarden.start(); - mLooper.dispatchAll(); - - when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - mClientListener.onStarted(); - mLooper.dispatchAll(); - - assertInEnabledState(); - verify(mClientModeManager).start(); - verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY); - verify(mScanRequestProxy).enableScanning(true, true); - } - - /** - * Test that ActiveModeWarden properly starts the SoftApManager from the - * DisabledState state. - */ - @Test - public void testEnterSoftApModeFromDisabled() throws Exception { - enterSoftApActiveMode(); - } - - /** - * Test that ActiveModeWarden properly starts the SoftApManager from another state. - */ - @Test - public void testEnterSoftApModeFromDifferentState() throws Exception { - enterClientModeActiveState(); - assertInEnabledState(); - reset(mBatteryStats, mScanRequestProxy); - enterSoftApActiveMode(); - } - - /** - * Test that we can disable wifi fully from the EnabledState (in ScanOnlyMode). - */ - @Test - public void testDisableWifiFromScanOnlyModeActiveState() throws Exception { - enterScanOnlyModeActiveState(); - - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); - mActiveModeWarden.scanAlwaysModeChanged(); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - - verify(mClientModeManager).stop(); - verify(mBatteryStats).reportWifiOff(); - assertInDisabledState(); - } - - /** - * Test that we can disable wifi when SoftApManager is active and not impact softap. - */ - @Test - public void testDisableWifiFromSoftApModeActiveStateDoesNotStopSoftAp() throws Exception { - enterSoftApActiveMode(); - enterScanOnlyModeActiveState(); - - reset(mDefaultModeManager); - enterStaDisabledMode(true); - verify(mSoftApManager, never()).stop(); - verify(mBatteryStats, never()).reportWifiOff(); - } - - /** - * Test that we can switch from the EnabledState (in ScanOnlyMode) to another mode. - */ - @Test - public void testSwitchModeWhenScanOnlyModeActiveState() throws Exception { - enterScanOnlyModeActiveState(); - - reset(mBatteryStats, mScanRequestProxy); - enterClientModeActiveState(); - mLooper.dispatchAll(); - verify(mClientModeManager).setRole(ROLE_CLIENT_PRIMARY); - assertInEnabledState(); - } - - /** - * Reentering EnabledState should be a NOP. - */ - @Test - public void testReenterClientModeActiveStateIsNop() throws Exception { - enterClientModeActiveState(); - verify(mClientModeManager, times(1)).start(); - - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - // Should not start again. - verify(mClientModeManager, times(1)).start(); - } - - /** - * Test that we can switch mode when SoftApManager is active to another mode. - */ - @Test - public void testSwitchModeWhenSoftApActiveMode() throws Exception { - enterSoftApActiveMode(); - - reset(mWifiNative); - - enterClientModeActiveState(); - mLooper.dispatchAll(); - verify(mSoftApManager, never()).stop(); - assertInEnabledState(); - verify(mWifiNative, never()).teardownAllInterfaces(); - } - - /** - * Test that we activate SoftApModeManager if we are already in DisabledState due to - * a failure. - */ - @Test - public void testEnterSoftApModeActiveWhenAlreadyInSoftApMode() throws Exception { - enterSoftApActiveMode(); - // now inject failure through the SoftApManager.Listener - mSoftApListener.onStartFailure(); - mLooper.dispatchAll(); - assertInDisabledState(); - // clear the first call to start SoftApManager - reset(mSoftApManager, mBatteryStats); - - enterSoftApActiveMode(); - } - - /** - * Test that we return to the DisabledState after a failure is reported when in the - * EnabledState. - */ - @Test - public void testScanOnlyModeFailureWhenActive() throws Exception { - enterScanOnlyModeActiveState(); - // now inject a failure through the ScanOnlyModeManager.Listener - mClientListener.onStartFailure(); - mLooper.dispatchAll(); - assertInDisabledState(); - verify(mBatteryStats).reportWifiOff(); - } - - /** - * Test that we return to the DisabledState after a failure is reported when - * SoftApManager is active. - */ - @Test - public void testSoftApFailureWhenActive() throws Exception { - enterSoftApActiveMode(); - // now inject failure through the SoftApManager.Listener - mSoftApListener.onStartFailure(); - mLooper.dispatchAll(); - verify(mBatteryStats).reportWifiOff(); - } - - /** - * Test that we return to the DisabledState after the ClientModeManager running in ScanOnlyMode - * is stopped. - */ - @Test - public void testScanOnlyModeDisabledWhenActive() throws Exception { - enterScanOnlyModeActiveState(); - - // now inject the stop message through the ScanOnlyModeManager.Listener - mClientListener.onStopped(); - mLooper.dispatchAll(); - - assertInDisabledState(); - verify(mBatteryStats).reportWifiOff(); - } - - /** - * Test that we return to the DisabledState after the SoftApManager is stopped. - */ - @Test - public void testSoftApDisabledWhenActive() throws Exception { - enterSoftApActiveMode(); - reset(mWifiNative); - // now inject failure through the SoftApManager.Listener - mSoftApListener.onStartFailure(); - mLooper.dispatchAll(); - verify(mBatteryStats).reportWifiOff(); - verifyNoMoreInteractions(mWifiNative); - } - - /** - * Verifies that SoftApStateChanged event is being passed from SoftApManager to WifiServiceImpl - */ - @Test - public void callsWifiServiceCallbackOnSoftApStateChanged() throws Exception { - enterSoftApActiveMode(); - - mSoftApListener.onStarted(); - mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0); - mLooper.dispatchAll(); - - verify(mSoftApStateMachineCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0); - } - - /** - * Verifies that SoftApStateChanged event isn't passed to WifiServiceImpl for LOHS, - * so the state change for LOHS doesn't affect Wifi Tethering indication. - */ - @Test - public void doesntCallWifiServiceCallbackOnLOHSStateChanged() throws Exception { - enterSoftApActiveMode(new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null, mSoftApCapability)); - - mSoftApListener.onStarted(); - mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0); - mLooper.dispatchAll(); - - verify(mSoftApStateMachineCallback, never()).onStateChanged(anyInt(), anyInt()); - verify(mSoftApStateMachineCallback, never()).onConnectedClientsChanged(any()); - verify(mSoftApStateMachineCallback, never()).onInfoChanged(any()); - } - - /** - * Verifies that NumClientsChanged event is being passed from SoftApManager to WifiServiceImpl - */ - @Test - public void callsWifiServiceCallbackOnSoftApConnectedClientsChanged() throws Exception { - final List<WifiClient> testClients = new ArrayList(); - enterSoftApActiveMode(); - mSoftApManagerCallback.onConnectedClientsChanged(testClients); - mLooper.dispatchAll(); - - verify(mSoftApStateMachineCallback).onConnectedClientsChanged(testClients); - } - - /** - * Verifies that SoftApInfoChanged event is being passed from SoftApManager to WifiServiceImpl - */ - @Test - public void callsWifiServiceCallbackOnSoftApInfoChanged() throws Exception { - enterSoftApActiveMode(); - mSoftApManagerCallback.onInfoChanged(mTestSoftApInfo); - mLooper.dispatchAll(); - - verify(mSoftApStateMachineCallback).onInfoChanged(mTestSoftApInfo); - } - - /** - * Test that we remain in the active state when we get a state change update that scan mode is - * active. - */ - @Test - public void testScanOnlyModeStaysActiveOnEnabledUpdate() throws Exception { - enterScanOnlyModeActiveState(); - // now inject success through the Listener - mClientListener.onStarted(); - mLooper.dispatchAll(); - assertInEnabledState(); - verify(mClientModeManager, never()).stop(); - } - - /** - * Test that a config passed in to the call to enterSoftApMode is used to create the new - * SoftApManager. - */ - @Test - public void testConfigIsPassedToWifiInjector() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid("ThisIsAConfig"); - SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), mSoftApCapability); - enterSoftApActiveMode(softApConfig); - } - - /** - * Test that when enterSoftAPMode is called with a null config, we pass a null config to - * WifiInjector.makeSoftApManager. - * - * Passing a null config to SoftApManager indicates that the default config should be used. - */ - @Test - public void testNullConfigIsPassedToWifiInjector() throws Exception { - enterSoftApActiveMode(); - } - - /** - * Test that two calls to switch to SoftAPMode in succession ends up with the correct config. - * - * Expectation: we should end up in SoftAPMode state configured with the second config. - */ - @Test - public void testStartSoftApModeTwiceWithTwoConfigs() throws Exception { - when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore); - Builder configBuilder1 = new SoftApConfiguration.Builder(); - configBuilder1.setSsid("ThisIsAConfig"); - SoftApModeConfiguration softApConfig1 = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder1.build(), - mSoftApCapability); - Builder configBuilder2 = new SoftApConfiguration.Builder(); - configBuilder2.setSsid("ThisIsASecondConfig"); - SoftApModeConfiguration softApConfig2 = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder2.build(), - mSoftApCapability); - - doAnswer(new Answer<SoftApManager>() { - public SoftApManager answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - mSoftApListener = (ActiveModeManager.Listener) args[0]; - return mSoftApManager; - } - }).when(mWifiInjector).makeSoftApManager(any(ActiveModeManager.Listener.class), - any(WifiManager.SoftApCallback.class), eq(softApConfig1)); - // make a second softap manager - SoftApManager softapManager = mock(SoftApManager.class); - GeneralUtil.Mutable<ActiveModeManager.Listener> softApListener = - new GeneralUtil.Mutable<>(); - doAnswer(new Answer<SoftApManager>() { - public SoftApManager answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - softApListener.value = (ActiveModeManager.Listener) args[0]; - return softapManager; - } - }).when(mWifiInjector).makeSoftApManager(any(ActiveModeManager.Listener.class), - any(WifiManager.SoftApCallback.class), eq(softApConfig2)); - - mActiveModeWarden.startSoftAp(softApConfig1); - mLooper.dispatchAll(); - mSoftApListener.onStarted(); - mActiveModeWarden.startSoftAp(softApConfig2); - mLooper.dispatchAll(); - softApListener.value.onStarted(); - - verify(mSoftApManager).start(); - verify(softapManager).start(); - verify(mBatteryStats).reportWifiOn(); - } - - /** - * Test that we safely disable wifi if it is already disabled. - */ - @Test - public void disableWifiWhenAlreadyOff() throws Exception { - enterStaDisabledMode(false); - verifyZeroInteractions(mWifiNative); - } - - /** - * Trigger recovery and a bug report if we see a native failure - * while the device is not shutting down - */ - @Test - public void handleWifiNativeFailureDeviceNotShuttingDown() throws Exception { - mWifiNativeStatusListener.onStatusChanged(false); - mLooper.dispatchAll(); - verify(mWifiDiagnostics).captureBugReportData( - WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); - verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); - } - - /** - * Verify the device shutting down doesn't trigger recovery or bug report. - */ - @Test - public void handleWifiNativeFailureDeviceShuttingDown() throws Exception { - mActiveModeWarden.notifyShuttingDown(); - mWifiNativeStatusListener.onStatusChanged(false); - mLooper.dispatchAll(); - verify(mWifiDiagnostics, never()).captureBugReportData( - WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); - verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); - } - - /** - * Verify an onStatusChanged callback with "true" does not trigger recovery. - */ - @Test - public void handleWifiNativeStatusReady() throws Exception { - mWifiNativeStatusListener.onStatusChanged(true); - mLooper.dispatchAll(); - verify(mWifiDiagnostics, never()).captureBugReportData( - WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); - verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); - } - - /** - * Verify that mode stop is safe even if the underlying Client mode exited already. - */ - @Test - public void shutdownWifiDoesNotCrashWhenClientModeExitsOnDestroyed() throws Exception { - enterClientModeActiveState(); - - mClientListener.onStopped(); - mLooper.dispatchAll(); - - shutdownWifi(); - - assertInDisabledState(); - } - - /** - * Verify that an interface destruction callback is safe after already having been stopped. - */ - @Test - public void onDestroyedCallbackDoesNotCrashWhenClientModeAlreadyStopped() throws Exception { - enterClientModeActiveState(); - - shutdownWifi(); - - mClientListener.onStopped(); - mLooper.dispatchAll(); - - assertInDisabledState(); - } - - /** - * Verify that mode stop is safe even if the underlying softap mode exited already. - */ - @Test - public void shutdownWifiDoesNotCrashWhenSoftApExitsOnDestroyed() throws Exception { - enterSoftApActiveMode(); - - mSoftApListener.onStopped(); - mLooper.dispatchAll(); - mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); - mLooper.dispatchAll(); - - shutdownWifi(); - - verify(mSoftApStateMachineCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); - } - - /** - * Verify that an interface destruction callback is safe after already having been stopped. - */ - @Test - public void onDestroyedCallbackDoesNotCrashWhenSoftApModeAlreadyStopped() throws Exception { - enterSoftApActiveMode(); - - shutdownWifi(); - - mSoftApListener.onStopped(); - mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); - mLooper.dispatchAll(); - - verify(mSoftApStateMachineCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); - } - - /** - * Verify that we do not crash when calling dump and wifi is fully disabled. - */ - @Test - public void dumpWhenWifiFullyOffDoesNotCrash() throws Exception { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - mActiveModeWarden.dump(null, writer, null); - } - - /** - * Verify that we trigger dump on active mode managers. - */ - @Test - public void dumpCallsActiveModeManagers() throws Exception { - enterSoftApActiveMode(); - enterClientModeActiveState(); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - mActiveModeWarden.dump(null, writer, null); - - verify(mSoftApManager).dump(null, writer, null); - verify(mClientModeManager).dump(null, writer, null); - } - - /** - * Verify that stopping tethering doesn't stop LOHS. - */ - @Test - public void testStopTetheringButNotLOHS() throws Exception { - // prepare WiFi configurations - when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore); - SoftApModeConfiguration tetherConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mSoftApCapability); - SoftApConfiguration lohsConfigWC = WifiApConfigStore.generateLocalOnlyHotspotConfig( - mContext, SoftApConfiguration.BAND_2GHZ, null); - SoftApModeConfiguration lohsConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_LOCAL_ONLY, lohsConfigWC, - mSoftApCapability); - - // mock SoftAPManagers - when(mSoftApManager.getRole()).thenReturn(ROLE_SOFTAP_TETHERED); - doAnswer(new Answer<SoftApManager>() { - public SoftApManager answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - mSoftApListener = (ActiveModeManager.Listener) args[0]; - return mSoftApManager; - } - }).when(mWifiInjector).makeSoftApManager(any(ActiveModeManager.Listener.class), - any(WifiManager.SoftApCallback.class), eq(tetherConfig)); - // make a second softap manager - SoftApManager lohsSoftapManager = mock(SoftApManager.class); - when(lohsSoftapManager.getRole()).thenReturn(ROLE_SOFTAP_LOCAL_ONLY); - GeneralUtil.Mutable<ActiveModeManager.Listener> lohsSoftApListener = - new GeneralUtil.Mutable<>(); - doAnswer(new Answer<SoftApManager>() { - public SoftApManager answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - lohsSoftApListener.value = (ActiveModeManager.Listener) args[0]; - return lohsSoftapManager; - } - }).when(mWifiInjector).makeSoftApManager(any(ActiveModeManager.Listener.class), - any(WifiManager.SoftApCallback.class), eq(lohsConfig)); - - // enable tethering and LOHS - mActiveModeWarden.startSoftAp(tetherConfig); - mLooper.dispatchAll(); - mSoftApListener.onStarted(); - mActiveModeWarden.startSoftAp(lohsConfig); - mLooper.dispatchAll(); - lohsSoftApListener.value.onStarted(); - verify(mSoftApManager).start(); - verify(lohsSoftapManager).start(); - verify(mBatteryStats).reportWifiOn(); - - // disable tethering - mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - verify(mSoftApManager).stop(); - verify(lohsSoftapManager, never()).stop(); - } - - /** - * Verify that toggling wifi from disabled starts client mode. - */ - @Test - public void enableWifi() throws Exception { - assertInDisabledState(); - - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - - mClientListener.onStarted(); - mLooper.dispatchAll(); - - assertInEnabledState(); - } - - /** - * Test verifying that we can enter scan mode when the scan mode changes - */ - @Test - public void enableScanMode() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - mActiveModeWarden.scanAlwaysModeChanged(); - mLooper.dispatchAll(); - verify(mClientModeManager).start(); - verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY); - assertInEnabledState(); - verify(mClientModeManager, never()).stop(); - } - - /** - * Verify that if scanning is enabled at startup, we enter scan mode - */ - @Test - public void testEnterScanModeAtStartWhenSet() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - - mActiveModeWarden = createActiveModeWarden(); - mActiveModeWarden.start(); - mLooper.dispatchAll(); - - assertInEnabledState(); - } - - /** - * Verify that if Wifi is enabled at startup, we enter client mode - */ - @Test - public void testEnterClientModeAtStartWhenSet() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); - - mActiveModeWarden = createActiveModeWarden(); - mActiveModeWarden.start(); - mLooper.dispatchAll(); - - assertInEnabledState(); - - verify(mClientModeManager).start(); - verify(mClientModeManager).setRole(ROLE_CLIENT_PRIMARY); - } - - /** - * Do not enter scan mode if location mode disabled. - */ - @Test - public void testDoesNotEnterScanModeWhenLocationModeDisabled() throws Exception { - // Start a new WifiController with wifi disabled - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); - - mActiveModeWarden = createActiveModeWarden(); - mActiveModeWarden.start(); - mLooper.dispatchAll(); - - assertInDisabledState(); - - // toggling scan always available is not sufficient for scan mode - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - mActiveModeWarden.scanAlwaysModeChanged(); - mLooper.dispatchAll(); - - assertInDisabledState(); - } - - /** - * Only enter scan mode if location mode enabled - */ - @Test - public void testEnterScanModeWhenLocationModeEnabled() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); - - reset(mContext); - when(mContext.getResources()).thenReturn(mResources); - mActiveModeWarden = createActiveModeWarden(); - mActiveModeWarden.start(); - mLooper.dispatchAll(); - - ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(bcastRxCaptor.capture(), any(IntentFilter.class)); - BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); - - assertInDisabledState(); - - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); - broadcastReceiver.onReceive(mContext, intent); - mLooper.dispatchAll(); - - assertInEnabledState(); - } - - - /** - * Disabling location mode when in scan mode will disable wifi - */ - @Test - public void testExitScanModeWhenLocationModeDisabled() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - - reset(mContext); - when(mContext.getResources()).thenReturn(mResources); - mActiveModeWarden = createActiveModeWarden(); - mActiveModeWarden.start(); - mLooper.dispatchAll(); - mClientListener.onStarted(); - mLooper.dispatchAll(); - - ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(bcastRxCaptor.capture(), any(IntentFilter.class)); - BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); - - assertInEnabledState(); - - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); - Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); - broadcastReceiver.onReceive(mContext, intent); - mLooper.dispatchAll(); - - mClientListener.onStopped(); - mLooper.dispatchAll(); - - assertInDisabledState(); - } - - /** - * When in Client mode, make sure ECM triggers wifi shutdown. - */ - @Test - public void testEcmOnFromClientMode() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); - enableWifi(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertWifiShutDown(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - } - - /** - * ECM disabling messages, when in client mode (not expected) do not trigger state changes. - */ - @Test - public void testEcmOffInClientMode() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); - enableWifi(); - - // Test with WifiDisableInECBM turned off - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); - - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - } - - /** - * When ECM activates and we are in client mode, disabling ECM should return us to client mode. - */ - @Test - public void testEcmDisabledReturnsToClientMode() throws Exception { - enableWifi(); - assertInEnabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertWifiShutDown(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - - assertInEnabledState(); - } - - /** - * When Ecm mode is enabled, we should shut down wifi when we get an emergency mode changed - * update. - */ - @Test - public void testEcmOnFromScanMode() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - mActiveModeWarden.scanAlwaysModeChanged(); - mLooper.dispatchAll(); - - mClientListener.onStarted(); - mLooper.dispatchAll(); - - assertInEnabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertWifiShutDown(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - } - - /** - * When Ecm mode is disabled, we should not shut down scan mode if we get an emergency mode - * changed update, but we should turn off soft AP - */ - @Test - public void testEcmOffInScanMode() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - mActiveModeWarden.scanAlwaysModeChanged(); - mLooper.dispatchAll(); - - assertInEnabledState(); - - // Test with WifiDisableInECBM turned off: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); - - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - } - - /** - * When ECM is disabled, we should return to scan mode - */ - @Test - public void testEcmDisabledReturnsToScanMode() throws Exception { - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - mActiveModeWarden.scanAlwaysModeChanged(); - mLooper.dispatchAll(); - - assertInEnabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertWifiShutDown(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - - assertInEnabledState(); - } - - /** - * When Ecm mode is enabled, we should shut down wifi when we get an emergency mode changed - * update. - */ - @Test - public void testEcmOnFromSoftApMode() throws Exception { - enterSoftApActiveMode(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - } - - /** - * When Ecm mode is disabled, we should shut down softap mode if we get an emergency mode - * changed update - */ - @Test - public void testEcmOffInSoftApMode() throws Exception { - enterSoftApActiveMode(); - - // Test with WifiDisableInECBM turned off: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); - - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - - verify(mSoftApManager).stop(); - } - - /** - * When ECM is activated and we were in softap mode, we should just return to wifi off when ECM - * ends - */ - @Test - public void testEcmDisabledRemainsDisabledWhenSoftApHadBeenOn() throws Exception { - assertInDisabledState(); - - enterSoftApActiveMode(); - - // verify Soft AP Manager started - verify(mSoftApManager).start(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - mSoftApListener.onStopped(); - mLooper.dispatchAll(); - }); - - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - - assertInDisabledState(); - - // verify no additional calls to enable softap - verify(mSoftApManager).start(); - } - - /** - * Wifi should remain off when already disabled and we enter ECM. - */ - @Test - public void testEcmOnFromDisabledMode() throws Exception { - assertInDisabledState(); - verify(mSoftApManager, never()).start(); - verify(mClientModeManager, never()).start(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - } - - - /** - * Updates about call state change also trigger entry of ECM mode. - */ - @Test - public void testEnterEcmOnEmergencyCallStateChange() throws Exception { - assertInDisabledState(); - - enableWifi(); - assertInEnabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertEnteredEcmMode(() -> { - // test call state changed - mActiveModeWarden.emergencyCallStateChanged(true); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - - mActiveModeWarden.emergencyCallStateChanged(false); - mLooper.dispatchAll(); - - assertInEnabledState(); - } - - /** - * Verify when both ECM and call state changes arrive, we enter ECM mode - */ - @Test - public void testEnterEcmWithBothSignals() throws Exception { - assertInDisabledState(); - - enableWifi(); - assertInEnabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertWifiShutDown(() -> { - mActiveModeWarden.emergencyCallStateChanged(true); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - - assertWifiShutDown(() -> { - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }, 0); // does not cause another shutdown - - // client mode only started once so far - verify(mClientModeManager).start(); - - mActiveModeWarden.emergencyCallStateChanged(false); - mLooper.dispatchAll(); - - // stay in ecm, do not send an additional client mode trigger - assertInEmergencyMode(); - // assert that the underlying state is in disabled state - assertInDisabledState(); - - // client mode still only started once - verify(mClientModeManager).start(); - - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - - // now we can re-enable wifi - verify(mClientModeManager, times(2)).start(); - assertInEnabledState(); - } - - /** - * Verify when both ECM and call state changes arrive but out of order, we enter ECM mode - */ - @Test - public void testEnterEcmWithBothSignalsOutOfOrder() throws Exception { - assertInDisabledState(); - - enableWifi(); - - assertInEnabledState(); - verify(mClientModeManager).start(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - assertInDisabledState(); - - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallStateChanged(true); - mLooper.dispatchAll(); - }, 0); // does not enter ECM state again - - mActiveModeWarden.emergencyCallStateChanged(false); - mLooper.dispatchAll(); - - // stay in ecm, do not send an additional client mode trigger - assertInEmergencyMode(); - // assert that the underlying state is in disabled state - assertInDisabledState(); - - // client mode still only started once - verify(mClientModeManager).start(); - - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - - // now we can re-enable wifi - verify(mClientModeManager, times(2)).start(); - assertInEnabledState(); - } - - /** - * Verify when both ECM and call state changes arrive but completely out of order, - * we still enter and properly exit ECM mode - */ - @Test - public void testEnterEcmWithBothSignalsOppositeOrder() throws Exception { - assertInDisabledState(); - - enableWifi(); - - assertInEnabledState(); - verify(mClientModeManager).start(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallStateChanged(true); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - assertInDisabledState(); - - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }, 0); // still only 1 shutdown - - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - - // stay in ecm, do not send an additional client mode trigger - assertInEmergencyMode(); - // assert that the underlying state is in disabled state - assertInDisabledState(); - - // client mode still only started once - verify(mClientModeManager).start(); - - mActiveModeWarden.emergencyCallStateChanged(false); - mLooper.dispatchAll(); - - // now we can re-enable wifi - verify(mClientModeManager, times(2)).start(); - assertInEnabledState(); - } - - /** - * When ECM is active, we might get addition signals of ECM mode, drop those additional signals, - * we must exit when one of each signal is received. - * - * In any case, duplicate signals indicate a bug from Telephony. Each signal should be turned - * off before it is turned on again. - */ - @Test - public void testProperExitFromEcmModeWithMultipleMessages() throws Exception { - assertInDisabledState(); - - enableWifi(); - - verify(mClientModeManager).start(); - assertInEnabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallbackModeChanged(true); - mActiveModeWarden.emergencyCallStateChanged(true); - mActiveModeWarden.emergencyCallStateChanged(true); - mActiveModeWarden.emergencyCallbackModeChanged(true); - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - assertInDisabledState(); - - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - }, 0); - - // didn't enter client mode again - verify(mClientModeManager).start(); - assertInDisabledState(); - - // now we will exit ECM - mActiveModeWarden.emergencyCallStateChanged(false); - mLooper.dispatchAll(); - - // now we can re-enable wifi - verify(mClientModeManager, times(2)).start(); - assertInEnabledState(); - } - - /** - * Toggling wifi when in ECM does not exit ecm mode and enable wifi - */ - @Test - public void testWifiDoesNotToggleOnWhenInEcm() throws Exception { - assertInDisabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - // test ecm changed - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - - // now toggle wifi and verify we do not start wifi - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - - verify(mClientModeManager, never()).start(); - assertInDisabledState(); - } - - @Test - public void testAirplaneModeDoesNotToggleOnWhenInEcm() throws Exception { - // TODO(b/139829963): investigate the expected behavior is when toggling airplane mode in - // ECM - } - - /** - * Toggling scan mode when in ECM does not exit ecm mode and enable scan mode - */ - @Test - public void testScanModeDoesNotToggleOnWhenInEcm() throws Exception { - assertInDisabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - - // now enable scanning and verify we do not start wifi - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - mActiveModeWarden.scanAlwaysModeChanged(); - mLooper.dispatchAll(); - - verify(mClientModeManager, never()).start(); - assertInDisabledState(); - } - - - /** - * Toggling softap mode when in ECM does not exit ecm mode and enable softap - */ - @Test - public void testSoftApModeDoesNotToggleOnWhenInEcm() throws Exception { - assertInDisabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - - mActiveModeWarden.startSoftAp( - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mSoftApCapability)); - mLooper.dispatchAll(); - - verify(mSoftApManager, never()).start(); - assertInDisabledState(); - } - - /** - * Toggling off softap mode when in ECM does not induce a mode change - */ - @Test - public void testSoftApStoppedDoesNotSwitchModesWhenInEcm() throws Exception { - assertInDisabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - - mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_UNSPECIFIED); - mLooper.dispatchAll(); - - assertInDisabledState(); - verifyNoMoreInteractions(mSoftApManager, mClientModeManager); - } - - /** - * Toggling softap mode when in airplane mode needs to enable softap - */ - @Test - public void testSoftApModeToggleWhenInAirplaneMode() throws Exception { - // Test with airplane mode turned on: - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - - // Turn on SoftAp. - mActiveModeWarden.startSoftAp( - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mSoftApCapability)); - mLooper.dispatchAll(); - verify(mSoftApManager).start(); - - // Turn off SoftAp. - mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_UNSPECIFIED); - mLooper.dispatchAll(); - - verify(mSoftApManager).stop(); - } - - /** - * Toggling off scan mode when in ECM does not induce a mode change - */ - @Test - public void testScanModeStoppedSwitchModeToDisabledStateWhenInEcm() throws Exception { - enterScanOnlyModeActiveState(); - assertInEnabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - - // Spurious onStopped - mClientListener.onStopped(); - mLooper.dispatchAll(); - - assertInDisabledState(); - } - - /** - * Toggling off client mode when in ECM does not induce a mode change - */ - @Test - public void testClientModeStoppedSwitchModeToDisabledStateWhenInEcm() throws Exception { - enterClientModeActiveState(); - assertInEnabledState(); - - // Test with WifiDisableInECBM turned on: - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - assertEnteredEcmMode(() -> { - // test ecm changed - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - - // Spurious onStopped - mClientListener.onStopped(); - mLooper.dispatchAll(); - - assertInDisabledState(); - } - - /** - * When AP mode is enabled and wifi was previously in AP mode, we should return to - * EnabledState after the AP is disabled. - * Enter EnabledState, activate AP mode, disable AP mode. - * <p> - * Expected: AP should successfully start and exit, then return to EnabledState. - */ - @Test - public void testReturnToEnabledStateAfterAPModeShutdown() throws Exception { - enableWifi(); - assertInEnabledState(); - verify(mClientModeManager).start(); - - mActiveModeWarden.startSoftAp( - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mSoftApCapability)); - // add an "unexpected" sta mode stop to simulate a single interface device - mClientListener.onStopped(); - mLooper.dispatchAll(); - - // Now stop the AP - mSoftApListener.onStopped(); - mLooper.dispatchAll(); - - // We should re-enable client mode - verify(mClientModeManager, times(2)).start(); - assertInEnabledState(); - } - - /** - * When in STA mode and SoftAP is enabled and the device supports STA+AP (i.e. the STA wasn't - * shut down when the AP started), both modes will be running concurrently. - * - * Then when the AP is disabled, we should remain in STA mode. - * - * Enter EnabledState, activate AP mode, toggle WiFi off. - * <p> - * Expected: AP should successfully start and exit, then return to EnabledState. - */ - @Test - public void testReturnToEnabledStateAfterWifiEnabledShutdown() throws Exception { - enableWifi(); - assertInEnabledState(); - verify(mClientModeManager).start(); - - mActiveModeWarden.startSoftAp( - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mSoftApCapability)); - mLooper.dispatchAll(); - - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); - mActiveModeWarden.wifiToggled(); - mSoftApListener.onStopped(); - mLooper.dispatchAll(); - - // wasn't called again - verify(mClientModeManager).start(); - assertInEnabledState(); - } - - @Test - public void testRestartWifiStackInEnabledStateTriggersBugReport() throws Exception { - enableWifi(); - mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - mLooper.dispatchAll(); - verify(mClientModeImpl).takeBugReport(anyString(), anyString()); - } - - @Test - public void testRestartWifiWatchdogDoesNotTriggerBugReport() throws Exception { - enableWifi(); - mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - mLooper.dispatchAll(); - verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); - } - - /** - * When in sta mode, CMD_RECOVERY_DISABLE_WIFI messages should trigger wifi to disable. - */ - @Test - public void testRecoveryDisabledTurnsWifiOff() throws Exception { - enableWifi(); - assertInEnabledState(); - mActiveModeWarden.recoveryDisableWifi(); - mLooper.dispatchAll(); - verify(mClientModeManager).stop(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - assertInDisabledState(); - } - - /** - * When wifi is disabled, CMD_RECOVERY_DISABLE_WIFI should not trigger a state change. - */ - @Test - public void testRecoveryDisabledWhenWifiAlreadyOff() throws Exception { - assertInDisabledState(); - assertWifiShutDown(() -> { - mActiveModeWarden.recoveryDisableWifi(); - mLooper.dispatchAll(); - }); - } - - /** - * The command to trigger a WiFi reset should not trigger any action by WifiController if we - * are not in STA mode. - * WiFi is not in connect mode, so any calls to reset the wifi stack due to connection failures - * should be ignored. - * Create and start WifiController in DisabledState, send command to restart WiFi - * <p> - * Expected: WiFiController should not call ActiveModeWarden.disableWifi() - */ - @Test - public void testRestartWifiStackInDisabledState() throws Exception { - assertInDisabledState(); - - mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - mLooper.dispatchAll(); - - assertInDisabledState(); - verifyNoMoreInteractions(mClientModeManager, mSoftApManager); - } - - /** - * The command to trigger a WiFi reset should trigger a wifi reset in ClientModeImpl through - * the ActiveModeWarden.shutdownWifi() call when in STA mode. - * When WiFi is in scan mode, calls to reset the wifi stack due to native failure - * should trigger a supplicant stop, and subsequently, a driver reload. - * Create and start WifiController in EnabledState, send command to restart WiFi - * <p> - * Expected: WiFiController should call ActiveModeWarden.shutdownWifi() and - * ActiveModeWarden should enter SCAN_ONLY mode and the wifi driver should be started. - */ - @Test - public void testRestartWifiStackInDisabledStateWithScanState() throws Exception { - assertInDisabledState(); - - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - mActiveModeWarden.scanAlwaysModeChanged(); - mLooper.dispatchAll(); - - assertInEnabledState(); - verify(mClientModeManager).start(); - verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY); - - mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - mLooper.dispatchAll(); - - verify(mClientModeManager).stop(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - assertInDisabledState(); - - mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); - mLooper.dispatchAll(); - - verify(mClientModeManager, times(2)).start(); - verify(mClientModeManager, times(2)).setRole(ROLE_CLIENT_SCAN_ONLY); - assertInEnabledState(); - } - - /** - * The command to trigger a WiFi reset should trigger a wifi reset in ClientModeImpl through - * the ActiveModeWarden.shutdownWifi() call when in STA mode. - * WiFi is in connect mode, calls to reset the wifi stack due to connection failures - * should trigger a supplicant stop, and subsequently, a driver reload. - * Create and start WifiController in EnabledState, send command to restart WiFi - * <p> - * Expected: WiFiController should call ActiveModeWarden.shutdownWifi() and - * ActiveModeWarden should enter CONNECT_MODE and the wifi driver should be started. - */ - @Test - public void testRestartWifiStackInEnabledState() throws Exception { - enableWifi(); - assertInEnabledState(); - verify(mClientModeManager).start(); - - assertWifiShutDown(() -> { - mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - mLooper.dispatchAll(); - // Complete the stop - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - - // still only started once - verify(mClientModeManager).start(); - - mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); - mLooper.dispatchAll(); - - // started again - verify(mClientModeManager, times(2)).start(); - assertInEnabledState(); - } - - /** - * The command to trigger a WiFi reset should not trigger a reset when in ECM mode. - * Enable wifi and enter ECM state, send command to restart wifi. - * <p> - * Expected: The command to trigger a wifi reset should be ignored and we should remain in ECM - * mode. - */ - @Test - public void testRestartWifiStackDoesNotExitECMMode() throws Exception { - enableWifi(); - assertInEnabledState(); - verify(mClientModeManager).start(); - verify(mClientModeManager).setRole(ROLE_CLIENT_PRIMARY); - - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallStateChanged(true); - mLooper.dispatchAll(); - mClientListener.onStopped(); - mLooper.dispatchAll(); - }); - assertInEmergencyMode(); - assertInDisabledState(); - verify(mClientModeManager).stop(); - verify(mClientModeManager, atLeastOnce()).getRole(); - - mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - mLooper.dispatchAll(); - - verify(mClientModeManager).start(); // wasn't called again - assertInEmergencyMode(); - assertInDisabledState(); - verifyNoMoreInteractions(mClientModeManager, mSoftApManager); - } - - /** - * The command to trigger a WiFi reset should trigger a reset when in AP mode. - * Enter AP mode, send command to restart wifi. - * <p> - * Expected: The command to trigger a wifi reset should trigger wifi shutdown. - */ - @Test - public void testRestartWifiStackFullyStopsWifi() throws Exception { - mActiveModeWarden.startSoftAp(new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null, mSoftApCapability)); - mLooper.dispatchAll(); - verify(mSoftApManager).start(); - verify(mSoftApManager).setRole(ROLE_SOFTAP_LOCAL_ONLY); - - assertWifiShutDown(() -> { - mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_STA_IFACE_DOWN); - mLooper.dispatchAll(); - }); - } - - /** - * Tests that when Wifi is already disabled and another Wifi toggle command arrives, - * don't enter scan mode if {@link WifiSettingsStore#isScanAlwaysAvailable()} is false. - * Note: {@link WifiSettingsStore#isScanAlwaysAvailable()} returns false if either the wifi - * scanning is disabled and airplane mode is on. - */ - @Test - public void staDisabled_toggleWifiOff_scanNotAvailable_dontGoToScanMode() { - assertInDisabledState(); - - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - - assertInDisabledState(); - verify(mClientModeManager, never()).start(); - } - - /** - * Tests that when Wifi is already disabled and another Wifi toggle command arrives, - * enter scan mode if {@link WifiSettingsStore#isScanAlwaysAvailable()} is true. - * Note: {@link WifiSettingsStore#isScanAlwaysAvailable()} returns true if both the wifi - * scanning is enabled and airplane mode is off. - */ - @Test - public void staDisabled_toggleWifiOff_scanAvailable_goToScanMode() { - assertInDisabledState(); - - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - - mActiveModeWarden.wifiToggled(); - mLooper.dispatchAll(); - - assertInEnabledState(); - verify(mClientModeManager).start(); - verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY); - } - - /** - * Tests that if the carrier config to disable Wifi is enabled during ECM, Wifi is shut down - * when entering ECM and turned back on when exiting ECM. - */ - @Test - public void ecmDisablesWifi_exitEcm_restartWifi() throws Exception { - enterClientModeActiveState(); - - verify(mClientModeManager).start(); - - when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); - assertEnteredEcmMode(() -> { - mActiveModeWarden.emergencyCallbackModeChanged(true); - mLooper.dispatchAll(); - }); - assertInEnabledState(); - verify(mClientModeManager).stop(); - - mActiveModeWarden.emergencyCallbackModeChanged(false); - mLooper.dispatchAll(); - - assertThat(mActiveModeWarden.isInEmergencyMode()).isFalse(); - // client mode restarted - verify(mClientModeManager, times(2)).start(); - assertInEnabledState(); - } - - @Test - public void testUpdateCapabilityInSoftApActiveMode() throws Exception { - SoftApCapability testCapability = new SoftApCapability(0); - enterSoftApActiveMode(); - mActiveModeWarden.updateSoftApCapability(testCapability); - mLooper.dispatchAll(); - verify(mSoftApManager).updateCapability(testCapability); - } - - @Test - public void testUpdateConfigInSoftApActiveMode() throws Exception { - SoftApConfiguration testConfig = new SoftApConfiguration.Builder() - .setSsid("Test123").build(); - enterSoftApActiveMode(); - mActiveModeWarden.updateSoftApConfiguration(testConfig); - mLooper.dispatchAll(); - verify(mSoftApManager).updateConfiguration(testConfig); - } - - @Test - public void testUpdateCapabilityInNonSoftApActiveMode() throws Exception { - SoftApCapability testCapability = new SoftApCapability(0); - enterClientModeActiveState(); - mActiveModeWarden.updateSoftApCapability(testCapability); - mLooper.dispatchAll(); - verify(mSoftApManager, never()).updateCapability(any()); - } - - @Test - public void testUpdateConfigInNonSoftApActiveMode() throws Exception { - SoftApConfiguration testConfig = new SoftApConfiguration.Builder() - .setSsid("Test123").build(); - enterClientModeActiveState(); - mActiveModeWarden.updateSoftApConfiguration(testConfig); - mLooper.dispatchAll(); - verify(mSoftApManager, never()).updateConfiguration(any()); - } - - @Test - public void interfaceAvailabilityListener() throws Exception { - assertFalse(mActiveModeWarden.canRequestMoreClientModeManagers()); - assertFalse(mActiveModeWarden.canRequestMoreSoftApManagers()); - - assertNotNull(mClientIfaceAvailableListener.getValue()); - assertNotNull(mSoftApIfaceAvailableListener.getValue()); - - mClientIfaceAvailableListener.getValue().onAvailabilityChanged(true); - mLooper.dispatchAll(); - assertTrue(mActiveModeWarden.canRequestMoreClientModeManagers()); - - mSoftApIfaceAvailableListener.getValue().onAvailabilityChanged(true); - mLooper.dispatchAll(); - assertTrue(mActiveModeWarden.canRequestMoreSoftApManagers()); - - mClientIfaceAvailableListener.getValue().onAvailabilityChanged(false); - mLooper.dispatchAll(); - assertFalse(mActiveModeWarden.canRequestMoreClientModeManagers()); - - mSoftApIfaceAvailableListener.getValue().onAvailabilityChanged(false); - mLooper.dispatchAll(); - assertFalse(mActiveModeWarden.canRequestMoreSoftApManagers()); - } - - @Test - public void isStaApConcurrencySupported() throws Exception { - when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false); - assertFalse(mActiveModeWarden.isStaApConcurrencySupported()); - - when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true); - assertTrue(mActiveModeWarden.isStaApConcurrencySupported()); - } - - @Test - public void airplaneModeToggleOnDisablesWifi() throws Exception { - enterClientModeActiveState(); - assertInEnabledState(); - - assertWifiShutDown(() -> { - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - mActiveModeWarden.airplaneModeToggled(); - mLooper.dispatchAll(); - }); - - mClientListener.onStopped(); - mLooper.dispatchAll(); - assertInDisabledState(); - } - - @Test - public void airplaneModeToggleOnDisablesSoftAp() throws Exception { - enterSoftApActiveMode(); - assertInEnabledState(); - - assertWifiShutDown(() -> { - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - mActiveModeWarden.airplaneModeToggled(); - mLooper.dispatchAll(); - }); - - mSoftApListener.onStopped(); - mLooper.dispatchAll(); - assertInDisabledState(); - } - - @Test - public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager() - throws Exception { - enterClientModeActiveState(); - assertInEnabledState(); - - // APM toggle on - assertWifiShutDown(() -> { - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - mActiveModeWarden.airplaneModeToggled(); - mLooper.dispatchAll(); - }); - - - // APM toggle off before the stop is complete. - assertInEnabledState(); - when(mClientModeManager.isStopping()).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - mActiveModeWarden.airplaneModeToggled(); - mLooper.dispatchAll(); - - mClientListener.onStopped(); - mLooper.dispatchAll(); - - verify(mClientModeManager, times(2)).start(); - verify(mClientModeManager, times(2)).setRole(ROLE_CLIENT_PRIMARY); - - mClientListener.onStarted(); - mLooper.dispatchAll(); - - // We should be back to enabled state. - assertInEnabledState(); - } - - @Test - public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager2() - throws Exception { - enterClientModeActiveState(); - assertInEnabledState(); - - // APM toggle on - assertWifiShutDown(() -> { - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - mActiveModeWarden.airplaneModeToggled(); - mLooper.dispatchAll(); - }); - - - // APM toggle off before the stop is complete. - assertInEnabledState(); - when(mClientModeManager.isStopping()).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - mActiveModeWarden.airplaneModeToggled(); - // This test is identical to - // airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager, except the - // dispatchAll() here is removed. There could be a race between airplaneModeToggled and - // mClientListener.onStopped(). See b/160105640#comment5. - - mClientListener.onStopped(); - mLooper.dispatchAll(); - - verify(mClientModeManager, times(2)).start(); - verify(mClientModeManager, times(2)).setRole(ROLE_CLIENT_PRIMARY); - - mClientListener.onStarted(); - mLooper.dispatchAll(); - - // We should be back to enabled state. - assertInEnabledState(); - } - - @Test - public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithTwoModeManager() - throws Exception { - enterClientModeActiveState(); - enterSoftApActiveMode(); - assertInEnabledState(); - - // APM toggle on - assertWifiShutDown(() -> { - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - mActiveModeWarden.airplaneModeToggled(); - mLooper.dispatchAll(); - }); - - - // APM toggle off before the stop is complete. - assertInEnabledState(); - when(mClientModeManager.isStopping()).thenReturn(true); - when(mSoftApManager.isStopping()).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - mActiveModeWarden.airplaneModeToggled(); - mLooper.dispatchAll(); - - // AP stopped, should not process APM toggle. - mSoftApListener.onStopped(); - mLooper.dispatchAll(); - verify(mClientModeManager, times(1)).start(); - verify(mClientModeManager, times(1)).setRole(ROLE_CLIENT_PRIMARY); - - // STA also stopped, should process APM toggle. - mClientListener.onStopped(); - mLooper.dispatchAll(); - verify(mClientModeManager, times(2)).start(); - verify(mClientModeManager, times(2)).setRole(ROLE_CLIENT_PRIMARY); - - mClientListener.onStarted(); - mLooper.dispatchAll(); - - // We should be back to enabled state. - assertInEnabledState(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/BinderUtil.java b/tests/wifitests/src/com/android/server/wifi/BinderUtil.java deleted file mode 100644 index 107de7c8d..000000000 --- a/tests/wifitests/src/com/android/server/wifi/BinderUtil.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.os.Binder; - -/** - * Utilities for faking the calling uid in Binder. - */ -public class BinderUtil { - /** - * Fake the calling uid in Binder. - * @param uid the calling uid that Binder should return from now on - */ - public static void setUid(int uid) { - Binder.restoreCallingIdentity((((long) uid) << 32) | Binder.getCallingPid()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/BinderUtilTest.java b/tests/wifitests/src/com/android/server/wifi/BinderUtilTest.java deleted file mode 100644 index af570a1e6..000000000 --- a/tests/wifitests/src/com/android/server/wifi/BinderUtilTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import android.os.Binder; - -import androidx.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for {@link com.android.server.wifi.BinderUtil}. - */ -@SmallTest -public class BinderUtilTest extends WifiBaseTest { - static final int FAKE_UID = 30000000; - - private long mToken; - - /** - * Sets up the test harness before running a test. - */ - @Before - public void setUp() { - mToken = Binder.clearCallingIdentity(); - } - - /** - * Cleans up the test harness after running a test. - */ - @After - public void cleanUp() { - Binder.restoreCallingIdentity(mToken); - } - - /** - * Test using {@link BinderUtil.setUid} to set and restore the Binder uid. - */ - @Test - public void setUid() { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - assertFalse(uid == FAKE_UID); - - // Verify that setUid() can be used to fake the Binder uid without affecting the pid. - BinderUtil.setUid(FAKE_UID); - assertEquals(pid, Binder.getCallingPid()); - assertEquals(FAKE_UID, Binder.getCallingUid()); - - // Verify that setUid() can be used to restore the original Binder uid without affecting the - // pid. - BinderUtil.setUid(uid); - assertEquals(pid, Binder.getCallingPid()); - assertEquals(uid, Binder.getCallingUid()); - } - - /** - * Test using {@link BinderUtil.setUid} to set the Binder uid and - * {@link Binder.restoreCallingIdentity} to restore it. - */ - @Test - public void setUidAndRestoreCallingIdentity() { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - assertFalse(uid == FAKE_UID); - - // Verify that setUid() can be used to fake the Binder uid without affecting the pid. - BinderUtil.setUid(FAKE_UID); - assertEquals(pid, Binder.getCallingPid()); - assertEquals(FAKE_UID, Binder.getCallingUid()); - - // Verify that the setUid() calls above did not break Binder.restoreCallingIdentity(). - Binder.restoreCallingIdentity(mToken); - assertEquals(pid, Binder.getCallingPid()); - assertEquals(uid, Binder.getCallingUid()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java deleted file mode 100644 index 1007391e3..000000000 --- a/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java +++ /dev/null @@ -1,839 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.times; - -import android.content.Context; -import android.net.wifi.ScanResult; -import android.util.LocalLog; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -/** - * Unit tests for {@link com.android.server.wifi.BssidBlocklistMonitor}. - */ -@SmallTest -public class BssidBlocklistMonitorTest { - private static final int TEST_NUM_MAX_FIRMWARE_SUPPORT_BSSIDS = 3; - private static final String TEST_SSID_1 = "TestSSID1"; - private static final String TEST_SSID_2 = "TestSSID2"; - private static final String TEST_SSID_3 = "TestSSID3"; - private static final String TEST_BSSID_1 = "0a:08:5c:67:89:00"; - private static final String TEST_BSSID_2 = "0a:08:5c:67:89:01"; - private static final String TEST_BSSID_3 = "0a:08:5c:67:89:02"; - private static final int TEST_GOOD_RSSI = -50; - private static final int TEST_SUFFICIENT_RSSI = -67; - private static final int MIN_RSSI_DIFF_TO_UNBLOCK_BSSID = 5; - private static final int TEST_FRAMEWORK_BLOCK_REASON = - BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE; - private static final int TEST_L2_FAILURE = BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION; - private static final int TEST_DHCP_FAILURE = BssidBlocklistMonitor.REASON_DHCP_FAILURE; - private static final long BASE_BLOCKLIST_DURATION = TimeUnit.MINUTES.toMillis(5); // 5 minutes - private static final long BASE_CONNECTED_SCORE_BLOCKLIST_DURATION = - TimeUnit.SECONDS.toMillis(30); - private static final long ABNORMAL_DISCONNECT_TIME_WINDOW_MS = TimeUnit.SECONDS.toMillis(30); - private static final long ABNORMAL_DISCONNECT_RESET_TIME_MS = TimeUnit.HOURS.toMillis(3); - private static final int FAILURE_STREAK_CAP = 7; - private static final Map<Integer, Integer> BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP = - Map.ofEntries( - Map.entry(BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, 1), - Map.entry(BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, 1), - Map.entry(BssidBlocklistMonitor.REASON_WRONG_PASSWORD, 1), - Map.entry(BssidBlocklistMonitor.REASON_EAP_FAILURE, 1), - Map.entry(BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION, 3), - Map.entry(BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, 3), - Map.entry(BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE, 3), - Map.entry(BssidBlocklistMonitor.REASON_DHCP_FAILURE, 3), - Map.entry(BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, 3), - Map.entry(BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE, 1), - Map.entry(BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT, 1), - Map.entry(BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE, 1) - ); - private static final int NUM_FAILURES_TO_BLOCKLIST = - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(TEST_L2_FAILURE); - - @Mock private Context mContext; - @Mock private WifiConnectivityHelper mWifiConnectivityHelper; - @Mock private WifiLastResortWatchdog mWifiLastResortWatchdog; - @Mock private Clock mClock; - @Mock private LocalLog mLocalLog; - @Mock private WifiScoreCard mWifiScoreCard; - @Mock private ScoringParams mScoringParams; - - private MockResources mResources; - private BssidBlocklistMonitor mBssidBlocklistMonitor; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - when(mWifiConnectivityHelper.getMaxNumBlacklistBssid()) - .thenReturn(TEST_NUM_MAX_FIRMWARE_SUPPORT_BSSIDS); - when(mScoringParams.getSufficientRssi(anyInt())).thenReturn(TEST_SUFFICIENT_RSSI); - mResources = new MockResources(); - mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorBaseBlockDurationMs, - (int) BASE_BLOCKLIST_DURATION); - mResources.setInteger( - R.integer.config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs, - (int) BASE_CONNECTED_SCORE_BLOCKLIST_DURATION); - mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorFailureStreakCap, - FAILURE_STREAK_CAP); - mResources.setInteger(R.integer.config_wifiBssidBlocklistAbnormalDisconnectTimeWindowMs, - (int) ABNORMAL_DISCONNECT_TIME_WINDOW_MS); - mResources.setInteger( - R.integer.config_wifiBssidBlocklistMonitorApUnableToHandleNewStaThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA)); - mResources.setInteger( - R.integer.config_wifiBssidBlocklistMonitorNetworkValidationFailureThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE)); - mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorWrongPasswordThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_WRONG_PASSWORD)); - mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorEapFailureThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_EAP_FAILURE)); - mResources.setInteger( - R.integer.config_wifiBssidBlocklistMonitorAssociationRejectionThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION)); - mResources.setInteger( - R.integer.config_wifiBssidBlocklistMonitorAssociationTimeoutThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT)); - mResources.setInteger( - R.integer.config_wifiBssidBlocklistMonitorAuthenticationFailureThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE)); - mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorDhcpFailureThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_DHCP_FAILURE)); - mResources.setInteger( - R.integer.config_wifiBssidBlocklistMonitorAbnormalDisconnectThreshold, - BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT)); - - when(mContext.getResources()).thenReturn(mResources); - mBssidBlocklistMonitor = new BssidBlocklistMonitor(mContext, mWifiConnectivityHelper, - mWifiLastResortWatchdog, mClock, mLocalLog, mWifiScoreCard, mScoringParams); - } - - private void verifyAddTestBssidToBlocklist() { - mBssidBlocklistMonitor.handleBssidConnectionFailure( - TEST_BSSID_1, TEST_SSID_1, - BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, TEST_GOOD_RSSI); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - // Verify adding 2 BSSID for SSID_1 and 1 BSSID for SSID_2 to the blocklist. - private void verifyAddMultipleBssidsToBlocklist() { - when(mClock.getWallClockMillis()).thenReturn(0L); - mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_1, - TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, - TEST_GOOD_RSSI); - when(mClock.getWallClockMillis()).thenReturn(1L); - mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_2, - TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, - TEST_GOOD_RSSI); - mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_3, - TEST_SSID_2, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, - TEST_GOOD_RSSI); - - // Verify that we have 3 BSSIDs in the blocklist. - Set<String> bssidList = mBssidBlocklistMonitor.updateAndGetBssidBlocklist(); - assertEquals(3, bssidList.size()); - assertTrue(bssidList.contains(TEST_BSSID_1)); - assertTrue(bssidList.contains(TEST_BSSID_2)); - assertTrue(bssidList.contains(TEST_BSSID_3)); - } - - private void handleBssidConnectionFailureMultipleTimes(String bssid, int reason, int times) { - handleBssidConnectionFailureMultipleTimes(bssid, TEST_SSID_1, reason, times); - } - - private void handleBssidConnectionFailureMultipleTimes(String bssid, String ssid, int reason, - int times) { - for (int i = 0; i < times; i++) { - mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid, ssid, reason, - TEST_GOOD_RSSI); - } - } - - /** - * Verify updateAndGetNumBlockedBssidsForSsid returns the correct number of blocked BSSIDs. - */ - @Test - public void testUpdateAndGetNumBlockedBssidsForSsid() { - verifyAddMultipleBssidsToBlocklist(); - assertEquals(2, mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(TEST_SSID_1)); - assertEquals(1, mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(TEST_SSID_2)); - } - - /** - * Verify that updateAndGetBssidBlocklist removes expired blocklist entries and clears - * all failure counters for those networks. - */ - @Test - public void testBssidIsRemovedFromBlocklistAfterTimeout() { - verifyAddTestBssidToBlocklist(); - // Verify TEST_BSSID_1 is not removed from the blocklist until sufficient time have passed. - when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - - // Verify that TEST_BSSID_1 is removed from the blocklist after the timeout duration. - // By default there is no blocklist streak so the timeout duration is simply - // BASE_BLOCKLIST_DURATION - when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - } - - /** - * Verify that updateAndGetBssidBlocklist(ssid) updates firmware roaming configuration - * if a BSSID that belongs to the ssid is removed from blocklist. - */ - @Test - public void testBssidRemovalUpdatesFirmwareConfiguration() { - verifyAddTestBssidToBlocklist(); - when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1); - assertEquals(0, mBssidBlocklistMonitor - .updateAndGetBssidBlocklistForSsid(TEST_SSID_1).size()); - verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(eq(new ArrayList<>()), - eq(new ArrayList<>())); - } - - /** - * Verify that updateAndGetBssidBlocklist(ssid) does not update firmware roaming configuration - * if there are no BSSIDs belonging to the ssid removed from blocklist. - */ - @Test - public void testBssidRemovalNotUpdateFirmwareConfiguration() { - verifyAddTestBssidToBlocklist(); - when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1); - assertEquals(0, mBssidBlocklistMonitor - .updateAndGetBssidBlocklistForSsid(TEST_SSID_2).size()); - verify(mWifiConnectivityHelper, never()).setFirmwareRoamingConfiguration( - eq(new ArrayList<>()), eq(new ArrayList<>())); - } - - /** - * Verify that when adding a AP that had already been failing (therefore has a blocklist - * streak), we are setting the blocklist duration using an exponential backoff technique. - */ - @Test - public void testBssidIsRemoveFromBlocklistAfterTimoutExponentialBackoff() { - verifyAddTestBssidToBlocklist(); - int multiplier = 2; - long duration = 0; - for (int i = 1; i <= FAILURE_STREAK_CAP; i++) { - when(mWifiScoreCard.getBssidBlocklistStreak(anyString(), anyString(), anyInt())) - .thenReturn(i); - when(mClock.getWallClockMillis()).thenReturn(0L); - verifyAddTestBssidToBlocklist(); - - // calculate the expected blocklist duration then verify that timeout happens - // exactly after the duration. - duration = multiplier * BASE_BLOCKLIST_DURATION; - when(mClock.getWallClockMillis()).thenReturn(duration); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - when(mClock.getWallClockMillis()).thenReturn(duration + 1); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - multiplier *= 2; - } - - // finally verify that the timout is capped by the FAILURE_STREAK_CAP - when(mWifiScoreCard.getBssidBlocklistStreak(anyString(), anyString(), anyInt())) - .thenReturn(FAILURE_STREAK_CAP + 1); - when(mClock.getWallClockMillis()).thenReturn(0L); - verifyAddTestBssidToBlocklist(); - when(mClock.getWallClockMillis()).thenReturn(duration); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - when(mClock.getWallClockMillis()).thenReturn(duration + 1); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - } - - /** - * Verify that consecutive failures will add a BSSID to blocklist. - */ - @Test - public void testRepeatedConnectionFailuresAddToBlocklist() { - // First verify that n-1 failrues does not add the BSSID to blocklist - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, - NUM_FAILURES_TO_BLOCKLIST - 1); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Simulate a long time passing to make sure failure counters are not being cleared through - // some time based check - when(mClock.getWallClockMillis()).thenReturn(10 * BASE_BLOCKLIST_DURATION); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Verify that 1 more failure will add the BSSID to blacklist. - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, 1); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - /** - * Verify that only abnormal disconnects that happened in a window of time right after - * connection gets counted in the BssidBlocklistMonitor. - */ - @Test - public void testAbnormalDisconnectRecencyCheck() { - // does some setup so that 1 failure is enough to add the BSSID to blocklist. - when(mWifiScoreCard.getBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT)).thenReturn(1); - - // simulate an abnormal disconnect coming in after the allowed window of time - when(mWifiScoreCard.getBssidConnectionTimestampMs(TEST_SSID_1, TEST_BSSID_1)) - .thenReturn(0L); - when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_TIME_WINDOW_MS + 1); - assertFalse(mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_1, TEST_SSID_1, - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, TEST_GOOD_RSSI)); - verify(mWifiScoreCard, never()).incrementBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT); - - // simulate another abnormal disconnect within the time window and verify the BSSID is - // added to blocklist. - when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_TIME_WINDOW_MS); - assertTrue(mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_1, TEST_SSID_1, - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, TEST_GOOD_RSSI)); - verify(mWifiScoreCard).incrementBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT); - } - - /** - * Verify that when the BSSID blocklist streak is greater or equal to 1, then we block a - * BSSID on a single failure regardless of failure type. - */ - @Test - public void testBlocklistStreakExpeditesAddingToBlocklist() { - when(mWifiScoreCard.getBssidBlocklistStreak(anyString(), anyString(), anyInt())) - .thenReturn(1); - assertTrue(mBssidBlocklistMonitor.handleBssidConnectionFailure( - TEST_BSSID_1, TEST_SSID_1, TEST_L2_FAILURE, TEST_GOOD_RSSI)); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - /** - * Verify that onSuccessfulConnection resets L2 related failure counts. - */ - @Test - public void testL2FailureCountIsResetAfterSuccessfulConnection() { - // First simulate getting a particular L2 failure n-1 times - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, - NUM_FAILURES_TO_BLOCKLIST - 1); - - // Verify that a connection success event will clear the failure count. - mBssidBlocklistMonitor.handleBssidConnectionSuccess(TEST_BSSID_1, TEST_SSID_1); - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, - NUM_FAILURES_TO_BLOCKLIST - 1); - - // Verify we have not blocklisted anything yet because the failure count was cleared. - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Verify that TEST_BSSID_1 is added to blocklist after 1 more failure. - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, 1); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - /** - * Verify that handleDhcpProvisioningSuccess resets DHCP failure counts. - */ - @Test - public void testL3FailureCountIsResetAfterDhcpConfiguration() { - // First simulate getting an DHCP failure n-1 times. - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_DHCP_FAILURE, - NUM_FAILURES_TO_BLOCKLIST - 1); - - // Verify that a dhcp provisioning success event will clear appropirate failure counts. - mBssidBlocklistMonitor.handleDhcpProvisioningSuccess(TEST_BSSID_1, TEST_SSID_1); - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_DHCP_FAILURE, - NUM_FAILURES_TO_BLOCKLIST - 1); - - // Verify we have not blocklisted anything yet because the failure count was cleared. - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Verify that TEST_BSSID_1 is added to blocklist after 1 more failure. - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_DHCP_FAILURE, 1); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - /** - * Verify that handleBssidConnectionSuccess resets appropriate blocklist streak counts, and - * notifies WifiScorecard of the successful connection. - */ - @Test - public void testNetworkConnectionResetsBlocklistStreak() { - when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_RESET_TIME_MS + 1); - mBssidBlocklistMonitor.handleBssidConnectionSuccess(TEST_BSSID_1, TEST_SSID_1); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_WRONG_PASSWORD); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_EAP_FAILURE); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE); - verify(mWifiScoreCard).setBssidConnectionTimestampMs(TEST_SSID_1, TEST_BSSID_1, - ABNORMAL_DISCONNECT_RESET_TIME_MS + 1); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE); - } - - /** - * Verify that the abnormal disconnect streak is not reset if insufficient time has passed. - */ - @Test - public void testNetworkConnectionNotResetAbnormalDisconnectStreak() { - when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_RESET_TIME_MS); - mBssidBlocklistMonitor.handleBssidConnectionSuccess(TEST_BSSID_1, TEST_SSID_1); - verify(mWifiScoreCard).setBssidConnectionTimestampMs(TEST_SSID_1, TEST_BSSID_1, - ABNORMAL_DISCONNECT_RESET_TIME_MS); - verify(mWifiScoreCard, never()).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT); - } - - /** - * Verify that the streak count for REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE is not reset - * if insufficient time has passed. - */ - @Test - public void testNetworkConnectionNotResetConnectedScoreStreak() { - when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_RESET_TIME_MS); - mBssidBlocklistMonitor.handleBssidConnectionSuccess(TEST_BSSID_1, TEST_SSID_1); - verify(mWifiScoreCard).setBssidConnectionTimestampMs(TEST_SSID_1, TEST_BSSID_1, - ABNORMAL_DISCONNECT_RESET_TIME_MS); - verify(mWifiScoreCard, never()).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE); - } - - /** - * Verify that handleDhcpProvisioningSuccess resets appropriate blocklist streak counts. - */ - @Test - public void testDhcpProvisioningResetsBlocklistStreak() { - mBssidBlocklistMonitor.handleDhcpProvisioningSuccess(TEST_BSSID_1, TEST_SSID_1); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_DHCP_FAILURE); - } - - /** - * Verify that handleNetworkValidationSuccess resets appropriate blocklist streak counts - * and removes the BSSID from blocklist. - */ - @Test - public void testNetworkValidationResetsBlocklistStreak() { - verifyAddTestBssidToBlocklist(); - mBssidBlocklistMonitor.handleNetworkValidationSuccess(TEST_BSSID_1, TEST_SSID_1); - verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - } - - /** - * Verify that L3 failure counts are not affected when L2 failure counts are reset. - */ - @Test - public void testL3FailureCountIsNotResetByConnectionSuccess() { - // First simulate getting an L3 failure n-1 times. - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_DHCP_FAILURE, - NUM_FAILURES_TO_BLOCKLIST - 1); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Verify that the failure counter is not cleared by |handleBssidConnectionSuccess|. - mBssidBlocklistMonitor.handleBssidConnectionSuccess(TEST_BSSID_1, TEST_SSID_1); - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_DHCP_FAILURE, 1); - assertEquals(1, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - } - - /** - * Verify that the blocklist streak is incremented after adding a BSSID to blocklist. - * And then verify the blocklist streak is not reset by a regular timeout. - */ - @Test - public void testIncrementingBlocklistStreakCount() { - for (Map.Entry<Integer, Integer> entry : BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.entrySet()) { - int reason = entry.getKey(); - int threshold = entry.getValue(); - when(mClock.getWallClockMillis()).thenReturn(0L); - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_SSID_1, reason, threshold); - - // verify that the blocklist streak is incremented - verify(mWifiScoreCard).incrementBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, reason); - - // Verify that TEST_BSSID_1 is removed from the blocklist after the timeout duration. - when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // But the blocklist streak count is not cleared - verify(mWifiScoreCard, never()).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, - reason); - } - } - - /** - * Verify that when a failure signal is received for a BSSID with different SSID from before, - * then the failure counts are reset. - */ - @Test - public void testFailureCountIsResetIfSsidChanges() { - // First simulate getting a particular L2 failure n-1 times - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, - NUM_FAILURES_TO_BLOCKLIST - 1); - - // Verify that when the SSID changes, the failure counts are cleared. - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_SSID_2, TEST_L2_FAILURE, - NUM_FAILURES_TO_BLOCKLIST - 1); - - // Verify we have not blocklisted anything yet because the failure count was cleared. - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Verify that TEST_BSSID_1 is added to blocklist after 1 more failure. - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_SSID_2, TEST_L2_FAILURE, 1); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - /** - * Verify that a BSSID is not added to blocklist as long as - * mWifiLastResortWatchdog.shouldIgnoreBssidUpdate is returning true, for failure reasons - * that are also being tracked by the watchdog. - */ - @Test - public void testWatchdogIsGivenChanceToTrigger() { - // Verify that |shouldIgnoreBssidUpdate| can prevent a BSSID from being added to blocklist. - when(mWifiLastResortWatchdog.shouldIgnoreBssidUpdate(anyString())).thenReturn(true); - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, - NUM_FAILURES_TO_BLOCKLIST * 2); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Verify that after watchdog is okay with blocking a BSSID, it gets blocked after 1 - // more failure. - when(mWifiLastResortWatchdog.shouldIgnoreBssidUpdate(anyString())).thenReturn(false); - handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, 1); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - /** - * Verify that non device related errors, and errors that are not monitored by the watchdog - * bypasses the watchdog check. - */ - @Test - public void testUnrelatedErrorsBypassWatchdogCheck() { - when(mWifiLastResortWatchdog.shouldIgnoreBssidUpdate(anyString())).thenReturn(true); - verifyAddTestBssidToBlocklist(); - verify(mWifiLastResortWatchdog, never()).shouldIgnoreBssidUpdate(anyString()); - } - - /** - * Verify that we are correctly filtering by SSID when sending a blocklist down to firmware. - */ - @Test - public void testSendBlocklistToFirmwareFilterBySsid() { - verifyAddMultipleBssidsToBlocklist(); - - // Verify we are sending 2 BSSIDs down to the firmware for SSID_1. - ArrayList<String> blocklist1 = new ArrayList<>(); - blocklist1.add(TEST_BSSID_2); - blocklist1.add(TEST_BSSID_1); - mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(TEST_SSID_1); - verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(eq(blocklist1), - eq(new ArrayList<>())); - - // Verify we are sending 1 BSSID down to the firmware for SSID_2. - ArrayList<String> blocklist2 = new ArrayList<>(); - blocklist2.add(TEST_BSSID_3); - mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(TEST_SSID_2); - verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(eq(blocklist2), - eq(new ArrayList<>())); - - // Verify we are not sending any BSSIDs down to the firmware since there does not - // exists any BSSIDs for TEST_SSID_3 in the blocklist. - mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(TEST_SSID_3); - verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(eq(new ArrayList<>()), - eq(new ArrayList<>())); - } - - /** - * Verify that when sending the blocklist down to firmware, the list is sorted by latest - * end time first. - * Also verify that when there are more blocklisted BSSIDs than the allowed limit by the - * firmware, the list sent down is trimmed. - */ - @Test - public void testMostRecentBlocklistEntriesAreSentToFirmware() { - // Add BSSIDs to blocklist - String bssid = "0a:08:5c:67:89:0"; - for (int i = 0; i < 10; i++) { - when(mClock.getWallClockMillis()).thenReturn((long) i); - mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid + i, - TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, - TEST_GOOD_RSSI); - - // This will build a List of BSSIDs starting from the latest added ones that is at - // most size |TEST_NUM_MAX_FIRMWARE_SUPPORT_BSSIDS|. - // Then verify that the blocklist is sent down in this sorted order. - ArrayList<String> blocklist = new ArrayList<>(); - for (int j = i; j > i - TEST_NUM_MAX_FIRMWARE_SUPPORT_BSSIDS; j--) { - if (j < 0) { - break; - } - blocklist.add(bssid + j); - } - mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(TEST_SSID_1); - verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(eq(blocklist), - eq(new ArrayList<>())); - } - assertEquals(10, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - } - - /** - * Verifies that when firmware roaming is disabled, the blocklist does not get plumbed to - * hardware, but the blocklist should still accessible by the framework. - */ - @Test - public void testFirmwareRoamingDisabled() { - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false); - verifyAddTestBssidToBlocklist(); - - mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(TEST_SSID_1); - verify(mWifiConnectivityHelper, never()).setFirmwareRoamingConfiguration(any(), any()); - } - - /** - * Verify that clearBssidBlocklist resets internal state. - */ - @Test - public void testClearBssidBlocklist() { - verifyAddTestBssidToBlocklist(); - mBssidBlocklistMonitor.clearBssidBlocklist(); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - } - - /** - * Verify that the BssidStatusHistoryLoggerSize is capped. - */ - @Test - public void testBssidStatusHistoryLoggerSize() { - int bssidStatusHistoryLoggerSize = 30; - for (int i = 0; i < bssidStatusHistoryLoggerSize; i++) { - verifyAddTestBssidToBlocklist(); - mBssidBlocklistMonitor.clearBssidBlocklist(); - assertEquals(i + 1, mBssidBlocklistMonitor.getBssidStatusHistoryLoggerSize()); - } - verifyAddTestBssidToBlocklist(); - mBssidBlocklistMonitor.clearBssidBlocklist(); - assertEquals(bssidStatusHistoryLoggerSize, - mBssidBlocklistMonitor.getBssidStatusHistoryLoggerSize()); - } - - /** - * Verify that clearBssidBlocklistForSsid removes all BSSIDs for that network from the - * blocklist. - */ - @Test - public void testClearBssidBlocklistForSsid() { - verifyAddMultipleBssidsToBlocklist(); - - // Clear the blocklist for SSID 1. - mBssidBlocklistMonitor.clearBssidBlocklistForSsid(TEST_SSID_1); - - // Verify that the blocklist is deleted for SSID 1 and the BSSID for SSID 2 still remains. - Set<String> bssidList = mBssidBlocklistMonitor.updateAndGetBssidBlocklist(); - assertEquals(1, bssidList.size()); - assertTrue(bssidList.contains(TEST_BSSID_3)); - verify(mWifiScoreCard, never()).resetBssidBlocklistStreakForSsid(TEST_SSID_1); - } - - /** - * Verify that handleNetworkRemoved removes all BSSIDs for that network from the blocklist - * and also reset the blocklist streak count from WifiScoreCard. - */ - @Test - public void testHandleNetworkRemovedResetsState() { - verifyAddMultipleBssidsToBlocklist(); - - // Clear the blocklist for SSID 1. - mBssidBlocklistMonitor.handleNetworkRemoved(TEST_SSID_1); - - // Verify that the blocklist is deleted for SSID 1 and the BSSID for SSID 2 still remains. - Set<String> bssidList = mBssidBlocklistMonitor.updateAndGetBssidBlocklist(); - assertEquals(1, bssidList.size()); - assertTrue(bssidList.contains(TEST_BSSID_3)); - verify(mWifiScoreCard).resetBssidBlocklistStreakForSsid(TEST_SSID_1); - } - - /** - * Verify that |blockBssidForDurationMs| adds a BSSID to blocklist for the specified duration. - */ - @Test - public void testBlockBssidForDurationMs() { - when(mClock.getWallClockMillis()).thenReturn(0L); - long testDuration = 5500L; - mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, testDuration, - TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI); - assertEquals(1, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Verify that the BSSID is removed from blocklist by clearBssidBlocklistForSsid - mBssidBlocklistMonitor.clearBssidBlocklistForSsid(TEST_SSID_1); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - assertEquals(1, mBssidBlocklistMonitor.getBssidStatusHistoryLoggerSize()); - - // Add the BSSID to blocklist again. - mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, testDuration, - TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI); - assertEquals(1, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // Verify that the BSSID is removed from blocklist once the specified duration is over. - when(mClock.getWallClockMillis()).thenReturn(testDuration + 1); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - assertEquals(2, mBssidBlocklistMonitor.getBssidStatusHistoryLoggerSize()); - } - - /** - * Verify that invalid inputs are handled and result in no-op. - */ - @Test - public void testBlockBssidForDurationMsInvalidInputs() { - // test invalid BSSID - when(mClock.getWallClockMillis()).thenReturn(0L); - long testDuration = 5500L; - mBssidBlocklistMonitor.blockBssidForDurationMs(null, TEST_SSID_1, testDuration, - TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // test invalid SSID - mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, null, testDuration, - TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - - // test invalid duration - mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, -1, - TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - } - - private void simulateRssiUpdate(String bssid, int rssi) { - ScanDetail scanDetail = mock(ScanDetail.class); - ScanResult scanResult = mock(ScanResult.class); - scanResult.BSSID = bssid; - scanResult.level = rssi; - when(scanDetail.getScanResult()).thenReturn(scanResult); - List<ScanDetail> scanDetails = new ArrayList<>(); - scanDetails.add(scanDetail); - mBssidBlocklistMonitor.tryEnablingBlockedBssids(scanDetails); - } - - /** - * Verify that if the RSSI is low when the BSSID is blocked, a RSSI improvement will remove - * the BSSID from blocklist. - */ - @Test - public void testUnblockBssidAfterRssiImproves() { - when(mClock.getWallClockMillis()).thenReturn(0L); - // verify TEST_BSSID_1 is blocked - mBssidBlocklistMonitor.handleBssidConnectionFailure( - TEST_BSSID_1, TEST_SSID_1, BssidBlocklistMonitor.REASON_EAP_FAILURE, - TEST_SUFFICIENT_RSSI - MIN_RSSI_DIFF_TO_UNBLOCK_BSSID); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - - // verify the blocklist is not cleared when the rssi improvement is not large enough. - simulateRssiUpdate(TEST_BSSID_1, TEST_SUFFICIENT_RSSI - 1); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - - // verify TEST_BSSID_1 is removed from the blocklist after RSSI improves - simulateRssiUpdate(TEST_BSSID_1, TEST_SUFFICIENT_RSSI); - assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size()); - } - - /** - * Verify that if the RSSI is already good when the BSSID is blocked, a RSSI improvement will - * not remove the BSSID from blocklist. - */ - @Test - public void testBssidNotUnblockedIfRssiAlreadyGood() { - when(mClock.getWallClockMillis()).thenReturn(0L); - // verify TEST_BSSID_1 is blocked - mBssidBlocklistMonitor.handleBssidConnectionFailure( - TEST_BSSID_1, TEST_SSID_1, BssidBlocklistMonitor.REASON_EAP_FAILURE, - TEST_SUFFICIENT_RSSI); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - - // verify TEST_BSSID_1 is not removed from blocklist - simulateRssiUpdate(TEST_BSSID_1, TEST_GOOD_RSSI); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - /** - * Verify that the logic to unblock BSSIDs after RSSI improvement does not apply for some - * failure reasons. - */ - @Test - public void testRssiImprovementNotUnblockBssidForSomeFailureReasons() { - when(mClock.getWallClockMillis()).thenReturn(0L); - mBssidBlocklistMonitor.handleBssidConnectionFailure( - TEST_BSSID_1, TEST_SSID_1, BssidBlocklistMonitor.REASON_WRONG_PASSWORD, - TEST_SUFFICIENT_RSSI - MIN_RSSI_DIFF_TO_UNBLOCK_BSSID); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - - simulateRssiUpdate(TEST_BSSID_1, TEST_SUFFICIENT_RSSI); - assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); - } - - /** - * Verify the failure reasons for all blocked BSSIDs are retrieved. - */ - @Test - public void testGetFailureReasonsForSsid() { - // Null input should not crash - mBssidBlocklistMonitor.getFailureReasonsForSsid(null).size(); - assertEquals(0, mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1).size()); - mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, 1000, - BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, TEST_GOOD_RSSI); - mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_2, TEST_SSID_1, 1000, - BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, TEST_GOOD_RSSI); - - assertEquals(2, mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1).size()); - assertTrue(mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1) - .contains(BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA)); - assertTrue(mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1) - .contains(BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ByteBufferReaderTest.java b/tests/wifitests/src/com/android/server/wifi/ByteBufferReaderTest.java deleted file mode 100644 index c2a4021dd..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ByteBufferReaderTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; - -/** - * Unit tests for {@link com.android.server.wifi.ByteBufferReader}. - */ -@SmallTest -public class ByteBufferReaderTest extends WifiBaseTest { - /** - * Verify that BufferUnderflowException will be thrown when reading an integer from a buffer - * that contained less data than needed. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void readIntegerWithBufferUnderflow() throws Exception { - byte[] data = new byte[1]; - ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); - ByteBufferReader.readInteger(buffer, buffer.order(), 2); - } - - /** - * Verify that IllegalArgumentException will be thrown when reading an integer that exceeds - * the maximum integer size. - * - * @throws Exception - */ - @Test(expected = IllegalArgumentException.class) - public void readIntegerExceedingMaximumLength() throws Exception { - int length = ByteBufferReader.MAXIMUM_INTEGER_SIZE + 1; - byte[] data = new byte[length]; - ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); - ByteBufferReader.readInteger(buffer, buffer.order(), length); - } - - /** - * Verify that IllegalArgumentException will be thrown when reading an integer with size - * less than the minimum. - * - * @throws Exception - */ - @Test(expected = IllegalArgumentException.class) - public void readIntegerLessThanMinimumLength() throws Exception { - int length = ByteBufferReader.MINIMUM_INTEGER_SIZE - 1; - byte[] data = new byte[length]; - ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); - ByteBufferReader.readInteger(buffer, buffer.order(), length); - } - - /** - * Verify that the expected integer value is returned when reading an integer with minimum - * integer size. - * - * @throws Exception - */ - @Test - public void readIntegerWithMinimumSize() throws Exception { - byte[] data = new byte[] {0x1}; - ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); - assertEquals(1, ByteBufferReader.readInteger(buffer, buffer.order(), - ByteBufferReader.MINIMUM_INTEGER_SIZE)); - } - - /** - * Verify that the expected integer value is returned when reading an integer with maximum - * integer size. - * - * @throws Exception - */ - @Test - public void readIntegerWithMaximumSize() throws Exception { - byte[] data = new byte[] {0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11}; - - // Little Endian parsing. - ByteBuffer leBuffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); - long leValue = 0x110000000000001fL; - assertEquals(leValue, ByteBufferReader.readInteger(leBuffer, leBuffer.order(), - ByteBufferReader.MAXIMUM_INTEGER_SIZE)); - - // Big Endian parsing. - ByteBuffer beBuffer = ByteBuffer.wrap(data).order(ByteOrder.BIG_ENDIAN); - long beValue = 0x1f00000000000011L; - assertEquals(beValue, ByteBufferReader.readInteger(beBuffer, beBuffer.order(), - ByteBufferReader.MAXIMUM_INTEGER_SIZE)); - } - - /** - * Verify that NegativeArraySizeException will be thrown when attempting to read a string with - * negative size. - * - * @throws Exception - */ - @Test(expected = NegativeArraySizeException.class) - public void readStringWithNegativeSize() throws Exception { - ByteBufferReader.readString(ByteBuffer.wrap(new byte[10]), -1, StandardCharsets.US_ASCII); - } - - /** - * Verify that an empty String will be returned when reading a string with zero size. - * - * @throws Exception - */ - @Test - public void readStringWithZeroSize() throws Exception { - String str = ByteBufferReader.readString( - ByteBuffer.wrap(new byte[10]), 0, StandardCharsets.US_ASCII); - assertTrue(str.isEmpty()); - } - - /** - * Verify that the expected string value is returned when reading a string from a buffer that - * contained a valid string. - * - * @throws Exception - */ - @Test - public void readString() throws Exception { - String expectedValue = "Hello World"; - ByteBuffer buffer = ByteBuffer.wrap(expectedValue.getBytes(StandardCharsets.US_ASCII)); - String actualValue = ByteBufferReader.readString( - buffer, buffer.remaining(), StandardCharsets.US_ASCII); - assertEquals(expectedValue, actualValue); - } - - /** - * Verify that the expected string value is returned when reading a buffer that contained the - * size of the string and the string value. - * - * @throws Exception - */ - @Test - public void readStringWithByteLength() throws Exception { - String expectedValue = "Hello World"; - ByteBuffer buffer = ByteBuffer.allocate(expectedValue.length() + 1); - buffer.put((byte) expectedValue.length()); - buffer.put(expectedValue.getBytes(StandardCharsets.US_ASCII)); - // Rewind the buffer's position to the beginning for reading. - buffer.position(0); - String actualValue = - ByteBufferReader.readStringWithByteLength(buffer, StandardCharsets.US_ASCII); - assertEquals(expectedValue, actualValue); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java b/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java deleted file mode 100644 index 7b45848f7..000000000 --- a/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.lessThan; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiCandidates.Candidate; -import com.android.server.wifi.WifiCandidates.CandidateScorer; -import com.android.server.wifi.WifiCandidates.ScoredCandidate; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for implementations of - * {@link com.android.server.wifi.WifiCandidates.CandidateScorer}. - * - * Runs tests that any reasonable CandidateScorer should pass. - * Individual scorers may have additional tests of their own. - */ -@SmallTest -@RunWith(Parameterized.class) -public class CandidateScorerTest extends WifiBaseTest { - - @Parameters(name = "{index}: {0}") - public static List<Object[]> listOfObjectArraysBecauseJUnitMadeUs() { - ScoringParams sp; - ArrayList<Object[]> ans = new ArrayList<>(); - - sp = new ScoringParams(); - ans.add(new Object[]{ - "Compatibility Scorer", - CompatibilityScorer.COMPATIBILITY_SCORER_DEFAULT_EXPID, - new CompatibilityScorer(sp), - sp}); - - sp = new ScoringParams(); - ans.add(new Object[]{ - "Score Card Based Scorer", - ScoreCardBasedScorer.SCORE_CARD_BASED_SCORER_DEFAULT_EXPID, - new ScoreCardBasedScorer(sp), - sp}); - - sp = new ScoringParams(); - ans.add(new Object[]{ - "Bubble Function Scorer", - BubbleFunScorer.BUBBLE_FUN_SCORER_DEFAULT_EXPID, - new BubbleFunScorer(sp), - sp}); - - sp = new ScoringParams(); - ans.add(new Object[]{ - "Throughput Scorer", - ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID, - new ThroughputScorer(sp), - sp}); - - return ans; - } - - @Parameter(0) - public String mTitleForUseInGeneratedParameterNames; - - @Parameter(1) - public int mExpectedExpId; - - @Parameter(2) - public CandidateScorer mCandidateScorer; - - @Parameter(3) - public ScoringParams mScoringParams; - - private static final double TOL = 1e-6; // for assertEquals(double, double, tolerance) - - private ConcreteCandidate mCandidate1; - private ConcreteCandidate mCandidate2; - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - mScoringParams.update(""); - mCandidate1 = new ConcreteCandidate().setNominatorId(0) - .setScanRssi(-50).setFrequency(5180); - mCandidate2 = new ConcreteCandidate().setNominatorId(0) - .setScanRssi(-50).setFrequency(5180); - } - - /** - * Test that the expected expid is computed with the built-in defaults. - */ - @Test - public void testExpid() throws Exception { - String identifier = mCandidateScorer.getIdentifier(); - assertEquals(identifier, - mExpectedExpId, - WifiNetworkSelector.experimentIdFromIdentifier(identifier)); - } - - /** - * Utility function to build and evaluate a candidate. - */ - private double evaluate(ConcreteCandidate candidate) { - ArrayList<Candidate> candidates = new ArrayList<>(1); - candidates.add(candidate); - ScoredCandidate choice = mCandidateScorer.scoreCandidates(candidates); - return Math.max(-999999999.0, choice.value); - } - - /** - * Evaluating equal inputs should give the same result. - */ - @Test - public void testEqualInputsShouldGiveTheSameResult() throws Exception { - assertEquals(evaluate(mCandidate1), evaluate(mCandidate2), TOL); - } - - /** - * Prefer 5 GHz over 2.4 GHz in non-fringe conditions, similar rssi. - */ - @Test - public void testPrefer5GhzOver2GhzInNonFringeConditionsSimilarRssi() throws Exception { - assertThat(evaluate(mCandidate1.setFrequency(5180).setScanRssi(-44)), - greaterThan(evaluate(mCandidate2.setFrequency(2432).setScanRssi(-44)))); - } - - /** - * Prefer higher rssi. - */ - @Test - public void testPreferHigherRssi() throws Exception { - assertThat(evaluate(mCandidate1.setScanRssi(-70)), - greaterThan(evaluate(mCandidate2.setScanRssi(-71)))); - } - - /** - * Prefer a secure network over an open one. - */ - @Test - public void testPreferASecureNetworkOverAnOpenOne() throws Exception { - assertThat(evaluate(mCandidate1), - greaterThan(evaluate(mCandidate2.setOpenNetwork(true)))); - } - - /** - * Prefer the current network, even if rssi difference is significant. - */ - @Test - public void testPreferTheCurrentNetworkEvenIfRssiDifferenceIsSignificant() throws Exception { - assertThat(evaluate(mCandidate1.setScanRssi(-76).setCurrentNetwork(true) - .setPredictedThroughputMbps(433)), - greaterThan(evaluate(mCandidate2.setScanRssi(-69) - .setPredictedThroughputMbps(433)))); - } - - /** - * Prefer the current network, even if throughput difference is significant. - */ - @Test - public void testPreferTheCurrentNetworkEvenIfTputDifferenceIsSignificant() throws Exception { - assertThat(evaluate(mCandidate1.setScanRssi(-57) - .setCurrentNetwork(true) - .setPredictedThroughputMbps(433)), - greaterThan(evaluate(mCandidate2.setScanRssi(-57) - .setPredictedThroughputMbps(560)))); - } - - /** - * Prefer to switch when current network has low throughput and no internet (unexpected) - */ - @Test - public void testSwitchifCurrentNetworkNoInternetUnexpectedAndLowThroughput() throws Exception { - if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; - assertThat(evaluate(mCandidate1.setScanRssi(-57) - .setCurrentNetwork(true) - .setPredictedThroughputMbps(433) - .setNoInternetAccess(true) - .setNoInternetAccessExpected(false)), - lessThan(evaluate(mCandidate2.setScanRssi(-57) - .setPredictedThroughputMbps(560)))); - } - - /** - * Prefer current network when current network has low throughput and no internet (but expected) - */ - @Test - public void testSwitchifCurrentNetworkHasNoInternetExceptedAndLowThroughput() throws Exception { - if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; - assertThat(evaluate(mCandidate1.setScanRssi(-57) - .setCurrentNetwork(true) - .setPredictedThroughputMbps(433) - .setNoInternetAccess(true) - .setNoInternetAccessExpected(true)), - greaterThan(evaluate(mCandidate2.setScanRssi(-57) - .setPredictedThroughputMbps(560)))); - } - - /** - * Prefer to switch with a larger rssi difference. - */ - @Test - public void testSwitchWithLargerDifference() throws Exception { - assertThat(evaluate(mCandidate1.setScanRssi(-80) - .setCurrentNetwork(true)), - lessThan(evaluate(mCandidate2.setScanRssi(-60)))); - } - - /** - * Stay on recently selected network. - */ - @Test - public void testStayOnRecentlySelected() throws Exception { - assertThat(evaluate(mCandidate1.setScanRssi(-80) - .setCurrentNetwork(true) - .setLastSelectionWeight(0.25)), - greaterThan(evaluate(mCandidate2.setScanRssi(-60)))); - } - - /** - * Above saturation, don't switch from current even with a large rssi difference. - */ - @Test - public void testAboveSaturationDoNotSwitchAwayEvenWithALargeRssiDifference() throws Exception { - int currentRssi = (mExpectedExpId == ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) - ? mScoringParams.getSufficientRssi(mCandidate1.getFrequency()) : - mScoringParams.getGoodRssi(mCandidate1.getFrequency()); - int unbelievablyGoodRssi = -1; - assertThat(evaluate(mCandidate1.setScanRssi(currentRssi).setCurrentNetwork(true)), - greaterThan(evaluate(mCandidate2.setScanRssi(unbelievablyGoodRssi)))); - } - - - /** - * Prefer high throughput network. - */ - @Test - public void testPreferHighThroughputNetwork() throws Exception { - if (mExpectedExpId == ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) { - assertThat(evaluate(mCandidate1.setScanRssi(-74) - .setPredictedThroughputMbps(100)), - greaterThan(evaluate(mCandidate2.setScanRssi(-74) - .setPredictedThroughputMbps(50)))); - } - } - - /** - * Prefer saved over suggestion. - */ - @Test - public void testPreferSavedOverSuggestion() throws Exception { - if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; - assertThat(evaluate(mCandidate1.setScanRssi(-77).setEphemeral(false)), - greaterThan(evaluate(mCandidate2.setScanRssi(-40) - .setEphemeral(true) - .setPredictedThroughputMbps(1000)))); - } - - /** - * Prefer metered saved over unmetered suggestion. - */ - @Test - public void testPreferMeteredSavedOverUnmeteredSuggestion() throws Exception { - if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; - assertThat(evaluate(mCandidate1.setScanRssi(-77).setEphemeral(false).setMetered(false)), - greaterThan(evaluate(mCandidate2.setScanRssi(-40) - .setEphemeral(true) - .setMetered(true) - .setPredictedThroughputMbps(1000)))); - } - - /** - * Prefer trusted metered suggestion over privileged untrusted. - */ - @Test - public void testPreferTrustedOverUntrusted() throws Exception { - if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; - assertThat(evaluate(mCandidate1.setScanRssi(-77).setEphemeral(true).setMetered(true)), - greaterThan(evaluate(mCandidate2.setScanRssi(-40) - .setEphemeral(true) - .setPredictedThroughputMbps(1000) - .setTrusted(false) - .setCarrierOrPrivileged(true)))); - } - - /** - * Prefer carrier untrusted over other untrusted. - */ - @Test - public void testPreferCarrierUntrustedOverOtherUntrusted() throws Exception { - if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; - assertThat(evaluate(mCandidate1.setScanRssi(-77) - .setEphemeral(true) - .setMetered(true) - .setCarrierOrPrivileged(true)), - greaterThan(evaluate(mCandidate2.setScanRssi(-40) - .setPredictedThroughputMbps(1000) - .setTrusted(false)))); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java deleted file mode 100644 index d4af7ecac..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ /dev/null @@ -1,5364 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; -import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE; -import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NOT_METERED; -import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE; -import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY; - -import static com.android.server.wifi.ClientModeImpl.CMD_PRE_DHCP_ACTION; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyByte; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.argThat; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; - -import android.app.ActivityManager; -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.app.test.TestAlarmManager; -import android.bluetooth.BluetoothAdapter; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; -import android.net.ConnectivityManager; -import android.net.DhcpResultsParcelable; -import android.net.InetAddresses; -import android.net.Layer2InformationParcelable; -import android.net.Layer2PacketParcelable; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.MacAddress; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkSpecifier; -import android.net.StaticIpConfiguration; -import android.net.ip.IIpClient; -import android.net.ip.IpClientCallbacks; -import android.net.wifi.IActionListener; -import android.net.wifi.ScanResult; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.KeyMgmt; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiNetworkAgentSpecifier; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.net.wifi.p2p.WifiP2pManager; -import android.os.BatteryStatsManager; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.IPowerManager; -import android.os.IThermalService; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.PowerManager; -import android.os.Process; -import android.os.UserManager; -import android.os.test.TestLooper; -import android.provider.Settings; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.test.mock.MockContentProvider; -import android.test.mock.MockContentResolver; -import android.util.Log; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.internal.util.AsyncChannel; -import com.android.internal.util.IState; -import com.android.internal.util.StateMachine; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.hotspot2.PasspointProvisioningTestUtil; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; -import com.android.server.wifi.util.RssiUtilTest; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.function.Consumer; - -/** - * Unit tests for {@link com.android.server.wifi.ClientModeImpl}. - */ -@SmallTest -public class ClientModeImplTest extends WifiBaseTest { - public static final String TAG = "ClientModeImplTest"; - - private static final int MANAGED_PROFILE_UID = 1100000; - private static final int OTHER_USER_UID = 1200000; - private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE = - (ActivityManager.isLowRamDeviceStatic() - ? ClientModeImpl.NUM_LOG_RECS_VERBOSE_LOW_MEMORY - : ClientModeImpl.NUM_LOG_RECS_VERBOSE); - private static final int FRAMEWORK_NETWORK_ID = 0; - private static final int PASSPOINT_NETWORK_ID = 1; - private static final int TEST_RSSI = -54; - private static final int TEST_NETWORK_ID = 54; - private static final int WPS_SUPPLICANT_NETWORK_ID = 5; - private static final int WPS_FRAMEWORK_NETWORK_ID = 10; - private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\""; - private static final String OP_PACKAGE_NAME = "com.xxx"; - private static final int TEST_UID = Process.SYSTEM_UID + 1000; - private static final MacAddress TEST_GLOBAL_MAC_ADDRESS = - MacAddress.fromString("10:22:34:56:78:92"); - private static final MacAddress TEST_LOCAL_MAC_ADDRESS = - MacAddress.fromString("2a:53:43:c3:56:21"); - private static final MacAddress TEST_DEFAULT_MAC_ADDRESS = - MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); - - // NetworkAgent creates threshold ranges with Integers - private static final int RSSI_THRESHOLD_MAX = -30; - private static final int RSSI_THRESHOLD_MIN = -76; - // Threshold breach callbacks are called with bytes - private static final byte RSSI_THRESHOLD_BREACH_MIN = -80; - private static final byte RSSI_THRESHOLD_BREACH_MAX = -20; - - private static final int DATA_SUBID = 1; - private static final int CARRIER_ID_1 = 100; - - private long mBinderToken; - private MockitoSession mSession; - - private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) { - return mock(class1, withSettings().extraInterfaces(interfaces)); - } - - private void enableDebugLogs() { - mCmi.enableVerboseLogging(1); - } - - private FrameworkFacade getFrameworkFacade() throws Exception { - FrameworkFacade facade = mock(FrameworkFacade.class); - - doAnswer(new AnswerWithArguments() { - public void answer( - Context context, String ifname, IpClientCallbacks callback) { - mIpClientCallback = callback; - callback.onIpClientCreated(mIpClient); - } - }).when(facade).makeIpClient(any(), anyString(), any()); - - return facade; - } - - private Context getContext() throws Exception { - when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true); - - Context context = mock(Context.class); - when(context.getPackageManager()).thenReturn(mPackageManager); - - MockContentResolver mockContentResolver = new MockContentResolver(); - mockContentResolver.addProvider(Settings.AUTHORITY, - new MockContentProvider(context) { - @Override - public Bundle call(String method, String arg, Bundle extras) { - return new Bundle(); - } - }); - when(context.getContentResolver()).thenReturn(mockContentResolver); - - when(context.getSystemService(Context.POWER_SERVICE)).thenReturn( - new PowerManager(context, mock(IPowerManager.class), mock(IThermalService.class), - new Handler())); - - mAlarmManager = new TestAlarmManager(); - when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn( - mAlarmManager.getAlarmManager()); - - when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn( - mConnectivityManager); - - when(context.getOpPackageName()).thenReturn(OP_PACKAGE_NAME); - - when(context.getSystemService(ActivityManager.class)).thenReturn( - mock(ActivityManager.class)); - - WifiP2pManager p2pm = mock(WifiP2pManager.class); - when(context.getSystemService(WifiP2pManager.class)).thenReturn(p2pm); - final CountDownLatch untilDone = new CountDownLatch(1); - mP2pThread = new HandlerThread("WifiP2pMockThread") { - @Override - protected void onLooperPrepared() { - untilDone.countDown(); - } - }; - mP2pThread.start(); - untilDone.await(); - Handler handler = new Handler(mP2pThread.getLooper()); - when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler)); - - return context; - } - - private MockResources getMockResources() { - MockResources resources = new MockResources(); - return resources; - } - - private IState getCurrentState() throws - NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Method method = StateMachine.class.getDeclaredMethod("getCurrentState"); - method.setAccessible(true); - return (IState) method.invoke(mCmi); - } - - private static HandlerThread getCmiHandlerThread(ClientModeImpl cmi) throws - NoSuchFieldException, InvocationTargetException, IllegalAccessException { - Field field = StateMachine.class.getDeclaredField("mSmThread"); - field.setAccessible(true); - return (HandlerThread) field.get(cmi); - } - - private static void stopLooper(final Looper looper) throws Exception { - new Handler(looper).post(new Runnable() { - @Override - public void run() { - looper.quitSafely(); - } - }); - } - - private void dumpState() { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - mCmi.dump(null, writer, null); - writer.flush(); - Log.d(TAG, "ClientModeImpl state -" + stream.toString()); - } - - private static ScanDetail getGoogleGuestScanDetail(int rssi, String bssid, int freq) { - ScanResult.InformationElement[] ie = new ScanResult.InformationElement[1]; - ie[0] = ScanResults.generateSsidIe(sSSID); - NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq); - ScanDetail detail = new ScanDetail(nd, sWifiSsid, bssid, "", rssi, freq, - Long.MAX_VALUE, /* needed so that scan results aren't rejected because - there older than scan start */ - ie, new ArrayList<String>(), ScanResults.generateIERawDatafromScanResultIE(ie)); - - return detail; - } - - private ArrayList<ScanDetail> getMockScanResults() { - ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825); - ArrayList<ScanDetail> list = sr.getScanDetailArrayList(); - - list.add(getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); - return list; - } - - private void injectDhcpSuccess(DhcpResultsParcelable dhcpResults) { - mIpClientCallback.onNewDhcpResults(dhcpResults); - mIpClientCallback.onProvisioningSuccess(new LinkProperties()); - } - - private void injectDhcpFailure() { - mIpClientCallback.onNewDhcpResults((DhcpResultsParcelable) null); - mIpClientCallback.onProvisioningFailure(new LinkProperties()); - } - - static final String sSSID = "\"GoogleGuest\""; - static final String SSID_NO_QUOTE = sSSID.replace("\"", ""); - static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(SSID_NO_QUOTE); - static final String sBSSID = "01:02:03:04:05:06"; - static final String sBSSID1 = "02:01:04:03:06:05"; - static final int sFreq = 2437; - static final int sFreq1 = 5240; - static final String WIFI_IFACE_NAME = "mockWlan"; - static final String sFilsSsid = "FILS-AP"; - - ClientModeImpl mCmi; - HandlerThread mWifiCoreThread; - HandlerThread mP2pThread; - HandlerThread mSyncThread; - AsyncChannel mCmiAsyncChannel; - AsyncChannel mNetworkAgentAsyncChannel; - TestAlarmManager mAlarmManager; - MockWifiMonitor mWifiMonitor; - TestLooper mLooper; - Context mContext; - MockResources mResources; - FrameworkFacade mFrameworkFacade; - IpClientCallbacks mIpClientCallback; - OsuProvider mOsuProvider; - WifiConfiguration mConnectedNetwork; - WifiCarrierInfoManager mWifiCarrierInfoManager; - - @Mock WifiScanner mWifiScanner; - @Mock SupplicantStateTracker mSupplicantStateTracker; - @Mock WifiMetrics mWifiMetrics; - @Mock UserManager mUserManager; - @Mock BackupManagerProxy mBackupManagerProxy; - @Mock WifiCountryCode mCountryCode; - @Mock WifiInjector mWifiInjector; - @Mock WifiLastResortWatchdog mWifiLastResortWatchdog; - @Mock BssidBlocklistMonitor mBssidBlocklistMonitor; - @Mock PropertyService mPropertyService; - @Mock BuildProperties mBuildProperties; - @Mock IBinder mPackageManagerBinder; - @Mock SarManager mSarManager; - @Mock WifiConfigManager mWifiConfigManager; - @Mock WifiNative mWifiNative; - @Mock WifiScoreCard mWifiScoreCard; - @Mock WifiHealthMonitor mWifiHealthMonitor; - @Mock WifiTrafficPoller mWifiTrafficPoller; - @Mock WifiConnectivityManager mWifiConnectivityManager; - @Mock WifiStateTracker mWifiStateTracker; - @Mock PasspointManager mPasspointManager; - @Mock SelfRecovery mSelfRecovery; - @Mock WifiPermissionsUtil mWifiPermissionsUtil; - @Mock IIpClient mIpClient; - @Mock TelephonyManager mTelephonyManager; - @Mock TelephonyManager mDataTelephonyManager; - @Mock WrongPasswordNotifier mWrongPasswordNotifier; - @Mock Clock mClock; - @Mock ScanDetailCache mScanDetailCache; - @Mock BaseWifiDiagnostics mWifiDiagnostics; - @Mock ConnectivityManager mConnectivityManager; - @Mock IProvisioningCallback mProvisioningCallback; - @Mock HandlerThread mWifiHandlerThread; - @Mock WifiPermissionsWrapper mWifiPermissionsWrapper; - @Mock WakeupController mWakeupController; - @Mock WifiDataStall mWifiDataStall; - @Mock WifiNetworkFactory mWifiNetworkFactory; - @Mock UntrustedWifiNetworkFactory mUntrustedWifiNetworkFactory; - @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - @Mock LinkProbeManager mLinkProbeManager; - @Mock PackageManager mPackageManager; - @Mock WifiLockManager mWifiLockManager; - @Mock AsyncChannel mNullAsyncChannel; - @Mock Handler mNetworkAgentHandler; - @Mock BatteryStatsManager mBatteryStatsManager; - @Mock MboOceController mMboOceController; - @Mock SubscriptionManager mSubscriptionManager; - @Mock ConnectionFailureNotifier mConnectionFailureNotifier; - @Mock EapFailureNotifier mEapFailureNotifier; - @Mock SimRequiredNotifier mSimRequiredNotifier; - @Mock ThroughputPredictor mThroughputPredictor; - @Mock ScanRequestProxy mScanRequestProxy; - @Mock DeviceConfigFacade mDeviceConfigFacade; - @Mock Network mNetwork; - - final ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener> mConfigUpdateListenerCaptor = - ArgumentCaptor.forClass(WifiConfigManager.OnNetworkUpdateListener.class); - - public ClientModeImplTest() throws Exception { - } - - @Before - public void setUp() throws Exception { - Log.d(TAG, "Setting up ..."); - - // Ensure looper exists - mLooper = new TestLooper(); - - MockitoAnnotations.initMocks(this); - - /** uncomment this to enable logs from ClientModeImpls */ - // enableDebugLogs(); - mWifiMonitor = new MockWifiMonitor(); - when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); - when(mWifiInjector.getClock()).thenReturn(new Clock()); - when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); - when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService); - when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties); - when(mWifiInjector.getWifiBackupRestore()).thenReturn(mock(WifiBackupRestore.class)); - when(mWifiInjector.getWifiDiagnostics()).thenReturn(mWifiDiagnostics); - when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); - when(mWifiInjector.makeWifiConnectivityManager(any())) - .thenReturn(mWifiConnectivityManager); - when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager); - when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker); - when(mWifiInjector.getWifiMonitor()).thenReturn(mWifiMonitor); - when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); - when(mWifiInjector.getWifiTrafficPoller()).thenReturn(mWifiTrafficPoller); - when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); - when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil); - when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager); - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager); - when(mWifiInjector.getClock()).thenReturn(mClock); - when(mWifiHandlerThread.getLooper()).thenReturn(mLooper.getLooper()); - when(mWifiInjector.getWifiHandlerThread()).thenReturn(mWifiHandlerThread); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiInjector.getWakeupController()).thenReturn(mWakeupController); - when(mWifiInjector.getScoringParams()).thenReturn(new ScoringParams()); - when(mWifiInjector.getWifiDataStall()).thenReturn(mWifiDataStall); - when(mWifiInjector.makeWifiNetworkFactory(any(), any())).thenReturn(mWifiNetworkFactory); - when(mWifiInjector.makeUntrustedWifiNetworkFactory(any(), any())) - .thenReturn(mUntrustedWifiNetworkFactory); - when(mWifiInjector.getWifiNetworkSuggestionsManager()) - .thenReturn(mWifiNetworkSuggestionsManager); - when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard); - when(mWifiInjector.getWifiHealthMonitor()).thenReturn(mWifiHealthMonitor); - when(mWifiInjector.getWifiLockManager()).thenReturn(mWifiLockManager); - when(mWifiInjector.getWifiThreadRunner()) - .thenReturn(new WifiThreadRunner(new Handler(mLooper.getLooper()))); - when(mWifiInjector.makeConnectionFailureNotifier(any())) - .thenReturn(mConnectionFailureNotifier); - when(mWifiInjector.getBssidBlocklistMonitor()).thenReturn(mBssidBlocklistMonitor); - when(mWifiInjector.getThroughputPredictor()).thenReturn(mThroughputPredictor); - when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy); - when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade); - when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any())) - .thenReturn(Pair.create(Process.INVALID_UID, "")); - when(mWifiNative.initialize()).thenReturn(true); - when(mWifiNative.getFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn( - TEST_GLOBAL_MAC_ADDRESS); - when(mWifiNative.getMacAddress(WIFI_IFACE_NAME)) - .thenReturn(TEST_GLOBAL_MAC_ADDRESS.toString()); - WifiNative.ConnectionCapabilities cap = new WifiNative.ConnectionCapabilities(); - cap.wifiStandard = ScanResult.WIFI_STANDARD_11AC; - when(mWifiNative.getConnectionCapabilities(WIFI_IFACE_NAME)).thenReturn(cap); - when(mWifiNative.setMacAddress(eq(WIFI_IFACE_NAME), anyObject())) - .then(new AnswerWithArguments() { - public boolean answer(String iface, MacAddress mac) { - when(mWifiNative.getMacAddress(iface)).thenReturn(mac.toString()); - return true; - } - }); - doAnswer(new AnswerWithArguments() { - public MacAddress answer( - WifiConfiguration config) { - return config.getRandomizedMacAddress(); - } - }).when(mWifiConfigManager).getRandomizedMacAndUpdateIfNeeded(any()); - when(mWifiNative.connectToNetwork(any(), any())).thenReturn(true); - - when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(true); - when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(true); - - mFrameworkFacade = getFrameworkFacade(); - mContext = getContext(); - - mResources = getMockResources(); - mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, true); - mResources.setIntArray(R.array.config_wifiRssiLevelThresholds, - RssiUtilTest.RSSI_THRESHOLDS); - mResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, 3000); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.createContextAsUser(any(), anyInt())).thenReturn(mContext); - - when(mFrameworkFacade.getIntegerSetting(mContext, - Settings.Global.WIFI_FREQUENCY_BAND, - WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn( - WifiManager.WIFI_FREQUENCY_BAND_AUTO); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mWifiPermissionsWrapper.getLocalMacAddressPermission(anyInt())) - .thenReturn(PackageManager.PERMISSION_DENIED); - doAnswer(inv -> { - mIpClientCallback.onQuit(); - return null; - }).when(mIpClient).shutdown(); - when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(), anyInt(), any(), - anyInt())).thenReturn(mNetwork); - List<SubscriptionInfo> subList = Arrays.asList(mock(SubscriptionInfo.class)); - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subList); - when(mSubscriptionManager.getActiveSubscriptionIdList()) - .thenReturn(new int[]{DATA_SUBID}); - - WifiCarrierInfoManager tu = new WifiCarrierInfoManager(mTelephonyManager, - mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class), - mock(WifiContext.class), mock(WifiConfigStore.class), mock(Handler.class), - mWifiMetrics); - mWifiCarrierInfoManager = spy(tu); - // static mocking - mSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT) - .spyStatic(MacAddress.class) - .startMocking(); - initializeCmi(); - - mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true); - mConnectedNetwork = spy(WifiConfigurationTestUtil.createOpenNetwork()); - when(mNullAsyncChannel.sendMessageSynchronously(any())).thenReturn(null); - when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(new Pair<>(null, null)); - when(mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled()).thenReturn(true); - when(mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled()).thenReturn(true); - when(mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled()).thenReturn(true); - when(mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()).thenReturn( - DeviceConfigFacade.DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS); - when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString())) - .thenReturn(WifiHealthMonitor.REASON_NO_FAILURE); - when(mWifiScoreCard.detectAbnormalDisconnection()) - .thenReturn(WifiHealthMonitor.REASON_NO_FAILURE); - when(mThroughputPredictor.predictMaxTxThroughput(any())).thenReturn(90); - when(mThroughputPredictor.predictMaxRxThroughput(any())).thenReturn(80); - } - - private void registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger, - Handler wrappedHandler) { - final AsyncChannel channel = new AsyncChannel(); - Handler handler = new Handler(mLooper.getLooper()) { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - consumer.accept(channel); - } else { - Log.d(TAG, "Failed to connect Command channel " + this); - } - break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - Log.d(TAG, "Command channel disconnected " + this); - break; - case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: - Log.d(TAG, "Command channel fully connected " + this); - break; - default: - if (wrappedHandler != null) { - wrappedHandler.handleMessage(msg); - } - break; - } - } - }; - - channel.connect(mContext, handler, messenger); - mLooper.dispatchAll(); - } - - private void registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger) { - registerAsyncChannel(consumer, messenger, null /* wrappedHandler */); - } - - private void initializeCmi() throws Exception { - mCmi = new ClientModeImpl(mContext, mFrameworkFacade, mLooper.getLooper(), - mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative, - mWrongPasswordNotifier, mSarManager, mWifiTrafficPoller, mLinkProbeManager, - mBatteryStatsManager, mSupplicantStateTracker, mMboOceController, - mWifiCarrierInfoManager, mEapFailureNotifier, mSimRequiredNotifier); - mCmi.start(); - mWifiCoreThread = getCmiHandlerThread(mCmi); - - registerAsyncChannel((x) -> { - mCmiAsyncChannel = x; - }, mCmi.getMessenger()); - - mBinderToken = Binder.clearCallingIdentity(); - - /* Send the BOOT_COMPLETED message to setup some CMI state. */ - mCmi.handleBootCompleted(); - mLooper.dispatchAll(); - - verify(mWifiNetworkFactory, atLeastOnce()).register(); - verify(mUntrustedWifiNetworkFactory, atLeastOnce()).register(); - verify(mWifiConfigManager, atLeastOnce()).addOnNetworkUpdateListener( - mConfigUpdateListenerCaptor.capture()); - assertNotNull(mConfigUpdateListenerCaptor.getValue()); - - mCmi.initialize(); - mLooper.dispatchAll(); - } - - @After - public void cleanUp() throws Exception { - Binder.restoreCallingIdentity(mBinderToken); - - if (mSyncThread != null) stopLooper(mSyncThread.getLooper()); - if (mWifiCoreThread != null) stopLooper(mWifiCoreThread.getLooper()); - if (mP2pThread != null) stopLooper(mP2pThread.getLooper()); - - mWifiCoreThread = null; - mP2pThread = null; - mSyncThread = null; - mCmiAsyncChannel = null; - mNetworkAgentAsyncChannel = null; - mNetworkAgentHandler = null; - mCmi = null; - mSession.finishMocking(); - } - - @Test - public void createNew() throws Exception { - assertEquals("DefaultState", getCurrentState().getName()); - - mCmi.handleBootCompleted(); - mLooper.dispatchAll(); - assertEquals("DefaultState", getCurrentState().getName()); - } - - @Test - public void loadComponentsInStaMode() throws Exception { - startSupplicantAndDispatchMessages(); - assertEquals("DisconnectedState", getCurrentState().getName()); - } - - @Test - public void checkInitialStateStickyWhenDisabledMode() throws Exception { - mLooper.dispatchAll(); - assertEquals("DefaultState", getCurrentState().getName()); - assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest()); - - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest()); - assertEquals("DefaultState", getCurrentState().getName()); - } - - @Test - public void shouldStartSupplicantWhenConnectModeRequested() throws Exception { - // The first time we start out in DefaultState, we sit around here. - mLooper.dispatchAll(); - assertEquals("DefaultState", getCurrentState().getName()); - assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest()); - - // But if someone tells us to enter connect mode, we start up supplicant - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - mLooper.dispatchAll(); - assertEquals("DisconnectedState", getCurrentState().getName()); - } - - /** - * Test that mode changes accurately reflect the value for isWifiEnabled. - */ - @Test - public void checkIsWifiEnabledForModeChanges() throws Exception { - // Check initial state - mLooper.dispatchAll(); - assertEquals("DefaultState", getCurrentState().getName()); - assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState()); - - // switch to connect mode and verify wifi is reported as enabled - startSupplicantAndDispatchMessages(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - assertEquals("enabled", mCmi.syncGetWifiStateByName()); - - // now disable wifi and verify the reported wifi state - mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest()); - assertEquals("DefaultState", getCurrentState().getName()); - assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState()); - assertEquals("disabled", mCmi.syncGetWifiStateByName()); - verify(mContext, never()).sendStickyBroadcastAsUser( - (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); - } - - private class WifiEnablingStateIntentMatcher implements ArgumentMatcher<Intent> { - @Override - public boolean matches(Intent intent) { - if (WifiManager.WIFI_STATE_CHANGED_ACTION != intent.getAction()) { - // not the correct type - return false; - } - return WifiManager.WIFI_STATE_ENABLING - == intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_DISABLED); - } - } - - private void canForgetNetwork() throws Exception { - when(mWifiConfigManager.removeNetwork(eq(0), anyInt(), any())).thenReturn(true); - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.forget(0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt(), any()); - } - - /** - * Verifies that configs can be removed when not in client mode. - */ - @Test - public void canForgetNetworkConfigWhenWifiDisabled() throws Exception { - canForgetNetwork(); - } - - /** - * Verifies that configs can be forgotten when in client mode. - */ - @Test - public void canForgetNetworkConfigInClientMode() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - canForgetNetwork(); - } - - private void canSaveNetworkConfig() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - - int networkId = TEST_NETWORK_ID; - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) - .thenReturn(new NetworkUpdateResult(networkId)); - when(mWifiConfigManager.enableNetwork(eq(networkId), eq(false), anyInt(), any())) - .thenReturn(true); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.save(config, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()); - verify(mWifiConfigManager).enableNetwork(eq(networkId), eq(false), anyInt(), any()); - } - - /** - * Verifies that configs can be saved when not in client mode. - */ - @Test - public void canSaveNetworkConfigWhenWifiDisabled() throws Exception { - canSaveNetworkConfig(); - } - - /** - * Verifies that configs can be saved when in client mode. - */ - @Test - public void canSaveNetworkConfigInClientMode() throws Exception { - loadComponentsInStaMode(); - canSaveNetworkConfig(); - } - - /** - * Verifies that null configs are rejected in SAVE_NETWORK message. - */ - @Test - public void saveNetworkConfigFailsWithNullConfig() throws Exception { - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.save(null, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onFailure(WifiManager.ERROR); - - verify(mWifiConfigManager, never()) - .addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()); - verify(mWifiConfigManager, never()) - .enableNetwork(anyInt(), anyBoolean(), anyInt(), any()); - } - - /** - * Verifies that configs save fails when the addition of network fails. - */ - @Test - public void saveNetworkConfigFailsWithConfigAddFailure() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) - .thenReturn(new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID)); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.save(config, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onFailure(WifiManager.ERROR); - - verify(mWifiConfigManager).addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()); - verify(mWifiConfigManager, never()) - .enableNetwork(anyInt(), anyBoolean(), anyInt(), any()); - } - - /** - * Verifies that configs save fails when the enable of network fails. - */ - @Test - public void saveNetworkConfigFailsWithConfigEnableFailure() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - - int networkId = 5; - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) - .thenReturn(new NetworkUpdateResult(networkId)); - when(mWifiConfigManager.enableNetwork(eq(networkId), eq(false), anyInt(), any())) - .thenReturn(false); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.save(config, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onFailure(WifiManager.ERROR); - - verify(mWifiConfigManager).addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()); - verify(mWifiConfigManager).enableNetwork(eq(networkId), eq(false), anyInt(), any()); - } - - /** - * Helper method to move through startup states. - */ - private void startSupplicantAndDispatchMessages() throws Exception { - mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_ENABLED); - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - - mLooper.dispatchAll(); - - verify(mWifiLastResortWatchdog, atLeastOnce()).clearAllFailureCounts(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - } - - private void initializeMocksForAddedNetwork(boolean isHidden) throws Exception { - WifiConfiguration config = new WifiConfiguration(); - config.networkId = FRAMEWORK_NETWORK_ID; - config.SSID = sSSID; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - config.hiddenSSID = isHidden; - - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(Arrays.asList(config)); - when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); - } - - private void initializeAndAddNetworkAndVerifySuccess() throws Exception { - initializeAndAddNetworkAndVerifySuccess(false); - } - - private void initializeAndAddNetworkAndVerifySuccess(boolean isHidden) throws Exception { - loadComponentsInStaMode(); - initializeMocksForAddedNetwork(isHidden); - } - - private void setupAndStartConnectSequence(WifiConfiguration config) throws Exception { - when(mWifiConfigManager.enableNetwork( - eq(config.networkId), eq(true), anyInt(), any())) - .thenReturn(true); - when(mWifiConfigManager.updateLastConnectUid(eq(config.networkId), anyInt())) - .thenReturn(true); - when(mWifiConfigManager.getConfiguredNetwork(eq(config.networkId))) - .thenReturn(config); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking( - eq(config.networkId))).thenReturn(config); - - verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, config.networkId, mock(Binder.class), connectActionListener, 0, - Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(mWifiConfigManager).userEnabledNetwork(config.networkId); - verify(connectActionListener).onSuccess(); - } - - private void validateSuccessfulConnectSequence(WifiConfiguration config) { - verify(mWifiConfigManager).enableNetwork( - eq(config.networkId), eq(true), anyInt(), any()); - verify(mWifiConnectivityManager).setUserConnectChoice(eq(config.networkId)); - verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId)); - verify(mWifiConfigManager).getConfiguredNetworkWithoutMasking(eq(config.networkId)); - verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - } - - private void validateFailureConnectSequence(WifiConfiguration config) { - verify(mWifiConfigManager).enableNetwork( - eq(config.networkId), eq(true), anyInt(), any()); - verify(mWifiConnectivityManager).setUserConnectChoice(eq(config.networkId)); - verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId)); - verify(mWifiConfigManager, never()) - .getConfiguredNetworkWithoutMasking(eq(config.networkId)); - verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - } - - /** - * Tests the network connection initiation sequence with the default network request pending - * from WifiNetworkFactory. - * This simulates the connect sequence using the public - * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke - * {@link WifiNative#connectToNetwork(WifiConfiguration)}. - */ - @Test - public void triggerConnect() throws Exception { - loadComponentsInStaMode(); - WifiConfiguration config = mConnectedNetwork; - config.networkId = FRAMEWORK_NETWORK_ID; - config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS); - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - setupAndStartConnectSequence(config); - validateSuccessfulConnectSequence(config); - } - - /** - * Tests the network connection initiation sequence with the default network request pending - * from WifiNetworkFactory. - * This simulates the connect sequence using the public - * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke - * {@link WifiNative#connectToNetwork(WifiConfiguration)}. - */ - @Test - public void triggerConnectFromNonSettingsApp() throws Exception { - loadComponentsInStaMode(); - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - config.networkId = FRAMEWORK_NETWORK_ID; - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(Process.myUid())) - .thenReturn(false); - setupAndStartConnectSequence(config); - verify(mWifiConfigManager).enableNetwork( - eq(config.networkId), eq(true), anyInt(), any()); - verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(config.networkId)); - verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId)); - verify(mWifiConfigManager).getConfiguredNetworkWithoutMasking(eq(config.networkId)); - verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - } - - /** - * Tests the network connection initiation sequence with no network request pending from - * from WifiNetworkFactory. - * This simulates the connect sequence using the public - * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we don't invoke - * {@link WifiNative#connectToNetwork(WifiConfiguration)}. - */ - @Test - public void triggerConnectWithNoNetworkRequest() throws Exception { - loadComponentsInStaMode(); - // Remove the network requests. - when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false); - when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - config.networkId = FRAMEWORK_NETWORK_ID; - setupAndStartConnectSequence(config); - validateFailureConnectSequence(config); - } - - /** - * Tests the entire successful network connection flow. - */ - @Test - public void connect() throws Exception { - triggerConnect(); - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID); - config.carrierId = CARRIER_ID_1; - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - - when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); - when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.ASSOCIATED)); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - - DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable(); - dhcpResults.baseConfiguration = new StaticIpConfiguration(); - dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4"); - dhcpResults.baseConfiguration.ipAddress = - new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0); - dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8")); - dhcpResults.leaseDuration = 3600; - - injectDhcpSuccess(dhcpResults); - mLooper.dispatchAll(); - - // Verify WifiMetrics logging for metered metrics based on DHCP results - verify(mWifiMetrics).addMeteredStat(any(), anyBoolean()); - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertNotNull(wifiInfo); - assertEquals(sBSSID, wifiInfo.getBSSID()); - assertEquals(sFreq, wifiInfo.getFrequency()); - assertTrue(sWifiSsid.equals(wifiInfo.getWifiSsid())); - assertNull(wifiInfo.getPasspointProviderFriendlyName()); - // Ensure the connection stats for the network is updated. - verify(mWifiConfigManager).updateNetworkAfterConnect(FRAMEWORK_NETWORK_ID); - verify(mWifiConfigManager).updateRandomizedMacExpireTime(any(), anyLong()); - - // Anonymous Identity is not set. - assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - verify(mWifiStateTracker).updateState(eq(WifiStateTracker.CONNECTED)); - assertEquals("ConnectedState", getCurrentState().getName()); - verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionSuccess(); - verify(mWifiLockManager).updateWifiClientConnected(true); - verify(mWifiNative).getConnectionCapabilities(any()); - verify(mThroughputPredictor).predictMaxTxThroughput(any()); - verify(mWifiMetrics).setConnectionMaxSupportedLinkSpeedMbps(90, 80); - verify(mWifiDataStall).setConnectionCapabilities(any()); - assertEquals(90, wifiInfo.getMaxSupportedTxLinkSpeedMbps()); - } - - private void setupEapSimConnection() throws Exception { - mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE)); - mConnectedNetwork.carrierId = CARRIER_ID_1; - doReturn(DATA_SUBID).when(mWifiCarrierInfoManager) - .getBestMatchSubscriptionId(any(WifiConfiguration.class)); - when(mDataTelephonyManager.getSimOperator()).thenReturn("123456"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - mConnectedNetwork.enterpriseConfig.setAnonymousIdentity(""); - - triggerConnect(); - - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); - when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - assertEquals("ObtainingIpState", getCurrentState().getName()); - } - - /** - * When the SIM card was removed, if the current wifi connection is not using it, the connection - * should be kept. - */ - @Test - public void testResetSimWhenNonConnectedSimRemoved() throws Exception { - setupEapSimConnection(); - doReturn(true).when(mWifiCarrierInfoManager).isSimPresent(eq(DATA_SUBID)); - mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS, - ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED); - mLooper.dispatchAll(); - - verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), any()); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - } - - /** - * When the SIM card was removed, if the current wifi connection is using it, the connection - * should be disconnected, otherwise, the connection shouldn't be impacted. - */ - @Test - public void testResetSimWhenConnectedSimRemoved() throws Exception { - setupEapSimConnection(); - doReturn(false).when(mWifiCarrierInfoManager).isSimPresent(eq(DATA_SUBID)); - mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS, - ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED); - mLooper.dispatchAll(); - - verify(mSimRequiredNotifier).showSimRequiredNotification(any(), any()); - assertEquals("DisconnectingState", getCurrentState().getName()); - } - - /** - * When the SIM card was removed, if the current wifi connection is using it, the connection - * should be disconnected, otherwise, the connection shouldn't be impacted. - */ - @Test - public void testResetSimWhenConnectedSimRemovedAfterNetworkRemoval() throws Exception { - setupEapSimConnection(); - doReturn(false).when(mWifiCarrierInfoManager).isSimPresent(eq(DATA_SUBID)); - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null); - mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS, - ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED); - mLooper.dispatchAll(); - - verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), any()); - assertEquals("ObtainingIpState", getCurrentState().getName()); - } - - /** - * When the default data SIM is changed, if the current wifi connection is carrier wifi, - * the connection should be disconnected. - */ - @Test - public void testResetSimWhenDefaultDataSimChanged() throws Exception { - setupEapSimConnection(); - mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS, - ClientModeImpl.RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED); - mLooper.dispatchAll(); - - assertEquals("DisconnectingState", getCurrentState().getName()); - } - - /** - * Tests anonymous identity is set again whenever a connection is established for the carrier - * that supports encrypted IMSI and anonymous identity and no real pseudonym was provided. - */ - @Test - public void testSetAnonymousIdentityWhenConnectionIsEstablishedNoPseudonym() throws Exception { - mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE)); - when(mDataTelephonyManager.getSimOperator()).thenReturn("123456"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - mConnectedNetwork.enterpriseConfig.setAnonymousIdentity(""); - - String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org"; - MockitoSession mockSession = ExtendedMockito.mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID); - doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt()); - - // Initial value should be "not set" - assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - - triggerConnect(); - - // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm> - assertEquals(expectedAnonymousIdentity, - mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); - when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - when(mWifiNative.getEapAnonymousIdentity(anyString())) - .thenReturn(expectedAnonymousIdentity); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(mWifiNative).getEapAnonymousIdentity(any()); - - // Post connection value should remain "not set" - assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - // verify that WifiConfigManager#addOrUpdateNetwork() was called to clear any previously - // stored pseudonym. i.e. to enable Encrypted IMSI for subsequent connections. - // Note: This test will fail if future logic will have additional conditions that would - // trigger "add or update network" operation. The test needs to be updated to account for - // this change. - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt()); - mockSession.finishMocking(); - } - - /** - * Tests anonymous identity is set again whenever a connection is established for the carrier - * that supports encrypted IMSI and anonymous identity but real pseudonym was provided for - * subsequent connections. - */ - @Test - public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonym() - throws Exception { - mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE)); - when(mDataTelephonyManager.getSimOperator()).thenReturn("123456"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - mConnectedNetwork.enterpriseConfig.setAnonymousIdentity(""); - - String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org"; - String pseudonym = "83bcca9384fca@wlan.mnc456.mcc123.3gppnetwork.org"; - MockitoSession mockSession = ExtendedMockito.mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID); - doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt()); - - triggerConnect(); - - // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm> - assertEquals(expectedAnonymousIdentity, - mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); - when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - when(mWifiNative.getEapAnonymousIdentity(anyString())) - .thenReturn(pseudonym); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(mWifiNative).getEapAnonymousIdentity(any()); - assertEquals(pseudonym, - mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a - // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by - // pseudonym usage in all subsequent connections. - // Note: This test will fail if future logic will have additional conditions that would - // trigger "add or update network" operation. The test needs to be updated to account for - // this change. - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt()); - mockSession.finishMocking(); - } - - /** - * Tests anonymous identity is set again whenever a connection is established for the carrier - * that supports encrypted IMSI and anonymous identity but real but not decorated pseudonym was - * provided for subsequent connections. - */ - @Test - public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithNonDecoratedPseudonym() - throws Exception { - mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE)); - when(mDataTelephonyManager.getSimOperator()).thenReturn("123456"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - mConnectedNetwork.enterpriseConfig.setAnonymousIdentity(""); - - String realm = "wlan.mnc456.mcc123.3gppnetwork.org"; - String expectedAnonymousIdentity = "anonymous"; - String pseudonym = "83bcca9384fca"; - MockitoSession mockSession = ExtendedMockito.mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID); - doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt()); - - triggerConnect(); - - // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm> - assertEquals(expectedAnonymousIdentity + "@" + realm, - mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); - when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - when(mWifiNative.getEapAnonymousIdentity(anyString())) - .thenReturn(pseudonym); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(mWifiNative).getEapAnonymousIdentity(any()); - assertEquals(pseudonym + "@" + realm, - mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a - // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by - // pseudonym usage in all subsequent connections. - // Note: This test will fail if future logic will have additional conditions that would - // trigger "add or update network" operation. The test needs to be updated to account for - // this change. - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt()); - mockSession.finishMocking(); - } - /** - * Tests the Passpoint information is set in WifiInfo for Passpoint AP connection. - */ - @Test - public void connectPasspointAp() throws Exception { - loadComponentsInStaMode(); - WifiConfiguration config = spy(WifiConfigurationTestUtil.createPasspointNetwork()); - config.SSID = sWifiSsid.toString(); - config.BSSID = sBSSID; - config.networkId = FRAMEWORK_NETWORK_ID; - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - setupAndStartConnectSequence(config); - validateSuccessfulConnectSequence(config); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID, - SupplicantState.ASSOCIATING)); - mLooper.dispatchAll(); - - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertNotNull(wifiInfo); - assertEquals(WifiConfigurationTestUtil.TEST_FQDN, wifiInfo.getPasspointFqdn()); - assertEquals(WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME, - wifiInfo.getPasspointProviderFriendlyName()); - } - - /** - * Tests that Passpoint fields in WifiInfo are reset when connecting to a non-Passpoint network - * during DisconnectedState. - * @throws Exception - */ - @Test - public void testResetWifiInfoPasspointFields() throws Exception { - loadComponentsInStaMode(); - WifiConfiguration config = spy(WifiConfigurationTestUtil.createPasspointNetwork()); - config.SSID = sWifiSsid.toString(); - config.BSSID = sBSSID; - config.networkId = PASSPOINT_NETWORK_ID; - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - setupAndStartConnectSequence(config); - validateSuccessfulConnectSequence(config); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(PASSPOINT_NETWORK_ID, sWifiSsid, sBSSID, - SupplicantState.ASSOCIATING)); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID, - SupplicantState.ASSOCIATING)); - mLooper.dispatchAll(); - - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertNotNull(wifiInfo); - assertNull(wifiInfo.getPasspointFqdn()); - assertNull(wifiInfo.getPasspointProviderFriendlyName()); - } - - /** - * Tests the OSU information is set in WifiInfo for OSU AP connection. - */ - @Test - public void connectOsuAp() throws Exception { - loadComponentsInStaMode(); - WifiConfiguration osuConfig = spy(WifiConfigurationTestUtil.createEphemeralNetwork()); - osuConfig.SSID = sWifiSsid.toString(); - osuConfig.BSSID = sBSSID; - osuConfig.osu = true; - osuConfig.networkId = FRAMEWORK_NETWORK_ID; - osuConfig.providerFriendlyName = WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME; - osuConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - setupAndStartConnectSequence(osuConfig); - validateSuccessfulConnectSequence(osuConfig); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID, - SupplicantState.ASSOCIATING)); - mLooper.dispatchAll(); - - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertNotNull(wifiInfo); - assertTrue(wifiInfo.isOsuAp()); - assertEquals(WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME, - wifiInfo.getPasspointProviderFriendlyName()); - } - - /** - * Tests that OSU fields in WifiInfo are reset when connecting to a non-OSU network during - * DisconnectedState. - * @throws Exception - */ - @Test - public void testResetWifiInfoOsuFields() throws Exception { - loadComponentsInStaMode(); - WifiConfiguration osuConfig = spy(WifiConfigurationTestUtil.createEphemeralNetwork()); - osuConfig.SSID = sWifiSsid.toString(); - osuConfig.BSSID = sBSSID; - osuConfig.osu = true; - osuConfig.networkId = PASSPOINT_NETWORK_ID; - osuConfig.providerFriendlyName = WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME; - osuConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - setupAndStartConnectSequence(osuConfig); - validateSuccessfulConnectSequence(osuConfig); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(PASSPOINT_NETWORK_ID, sWifiSsid, sBSSID, - SupplicantState.ASSOCIATING)); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID, - SupplicantState.ASSOCIATING)); - mLooper.dispatchAll(); - - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertNotNull(wifiInfo); - assertFalse(wifiInfo.isOsuAp()); - } - - /** - * Verify that WifiStateTracker is called if wifi is disabled while connected. - */ - @Test - public void verifyWifiStateTrackerUpdatedWhenDisabled() throws Exception { - connect(); - - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - verify(mWifiStateTracker).updateState(eq(WifiStateTracker.DISCONNECTED)); - } - - /** - * Tests the network connection initiation sequence with no network request pending from - * from WifiNetworkFactory when we're already connected to a different network. - * This simulates the connect sequence using the public - * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke - * {@link WifiNative#connectToNetwork(WifiConfiguration)}. - */ - @Test - public void triggerConnectWithNoNetworkRequestAndAlreadyConnected() throws Exception { - // Simulate the first connection. - connect(); - - // Remove the network requests. - when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false); - when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - config.networkId = FRAMEWORK_NETWORK_ID + 1; - setupAndStartConnectSequence(config); - validateSuccessfulConnectSequence(config); - verify(mWifiPermissionsUtil, atLeastOnce()).checkNetworkSettingsPermission(anyInt()); - } - - /** - * Tests the network connection initiation sequence from a non-privileged app with no network - * request pending from from WifiNetworkFactory when we're already connected to a different - * network. - * This simulates the connect sequence using the public - * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we don't invoke - * {@link WifiNative#connectToNetwork(WifiConfiguration)}. - */ - @Test - public void triggerConnectWithNoNetworkRequestAndAlreadyConnectedButNonPrivilegedApp() - throws Exception { - // Simulate the first connection. - connect(); - - // Remove the network requests. - when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false); - when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false); - - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - config.networkId = FRAMEWORK_NETWORK_ID + 1; - setupAndStartConnectSequence(config); - verify(mWifiConfigManager).enableNetwork( - eq(config.networkId), eq(true), anyInt(), any()); - verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(config.networkId)); - verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId)); - verify(mWifiConfigManager, never()) - .getConfiguredNetworkWithoutMasking(eq(config.networkId)); - verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - verify(mWifiPermissionsUtil, times(4)).checkNetworkSettingsPermission(anyInt()); - } - - @Test - public void enableWithInvalidNetworkId() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - when(mWifiConfigManager.getConfiguredNetwork(eq(0))).thenReturn(null); - - verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onFailure(anyInt()); - - verify(mWifiConfigManager, never()).enableNetwork(eq(0), eq(true), anyInt(), any()); - verify(mWifiConfigManager, never()).updateLastConnectUid(eq(0), anyInt()); - } - - /** - * If caller tries to connect to a network that is already connected, the connection request - * should succeed. - * - * Test: Create and connect to a network, then try to reconnect to the same network. Verify - * that connection request returns with CONNECT_NETWORK_SUCCEEDED. - */ - @Test - public void reconnectToConnectedNetworkWithNetworkId() throws Exception { - connect(); - - // try to reconnect - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0, - Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - // Verify that we didn't trigger a second connection. - verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any()); - } - - /** - * If caller tries to connect to a network that is already connected, the connection request - * should succeed. - * - * Test: Create and connect to a network, then try to reconnect to the same network. Verify - * that connection request returns with CONNECT_NETWORK_SUCCEEDED. - */ - @Test - public void reconnectToConnectedNetworkWithConfig() throws Exception { - connect(); - - // try to reconnect - WifiConfiguration config = new WifiConfiguration(); - config.networkId = FRAMEWORK_NETWORK_ID; - when(mWifiConfigManager.addOrUpdateNetwork(eq(config), anyInt())) - .thenReturn(new NetworkUpdateResult(FRAMEWORK_NETWORK_ID)); - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(config, WifiConfiguration.INVALID_NETWORK_ID, mock(Binder.class), - connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - // Verify that we didn't trigger a second connection. - verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any()); - } - - /** - * If caller tries to connect to a network that is already connecting, the connection request - * should succeed. - * - * Test: Create and trigger connect to a network, then try to reconnect to the same network. - * Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED and did not trigger a - * new connection. - */ - @Test - public void reconnectToConnectingNetwork() throws Exception { - triggerConnect(); - - // try to reconnect to the same network (before connection is established). - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0, - Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - // Verify that we didn't trigger a second connection. - verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any()); - } - - /** - * If caller tries to connect to a network that is already connecting, the connection request - * should succeed. - * - * Test: Create and trigger connect to a network, then try to reconnect to the same network. - * Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED and did trigger a new - * connection. - */ - @Test - public void reconnectToConnectingNetworkWithCredentialChange() throws Exception { - triggerConnect(); - - // try to reconnect to the same network with a credential changed (before connection is - // established). - WifiConfiguration config = new WifiConfiguration(); - config.networkId = FRAMEWORK_NETWORK_ID; - NetworkUpdateResult networkUpdateResult = - new NetworkUpdateResult(false /* ip */, false /* proxy */, true /* credential */); - networkUpdateResult.setNetworkId(FRAMEWORK_NETWORK_ID); - when(mWifiConfigManager.addOrUpdateNetwork(eq(config), anyInt())) - .thenReturn(networkUpdateResult); - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(config, WifiConfiguration.INVALID_NETWORK_ID, mock(Binder.class), - connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - // Verify that we triggered a second connection. - verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any()); - } - - /** - * If caller tries to connect to a network that previously failed connection, the connection - * request should succeed. - * - * Test: Create and trigger connect to a network, then fail the connection. Now try to reconnect - * to the same network. Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED - * and did trigger a new * connection. - */ - @Test - public void connectAfterAssociationRejection() throws Exception { - triggerConnect(); - - // fail the connection. - mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, - ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID); - mLooper.dispatchAll(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0, - Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - // Verify that we triggered a second connection. - verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any()); - } - - /** - * If caller tries to connect to a network that previously failed connection, the connection - * request should succeed. - * - * Test: Create and trigger connect to a network, then fail the connection. Now try to reconnect - * to the same network. Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED - * and did trigger a new * connection. - */ - @Test - public void connectAfterConnectionFailure() throws Exception { - triggerConnect(); - - // fail the connection. - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, FRAMEWORK_NETWORK_ID, 0, sBSSID); - mLooper.dispatchAll(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0, - Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - // Verify that we triggered a second connection. - verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any()); - } - - /** - * If caller tries to connect to a new network while still provisioning the current one, - * the connection attempt should succeed. - */ - @Test - public void connectWhileObtainingIp() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - reset(mWifiNative); - - // Connect to a different network - WifiConfiguration config = new WifiConfiguration(); - config.networkId = TEST_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config); - - mCmi.connect(null, TEST_NETWORK_ID, mock(Binder.class), null, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); - mLooper.dispatchAll(); - - verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId)); - - } - - /** - * Tests that manual connection to a network (from settings app) logs the correct nominator ID. - */ - @Test - public void testManualConnectNominator() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - WifiConfiguration config = new WifiConfiguration(); - config.networkId = TEST_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, TEST_NETWORK_ID, mock(Binder.class), connectActionListener, 0, - Process.SYSTEM_UID); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiMetrics).setNominatorForNetwork(TEST_NETWORK_ID, - WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL); - } - - @Test - public void testDhcpFailure() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.ASSOCIATED)); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - verify(mBssidBlocklistMonitor).handleBssidConnectionSuccess(sBSSID, sSSID); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - injectDhcpFailure(); - mLooper.dispatchAll(); - - assertEquals("DisconnectingState", getCurrentState().getName()); - // Verify this is not counted as a IP renewal failure - verify(mWifiMetrics, never()).incrementIpRenewalFailure(); - // Verifies that WifiLastResortWatchdog be notified - // by DHCP failure - verify(mWifiLastResortWatchdog, times(2)).noteConnectionFailureAndTriggerIfNeeded( - sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_DHCP); - verify(mBssidBlocklistMonitor, times(2)).handleBssidConnectionFailure(eq(sBSSID), - eq(sSSID), eq(BssidBlocklistMonitor.REASON_DHCP_FAILURE), anyInt()); - verify(mBssidBlocklistMonitor, times(2)).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID), - eq(BssidBlocklistMonitor.REASON_DHCP_FAILURE), anyInt()); - verify(mBssidBlocklistMonitor, never()).handleDhcpProvisioningSuccess(sBSSID, sSSID); - verify(mBssidBlocklistMonitor, never()).handleNetworkValidationSuccess(sBSSID, sSSID); - } - - /** - * Verify that a IP renewal failure is logged when IP provisioning fail in the - * ConnectedState. - */ - @Test - public void testDhcpRenewalMetrics() throws Exception { - connect(); - injectDhcpFailure(); - mLooper.dispatchAll(); - - verify(mWifiMetrics).incrementIpRenewalFailure(); - } - - /** - * Verify that the network selection status will be updated with DISABLED_AUTHENTICATION_FAILURE - * when wrong password authentication failure is detected and the network had been - * connected previously. - */ - @Test - public void testWrongPasswordWithPreviouslyConnected() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - WifiConfiguration config = new WifiConfiguration(); - config.getNetworkSelectionStatus().setHasEverConnected(true); - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config); - - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); - mLooper.dispatchAll(); - - verify(mWrongPasswordNotifier, never()).onWrongPasswordError(anyString()); - verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(), - eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE)); - - assertEquals("DisconnectedState", getCurrentState().getName()); - } - - /** - * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD - * when wrong password authentication failure is detected and the network has never been - * connected. - */ - @Test - public void testWrongPasswordWithNeverConnected() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - WifiConfiguration config = new WifiConfiguration(); - config.SSID = sSSID; - config.getNetworkSelectionStatus().setHasEverConnected(false); - config.carrierId = CARRIER_ID_1; - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config); - - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); - mLooper.dispatchAll(); - - verify(mWrongPasswordNotifier).onWrongPasswordError(eq(sSSID)); - verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(), - eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD)); - verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionAuthFailure(); - assertEquals("DisconnectedState", getCurrentState().getName()); - } - - /** - * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD - * when wrong password authentication failure is detected and the network is unknown. - */ - @Test - public void testWrongPasswordWithNullNetwork() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null); - - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); - mLooper.dispatchAll(); - - verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(), - eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD)); - assertEquals("DisconnectedState", getCurrentState().getName()); - } - - /** - * Verify that the function resetCarrierKeysForImsiEncryption() in TelephonyManager - * is called when a Authentication failure is detected with a vendor specific EAP Error - * of certification expired while using EAP-SIM - * In this test case, it is assumed that the network had been connected previously. - */ - @Test - public void testEapSimErrorVendorSpecific() throws Exception { - when(mWifiMetrics.startConnectionEvent(any(), anyString(), anyInt())).thenReturn(80000); - initializeAndAddNetworkAndVerifySuccess(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - WifiConfiguration config = new WifiConfiguration(); - config.SSID = sSSID; - config.getNetworkSelectionStatus().setHasEverConnected(true); - config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); - config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config); - MockitoSession mockSession = ExtendedMockito.mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID); - when(SubscriptionManager.isValidSubscriptionId(anyInt())).thenReturn(true); - when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString())) - .thenReturn(WifiHealthMonitor.REASON_AUTH_FAILURE); - - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, - WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED); - mLooper.dispatchAll(); - - verify(mEapFailureNotifier).onEapFailure( - WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED, config); - verify(mDataTelephonyManager).resetCarrierKeysForImsiEncryption(); - mockSession.finishMocking(); - verify(mDeviceConfigFacade).isAbnormalConnectionFailureBugreportEnabled(); - verify(mWifiScoreCard).detectAbnormalConnectionFailure(anyString()); - verify(mWifiDiagnostics, times(2)).takeBugReport(anyString(), anyString()); - } - - /** - * Verify that the function resetCarrierKeysForImsiEncryption() in TelephonyManager - * is not called when a Authentication failure is detected with a vendor specific EAP Error - * of certification expired while using other methods than EAP-SIM, EAP-AKA, or EAP-AKA'. - */ - @Test - public void testEapTlsErrorVendorSpecific() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - WifiConfiguration config = new WifiConfiguration(); - config.getNetworkSelectionStatus().setHasEverConnected(true); - config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config); - - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, - WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED); - mLooper.dispatchAll(); - - verify(mDataTelephonyManager, never()).resetCarrierKeysForImsiEncryption(); - } - - /** - * Verify that the network selection status will be updated with - * DISABLED_AUTHENTICATION_NO_SUBSCRIBED when service is not subscribed. - */ - @Test - public void testEapSimNoSubscribedError() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null); - - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, - WifiNative.EAP_SIM_NOT_SUBSCRIBED); - mLooper.dispatchAll(); - - verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(), - eq(WifiConfiguration.NetworkSelectionStatus - .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION)); - } - - @Test - public void testBadNetworkEvent() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString()); - } - - - @Test - public void getWhatToString() throws Exception { - assertEquals("CMD_CHANNEL_HALF_CONNECTED", mCmi.getWhatToString( - AsyncChannel.CMD_CHANNEL_HALF_CONNECTED)); - assertEquals("CMD_PRE_DHCP_ACTION", mCmi.getWhatToString(CMD_PRE_DHCP_ACTION)); - assertEquals("CMD_IP_REACHABILITY_LOST", mCmi.getWhatToString( - ClientModeImpl.CMD_IP_REACHABILITY_LOST)); - } - - @Test - public void disconnect() throws Exception { - when(mWifiScoreCard.detectAbnormalDisconnection()) - .thenReturn(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL); - InOrder inOrderWifiLockManager = inOrder(mWifiLockManager); - connect(); - inOrderWifiLockManager.verify(mWifiLockManager).updateWifiClientConnected(true); - - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, sBSSID); - mLooper.dispatchAll(); - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); - mLooper.dispatchAll(); - - verify(mWifiStateTracker).updateState(eq(WifiStateTracker.DISCONNECTED)); - verify(mWifiNetworkSuggestionsManager).handleDisconnect(any(), any()); - assertEquals("DisconnectedState", getCurrentState().getName()); - inOrderWifiLockManager.verify(mWifiLockManager).updateWifiClientConnected(false); - verify(mWifiScoreCard).detectAbnormalDisconnection(); - verify(mWifiDiagnostics).takeBugReport(anyString(), anyString()); - } - - /** - * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected - * to true. - * - * Test: Successfully create and connect to a network. Check the config and verify - * WifiConfiguration.getHasEverConnected() is true. - */ - @Test - public void setHasEverConnectedTrueOnConnect() throws Exception { - connect(); - verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(0); - } - - /** - * Fail network connection attempt and verify HasEverConnected remains false. - * - * Test: Successfully create a network but fail when connecting. Check the config and verify - * WifiConfiguration.getHasEverConnected() is false. - */ - @Test - public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception { - testDhcpFailure(); - verify(mWifiConfigManager, never()).updateNetworkAfterConnect(0); - } - - @Test - public void iconQueryTest() throws Exception { - // TODO(b/31065385): Passpoint config management. - } - - @Test - public void verboseLogRecSizeIsGreaterThanNormalSize() { - assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > ClientModeImpl.NUM_LOG_RECS_NORMAL); - } - - /** - * Verifies that, by default, we allow only the "normal" number of log records. - */ - @Test - public void normalLogRecSizeIsUsedByDefault() { - assertEquals(ClientModeImpl.NUM_LOG_RECS_NORMAL, mCmi.getLogRecMaxSize()); - } - - /** - * Verifies that, in verbose mode, we allow a larger number of log records. - */ - @Test - public void enablingVerboseLoggingUpdatesLogRecSize() { - mCmi.enableVerboseLogging(1); - assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mCmi.getLogRecMaxSize()); - } - - @Test - public void disablingVerboseLoggingClearsRecords() { - mCmi.sendMessage(ClientModeImpl.CMD_DISCONNECT); - mLooper.dispatchAll(); - assertTrue(mCmi.getLogRecSize() >= 1); - - mCmi.enableVerboseLogging(0); - assertEquals(0, mCmi.getLogRecSize()); - } - - @Test - public void disablingVerboseLoggingUpdatesLogRecSize() { - mCmi.enableVerboseLogging(1); - mCmi.enableVerboseLogging(0); - assertEquals(ClientModeImpl.NUM_LOG_RECS_NORMAL, mCmi.getLogRecMaxSize()); - } - - @Test - public void logRecsIncludeDisconnectCommand() { - // There's nothing special about the DISCONNECT command. It's just representative of - // "normal" commands. - mCmi.sendMessage(ClientModeImpl.CMD_DISCONNECT); - mLooper.dispatchAll(); - assertEquals(1, mCmi.copyLogRecs() - .stream() - .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_DISCONNECT) - .count()); - } - - @Test - public void logRecsExcludeRssiPollCommandByDefault() { - mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL); - mLooper.dispatchAll(); - assertEquals(0, mCmi.copyLogRecs() - .stream() - .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_RSSI_POLL) - .count()); - } - - @Test - public void logRecsIncludeRssiPollCommandWhenVerboseLoggingIsEnabled() { - mCmi.enableVerboseLogging(1); - mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL); - mLooper.dispatchAll(); - assertEquals(1, mCmi.copyLogRecs() - .stream() - .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_RSSI_POLL) - .count()); - } - - /** - * Verify that syncStartSubscriptionProvisioning will redirect calls with right parameters - * to {@link PasspointManager} with expected true being returned when in client mode. - */ - @Test - public void syncStartSubscriptionProvisioningInClientMode() throws Exception { - loadComponentsInStaMode(); - when(mPasspointManager.startSubscriptionProvisioning(anyInt(), - any(OsuProvider.class), any(IProvisioningCallback.class))).thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mCmi.syncStartSubscriptionProvisioning( - OTHER_USER_UID, mOsuProvider, mProvisioningCallback, mCmiAsyncChannel)); - verify(mPasspointManager).startSubscriptionProvisioning(OTHER_USER_UID, mOsuProvider, - mProvisioningCallback); - mLooper.stopAutoDispatch(); - } - - /** - * Verify that syncStartSubscriptionProvisioning will be a no-op and return false before - * SUPPLICANT_START command is received by the CMI. - */ - @Test - public void syncStartSubscriptionProvisioningBeforeSupplicantOrAPStart() throws Exception { - mLooper.startAutoDispatch(); - assertFalse(mCmi.syncStartSubscriptionProvisioning( - OTHER_USER_UID, mOsuProvider, mProvisioningCallback, mCmiAsyncChannel)); - mLooper.stopAutoDispatch(); - verify(mPasspointManager, never()).startSubscriptionProvisioning( - anyInt(), any(OsuProvider.class), any(IProvisioningCallback.class)); - } - - /** - * Verify that syncStartSubscriptionProvisioning will be a no-op and return false when not in - * client mode. - */ - @Test - public void syncStartSubscriptionProvisioningNoOpWifiDisabled() throws Exception { - mLooper.startAutoDispatch(); - assertFalse(mCmi.syncStartSubscriptionProvisioning( - OTHER_USER_UID, mOsuProvider, mProvisioningCallback, mCmiAsyncChannel)); - mLooper.stopAutoDispatch(); - verify(mPasspointManager, never()).startSubscriptionProvisioning( - anyInt(), any(OsuProvider.class), any(IProvisioningCallback.class)); - } - - /** - * Test that we disconnect from a network if it was removed while we are in the - * ObtainingIpState. - */ - @Test - public void disconnectFromNetworkWhenRemovedWhileObtainingIpAddr() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt(), any())) - .thenReturn(true); - when(mWifiConfigManager.updateLastConnectUid(eq(0), anyInt())).thenReturn(true); - - verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - verify(mWifiConnectivityManager).setUserConnectChoice(eq(0)); - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - - when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); - when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - - // now remove the config - reset(connectActionListener); - when(mWifiConfigManager.removeNetwork(eq(FRAMEWORK_NETWORK_ID), anyInt(), any())) - .thenReturn(true); - mCmi.forget(FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0, - Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - verify(mWifiConfigManager).removeNetwork(eq(FRAMEWORK_NETWORK_ID), anyInt(), any()); - // trigger removal callback to trigger disconnect. - WifiConfiguration removedConfig = new WifiConfiguration(); - removedConfig.networkId = FRAMEWORK_NETWORK_ID; - mConfigUpdateListenerCaptor.getValue().onNetworkRemoved(removedConfig); - - reset(mWifiConfigManager); - - when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID)).thenReturn(null); - - DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable(); - dhcpResults.baseConfiguration = new StaticIpConfiguration(); - dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4"); - dhcpResults.baseConfiguration.ipAddress = - new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0); - dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8")); - dhcpResults.leaseDuration = 3600; - - injectDhcpSuccess(dhcpResults); - mLooper.dispatchAll(); - - assertEquals("DisconnectingState", getCurrentState().getName()); - } - - /** - * Test verifying that interface Supplicant update for inactive driver does not trigger - * SelfRecovery when WifiNative reports the interface is up. - */ - @Test - public void testSupplicantUpdateDriverInactiveIfaceUpClientModeDoesNotTriggerSelfRecovery() - throws Exception { - // Trigger initialize to capture the death handler registration. - loadComponentsInStaMode(); - - when(mWifiNative.isInterfaceUp(eq(WIFI_IFACE_NAME))).thenReturn(true); - - // make sure supplicant has been reported as inactive - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, WifiSsid.createFromAsciiEncoded(""), null, - SupplicantState.INTERFACE_DISABLED)); - mLooper.dispatchAll(); - - // CMI should trigger self recovery, but not disconnect until externally triggered - verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); - } - - /** - * Verifies that WifiInfo is updated upon SUPPLICANT_STATE_CHANGE_EVENT. - */ - @Test - public void testWifiInfoUpdatedUponSupplicantStateChangedEvent() throws Exception { - // Connect to network with |sBSSID|, |sFreq|. - connect(); - - // Set the scan detail cache for roaming target. - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - when(mScanDetailCache.getScanDetail(sBSSID1)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq1)); - when(mScanDetailCache.getScanResult(sBSSID1)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq1).getScanResult()); - - // This simulates the behavior of roaming to network with |sBSSID1|, |sFreq1|. - // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated. - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID1, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertEquals(sBSSID1, wifiInfo.getBSSID()); - assertEquals(sFreq1, wifiInfo.getFrequency()); - assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState()); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID1, SupplicantState.DISCONNECTED)); - mLooper.dispatchAll(); - - wifiInfo = mCmi.getWifiInfo(); - assertNull(wifiInfo.getBSSID()); - assertEquals(WifiManager.UNKNOWN_SSID, wifiInfo.getSSID()); - assertEquals(WifiConfiguration.INVALID_NETWORK_ID, wifiInfo.getNetworkId()); - assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); - } - - /** - * Verifies that WifiInfo is updated upon CMD_ASSOCIATED_BSSID event. - */ - @Test - public void testWifiInfoUpdatedUponAssociatedBSSIDEvent() throws Exception { - // Connect to network with |sBSSID|, |sFreq|. - connect(); - - // Set the scan detail cache for roaming target. - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - when(mScanDetailCache.getScanDetail(sBSSID1)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq1)); - when(mScanDetailCache.getScanResult(sBSSID1)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq1).getScanResult()); - - // This simulates the behavior of roaming to network with |sBSSID1|, |sFreq1|. - // Send a CMD_ASSOCIATED_BSSID, verify WifiInfo is updated. - mCmi.sendMessage(WifiMonitor.ASSOCIATED_BSSID_EVENT, 0, 0, sBSSID1); - mLooper.dispatchAll(); - - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertEquals(sBSSID1, wifiInfo.getBSSID()); - assertEquals(sFreq1, wifiInfo.getFrequency()); - assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState()); - } - - /** - * Verifies that WifiInfo is cleared upon exiting and entering WifiInfo, and that it is not - * updated by SUPPLICAN_STATE_CHANGE_EVENTs in ScanModeState. - * This protects ClientModeImpl from getting into a bad state where WifiInfo says wifi is - * already Connected or Connecting, (when it is in-fact Disconnected), so - * WifiConnectivityManager does not attempt any new Connections, freezing wifi. - */ - @Test - public void testWifiInfoCleanedUpEnteringExitingConnectModeState() throws Exception { - InOrder inOrder = inOrder(mWifiConnectivityManager, mWifiNetworkFactory); - InOrder inOrderSarMgr = inOrder(mSarManager); - InOrder inOrderMetrics = inOrder(mWifiMetrics); - Log.i(TAG, mCmi.getCurrentState().getName()); - String initialBSSID = "aa:bb:cc:dd:ee:ff"; - WifiInfo wifiInfo = mCmi.getWifiInfo(); - wifiInfo.setBSSID(initialBSSID); - - // Set CMI to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager - startSupplicantAndDispatchMessages(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true)); - inOrder.verify(mWifiNetworkFactory).setWifiState(eq(true)); - inOrderMetrics.verify(mWifiMetrics) - .setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); - inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_ENABLED); - assertNull(wifiInfo.getBSSID()); - - // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - assertEquals(sBSSID, wifiInfo.getBSSID()); - assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState()); - - // Set CMI to DISABLED_MODE, verify state and wifi disabled in ConnectivityManager, and - // WifiInfo is reset() and state set to DISCONNECTED - mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - - assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest()); - assertEquals("DefaultState", getCurrentState().getName()); - assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState()); - inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(false)); - inOrder.verify(mWifiNetworkFactory).setWifiState(eq(false)); - inOrderMetrics.verify(mWifiMetrics).setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); - inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_DISABLED); - assertNull(wifiInfo.getBSSID()); - assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); - verify(mPasspointManager).clearAnqpRequestsAndFlushCache(); - - // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is not updated - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - assertNull(wifiInfo.getBSSID()); - assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); - - // Set the bssid to something, so we can verify it is cleared (just in case) - wifiInfo.setBSSID(initialBSSID); - - // Set CMI to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager, - // and WifiInfo has been reset - startSupplicantAndDispatchMessages(); - - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true)); - inOrder.verify(mWifiNetworkFactory).setWifiState(eq(true)); - inOrderMetrics.verify(mWifiMetrics) - .setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); - inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_ENABLED); - assertEquals("DisconnectedState", getCurrentState().getName()); - assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); - assertNull(wifiInfo.getBSSID()); - } - - /** - * Test that connected SSID and BSSID are exposed to system server. - * Also tests that {@link ClientModeImpl#syncRequestConnectionInfo()} always - * returns a copy of WifiInfo. - */ - @Test - public void testConnectedIdsAreVisibleFromSystemServer() throws Exception { - WifiInfo wifiInfo = mCmi.getWifiInfo(); - // Get into a connected state, with known BSSID and SSID - connect(); - assertEquals(sBSSID, wifiInfo.getBSSID()); - assertEquals(sWifiSsid, wifiInfo.getWifiSsid()); - - WifiInfo connectionInfo = mCmi.syncRequestConnectionInfo(); - - assertNotEquals(wifiInfo, connectionInfo); - assertEquals(wifiInfo.getSSID(), connectionInfo.getSSID()); - assertEquals(wifiInfo.getBSSID(), connectionInfo.getBSSID()); - assertEquals(wifiInfo.getMacAddress(), connectionInfo.getMacAddress()); - } - - /** - * Test that reconnectCommand() triggers connectivity scan when ClientModeImpl - * is in DisconnectedMode. - */ - @Test - public void testReconnectCommandWhenDisconnected() throws Exception { - // Connect to network with |sBSSID|, |sFreq|, and then disconnect. - disconnect(); - - mCmi.reconnectCommand(ClientModeImpl.WIFI_WORK_SOURCE); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager).forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); - } - - /** - * Test that reconnectCommand() doesn't trigger connectivity scan when ClientModeImpl - * is in ConnectedMode. - */ - @Test - public void testReconnectCommandWhenConnected() throws Exception { - // Connect to network with |sBSSID|, |sFreq|. - connect(); - - mCmi.reconnectCommand(ClientModeImpl.WIFI_WORK_SOURCE); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager, never()) - .forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); - } - - /** - * Adds the network without putting ClientModeImpl into ConnectMode. - */ - @Test - public void addNetworkInDefaultState() throws Exception { - // We should not be in initial state now. - assertTrue("DefaultState".equals(getCurrentState().getName())); - initializeMocksForAddedNetwork(false); - verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0)); - } - - /** - * Verifies that ClientModeImpl sets and unsets appropriate 'RecentFailureReason' values - * on a WifiConfiguration when it fails association, authentication, or successfully connects - */ - @Test - public void testExtraFailureReason_ApIsBusy() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - // Trigger a connection to this (CMD_START_CONNECT will actually fail, but it sets up - // targetNetworkId state) - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - // Simulate an ASSOCIATION_REJECTION_EVENT, due to the AP being busy - mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, - ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID); - mLooper.dispatchAll(); - verify(mWifiConfigManager).setRecentFailureAssociationStatus(eq(0), - eq(WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA)); - assertEquals("DisconnectedState", getCurrentState().getName()); - - // Simulate an AUTHENTICATION_FAILURE_EVENT, which should clear the ExtraFailureReason - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, 0, null); - mLooper.dispatchAll(); - verify(mWifiConfigManager, times(1)).clearRecentFailureReason(eq(0)); - verify(mWifiConfigManager, times(1)).setRecentFailureAssociationStatus(anyInt(), anyInt()); - - // Simulate a NETWORK_CONNECTION_EVENT which should clear the ExtraFailureReason - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); - mLooper.dispatchAll(); - verify(mWifiConfigManager, times(2)).clearRecentFailureReason(eq(0)); - verify(mWifiConfigManager, times(1)).setRecentFailureAssociationStatus(anyInt(), anyInt()); - } - - private WifiConfiguration makeLastSelectedWifiConfiguration(int lastSelectedNetworkId, - long timeSinceLastSelected) { - long lastSelectedTimestamp = 45666743454L; - - when(mClock.getElapsedSinceBootMillis()).thenReturn( - lastSelectedTimestamp + timeSinceLastSelected); - when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp); - when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId); - - WifiConfiguration currentConfig = new WifiConfiguration(); - currentConfig.networkId = lastSelectedNetworkId; - return currentConfig; - } - - /** - * Test that the helper method - * {@link ClientModeImpl#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)} - * returns true when we connect to the last selected network before expiration of - * {@link ClientModeImpl#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}. - */ - @Test - public void testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkNotExpired() { - WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5, - ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1); - assertTrue(mCmi.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig)); - } - - /** - * Test that the helper method - * {@link ClientModeImpl#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)} - * returns false when we connect to the last selected network after expiration of - * {@link ClientModeImpl#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}. - */ - @Test - public void testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkExpired() { - WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5, - ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS + 1); - assertFalse(mCmi.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig)); - } - - /** - * Test that the helper method - * {@link ClientModeImpl#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)} - * returns false when we connect to a different network to the last selected network. - */ - @Test - public void testShouldEvaluateWhetherToSendExplicitlySelected_DifferentNetwork() { - WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5, - ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1); - currentConfig.networkId = 4; - assertFalse(mCmi.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig)); - } - - private void expectRegisterNetworkAgent(Consumer<NetworkAgentConfig> configChecker, - Consumer<NetworkCapabilities> networkCapabilitiesChecker) { - // Expects that the code calls registerNetworkAgent and provides a way for the test to - // verify the messages sent through the NetworkAgent to ConnectivityService. - // We cannot just use a mock object here because mWifiNetworkAgent is private to CMI. - // TODO (b/134538181): consider exposing WifiNetworkAgent and using mocks. - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - ArgumentCaptor<NetworkAgentConfig> configCaptor = - ArgumentCaptor.forClass(NetworkAgentConfig.class); - ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor = - ArgumentCaptor.forClass(NetworkCapabilities.class); - verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(), - any(NetworkInfo.class), any(LinkProperties.class), - networkCapabilitiesCaptor.capture(), - anyInt(), configCaptor.capture(), anyInt()); - - registerAsyncChannel((x) -> { - mNetworkAgentAsyncChannel = x; - }, messengerCaptor.getValue(), mNetworkAgentHandler); - configChecker.accept(configCaptor.getValue()); - networkCapabilitiesChecker.accept(networkCapabilitiesCaptor.getValue()); - - mNetworkAgentAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); - mLooper.dispatchAll(); - } - - private void expectUnregisterNetworkAgent() { - // We cannot just use a mock object here because mWifiNetworkAgent is private to CMI. - // TODO (b/134538181): consider exposing WifiNetworkAgent and using mocks. - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - mLooper.dispatchAll(); - verify(mNetworkAgentHandler).handleMessage(messageCaptor.capture()); - Message message = messageCaptor.getValue(); - assertNotNull(message); - assertEquals(NetworkAgent.EVENT_NETWORK_INFO_CHANGED, message.what); - NetworkInfo networkInfo = (NetworkInfo) message.obj; - assertEquals(NetworkInfo.DetailedState.DISCONNECTED, networkInfo.getDetailedState()); - } - - private void expectNetworkAgentUpdateCapabilities( - Consumer<NetworkCapabilities> networkCapabilitiesChecker) { - // We cannot just use a mock object here because mWifiNetworkAgent is private to CMI. - // TODO (b/134538181): consider exposing WifiNetworkAgent and using mocks. - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - mLooper.dispatchAll(); - verify(mNetworkAgentHandler).handleMessage(messageCaptor.capture()); - Message message = messageCaptor.getValue(); - assertNotNull(message); - assertEquals(NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED, message.what); - networkCapabilitiesChecker.accept((NetworkCapabilities) message.obj); - } - - /** - * Verify that when a network is explicitly selected, but noInternetAccessExpected is false, - * the {@link NetworkAgentConfig} contains the right values of explicitlySelected, - * acceptUnvalidated and acceptPartialConnectivity. - */ - @Test - public void testExplicitlySelected_ExplicitInternetExpected() throws Exception { - // Network is explicitly selected. - WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID, - ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1); - mConnectedNetwork.noInternetAccessExpected = false; - - connect(); - expectRegisterNetworkAgent((agentConfig) -> { - assertTrue(agentConfig.explicitlySelected); - assertFalse(agentConfig.acceptUnvalidated); - assertFalse(agentConfig.acceptPartialConnectivity); - }, (cap) -> { }); - } - - /** - * Verify that when a network is not explicitly selected, but noInternetAccessExpected is true, - * the {@link NetworkAgentConfig} contains the right values of explicitlySelected, - * acceptUnvalidated and acceptPartialConnectivity. - */ - @Test - public void testExplicitlySelected_NotExplicitNoInternetExpected() throws Exception { - // Network is no longer explicitly selected. - WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID, - ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS + 1); - mConnectedNetwork.noInternetAccessExpected = true; - - connect(); - expectRegisterNetworkAgent((agentConfig) -> { - assertFalse(agentConfig.explicitlySelected); - assertFalse(agentConfig.acceptUnvalidated); - assertTrue(agentConfig.acceptPartialConnectivity); - }, (cap) -> { }); - } - - /** - * Verify that when a network is explicitly selected, and noInternetAccessExpected is true, - * the {@link NetworkAgentConfig} contains the right values of explicitlySelected, - * acceptUnvalidated and acceptPartialConnectivity. - */ - @Test - public void testExplicitlySelected_ExplicitNoInternetExpected() throws Exception { - // Network is explicitly selected. - WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID, - ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1); - mConnectedNetwork.noInternetAccessExpected = true; - - connect(); - expectRegisterNetworkAgent((agentConfig) -> { - assertTrue(agentConfig.explicitlySelected); - assertTrue(agentConfig.acceptUnvalidated); - assertTrue(agentConfig.acceptPartialConnectivity); - }, (cap) -> { }); - } - - /** - * Verify that CMI dump includes WakeupController. - */ - @Test - public void testDumpShouldDumpWakeupController() { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - mCmi.dump(null, writer, null); - verify(mWakeupController).dump(null, writer, null); - } - - @Test - public void takeBugReportCallsWifiDiagnostics() { - mCmi.takeBugReport(anyString(), anyString()); - verify(mWifiDiagnostics).takeBugReport(anyString(), anyString()); - } - - /** - * Verify that Rssi Monitoring is started and the callback registered after connecting. - */ - @Test - public void verifyRssiMonitoringCallbackIsRegistered() throws Exception { - // Simulate the first connection. - connect(); - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(), - any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class), - anyInt(), any(NetworkAgentConfig.class), anyInt()); - - ArrayList<Integer> thresholdsArray = new ArrayList<>(); - thresholdsArray.add(RSSI_THRESHOLD_MAX); - thresholdsArray.add(RSSI_THRESHOLD_MIN); - Bundle thresholds = new Bundle(); - thresholds.putIntegerArrayList("thresholds", thresholdsArray); - Message message = new Message(); - message.what = NetworkAgent.CMD_SET_SIGNAL_STRENGTH_THRESHOLDS; - message.obj = thresholds; - messengerCaptor.getValue().send(message); - mLooper.dispatchAll(); - - ArgumentCaptor<WifiNative.WifiRssiEventHandler> rssiEventHandlerCaptor = - ArgumentCaptor.forClass(WifiNative.WifiRssiEventHandler.class); - verify(mWifiNative).startRssiMonitoring(anyString(), anyByte(), anyByte(), - rssiEventHandlerCaptor.capture()); - - // breach below min - rssiEventHandlerCaptor.getValue().onRssiThresholdBreached(RSSI_THRESHOLD_BREACH_MIN); - mLooper.dispatchAll(); - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertEquals(RSSI_THRESHOLD_BREACH_MIN, wifiInfo.getRssi()); - - // breach above max - rssiEventHandlerCaptor.getValue().onRssiThresholdBreached(RSSI_THRESHOLD_BREACH_MAX); - mLooper.dispatchAll(); - assertEquals(RSSI_THRESHOLD_BREACH_MAX, wifiInfo.getRssi()); - } - - /** - * Verify that RSSI and link layer stats polling works in connected mode - */ - @Test - public void verifyConnectedModeRssiPolling() throws Exception { - final long startMillis = 1_500_000_000_100L; - WifiLinkLayerStats llStats = new WifiLinkLayerStats(); - llStats.txmpdu_be = 1000; - llStats.rxmpdu_bk = 2000; - WifiNl80211Manager.SignalPollResult signalPollResult = - new WifiNl80211Manager.SignalPollResult(-42, 65, 54, sFreq); - when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); - when(mWifiNative.signalPoll(any())).thenReturn(signalPollResult); - when(mClock.getWallClockMillis()).thenReturn(startMillis + 0); - mCmi.enableRssiPolling(true); - connect(); - mLooper.dispatchAll(); - when(mClock.getWallClockMillis()).thenReturn(startMillis + 3333); - mLooper.dispatchAll(); - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertEquals(llStats.txmpdu_be, wifiInfo.txSuccess); - assertEquals(llStats.rxmpdu_bk, wifiInfo.rxSuccess); - assertEquals(signalPollResult.currentRssiDbm, wifiInfo.getRssi()); - assertEquals(signalPollResult.txBitrateMbps, wifiInfo.getLinkSpeed()); - assertEquals(signalPollResult.txBitrateMbps, wifiInfo.getTxLinkSpeedMbps()); - assertEquals(signalPollResult.rxBitrateMbps, wifiInfo.getRxLinkSpeedMbps()); - assertEquals(sFreq, wifiInfo.getFrequency()); - verify(mWifiDataStall, atLeastOnce()).getTxThroughputKbps(); - verify(mWifiDataStall, atLeastOnce()).getRxThroughputKbps(); - verify(mWifiScoreCard).noteSignalPoll(any()); - } - - /** - * Verify RSSI polling with verbose logging - */ - @Test - public void verifyConnectedModeRssiPollingWithVerboseLogging() throws Exception { - mCmi.enableVerboseLogging(1); - verifyConnectedModeRssiPolling(); - } - - /** - * Verify that calls to start and stop filtering multicast packets are passed on to the IpClient - * instance. - */ - @Test - public void verifyMcastLockManagerFilterControllerCallsUpdateIpClient() throws Exception { - loadComponentsInStaMode(); - reset(mIpClient); - WifiMulticastLockManager.FilterController filterController = - mCmi.getMcastLockManagerFilterController(); - filterController.startFilteringMulticastPackets(); - verify(mIpClient).setMulticastFilter(eq(true)); - filterController.stopFilteringMulticastPackets(); - verify(mIpClient).setMulticastFilter(eq(false)); - } - - /** - * Verifies that when - * 1. Global feature support flag is set to false - * 2. connected MAC randomization is on and - * 3. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_PERSISTENT and - * 4. randomized MAC for the network to connect to is different from the current MAC. - * - * The factory MAC address is used for the connection, and no attempt is made to change it. - */ - @Test - public void testConnectedMacRandomizationNotSupported() throws Exception { - mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, false); - initializeCmi(); - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - connect(); - assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - verify(mWifiNative, never()).setMacAddress(any(), any()); - verify(mWifiNative, never()).getFactoryMacAddress(any()); - } - - /** - * Verifies that when - * 1. connected MAC randomization is on and - * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_PERSISTENT and - * 3. randomized MAC for the network to connect to is different from the current MAC. - * - * Then the current MAC gets set to the randomized MAC when CMD_START_CONNECT executes. - */ - @Test - public void testConnectedMacRandomizationRandomizationPersistentDifferentMac() - throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - connect(); - verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS); - verify(mWifiMetrics) - .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class)); - assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - } - - /** - * Verifies that when - * 1. connected MAC randomization is on and - * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_PERSISTENT and - * 3. randomized MAC for the network to connect to is same as the current MAC. - * - * Then MAC change should not occur when CMD_START_CONNECT executes. - */ - @Test - public void testConnectedMacRandomizationRandomizationPersistentSameMac() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - when(mWifiNative.getMacAddress(WIFI_IFACE_NAME)) - .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString()); - - connect(); - verify(mWifiNative, never()).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS); - verify(mWifiMetrics, never()) - .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class)); - assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - } - - /** - * Verifies that when - * 1. connected MAC randomization is on and - * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_NONE and - * 3. current MAC address is not the factory MAC. - * - * Then the current MAC gets set to the factory MAC when CMD_START_CONNECT executes. - * @throws Exception - */ - @Test - public void testConnectedMacRandomizationRandomizationNoneDifferentMac() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - when(mWifiNative.getMacAddress(WIFI_IFACE_NAME)) - .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString()); - - WifiConfiguration config = new WifiConfiguration(); - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_GLOBAL_MAC_ADDRESS); - verify(mWifiMetrics) - .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class)); - assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - } - - /** - * Verifies that when - * 1. connected MAC randomization is on and - * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_NONE and - * - * Then the factory MAC should be used to connect to the network. - * @throws Exception - */ - @Test - public void testConnectedMacRandomizationRandomizationNoneSameMac() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = new WifiConfiguration(); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - } - - /** - * Verifies that WifiInfo returns DEFAULT_MAC_ADDRESS as mac address when Connected MAC - * Randomization is on and the device is not connected to a wifi network. - */ - @Test - public void testWifiInfoReturnDefaultMacWhenDisconnectedWithRandomization() throws Exception { - when(mWifiNative.getMacAddress(WIFI_IFACE_NAME)) - .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString()); - - connect(); - assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, sBSSID); - mLooper.dispatchAll(); - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); - mLooper.dispatchAll(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mCmi.getWifiInfo().getMacAddress()); - assertFalse(mCmi.getWifiInfo().hasRealMacAddress()); - } - - /** - * Verifies that we don't set MAC address when config returns an invalid MAC address. - */ - @Test - public void testDoNotSetMacWhenInvalid() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = new WifiConfiguration(); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - config.setRandomizedMacAddress(MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS)); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - // setMacAddress is invoked once when ClientModeImpl starts to prevent leak of factory MAC. - verify(mWifiNative).setMacAddress(eq(WIFI_IFACE_NAME), any(MacAddress.class)); - } - - /** - * Verify that we don't crash when WifiNative returns null as the current MAC address. - * @throws Exception - */ - @Test - public void testMacRandomizationWifiNativeReturningNull() throws Exception { - when(mWifiNative.getMacAddress(anyString())).thenReturn(null); - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - connect(); - verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS); - } - - /** - * Verifies that a notification is posted when a connection failure happens on a network - * in the hotlist. Then verify that tapping on the notification launches an dialog, which - * could be used to set the randomization setting for a network to "Trusted". - */ - @Test - public void testConnectionFailureSendRandomizationSettingsNotification() throws Exception { - when(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(anyInt())).thenReturn(true); - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_TIMEOUT); - mLooper.dispatchAll(); - - WifiConfiguration config = mCmi.getCurrentWifiConfiguration(); - verify(mConnectionFailureNotifier) - .showFailedToConnectDueToNoRandomizedMacSupportNotification(FRAMEWORK_NETWORK_ID); - } - - /** - * Verifies that a notification is not posted when a wrong password failure happens on a - * network in the hotlist. - */ - @Test - public void testNotCallingIsInFlakyRandomizationSsidHotlistOnWrongPassword() throws Exception { - when(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(anyInt())).thenReturn(true); - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); - mLooper.dispatchAll(); - - verify(mConnectionFailureNotifier, never()) - .showFailedToConnectDueToNoRandomizedMacSupportNotification(anyInt()); - } - - /** - * Verifies that CMD_START_CONNECT make WifiDiagnostics report - * CONNECTION_EVENT_STARTED - * @throws Exception - */ - @Test - public void testReportConnectionEventIsCalledAfterCmdStartConnect() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - verify(mWifiDiagnostics, never()).reportConnectionEvent( - eq(WifiDiagnostics.CONNECTION_EVENT_STARTED)); - mLooper.dispatchAll(); - verify(mWifiDiagnostics).reportConnectionEvent( - eq(WifiDiagnostics.CONNECTION_EVENT_STARTED)); - } - - /** - * Verifies that CMD_DIAG_CONNECT_TIMEOUT is processed after the timeout threshold if we - * start a connection but do not finish it. - * @throws Exception - */ - @Test - public void testCmdDiagsConnectTimeoutIsGeneratedAfterCmdStartConnect() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - mLooper.moveTimeForward(ClientModeImpl.DIAGS_CONNECT_TIMEOUT_MILLIS); - mLooper.dispatchAll(); - verify(mWifiDiagnostics).reportConnectionEvent( - eq(BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT)); - } - - /** - * Verifies that CMD_DIAG_CONNECT_TIMEOUT does not get processed before the timeout threshold. - * @throws Exception - */ - @Test - public void testCmdDiagsConnectTimeoutIsNotProcessedBeforeTimerExpires() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - mLooper.moveTimeForward(ClientModeImpl.DIAGS_CONNECT_TIMEOUT_MILLIS - 1000); - mLooper.dispatchAll(); - verify(mWifiDiagnostics, never()).reportConnectionEvent( - eq(BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT)); - } - - private void verifyConnectionEventTimeoutDoesNotOccur() { - mLooper.moveTimeForward(ClientModeImpl.DIAGS_CONNECT_TIMEOUT_MILLIS); - mLooper.dispatchAll(); - verify(mWifiDiagnostics, never()).reportConnectionEvent( - eq(BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT)); - } - - /** - * Verifies that association failures make WifiDiagnostics report CONNECTION_EVENT_FAILED - * and then cancel any pending timeouts. - * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}. - * @throws Exception - */ - @Test - public void testReportConnectionEventIsCalledAfterAssociationFailure() throws Exception { - mConnectedNetwork.getNetworkSelectionStatus() - .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, - ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID); - verify(mWifiDiagnostics, never()).reportConnectionEvent( - eq(WifiDiagnostics.CONNECTION_EVENT_FAILED)); - mLooper.dispatchAll(); - verify(mWifiDiagnostics).reportConnectionEvent( - eq(WifiDiagnostics.CONNECTION_EVENT_FAILED)); - verify(mWifiConnectivityManager).handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, sBSSID, sSSID); - verify(mWifiNetworkFactory).handleConnectionAttemptEnded( - eq(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION), - any(WifiConfiguration.class)); - verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded( - eq(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION), - any(WifiConfiguration.class), eq(null)); - verify(mWifiMetrics, never()) - .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware(); - verifyConnectionEventTimeoutDoesNotOccur(); - } - - /** - * Verifies that authentication failures make WifiDiagnostics report - * CONNECTION_EVENT_FAILED and then cancel any pending timeouts. - * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}. - * @throws Exception - */ - @Test - public void testReportConnectionEventIsCalledAfterAuthenticationFailure() throws Exception { - mConnectedNetwork.getNetworkSelectionStatus() - .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); - verify(mWifiDiagnostics, never()).reportConnectionEvent( - eq(WifiDiagnostics.CONNECTION_EVENT_FAILED)); - mLooper.dispatchAll(); - verify(mWifiDiagnostics).reportConnectionEvent( - eq(WifiDiagnostics.CONNECTION_EVENT_FAILED)); - verify(mWifiConnectivityManager).handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, sBSSID, sSSID); - verify(mWifiNetworkFactory).handleConnectionAttemptEnded( - eq(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE), - any(WifiConfiguration.class)); - verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded( - eq(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE), - any(WifiConfiguration.class), eq(null)); - verify(mWifiMetrics, never()) - .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware(); - verifyConnectionEventTimeoutDoesNotOccur(); - } - - /** - * Verify that if a NETWORK_DISCONNECTION_EVENT is received in ConnectedState, then an - * abnormal disconnect is reported to BssidBlocklistMonitor. - */ - @Test - public void testAbnormalDisconnectNotifiesBssidBlocklistMonitor() throws Exception { - // trigger RSSI poll to update WifiInfo - mCmi.enableRssiPolling(true); - WifiLinkLayerStats llStats = new WifiLinkLayerStats(); - llStats.txmpdu_be = 1000; - llStats.rxmpdu_bk = 2000; - WifiNl80211Manager.SignalPollResult signalPollResult = - new WifiNl80211Manager.SignalPollResult(TEST_RSSI, 65, 54, sFreq); - when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); - when(mWifiNative.signalPoll(any())).thenReturn(signalPollResult); - - connect(); - mLooper.dispatchAll(); - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID), - eq(BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT), anyInt()); - } - - /** - * Verify that ClientModeImpl notifies BssidBlocklistMonitor correctly when the RSSI is - * too low. - */ - @Test - public void testNotifiesBssidBlocklistMonitorLowRssi() throws Exception { - int testLowRssi = -80; - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, - ClientModeImpl.SUPPLICANT_BSSID_ANY); - mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 1, 0, sBSSID); - when(mWifiConfigManager.findScanRssi(eq(FRAMEWORK_NETWORK_ID), anyInt())).thenReturn(-80); - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( - getGoogleGuestScanDetail(testLowRssi, sBSSID, sFreq)); - when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( - getGoogleGuestScanDetail(testLowRssi, sBSSID, sFreq).getScanResult()); - mLooper.dispatchAll(); - - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID, - BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, testLowRssi); - } - - /** - * Verifies that the BssidBlocklistMonitor is notified, but the WifiLastResortWatchdog is - * not notified of association rejections of type REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA. - * @throws Exception - */ - @Test - public void testAssociationRejectionWithReasonApUnableToHandleNewStaUpdatesWatchdog() - throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, - ClientModeImpl.REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID); - mLooper.dispatchAll(); - verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded( - anyString(), anyString(), anyInt()); - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID), - eq(BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA), anyInt()); - } - - /** - * Verifies that WifiLastResortWatchdog and BssidBlocklistMonitor is notified of - * general association rejection failures. - * @throws Exception - */ - @Test - public void testAssociationRejectionUpdatesWatchdog() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID); - config.carrierId = CARRIER_ID_1; - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded( - anyString(), anyString(), anyInt()); - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID), - eq(BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION), anyInt()); - verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionNonAuthFailure(); - } - - /** - * Verifies that WifiLastResortWatchdog is not notified of authentication failures of type - * ERROR_AUTH_FAILURE_WRONG_PSWD. - * @throws Exception - */ - @Test - public void testFailureWrongPassIsIgnoredByWatchdog() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); - mLooper.dispatchAll(); - verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded( - anyString(), anyString(), anyInt()); - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID), - eq(BssidBlocklistMonitor.REASON_WRONG_PASSWORD), anyInt()); - } - - /** - * Verifies that WifiLastResortWatchdog is not notified of authentication failures of type - * ERROR_AUTH_FAILURE_EAP_FAILURE. - * @throws Exception - */ - @Test - public void testEapFailureIsIgnoredByWatchdog() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE); - mLooper.dispatchAll(); - verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded( - anyString(), anyString(), anyInt()); - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID), - eq(BssidBlocklistMonitor.REASON_EAP_FAILURE), anyInt()); - } - - /** - * Verifies that WifiLastResortWatchdog is notified of other types of authentication failures. - * @throws Exception - */ - @Test - public void testAuthenticationFailureUpdatesWatchdog() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_TIMEOUT); - mLooper.dispatchAll(); - verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded( - anyString(), anyString(), anyInt()); - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID), - eq(BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE), anyInt()); - } - - /** - * Verify that BssidBlocklistMonitor is notified of the SSID pre-connection so that it could - * send down to firmware the list of blocked BSSIDs. - */ - @Test - public void testBssidBlocklistSentToFirmwareAfterCmdStartConnect() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - verify(mBssidBlocklistMonitor, never()).updateFirmwareRoamingConfiguration(sSSID); - mLooper.dispatchAll(); - verify(mBssidBlocklistMonitor).updateFirmwareRoamingConfiguration(sSSID); - // But don't expect to see connection success yet - verify(mWifiScoreCard, never()).noteIpConfiguration(any()); - // And certainly not validation success - verify(mWifiScoreCard, never()).noteValidationSuccess(any()); - } - - /** - * Verifies that dhcp failures make WifiDiagnostics report CONNECTION_EVENT_FAILED and then - * cancel any pending timeouts. - * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}. - * @throws Exception - */ - @Test - public void testReportConnectionEventIsCalledAfterDhcpFailure() throws Exception { - mConnectedNetwork.getNetworkSelectionStatus() - .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - testDhcpFailure(); - verify(mWifiDiagnostics, atLeastOnce()).reportConnectionEvent( - eq(WifiDiagnostics.CONNECTION_EVENT_FAILED)); - verify(mWifiConnectivityManager, atLeastOnce()).handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, sBSSID, sSSID); - verify(mWifiNetworkFactory, atLeastOnce()).handleConnectionAttemptEnded( - eq(WifiMetrics.ConnectionEvent.FAILURE_DHCP), any(WifiConfiguration.class)); - verify(mWifiNetworkSuggestionsManager, atLeastOnce()).handleConnectionAttemptEnded( - eq(WifiMetrics.ConnectionEvent.FAILURE_DHCP), any(WifiConfiguration.class), - any(String.class)); - verify(mWifiMetrics, never()) - .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware(); - verifyConnectionEventTimeoutDoesNotOccur(); - } - - /** - * Verifies that a successful validation make WifiDiagnostics report CONNECTION_EVENT_SUCCEEDED - * and then cancel any pending timeouts. - * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}. - * @throws Exception - */ - @Test - public void testReportConnectionEventIsCalledAfterSuccessfulConnection() throws Exception { - mConnectedNetwork.getNetworkSelectionStatus() - .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq).getScanResult()); - connect(); - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(), - any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class), - anyInt(), any(NetworkAgentConfig.class), anyInt()); - - Message message = new Message(); - message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS; - message.arg1 = NetworkAgent.VALID_NETWORK; - message.obj = new Bundle(); - messengerCaptor.getValue().send(message); - mLooper.dispatchAll(); - - verify(mWifiDiagnostics).reportConnectionEvent( - eq(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED)); - verify(mWifiConnectivityManager).handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, sBSSID, sSSID); - verify(mWifiNetworkFactory).handleConnectionAttemptEnded( - eq(WifiMetrics.ConnectionEvent.FAILURE_NONE), any(WifiConfiguration.class)); - verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded( - eq(WifiMetrics.ConnectionEvent.FAILURE_NONE), any(WifiConfiguration.class), - any(String.class)); - // BSSID different, record this connection. - verify(mWifiMetrics).incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware(); - verifyConnectionEventTimeoutDoesNotOccur(); - } - - /** - * Verify that score card is notified of a connection attempt - */ - @Test - public void testScoreCardNoteConnectionAttemptAfterCmdStartConnect() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - verify(mWifiScoreCard, never()).noteConnectionAttempt(any(), anyInt(), anyString()); - mLooper.dispatchAll(); - verify(mWifiScoreCard).noteConnectionAttempt(any(), anyInt(), anyString()); - verify(mWifiConfigManager).findScanRssi(anyInt(), anyInt()); - // But don't expect to see connection success yet - verify(mWifiScoreCard, never()).noteIpConfiguration(any()); - // And certainly not validation success - verify(mWifiScoreCard, never()).noteValidationSuccess(any()); - - } - - /** - * Verify that score card is notified of a successful connection - */ - @Test - public void testScoreCardNoteConnectionComplete() throws Exception { - Pair<String, String> l2KeyAndCluster = Pair.create("Wad", "Gab"); - when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(l2KeyAndCluster); - connect(); - mLooper.dispatchAll(); - verify(mWifiScoreCard).noteIpConfiguration(any()); - ArgumentCaptor<Layer2InformationParcelable> captor = - ArgumentCaptor.forClass(Layer2InformationParcelable.class); - verify(mIpClient, atLeastOnce()).updateLayer2Information(captor.capture()); - final Layer2InformationParcelable info = captor.getValue(); - assertEquals(info.l2Key, "Wad"); - assertEquals(info.cluster, "Gab"); - } - - /** - * Verify that score card/health monitor are notified when wifi is disabled while disconnected - */ - @Test - public void testScoreCardNoteWifiDisabledWhileDisconnected() throws Exception { - // connecting and disconnecting shouldn't note wifi disabled - disconnect(); - mLooper.dispatchAll(); - - verify(mWifiScoreCard, times(1)).resetConnectionState(); - verify(mWifiScoreCard, never()).noteWifiDisabled(any()); - verify(mWifiHealthMonitor, never()).setWifiEnabled(false); - - // disabling while disconnected should note wifi disabled - mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - verify(mWifiScoreCard, times(2)).resetConnectionState(); - verify(mWifiHealthMonitor).setWifiEnabled(false); - } - - /** - * Verify that score card/health monitor are notified when wifi is disabled while connected - */ - @Test - public void testScoreCardNoteWifiDisabledWhileConnected() throws Exception { - // Get into connected state - connect(); - mLooper.dispatchAll(); - verify(mWifiScoreCard, never()).noteWifiDisabled(any()); - verify(mWifiHealthMonitor, never()).setWifiEnabled(false); - - // disabling while connected should note wifi disabled - mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - - verify(mWifiScoreCard).noteWifiDisabled(any()); - verify(mWifiScoreCard).resetConnectionState(); - verify(mWifiHealthMonitor).setWifiEnabled(false); - } - - /** - * Verify that we do not crash on quick toggling wifi on/off - */ - @Test - public void quickTogglesDoNotCrash() throws Exception { - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - mLooper.dispatchAll(); - - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - mLooper.dispatchAll(); - - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - } - - /** - * Verify that valid calls to set the current wifi state are returned when requested. - */ - @Test - public void verifySetAndGetWifiStateCallsWorking() throws Exception { - // we start off disabled - assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState()); - - // now check after updating - mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_UNKNOWN); - assertEquals(WifiManager.WIFI_STATE_UNKNOWN, mCmi.syncGetWifiState()); - - // check after two updates - mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_ENABLING); - mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_ENABLED); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - } - - /** - * Verify that invalid states do not change the saved wifi state. - */ - @Test - public void verifyInvalidStatesDoNotChangeSavedWifiState() throws Exception { - int invalidStateNegative = -1; - int invalidStatePositive = 5; - - // we start off disabled - assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState()); - - mCmi.setWifiStateForApiCalls(invalidStateNegative); - assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState()); - - mCmi.setWifiStateForApiCalls(invalidStatePositive); - assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState()); - } - - /** - * Verify that IPClient instance is shutdown when wifi is disabled. - */ - @Test - public void verifyIpClientShutdownWhenDisabled() throws Exception { - loadComponentsInStaMode(); - - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - verify(mIpClient).shutdown(); - verify(mWifiConfigManager).removeAllEphemeralOrPasspointConfiguredNetworks(); - verify(mWifiConfigManager).clearUserTemporarilyDisabledList(); - } - - /** - * Verify that WifiInfo's MAC address is updated when the state machine receives - * NETWORK_CONNECTION_EVENT while in ConnectedState. - */ - @Test - public void verifyWifiInfoMacUpdatedWithNetworkConnectionWhileConnected() throws Exception { - connect(); - assertEquals("ConnectedState", getCurrentState().getName()); - assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - - // Verify receiving a NETWORK_CONNECTION_EVENT changes the MAC in WifiInfo - when(mWifiNative.getMacAddress(WIFI_IFACE_NAME)) - .thenReturn(TEST_GLOBAL_MAC_ADDRESS.toString()); - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - } - - /** - * Verify that WifiInfo's MAC address is updated when the state machine receives - * NETWORK_CONNECTION_EVENT while in DisconnectedState. - */ - @Test - public void verifyWifiInfoMacUpdatedWithNetworkConnectionWhileDisconnected() throws Exception { - disconnect(); - assertEquals("DisconnectedState", getCurrentState().getName()); - // Since MAC randomization is enabled, wifiInfo's MAC should be set to default MAC - // when disconnect happens. - assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mCmi.getWifiInfo().getMacAddress()); - - when(mWifiNative.getMacAddress(WIFI_IFACE_NAME)) - .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString()); - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress()); - } - - /** - * Verify that we temporarily disable the network when auto-connected to a network - * with no internet access. - */ - @Test - public void verifyAutoConnectedNetworkWithInternetValidationFailure() throws Exception { - // Setup RSSI poll to update WifiInfo with low RSSI - mCmi.enableRssiPolling(true); - WifiLinkLayerStats llStats = new WifiLinkLayerStats(); - llStats.txmpdu_be = 1000; - llStats.rxmpdu_bk = 2000; - WifiNl80211Manager.SignalPollResult signalPollResult = - new WifiNl80211Manager.SignalPollResult(RSSI_THRESHOLD_BREACH_MIN, 65, 54, sFreq); - when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); - when(mWifiNative.signalPoll(any())).thenReturn(signalPollResult); - - // Simulate the first connection. - connect(); - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(), - any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class), - anyInt(), any(NetworkAgentConfig.class), anyInt()); - - WifiConfiguration currentNetwork = new WifiConfiguration(); - currentNetwork.networkId = FRAMEWORK_NETWORK_ID; - currentNetwork.SSID = DEFAULT_TEST_SSID; - currentNetwork.noInternetAccessExpected = false; - currentNetwork.numNoInternetAccessReports = 1; - when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(currentNetwork); - when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1); - - Message message = new Message(); - message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS; - message.arg1 = NetworkAgent.INVALID_NETWORK; - message.obj = new Bundle(); - messengerCaptor.getValue().send(message); - mLooper.dispatchAll(); - - verify(mWifiConfigManager) - .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID); - verify(mWifiConfigManager).updateNetworkSelectionStatus( - FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY); - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID, - BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, RSSI_THRESHOLD_BREACH_MIN); - verify(mWifiScoreCard).noteValidationFailure(any()); - } - - /** - * Verify that we don't temporarily disable the network when user selected to connect to a - * network with no internet access. - */ - @Test - public void verifyLastSelectedNetworkWithInternetValidationFailure() throws Exception { - // Simulate the first connection. - connect(); - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(), - any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class), - anyInt(), any(NetworkAgentConfig.class), anyInt()); - - WifiConfiguration currentNetwork = new WifiConfiguration(); - currentNetwork.networkId = FRAMEWORK_NETWORK_ID; - currentNetwork.noInternetAccessExpected = false; - currentNetwork.numNoInternetAccessReports = 1; - when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(currentNetwork); - when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID); - - Message message = new Message(); - message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS; - message.arg1 = NetworkAgent.INVALID_NETWORK; - message.obj = new Bundle(); - messengerCaptor.getValue().send(message); - mLooper.dispatchAll(); - - verify(mWifiConfigManager) - .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID); - verify(mWifiConfigManager, never()).updateNetworkSelectionStatus( - FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY); - } - - /** - * Verify that we temporarily disable the network when auto-connected to a network - * with no internet access. - */ - @Test - public void verifyAutoConnectedNoInternetExpectedNetworkWithInternetValidationFailure() - throws Exception { - // Simulate the first connection. - connect(); - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(), - any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class), - anyInt(), any(NetworkAgentConfig.class), anyInt()); - - WifiConfiguration currentNetwork = new WifiConfiguration(); - currentNetwork.networkId = FRAMEWORK_NETWORK_ID; - currentNetwork.noInternetAccessExpected = true; - currentNetwork.numNoInternetAccessReports = 1; - when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(currentNetwork); - when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1); - - Message message = new Message(); - message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS; - message.arg1 = NetworkAgent.INVALID_NETWORK; - message.obj = new Bundle(); - messengerCaptor.getValue().send(message); - mLooper.dispatchAll(); - - verify(mWifiConfigManager) - .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID); - verify(mWifiConfigManager, never()).updateNetworkSelectionStatus( - FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY); - } - - /** - * Verify that we enable the network when we detect validated internet access. - */ - @Test - public void verifyNetworkSelectionEnableOnInternetValidation() throws Exception { - // Simulate the first connection. - connect(); - verify(mBssidBlocklistMonitor).handleBssidConnectionSuccess(sBSSID, sSSID); - verify(mBssidBlocklistMonitor).handleDhcpProvisioningSuccess(sBSSID, sSSID); - verify(mBssidBlocklistMonitor, never()).handleNetworkValidationSuccess(sBSSID, sSSID); - - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(), - any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class), - anyInt(), any(NetworkAgentConfig.class), anyInt()); - - when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1); - - Message message = new Message(); - message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS; - message.arg1 = NetworkAgent.VALID_NETWORK; - message.obj = new Bundle(); - messengerCaptor.getValue().send(message); - mLooper.dispatchAll(); - - verify(mWifiConfigManager) - .setNetworkValidatedInternetAccess(FRAMEWORK_NETWORK_ID, true); - verify(mWifiConfigManager).updateNetworkSelectionStatus( - FRAMEWORK_NETWORK_ID, DISABLED_NONE); - verify(mWifiScoreCard).noteValidationSuccess(any()); - verify(mBssidBlocklistMonitor).handleNetworkValidationSuccess(sBSSID, sSSID); - } - - private void connectWithValidInitRssi(int initRssiDbm) throws Exception { - triggerConnect(); - mCmi.getWifiInfo().setRssi(initRssiDbm); - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.ASSOCIATED)); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - } - - /** - * Verify that we set the INTERNET and bandwidth capability in the network agent when connected - * as a result of auto-join/legacy API's. Also verify up/down stream bandwidth values when - * Rx link speed is unavailable. - */ - @Test - public void verifyNetworkCapabilities() throws Exception { - when(mWifiDataStall.getTxThroughputKbps()).thenReturn(70_000); - when(mWifiDataStall.getRxThroughputKbps()).thenReturn(-1); - when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any())) - .thenReturn(Pair.create(Process.INVALID_UID, "")); - // Simulate the first connection. - connectWithValidInitRssi(-42); - - ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor = - ArgumentCaptor.forClass(NetworkCapabilities.class); - verify(mConnectivityManager).registerNetworkAgent(any(Messenger.class), - any(NetworkInfo.class), any(LinkProperties.class), - networkCapabilitiesCaptor.capture(), anyInt(), any(NetworkAgentConfig.class), - anyInt()); - - NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue(); - assertNotNull(networkCapabilities); - - // Should have internet capability. - assertTrue(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)); - assertNull(networkCapabilities.getNetworkSpecifier()); - - assertEquals(mConnectedNetwork.creatorUid, networkCapabilities.getOwnerUid()); - assertArrayEquals( - new int[] {mConnectedNetwork.creatorUid}, - networkCapabilities.getAdministratorUids()); - - // Should set bandwidth correctly - assertEquals(-42, mCmi.getWifiInfo().getRssi()); - assertEquals(70_000, networkCapabilities.getLinkUpstreamBandwidthKbps()); - assertEquals(70_000, networkCapabilities.getLinkDownstreamBandwidthKbps()); - } - - /** - * Verify that we don't set the INTERNET capability in the network agent when connected - * as a result of the new network request API. Also verify up/down stream bandwidth values - * when both Tx and Rx link speed are unavailable. - */ - @Test - public void verifyNetworkCapabilitiesForSpecificRequest() throws Exception { - when(mWifiDataStall.getTxThroughputKbps()).thenReturn(-1); - when(mWifiDataStall.getRxThroughputKbps()).thenReturn(-1); - when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any())) - .thenReturn(Pair.create(TEST_UID, OP_PACKAGE_NAME)); - // Simulate the first connection. - connectWithValidInitRssi(-42); - ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor = - ArgumentCaptor.forClass(NetworkCapabilities.class); - verify(mConnectivityManager).registerNetworkAgent(any(Messenger.class), - any(NetworkInfo.class), any(LinkProperties.class), - networkCapabilitiesCaptor.capture(), anyInt(), any(NetworkAgentConfig.class), - anyInt()); - - NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue(); - assertNotNull(networkCapabilities); - - // should not have internet capability. - assertFalse(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)); - - NetworkSpecifier networkSpecifier = networkCapabilities.getNetworkSpecifier(); - assertTrue(networkSpecifier instanceof WifiNetworkAgentSpecifier); - WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier = - (WifiNetworkAgentSpecifier) networkSpecifier; - WifiNetworkAgentSpecifier expectedWifiNetworkAgentSpecifier = - new WifiNetworkAgentSpecifier(mCmi.getCurrentWifiConfiguration()); - assertEquals(expectedWifiNetworkAgentSpecifier, wifiNetworkAgentSpecifier); - assertEquals(TEST_UID, networkCapabilities.getRequestorUid()); - assertEquals(OP_PACKAGE_NAME, networkCapabilities.getRequestorPackageName()); - assertEquals(90_000, networkCapabilities.getLinkUpstreamBandwidthKbps()); - assertEquals(80_000, networkCapabilities.getLinkDownstreamBandwidthKbps()); - } - - /** - * Verify that we check for data stall during rssi poll - * and then check that wifi link layer usage data are being updated. - */ - @Test - public void verifyRssiPollChecksDataStall() throws Exception { - mCmi.enableRssiPolling(true); - connect(); - - WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats(); - when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats); - mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1); - mLooper.dispatchAll(); - WifiLinkLayerStats newLLStats = new WifiLinkLayerStats(); - when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(newLLStats); - mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1); - mLooper.dispatchAll(); - verify(mWifiDataStall).checkDataStallAndThroughputSufficiency( - oldLLStats, newLLStats, mCmi.getWifiInfo()); - verify(mWifiMetrics).incrementWifiLinkLayerUsageStats(newLLStats); - } - - /** - * Verify that we update wifi usability stats entries during rssi poll and that when we get - * a data stall we label and save the current list of usability stats entries. - * @throws Exception - */ - @Test - public void verifyRssiPollUpdatesWifiUsabilityMetrics() throws Exception { - mCmi.enableRssiPolling(true); - connect(); - - WifiLinkLayerStats stats = new WifiLinkLayerStats(); - when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats); - when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(), any(), any())) - .thenReturn(WifiIsUnusableEvent.TYPE_UNKNOWN); - mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1); - mLooper.dispatchAll(); - verify(mWifiMetrics).updateWifiUsabilityStatsEntries(any(), eq(stats)); - verify(mWifiMetrics, never()).addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - eq(anyInt()), eq(-1)); - - when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(), any(), any())) - .thenReturn(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1); - mLooper.dispatchAll(); - verify(mWifiMetrics, times(2)).updateWifiUsabilityStatsEntries(any(), eq(stats)); - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(10L + ClientModeImpl.DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS); - mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1); - mLooper.dispatchAll(); - verify(mWifiMetrics).addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1); - } - - /** - * Verify that when ordered to setPowerSave(true) while Interface is created, - * WifiNative is called with the right powerSave mode. - */ - @Test - public void verifySetPowerSaveTrueSuccess() throws Exception { - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - assertTrue(mCmi.setPowerSave(true)); - verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, true); - } - - /** - * Verify that when ordered to setPowerSave(false) while Interface is created, - * WifiNative is called with the right powerSave mode. - */ - @Test - public void verifySetPowerSaveFalseSuccess() throws Exception { - mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME); - assertTrue(mCmi.setPowerSave(false)); - verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false); - } - - /** - * Verify that when interface is not created yet (InterfaceName is null), - * then setPowerSave() returns with error and no call in WifiNative happens. - */ - @Test - public void verifySetPowerSaveFailure() throws Exception { - boolean powerSave = true; - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - assertFalse(mCmi.setPowerSave(powerSave)); - verify(mWifiNative, never()).setPowerSave(anyString(), anyBoolean()); - } - - /** - * Verify that we call into WifiTrafficPoller during rssi poll - */ - @Test - public void verifyRssiPollCallsWifiTrafficPoller() throws Exception { - mCmi.enableRssiPolling(true); - connect(); - - verify(mWifiTrafficPoller).notifyOnDataActivity(anyLong(), anyLong()); - } - - /** - * Verify that LinkProbeManager is updated during RSSI poll - */ - @Test - public void verifyRssiPollCallsLinkProbeManager() throws Exception { - mCmi.enableRssiPolling(true); - - connect(); - // reset() should be called when RSSI polling is enabled and entering L2ConnectedState - verify(mLinkProbeManager).resetOnNewConnection(); // called first time here - verify(mLinkProbeManager, never()).resetOnScreenTurnedOn(); // not called - verify(mLinkProbeManager).updateConnectionStats(any(), any()); - - mCmi.enableRssiPolling(false); - mLooper.dispatchAll(); - // reset() should be called when in L2ConnectedState (or child states) and RSSI polling - // becomes enabled - mCmi.enableRssiPolling(true); - mLooper.dispatchAll(); - verify(mLinkProbeManager, times(1)).resetOnNewConnection(); // verify not called again - verify(mLinkProbeManager).resetOnScreenTurnedOn(); // verify called here - } - - /** - * Verify that when ordered to setLowLatencyMode(true), - * WifiNative is called with the right lowLatency mode. - */ - @Test - public void verifySetLowLatencyTrueSuccess() throws Exception { - when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(true); - assertTrue(mCmi.setLowLatencyMode(true)); - verify(mWifiNative).setLowLatencyMode(true); - } - - /** - * Verify that when ordered to setLowLatencyMode(false), - * WifiNative is called with the right lowLatency mode. - */ - @Test - public void verifySetLowLatencyFalseSuccess() throws Exception { - when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(true); - assertTrue(mCmi.setLowLatencyMode(false)); - verify(mWifiNative).setLowLatencyMode(false); - } - - /** - * Verify that when WifiNative fails to set low latency mode, - * then the call setLowLatencyMode() returns with failure, - */ - @Test - public void verifySetLowLatencyModeFailure() throws Exception { - final boolean lowLatencyMode = true; - when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(false); - assertFalse(mCmi.setLowLatencyMode(lowLatencyMode)); - verify(mWifiNative).setLowLatencyMode(eq(lowLatencyMode)); - } - - /** - * Verify getting the factory MAC address success case. - */ - @Test - public void testGetFactoryMacAddressSuccess() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress()); - verify(mWifiNative).getFactoryMacAddress(WIFI_IFACE_NAME); - verify(mWifiNative).getMacAddress(anyString()); // called once when setting up client mode - } - - /** - * Verify getting the factory MAC address failure case. - */ - @Test - public void testGetFactoryMacAddressFail() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - when(mWifiNative.getFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn(null); - assertNull(mCmi.getFactoryMacAddress()); - verify(mWifiNative).getFactoryMacAddress(WIFI_IFACE_NAME); - verify(mWifiNative).getMacAddress(anyString()); // called once when setting up client mode - } - - /** - * Verify that when WifiNative#getFactoryMacAddress fails, if the device does not support - * MAC randomization then the currently programmed MAC address gets returned. - */ - @Test - public void testGetFactoryMacAddressFailWithNoMacRandomizationSupport() throws Exception { - mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, false); - initializeCmi(); - initializeAndAddNetworkAndVerifySuccess(); - when(mWifiNative.getFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn(null); - mCmi.getFactoryMacAddress(); - verify(mWifiNative).getFactoryMacAddress(anyString()); - verify(mWifiNative, times(2)).getMacAddress(WIFI_IFACE_NAME); - } - - @Test - public void testSetDeviceMobilityState() { - mCmi.setDeviceMobilityState(WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - verify(mWifiConnectivityManager).setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - verify(mWifiHealthMonitor).setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - verify(mWifiDataStall).setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - } - - /** - * Verify the MAC address is being randomized at start to prevent leaking the factory MAC. - */ - @Test - public void testRandomizeMacAddressOnStart() throws Exception { - ArgumentCaptor<MacAddress> macAddressCaptor = ArgumentCaptor.forClass(MacAddress.class); - loadComponentsInStaMode(); - verify(mWifiNative).setMacAddress(anyString(), macAddressCaptor.capture()); - MacAddress currentMac = macAddressCaptor.getValue(); - - assertNotEquals("The currently programmed MAC address should be different from the factory " - + "MAC address after ClientModeImpl starts", - mCmi.getFactoryMacAddress(), currentMac.toString()); - } - - /** - * Verify the MAC address is being randomized at start to prevent leaking the factory MAC. - */ - @Test - public void testNoRandomizeMacAddressOnStartIfMacRandomizationNotEnabled() throws Exception { - mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, false); - loadComponentsInStaMode(); - verify(mWifiNative, never()).setMacAddress(anyString(), any()); - } - - /** - * Verify bugreport will be taken when get IP_REACHABILITY_LOST - */ - @Test - public void testTakebugreportbyIpReachabilityLost() throws Exception { - connect(); - - mCmi.sendMessage(ClientModeImpl.CMD_IP_REACHABILITY_LOST); - mLooper.dispatchAll(); - verify(mWifiDiagnostics).captureBugReportData( - eq(WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST)); - } - - /** - * Verify removing sim will also remove an ephemeral Passpoint Provider. And reset carrier - * privileged suggestor apps. - */ - @Test - public void testResetSimNetworkWhenRemovingSim() throws Exception { - // Switch to connect mode and verify wifi is reported as enabled - startSupplicantAndDispatchMessages(); - - // Indicate that sim is removed. - mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS, - ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED); - mLooper.dispatchAll(); - - verify(mWifiConfigManager).resetSimNetworks(); - verify(mWifiNetworkSuggestionsManager).resetCarrierPrivilegedApps(); - } - - /** - * Verify inserting sim will reset carrier privileged suggestor apps. - * and remove any previous notifications due to sim removal - */ - @Test - public void testResetCarrierPrivilegedAppsWhenInsertingSim() throws Exception { - // Switch to connect mode and verify wifi is reported as enabled - startSupplicantAndDispatchMessages(); - - // Indicate that sim is inserted. - mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS, - ClientModeImpl.RESET_SIM_REASON_SIM_INSERTED); - mLooper.dispatchAll(); - - verify(mWifiConfigManager, never()).resetSimNetworks(); - verify(mWifiNetworkSuggestionsManager).resetCarrierPrivilegedApps(); - verify(mSimRequiredNotifier).dismissSimRequiredNotification(); - } - - /** - * Verifies that WifiLastResortWatchdog is notified of FOURWAY_HANDSHAKE_TIMEOUT. - */ - @Test - public void testHandshakeTimeoutUpdatesWatchdog() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - // Verifies that WifiLastResortWatchdog won't be notified - // by other reason code - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 2, sBSSID); - mLooper.dispatchAll(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded( - sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - - // Verifies that WifiLastResortWatchdog be notified - // for FOURWAY_HANDSHAKE_TIMEOUT. - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 15, sBSSID); - mLooper.dispatchAll(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded( - sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - - } - - /** - * Verify that WifiInfo is correctly populated after connection. - */ - @Test - public void verifyWifiInfoGetNetworkSpecifierPackageName() throws Exception { - mConnectedNetwork.fromWifiNetworkSpecifier = true; - mConnectedNetwork.ephemeral = true; - mConnectedNetwork.trusted = true; - mConnectedNetwork.creatorName = OP_PACKAGE_NAME; - connect(); - - assertTrue(mCmi.getWifiInfo().isEphemeral()); - assertTrue(mCmi.getWifiInfo().isTrusted()); - assertEquals(OP_PACKAGE_NAME, - mCmi.getWifiInfo().getRequestingPackageName()); - } - - /** - * Verify that WifiInfo is correctly populated after connection. - */ - @Test - public void verifyWifiInfoGetNetworkSuggestionPackageName() throws Exception { - mConnectedNetwork.fromWifiNetworkSuggestion = true; - mConnectedNetwork.ephemeral = true; - mConnectedNetwork.trusted = true; - mConnectedNetwork.creatorName = OP_PACKAGE_NAME; - connect(); - - assertTrue(mCmi.getWifiInfo().isEphemeral()); - assertTrue(mCmi.getWifiInfo().isTrusted()); - assertEquals(OP_PACKAGE_NAME, - mCmi.getWifiInfo().getRequestingPackageName()); - } - - /** - * Verify that a WifiIsUnusableEvent is logged and the current list of usability stats entries - * are labeled and saved when receiving an IP reachability lost message. - * @throws Exception - */ - @Test - public void verifyIpReachabilityLostMsgUpdatesWifiUsabilityMetrics() throws Exception { - connect(); - - mCmi.sendMessage(ClientModeImpl.CMD_IP_REACHABILITY_LOST); - mLooper.dispatchAll(); - verify(mWifiMetrics).logWifiIsUnusableEvent( - WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST); - verify(mWifiMetrics).addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1); - } - - /** - * Tests that when {@link ClientModeImpl} receives a SUP_REQUEST_IDENTITY message, it responds - * to the supplicant with the SIM identity. - */ - @Test - public void testSupRequestIdentity_setsIdentityResponse() throws Exception { - mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE)); - mConnectedNetwork.SSID = DEFAULT_TEST_SSID; - - when(mDataTelephonyManager.getSubscriberId()).thenReturn("3214561234567890"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("321456"); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - MockitoSession mockSession = ExtendedMockito.mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID); - when(SubscriptionManager.isValidSubscriptionId(anyInt())).thenReturn(true); - - triggerConnect(); - - mCmi.sendMessage(WifiMonitor.SUP_REQUEST_IDENTITY, - 0, FRAMEWORK_NETWORK_ID, DEFAULT_TEST_SSID); - mLooper.dispatchAll(); - - verify(mWifiNative).simIdentityResponse(WIFI_IFACE_NAME, - "13214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", ""); - mockSession.finishMocking(); - } - - /** - * Verifies that WifiLastResortWatchdog is notified of DHCP failures when recevied - * NETWORK_DISCONNECTION_EVENT while in ObtainingIpState. - */ - @Test - public void testDhcpFailureUpdatesWatchdog_WhenDisconnectedWhileObtainingIpAddr() - throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - - // Verifies that WifiLastResortWatchdog be notified. - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded( - sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - - /** - * Verifies that we trigger a disconnect when the {@link WifiConfigManager}. - * OnNetworkUpdateListener#onNetworkRemoved(WifiConfiguration)} is invoked. - */ - @Test - public void testOnNetworkRemoved() throws Exception { - connect(); - - WifiConfiguration removedNetwork = new WifiConfiguration(); - removedNetwork.networkId = FRAMEWORK_NETWORK_ID; - mConfigUpdateListenerCaptor.getValue().onNetworkRemoved(removedNetwork); - mLooper.dispatchAll(); - - verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID); - assertEquals("DisconnectingState", getCurrentState().getName()); - } - - /** - * Verifies that we trigger a disconnect when the {@link WifiConfigManager - * .OnNetworkUpdateListener#onNetworkPermanentlyDisabled(WifiConfiguration, int)} is invoked. - */ - @Test - public void testOnNetworkPermanentlyDisabled() throws Exception { - connect(); - - WifiConfiguration disabledNetwork = new WifiConfiguration(); - disabledNetwork.networkId = FRAMEWORK_NETWORK_ID; - mConfigUpdateListenerCaptor.getValue().onNetworkPermanentlyDisabled(disabledNetwork, - WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD); - mLooper.dispatchAll(); - - assertEquals("DisconnectingState", getCurrentState().getName()); - } - - /** - * Verifies that we don't trigger a disconnect when the {@link WifiConfigManager - * .OnNetworkUpdateListener#onNetworkPermanentlyDisabled(WifiConfiguration, int)} is invoked. - */ - @Test - public void testOnNetworkPermanentlyDisabledWithNoInternet() throws Exception { - connect(); - - WifiConfiguration disabledNetwork = new WifiConfiguration(); - disabledNetwork.networkId = FRAMEWORK_NETWORK_ID; - mConfigUpdateListenerCaptor.getValue().onNetworkPermanentlyDisabled(disabledNetwork, - WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT); - mLooper.dispatchAll(); - - assertEquals("ConnectedState", getCurrentState().getName()); - } - - /** - * Verifies that we don't trigger a disconnect when the {@link WifiConfigManager - * .OnNetworkUpdateListener#onNetworkTemporarilyDisabled(WifiConfiguration, int)} is invoked. - */ - @Test - public void testOnNetworkTemporarilyDisabledWithNoInternet() throws Exception { - connect(); - - WifiConfiguration disabledNetwork = new WifiConfiguration(); - disabledNetwork.networkId = FRAMEWORK_NETWORK_ID; - mConfigUpdateListenerCaptor.getValue().onNetworkTemporarilyDisabled(disabledNetwork, - WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY); - mLooper.dispatchAll(); - - assertEquals("ConnectedState", getCurrentState().getName()); - } - - /** - * Verify that MboOce/WifiDataStall enable/disable methods are called in ClientMode. - */ - @Test - public void verifyMboOceWifiDataStallSetupInClientMode() throws Exception { - startSupplicantAndDispatchMessages(); - verify(mMboOceController).enable(); - verify(mWifiDataStall).enablePhoneStateListener(); - mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null); - mLooper.dispatchAll(); - verify(mMboOceController).disable(); - verify(mWifiDataStall).disablePhoneStateListener(); - } - - /** - * Verify that Bluetooth active is set correctly with BT state/connection state changes - */ - @Test - public void verifyBluetoothStateAndConnectionStateChanges() throws Exception { - startSupplicantAndDispatchMessages(); - mCmi.sendBluetoothAdapterStateChange(BluetoothAdapter.STATE_ON); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager, times(1)).setBluetoothConnected(false); - - mCmi.sendBluetoothAdapterConnectionStateChange(BluetoothAdapter.STATE_CONNECTED); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager, times(1)).setBluetoothConnected(true); - - mCmi.sendBluetoothAdapterStateChange(BluetoothAdapter.STATE_OFF); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager, times(2)).setBluetoothConnected(false); - - mCmi.sendBluetoothAdapterStateChange(BluetoothAdapter.STATE_ON); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager, times(3)).setBluetoothConnected(false); - - mCmi.sendBluetoothAdapterConnectionStateChange(BluetoothAdapter.STATE_CONNECTING); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager, times(2)).setBluetoothConnected(true); - - mCmi.sendBluetoothAdapterConnectionStateChange(BluetoothAdapter.STATE_DISCONNECTED); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager, times(4)).setBluetoothConnected(false); - - mCmi.sendBluetoothAdapterConnectionStateChange(BluetoothAdapter.STATE_CONNECTED); - mLooper.dispatchAll(); - verify(mWifiConnectivityManager, times(3)).setBluetoothConnected(true); - } - - /** - * Test that handleBssTransitionRequest() blocklist the BSS upon - * receiving BTM request frame that contains MBO-OCE IE with an - * association retry delay attribute. - */ - @Test - public void testBtmFrameWithMboAssocretryDelayBlockListTheBssid() throws Exception { - // Connect to network with |sBSSID|, |sFreq|. - connect(); - - MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData(); - - btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED; - btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT - | MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED; - btmFrmData.mBlockListDurationMs = 60000; - - mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData); - mLooper.dispatchAll(); - - verify(mWifiMetrics, times(1)).incrementSteeringRequestCountIncludingMboAssocRetryDelay(); - verify(mBssidBlocklistMonitor).blockBssidForDurationMs(eq(sBSSID), eq(sSSID), - eq(btmFrmData.mBlockListDurationMs), anyInt(), anyInt()); - } - - /** - * Test that handleBssTransitionRequest() blocklist the BSS upon - * receiving BTM request frame that contains disassociation imminent bit - * set to 1. - */ - @Test - public void testBtmFrameWithDisassocImminentBitBlockListTheBssid() throws Exception { - // Connect to network with |sBSSID|, |sFreq|. - connect(); - - MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData(); - - btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT; - btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT; - - mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData); - mLooper.dispatchAll(); - - verify(mWifiMetrics, never()).incrementSteeringRequestCountIncludingMboAssocRetryDelay(); - verify(mBssidBlocklistMonitor).blockBssidForDurationMs(eq(sBSSID), eq(sSSID), - eq(MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS), anyInt(), anyInt()); - } - - /** - * Test that handleBssTransitionRequest() trigger force scan for - * network selection when status code is REJECT. - */ - @Test - public void testBTMRequestRejectTriggerNetworkSelction() throws Exception { - // Connect to network with |sBSSID|, |sFreq|. - connect(); - - MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData(); - - btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED; - btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT - | MboOceConstants.BTM_DATA_FLAG_BSS_TERMINATION_INCLUDED - | MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED; - btmFrmData.mBlockListDurationMs = 60000; - - mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData); - mLooper.dispatchAll(); - - verify(mBssidBlocklistMonitor, never()).blockBssidForDurationMs(eq(sBSSID), eq(sSSID), - eq(btmFrmData.mBlockListDurationMs), anyInt(), anyInt()); - verify(mWifiConnectivityManager).forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); - verify(mWifiMetrics, times(1)).incrementMboCellularSwitchRequestCount(); - verify(mWifiMetrics, times(1)) - .incrementForceScanCountDueToSteeringRequest(); - - } - - /** - * Test that handleBssTransitionRequest() does not trigger force - * scan when status code is accept. - */ - @Test - public void testBTMRequestAcceptDoNotTriggerNetworkSelction() throws Exception { - // Connect to network with |sBSSID|, |sFreq|. - connect(); - - MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData(); - - btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT; - btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT; - - mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData); - mLooper.dispatchAll(); - - verify(mWifiConnectivityManager, never()) - .forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); - } - - /** - * Test that the interval for poll RSSI is read from config overlay correctly. - */ - @Test - public void testPollRssiIntervalIsSetCorrectly() throws Exception { - assertEquals(3000, mCmi.getPollRssiIntervalMsecs()); - mResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, 6000); - assertEquals(6000, mCmi.getPollRssiIntervalMsecs()); - mResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, 7000); - assertEquals(6000, mCmi.getPollRssiIntervalMsecs()); - } - - /** - * Verifies that the logic does not modify PSK key management when WPA3 auto upgrade feature is - * disabled. - * - * @throws Exception - */ - @Test - public void testNoWpa3UpgradeWhenOverlaysAreOff() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = mock(WifiConfiguration.class); - BitSet allowedKeyManagement = mock(BitSet.class); - config.allowedKeyManagement = allowedKeyManagement; - when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))).thenReturn( - true); - when(config.getNetworkSelectionStatus()) - .thenReturn(new WifiConfiguration.NetworkSelectionStatus()); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, false); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); - } - - /** - * Verifies that the logic always enables SAE key management when WPA3 auto upgrade offload - * feature is enabled. - * - * @throws Exception - */ - @Test - public void testWpa3UpgradeOffload() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = mock(WifiConfiguration.class); - BitSet allowedKeyManagement = mock(BitSet.class); - BitSet allowedAuthAlgorithms = mock(BitSet.class); - config.allowedKeyManagement = allowedKeyManagement; - config.allowedAuthAlgorithms = allowedAuthAlgorithms; - when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))).thenReturn( - true); - when(config.getNetworkSelectionStatus()) - .thenReturn(new WifiConfiguration.NetworkSelectionStatus()); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, true); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(allowedKeyManagement).set(eq(WifiConfiguration.KeyMgmt.SAE)); - verify(allowedAuthAlgorithms).clear(); - } - - /** - * Verifies that the logic does not enable SAE key management when WPA3 auto upgrade feature is - * enabled but no SAE candidate is available. - * - * @throws Exception - */ - @Test - public void testNoWpa3UpgradeWithPskCandidate() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = mock(WifiConfiguration.class); - BitSet allowedKeyManagement = mock(BitSet.class); - config.allowedKeyManagement = allowedKeyManagement; - when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))) - .thenReturn(true); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); - - String ssid = "WPA2-Network"; - String caps = "[WPA2-FT/PSK+PSK][ESS][WPS]"; - ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, - 0, true); - scanResult.informationElements = new ScanResult.InformationElement[]{ - createIE(ScanResult.InformationElement.EID_SSID, - ssid.getBytes(StandardCharsets.UTF_8)) - }; - when(networkSelectionStatus.getCandidate()).thenReturn(scanResult); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); - } - - /** - * Verifies that the logic enables SAE key management when WPA3 auto upgrade feature is - * enabled and an SAE candidate is available. - * - * @throws Exception - */ - @Test - public void testWpa3UpgradeWithSaeCandidate() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = mock(WifiConfiguration.class); - BitSet allowedKeyManagement = mock(BitSet.class); - BitSet allowedAuthAlgorithms = mock(BitSet.class); - BitSet allowedProtocols = mock(BitSet.class); - BitSet allowedPairwiseCiphers = mock(BitSet.class); - BitSet allowedGroupCiphers = mock(BitSet.class); - config.allowedKeyManagement = allowedKeyManagement; - config.allowedAuthAlgorithms = allowedAuthAlgorithms; - config.allowedProtocols = allowedProtocols; - config.allowedPairwiseCiphers = allowedPairwiseCiphers; - config.allowedGroupCiphers = allowedGroupCiphers; - when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))) - .thenReturn(true); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config); - when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt())).thenReturn(null); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); - - final String ssid = "WPA3-Network"; - String caps = "[WPA2-FT/SAE+SAE][ESS][WPS]"; - ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, - 0, true); - scanResult.informationElements = new ScanResult.InformationElement[]{ - createIE(ScanResult.InformationElement.EID_SSID, - ssid.getBytes(StandardCharsets.UTF_8)) - }; - when(networkSelectionStatus.getCandidate()).thenReturn(scanResult); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(config).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); - } - - /** - * Verifies that the logic does not enable SAE key management when WPA3 auto upgrade feature is - * enabled and an SAE candidate is available, while another WPA2 AP is in range. - * - * @throws Exception - */ - @Test - public void testWpa3UpgradeWithSaeCandidateAndPskApInRange() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = mock(WifiConfiguration.class); - BitSet allowedKeyManagement = mock(BitSet.class); - BitSet allowedAuthAlgorithms = mock(BitSet.class); - BitSet allowedProtocols = mock(BitSet.class); - BitSet allowedPairwiseCiphers = mock(BitSet.class); - BitSet allowedGroupCiphers = mock(BitSet.class); - config.allowedKeyManagement = allowedKeyManagement; - config.allowedAuthAlgorithms = allowedAuthAlgorithms; - config.allowedProtocols = allowedProtocols; - config.allowedPairwiseCiphers = allowedPairwiseCiphers; - config.allowedGroupCiphers = allowedGroupCiphers; - when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))) - .thenReturn(true); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config); - when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt())).thenReturn(null); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); - - final String saeBssid = "ab:cd:01:ef:45:89"; - final String pskBssid = "ab:cd:01:ef:45:9a"; - - final String ssidSae = "Mixed-Network"; - config.SSID = ScanResultUtil.createQuotedSSID(ssidSae); - config.networkId = 1; - - String capsSae = "[WPA2-FT/SAE+SAE][ESS][WPS]"; - ScanResult scanResultSae = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidSae), ssidSae, - saeBssid, 1245, 0, capsSae, -78, 2412, 1025, 22, 33, 20, 0, - 0, true); - ScanResult.InformationElement ieSae = createIE(ScanResult.InformationElement.EID_SSID, - ssidSae.getBytes(StandardCharsets.UTF_8)); - scanResultSae.informationElements = new ScanResult.InformationElement[]{ieSae}; - when(networkSelectionStatus.getCandidate()).thenReturn(scanResultSae); - ScanResult.InformationElement[] ieArr = new ScanResult.InformationElement[1]; - ieArr[0] = ieSae; - - final String ssidPsk = "Mixed-Network"; - String capsPsk = "[WPA2-FT/PSK+PSK][ESS][WPS]"; - ScanResult scanResultPsk = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidPsk), ssidPsk, - pskBssid, 1245, 0, capsPsk, -48, 2462, 1025, 22, 33, 20, 0, - 0, true); - ScanResult.InformationElement iePsk = createIE(ScanResult.InformationElement.EID_SSID, - ssidPsk.getBytes(StandardCharsets.UTF_8)); - scanResultPsk.informationElements = new ScanResult.InformationElement[]{iePsk}; - ScanResult.InformationElement[] ieArrPsk = new ScanResult.InformationElement[1]; - ieArrPsk[0] = iePsk; - List<ScanResult> scanResults = new ArrayList<>(); - scanResults.add(scanResultPsk); - scanResults.add(scanResultSae); - - when(mScanRequestProxy.getScanResults()).thenReturn(scanResults); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); - } - - /** - * Verifies that the logic enables SAE key management when WPA3 auto upgrade feature is - * enabled and no candidate is available (i.e. user selected a WPA2 saved network and the - * network is actually WPA3. - * - * @throws Exception - */ - @Test - public void testWpa3UpgradeWithNoCandidate() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = mock(WifiConfiguration.class); - BitSet allowedKeyManagement = mock(BitSet.class); - BitSet allowedAuthAlgorithms = mock(BitSet.class); - BitSet allowedProtocols = mock(BitSet.class); - BitSet allowedPairwiseCiphers = mock(BitSet.class); - BitSet allowedGroupCiphers = mock(BitSet.class); - config.allowedKeyManagement = allowedKeyManagement; - config.allowedAuthAlgorithms = allowedAuthAlgorithms; - config.allowedProtocols = allowedProtocols; - config.allowedPairwiseCiphers = allowedPairwiseCiphers; - config.allowedGroupCiphers = allowedGroupCiphers; - when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))) - .thenReturn(true); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config); - - mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false); - - final String saeBssid = "ab:cd:01:ef:45:89"; - final String ssidSae = "WPA3-Network"; - config.SSID = ScanResultUtil.createQuotedSSID(ssidSae); - config.networkId = 1; - - String capsSae = "[WPA2-FT/SAE+SAE][ESS][WPS]"; - ScanResult scanResultSae = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidSae), ssidSae, - saeBssid, 1245, 0, capsSae, -78, 2412, 1025, 22, 33, 20, 0, - 0, true); - ScanResult.InformationElement ieSae = createIE(ScanResult.InformationElement.EID_SSID, - ssidSae.getBytes(StandardCharsets.UTF_8)); - scanResultSae.informationElements = new ScanResult.InformationElement[]{ieSae}; - when(networkSelectionStatus.getCandidate()).thenReturn(null); - List<ScanResult> scanResults = new ArrayList<>(); - scanResults.add(scanResultSae); - - when(mScanRequestProxy.getScanResults()).thenReturn(scanResults); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - verify(config).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE)); - } - - private static ScanResult.InformationElement createIE(int id, byte[] bytes) { - ScanResult.InformationElement ie = new ScanResult.InformationElement(); - ie.id = id; - ie.bytes = bytes; - return ie; - } - - /* - * Verify isWifiBandSupported for 5GHz with an overlay override config - */ - @Test - public void testIsWifiBandSupported5gWithOverride() throws Exception { - mResources.setBoolean(R.bool.config_wifi5ghzSupport, true); - assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ)); - verify(mWifiNative, never()).getChannelsForBand(anyInt()); - } - - /** - * Verify isWifiBandSupported for 6GHz with an overlay override config - */ - @Test - public void testIsWifiBandSupported6gWithOverride() throws Exception { - mResources.setBoolean(R.bool.config_wifi6ghzSupport, true); - assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ)); - verify(mWifiNative, never()).getChannelsForBand(anyInt()); - } - - /** - * Verify isWifiBandSupported for 5GHz with no overlay override config no channels - */ - @Test - public void testIsWifiBandSupported5gNoOverrideNoChannels() throws Exception { - final int[] emptyArray = {}; - mResources.setBoolean(R.bool.config_wifi5ghzSupport, false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray); - assertFalse(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ)); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ); - } - - /** - * Verify isWifiBandSupported for 5GHz with no overlay override config with channels - */ - @Test - public void testIsWifiBandSupported5gNoOverrideWithChannels() throws Exception { - final int[] channelArray = {5170}; - mResources.setBoolean(R.bool.config_wifi5ghzSupport, false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray); - assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ)); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ); - } - - /** - * Verify isWifiBandSupported for 6GHz with no overlay override config no channels - */ - @Test - public void testIsWifiBandSupported6gNoOverrideNoChannels() throws Exception { - final int[] emptyArray = {}; - mResources.setBoolean(R.bool.config_wifi6ghzSupport, false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray); - assertFalse(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ)); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ); - } - - /** - * Verify isWifiBandSupported for 6GHz with no overlay override config with channels - */ - @Test - public void testIsWifiBandSupported6gNoOverrideWithChannels() throws Exception { - final int[] channelArray = {6420}; - mResources.setBoolean(R.bool.config_wifi6ghzSupport, false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray); - assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ)); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ); - } - - /** - * Helper function for setting up fils test. - * - * @param isDriverSupportFils true if driver support fils. - * @return wifi configuration. - */ - private WifiConfiguration setupFilsTest(boolean isDriverSupportFils) { - assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); - assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); - - WifiConfiguration config = new WifiConfiguration(); - config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - config.SSID = ScanResultUtil.createQuotedSSID(sFilsSsid); - config.networkId = 1; - config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS); - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config); - if (isDriverSupportFils) { - when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_FILS_SHA256 | WifiManager.WIFI_FEATURE_FILS_SHA384); - } else { - when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn((long) 0); - } - - return config; - } - - /** - * Helper function for setting up a scan result with FILS supported AP. - * - */ - private void setupFilsEnabledApInScanResult() { - String caps = "[WPA2-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP]" - + "[RSN-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP][ESS]"; - ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(sFilsSsid), - sFilsSsid, sBSSID, 1245, 0, caps, -78, 2412, 1025, 22, 33, 20, 0, 0, true); - ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID, - sFilsSsid.getBytes(StandardCharsets.UTF_8)); - scanResult.informationElements = new ScanResult.InformationElement[]{ie}; - List<ScanResult> scanResults = new ArrayList<>(); - scanResults.add(scanResult); - - when(mScanRequestProxy.getScanResults()).thenReturn(scanResults); - } - - - /** - * Helper function to send CMD_START_FILS_CONNECTION along with HLP IEs. - * - */ - private void prepareFilsHlpPktAndSendStartConnect() { - Layer2PacketParcelable l2Packet = new Layer2PacketParcelable(); - l2Packet.dstMacAddress = TEST_GLOBAL_MAC_ADDRESS; - l2Packet.payload = new byte[] {0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, - 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x55, 0x66}; - mCmi.sendMessage(ClientModeImpl.CMD_START_FILS_CONNECTION, 0, 0, - Collections.singletonList(l2Packet)); - mLooper.dispatchAll(); - } - - /** - * Verifies that while connecting to AP, the logic looks into the scan result and - * looks for AP matching the network type and ssid and update the wificonfig with FILS - * AKM if supported. - * - * @throws Exception - */ - @Test - public void testFilsAKMUpdateBeforeConnect() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - WifiConfiguration config = setupFilsTest(true); - setupFilsEnabledApInScanResult(); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256)); - verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - } - - /** - * Verifies that while connecting to AP, framework updates the wifi config with - * FILS AKM only if underlying driver support FILS feature. - * - * @throws Exception - */ - @Test - public void testFilsAkmIsNotAddedinWifiConfigIfDriverDoesNotSupportFils() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - WifiConfiguration config = setupFilsTest(false); - setupFilsEnabledApInScanResult(); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - assertFalse(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256)); - verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - } - - - /** - * Verifies that the HLP (DHCP) packets are send to wpa_supplicant - * prior to Fils connection. - * - * @throws Exception - */ - @Test - public void testFilsHlpUpdateBeforeFilsConnection() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - WifiConfiguration config = setupFilsTest(true); - setupFilsEnabledApInScanResult(); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - prepareFilsHlpPktAndSendStartConnect(); - - verify(mWifiNative).flushAllHlp(eq(WIFI_IFACE_NAME)); - verify(mWifiNative).addHlpReq(eq(WIFI_IFACE_NAME), any(), any()); - verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - } - - /** - * Verifies that an association rejection in first FILS connect attempt doesn't block - * the second connection attempt. - * - * @throws Exception - */ - @Test - public void testFilsSecondConnectAttemptIsNotBLockedAfterAssocReject() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - WifiConfiguration config = setupFilsTest(true); - setupFilsEnabledApInScanResult(); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - prepareFilsHlpPktAndSendStartConnect(); - - verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - - mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, 2, sBSSID); - mLooper.dispatchAll(); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - prepareFilsHlpPktAndSendStartConnect(); - - verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config)); - } - - /** - * Verifies Fils connection. - * - * @throws Exception - */ - @Test - public void testFilsConnection() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - WifiConfiguration config = setupFilsTest(true); - setupFilsEnabledApInScanResult(); - - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - prepareFilsHlpPktAndSendStartConnect(); - - verify(mWifiMetrics, times(1)).incrementConnectRequestWithFilsAkmCount(); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 1, sBSSID); - mLooper.dispatchAll(); - - verify(mWifiMetrics, times(1)).incrementL2ConnectionThroughFilsAuthCount(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, WifiSsid.createFromAsciiEncoded(sFilsSsid), - sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - - DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable(); - dhcpResults.baseConfiguration = new StaticIpConfiguration(); - dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4"); - dhcpResults.baseConfiguration.ipAddress = - new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0); - dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8")); - dhcpResults.leaseDuration = 3600; - - injectDhcpSuccess(dhcpResults); - mLooper.dispatchAll(); - - WifiInfo wifiInfo = mCmi.getWifiInfo(); - assertNotNull(wifiInfo); - assertEquals(sBSSID, wifiInfo.getBSSID()); - assertTrue(WifiSsid.createFromAsciiEncoded(sFilsSsid).equals(wifiInfo.getWifiSsid())); - assertEquals("ConnectedState", getCurrentState().getName()); - } - - /** - * Tests the wifi info is updated correctly for connecting network. - */ - @Test - public void testWifiInfoOnConnectingNextNetwork() throws Exception { - - mConnectedNetwork.ephemeral = true; - mConnectedNetwork.trusted = true; - mConnectedNetwork.osu = true; - - triggerConnect(); - when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) - .thenReturn(mScanDetailCache); - - when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); - when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( - getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); - - // before the fist success connection, there is no valid wifi info. - assertEquals(WifiConfiguration.INVALID_NETWORK_ID, mCmi.getWifiInfo().getNetworkId()); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(FRAMEWORK_NETWORK_ID, - sWifiSsid, sBSSID, SupplicantState.ASSOCIATED)); - mLooper.dispatchAll(); - - // retrieve correct wifi info on receiving the supplicant state change event. - assertEquals(FRAMEWORK_NETWORK_ID, mCmi.getWifiInfo().getNetworkId()); - assertEquals(mConnectedNetwork.ephemeral, mCmi.getWifiInfo().isEphemeral()); - assertEquals(mConnectedNetwork.trusted, mCmi.getWifiInfo().isTrusted()); - assertEquals(mConnectedNetwork.osu, mCmi.getWifiInfo().isOsuAp()); - } - - /** - * Verify that we disconnect when we mark a previous unmetered network metered. - */ - @Test - public void verifyDisconnectOnMarkingNetworkMetered() throws Exception { - connect(); - expectRegisterNetworkAgent((config) -> { }, (cap) -> { - assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)); - }); - - WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork); - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED; - - mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig); - mLooper.dispatchAll(); - assertEquals("DisconnectingState", getCurrentState().getName()); - } - - /** - * Verify that we only update capabilites when we mark a previous unmetered network metered. - */ - @Test - public void verifyUpdateCapabilitiesOnMarkingNetworkUnmetered() throws Exception { - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED; - connect(); - expectRegisterNetworkAgent((config) -> { }, (cap) -> { - assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)); - }); - reset(mNetworkAgentHandler); - - WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork); - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED; - - mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig); - mLooper.dispatchAll(); - assertEquals("ConnectedState", getCurrentState().getName()); - - expectNetworkAgentUpdateCapabilities((cap) -> { - assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)); - }); - } - - - /** - * Verify that we disconnect when we mark a previous unmetered network metered. - */ - @Test - public void verifyDisconnectOnMarkingNetworkAutoMeteredWithMeteredHint() throws Exception { - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED; - connect(); - expectRegisterNetworkAgent((config) -> { }, (cap) -> { - assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)); - }); - reset(mNetworkAgentHandler); - - // Mark network metered none. - WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork); - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE; - - // Set metered hint in WifiInfo (either via DHCP or ScanResult IE). - WifiInfo wifiInfo = mCmi.getWifiInfo(); - wifiInfo.setMeteredHint(true); - - mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig); - mLooper.dispatchAll(); - assertEquals("DisconnectingState", getCurrentState().getName()); - } - - /** - * Verify that we only update capabilites when we mark a previous unmetered network metered. - */ - @Test - public void verifyUpdateCapabilitiesOnMarkingNetworkAutoMeteredWithoutMeteredHint() - throws Exception { - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED; - connect(); - expectRegisterNetworkAgent((config) -> { }, (cap) -> { - assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)); - }); - reset(mNetworkAgentHandler); - - WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork); - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE; - - // Reset metered hint in WifiInfo. - WifiInfo wifiInfo = mCmi.getWifiInfo(); - wifiInfo.setMeteredHint(false); - - mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig); - mLooper.dispatchAll(); - assertEquals("ConnectedState", getCurrentState().getName()); - - expectNetworkAgentUpdateCapabilities((cap) -> { - assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)); - }); - } - - /** - * Verify that we do nothing on no metered change. - */ - @Test - public void verifyDoNothingMarkingNetworkAutoMeteredWithMeteredHint() throws Exception { - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED; - connect(); - expectRegisterNetworkAgent((config) -> { }, (cap) -> { - assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)); - }); - reset(mNetworkAgentHandler); - - // Mark network metered none. - WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork); - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE; - - // Set metered hint in WifiInfo (either via DHCP or ScanResult IE). - WifiInfo wifiInfo = mCmi.getWifiInfo(); - wifiInfo.setMeteredHint(true); - - mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig); - mLooper.dispatchAll(); - assertEquals("ConnectedState", getCurrentState().getName()); - - verifyNoMoreInteractions(mNetworkAgentHandler); - } - - /** - * Verify that we do nothing on no metered change. - */ - @Test - public void verifyDoNothingMarkingNetworkAutoMeteredWithoutMeteredHint() throws Exception { - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED; - connect(); - expectRegisterNetworkAgent((config) -> { }, (cap) -> { - assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)); - }); - reset(mNetworkAgentHandler); - - // Mark network metered none. - WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork); - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE; - - // Reset metered hint in WifiInfo. - WifiInfo wifiInfo = mCmi.getWifiInfo(); - wifiInfo.setMeteredHint(false); - - mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig); - mLooper.dispatchAll(); - assertEquals("ConnectedState", getCurrentState().getName()); - - verifyNoMoreInteractions(mNetworkAgentHandler); - } - - /* - * Verify that network cached data is cleared correctly in - * disconnected state. - */ - @Test - public void testNetworkCachedDataIsClearedCorrectlyInDisconnectedState() throws Exception { - // Setup CONNECT_MODE & a WifiConfiguration - initializeAndAddNetworkAndVerifySuccess(); - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - // got UNSPECIFIED during this connection attempt - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 1, sBSSID); - mLooper.dispatchAll(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - verify(mWifiNative, never()).removeNetworkCachedData(anyInt()); - - // got 4WAY_HANDSHAKE_TIMEOUT during this connection attempt - mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID); - mLooper.dispatchAll(); - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 15, sBSSID); - mLooper.dispatchAll(); - - assertEquals("DisconnectedState", getCurrentState().getName()); - verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID); - } - - /* - * Verify that network cached data is cleared correctly in - * disconnected state. - */ - @Test - public void testNetworkCachedDataIsClearedCorrectlyInObtainingIpState() throws Exception { - initializeAndAddNetworkAndVerifySuccess(); - - verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME); - - IActionListener connectActionListener = mock(IActionListener.class); - mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid()); - mLooper.dispatchAll(); - verify(connectActionListener).onSuccess(); - - verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any()); - - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); - mLooper.dispatchAll(); - - assertEquals("ObtainingIpState", getCurrentState().getName()); - - // got 4WAY_HANDSHAKE_TIMEOUT during this connection attempt - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 15, sBSSID); - mLooper.dispatchAll(); - - verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID); - } - - /* - * Verify that network cached data is NOT cleared in ConnectedState. - */ - @Test - public void testNetworkCachedDataIsClearedIf4WayHandshakeFailure() throws Exception { - when(mWifiScoreCard.detectAbnormalDisconnection()) - .thenReturn(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL); - InOrder inOrderWifiLockManager = inOrder(mWifiLockManager); - connect(); - inOrderWifiLockManager.verify(mWifiLockManager).updateWifiClientConnected(true); - - // got 4WAY_HANDSHAKE_TIMEOUT - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 15, sBSSID); - mLooper.dispatchAll(); - verify(mWifiNative, never()).removeNetworkCachedData(anyInt()); - } - - /** - * Verify that network cached data is cleared on updating a network. - */ - @Test - public void testNetworkCachedDataIsClearedOnUpdatingNetwork() throws Exception { - WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork); - mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED; - - mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig); - mLooper.dispatchAll(); - verify(mWifiNative).removeNetworkCachedData(eq(oldConfig.networkId)); - } - - - @Test - public void testIpReachabilityLostAndRoamEventsRace() throws Exception { - connect(); - expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { }); - reset(mNetworkAgentHandler); - - // Trigger ip reachibility loss and ensure we trigger a disconnect & we're in - // "DisconnectingState" - mCmi.sendMessage(ClientModeImpl.CMD_IP_REACHABILITY_LOST); - mLooper.dispatchAll(); - verify(mWifiNative).disconnect(any()); - assertEquals("DisconnectingState", getCurrentState().getName()); - - // Now send a network connection (indicating a roam) event before we get the disconnect - // event. - mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - // ensure that we ignored the transient roam while we're disconnecting. - assertEquals("DisconnectingState", getCurrentState().getName()); - verifyNoMoreInteractions(mNetworkAgentHandler); - - // Now send the disconnect event and ensure that we transition to "DisconnectedState". - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); - mLooper.dispatchAll(); - assertEquals("DisconnectedState", getCurrentState().getName()); - expectUnregisterNetworkAgent(); - - verifyNoMoreInteractions(mNetworkAgentHandler); - } - - @Test - public void testSyncGetCurrentNetwork() throws Exception { - // syncGetCurrentNetwork() returns null when disconnected - mLooper.startAutoDispatch(); - assertNull(mCmi.syncGetCurrentNetwork(mCmiAsyncChannel)); - mLooper.stopAutoDispatch(); - - connect(); - - // syncGetCurrentNetwork() returns non-null Network when connected - mLooper.startAutoDispatch(); - assertEquals(mNetwork, mCmi.syncGetCurrentNetwork(mCmiAsyncChannel)); - mLooper.stopAutoDispatch(); - } - - @Test - public void clearRequestingPackageNameInWifiInfoOnConnectionFailure() throws Exception { - mConnectedNetwork.fromWifiNetworkSpecifier = true; - mConnectedNetwork.ephemeral = true; - mConnectedNetwork.creatorName = OP_PACKAGE_NAME; - - triggerConnect(); - - // association completed - mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.ASSOCIATED)); - mLooper.dispatchAll(); - - assertTrue(mCmi.getWifiInfo().isEphemeral()); - assertEquals(OP_PACKAGE_NAME, mCmi.getWifiInfo().getRequestingPackageName()); - - // fail the connection. - mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, FRAMEWORK_NETWORK_ID, 0, sBSSID); - mLooper.dispatchAll(); - - assertFalse(mCmi.getWifiInfo().isEphemeral()); - assertNull(mCmi.getWifiInfo().getRequestingPackageName()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java deleted file mode 100644 index 92f3d9bac..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java +++ /dev/null @@ -1,1195 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_STATE; -import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE; -import static android.net.wifi.WifiManager.WIFI_STATE_CHANGED_ACTION; -import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; -import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; -import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; -import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; -import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.lenient; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.NetworkRequest; -import android.os.Handler; -import android.os.PersistableBundle; -import android.os.UserHandle; -import android.os.test.TestLooper; -import android.telephony.AccessNetworkConstants; -import android.telephony.CarrierConfigManager; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.telephony.ims.ImsMmTelManager; -import android.telephony.ims.RegistrationManager; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; - -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executor; - -/** - * Unit tests for {@link ClientModeManager}. - */ -@SmallTest -public class ClientModeManagerTest extends WifiBaseTest { - private static final String TAG = "ClientModeManagerTest"; - private static final String TEST_INTERFACE_NAME = "testif0"; - private static final String OTHER_INTERFACE_NAME = "notTestIf"; - private static final int TEST_WIFI_OFF_DEFERRING_TIME_MS = 4000; - private static final int TEST_ACTIVE_SUBSCRIPTION_ID = 1; - - TestLooper mLooper; - - ClientModeManager mClientModeManager; - - @Mock Context mContext; - @Mock WifiMetrics mWifiMetrics; - @Mock WifiNative mWifiNative; - @Mock Clock mClock; - @Mock ClientModeManager.Listener mListener; - @Mock SarManager mSarManager; - @Mock WakeupController mWakeupController; - @Mock ClientModeImpl mClientModeImpl; - @Mock CarrierConfigManager mCarrierConfigManager; - @Mock PersistableBundle mCarrierConfigBundle; - @Mock ImsMmTelManager mImsMmTelManager; - @Mock ConnectivityManager mConnectivityManager; - @Mock SubscriptionManager mSubscriptionManager; - @Mock SubscriptionInfo mActiveSubscriptionInfo; - private RegistrationManager.RegistrationCallback mImsMmTelManagerRegistrationCallback = null; - private @RegistrationManager.ImsRegistrationState int mCurrentImsRegistrationState = - RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED; - private @AccessNetworkConstants.TransportType int mCurrentImsConnectionType = - AccessNetworkConstants.TRANSPORT_TYPE_INVALID; - private NetworkRequest mImsRequest = null; - private NetworkCallback mImsNetworkCallback = null; - private Handler mImsNetworkCallbackHandler = null; - private long mElapsedSinceBootMillis = 0L; - private List<SubscriptionInfo> mSubscriptionInfoList = new ArrayList<>(); - private MockResources mResources; - - private MockitoSession mStaticMockSession = null; - - final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor = - ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class); - - /** - * If mContext is reset, call it again to ensure system services could be retrieved - * from the context. - */ - private void setUpSystemServiceForContext() { - when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) - .thenReturn(mCarrierConfigManager); - when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)) - .thenReturn(mSubscriptionManager); - when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)) - .thenReturn(mConnectivityManager); - when(mContext.getResources()).thenReturn(mResources); - } - - /* - * Use this helper to move mock looper and clock together. - */ - private void moveTimeForward(long timeMillis) { - mLooper.moveTimeForward(timeMillis); - mElapsedSinceBootMillis += timeMillis; - } - - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - // Prepare data - mResources = new MockResources(); - mResources.setInteger(R.integer.config_wifiDelayDisconnectOnImsLostMs, 0); - mSubscriptionInfoList.add(mActiveSubscriptionInfo); - - setUpSystemServiceForContext(); - - /** - * default mock for IMS deregistration: - * * No wifi calling - * * No network - * * no deferring time for wifi off - */ - mStaticMockSession = mockitoSession() - .mockStatic(ImsMmTelManager.class) - .mockStatic(SubscriptionManager.class) - .startMocking(); - lenient().when(ImsMmTelManager.createForSubscriptionId(eq(TEST_ACTIVE_SUBSCRIPTION_ID))) - .thenReturn(mImsMmTelManager); - lenient().when(SubscriptionManager.isValidSubscriptionId(eq(TEST_ACTIVE_SUBSCRIPTION_ID))) - .thenReturn(true); - doAnswer(new AnswerWithArguments() { - public void answer(Executor executor, RegistrationManager.RegistrationCallback c) { - mImsMmTelManagerRegistrationCallback = c; - // When the callback is registered, it will initiate the callback c to - // be called with the current registration state. - switch (mCurrentImsRegistrationState) { - case RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED: - c.onUnregistered(null); - break; - case RegistrationManager.REGISTRATION_STATE_REGISTERED: - c.onRegistered(mCurrentImsConnectionType); - break; - } - } - }).when(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - doAnswer(new AnswerWithArguments() { - public void answer(RegistrationManager.RegistrationCallback c) { - if (mImsMmTelManagerRegistrationCallback == c) { - mImsMmTelManagerRegistrationCallback = null; - } - } - }).when(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - when(mImsMmTelManager.isAvailable(anyInt(), anyInt())).thenReturn(false); - - when(mActiveSubscriptionInfo.getSubscriptionId()).thenReturn(TEST_ACTIVE_SUBSCRIPTION_ID); - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(mSubscriptionInfoList); - when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfigBundle); - when(mCarrierConfigBundle - .getInt(eq(CarrierConfigManager.Ims.KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT))) - .thenReturn(0); - doAnswer(new AnswerWithArguments() { - public void answer(NetworkRequest req, NetworkCallback callback, Handler handler) { - mImsRequest = req; - mImsNetworkCallback = callback; - mImsNetworkCallbackHandler = handler; - } - }).when(mConnectivityManager).registerNetworkCallback(any(), any(), any()); - doAnswer(new AnswerWithArguments() { - public void answer(NetworkCallback callback) { - if (mImsNetworkCallback == callback) mImsNetworkCallback = null; - } - }).when(mConnectivityManager).unregisterNetworkCallback(any(NetworkCallback.class)); - doAnswer(new AnswerWithArguments() { - public long answer() { - return mElapsedSinceBootMillis; - } - }).when(mClock).getElapsedSinceBootMillis(); - - mLooper = new TestLooper(); - mClientModeManager = createClientModeManager(); - mLooper.dispatchAll(); - } - - @After - public void cleanUp() throws Exception { - mStaticMockSession.finishMocking(); - } - - private ClientModeManager createClientModeManager() { - return new ClientModeManager(mContext, mLooper.getLooper(), mClock, mWifiNative, mListener, - mWifiMetrics, mSarManager, mWakeupController, mClientModeImpl); - } - - private void startClientInScanOnlyModeAndVerifyEnabled() throws Exception { - when(mWifiNative.setupInterfaceForClientInScanMode(any())) - .thenReturn(TEST_INTERFACE_NAME); - mClientModeManager.start(); - mLooper.dispatchAll(); - - verify(mWifiNative).setupInterfaceForClientInScanMode( - mInterfaceCallbackCaptor.capture()); - verify(mClientModeImpl).setOperationalMode( - ClientModeImpl.SCAN_ONLY_MODE, TEST_INTERFACE_NAME); - verify(mSarManager).setScanOnlyWifiState(WIFI_STATE_ENABLED); - - // now mark the interface as up - mInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - - // Ensure that no public broadcasts were sent. - verifyNoMoreInteractions(mContext); - verify(mListener).onStarted(); - } - - private void startClientInConnectModeAndVerifyEnabled() throws Exception { - when(mWifiNative.setupInterfaceForClientInScanMode(any())) - .thenReturn(TEST_INTERFACE_NAME); - when(mWifiNative.switchClientInterfaceToConnectivityMode(any())) - .thenReturn(true); - mClientModeManager.start(); - mLooper.dispatchAll(); - - verify(mWifiNative).setupInterfaceForClientInScanMode( - mInterfaceCallbackCaptor.capture()); - verify(mClientModeImpl).setOperationalMode( - ClientModeImpl.SCAN_ONLY_MODE, TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - mLooper.dispatchAll(); - - verify(mWifiNative).switchClientInterfaceToConnectivityMode(TEST_INTERFACE_NAME); - verify(mClientModeImpl).setOperationalMode( - ClientModeImpl.CONNECT_MODE, TEST_INTERFACE_NAME); - verify(mSarManager).setClientWifiState(WIFI_STATE_ENABLED); - - // now mark the interface as up - mInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> intents = intentCaptor.getAllValues(); - assertEquals(2, intents.size()); - Log.d(TAG, "captured intents: " + intents); - checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, - WIFI_STATE_DISABLED); - checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED, - WIFI_STATE_ENABLING); - - verify(mListener, times(2)).onStarted(); - } - - private void checkWifiConnectModeStateChangedBroadcast( - Intent intent, int expectedCurrentState, int expectedPrevState) { - String action = intent.getAction(); - assertEquals(WIFI_STATE_CHANGED_ACTION, action); - int currentState = intent.getIntExtra(EXTRA_WIFI_STATE, WIFI_STATE_UNKNOWN); - assertEquals(expectedCurrentState, currentState); - int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_STATE, WIFI_STATE_UNKNOWN); - assertEquals(expectedPrevState, prevState); - - verify(mClientModeImpl, atLeastOnce()).setWifiStateForApiCalls(expectedCurrentState); - } - - private void verifyConnectModeNotificationsForCleanShutdown(int fromState) { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()) - .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL)); - - List<Intent> intents = intentCaptor.getAllValues(); - assertTrue(intents.size() >= 2); - checkWifiConnectModeStateChangedBroadcast(intents.get(intents.size() - 2), - WIFI_STATE_DISABLING, fromState); - checkWifiConnectModeStateChangedBroadcast(intents.get(intents.size() - 1), - WIFI_STATE_DISABLED, WIFI_STATE_DISABLING); - } - - private void verifyConnectModeNotificationsForFailure() { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()) - .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL)); - - List<Intent> intents = intentCaptor.getAllValues(); - assertEquals(2, intents.size()); - checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLING, - WIFI_STATE_UNKNOWN); - checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, - WIFI_STATE_DISABLING); - } - - /** - * ClientMode start sets up an interface in ClientMode. - */ - @Test - public void clientInConnectModeStartCreatesClientInterface() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - } - - /** - * ClientMode start sets up an interface in ClientMode. - */ - @Test - public void clientInScanOnlyModeStartCreatesClientInterface() throws Exception { - startClientInScanOnlyModeAndVerifyEnabled(); - } - - /** - * Switch ClientModeManager from ScanOnly mode To Connect mode. - */ - @Test - public void switchFromScanOnlyModeToConnectMode() throws Exception { - startClientInScanOnlyModeAndVerifyEnabled(); - - when(mWifiNative.switchClientInterfaceToConnectivityMode(any())) - .thenReturn(true); - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - mLooper.dispatchAll(); - - verify(mSarManager).setScanOnlyWifiState(WIFI_STATE_DISABLED); - verify(mClientModeImpl).setOperationalMode( - ClientModeImpl.SCAN_ONLY_MODE, TEST_INTERFACE_NAME); - verify(mClientModeImpl).setOperationalMode( - ClientModeImpl.CONNECT_MODE, TEST_INTERFACE_NAME); - verify(mSarManager).setClientWifiState(WIFI_STATE_ENABLED); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> intents = intentCaptor.getAllValues(); - assertEquals(2, intents.size()); - Log.d(TAG, "captured intents: " + intents); - checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, - WIFI_STATE_DISABLED); - checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED, - WIFI_STATE_ENABLING); - - verify(mListener, times(2)).onStarted(); - } - - /** - * Switch ClientModeManager from Connect mode to ScanOnly mode. - */ - @Test - public void switchFromConnectModeToScanOnlyMode() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - - when(mWifiNative.switchClientInterfaceToScanMode(any())) - .thenReturn(true); - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - verify(mSarManager).setClientWifiState(WIFI_STATE_DISABLED); - verify(mWifiNative).setupInterfaceForClientInScanMode( - mInterfaceCallbackCaptor.capture()); - verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME); - verify(mClientModeImpl, times(2)).setOperationalMode( - ClientModeImpl.SCAN_ONLY_MODE, TEST_INTERFACE_NAME); - verify(mSarManager, times(2)).setScanOnlyWifiState(WIFI_STATE_ENABLED); - - verify(mContext).getSystemService(anyString()); - verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any()); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - - // Ensure that no public broadcasts were sent. - verifyNoMoreInteractions(mContext); - verify(mListener, times(3)).onStarted(); - } - - /** - * ClientMode increments failure metrics when failing to setup client mode in connectivity mode. - */ - @Test - public void detectAndReportErrorWhenSetupForClientInConnectivityModeWifiNativeFailure() - throws Exception { - when(mWifiNative.setupInterfaceForClientInScanMode(any())) - .thenReturn(TEST_INTERFACE_NAME); - when(mWifiNative.switchClientInterfaceToConnectivityMode(any())).thenReturn(false); - - mClientModeManager.start(); - mLooper.dispatchAll(); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - mLooper.dispatchAll(); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - List<Intent> intents = intentCaptor.getAllValues(); - assertEquals(2, intents.size()); - checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, - WIFI_STATE_DISABLED); - checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, - WIFI_STATE_UNKNOWN); - verify(mListener).onStartFailure(); - } - - /** - * Calling ClientModeManager.start twice does not crash or restart client mode. - */ - @Test - public void clientModeStartCalledTwice() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - reset(mWifiNative, mContext); - mClientModeManager.start(); - mLooper.dispatchAll(); - verifyNoMoreInteractions(mWifiNative, mContext); - } - - /** - * ClientMode stop properly cleans up state - */ - @Test - public void clientModeStopCleansUpState() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - assertTrue(mClientModeManager.isStopping()); - mLooper.dispatchAll(); - verify(mListener).onStopped(); - assertFalse(mClientModeManager.isStopping()); - - verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any()); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - // on an explicit stop, we should not trigger the callback - verifyNoMoreInteractions(mListener); - } - - /** - * Calling stop when ClientMode is not started should not send scan state updates - */ - @Test - public void clientModeStopWhenNotStartedDoesNotUpdateScanStateUpdates() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - reset(mContext); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - reset(mContext, mListener); - setUpSystemServiceForContext(); - // now call stop again - mClientModeManager.stop(); - mLooper.dispatchAll(); - verify(mContext, never()).sendStickyBroadcastAsUser(any(), any()); - verifyNoMoreInteractions(mListener); - } - - /** - * Triggering interface down when ClientMode is active properly exits the active state. - */ - @Test - public void clientModeStartedStopsWhenInterfaceDown() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - reset(mContext); - setUpSystemServiceForContext(); - when(mClientModeImpl.isConnectedMacRandomizationEnabled()).thenReturn(false); - mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - verify(mClientModeImpl).failureDetected(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); - verifyConnectModeNotificationsForFailure(); - verify(mListener).onStopped(); - } - - /** - * Triggering interface down when ClientMode is active and Connected MacRandomization is enabled - * does not exit the active state. - */ - @Test - public void clientModeStartedWithConnectedMacRandDoesNotStopWhenInterfaceDown() - throws Exception { - startClientInConnectModeAndVerifyEnabled(); - reset(mContext); - setUpSystemServiceForContext(); - when(mClientModeImpl.isConnectedMacRandomizationEnabled()).thenReturn(true); - mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - verify(mClientModeImpl, never()).failureDetected(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); - verify(mContext, never()).sendStickyBroadcastAsUser(any(), any()); - } - - /** - * Testing the handling of an interface destroyed notification. - */ - @Test - public void clientModeStartedStopsOnInterfaceDestroyed() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - reset(mContext); - setUpSystemServiceForContext(); - mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - verify(mClientModeImpl).handleIfaceDestroyed(); - verify(mListener).onStopped(); - } - - /** - * Verify that onDestroyed after client mode is stopped doesn't trigger a callback. - */ - @Test - public void noCallbackOnInterfaceDestroyedWhenAlreadyStopped() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - - reset(mListener); - - mClientModeManager.stop(); - mLooper.dispatchAll(); - - // now trigger interface destroyed and make sure callback doesn't get called - mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - verify(mListener).onStopped(); - - verifyNoMoreInteractions(mListener); - verify(mClientModeImpl, never()).handleIfaceDestroyed(); - } - - /** - * Entering ScanOnly state starts the WakeupController. - */ - @Test - public void scanModeEnterStartsWakeupController() throws Exception { - startClientInScanOnlyModeAndVerifyEnabled(); - - verify(mWakeupController).start(); - } - - /** - * Exiting ScanOnly state stops the WakeupController. - */ - @Test - public void scanModeExitStopsWakeupController() throws Exception { - startClientInScanOnlyModeAndVerifyEnabled(); - - mClientModeManager.stop(); - mLooper.dispatchAll(); - - InOrder inOrder = inOrder(mWakeupController, mWifiNative, mListener); - - inOrder.verify(mListener).onStarted(); - inOrder.verify(mWakeupController).start(); - inOrder.verify(mWakeupController).stop(); - inOrder.verify(mWifiNative).teardownInterface(eq(TEST_INTERFACE_NAME)); - } - - private void setUpVoWifiTest( - boolean isWifiCallingAvailable, - int wifiOffDeferringTimeMs) { - mCurrentImsRegistrationState = (isWifiCallingAvailable) - ? RegistrationManager.REGISTRATION_STATE_REGISTERED - : RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED; - mCurrentImsConnectionType = (isWifiCallingAvailable) - ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN - : AccessNetworkConstants.TRANSPORT_TYPE_WWAN; - when(mImsMmTelManager.isAvailable(anyInt(), anyInt())).thenReturn(isWifiCallingAvailable); - when(mCarrierConfigBundle - .getInt(eq(CarrierConfigManager.Ims.KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT))) - .thenReturn(wifiOffDeferringTimeMs); - } - - /** - * ClientMode stop properly with IMS deferring time without WifiCalling. - */ - @Test - public void clientModeStopWithWifiOffDeferringTimeNoWifiCalling() throws Exception { - setUpVoWifiTest(false, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - verify(mListener).onStopped(); - - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any()); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mWifiMetrics).noteWifiOff(eq(false), eq(false), anyInt()); - - // on an explicit stop, we should not trigger the callback - verifyNoMoreInteractions(mListener); - } - - /** - * ClientMode stop properly with IMS deferring time and IMS is registered on WWAN. - */ - @Test - public void clientModeStopWithWifiOffDeferringTimeAndImsOnWwan() throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - mCurrentImsConnectionType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN; - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - verify(mListener).onStopped(); - - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt()); - - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - // on an explicit stop, we should not trigger the callback - verifyNoMoreInteractions(mListener); - } - - /** - * ClientMode stop properly with IMS deferring time, Wifi calling. - */ - @Test - public void clientModeStopWithWifiOffDeferringTimeWithWifiCalling() throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - - // Not yet finish IMS deregistration. - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mListener, never()).onStopped(); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Notify wifi service IMS service is de-registered. - assertNotNull(mImsMmTelManagerRegistrationCallback); - mImsMmTelManagerRegistrationCallback.onUnregistered(null); - assertNotNull(mImsNetworkCallback); - mImsNetworkCallback.onLost(null); - mLooper.dispatchAll(); - - // Now Wifi could be turned off actually. - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - assertNull(mImsNetworkCallback); - verify(mListener).onStopped(); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt()); - - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - // on an explicit stop, we should not trigger the callback - verifyNoMoreInteractions(mListener); - } - - /** - * ClientMode stop properly with IMS deferring time and Wifi calling. - * - * IMS deregistration is done before reaching the timeout. - */ - @Test - public void clientModeStopWithWifiOffDeferringTimeAndWifiCallingOnImsRegistered() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - - // Not yet finish IMS deregistration. - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mListener, never()).onStopped(); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Notify wifi service IMS service is de-registered. - assertNotNull(mImsMmTelManagerRegistrationCallback); - mImsMmTelManagerRegistrationCallback.onRegistered(0); - mLooper.dispatchAll(); - - // Now Wifi could be turned off actually. - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mListener).onStopped(); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt()); - - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - // on an explicit stop, we should not trigger the callback - verifyNoMoreInteractions(mListener); - } - - /** - * ClientMode stop properly with IMS deferring time and Wifi calling. - * - * IMS deregistration is NOT done before reaching the timeout. - */ - @Test - public void clientModeStopWithWifiOffDeferringTimeAndWifiCallingTimedOut() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mListener, never()).onStopped(); - - // 1/2 deferring time passed, should be still waiting for the callback. - moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS / 2); - mLooper.dispatchAll(); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mListener, never()).onStopped(); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Exceeding the timeout, wifi should be stopped. - moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS / 2 + 1000); - mLooper.dispatchAll(); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mListener).onStopped(); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(true), anyInt()); - - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - // on an explicit stop, we should not trigger the callback - verifyNoMoreInteractions(mListener); - } - - /** - * ClientMode stop properly with IMS deferring time and Wifi calling. - * - * IMS deregistration is NOT done before reaching the timeout with multiple stop calls. - */ - @Test - public void clientModeStopWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleStop() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mListener, never()).onStopped(); - - mClientModeManager.stop(); - mLooper.dispatchAll(); - // should not register another listener. - verify(mImsMmTelManager, times(1)).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mListener, never()).onStopped(); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Exceeding the timeout, wifi should be stopped. - moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS + 1000); - mLooper.dispatchAll(); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mListener).onStopped(); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(true), anyInt()); - - verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED); - - // on an explicit stop, we should not trigger the callback - verifyNoMoreInteractions(mListener); - } - - /** - * ClientMode does not stop with IMS deferring time and Wifi calling - * when the target role is not ROLE_UNSPECIFIED. - * - * Simulate a user toggle wifi multiple times before doing wifi stop and stay at - * ON position. - */ - @Test - public void clientModeNotStopWithWifiOffDeferringTimeAndWifiCallingTimedOut() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mListener, never()).onStopped(); - - mClientModeManager.start(); - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - mLooper.dispatchAll(); - mClientModeManager.stop(); - mLooper.dispatchAll(); - mClientModeManager.start(); - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - mLooper.dispatchAll(); - // should not register another listener. - verify(mImsMmTelManager, times(1)).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mListener, never()).onStopped(); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Exceeding the timeout, wifi should NOT be stopped. - moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS + 1000); - mLooper.dispatchAll(); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mListener, never()).onStopped(); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // on an explicit stop, we should not trigger the callback - verifyNoMoreInteractions(mListener); - } - - /** - * Switch to scan mode properly with IMS deferring time without WifiCalling. - */ - @Test - public void switchToScanOnlyModeWithWifiOffDeferringTimeNoWifiCalling() throws Exception { - setUpVoWifiTest(false, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - when(mWifiNative.switchClientInterfaceToScanMode(any())) - .thenReturn(true); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - - verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME); - verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any()); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mWifiMetrics).noteWifiOff(eq(false), eq(false), anyInt()); - } - - /** - * Switch to scan mode properly with IMS deferring time and IMS is registered on WWAN. - */ - @Test - public void switchToScanOnlyModeWithWifiOffDeferringTimeAndImsOnWwan() throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - mCurrentImsConnectionType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN; - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - when(mWifiNative.switchClientInterfaceToScanMode(any())) - .thenReturn(true); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - - verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME); - - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt()); - } - - /** - * Switch to scan mode properly with IMS deferring time and Wifi calling. - * - * IMS deregistration is done before reaching the timeout. - */ - @Test - public void switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingOnImsUnregistered() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - when(mWifiNative.switchClientInterfaceToScanMode(any())) - .thenReturn(true); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - - // Not yet finish IMS deregistration. - verify(mWifiNative, never()).switchClientInterfaceToScanMode(any()); - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Notify wifi service IMS service is de-registered. - assertNotNull(mImsMmTelManagerRegistrationCallback); - mImsMmTelManagerRegistrationCallback.onUnregistered(null); - assertNotNull(mImsNetworkCallback); - mImsNetworkCallback.onLost(null); - mLooper.dispatchAll(); - - // Now Wifi could be switched to scan mode actually. - verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - assertNull(mImsNetworkCallback); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt()); - } - - /** - * Switch to scan mode properly with IMS deferring time and Wifi calling. - * - * IMS deregistration is done before reaching the timeout. - */ - @Test - public void switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingOnImsRegistered() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - when(mWifiNative.switchClientInterfaceToScanMode(any())) - .thenReturn(true); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - - // Not yet finish IMS deregistration. - verify(mWifiNative, never()).switchClientInterfaceToScanMode(any()); - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Notify wifi service IMS service is de-registered. - assertNotNull(mImsMmTelManagerRegistrationCallback); - mImsMmTelManagerRegistrationCallback.onRegistered(0); - mLooper.dispatchAll(); - - // Now Wifi could be switched to scan mode actually. - verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt()); - } - - /** - * Switch to scan mode properly with IMS deferring time and Wifi calling. - * - * IMS deregistration is NOT done before reaching the timeout. - */ - @Test - public void switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingTimedOut() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - when(mWifiNative.switchClientInterfaceToScanMode(any())) - .thenReturn(true); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - - verify(mWifiNative, never()).switchClientInterfaceToScanMode(any()); - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - - // 1/2 deferring time passed, should be still waiting for the callback. - moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS / 2); - mLooper.dispatchAll(); - verify(mWifiNative, never()).switchClientInterfaceToScanMode(any()); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Exceeding the timeout, wifi should be stopped. - moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS / 2 + 1000); - mLooper.dispatchAll(); - verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(true), anyInt()); - } - - /** - * Switch to scan mode properly with IMS deferring time and Wifi calling. - * - * IMS deregistration is NOT done before reaching the timeout with multiple stop calls. - */ - @Test - public void - switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleSwitch() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - when(mWifiNative.switchClientInterfaceToScanMode(any())) - .thenReturn(true); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - // should not register another listener. - verify(mWifiNative, never()).switchClientInterfaceToScanMode(any()); - verify(mImsMmTelManager, times(1)).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Exceeding the timeout, wifi should be stopped. - moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS + 1000); - mLooper.dispatchAll(); - verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mWifiMetrics).noteWifiOff(eq(true), eq(true), anyInt()); - } - - /** - * Stay at connected mode with IMS deferring time and Wifi calling - * when the target state is not ROLE_CLIENT_SCAN_ONLY. - * - * Simulate a user toggle wifi multiple times before doing wifi stop and stay at - * ON position. - */ - @Test - public void - stayAtConnectedModeWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleSwitch() - throws Exception { - setUpVoWifiTest(true, - TEST_WIFI_OFF_DEFERRING_TIME_MS); - - startClientInConnectModeAndVerifyEnabled(); - reset(mContext, mListener); - setUpSystemServiceForContext(); - when(mWifiNative.switchClientInterfaceToScanMode(any())) - .thenReturn(true); - - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - mLooper.dispatchAll(); - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY); - mLooper.dispatchAll(); - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - mLooper.dispatchAll(); - - verify(mImsMmTelManager).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - - // should not register another listener. - verify(mWifiNative, never()).switchClientInterfaceToScanMode(any()); - verify(mImsMmTelManager, times(1)).registerImsRegistrationCallback( - any(Executor.class), - any(RegistrationManager.RegistrationCallback.class)); - verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - - // Exceeding the timeout, wifi should NOT be stopped. - moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS + 1000); - mLooper.dispatchAll(); - verify(mWifiNative, never()).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME); - verify(mImsMmTelManager).unregisterImsRegistrationCallback( - any(RegistrationManager.RegistrationCallback.class)); - assertNull(mImsMmTelManagerRegistrationCallback); - verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt()); - } - - /** - * ClientMode starts up in connect mode and then change connectivity roles. - */ - @Test - public void clientInConnectModeChangeRoles() throws Exception { - startClientInConnectModeAndVerifyEnabled(); - reset(mListener); - - // Set the same role again, no-op. - assertEquals(ActiveModeManager.ROLE_CLIENT_PRIMARY, mClientModeManager.getRole()); - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY); - mLooper.dispatchAll(); - verify(mListener, never()).onStarted(); // no callback sent. - - // Change the connectivity role. - mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_SECONDARY); - mLooper.dispatchAll(); - verify(mListener).onStarted(); // callback sent. - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java b/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java deleted file mode 100644 index 37d2945cf..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import android.util.ArrayMap; - -import com.android.server.wifi.proto.WifiScoreCardProto; - -import java.util.Map; - -public final class ConcreteCandidate implements WifiCandidates.Candidate { - private WifiCandidates.Key mKey; - private int mNetworkConfigId = -1; - private boolean mIsOpenNetwork; - private boolean mIsCurrentNetwork; - private boolean mIsCurrentBssid; - private boolean mIsPasspoint; - private boolean mIsEphemeral; - private boolean mIsTrusted = true; - private boolean mCarrierOrPrivileged; - private boolean mIsMetered; - private boolean mHasNoInternetAccess; - private boolean mIsNoInternetAccessExpected; - private int mNominatorId = -1; - private double mLastSelectionWeight; - private int mScanRssi = -127; - private int mFrequency = -1; - private int mPredictedThroughputMbps = 0; - private int mEstimatedPercentInternetAvailability = 50; - - private final Map<WifiScoreCardProto.Event, WifiScoreCardProto.Signal> - mEventStatisticsMap = new ArrayMap<>(); - - ConcreteCandidate() { - } - - public ConcreteCandidate(WifiCandidates.Candidate candidate) { - mKey = candidate.getKey(); - mNetworkConfigId = candidate.getNetworkConfigId(); - mIsOpenNetwork = candidate.isOpenNetwork(); - mIsCurrentNetwork = candidate.isCurrentNetwork(); - mIsCurrentBssid = candidate.isCurrentBssid(); - mIsPasspoint = candidate.isPasspoint(); - mIsEphemeral = candidate.isEphemeral(); - mIsTrusted = candidate.isTrusted(); - mCarrierOrPrivileged = candidate.isCarrierOrPrivileged(); - mIsMetered = candidate.isMetered(); - mHasNoInternetAccess = candidate.hasNoInternetAccess(); - mIsNoInternetAccessExpected = candidate.isNoInternetAccessExpected(); - mNominatorId = candidate.getNominatorId(); - mLastSelectionWeight = candidate.getLastSelectionWeight(); - mScanRssi = candidate.getScanRssi(); - mFrequency = candidate.getFrequency(); - mPredictedThroughputMbps = candidate.getPredictedThroughputMbps(); - mEstimatedPercentInternetAvailability = candidate - .getEstimatedPercentInternetAvailability(); - for (WifiScoreCardProto.Event event : WifiScoreCardProto.Event.values()) { - WifiScoreCardProto.Signal signal = candidate.getEventStatistics(event); - if (signal != null) { - mEventStatisticsMap.put(event, signal); - } - } - } - - public ConcreteCandidate setKey(WifiCandidates.Key key) { - mKey = key; - return this; - } - - @Override - public WifiCandidates.Key getKey() { - return mKey; - } - - public ConcreteCandidate setNetworkConfigId(int networkConfigId) { - mNetworkConfigId = networkConfigId; - return this; - } - - @Override - public int getNetworkConfigId() { - return mNetworkConfigId; - } - - public ConcreteCandidate setOpenNetwork(boolean isOpenNetwork) { - mIsOpenNetwork = isOpenNetwork; - return this; - } - - @Override - public boolean isOpenNetwork() { - return mIsOpenNetwork; - } - - public ConcreteCandidate setPasspoint(boolean isPasspoint) { - mIsPasspoint = isPasspoint; - return this; - } - - @Override - public boolean isPasspoint() { - return mIsPasspoint; - } - - public ConcreteCandidate setEphemeral(boolean isEphemeral) { - mIsEphemeral = isEphemeral; - return this; - } - - @Override - public boolean isEphemeral() { - return mIsEphemeral; - } - - public ConcreteCandidate setTrusted(boolean isTrusted) { - mIsTrusted = isTrusted; - return this; - } - - @Override - public boolean isTrusted() { - return mIsTrusted; - } - - public ConcreteCandidate setCarrierOrPrivileged(boolean carrierOrPrivileged) { - mCarrierOrPrivileged = carrierOrPrivileged; - return this; - } - - @Override - public boolean isCarrierOrPrivileged() { - return mCarrierOrPrivileged; - } - - public ConcreteCandidate setMetered(boolean isMetered) { - mIsMetered = isMetered; - return this; - } - - @Override - public boolean isMetered() { - return mIsMetered; - } - - public ConcreteCandidate setNoInternetAccess(boolean hasNoInternetAccess) { - mHasNoInternetAccess = hasNoInternetAccess; - return this; - } - - @Override - public boolean hasNoInternetAccess() { - return mHasNoInternetAccess; - } - - public ConcreteCandidate setNoInternetAccessExpected(boolean isNoInternetAccessExpected) { - mIsNoInternetAccessExpected = isNoInternetAccessExpected; - return this; - } - - @Override - public boolean isNoInternetAccessExpected() { - return mIsNoInternetAccessExpected; - } - - public ConcreteCandidate setNominatorId(int nominatorId) { - mNominatorId = nominatorId; - return this; - } - - @Override - public int getNominatorId() { - return mNominatorId; - } - - public ConcreteCandidate setLastSelectionWeight(double lastSelectionWeight) { - mLastSelectionWeight = lastSelectionWeight; - return this; - } - - @Override - public double getLastSelectionWeight() { - return mLastSelectionWeight; - } - - public ConcreteCandidate setCurrentNetwork(boolean isCurrentNetwork) { - mIsCurrentNetwork = isCurrentNetwork; - return this; - } - - @Override - public boolean isCurrentNetwork() { - return mIsCurrentNetwork; - } - - public ConcreteCandidate setCurrentBssid(boolean isCurrentBssid) { - mIsCurrentBssid = isCurrentBssid; - return this; - } - - @Override - public boolean isCurrentBssid() { - return mIsCurrentBssid; - } - - public ConcreteCandidate setScanRssi(int scanRssi) { - mScanRssi = scanRssi; - return this; - } - - @Override - public int getScanRssi() { - return mScanRssi; - } - - public ConcreteCandidate setFrequency(int frequency) { - mFrequency = frequency; - return this; - } - - @Override - public int getFrequency() { - return mFrequency; - } - - public ConcreteCandidate setPredictedThroughputMbps(int predictedThroughputMbps) { - mPredictedThroughputMbps = predictedThroughputMbps; - return this; - } - - @Override - public int getPredictedThroughputMbps() { - return mPredictedThroughputMbps; - } - - public ConcreteCandidate setEstimatedPercentInternetAvailability(int percent) { - mEstimatedPercentInternetAvailability = percent; - return this; - } - - @Override - public int getEstimatedPercentInternetAvailability() { - return mEstimatedPercentInternetAvailability; - } - - public ConcreteCandidate setEventStatistics( - WifiScoreCardProto.Event event, - WifiScoreCardProto.Signal signal) { - mEventStatisticsMap.put(event, signal); - return this; - } - - @Override - public WifiScoreCardProto.Signal getEventStatistics(WifiScoreCardProto.Event event) { - return mEventStatisticsMap.get(event); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java b/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java deleted file mode 100644 index 02994ecad..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.when; - -import android.content.pm.UserInfo; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.SparseArray; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.ConfigurationMapTest}. - */ -@SmallTest -public class ConfigurationMapTest extends WifiBaseTest { - private static final int SYSTEM_MANAGE_PROFILE_USER_ID = 12; - private static final List<WifiConfiguration> CONFIGS = Arrays.asList( - WifiConfigurationTestUtil.generateWifiConfig( - 0, 1000000, "\"red\"", true, true, null, null), - WifiConfigurationTestUtil.generateWifiConfig( - 1, 1000001, "\"green\"", true, false, "example.com", "Green"), - WifiConfigurationTestUtil.generateWifiConfig( - 2, 1200000, "\"blue\"", false, true, null, null), - WifiConfigurationTestUtil.generateWifiConfig( - 3, 1100000, "\"cyan\"", true, true, null, null), - WifiConfigurationTestUtil.generateWifiConfig( - 4, 1100001, "\"yellow\"", true, true, "example.org", "Yellow"), - WifiConfigurationTestUtil.generateWifiConfig( - 5, 1100002, "\"magenta\"", false, false, null, null)); - - private static final SparseArray<List<UserInfo>> USER_PROFILES = new SparseArray<>(); - static { - USER_PROFILES.put(UserHandle.USER_SYSTEM, Arrays.asList( - new UserInfo(UserHandle.USER_SYSTEM, "Owner", 0), - new UserInfo(SYSTEM_MANAGE_PROFILE_USER_ID, "Managed Profile", 0))); - USER_PROFILES.put(10, Arrays.asList(new UserInfo(10, "Alice", 0))); - USER_PROFILES.put(11, Arrays.asList(new UserInfo(11, "Bob", 0))); - } - - @Mock UserManager mUserManager; - - private int mCurrentUserId = UserHandle.USER_SYSTEM; - private ConfigurationMap mConfigs; - - /** - * Sets up the test harness before running a test. - */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - // by default, return false - when(mUserManager.isSameProfileGroup(any(), any())).thenReturn(false); - // return true for these 2 userids - when(mUserManager.isSameProfileGroup(UserHandle.SYSTEM, - UserHandle.of(SYSTEM_MANAGE_PROFILE_USER_ID))) - .thenReturn(true); - when(mUserManager.isSameProfileGroup(UserHandle.of(SYSTEM_MANAGE_PROFILE_USER_ID), - UserHandle.SYSTEM)) - .thenReturn(true); - mConfigs = new ConfigurationMap(mUserManager); - } - - private void switchUser(int newUserId) { - mCurrentUserId = newUserId; - mConfigs.setNewUser(newUserId); - mConfigs.clear(); - } - - private Collection<WifiConfiguration> getEnabledNetworksForCurrentUser() { - List<WifiConfiguration> list = new ArrayList<>(); - for (WifiConfiguration config : mConfigs.valuesForCurrentUser()) { - if (config.status != WifiConfiguration.Status.DISABLED) { - list.add(config); - } - } - return list; - } - - private WifiConfiguration getEphemeralForCurrentUser(String ssid) { - for (WifiConfiguration config : mConfigs.valuesForCurrentUser()) { - if (ssid.equals(config.SSID) && config.ephemeral) { - return config; - } - } - return null; - } - - private void addNetworks(List<WifiConfiguration> configs) { - for (WifiConfiguration config : configs) { - assertNull(mConfigs.put(config)); - } - } - - private void verifyGetters(List<WifiConfiguration> configs) { - final Set<WifiConfiguration> configsForCurrentUser = new HashSet<>(); - final Set<WifiConfiguration> enabledConfigsForCurrentUser = new HashSet<>(); - final List<WifiConfiguration> configsNotForCurrentUser = new ArrayList<>(); - - // Find out which network configurations should be / should not be visible to the current - // user. Also, check that *ForAllUsers() methods can be used to access all network - // configurations, irrespective of their visibility to the current user. - for (WifiConfiguration config : configs) { - final UserHandle currentUser = UserHandle.of(mCurrentUserId); - final UserHandle creatorUser = UserHandle.getUserHandleForUid(config.creatorUid); - if (config.shared || currentUser.equals(creatorUser) - || mUserManager.isSameProfileGroup(currentUser, creatorUser)) { - configsForCurrentUser.add(config); - if (config.status != WifiConfiguration.Status.DISABLED) { - enabledConfigsForCurrentUser.add(config); - } - } else { - configsNotForCurrentUser.add(config); - } - - assertEquals(config, mConfigs.getForAllUsers(config.networkId)); - } - - // Verify that *ForCurrentUser() methods can be used to access network configurations - // visible to the current user. - for (WifiConfiguration config : configsForCurrentUser) { - assertEquals(config, mConfigs.getForCurrentUser(config.networkId)); - assertEquals(config, mConfigs.getByConfigKeyForCurrentUser(config.getKey())); - final boolean wasEphemeral = config.ephemeral; - config.ephemeral = false; - assertNull(getEphemeralForCurrentUser(config.SSID)); - config.ephemeral = true; - assertEquals(config, getEphemeralForCurrentUser(config.SSID)); - config.ephemeral = wasEphemeral; - } - - // Verify that *ForCurrentUser() methods cannot be used to access network configurations not - // visible to the current user. - for (WifiConfiguration config : configsNotForCurrentUser) { - assertNull(mConfigs.getForCurrentUser(config.networkId)); - assertNull(mConfigs.getByConfigKeyForCurrentUser(config.getKey())); - final boolean wasEphemeral = config.ephemeral; - config.ephemeral = false; - assertNull(getEphemeralForCurrentUser(config.SSID)); - config.ephemeral = true; - assertNull(getEphemeralForCurrentUser(config.SSID)); - config.ephemeral = wasEphemeral; - } - - // Verify that the methods which refer to more than one network configuration return the - // correct sets of networks. - assertEquals(configs.size(), mConfigs.sizeForAllUsers()); - assertEquals(configsForCurrentUser.size(), mConfigs.sizeForCurrentUser()); - assertEquals(enabledConfigsForCurrentUser, - new HashSet<WifiConfiguration>(getEnabledNetworksForCurrentUser())); - assertEquals(new HashSet<>(configs), - new HashSet<WifiConfiguration>(mConfigs.valuesForAllUsers())); - } - - private ScanResult createScanResultForNetwork(WifiConfiguration config) { - return WifiConfigurationTestUtil.createScanDetailForNetwork(config, "", 0, 0, 0, 0) - .getScanResult(); - } - - /** - * Helper function to create a scan result matching the network and ensuring that - * {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} can match that network. - */ - private void verifyScanResultMatchWithNetwork(WifiConfiguration config) { - mConfigs.put(config); - ScanResult scanResult = createScanResultForNetwork(config); - WifiConfiguration retrievedConfig = - mConfigs.getByScanResultForCurrentUser(scanResult); - assertNotNull(retrievedConfig); - assertEquals(config.getKey(), retrievedConfig.getKey()); - } - - /** - * Verifies that all getters return the correct network configurations, taking into account the - * current user. Also verifies that handleUserSwitch() returns the list of network - * configurations that are no longer visible. - */ - @Test - public void testGettersAndHandleUserSwitch() { - addNetworks(CONFIGS); - verifyGetters(CONFIGS); - - switchUser(10); - addNetworks(CONFIGS); - verifyGetters(CONFIGS); - - switchUser(11); - addNetworks(CONFIGS); - verifyGetters(CONFIGS); - } - - /** - * Verifies put(), remove() and clear(). - */ - @Test - public void testPutRemoveClear() { - final List<WifiConfiguration> configs = new ArrayList<>(); - final WifiConfiguration config1 = CONFIGS.get(0); - - // Verify that there are no network configurations to start with. - switchUser(UserHandle.getUserHandleForUid(config1.creatorUid).getIdentifier()); - verifyGetters(configs); - - // Add |config1|. - assertNull(mConfigs.put(config1)); - // Verify that the getters return |config1|. - configs.add(config1); - verifyGetters(configs); - - // Overwrite |config1| with |config2|. - final WifiConfiguration config2 = CONFIGS.get(1); - config2.networkId = config1.networkId; - assertEquals(config1, mConfigs.put(config2)); - // Verify that the getters return |config2| only. - configs.clear(); - configs.add(config2); - verifyGetters(configs); - - // Add |config3|, which belongs to a managed profile of the current user. - final WifiConfiguration config3 = CONFIGS.get(2); - assertNull(mConfigs.put(config3)); - // Verify that the getters return |config2| and |config3|. - configs.add(config3); - verifyGetters(configs); - - // Remove |config2|. - assertEquals(config2, mConfigs.remove(config2.networkId)); - // Verify that the getters return |config3| only. - configs.remove(config2); - verifyGetters(configs); - - // Clear all network configurations. - mConfigs.clear(); - // Verify that the getters do not return any network configurations. - configs.clear(); - verifyGetters(configs); - } - - /** - * Verifies that {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} can - * positively match the corresponding networks. - */ - @Test - public void testScanResultDoesMatchCorrespondingNetworks() { - verifyScanResultMatchWithNetwork(WifiConfigurationTestUtil.createOpenNetwork()); - verifyScanResultMatchWithNetwork(WifiConfigurationTestUtil.createPskNetwork()); - verifyScanResultMatchWithNetwork(WifiConfigurationTestUtil.createWepNetwork()); - verifyScanResultMatchWithNetwork(WifiConfigurationTestUtil.createEapNetwork()); - } - - /** - * Verifies that {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} does not - * match other networks. - */ - @Test - public void testScanResultDoesNotMatchWithOtherNetworks() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - ScanResult scanResult = createScanResultForNetwork(config); - // Change the network security type and the old scan result should not match now. - config.allowedKeyManagement.clear(); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - mConfigs.put(config); - assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); - } - - /** - * Verifies that {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} does not - * match networks which have been removed. - */ - @Test - public void testScanResultDoesNotMatchAfterNetworkRemove() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - ScanResult scanResult = createScanResultForNetwork(config); - config.networkId = 5; - mConfigs.put(config); - // Create another network in the map. - mConfigs.put(WifiConfigurationTestUtil.createPskNetwork()); - assertNotNull(mConfigs.getByScanResultForCurrentUser(scanResult)); - - mConfigs.remove(config.networkId); - assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); - } - - /** - * Verifies that {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} does not - * match networks after clear. - */ - @Test - public void testScanResultDoesNotMatchAfterClear() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - ScanResult scanResult = createScanResultForNetwork(config); - config.networkId = 5; - mConfigs.put(config); - // Create another network in the map. - mConfigs.put(WifiConfigurationTestUtil.createPskNetwork()); - assertNotNull(mConfigs.getByScanResultForCurrentUser(scanResult)); - - mConfigs.clear(); - assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); - } - - @Test - public void testScanResultDoesNotMatchForWifiNetworkSpecifier() { - // Add regular saved network, this should create a scan result match info cache entry. - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - ScanResult scanResult = createScanResultForNetwork(config); - config.networkId = 5; - mConfigs.put(config); - assertNotNull(mConfigs.getByScanResultForCurrentUser(scanResult)); - - mConfigs.clear(); - - // Create WifiNetworkSpecifier network, this should not create a scan result match info - // cache entry. - config.ephemeral = true; - config.fromWifiNetworkSpecifier = true; - mConfigs.put(config); - assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ConnectionFailureNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/ConnectionFailureNotifierTest.java deleted file mode 100644 index 1c9df67bc..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ConnectionFailureNotifierTest.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.AlertDialog; -import android.app.Notification; -import android.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.res.Resources; -import android.net.wifi.WifiConfiguration; -import android.os.Handler; -import android.os.Process; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link ConnectionFailureNotifier}. - */ -@SmallTest -public class ConnectionFailureNotifierTest extends WifiBaseTest { - @Mock private Context mContext; - @Mock private WifiInjector mWifiInjector; - @Mock private Resources mResources; - @Mock private FrameworkFacade mFrameworkFacade; - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private WifiConnectivityManager mWifiConnectivityManager; - @Mock private NotificationManager mNotificationManager; - @Mock private ConnectionFailureNotificationBuilder mConnectionFailureNotificationBuilder; - @Mock private Notification mNotification; - @Mock private AlertDialog mAlertDialog; - - final ArgumentCaptor<BroadcastReceiver> mBroadCastReceiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - private ConnectionFailureNotifier mConnectionFailureNotifier; - TestLooper mLooper; - - /** Initialize objects before each test run. */ - @Before - public void setUp() throws Exception { - // Ensure looper exists - mLooper = new TestLooper(); - MockitoAnnotations.initMocks(this); - when(mContext.getResources()).thenReturn(mResources); - when(mWifiInjector.getNotificationManager()).thenReturn(mNotificationManager); - when(mWifiInjector.getConnectionFailureNotificationBuilder()) - .thenReturn(mConnectionFailureNotificationBuilder); - when(mConnectionFailureNotificationBuilder - .buildNoMacRandomizationSupportNotification(any())).thenReturn(mNotification); - when(mConnectionFailureNotificationBuilder.buildChangeMacRandomizationSettingDialog(any(), - any())).thenReturn(mAlertDialog); - mConnectionFailureNotifier = new ConnectionFailureNotifier(mContext, mWifiInjector, - mFrameworkFacade, mWifiConfigManager, mWifiConnectivityManager, - new Handler(mLooper.getLooper())); - - verify(mContext).registerReceiver(mBroadCastReceiverCaptor.capture(), any()); - } - - private class DisableMacRandomizationMatcher implements ArgumentMatcher<WifiConfiguration> { - @Override - public boolean matches(WifiConfiguration config) { - return config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_NONE; - } - } - - // Returns an intent that simulates the broadcast which is received when the user tap - // on the notification to change MAC randomization settings. - private Intent buildBroadcastForRandomizationSettingsDialog(WifiConfiguration config) { - Intent intent = mock(Intent.class); - when(intent.getAction()).thenReturn(ConnectionFailureNotificationBuilder - .ACTION_SHOW_SET_RANDOMIZATION_DETAILS); - when(intent.getIntExtra(eq(ConnectionFailureNotificationBuilder - .RANDOMIZATION_SETTINGS_NETWORK_ID), anyInt())).thenReturn(config.networkId); - when(intent.getStringExtra( - eq(ConnectionFailureNotificationBuilder.RANDOMIZATION_SETTINGS_NETWORK_SSID))) - .thenReturn(config.getSsidAndSecurityTypeString()); - return intent; - } - - /** - * Verify that a notification is posted when a connection failure happens on a network - * in the hotlist. Then verify that tapping on the notification launches an dialog, which - * could be used to set the randomization setting for a network to "Trusted". - */ - @Test - public void testConnectionFailureSendRandomizationSettingsNotification() { - // Verify that the network is using randomized MAC at the start. - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - when(mWifiConfigManager.getConfiguredNetwork(config.networkId)).thenReturn(config); - assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT, config.macRandomizationSetting); - - mConnectionFailureNotifier.showFailedToConnectDueToNoRandomizedMacSupportNotification( - config.networkId); - // verify that a notification is sent - verify(mNotificationManager).notify( - eq(SystemMessage.NOTE_NETWORK_NO_MAC_RANDOMIZATION_SUPPORT), eq(mNotification)); - - // sets up the intent that simulates the user tapping on the notification. - Intent intent = buildBroadcastForRandomizationSettingsDialog(config); - - // simulate the user tapping on the notification, then verify the dialog shows up, and - // the appropriate callback is registered - ArgumentCaptor<DialogInterface.OnClickListener> onClickListenerArgumentCaptor = - ArgumentCaptor.forClass(DialogInterface.OnClickListener.class); - mBroadCastReceiverCaptor.getValue().onReceive(mContext, intent); - verify(mConnectionFailureNotificationBuilder).buildChangeMacRandomizationSettingDialog( - eq(config.SSID), onClickListenerArgumentCaptor.capture()); - - // simulate the user tapping on the option to reset MAC address to factory MAC - onClickListenerArgumentCaptor.getValue().onClick(null, 0); - mLooper.dispatchAll(); - - // verify the WifiConfiguration is updated properly. - verify(mWifiConfigManager).addOrUpdateNetwork( - argThat(new DisableMacRandomizationMatcher()), eq(Process.SYSTEM_UID)); - // verify that we try to connect to the updated network. - verify(mWifiConnectivityManager).forceConnectivityScan(any()); - } - - /** - * Verify that if the WifiConfiguration if not found (may have been deleted by the timed the - * notification is tapped), then the AlertDialog does not show up. - */ - @Test - public void testWifiConfigurationMismatch() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - when(mWifiConfigManager.getConfiguredNetwork(config.networkId)).thenReturn(config); - mConnectionFailureNotifier.showFailedToConnectDueToNoRandomizedMacSupportNotification( - config.networkId); - // verify that a notification is sent - verify(mNotificationManager).notify( - eq(SystemMessage.NOTE_NETWORK_NO_MAC_RANDOMIZATION_SUPPORT), any()); - - // sets up the intent that simulates the user tapping on the notification. - Intent intent = buildBroadcastForRandomizationSettingsDialog(config); - - // the WifiConfiguration that is found doesn't match with the one received from broadcast. - when(mWifiConfigManager.getConfiguredNetwork(anyInt())) - .thenReturn(WifiConfigurationTestUtil.createOpenNetwork()); - mBroadCastReceiverCaptor.getValue().onReceive(mContext, intent); - - // verify that the AlertDialog is not launched in this case - verify(mConnectionFailureNotificationBuilder, never()) - .buildChangeMacRandomizationSettingDialog(any(), any()); - - verify(mFrameworkFacade, never()).makeAlertDialogBuilder(any()); - // instead we are showings a toast due to failing to find the network - verify(mFrameworkFacade).showToast(any(), any()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/CustomTestRunner.java b/tests/wifitests/src/com/android/server/wifi/CustomTestRunner.java deleted file mode 100644 index 3d9f54ade..000000000 --- a/tests/wifitests/src/com/android/server/wifi/CustomTestRunner.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import android.os.Bundle; -import android.util.Log; - -import androidx.test.runner.AndroidJUnitRunner; - -public class CustomTestRunner extends AndroidJUnitRunner { - @Override - public void onCreate(Bundle arguments) { - // Override the default TerribleFailureHandler, as that handler might terminate - // the process (if we're on an eng build). - Log.setWtfHandler((tag, what, system) -> Log.e(tag, "WTF", what)); - super.onCreate(arguments); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java b/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java deleted file mode 100644 index a570d2948..000000000 --- a/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; -import static org.mockito.MockitoAnnotations.*; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.content.Context; -import android.os.Handler; -import android.os.test.TestLooper; -import android.provider.DeviceConfig; -import android.provider.DeviceConfig.OnPropertiesChangedListener; -import android.util.ArraySet; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; - -import java.util.Collections; -import java.util.Set; - - -/** - * Unit tests for {@link com.android.server.wifi.DeviceConfigFacade}. - */ -@SmallTest -public class DeviceConfigFacadeTest extends WifiBaseTest { - @Mock Context mContext; - @Mock WifiMetrics mWifiMetrics; - - final ArgumentCaptor<OnPropertiesChangedListener> mOnPropertiesChangedListenerCaptor = - ArgumentCaptor.forClass(OnPropertiesChangedListener.class); - - private DeviceConfigFacade mDeviceConfigFacade; - private TestLooper mLooper = new TestLooper(); - private MockitoSession mSession; - - /** - * Setup the mocks and an instance of WifiConfigManager before each test. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - // static mocking - mSession = ExtendedMockito.mockitoSession() - .mockStatic(DeviceConfig.class, withSettings().lenient()) - .startMocking(); - // Have DeviceConfig return the default value passed in. - when(DeviceConfig.getBoolean(anyString(), anyString(), anyBoolean())) - .then(new AnswerWithArguments() { - public boolean answer(String namespace, String field, boolean def) { - return def; - } - }); - when(DeviceConfig.getInt(anyString(), anyString(), anyInt())) - .then(new AnswerWithArguments() { - public int answer(String namespace, String field, int def) { - return def; - } - }); - when(DeviceConfig.getLong(anyString(), anyString(), anyLong())) - .then(new AnswerWithArguments() { - public long answer(String namespace, String field, long def) { - return def; - } - }); - when(DeviceConfig.getString(anyString(), anyString(), anyString())) - .then(new AnswerWithArguments() { - public String answer(String namespace, String field, String def) { - return def; - } - }); - - mDeviceConfigFacade = new DeviceConfigFacade(mContext, new Handler(mLooper.getLooper()), - mWifiMetrics); - verify(() -> DeviceConfig.addOnPropertiesChangedListener(anyString(), any(), - mOnPropertiesChangedListenerCaptor.capture())); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - mSession.finishMocking(); - } - - /** - * Verifies that default values are set correctly - */ - @Test - public void testDefaultValue() throws Exception { - assertEquals(false, mDeviceConfigFacade.isAbnormalConnectionBugreportEnabled()); - assertEquals(DeviceConfigFacade.DEFAULT_ABNORMAL_CONNECTION_DURATION_MS, - mDeviceConfigFacade.getAbnormalConnectionDurationMs()); - assertEquals(DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS, - mDeviceConfigFacade.getDataStallDurationMs()); - assertEquals(DeviceConfigFacade.DEFAULT_DATA_STALL_TX_TPUT_THR_KBPS, - mDeviceConfigFacade.getDataStallTxTputThrKbps()); - assertEquals(DeviceConfigFacade.DEFAULT_DATA_STALL_RX_TPUT_THR_KBPS, - mDeviceConfigFacade.getDataStallRxTputThrKbps()); - assertEquals(DeviceConfigFacade.DEFAULT_DATA_STALL_TX_PER_THR, - mDeviceConfigFacade.getDataStallTxPerThr()); - assertEquals(DeviceConfigFacade.DEFAULT_DATA_STALL_CCA_LEVEL_THR, - mDeviceConfigFacade.getDataStallCcaLevelThr()); - assertEquals(DeviceConfigFacade.DEFAULT_TX_TPUT_SUFFICIENT_THR_LOW_KBPS, - mDeviceConfigFacade.getTxTputSufficientLowThrKbps()); - assertEquals(DeviceConfigFacade.DEFAULT_TX_TPUT_SUFFICIENT_THR_HIGH_KBPS, - mDeviceConfigFacade.getTxTputSufficientHighThrKbps()); - assertEquals(DeviceConfigFacade.DEFAULT_RX_TPUT_SUFFICIENT_THR_LOW_KBPS, - mDeviceConfigFacade.getRxTputSufficientLowThrKbps()); - assertEquals(DeviceConfigFacade.DEFAULT_RX_TPUT_SUFFICIENT_THR_HIGH_KBPS, - mDeviceConfigFacade.getRxTputSufficientHighThrKbps()); - assertEquals(DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM, - mDeviceConfigFacade.getTputSufficientRatioThrNum()); - assertEquals(DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_RATIO_THR_DEN, - mDeviceConfigFacade.getTputSufficientRatioThrDen()); - assertEquals(DeviceConfigFacade.DEFAULT_TX_PACKET_PER_SECOND_THR, - mDeviceConfigFacade.getTxPktPerSecondThr()); - assertEquals(DeviceConfigFacade.DEFAULT_RX_PACKET_PER_SECOND_THR, - mDeviceConfigFacade.getRxPktPerSecondThr()); - assertEquals(DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT, - mDeviceConfigFacade.getConnectionFailureHighThrPercent()); - assertEquals(DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_COUNT_MIN, - mDeviceConfigFacade.getConnectionFailureCountMin()); - assertEquals(DeviceConfigFacade.DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT, - mDeviceConfigFacade.getAssocRejectionHighThrPercent()); - assertEquals(DeviceConfigFacade.DEFAULT_ASSOC_REJECTION_COUNT_MIN, - mDeviceConfigFacade.getAssocRejectionCountMin()); - assertEquals(DeviceConfigFacade.DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT, - mDeviceConfigFacade.getAssocTimeoutHighThrPercent()); - assertEquals(DeviceConfigFacade.DEFAULT_ASSOC_TIMEOUT_COUNT_MIN, - mDeviceConfigFacade.getAssocTimeoutCountMin()); - assertEquals(DeviceConfigFacade.DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT, - mDeviceConfigFacade.getAuthFailureHighThrPercent()); - assertEquals(DeviceConfigFacade.DEFAULT_AUTH_FAILURE_COUNT_MIN, - mDeviceConfigFacade.getAuthFailureCountMin()); - assertEquals(DeviceConfigFacade.DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT, - mDeviceConfigFacade.getShortConnectionNonlocalHighThrPercent()); - assertEquals(DeviceConfigFacade.DEFAULT_SHORT_CONNECTION_NONLOCAL_COUNT_MIN, - mDeviceConfigFacade.getShortConnectionNonlocalCountMin()); - assertEquals(DeviceConfigFacade.DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT, - mDeviceConfigFacade.getDisconnectionNonlocalHighThrPercent()); - assertEquals(DeviceConfigFacade.DEFAULT_DISCONNECTION_NONLOCAL_COUNT_MIN, - mDeviceConfigFacade.getDisconnectionNonlocalCountMin()); - assertEquals(DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR, - mDeviceConfigFacade.getHealthMonitorRatioThrNumerator()); - assertEquals(DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM, - mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()); - assertEquals(Collections.emptySet(), - mDeviceConfigFacade.getRandomizationFlakySsidHotlist()); - assertEquals(Collections.emptySet(), - mDeviceConfigFacade.getAggressiveMacRandomizationSsidAllowlist()); - assertEquals(Collections.emptySet(), - mDeviceConfigFacade.getAggressiveMacRandomizationSsidBlocklist()); - assertEquals(false, mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled()); - assertEquals(false, mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled()); - assertEquals(DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT, - mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()); - assertEquals(DeviceConfigFacade.DEFAULT_BUG_REPORT_MIN_WINDOW_MS, - mDeviceConfigFacade.getBugReportMinWindowMs()); - assertEquals(false, mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled()); - assertEquals(DeviceConfigFacade.DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS, - mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()); - assertEquals(DeviceConfigFacade.DEFAULT_TX_LINK_SPEED_LOW_THRESHOLD_MBPS, - mDeviceConfigFacade.getTxLinkSpeedLowThresholdMbps()); - assertEquals(DeviceConfigFacade.DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS, - mDeviceConfigFacade.getRxLinkSpeedLowThresholdMbps()); - assertEquals(DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_RSSI_POLL_VALID_TIME_MS, - mDeviceConfigFacade.getHealthMonitorRssiPollValidTimeMs()); - assertEquals(DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_SHORT_CONNECTION_DURATION_THR_MS, - mDeviceConfigFacade.getHealthMonitorShortConnectionDurationThrMs()); - assertEquals(DeviceConfigFacade.DEFAULT_ABNORMAL_DISCONNECTION_REASON_CODE_MASK, - mDeviceConfigFacade.getAbnormalDisconnectionReasonCodeMask()); - assertEquals(DeviceConfigFacade.DEFAULT_NONSTATIONARY_SCAN_RSSI_VALID_TIME_MS, - mDeviceConfigFacade.getNonstationaryScanRssiValidTimeMs()); - assertEquals(DeviceConfigFacade.DEFAULT_STATIONARY_SCAN_RSSI_VALID_TIME_MS, - mDeviceConfigFacade.getStationaryScanRssiValidTimeMs()); - assertEquals(DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS, - mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()); - assertEquals(DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS, - mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()); - assertEquals(DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS, - mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()); - assertEquals(DeviceConfigFacade.DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM, - mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm()); - } - - /** - * Verifies that all fields are updated properly. - */ - @Test - public void testFieldUpdates() throws Exception { - // Simulate updating the fields - when(DeviceConfig.getBoolean(anyString(), eq("abnormal_connection_bugreport_enabled"), - anyBoolean())).thenReturn(true); - when(DeviceConfig.getInt(anyString(), eq("abnormal_connection_duration_ms"), - anyInt())).thenReturn(100); - when(DeviceConfig.getInt(anyString(), eq("data_stall_duration_ms"), - anyInt())).thenReturn(0); - when(DeviceConfig.getInt(anyString(), eq("data_stall_tx_tput_thr_kbps"), - anyInt())).thenReturn(1000); - when(DeviceConfig.getInt(anyString(), eq("data_stall_rx_tput_thr_kbps"), - anyInt())).thenReturn(1500); - when(DeviceConfig.getInt(anyString(), eq("data_stall_tx_per_thr"), - anyInt())).thenReturn(95); - when(DeviceConfig.getInt(anyString(), eq("data_stall_cca_level_thr"), - anyInt())).thenReturn(80); - when(DeviceConfig.getInt(anyString(), eq("tput_sufficient_low_thr_kbps"), - anyInt())).thenReturn(4000); - when(DeviceConfig.getInt(anyString(), eq("tput_sufficient_high_thr_kbps"), - anyInt())).thenReturn(8000); - when(DeviceConfig.getInt(anyString(), eq("rx_tput_sufficient_low_thr_kbps"), - anyInt())).thenReturn(5000); - when(DeviceConfig.getInt(anyString(), eq("rx_tput_sufficient_high_thr_kbps"), - anyInt())).thenReturn(9000); - when(DeviceConfig.getInt(anyString(), eq("tput_sufficient_ratio_thr_num"), - anyInt())).thenReturn(3); - when(DeviceConfig.getInt(anyString(), eq("tput_sufficient_ratio_thr_den"), - anyInt())).thenReturn(2); - when(DeviceConfig.getInt(anyString(), eq("tx_pkt_per_second_thr"), - anyInt())).thenReturn(10); - when(DeviceConfig.getInt(anyString(), eq("rx_pkt_per_second_thr"), - anyInt())).thenReturn(5); - when(DeviceConfig.getInt(anyString(), eq("connection_failure_high_thr_percent"), - anyInt())).thenReturn(31); - when(DeviceConfig.getInt(anyString(), eq("connection_failure_count_min"), - anyInt())).thenReturn(4); - when(DeviceConfig.getInt(anyString(), eq("assoc_rejection_high_thr_percent"), - anyInt())).thenReturn(10); - when(DeviceConfig.getInt(anyString(), eq("assoc_rejection_count_min"), - anyInt())).thenReturn(5); - when(DeviceConfig.getInt(anyString(), eq("assoc_timeout_high_thr_percent"), - anyInt())).thenReturn(12); - when(DeviceConfig.getInt(anyString(), eq("assoc_timeout_count_min"), - anyInt())).thenReturn(6); - when(DeviceConfig.getInt(anyString(), eq("auth_failure_high_thr_percent"), - anyInt())).thenReturn(11); - when(DeviceConfig.getInt(anyString(), eq("auth_failure_count_min"), - anyInt())).thenReturn(7); - when(DeviceConfig.getInt(anyString(), eq("short_connection_nonlocal_high_thr_percent"), - anyInt())).thenReturn(8); - when(DeviceConfig.getInt(anyString(), eq("short_connection_nonlocal_count_min"), - anyInt())).thenReturn(8); - when(DeviceConfig.getInt(anyString(), eq("disconnection_nonlocal_high_thr_percent"), - anyInt())).thenReturn(12); - when(DeviceConfig.getInt(anyString(), eq("disconnection_nonlocal_count_min"), - anyInt())).thenReturn(9); - when(DeviceConfig.getInt(anyString(), eq("health_monitor_ratio_thr_numerator"), - anyInt())).thenReturn(3); - when(DeviceConfig.getInt(anyString(), eq("health_monitor_min_rssi_thr_dbm"), - anyInt())).thenReturn(-67); - String testSsidList = "ssid_1,ssid_2"; - when(DeviceConfig.getString(anyString(), eq("randomization_flaky_ssid_hotlist"), - anyString())).thenReturn(testSsidList); - when(DeviceConfig.getString(anyString(), eq("aggressive_randomization_ssid_allowlist"), - anyString())).thenReturn(testSsidList); - when(DeviceConfig.getString(anyString(), eq("aggressive_randomization_ssid_blocklist"), - anyString())).thenReturn(testSsidList); - when(DeviceConfig.getBoolean(anyString(), - eq("abnormal_connection_failure_bugreport_enabled"), - anyBoolean())).thenReturn(true); - when(DeviceConfig.getBoolean(anyString(), eq("abnormal_disconnection_bugreport_enabled"), - anyBoolean())).thenReturn(true); - when(DeviceConfig.getInt(anyString(), eq("health_monitor_min_num_connection_attempt"), - anyInt())).thenReturn(20); - when(DeviceConfig.getInt(anyString(), eq("bug_report_min_window_ms"), - anyInt())).thenReturn(1000); - when(DeviceConfig.getBoolean(anyString(), eq("overlapping_connection_bugreport_enabled"), - anyBoolean())).thenReturn(true); - when(DeviceConfig.getInt(anyString(), eq("overlapping_connection_duration_threshold_ms"), - anyInt())).thenReturn(50000); - when(DeviceConfig.getInt(anyString(), eq("tx_link_speed_low_threshold_mbps"), - anyInt())).thenReturn(9); - when(DeviceConfig.getInt(anyString(), eq("rx_link_speed_low_threshold_mbps"), - anyInt())).thenReturn(10); - when(DeviceConfig.getInt(anyString(), eq("health_monitor_short_connection_duration_thr_ms"), - anyInt())).thenReturn(30_000); - when(DeviceConfig.getLong(anyString(), eq("abnormal_disconnection_reason_code_mask"), - anyLong())).thenReturn(0xffff_fff3_0000_ffffL); - when(DeviceConfig.getInt(anyString(), eq("health_monitor_rssi_poll_valid_time_ms"), - anyInt())).thenReturn(2000); - when(DeviceConfig.getInt(anyString(), eq("nonstationary_scan_rssi_valid_time_ms"), - anyInt())).thenReturn(4000); - when(DeviceConfig.getInt(anyString(), eq("stationary_scan_rssi_valid_time_ms"), - anyInt())).thenReturn(3000); - when(DeviceConfig.getInt(anyString(), eq("health_monitor_fw_alert_valid_time_ms"), - anyInt())).thenReturn(1000); - when(DeviceConfig.getInt(anyString(), eq("min_confirmation_duration_send_low_score_ms"), - anyInt())).thenReturn(4000); - when(DeviceConfig.getInt(anyString(), eq("min_confirmation_duration_send_high_score_ms"), - anyInt())).thenReturn(1000); - when(DeviceConfig.getInt(anyString(), eq("rssi_threshold_not_send_low_score_to_cs_dbm"), - anyInt())).thenReturn(-70); - mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); - - // Verifying fields are updated to the new values - Set<String> testSsidSet = new ArraySet<>(); - testSsidSet.add("\"ssid_1\""); - testSsidSet.add("\"ssid_2\""); - assertEquals(true, mDeviceConfigFacade.isAbnormalConnectionBugreportEnabled()); - assertEquals(100, mDeviceConfigFacade.getAbnormalConnectionDurationMs()); - assertEquals(0, mDeviceConfigFacade.getDataStallDurationMs()); - assertEquals(1000, mDeviceConfigFacade.getDataStallTxTputThrKbps()); - assertEquals(1500, mDeviceConfigFacade.getDataStallRxTputThrKbps()); - assertEquals(95, mDeviceConfigFacade.getDataStallTxPerThr()); - assertEquals(80, mDeviceConfigFacade.getDataStallCcaLevelThr()); - assertEquals(4000, mDeviceConfigFacade.getTxTputSufficientLowThrKbps()); - assertEquals(8000, mDeviceConfigFacade.getTxTputSufficientHighThrKbps()); - assertEquals(5000, mDeviceConfigFacade.getRxTputSufficientLowThrKbps()); - assertEquals(9000, mDeviceConfigFacade.getRxTputSufficientHighThrKbps()); - assertEquals(3, mDeviceConfigFacade.getTputSufficientRatioThrNum()); - assertEquals(2, mDeviceConfigFacade.getTputSufficientRatioThrDen()); - assertEquals(10, mDeviceConfigFacade.getTxPktPerSecondThr()); - assertEquals(5, mDeviceConfigFacade.getRxPktPerSecondThr()); - assertEquals(31, mDeviceConfigFacade.getConnectionFailureHighThrPercent()); - assertEquals(4, mDeviceConfigFacade.getConnectionFailureCountMin()); - assertEquals(10, mDeviceConfigFacade.getAssocRejectionHighThrPercent()); - assertEquals(5, mDeviceConfigFacade.getAssocRejectionCountMin()); - assertEquals(12, mDeviceConfigFacade.getAssocTimeoutHighThrPercent()); - assertEquals(6, mDeviceConfigFacade.getAssocTimeoutCountMin()); - assertEquals(11, mDeviceConfigFacade.getAuthFailureHighThrPercent()); - assertEquals(7, mDeviceConfigFacade.getAuthFailureCountMin()); - assertEquals(8, mDeviceConfigFacade.getShortConnectionNonlocalHighThrPercent()); - assertEquals(8, mDeviceConfigFacade.getShortConnectionNonlocalCountMin()); - assertEquals(12, mDeviceConfigFacade.getDisconnectionNonlocalHighThrPercent()); - assertEquals(9, mDeviceConfigFacade.getDisconnectionNonlocalCountMin()); - assertEquals(3, mDeviceConfigFacade.getHealthMonitorRatioThrNumerator()); - assertEquals(-67, mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()); - assertEquals(testSsidSet, mDeviceConfigFacade.getRandomizationFlakySsidHotlist()); - assertEquals(testSsidSet, - mDeviceConfigFacade.getAggressiveMacRandomizationSsidAllowlist()); - assertEquals(testSsidSet, - mDeviceConfigFacade.getAggressiveMacRandomizationSsidBlocklist()); - assertEquals(true, mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled()); - assertEquals(true, mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled()); - assertEquals(20, mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()); - assertEquals(1000, mDeviceConfigFacade.getBugReportMinWindowMs()); - assertEquals(true, mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled()); - assertEquals(50000, mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()); - assertEquals(9, mDeviceConfigFacade.getTxLinkSpeedLowThresholdMbps()); - assertEquals(10, mDeviceConfigFacade.getRxLinkSpeedLowThresholdMbps()); - assertEquals(30_000, - mDeviceConfigFacade.getHealthMonitorShortConnectionDurationThrMs()); - assertEquals(0xffff_fff3_0000_ffffL, - mDeviceConfigFacade.getAbnormalDisconnectionReasonCodeMask()); - assertEquals(2000, mDeviceConfigFacade.getHealthMonitorRssiPollValidTimeMs()); - assertEquals(4000, mDeviceConfigFacade.getNonstationaryScanRssiValidTimeMs()); - assertEquals(3000, mDeviceConfigFacade.getStationaryScanRssiValidTimeMs()); - assertEquals(1000, mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()); - assertEquals(4000, mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()); - assertEquals(1000, mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()); - assertEquals(-70, mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/DppManagerTest.java b/tests/wifitests/src/com/android/server/wifi/DppManagerTest.java deleted file mode 100644 index e274d680f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/DppManagerTest.java +++ /dev/null @@ -1,928 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import static android.hardware.wifi.supplicant.V1_2.DppAkm.PSK; -import static android.hardware.wifi.supplicant.V1_2.DppAkm.SAE; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.AUTHENTICATION; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.BUSY; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.CANNOT_FIND_NETWORK; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.CONFIGURATION; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.CONFIGURATION_REJECTED; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.ENROLLEE_AUTHENTICATION; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.FAILURE; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.NOT_COMPATIBLE; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.NOT_SUPPORTED; -import static android.hardware.wifi.supplicant.V1_3.DppFailureCode.TIMEOUT; -import static android.hardware.wifi.supplicant.V1_3.DppProgressCode.AUTHENTICATION_SUCCESS; -import static android.hardware.wifi.supplicant.V1_3.DppProgressCode.CONFIGURATION_ACCEPTED; -import static android.hardware.wifi.supplicant.V1_3.DppProgressCode.CONFIGURATION_SENT_WAITING_RESPONSE; -import static android.hardware.wifi.supplicant.V1_3.DppProgressCode.RESPONSE_PENDING; -import static android.hardware.wifi.supplicant.V1_3.DppSuccessCode.CONFIGURATION_APPLIED; -import static android.hardware.wifi.supplicant.V1_3.DppSuccessCode.CONFIGURATION_SENT; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT; -import static android.net.wifi.WifiManager.EASY_CONNECT_NETWORK_ROLE_STA; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.wifi.EasyConnectStatusCallback; -import android.net.wifi.IDppCallback; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.IBinder; -import android.os.test.TestLooper; -import android.test.suitebuilder.annotation.SmallTest; - -import com.android.internal.util.WakeupMessage; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for {@link DppManager}. - */ -@SmallTest -public class DppManagerTest extends WifiBaseTest { - private static final String TAG = "DppManagerTest"; - private static final String TEST_INTERFACE_NAME = "testif0"; - private static final int TEST_PEER_ID = 1; - private static final String TEST_SSID = "\"Test_SSID\""; - private static final String TEST_SSID_NO_QUOTE = TEST_SSID.replace("\"", ""); - private static final String TEST_SSID_ENCODED = "546573745f53534944"; - private static final String TEST_PASSWORD = "\"secretPassword\""; - private static final String TEST_PASSWORD_ENCODED = "73656372657450617373776f7264"; - private static final int TEST_NETWORK_ID = 1; - private static final String TEST_BSSID = "01:02:03:04:05:06"; - - TestLooper mLooper; - - DppManager mDppManager; - - @Mock - Context mContext; - @Mock - WifiMetrics mWifiMetrics; - @Mock - WifiNative mWifiNative; - @Mock - WifiConfigManager mWifiConfigManager; - @Mock - IBinder mBinder; - @Mock - IDppCallback mDppCallback; - @Mock - IDppCallback mDppCallbackConcurrent; - @Mock - WakeupMessage mWakeupMessage; - @Mock - DppMetrics mDppMetrics; - @Mock - ScanRequestProxy mScanRequestProxy; - - String mUri = - "DPP:C:81/1;I:DPP_TESTER;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADebGHMJoCcE7OZP/aek5muaJo" - + "zGy2FVKPRjA/I/qyC8Q=;;"; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - mDppManager = createDppManager(); - mLooper.dispatchAll(); - - // Add Peer URI successful, return peer ID 1 - when(mWifiNative.addDppPeerUri(anyString(), anyString())) - .thenReturn(1); - when(mWifiNative.removeDppUri(anyString(), anyInt())) - .thenReturn(true); - - // Return test interface name - when(mWifiNative.getClientInterfaceName()).thenReturn(TEST_INTERFACE_NAME); - - // Successfully start enrollee - when(mWifiNative.startDppEnrolleeInitiator(anyString(), anyInt(), anyInt())).thenReturn( - true); - - // Successfully start configurator - when(mWifiNative.startDppConfiguratorInitiator(anyString(), anyInt(), anyInt(), anyString(), - any(), any(), anyInt(), anyInt())).thenReturn(true); - } - - private DppManager createDppManager() { - DppManager dppManger = new DppManager(new Handler(mLooper.getLooper()), mWifiNative, - mWifiConfigManager, mContext, mDppMetrics, mScanRequestProxy); - dppManger.mDppTimeoutMessage = mWakeupMessage; - dppManger.enableVerboseLogging(1); - return dppManger; - } - - /** - * DPP Tests - */ - @Test - public void testStartDppAsConfiguratorInitiatorWithBadNetworkId() throws Exception { - // Return NULL when for the selected network (invalid network) - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(null); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallback); - verify(mDppCallback).onFailure( - eq(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK)); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsConfiguratorInitiatorFailAddPeer() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = "\"Test_SSID\""; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.preSharedKey = "\"secretPassword\""; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - // Fail to add Peer URI - when(mWifiNative.addDppPeerUri(anyString(), anyString())).thenReturn(-1); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallback); - verify(mDppCallback).onFailure( - eq(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_INVALID_URI)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsEnrolleeInitiatorFailAddPeer() throws Exception { - // Fail to add Peer URI - when(mWifiNative.addDppPeerUri(anyString(), anyString())).thenReturn(-1); - - mDppManager.startDppAsEnrolleeInitiator(0, mBinder, mUri, mDppCallback); - verify(mDppCallback).onFailure( - eq(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppEnrolleeInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_INVALID_URI)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsConfiguratorInitiatorFailStart() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = "\"Test_SSID\""; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.preSharedKey = "\"secretPassword\""; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - // Fail to start - when(mWifiNative.startDppConfiguratorInitiator(anyString(), anyInt(), anyInt(), anyString(), - any(), any(), anyInt(), anyInt())).thenReturn(false); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallback); - verify(mDppCallback).onFailure(eq(EASY_CONNECT_EVENT_FAILURE_GENERIC), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EASY_CONNECT_EVENT_FAILURE_GENERIC)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsEnrolleeInitiatorFailStart() throws Exception { - // Fail to start - when(mWifiNative.startDppEnrolleeInitiator(anyString(), anyInt(), anyInt())).thenReturn( - false); - - mDppManager.startDppAsEnrolleeInitiator(0, mBinder, mUri, mDppCallback); - verify(mDppCallback).onFailure(eq(EASY_CONNECT_EVENT_FAILURE_GENERIC), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppEnrolleeInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EASY_CONNECT_EVENT_FAILURE_GENERIC)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsConfiguratorInitiatorStartCorrectlyWpa2Psk() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.preSharedKey = TEST_PASSWORD; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallback); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppConfiguratorInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt(), eq(TEST_SSID_ENCODED), eq(TEST_PASSWORD_ENCODED), any(), - eq(EASY_CONNECT_NETWORK_ROLE_STA), eq(PSK)); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsConfiguratorInitiatorStartCorrectlyWpa3Sae() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.preSharedKey = TEST_PASSWORD; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallback); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppConfiguratorInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt(), eq(TEST_SSID_ENCODED), eq(TEST_PASSWORD_ENCODED), any(), - eq(EASY_CONNECT_NETWORK_ROLE_STA), eq(SAE)); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsConfiguratorInitiatorFailOpenNetwork() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallback); - verify(mDppCallback).onFailure(eq(EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK)); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsConfiguratorInitiatorFailEapNetwork() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallback); - verify(mDppCallback).onFailure(eq(EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK)); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsEnrolleeInitiatorStartCorrectly() throws Exception { - mDppManager.startDppAsEnrolleeInitiator(0, mBinder, mUri, mDppCallback); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppEnrolleeInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt()); - verify(mDppMetrics).updateDppEnrolleeInitiatorRequests(); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsConfiguratorInitiatorStartCorrectlyAndRejectConcurrentRequest() - throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = 1; - selectedNetwork.preSharedKey = TEST_PASSWORD; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, mDppCallback); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppConfiguratorInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt(), eq(TEST_SSID_ENCODED), eq(TEST_PASSWORD_ENCODED), any(), - eq(EASY_CONNECT_NETWORK_ROLE_STA), eq(SAE)); - - mDppManager.startDppAsConfiguratorInitiator(1, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallbackConcurrent); - verify(mDppCallbackConcurrent).onFailure(eq(EASY_CONNECT_EVENT_FAILURE_BUSY), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallbackConcurrent, never()).onSuccess(anyInt()); - verify(mDppCallbackConcurrent, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics, times(2)).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EASY_CONNECT_EVENT_FAILURE_BUSY)); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsEnrolleeInitiatorStartCorrectlyAndRejectConcurrentRequest() - throws Exception { - mDppManager.startDppAsEnrolleeInitiator(0, mBinder, mUri, mDppCallback); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppEnrolleeInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt()); - - mDppManager.startDppAsEnrolleeInitiator(1, mBinder, mUri, mDppCallbackConcurrent); - verify(mDppCallbackConcurrent).onFailure(eq(EASY_CONNECT_EVENT_FAILURE_BUSY), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallbackConcurrent, never()).onSuccess(anyInt()); - verify(mDppCallbackConcurrent, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics, times(2)).updateDppEnrolleeInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EASY_CONNECT_EVENT_FAILURE_BUSY)); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsConfiguratorInitiatorStartOnSuccessCallback() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = 1; - selectedNetwork.preSharedKey = TEST_PASSWORD; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - ArgumentCaptor<WifiNative.DppEventCallback> dppEventCallbackCaptor = - ArgumentCaptor.forClass( - WifiNative.DppEventCallback.class); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, mDppCallback); - verify(mWifiNative).registerDppEventCallback(dppEventCallbackCaptor.capture()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppConfiguratorInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt(), eq(TEST_SSID_ENCODED), eq(TEST_PASSWORD_ENCODED), any(), - eq(EASY_CONNECT_NETWORK_ROLE_STA), eq( - SAE)); - - WifiNative.DppEventCallback dppEventCallback = dppEventCallbackCaptor.getValue(); - - // Generate a progress event - dppEventCallback.onProgress(AUTHENTICATION_SUCCESS); - mLooper.dispatchAll(); - verify(mDppCallback).onProgress(eq(EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS)); - - // Generate an onSuccess callback - dppEventCallback.onSuccess(CONFIGURATION_SENT); - mLooper.dispatchAll(); - verify(mDppCallback).onSuccess(eq(EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT)); - verify(mDppMetrics, times(1)).updateDppR1CapableEnrolleeResponderDevices(); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppConfiguratorSuccess(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - } - - @Test - public void testStartDppAsEnrolleeInitiatorStartCorrectlyOnSuccessCallback() throws Exception { - ArgumentCaptor<WifiNative.DppEventCallback> dppEventCallbackCaptor = - ArgumentCaptor.forClass( - WifiNative.DppEventCallback.class); - - mDppManager.startDppAsEnrolleeInitiator(0, mBinder, mUri, mDppCallback); - verify(mWifiNative).registerDppEventCallback(dppEventCallbackCaptor.capture()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppEnrolleeInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt()); - - // Generate an onSuccessConfigReceived callback - WifiNative.DppEventCallback dppEventCallback = dppEventCallbackCaptor.getValue(); - - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.preSharedKey = TEST_PASSWORD; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - - // Generate a progress event - dppEventCallback.onProgress(AUTHENTICATION_SUCCESS); - mLooper.dispatchAll(); - verify(mDppCallback).onProgress(eq(EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS)); - - // Generate result - NetworkUpdateResult networkUpdateResult = new NetworkUpdateResult(TEST_NETWORK_ID); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), - anyInt())).thenReturn(networkUpdateResult); - - dppEventCallback.onSuccessConfigReceived(selectedNetwork); - mLooper.dispatchAll(); - verify(mDppCallback).onSuccessConfigReceived(eq(TEST_NETWORK_ID)); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppMetrics).updateDppEnrolleeInitiatorRequests(); - verify(mDppMetrics).updateDppEnrolleeSuccess(); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - verifyCleanUpResources(); - } - - @Test - public void testStartDppAsConfiguratorInitiatorStartOnFailureCallback() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.preSharedKey = TEST_PASSWORD; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - ArgumentCaptor<WifiNative.DppEventCallback> dppEventCallbackCaptor = - ArgumentCaptor.forClass( - WifiNative.DppEventCallback.class); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, - mDppCallback); - verify(mWifiNative).registerDppEventCallback(dppEventCallbackCaptor.capture()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppConfiguratorInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt(), eq(TEST_SSID_ENCODED), eq(TEST_PASSWORD_ENCODED), any(), - eq(EASY_CONNECT_NETWORK_ROLE_STA), eq( - SAE)); - - WifiNative.DppEventCallback dppEventCallback = dppEventCallbackCaptor.getValue(); - - // Generate a progress event - dppEventCallback.onProgress(RESPONSE_PENDING); - mLooper.dispatchAll(); - verify(mDppCallback).onProgress(eq(EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING)); - - // Generate an onFailure callback - dppEventCallback.onFailure(AUTHENTICATION, null, null, null); - mLooper.dispatchAll(); - verify(mDppCallback).onFailure(eq(EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - verifyCleanUpResources(); - } - - @Test - public void testStartDppAsEnrolleeInitiatorStartCorrectlyOnFailureCallback() throws Exception { - // Add Peer URI successful, return peer ID 1 - when(mWifiNative.addDppPeerUri(anyString(), anyString())) - .thenReturn(1); - when(mWifiNative.removeDppUri(anyString(), anyInt())) - .thenReturn(true); - - // Return test interface name - when(mWifiNative.getClientInterfaceName()).thenReturn(TEST_INTERFACE_NAME); - - // Successful start - when(mWifiNative.startDppEnrolleeInitiator(anyString(), anyInt(), anyInt())).thenReturn( - true); - - ArgumentCaptor<WifiNative.DppEventCallback> dppEventCallbackCaptor = - ArgumentCaptor.forClass( - WifiNative.DppEventCallback.class); - - mDppManager.startDppAsEnrolleeInitiator(0, mBinder, mUri, mDppCallback); - verify(mWifiNative).registerDppEventCallback(dppEventCallbackCaptor.capture()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppEnrolleeInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt()); - - WifiNative.DppEventCallback dppEventCallback = dppEventCallbackCaptor.getValue(); - - // Generate a progress event - dppEventCallback.onProgress(RESPONSE_PENDING); - mLooper.dispatchAll(); - verify(mDppCallback).onProgress(eq(EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING)); - - // Generate an onFailure callback - dppEventCallback.onFailure(AUTHENTICATION, null, null, null); - mLooper.dispatchAll(); - verify(mDppCallback).onFailure(eq(EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION), eq(null), - eq(null), eq(new int[0])); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppEnrolleeInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - verifyCleanUpResources(); - } - - @Test - public void testDppStopSessionNotStarted() throws Exception { - // Check that nothing happens if no DPP session started. - mDppManager.stopDppSession(0); - - // Check that nothing is removed or canceled - mDppManager.stopDppSession(0); - verify(mWifiNative, never()).removeDppUri(eq(TEST_INTERFACE_NAME), anyInt()); - verify(mWakeupMessage, never()).cancel(); - } - - @Test - public void testDppStopSessionIncorrectUid() throws Exception { - // Check that nothing happens if UID is incorrect - // Add Peer URI successful, return peer ID 1 - when(mWifiNative.addDppPeerUri(anyString(), anyString())) - .thenReturn(1); - when(mWifiNative.removeDppUri(anyString(), anyInt())) - .thenReturn(true); - - // Return test interface name - when(mWifiNative.getClientInterfaceName()).thenReturn(TEST_INTERFACE_NAME); - - // Successful start - when(mWifiNative.startDppEnrolleeInitiator(anyString(), anyInt(), anyInt())).thenReturn( - true); - - ArgumentCaptor<WifiNative.DppEventCallback> dppEventCallbackCaptor = - ArgumentCaptor.forClass( - WifiNative.DppEventCallback.class); - - // Start with UID 10 - mDppManager.startDppAsEnrolleeInitiator(10, mBinder, mUri, mDppCallback); - verify(mWifiNative).registerDppEventCallback(dppEventCallbackCaptor.capture()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppEnrolleeInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt()); - - // Check that nothing is removed or canceled - mDppManager.stopDppSession(0); - verify(mWifiNative, never()).removeDppUri(eq(TEST_INTERFACE_NAME), anyInt()); - verify(mWakeupMessage, never()).cancel(); - } - - @Test - public void testDppStopSession() throws Exception { - // Check that nothing happens if UID is incorrect - // Add Peer URI successful, return peer ID 1 - when(mWifiNative.addDppPeerUri(anyString(), anyString())) - .thenReturn(1); - when(mWifiNative.removeDppUri(anyString(), anyInt())) - .thenReturn(true); - - // Return test interface name - when(mWifiNative.getClientInterfaceName()).thenReturn(TEST_INTERFACE_NAME); - - // Successful start - when(mWifiNative.startDppEnrolleeInitiator(anyString(), anyInt(), anyInt())).thenReturn( - true); - - ArgumentCaptor<WifiNative.DppEventCallback> dppEventCallbackCaptor = - ArgumentCaptor.forClass( - WifiNative.DppEventCallback.class); - - // Start with UID 10 - mDppManager.startDppAsEnrolleeInitiator(10, mBinder, mUri, mDppCallback); - verify(mWifiNative).registerDppEventCallback(dppEventCallbackCaptor.capture()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppEnrolleeInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt()); - - // Check that WifiNative is called to stop the DPP session - mDppManager.stopDppSession(10); - verify(mWifiNative).stopDppInitiator(eq(TEST_INTERFACE_NAME)); - verifyCleanUpResources(); - } - - private void verifyCleanUpResources() { - verify(mWifiNative).removeDppUri(eq(TEST_INTERFACE_NAME), anyInt()); - verify(mWakeupMessage).cancel(); - } - - @Test - public void testOnFailureCallbackNotCompatible() throws Exception { - testOnFailureCallback(NOT_COMPATIBLE, EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE); - } - - @Test - public void testOnFailureCallbackConfiguration() throws Exception { - testOnFailureCallback(CONFIGURATION, EASY_CONNECT_EVENT_FAILURE_CONFIGURATION); - } - - @Test - public void testOnFailureCallbackTimeout() throws Exception { - testOnFailureCallback(TIMEOUT, EASY_CONNECT_EVENT_FAILURE_TIMEOUT); - } - - @Test - public void testOnFailureCallbackNotSupported() throws Exception { - testOnFailureCallback(NOT_SUPPORTED, EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED); - } - - @Test - public void testOnFailureCallbackBusy() throws Exception { - testOnFailureCallback(BUSY, EASY_CONNECT_EVENT_FAILURE_BUSY); - } - - @Test - public void testOnFailureCallbackFailure() throws Exception { - testOnFailureCallback(FAILURE, EASY_CONNECT_EVENT_FAILURE_GENERIC); - } - - /** - * Helper function for setting up a scan result. - * - * @param frequency Network's operating channel in Mhz. - * - */ - private void addTestNetworkInScanResult(int frequency) { - String caps = "[WPA2-FT/SAE+SAE][ESS][WPS]"; - ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(TEST_SSID_NO_QUOTE), - TEST_SSID_NO_QUOTE, TEST_BSSID, 1245, 0, caps, -78, frequency, - 1025, 22, 33, 20, 0, 0, true); - List<ScanResult> scanResults = new ArrayList<>(); - scanResults.add(scanResult); - when(mScanRequestProxy.getScanResults()).thenReturn(scanResults); - } - - @Test - public void testOnFailureCallbackCannotFindNetworkNoErrCodeChangeOnChannelMatch() - throws Exception { - int[] bandList = new int[]{81, 83, 84, 115}; - addTestNetworkInScanResult(2437); //channel number 6 - // Include Network channel(6) in Enrollee scanned channels. - testOnFailureCallback(CANNOT_FIND_NETWORK, TEST_SSID_NO_QUOTE, - "81/1,2,3,4,5,6,7,8,9,10,11,115/48", - bandList, EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK); - } - - @Test - public void testOnFailureCallbackCannotFindNetworkErrCodeIsUpdatedOnChannelMismatch() - throws Exception { - int[] bandList = new int[]{81, 83, 84, 115}; - addTestNetworkInScanResult(5180); //channel number 36 - // Don't include Network channel(36) in Enrollee scanned channels. - testOnFailureCallback(CANNOT_FIND_NETWORK, TEST_SSID_NO_QUOTE, - "81/1,2,3,4,5,6,7,8,9,10,11,115/48", - bandList, EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE); - } - - @Test - public void testOnFailureCallbackCannotFindNetworkNoErrCodeChangeOnInvalidScannedChannelList() - throws Exception { - int[] bandList = new int[]{81, 83, 84}; - addTestNetworkInScanResult(5180); //channel number 36 - // Send Invalid operating class/channel list - testOnFailureCallback(CANNOT_FIND_NETWORK, TEST_SSID_NO_QUOTE, - "1035/1,2,3,4,5,6,7,8,9,10,11,25/45", - bandList, EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK); - } - - @Test - public void testOnFailureCallbackCannotFindNetwork() throws Exception { - int[] bandList = new int[]{1, 6, 11}; - testOnFailureCallback(CANNOT_FIND_NETWORK, TEST_SSID_NO_QUOTE, "1, 3, 6, 8, 11", - bandList, EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK); - } - - @Test - public void testOnFailureCallbackConfigurationRejected() throws Exception { - testOnFailureCallback(CONFIGURATION_REJECTED, - EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION); - } - - @Test - public void testOnFailureCallbackEnrolleeAuthentication() throws Exception { - int[] bandList = new int[]{1, 6, 11}; - testOnFailureCallback(ENROLLEE_AUTHENTICATION, new String(TEST_SSID_NO_QUOTE), null, - bandList, EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION); - } - - @Test - public void testStartDppAsConfiguratorInitiatorStartOnSuccessCallbackR2() throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = 1; - selectedNetwork.preSharedKey = TEST_PASSWORD; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - - ArgumentCaptor<WifiNative.DppEventCallback> dppEventCallbackCaptor = - ArgumentCaptor.forClass( - WifiNative.DppEventCallback.class); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, mDppCallback); - verify(mWifiNative).registerDppEventCallback(dppEventCallbackCaptor.capture()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppConfiguratorInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt(), eq(TEST_SSID_ENCODED), eq(TEST_PASSWORD_ENCODED), any(), - eq(EASY_CONNECT_NETWORK_ROLE_STA), eq( - SAE)); - - WifiNative.DppEventCallback dppEventCallback = dppEventCallbackCaptor.getValue(); - - // Generate a progress events - dppEventCallback.onProgress(AUTHENTICATION_SUCCESS); - mLooper.dispatchAll(); - verify(mDppCallback).onProgress(eq(EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS)); - - dppEventCallback.onProgress(CONFIGURATION_ACCEPTED); - mLooper.dispatchAll(); - verify(mDppCallback).onProgress(eq(EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED)); - - dppEventCallback.onProgress(CONFIGURATION_SENT_WAITING_RESPONSE); - mLooper.dispatchAll(); - verify(mDppCallback) - .onProgress(eq(EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE)); - verify(mDppMetrics, times(1)).updateDppR2CapableEnrolleeResponderDevices(); - - // Generate an onSuccess callback - dppEventCallback.onSuccess(CONFIGURATION_APPLIED); - mLooper.dispatchAll(); - verify(mDppCallback).onSuccess(eq(EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED)); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppConfiguratorSuccess(eq(EasyConnectStatusCallback - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - verifyNoMoreInteractions(mDppMetrics); - } - - private void testOnFailureCallback(int internalFailure, String ssid, String channelList, - int[] bandList, int appFailure) throws Exception { - // Generate a mock WifiConfiguration object - WifiConfiguration selectedNetwork = new WifiConfiguration(); - selectedNetwork.SSID = TEST_SSID; - selectedNetwork.networkId = TEST_NETWORK_ID; - selectedNetwork.preSharedKey = TEST_PASSWORD; - selectedNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - - when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn( - selectedNetwork); - ArgumentCaptor<WifiNative.DppEventCallback> dppEventCallbackCaptor = - ArgumentCaptor.forClass( - WifiNative.DppEventCallback.class); - - mDppManager.startDppAsConfiguratorInitiator(0, mBinder, mUri, 1, - EASY_CONNECT_NETWORK_ROLE_STA, mDppCallback); - verify(mWifiNative).registerDppEventCallback(dppEventCallbackCaptor.capture()); - verify(mDppCallback, never()).onFailure(anyInt(), anyString(), anyString(), any()); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mWifiNative).startDppConfiguratorInitiator(eq(TEST_INTERFACE_NAME), - eq(TEST_PEER_ID), anyInt(), eq(TEST_SSID_ENCODED), eq(TEST_PASSWORD_ENCODED), any(), - eq(EASY_CONNECT_NETWORK_ROLE_STA), eq(SAE)); - - WifiNative.DppEventCallback dppEventCallback = dppEventCallbackCaptor.getValue(); - - // Generate an onFailure callback - dppEventCallback.onFailure(internalFailure, ssid, channelList, bandList); - mLooper.dispatchAll(); - verify(mDppCallback).onFailure(eq(appFailure), eq(ssid), eq(channelList), - eq(bandList)); - verify(mDppCallback, never()).onSuccess(anyInt()); - verify(mDppCallback, never()).onSuccessConfigReceived(anyInt()); - verify(mDppMetrics).updateDppConfiguratorInitiatorRequests(); - verify(mDppMetrics).updateDppFailure(eq(appFailure)); - verify(mDppMetrics).updateDppOperationTime(anyInt()); - if ((internalFailure == CANNOT_FIND_NETWORK) - && (appFailure == EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE)) { - verify(mDppMetrics, times(1)).updateDppR2EnrolleeResponderIncompatibleConfiguration(); - } - verifyNoMoreInteractions(mDppMetrics); - verifyCleanUpResources(); - } - - private void testOnFailureCallback(int internalFailure, int appFailure) throws Exception { - testOnFailureCallback(internalFailure, null, null, new int[0], appFailure); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/DppMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/DppMetricsTest.java deleted file mode 100644 index e43da8f06..000000000 --- a/tests/wifitests/src/com/android/server/wifi/DppMetricsTest.java +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED; -import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT; - -import static com.android.server.wifi.DppMetrics.DPP_OPERATION_TIME; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import android.test.suitebuilder.annotation.SmallTest; - -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HistogramBucketInt32; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.util.Random; - -/** - * Unit tests for {@link com.android.server.wifi.DppMetrics}. - */ -@SmallTest -public class DppMetricsTest extends WifiBaseTest { - private static final int MAX_ITERATIONS = 30; - - private DppMetrics mDppMetrics = new DppMetrics(); - - @Before - public void setUp() throws Exception { - mDppMetrics.clear(); - } - - @After - public void cleanUp() { - mDppMetrics.clear(); - } - - /** - * Helper function that matches histogram buckets to an expected value - * - * @param index Bucket index - * @param value Expected value - */ - private void checkOperationBucketEqualsTo(int index, int value) { - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - HistogramBucketInt32 hb = mWifiDppLogProto.dppOperationTime[index]; - assertEquals(hb.count, value); - } - - /** - * Helper function that returns a number to be used to call a counter update method - * - * @param max Upper limit for the random number - * @return returns a random number between 0 and max - */ - private int getNumOfTimes(int max) { - Random random = new Random(); - return random.nextInt(max); - } - - /** - * Helper function to check DPP Failures in the histogram bucket - * - * @param key Key to verify - * @param value Expected value - */ - private void checkDppFailures(int key, int value) { - boolean found = false; - - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - - for (WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket hb : - mWifiDppLogProto.dppFailureCode) { - if (hb.dppStatusType == key) { - assertEquals(hb.count, value); - found = true; - break; - } - } - - assertTrue(found); - } - - /** - * Helper function to check DPP Successes in the histogram bucket - * - * @param key Key to verify - * @param value Expected value - */ - private void checkDppSuccesses(int key, int value) { - boolean found = false; - - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - - for (WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket hb : - mWifiDppLogProto.dppConfiguratorSuccessCode) { - if (hb.dppStatusType == key) { - assertEquals(hb.count, value); - found = true; - break; - } - } - - assertTrue(found); - } - - /** - * Test numDppConfiguratorInitiatorRequests - * - * @throws Exception - */ - @Test - public void testUpdateDppConfiguratorInitiatorRequests() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppConfiguratorInitiatorRequests(); - } - - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - assertEquals(mWifiDppLogProto.numDppConfiguratorInitiatorRequests, value); - } - - /** - * Test numDppEnrolleeInitiatorRequests - * - * @throws Exception - */ - @Test - public void testUpdateDppEnrolleeInitiatorRequests() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppEnrolleeInitiatorRequests(); - } - - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - assertEquals(mWifiDppLogProto.numDppEnrolleeInitiatorRequests, value); - } - - /** - * Test EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT - * - * @throws Exception - */ - @Test - public void testUpdateDppConfiguratorSuccess() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppConfiguratorSuccess(EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT); - } - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppConfiguratorSuccess( - EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED); - } - - // Confirm that the consolidated log has the expected value - checkDppSuccesses(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT, - value); - checkDppSuccesses(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED, value); - } - - /** - * Test numDppEnrolleeSuccess - * - * @throws Exception - */ - @Test - public void testUpdateDppEnrolleeSuccess() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppEnrolleeSuccess(); - } - - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - assertEquals(mWifiDppLogProto.numDppEnrolleeSuccess, value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_INVALID_URI - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureInvalidUri() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_INVALID_URI); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_INVALID_URI, value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureAuthentication() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION, - value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureNotCompatible() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE, - value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_CONFIGURATION - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureConfiguration() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_CONFIGURATION); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, - value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_BUSY - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureBusy() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_BUSY); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_BUSY, value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_TIMEOUT - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureTimeout() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_TIMEOUT); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_TIMEOUT, value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_GENERIC - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureGeneric() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_GENERIC); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_GENERIC, value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureNotSupported() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED, - value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureInvalidNetwork() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, - value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureCannotFindNetwork() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK, - value); - } - - /** - * Test EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureEnrolleeAuthentication() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure(EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION, value); - } - - /** - * Test - * EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION - * - * @throws Exception - */ - @Test - public void testUpdateDppFailureEnrolleeRejectedConfiguration() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppFailure( - EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION); - } - - // Confirm that the consolidated log has the expected value - checkDppFailures(WifiMetricsProto.WifiDppLog - .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION, value); - } - - /** - * Test DPP operation time histogram. Pick a single time value from each bucket by selecting - * the max value minus 1, and call the update method random amount of times with this value. - * Then confirm that the output histogram has the expected value in each target bucket. - * - * @throws Exception - */ - @Test - public void testUpdateHistogramDppOperationTime() throws Exception { - // Iterate through the histogram array - for (int i = 0; i <= DPP_OPERATION_TIME.length; i++) { - // Get a random value and call the operation time update method - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - int timeMs; - - if (i < DPP_OPERATION_TIME.length) { - timeMs = DPP_OPERATION_TIME[i] - 1; - } else { - timeMs = DPP_OPERATION_TIME[i - 1]; - } - - // Framework uses milliseconds when it gets the time, convert to milliseconds - timeMs *= 1000; - - for (int j = 0; j < value; j++) { - // Add a time value that would fall in the i'th bucket - mDppMetrics.updateDppOperationTime(timeMs); - } - - // Confirm that output matches the expected value - checkOperationBucketEqualsTo(i, value); - } - } - - /** - * Test numDppR1CapableEnrolleeResponderDevices - * - * @throws Exception - */ - @Test - public void testUpdateDppR1CapableEnrolleeResponderDevices() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppR1CapableEnrolleeResponderDevices(); - } - - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - assertEquals(mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices, value); - } - - /** - * Test numDppR2CapableEnrolleeResponderDevices - * - * @throws Exception - */ - @Test - public void testUpdateDppR2CapableEnrolleeResponderDevices() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppR2CapableEnrolleeResponderDevices(); - } - - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - assertEquals(mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices, value); - } - - /** - * Test numDppR2EnrolleeResponderIncompatibleConfiguration - * - * @throws Exception - */ - @Test - public void testUpdateDppR2EnrolleeResponderIncompatibleConfiguration() throws Exception { - // Get a random value and call the update method 'value' times - int value = getNumOfTimes(MAX_ITERATIONS) + 1; - - for (int i = 0; i < value; i++) { - mDppMetrics.updateDppR2EnrolleeResponderIncompatibleConfiguration(); - } - - // Confirm that the consolidated log has the expected value - WifiMetricsProto.WifiDppLog mWifiDppLogProto = mDppMetrics.consolidateProto(); - assertEquals(mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration, value); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java deleted file mode 100644 index 26391334c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.ActivityManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.net.wifi.WifiConfiguration; -import android.os.UserHandle; -import android.provider.Settings; -import android.service.notification.StatusBarNotification; -import android.telephony.SubscriptionManager; - -import androidx.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Answers; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; - -import java.util.Arrays; - -/** - * Unit tests for {@link com.android.server.wifi.EapFailureNotifier}. - */ -@SmallTest -public class EapFailureNotifierTest extends WifiBaseTest { - private static final String TEST_SETTINGS_PACKAGE = "android"; - - @Mock WifiContext mContext; - @Mock Resources mResources; - @Mock PackageManager mPackageManager; - @Mock NotificationManager mNotificationManager; - @Mock FrameworkFacade mFrameworkFacade; - @Mock Notification mNotification; - @Mock - WifiCarrierInfoManager mWifiCarrierInfoManager; - @Mock WifiConfiguration mWifiConfiguration; - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Notification.Builder mNotificationBuilder; - private static final int DEFINED_ERROR_CODE = 32764; - private static final int UNDEFINED_ERROR_CODE = 12345; - private static final String SSID_1 = "Carrier_AP_1"; - private static final String SSID_2 = "Carrier_AP_2"; - private static final String DEFINED_ERROR_RESOURCE_NAME = "wifi_eap_error_message_code_32764"; - private static final String UNDEFINED_ERROR_RESOURCE_NAME = "wifi_eap_error_message_code_12345"; - private MockitoSession mStaticMockSession = null; - - - EapFailureNotifier mEapFailureNotifier; - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - ResolveInfo settingsResolveInfo = new ResolveInfo(); - settingsResolveInfo.activityInfo = new ActivityInfo(); - settingsResolveInfo.activityInfo.packageName = TEST_SETTINGS_PACKAGE; - when(mPackageManager.queryIntentActivitiesAsUser( - argThat(((intent) -> intent.getAction().equals(Settings.ACTION_WIFI_SETTINGS))), - anyInt(), any())) - .thenReturn(Arrays.asList(settingsResolveInfo)); - // static mocking - mStaticMockSession = mockitoSession() - .mockStatic(SubscriptionManager.class) - .mockStatic(ActivityManager.class, withSettings().lenient()) - .startMocking(); - when(ActivityManager.getCurrentUser()).thenReturn(UserHandle.USER_SYSTEM); - when(mContext.getSystemService(NotificationManager.class)) - .thenReturn(mNotificationManager); - when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(mWifiConfiguration)).thenReturn(0); - lenient().when(SubscriptionManager.getResourcesForSubId(eq(mContext), anyInt())) - .thenReturn(mResources); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mResources.getIdentifier(eq(DEFINED_ERROR_RESOURCE_NAME), anyString(), - anyString())).thenReturn(1); - when(mResources.getIdentifier(eq(UNDEFINED_ERROR_RESOURCE_NAME), anyString(), - anyString())).thenReturn(0); - when(mResources.getString(eq(0), anyString())).thenReturn(null); - when(mResources.getString(eq(1), anyString())).thenReturn("Error Message"); - when(mContext.createPackageContext(anyString(), eq(0))).thenReturn(mContext); - when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.oem.android.wifi.resources"); - when(mContext.getWifiOverlayJavaPkgName()).thenReturn("test.com.android.wifi.resources"); - mEapFailureNotifier = - new EapFailureNotifier(mContext, mFrameworkFacade, mWifiCarrierInfoManager); - } - - @After - public void cleanUp() throws Exception { - validateMockitoUsage(); - if (mStaticMockSession != null) { - mStaticMockSession.finishMocking(); - } - } - - /** - * Verify that a eap failure notification will be generated with the following conditions : - * No eap failure notification of eap failure is displayed now. - * Error code is defined by carrier - * @throws Exception - */ - @Test - public void onEapFailureWithDefinedErroCodeWithoutNotificationShown() throws Exception { - when(mFrameworkFacade.makeNotificationBuilder(any(), - eq(WifiService.NOTIFICATION_NETWORK_ALERTS))).thenReturn(mNotificationBuilder); - StatusBarNotification[] activeNotifications = new StatusBarNotification[1]; - activeNotifications[0] = new StatusBarNotification("android", "", 56, "", 0, 0, 0, - mNotification, android.os.Process.myUserHandle(), 0); - when(mNotificationManager.getActiveNotifications()).thenReturn(activeNotifications); - mWifiConfiguration.SSID = SSID_2; - mEapFailureNotifier.onEapFailure(DEFINED_ERROR_CODE, mWifiConfiguration); - verify(mNotificationManager).notify(eq(EapFailureNotifier.NOTIFICATION_ID), any()); - ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); - verify(mFrameworkFacade).getActivity( - eq(mContext), eq(0), intent.capture(), eq(PendingIntent.FLAG_UPDATE_CURRENT)); - assertEquals(TEST_SETTINGS_PACKAGE, intent.getValue().getPackage()); - assertEquals(Settings.ACTION_WIFI_SETTINGS, intent.getValue().getAction()); - } - - /** - * Verify that a eap failure notification will be generated with the following conditions : - * Previous notification of eap failure is still displayed on the notification bar. - * Ssid of previous notification is not same as current ssid - * Error code is defined by carrier - * @throws Exception - */ - @Test - public void onEapFailureWithDefinedErroCodeWithNotificationShownWithoutSameSsid() - throws Exception { - when(mFrameworkFacade.makeNotificationBuilder(any(), - eq(WifiService.NOTIFICATION_NETWORK_ALERTS))).thenReturn(mNotificationBuilder); - StatusBarNotification[] activeNotifications = new StatusBarNotification[1]; - activeNotifications[0] = new StatusBarNotification("android", "", 57, "", 0, 0, 0, - mNotification, android.os.Process.myUserHandle(), 0); - when(mNotificationManager.getActiveNotifications()).thenReturn(activeNotifications); - mEapFailureNotifier.setCurrentShownSsid(SSID_1); - mWifiConfiguration.SSID = SSID_2; - mEapFailureNotifier.onEapFailure(DEFINED_ERROR_CODE, mWifiConfiguration); - verify(mNotificationManager).notify(eq(EapFailureNotifier.NOTIFICATION_ID), any()); - ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); - verify(mFrameworkFacade).getActivity( - eq(mContext), eq(0), intent.capture(), eq(PendingIntent.FLAG_UPDATE_CURRENT)); - assertEquals(TEST_SETTINGS_PACKAGE, intent.getValue().getPackage()); - assertEquals(Settings.ACTION_WIFI_SETTINGS, intent.getValue().getAction()); - } - - /** - * Verify that a eap failure notification will Not be generated with the following conditions : - * Previous notification of eap failure is still displayed on the notification bar. - * Ssid of previous notification is same as current ssid - * Error code is defined by carrier - * @throws Exception - */ - @Test - public void onEapFailureWithDefinedErroCodeWithNotificationShownWithSameSsid() - throws Exception { - when(mFrameworkFacade.makeNotificationBuilder(any(), - eq(WifiService.NOTIFICATION_NETWORK_ALERTS))).thenReturn(mNotificationBuilder); - StatusBarNotification[] activeNotifications = new StatusBarNotification[1]; - activeNotifications[0] = new StatusBarNotification("android", "", 57, "", 0, 0, 0, - mNotification, android.os.Process.myUserHandle(), 0); - when(mNotificationManager.getActiveNotifications()).thenReturn(activeNotifications); - mEapFailureNotifier.setCurrentShownSsid(SSID_1); - mWifiConfiguration.SSID = SSID_1; - mEapFailureNotifier.onEapFailure(DEFINED_ERROR_CODE, mWifiConfiguration); - verify(mFrameworkFacade, never()).makeNotificationBuilder(any(), - eq(WifiService.NOTIFICATION_NETWORK_ALERTS)); - } - - /** - * Verify that a eap failure notification will Not be generated with the following conditions : - * Error code is NOT defined by carrier - * @throws Exception - */ - @Test - public void onEapFailureWithUnDefinedErrorCode() throws Exception { - when(mFrameworkFacade.makeNotificationBuilder(any(), - eq(WifiService.NOTIFICATION_NETWORK_ALERTS))).thenReturn(mNotificationBuilder); - StatusBarNotification[] activeNotifications = new StatusBarNotification[1]; - activeNotifications[0] = new StatusBarNotification("android", "", 56, "", 0, 0, 0, - mNotification, android.os.Process.myUserHandle(), 0); - when(mNotificationManager.getActiveNotifications()).thenReturn(activeNotifications); - mWifiConfiguration.SSID = SSID_1; - mEapFailureNotifier.onEapFailure(UNDEFINED_ERROR_CODE, mWifiConfiguration); - verify(mFrameworkFacade, never()).makeNotificationBuilder(any(), - eq(WifiService.NOTIFICATION_NETWORK_ALERTS)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/FakeKeys.java b/tests/wifitests/src/com/android/server/wifi/FakeKeys.java deleted file mode 100644 index 5145b1345..000000000 --- a/tests/wifitests/src/com/android/server/wifi/FakeKeys.java +++ /dev/null @@ -1,657 +0,0 @@ -package com.android.server.wifi; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; - -/** - * A class containing test certificates. - */ -public class FakeKeys { - private static final String CA_CERT0_STRING = "-----BEGIN CERTIFICATE-----\n" + - "MIIDKDCCAhCgAwIBAgIJAILlFdwzLVurMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\n" + - "BAMTB0VBUCBDQTEwHhcNMTYwMTEyMTE1MDE1WhcNMjYwMTA5MTE1MDE1WjASMRAw\n" + - "DgYDVQQDEwdFQVAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" + - "znAPUz26Msae4ws43czR41/J2QtrSIZUKmVUsVumDbYHrPNvTXKSMXAcewORDQYX\n" + - "RqvHvpn8CscB1+oGXZvHwxj4zV0WKoK2zeXkau3vcyl3HIKupJfq2TEACefVjj0t\n" + - "JW+X35PGWp9/H5zIUNVNVjS7Ums84IvKhRB8512PB9UyHagXYVX5GWpAcVpyfrlR\n" + - "FI9Qdhh+Pbk0uyktdbf/CdfgHOoebrTtwRljM0oDtX+2Cv6j0wBK7hD8pPvf1+uy\n" + - "GzczigAU/4Kw7eZqydf9B+5RupR+IZipX41xEiIrKRwqi517WWzXcjaG2cNbf451\n" + - "xpH5PnV3i1tq04jMGQUzFwIDAQABo4GAMH4wHQYDVR0OBBYEFIwX4vs8BiBcScod\n" + - "5noZHRM8E4+iMEIGA1UdIwQ7MDmAFIwX4vs8BiBcScod5noZHRM8E4+ioRakFDAS\n" + - "MRAwDgYDVQQDEwdFQVAgQ0ExggkAguUV3DMtW6swDAYDVR0TBAUwAwEB/zALBgNV\n" + - "HQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAFfQqOTA7Rv7K+luQ7pnas4BYwHE\n" + - "9GEP/uohv6KOy0TGQFbrRTjFoLVNB9BZ1ymMDZ0/TIwIUc7wi7a8t5mEqYH153wW\n" + - "aWooiSjyLLhuI4sNrNCOtisdBq2r2MFXt6h0mAQYOPv8R8K7/fgSxGFqzhyNmmVL\n" + - "1qBJldx34SpwsTALQVPb4hGwJzZfr1PcpEQx6xMnTl8xEWZE3Ms99uaUxbQqIwRu\n" + - "LgAOkNCmY2m89VhzaHJ1uV85AdM/tD+Ysmlnnjt9LRCejbBipjIGjOXrg1JP+lxV\n" + - "muM4vH+P/mlmxsPPz0d65b+EGmJZpoLkO/tdNNvCYzjJpTEWpEsO6NMhKYo=\n" + - "-----END CERTIFICATE-----\n"; - public static final X509Certificate CA_CERT0 = loadCertificate(CA_CERT0_STRING); - - private static final String CA_CERT1_STRING = "-----BEGIN CERTIFICATE-----\n" + - "MIIDKDCCAhCgAwIBAgIJAOM5SzKO2pzCMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\n" + - "BAMTB0VBUCBDQTAwHhcNMTYwMTEyMDAxMDQ3WhcNMjYwMTA5MDAxMDQ3WjASMRAw\n" + - "DgYDVQQDEwdFQVAgQ0EwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" + - "89ug+IEKVQXnJGKg5g4uVHg6J/8iRUxR5k2eH5o03hrJNMfN2D+cBe/wCiZcnWbI\n" + - "GbGZACWm2nQth2wy9Zgm2LOd3b4ocrHYls3XLq6Qb5Dd7a0JKU7pdGufiNVEkrmF\n" + - "EB+N64wgwH4COTvCiN4erp5kyJwkfqAl2xLkZo0C464c9XoyQOXbmYD9A8v10wZu\n" + - "jyNsEo7Nr2USyw+qhjWSbFbEirP77Tvx+7pJQJwdtk1V9Tn73T2dGF2WHYejei9S\n" + - "mcWpdIUqsu9etYH+zDmtu7I1xlkwiaVsNr2+D+qaCJyOYqrDTKVNK5nmbBPXDWZc\n" + - "NoDbTOoqquX7xONpq9M6jQIDAQABo4GAMH4wHQYDVR0OBBYEFAZ3A2S4qJZZwuNY\n" + - "wkJ6mAdc0gVdMEIGA1UdIwQ7MDmAFAZ3A2S4qJZZwuNYwkJ6mAdc0gVdoRakFDAS\n" + - "MRAwDgYDVQQDEwdFQVAgQ0EwggkA4zlLMo7anMIwDAYDVR0TBAUwAwEB/zALBgNV\n" + - "HQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHmdMwEhtys4d0E+t7owBmoVR+lU\n" + - "hMCcRtWs8YKX5WIM2kTweT0h/O1xwE1mWmRv/IbDAEb8od4BjAQLhIcolStr2JaO\n" + - "9ZzyxjOnNzqeErh/1DHDbb/moPpqfeJ8YiEz7nH/YU56Q8iCPO7TsgS0sNNE7PfN\n" + - "IUsBW0yHRgpQ4OxWmiZG2YZWiECRzAC0ecPzo59N5iH4vLQIMTMYquiDeMPQnn1e\n" + - "NDGxG8gCtDKIaS6tMg3a28MvWB094pr2ETou8O1C8Ji0Y4hE8QJmSdT7I4+GZjgW\n" + - "g94DZ5RiL7sdp3vC48CXOmeT61YBIvhGUsE1rPhXqkpqQ3Z3C4TFF0jXZZc=\n" + - "-----END CERTIFICATE-----\n"; - public static final X509Certificate CA_CERT1 = loadCertificate(CA_CERT1_STRING); - - private static final String CLIENT_CERT_STR = "-----BEGIN CERTIFICATE-----\n" + - "MIIE/DCCAuQCAQEwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxCzAJBgNV\n" + - "BAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdUZXN0aW5n\n" + - "MB4XDTE2MDkzMDIwNTQyOFoXDTE3MDkzMDIwNTQyOFowRDELMAkGA1UEBhMCVVMx\n" + - "CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdU\n" + - "ZXN0aW5nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnpmcbuaeHfnJ\n" + - "k+2QNvxmdVFTawyFMNk0USCq5sexscwmxbewG/Rb8YnixwJWS44v2XkSujB67z5C\n" + - "s2qudFEhRXKdEuC6idbAuA97KjipHh0AAniWMsyv61fvbgsUC0b0canx3LiDq81p\n" + - "y28NNGmAvoazLZUZ4AhBRiwYZY6FKk723gmZoGbEIeG7J1dlXPusc1662rIjz4eU\n" + - "zlmmlvqyHfNqnNk8L14Vug6Xh+lOEGN85xhu1YHAEKGrS89kZxs5rum/cZU8KH2V\n" + - "v6eKnY03kxjiVLQtnLpm/7VUEoCMGHyruRj+p3my4+DgqMsmsH52RZCBsjyGlpbU\n" + - "NOwOTIX6xh+Rqloduz4AnrMYYIiIw2s8g+2zJM7VbcVKx0fGS26BKdrxgrXWfmNE\n" + - "nR0/REQ5AxDGw0jfTUvtdTkXAf+K4MDjcNLEZ+MA4rHfAfQWZtUR5BkHCQYxNpJk\n" + - "pA0gyk+BpKdC4WdzI14NSWsu5sRCmBCFqH6BTOSEq/V1cNorBxNwLSSTwFFqUDqx\n" + - "Y5nQLXygkJf9WHZWtSKeSjtOYgilz7UKzC2s3CsjmIyGFe+SwpuHJnuE4Uc8Z5Cb\n" + - "bjNGHPzqL6XnmzZHJp7RF8kBdKdjGC7dCUltzOfICZeKlzOOq+Kw42T/nXjuXvpb\n" + - "nkXNxg741Nwd6RecykXJbseFwm3EYxkCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA\n" + - "Ga1mGwI9aXkL2fTPXO9YkAPzoGeX8aeuVYSQaSkNq+5vnogYCyAt3YDHjRG+ewTT\n" + - "WbnPA991xRAPac+biJeXWmwvgGj0YuT7e79phAiGkTTnbAjFHGfYnBy/tI/v7btO\n" + - "hRNElA5yTJ1m2fVbBEKXzMR83jrT9iyI+YLRN86zUZIaC86xxSbqnrdWN2jOK6MX\n" + - "dS8Arp9tPQjC/4gW+2Ilxv68jiYh+5auWHQZVjppWVY//iu4mAbkq1pTwQEhZ8F8\n" + - "Zrmh9DHh60hLFcfSuhIAwf/NMzppwdkjy1ruKVrpijhGKGp4OWu8nvOUgHSzxc7F\n" + - "PwpVZ5N2Ku4L8MLO6BG2VasRJK7l17TzDXlfLZHJjkuryOFxVaQKt8ZNFgTOaCXS\n" + - "E+gpTLksKU7riYckoiP4+H1sn9qcis0e8s4o/uf1UVc8GSdDw61ReGM5oZEDm1u8\n" + - "H9x20QU6igLqzyBpqvCKv7JNgU1uB2PAODHH78zJiUfnKd1y+o+J1iWzaGj3EFji\n" + - "T8AXksbTP733FeFXfggXju2dyBH+Z1S5BBTEOd1brWgXlHSAZGm97MKZ94r6/tkX\n" + - "qfv3fCos0DKz0oV7qBxYS8wiYhzrRVxG6ITAoH8uuUVVQaZF+G4nJ2jEqNbfuKyX\n" + - "ATQsVNjNNlDA0J33GobPMjT326wa4YAWMx8PI5PJZ3g=\n" + - "-----END CERTIFICATE-----\n"; - public static final X509Certificate CLIENT_CERT = loadCertificate(CLIENT_CERT_STR); - - private static final byte[] FAKE_RSA_KEY_1 = new byte[] { - (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01, - (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, - (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, - (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82, - (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e, - (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81, - (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b, - (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66, - (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a, - (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02, - (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3, - (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d, - (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67, - (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb, - (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2, - (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79, - (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce, - (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08, - (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b, - (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4, - (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d, - (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23, - (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08, - (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1, - (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4, - (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16, - (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e, - (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01, - (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16, - (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98, - (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf, - (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a, - (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2, - (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc, - (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5, - (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a, - (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b, - (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9, - (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12, - (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e, - (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d, - (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2, - (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d, - (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc, - (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98, - (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96, - (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30, - (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e, - (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad, - (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f, - (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89, - (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13, - (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a, - (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e, - (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa, - (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47, - (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44, - (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22, - (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10, - (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45, - (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4, - (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda, - (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1, - (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab, - (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7, - (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc, - (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d, - (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82, - (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3, - (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a, - (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9, - (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6, - (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00, - (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd, - (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb, - (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4, - (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0, - (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2, - (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce, - (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a, - (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21, - (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d, - (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1, - (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41, - (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce, - (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0, - (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40, - (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a, - (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c, - (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90, - (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf, - (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb, - (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14, - (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab, - (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02, - (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67, - (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d, - (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d, - (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b, - (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2, - (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28, - (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd, - (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d, - (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b, - (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1, - (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51 - }; - public static final PrivateKey RSA_KEY1 = loadPrivateKey("RSA", FAKE_RSA_KEY_1); - - private static final String CA_SUITE_B_RSA3072_CERT_STRING = - "-----BEGIN CERTIFICATE-----\n" - + "MIIEnTCCAwWgAwIBAgIUD87Y8fFLzLr1HQ/64aEnjNq2R/4wDQYJKoZIhvcNAQEM\n" - + "BQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAO\n" - + "BgNVBAoMB0FuZHJvaWQxDjAMBgNVBAsMBVdpLUZpMRIwEAYDVQQDDAl1bml0ZXN0\n" - + "Q0EwHhcNMjAwNzIxMDIxNzU0WhcNMzAwNTMwMDIxNzU0WjBeMQswCQYDVQQGEwJV\n" - + "UzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA01UVjEQMA4GA1UECgwHQW5kcm9pZDEO\n" - + "MAwGA1UECwwFV2ktRmkxEjAQBgNVBAMMCXVuaXRlc3RDQTCCAaIwDQYJKoZIhvcN\n" - + "AQEBBQADggGPADCCAYoCggGBAMtrsT0otlxh0QS079KpRRbU1PQjCihSoltXnrxF\n" - + "sTWZs2weVEeYVyYU5LaauCDDgISCMtjtfbfylMBeYjpWB5hYzYQOiTzo0anWhMyb\n" - + "Ngb7gpMVZuIl6lwMYRyVRKwHWnTo2EUg1ZzW5rGe5fs/KHj6//hoNFm+3Oju0TQd\n" - + "nraQULpoERPF5B7p85Cssk8uNbviBfZXvtCuJ4N6w7PNceOY/9bbwc1mC+pPZmzV\n" - + "SOAg0vvbIQRzChm63C3jBC3xmxSOOZVrKN4zKDG2s8P0oCNGt0NlgRMrgbPRekzg\n" - + "4avkbA0vTuc2AyriTEYkdea/Mt4EpRg9XuOb43U/GJ/d/vQv2/9fsxhXmsZrn8kr\n" - + "Qo5MMHJFUd96GgHmvYSU3Mf/5r8gF626lvqHioGuTAuHUSnr02ri1WUxZ15LDRgY\n" - + "quMjDCFZfucjJPDAdtiHcFSej/4SLJlN39z8oKKNPn3aL9Gv49oAKs9S8tfDVzMk\n" - + "fDLROQFHFuW715GnnMgEAoOpRwIDAQABo1MwUTAdBgNVHQ4EFgQUeVuGmSVN4ARs\n" - + "mesUMWSJ2qWLbxUwHwYDVR0jBBgwFoAUeVuGmSVN4ARsmesUMWSJ2qWLbxUwDwYD\n" - + "VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQwFAAOCAYEAit1Lo/hegZpPuT9dlWZJ\n" - + "bC8JvAf95O8lnn6LFb69pgYOHCLgCIlvYXu9rdBUJgZo+V1MzJJljiO6RxWRfKbQ\n" - + "8WBYkoqR1EqriR3Kn8q/SjIZCdFSaznTyU1wQMveBQ6RJWXSUhYVfE9RjyFTp7B4\n" - + "UyH2uCluR/0T06HQNGfH5XpIYQqCk1Zgng5lmEmheLDPoJpa92lKeQFJMC6eYz9g\n" - + "lF1GHxPxkPfbMJ6ZDp5X6Yopu6Q6uEXhVKM/iQVcgzRkx9rid+xTYl+nOKyK/XfC\n" - + "z8P0/TFIoPTW02DLge5wKagdoCpy1B7HdrAXyUjoH4B8MsUkq3kYPFSjPzScuTtV\n" - + "kUuDw5ipCNeXCRnhbYqRDk6PX5GUu2cmN9jtaH3tbgm3fKNOsd/BO1fLIl7qjXlR\n" - + "27HHbC0JXjNvlm2DLp23v4NTxS7WZGYsxyUj5DZrxBxqCsTXu/01w1BrQKWKh9FM\n" - + "aVrlA8omfVODK2CSuw+KhEMHepRv/AUgsLl4L4+RMoa+\n" - + "-----END CERTIFICATE-----\n"; - public static final X509Certificate CA_SUITE_B_RSA3072_CERT = - loadCertificate(CA_SUITE_B_RSA3072_CERT_STRING); - - private static final String CA_SUITE_B_ECDSA_CERT_STRING = - "-----BEGIN CERTIFICATE-----\n" - + "MIICTzCCAdSgAwIBAgIUdnLttwNPnQzFufplGOr9bTrGCqMwCgYIKoZIzj0EAwMw\n" - + "XjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNV\n" - + "BAoMB0FuZHJvaWQxDjAMBgNVBAsMBVdpLUZpMRIwEAYDVQQDDAl1bml0ZXN0Q0Ew\n" - + "HhcNMjAwNzIxMDIyNDA1WhcNMzAwNTMwMDIyNDA1WjBeMQswCQYDVQQGEwJVUzEL\n" - + "MAkGA1UECAwCQ0ExDDAKBgNVBAcMA01UVjEQMA4GA1UECgwHQW5kcm9pZDEOMAwG\n" - + "A1UECwwFV2ktRmkxEjAQBgNVBAMMCXVuaXRlc3RDQTB2MBAGByqGSM49AgEGBSuB\n" - + "BAAiA2IABFmntXwk9icqhDQFUP1xy04WyEpaGW4q6Q+8pujlSl/X3iotPZ++GZfp\n" - + "Mfv3YDHDBl6sELPQ2BEjyPXmpsKjOUdiUe69e88oGEdeqT2xXiQ6uzpTfJD4170i\n" - + "O/TwLrQGKKNTMFEwHQYDVR0OBBYEFCjptsX3g4g5W0L4oEP6N3gfyiZXMB8GA1Ud\n" - + "IwQYMBaAFCjptsX3g4g5W0L4oEP6N3gfyiZXMA8GA1UdEwEB/wQFMAMBAf8wCgYI\n" - + "KoZIzj0EAwMDaQAwZgIxAK61brUYRbLmQKiaEboZgrHtnPAcGo7Yzx3MwHecx3Dm\n" - + "5soIeLVYc8bPYN1pbhXW1gIxALdEe2sh03nBHyQH4adYoZungoCwt8mp/7sJFxou\n" - + "9UnRegyBgGzf74ROWdpZHzh+Pg==\n" - + "-----END CERTIFICATE-----\n"; - public static final X509Certificate CA_SUITE_B_ECDSA_CERT = - loadCertificate(CA_SUITE_B_ECDSA_CERT_STRING); - - private static final String CLIENT_SUITE_B_RSA3072_CERT_STRING = - "-----BEGIN CERTIFICATE-----\n" - + "MIIERzCCAq8CFDopjyNgaj+c2TN2k06h7okEWpHJMA0GCSqGSIb3DQEBDAUAMF4x\n" - + "CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDTVRWMRAwDgYDVQQK\n" - + "DAdBbmRyb2lkMQ4wDAYDVQQLDAVXaS1GaTESMBAGA1UEAwwJdW5pdGVzdENBMB4X\n" - + "DTIwMDcyMTAyMjkxMVoXDTMwMDUzMDAyMjkxMVowYjELMAkGA1UEBhMCVVMxCzAJ\n" - + "BgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNVBAoMB0FuZHJvaWQxDjAMBgNV\n" - + "BAsMBVdpLUZpMRYwFAYDVQQDDA11bml0ZXN0Q2xpZW50MIIBojANBgkqhkiG9w0B\n" - + "AQEFAAOCAY8AMIIBigKCAYEAwSK3C5K5udtCKTnE14e8z2cZvwmB4Xe+a8+7QLud\n" - + "Hooc/lQzClgK4MbVUC0D3FE+U32C78SxKoTaRWtvPmNm+UaFT8KkwyUno/dv+2XD\n" - + "pd/zARQ+3FwAfWopAhEyCVSxwsCa+slQ4juRIMIuUC1Mm0NaptZyM3Tj/ICQEfpk\n" - + "o9qVIbiK6eoJMTkY8EWfAn7RTFdfR1OLuO0mVOjgLW9/+upYv6hZ19nAMAxw4QTJ\n" - + "x7lLwALX7B+tDYNEZHDqYL2zyvQWAj2HClere8QYILxkvktgBg2crEJJe4XbDH7L\n" - + "A3rrXmsiqf1ZbfFFEzK9NFqovL+qGh+zIP+588ShJFO9H/RDnDpiTnAFTWXQdTwg\n" - + "szSS0Vw2PB+JqEABAa9DeMvXT1Oy+NY3ItPHyy63nQZVI2rXANw4NhwS0Z6DF+Qs\n" - + "TNrj+GU7e4SG/EGR8SvldjYfQTWFLg1l/UT1hOOkQZwdsaW1zgKyeuiFB2KdMmbA\n" - + "Sq+Ux1L1KICo0IglwWcB/8nnAgMBAAEwDQYJKoZIhvcNAQEMBQADggGBAMYwJkNw\n" - + "BaCviKFmReDTMwWPRy4AMNViEeqAXgERwDEKwM7efjsaj5gctWfKsxX6UdLzkhgg\n" - + "6S/T6PxVWKzJ6l7SoOuTa6tMQOZp+h3R1mdfEQbw8B5cXBxZ+batzAai6Fiy1FKS\n" - + "/ka3INbcGfYuIYghfTrb4/NJKN06ZaQ1bpPwq0e4gN7800T2nbawvSf7r+8ZLcG3\n" - + "6bGCjRMwDSIipNvOwoj3TG315XC7TccX5difQ4sKOY+d2MkVJ3RiO0Ciw2ZbEW8d\n" - + "1FH5vUQJWnBUfSFznosGzLwH3iWfqlP+27jNE+qB2igEwCRFgVAouURx5ou43xuX\n" - + "qf6JkdI3HTJGLIWxkp7gOeln4dEaYzKjYw+P0VqJvKVqQ0IXiLjHgE0J9p0vgyD6\n" - + "HVVcP7U8RgqrbIjL1QgHU4KBhGi+WSUh/mRplUCNvHgcYdcHi/gHpj/j6ubwqIGV\n" - + "z4iSolAHYTmBWcLyE0NgpzE6ntp+53r2KaUJA99l2iGVzbWTwqPSm0XAVw==\n" - + "-----END CERTIFICATE-----\n"; - public static final X509Certificate CLIENT_SUITE_B_RSA3072_CERT = - loadCertificate(CLIENT_SUITE_B_RSA3072_CERT_STRING); - - private static final byte[] CLIENT_SUITE_B_RSA3072_KEY_DATA = new byte[]{ - (byte) 0x30, (byte) 0x82, (byte) 0x06, (byte) 0xfe, (byte) 0x02, (byte) 0x01, - (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, - (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, - (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82, - (byte) 0x06, (byte) 0xe8, (byte) 0x30, (byte) 0x82, (byte) 0x06, (byte) 0xe4, - (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x82, (byte) 0x01, - (byte) 0x81, (byte) 0x00, (byte) 0xc1, (byte) 0x22, (byte) 0xb7, (byte) 0x0b, - (byte) 0x92, (byte) 0xb9, (byte) 0xb9, (byte) 0xdb, (byte) 0x42, (byte) 0x29, - (byte) 0x39, (byte) 0xc4, (byte) 0xd7, (byte) 0x87, (byte) 0xbc, (byte) 0xcf, - (byte) 0x67, (byte) 0x19, (byte) 0xbf, (byte) 0x09, (byte) 0x81, (byte) 0xe1, - (byte) 0x77, (byte) 0xbe, (byte) 0x6b, (byte) 0xcf, (byte) 0xbb, (byte) 0x40, - (byte) 0xbb, (byte) 0x9d, (byte) 0x1e, (byte) 0x8a, (byte) 0x1c, (byte) 0xfe, - (byte) 0x54, (byte) 0x33, (byte) 0x0a, (byte) 0x58, (byte) 0x0a, (byte) 0xe0, - (byte) 0xc6, (byte) 0xd5, (byte) 0x50, (byte) 0x2d, (byte) 0x03, (byte) 0xdc, - (byte) 0x51, (byte) 0x3e, (byte) 0x53, (byte) 0x7d, (byte) 0x82, (byte) 0xef, - (byte) 0xc4, (byte) 0xb1, (byte) 0x2a, (byte) 0x84, (byte) 0xda, (byte) 0x45, - (byte) 0x6b, (byte) 0x6f, (byte) 0x3e, (byte) 0x63, (byte) 0x66, (byte) 0xf9, - (byte) 0x46, (byte) 0x85, (byte) 0x4f, (byte) 0xc2, (byte) 0xa4, (byte) 0xc3, - (byte) 0x25, (byte) 0x27, (byte) 0xa3, (byte) 0xf7, (byte) 0x6f, (byte) 0xfb, - (byte) 0x65, (byte) 0xc3, (byte) 0xa5, (byte) 0xdf, (byte) 0xf3, (byte) 0x01, - (byte) 0x14, (byte) 0x3e, (byte) 0xdc, (byte) 0x5c, (byte) 0x00, (byte) 0x7d, - (byte) 0x6a, (byte) 0x29, (byte) 0x02, (byte) 0x11, (byte) 0x32, (byte) 0x09, - (byte) 0x54, (byte) 0xb1, (byte) 0xc2, (byte) 0xc0, (byte) 0x9a, (byte) 0xfa, - (byte) 0xc9, (byte) 0x50, (byte) 0xe2, (byte) 0x3b, (byte) 0x91, (byte) 0x20, - (byte) 0xc2, (byte) 0x2e, (byte) 0x50, (byte) 0x2d, (byte) 0x4c, (byte) 0x9b, - (byte) 0x43, (byte) 0x5a, (byte) 0xa6, (byte) 0xd6, (byte) 0x72, (byte) 0x33, - (byte) 0x74, (byte) 0xe3, (byte) 0xfc, (byte) 0x80, (byte) 0x90, (byte) 0x11, - (byte) 0xfa, (byte) 0x64, (byte) 0xa3, (byte) 0xda, (byte) 0x95, (byte) 0x21, - (byte) 0xb8, (byte) 0x8a, (byte) 0xe9, (byte) 0xea, (byte) 0x09, (byte) 0x31, - (byte) 0x39, (byte) 0x18, (byte) 0xf0, (byte) 0x45, (byte) 0x9f, (byte) 0x02, - (byte) 0x7e, (byte) 0xd1, (byte) 0x4c, (byte) 0x57, (byte) 0x5f, (byte) 0x47, - (byte) 0x53, (byte) 0x8b, (byte) 0xb8, (byte) 0xed, (byte) 0x26, (byte) 0x54, - (byte) 0xe8, (byte) 0xe0, (byte) 0x2d, (byte) 0x6f, (byte) 0x7f, (byte) 0xfa, - (byte) 0xea, (byte) 0x58, (byte) 0xbf, (byte) 0xa8, (byte) 0x59, (byte) 0xd7, - (byte) 0xd9, (byte) 0xc0, (byte) 0x30, (byte) 0x0c, (byte) 0x70, (byte) 0xe1, - (byte) 0x04, (byte) 0xc9, (byte) 0xc7, (byte) 0xb9, (byte) 0x4b, (byte) 0xc0, - (byte) 0x02, (byte) 0xd7, (byte) 0xec, (byte) 0x1f, (byte) 0xad, (byte) 0x0d, - (byte) 0x83, (byte) 0x44, (byte) 0x64, (byte) 0x70, (byte) 0xea, (byte) 0x60, - (byte) 0xbd, (byte) 0xb3, (byte) 0xca, (byte) 0xf4, (byte) 0x16, (byte) 0x02, - (byte) 0x3d, (byte) 0x87, (byte) 0x0a, (byte) 0x57, (byte) 0xab, (byte) 0x7b, - (byte) 0xc4, (byte) 0x18, (byte) 0x20, (byte) 0xbc, (byte) 0x64, (byte) 0xbe, - (byte) 0x4b, (byte) 0x60, (byte) 0x06, (byte) 0x0d, (byte) 0x9c, (byte) 0xac, - (byte) 0x42, (byte) 0x49, (byte) 0x7b, (byte) 0x85, (byte) 0xdb, (byte) 0x0c, - (byte) 0x7e, (byte) 0xcb, (byte) 0x03, (byte) 0x7a, (byte) 0xeb, (byte) 0x5e, - (byte) 0x6b, (byte) 0x22, (byte) 0xa9, (byte) 0xfd, (byte) 0x59, (byte) 0x6d, - (byte) 0xf1, (byte) 0x45, (byte) 0x13, (byte) 0x32, (byte) 0xbd, (byte) 0x34, - (byte) 0x5a, (byte) 0xa8, (byte) 0xbc, (byte) 0xbf, (byte) 0xaa, (byte) 0x1a, - (byte) 0x1f, (byte) 0xb3, (byte) 0x20, (byte) 0xff, (byte) 0xb9, (byte) 0xf3, - (byte) 0xc4, (byte) 0xa1, (byte) 0x24, (byte) 0x53, (byte) 0xbd, (byte) 0x1f, - (byte) 0xf4, (byte) 0x43, (byte) 0x9c, (byte) 0x3a, (byte) 0x62, (byte) 0x4e, - (byte) 0x70, (byte) 0x05, (byte) 0x4d, (byte) 0x65, (byte) 0xd0, (byte) 0x75, - (byte) 0x3c, (byte) 0x20, (byte) 0xb3, (byte) 0x34, (byte) 0x92, (byte) 0xd1, - (byte) 0x5c, (byte) 0x36, (byte) 0x3c, (byte) 0x1f, (byte) 0x89, (byte) 0xa8, - (byte) 0x40, (byte) 0x01, (byte) 0x01, (byte) 0xaf, (byte) 0x43, (byte) 0x78, - (byte) 0xcb, (byte) 0xd7, (byte) 0x4f, (byte) 0x53, (byte) 0xb2, (byte) 0xf8, - (byte) 0xd6, (byte) 0x37, (byte) 0x22, (byte) 0xd3, (byte) 0xc7, (byte) 0xcb, - (byte) 0x2e, (byte) 0xb7, (byte) 0x9d, (byte) 0x06, (byte) 0x55, (byte) 0x23, - (byte) 0x6a, (byte) 0xd7, (byte) 0x00, (byte) 0xdc, (byte) 0x38, (byte) 0x36, - (byte) 0x1c, (byte) 0x12, (byte) 0xd1, (byte) 0x9e, (byte) 0x83, (byte) 0x17, - (byte) 0xe4, (byte) 0x2c, (byte) 0x4c, (byte) 0xda, (byte) 0xe3, (byte) 0xf8, - (byte) 0x65, (byte) 0x3b, (byte) 0x7b, (byte) 0x84, (byte) 0x86, (byte) 0xfc, - (byte) 0x41, (byte) 0x91, (byte) 0xf1, (byte) 0x2b, (byte) 0xe5, (byte) 0x76, - (byte) 0x36, (byte) 0x1f, (byte) 0x41, (byte) 0x35, (byte) 0x85, (byte) 0x2e, - (byte) 0x0d, (byte) 0x65, (byte) 0xfd, (byte) 0x44, (byte) 0xf5, (byte) 0x84, - (byte) 0xe3, (byte) 0xa4, (byte) 0x41, (byte) 0x9c, (byte) 0x1d, (byte) 0xb1, - (byte) 0xa5, (byte) 0xb5, (byte) 0xce, (byte) 0x02, (byte) 0xb2, (byte) 0x7a, - (byte) 0xe8, (byte) 0x85, (byte) 0x07, (byte) 0x62, (byte) 0x9d, (byte) 0x32, - (byte) 0x66, (byte) 0xc0, (byte) 0x4a, (byte) 0xaf, (byte) 0x94, (byte) 0xc7, - (byte) 0x52, (byte) 0xf5, (byte) 0x28, (byte) 0x80, (byte) 0xa8, (byte) 0xd0, - (byte) 0x88, (byte) 0x25, (byte) 0xc1, (byte) 0x67, (byte) 0x01, (byte) 0xff, - (byte) 0xc9, (byte) 0xe7, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, - (byte) 0x01, (byte) 0x02, (byte) 0x82, (byte) 0x01, (byte) 0x80, (byte) 0x04, - (byte) 0xb1, (byte) 0xcc, (byte) 0x53, (byte) 0x3a, (byte) 0xb0, (byte) 0xcb, - (byte) 0x04, (byte) 0xba, (byte) 0x59, (byte) 0xf8, (byte) 0x2e, (byte) 0x81, - (byte) 0xb2, (byte) 0xa9, (byte) 0xf3, (byte) 0x3c, (byte) 0xa5, (byte) 0x52, - (byte) 0x90, (byte) 0x6f, (byte) 0x98, (byte) 0xc4, (byte) 0x69, (byte) 0x5b, - (byte) 0x83, (byte) 0x84, (byte) 0x20, (byte) 0xb1, (byte) 0xae, (byte) 0xc3, - (byte) 0x04, (byte) 0x46, (byte) 0x6a, (byte) 0x24, (byte) 0x2f, (byte) 0xcd, - (byte) 0x6b, (byte) 0x90, (byte) 0x70, (byte) 0x20, (byte) 0x45, (byte) 0x25, - (byte) 0x1a, (byte) 0xc3, (byte) 0x02, (byte) 0x42, (byte) 0xf3, (byte) 0x49, - (byte) 0xe2, (byte) 0x3e, (byte) 0x21, (byte) 0x87, (byte) 0xdd, (byte) 0x6a, - (byte) 0x94, (byte) 0x2a, (byte) 0x1e, (byte) 0x0f, (byte) 0xdb, (byte) 0x77, - (byte) 0x5f, (byte) 0xc1, (byte) 0x2c, (byte) 0x03, (byte) 0xfb, (byte) 0xcf, - (byte) 0x91, (byte) 0x82, (byte) 0xa1, (byte) 0xbf, (byte) 0xb0, (byte) 0x73, - (byte) 0xfa, (byte) 0xda, (byte) 0xbc, (byte) 0xf8, (byte) 0x9f, (byte) 0x45, - (byte) 0xd3, (byte) 0xe8, (byte) 0xbb, (byte) 0x38, (byte) 0xfb, (byte) 0xc2, - (byte) 0x2d, (byte) 0x76, (byte) 0x51, (byte) 0x96, (byte) 0x18, (byte) 0x03, - (byte) 0x15, (byte) 0xd9, (byte) 0xea, (byte) 0x82, (byte) 0x25, (byte) 0x83, - (byte) 0xff, (byte) 0x5c, (byte) 0x85, (byte) 0x06, (byte) 0x09, (byte) 0xb2, - (byte) 0x46, (byte) 0x12, (byte) 0x64, (byte) 0x02, (byte) 0x74, (byte) 0x4f, - (byte) 0xbc, (byte) 0x9a, (byte) 0x25, (byte) 0x18, (byte) 0x01, (byte) 0x07, - (byte) 0x17, (byte) 0x25, (byte) 0x55, (byte) 0x7c, (byte) 0xdc, (byte) 0xe1, - (byte) 0xd1, (byte) 0x5a, (byte) 0x2f, (byte) 0x25, (byte) 0xaf, (byte) 0xf6, - (byte) 0x8f, (byte) 0xa4, (byte) 0x9a, (byte) 0x5a, (byte) 0x3a, (byte) 0xfe, - (byte) 0x2e, (byte) 0x93, (byte) 0x24, (byte) 0xa0, (byte) 0x27, (byte) 0xac, - (byte) 0x07, (byte) 0x75, (byte) 0x33, (byte) 0x01, (byte) 0x54, (byte) 0x23, - (byte) 0x0f, (byte) 0xe8, (byte) 0x9f, (byte) 0xfa, (byte) 0x36, (byte) 0xe6, - (byte) 0x3a, (byte) 0xd5, (byte) 0x78, (byte) 0xb0, (byte) 0xe4, (byte) 0x6a, - (byte) 0x16, (byte) 0x50, (byte) 0xbd, (byte) 0x0f, (byte) 0x9f, (byte) 0x32, - (byte) 0xa1, (byte) 0x6b, (byte) 0xf5, (byte) 0xa4, (byte) 0x34, (byte) 0x58, - (byte) 0xb6, (byte) 0xa4, (byte) 0xb3, (byte) 0xc3, (byte) 0x83, (byte) 0x08, - (byte) 0x18, (byte) 0xc7, (byte) 0xef, (byte) 0x95, (byte) 0xe2, (byte) 0x1b, - (byte) 0xba, (byte) 0x35, (byte) 0x61, (byte) 0xa3, (byte) 0xb4, (byte) 0x30, - (byte) 0xe0, (byte) 0xd1, (byte) 0xc1, (byte) 0xa2, (byte) 0x3a, (byte) 0xc6, - (byte) 0xb4, (byte) 0xd2, (byte) 0x80, (byte) 0x5a, (byte) 0xaf, (byte) 0xa4, - (byte) 0x54, (byte) 0x3c, (byte) 0x66, (byte) 0x5a, (byte) 0x1c, (byte) 0x4d, - (byte) 0xe1, (byte) 0xd9, (byte) 0x98, (byte) 0x44, (byte) 0x01, (byte) 0x1b, - (byte) 0x8c, (byte) 0xe9, (byte) 0x80, (byte) 0x54, (byte) 0x83, (byte) 0x3d, - (byte) 0x96, (byte) 0x25, (byte) 0x41, (byte) 0x1c, (byte) 0xad, (byte) 0xae, - (byte) 0x3b, (byte) 0x7a, (byte) 0xd7, (byte) 0x9d, (byte) 0x10, (byte) 0x7c, - (byte) 0xd1, (byte) 0xa7, (byte) 0x96, (byte) 0x39, (byte) 0xa5, (byte) 0x2f, - (byte) 0xbe, (byte) 0xc3, (byte) 0x2c, (byte) 0x64, (byte) 0x01, (byte) 0xfe, - (byte) 0xa2, (byte) 0xd1, (byte) 0x6a, (byte) 0xcf, (byte) 0x4c, (byte) 0x76, - (byte) 0x3b, (byte) 0xc8, (byte) 0x35, (byte) 0x21, (byte) 0xda, (byte) 0x98, - (byte) 0xcf, (byte) 0xf9, (byte) 0x29, (byte) 0xff, (byte) 0x30, (byte) 0x59, - (byte) 0x36, (byte) 0x53, (byte) 0x0b, (byte) 0xbb, (byte) 0xfa, (byte) 0xba, - (byte) 0xc4, (byte) 0x03, (byte) 0x23, (byte) 0xe0, (byte) 0xd3, (byte) 0x33, - (byte) 0xff, (byte) 0x32, (byte) 0xdb, (byte) 0x30, (byte) 0x64, (byte) 0xc7, - (byte) 0x56, (byte) 0xca, (byte) 0x55, (byte) 0x14, (byte) 0xee, (byte) 0x58, - (byte) 0xfe, (byte) 0x96, (byte) 0x7e, (byte) 0x1c, (byte) 0x34, (byte) 0x16, - (byte) 0xeb, (byte) 0x76, (byte) 0x26, (byte) 0x48, (byte) 0xe2, (byte) 0xe5, - (byte) 0x5c, (byte) 0xd5, (byte) 0x83, (byte) 0x37, (byte) 0xd9, (byte) 0x09, - (byte) 0x71, (byte) 0xbc, (byte) 0x54, (byte) 0x25, (byte) 0xca, (byte) 0x2e, - (byte) 0xdb, (byte) 0x36, (byte) 0x39, (byte) 0xcc, (byte) 0x3a, (byte) 0x81, - (byte) 0x95, (byte) 0x9e, (byte) 0xf4, (byte) 0x01, (byte) 0xa7, (byte) 0xc0, - (byte) 0x20, (byte) 0xce, (byte) 0x70, (byte) 0x55, (byte) 0x2c, (byte) 0xe0, - (byte) 0x93, (byte) 0x72, (byte) 0xa6, (byte) 0x25, (byte) 0xda, (byte) 0x64, - (byte) 0x19, (byte) 0x18, (byte) 0xd2, (byte) 0x31, (byte) 0xe2, (byte) 0x7c, - (byte) 0xf2, (byte) 0x30, (byte) 0x9e, (byte) 0x8d, (byte) 0xc6, (byte) 0x14, - (byte) 0x8a, (byte) 0x38, (byte) 0xf0, (byte) 0x94, (byte) 0xeb, (byte) 0xf4, - (byte) 0x64, (byte) 0x92, (byte) 0x3d, (byte) 0x67, (byte) 0xa6, (byte) 0x2c, - (byte) 0x52, (byte) 0xfc, (byte) 0x60, (byte) 0xca, (byte) 0x2a, (byte) 0xcf, - (byte) 0x24, (byte) 0xd5, (byte) 0x42, (byte) 0x5f, (byte) 0xc7, (byte) 0x9f, - (byte) 0xf3, (byte) 0xb4, (byte) 0xdf, (byte) 0x76, (byte) 0x6e, (byte) 0x53, - (byte) 0xa1, (byte) 0x7b, (byte) 0xae, (byte) 0xa5, (byte) 0x84, (byte) 0x1f, - (byte) 0xfa, (byte) 0xc0, (byte) 0xb4, (byte) 0x6c, (byte) 0xc9, (byte) 0x02, - (byte) 0x81, (byte) 0xc1, (byte) 0x00, (byte) 0xf3, (byte) 0x17, (byte) 0xd9, - (byte) 0x48, (byte) 0x17, (byte) 0x87, (byte) 0x84, (byte) 0x16, (byte) 0xea, - (byte) 0x2d, (byte) 0x31, (byte) 0x1b, (byte) 0xce, (byte) 0xec, (byte) 0xaf, - (byte) 0xdc, (byte) 0x6b, (byte) 0xaf, (byte) 0xc8, (byte) 0xf1, (byte) 0x40, - (byte) 0xa7, (byte) 0x4f, (byte) 0xef, (byte) 0x48, (byte) 0x08, (byte) 0x5e, - (byte) 0x9a, (byte) 0xd1, (byte) 0xc0, (byte) 0xb1, (byte) 0xfe, (byte) 0xe7, - (byte) 0x03, (byte) 0xd5, (byte) 0x96, (byte) 0x01, (byte) 0xe8, (byte) 0x40, - (byte) 0xca, (byte) 0x78, (byte) 0xcb, (byte) 0xb3, (byte) 0x28, (byte) 0x1a, - (byte) 0xf0, (byte) 0xe5, (byte) 0xf6, (byte) 0x46, (byte) 0xef, (byte) 0xcd, - (byte) 0x1a, (byte) 0x0f, (byte) 0x13, (byte) 0x2d, (byte) 0x38, (byte) 0xf8, - (byte) 0xf7, (byte) 0x88, (byte) 0x21, (byte) 0x15, (byte) 0xce, (byte) 0x48, - (byte) 0xf4, (byte) 0x92, (byte) 0x7e, (byte) 0x9b, (byte) 0x2e, (byte) 0x2f, - (byte) 0x22, (byte) 0x3e, (byte) 0x5c, (byte) 0x67, (byte) 0xd7, (byte) 0x58, - (byte) 0xf6, (byte) 0xef, (byte) 0x1f, (byte) 0xb4, (byte) 0x04, (byte) 0xc7, - (byte) 0xfd, (byte) 0x8c, (byte) 0x4e, (byte) 0x27, (byte) 0x9e, (byte) 0xb9, - (byte) 0xef, (byte) 0x0f, (byte) 0xf7, (byte) 0x4a, (byte) 0xc2, (byte) 0xf4, - (byte) 0x64, (byte) 0x6b, (byte) 0xe0, (byte) 0xfb, (byte) 0xe3, (byte) 0x45, - (byte) 0xd5, (byte) 0x37, (byte) 0xa0, (byte) 0x2a, (byte) 0xc6, (byte) 0xf3, - (byte) 0xf6, (byte) 0xcc, (byte) 0xb5, (byte) 0x94, (byte) 0xbf, (byte) 0x56, - (byte) 0xa0, (byte) 0x61, (byte) 0x36, (byte) 0x88, (byte) 0x35, (byte) 0xd5, - (byte) 0xa5, (byte) 0xad, (byte) 0x20, (byte) 0x48, (byte) 0xda, (byte) 0x70, - (byte) 0x35, (byte) 0xd9, (byte) 0x75, (byte) 0x66, (byte) 0xa5, (byte) 0xac, - (byte) 0x86, (byte) 0x7a, (byte) 0x75, (byte) 0x49, (byte) 0x88, (byte) 0x40, - (byte) 0xce, (byte) 0xb0, (byte) 0x6f, (byte) 0x57, (byte) 0x15, (byte) 0x54, - (byte) 0xd3, (byte) 0x2f, (byte) 0x11, (byte) 0x9b, (byte) 0xe3, (byte) 0x87, - (byte) 0xc8, (byte) 0x8d, (byte) 0x98, (byte) 0xc6, (byte) 0xe0, (byte) 0xbc, - (byte) 0x85, (byte) 0xb9, (byte) 0x04, (byte) 0x43, (byte) 0xa9, (byte) 0x41, - (byte) 0xce, (byte) 0x42, (byte) 0x1a, (byte) 0x57, (byte) 0x10, (byte) 0xd8, - (byte) 0xe4, (byte) 0x6a, (byte) 0x51, (byte) 0x10, (byte) 0x0a, (byte) 0xec, - (byte) 0xe4, (byte) 0x57, (byte) 0xc7, (byte) 0xee, (byte) 0xe9, (byte) 0xd6, - (byte) 0xcb, (byte) 0x3e, (byte) 0xba, (byte) 0xfa, (byte) 0xe9, (byte) 0x0e, - (byte) 0xed, (byte) 0x87, (byte) 0x04, (byte) 0x9a, (byte) 0x48, (byte) 0xba, - (byte) 0xaf, (byte) 0x08, (byte) 0xf5, (byte) 0x02, (byte) 0x81, (byte) 0xc1, - (byte) 0x00, (byte) 0xcb, (byte) 0x63, (byte) 0xd6, (byte) 0x54, (byte) 0xb6, - (byte) 0xf3, (byte) 0xf3, (byte) 0x8c, (byte) 0xf8, (byte) 0xd0, (byte) 0xd2, - (byte) 0x84, (byte) 0xc1, (byte) 0xf5, (byte) 0x12, (byte) 0xe0, (byte) 0x02, - (byte) 0x80, (byte) 0x42, (byte) 0x92, (byte) 0x4e, (byte) 0xa4, (byte) 0x5c, - (byte) 0xa5, (byte) 0x64, (byte) 0xec, (byte) 0xb7, (byte) 0xdc, (byte) 0xe0, - (byte) 0x2d, (byte) 0x5d, (byte) 0xac, (byte) 0x0e, (byte) 0x24, (byte) 0x48, - (byte) 0x13, (byte) 0x05, (byte) 0xe8, (byte) 0xff, (byte) 0x96, (byte) 0x93, - (byte) 0xba, (byte) 0x3c, (byte) 0x88, (byte) 0xcc, (byte) 0x80, (byte) 0xf9, - (byte) 0xdb, (byte) 0xa8, (byte) 0x4d, (byte) 0x86, (byte) 0x47, (byte) 0xc8, - (byte) 0xbf, (byte) 0x34, (byte) 0x2d, (byte) 0xda, (byte) 0xb6, (byte) 0x28, - (byte) 0xf0, (byte) 0x1e, (byte) 0xd2, (byte) 0x46, (byte) 0x0d, (byte) 0x6f, - (byte) 0x36, (byte) 0x8e, (byte) 0x84, (byte) 0xd8, (byte) 0xaf, (byte) 0xf7, - (byte) 0x69, (byte) 0x23, (byte) 0x77, (byte) 0xfb, (byte) 0xc5, (byte) 0x04, - (byte) 0x08, (byte) 0x18, (byte) 0xac, (byte) 0x85, (byte) 0x80, (byte) 0x87, - (byte) 0x1c, (byte) 0xfe, (byte) 0x8e, (byte) 0x5d, (byte) 0x00, (byte) 0x7f, - (byte) 0x5b, (byte) 0x33, (byte) 0xf5, (byte) 0xdf, (byte) 0x70, (byte) 0x81, - (byte) 0xad, (byte) 0x81, (byte) 0xf4, (byte) 0x5a, (byte) 0x37, (byte) 0x8a, - (byte) 0x79, (byte) 0x09, (byte) 0xc5, (byte) 0x55, (byte) 0xab, (byte) 0x58, - (byte) 0x7c, (byte) 0x47, (byte) 0xca, (byte) 0xa5, (byte) 0x80, (byte) 0x49, - (byte) 0x5f, (byte) 0x71, (byte) 0x83, (byte) 0xfb, (byte) 0x3b, (byte) 0x06, - (byte) 0xec, (byte) 0x75, (byte) 0x23, (byte) 0xc4, (byte) 0x32, (byte) 0xc7, - (byte) 0x18, (byte) 0xf6, (byte) 0x82, (byte) 0x95, (byte) 0x98, (byte) 0x39, - (byte) 0xf7, (byte) 0x92, (byte) 0x31, (byte) 0xc0, (byte) 0x89, (byte) 0xba, - (byte) 0xd4, (byte) 0xd4, (byte) 0x58, (byte) 0x4e, (byte) 0x38, (byte) 0x35, - (byte) 0x10, (byte) 0xb9, (byte) 0xf1, (byte) 0x27, (byte) 0xdc, (byte) 0xff, - (byte) 0xc7, (byte) 0xb2, (byte) 0xba, (byte) 0x1f, (byte) 0x27, (byte) 0xaf, - (byte) 0x99, (byte) 0xd5, (byte) 0xb0, (byte) 0x39, (byte) 0xe7, (byte) 0x43, - (byte) 0x88, (byte) 0xd3, (byte) 0xce, (byte) 0x38, (byte) 0xc2, (byte) 0x99, - (byte) 0x43, (byte) 0xfc, (byte) 0x8a, (byte) 0xe3, (byte) 0x60, (byte) 0x0d, - (byte) 0x0a, (byte) 0xb8, (byte) 0xc4, (byte) 0x29, (byte) 0xca, (byte) 0x0d, - (byte) 0x30, (byte) 0xaf, (byte) 0xca, (byte) 0xd0, (byte) 0xaa, (byte) 0x67, - (byte) 0xb1, (byte) 0xdd, (byte) 0xdb, (byte) 0x7a, (byte) 0x11, (byte) 0xad, - (byte) 0xeb, (byte) 0x02, (byte) 0x81, (byte) 0xc0, (byte) 0x71, (byte) 0xb8, - (byte) 0xcf, (byte) 0x72, (byte) 0x35, (byte) 0x67, (byte) 0xb5, (byte) 0x38, - (byte) 0x8f, (byte) 0x16, (byte) 0xd3, (byte) 0x29, (byte) 0x82, (byte) 0x35, - (byte) 0x21, (byte) 0xd4, (byte) 0x49, (byte) 0x20, (byte) 0x74, (byte) 0x2d, - (byte) 0xc0, (byte) 0xa4, (byte) 0x44, (byte) 0xf5, (byte) 0xd8, (byte) 0xc9, - (byte) 0xe9, (byte) 0x90, (byte) 0x1d, (byte) 0xde, (byte) 0x3a, (byte) 0xa6, - (byte) 0xd7, (byte) 0xe5, (byte) 0xe8, (byte) 0x4e, (byte) 0x83, (byte) 0xd7, - (byte) 0xe6, (byte) 0x2f, (byte) 0x92, (byte) 0x31, (byte) 0x21, (byte) 0x3f, - (byte) 0xfa, (byte) 0xd2, (byte) 0x85, (byte) 0x92, (byte) 0x1f, (byte) 0xff, - (byte) 0x61, (byte) 0x00, (byte) 0xf6, (byte) 0xda, (byte) 0x6e, (byte) 0xc6, - (byte) 0x7f, (byte) 0x5a, (byte) 0x35, (byte) 0x79, (byte) 0xdc, (byte) 0xdc, - (byte) 0xa3, (byte) 0x2e, (byte) 0x9f, (byte) 0x35, (byte) 0xd1, (byte) 0x5c, - (byte) 0xda, (byte) 0xb9, (byte) 0xf7, (byte) 0x58, (byte) 0x7d, (byte) 0x4f, - (byte) 0xb6, (byte) 0x13, (byte) 0xd7, (byte) 0x2c, (byte) 0x0a, (byte) 0xa8, - (byte) 0x4d, (byte) 0xf2, (byte) 0xe4, (byte) 0x67, (byte) 0x4f, (byte) 0x8b, - (byte) 0xa6, (byte) 0xca, (byte) 0x1a, (byte) 0xbb, (byte) 0x02, (byte) 0x63, - (byte) 0x8f, (byte) 0xb7, (byte) 0x46, (byte) 0xec, (byte) 0x7a, (byte) 0x8a, - (byte) 0x09, (byte) 0x0a, (byte) 0x45, (byte) 0x3a, (byte) 0x8d, (byte) 0xa8, - (byte) 0x83, (byte) 0x4b, (byte) 0x0a, (byte) 0xdb, (byte) 0x4b, (byte) 0x99, - (byte) 0xf3, (byte) 0x69, (byte) 0x95, (byte) 0xf0, (byte) 0xcf, (byte) 0xe9, - (byte) 0xf7, (byte) 0x67, (byte) 0xc9, (byte) 0x45, (byte) 0x18, (byte) 0x2f, - (byte) 0xf0, (byte) 0x5c, (byte) 0x90, (byte) 0xbd, (byte) 0xa6, (byte) 0x66, - (byte) 0x8c, (byte) 0xfe, (byte) 0x60, (byte) 0x5d, (byte) 0x6c, (byte) 0x27, - (byte) 0xec, (byte) 0xc1, (byte) 0x84, (byte) 0xb2, (byte) 0xa1, (byte) 0x97, - (byte) 0x9e, (byte) 0x16, (byte) 0x29, (byte) 0xa7, (byte) 0xe0, (byte) 0x38, - (byte) 0xa2, (byte) 0x36, (byte) 0x05, (byte) 0x5f, (byte) 0xda, (byte) 0x72, - (byte) 0x1a, (byte) 0x5f, (byte) 0xa8, (byte) 0x7d, (byte) 0x41, (byte) 0x35, - (byte) 0xf6, (byte) 0x4e, (byte) 0x0a, (byte) 0x88, (byte) 0x8e, (byte) 0x00, - (byte) 0x98, (byte) 0xa6, (byte) 0xca, (byte) 0xc1, (byte) 0xdf, (byte) 0x72, - (byte) 0x6c, (byte) 0xfe, (byte) 0x29, (byte) 0xbe, (byte) 0xa3, (byte) 0x9b, - (byte) 0x0b, (byte) 0x5c, (byte) 0x0b, (byte) 0x9d, (byte) 0xa7, (byte) 0x71, - (byte) 0xce, (byte) 0x04, (byte) 0xfa, (byte) 0xac, (byte) 0x01, (byte) 0x8d, - (byte) 0x52, (byte) 0xa0, (byte) 0x3d, (byte) 0xdd, (byte) 0x02, (byte) 0x81, - (byte) 0xc1, (byte) 0x00, (byte) 0xc1, (byte) 0xc0, (byte) 0x2e, (byte) 0xa9, - (byte) 0xee, (byte) 0xca, (byte) 0xff, (byte) 0xe4, (byte) 0xf8, (byte) 0x15, - (byte) 0xfd, (byte) 0xa5, (byte) 0x68, (byte) 0x1b, (byte) 0x2d, (byte) 0x4a, - (byte) 0xe6, (byte) 0x37, (byte) 0x06, (byte) 0xb3, (byte) 0xd7, (byte) 0x64, - (byte) 0xad, (byte) 0xb9, (byte) 0x05, (byte) 0x26, (byte) 0x97, (byte) 0x94, - (byte) 0x3a, (byte) 0x9e, (byte) 0x1c, (byte) 0xd0, (byte) 0xcd, (byte) 0x7b, - (byte) 0xf4, (byte) 0x88, (byte) 0xe2, (byte) 0xa5, (byte) 0x6d, (byte) 0xed, - (byte) 0x24, (byte) 0x77, (byte) 0x52, (byte) 0x39, (byte) 0x43, (byte) 0x0f, - (byte) 0x4e, (byte) 0x75, (byte) 0xd8, (byte) 0xa3, (byte) 0x59, (byte) 0x5a, - (byte) 0xc2, (byte) 0xba, (byte) 0x9a, (byte) 0x5b, (byte) 0x60, (byte) 0x31, - (byte) 0x0d, (byte) 0x58, (byte) 0x89, (byte) 0x13, (byte) 0xe8, (byte) 0x95, - (byte) 0xdd, (byte) 0xae, (byte) 0xcc, (byte) 0x1f, (byte) 0x73, (byte) 0x48, - (byte) 0x55, (byte) 0xd8, (byte) 0xfb, (byte) 0x67, (byte) 0xce, (byte) 0x18, - (byte) 0x85, (byte) 0x59, (byte) 0xad, (byte) 0x1f, (byte) 0x93, (byte) 0xe1, - (byte) 0xb7, (byte) 0x54, (byte) 0x80, (byte) 0x8e, (byte) 0x5f, (byte) 0xbc, - (byte) 0x1c, (byte) 0x96, (byte) 0x66, (byte) 0x2e, (byte) 0x40, (byte) 0x17, - (byte) 0x2e, (byte) 0x01, (byte) 0x7a, (byte) 0x7d, (byte) 0xaa, (byte) 0xff, - (byte) 0xa3, (byte) 0xd2, (byte) 0xdf, (byte) 0xe2, (byte) 0xf3, (byte) 0x54, - (byte) 0x51, (byte) 0xeb, (byte) 0xba, (byte) 0x7c, (byte) 0x2a, (byte) 0x22, - (byte) 0xc6, (byte) 0x42, (byte) 0xbc, (byte) 0xa1, (byte) 0x6c, (byte) 0xcf, - (byte) 0x73, (byte) 0x2e, (byte) 0x07, (byte) 0xfc, (byte) 0xf5, (byte) 0x67, - (byte) 0x25, (byte) 0xd0, (byte) 0xfa, (byte) 0xeb, (byte) 0xb4, (byte) 0xd4, - (byte) 0x19, (byte) 0xcc, (byte) 0x64, (byte) 0xa1, (byte) 0x2e, (byte) 0x78, - (byte) 0x45, (byte) 0xd9, (byte) 0x7f, (byte) 0x1b, (byte) 0x4c, (byte) 0x10, - (byte) 0x31, (byte) 0x44, (byte) 0xe8, (byte) 0xcc, (byte) 0xf9, (byte) 0x1b, - (byte) 0x87, (byte) 0x31, (byte) 0xd6, (byte) 0x69, (byte) 0x85, (byte) 0x4a, - (byte) 0x49, (byte) 0xf6, (byte) 0xb2, (byte) 0xe0, (byte) 0xb8, (byte) 0x98, - (byte) 0x3c, (byte) 0xf6, (byte) 0x78, (byte) 0x46, (byte) 0xc8, (byte) 0x3d, - (byte) 0x60, (byte) 0xc1, (byte) 0xaa, (byte) 0x2f, (byte) 0x28, (byte) 0xa1, - (byte) 0x14, (byte) 0x6b, (byte) 0x75, (byte) 0x4d, (byte) 0xb1, (byte) 0x3d, - (byte) 0x80, (byte) 0x49, (byte) 0x33, (byte) 0xfd, (byte) 0x71, (byte) 0xc0, - (byte) 0x13, (byte) 0x1e, (byte) 0x16, (byte) 0x69, (byte) 0x80, (byte) 0xa4, - (byte) 0x9c, (byte) 0xd7, (byte) 0x02, (byte) 0x81, (byte) 0xc1, (byte) 0x00, - (byte) 0x8c, (byte) 0x33, (byte) 0x2d, (byte) 0xd9, (byte) 0xf3, (byte) 0x42, - (byte) 0x4d, (byte) 0xca, (byte) 0x5e, (byte) 0x60, (byte) 0x14, (byte) 0x10, - (byte) 0xf6, (byte) 0xf3, (byte) 0x71, (byte) 0x15, (byte) 0x88, (byte) 0x54, - (byte) 0x84, (byte) 0x21, (byte) 0x04, (byte) 0xb1, (byte) 0xaf, (byte) 0x02, - (byte) 0x11, (byte) 0x7f, (byte) 0x42, (byte) 0x3e, (byte) 0x86, (byte) 0xcb, - (byte) 0x6c, (byte) 0xf5, (byte) 0x57, (byte) 0x78, (byte) 0x4a, (byte) 0x03, - (byte) 0x9b, (byte) 0x80, (byte) 0xc2, (byte) 0x04, (byte) 0x3a, (byte) 0x6b, - (byte) 0xb3, (byte) 0x30, (byte) 0x31, (byte) 0x7e, (byte) 0xc3, (byte) 0x89, - (byte) 0x09, (byte) 0x4e, (byte) 0x86, (byte) 0x59, (byte) 0x41, (byte) 0xb5, - (byte) 0xae, (byte) 0xd5, (byte) 0xc6, (byte) 0x38, (byte) 0xbc, (byte) 0xd7, - (byte) 0xd7, (byte) 0x8e, (byte) 0xa3, (byte) 0x1a, (byte) 0xde, (byte) 0x32, - (byte) 0xad, (byte) 0x8d, (byte) 0x15, (byte) 0x81, (byte) 0xfe, (byte) 0xac, - (byte) 0xbd, (byte) 0xd0, (byte) 0xca, (byte) 0xbc, (byte) 0xd8, (byte) 0x6a, - (byte) 0xe1, (byte) 0xfe, (byte) 0xda, (byte) 0xc4, (byte) 0xd8, (byte) 0x62, - (byte) 0x71, (byte) 0x20, (byte) 0xa3, (byte) 0xd3, (byte) 0x06, (byte) 0x11, - (byte) 0xa9, (byte) 0x53, (byte) 0x7a, (byte) 0x44, (byte) 0x89, (byte) 0x3d, - (byte) 0x28, (byte) 0x5e, (byte) 0x7d, (byte) 0xf0, (byte) 0x60, (byte) 0xeb, - (byte) 0xb5, (byte) 0xdf, (byte) 0xed, (byte) 0x4f, (byte) 0x6d, (byte) 0x05, - (byte) 0x59, (byte) 0x06, (byte) 0xb0, (byte) 0x62, (byte) 0x50, (byte) 0x1c, - (byte) 0xb7, (byte) 0x2c, (byte) 0x44, (byte) 0xa4, (byte) 0x49, (byte) 0xf8, - (byte) 0x4f, (byte) 0x4b, (byte) 0xab, (byte) 0x71, (byte) 0x5b, (byte) 0xcb, - (byte) 0x31, (byte) 0x10, (byte) 0x41, (byte) 0xe0, (byte) 0x1a, (byte) 0x15, - (byte) 0xdc, (byte) 0x4c, (byte) 0x5d, (byte) 0x4f, (byte) 0x62, (byte) 0x83, - (byte) 0xa4, (byte) 0x80, (byte) 0x06, (byte) 0x36, (byte) 0xba, (byte) 0xc9, - (byte) 0xe2, (byte) 0xa4, (byte) 0x11, (byte) 0x98, (byte) 0x6b, (byte) 0x4c, - (byte) 0xe9, (byte) 0x90, (byte) 0x55, (byte) 0x18, (byte) 0xde, (byte) 0xe1, - (byte) 0x42, (byte) 0x38, (byte) 0x28, (byte) 0xa3, (byte) 0x54, (byte) 0x56, - (byte) 0x31, (byte) 0xaf, (byte) 0x5a, (byte) 0xd6, (byte) 0xf0, (byte) 0x26, - (byte) 0xe0, (byte) 0x7a, (byte) 0xd9, (byte) 0x6c, (byte) 0x64, (byte) 0xca, - (byte) 0x5d, (byte) 0x6d, (byte) 0x3d, (byte) 0x9a, (byte) 0xfe, (byte) 0x36, - (byte) 0x93, (byte) 0x9e, (byte) 0x62, (byte) 0x94, (byte) 0xc6, (byte) 0x07, - (byte) 0x83, (byte) 0x96, (byte) 0xd6, (byte) 0x27, (byte) 0xa6, (byte) 0xd8 - }; - public static final PrivateKey CLIENT_SUITE_B_RSA3072_KEY = - loadPrivateKey("RSA", CLIENT_SUITE_B_RSA3072_KEY_DATA); - - private static final String CLIENT_SUITE_B_ECDSA_CERT_STRING = - "-----BEGIN CERTIFICATE-----\n" - + "MIIB9zCCAX4CFDpfSZh3AH07BEfGWuMDa7Ynz6y+MAoGCCqGSM49BAMDMF4xCzAJ\n" - + "BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDTVRWMRAwDgYDVQQKDAdB\n" - + "bmRyb2lkMQ4wDAYDVQQLDAVXaS1GaTESMBAGA1UEAwwJdW5pdGVzdENBMB4XDTIw\n" - + "MDcyMTAyMjk1MFoXDTMwMDUzMDAyMjk1MFowYjELMAkGA1UEBhMCVVMxCzAJBgNV\n" - + "BAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNVBAoMB0FuZHJvaWQxDjAMBgNVBAsM\n" - + "BVdpLUZpMRYwFAYDVQQDDA11bml0ZXN0Q2xpZW50MHYwEAYHKoZIzj0CAQYFK4EE\n" - + "ACIDYgAEhxhVJ7dcSqrto0X+dgRxtd8BWG8cWmPjBji3MIxDLfpcMDoIB84ae1Ew\n" - + "gJn4YUYHrWsUDiVNihv8j7a/Ol1qcIY2ybH7tbezefLmagqA4vXEUXZXoUyL4ZNC\n" - + "DWcdw6LrMAoGCCqGSM49BAMDA2cAMGQCMH4aP73HrriRUJRguiuRic+X4Cqj/7YQ\n" - + "ueJmP87KF92/thhoQ9OrRo8uJITPmNDswwIwP2Q1AZCSL4BI9dYrqu07Ar+pSkXE\n" - + "R7oOqGdZR+d/MvXcFSrbIaLKEoHXmQamIHLe\n" - + "-----END CERTIFICATE-----\n"; - public static final X509Certificate CLIENT_SUITE_B_ECDSA_CERT = - loadCertificate(CLIENT_SUITE_B_ECDSA_CERT_STRING); - - private static final byte[] CLIENT_SUITE_B_ECC_KEY_DATA = new byte[]{ - (byte) 0x30, (byte) 0x81, (byte) 0xb6, (byte) 0x02, (byte) 0x01, (byte) 0x00, - (byte) 0x30, (byte) 0x10, (byte) 0x06, (byte) 0x07, (byte) 0x2a, (byte) 0x86, - (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x02, (byte) 0x01, (byte) 0x06, - (byte) 0x05, (byte) 0x2b, (byte) 0x81, (byte) 0x04, (byte) 0x00, (byte) 0x22, - (byte) 0x04, (byte) 0x81, (byte) 0x9e, (byte) 0x30, (byte) 0x81, (byte) 0x9b, - (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x04, (byte) 0x30, (byte) 0xea, - (byte) 0x6c, (byte) 0x4b, (byte) 0x6d, (byte) 0x43, (byte) 0xf9, (byte) 0x6c, - (byte) 0x91, (byte) 0xdc, (byte) 0x2d, (byte) 0x6e, (byte) 0x87, (byte) 0x4f, - (byte) 0x0a, (byte) 0x0b, (byte) 0x97, (byte) 0x25, (byte) 0x1c, (byte) 0x79, - (byte) 0xa2, (byte) 0x07, (byte) 0xdc, (byte) 0x94, (byte) 0xc2, (byte) 0xee, - (byte) 0x64, (byte) 0x51, (byte) 0x6d, (byte) 0x4e, (byte) 0x35, (byte) 0x1c, - (byte) 0x22, (byte) 0x2f, (byte) 0xc0, (byte) 0xea, (byte) 0x09, (byte) 0x47, - (byte) 0x3e, (byte) 0xb9, (byte) 0xb6, (byte) 0xb8, (byte) 0x83, (byte) 0x9e, - (byte) 0xed, (byte) 0x59, (byte) 0xe5, (byte) 0xe7, (byte) 0x0f, (byte) 0xa1, - (byte) 0x64, (byte) 0x03, (byte) 0x62, (byte) 0x00, (byte) 0x04, (byte) 0x87, - (byte) 0x18, (byte) 0x55, (byte) 0x27, (byte) 0xb7, (byte) 0x5c, (byte) 0x4a, - (byte) 0xaa, (byte) 0xed, (byte) 0xa3, (byte) 0x45, (byte) 0xfe, (byte) 0x76, - (byte) 0x04, (byte) 0x71, (byte) 0xb5, (byte) 0xdf, (byte) 0x01, (byte) 0x58, - (byte) 0x6f, (byte) 0x1c, (byte) 0x5a, (byte) 0x63, (byte) 0xe3, (byte) 0x06, - (byte) 0x38, (byte) 0xb7, (byte) 0x30, (byte) 0x8c, (byte) 0x43, (byte) 0x2d, - (byte) 0xfa, (byte) 0x5c, (byte) 0x30, (byte) 0x3a, (byte) 0x08, (byte) 0x07, - (byte) 0xce, (byte) 0x1a, (byte) 0x7b, (byte) 0x51, (byte) 0x30, (byte) 0x80, - (byte) 0x99, (byte) 0xf8, (byte) 0x61, (byte) 0x46, (byte) 0x07, (byte) 0xad, - (byte) 0x6b, (byte) 0x14, (byte) 0x0e, (byte) 0x25, (byte) 0x4d, (byte) 0x8a, - (byte) 0x1b, (byte) 0xfc, (byte) 0x8f, (byte) 0xb6, (byte) 0xbf, (byte) 0x3a, - (byte) 0x5d, (byte) 0x6a, (byte) 0x70, (byte) 0x86, (byte) 0x36, (byte) 0xc9, - (byte) 0xb1, (byte) 0xfb, (byte) 0xb5, (byte) 0xb7, (byte) 0xb3, (byte) 0x79, - (byte) 0xf2, (byte) 0xe6, (byte) 0x6a, (byte) 0x0a, (byte) 0x80, (byte) 0xe2, - (byte) 0xf5, (byte) 0xc4, (byte) 0x51, (byte) 0x76, (byte) 0x57, (byte) 0xa1, - (byte) 0x4c, (byte) 0x8b, (byte) 0xe1, (byte) 0x93, (byte) 0x42, (byte) 0x0d, - (byte) 0x67, (byte) 0x1d, (byte) 0xc3, (byte) 0xa2, (byte) 0xeb - }; - public static final PrivateKey CLIENT_SUITE_B_ECC_KEY = - loadPrivateKey("EC", CLIENT_SUITE_B_ECC_KEY_DATA); - - private static X509Certificate loadCertificate(String blob) { - try { - final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - InputStream stream = new ByteArrayInputStream(blob.getBytes(StandardCharsets.UTF_8)); - - return (X509Certificate) certFactory.generateCertificate(stream); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - private static PrivateKey loadPrivateKey(String algorithm, byte[] fakeKey) { - try { - KeyFactory kf = KeyFactory.getInstance(algorithm); - return kf.generatePrivate(new PKCS8EncodedKeySpec(fakeKey)); - } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { - return null; - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java b/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java deleted file mode 100644 index bd9a1691a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java +++ /dev/null @@ -1,3301 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static com.android.server.wifi.HalDeviceManager.START_HAL_RETRY_TIMES; - -import static junit.framework.Assert.assertEquals; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil; -import android.hardware.wifi.V1_0.IWifi; -import android.hardware.wifi.V1_0.IWifiApIface; -import android.hardware.wifi.V1_0.IWifiChip; -import android.hardware.wifi.V1_0.IWifiChipEventCallback; -import android.hardware.wifi.V1_0.IWifiEventCallback; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.IWifiP2pIface; -import android.hardware.wifi.V1_0.IWifiRttController; -import android.hardware.wifi.V1_0.IWifiStaIface; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hidl.manager.V1_0.IServiceNotification; -import android.hidl.manager.V1_2.IServiceManager; -import android.os.Handler; -import android.os.IHwBinder; -import android.os.test.TestLooper; -import android.util.Log; -import android.util.SparseArray; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; - -import org.hamcrest.core.IsNull; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Unit test harness for HalDeviceManagerTest. - */ -@SmallTest -public class HalDeviceManagerTest extends WifiBaseTest { - private HalDeviceManager mDut; - @Mock IServiceManager mServiceManagerMock; - @Mock IWifi mWifiMock; - @Mock IWifiRttController mRttControllerMock; - @Mock HalDeviceManager.ManagerStatusListener mManagerStatusListenerMock; - @Mock private Clock mClock; - private TestLooper mTestLooper; - private Handler mHandler; - private ArgumentCaptor<IHwBinder.DeathRecipient> mDeathRecipientCaptor = - ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); - private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor = - ArgumentCaptor.forClass(IServiceNotification.Stub.class); - private ArgumentCaptor<IWifiEventCallback> mWifiEventCallbackCaptor = ArgumentCaptor.forClass( - IWifiEventCallback.class); - private InOrder mInOrder; - @Rule public ErrorCollector collector = new ErrorCollector(); - private WifiStatus mStatusOk; - private WifiStatus mStatusFail; - - private class HalDeviceManagerSpy extends HalDeviceManager { - HalDeviceManagerSpy() { - super(mClock, mHandler); - } - - @Override - protected IWifi getWifiServiceMockable() { - return mWifiMock; - } - - @Override - protected IServiceManager getServiceManagerMockable() { - return mServiceManagerMock; - } - } - - @Before - public void before() throws Exception { - MockitoAnnotations.initMocks(this); - - mTestLooper = new TestLooper(); - mHandler = new Handler(mTestLooper.getLooper()); - - // initialize dummy status objects - mStatusOk = getStatus(WifiStatusCode.SUCCESS); - mStatusFail = getStatus(WifiStatusCode.ERROR_UNKNOWN); - - when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), - any(IServiceNotification.Stub.class))).thenReturn(true); - when(mServiceManagerMock.listManifestByInterface(eq(IWifi.kInterfaceName))) - .thenReturn(new ArrayList(Arrays.asList("default"))); - when(mWifiMock.linkToDeath(any(IHwBinder.DeathRecipient.class), anyLong())).thenReturn( - true); - when(mWifiMock.registerEventCallback(any(IWifiEventCallback.class))).thenReturn(mStatusOk); - when(mWifiMock.start()).thenReturn(mStatusOk); - when(mWifiMock.stop()).thenReturn(mStatusOk); - when(mWifiMock.isStarted()).thenReturn(true); - - mDut = new HalDeviceManagerSpy(); - } - - /** - * Print out the dump of the device manager after each test. Not used in test validation - * (internal state) - but can help in debugging failed tests. - */ - @After - public void after() throws Exception { - dumpDut("after: "); - } - - ////////////////////////////////////////////////////////////////////////////////////// - // Chip Independent Tests - ////////////////////////////////////////////////////////////////////////////////////// - - /** - * Test basic startup flow: - * - IServiceManager registrations - * - IWifi registrations - * - IWifi startup delayed - * - Start Wi-Fi -> onStart - * - Stop Wi-Fi -> onStop - */ - @Test - public void testStartStopFlow() throws Exception { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // act: stop Wi-Fi - mDut.stop(); - mTestLooper.dispatchAll(); - - // verify: onStop called - mInOrder.verify(mWifiMock).stop(); - mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); - - verifyNoMoreInteractions(mManagerStatusListenerMock); - } - - /** - * Test the service manager notification coming in after - * {@link HalDeviceManager#initIWifiIfNecessary()} is already invoked as a part of - * {@link HalDeviceManager#initialize()}. - */ - @Test - public void testServiceRegisterationAfterInitialize() throws Exception { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - - // This should now be ignored since IWifi is already non-null. - mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", true); - - verifyNoMoreInteractions(mManagerStatusListenerMock, mWifiMock, mServiceManagerMock); - } - - /** - * Validate that multiple callback registrations are called and that duplicate ones are - * only called once. - */ - @Test - public void testMultipleCallbackRegistrations() throws Exception { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - - // register another 2 callbacks - one of them twice - HalDeviceManager.ManagerStatusListener callback1 = mock( - HalDeviceManager.ManagerStatusListener.class); - HalDeviceManager.ManagerStatusListener callback2 = mock( - HalDeviceManager.ManagerStatusListener.class); - mDut.registerStatusListener(callback2, mHandler); - mDut.registerStatusListener(callback1, mHandler); - mDut.registerStatusListener(callback2, mHandler); - - // startup - executeAndValidateStartupSequence(); - - // verify - verify(callback1).onStatusChanged(); - verify(callback2).onStatusChanged(); - - verifyNoMoreInteractions(mManagerStatusListenerMock, callback1, callback2); - } - - /** - * Validate IWifi death listener and registration flow. - */ - @Test - public void testWifiDeathAndRegistration() throws Exception { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // act: IWifi service death - mDeathRecipientCaptor.getValue().serviceDied(0); - mTestLooper.dispatchAll(); - - // verify: getting onStop - mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); - - // act: service startup - mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", false); - - // verify: initialization of IWifi - mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong()); - mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture()); - - // act: start - collector.checkThat(mDut.start(), equalTo(true)); - mWifiEventCallbackCaptor.getValue().onStart(); - mTestLooper.dispatchAll(); - - // verify: service and callback calls - mInOrder.verify(mWifiMock).start(); - mInOrder.verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); - - verifyNoMoreInteractions(mManagerStatusListenerMock); - } - - /** - * Validate IWifi onFailure causes notification - */ - @Test - public void testWifiFail() throws Exception { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // act: IWifi failure - mWifiEventCallbackCaptor.getValue().onFailure(mStatusFail); - mTestLooper.dispatchAll(); - - // verify: getting onStop - mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); - - // act: start again - collector.checkThat(mDut.start(), equalTo(true)); - mWifiEventCallbackCaptor.getValue().onStart(); - mTestLooper.dispatchAll(); - - // verify: service and callback calls - mInOrder.verify(mWifiMock).start(); - mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); - - verifyNoMoreInteractions(mManagerStatusListenerMock); - } - - /** - * Validates that when (for some reason) the cache is out-of-sync with the actual chip status - * then Wi-Fi is shut-down. - * - * Uses TestChipV1 - but nothing specific to its configuration. The test validates internal - * HDM behavior. - */ - @Test - public void testCacheMismatchError() throws Exception { - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener staDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener nanDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InOrder availInOrder = inOrder(staAvailListener, nanAvailListener); - - // Request STA - IWifiIface staIface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener, // destroyedListener - staAvailListener // availableListener - ); - availInOrder.verify(staAvailListener).onAvailabilityChanged(false); - - // Request NAN - IWifiIface nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.STA_CHIP_MODE_ID, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - nanAvailListener // availableListener - ); - availInOrder.verify(nanAvailListener).onAvailabilityChanged(false); - - // fiddle with the "chip" by removing the STA - chipMock.interfaceNames.get(IfaceType.STA).remove("wlan0"); - - // now try to request another NAN - IWifiIface nanIface2 = mDut.createNanIface(nanDestroyedListener, mHandler); - collector.checkThat("NAN can't be created", nanIface2, IsNull.nullValue()); - - mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener, - mHandler); - mTestLooper.dispatchAll(); - - // extra (apparently duplicate) call since everything was cleaned-up once a cache mismatch - // was detected - so this is a call on a new registration - availInOrder.verify(nanAvailListener).onAvailabilityChanged(false); - - // verify that Wi-Fi is shut-down: should also get all onDestroyed messages that are - // registered (even if they seem out-of-sync to chip) - verify(mWifiMock, times(2)).stop(); - verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); - verify(staDestroyedListener).onDestroyed(getName(staIface)); - verify(nanDestroyedListener).onDestroyed(getName(nanIface)); - - verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener, - nanDestroyedListener, nanAvailListener); - } - - /** - * Validates that a duplicate registration of the same InterfaceAvailableForRequestListener - * listener will result in a single callback. - * - * Also validates that get an immediate call on registration if available. - * - * Uses TestChipV1 - but nothing specific to its configuration. The test validates internal - * HDM behavior. - */ - @Test - public void testDuplicateAvailableRegistrations() throws Exception { - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - // get STA interface - IWifiIface staIface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - null, // destroyedListener - null // availableListener - ); - collector.checkThat("STA created", staIface, IsNull.notNullValue()); - - // act: register the same listener twice - mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener, - mHandler); - mTestLooper.dispatchAll(); - - verify(staAvailListener).onAvailabilityChanged(false); - - // remove STA interface -> should trigger callbacks - mDut.removeIface(staIface); - mTestLooper.dispatchAll(); - - // verify: only a single trigger - verify(staAvailListener).onAvailabilityChanged(true); - - verifyNoMoreInteractions(staAvailListener); - } - - /** - * Validate that when no chip info is found an empty list is returned. - */ - @Test - public void testGetSupportedIfaceTypesError() throws Exception { - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(); - - // verify results - assertEquals(0, results.size()); - } - - /** - * Test start HAL can retry upon failure. - * - * Uses TestChipV1 - but nothing specific to its configuration. The test validates internal - * HDM behavior. - */ - @Test - public void testStartHalRetryUponNotAvailableFailure() throws Exception { - // Override the stubbing for mWifiMock in before(). - when(mWifiMock.start()) - .thenReturn(getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE)) - .thenReturn(mStatusOk); - - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(2, true); - } - - /** - * Test start HAL fails after multiple retry failures. - * - * Uses TestChipV1 - but nothing specific to its configuration. The test validates internal - * HDM behavior. - */ - @Test - public void testStartHalRetryFailUponMultipleNotAvailableFailures() throws Exception { - // Override the stubbing for mWifiMock in before(). - when(mWifiMock.start()).thenReturn(getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE)); - - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(START_HAL_RETRY_TIMES + 1, false); - } - - /** - * Test start HAL fails after multiple retry failures. - * - * Uses TestChipV1 - but nothing specific to its configuration. The test validates internal - * HDM behavior. - */ - @Test - public void testStartHalRetryFailUponTrueFailure() throws Exception { - // Override the stubbing for mWifiMock in before(). - when(mWifiMock.start()).thenReturn(getStatus(WifiStatusCode.ERROR_UNKNOWN)); - - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(1, false); - } - - /** - * Validate that isSupported() returns true when IServiceManager finds the vendor HAL daemon in - * the VINTF. - */ - @Test - public void testIsSupportedTrue() throws Exception { - mInOrder = inOrder(mServiceManagerMock, mWifiMock); - executeAndValidateInitializationSequence(); - assertTrue(mDut.isSupported()); - } - - /** - * Validate that isSupported() returns false when IServiceManager does not find the vendor HAL - * daemon in the VINTF. - */ - @Test - public void testIsSupportedFalse() throws Exception { - when(mServiceManagerMock.listManifestByInterface(eq(IWifi.kInterfaceName))) - .thenReturn(new ArrayList()); - mInOrder = inOrder(mServiceManagerMock, mWifiMock); - executeAndValidateInitializationSequence(false); - assertFalse(mDut.isSupported()); - } - - /** - * Validate RTT configuration when the callback is registered first and the chip is - * configured later - i.e. RTT isn't available immediately. - */ - @Test - public void testAndTriggerRttLifecycleCallbacksRegBeforeChipConfig() throws Exception { - HalDeviceManager.InterfaceRttControllerLifecycleCallback cb = mock( - HalDeviceManager.InterfaceRttControllerLifecycleCallback.class); - - InOrder io = inOrder(cb); - - // initialize a test chip (V1 is fine since we're not testing any specifics of - // concurrency in this test). - ChipMockBase chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // register initial cb: don't expect RTT since chip isn't configured - mDut.registerRttControllerLifecycleCallback(cb, mHandler); - mTestLooper.dispatchAll(); - io.verify(cb, times(0)).onNewRttController(any()); - - // create a STA - that will get the chip configured and get us an RTT controller - validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, - "wlan0", - TestChipV1.STA_CHIP_MODE_ID, - null, // tearDownList - null, // destroyedListener - null // availableListener - ); - verify(chipMock.chip).createRttController(any(), any()); - io.verify(cb).onNewRttController(any()); - - verifyNoMoreInteractions(cb); - } - - /** - * Validate the RTT Controller lifecycle using a multi-mode chip (i.e. a chip which can - * switch modes, during which RTT is destroyed). - * - * 1. Validate that an RTT is created as soon as the callback is registered - if the chip - * is already configured (i.e. it is possible to create the RTT controller). - * - * 2. Validate that only the registered callback is triggered, not previously registered ones - * and not duplicate ones. - * - * 3. Validate that onDestroy callbacks are triggered on mode change. - */ - @Test - public void testAndTriggerRttLifecycleCallbacksMultiModeChip() throws Exception { - HalDeviceManager.InterfaceRttControllerLifecycleCallback cb1 = mock( - HalDeviceManager.InterfaceRttControllerLifecycleCallback.class); - HalDeviceManager.InterfaceRttControllerLifecycleCallback cb2 = mock( - HalDeviceManager.InterfaceRttControllerLifecycleCallback.class); - - InOrder io1 = inOrder(cb1); - InOrder io2 = inOrder(cb2); - - // initialize a test chip (V1 is a must since we're testing a multi-mode chip) & create a - // STA (which will configure the chip). - ChipMockBase chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, - "wlan0", - TestChipV1.STA_CHIP_MODE_ID, - null, // tearDownList - null, // destroyedListener - null // availableListener - ); - mInOrder.verify(chipMock.chip, times(0)).createRttController(any(), any()); - - // register initial cb - expect the cb right away - mDut.registerRttControllerLifecycleCallback(cb1, mHandler); - mTestLooper.dispatchAll(); - verify(chipMock.chip).createRttController(any(), any()); - io1.verify(cb1).onNewRttController(mRttControllerMock); - - // register a second callback and the first one again - mDut.registerRttControllerLifecycleCallback(cb2, mHandler); - mDut.registerRttControllerLifecycleCallback(cb1, mHandler); - mTestLooper.dispatchAll(); - io2.verify(cb2).onNewRttController(mRttControllerMock); - - // change to AP mode (which for TestChipV1 doesn't allow RTT): trigger onDestroyed for all - validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.STA_CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) - IfaceType.AP, - "wlan0", - TestChipV1.AP_CHIP_MODE_ID, - null, // tearDownList - null, // destroyedListener - null // availableListener - ); - mTestLooper.dispatchAll(); - verify(chipMock.chip, times(2)).createRttController(any(), any()); // but returns a null! - io1.verify(cb1).onRttControllerDestroyed(); - io2.verify(cb2).onRttControllerDestroyed(); - - // change back to STA mode (which for TestChipV1 will re-allow RTT): trigger onNew for all - validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.AP_CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, - "wlan0", - TestChipV1.STA_CHIP_MODE_ID, - null, // tearDownList - null, // destroyedListener - null // availableListener - ); - mTestLooper.dispatchAll(); - verify(chipMock.chip, times(3)).createRttController(any(), any()); - io1.verify(cb1).onNewRttController(mRttControllerMock); - io2.verify(cb2).onNewRttController(mRttControllerMock); - - verifyNoMoreInteractions(cb1, cb2); - } - - /** - * Validate the RTT Controller lifecycle using a single-mode chip. Specifically validate - * that RTT isn't impacted during STA -> AP change. - */ - @Test - public void testAndTriggerRttLifecycleCallbacksSingleModeChip() throws Exception { - HalDeviceManager.InterfaceRttControllerLifecycleCallback cb = mock( - HalDeviceManager.InterfaceRttControllerLifecycleCallback.class); - - InOrder io = inOrder(cb); - - // initialize a test chip (V2 is a must since we need a single mode chip) - // & create a STA (which will configure the chip). - ChipMockBase chipMock = new TestChipV2(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, - "wlan0", - TestChipV2.CHIP_MODE_ID, - null, // tearDownList - null, // destroyedListener - null // availableListener - ); - mInOrder.verify(chipMock.chip, times(0)).createRttController(any(), any()); - - // register initial cb - expect the cb right away - mDut.registerRttControllerLifecycleCallback(cb, mHandler); - mTestLooper.dispatchAll(); - verify(chipMock.chip).createRttController(any(), any()); - io.verify(cb).onNewRttController(mRttControllerMock); - - // create an AP: no mode change for TestChipV2 -> expect no impact on RTT - validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV2.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) - IfaceType.AP, - "wlan0", - TestChipV2.CHIP_MODE_ID, - null, // tearDownList - null, // destroyedListener - null // availableListener - ); - mTestLooper.dispatchAll(); - - verifyNoMoreInteractions(cb); - } - - ////////////////////////////////////////////////////////////////////////////////////// - // Chip Specific Tests - but should work on all chips! - // (i.e. add copies for each test chip) - ////////////////////////////////////////////////////////////////////////////////////// - - // TestChipV1 - - /** - * Validate creation of STA interface from blank start-up. The remove interface. - */ - @Test - public void testCreateStaInterfaceNoInitModeTestChipV1() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.STA, "wlan0", - TestChipV1.STA_CHIP_MODE_ID, false); - } - - /** - * Validate creation of AP interface from blank start-up. The remove interface. - */ - @Test - public void testCreateApInterfaceNoInitModeTestChipV1() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.AP, "wlan0", - TestChipV1.AP_CHIP_MODE_ID, false); - } - - /** - * Validate creation of P2P interface from blank start-up. The remove interface. - */ - @Test - public void testCreateP2pInterfaceNoInitModeTestChipV1() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.P2P, "p2p0", - TestChipV1.STA_CHIP_MODE_ID, false); - } - - /** - * Validate creation of NAN interface from blank start-up. The remove interface. - */ - @Test - public void testCreateNanInterfaceNoInitModeTestChipV1() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.NAN, "wlan0", - TestChipV1.STA_CHIP_MODE_ID, false); - } - - // TestChipV2 - - /** - * Validate creation of STA interface from blank start-up. The remove interface. - */ - @Test - public void testCreateStaInterfaceNoInitModeTestChipV2() throws Exception { - // Note: we expected 2 available callbacks since we now have 2 STAs possible. So - // we get callback 1 after creating the first STA (since we can create another STA), - // and we get callback 2 after destroying the first STA (since we can create another STA - - // as expected). - runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.STA, "wlan0", - TestChipV2.CHIP_MODE_ID, true); - } - - /** - * Validate creation of AP interface from blank start-up. The remove interface. - */ - @Test - public void testCreateApInterfaceNoInitModeTestChipV2() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.AP, "wlan0", - TestChipV2.CHIP_MODE_ID, false); - } - - /** - * Validate creation of P2P interface from blank start-up. The remove interface. - */ - @Test - public void testCreateP2pInterfaceNoInitModeTestChipV2() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.P2P, "p2p0", - TestChipV2.CHIP_MODE_ID, false); - } - - /** - * Validate creation of NAN interface from blank start-up. The remove interface. - */ - @Test - public void testCreateNanInterfaceNoInitModeTestChipV2() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.NAN, "wlan0", - TestChipV2.CHIP_MODE_ID, false); - } - - // TestChipV3 - - /** - * Validate creation of STA interface from blank start-up. The remove interface. - */ - @Test - public void testCreateStaInterfaceNoInitModeTestChipV3() throws Exception { - // Note: we expected 2 available callbacks since we now have 2 STAs possible. So - // we get callback 1 after creating the first STA (since we can create another STA), - // and we get callback 2 after destroying the first STA (since we can create another STA - - // as expected). - runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.STA, "wlan0", - TestChipV3.CHIP_MODE_ID, true); - } - - /** - * Validate creation of AP interface from blank start-up. The remove interface. - */ - @Test - public void testCreateApInterfaceNoInitModeTestChipV3() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.AP, "wlan0", - TestChipV3.CHIP_MODE_ID, false); - } - - /** - * Validate creation of P2P interface from blank start-up. The remove interface. - */ - @Test - public void testCreateP2pInterfaceNoInitModeTestChipV3() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.P2P, "p2p0", - TestChipV3.CHIP_MODE_ID, false); - } - - /** - * Validate creation of NAN interface from blank start-up. The remove interface. - */ - @Test - public void testCreateNanInterfaceNoInitModeTestChipV3() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.NAN, "wlan0", - TestChipV3.CHIP_MODE_ID, false); - } - - // TestChipV4 - - /** - * Validate creation of STA interface from blank start-up. The remove interface. - */ - @Test - public void testCreateStaInterfaceNoInitModeTestChipV4() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV4(), IfaceType.STA, "wlan0", - TestChipV4.CHIP_MODE_ID, false); - } - - /** - * Validate creation of AP interface from blank start-up. The remove interface. - */ - @Test - public void testCreateApInterfaceNoInitModeTestChipV4() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV4(), IfaceType.AP, "wlan0", - TestChipV4.CHIP_MODE_ID, false); - } - - /** - * Validate creation of P2P interface from blank start-up. The remove interface. - */ - @Test - public void testCreateP2pInterfaceNoInitModeTestChipV4() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV4(), IfaceType.P2P, "p2p0", - TestChipV4.CHIP_MODE_ID, false); - } - - /** - * Validate creation of NAN interface from blank start-up. The remove interface. - */ - @Test - public void testCreateNanInterfaceNoInitModeTestChipV4() throws Exception { - runCreateSingleXxxInterfaceNoInitMode(new TestChipV4(), IfaceType.NAN, "wlan0", - TestChipV4.CHIP_MODE_ID, false); - } - - ////////////////////////////////////////////////////////////////////////////////////// - // TestChipV1 Specific Tests - ////////////////////////////////////////////////////////////////////////////////////// - - /** - * Validate creation of AP interface when in STA mode - but with no interface created. Expect - * a change in chip mode. - */ - @Test - public void testCreateApWithStaModeUpTestChipV1() throws Exception { - final String name = "wlan0"; - - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener idl = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.STA_CHIP_MODE_ID, // chipModeId - IfaceType.AP, // ifaceTypeToCreate - name, // ifaceName - TestChipV1.AP_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - idl, // destroyedListener - iafrl // availableListener - ); - collector.checkThat("allocated interface", iface, IsNull.notNullValue()); - - verify(iafrl).onAvailabilityChanged(false); - - // act: stop Wi-Fi - mDut.stop(); - mTestLooper.dispatchAll(); - - // verify: callback triggered - verify(idl).onDestroyed(getName(iface)); - verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); - - verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); - } - - /** - * Validate creation of AP interface when in STA mode with a single STA iface created. - * Expect a change in chip mode. - */ - @Test - public void testCreateApWithStIfaceUpTestChipV1UsingNoHandlerListeners() throws Exception { - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - - InterfaceDestroyedListener staIdl = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener staIafrl = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - InterfaceDestroyedListener apIdl = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener apIafrl = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock, staIdl, staIafrl, apIdl, apIafrl); - executeAndValidateInitializationSequence(); - - // Register listener & start Wi-Fi - mDut.registerStatusListener(mManagerStatusListenerMock, null); - assertTrue(mDut.start()); - mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); - - mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staIafrl, null); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.AP, apIafrl, null); - - mInOrder.verify(staIafrl).onAvailabilityChanged(true); - mInOrder.verify(apIafrl).onAvailabilityChanged(true); - - // Create STA Iface first. - IWifiStaIface staIface = mock(IWifiStaIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.STA)).when(staIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, staIface)).when( - chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); - assertEquals(staIface, mDut.createStaIface(staIdl, null)); - - mInOrder.verify(chipMock.chip).configureChip(TestChipV1.STA_CHIP_MODE_ID); - mInOrder.verify(staIafrl).onAvailabilityChanged(false); - - // Now Create AP Iface. - IWifiApIface apIface = mock(IWifiApIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(apIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.AP)).when(apIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, apIface)).when( - chipMock.chip).createApIface(any(IWifiChip.createApIfaceCallback.class)); - assertEquals(apIface, mDut.createApIface(apIdl, null)); - - mInOrder.verify(chipMock.chip).removeStaIface(getName(staIface)); - mInOrder.verify(staIdl).onDestroyed(getName(staIface)); - mInOrder.verify(chipMock.chip).configureChip(TestChipV1.AP_CHIP_MODE_ID); - mInOrder.verify(apIafrl).onAvailabilityChanged(false); - mInOrder.verify(staIafrl).onAvailabilityChanged(true); - - // Stop Wi-Fi - mDut.stop(); - - mInOrder.verify(mWifiMock).stop(); - mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); - mInOrder.verify(apIdl).onDestroyed(getName(apIface)); - - verifyNoMoreInteractions(mManagerStatusListenerMock, staIdl, staIafrl, apIdl, apIafrl); - } - - /** - * Validate creation of AP interface when in AP mode - but with no interface created. Expect - * no change in chip mode. - */ - @Test - public void testCreateApWithApModeUpTestChipV1() throws Exception { - final String name = "wlan0"; - - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener idl = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.AP_CHIP_MODE_ID, // chipModeId - IfaceType.AP, // ifaceTypeToCreate - name, // ifaceName - TestChipV1.AP_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - idl, // destroyedListener - iafrl // availableListener - ); - collector.checkThat("allocated interface", iface, IsNull.notNullValue()); - - verify(iafrl).onAvailabilityChanged(false); - - // act: stop Wi-Fi - mDut.stop(); - mTestLooper.dispatchAll(); - - // verify: callback triggered - verify(idl).onDestroyed(getName(iface)); - verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); - - verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); - } - - /** - * Validate AP up/down creation of AP interface when a STA already created. Expect: - * - STA created - * - P2P created - * - When AP requested: - * - STA & P2P torn down - * - AP created - * - P2P creation refused - * - Request STA: will tear down AP - * - When AP destroyed: - * - Get p2p available listener callback - * - Can create P2P when requested - * - Create P2P - * - Request NAN: will get refused - * - Tear down P2P: - * - should get nan available listener callback - * - Can create NAN when requested - */ - @Test - public void testCreateSameAndDiffPrioritiesTestChipV1() throws Exception { - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener staDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener staDestroyedListener2 = mock( - InterfaceDestroyedListener.class); - - InterfaceDestroyedListener apDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener apAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener p2pDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener p2pDestroyedListener2 = mock( - InterfaceDestroyedListener.class); - - InterfaceDestroyedListener nanDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InOrder inOrderAvail = inOrder(staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener); - - // register listeners for interface availability - mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.AP, apAvailListener, mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.P2P, p2pAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener, - mHandler); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - - // Request STA - IWifiIface staIface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener, // destroyedListener - null // availableListener - ); - collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue()); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false); - - // request STA2: should fail - IWifiIface staIface2 = mDut.createStaIface(null, null); - collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); - - // register additional InterfaceDestroyedListeners - including a duplicate (verify that - // only called once!) - mDut.registerDestroyedListener(staIface, staDestroyedListener2, mHandler); - mDut.registerDestroyedListener(staIface, staDestroyedListener, mHandler); - - // Request P2P - IWifiIface p2pIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.STA_CHIP_MODE_ID, // chipModeId - IfaceType.P2P, // ifaceTypeToCreate - "p2p0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - p2pDestroyedListener, // destroyedListener - null // availableListener - ); - collector.checkThat("allocated P2P interface", p2pIface, IsNull.notNullValue()); - - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false); - - // Request AP - IWifiIface apIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.STA_CHIP_MODE_ID, // chipModeId - IfaceType.AP, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV1.AP_CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{staIface, p2pIface}, // tearDownList - apDestroyedListener, // destroyedListener - null, // availableListener - // destroyedInterfacesDestroyedListeners... - new InterfaceDestroyedListenerWithIfaceName( - getName(staIface), staDestroyedListener), - new InterfaceDestroyedListenerWithIfaceName( - getName(staIface), staDestroyedListener2), - new InterfaceDestroyedListenerWithIfaceName( - getName(p2pIface), p2pDestroyedListener) - ); - collector.checkThat("allocated AP interface", apIface, IsNull.notNullValue()); - - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false); - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false); - - // request AP2: should fail - IWifiIface apIface2 = mDut.createApIface(null, null); - collector.checkThat("AP2 should not be created", apIface2, IsNull.nullValue()); - - // Request P2P: expect failure - p2pIface = mDut.createP2pIface(p2pDestroyedListener, mHandler); - collector.checkThat("P2P can't be created", p2pIface, IsNull.nullValue()); - - // Request STA: expect success - staIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.AP_CHIP_MODE_ID, // chipModeId - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener, // destroyedListener - null, // availableListener - // destroyedInterfacesDestroyedListeners... - new InterfaceDestroyedListenerWithIfaceName( - getName(apIface), apDestroyedListener) - ); - collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue()); - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - - mTestLooper.dispatchAll(); - verify(apDestroyedListener).onDestroyed(getName(apIface)); - - // Request P2P: expect success now - p2pIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.STA_CHIP_MODE_ID, // chipModeId - IfaceType.P2P, // ifaceTypeToCreate - "p2p0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - p2pDestroyedListener2, // destroyedListener - null // availableListener - ); - collector.checkThat("allocated P2P interface", p2pIface, IsNull.notNullValue()); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false); - - // create NAN: will destroy P2P - IWifiIface nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV1.STA_CHIP_MODE_ID, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - nanAvailListener, // availableListener - new InterfaceDestroyedListenerWithIfaceName("p2p0", p2pDestroyedListener2) - ); - collector.checkThat("allocated NAN interface", nanIface, IsNull.notNullValue()); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false); - - // Tear down NAN - mDut.removeIface(nanIface); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - verify(chipMock.chip, times(1)).removeNanIface("wlan0"); - verify(nanDestroyedListener).onDestroyed(getName(nanIface)); - - verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener, - staDestroyedListener2, apDestroyedListener, apAvailListener, p2pDestroyedListener, - nanDestroyedListener, nanAvailListener, p2pDestroyedListener2); - } - - /** - * Validate P2P and NAN interactions. Expect: - * - STA created - * - NAN created - * - When P2P requested: - * - NAN torn down - * - P2P created - * - NAN creation refused - * - When P2P destroyed: - * - get nan available listener - * - Can create NAN when requested - */ - @Test - public void testP2pAndNanInteractionsTestChipV1() throws Exception { - runP2pAndNanExclusiveInteractionsTestChip(new TestChipV1(), TestChipV1.STA_CHIP_MODE_ID); - } - - /** - * Validates that trying to allocate a STA and then another STA fails. Only one STA at a time - * is permitted (by TestChipV1 chip). - */ - @Test - public void testDuplicateStaRequestsTestChipV1() throws Exception { - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener staDestroyedListener1 = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener1 = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener staDestroyedListener2 = mock( - InterfaceDestroyedListener.class); - - // get STA interface - IWifiIface staIface1 = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV1.STA_CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener1, // destroyedListener - staAvailListener1 // availableListener - ); - collector.checkThat("STA created", staIface1, IsNull.notNullValue()); - - verify(staAvailListener1).onAvailabilityChanged(false); - - // get STA interface again - IWifiIface staIface2 = mDut.createStaIface(staDestroyedListener2, mHandler); - collector.checkThat("STA created", staIface2, IsNull.nullValue()); - - verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener1, - staAvailListener1, staDestroyedListener2); - } - - /** - * Validate that the getSupportedIfaceTypes API works when requesting for all chips. - */ - @Test - public void testGetSupportedIfaceTypesAllTestChipV1() throws Exception { - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(); - - // verify results - Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); - - assertEquals(correctResults, results); - } - - /** - * Validate that the getSupportedIfaceTypes API works when requesting for a specific chip. - */ - @Test - public void testGetSupportedIfaceTypesOneChipTestChipV1() throws Exception { - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(chipMock.chip); - - // verify results - Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); - - assertEquals(correctResults, results); - } - - /** - * Validate {@link HalDeviceManager#canSupportIfaceCombo(SparseArray)} - */ - @Test - public void testCanSupportIfaceComboTestChipV1() throws Exception { - final String name = "wlan0"; - - TestChipV1 chipMock = new TestChipV1(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.AP, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.P2P, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.NAN, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.P2P, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.NAN, 1); - }} - )); - - assertFalse(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.AP, 1); - }} - )); - assertFalse(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 2); - }} - )); - assertFalse(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.P2P, 1); - put(IfaceType.NAN, 1); - }} - )); - - verifyNoMoreInteractions(mManagerStatusListenerMock); - } - - - ////////////////////////////////////////////////////////////////////////////////////// - // TestChipV2 Specific Tests - ////////////////////////////////////////////////////////////////////////////////////// - - /** - * Validate a flow sequence for test chip 2: - * - create STA - * - create P2P - * - request NAN: failure - * - create AP - * - create STA: will get refused - * - create AP: will get refused - * - tear down AP - * - create STA - * - create STA: will get refused - * - create AP: should get created and the last created STA should get destroyed - * - tear down P2P - * - create NAN - */ - @Test - public void testInterfaceCreationFlowTestChipV2() throws Exception { - TestChipV2 chipMock = new TestChipV2(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener staDestroyedListener = mock( - InterfaceDestroyedListener.class); - InterfaceDestroyedListener staDestroyedListener2 = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener apDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener apAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener p2pDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener nanDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InOrder inOrderAvail = inOrder(staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener); - - // register listeners for interface availability - mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.AP, apAvailListener, mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.P2P, p2pAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener, - mHandler); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - - // create STA - when(mClock.getUptimeSinceBootMillis()).thenReturn(15L); - IWifiIface staIface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV2.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("STA interface wasn't created", staIface, IsNull.notNullValue()); - - // create P2P - IWifiIface p2pIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV2.CHIP_MODE_ID, // chipModeId - IfaceType.P2P, // ifaceTypeToCreate - "p2p0", // ifaceName - TestChipV2.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - p2pDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue()); - - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false); - - // create NAN - IWifiIface nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV2.CHIP_MODE_ID, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV2.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - null, // availableListener (already registered) - new InterfaceDestroyedListenerWithIfaceName( - getName(p2pIface), p2pDestroyedListener) - ); - collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); - - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false); - - // create AP - IWifiIface apIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV2.CHIP_MODE_ID, // chipModeId - IfaceType.AP, // ifaceTypeToCreate - "wlan1", // ifaceName - TestChipV2.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - apDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("AP interface wasn't created", apIface, IsNull.notNullValue()); - - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false); - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false); - - // request STA2: should fail - IWifiIface staIface2 = mDut.createStaIface(null, null); - collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); - - // request AP2: should fail - IWifiIface apIface2 = mDut.createApIface(null, null); - collector.checkThat("AP2 should not be created", apIface2, IsNull.nullValue()); - - // tear down AP - mDut.removeIface(apIface); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true); - verify(chipMock.chip).removeApIface("wlan1"); - verify(apDestroyedListener).onDestroyed(getName(apIface)); - - // create STA2: using a later clock - when(mClock.getUptimeSinceBootMillis()).thenReturn(20L); - staIface2 = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV2.CHIP_MODE_ID, // chipModeId - IfaceType.STA, // ifaceTypeToCreate - "wlan1", // ifaceName - TestChipV2.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener2, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("STA 2 interface wasn't created", staIface2, IsNull.notNullValue()); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false); - - // request STA3: should fail - IWifiIface staIface3 = mDut.createStaIface(null, null); - collector.checkThat("STA3 should not be created", staIface3, IsNull.nullValue()); - - // create AP - this will destroy the last STA created, i.e. STA2 - apIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV2.CHIP_MODE_ID, // chipModeId - IfaceType.AP, // ifaceTypeToCreate - "wlan1", // ifaceName - TestChipV2.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - apDestroyedListener, // destroyedListener - null, // availableListener (already registered), - // destroyedInterfacesDestroyedListeners... - new InterfaceDestroyedListenerWithIfaceName( - getName(staIface2), staDestroyedListener2) - ); - collector.checkThat("AP interface wasn't created", apIface, IsNull.notNullValue()); - - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false); - - // tear down NAN - mDut.removeIface(nanIface); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - verify(chipMock.chip).removeNanIface("wlan0"); - verify(nanDestroyedListener).onDestroyed(getName(nanIface)); - - // create NAN - nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV2.CHIP_MODE_ID, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV2.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); - - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false); - - verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, - staDestroyedListener2, apDestroyedListener, p2pDestroyedListener, - nanDestroyedListener, staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener, staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener); - } - - /** - * Validate P2P and NAN interactions. Expect: - * - STA created - * - NAN created - * - When P2P requested: - * - NAN torn down - * - P2P created - * - NAN creation refused - * - When P2P destroyed: - * - get nan available listener - * - Can create NAN when requested - */ - @Test - public void testP2pAndNanInteractionsTestChipV2() throws Exception { - runP2pAndNanExclusiveInteractionsTestChip(new TestChipV2(), TestChipV2.CHIP_MODE_ID); - } - - /** - * Validate that the getSupportedIfaceTypes API works when requesting for all chips. - */ - @Test - public void testGetSupportedIfaceTypesAllTestChipV2() throws Exception { - TestChipV2 chipMock = new TestChipV2(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(); - - // verify results - Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); - - assertEquals(correctResults, results); - } - - /** - * Validate that the getSupportedIfaceTypes API works when requesting for a specific chip. - */ - @Test - public void testGetSupportedIfaceTypesOneChipTestChipV2() throws Exception { - TestChipV2 chipMock = new TestChipV2(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(chipMock.chip); - - // verify results - Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); - - assertEquals(correctResults, results); - } - - /** - * Validate {@link HalDeviceManager#canSupportIfaceCombo(SparseArray)} - */ - @Test - public void testCanSupportIfaceComboTestChipV2() throws Exception { - final String name = "wlan0"; - - TestChipV2 chipMock = new TestChipV2(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.AP, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.P2P, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.NAN, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.P2P, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.NAN, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.AP, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 2); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.P2P, 1); - put(IfaceType.AP, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.P2P, 1); - put(IfaceType.AP, 1); - }} - )); - assertTrue(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 1); - put(IfaceType.AP, 1); - put(IfaceType.NAN, 1); - }} - )); - - assertFalse(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.P2P, 1); - put(IfaceType.NAN, 1); - }} - )); - assertFalse(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.AP, 2); - }} - )); - assertFalse(mDut.canSupportIfaceCombo(new SparseArray<Integer>() {{ - put(IfaceType.STA, 2); - put(IfaceType.AP, 1); - }} - )); - - verifyNoMoreInteractions(mManagerStatusListenerMock); - } - - ////////////////////////////////////////////////////////////////////////////////////// - // TestChipV3 Specific Tests - ////////////////////////////////////////////////////////////////////////////////////// - - /** - * Validate a flow sequence for test chip 3: - * - create STA - * - create P2P - * - request NAN: failure - * - create AP: should tear down P2P first - * - create STA: will get refused - * - create AP: will get refused - * - request P2P: failure - * - tear down AP - * - create STA - * - create STA: will get refused - * - create NAN: should tear down last created STA - * - create STA: will get refused - */ - @Test - public void testInterfaceCreationFlowTestChipV3() throws Exception { - TestChipV3 chipMock = new TestChipV3(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener staDestroyedListener = mock( - InterfaceDestroyedListener.class); - InterfaceDestroyedListener staDestroyedListener2 = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener apDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener apAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener p2pDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener nanDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InOrder inOrderAvail = inOrder(staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener); - - // register listeners for interface availability - mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.AP, apAvailListener, mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.P2P, p2pAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener, - mHandler); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - - // create STA - when(mClock.getUptimeSinceBootMillis()).thenReturn(15L); - IWifiIface staIface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV3.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("STA interface wasn't created", staIface, IsNull.notNullValue()); - - // create P2P - IWifiIface p2pIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV3.CHIP_MODE_ID, // chipModeId - IfaceType.P2P, // ifaceTypeToCreate - "p2p0", // ifaceName - TestChipV3.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - p2pDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue()); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false); - - // create NAN - IWifiIface nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV3.CHIP_MODE_ID, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV3.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - null, // availableListener (already registered) - new InterfaceDestroyedListenerWithIfaceName("p2p0", p2pDestroyedListener) - ); - collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); - - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false); - - // create AP: will destroy P2P - IWifiIface apIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV3.CHIP_MODE_ID, // chipModeId - IfaceType.AP, // ifaceTypeToCreate - "wlan1", // ifaceName - TestChipV3.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - apDestroyedListener, // destroyedListener - null, // availableListener (already registered) - new InterfaceDestroyedListenerWithIfaceName("wlan0", nanDestroyedListener) - ); - collector.checkThat("AP interface wasn't created", apIface, IsNull.notNullValue()); - verify(chipMock.chip).removeP2pIface("p2p0"); - - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false); - - // request STA2: should fail - IWifiIface staIface2 = mDut.createStaIface(null, null); - collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); - - // request AP2: should fail - IWifiIface apIface2 = mDut.createApIface(null, null); - collector.checkThat("AP2 should not be created", apIface2, IsNull.nullValue()); - - // request P2P: should fail - p2pIface = mDut.createP2pIface(null, null); - collector.checkThat("P2P should not be created", p2pIface, IsNull.nullValue()); - - // tear down AP - mDut.removeIface(apIface); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - verify(chipMock.chip).removeApIface("wlan1"); - verify(apDestroyedListener).onDestroyed(getName(apIface)); - - // create STA2: using a later clock - when(mClock.getUptimeSinceBootMillis()).thenReturn(20L); - staIface2 = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV3.CHIP_MODE_ID, // chipModeId - IfaceType.STA, // ifaceTypeToCreate - "wlan1", // ifaceName - TestChipV3.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener2, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("STA 2 interface wasn't created", staIface2, IsNull.notNullValue()); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false); - - // request STA3: should fail - IWifiIface staIface3 = mDut.createStaIface(null, null); - collector.checkThat("STA3 should not be created", staIface3, IsNull.nullValue()); - - // create NAN: should destroy the last created STA (STA2) - nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV3.CHIP_MODE_ID, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV3.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - null, // availableListener (already registered) - new InterfaceDestroyedListenerWithIfaceName( - getName(staIface2), staDestroyedListener2) - ); - collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); - - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false); - verify(chipMock.chip).removeStaIface("wlan1"); - verify(staDestroyedListener2).onDestroyed(getName(staIface2)); - - // request STA2: should fail - staIface2 = mDut.createStaIface(null, null); - collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); - - verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, - staDestroyedListener2, apDestroyedListener, p2pDestroyedListener, - nanDestroyedListener, staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener, staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener); - } - - /** - * Validate P2P and NAN interactions. Expect: - * - STA created - * - NAN created - * - When P2P requested: - * - NAN torn down - * - P2P created - * - NAN creation refused - * - When P2P destroyed: - * - get nan available listener - * - Can create NAN when requested - */ - @Test - public void testP2pAndNanInteractionsTestChipV3() throws Exception { - runP2pAndNanExclusiveInteractionsTestChip(new TestChipV3(), TestChipV3.CHIP_MODE_ID); - } - - /** - * Validate that the getSupportedIfaceTypes API works when requesting for all chips. - */ - @Test - public void testGetSupportedIfaceTypesAllTestChipV3() throws Exception { - TestChipV3 chipMock = new TestChipV3(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(); - - // verify results - Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); - - assertEquals(correctResults, results); - } - - /** - * Validate that the getSupportedIfaceTypes API works when requesting for a specific chip. - */ - @Test - public void testGetSupportedIfaceTypesOneChipTestChipV3() throws Exception { - TestChipV3 chipMock = new TestChipV3(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(chipMock.chip); - - // verify results - Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); - - assertEquals(correctResults, results); - } - - ////////////////////////////////////////////////////////////////////////////////////// - // TestChipV4 Specific Tests - ////////////////////////////////////////////////////////////////////////////////////// - - /** - * Validate a flow sequence for test chip 4: - * - create STA - * - create P2P - * - request NAN: failure - * - create AP: should tear down P2P first - * - create STA: will get refused - * - create AP: will get refused - * - request P2P: failure - * - tear down AP - * - create STA: will get refused - * - create NAN - * - create STA: will get refused - */ - @Test - public void testInterfaceCreationFlowTestChipV4() throws Exception { - TestChipV4 chipMock = new TestChipV4(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener staDestroyedListener = mock( - InterfaceDestroyedListener.class); - InterfaceDestroyedListener staDestroyedListener2 = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener apDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener apAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener p2pDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener nanDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InOrder inOrderAvail = inOrder(staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener); - - // register listeners for interface availability - mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.AP, apAvailListener, mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.P2P, p2pAvailListener, - mHandler); - mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener, - mHandler); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - - // create STA - when(mClock.getUptimeSinceBootMillis()).thenReturn(15L); - IWifiIface staIface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV4.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - staDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("STA interface wasn't created", staIface, IsNull.notNullValue()); - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false); - - // create P2P - IWifiIface p2pIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV4.CHIP_MODE_ID, // chipModeId - IfaceType.P2P, // ifaceTypeToCreate - "p2p0", // ifaceName - TestChipV4.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - p2pDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue()); - - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false); - - // create NAN: will destroy P2P - IWifiIface nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV4.CHIP_MODE_ID, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV4.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - nanAvailListener, // availableListener - new InterfaceDestroyedListenerWithIfaceName("p2p0", p2pDestroyedListener) - ); - collector.checkThat("allocated NAN interface", nanIface, IsNull.notNullValue()); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false); - - // create AP: will destroy NAN - IWifiIface apIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV4.CHIP_MODE_ID, // chipModeId - IfaceType.AP, // ifaceTypeToCreate - "wlan1", // ifaceName - TestChipV4.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - apDestroyedListener, // destroyedListener - null, // availableListener (already registered) - new InterfaceDestroyedListenerWithIfaceName("wlan0", nanDestroyedListener) - ); - collector.checkThat("AP interface wasn't created", apIface, IsNull.notNullValue()); - verify(chipMock.chip).removeP2pIface("p2p0"); - - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false); - - // request STA2: should fail - IWifiIface staIface2 = mDut.createStaIface(null, null); - collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); - - // request AP2: should fail - IWifiIface apIface2 = mDut.createApIface(null, null); - collector.checkThat("AP2 should not be created", apIface2, IsNull.nullValue()); - - // request P2P: should fail - p2pIface = mDut.createP2pIface(null, null); - collector.checkThat("P2P should not be created", p2pIface, IsNull.nullValue()); - - // tear down AP - mDut.removeIface(apIface); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true); - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true); - verify(chipMock.chip).removeApIface("wlan1"); - verify(apDestroyedListener).onDestroyed(getName(apIface)); - - // request STA2: should fail - staIface2 = mDut.createStaIface(null, null); - collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); - - // create NAN - nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV4.CHIP_MODE_ID, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV4.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - null // availableListener (already registered) - ); - collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); - - inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false); - - // request STA2: should fail - staIface2 = mDut.createStaIface(null, null); - collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); - - // tear down STA - mDut.removeIface(staIface); - mTestLooper.dispatchAll(); - - inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true); - verify(chipMock.chip).removeStaIface("wlan0"); - verify(staDestroyedListener).onDestroyed(getName(staIface)); - - verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, - staDestroyedListener2, apDestroyedListener, p2pDestroyedListener, - nanDestroyedListener, staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener, staAvailListener, apAvailListener, p2pAvailListener, - nanAvailListener); - } - - /** - * Validate P2P and NAN interactions. Expect: - * - STA created - * - NAN created - * - When P2P requested: - * - NAN torn down - * - P2P created - * - NAN creation refused - * - When P2P destroyed: - * - get nan available listener - * - Can create NAN when requested - */ - @Test - public void testP2pAndNanInteractionsTestChipV4() throws Exception { - runP2pAndNanExclusiveInteractionsTestChip(new TestChipV4(), TestChipV4.CHIP_MODE_ID); - } - - /** - * Validate that the getSupportedIfaceTypes API works when requesting for all chips. - */ - @Test - public void testGetSupportedIfaceTypesAllTestChipV4() throws Exception { - TestChipV4 chipMock = new TestChipV4(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(); - - // verify results - Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); - - assertEquals(correctResults, results); - } - - /** - * Validate that the getSupportedIfaceTypes API works when requesting for a specific chip. - */ - @Test - public void testGetSupportedIfaceTypesOneChipTestChipV4() throws Exception { - TestChipV4 chipMock = new TestChipV4(); - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // try API - Set<Integer> results = mDut.getSupportedIfaceTypes(chipMock.chip); - - // verify results - Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); - - assertEquals(correctResults, results); - } - - - /////////////////////////////////////////////////////////////////////////////////////// - // utilities - /////////////////////////////////////////////////////////////////////////////////////// - - private void dumpDut(String prefix) { - StringWriter sw = new StringWriter(); - mDut.dump(null, new PrintWriter(sw), null); - Log.e("HalDeviceManager", prefix + sw.toString()); - } - - private void executeAndValidateInitializationSequence() throws Exception { - executeAndValidateInitializationSequence(true); - } - - private void executeAndValidateInitializationSequence(boolean isSupported) throws Exception { - // act: - mDut.initialize(); - - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications(eq(IWifi.kInterfaceName), - eq(""), mServiceNotificationCaptor.capture()); - - // If not using the lazy version of the IWifi service, the process should already be up at - // this point. - mInOrder.verify(mServiceManagerMock).listManifestByInterface(eq(IWifi.kInterfaceName)); - - // verify: wifi initialization sequence if vendor HAL is supported. - if (isSupported) { - mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong()); - mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture()); - // verify: onStop called as a part of initialize. - mInOrder.verify(mWifiMock).stop(); - collector.checkThat("isReady is true", mDut.isReady(), equalTo(true)); - } else { - collector.checkThat("isReady is false", mDut.isReady(), equalTo(false)); - } - } - - private void executeAndValidateStartupSequence() throws Exception { - executeAndValidateStartupSequence(1, true); - } - - private void executeAndValidateStartupSequence(int numAttempts, boolean success) - throws Exception { - // act: register listener & start Wi-Fi - mDut.registerStatusListener(mManagerStatusListenerMock, mHandler); - collector.checkThat(mDut.start(), equalTo(success)); - - // verify - mInOrder.verify(mWifiMock, times(numAttempts)).start(); - - if (success) { - // act: trigger onStart callback of IWifiEventCallback - mWifiEventCallbackCaptor.getValue().onStart(); - mTestLooper.dispatchAll(); - - // verify: onStart called on registered listener - mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); - } - } - - private void runCreateSingleXxxInterfaceNoInitMode(ChipMockBase chipMock, int ifaceTypeToCreate, - String ifaceName, int finalChipMode, boolean multipleIfaceSupport) throws Exception { - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener idl = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InOrder availInOrder = inOrder(iafrl); - - IWifiIface iface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - ifaceTypeToCreate, - ifaceName, - finalChipMode, - null, // tearDownList - idl, // destroyedListener - iafrl // availableListener - ); - collector.checkThat("allocated interface", iface, IsNull.notNullValue()); - availInOrder.verify(iafrl).onAvailabilityChanged(multipleIfaceSupport); - - // act: remove interface - mDut.removeIface(iface); - mTestLooper.dispatchAll(); - - // verify: callback triggered - switch (ifaceTypeToCreate) { - case IfaceType.STA: - mInOrder.verify(chipMock.chip).removeStaIface(ifaceName); - break; - case IfaceType.AP: - mInOrder.verify(chipMock.chip).removeApIface(ifaceName); - break; - case IfaceType.P2P: - mInOrder.verify(chipMock.chip).removeP2pIface(ifaceName); - break; - case IfaceType.NAN: - mInOrder.verify(chipMock.chip).removeNanIface(ifaceName); - break; - } - - verify(idl).onDestroyed(ifaceName); - if (!multipleIfaceSupport) { - availInOrder.verify(iafrl).onAvailabilityChanged(true); - } - - verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); - } - - /** - * Validate P2P and NAN interactions. Expect: - * - STA created - * - NAN created - * - When P2P requested: - * - NAN torn down - * - P2P created - * - NAN creation refused - * - When P2P destroyed: - * - get nan available listener - * - Can create NAN when requested - * - * Relevant for any chip which supports STA + NAN || P2P (or a richer combination - but bottom - * line of NAN and P2P being exclusive). - */ - public void runP2pAndNanExclusiveInteractionsTestChip(ChipMockBase chipMock, - int onlyChipMode) throws Exception { - chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - InterfaceDestroyedListener staDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener nanDestroyedListener = mock( - InterfaceDestroyedListener.class); - HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - - InterfaceDestroyedListener p2pDestroyedListener = mock( - InterfaceDestroyedListener.class); - - InOrder availInOrder = inOrder(staAvailListener, nanAvailListener); - - // Request STA - IWifiIface staIface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - IfaceType.STA, // ifaceTypeToCreate - "wlan0", // ifaceName - onlyChipMode, // finalChipMode - null, // tearDownList - staDestroyedListener, // destroyedListener - staAvailListener // availableListener - ); - collector.checkThat("STA can't be created", staIface, IsNull.notNullValue()); - availInOrder.verify(staAvailListener).onAvailabilityChanged( - chipMock.chipMockId == CHIP_MOCK_V2 || chipMock.chipMockId == CHIP_MOCK_V3); - - // Request NAN - IWifiIface nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - onlyChipMode, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - onlyChipMode, // finalChipMode - null, // tearDownList - nanDestroyedListener, // destroyedListener - nanAvailListener // availableListener - ); - if (chipMock.chipMockId == CHIP_MOCK_V3) { - availInOrder.verify(staAvailListener).onAvailabilityChanged(false); - } - availInOrder.verify(nanAvailListener).onAvailabilityChanged(false); - - // Request P2P - IWifiIface p2pIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - onlyChipMode, // chipModeId - IfaceType.P2P, // ifaceTypeToCreate - "p2p0", // ifaceName - onlyChipMode, // finalChipMode - new IWifiIface[]{nanIface}, // tearDownList - p2pDestroyedListener, // destroyedListener - null, // availableListener - // destroyedInterfacesDestroyedListeners... - new InterfaceDestroyedListenerWithIfaceName( - getName(nanIface), nanDestroyedListener) - ); - collector.checkThat("P2P can't be created", p2pIface, IsNull.notNullValue()); - availInOrder.verify(nanAvailListener).onAvailabilityChanged(true); - - mTestLooper.dispatchAll(); - verify(nanDestroyedListener).onDestroyed(getName(nanIface)); - - // Request NAN - nanIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - onlyChipMode, // chipModeId - IfaceType.NAN, // ifaceTypeToCreate - "wlan0", // ifaceName - onlyChipMode, // finalChipMode - new IWifiIface[]{p2pIface}, // tearDownList - nanDestroyedListener, // destroyedListener - nanAvailListener // availableListener - ); - collector.checkThat("NAN can't be created", nanIface, IsNull.notNullValue()); - availInOrder.verify(nanAvailListener).onAvailabilityChanged(false); - - mTestLooper.dispatchAll(); - verify(p2pDestroyedListener).onDestroyed(getName(p2pIface)); - - verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener, - nanDestroyedListener, nanAvailListener, p2pDestroyedListener); - } - - private IWifiIface validateInterfaceSequence(ChipMockBase chipMock, - boolean chipModeValid, int chipModeId, - int ifaceTypeToCreate, String ifaceName, int finalChipMode, - IWifiIface[] tearDownList, - InterfaceDestroyedListener destroyedListener, - HalDeviceManager.InterfaceAvailableForRequestListener availableListener, - InterfaceDestroyedListenerWithIfaceName...destroyedInterfacesDestroyedListeners) - throws Exception { - // configure chip mode response - chipMock.chipModeValid = chipModeValid; - chipMock.chipModeId = chipModeId; - - IWifiIface iface = null; - - // configure: interface to be created - // act: request the interface - switch (ifaceTypeToCreate) { - case IfaceType.STA: - iface = mock(IWifiStaIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.STA)).when(iface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( - chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); - - mDut.createStaIface(destroyedListener, mHandler); - break; - case IfaceType.AP: - iface = mock(IWifiApIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.AP)).when(iface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( - chipMock.chip).createApIface(any(IWifiChip.createApIfaceCallback.class)); - - mDut.createApIface(destroyedListener, mHandler); - break; - case IfaceType.P2P: - iface = mock(IWifiP2pIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.P2P)).when(iface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( - chipMock.chip).createP2pIface(any(IWifiChip.createP2pIfaceCallback.class)); - - mDut.createP2pIface(destroyedListener, mHandler); - break; - case IfaceType.NAN: - iface = mock(IWifiNanIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.NAN)).when(iface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( - chipMock.chip).createNanIface(any(IWifiChip.createNanIfaceCallback.class)); - - mDut.createNanIface(destroyedListener, mHandler); - break; - } - if (availableListener != null) { - mDut.registerInterfaceAvailableForRequestListener(ifaceTypeToCreate, availableListener, - mHandler); - } - - // validate: optional tear down of interfaces - if (tearDownList != null) { - for (IWifiIface tearDownIface: tearDownList) { - switch (getType(tearDownIface)) { - case IfaceType.STA: - mInOrder.verify(chipMock.chip).removeStaIface(getName(tearDownIface)); - break; - case IfaceType.AP: - mInOrder.verify(chipMock.chip).removeApIface(getName(tearDownIface)); - break; - case IfaceType.P2P: - mInOrder.verify(chipMock.chip).removeP2pIface(getName(tearDownIface)); - break; - case IfaceType.NAN: - mInOrder.verify(chipMock.chip).removeNanIface(getName(tearDownIface)); - break; - } - } - } - - // validate: optional switch to the requested mode - if (!chipModeValid || chipModeId != finalChipMode) { - mInOrder.verify(chipMock.chip).configureChip(finalChipMode); - } else { - mInOrder.verify(chipMock.chip, times(0)).configureChip(anyInt()); - } - - // validate: create interface - switch (ifaceTypeToCreate) { - case IfaceType.STA: - mInOrder.verify(chipMock.chip).createStaIface( - any(IWifiChip.createStaIfaceCallback.class)); - break; - case IfaceType.AP: - mInOrder.verify(chipMock.chip).createApIface( - any(IWifiChip.createApIfaceCallback.class)); - break; - case IfaceType.P2P: - mInOrder.verify(chipMock.chip).createP2pIface( - any(IWifiChip.createP2pIfaceCallback.class)); - break; - case IfaceType.NAN: - mInOrder.verify(chipMock.chip).createNanIface( - any(IWifiChip.createNanIfaceCallback.class)); - break; - } - - // verify: callbacks on deleted interfaces - mTestLooper.dispatchAll(); - for (int i = 0; i < destroyedInterfacesDestroyedListeners.length; ++i) { - destroyedInterfacesDestroyedListeners[i].validate(); - } - return iface; - } - - private int getType(IWifiIface iface) throws Exception { - Mutable<Integer> typeResp = new Mutable<>(); - iface.getType((WifiStatus status, int type) -> { - typeResp.value = type; - }); - return typeResp.value; - } - - private String getName(IWifiIface iface) throws Exception { - Mutable<String> nameResp = new Mutable<>(); - iface.getName((WifiStatus status, String name) -> { - nameResp.value = name; - }); - return nameResp.value; - } - - private WifiStatus getStatus(int code) { - WifiStatus status = new WifiStatus(); - status.code = code; - return status; - } - - private static class InterfaceDestroyedListenerWithIfaceName { - private final String mIfaceName; - @Mock private final InterfaceDestroyedListener mListener; - - InterfaceDestroyedListenerWithIfaceName( - String ifaceName, InterfaceDestroyedListener listener) { - mIfaceName = ifaceName; - mListener = listener; - } - - public void validate() { - verify(mListener).onDestroyed(mIfaceName); - } - } - - private static class Mutable<E> { - public E value; - - Mutable() { - value = null; - } - - Mutable(E value) { - this.value = value; - } - } - - // Answer objects - private class GetChipIdsAnswer extends MockAnswerUtil.AnswerWithArguments { - private WifiStatus mStatus; - private ArrayList<Integer> mChipIds; - - GetChipIdsAnswer(WifiStatus status, ArrayList<Integer> chipIds) { - mStatus = status; - mChipIds = chipIds; - } - - public void answer(IWifi.getChipIdsCallback cb) { - cb.onValues(mStatus, mChipIds); - } - } - - private class GetChipAnswer extends MockAnswerUtil.AnswerWithArguments { - private WifiStatus mStatus; - private IWifiChip mChip; - - GetChipAnswer(WifiStatus status, IWifiChip chip) { - mStatus = status; - mChip = chip; - } - - public void answer(int chipId, IWifi.getChipCallback cb) { - cb.onValues(mStatus, mChip); - } - } - - private class GetIdAnswer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - - GetIdAnswer(ChipMockBase chipMockBase) { - mChipMockBase = chipMockBase; - } - - public void answer(IWifiChip.getIdCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.chipId); - } - } - - private class GetAvailableModesAnswer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - - GetAvailableModesAnswer(ChipMockBase chipMockBase) { - mChipMockBase = chipMockBase; - } - - public void answer(IWifiChip.getAvailableModesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.availableModes); - } - } - - private class GetModeAnswer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - - GetModeAnswer(ChipMockBase chipMockBase) { - mChipMockBase = chipMockBase; - } - - public void answer(IWifiChip.getModeCallback cb) { - cb.onValues(mChipMockBase.chipModeValid ? mStatusOk - : getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE), mChipMockBase.chipModeId); - } - } - - private class ConfigureChipAnswer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - - ConfigureChipAnswer(ChipMockBase chipMockBase) { - mChipMockBase = chipMockBase; - } - - public WifiStatus answer(int chipMode) { - mChipMockBase.chipModeValid = true; - mChipMockBase.chipModeId = chipMode; - return mStatusOk; - } - } - - private class GetXxxIfaceNamesAnswer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - - GetXxxIfaceNamesAnswer(ChipMockBase chipMockBase) { - mChipMockBase = chipMockBase; - } - - public void answer(IWifiChip.getStaIfaceNamesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.STA)); - } - - public void answer(IWifiChip.getApIfaceNamesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.AP)); - } - - public void answer(IWifiChip.getP2pIfaceNamesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.P2P)); - } - - public void answer(IWifiChip.getNanIfaceNamesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.NAN)); - } - } - - private class GetXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - - GetXxxIfaceAnswer(ChipMockBase chipMockBase) { - mChipMockBase = chipMockBase; - } - - public void answer(String name, IWifiChip.getStaIfaceCallback cb) { - IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.STA).get(name); - cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiStaIface) iface); - } - - public void answer(String name, IWifiChip.getApIfaceCallback cb) { - IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.AP).get(name); - cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiApIface) iface); - } - - public void answer(String name, IWifiChip.getP2pIfaceCallback cb) { - IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.P2P).get(name); - cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiP2pIface) iface); - } - - public void answer(String name, IWifiChip.getNanIfaceCallback cb) { - IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.NAN).get(name); - cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiNanIface) iface); - } - } - - private class CreateXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - private WifiStatus mStatus; - private IWifiIface mWifiIface; - - CreateXxxIfaceAnswer(ChipMockBase chipMockBase, WifiStatus status, IWifiIface wifiIface) { - mChipMockBase = chipMockBase; - mStatus = status; - mWifiIface = wifiIface; - } - - private void addInterfaceInfo(int type) { - if (mStatus.code == WifiStatusCode.SUCCESS) { - try { - mChipMockBase.interfaceNames.get(type).add(getName(mWifiIface)); - mChipMockBase.interfacesByName.get(type).put(getName(mWifiIface), mWifiIface); - } catch (Exception e) { - // do nothing - } - } - } - - public void answer(IWifiChip.createStaIfaceCallback cb) { - cb.onValues(mStatus, (IWifiStaIface) mWifiIface); - addInterfaceInfo(IfaceType.STA); - } - - public void answer(IWifiChip.createApIfaceCallback cb) { - cb.onValues(mStatus, (IWifiApIface) mWifiIface); - addInterfaceInfo(IfaceType.AP); - } - - public void answer(IWifiChip.createP2pIfaceCallback cb) { - cb.onValues(mStatus, (IWifiP2pIface) mWifiIface); - addInterfaceInfo(IfaceType.P2P); - } - - public void answer(IWifiChip.createNanIfaceCallback cb) { - cb.onValues(mStatus, (IWifiNanIface) mWifiIface); - addInterfaceInfo(IfaceType.NAN); - } - } - - private class CreateRttControllerAnswer extends MockAnswerUtil.AnswerWithArguments { - private final ChipMockBase mChipMockBase; - private final IWifiRttController mRttController; - - CreateRttControllerAnswer(ChipMockBase chipMockBase, IWifiRttController rttController) { - mChipMockBase = chipMockBase; - mRttController = rttController; - } - - public void answer(IWifiIface boundIface, IWifiChip.createRttControllerCallback cb) { - if (mChipMockBase.chipModeIdValidForRtt == mChipMockBase.chipModeId) { - cb.onValues(mStatusOk, mRttController); - } else { - cb.onValues(mStatusFail, null); - } - } - } - - private class RemoveXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - private int mType; - - RemoveXxxIfaceAnswer(ChipMockBase chipMockBase, int type) { - mChipMockBase = chipMockBase; - mType = type; - } - - private WifiStatus removeIface(int type, String ifname) { - try { - if (!mChipMockBase.interfaceNames.get(type).remove(ifname)) { - return mStatusFail; - } - if (mChipMockBase.interfacesByName.get(type).remove(ifname) == null) { - return mStatusFail; - } - } catch (Exception e) { - return mStatusFail; - } - return mStatusOk; - } - - public WifiStatus answer(String ifname) { - return removeIface(mType, ifname); - } - } - - private class GetNameAnswer extends MockAnswerUtil.AnswerWithArguments { - private String mName; - - GetNameAnswer(String name) { - mName = name; - } - - public void answer(IWifiIface.getNameCallback cb) { - cb.onValues(mStatusOk, mName); - } - } - - private class GetTypeAnswer extends MockAnswerUtil.AnswerWithArguments { - private int mType; - - GetTypeAnswer(int type) { - mType = type; - } - - public void answer(IWifiIface.getTypeCallback cb) { - cb.onValues(mStatusOk, mType); - } - } - - // chip configuration - - private static final int CHIP_MOCK_V1 = 0; - private static final int CHIP_MOCK_V2 = 1; - private static final int CHIP_MOCK_V3 = 2; - private static final int CHIP_MOCK_V4 = 3; - - private class ChipMockBase { - public int chipMockId; - - public IWifiChip chip; - public int chipId; - public boolean chipModeValid = false; - public int chipModeId = -1000; - public int chipModeIdValidForRtt = -1; // single chip mode ID where RTT can be created - public Map<Integer, ArrayList<String>> interfaceNames = new HashMap<>(); - public Map<Integer, Map<String, IWifiIface>> interfacesByName = new HashMap<>(); - - public ArrayList<IWifiChip.ChipMode> availableModes; - - void initialize() throws Exception { - chip = mock(IWifiChip.class); - - interfaceNames.put(IfaceType.STA, new ArrayList<>()); - interfaceNames.put(IfaceType.AP, new ArrayList<>()); - interfaceNames.put(IfaceType.P2P, new ArrayList<>()); - interfaceNames.put(IfaceType.NAN, new ArrayList<>()); - - interfacesByName.put(IfaceType.STA, new HashMap<>()); - interfacesByName.put(IfaceType.AP, new HashMap<>()); - interfacesByName.put(IfaceType.P2P, new HashMap<>()); - interfacesByName.put(IfaceType.NAN, new HashMap<>()); - - when(chip.registerEventCallback(any(IWifiChipEventCallback.class))).thenReturn( - mStatusOk); - when(chip.configureChip(anyInt())).thenAnswer(new ConfigureChipAnswer(this)); - doAnswer(new GetIdAnswer(this)).when(chip).getId(any(IWifiChip.getIdCallback.class)); - doAnswer(new GetModeAnswer(this)).when(chip).getMode( - any(IWifiChip.getModeCallback.class)); - GetXxxIfaceNamesAnswer getXxxIfaceNamesAnswer = new GetXxxIfaceNamesAnswer(this); - doAnswer(getXxxIfaceNamesAnswer).when(chip).getStaIfaceNames( - any(IWifiChip.getStaIfaceNamesCallback.class)); - doAnswer(getXxxIfaceNamesAnswer).when(chip).getApIfaceNames( - any(IWifiChip.getApIfaceNamesCallback.class)); - doAnswer(getXxxIfaceNamesAnswer).when(chip).getP2pIfaceNames( - any(IWifiChip.getP2pIfaceNamesCallback.class)); - doAnswer(getXxxIfaceNamesAnswer).when(chip).getNanIfaceNames( - any(IWifiChip.getNanIfaceNamesCallback.class)); - GetXxxIfaceAnswer getXxxIfaceAnswer = new GetXxxIfaceAnswer(this); - doAnswer(getXxxIfaceAnswer).when(chip).getStaIface(anyString(), - any(IWifiChip.getStaIfaceCallback.class)); - doAnswer(getXxxIfaceAnswer).when(chip).getApIface(anyString(), - any(IWifiChip.getApIfaceCallback.class)); - doAnswer(getXxxIfaceAnswer).when(chip).getP2pIface(anyString(), - any(IWifiChip.getP2pIfaceCallback.class)); - doAnswer(getXxxIfaceAnswer).when(chip).getNanIface(anyString(), - any(IWifiChip.getNanIfaceCallback.class)); - doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.STA)).when(chip).removeStaIface( - anyString()); - doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.AP)).when(chip).removeApIface( - anyString()); - doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.P2P)).when(chip).removeP2pIface( - anyString()); - doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.NAN)).when(chip).removeNanIface( - anyString()); - - doAnswer(new CreateRttControllerAnswer(this, mRttControllerMock)).when( - chip).createRttController(any(), any()); - } - } - - // test chip configuration V1: - // mode: STA + (NAN || P2P) - // mode: AP - private class TestChipV1 extends ChipMockBase { - static final int STA_CHIP_MODE_ID = 0; - static final int AP_CHIP_MODE_ID = 1; - - void initialize() throws Exception { - super.initialize(); - - chipMockId = CHIP_MOCK_V1; - - // chip Id configuration - ArrayList<Integer> chipIds; - chipId = 10; - chipIds = new ArrayList<>(); - chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(10), - any(IWifi.getChipCallback.class)); - - // initialize dummy chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - - // Mode 0: 1xSTA + 1x{P2P,NAN} - // Mode 1: 1xAP - availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = STA_CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - cm.availableCombinations.add(cic); - availableModes.add(cm); - - cm = new IWifiChip.ChipMode(); - cm.id = AP_CHIP_MODE_ID; - cic = new IWifiChip.ChipIfaceCombination(); - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - cm.availableCombinations.add(cic); - availableModes.add(cm); - - chipModeIdValidForRtt = STA_CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); - } - } - - // test chip configuration V2: - // mode: STA + (STA || AP) + (NAN || P2P) - private class TestChipV2 extends ChipMockBase { - // only mode (different number from any in TestChipV1 so can catch test errors) - static final int CHIP_MODE_ID = 5; - - void initialize() throws Exception { - super.initialize(); - - chipMockId = CHIP_MOCK_V2; - - // chip Id configuration - ArrayList<Integer> chipIds; - chipId = 12; - chipIds = new ArrayList<>(); - chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(12), - any(IWifi.getChipCallback.class)); - - // initialize dummy chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - - // Mode 0 (only one): 1xSTA + 1x{STA,AP} + 1x{P2P,NAN} - availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - cm.availableCombinations.add(cic); - availableModes.add(cm); - - chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); - } - } - - // test chip configuration V3: - // mode: - // STA + (STA || AP) - // STA + (NAN || P2P) - private class TestChipV3 extends ChipMockBase { - // only mode (different number from any in other TestChips so can catch test errors) - static final int CHIP_MODE_ID = 7; - - void initialize() throws Exception { - super.initialize(); - - chipMockId = CHIP_MOCK_V3; - - // chip Id configuration - ArrayList<Integer> chipIds; - chipId = 15; - chipIds = new ArrayList<>(); - chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(15), - any(IWifi.getChipCallback.class)); - - // initialize dummy chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - - // Mode 0 (only one): 1xSTA + 1x{STA,AP}, 1xSTA + 1x{P2P,NAN} - availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - availableModes.add(cm); - - chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); - } - } - - // test chip configuration V4: - // mode: - // STA + AP - // STA + (NAN || P2P) - private class TestChipV4 extends ChipMockBase { - // only mode (different number from any in other TestChips so can catch test errors) - static final int CHIP_MODE_ID = 15; - - void initialize() throws Exception { - super.initialize(); - - chipMockId = CHIP_MOCK_V4; - - // chip Id configuration - ArrayList<Integer> chipIds; - chipId = 23; - chipIds = new ArrayList<>(); - chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(23), - any(IWifi.getChipCallback.class)); - - // initialize dummy chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - - // Mode 0 (only one): 1xSTA + 1xAP, 1xSTA + 1x{P2P,NAN} - availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - availableModes.add(cm); - - chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java b/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java deleted file mode 100644 index 8f8c7a52e..000000000 --- a/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; - -import android.app.test.MockAnswerUtil; -import android.content.Context; -import android.hardware.wifi.hostapd.V1_0.HostapdStatus; -import android.hardware.wifi.hostapd.V1_0.HostapdStatusCode; -import android.hardware.wifi.hostapd.V1_0.IHostapd; -import android.hardware.wifi.hostapd.V1_1.IHostapdCallback; -import android.hardware.wifi.hostapd.V1_2.DebugLevel; -import android.hidl.manager.V1_0.IServiceManager; -import android.hidl.manager.V1_0.IServiceNotification; -import android.net.MacAddress; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApConfiguration.Builder; -import android.net.wifi.WifiManager; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.Handler; -import android.os.IHwBinder; -import android.os.RemoteException; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.NativeUtil; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; - -/** - * Unit tests for HostapdHal - */ -@SmallTest -public class HostapdHalTest extends WifiBaseTest { - private static final String IFACE_NAME = "mock-wlan0"; - private static final String NETWORK_SSID = "test-ssid"; - private static final String NETWORK_PSK = "test-psk"; - - private @Mock Context mContext; - private @Mock IServiceManager mServiceManagerMock; - private @Mock IHostapd mIHostapdMock; - private @Mock WifiNative.HostapdDeathEventHandler mHostapdHalDeathHandler; - private @Mock WifiNl80211Manager.SoftApCallback mSoftApListener; - private android.hardware.wifi.hostapd.V1_1.IHostapd mIHostapdMockV11; - private android.hardware.wifi.hostapd.V1_2.IHostapd mIHostapdMockV12; - private IHostapdCallback mIHostapdCallback; - private MockResources mResources; - HostapdStatus mStatusSuccess; - HostapdStatus mStatusFailure; - android.hardware.wifi.hostapd.V1_2.HostapdStatus mStatusSuccess12; - android.hardware.wifi.hostapd.V1_2.HostapdStatus mStatusFailure12; - private TestLooper mLooper = new TestLooper(); - private HostapdHal mHostapdHal; - private ArgumentCaptor<IHwBinder.DeathRecipient> mServiceManagerDeathCaptor = - ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); - private ArgumentCaptor<IHwBinder.DeathRecipient> mHostapdDeathCaptor = - ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); - private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor = - ArgumentCaptor.forClass(IServiceNotification.Stub.class); - private ArgumentCaptor<IHostapd.IfaceParams> mIfaceParamsCaptor = - ArgumentCaptor.forClass(IHostapd.IfaceParams.class); - private ArgumentCaptor<android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams> - mIfaceParamsCaptorV1_1 = - ArgumentCaptor.forClass(android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams.class); - private ArgumentCaptor<android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams> - mIfaceParamsCaptorV12 = - ArgumentCaptor.forClass(android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams.class); - private ArgumentCaptor<IHostapd.NetworkParams> mNetworkParamsCaptor = - ArgumentCaptor.forClass(IHostapd.NetworkParams.class); - private ArgumentCaptor<android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams> - mNetworkParamsV12Captor = ArgumentCaptor.forClass( - android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams.class); - private ArgumentCaptor<Long> mDeathRecipientCookieCaptor = ArgumentCaptor.forClass(Long.class); - private InOrder mInOrder; - - private class HostapdHalSpy extends HostapdHal { - HostapdHalSpy() { - super(mContext, new Handler(mLooper.getLooper())); - } - - @Override - protected IServiceManager getServiceManagerMockable() throws RemoteException { - return mServiceManagerMock; - } - - @Override - protected IHostapd getHostapdMockable() throws RemoteException { - return mIHostapdMock; - } - - @Override - protected android.hardware.wifi.hostapd.V1_1.IHostapd getHostapdMockableV1_1() - throws RemoteException { - return mIHostapdMockV11; - } - - @Override - protected android.hardware.wifi.hostapd.V1_2.IHostapd getHostapdMockableV1_2() - throws RemoteException { - return mIHostapdMockV12; - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mResources = new MockResources(); - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false); - mResources.setBoolean(R.bool.config_wifi_softap_ieee80211ac_supported, false); - mResources.setBoolean(R.bool.config_wifiSoftapIeee80211axSupported, false); - mResources.setBoolean(R.bool.config_wifiSoftap6ghzSupported, false); - mResources.setBoolean(R.bool.config_wifiSoftapAcsIncludeDfs, false); - mResources.setString(R.string.config_wifiSoftap2gChannelList, ""); - mResources.setString(R.string.config_wifiSoftap5gChannelList, ""); - mResources.setString(R.string.config_wifiSoftap6gChannelList, ""); - - mStatusSuccess = createHostapdStatus(HostapdStatusCode.SUCCESS); - mStatusFailure = createHostapdStatus(HostapdStatusCode.FAILURE_UNKNOWN); - - - mStatusSuccess12 = createHostapdStatus_1_2(HostapdStatusCode.SUCCESS); - mStatusFailure12 = createHostapdStatus_1_2(HostapdStatusCode.FAILURE_UNKNOWN); - - when(mContext.getResources()).thenReturn(mResources); - when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), - any(IServiceNotification.Stub.class))).thenReturn(true); - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.EMPTY); - when(mIHostapdMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mIHostapdMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mIHostapdMock.addAccessPoint( - mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture())) - .thenReturn(mStatusSuccess); - when(mIHostapdMock.removeAccessPoint(any())).thenReturn(mStatusSuccess); - mHostapdHal = new HostapdHalSpy(); - } - - /** - * Sunny day scenario for HostapdHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_success() throws Exception { - executeAndValidateInitializationSequence(false, false); - } - - /** - * Failure scenario for HostapdHal initialization - */ - @Test - public void testInitialize_registerException() throws Exception { - executeAndValidateInitializationSequence(true, false); - } - - /** - * Failure scenario for HostapdHal initialization - */ - @Test - public void testInitialize_registerFailure() throws Exception { - executeAndValidateInitializationSequence(false, true); - } - - /** - * Sunny day scenario for V1.1 HostapdHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_successV1_1() throws Exception { - when(mServiceManagerMock.getTransport(eq( - android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class); - executeAndValidateInitializationSequenceV1_1(false); - } - - /** - * Failure scenario for V1.1 HostapdHal initialization - */ - @Test - public void testInitialize_registerCallbackFailureV1_1() throws Exception { - when(mServiceManagerMock.getTransport(eq( - android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class); - executeAndValidateInitializationSequenceV1_1(true); - } - - /** - * Verifies the hostapd death handling. - */ - @Test - public void testDeathHandling() throws Exception { - executeAndValidateInitializationSequence(); - - mHostapdHal.registerDeathHandler(mHostapdHalDeathHandler); - mHostapdDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue()); - mLooper.dispatchAll(); - verify(mHostapdHalDeathHandler).onDeath(); - } - - /** - * Verifies the hostapd death handling. - */ - @Test - public void testStaleDeathHandling() throws Exception { - executeAndValidateInitializationSequence(); - - mHostapdHal.registerDeathHandler(mHostapdHalDeathHandler); - mHostapdDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue() - 1); - mLooper.dispatchAll(); - verify(mHostapdHalDeathHandler, never()).onDeath(); - } - - /** - * Verifies the successful addition of access point. - */ - @Test - public void testAddAccessPointSuccess_Psk_Band2G() throws Exception { - executeAndValidateInitializationSequence(); - final int apChannel = 6; - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC); - assertEquals(IHostapd.Band.BAND_2_4_GHZ, mIfaceParamsCaptor.getValue().channelParams.band); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs); - assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertFalse(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase); - } - - /** - * Verifies the successful addition of access point. - */ - @Test - public void testAddAccessPointSuccess_Open_Band5G() throws Exception { - executeAndValidateInitializationSequence(); - final int apChannel = 149; - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(true); - configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_5GHZ); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC); - assertEquals(IHostapd.Band.BAND_5_GHZ, mIfaceParamsCaptor.getValue().channelParams.band); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs); - assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertTrue(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.NONE, mNetworkParamsCaptor.getValue().encryptionType); - assertNotNull(mNetworkParamsCaptor.getValue().pskPassphrase); - } - - /** - * Verifies the successful addition of access point. - */ - @Test - public void testAddAccessPointSuccess_Psk_Band5G_Hidden() throws Exception { - executeAndValidateInitializationSequence(); - final int apChannel = 149; - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(true); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_5GHZ); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC); - assertEquals(IHostapd.Band.BAND_5_GHZ, mIfaceParamsCaptor.getValue().channelParams.band); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs); - assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertTrue(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase); - } - - /** - * Verifies the successful addition of access point. - */ - @Test - public void testAddAccessPointSuccess_Psk_Band2G_WithACS() throws Exception { - // Enable ACS in the config. - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true); - mHostapdHal = new HostapdHalSpy(); - - executeAndValidateInitializationSequence(); - final int apChannel = 6; - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC); - assertEquals(IHostapd.Band.BAND_2_4_GHZ, mIfaceParamsCaptor.getValue().channelParams.band); - assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertFalse(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase); - } - - /** - * Verifies the successful addition of access point. - */ - @Test - public void testAddAccessPointSuccess_Psk_Band2G_WithIeee80211AC() throws Exception { - // Enable ACS & 80211AC in the config. - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true); - mResources.setBoolean(R.bool.config_wifi_softap_ieee80211ac_supported, true); - mHostapdHal = new HostapdHalSpy(); - - executeAndValidateInitializationSequence(); - final int apChannel = 6; - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC); - assertEquals(IHostapd.Band.BAND_2_4_GHZ, mIfaceParamsCaptor.getValue().channelParams.band); - assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertFalse(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase); - } - - /** - * Verifies the successful addition of access point. - */ - @Test - public void testAddAccessPointSuccess_Psk_BandAny_WithACS() throws Exception { - // Enable ACS in the config. - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true); - mHostapdHal = new HostapdHalSpy(); - - executeAndValidateInitializationSequence(); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configurationBuilder.setBand(SoftApConfiguration.BAND_ANY); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC); - assertEquals(IHostapd.Band.BAND_ANY, mIfaceParamsCaptor.getValue().channelParams.band); - assertTrue(mIfaceParamsCaptor.getValue().channelParams.enableAcs); - assertTrue(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertFalse(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase); - } - - /** - * Verifies the successful addition of access point. - */ - @Test - public void testAddAccessPointSuccess_Psk_WithoutACS() throws Exception { - // Disable ACS in the config. - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false); - mHostapdHal = new HostapdHalSpy(); - - executeAndValidateInitializationSequence(); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configurationBuilder.setBand(SoftApConfiguration.BAND_ANY); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertFalse(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase); - } - - /** - * Verifies the successful addition of access point. - * Verifies that channel info for ACS is handled. - */ - @Test - public void testAddAccessPointSuccess_Psk_BandAny_WithACS_AcsChannels() throws Exception { - when(mServiceManagerMock.getTransport(eq( - android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class); - // Enable ACS and set available channels in the config. - final String acsChannelStr2g = "1,6,11-13"; - final String acsChannelStr5g = "40"; - final String acsChannelStr6g = ""; - android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange1 = - new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange(); - android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange2 = - new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange(); - android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange3 = - new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange(); - android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange4 = - new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange(); - channelRange1.start = channelRange1.end = 1; - channelRange2.start = channelRange2.end = 6; - channelRange3.start = 11; - channelRange3.end = 13; - channelRange4.start = channelRange4.end = 40; - ArrayList<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange> acsChannelRanges = - new ArrayList<>(); - acsChannelRanges.add(channelRange1); - acsChannelRanges.add(channelRange2); - acsChannelRanges.add(channelRange3); - acsChannelRanges.add(channelRange4); - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true); - mResources.setString(R.string.config_wifiSoftap2gChannelList, acsChannelStr2g); - mResources.setString(R.string.config_wifiSoftap5gChannelList, acsChannelStr5g); - mResources.setString(R.string.config_wifiSoftap6gChannelList, acsChannelStr6g); - mHostapdHal = new HostapdHalSpy(); - - when(mIHostapdMockV11.addAccessPoint_1_1( - mIfaceParamsCaptorV1_1.capture(), mNetworkParamsCaptor.capture())) - .thenReturn(mStatusSuccess); - - executeAndValidateInitializationSequenceV1_1(false); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configurationBuilder.setBand(SoftApConfiguration.BAND_ANY); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMockV11).addAccessPoint_1_1(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptorV1_1.getValue().V1_0.ifaceName); - assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptorV1_1.getValue().V1_0.hwModeParams.enable80211AC); - assertEquals(IHostapd.Band.BAND_ANY, - mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.band); - assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.enableAcs); - assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.acsShouldExcludeDfs); - assertEquals(acsChannelRanges, - mIfaceParamsCaptorV1_1.getValue().channelParams.acsChannelRanges); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertFalse(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase); - } - - /** - * Verifies the failure handling in addition of access point. - */ - @Test - public void testAddAccessPointFailure() throws Exception { - executeAndValidateInitializationSequence(); - when(mIHostapdMock.addAccessPoint(any(), any())).thenReturn(mStatusFailure); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(true); - configurationBuilder.setChannel(6, SoftApConfiguration.BAND_2GHZ); - - assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - } - - /** - * Verifies the failure handling in addition of access point. - */ - @Test - public void testAddAccessPointRemoteException() throws Exception { - executeAndValidateInitializationSequence(); - doThrow(new RemoteException()).when(mIHostapdMock).addAccessPoint(any(), any()); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(true); - configurationBuilder.setChannel(6, SoftApConfiguration.BAND_2GHZ); - - assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - } - - /** - * Verifies the successful removal of access point. - */ - @Test - public void testRemoveAccessPointSuccess() throws Exception { - executeAndValidateInitializationSequence(); - - assertTrue(mHostapdHal.removeAccessPoint(IFACE_NAME)); - verify(mIHostapdMock).removeAccessPoint(any()); - } - - /** - * Verifies the failure handling in removal of access point. - */ - @Test - public void testRemoveAccessPointFailure() throws Exception { - executeAndValidateInitializationSequence(); - when(mIHostapdMock.removeAccessPoint(any())).thenReturn(mStatusFailure); - - assertFalse(mHostapdHal.removeAccessPoint(IFACE_NAME)); - verify(mIHostapdMock).removeAccessPoint(any()); - } - - /** - * Verifies the failure handling in addition of access point. - */ - @Test - public void testRemoveAccessPointRemoteException() throws Exception { - executeAndValidateInitializationSequence(); - doThrow(new RemoteException()).when(mIHostapdMock).removeAccessPoint(any()); - - assertFalse(mHostapdHal.removeAccessPoint(IFACE_NAME)); - verify(mIHostapdMock).removeAccessPoint(any()); - } - - /** - * Verifies the handling of onFailure callback from hostapd. - */ - @Test - public void testOnFailureCallbackHandling() throws Exception { - when(mServiceManagerMock.getTransport(eq( - android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class); - when(mIHostapdMockV11.addAccessPoint_1_1( - mIfaceParamsCaptorV1_1.capture(), mNetworkParamsCaptor.capture())) - .thenReturn(mStatusSuccess); - executeAndValidateInitializationSequenceV1_1(false); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMockV11).addAccessPoint_1_1(any(), any()); - - // Trigger on failure. - mIHostapdCallback.onFailure(IFACE_NAME); - verify(mSoftApListener).onFailure(); - - // Now remove the access point and ensure that the callback is no longer handled. - reset(mSoftApListener); - assertTrue(mHostapdHal.removeAccessPoint(IFACE_NAME)); - mIHostapdCallback.onFailure(IFACE_NAME); - verify(mSoftApListener, never()).onFailure(); - } - - private void executeAndValidateInitializationSequence() throws Exception { - executeAndValidateInitializationSequence(false, false); - } - - /** - * Calls.initialize(), mocking various callback answers and verifying flow, asserting for the - * expected result. Verifies if IHostapd manager is initialized or reset. - */ - private void executeAndValidateInitializationSequence( - boolean causeRegisterRemoteException, boolean causeRegisterFailure) throws Exception { - boolean shouldSucceed = !causeRegisterRemoteException && !causeRegisterFailure; - mInOrder = inOrder(mServiceManagerMock, mIHostapdMock); - if (causeRegisterFailure) { - when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), - any(IServiceNotification.Stub.class))).thenReturn(false); - } else if (causeRegisterRemoteException) { - doThrow(new RemoteException()).when(mServiceManagerMock) - .registerForNotifications( - anyString(), anyString(), any(IServiceNotification.Stub.class)); - } - // Initialize HostapdHal, should call serviceManager.registerForNotifications - assertEquals(shouldSucceed, mHostapdHal.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(IHostapd.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - if (shouldSucceed) { - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(IHostapd.kInterfaceName, "", true); - assertTrue(mHostapdHal.isInitializationComplete()); - mInOrder.verify(mIHostapdMock).linkToDeath(mHostapdDeathCaptor.capture(), - mDeathRecipientCookieCaptor.capture()); - } else { - assertFalse(mHostapdHal.isInitializationComplete()); - mInOrder.verify(mIHostapdMock, never()).linkToDeath( - mHostapdDeathCaptor.capture(), anyLong()); - } - } - - /** - * Calls.initialize(), mocking various callback answers and verifying flow, asserting for the - * expected result. Verifies if IHostapd manager is initialized or reset. - */ - private void executeAndValidateInitializationSequenceV1_1( - boolean causeCallbackFailure) throws Exception { - boolean shouldSucceed = !causeCallbackFailure; - mInOrder = inOrder(mServiceManagerMock, mIHostapdMock); - if (causeCallbackFailure) { - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public HostapdStatus answer(IHostapdCallback cb) - throws RemoteException { - return mStatusFailure; - } - }).when(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class)); - } else { - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public HostapdStatus answer(IHostapdCallback cb) - throws RemoteException { - mIHostapdCallback = cb; - return mStatusSuccess; - } - }).when(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class)); - } - // Initialize HostapdHal, should call serviceManager.registerForNotifications - assertTrue(mHostapdHal.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(IHostapd.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(IHostapd.kInterfaceName, "", true); - assertEquals(shouldSucceed, mHostapdHal.isInitializationComplete()); - mInOrder.verify(mIHostapdMock).linkToDeath(mHostapdDeathCaptor.capture(), anyLong()); - verify(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class)); - } - - /** - * Calls.initialize(), mocking various callback answers and verifying flow, asserting for the - * expected result. Verifies if IHostapd manager is initialized or reset. - */ - private void executeAndValidateInitializationSequenceV1_2( - boolean causeCallbackFailure) throws Exception { - boolean shouldSucceed = !causeCallbackFailure; - mInOrder = inOrder(mServiceManagerMock, mIHostapdMock); - when(mIHostapdMockV12.setDebugParams(anyInt())) - .thenReturn(mStatusSuccess12); - if (causeCallbackFailure) { - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public HostapdStatus answer(IHostapdCallback cb) - throws RemoteException { - return mStatusFailure; - } - }).when(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class)); - } else { - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public HostapdStatus answer(IHostapdCallback cb) - throws RemoteException { - mIHostapdCallback = cb; - return mStatusSuccess; - } - }).when(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class)); - } - // Initialize HostapdHal, should call serviceManager.registerForNotifications - assertTrue(mHostapdHal.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(IHostapd.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(IHostapd.kInterfaceName, "", true); - assertEquals(shouldSucceed, mHostapdHal.isInitializationComplete()); - mInOrder.verify(mIHostapdMock).linkToDeath(mHostapdDeathCaptor.capture(), anyLong()); - verify(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class)); - } - - private HostapdStatus createHostapdStatus(int code) { - HostapdStatus status = new HostapdStatus(); - status.code = code; - return status; - } - - private android.hardware.wifi.hostapd.V1_2.HostapdStatus createHostapdStatus_1_2(int code) { - android.hardware.wifi.hostapd.V1_2.HostapdStatus status = - new android.hardware.wifi.hostapd.V1_2.HostapdStatus(); - status.code = code; - return status; - } - - /** - * Verifies the successful execute forceClientDisconnect. - */ - @Test - public void testForceClientDisconnectSuccess() throws Exception { - executeAndValidateInitializationSequence(); - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0"); - mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class); - when(mIHostapdMockV12.forceClientDisconnect(any(), any(), anyShort())) - .thenReturn(mStatusSuccess12); - - assertTrue(mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER)); - verify(mIHostapdMockV12).forceClientDisconnect(any(), any(), anyShort()); - } - - @Test - public void testForceClientDisconnectFailureDueToInvalidArg() throws Exception { - executeAndValidateInitializationSequence(); - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0"); - mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class); - when(mIHostapdMockV12.forceClientDisconnect(any(), any(), anyShort())) - .thenReturn(mStatusSuccess12); - - try { - mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client, -1); - fail(); - } catch (IllegalArgumentException e) { - } - } - - /** - * Verifies the failure handling in forceClientDisconnect. - */ - @Test - public void testForceClientDisconnectFailure() throws Exception { - executeAndValidateInitializationSequence(); - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0"); - mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class); - when(mIHostapdMockV12.forceClientDisconnect(any(), any(), anyShort())) - .thenReturn(mStatusFailure12); - - assertFalse(mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER)); - verify(mIHostapdMockV12).forceClientDisconnect(any(), any(), anyShort()); - } - - /** - * Verifies the exception handling in forceClientDisconnect. - */ - @Test - public void testforceClientDisconnectRemoteException() throws Exception { - executeAndValidateInitializationSequence(); - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0"); - mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class); - doThrow(new RemoteException()).when(mIHostapdMockV12) - .forceClientDisconnect(any(), any(), anyShort()); - - assertFalse(mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client, 0)); - verify(mIHostapdMockV12).forceClientDisconnect(any(), any(), anyShort()); - } - - /** - * Verifies the HIDL not support handling in forceClientDisconnect. - */ - @Test - public void testforceClientDisconnectHIDLNotSupport() throws Exception { - executeAndValidateInitializationSequence(); - MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0"); - - assertFalse(mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client, 0)); - } - - /** - * Verifies the setting of log level. - */ - @Test - public void testSetLogLevel() throws Exception { - executeAndValidateInitializationSequence(); - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class); - when(mIHostapdMockV12.setDebugParams(anyInt())) - .thenReturn(mStatusSuccess12); - - mHostapdHal.enableVerboseLogging(true); - verify(mIHostapdMockV12) - .setDebugParams(eq(DebugLevel.DEBUG)); - - mHostapdHal.enableVerboseLogging(false); - verify(mIHostapdMockV12) - .setDebugParams(eq(DebugLevel.INFO)); - } - - /* - * Sunny day scenario for V1.2 HostapdHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_successV1_2() throws Exception { - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class); - mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class); - executeAndValidateInitializationSequenceV1_2(false); - } - - /** - * Verifies the successful addition of access point with SAE. - */ - @Test - public void testAddAccessPointSuccess_SAE_WithoutACS() throws Exception { - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class); - mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class); - // Disable ACS in the config. - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false); - mHostapdHal = new HostapdHalSpy(); - - executeAndValidateInitializationSequenceV1_2(false); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); - configurationBuilder.setBand(SoftApConfiguration.BAND_ANY); - - when(mIHostapdMockV12.addAccessPoint_1_2( - mIfaceParamsCaptorV12.capture(), mNetworkParamsV12Captor.capture())) - .thenReturn(mStatusSuccess12); - - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMockV12).addAccessPoint_1_2(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptorV12.getValue().V1_1.V1_0.ifaceName); - assertTrue(mIfaceParamsCaptorV12.getValue().V1_1.V1_0.hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptorV12.getValue().V1_1.V1_0.hwModeParams.enable80211AC); - assertFalse(mIfaceParamsCaptorV12.getValue().V1_1.V1_0.channelParams.enableAcs); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsV12Captor.getValue().V1_0.ssid); - assertFalse(mNetworkParamsV12Captor.getValue().V1_0.isHidden); - assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE, - mNetworkParamsV12Captor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsV12Captor.getValue().passphrase); - assertEquals("", mNetworkParamsV12Captor.getValue().V1_0.pskPassphrase); - } - - /** - * Verifies the successful addition of access point with SAE Transition. - */ - @Test - public void testAddAccessPointSuccess_SAE_Transition_WithoutACS() throws Exception { - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class); - mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class); - // Disable ACS in the config. - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false); - mHostapdHal = new HostapdHalSpy(); - - executeAndValidateInitializationSequenceV1_2(false); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); - configurationBuilder.setBand(SoftApConfiguration.BAND_ANY); - - when(mIHostapdMockV12.addAccessPoint_1_2( - mIfaceParamsCaptorV12.capture(), mNetworkParamsV12Captor.capture())) - .thenReturn(mStatusSuccess12); - - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMockV12).addAccessPoint_1_2(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptorV12.getValue().V1_1.V1_0.ifaceName); - assertTrue(mIfaceParamsCaptorV12.getValue().V1_1.V1_0.hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptorV12.getValue().V1_1.V1_0.hwModeParams.enable80211AC); - assertFalse(mIfaceParamsCaptorV12.getValue().V1_1.V1_0.channelParams.enableAcs); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsV12Captor.getValue().V1_0.ssid); - assertFalse(mNetworkParamsV12Captor.getValue().V1_0.isHidden); - assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE_TRANSITION, - mNetworkParamsV12Captor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsV12Captor.getValue().passphrase); - assertEquals("", mNetworkParamsV12Captor.getValue().V1_0.pskPassphrase); - } - - /** - * Verifies the failure handling addition of access point with SAE Transition in old hal. - */ - @Test - public void testAddAccessPointFailure_SAEWithOldHal() throws Exception { - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class); - // Disable ACS in the config. - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false); - mHostapdHal = new HostapdHalSpy(); - - executeAndValidateInitializationSequenceV1_1(false); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); - configurationBuilder.setBand(SoftApConfiguration.BAND_ANY); - - assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - } - - /** - * Verifies the successful addition of access point when ACS is allowed to include DFS channels. - */ - @Test - public void testAddAccessPointSuccess_WithACS_IncludeDFSChannels() throws Exception { - // Enable ACS in the config. - mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true); - mResources.setBoolean(R.bool.config_wifiSoftapAcsIncludeDfs, true); - mHostapdHal = new HostapdHalSpy(); - - executeAndValidateInitializationSequence(); - - Builder configurationBuilder = new SoftApConfiguration.Builder(); - configurationBuilder.setSsid(NETWORK_SSID); - configurationBuilder.setHiddenSsid(false); - configurationBuilder.setPassphrase(NETWORK_PSK, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configurationBuilder.setBand(SoftApConfiguration.BAND_ANY); - - assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, - configurationBuilder.build(), - () -> mSoftApListener.onFailure())); - verify(mIHostapdMock).addAccessPoint(any(), any()); - - assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName); - assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N); - assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC); - assertEquals(IHostapd.Band.BAND_ANY, mIfaceParamsCaptor.getValue().channelParams.band); - assertTrue(mIfaceParamsCaptor.getValue().channelParams.enableAcs); - assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs); - - assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID), - mNetworkParamsCaptor.getValue().ssid); - assertFalse(mNetworkParamsCaptor.getValue().isHidden); - assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType); - assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase); - } -} - diff --git a/tests/wifitests/src/com/android/server/wifi/IMSIParameterTest.java b/tests/wifitests/src/com/android/server/wifi/IMSIParameterTest.java deleted file mode 100644 index 8bccafb5d..000000000 --- a/tests/wifitests/src/com/android/server/wifi/IMSIParameterTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -/** - * Unit tests for {@link com.android.server.wifi.IMSIParameter}. - */ -@SmallTest -public class IMSIParameterTest extends WifiBaseTest { - private static final String VALID_FULL_IMSI = "123456789012345"; - private static final String VALID_MCC_MNC = "12345"; - private static final String VALID_MCC_MNC_6 = "123456"; - private static final String INVALID_MCC_MNC = "1234"; - - /** - * Data points for testing function {@link IMSIParameter#build}. - */ - private static final Map<String, IMSIParameter> BUILD_PARAM_TEST_MAP = new HashMap<>(); - static { - BUILD_PARAM_TEST_MAP.put(null, null); - BUILD_PARAM_TEST_MAP.put("", null); - BUILD_PARAM_TEST_MAP.put("1234a123", null); // IMSI contained invalid character. - BUILD_PARAM_TEST_MAP.put("1234567890123451", null); // IMSI is over full IMSI length. - BUILD_PARAM_TEST_MAP.put("123456789012345", new IMSIParameter("123456789012345", false)); - BUILD_PARAM_TEST_MAP.put("1234*", null); - BUILD_PARAM_TEST_MAP.put("12345*", new IMSIParameter("12345", true)); - BUILD_PARAM_TEST_MAP.put("123456*", new IMSIParameter("123456", true)); - BUILD_PARAM_TEST_MAP.put("1234567*", null); - } - - /** - * Verify the expectations of {@link IMSIParameter#build} function using the predefined - * test data {@link #BUILD_PARAM_TEST_MAP}. - * - * @throws Exception - */ - @Test - public void verifyBuildIMSIParameter() throws Exception { - for (Map.Entry<String, IMSIParameter> entry : BUILD_PARAM_TEST_MAP.entrySet()) { - assertEquals(entry.getValue(), IMSIParameter.build(entry.getKey())); - } - } - - /** - * Verify that attempt to match a null IMSI will not cause any crash and should return false. - * - * @throws Exception - */ - @Test - public void matchesNullImsi() throws Exception { - IMSIParameter param = new IMSIParameter("12345", false); - assertFalse(param.matchesImsi(null)); - } - - /** - * Verify that an IMSIParameter containing a full IMSI will only match against an IMSI of the - * same value. - * - * @throws Exception - */ - @Test - public void matchesImsiWithFullImsi() throws Exception { - IMSIParameter param = new IMSIParameter(VALID_FULL_IMSI, false); - - // Full IMSI requires exact matching. - assertFalse(param.matchesImsi(INVALID_MCC_MNC)); - assertFalse(param.matchesImsi(VALID_MCC_MNC)); - assertTrue(param.matchesImsi(VALID_FULL_IMSI)); - } - - /** - * Verify that an IMSIParameter containing a prefix IMSI will match against any IMSI that - * starts with the same prefix. - * - * @throws Exception - */ - @Test - public void matchesImsiWithPrefixImsi() throws Exception { - IMSIParameter param = new IMSIParameter(VALID_MCC_MNC, true); - - // Prefix IMSI will match any full IMSI that starts with the same prefix. - assertFalse(param.matchesImsi(INVALID_MCC_MNC)); - assertTrue(param.matchesImsi(VALID_FULL_IMSI)); - } - - /** - * Verify that attempt to match a null MCC-MNC will not cause any crash and should return - * false. - * - * @throws Exception - */ - @Test - public void matchesNullMccMnc() throws Exception { - IMSIParameter param = new IMSIParameter(VALID_MCC_MNC, true); - assertFalse(param.matchesMccMnc(null)); - } - - /** - * Verify that an IMSIParameter containing a full IMSI will only match against a 6 digit - * MCC-MNC that is a prefix of the IMSI. - * - * @throws Exception - */ - @Test - public void matchesMccMncFullImsi() throws Exception { - IMSIParameter param = new IMSIParameter(VALID_FULL_IMSI, false); - - assertFalse(param.matchesMccMnc(INVALID_MCC_MNC)); // Invalid length for MCC-MNC - assertTrue(param.matchesMccMnc(VALID_MCC_MNC)); - assertTrue(param.matchesMccMnc(VALID_MCC_MNC_6)); - } - - /** - * Verify that an IMSIParameter containing an IMSI prefix whose length is different from - * that of matching MccMnc, it should return false. - * - * @throws Exception - */ - @Test - public void matchesMccMncWithPrefixImsiWithDifferentMccMncLength() throws Exception { - IMSIParameter param = new IMSIParameter(VALID_MCC_MNC, true); - - assertFalse(param.matchesMccMnc(VALID_MCC_MNC_6)); // length of Prefix mismatch - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java deleted file mode 100644 index 77d5c1933..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.util.Xml; - -import com.android.internal.util.FastXmlSerializer; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -public class ImsiPrivacyProtectionExemptionStoreDataTest { - private static final int TEST_CARRIER_ID = 1911; - - private @Mock ImsiPrivacyProtectionExemptionStoreData.DataSource mDataSource; - private ImsiPrivacyProtectionExemptionStoreData mImsiPrivacyProtectionExemptionStoreData; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mImsiPrivacyProtectionExemptionStoreData = - new ImsiPrivacyProtectionExemptionStoreData(mDataSource); - } - - /** - * Helper function for serializing configuration data to a XML block. - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mImsiPrivacyProtectionExemptionStoreData.serializeData(out, null); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing configuration data from a XML block. - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mImsiPrivacyProtectionExemptionStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, null); - } - - /** - * Verify store file Id. - */ - @Test - public void verifyStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_USER_GENERAL, - mImsiPrivacyProtectionExemptionStoreData.getStoreFileId()); - } - - /** - * Verify serialize and deserialize Protection exemption map. - */ - @Test - public void testSerializeDeserialize() throws Exception { - Map<Integer, Boolean> imsiPrivacyProtectionExemptionMap = new HashMap<>(); - imsiPrivacyProtectionExemptionMap.put(TEST_CARRIER_ID, true); - assertSerializeDeserialize(imsiPrivacyProtectionExemptionMap); - } - - /** - * Verify serialize and deserialize empty protection exemption map. - */ - @Test - public void testSerializeDeserializeEmpty() throws Exception { - Map<Integer, Boolean> imsiPrivacyProtectionExemptionMap = new HashMap<>(); - assertSerializeDeserialize(imsiPrivacyProtectionExemptionMap); - } - - @Test - public void testDeserializeOnNewDeviceOrNewUser() throws Exception { - ArgumentCaptor<Map> deserializedNetworkSuggestionsMap = - ArgumentCaptor.forClass(Map.class); - mImsiPrivacyProtectionExemptionStoreData.deserializeData(null, 0, - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, null); - verify(mDataSource).fromDeserialized(deserializedNetworkSuggestionsMap.capture()); - assertTrue(deserializedNetworkSuggestionsMap.getValue().isEmpty()); - } - - - private Map<Integer, Boolean> assertSerializeDeserialize( - Map<Integer, Boolean> mImsiPrivacyProtectionExemptionMap) throws Exception { - // Setup the data to serialize. - when(mDataSource.toSerialize()).thenReturn(mImsiPrivacyProtectionExemptionMap); - - // Serialize/deserialize data. - deserializeData(serializeData()); - - // Verify the deserialized data. - ArgumentCaptor<HashMap> deserializedNetworkSuggestionsMap = - ArgumentCaptor.forClass(HashMap.class); - verify(mDataSource).fromDeserialized(deserializedNetworkSuggestionsMap.capture()); - assertEquals(mImsiPrivacyProtectionExemptionMap, - deserializedNetworkSuggestionsMap.getValue()); - return deserializedNetworkSuggestionsMap.getValue(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/IpConfigStoreTestWriter.java b/tests/wifitests/src/com/android/server/wifi/IpConfigStoreTestWriter.java deleted file mode 100644 index f5a81bcb4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/IpConfigStoreTestWriter.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import android.net.IpConfiguration; -import android.net.LinkAddress; -import android.net.ProxyInfo; -import android.net.StaticIpConfiguration; -import android.util.Log; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.InetAddress; - -/** - * Copied from frameworks/base/services/core/java/com/android/server/net/IpConfigStore.java - */ -public class IpConfigStoreTestWriter { - private static final String TAG = "IpConfigStoreTestWriter"; - - private static final String ID_KEY = "id"; - private static final String IP_ASSIGNMENT_KEY = "ipAssignment"; - private static final String LINK_ADDRESS_KEY = "linkAddress"; - private static final String GATEWAY_KEY = "gateway"; - private static final String DNS_KEY = "dns"; - private static final String PROXY_SETTINGS_KEY = "proxySettings"; - private static final String PROXY_HOST_KEY = "proxyHost"; - private static final String PROXY_PORT_KEY = "proxyPort"; - private static final String PROXY_PAC_FILE = "proxyPac"; - private static final String EXCLUSION_LIST_KEY = "exclusionList"; - private static final String EOS = "eos"; - - /** Serialize an IpConfiguration object */ - public static boolean writeConfig(DataOutputStream out, String configKey, - IpConfiguration config, int version) throws IOException { - boolean written = false; - - try { - switch (config.ipAssignment) { - case STATIC: - out.writeUTF(IP_ASSIGNMENT_KEY); - out.writeUTF(config.ipAssignment.toString()); - StaticIpConfiguration staticIpConfiguration = config.staticIpConfiguration; - if (staticIpConfiguration != null) { - if (staticIpConfiguration.ipAddress != null) { - LinkAddress ipAddress = staticIpConfiguration.ipAddress; - out.writeUTF(LINK_ADDRESS_KEY); - out.writeUTF(ipAddress.getAddress().getHostAddress()); - out.writeInt(ipAddress.getPrefixLength()); - } - if (staticIpConfiguration.gateway != null) { - out.writeUTF(GATEWAY_KEY); - out.writeInt(0); // Default route. - out.writeInt(1); // Have a gateway. - out.writeUTF(staticIpConfiguration.gateway.getHostAddress()); - } - for (InetAddress inetAddr : staticIpConfiguration.dnsServers) { - out.writeUTF(DNS_KEY); - out.writeUTF(inetAddr.getHostAddress()); - } - } - written = true; - break; - case DHCP: - out.writeUTF(IP_ASSIGNMENT_KEY); - out.writeUTF(config.ipAssignment.toString()); - written = true; - break; - case UNASSIGNED: - /* Ignore */ - break; - default: - loge("Ignore invalid ip assignment while writing"); - break; - } - - switch (config.proxySettings) { - case STATIC: - ProxyInfo proxyProperties = config.httpProxy; - String exclusionList = proxyProperties.getExclusionListAsString(); - out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); - out.writeUTF(PROXY_HOST_KEY); - out.writeUTF(proxyProperties.getHost()); - out.writeUTF(PROXY_PORT_KEY); - out.writeInt(proxyProperties.getPort()); - if (exclusionList != null) { - out.writeUTF(EXCLUSION_LIST_KEY); - out.writeUTF(exclusionList); - } - written = true; - break; - case PAC: - ProxyInfo proxyPacProperties = config.httpProxy; - out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); - out.writeUTF(PROXY_PAC_FILE); - out.writeUTF(proxyPacProperties.getPacFileUrl().toString()); - written = true; - break; - case NONE: - out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); - written = true; - break; - case UNASSIGNED: - /* Ignore */ - break; - default: - loge("Ignore invalid proxy settings while writing"); - break; - } - - if (written) { - out.writeUTF(ID_KEY); - if (version < 3) { - out.writeInt(Integer.valueOf(configKey)); - } else { - out.writeUTF(configKey); - } - } - } catch (NullPointerException e) { - loge("Failure in writing " + config + e); - } - out.writeUTF(EOS); - - return written; - } - - private static void loge(String s) { - Log.e(TAG, s); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/LastMileLoggerTest.java b/tests/wifitests/src/com/android/server/wifi/LastMileLoggerTest.java deleted file mode 100644 index 6d76f4a85..000000000 --- a/tests/wifitests/src/com/android/server/wifi/LastMileLoggerTest.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.contains; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.FileUtils; - -import libcore.io.IoUtils; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; - -/** - * Unit tests for {@link LastMileLogger}. - */ -@SmallTest -public class LastMileLoggerTest extends WifiBaseTest { - @Mock WifiInjector mWifiInjector; - @Spy FakeWifiLog mLog; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mWifiInjector.makeLog(anyString())).thenReturn(mLog); - mTraceDataFile = File.createTempFile(TRACE_DATA_PREFIX, null); - mTraceEnableFile = File.createTempFile(TRACE_ENABLE_PREFIX, null); - mTraceReleaseFile = File.createTempFile(TRACE_RELEASE_PREFIX, null); - mTraceDataFile.deleteOnExit(); - mTraceEnableFile.deleteOnExit(); - mTraceReleaseFile.deleteOnExit(); - FileUtils.stringToFile(mTraceEnableFile.getPath(), "0"); - mLastMileLogger = new LastMileLogger(mWifiInjector, mTraceDataFile.getPath(), - mTraceEnableFile.getPath(), mTraceReleaseFile.getPath()); - } - - @Test - public void ctorDoesNotCrash() throws Exception { - new LastMileLogger(mWifiInjector, mTraceDataFile.getPath(), mTraceEnableFile.getPath(), - mTraceReleaseFile.getPath()); - verifyZeroInteractions(mLog); - } - - @Test - public void connectionEventStartedEnablesTracing() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - assertEquals("1", IoUtils.readFileAsString(mTraceEnableFile.getPath())); - } - - @Test - public void connectionEventStartedDoesNotCrashIfReleaseFileIsMissing() throws Exception { - mTraceReleaseFile.delete(); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - verify(mLog).warn(contains("Failed to open free_buffer")); - } - - @Test - public void connectionEventStartedDoesNotEnableTracingIfReleaseFileIsMissing() - throws Exception { - mTraceReleaseFile.delete(); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - assertEquals("0", IoUtils.readFileAsString(mTraceEnableFile.getPath())); - } - - @Test - public void connectionEventStartedDoesNotAttemptToReopenReleaseFile() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - - // This is a rather round-about way of verifying that we don't attempt to re-open - // the file. Namely: if we delete the |release| file, and CONNECTION_EVENT_STARTED - // _did_ re-open the file, then we'd log an error message. Since the test is deleting the - // |release| file, the absence of a warning message means that we didn't try to open the - // file again. - // - // A more direct test would require the use of a factory for the creation of the - // FileInputStream. - mTraceReleaseFile.delete(); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - verifyZeroInteractions(mLog); - } - - @Test - public void connectionEventStartedDoesNotCrashIfEnableFileIsMissing() throws Exception { - mTraceEnableFile.delete(); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - } - - @Test - public void connectionEventStartedDoesNotCrashOnRepeatedCalls() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - } - - @Test - public void connectionEventSucceededDisablesTracing() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); - assertEquals("0", IoUtils.readFileAsString(mTraceEnableFile.getPath())); - } - - @Test - public void connectionEventSucceededDoesNotCrashIfEnableFileIsMissing() throws Exception { - mTraceEnableFile.delete(); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); - } - - @Test - public void connectionEventSucceededDoesNotCrashOnRepeatedCalls() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); - } - - @Test - public void connectionEventFailedDisablesTracingWhenPendingFails() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - assertEquals("0", IoUtils.readFileAsString(mTraceEnableFile.getPath())); - } - - @Test - public void connectionEventTimeoutDisablesTracing() - throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT); - assertEquals("0", IoUtils.readFileAsString(mTraceEnableFile.getPath())); - } - - @Test - public void connectionEventFailedDoesNotCrashIfEnableFileIsMissing() throws Exception { - mTraceEnableFile.delete(); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - } - - @Test - public void connectionEventFailedDoesNotCrashIfDataFileIsMissing() throws Exception { - mTraceDataFile.delete(); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - } - - @Test - public void connectionEventFailedDoesNotCrashOnRepeatedCalls() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - } - - @Test - public void dumpShowsFailureTrace() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - FileUtils.stringToFile(mTraceDataFile.getPath(), "rdev_connect"); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - assertTrue(getDumpString().contains("--- Last failed")); - assertTrue(getDumpString().contains("rdev_connect")); - } - - - @Test - public void dumpShowsPendingConnectionTrace() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - FileUtils.stringToFile(mTraceDataFile.getPath(), "rdev_connect"); - assertTrue(getDumpString().contains("No last mile log for \"Last failed")); - assertTrue(getDumpString().contains("--- Latest")); - assertTrue(getDumpString().contains("rdev_connect")); - } - - @Test - public void dumpShowsLastFailureTraceAndPendingConnectionTrace() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - FileUtils.stringToFile(mTraceDataFile.getPath(), "rdev_connect try #1"); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - FileUtils.stringToFile(mTraceDataFile.getPath(), "rdev_connect try #2"); - - String dumpString = getDumpString(); - assertTrue(dumpString.contains("rdev_connect try #1")); - assertTrue(dumpString.contains("rdev_connect try #2")); - } - - @Test - public void dumpShowsLastFailureTraceAndCurrentConnectionTrace() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - FileUtils.stringToFile(mTraceDataFile.getPath(), "rdev_connect try #1"); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - FileUtils.stringToFile(mTraceDataFile.getPath(), "rdev_connect try #2"); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); - - String dumpString = getDumpString(); - assertTrue(dumpString.contains("rdev_connect try #1")); - assertTrue(dumpString.contains("rdev_connect try #2")); - } - - @Test - public void dumpDoesNotClearLastFailureData() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - FileUtils.stringToFile(mTraceDataFile.getPath(), "rdev_connect"); - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); - - getDumpString(); - String dumpString = getDumpString(); - assertTrue(dumpString.contains("rdev_connect")); - } - - @Test - public void dumpDoesNotClearPendingConnectionTrace() throws Exception { - mLastMileLogger.reportConnectionEvent(BaseWifiDiagnostics.CONNECTION_EVENT_STARTED); - FileUtils.stringToFile(mTraceDataFile.getPath(), "rdev_connect"); - - getDumpString(); - String dumpString = getDumpString(); - assertTrue(dumpString.contains("rdev_connect")); - } - - @Test - public void dumpDoesNotCrashIfDataFileIsEmpty() throws Exception { - getDumpString(); - } - - @Test - public void dumpDoesNotCrashIfDataFileIsMissing() throws Exception { - mTraceDataFile.delete(); - getDumpString(); - } - - private static final String TRACE_DATA_PREFIX = "last-mile-logger-trace-data"; - private static final String TRACE_ENABLE_PREFIX = "last-mile-logger-trace-enable"; - private static final String TRACE_RELEASE_PREFIX = "last-mile-logger-trace-release"; - private LastMileLogger mLastMileLogger; - private File mTraceDataFile; - private File mTraceEnableFile; - private File mTraceReleaseFile; - - private String getDumpString() { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mLastMileLogger.dump(pw); - return sw.toString(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/LinkProbeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/LinkProbeManagerTest.java deleted file mode 100644 index 746976aef..000000000 --- a/tests/wifitests/src/com/android/server/wifi/LinkProbeManagerTest.java +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static junit.framework.Assert.assertEquals; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.wifi.WifiInfo; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.Handler; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.HashSet; - -/** - * Unit tests for LinkProbeManager - */ -@SmallTest -public class LinkProbeManagerTest extends WifiBaseTest { - - private static final String TEST_IFACE_NAME = "testIfaceName"; - private static final String TEST_BSSID = "6c:f3:7f:ae:8c:f3"; - private static final int TEST_ELAPSED_TIME_MS = 100; - - private LinkProbeManager mLinkProbeManager; - - private WifiInfo mWifiInfo; - private long mTimeMs; - @Mock private Clock mClock; - @Mock private WifiNative mWifiNative; - @Mock private WifiMetrics mWifiMetrics; - @Mock private FrameworkFacade mFrameworkFacade; - @Mock private Context mContext; - - private TestLooper mLooper = new TestLooper(); - private MockResources mResources; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mResources = new MockResources(); - mResources.setBoolean(R.bool.config_wifi_link_probing_supported, true); - when(mContext.getResources()).thenReturn(mResources); - - initLinkProbeManager(); - - mWifiInfo = new WifiInfo(); - mWifiInfo.setBSSID(TEST_BSSID); - mTimeMs = 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - - // Simulate new connection to trigger check for isSupported resource flag. - mLinkProbeManager.resetOnNewConnection(); - mLinkProbeManager.resetOnScreenTurnedOn(); - } - - private void initLinkProbeManager() { - mLinkProbeManager = new LinkProbeManager(mClock, mWifiNative, mWifiMetrics, - mFrameworkFacade, new Handler(mLooper.getLooper()), mContext); - } - - /** - * Tests that link probing is correctly triggered when the required conditions are met, and an - * ACK was received from the AP. - */ - @Test - public void testLinkProbeTriggeredAndAcked() throws Exception { - // initialize tx success counter - mWifiInfo.txSuccess = 50; - mTimeMs += 3000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - // should not probe yet - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - verify(mWifiMetrics, never()).incrementLinkProbeExperimentProbeCount(any()); - - // tx success counter did not change since last update - mWifiInfo.txSuccess = 50; - // below RSSI threshold - int rssi = LinkProbeManager.RSSI_THRESHOLD - 5; - mWifiInfo.setRssi(rssi); - // above link speed threshold - int linkSpeed = LinkProbeManager.LINK_SPEED_THRESHOLD_MBPS + 10; - mWifiInfo.setLinkSpeed(linkSpeed); - // more than DELAY_AFTER_TX_SUCCESS_MS passed - long timeDelta = LinkProbeManager.DELAY_AFTER_TX_SUCCESS_MS + 20000; - mTimeMs += timeDelta; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - ArgumentCaptor<WifiNl80211Manager.SendMgmtFrameCallback> callbackCaptor = - ArgumentCaptor.forClass(WifiNl80211Manager.SendMgmtFrameCallback.class); - verify(mWifiNative).probeLink(eq(TEST_IFACE_NAME), any(), callbackCaptor.capture(), - anyInt()); - ArgumentCaptor<String> experimentIdCaptor = ArgumentCaptor.forClass(String.class); - verify(mWifiMetrics, atLeastOnce()).incrementLinkProbeExperimentProbeCount( - experimentIdCaptor.capture()); - int numExperimentIds = LinkProbeManager.EXPERIMENT_DELAYS_MS.length - * LinkProbeManager.EXPERIMENT_RSSIS.length - * LinkProbeManager.EXPERIMENT_LINK_SPEEDS.length; - assertEquals(numExperimentIds, new HashSet<>(experimentIdCaptor.getAllValues()).size()); - - callbackCaptor.getValue().onAck(TEST_ELAPSED_TIME_MS); - verify(mWifiMetrics).logLinkProbeSuccess(timeDelta, rssi, linkSpeed, TEST_ELAPSED_TIME_MS); - } - - /** - * Tests that link probing is correctly triggered when the required conditions are met, but - * no ACK was received from the AP. - */ - @Test - public void testLinkProbeTriggeredAndFailed() throws Exception { - // initialize tx success counter - mWifiInfo.txSuccess = 50; - mTimeMs += 3000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - // should not probe yet - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - - // tx success counter did not change since last update - mWifiInfo.txSuccess = 50; - // above RSSI threshold - int rssi = LinkProbeManager.RSSI_THRESHOLD + 5; - mWifiInfo.setRssi(rssi); - // below link speed threshold - int linkSpeed = LinkProbeManager.LINK_SPEED_THRESHOLD_MBPS - 2; - mWifiInfo.setLinkSpeed(linkSpeed); - // more than DELAY_BETWEEN_PROBES_MS passed - long timeDelta = LinkProbeManager.DELAY_BETWEEN_PROBES_MS + 1000; - mTimeMs += timeDelta; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - ArgumentCaptor<WifiNl80211Manager.SendMgmtFrameCallback> callbackCaptor = - ArgumentCaptor.forClass(WifiNl80211Manager.SendMgmtFrameCallback.class); - verify(mWifiNative).probeLink(eq(TEST_IFACE_NAME), any(), callbackCaptor.capture(), - anyInt()); - - callbackCaptor.getValue().onFailure(WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK); - verify(mWifiMetrics).logLinkProbeFailure(timeDelta, rssi, linkSpeed, - WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK); - } - - /** - * Tests that link probing is not triggered more than once every DELAY_BETWEEN_PROBES_MS - */ - @Test - public void testLinkProbeNotTriggeredTooFrequently() throws Exception { - testLinkProbeTriggeredAndAcked(); - - // tx success counter did not change since last update - mWifiInfo.txSuccess = 50; - // below RSSI threshold - mWifiInfo.setRssi(LinkProbeManager.RSSI_THRESHOLD - 5); - // above link speed threshold - mWifiInfo.setLinkSpeed(LinkProbeManager.LINK_SPEED_THRESHOLD_MBPS + 10); - // *** but less than DELAY_BETWEEN_PROBES_MS has passed since last probe *** - mTimeMs += LinkProbeManager.DELAY_BETWEEN_PROBES_MS - 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - // should not probe - verifyNoMoreInteractions(mWifiNative); - } - - /** - * Tests that link probing is not triggered when Tx has succeeded within the last - * DELAY_AFTER_TX_SUCCESS_MS. - */ - @Test - public void testLinkProbeNotTriggeredWhenTxSucceeded() throws Exception { - // initialize tx success counter - mWifiInfo.txSuccess = 50; - mTimeMs += 3000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - // should not probe yet - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - - // tx succeeded - mWifiInfo.txSuccess = 55; - mTimeMs += 3000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - // should not probe yet - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - - // tx success counter did not change since last update - mWifiInfo.txSuccess = 55; - // below RSSI threshold - mWifiInfo.setRssi(LinkProbeManager.RSSI_THRESHOLD - 5); - // above link speed threshold - mWifiInfo.setLinkSpeed(LinkProbeManager.LINK_SPEED_THRESHOLD_MBPS + 10); - // *** but less than DELAY_AFTER_TX_SUCCESS_MS has passed since last tx success *** - mTimeMs += LinkProbeManager.DELAY_AFTER_TX_SUCCESS_MS - 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - } - - /** - * Tests that link probing is not triggered when screen was turned on within the last - * {@link LinkProbeManager#SCREEN_ON_DELAY_MS}. - */ - @Test - public void testLinkProbeNotTriggeredWhenScreenJustTurnedOn() throws Exception { - mTimeMs += 30 * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.resetOnScreenTurnedOn(); - // should not probe yet - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - - // tx success counter did not change since initialization - mWifiInfo.txSuccess = 0; - // below RSSI threshold - mWifiInfo.setRssi(LinkProbeManager.RSSI_THRESHOLD - 5); - // above link speed threshold - mWifiInfo.setLinkSpeed(LinkProbeManager.LINK_SPEED_THRESHOLD_MBPS + 10); - // *** but less than SCREEN_ON_DELAY_MS has passed since last screen on *** - mTimeMs += LinkProbeManager.SCREEN_ON_DELAY_MS - 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - } - - /** - * Tests that link probing is triggered when screen was turned on more than - * {@link LinkProbeManager#SCREEN_ON_DELAY_MS} ago. - */ - @Test - public void testLinkProbeTriggeredAfterScreenTurnedOn() throws Exception { - mTimeMs += 30 * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.resetOnScreenTurnedOn(); - // should not probe yet - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - - // tx success counter did not change since initialization - mWifiInfo.txSuccess = 0; - // below RSSI threshold - mWifiInfo.setRssi(LinkProbeManager.RSSI_THRESHOLD - 5); - // above link speed threshold - mWifiInfo.setLinkSpeed(LinkProbeManager.LINK_SPEED_THRESHOLD_MBPS + 10); - // *** more than SCREEN_ON_DELAY_MS has passed since last screen on *** - mTimeMs += LinkProbeManager.SCREEN_ON_DELAY_MS + 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - verify(mWifiNative).probeLink(eq(TEST_IFACE_NAME), any(), any(), anyInt()); - } - - /** - * Tests when link probing feature is not supported by the device, no probes should run. - */ - @Test - public void testLinkProbeFeatureUnsupported() throws Exception { - mResources.setBoolean(R.bool.config_wifi_link_probing_supported, false); - initLinkProbeManager(); - - // initialize tx success counter - mWifiInfo.txSuccess = 50; - mTimeMs += 3000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - // should not probe yet - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - - // tx success counter did not change since last update - mWifiInfo.txSuccess = 50; - // below RSSI threshold - int rssi = LinkProbeManager.RSSI_THRESHOLD - 5; - mWifiInfo.setRssi(rssi); - // above link speed threshold - int linkSpeed = LinkProbeManager.LINK_SPEED_THRESHOLD_MBPS + 10; - mWifiInfo.setLinkSpeed(linkSpeed); - // more than DELAY_AFTER_TX_SUCCESS_MS passed - long timeDelta = LinkProbeManager.DELAY_AFTER_TX_SUCCESS_MS + 1000; - mTimeMs += timeDelta; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - verify(mWifiNative, never()).probeLink(any() , any(), any(), anyInt()); - } - - /** - * Tests exhausting the daily link probe quota and verify that no more link probes are made - * after the limit is reached. Tests that the quota is reset upon entering a new day. - */ - @Test - public void testLinkProbeQuotaExceeded() { - mTimeMs += 30 * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - // should not probe yet - verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt()); - - // tx success counter did not change since initialization - mWifiInfo.txSuccess = 0; - // below RSSI threshold - mWifiInfo.setRssi(LinkProbeManager.RSSI_THRESHOLD - 5); - // above link speed threshold - mWifiInfo.setLinkSpeed(LinkProbeManager.LINK_SPEED_THRESHOLD_MBPS + 10); - - // exhaust quota - for (int i = 1; i <= LinkProbeManager.MAX_PROBE_COUNT_IN_PERIOD; i++) { - mTimeMs += LinkProbeManager.DELAY_BETWEEN_PROBES_MS + 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - } - verify(mWifiNative, times((int) LinkProbeManager.MAX_PROBE_COUNT_IN_PERIOD)) - .probeLink(eq(TEST_IFACE_NAME), any(), any(), anyInt()); - // verify no more quota - for (int i = 0; i < 10; i++) { - mTimeMs += LinkProbeManager.DELAY_BETWEEN_PROBES_MS + 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - } - verify(mWifiNative, times((int) LinkProbeManager.MAX_PROBE_COUNT_IN_PERIOD)) - .probeLink(eq(TEST_IFACE_NAME), any(), any(), anyInt()); - - // start new period - mTimeMs += LinkProbeManager.PERIOD_MILLIS + 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - - // exhaust quota again - for (int i = 1; i <= LinkProbeManager.MAX_PROBE_COUNT_IN_PERIOD; i++) { - mTimeMs += LinkProbeManager.DELAY_BETWEEN_PROBES_MS + 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - } - verify(mWifiNative, times((int) (2 * LinkProbeManager.MAX_PROBE_COUNT_IN_PERIOD))) - .probeLink(eq(TEST_IFACE_NAME), any(), any(), anyInt()); - // verify no more quota again - for (int i = 0; i < 10; i++) { - mTimeMs += LinkProbeManager.DELAY_BETWEEN_PROBES_MS + 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mTimeMs); - mLinkProbeManager.updateConnectionStats(mWifiInfo, TEST_IFACE_NAME); - } - verify(mWifiNative, times((int) (2 * LinkProbeManager.MAX_PROBE_COUNT_IN_PERIOD))) - .probeLink(eq(TEST_IFACE_NAME), any(), any(), anyInt()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/LocalOnlyHotspotRequestInfoTest.java b/tests/wifitests/src/com/android/server/wifi/LocalOnlyHotspotRequestInfoTest.java deleted file mode 100644 index 0d29c3199..000000000 --- a/tests/wifitests/src/com/android/server/wifi/LocalOnlyHotspotRequestInfoTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; - -import android.net.wifi.ILocalOnlyHotspotCallback; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiManager; -import android.os.IBinder; -import android.os.Process; -import android.os.RemoteException; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/* - * Unit tests for {@link com.android.server.wifi.LocalOnlyHotspotRequestInfo}. - */ -@SmallTest -public class LocalOnlyHotspotRequestInfoTest extends WifiBaseTest { - - private static final String TAG = "LocalOnlyHotspotRequestInfoTest"; - @Mock IBinder mAppBinder; - @Mock ILocalOnlyHotspotCallback mCallback; - @Mock LocalOnlyHotspotRequestInfo.RequestingApplicationDeathCallback mDeathCallback; - RemoteException mRemoteException; - private LocalOnlyHotspotRequestInfo mLOHSRequestInfo; - - /** - * Setup test. - */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(mCallback.asBinder()).thenReturn(mAppBinder); - mRemoteException = new RemoteException("Test Remote Exception"); - } - - /** - * Make sure we link the call to request LocalOnlyHotspot by an app is linked to their Binder - * call. This allows us to clean up if the app dies. - */ - @Test - public void verifyBinderLinkToDeathIsCalled() throws Exception { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, null); - verify(mAppBinder).linkToDeath(eq(mLOHSRequestInfo), eq(0)); - } - - /** - * Calls to link the requestor to binder death should not pass null binder - */ - @Test(expected = NullPointerException.class) - public void verifyNullCallbackChecked() throws Exception { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(null, mDeathCallback, null); - } - - /** - * Calls to create the requestor to binder death should not pass null death callback. - */ - @Test(expected = NullPointerException.class) - public void verifyNullDeathCallbackChecked() throws Exception { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, null, null); - } - - /** - * Calls to unlink the DeathRecipient should call to unlink from Binder. - */ - @Test - public void verifyUnlinkDeathRecipientUnlinksFromBinder() throws Exception { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, null); - mLOHSRequestInfo.unlinkDeathRecipient(); - verify(mAppBinder).unlinkToDeath(eq(mLOHSRequestInfo), eq(0)); - } - - /** - * Binder death notification should trigger a callback on the requestor. - */ - @Test - public void verifyBinderDeathTriggersCallback() { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, null); - mLOHSRequestInfo.binderDied(); - verify(mDeathCallback).onLocalOnlyHotspotRequestorDeath(eq(mLOHSRequestInfo)); - } - - /** - * Verify a RemoteException when calling linkToDeath triggers the callback. - */ - @Test - public void verifyRemoteExceptionTriggersCallback() throws Exception { - doThrow(mRemoteException).when(mAppBinder) - .linkToDeath(any(IBinder.DeathRecipient.class), eq(0)); - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, null); - verify(mDeathCallback).onLocalOnlyHotspotRequestorDeath(eq(mLOHSRequestInfo)); - } - - /** - * Verify the pid is properly set. - */ - @Test - public void verifyPid() { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, null); - assertEquals(Process.myPid(), mLOHSRequestInfo.getPid()); - } - - @Test - public void verifyCustomConfig() { - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setSsid("customSsid") - .build(); - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, config); - assertEquals(config, mLOHSRequestInfo.getCustomConfig()); - } - - /** - * Verify that sendHotspotFailedMessage does send a Message properly - */ - @Test - public void verifySendFailedMessage() throws Exception { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, null); - mLOHSRequestInfo.sendHotspotFailedMessage( - WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC); - verify(mCallback).onHotspotFailed(WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC); - } - - /** - * Verify that sendHotspotStartedMessage does send a Message properly - */ - @Test - public void verifySendStartedMessage() throws Exception { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, null); - SoftApConfiguration config = mock(SoftApConfiguration.class); - mLOHSRequestInfo.sendHotspotStartedMessage(config); - ArgumentCaptor<SoftApConfiguration> mSoftApConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - - verify(mCallback).onHotspotStarted(mSoftApConfigCaptor.capture()); - assertEquals(config, mSoftApConfigCaptor.getValue()); - } - - /** - * Verify that sendHotspotStoppedMessage does send a Message properly - */ - @Test - public void verifySendStoppedMessage() throws Exception { - mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mCallback, mDeathCallback, null); - mLOHSRequestInfo.sendHotspotStoppedMessage(); - verify(mCallback).onHotspotStopped(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/LogcatLogTest.java b/tests/wifitests/src/com/android/server/wifi/LogcatLogTest.java deleted file mode 100644 index a29c863d8..000000000 --- a/tests/wifitests/src/com/android/server/wifi/LogcatLogTest.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for {@link LogcatLog}. - */ -@SmallTest -public class LogcatLogTest extends WifiBaseTest { - private static final String TAG = "LogcatLogTest"; - private LogcatLog mLogger; - - /** Initializes test fixture. */ - @Before - public void setUp() { - mLogger = new LogcatLog(TAG); - } - - /** - * Verifies that LogcatLog's LogMessage implementation correctly - * handles a format with no parameters. - * - * Note: In practice, we expect clients to use eC() and friends - * when the message is a literal. But we still want to make sure - * this functionality works. - */ - @Test - public void logMessageWorksWithParameterlessFormat() { - WifiLog.LogMessage logMessage = mLogger.err("hello world"); - logMessage.flush(); - assertEquals("hello world", logMessage.toString()); - } - - /** Verifies that LogMessage works with an empty format. */ - @Test - public void logMessageWorksWithEmptyFormat() { - WifiLog.LogMessage logMessage = mLogger.err(""); - logMessage.flush(); - assertEquals("", logMessage.toString()); - } - - /** Verifies that LogMessage works with a value-only format. */ - @Test - public void logMessageWorksWithValueOnly() { - WifiLog.LogMessage logMessage = mLogger.err("%"); - logMessage.c(1).flush(); - assertEquals("1", logMessage.toString()); - } - - /** - * Verifies that LogMessage works when the placeholder is replaced - * by the placeholder character. - */ - @Test - public void logMessageIsNotConfusedByPlaceholderInValue() { - WifiLog.LogMessage logMessage = mLogger.err("%"); - logMessage.c('%').flush(); - assertEquals("%", logMessage.toString()); - } - - /** Verifies that LogMessage works when a value is at the start of the format. */ - @Test - public void logMessageWorksWithValueAtBegin() { - WifiLog.LogMessage logMessage = mLogger.err("%stuff"); - logMessage.c(1).flush(); - assertEquals("1stuff", logMessage.toString()); - } - - /** Verifies that LogMessage works when a value is in the middle of the format. */ - @Test - public void logMessageWorksWithValueInMiddle() { - WifiLog.LogMessage logMessage = mLogger.err("s%uff"); - logMessage.c(1).flush(); - assertEquals("s1uff", logMessage.toString()); - } - - /** Verifies that LogMessage works when a value is at the end of the format. */ - @Test - public void logMessageWorksWithValueAtEnd() { - WifiLog.LogMessage logMessage = mLogger.err("stuff%"); - logMessage.c(1).flush(); - assertEquals("stuff1", logMessage.toString()); - } - - /** Verifies that LogMessage works when a format has multiple values. */ - @Test - public void logMessageWorksWithMultipleValues() { - WifiLog.LogMessage logMessage = mLogger.err("% %"); - logMessage.c("hello").c("world").flush(); - assertEquals("hello world", logMessage.toString()); - } - - /** Verifies that LogMessage works when a format has multiple values and literals. */ - @Test - public void logMessageWorksWithMultipleValuesAndLiterals() { - WifiLog.LogMessage logMessage = mLogger.err("first:% second:%"); - logMessage.c("hello").c("world").flush(); - assertEquals("first:hello second:world", logMessage.toString()); - } - - /** Verifies that LogMessage works when a format has multiple adjacent values. */ - @Test - public void logMessageWorksWithAdjacentValues() { - WifiLog.LogMessage logMessage = mLogger.err("%%"); - logMessage.c("hello").c("world").flush(); - assertEquals("helloworld", logMessage.toString()); - } - - /** Verifies that LogMessage silently ignores extraneous values. */ - @Test - public void logMessageSilentlyIgnoresExtraneousValues() { - WifiLog.LogMessage logMessage = mLogger.err("%"); - logMessage.c("hello world").c("more stuff").flush(); - assertEquals("hello world", logMessage.toString()); - } - - /** - * Verifies that LogMessage silently ignores extraneous values, - * even with an empty format string. - */ - @Test - public void logMessageSilentlyIgnoresExtraneousValuesEvenForEmptyFormat() { - WifiLog.LogMessage logMessage = mLogger.err(""); - logMessage.c("hello world").c("more stuff").flush(); - assertEquals("", logMessage.toString()); - } - - /** - * Verifies that LogMessage silently ignores extraneous values, - * even if the format string is all literals. - */ - @Test - public void logMessageSilentlyIgnoresExtraneousValuesEvenForFormatWithoutPlaceholders() { - WifiLog.LogMessage logMessage = mLogger.err("literal format"); - logMessage.c("hello world").c("more stuff").flush(); - assertEquals("literal format", logMessage.toString()); - } - - /** Verifies that LogMessage copies an unused placeholder to output. */ - @Test - public void logMessageCopiesUnusedPlaceholderToOutput() { - WifiLog.LogMessage logMessage = mLogger.err("%"); - logMessage.flush(); - assertEquals("%", logMessage.toString()); - } - - /** Verifies that LogMessage copies multiple unused placeholders to output. */ - @Test - public void logMessageCopiesMultipleUnusedPlaceholdersToOutput() { - WifiLog.LogMessage logMessage = mLogger.err("%%%%%"); - logMessage.flush(); - assertEquals("%%%%%", logMessage.toString()); - } - - /** - * Verifies that LogMessage copies an unused placeholder to output, - * even if preceded by non-placeholders. - */ - @Test - public void logMessageCopiesUnusedPlaceholderAtEndToOutput() { - WifiLog.LogMessage logMessage = mLogger.err("foo%"); - logMessage.flush(); - assertEquals("foo%", logMessage.toString()); - } - - /** - * Verifies that LogMessage copies an unused placeholder to output, - * even if followed by non-placeholders. - */ - @Test - public void logMessageCopiesUnusedPlaceholderAtBeginToOutput() { - WifiLog.LogMessage logMessage = mLogger.err("%foo"); - logMessage.flush(); - assertEquals("%foo", logMessage.toString()); - } - - /** - * Verifies that LogMessage copies an unused placeholder to output, - * even if it is in the middle of non-placeholders. - */ - @Test - public void logMessageCopiesUnusedPlaceholderInMiddleToOutput() { - WifiLog.LogMessage logMessage = mLogger.err("f%o"); - logMessage.flush(); - assertEquals("f%o", logMessage.toString()); - } - - /** - * Verifies that LogMessage copies multiple unused placeholders to output, - * even if they are embedded amongst non-placeholders. - */ - @Test - public void logMessageCopiesUnusedPlaceholdersInMiddleToOutput() { - WifiLog.LogMessage logMessage = mLogger.err("f%o%o%d"); - logMessage.flush(); - assertEquals("f%o%o%d", logMessage.toString()); - } - - /** - * Verifies that LogMessage preserves meta-characters in format string. - * - * Note that we deliberately test only the meta-characters that we - * expect to find in log messages. (Newline might also be - * preserved, but clients shouldn't depend on that, as messages - * that have newlines make logs hard to read.) - */ - @Test - public void logMessagePreservesMetaCharactersInFormat() { - WifiLog.LogMessage logMessage = mLogger.err("\\hello\tworld\\"); - logMessage.flush(); - assertEquals("\\hello\tworld\\", logMessage.toString()); - } - - /** Verifies that LogMessage propagates meta-characters in char values. */ - @Test - public void logMessagePropagatesMetaCharactersInCharValues() { - WifiLog.LogMessage logMessage = mLogger.err("hello%big%world"); - logMessage.c('\t').c('\\').flush(); - assertEquals("hello\tbig\\world", logMessage.toString()); - } - - /** Verifies that LogMessage propagates meta-characters in String values. */ - @Test - public void logMessagePropagatesMetaCharactersInStringValues() { - WifiLog.LogMessage logMessage = mLogger.err("%%world"); - logMessage.c("hello\t").c("big\\").flush(); - assertEquals("hello\tbig\\world", logMessage.toString()); - } - - @Test - public void traceLogMessageIncludesCallerName() { - try { - LogcatLog.enableVerboseLogging(1); - WifiLog.LogMessage logMessage = mLogger.trace("%"); - logMessage.c("says hello").flush(); - assertEquals("traceLogMessageIncludesCallerName says hello", - logMessage.toString()); - } finally { - LogcatLog.enableVerboseLogging(0); - } - } - - @Test - public void traceLogMessageRespectsNumFramesToIgnore() { - try { - LogcatLog.enableVerboseLogging(1); - WifiLog.LogMessage logMessage = traceHelper("%"); - logMessage.c("says hello").flush(); - assertEquals("traceLogMessageRespectsNumFramesToIgnore says hello", - logMessage.toString()); - } finally { - LogcatLog.enableVerboseLogging(0); - } - } - - @Test - public void traceLogMessageDoesNotCrashOnOversizedNumFramesToIgnore() { - try { - LogcatLog.enableVerboseLogging(1); - WifiLog.LogMessage logMessage = mLogger.trace("%", - (new Throwable()).getStackTrace().length); - logMessage.c("says hello").flush(); - assertEquals("<unknown> says hello", logMessage.toString()); - } finally { - LogcatLog.enableVerboseLogging(0); - } - } - - @Test - public void traceLogMessageDoesNotCrashOnOverflowingNumFramesToIgnore() { - try { - LogcatLog.enableVerboseLogging(1); - WifiLog.LogMessage logMessage = mLogger.trace("%", Integer.MAX_VALUE); - logMessage.c("says hello").flush(); - assertEquals("<unknown> says hello", logMessage.toString()); - } finally { - LogcatLog.enableVerboseLogging(0); - } - } - - @Test - public void traceLogMessageDoesNotCrashOnUndersizedNumFramesToIgnore() { - try { - LogcatLog.enableVerboseLogging(1); - WifiLog.LogMessage logMessage = mLogger.trace("%", Integer.MIN_VALUE); - logMessage.c("says hello").flush(); - assertEquals("<unknown> says hello", logMessage.toString()); - } finally { - LogcatLog.enableVerboseLogging(0); - } - } - - @Test - public void traceLogMessageReturnsDummyLogMessageByDefault() { - assertThat(mLogger.trace("%"), instanceOf(DummyLogMessage.class)); - } - - @Test - public void dumpLogMessageReturnsDummyLogMessageByDefault() { - assertThat(mLogger.dump("%"), instanceOf(DummyLogMessage.class)); - } - - private WifiLog.LogMessage traceHelper(String format) { - return mLogger.trace(format, 1); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/MacAddressUtilTest.java b/tests/wifitests/src/com/android/server/wifi/MacAddressUtilTest.java deleted file mode 100644 index 786722382..000000000 --- a/tests/wifitests/src/com/android/server/wifi/MacAddressUtilTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.net.MacAddress; -import android.net.wifi.WifiConfiguration; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.security.ProviderException; -import java.util.Random; - -import javax.crypto.Mac; - -/** - * Unit tests for {@link com.android.server.wifi.MacAddressUtil}. - */ -@SmallTest -public class MacAddressUtilTest extends WifiBaseTest { - private MacAddressUtil mMacAddressUtil; - - @Mock private Mac mMac; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mMacAddressUtil = new MacAddressUtil(); - } - - /** - * Verifies that calculatePersistentMac generate valid randomized MACs. - */ - @Test - public void testCalculatePersistentMac() { - // verify null inputs - assertNull(mMacAddressUtil.calculatePersistentMac(null, null)); - - Random rand = new Random(); - // Verify that a the MAC address calculated is valid - for (int i = 0; i < 10; i++) { - byte[] bytes = new byte[32]; - rand.nextBytes(bytes); - when(mMac.doFinal(any())).thenReturn(bytes); - MacAddress macAddress = mMacAddressUtil.calculatePersistentMac( - "TEST_SSID_AND_SECURITY_TYPE_" + i, mMac); - assertTrue(WifiConfiguration.isValidMacAddressForRandomization(macAddress)); - } - } - - /** - * Verify the java.security.ProviderException is caught. - */ - @Test - public void testCalculatePersistentMacCatchesException() { - when(mMac.doFinal(any())).thenThrow(new ProviderException("error occurred")); - try { - assertNull(mMacAddressUtil.calculatePersistentMac("TEST_SSID_AND_SECURITY_TYPE", - mMac)); - } catch (Exception e) { - fail("Exception not caught."); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java b/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java deleted file mode 100644 index 239fea95f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.*; - -import android.net.wifi.WifiManager; -import android.os.test.TestLooper; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - - -/** - * unit tests for {@link com.android.server.wifi.MboOceController}. - */ -@SmallTest -public class MboOceControllerTest extends WifiBaseTest { - private static final String TAG = "MboOceControllerTest"; - private static final String INTERFACE_NAME = "wlan0"; - - private MboOceController mMboOceController; - private TestLooper mLooper; - @Mock WifiNative mWifiNative; - @Mock TelephonyManager mTelephonyManager; - - /** - * Initializes common state (e.g. mocks) needed by test cases. - */ - @Before - public void setUp() throws Exception { - /* Ensure Looper exists */ - mLooper = new TestLooper(); - MockitoAnnotations.initMocks(this); - - mMboOceController = new MboOceController(mTelephonyManager, mWifiNative); - - when(mWifiNative.getClientInterfaceName()).thenReturn(INTERFACE_NAME); - } - - /** - * Helper function to initialize mboOceController - */ - private PhoneStateListener enableMboOceController(boolean isMboEnabled, boolean isOceEnabled) { - long featureSet = 0; - PhoneStateListener dataConnectionStateListener = null; - - if (isMboEnabled) { - featureSet |= WifiManager.WIFI_FEATURE_MBO; - } - if (isOceEnabled) { - featureSet |= WifiManager.WIFI_FEATURE_OCE; - } - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) featureSet); - - mMboOceController.enable(); - - if (isMboEnabled) { - /* Capture the PhoneStateListener */ - ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_DATA_CONNECTION_STATE)); - dataConnectionStateListener = phoneStateListenerCaptor.getValue(); - assertNotNull(dataConnectionStateListener); - } - - return dataConnectionStateListener; - - } - - /** - * Test that we do not register for cellular Data state change - * events when MBO is disabled. - */ - @Test - public void testMboDisabledDoNotRegisterCellularDataStateChangeEvents() - throws Exception { - enableMboOceController(false, false); - verify(mTelephonyManager, never()).listen(any(), anyInt()); - } - - /** - * Test that we register for cellular Data state change - * events and update cellular data status changes when MBO is enabled. - */ - @Test - public void testMboEnabledUpdateCellularDataStateChangeEvents() throws Exception { - InOrder inOrder = inOrder(mWifiNative); - PhoneStateListener dataConnectionStateListener; - dataConnectionStateListener = enableMboOceController(true, false); - dataConnectionStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, - TelephonyManager.NETWORK_TYPE_LTE); - verify(mWifiNative).setMboCellularDataStatus(eq(INTERFACE_NAME), eq(true)); - dataConnectionStateListener.onDataConnectionStateChanged( - TelephonyManager.DATA_DISCONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - verify(mWifiNative).setMboCellularDataStatus(eq(INTERFACE_NAME), eq(false)); - } - - /** - * Test that we unregister data connection state events - * when disable mMboOceController is called. - */ - @Test - public void testDisableMboOceControllerUnRegisterCellularDataStateChangeEvents() - throws Exception { - enableMboOceController(true, false); - mMboOceController.disable(); - ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_NONE)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/MemoryStoreImplTest.java b/tests/wifitests/src/com/android/server/wifi/MemoryStoreImplTest.java deleted file mode 100644 index 307ef647e..000000000 --- a/tests/wifitests/src/com/android/server/wifi/MemoryStoreImplTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2019 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.net.IpMemoryStore; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -//import java.util.HashMap; -//import java.util.Map; - -/** - * Unit tests for {@link com.android.server.wifi.MemoryStoreImpl}. - */ -@SmallTest -public class MemoryStoreImplTest extends WifiBaseTest { - @Mock Context mContext; - @Mock WifiScoreCard mWifiScoreCard; - @Mock WifiHealthMonitor mWifiHealthMonitor; - @Mock WifiScoreCard.BlobListener mBlobListener; - @Mock WifiInjector mWifiInjector; - @Mock IpMemoryStore mIpMemoryStore; - private MemoryStoreImpl mMemoryStoreImpl; - private static final String DATA_NAME = "test"; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mMemoryStoreImpl = new MemoryStoreImpl(mContext, mWifiInjector, mWifiScoreCard, - mWifiHealthMonitor); - } - - /** - * Attempt to start before ip memory service is ready should not call install. - */ - @Test - public void attemptToStartBeforeIpMemoryServiceIsReadyShouldNotCallInstall() throws Exception { - mMemoryStoreImpl.start(); - verify(mWifiScoreCard, never()).installMemoryStore(any()); - } - - /** - * Test start installs itself. - */ - @Test - public void testStartInstallsItself() throws Exception { - when(mWifiInjector.getIpMemoryStore()).thenReturn(mIpMemoryStore); - mMemoryStoreImpl.start(); - verify(mWifiScoreCard).installMemoryStore(eq(mMemoryStoreImpl)); - } - - /** - * Test that stop does pending writes. - * - * Also check that stop is harmless if done before start or if done twice. - */ - @Test - public void testThatStopDoesPendingWrites() throws Exception { - when(mWifiInjector.getIpMemoryStore()).thenReturn(mIpMemoryStore); - - // stop without start is a NOP - mMemoryStoreImpl.stop(); - verifyNoMoreInteractions(mWifiScoreCard); - - // start / stop calls for pending writes - mMemoryStoreImpl.start(); - mMemoryStoreImpl.stop(); - verify(mWifiScoreCard).installMemoryStore(eq(mMemoryStoreImpl)); - verify(mWifiScoreCard).doWrites(); - verifyNoMoreInteractions(mWifiScoreCard); - - // stopping again should do nothing more - mMemoryStoreImpl.stop(); - verifyNoMoreInteractions(mWifiScoreCard); - } - - /** - * WifiScoreCard read should call ip memory store retrieveBlob. - */ - @Test - public void wifiScoreCardReadShouldCallIpMemoryStoreRetrieveBlob() throws Exception { - final byte[] myBlob = new byte[]{0x0, 0x3}; - final String myL2Key = "L2Key:" + myBlob; - final android.net.ipmemorystore.Status statusSuccess = - new android.net.ipmemorystore.Status(android.net.ipmemorystore.Status.SUCCESS); - - when(mWifiInjector.getIpMemoryStore()).thenReturn(mIpMemoryStore); - mMemoryStoreImpl.start(); - mMemoryStoreImpl.read(myL2Key, DATA_NAME, mBlobListener); - verify(mIpMemoryStore).retrieveBlob( - eq(myL2Key), // String l2Key - eq(MemoryStoreImpl.WIFI_FRAMEWORK_IP_MEMORY_STORE_CLIENT_ID), // String clientId - eq(DATA_NAME), - mOnBlobRetrievedListenerCaptor.capture()); - verifyNoMoreInteractions(mIpMemoryStore, mBlobListener); - // Now simulate the completion of the read request - final android.net.ipmemorystore.Blob wrappedBlob = new android.net.ipmemorystore.Blob(); - wrappedBlob.data = myBlob; - mOnBlobRetrievedListenerCaptor.getValue() - .onBlobRetrieved( - statusSuccess, - myL2Key, - DATA_NAME, - wrappedBlob); - verify(mBlobListener).onBlobRetrieved(mBytesCaptor.capture()); - assertArrayEquals(myBlob, mBytesCaptor.getValue()); - } - final ArgumentCaptor<android.net.ipmemorystore.OnBlobRetrievedListener> - mOnBlobRetrievedListenerCaptor = - ArgumentCaptor.forClass(android.net.ipmemorystore.OnBlobRetrievedListener.class); - final ArgumentCaptor<byte[]> - mBytesCaptor = - ArgumentCaptor.forClass(byte[].class); - - /** - * WifiScoreCard write should call ip memory store storeBlob. - */ - @Test - public void wifiScoreCardWriteShouldCallIpMemoryStoreStoreBlob() throws Exception { - final byte[] myBlob = new byte[]{0x0, 0x3, 0x1}; - final String myL2Key = "L2Key:" + myBlob; - when(mWifiInjector.getIpMemoryStore()).thenReturn(mIpMemoryStore); - mMemoryStoreImpl.start(); - mMemoryStoreImpl.write(myL2Key, DATA_NAME, myBlob); - verify(mIpMemoryStore).storeBlob( - eq(myL2Key), - eq(MemoryStoreImpl.WIFI_FRAMEWORK_IP_MEMORY_STORE_CLIENT_ID), - eq(DATA_NAME), - mIpMemoryStoreBlobCaptor.capture(), - eq(null)); - android.net.ipmemorystore.Blob blob = mIpMemoryStoreBlobCaptor.getValue(); - assertArrayEquals(myBlob, blob.data); - verifyNoMoreInteractions(mIpMemoryStore); - } - final ArgumentCaptor<android.net.ipmemorystore.Blob> mIpMemoryStoreBlobCaptor = - ArgumentCaptor.forClass(android.net.ipmemorystore.Blob.class); - - /** - * An exception should disable further operations. - */ - @Test - public void exceptionDisablesFurtherOperations() throws Exception { - final byte[] myBlob = new byte[]{0x0, 0x3, 0x1}; - final String myL2Key = "L2Key:" + myBlob; - when(mWifiInjector.getIpMemoryStore()).thenReturn(mIpMemoryStore); - doThrow(new RuntimeException("Just a test")) - .when(mIpMemoryStore).storeBlob(any(), any(), any(), any(), any()); - mMemoryStoreImpl.start(); - mMemoryStoreImpl.write(myL2Key, DATA_NAME, myBlob); - // After the failed write, the read should do nothing. - mMemoryStoreImpl.read(myL2Key, DATA_NAME, mBlobListener); - verify(mIpMemoryStore, never()) - .retrieveBlob(any(), any(), any(), any()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/MockKeyStore.java b/tests/wifitests/src/com/android/server/wifi/MockKeyStore.java deleted file mode 100644 index 4c30af35c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/MockKeyStore.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.android.server.wifi; - -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.security.KeyStore; -import android.util.SparseArray; - -import org.mockito.Matchers; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.util.Arrays; -import java.util.HashMap; - -class MockKeyStore { - - public static class KeyBlob { - public byte[] blob; - public int flag; - - public void update(byte[] blob, int flag) { - this.blob = Arrays.copyOf(blob, blob.length); - this.flag = flag; - } - } - private SparseArray<HashMap<String, KeyBlob>> mStore; - - public MockKeyStore() { - mStore = new SparseArray<HashMap<String, KeyBlob>>(); - } - - public KeyStore createMock() { - KeyStore mock = mock(KeyStore.class); - when(mock.state()).thenReturn(KeyStore.State.UNLOCKED); - - when(mock.put(anyString(), Matchers.any(byte[].class), anyInt(), anyInt())) - .thenAnswer(new Answer<Boolean>() { - - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - Object[] args = invocation.getArguments(); - return put((String) args[0], (byte[]) args[1], (Integer) args[2], - (Integer) args[3]); - } - }); - - when(mock.importKey(anyString(), Matchers.any(byte[].class), anyInt(), anyInt())) - .thenAnswer(new Answer<Boolean>() { - - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - Object[] args = invocation.getArguments(); - return importKey((String) args[0], (byte[]) args[1], (Integer) args[2], - (Integer) args[3]); - } - }); - - when(mock.delete(anyString(), anyInt())).thenAnswer(new Answer<Boolean>() { - - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - Object[] args = invocation.getArguments(); - return delete((String) args[0], (Integer) args[1]); - } - }); - - when(mock.contains(anyString(), anyInt())).thenAnswer(new Answer<Boolean>() { - - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - Object[] args = invocation.getArguments(); - return contains((String) args[0], (Integer) args[1]); - } - }); - - return mock; - } - - private KeyBlob access(int uid, String key, boolean createIfNotExist) { - if (mStore.get(uid) == null) { - mStore.put(uid, new HashMap<String, KeyBlob>()); - } - HashMap<String, KeyBlob> map = mStore.get(uid); - if (map.containsKey(key)) { - return map.get(key); - } else { - if (createIfNotExist) { - KeyBlob blob = new KeyBlob(); - map.put(key, blob); - return blob; - } else { - return null; - } - } - } - - public KeyBlob getKeyBlob(int uid, String key) { - return access(uid, key, false); - } - - private boolean put(String key, byte[] value, int uid, int flags) { - access(uid, key, true).update(value, flags); - return true; - } - - private boolean importKey(String keyName, byte[] key, int uid, int flags) { - return put(keyName, key, uid, flags); - } - - private boolean delete(String key, int uid) { - if (mStore.get(uid) != null) { - mStore.get(uid).remove(key); - } - return true; - } - - private boolean contains(String key, int uid) { - return access(uid, key, false) != null; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("KeyStore {"); - for (int i = 0; i < mStore.size(); i++) { - int uid = mStore.keyAt(i); - for (String keyName : mStore.get(uid).keySet()) { - sb.append(String.format("%d:%s, ", uid, keyName)); - } - } - sb.append("}"); - return sb.toString(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/MockResources.java b/tests/wifitests/src/com/android/server/wifi/MockResources.java deleted file mode 100644 index bde33d799..000000000 --- a/tests/wifitests/src/com/android/server/wifi/MockResources.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import java.util.HashMap; - -public class MockResources extends android.test.mock.MockResources { - - private HashMap<Integer, Boolean> mBooleanValues; - private HashMap<Integer, Integer> mIntegerValues; - private HashMap<Integer, String> mStringValues; - private HashMap<Integer, CharSequence> mTextValues; - private HashMap<Integer, int[]> mIntArrayValues; - private HashMap<Integer, String[]> mStringArrayValues; - - public MockResources() { - mBooleanValues = new HashMap<Integer, Boolean>(); - mIntegerValues = new HashMap<Integer, Integer>(); - mStringValues = new HashMap<Integer, String>(); - mTextValues = new HashMap<Integer, CharSequence>(); - mIntArrayValues = new HashMap<Integer, int[]>(); - mStringArrayValues = new HashMap<Integer, String[]>(); - } - - @Override - public boolean getBoolean(int id) { - if (mBooleanValues.containsKey(id)) { - return mBooleanValues.get(id); - } else { - return false; - } - } - - @Override - public int getInteger(int id) { - if (mIntegerValues.containsKey(id)) { - return mIntegerValues.get(id); - } else { - return 0; - } - } - - @Override - public String getString(int id) { - if (mStringValues.containsKey(id)) { - return mStringValues.get(id); - } else { - return null; - } - } - - @Override - public CharSequence getText(int id) { - if (mTextValues.containsKey(id)) { - return mTextValues.get(id); - } else { - return null; - } - } - - @Override - public int[] getIntArray(int id) { - if (mIntArrayValues.containsKey(id)) { - return mIntArrayValues.get(id); - } else { - return null; - } - } - - @Override - public String[] getStringArray(int id) { - if (mStringArrayValues.containsKey(id)) { - return mStringArrayValues.get(id); - } else { - return null; - } - } - - public void setBoolean(int id, boolean value) { - mBooleanValues.put(id, value); - } - - public void setInteger(int id, int value) { - mIntegerValues.put(id, value); - } - - public void setString(int id, String value) { - mStringValues.put(id, value); - } - - public void setText(int id, CharSequence value) { - mTextValues.put(id, value); - } - - public void setIntArray(int id, int[] value) { - mIntArrayValues.put(id, value); - } - - public void setStringArray(int id, String[] value) { - mStringArrayValues.put(id, value); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/MockWifiMonitor.java b/tests/wifitests/src/com/android/server/wifi/MockWifiMonitor.java deleted file mode 100644 index 908feaf97..000000000 --- a/tests/wifitests/src/com/android/server/wifi/MockWifiMonitor.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; - -import android.os.Handler; -import android.os.Message; -import android.util.SparseArray; - -import java.util.HashMap; -import java.util.Map; - -/** - * Creates a mock WifiMonitor. - * WARNING: This does not perfectly mock the behavior of WifiMonitor at the moment - * ex. startMonitoring does nothing and will not send a connection/disconnection event - */ -public class MockWifiMonitor extends WifiMonitor { - private final Map<String, SparseArray<Handler>> mHandlerMap = new HashMap<>(); - - public MockWifiMonitor() { - super(mock(WifiInjector.class)); - } - - @Override - public void registerHandler(String iface, int what, Handler handler) { - SparseArray<Handler> ifaceHandlers = mHandlerMap.get(iface); - if (ifaceHandlers == null) { - ifaceHandlers = new SparseArray<>(); - mHandlerMap.put(iface, ifaceHandlers); - } - ifaceHandlers.put(what, handler); - } - - @Override - public synchronized void startMonitoring(String iface) { - return; - } - - /** - * Send a message and assert that it was dispatched to a handler - */ - public void sendMessage(String iface, int what) { - sendMessage(iface, Message.obtain(null, what)); - } - - public void sendMessage(String iface, Message message) { - SparseArray<Handler> ifaceHandlers = mHandlerMap.get(iface); - if (ifaceHandlers != null) { - assertTrue("No handler for iface=" + iface + ",what=" + message.what, - sendMessage(ifaceHandlers, message)); - } else { - boolean sent = false; - for (Map.Entry<String, SparseArray<Handler>> entry : mHandlerMap.entrySet()) { - if (sendMessage(entry.getValue(), Message.obtain(message))) { - sent = true; - } - } - assertTrue("No handler for message with nonexistant iface, iface=" + iface - + ",what=" + message.what, sent); - } - } - - private boolean sendMessage(SparseArray<Handler> ifaceHandlers, Message message) { - Handler handler = ifaceHandlers.get(message.what); - if (handler != null) { - message.setTarget(handler); - message.sendToTarget(); - return true; - } - return false; - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java deleted file mode 100644 index c59c8c441..000000000 --- a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java +++ /dev/null @@ -1,809 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static android.os.Process.SYSTEM_UID; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.MacAddress; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtilTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.NetworkListStoreData}. - */ -@SmallTest -public class NetworkListStoreDataTest extends WifiBaseTest { - - private static final String TEST_SSID = "WifiConfigStoreDataSSID_"; - private static final String TEST_CONNECT_CHOICE = "XmlUtilConnectChoice"; - private static final long TEST_CONNECT_CHOICE_TIMESTAMP = 0x4566; - private static final String TEST_CREATOR_NAME = "CreatorName"; - private static final MacAddress TEST_RANDOMIZED_MAC = - MacAddress.fromString("da:a1:19:c4:26:fa"); - - private static final String SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT = - "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">%s</string>\n" - + "<string name=\"SSID\">%s</string>\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"%s\" />\n" - + "<boolean name=\"AutoJoinEnabled\" value=\"true\" />\n" - + "<boolean name=\"Trusted\" value=\"true\" />\n" - + "<null name=\"BSSID\" />\n" - + "<int name=\"Status\" value=\"2\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"2\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"CreatorUid\" value=\"%d\" />\n" - + "<string name=\"CreatorName\">%s</string>\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n" - + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">%s</string>\n" - + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n" - + "<int name=\"CarrierId\" value=\"-1\" />\n" - + "<boolean name=\"IsMostRecentlyConnected\" value=\"false\" />\n" - + "</WifiConfiguration>\n" - + "<NetworkStatus>\n" - + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" - + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" - + "<null name=\"ConnectChoice\" />\n" - + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" - + "</NetworkStatus>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n"; - - private static final String SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT = - "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">%s</string>\n" - + "<string name=\"SSID\">%s</string>\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">0c</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"%s\" />\n" - + "<boolean name=\"AutoJoinEnabled\" value=\"true\" />\n" - + "<boolean name=\"Trusted\" value=\"true\" />\n" - + "<null name=\"BSSID\" />\n" - + "<int name=\"Status\" value=\"2\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"0\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"CreatorUid\" value=\"%d\" />\n" - + "<string name=\"CreatorName\">%s</string>\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n" - + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">%s</string>\n" - + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n" - + "<int name=\"CarrierId\" value=\"-1\" />\n" - + "<boolean name=\"IsMostRecentlyConnected\" value=\"false\" />\n" - + "</WifiConfiguration>\n" - + "<NetworkStatus>\n" - + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" - + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" - + "<null name=\"ConnectChoice\" />\n" - + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" - + "</NetworkStatus>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "<WifiEnterpriseConfiguration>\n" - + "<string name=\"Identity\"></string>\n" - + "<string name=\"AnonIdentity\"></string>\n" - + "<string name=\"Password\"></string>\n" - + "<string name=\"ClientCert\"></string>\n" - + "<string name=\"CaCert\"></string>\n" - + "<string name=\"SubjectMatch\"></string>\n" - + "<string name=\"Engine\"></string>\n" - + "<string name=\"EngineId\"></string>\n" - + "<string name=\"PrivateKeyId\"></string>\n" - + "<string name=\"AltSubjectMatch\"></string>\n" - + "<string name=\"DomSuffixMatch\">%s</string>\n" - + "<string name=\"CaPath\">%s</string>\n" - + "<int name=\"EapMethod\" value=\"2\" />\n" - + "<int name=\"Phase2Method\" value=\"0\" />\n" - + "<string name=\"PLMN\"></string>\n" - + "<string name=\"Realm\"></string>\n" - + "<int name=\"Ocsp\" value=\"0\" />\n" - + "<string name=\"WapiCertSuite\"></string>\n" - + "</WifiEnterpriseConfiguration>\n" - + "</Network>\n"; - - private static final String SINGLE_SAE_NETWORK_DATA_XML_STRING_FORMAT = - "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">%s</string>\n" - + "<string name=\"SSID\">%s</string>\n" - + "<string name=\"PreSharedKey\">"WifiConfigurationTestUtilPsk"" - + "</string>\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"true\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"2\">0001</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"1\">02</byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"1\">28</byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"1\">0c</byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"%s\" />\n" - + "<boolean name=\"AutoJoinEnabled\" value=\"true\" />\n" - + "<boolean name=\"Trusted\" value=\"true\" />\n" - + "<null name=\"BSSID\" />\n" - + "<int name=\"Status\" value=\"2\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"0\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"CreatorUid\" value=\"%d\" />\n" - + "<string name=\"CreatorName\">%s</string>\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n" - + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">%s</string>\n" - + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n" - + "<int name=\"CarrierId\" value=\"-1\" />\n" - + "<boolean name=\"IsMostRecentlyConnected\" value=\"false\" />\n" - + "</WifiConfiguration>\n" - + "<NetworkStatus>\n" - + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" - + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" - + "<null name=\"ConnectChoice\" />\n" - + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" - + "</NetworkStatus>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n"; - - /** - * Repro'es the scenario in b/153435438. - * Network has - * - Valid preSharedKey - * - KeyMgmt set to KeyMgmt.OSEN - * - ConfigKey set to "SSID"NONE - */ - private static final String SINGLE_INVALID_NETWORK_DATA_XML_STRING_FORMAT = - "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">%s</string>\n" - + "<string name=\"SSID\">%s</string>\n" - + "<string name=\"PreSharedKey\">%s</string>\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">20</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"%s\" />\n" - + "<boolean name=\"AutoJoinEnabled\" value=\"true\" />\n" - + "<boolean name=\"Trusted\" value=\"true\" />\n" - + "<null name=\"BSSID\" />\n" - + "<int name=\"Status\" value=\"2\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"0\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"CreatorUid\" value=\"%d\" />\n" - + "<string name=\"CreatorName\">%s</string>\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n" - + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">%s</string>\n" - + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n" - + "<int name=\"CarrierId\" value=\"-1\" />\n" - + "<boolean name=\"IsMostRecentlyConnected\" value=\"false\" />\n" - + "</WifiConfiguration>\n" - + "<NetworkStatus>\n" - + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" - + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" - + "<null name=\"ConnectChoice\" />\n" - + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" - + "</NetworkStatus>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">UNASSIGNED</string>\n" - + "<string name=\"ProxySettings\">UNASSIGNED</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n"; - - // We use {@link NetworkListSharedStoreData} instance because {@link NetworkListStoreData} is - // abstract. - private NetworkListSharedStoreData mNetworkListSharedStoreData; - @Mock private Context mContext; - @Mock private PackageManager mPackageManager; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME); - mNetworkListSharedStoreData = new NetworkListSharedStoreData(mContext); - } - - /** - * Helper function for serializing configuration data to a XML block. - * - * @return byte[] of the XML data - * @throws Exception - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkListSharedStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing configuration data from a XML block. - * - * @param data XML data to parse from - * @return List of WifiConfiguration parsed - * @throws Exception - */ - private List<WifiConfiguration> deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkListSharedStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - return mNetworkListSharedStoreData.getConfigurations(); - } - - /** - * Helper function for generating a network list for testing purpose. The network list - * will contained an open, an EAP and an SAE networks. - * - * @param shared Flag indicating shared network - * @return List of WifiConfiguration - */ - private List<WifiConfiguration> getTestNetworksConfig(boolean shared) { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.creatorName = TEST_CREATOR_NAME; - openNetwork.shared = shared; - openNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); - openNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); - openNetwork.meteredOverride = WifiConfiguration.METERED_OVERRIDE_NOT_METERED; - WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(); - eapNetwork.shared = shared; - eapNetwork.creatorName = TEST_CREATOR_NAME; - eapNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); - eapNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); - WifiConfiguration saeNetwork = WifiConfigurationTestUtil.createSaeNetwork(); - saeNetwork.shared = shared; - saeNetwork.creatorName = TEST_CREATOR_NAME; - saeNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); - saeNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); - saeNetwork.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); - List<WifiConfiguration> networkList = new ArrayList<>(); - networkList.add(openNetwork); - networkList.add(eapNetwork); - networkList.add(saeNetwork); - return networkList; - } - - /** - * Helper function for generating XML block containing two networks, an open and an EAP - * network. - * - * @param openNetwork The WifiConfiguration for an open network - * @param eapNetwork The WifiConfiguration for an EAP network - * @param saeNetwork The WifiConfiguration for an SAE network - * @return byte[] of the XML data - */ - private byte[] getTestNetworksXmlBytes(WifiConfiguration openNetwork, - WifiConfiguration eapNetwork, WifiConfiguration saeNetwork) { - String openNetworkXml = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT, - openNetwork.getKey().replaceAll("\"", """), - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, - openNetwork.creatorName, openNetwork.getRandomizedMacAddress()); - String eapNetworkXml = String.format(SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT, - eapNetwork.getKey().replaceAll("\"", """), - eapNetwork.SSID.replaceAll("\"", """), - eapNetwork.shared, eapNetwork.creatorUid, - eapNetwork.creatorName, eapNetwork.getRandomizedMacAddress(), - eapNetwork.enterpriseConfig.getDomainSuffixMatch(), - eapNetwork.enterpriseConfig.getCaPath()); - String saeNetworkXml = String.format(SINGLE_SAE_NETWORK_DATA_XML_STRING_FORMAT, - saeNetwork.getKey().replaceAll("\"", """), - saeNetwork.SSID.replaceAll("\"", """), - saeNetwork.shared, saeNetwork.creatorUid, - saeNetwork.creatorName, saeNetwork.getRandomizedMacAddress()); - return (openNetworkXml + eapNetworkXml + saeNetworkXml).getBytes(StandardCharsets.UTF_8); - } - - /** - * Verify that serializing the store data without any configuration doesn't cause any crash - * and no data should be serialized. - * - * @throws Exception - */ - @Test - public void serializeEmptyConfigs() throws Exception { - assertEquals(0, serializeData().length); - } - - /** - * Verify that parsing an empty data doesn't cause any crash and no configuration should - * be parsed. - * - * @throws Exception - */ - @Test - public void deserializeEmptyData() throws Exception { - assertTrue(deserializeData(new byte[0]).isEmpty()); - } - - /** - * Verify that {@link NetworkListSharedStoreData} is written to - * {@link WifiConfigStore#STORE_FILE_NAME_SHARED_GENERAL}. - * Verify that {@link NetworkListUserStoreData} is written to - * {@link WifiConfigStore#STORE_FILE_NAME_USER_GENERAL}. - * - * @throws Exception - */ - @Test - public void getUserStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_SHARED_GENERAL, - mNetworkListSharedStoreData.getStoreFileId()); - assertEquals(WifiConfigStore.STORE_FILE_USER_GENERAL, - new NetworkListUserStoreData(mContext).getStoreFileId()); - } - - /** - * Verify that the shared configurations (containing an open, an EAP and an SAE networks) are - * serialized correctly, matching the expected XML string. - * - * @throws Exception - */ - @Test - public void serializeSharedConfigurations() throws Exception { - List<WifiConfiguration> networkList = getTestNetworksConfig(true /* shared */); - mNetworkListSharedStoreData.setConfigurations(networkList); - byte[] expectedData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1), - networkList.get(2)); - byte[] serializedData = serializeData(); - assertArrayEquals(expectedData, serializeData()); - } - - /** - * Verify that the shared configurations are parsed correctly from a XML string containing - * test networks (an open and an EAP network). - * @throws Exception - */ - @Test - public void deserializeSharedConfigurations() throws Exception { - List<WifiConfiguration> networkList = getTestNetworksConfig(true /* shared */); - byte[] xmlData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1), - networkList.get(2)); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore( - networkList, deserializeData(xmlData)); - } - - /** - * Verify that we ignore any unknown tags when parsing a <Network> block. - */ - @Test - public void parseNetworkWithUnknownTag() throws Exception { - String configFormat = - "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">%s</string>\n" - + "<string name=\"SSID\">%s</string>\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"%s\" />\n" - + "<boolean name=\"AutoJoinEnabled\" value=\"true\" />\n" - + "<boolean name=\"Trusted\" value=\"true\" />\n" - + "<null name=\"BSSID\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"CreatorUid\" value=\"%d\" />\n" - + "<null name=\"CreatorName\" />\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">%s</string>\n" - + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n" - + "</WifiConfiguration>\n" - + "<NetworkStatus>\n" - + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" - + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" - + "<null name=\"ConnectChoice\" />\n" - + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" - + "</NetworkStatus>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "<Unknown>" // Unknown tag. - + "<int name=\"test\" value=\"0\" />\n" - + "</Unknown>" - + "</Network>\n"; - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - byte[] xmlData = String.format(configFormat, - openNetwork.getKey().replaceAll("\"", """), - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, openNetwork.getRandomizedMacAddress()) - .getBytes(StandardCharsets.UTF_8); - List<WifiConfiguration> deserializedConfigs = deserializeData(xmlData); - assertEquals(1, deserializedConfigs.size()); - WifiConfiguration deserializedConfig = deserializedConfigs.get(0); - - assertEquals(openNetwork.SSID, deserializedConfig.SSID); - assertEquals(openNetwork.getKey(), deserializedConfig.getKey()); - } - - /** - * Verify that a XmlPullParseException will be thrown when parsing a network configuration - * containing a mismatched config key. - * - * @throws Exception - */ - @Test(expected = XmlPullParserException.class) - public void parseNetworkWithMismatchConfigKey() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT, - "InvalidConfigKey", - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, - openNetwork.creatorName, openNetwork.getRandomizedMacAddress()) - .getBytes(StandardCharsets.UTF_8); - deserializeData(xmlData); - } - - /** - * Tests that an invalid data in one of the WifiConfiguration object parsing would be skipped - * gracefully. The other networks in the XML should still be parsed out correctly. - */ - @Test - public void parseNetworkListWithOneNetworkIllegalArgException() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(); - WifiConfiguration saeNetwork = WifiConfigurationTestUtil.createSaeNetwork(); - String xmlString = new String(getTestNetworksXmlBytes(openNetwork, eapNetwork, saeNetwork)); - // Manipulate the XML data to set the EAP method to None, this should raise an Illegal - // argument exception in WifiEnterpriseConfig.setEapMethod(). - xmlString = xmlString.replaceAll( - String.format(XmlUtilTest.XML_STRING_EAP_METHOD_REPLACE_FORMAT, - eapNetwork.enterpriseConfig.getEapMethod()), - String.format(XmlUtilTest.XML_STRING_EAP_METHOD_REPLACE_FORMAT, - WifiEnterpriseConfig.Eap.NONE)); - List<WifiConfiguration> retrievedNetworkList = - deserializeData(xmlString.getBytes(StandardCharsets.UTF_8)); - // Retrieved network should not contain the eap network. - assertEquals(2, retrievedNetworkList.size()); - for (WifiConfiguration network : retrievedNetworkList) { - assertNotEquals(eapNetwork.SSID, network.SSID); - } - } - - /** - * Verify that a saved network config with invalid creatorUid resets it to - * {@link android.os.Process#SYSTEM_UID}. - */ - @Test - public void parseNetworkWithInvalidCreatorUidResetsToSystem() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.creatorUid = -1; - // Return null for invalid uid. - when(mPackageManager.getNameForUid(eq(openNetwork.creatorUid))).thenReturn(null); - - byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT, - openNetwork.getKey().replaceAll("\"", """), - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, - openNetwork.creatorName, openNetwork.getRandomizedMacAddress()) - .getBytes(StandardCharsets.UTF_8); - List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData); - assertEquals(1, deserializedNetworks.size()); - assertEquals(openNetwork.getKey(), deserializedNetworks.get(0).getKey()); - assertEquals(SYSTEM_UID, deserializedNetworks.get(0).creatorUid); - assertEquals(TEST_CREATOR_NAME, deserializedNetworks.get(0).creatorName); - } - - /** - * Verify that a saved network config with invalid creatorName resets it to the package name - * provided {@link PackageManager} for the creatorUid. - */ - @Test - public void parseNetworkWithInvalidCreatorNameResetsToPackageNameForCreatorUid() - throws Exception { - String badCreatorName = "bad"; - String correctCreatorName = "correct"; - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.creatorUid = 1324422; - openNetwork.creatorName = badCreatorName; - when(mPackageManager.getNameForUid(eq(openNetwork.creatorUid))) - .thenReturn(correctCreatorName); - - byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT, - openNetwork.getKey().replaceAll("\"", """), - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, - openNetwork.creatorName, openNetwork.getRandomizedMacAddress()) - .getBytes(StandardCharsets.UTF_8); - List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData); - assertEquals(1, deserializedNetworks.size()); - assertEquals(openNetwork.getKey(), deserializedNetworks.get(0).getKey()); - assertEquals(openNetwork.creatorUid, deserializedNetworks.get(0).creatorUid); - assertEquals(correctCreatorName, deserializedNetworks.get(0).creatorName); - } - - /** - * Verify that a saved network config with invalid creatorName resets it to the package name - * provided {@link PackageManager} for the creatorUid. - */ - @Test - public void parseNetworkWithNullCreatorNameResetsToPackageNameForCreatorUid() - throws Exception { - String correctCreatorName = "correct"; - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.creatorUid = 1324422; - openNetwork.creatorName = null; - when(mPackageManager.getNameForUid(eq(openNetwork.creatorUid))) - .thenReturn(correctCreatorName); - - byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT, - openNetwork.getKey().replaceAll("\"", """), - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, - openNetwork.creatorName, openNetwork.getRandomizedMacAddress()) - .getBytes(StandardCharsets.UTF_8); - List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData); - assertEquals(1, deserializedNetworks.size()); - assertEquals(openNetwork.getKey(), deserializedNetworks.get(0).getKey()); - assertEquals(openNetwork.creatorUid, deserializedNetworks.get(0).creatorUid); - assertEquals(correctCreatorName, deserializedNetworks.get(0).creatorName); - } - - /** - * Verify that a saved network config with valid creatorUid is preserved. - */ - @Test - public void parseNetworkWithValidCreatorUid() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.creatorUid = 1324422; - - byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT, - openNetwork.getKey().replaceAll("\"", """), - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, - openNetwork.creatorName, openNetwork.getRandomizedMacAddress()) - .getBytes(StandardCharsets.UTF_8); - List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData); - assertEquals(1, deserializedNetworks.size()); - assertEquals(openNetwork.getKey(), deserializedNetworks.get(0).getKey()); - assertEquals(openNetwork.creatorUid, deserializedNetworks.get(0).creatorUid); - assertEquals(TEST_CREATOR_NAME, deserializedNetworks.get(0).creatorName); - } - - /** - * Verify that an SAE saved network config with legacy security settings is cleared from them - * when deserializing it. - */ - @Test - public void fixSaeNetworkWithLegacySecurity() throws Exception { - WifiConfiguration saeNetwork = WifiConfigurationTestUtil.createSaeNetwork(); - saeNetwork.shared = false; - saeNetwork.creatorName = TEST_CREATOR_NAME; - saeNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); - saeNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); - - String saeNetworkWithOpenAuthXml = String.format(SINGLE_SAE_NETWORK_DATA_XML_STRING_FORMAT, - saeNetwork.getKey().replaceAll("\"", """), - saeNetwork.SSID.replaceAll("\"", """), - saeNetwork.shared, saeNetwork.creatorUid, - saeNetwork.creatorName, saeNetwork.getRandomizedMacAddress()); - - saeNetworkWithOpenAuthXml.replaceAll("name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>", - "<name=\"AllowedAuthAlgos\" num=\"1\">01</byte-array>"); - - saeNetworkWithOpenAuthXml.replaceAll("name=\"AllowedProtocols\" num=\"1\">02</byte-array>", - "name=\"AllowedProtocols\" num=\"1\">03</byte-array>"); - - saeNetworkWithOpenAuthXml.replaceAll( - "name=\"AllowedGroupCiphers\" num=\"1\">28</byte-array>", - "name=\"AllowedGroupCiphers\" num=\"1\">0f</byte-array>"); - - saeNetworkWithOpenAuthXml.replaceAll( - "name=\"AllowedPairwiseCiphers\" num=\"1\">0c</byte-array>", - "name=\"AllowedPairwiseCiphers\" num=\"1\">06</byte-array>"); - - List<WifiConfiguration> retrievedNetworkList = - deserializeData(saeNetworkWithOpenAuthXml.getBytes(StandardCharsets.UTF_8)); - - assertEquals(1, retrievedNetworkList.size()); - - assertFalse(retrievedNetworkList.get(0).allowedAuthAlgorithms - .get(WifiConfiguration.AuthAlgorithm.OPEN)); - - assertTrue(retrievedNetworkList.get(0).allowedPairwiseCiphers - .get(WifiConfiguration.PairwiseCipher.GCMP_256)); - assertTrue(retrievedNetworkList.get(0).allowedGroupCiphers - .get(WifiConfiguration.GroupCipher.GCMP_256)); - } - - /** - * The WifiConfiguration store should follow the sort of the SSIDs. - */ - @Test - public void testWifiConfigSaveToStoreOrder() throws Exception { - String testSSID = "TEST_SSID"; - List<WifiConfiguration> storedWIfiConfig = new ArrayList<>(); - for (int i = 1; i <= 1; i++) { - WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork( - ScanResultUtil.createQuotedSSID(testSSID + (1 - i))); - network.creatorName = TEST_CREATOR_NAME; - } - // Add to store data based on added order. - mNetworkListSharedStoreData.setConfigurations(storedWIfiConfig); - byte[] output1 = serializeData(); - // Add to store data based on SSID sort. - Collections.sort(storedWIfiConfig, Comparator.comparing(a -> a.SSID)); - mNetworkListSharedStoreData.setConfigurations(storedWIfiConfig); - byte[] output2 = serializeData(); - assertArrayEquals(output2, output1); - } - - /** - * Verify that we parse out a badly formed WifiConfiguration saved on the device because - * our previous validation logic did not catch it. - * - * See b/153435438#comment26 for the exact problem. - */ - @Test - public void parseNetworkWithInvalidConfigKeyAndKeyMmt() throws Exception { - // Valid psk network (that we should recreate after deserialization) - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); - pskNetwork.creatorName = TEST_CREATOR_NAME; - String invalidConfigKey = pskNetwork.getKey(); - invalidConfigKey.replace("WPA_PSK", "NONE"); - // XML data has 2 things that needs to be corrected: - // - ConfigKey is set to "SSID"NONE instead of "SSID"WPA_PSK - // - KeyMgmt has KeyMgmt.OSEN bit set instead of KeyMgmt.WPA_PSK - byte[] xmlData = String.format(SINGLE_INVALID_NETWORK_DATA_XML_STRING_FORMAT, - invalidConfigKey, - pskNetwork.SSID.replaceAll("\"", """), - pskNetwork.preSharedKey.replaceAll("\"", """), - pskNetwork.shared, pskNetwork.creatorUid, - pskNetwork.creatorName, pskNetwork.getRandomizedMacAddress()) - .getBytes(StandardCharsets.UTF_8); - List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData); - assertEquals(1, deserializedNetworks.size()); - - WifiConfiguration deserializedPskNetwork = deserializedNetworks.get(0); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigStore( - pskNetwork, deserializedPskNetwork); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java deleted file mode 100644 index 7f7c770f2..000000000 --- a/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.net.util.MacAddressUtils; -import android.net.wifi.WifiConfiguration; -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.WifiNetworkFactory.AccessPoint; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.NetworkRequestStoreData}. - */ -@SmallTest -public class NetworkRequestStoreDataTest extends WifiBaseTest { - private static final String TEST_PACKAGE_NAME_1 = "com.android.test.1"; - private static final String TEST_PACKAGE_NAME_2 = "com.android.test.2"; - private static final String TEST_CORRUPT_DATA_INVALID_SSID = - "<NetworkRequestMap>\n" - + "<ApprovedAccessPointsPerApp>\n" - + "<string name=\"RequestorPackageName\">com.android.test.1</string>\n" - + "<AccessPoint>\n" - + "<blah blah=\"SSID\">"WifiConfigurationTestUtilSSID7"</blah>\n" - + "<null name=\"BSSID\" />\n" - + "<int name=\"NetworkType\" value=\"2\" />\n" - + "</AccessPoint>\n" - + "</ApprovedAccessPointsPerApp>" - + "</NetworkRequestMap>"; - - private @Mock NetworkRequestStoreData.DataSource mDataSource; - private NetworkRequestStoreData mNetworkRequestStoreData; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mNetworkRequestStoreData = new NetworkRequestStoreData(mDataSource); - } - - /** - * Helper function for serializing configuration data to a XML block. - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing configuration data from a XML block. - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - } - - /** - * Verify store file Id. - */ - @Test - public void verifyStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_USER_GENERAL, - mNetworkRequestStoreData.getStoreFileId()); - } - - /** - * Serialize/Deserialize a single approved access points from a single app. - */ - @Test - public void serializeDeserializeSingleNetworkRequestFromSingleApp() throws Exception { - Map<String, Set<AccessPoint>> approvedAccessPointsMap = new HashMap<>(); - - AccessPoint accessPoint = new AccessPoint( - WifiConfigurationTestUtil.createPskNetwork().SSID, - MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_PSK); - Set<AccessPoint> accessPoints = new HashSet<AccessPoint>() {{ - add(accessPoint); - }}; - approvedAccessPointsMap.put(TEST_PACKAGE_NAME_1, accessPoints); - - assertSerializeDeserialize(approvedAccessPointsMap); - } - - /** - * Serialize/Deserialize a single approved access point from multiple apps. - */ - @Test - public void serializeDeserializeSingleNetworkRequestFromMultipleApps() throws Exception { - Map<String, Set<AccessPoint>> approvedAccessPointsMap = new HashMap<>(); - - AccessPoint accessPoint1 = new AccessPoint( - WifiConfigurationTestUtil.createPskNetwork().SSID, - MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_PSK); - Set<AccessPoint> accessPoints1 = new HashSet<AccessPoint>() {{ - add(accessPoint1); - }}; - approvedAccessPointsMap.put(TEST_PACKAGE_NAME_1, accessPoints1); - - AccessPoint accessPoint2 = new AccessPoint( - WifiConfigurationTestUtil.createPskNetwork().SSID, - MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_PSK); - Set<AccessPoint> accessPoints2 = new HashSet<AccessPoint>() {{ - add(accessPoint2); - }}; - approvedAccessPointsMap.put(TEST_PACKAGE_NAME_2, accessPoints2); - - assertSerializeDeserialize(approvedAccessPointsMap); - } - - /** - * Serialize/Deserialize multiple approved access points from multiple apps. - */ - @Test - public void serializeDeserializeMultipleNetworkRequestFromMultipleApps() throws Exception { - Map<String, Set<AccessPoint>> approvedAccessPointsMap = new HashMap<>(); - - AccessPoint accessPoint1 = new AccessPoint( - WifiConfigurationTestUtil.createPskNetwork().SSID, - MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_PSK); - AccessPoint accessPoint2 = new AccessPoint( - WifiConfigurationTestUtil.createOpenNetwork().SSID, - MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_OPEN); - Set<AccessPoint> accessPoints1 = new HashSet<AccessPoint>() {{ - add(accessPoint1); - add(accessPoint2); - }}; - approvedAccessPointsMap.put(TEST_PACKAGE_NAME_1, accessPoints1); - - AccessPoint accessPoint3 = new AccessPoint( - WifiConfigurationTestUtil.createSaeNetwork().SSID, - MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_SAE); - AccessPoint accessPoint4 = new AccessPoint( - WifiConfigurationTestUtil.createOpenNetwork().SSID, - MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_OPEN); - Set<AccessPoint> accessPoints2 = new HashSet<AccessPoint>() {{ - add(accessPoint3); - add(accessPoint4); - }}; - approvedAccessPointsMap.put(TEST_PACKAGE_NAME_2, accessPoints2); - - assertSerializeDeserialize(approvedAccessPointsMap); - } - - /** - * Deserialize corrupt data and ensure that we gracefully handle any errors in the data. - * graceful == throw XmlPullParserException (which is handled in - * {@link WifiConfigManager#loadFromStore()}). - */ - @Test(expected = XmlPullParserException.class) - public void deserializeCorruptData() throws Exception { - deserializeData(TEST_CORRUPT_DATA_INVALID_SSID.getBytes()); - } - - private void assertSerializeDeserialize( - Map<String, Set<AccessPoint>> approvedAccessPointsMap) - throws Exception { - // Setup the data to serialize. - when(mDataSource.toSerialize()).thenReturn(approvedAccessPointsMap); - - // Serialize/deserialize data. - deserializeData(serializeData()); - - // Verify the deserialized data. - ArgumentCaptor<HashMap> deserializedApprovedAccessPointsMap = - ArgumentCaptor.forClass(HashMap.class); - verify(mDataSource).fromDeserialized(deserializedApprovedAccessPointsMap.capture()); - assertEquals(approvedAccessPointsMap, deserializedApprovedAccessPointsMap.getValue()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java deleted file mode 100644 index 1e0677316..000000000 --- a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java +++ /dev/null @@ -1,1185 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID; -import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus - .NETWORK_SELECTION_TEMPORARY_DISABLED; - -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP; -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; -import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiSsid; -import android.util.LocalLog; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; -import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo; -import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Unit tests for {@link NetworkSuggestionNominator}. - */ -@SmallTest -public class NetworkSuggestionNominatorTest extends WifiBaseTest { - private static final int TEST_UID = 3555; - private static final int TEST_UID_OTHER = 3545; - private static final int TEST_NETWORK_ID = 55; - private static final String TEST_PACKAGE = "com.test"; - private static final String TEST_PACKAGE_OTHER = "com.test.other"; - private static final String TEST_FQDN = "fqdn"; - private static final int TEST_CARRIER_ID = 1911; - private static final String TEST_CARRIER_NAME = "testCarrier"; - private static final int TEST_SUB_ID = 2020; - - - private @Mock WifiConfigManager mWifiConfigManager; - private @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private @Mock PasspointNetworkNominateHelper mPasspointNetworkNominateHelper; - private @Mock Clock mClock; - private @Mock - WifiCarrierInfoManager mWifiCarrierInfoManager; - private NetworkSuggestionNominator mNetworkSuggestionNominator; - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mNetworkSuggestionNominator = new NetworkSuggestionNominator( - mWifiNetworkSuggestionsManager, mWifiConfigManager, mPasspointNetworkNominateHelper, - new LocalLog(100), mWifiCarrierInfoManager); - } - - /** - * Ensure that we ignore all scan results not matching the network suggestion. - * Expected connectable Networks: {} - */ - @Test - public void testSelectNetworkSuggestionForNoMatch() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {}; - int[] securities = {}; - boolean[] appInteractions = {}; - boolean[] meteredness = {}; - int[] priorities = {}; - int[] uids = {}; - String[] packageNames = {}; - boolean[] autojoin = {}; - boolean[] shareWithUser = {}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - assertTrue(connectableNetworks.isEmpty()); - } - - /** - * Ensure that we nominate the only matching network suggestion. - * Expected connectable Networks: {suggestionSsids[0]} - */ - @Test - public void testSelectNetworkSuggestionForOneMatch() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - validateConnectableNetworks(connectableNetworks, scanSsids[0]); - verifyAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - } - - @Test - public void testSelectNetworkSuggestionForOneMatchWithInsecureEnterpriseSuggestion() { - String[] scanSsids = {"test1"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_EAP}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - WifiConfiguration config = suggestions[0].wns.wifiConfiguration; - config.enterpriseConfig.setCaPath(null); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - // Verify no network is nominated. - assertTrue(connectableNetworks.isEmpty()); - } - - /** - * Ensure that we nominate the all network suggestion corresponding to the scan results - * Expected connectable Networks: {suggestionSsids[0], suggestionSsids[1]} - */ - @Test - public void testSelectNetworkSuggestionForMultipleMatch() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-56, -45}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\"", "\"" + scanSsids[1] + "\""}; - int[] securities = {SECURITY_PSK, SECURITY_PSK}; - boolean[] appInteractions = {true, true}; - boolean[] meteredness = {true, true}; - int[] priorities = {-1, -1}; - int[] uids = {TEST_UID, TEST_UID}; - String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE}; - boolean[] autojoin = {true, true}; - boolean[] shareWithUser = {true, true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration, - suggestions[1].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - validateConnectableNetworks(connectableNetworks, scanSsids[0], scanSsids[1]); - - verifyAddToWifiConfigManager(suggestions[1].wns.wifiConfiguration, - suggestions[1].wns.wifiConfiguration); - } - - /** - * Ensure that we nominate the network suggestion corresponding to the scan result with - * higest priority. - * Expected connectable Networks: {suggestionSsids[0]} - */ - @Test - public void testSelectNetworkSuggestionForMultipleMatchHighPriorityWins() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-56, -45}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\"", "\"" + scanSsids[1] + "\""}; - int[] securities = {SECURITY_PSK, SECURITY_PSK}; - boolean[] appInteractions = {true, true}; - boolean[] meteredness = {true, true}; - int[] priorities = {5, 1}; - int[] uids = {TEST_UID, TEST_UID}; - String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE}; - boolean[] autojoin = {true, true}; - boolean[] shareWithUser = {true, true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration, - suggestions[1].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - validateConnectableNetworks(connectableNetworks, scanSsids[0]); - - verifyAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - } - - /** - * Ensure that we nominate one network when multiple suggestor suggested same network. - * - * Expected connectable Networks: {suggestionSsids[0], - * (suggestionSsids[1] || suggestionSsids[2]} - */ - @Test - public void testSelectNetworkSuggestionForMultipleMatchWithMultipleSuggestions() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-23, -45}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\"", "\"" + scanSsids[1] + "\"", - "\"" + scanSsids[1] + "\""}; - int[] securities = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK}; - boolean[] appInteractions = {true, true, false}; - boolean[] meteredness = {true, true, false}; - int[] priorities = {-1, -1, -1}; - int[] uids = {TEST_UID, TEST_UID, TEST_UID_OTHER}; - String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE, TEST_PACKAGE_OTHER}; - boolean[] autojoin = {true, true, true}; - boolean[] shareWithUser = {true, true, true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration, - suggestions[1].wns.wifiConfiguration, suggestions[2].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - validateConnectableNetworks(connectableNetworks, scanSsids); - - verifyAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration, - suggestions[1].wns.wifiConfiguration); - } - - /** - * Ensure that we nominate the network suggestion with the higest priority among network - * suggestions from the same package. Among different packages, nominate all the suggestion - * corresponding to the scan result. - * - * The suggestion[1] has higher priority than suggestion[0]. - * - * Expected connectable Networks: {suggestionSsids[1], - * (suggestionSsids[2], - * suggestionSsids[3]} - */ - @Test - public void - testSelectNetworkSuggestionForMultipleMatchWithMultipleSuggestionsHighPriorityWins() { - String[] scanSsids = {"test1", "test2", "test3", "test4"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:fc:de:34:12", - "6c:fd:a1:11:11:98"}; - int[] freqs = {2470, 2437, 2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", - "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-23, -45, -56, -65}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\"", "\"" + scanSsids[1] + "\"", - "\"" + scanSsids[2] + "\"", "\"" + scanSsids[3] + "\""}; - int[] securities = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK, SECURITY_PSK}; - boolean[] appInteractions = {true, true, false, false}; - boolean[] meteredness = {true, true, false, false}; - int[] priorities = {0, 5, -1, -1}; - int[] uids = {TEST_UID, TEST_UID, TEST_UID_OTHER, TEST_UID_OTHER}; - String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE, TEST_PACKAGE_OTHER, - TEST_PACKAGE_OTHER}; - boolean[] autojoin = {true, true, true, true}; - boolean[] shareWithUser = {true, true, true, true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration, - suggestions[1].wns.wifiConfiguration, suggestions[2].wns.wifiConfiguration, - suggestions[3].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - validateConnectableNetworks(connectableNetworks, scanSsids[1], scanSsids[2], scanSsids[3]); - - verifyAddToWifiConfigManager(suggestions[1].wns.wifiConfiguration, - suggestions[2].wns.wifiConfiguration, suggestions[3].wns.wifiConfiguration); - } - - /** - * Ensure that we nominate no candidate if the only matching network suggestion, but we failed - * the {@link WifiConfigManager} interactions. - * - * Expected connectable Networks: {} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchButFailToAddToWifiConfigManager() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // Fail add to WifiConfigManager - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), anyString())) - .thenReturn(new NetworkUpdateResult(INVALID_NETWORK_ID)); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - assertTrue(connectableNetworks.isEmpty()); - - verify(mWifiConfigManager, times(suggestionSsids.length)) - .isNetworkTemporarilyDisabledByUser(anyString()); - verify(mWifiConfigManager).getConfiguredNetwork(eq( - suggestions[0].wns.wifiConfiguration.getKey())); - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), anyString()); - // Verify we did not try to add any new networks or other interactions with - // WifiConfigManager. - verifyNoMoreInteractions(mWifiConfigManager); - } - - /** - * Ensure that we nominate the only matching network suggestion, but that matches an existing - * saved network (maybe saved or maybe it exists from a previous connection attempt) . - * - * Expected connectable Networks: {suggestionSsids[0]} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchForExistingNetwork() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - suggestions[0].wns.wifiConfiguration.fromWifiNetworkSuggestion = true; - suggestions[0].wns.wifiConfiguration.ephemeral = true; - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - // Existing saved network matching the credentials. - when(mWifiConfigManager.getConfiguredNetwork(suggestions[0].wns.wifiConfiguration.getKey())) - .thenReturn(suggestions[0].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - validateConnectableNetworks(connectableNetworks, new String[] {scanSsids[0]}); - - // check for any saved networks. - verify(mWifiConfigManager, times(suggestionSsids.length)) - .isNetworkTemporarilyDisabledByUser(anyString()); - verify(mWifiConfigManager) - .getConfiguredNetwork(suggestions[0].wns.wifiConfiguration.getKey()); - // Verify we did not try to add any new networks or other interactions with - // WifiConfigManager. - verifyNoMoreInteractions(mWifiConfigManager); - } - - /** - * Ensure that we don't nominate the only matching network suggestion if it was previously - * disabled by the user. - * - * Expected connectable Networks: {} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchButUserForgotTheNetwork() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - // Network was disabled by the user. - when(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(suggestionSsids[0])) - .thenReturn(true); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> - connectableNetworks.add(Pair.create(scanDetail, configuration))); - - assertTrue(connectableNetworks.isEmpty()); - - verify(mWifiConfigManager, times(suggestionSsids.length)) - .isNetworkTemporarilyDisabledByUser(anyString()); - // Verify we did try to add any new networks or other interactions with - // WifiConfigManager. - verifyAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - } - - /** - * Ensure that we don't nominate the only matching network suggestion if the network - * configuration already exists (maybe saved or maybe it exists from a previous connection - * attempt) and blacklisted. - * - * Expected connectable Networks: {} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchForExistingNetworkButTempDisabled() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - suggestions[0].wns.wifiConfiguration.fromWifiNetworkSuggestion = true; - suggestions[0].wns.wifiConfiguration.ephemeral = true; - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - // Mark the network disabled. - suggestions[0].wns.wifiConfiguration.getNetworkSelectionStatus().setNetworkSelectionStatus( - NETWORK_SELECTION_TEMPORARY_DISABLED); - // Existing network matching the credentials. - when(mWifiConfigManager.getConfiguredNetwork(suggestions[0].wns.wifiConfiguration.getKey())) - .thenReturn(suggestions[0].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - assertTrue(connectableNetworks.isEmpty()); - - verify(mWifiConfigManager, times(suggestionSsids.length)) - .isNetworkTemporarilyDisabledByUser(anyString()); - verify(mWifiConfigManager).getConfiguredNetwork(eq( - suggestions[0].wns.wifiConfiguration.getKey())); - verify(mWifiConfigManager).tryEnableNetwork(eq( - suggestions[0].wns.wifiConfiguration.networkId)); - // Verify we did not try to add any new networks or other interactions with - // WifiConfigManager. - verifyNoMoreInteractions(mWifiConfigManager); - } - - /** - * Ensure that we do nominate the only matching network suggestion if the network configuration - * already exists (maybe saved or maybe it exists from a previous connection attempt) and a - * temporary blacklist expired. - * - * Expected connectable Networks: {suggestionSsids[0]} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchForExistingNetworkButTempDisableExpired() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - suggestions[0].wns.wifiConfiguration.fromWifiNetworkSuggestion = true; - suggestions[0].wns.wifiConfiguration.ephemeral = true; - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - // Mark the network disabled. - suggestions[0].wns.wifiConfiguration.getNetworkSelectionStatus().setNetworkSelectionStatus( - NETWORK_SELECTION_TEMPORARY_DISABLED); - // Existing network matching the credentials. - when(mWifiConfigManager.getConfiguredNetwork(suggestions[0].wns.wifiConfiguration.getKey())) - .thenReturn(suggestions[0].wns.wifiConfiguration); - when(mWifiConfigManager.tryEnableNetwork(suggestions[0].wns.wifiConfiguration.networkId)) - .thenReturn(true); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - validateConnectableNetworks(connectableNetworks, new String[] {scanSsids[0]}); - - verify(mWifiConfigManager, times(suggestionSsids.length)) - .isNetworkTemporarilyDisabledByUser(anyString()); - verify(mWifiConfigManager).getConfiguredNetwork(eq( - suggestions[0].wns.wifiConfiguration.getKey())); - verify(mWifiConfigManager).tryEnableNetwork(eq( - suggestions[0].wns.wifiConfiguration.networkId)); - // Verify we did not try to add any new networks or other interactions with - // WifiConfigManager. - verifyNoMoreInteractions(mWifiConfigManager); - } - - /** - * Ensure that we do nominate the only matching passponit network suggestion. - * Expected connectable Networks: {suggestionSsids[0]} - */ - @Test - public void testSuggestionPasspointNetworkCandidatesMatches() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, packageNames, - autojoin, shareWithUser); - HashSet<ExtendedWifiNetworkSuggestion> matchedExtSuggestions = new HashSet<>(); - matchedExtSuggestions.add(suggestions[0]); - List<Pair<ScanDetail, WifiConfiguration>> passpointCandidates = new ArrayList<>(); - suggestions[0].wns.wifiConfiguration.FQDN = TEST_FQDN; - passpointCandidates.add(Pair.create(scanDetails[0], suggestions[0].wns.wifiConfiguration)); - when(mPasspointNetworkNominateHelper - .getPasspointNetworkCandidates(Arrays.asList(scanDetails), true)) - .thenReturn(passpointCandidates); - when(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForFqdn(TEST_FQDN)) - .thenReturn(matchedExtSuggestions); - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - assertEquals(1, connectableNetworks.size()); - validateConnectableNetworks(connectableNetworks, new String[] {scanSsids[0]}); - } - - /** - * Ensure that we will not nominate the matching network suggestions which auto-join is - * disabled. - * Expected connectable Networks: {} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchButAutojoinDisabled() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\"", "\"" + scanSsids[1] + "\""}; - int[] securities = {SECURITY_PSK, SECURITY_PSK}; - boolean[] appInteractions = {true, true}; - boolean[] meteredness = {true, true}; - int[] priorities = {-1, -1}; - int[] uids = {TEST_UID, TEST_UID}; - String[] packageNames = {TEST_PACKAGE, TEST_PACKAGE}; - boolean[] autojoin = {false, false}; - boolean[] shareWithUser = {true, false}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration, - suggestions[1].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - // Verify no network is nominated. - assertTrue(connectableNetworks.isEmpty()); - // Verify we only add network apps shared with user to WifiConfigManager - verifyAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - verify(mWifiConfigManager, never()) - .addOrUpdateNetwork(argThat(new WifiConfigMatcher( - suggestions[1].wns.wifiConfiguration)), anyInt(), anyString()); - } - - @Test - public void testSelectNetworkSuggestionForOneMatchSimBasedWithNoSim() { - String[] scanSsids = {"test1"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_EAP}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - WifiConfiguration eapSimConfig = suggestions[0].wns.wifiConfiguration; - eapSimConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); - eapSimConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); - eapSimConfig.carrierId = TEST_CARRIER_ID; - when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(eapSimConfig)) - .thenReturn(TEST_SUB_ID); - when(mWifiCarrierInfoManager.isSimPresent(TEST_SUB_ID)).thenReturn(false); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - // Verify no network is nominated. - assertTrue(connectableNetworks.isEmpty()); - verifyAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - } - - @Test - public void testSelectNetworkSuggestionForOneMatchSimBasedWithEncryptionInfoNotAvailabele() { - String[] scanSsids = {"test1"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_EAP}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - WifiConfiguration eapSimConfig = suggestions[0].wns.wifiConfiguration; - eapSimConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); - eapSimConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); - eapSimConfig.carrierId = TEST_CARRIER_ID; - when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(eapSimConfig)) - .thenReturn(TEST_SUB_ID); - when(mWifiCarrierInfoManager.isSimPresent(TEST_SUB_ID)).thenReturn(true); - when(mWifiCarrierInfoManager.requiresImsiEncryption(TEST_SUB_ID)).thenReturn(true); - when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(TEST_SUB_ID)).thenReturn(false); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - // setup config manager interactions. - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - // Verify no network is nominated. - assertTrue(connectableNetworks.isEmpty()); - verifyAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - } - - /** - * Ensure that we nominate the no matching network suggestion. - * Because the only matched suggestion is untrusted and untrusted is not allowed - * Expected connectable Networks: {} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchUntrustedNotAllow() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - suggestions[0].wns.wifiConfiguration.trusted = false; - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - assertTrue(connectableNetworks.isEmpty()); - } - - /** - * Ensure that we nominate the one matching network suggestion. - * Because the only matched suggestion is untrusted and untrusted is allowed - * Expected connectable Networks: {suggestionSsids[0]} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchUntrustedAllow() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - suggestions[0].wns.wifiConfiguration.trusted = false; - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - - setupAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, true, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - - validateConnectableNetworks(connectableNetworks, scanSsids[0]); - - verifyAddToWifiConfigManager(suggestions[0].wns.wifiConfiguration); - } - - /** - * Ensure that we nominate the no matching network suggestion. - * Because the only matched suggestion is untrusted and untrusted is not allowed - * Expected connectable Networks: {} - */ - @Test - public void testSelectNetworkSuggestionForOneMatchMeteredNonDataSim() { - String[] scanSsids = {"test1", "test2"}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-67, -76}; - String[] suggestionSsids = {"\"" + scanSsids[0] + "\""}; - int[] securities = {SECURITY_PSK}; - boolean[] appInteractions = {true}; - boolean[] meteredness = {true}; - int[] priorities = {-1}; - int[] uids = {TEST_UID}; - String[] packageNames = {TEST_PACKAGE}; - boolean[] autojoin = {true}; - boolean[] shareWithUser = {true}; - - ScanDetail[] scanDetails = - buildScanDetails(scanSsids, bssids, freqs, caps, levels, mClock); - ExtendedWifiNetworkSuggestion[] suggestions = buildNetworkSuggestions(suggestionSsids, - securities, appInteractions, meteredness, priorities, uids, - packageNames, autojoin, shareWithUser); - suggestions[0].wns.wifiConfiguration.meteredHint = true; - when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(any())).thenReturn(true); - // Link the scan result with suggestions. - linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions); - - List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>(); - mNetworkSuggestionNominator.nominateNetworks( - Arrays.asList(scanDetails), null, null, true, false, - (ScanDetail scanDetail, WifiConfiguration configuration) -> { - connectableNetworks.add(Pair.create(scanDetail, configuration)); - }); - - assertTrue(connectableNetworks.isEmpty()); - } - - private void setupAddToWifiConfigManager(WifiConfiguration...candidates) { - for (int i = 0; i < candidates.length; i++) { - WifiConfiguration candidate = candidates[i]; - // setup & verify the WifiConfigmanager interactions for adding/enabling the network. - when(mWifiConfigManager.addOrUpdateNetwork( - argThat(new WifiConfigMatcher(candidate)), anyInt(), anyString())) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID + i)); - when(mWifiConfigManager.updateNetworkSelectionStatus(eq(TEST_NETWORK_ID + i), anyInt())) - .thenReturn(true); - candidate.networkId = TEST_NETWORK_ID + i; - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID + i)) - .thenReturn(candidate); - } - } - - class WifiConfigMatcher implements ArgumentMatcher<WifiConfiguration> { - private final WifiConfiguration mConfig; - - WifiConfigMatcher(WifiConfiguration config) { - assertNotNull(config); - mConfig = config; - } - - @Override - public boolean matches(WifiConfiguration otherConfig) { - if (otherConfig == null) return false; - return mConfig.getKey().equals(otherConfig.getKey()); - } - } - - private void verifyAddToWifiConfigManager(WifiConfiguration...candidates) { - // check for any saved networks. - verify(mWifiConfigManager, atLeast(candidates.length)).getConfiguredNetwork(anyString()); - - ArgumentCaptor<WifiConfiguration> wifiConfigurationCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - verify(mWifiConfigManager, times(candidates.length)).addOrUpdateNetwork( - wifiConfigurationCaptor.capture(), anyInt(), anyString()); - verify(mWifiConfigManager, times(candidates.length)).allowAutojoin(anyInt(), anyBoolean()); - for (int i = 0; i < candidates.length; i++) { - WifiConfiguration addedWifiConfiguration = null; - for (WifiConfiguration configuration : wifiConfigurationCaptor.getAllValues()) { - if (configuration.SSID.equals(candidates[i].SSID)) { - addedWifiConfiguration = configuration; - break; - } - } - assertNotNull(addedWifiConfiguration); - assertTrue(addedWifiConfiguration.ephemeral); - assertTrue(addedWifiConfiguration.fromWifiNetworkSuggestion); - } - - verify(mWifiConfigManager, times(candidates.length)).updateNetworkSelectionStatus( - anyInt(), anyInt()); - verify(mWifiConfigManager, times(candidates.length)).getConfiguredNetwork(anyInt()); - } - - /** - * Build an array of scanDetails based on the caller supplied network SSID, BSSID, - * frequency, capability and RSSI level information. - */ - private static ScanDetail[] buildScanDetails(String[] ssids, String[] bssids, int[] freqs, - String[] caps, int[] levels, Clock clock) { - if (ssids == null || ssids.length == 0) return new ScanDetail[0]; - - ScanDetail[] scanDetails = new ScanDetail[ssids.length]; - long timeStamp = clock.getElapsedSinceBootMillis(); - for (int index = 0; index < ssids.length; index++) { - scanDetails[index] = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssids[index]), - bssids[index], caps[index], levels[index], freqs[index], timeStamp, 0); - } - return scanDetails; - } - - /** - * Generate an array of {@link android.net.wifi.WifiConfiguration} based on the caller - * supplied network SSID and security information. - */ - private static WifiConfiguration[] buildWifiConfigurations(String[] ssids, int[] securities) { - if (ssids == null || ssids.length == 0) return new WifiConfiguration[0]; - - WifiConfiguration[] configs = new WifiConfiguration[ssids.length]; - for (int index = 0; index < ssids.length; index++) { - configs[index] = generateWifiConfig(-1, 0, ssids[index], false, true, null, - null, securities[index]); - } - return configs; - } - - private ExtendedWifiNetworkSuggestion[] buildNetworkSuggestions( - String[] ssids, int[] securities, boolean[] appInteractions, boolean[] meteredness, - int[] priorities, int[] uids, String[] packageNames, boolean[] autojoin, - boolean[] shareWithUser) { - WifiConfiguration[] configs = buildWifiConfigurations(ssids, securities); - ExtendedWifiNetworkSuggestion[] suggestions = - new ExtendedWifiNetworkSuggestion[configs.length]; - for (int i = 0; i < configs.length; i++) { - configs[i].priority = priorities[i]; - configs[i].creatorUid = uids[i]; - configs[i].meteredOverride = meteredness[i] - ? WifiConfiguration.METERED_OVERRIDE_METERED - : WifiConfiguration.METERED_OVERRIDE_NONE; - configs[i].creatorName = packageNames[i]; - configs[i].ephemeral = true; - configs[i].fromWifiNetworkSuggestion = true; - PerAppInfo perAppInfo = new PerAppInfo(uids[i], packageNames[i], null); - WifiNetworkSuggestion suggestion = - new WifiNetworkSuggestion(configs[i], null, appInteractions[i], false, - shareWithUser[i], true); - suggestions[i] = new ExtendedWifiNetworkSuggestion(suggestion, perAppInfo, autojoin[i]); - } - return suggestions; - } - - /** - * Link scan results to the network suggestions. - * - * The shorter of the 2 input params will be used to loop over so the inputs don't - * need to be of equal length. - * If there are more scan details than suggestions, the remaining - * scan details will be associated with a NULL suggestions. - * If there are more suggestions than scan details, the remaining - * suggestions will be associated with the last scan detail. - */ - private void linkScanDetailsWithNetworkSuggestions( - ScanDetail[] scanDetails, ExtendedWifiNetworkSuggestion[] suggestions) { - if (suggestions == null || scanDetails == null) { - return; - } - int minLength = Math.min(scanDetails.length, suggestions.length); - - // 1 to 1 mapping from scan detail to suggestion. - for (int i = 0; i < minLength; i++) { - ScanDetail scanDetail = scanDetails[i]; - final ExtendedWifiNetworkSuggestion matchingSuggestion = suggestions[i]; - HashSet<ExtendedWifiNetworkSuggestion> matchingSuggestions = - new HashSet<ExtendedWifiNetworkSuggestion>() {{ - add(matchingSuggestion); - }}; - when(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(eq(scanDetail))) - .thenReturn((matchingSuggestions)); - } - if (scanDetails.length > suggestions.length) { - // No match for the remaining scan details. - for (int i = minLength; i < scanDetails.length; i++) { - ScanDetail scanDetail = scanDetails[i]; - when(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - eq(scanDetail))).thenReturn(null); - } - } else if (suggestions.length > scanDetails.length) { - // All the additional suggestions match the last scan detail. - HashSet<ExtendedWifiNetworkSuggestion> matchingSuggestions = new HashSet<>(); - for (int i = minLength; i < suggestions.length; i++) { - matchingSuggestions.add(suggestions[i]); - } - ScanDetail lastScanDetail = scanDetails[minLength - 1]; - when(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - eq(lastScanDetail))).thenReturn((matchingSuggestions)); - } - } - - private void validateConnectableNetworks(List<Pair<ScanDetail, WifiConfiguration>> actual, - String...expectedSsids) { - Set<String> expectedSsidSet = new HashSet<>(Arrays.asList(expectedSsids)); - assertEquals(expectedSsidSet.size(), actual.size()); - - for (Pair<ScanDetail, WifiConfiguration> candidate : actual) { - // check if the scan detail matches the wificonfiguration. - assertEquals("\"" + candidate.first.getSSID() + "\"", candidate.second.SSID); - // check if both match one of the expected ssid's. - assertTrue(expectedSsidSet.remove(candidate.first.getSSID())); - } - assertTrue(expectedSsidSet.isEmpty()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java deleted file mode 100644 index ad31533ba..000000000 --- a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.net.wifi.EAPConstants; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; -import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -/** - * Unit tests for {@link com.android.server.wifi.NetworkSuggestionStoreData}. - */ -@SmallTest -public class NetworkSuggestionStoreDataTest extends WifiBaseTest { - private static final int TEST_UID_1 = 14556; - private static final int TEST_UID_2 = 14536; - private static final String TEST_PACKAGE_NAME_1 = "com.android.test.1"; - private static final String TEST_PACKAGE_NAME_2 = "com.android.test.2"; - private static final String TEST_FEATURE_ID = "com.android.feature.1"; - private static final String TEST_FQDN = "FQDN"; - private static final String TEST_FRIENDLY_NAME = "test_friendly_name"; - private static final String TEST_REALM = "realm.test.com"; - private static final String TEST_PRE_R_STORE_FORMAT_XML_STRING = - "<NetworkSuggestionPerApp>\n" - + "<string name=\"SuggestorPackageName\">%1$s</string>\n" - + "<string name=\"SuggestorFeatureId\">com.android.feature.1</string>\n" - + "<boolean name=\"SuggestorHasUserApproved\" value=\"false\" />\n" - + "<int name=\"SuggestorMaxSize\" value=\"100\" />\n" - + "<NetworkSuggestion>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">"WifiConfigurationTestSSID0"" - + "WPA_PSK</string>\n" - + "<string name=\"SSID\">"WifiConfigurationTestSSID0"</string>\n" - + "<null name=\"BSSID\" />\n" - + "<string name=\"PreSharedKey\">"WifiConfigurationTestUtilPsk"" - + "</string>\n" - + "<null name=\"SaePasswordId\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">02</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"true\" />\n" - + "<int name=\"Status\" value=\"2\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"0\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"NumAssociation\" value=\"0\" />\n" - + "<int name=\"CreatorUid\" value=\"5\" />\n" - + "<null name=\"CreatorName\" />\n" - + "<null name=\"CreationTime\" />\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n" - + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">02:00:00:00:00:00</string>\n" - + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n" - + "<int name=\"CarrierId\" value=\"-1\" />\n" - + "</WifiConfiguration>\n" - + "<boolean name=\"IsAppInteractionRequired\" value=\"true\" />\n" - + "<boolean name=\"IsUserInteractionRequired\" value=\"false\" />\n" - + "<boolean name=\"IsUserAllowedToManuallyConnect\" value=\"true\" />\n" - + "<int name=\"SuggestorUid\" value=\"%2$d\" />\n" - + "<string name=\"SuggestorPackageName\">%1$s</string>\n" - + "</NetworkSuggestion>\n" - + "</NetworkSuggestionPerApp>"; - private static final String TEST_POST_R_STORE_FORMAT_XML_STRING = - "<NetworkSuggestionPerApp>\n" - + "<string name=\"SuggestorPackageName\">%1$s</string>\n" - + "<string name=\"SuggestorFeatureId\">com.android.feature.1</string>\n" - + "<boolean name=\"SuggestorHasUserApproved\" value=\"false\" />\n" - + "<int name=\"SuggestorMaxSize\" value=\"100\" />\n" - + "<int name=\"SuggestorUid\" value=\"%2$d\" />\n" - + "<NetworkSuggestion>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">"WifiConfigurationTestSSID0"" - + "WPA_PSK</string>\n" - + "<string name=\"SSID\">"WifiConfigurationTestSSID0"</string>\n" - + "<null name=\"BSSID\" />\n" - + "<string name=\"PreSharedKey\">"WifiConfigurationTestUtilPsk"" - + "</string>\n" - + "<null name=\"SaePasswordId\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">02</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"true\" />\n" - + "<int name=\"Status\" value=\"2\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"0\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"NumAssociation\" value=\"0\" />\n" - + "<int name=\"CreatorUid\" value=\"5\" />\n" - + "<null name=\"CreatorName\" />\n" - + "<null name=\"CreationTime\" />\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n" - + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">02:00:00:00:00:00</string>\n" - + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n" - + "<int name=\"CarrierId\" value=\"-1\" />\n" - + "</WifiConfiguration>\n" - + "<boolean name=\"IsAppInteractionRequired\" value=\"true\" />\n" - + "<boolean name=\"IsUserInteractionRequired\" value=\"false\" />\n" - + "<boolean name=\"IsUserAllowedToManuallyConnect\" value=\"true\" />\n" - + "</NetworkSuggestion>\n" - + "</NetworkSuggestionPerApp>"; - private static final String TEST_CORRUPT_DATA_INVALID_SSID = - "<NetworkSuggestionPerApp>\n" - + "<string name=\"SuggestorPackageName\">com.android.test.1</string>\n" - + "<boolean name=\"SuggestorHasUserApproved\" value=\"false\" />\n" - + "<NetworkSuggestion>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">"WifiConfigurationTestUtilSSID7"NONE</string>\n" - + "<blah blah=\"SSID\">"WifiConfigurationTestUtilSSID7"</blah>\n" - + "<null name=\"BSSID\" />\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"true\" />\n" - + "<int name=\"Status\" value=\"2\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"0\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"NumAssociation\" value=\"0\" />\n" - + "<int name=\"CreatorUid\" value=\"5\" />\n" - + "<null name=\"CreatorName\" />\n" - + "<null name=\"CreationTime\" />\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n" - + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">02:00:00:00:00:00</string>\n" - + "</WifiConfiguration>\n" - + "<boolean name=\"IsAppInteractionRequired\" value=\"false\" />\n" - + "<boolean name=\"IsUserInteractionRequired\" value=\"false\" />\n" - + "<int name=\"SuggestorUid\" value=\"14556\" />\n" - + "</NetworkSuggestion>\n" - + "</NetworkSuggestionPerApp>"; - private static final String TEST_POST_R_APP_WITH_EMPTY_SUGGESTION = - "<NetworkSuggestionPerApp>\n" - + "<string name=\"SuggestorPackageName\">%1$s</string>\n" - + "<string name=\"SuggestorFeatureId\">com.android.feature.1</string>\n" - + "<boolean name=\"SuggestorHasUserApproved\" value=\"false\" />\n" - + "<int name=\"SuggestorMaxSize\" value=\"100\" />\n" - + "<int name=\"SuggestorUid\" value=\"%2$d\" />\n" - + "</NetworkSuggestionPerApp>"; - private static final String TEST_PRE_R_APP_WITH_EMPTY_SUGGESTION = - "<NetworkSuggestionPerApp>\n" - + "<string name=\"SuggestorPackageName\">%1$s</string>\n" - + "<string name=\"SuggestorFeatureId\">com.android.feature.1</string>\n" - + "<boolean name=\"SuggestorHasUserApproved\" value=\"false\" />\n" - + "<int name=\"SuggestorMaxSize\" value=\"100\" />\n" - + "</NetworkSuggestionPerApp>"; - - private @Mock NetworkSuggestionStoreData.DataSource mDataSource; - private NetworkSuggestionStoreData mNetworkSuggestionStoreData; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mNetworkSuggestionStoreData = new NetworkSuggestionStoreData(mDataSource); - } - - /** - * Helper function for serializing configuration data to a XML block. - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkSuggestionStoreData.serializeData(out, null); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing configuration data from a XML block. - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkSuggestionStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, null); - } - - /** - * Verify store file Id. - */ - @Test - public void verifyStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS, - mNetworkSuggestionStoreData.getStoreFileId()); - } - - /** - * Serialize/Deserialize a single network suggestion from a single app. - */ - @Test - public void serializeDeserializeSingleNetworkSuggestionFromSingleApp() throws Exception { - Map<String, PerAppInfo> networkSuggestionsMap = new HashMap<>(); - - PerAppInfo appInfo = new PerAppInfo(TEST_UID_1, TEST_PACKAGE_NAME_1, TEST_FEATURE_ID); - - WifiConfiguration configuration = WifiConfigurationTestUtil.createEapNetwork(); - configuration.enterpriseConfig = - WifiConfigurationTestUtil.createPEAPWifiEnterpriseConfigWithGTCPhase2(); - WifiNetworkSuggestion networkSuggestion = - new WifiNetworkSuggestion(configuration, null, false, false, true, true); - appInfo.hasUserApproved = false; - appInfo.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion, appInfo, true)); - networkSuggestionsMap.put(TEST_PACKAGE_NAME_1, appInfo); - - Map<String, PerAppInfo> deserializedPerAppInfoMap = - assertSerializeDeserialize(networkSuggestionsMap); - ExtendedWifiNetworkSuggestion deserializedSuggestion = - deserializedPerAppInfoMap.get(TEST_PACKAGE_NAME_1).extNetworkSuggestions.stream() - .findAny() - .orElse(null); - - WifiConfigurationTestUtil.assertConfigurationEqual( - configuration, deserializedSuggestion.wns.wifiConfiguration); - WifiConfigurationTestUtil.assertWifiEnterpriseConfigEqualForConfigStore( - configuration.enterpriseConfig, - deserializedSuggestion.wns.wifiConfiguration.enterpriseConfig); - } - - /** - * Serialize/Deserialize a single network suggestion from multiple apps. - */ - @Test - public void serializeDeserializeSingleNetworkSuggestionFromMultipleApps() throws Exception { - Map<String, PerAppInfo> networkSuggestionsMap = new HashMap<>(); - - PerAppInfo appInfo1 = new PerAppInfo(TEST_UID_1, TEST_PACKAGE_NAME_1, TEST_FEATURE_ID); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - appInfo1.hasUserApproved = false; - appInfo1.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion1, appInfo1, true)); - networkSuggestionsMap.put(TEST_PACKAGE_NAME_1, appInfo1); - - PerAppInfo appInfo2 = new PerAppInfo(TEST_UID_2, TEST_PACKAGE_NAME_2, TEST_FEATURE_ID); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - appInfo2.hasUserApproved = true; - appInfo2.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion2, appInfo2, true)); - networkSuggestionsMap.put(TEST_PACKAGE_NAME_2, appInfo2); - - assertSerializeDeserialize(networkSuggestionsMap); - } - - /** - * Serialize/Deserialize multiple network suggestion from multiple apps. - */ - @Test - public void serializeDeserializeMultipleNetworkSuggestionFromMultipleApps() throws Exception { - Map<String, PerAppInfo> networkSuggestionsMap = new HashMap<>(); - - PerAppInfo appInfo1 = new PerAppInfo(TEST_UID_1, TEST_PACKAGE_NAME_1, TEST_FEATURE_ID); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, true, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - appInfo1.hasUserApproved = true; - appInfo1.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion1, appInfo1, true)); - appInfo1.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion2, appInfo1, true)); - networkSuggestionsMap.put(TEST_PACKAGE_NAME_1, appInfo1); - - PerAppInfo appInfo2 = new PerAppInfo(TEST_UID_2, TEST_PACKAGE_NAME_2, TEST_FEATURE_ID); - WifiNetworkSuggestion networkSuggestion3 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - WifiNetworkSuggestion networkSuggestion4 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, true, true, true); - appInfo2.hasUserApproved = true; - appInfo2.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion3, appInfo2, true)); - appInfo2.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion4, appInfo2, true)); - networkSuggestionsMap.put(TEST_PACKAGE_NAME_2, appInfo2); - - assertSerializeDeserialize(networkSuggestionsMap); - } - - /** - * Deserialize corrupt data and ensure that we gracefully handle any errors in the data. - */ - @Test - public void deserializeCorruptData() throws Exception { - deserializeData(TEST_CORRUPT_DATA_INVALID_SSID.getBytes()); - } - - /** - * Deserialize a single network suggestion from a single app using a predefined string - * stored in the old/new XML format. - */ - @Test - public void deserializeFromPreRAndPostRFormat() throws Exception { - ArgumentCaptor<HashMap> deserializedNetworkSuggestionsMap = - ArgumentCaptor.forClass(HashMap.class); - - // Old format - String preRFormatXml = String.format( - TEST_PRE_R_STORE_FORMAT_XML_STRING, TEST_PACKAGE_NAME_1, TEST_UID_1); - deserializeData(preRFormatXml.getBytes()); - - // New format - String postRFormatXml = String.format( - TEST_POST_R_STORE_FORMAT_XML_STRING, TEST_PACKAGE_NAME_1, TEST_UID_1); - deserializeData(postRFormatXml.getBytes()); - - // Capture the deserialized data. - verify(mDataSource, times(2)).fromDeserialized(deserializedNetworkSuggestionsMap.capture()); - Map<String, PerAppInfo> deserializedPerAppInfoMapPreRFormat = - deserializedNetworkSuggestionsMap.getAllValues().get(0); - Map<String, PerAppInfo> deserializedPerAppInfoMapPostRFormat = - deserializedNetworkSuggestionsMap.getAllValues().get(1); - - // Ensure both formats produce the same parsed output. - assertEquals(deserializedPerAppInfoMapPreRFormat, deserializedPerAppInfoMapPostRFormat); - } - - /** - * Deserialize no network suggestion from a single app using a predefined string stored in the - * old/new XML format. - */ - @Test - public void deserializeEmptySuggestion() throws Exception { - ArgumentCaptor<HashMap> deserializedNetworkSuggestionsMap = - ArgumentCaptor.forClass(HashMap.class); - - // Old format with empty suggestion - String preRFormatXml = String.format( - TEST_PRE_R_APP_WITH_EMPTY_SUGGESTION, TEST_PACKAGE_NAME_1, TEST_UID_1); - deserializeData(preRFormatXml.getBytes()); - - // New format with empty suggestion - String postRFormatXml = String.format( - TEST_POST_R_APP_WITH_EMPTY_SUGGESTION, TEST_PACKAGE_NAME_1, TEST_UID_1); - deserializeData(postRFormatXml.getBytes()); - - // Capture the deserialized data. - verify(mDataSource, times(2)).fromDeserialized(deserializedNetworkSuggestionsMap.capture()); - Map<String, PerAppInfo> deserializedPerAppInfoMapPreRFormat = - deserializedNetworkSuggestionsMap.getAllValues().get(0); - Map<String, PerAppInfo> deserializedPerAppInfoMapPostRFormat = - deserializedNetworkSuggestionsMap.getAllValues().get(1); - // Verify PerAppInfo is no - assertNotNull(deserializedPerAppInfoMapPreRFormat.get(TEST_PACKAGE_NAME_1)); - assertNotNull(deserializedPerAppInfoMapPostRFormat.get(TEST_PACKAGE_NAME_1)); - } - - /** - * Serialize/Deserialize a single Passpoint network suggestion from a single app. - */ - @Test - public void serializeDeserializeSinglePasspointSuggestionFromSingleApp() throws Exception { - Map<String, PerAppInfo> networkSuggestionsMap = new HashMap<>(); - - PerAppInfo appInfo = new PerAppInfo(TEST_UID_1, TEST_PACKAGE_NAME_1, TEST_FEATURE_ID); - - WifiNetworkSuggestion.Builder builder = new WifiNetworkSuggestion.Builder(); - builder.setPasspointConfig( - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME)); - WifiNetworkSuggestion networkSuggestion = builder.build(); - appInfo.hasUserApproved = false; - appInfo.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion, appInfo, true)); - networkSuggestionsMap.put(TEST_PACKAGE_NAME_1, appInfo); - - Map<String, PerAppInfo> deserializedPerAppInfoMap = - assertSerializeDeserialize(networkSuggestionsMap); - ExtendedWifiNetworkSuggestion deserializedSuggestion = - deserializedPerAppInfoMap.get(TEST_PACKAGE_NAME_1).extNetworkSuggestions.stream() - .findAny() - .orElse(null); - assertEquals(networkSuggestion, deserializedSuggestion.wns); - } - - @Test - public void testDeserializeNullData() throws Exception { - mNetworkSuggestionStoreData.deserializeData(null, 0, - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, null); - verify(mDataSource).fromDeserialized(any()); - } - - private Map<String, PerAppInfo> assertSerializeDeserialize( - Map<String, PerAppInfo> networkSuggestionsMap) throws Exception { - // Setup the data to serialize. - when(mDataSource.toSerialize()).thenReturn(networkSuggestionsMap); - - // Serialize/deserialize data. - deserializeData(serializeData()); - - // Verify the deserialized data. - ArgumentCaptor<HashMap> deserializedNetworkSuggestionsMap = - ArgumentCaptor.forClass(HashMap.class); - verify(mDataSource).fromDeserialized(deserializedNetworkSuggestionsMap.capture()); - assertEquals(networkSuggestionsMap, deserializedNetworkSuggestionsMap.getValue()); - return deserializedNetworkSuggestionsMap.getValue(); - } - - private PasspointConfiguration createTestConfigWithUserCredential(String fqdn, - String friendlyName) { - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - homeSp.setFriendlyName(friendlyName); - config.setHomeSp(homeSp); - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put("en", friendlyName); - friendlyNames.put("kr", friendlyName + 1); - friendlyNames.put("jp", friendlyName + 2); - config.setServiceFriendlyNames(friendlyNames); - Credential credential = new Credential(); - credential.setRealm(TEST_REALM); - credential.setCaCertificate(FakeKeys.CA_CERT0); - Credential.UserCredential userCredential = new Credential.UserCredential(); - userCredential.setUsername("username"); - userCredential.setPassword("password"); - userCredential.setEapType(EAPConstants.EAP_TTLS); - userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP); - credential.setUserCredential(userCredential); - config.setCredential(credential); - return config; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java deleted file mode 100644 index 6dae6f55a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java +++ /dev/null @@ -1,820 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK; -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK; -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE; -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_USER_DISMISSED_NOTIFICATION; -import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.AVAILABLE_NETWORK_NOTIFIER_TAG; -import static com.android.server.wifi.OpenNetworkNotifier.DEFAULT_REPEAT_DELAY_SEC; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.anyInt; -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.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.net.Uri; -import android.net.wifi.IActionListener; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.os.Binder; -import android.os.Message; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.test.TestLooper; -import android.provider.Settings; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for {@link OpenNetworkNotifier}. - */ -@SmallTest -public class OpenNetworkNotifierTest extends WifiBaseTest { - - private static final String TEST_SSID_1 = "Test SSID 1"; - private static final String TEST_SSID_2 = "Test SSID 2"; - private static final int MIN_RSSI_LEVEL = -127; - private static final String OPEN_NET_NOTIFIER_TAG = OpenNetworkNotifier.TAG; - private static final int TEST_NETWORK_ID = 42; - - @Mock private Context mContext; - @Mock private Resources mResources; - @Mock private FrameworkFacade mFrameworkFacade; - @Mock private WifiMetrics mWifiMetrics; - @Mock private Clock mClock; - @Mock private WifiConfigStore mWifiConfigStore; - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private NotificationManager mNotificationManager; - @Mock private ClientModeImpl mClientModeImpl; - @Mock private ConnectToNetworkNotificationBuilder mNotificationBuilder; - @Mock private UserManager mUserManager; - private OpenNetworkNotifier mNotificationController; - private TestLooper mLooper; - private BroadcastReceiver mBroadcastReceiver; - private ContentObserver mContentObserver; - private ScanResult mDummyNetwork; - private List<ScanDetail> mOpenNetworks; - - /** Initialize objects before each test run. */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) - .thenReturn(mNotificationManager); - when(mFrameworkFacade.getIntegerSetting(mContext, - Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(1); - when(mFrameworkFacade.getIntegerSetting(mContext, - Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, DEFAULT_REPEAT_DELAY_SEC)) - .thenReturn(DEFAULT_REPEAT_DELAY_SEC); - when(mContext.getSystemService(UserManager.class)) - .thenReturn(mUserManager); - when(mContext.getResources()).thenReturn(mResources); - mDummyNetwork = new ScanResult(); - mDummyNetwork.SSID = TEST_SSID_1; - mDummyNetwork.capabilities = "[ESS]"; - mDummyNetwork.level = MIN_RSSI_LEVEL; - mOpenNetworks = new ArrayList<>(); - mOpenNetworks.add(new ScanDetail(mDummyNetwork, null /* networkDetail */)); - - mLooper = new TestLooper(); - mNotificationController = new OpenNetworkNotifier( - mContext, mLooper.getLooper(), mFrameworkFacade, mClock, mWifiMetrics, - mWifiConfigManager, mWifiConfigStore, mClientModeImpl, mNotificationBuilder); - ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); - mBroadcastReceiver = broadcastReceiverCaptor.getValue(); - ArgumentCaptor<ContentObserver> observerCaptor = - ArgumentCaptor.forClass(ContentObserver.class); - verify(mFrameworkFacade).registerContentObserver(eq(mContext), any(Uri.class), eq(true), - observerCaptor.capture()); - mContentObserver = observerCaptor.getValue(); - mNotificationController.handleScreenStateChanged(true); - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt())) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - } - - /** - * On {@link OpenNetworkNotifier} construction, WifiMetrics should track setting state. - */ - @Test - public void onCreate_setWifiNetworksAvailableNotificationSettingState() { - verify(mWifiMetrics).setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG, - true); - } - - /** - * When feature setting is toggled, WifiMetrics should track the disabled setting state. - */ - @Test - public void onFeatureDisable_setWifiNetworksAvailableNotificationSettingDisabled() { - when(mFrameworkFacade.getIntegerSetting(mContext, - Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(0); - mContentObserver.onChange(false); - - verify(mWifiMetrics).setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG, - false); - } - - /** - * When scan results with open networks are handled, a notification is posted. - */ - @Test - public void handleScanResults_hasOpenNetworks_notificationDisplayed() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - } - - /** - * When scan results with no open networks are handled, a notification is not posted. - */ - @Test - public void handleScanResults_emptyList_notificationNotDisplayed() { - mNotificationController.handleScanResults(new ArrayList<>()); - - verify(mNotificationManager, never()).notify(anyInt(), any()); - } - - /** - * When the feature is disabled, no notifications are posted. - */ - @Test - public void handleScanResults_featureDisabled_notificationNotDisplayed() { - when(mFrameworkFacade.getIntegerSetting(mContext, - Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(0); - mContentObserver.onChange(false); - mNotificationController.handleScanResults(new ArrayList<>()); - - verify(mNotificationManager, never()).notify(anyInt(), any()); - } - - /** - * When a notification is showing and scan results with no open networks are handled, the - * notification is cleared. - */ - @Test - public void handleScanResults_notificationShown_emptyList_notificationCleared() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mNotificationController.handleScanResults(new ArrayList<>()); - - verify(mNotificationManager).cancel(anyInt()); - } - - /** - * When a notification is showing and no recommendation is made for the new scan results, the - * notification is cleared. - */ - @Test - public void handleScanResults_notificationShown_noRecommendation_notificationCleared() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mOpenNetworks.clear(); - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationManager).cancel(anyInt()); - } - - /** - * When a notification is showing, screen is off, and scan results with no open networks are - * handled, the notification is cleared. - */ - @Test - public void handleScanResults_notificationShown_screenOff_emptyList_notificationCleared() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mNotificationController.handleScreenStateChanged(false); - mNotificationController.handleScanResults(new ArrayList<>()); - - verify(mNotificationManager).cancel(anyInt()); - } - - /** - * When {@link OpenNetworkNotifier#clearPendingNotification(boolean)} is called and a - * notification is shown, clear the notification. - */ - @Test - public void clearPendingNotification_clearsNotificationIfOneIsShowing() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mNotificationController.clearPendingNotification(true); - - verify(mNotificationManager).cancel(anyInt()); - } - - /** - * When {@link OpenNetworkNotifier#clearPendingNotification(boolean)} is called and a - * notification was not previously shown, do not clear the notification. - */ - @Test - public void clearPendingNotification_doesNotClearNotificationIfNoneShowing() { - mNotificationController.clearPendingNotification(true); - - verify(mNotificationManager, never()).cancel(anyInt()); - } - - /** - * When screen is off and notification is not displayed, notification is not posted on handling - * new scan results with open networks. - */ - @Test - public void screenOff_notificationNotShowing_handleScanResults_notificationNotDisplayed() { - mNotificationController.handleScreenStateChanged(false); - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationManager, never()).notify(anyInt(), any()); - } - - /** - * When screen is off and notification is displayed, the notification can be updated with a new - * recommendation. - */ - @Test - public void screenOff_notificationShowing_handleScanResults_recommendationCanBeUpdated() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - ScanResult newNetwork = new ScanResult(); - newNetwork.SSID = TEST_SSID_2; - mDummyNetwork.capabilities = "[ESS]"; - mDummyNetwork.level = MIN_RSSI_LEVEL + 1; - mOpenNetworks.add(new ScanDetail(newNetwork, null /* networkDetail */)); - - mNotificationController.handleScreenStateChanged(false); - mNotificationController.handleScanResults(mOpenNetworks); - - // Recommendation changed - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, newNetwork); - verify(mWifiMetrics).incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG); - verify(mNotificationManager, times(2)).notify(anyInt(), any()); - } - - /** - * When a notification is posted and cleared without resetting delay, the next scan with open - * networks should not post another notification. - */ - @Test - public void postNotification_clearNotificationWithoutDelayReset_shouldNotPostNotification() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mNotificationController.clearPendingNotification(false); - - verify(mNotificationManager).cancel(anyInt()); - - mNotificationController.handleScanResults(mOpenNetworks); - - // no new notification posted - verify(mNotificationManager).notify(anyInt(), any()); - } - - /** - * When a notification is posted and cleared without resetting delay, the next scan with open - * networks should post a notification. - */ - @Test - public void postNotification_clearNotificationWithDelayReset_shouldPostNotification() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mNotificationController.clearPendingNotification(true); - - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder, times(2)).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics, times(2)).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager, times(2)).notify(anyInt(), any()); - } - - private Intent createIntent(String action) { - return new Intent(action).putExtra(AVAILABLE_NETWORK_NOTIFIER_TAG, OPEN_NET_NOTIFIER_TAG); - } - - /** - * When user dismissed notification and there is a recommended network, network ssid should be - * blacklisted. - */ - @Test - public void userDismissedNotification_shouldBlacklistNetwork() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_USER_DISMISSED_NOTIFICATION)); - - verify(mWifiConfigManager).saveToStore(false /* forceWrite */); - - mNotificationController.clearPendingNotification(true); - List<ScanDetail> scanResults = mOpenNetworks; - mNotificationController.handleScanResults(scanResults); - - verify(mWifiMetrics).setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG, 1); - } - - /** - * When the user chooses to connect to recommended network, network ssid should be - * blacklisted so that if the user removes the network in the future the same notification - * won't show up again. - */ - @Test - public void userConnectedNotification_shouldBlacklistNetwork() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); - - verify(mWifiConfigManager).saveToStore(false /* forceWrite */); - verify(mWifiMetrics).setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG, 1); - - List<ScanDetail> scanResults = mOpenNetworks; - mNotificationController.handleScanResults(scanResults); - } - - /** - * When a notification is posted and cleared without resetting delay, after the delay has passed - * the next scan with open networks should post a notification. - */ - @Test - public void delaySet_delayPassed_shouldPostNotification() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mNotificationController.clearPendingNotification(false); - - // twice the delay time passed - when(mClock.getWallClockMillis()).thenReturn(DEFAULT_REPEAT_DELAY_SEC * 1000L * 2); - - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder, times(2)).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics, times(2)).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager, times(2)).notify(anyInt(), any()); - } - - /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} disables the feature. */ - @Test - public void userHasDisallowConfigWifiRestriction_notificationNotDisplayed() { - when(mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_CONFIG_WIFI, - UserHandle.CURRENT)) - .thenReturn(true); - - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationManager, never()).notify(anyInt(), any()); - } - - /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} clears the showing notification. */ - @Test - public void userHasDisallowConfigWifiRestriction_showingNotificationIsCleared() { - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - when(mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_CONFIG_WIFI, - UserHandle.CURRENT)) - .thenReturn(true); - - mNotificationController.handleScanResults(mOpenNetworks); - - verify(mNotificationManager).cancel(anyInt()); - } - - /** - * {@link ConnectToNetworkNotificationBuilder#ACTION_CONNECT_TO_NETWORK} does not connect to - * any network if the initial notification is not showing. - */ - @Test - public void actionConnectToNetwork_notificationNotShowing_doesNothing() { - mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); - verify(mClientModeImpl, never()).connect(any(), anyInt(), any(Binder.class), - any(IActionListener.class), anyInt(), eq(Process.SYSTEM_UID)); - } - - /** - * {@link ConnectToNetworkNotificationBuilder#ACTION_CONNECT_TO_NETWORK} connects to the - * currently recommended network if it exists. - */ - @Test - public void actionConnectToNetwork_currentRecommendationExists_connectsAndPostsNotification() { - mNotificationController.handleScanResults(mOpenNetworks); - - // Initial Notification - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); - - verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID), any(Binder.class), - any(IActionListener.class), anyInt(), eq(Process.SYSTEM_UID)); - // Connecting Notification - verify(mNotificationBuilder).createNetworkConnectingNotification(OPEN_NET_NOTIFIER_TAG, - mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); - verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, - ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); - verify(mNotificationManager, times(2)).notify(anyInt(), any()); - } - - /** - * {@link ConnectToNetworkNotificationBuilder#ACTION_PICK_WIFI_NETWORK} opens Wi-Fi settings - * if the recommendation notification is showing. - */ - @Test - public void actionPickWifiNetwork_currentRecommendationExists_opensWifiSettings() { - mNotificationController.handleScanResults(mOpenNetworks); - - // Initial Notification - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_PICK_WIFI_NETWORK)); - - ArgumentCaptor<Intent> pickerIntentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).startActivity(pickerIntentCaptor.capture()); - assertEquals(pickerIntentCaptor.getValue().getAction(), Settings.ACTION_WIFI_SETTINGS); - verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, - ConnectToNetworkNotificationAndActionCount.ACTION_PICK_WIFI_NETWORK); - } - - /** - * {@link OpenNetworkNotifier#handleWifiConnected(String ssid)} does not post connected - * notification if the connecting notification is not showing - */ - @Test - public void networkConnectionSuccess_wasNotInConnectingFlow_doesNothing() { - mNotificationController.handleWifiConnected(TEST_SSID_1); - - verify(mNotificationManager, never()).notify(anyInt(), any()); - verify(mWifiMetrics, never()).incrementConnectToNetworkNotification( - OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTED_TO_NETWORK); - } - - /** - * {@link OpenNetworkNotifier#handleWifiConnected(String ssid)} clears notification that - * is not connecting. - */ - @Test - public void networkConnectionSuccess_wasShowingNotification_clearsNotification() { - mNotificationController.handleScanResults(mOpenNetworks); - - // Initial Notification - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mNotificationController.handleWifiConnected(TEST_SSID_1); - - verify(mNotificationManager).cancel(anyInt()); - } - - /** - * {@link OpenNetworkNotifier#handleWifiConnected(String ssid)} posts the connected - * notification if the connecting notification is showing. - */ - @Test - public void networkConnectionSuccess_wasInConnectingFlow_postsConnectedNotification() { - mNotificationController.handleScanResults(mOpenNetworks); - - // Initial Notification - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); - - // Connecting Notification - verify(mNotificationBuilder).createNetworkConnectingNotification(OPEN_NET_NOTIFIER_TAG, - mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); - verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, - ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); - verify(mNotificationManager, times(2)).notify(anyInt(), any()); - - mNotificationController.handleWifiConnected(TEST_SSID_1); - - // Connected Notification - verify(mNotificationBuilder).createNetworkConnectedNotification(OPEN_NET_NOTIFIER_TAG, - mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTED_TO_NETWORK); - verify(mNotificationManager, times(3)).notify(anyInt(), any()); - } - - /** - * {@link OpenNetworkNotifier#handleConnectionFailure()} posts the Failed to Connect - * notification if the connecting notification is showing. - */ - @Test - public void networkConnectionFailure_wasNotInConnectingFlow_doesNothing() { - mNotificationController.handleConnectionFailure(); - - verify(mNotificationManager, never()).notify(anyInt(), any()); - verify(mWifiMetrics, never()).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT); - } - - /** - * {@link OpenNetworkNotifier#handleConnectionFailure()} posts the Failed to Connect - * notification if the connecting notification is showing. - */ - @Test - public void networkConnectionFailure_wasInConnectingFlow_postsFailedToConnectNotification() { - mNotificationController.handleScanResults(mOpenNetworks); - - // Initial Notification - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); - - // Connecting Notification - verify(mNotificationBuilder).createNetworkConnectingNotification(OPEN_NET_NOTIFIER_TAG, - mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); - verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, - ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); - verify(mNotificationManager, times(2)).notify(anyInt(), any()); - - mNotificationController.handleConnectionFailure(); - - // Failed to Connect Notification - verify(mNotificationBuilder).createNetworkFailedNotification(OPEN_NET_NOTIFIER_TAG); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT); - verify(mNotificationManager, times(3)).notify(anyInt(), any()); - } - - /** - * When a {@link WifiManager#CONNECT_NETWORK_FAILED} is received from the connection callback - * of {@link ClientModeImpl#sendMessage(Message)}, a Failed to Connect notification should - * be posted. On tapping this notification, Wi-Fi Settings should be launched. - */ - @Test - public void connectionFailedCallback_postsFailedToConnectNotification() throws RemoteException { - mNotificationController.handleScanResults(mOpenNetworks); - - // Initial Notification - verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( - OPEN_NET_NOTIFIER_TAG, mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); - verify(mNotificationManager).notify(anyInt(), any()); - - mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); - - verify(mWifiMetrics).setNominatorForNetwork(TEST_NETWORK_ID, - WifiMetricsProto.ConnectionEvent.NOMINATOR_OPEN_NETWORK_AVAILABLE); - - ArgumentCaptor<IActionListener> connectListenerCaptor = - ArgumentCaptor.forClass(IActionListener.class); - verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID), any(Binder.class), - connectListenerCaptor.capture(), anyInt(), eq(Process.SYSTEM_UID)); - IActionListener connectListener = connectListenerCaptor.getValue(); - - // Connecting Notification - verify(mNotificationBuilder).createNetworkConnectingNotification(OPEN_NET_NOTIFIER_TAG, - mDummyNetwork); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); - verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, - ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); - verify(mNotificationManager, times(2)).notify(anyInt(), any()); - - connectListener.onFailure(WifiManager.ERROR); - mLooper.dispatchAll(); - - // Failed to Connect Notification - verify(mNotificationBuilder).createNetworkFailedNotification(OPEN_NET_NOTIFIER_TAG); - verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT); - verify(mWifiMetrics).incrementNumNetworkConnectMessageFailedToSend(OPEN_NET_NOTIFIER_TAG); - verify(mNotificationManager, times(3)).notify(anyInt(), any()); - - mBroadcastReceiver.onReceive(mContext, - createIntent(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE)); - - ArgumentCaptor<Intent> pickerIntentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).startActivity(pickerIntentCaptor.capture()); - assertEquals(pickerIntentCaptor.getValue().getAction(), Settings.ACTION_WIFI_SETTINGS); - verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, - ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT, - ConnectToNetworkNotificationAndActionCount - .ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE); - } - - private List<ScanDetail> createOpenScanResults(String... ssids) { - List<ScanDetail> scanResults = new ArrayList<>(); - for (String ssid : ssids) { - ScanResult scanResult = new ScanResult(); - scanResult.SSID = ssid; - scanResult.capabilities = "[ESS]"; - scanResults.add(new ScanDetail(scanResult, null /* networkDetail */)); - } - return scanResults; - } - - /** If list of open networks contain only one network, that network should be returned. */ - @Test - public void onlyNetworkIsRecommended() { - List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1); - scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL; - - ScanResult actual = mNotificationController.recommendNetwork(scanResults); - ScanResult expected = scanResults.get(0).getScanResult(); - assertEquals(expected, actual); - } - - /** Verifies that the network with the highest rssi is recommended. */ - @Test - public void networkWithHighestRssiIsRecommended() { - List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1, TEST_SSID_2); - scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL; - scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL + 1; - - ScanResult actual = mNotificationController.recommendNetwork(scanResults); - ScanResult expected = scanResults.get(1).getScanResult(); - assertEquals(expected, actual); - } - - /** - * If the best available open network is blacklisted, no network should be recommended. - */ - @Test - public void blacklistBestNetworkSsid_shouldNeverRecommendNetwork() { - // Add TEST_SSID_1 to blacklist - userDismissedNotification_shouldBlacklistNetwork(); - - // Scan result with blacklisted SSID - List<ScanDetail> scanResults = createOpenScanResults(mDummyNetwork.SSID, TEST_SSID_2); - scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL + 1; - scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL; - - ScanResult actual = mNotificationController.recommendNetwork(scanResults); - assertNull(actual); - } - - /** - * Test null input is handled - */ - @Test - public void removeNetworkFromBlacklist_handlesNull() { - mNotificationController.handleWifiConnected(null); - verify(mWifiConfigManager, never()).saveToStore(false /* forceWrite */); - } - - /** - * If the blacklist didn't change then there is no need to continue further. - */ - @Test - public void removeNetworkFromBlacklist_returnsEarlyIfNothingIsRemoved() { - mNotificationController.handleWifiConnected(TEST_SSID_1); - verify(mWifiConfigManager, never()).saveToStore(false /* forceWrite */); - } - - /** - * If we connected to a blacklisted network, then remove it from the blacklist. - */ - @Test - public void connectToNetwork_shouldRemoveSsidFromBlacklist() { - // Add TEST_SSID_1 to blacklist - userDismissedNotification_shouldBlacklistNetwork(); - - // Simulate the user connecting to TEST_SSID_1 and verify it is removed from the blacklist - mNotificationController.handleWifiConnected(mDummyNetwork.SSID); - verify(mWifiConfigManager, times(2)).saveToStore(false /* forceWrite */); - verify(mWifiMetrics).setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG, 0); - ScanResult actual = mNotificationController.recommendNetwork(mOpenNetworks); - ScanResult expected = mOpenNetworks.get(0).getScanResult(); - assertEquals(expected, actual); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java deleted file mode 100644 index ad27814a0..000000000 --- a/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; - -import org.junit.Before; -import org.junit.Test; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -/** - * Unit tests for {@link com.android.server.wifi.RandomizedMacStoreData}. - */ -@SmallTest -public class RandomizedMacStoreDataTest extends WifiBaseTest { - private static final String TEST_MAC_ADDRESS_1 = "da:a1:19:0:0:0"; - private static final String TEST_MAC_ADDRESS_2 = "ff:ff:ff:0:0:0"; - private static final String TEST_CONFIG_KEY_1 = "TP-LINK_B6C1_5GWPA_PSK"; - private static final String TEST_CONFIG_KEY_2 = "GoogleGuest-LegacyNONE"; - private RandomizedMacStoreData mRandomizedMacStoreData; - - @Before - public void setUp() throws Exception { - mRandomizedMacStoreData = new RandomizedMacStoreData(); - } - - /** - * Helper function for serializing data to a XML block. - * - * @return byte[] of the XML data - * @throws Exception - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mRandomizedMacStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing data from a XML block. - * - * @param data XML data to parse from - * @return Map from configKey to MAC address - * @throws Exception - */ - private Map<String, String> deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mRandomizedMacStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - return mRandomizedMacStoreData.getMacMapping(); - } - - /** - * Verify that serializing empty Map causes no crash and no data should be serialized. - * - * @throws Exception - */ - @Test - public void serializeEmptyMap() throws Exception { - assertEquals(0, serializeData().length); - } - - /** - * Verify that parsing an empty data doesn't cause any crash and no configuration should - * be deserialized. - * - * @throws Exception - */ - @Test - public void deserializeEmptyData() throws Exception { - assertTrue(deserializeData(new byte[0]).isEmpty()); - } - - /** - * Verify that RandomizedMacStoreData is written to - * {@link WifiConfigStore#STORE_FILE_SHARED_GENERAL}. - * - * @throws Exception - */ - @Test - public void getSharedStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_SHARED_GENERAL, - mRandomizedMacStoreData.getStoreFileId()); - } - - /** - * Verify that MAC address mapping data is serialized and deserialized correctly. - * @throws Exception - */ - @Test - public void testSerializeDeserialize() throws Exception { - Map<String, String> macMap = new HashMap<>(); - macMap.put(TEST_CONFIG_KEY_1, TEST_MAC_ADDRESS_1); - macMap.put(TEST_CONFIG_KEY_2, TEST_MAC_ADDRESS_2); - mRandomizedMacStoreData.setMacMapping(macMap); - byte[] data = serializeData(); - Map<String, String> deserializedMap = deserializeData(data); - assertEquals(macMap, deserializedMap); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/RttManagerTest.java b/tests/wifitests/src/com/android/server/wifi/RttManagerTest.java deleted file mode 100644 index 1cb8eac73..000000000 --- a/tests/wifitests/src/com/android/server/wifi/RttManagerTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static junit.framework.Assert.assertTrue; - -import android.net.wifi.RttManager; -import android.net.wifi.RttManager.ParcelableRttParams; -import android.net.wifi.RttManager.RttParams; -import android.os.Parcel; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; - -/** - * Unit test for {@link RttManager} - */ -@SmallTest -public class RttManagerTest extends WifiBaseTest { - - // Verify ParcelableRttParams are the same after writing and reading from parcel. - private void verifyReadWriteParcelForRttParams(ParcelableRttParams params) { - Parcel parcel = Parcel.obtain(); - params.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - ParcelableRttParams paramsFromParcel = ParcelableRttParams.CREATOR.createFromParcel(parcel); - assertTrue(verifyEquals(params, paramsFromParcel)); - } - - // Check if two ParcelableRttParams equals. - private boolean verifyEquals(ParcelableRttParams params, ParcelableRttParams params2) { - if (params.mParams == params2.mParams) { - return true; - } - if (params == null || params2.mParams == null) { - return false; - } - RttParams[] paramsArray = params.mParams; - RttParams[] paramsArray2 = params2.mParams; - if (paramsArray.length != paramsArray2.length) { - return false; - } - for (int i = 0; i < paramsArray.length; i++) { - if (!rttParamsEquals(paramsArray[i], paramsArray2[i])) { - return false; - } - } - return true; - } - - // Check if two RttParams equals. Note only a subset of fields are checked. - private boolean rttParamsEquals(RttParams params1, RttParams params2) { - return params1.bssid.equals(params2.bssid) - && params1.secure == params2.secure - && params1.frequency == params2.frequency; - } - - /** - * Test writing and reading {@link RttParams} from Parcel. - */ - @Test - public void testRttParamsReadWriteParcel() throws Exception { - RttParams params = new RttParams(); - params.bssid = "12-34-56-78-9A-BC"; - params.secure = true; - params.frequency = 5240; - - RttParams params2 = new RttParams(); - params2.bssid = "12-34-56-78-9B-CD"; - params2.secure = false; - params2.frequency = 5220; - - ParcelableRttParams parcelableParams = new ParcelableRttParams(new RttParams[] { - params, params2 - }); - verifyReadWriteParcelForRttParams(parcelableParams); - // Make sure writing/reading parcel doesn't change value for empty RttParams. - verifyReadWriteParcelForRttParams(new ParcelableRttParams(new RttParams[0])); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java b/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java deleted file mode 100644 index 96b6f99ea..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * unit tests for {@link com.android.server.wifi.SarInfo}. - */ -@SmallTest -public class SarInfoTest extends WifiBaseTest { - private static final String TAG = "WifiSarInfoTest"; - - private SarInfo mSarInfo; - - private static final int SAR_SCENARIO_1 = 1; - private static final int SAR_SCENARIO_2 = 2; - - @Before - public void setUp() throws Exception { - mSarInfo = new SarInfo(); - } - - @After - public void cleanUp() throws Exception { - } - - /** - * Test that at start, resetSarScenarioNeeded returns true, - * to allow for initial setting of normal scenario. - */ - @Test - public void testSarInfo_resetSarScenarioNeed_atStart() throws Exception { - assertTrue(mSarInfo.resetSarScenarioNeeded()); - } - - /** - * Test that at start, setSarScenarioNeeded returns true. - */ - @Test - public void testSarInfo_setSarScenarioNeeded_atStart() throws Exception { - assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1)); - } - - /** - * Test performing two successive reset of SAR scenario. - * The first should succeed, while the second should fail, since it is redundant. - */ - @Test - public void testSarInfo_repeat_reset_scenario() throws Exception { - /* Initial reset is allowed */ - assertTrue(mSarInfo.resetSarScenarioNeeded()); - mSarInfo.reportingSuccessful(); - - /* Now resetting again should not be allowed */ - assertFalse(mSarInfo.resetSarScenarioNeeded()); - } - - /** - * Test performing set SAR scenario after reset. - * The two attempts should succeed. - */ - @Test - public void testSarInfo_set_after_reset_scenario() throws Exception { - assertTrue(mSarInfo.resetSarScenarioNeeded()); - mSarInfo.reportingSuccessful(); - - /* Setting scenario should be allowed, since last call was for a reset */ - assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1)); - } - - /** - * Test performing setting SAR scenario twice with same value. - * The second attempt should fail. - */ - @Test - public void testSarInfo_set_twice_same_value_scenario() throws Exception { - assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1)); - mSarInfo.reportingSuccessful(); - - /* Second attempt should fail */ - assertFalse(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1)); - } - - /** - * Test performing setting SAR scenario twice with different values. - * Both attempts should succeed. - */ - @Test - public void testSarInfo_set_twice_different_values_scenario() throws Exception { - assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1)); - mSarInfo.reportingSuccessful(); - - /* Setting scenario should be allowed */ - assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_2)); - } - - /** - * Test performing reset of SAR scenario after setting it. - * Both attempts should succeed. - */ - @Test - public void testSarInfo_reset_after_set_scenario() throws Exception { - assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1)); - mSarInfo.reportingSuccessful(); - - /* Resetting scenario should be allowed */ - assertTrue(mSarInfo.resetSarScenarioNeeded()); - } - - /** - * Test that at start, shouldReport returns false (wifi modes still disabled). - */ - @Test - public void testSarInfo_shouldReport_all_wifi_disabled() throws Exception { - assertFalse(mSarInfo.shouldReport()); - } - - /** - * Test that once Wifi (any mode) is enabled, shouldReport returns true. - */ - @Test - public void testSarInfo_shouldReport_wifi_enabled() throws Exception { - mSarInfo.isWifiClientEnabled = true; - assertTrue(mSarInfo.shouldReport()); - } - - /** - * Test having a voice call, shouldReport should return true - */ - @Test - public void testSarInfo_voice_call_wifi_enabled() throws Exception { - mSarInfo.isWifiClientEnabled = true; - assertTrue(mSarInfo.shouldReport()); - mSarInfo.reportingSuccessful(); - - mSarInfo.isVoiceCall = true; - assertTrue(mSarInfo.shouldReport()); - } - - /** - * Test a change in earpiece status, shouldReport should return true - */ - @Test - public void testSarInfo_earpiece_wifi_enabled() throws Exception { - mSarInfo.isWifiClientEnabled = true; - assertTrue(mSarInfo.shouldReport()); - mSarInfo.reportingSuccessful(); - - mSarInfo.isEarPieceActive = true; - assertTrue(mSarInfo.shouldReport()); - } - - /** - * Test starting SAP, shouldReport should return true - */ - @Test - public void testSarInfo_sap_wifi_enabled() throws Exception { - mSarInfo.isWifiClientEnabled = true; - assertTrue(mSarInfo.shouldReport()); - mSarInfo.reportingSuccessful(); - - mSarInfo.isWifiSapEnabled = true; - assertTrue(mSarInfo.shouldReport()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SarManagerTest.java b/tests/wifitests/src/com/android/server/wifi/SarManagerTest.java deleted file mode 100644 index ce9c596d4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SarManagerTest.java +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static android.telephony.TelephonyManager.CALL_STATE_IDLE; -import static android.telephony.TelephonyManager.CALL_STATE_OFFHOOK; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.net.wifi.WifiManager; -import android.os.Build; -import android.os.test.TestLooper; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * unit tests for {@link com.android.server.wifi.SarManager}. - */ -@SmallTest -public class SarManagerTest extends WifiBaseTest { - private static final String TAG = "WifiSarManagerTest"; - private static final String OP_PACKAGE_NAME = "com.xxx"; - - private void enableDebugLogs() { - mSarMgr.enableVerboseLogging(1); - } - - private MockResources getMockResources() { - MockResources resources = new MockResources(); - return resources; - } - - private SarManager mSarMgr; - private TestLooper mLooper; - private MockResources mResources; - private PhoneStateListener mPhoneStateListener; - private SarInfo mSarInfo; - - @Mock private Context mContext; - @Mock TelephonyManager mTelephonyManager; - @Mock private ApplicationInfo mMockApplInfo; - @Mock WifiNative mWifiNative; - - @Before - public void setUp() throws Exception { - /* Ensure Looper exists */ - mLooper = new TestLooper(); - - MockitoAnnotations.initMocks(this); - - /* Default behavior is to return with success */ - when(mWifiNative.selectTxPowerScenario(any(SarInfo.class))).thenReturn(true); - - mResources = getMockResources(); - - when(mContext.getResources()).thenReturn(mResources); - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.P; - when(mContext.getApplicationInfo()).thenReturn(mMockApplInfo); - when(mContext.getOpPackageName()).thenReturn(OP_PACKAGE_NAME); - } - - @After - public void cleanUp() throws Exception { - mSarMgr = null; - mLooper = null; - mContext = null; - mResources = null; - } - - /** - * Helper function to capture SarInfo object - */ - private void captureSarInfo(WifiNative wifiNative) { - /* Capture the SarInfo */ - ArgumentCaptor<SarInfo> sarInfoCaptor = ArgumentCaptor.forClass(SarInfo.class); - verify(wifiNative).selectTxPowerScenario(sarInfoCaptor.capture()); - mSarInfo = sarInfoCaptor.getValue(); - assertNotNull(mSarInfo); - } - - /** - * Helper function to set configuration for SAR and create the SAR Manager - * - */ - private void createSarManager(boolean isSarEnabled, boolean isSarSapEnabled) { - mResources.setBoolean( - R.bool.config_wifi_framework_enable_sar_tx_power_limit, isSarEnabled); - mResources.setBoolean( - R.bool.config_wifi_framework_enable_soft_ap_sar_tx_power_limit, - isSarSapEnabled); - - mSarMgr = new SarManager(mContext, mTelephonyManager, mLooper.getLooper(), - mWifiNative); - - mSarMgr.handleBootCompleted(); - - if (isSarEnabled) { - /* Capture the PhoneStateListener */ - ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_CALL_STATE)); - mPhoneStateListener = phoneStateListenerCaptor.getValue(); - assertNotNull(mPhoneStateListener); - } - - /* Enable logs from SarManager */ - enableDebugLogs(); - } - - /** - * Test that we do register the telephony call state listener on devices which do support - * setting/resetting Tx power limit. - */ - @Test - public void testSarMgr_enabledTxPowerScenario_registerPhone() throws Exception { - createSarManager(true, false); - verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_CALL_STATE)); - } - - /** - * Test that we do not register the telephony call state listener on devices which - * do not support setting/resetting Tx power limit. - */ - @Test - public void testSarMgr_disabledTxPowerScenario_registerPhone() throws Exception { - createSarManager(false, false); - verify(mTelephonyManager, never()).listen(any(), anyInt()); - } - - /** - * Test that for devices that support setting/resetting Tx Power limits, device sets the proper - * Tx power scenario upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA - * is enabled - * In this case Wifi is enabled first, then off-hook is detected - */ - @Test - public void testSarMgr_enabledTxPowerScenario_wifiOn_offHook() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - - /* Set phone state to OFFHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertTrue(mSarInfo.isVoiceCall); - } - - /** - * Test that for devices that support setting/resetting Tx Power limits, device sets the proper - * Tx power scenario upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA - * is enabled - * In this case off-hook event is detected first, then wifi is turned on - */ - @Test - public void testSarMgr_enabledTxPowerScenario_offHook_wifiOn() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Set phone state to OFFHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertTrue(mSarInfo.isVoiceCall); - } - - /** - * Test that for devices that support setting/resetting Tx Power limits, device sets the proper - * Tx power scenarios upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} and - * {@link TelephonyManager#CALL_STATE_IDLE} when WiFi STA is enabled - */ - @Test - public void testSarMgr_enabledTxPowerScenario_wifiOn_offHook_onHook() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - /* Now device should set tx power scenario to NORMAL */ - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - - /* Set phone state to OFFHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); - - /* Device should set tx power scenario to Voice call */ - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertTrue(mSarInfo.isVoiceCall); - - /* Set state back to ONHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, ""); - - /* Device should set tx power scenario to NORMAL again */ - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - - /* Disable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_DISABLED); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - } - - /** - * Test that for devices that support setting/resetting Tx Power limits, device does not - * sets the Tx power scenarios upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} and - * {@link TelephonyManager#CALL_STATE_IDLE} when WiFi STA is disabled - */ - @Test - public void testSarMgr_enabledTxPowerScenario_wifiOff_offHook_onHook() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Set phone state to OFFHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); - - /* Set state back to ONHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, ""); - - /* Device should not set tx power scenario at all */ - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - } - - /** - * Test that for devices supporting SAR the following scenario: - * - Wifi enabled - * - A call starts - * - Wifi disabled - * - Call ends - * - Wifi back on - */ - @Test - public void testSarMgr_enabledSar_wifiOn_offHook_wifiOff_onHook() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - /* Now device should set tx power scenario to NORMAL */ - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - - /* Set phone state to OFFHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertTrue(mSarInfo.isVoiceCall); - - /* Disable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_DISABLED); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - - /* Set state back to ONHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, ""); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - - /* Enable WiFi State again */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - } - - /** - * Test that for devices supporting SAR, Wifi disabled, a call starts, a call ends, Wifi - * enabled. - */ - @Test - public void testSarMgr_enabledSar_wifiOff_offHook_onHook_wifiOn() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Set phone state to OFFHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - - /* Set state back to ONHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, ""); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - } - - /** - * Test that for devices supporting SAR, Wifi disabled, a call starts, wifi on, wifi off, - * call ends. - */ - @Test - public void testSarMgr_enabledSar_offHook_wifiOnOff_onHook() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Set phone state to OFFHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - assertNotNull(mSarInfo); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertTrue(mSarInfo.isVoiceCall); - - /* Disable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_DISABLED); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - - /* Set state back to ONHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, ""); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - } - - /** - * Test the error case for for devices supporting SAR, Wifi enabled, a call starts, - * call ends. With all of these cases, the call to set Tx power scenario fails. - */ - @Test - public void testSarMgr_enabledSar_error_wifiOn_offOnHook() throws Exception { - createSarManager(true, false); - - when(mWifiNative.selectTxPowerScenario(any(SarInfo.class))).thenReturn(false); - InOrder inOrder = inOrder(mWifiNative); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - assertNotNull(mSarInfo); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - - /* Set phone state to OFFHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertTrue(mSarInfo.isVoiceCall); - - /* Set state back to ONHOOK */ - mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, ""); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - } - - /** - * Test that Start of SoftAP for a device that does not have SAR enabled does not result in - * setting the Tx power scenario - */ - @Test - public void testSarMgr_disabledTxPowerScenario_sapOn() throws Exception { - createSarManager(false, false); - - /* Enable WiFi SoftAP State */ - mSarMgr.setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED); - - verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - } - - /** - * Test that Start of SoftAP for a device that has SAR enabled. - */ - @Test - public void testSarMgr_enabledTxPowerScenario_sapOn() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Enable WiFi SoftAP State */ - mSarMgr.setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED); - captureSarInfo(mWifiNative); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertTrue(mSarInfo.isWifiSapEnabled); - assertFalse(mSarInfo.isWifiScanOnlyEnabled); - } - - /** - * Test that for a device that has SAR enabled, when scan-only state is enabled with both SoftAP - * and Client states disabled, the SarInfo is reported with proper values. - */ - @Test - public void testSarMgr_enabledTxPowerScenario_staOff_sapOff_scanOnlyOn() throws Exception { - createSarManager(true, false); - - /* Enable Wifi ScanOnly State */ - mSarMgr.setScanOnlyWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isWifiSapEnabled); - assertTrue(mSarInfo.isWifiScanOnlyEnabled); - } - - /** - * Test that for a device that has SAR enabled, when scan-only state is enabled, and then - * client state is enabled, no additional setting of Tx power scenario is initiated - */ - @Test - public void testSarMgr_enabledTxPowerScenario_staOn_sapOff_scanOnlyOn() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Enable Wifi ScanOnly State */ - mSarMgr.setScanOnlyWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isWifiSapEnabled); - assertTrue(mSarInfo.isWifiScanOnlyEnabled); - - /* Now enable Client state */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - } - - /** - * Test the success case for for devices supporting SAR, - * Wifi enabled, SoftAP enabled, wifi disabled, scan-only enabled, SoftAP disabled. - * - * SarManager should report these changes as they occur(only when changes occur to - * inputs affecting the SAR scenario). - */ - @Test - public void testSarMgr_enabledTxPowerScenario_wifi_sap_scanOnly() throws Exception { - createSarManager(true, false); - - InOrder inOrder = inOrder(mWifiNative); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertFalse(mSarInfo.isWifiSapEnabled); - assertFalse(mSarInfo.isWifiScanOnlyEnabled); - - /* Enable SoftAP state */ - mSarMgr.setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertTrue(mSarInfo.isWifiSapEnabled); - assertFalse(mSarInfo.isWifiScanOnlyEnabled); - - /* Disable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_DISABLED); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - - /* Enable ScanOnly state */ - mSarMgr.setScanOnlyWifiState(WifiManager.WIFI_STATE_ENABLED); - inOrder.verify(mWifiNative, never()).selectTxPowerScenario(any(SarInfo.class)); - - /* Disable SoftAP state */ - mSarMgr.setSapWifiState(WifiManager.WIFI_AP_STATE_DISABLED); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertFalse(mSarInfo.isWifiSapEnabled); - assertTrue(mSarInfo.isWifiScanOnlyEnabled); - } - - /** - * Test the error case for devices supporting SAR, - * Wifi enabled, SoftAP enabled, wifi disabled, scan-only enabled, SoftAP disabled - * Throughout this test case, calls to the hal return with error. - */ - @Test - public void testSarMgr_enabledTxPowerScenario_error_wifi_sap_scanOnly() throws Exception { - createSarManager(true, false); - - when(mWifiNative.selectTxPowerScenario(any(SarInfo.class))).thenReturn(false); - InOrder inOrder = inOrder(mWifiNative); - - /* Enable WiFi State */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); - captureSarInfo(mWifiNative); - - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertFalse(mSarInfo.isWifiSapEnabled); - assertFalse(mSarInfo.isWifiScanOnlyEnabled); - - /* Enable SoftAP state */ - mSarMgr.setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertTrue(mSarInfo.isWifiSapEnabled); - assertFalse(mSarInfo.isWifiScanOnlyEnabled); - - /* Disable WiFi State, reporting should still happen */ - mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_DISABLED); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertTrue(mSarInfo.isWifiSapEnabled); - assertFalse(mSarInfo.isWifiScanOnlyEnabled); - assertFalse(mSarInfo.isWifiClientEnabled); - - /* Enable ScanOnly state */ - mSarMgr.setScanOnlyWifiState(WifiManager.WIFI_STATE_ENABLED); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertTrue(mSarInfo.isWifiSapEnabled); - assertTrue(mSarInfo.isWifiScanOnlyEnabled); - assertFalse(mSarInfo.isWifiClientEnabled); - - /* Disable SoftAP state */ - mSarMgr.setSapWifiState(WifiManager.WIFI_AP_STATE_DISABLED); - inOrder.verify(mWifiNative).selectTxPowerScenario(eq(mSarInfo)); - assertFalse(mSarInfo.isVoiceCall); - assertFalse(mSarInfo.isWifiSapEnabled); - assertTrue(mSarInfo.isWifiScanOnlyEnabled); - assertFalse(mSarInfo.isWifiClientEnabled); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java b/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java deleted file mode 100644 index 33e61a44f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE; -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; - -import static org.mockito.Mockito.*; - -import android.net.wifi.WifiConfiguration; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.LocalLog; -import android.util.Pair; - -import com.android.server.wifi.WifiNetworkSelector.NetworkNominator.OnConnectableListener; -import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs; -import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for {@link SavedNetworkNominator}. - */ -@SmallTest -public class SavedNetworkNominatorTest extends WifiBaseTest { - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mLocalLog = new LocalLog(512); - mSavedNetworkNominator = new SavedNetworkNominator(mWifiConfigManager, - mPasspointNetworkNominateHelper, mLocalLog, mWifiCarrierInfoManager, - mWifiPermissionsUtil, mWifiNetworkSuggestionsManager); - when(mWifiCarrierInfoManager.isSimPresent(anyInt())).thenReturn(true); - when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any())).thenReturn(VALID_SUBID); - when(mWifiCarrierInfoManager.requiresImsiEncryption(VALID_SUBID)).thenReturn(true); - when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(anyInt())).thenReturn(true); - when(mWifiCarrierInfoManager.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(VALID_SUBID); - when(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(any(), any())) - .thenReturn(false); - - } - - /** Cleans up test. */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - private ArgumentCaptor<WifiConfiguration> mWifiConfigurationArgumentCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - private static final int VALID_SUBID = 10; - private static final int INVALID_SUBID = 1; - private static final int TEST_CARRIER_ID = 100; - private static final int RSSI_LEVEL = -50; - private static final int TEST_UID = 1001; - - private SavedNetworkNominator mSavedNetworkNominator; - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private Clock mClock; - @Mock private OnConnectableListener mOnConnectableListener; - @Mock private WifiCarrierInfoManager mWifiCarrierInfoManager; - @Mock private PasspointNetworkNominateHelper mPasspointNetworkNominateHelper; - @Mock private WifiPermissionsUtil mWifiPermissionsUtil; - @Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private LocalLog mLocalLog; - - /** - * Do not evaluate networks that {@link WifiConfiguration#useExternalScores}. - */ - @Test - public void ignoreNetworksIfUseExternalScores() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"}; - int[] levels = {RSSI_LEVEL, RSSI_LEVEL}; - int[] securities = {SECURITY_PSK, SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - for (WifiConfiguration wifiConfiguration : savedConfigs) { - wifiConfiguration.useExternalScores = true; - } - - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - - verify(mOnConnectableListener, never()).onConnectable(any(), any()); - } - - /** - * Do not evaluate networks which require SIM card when the SIM card is absent. - */ - @Test - public void ignoreNetworkIfSimIsAbsentForEapSimNetwork() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - int[] levels = {RSSI_LEVEL}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigForEapSimNetwork(ssids, bssids, - freqs, levels, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - savedConfigs[0].carrierId = TEST_CARRIER_ID; - // SIM is absent - when(mWifiCarrierInfoManager.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(INVALID_SUBID); - when(mWifiCarrierInfoManager.isSimPresent(eq(INVALID_SUBID))).thenReturn(false); - - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - - verify(mOnConnectableListener, never()).onConnectable(any(), any()); - } - - /** - * Do not evaluate networks that {@link WifiConfiguration#isEphemeral}. - */ - @Test - public void ignoreEphemeralNetworks() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[ESS]", "[ESS]"}; - int[] levels = {RSSI_LEVEL, RSSI_LEVEL}; - int[] securities = {SECURITY_NONE, SECURITY_NONE}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - for (WifiConfiguration wifiConfiguration : savedConfigs) { - wifiConfiguration.ephemeral = true; - } - - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - - verify(mOnConnectableListener, never()).onConnectable(any(), any()); - } - - /** - * Pick a worse candidate that allows auto-join over a better candidate that - * disallows auto-join. - */ - @Test - public void ignoreNetworksIfAutojoinNotAllowed() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[ESS]", "[ESS]"}; - int[] levels = {RSSI_LEVEL, RSSI_LEVEL}; - int[] securities = {SECURITY_NONE, SECURITY_NONE}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - - verify(mOnConnectableListener, times(2)).onConnectable(any(), any()); - reset(mOnConnectableListener); - savedConfigs[1].allowAutojoin = false; - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - verify(mOnConnectableListener).onConnectable(any(), - mWifiConfigurationArgumentCaptor.capture()); - WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], - mWifiConfigurationArgumentCaptor.getValue()); - } - - /** - * Do not return a candidate if all networks do not {@link WifiConfiguration#allowAutojoin} - */ - @Test - public void returnNoCandidateIfNoNetworksAllowAutojoin() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[ESS]", "[ESS]"}; - int[] levels = {RSSI_LEVEL, RSSI_LEVEL}; - int[] securities = {SECURITY_NONE, SECURITY_NONE}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - for (WifiConfiguration wifiConfiguration : savedConfigs) { - wifiConfiguration.allowAutojoin = false; - } - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - verify(mOnConnectableListener, never()).onConnectable(any(), any()); - } - - /** - * Ensure that we do nominate the only matching saved passponit network with auto-join enabled . - */ - @Test - public void returnCandidatesIfPasspointNetworksAvailableWithAutojoinEnabled() { - ScanDetail scanDetail1 = mock(ScanDetail.class); - ScanDetail scanDetail2 = mock(ScanDetail.class); - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - WifiConfiguration configuration1 = mock(WifiConfiguration.class); - configuration1.allowAutojoin = true; - WifiConfiguration configuration2 = mock(WifiConfiguration.class); - configuration2.allowAutojoin = false; - List<Pair<ScanDetail, WifiConfiguration>> passpointCandidates = - Arrays.asList(Pair.create(scanDetail1, configuration1), Pair.create(scanDetail2, - configuration2)); - when(mPasspointNetworkNominateHelper.getPasspointNetworkCandidates(scanDetails, false)) - .thenReturn(passpointCandidates); - mSavedNetworkNominator.nominateNetworks(scanDetails, null, null, - false, false, mOnConnectableListener); - verify(mOnConnectableListener).onConnectable(scanDetail1, configuration1); - verify(mOnConnectableListener, never()).onConnectable(scanDetail2, configuration2); - } - - /** - * Verify if a network is metered and with non-data sim, will not nominate as a candidate. - */ - @Test - public void testIgnoreNetworksIfMeteredAndFromNonDataSim() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - int[] levels = {RSSI_LEVEL}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigForEapSimNetwork(ssids, bssids, - freqs, levels, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - savedConfigs[0].carrierId = TEST_CARRIER_ID; - when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(savedConfigs[0])) - .thenReturn(false); - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - verify(mOnConnectableListener).onConnectable(any(), any()); - reset(mOnConnectableListener); - when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(savedConfigs[0])) - .thenReturn(true); - verify(mOnConnectableListener, never()).onConnectable(any(), any()); - } - - /** - * Verify a saved network is from app not user, if IMSI privacy protection is not required, will - * send notification for user to approve exemption, and not consider as a candidate. - */ - @Test - public void testIgnoreNetworksFromAppIfNoImsiProtection() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - int[] levels = {RSSI_LEVEL}; - when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(any())) - .thenReturn(false); - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigForEapSimNetwork(ssids, bssids, - freqs, levels, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - savedConfigs[0].carrierId = TEST_CARRIER_ID; - // Doesn't require Imsi protection and user didn't approved - when(mWifiCarrierInfoManager.requiresImsiEncryption(VALID_SUBID)).thenReturn(false); - when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID)) - .thenReturn(false); - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - verify(mOnConnectableListener, never()).onConnectable(any(), any()); - verify(mWifiCarrierInfoManager) - .sendImsiProtectionExemptionNotificationIfRequired(TEST_CARRIER_ID); - // Simulate user approved - when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID)) - .thenReturn(true); - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - verify(mOnConnectableListener).onConnectable(any(), any()); - // If from settings app, will bypass the IMSI check. - when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID)) - .thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - } - - @Test - public void testIgnoreOpenNetworkWithSameNetworkSuggestionHasSecureNetworkFromSameCarrier() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - String[] caps = {"[ESS]"}; - int[] levels = {RSSI_LEVEL}; - int[] securities = {SECURITY_NONE}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - - when(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(any(), any())) - .thenReturn(true); - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - verify(mOnConnectableListener, never()).onConnectable(any(), any()); - - when(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(any(), any())) - .thenReturn(false); - mSavedNetworkNominator.nominateNetworks(scanDetails, - null, null, true, false, mOnConnectableListener); - verify(mOnConnectableListener).onConnectable(any(), any()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java b/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java deleted file mode 100644 index cc96602d5..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java +++ /dev/null @@ -1,1029 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; - -import static com.android.server.wifi.ScanRequestProxy.SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; -import static com.android.server.wifi.ScanRequestProxy.SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS; -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_SCAN_THROTTLE_ENABLED; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.Intent; -import android.net.wifi.IScanResultsCallback; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ScanSettings.HiddenNetwork; -import android.os.Handler; -import android.os.IBinder; -import android.os.UserHandle; -import android.os.WorkSource; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.WifiPermissionsUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.ScanRequestProxy}. - */ -@SmallTest -public class ScanRequestProxyTest extends WifiBaseTest { - private static final int TEST_UID = 5; - private static final String TEST_PACKAGE_NAME_1 = "com.test.1"; - private static final String TEST_PACKAGE_NAME_2 = "com.test.2"; - private static final List<HiddenNetwork> TEST_HIDDEN_NETWORKS_LIST = - new ArrayList<HiddenNetwork>() {{ - add(new HiddenNetwork("test_ssid_1")); - add(new HiddenNetwork("test_ssid_2")); - - }}; - private static final List<HiddenNetwork> TEST_HIDDEN_NETWORKS_LIST_NS = - new ArrayList<HiddenNetwork>() {{ - add(new HiddenNetwork("test_ssid_3")); - add(new HiddenNetwork("test_ssid_4")); - }}; - - @Mock private Context mContext; - @Mock private AppOpsManager mAppOps; - @Mock private ActivityManager mActivityManager; - @Mock private WifiInjector mWifiInjector; - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private WifiScanner mWifiScanner; - @Mock private WifiPermissionsUtil mWifiPermissionsUtil; - @Mock private WifiMetrics mWifiMetrics; - @Mock private Clock mClock; - @Mock private WifiSettingsConfigStore mWifiSettingsConfigStore; - @Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - @Mock private IScanResultsCallback mScanResultsCallback; - @Mock private IScanResultsCallback mAnotherScanResultsCallback; - @Mock private TestLooper mLooper; - @Mock private IBinder mBinder; - @Mock private IBinder mAnotherBinder; - - private ArgumentCaptor<WorkSource> mWorkSourceArgumentCaptor = - ArgumentCaptor.forClass(WorkSource.class); - private ArgumentCaptor<WifiScanner.ScanSettings> mScanSettingsArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanSettings.class); - private ArgumentCaptor<WifiScanner.ScanListener> mScanRequestListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - private ArgumentCaptor<WifiScanner.ScanListener> mGlobalScanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - private WifiScanner.ScanData[] mTestScanDatas1; - private WifiScanner.ScanData[] mTestScanDatas2; - private InOrder mInOrder; - - private ScanRequestProxy mScanRequestProxy; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); - when(mWifiInjector.getWifiNetworkSuggestionsManager()) - .thenReturn(mWifiNetworkSuggestionsManager); - when(mWifiConfigManager.retrieveHiddenNetworkList()).thenReturn(TEST_HIDDEN_NETWORKS_LIST); - when(mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList()) - .thenReturn(TEST_HIDDEN_NETWORKS_LIST_NS); - doNothing().when(mWifiScanner).registerScanListener( - any(), - mGlobalScanListenerArgumentCaptor.capture()); - doNothing().when(mWifiScanner).startScan( - mScanSettingsArgumentCaptor.capture(), - any(), - mScanRequestListenerArgumentCaptor.capture(), - mWorkSourceArgumentCaptor.capture()); - - mInOrder = inOrder(mWifiScanner, mWifiConfigManager, - mContext, mWifiNetworkSuggestionsManager); - mTestScanDatas1 = - ScanTestUtil.createScanDatas(new int[][]{{ 2417, 2427, 5180, 5170 }}, - new int[]{0}, - new int[]{WifiScanner.WIFI_BAND_ALL}); - mTestScanDatas2 = - ScanTestUtil.createScanDatas(new int[][]{{ 2412, 2422, 5200, 5210 }}, - new int[]{0}, - new int[]{WifiScanner.WIFI_BAND_ALL}); - - // Scan throttling is enabled by default. - when(mWifiSettingsConfigStore.get(eq(WIFI_SCAN_THROTTLE_ENABLED))).thenReturn(true); - mLooper = new TestLooper(); - mScanRequestProxy = - new ScanRequestProxy(mContext, mAppOps, mActivityManager, mWifiInjector, - mWifiConfigManager, mWifiPermissionsUtil, mWifiMetrics, mClock, - new Handler(mLooper.getLooper()), mWifiSettingsConfigStore); - when(mScanResultsCallback.asBinder()).thenReturn(mBinder); - when(mAnotherScanResultsCallback.asBinder()).thenReturn(mAnotherBinder); - } - - @After - public void cleanUp() throws Exception { - verifyNoMoreInteractions(mWifiScanner, mWifiConfigManager, mContext, mWifiMetrics); - validateMockitoUsage(); - } - - private void enableScanning() { - // Enable scanning - mScanRequestProxy.enableScanning(true, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); - mInOrder.verify(mWifiScanner).setScanningEnabled(true); - validateScanAvailableBroadcastSent(true); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(782L); - } - - /** - * Verify scan enable sequence. - */ - @Test - public void testEnableScanning() { - mScanRequestProxy.enableScanning(true, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); - mInOrder.verify(mWifiScanner).setScanningEnabled(true); - validateScanAvailableBroadcastSent(true); - } - - /** - * Verify scan disable sequence. - */ - @Test - public void testDisableScanning() { - mScanRequestProxy.enableScanning(false, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); - mInOrder.verify(mWifiScanner).setScanningEnabled(false); - validateScanAvailableBroadcastSent(false); - } - - /** - * Verify scan request will be rejected if we cannot get a handle to wifiscanner. - */ - @Test - public void testStartScanFailWithoutScanner() { - when(mWifiInjector.getWifiScanner()).thenReturn(null); - assertFalse(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - validateScanResultsFailureBroadcastSent(TEST_PACKAGE_NAME_1); - } - - /** - * Verify scan request will forwarded to wifiscanner if wifiscanner is present. - */ - @Test - public void testStartScanSuccess() { - enableScanning(); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - assertTrue(mWorkSourceArgumentCaptor.getValue().equals( - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1))); - validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false); - - verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify scan request will forwarded to wifiscanner if wifiscanner is present. - */ - @Test - public void testStartScanSuccessFromAppWithNetworkSettings() { - enableScanning(); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(TEST_UID)).thenReturn(true); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - assertTrue(mWorkSourceArgumentCaptor.getValue().equals( - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1))); - validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false, true); - } - - /** - * Verify scan request will forwarded to wifiscanner if wifiscanner is present. - */ - @Test - public void testStartScanSuccessFromAppWithNetworkSetupWizard() { - enableScanning(); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(TEST_UID)).thenReturn(true); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - assertEquals(mWorkSourceArgumentCaptor.getValue(), - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)); - validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false, true); - } - - /** - * Verify that hidden network list is not retrieved when hidden network scanning is disabled. - */ - @Test - public void testStartScanWithHiddenNetworkScanningDisabled() { - mScanRequestProxy.enableScanning(true, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); - mInOrder.verify(mWifiScanner).setScanningEnabled(true); - validateScanAvailableBroadcastSent(true); - - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiConfigManager, never()).retrieveHiddenNetworkList(); - mInOrder.verify(mWifiNetworkSuggestionsManager, never()).retrieveHiddenNetworkList(); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - assertEquals(mWorkSourceArgumentCaptor.getValue(), - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)); - validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false); - - verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify that hidden network list is retrieved when hidden network scanning is enabled. - */ - @Test - public void testStartScanWithHiddenNetworkScanningEnabled() { - mScanRequestProxy.enableScanning(true, true); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); - mInOrder.verify(mWifiScanner).setScanningEnabled(true); - validateScanAvailableBroadcastSent(true); - - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - - mInOrder.verify(mWifiConfigManager).retrieveHiddenNetworkList(); - mInOrder.verify(mWifiNetworkSuggestionsManager).retrieveHiddenNetworkList(); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - assertEquals(mWorkSourceArgumentCaptor.getValue(), - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)); - validateScanSettings(mScanSettingsArgumentCaptor.getValue(), true); - - verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify a successful scan request and processing of scan results. - */ - @Test - public void testScanSuccess() { - // Make a scan request. - testStartScanSuccess(); - - // Verify the scan results processing. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - validateScanResultsAvailableBroadcastSent(true); - - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify a successful scan request and processing of scan failure. - */ - @Test - public void testScanFailure() { - // Make a scan request. - testStartScanSuccess(); - - // Verify the scan failure processing. - mScanRequestListenerArgumentCaptor.getValue().onFailure(0, "failed"); - validateScanResultsAvailableBroadcastSent(false); - - // Ensure scan results in the cache is empty. - assertTrue(mScanRequestProxy.getScanResults().isEmpty()); - - verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify processing of successive successful scans. - */ - @Test - public void testScanSuccessOverwritesPreviousResults() { - enableScanning(); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Verify the scan results processing for request 1. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - // Make scan request 2. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Verify the scan results processing for request 2. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas2[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - verify(mWifiMetrics, times(2)).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify processing of a successful scan followed by a failure. - */ - @Test - public void testScanFailureDoesNotOverwritePreviousResults() { - enableScanning(); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Verify the scan results processing for request 1. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - // Make scan request 2. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Verify the scan failure processing. - mScanRequestListenerArgumentCaptor.getValue().onFailure(0, "failed"); - validateScanResultsAvailableBroadcastSent(false); - // Validate the scan results from a previous successful scan in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - verify(mWifiMetrics, times(2)).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify processing of a new scan request after a previous scan success. - * Verify that we send out two broadcasts (two successes). - */ - @Test - public void testNewScanRequestAfterPreviousScanSucceeds() { - enableScanning(); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Now send the scan results for request 1. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - // Make scan request 2. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - // Ensure that we did send a second scan request to scanner. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Now send the scan results for request 2. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas2[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - verify(mWifiMetrics, times(2)).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify processing of a new scan request after a previous scan success, but with bad scan - * data. - * Verify that we send out two broadcasts (one failure & one success). - */ - @Test - public void testNewScanRequestAfterPreviousScanSucceedsWithInvalidScanDatas() { - enableScanning(); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - // Now send scan success for request 1, but with invalid scan datas. - mGlobalScanListenerArgumentCaptor.getValue().onResults( - new WifiScanner.ScanData[] {mTestScanDatas1[0], mTestScanDatas2[0]}); - validateScanResultsAvailableBroadcastSent(false); - // Validate the scan results in the cache. - assertTrue(mScanRequestProxy.getScanResults().isEmpty()); - - // Make scan request 2. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - // Ensure that we did send a second scan request to scanner. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Now send the scan results for request 2. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas2[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - verify(mWifiMetrics, times(2)).incrementExternalAppOneshotScanRequestsCount(); - } - - - /** - * Verify processing of a new scan request after a previous scan failure. - * Verify that we send out two broadcasts (one failure & one success). - */ - @Test - public void testNewScanRequestAfterPreviousScanFailure() { - enableScanning(); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - // Now send scan failure for request 1. - mScanRequestListenerArgumentCaptor.getValue().onFailure(0, "failed"); - validateScanResultsAvailableBroadcastSent(false); - // Validate the scan results in the cache. - assertTrue(mScanRequestProxy.getScanResults().isEmpty()); - - // Make scan request 2. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - // Ensure that we did send a second scan request to scanner. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Now send the scan results for request 2. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas2[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - verify(mWifiMetrics, times(2)).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify that we clear scan results when scan state is toggled. - */ - @Test - public void testToggleScanStateClearsScanResults() { - // Enable scanning - mScanRequestProxy.enableScanning(true, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); - mInOrder.verify(mWifiScanner).setScanningEnabled(true); - validateScanAvailableBroadcastSent(true); - - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Verify the scan results processing for request 1. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - // Disable scanning - mScanRequestProxy.enableScanning(false, false); - verify(mWifiScanner).setScanningEnabled(false); - validateScanAvailableBroadcastSent(false); - - assertTrue(mScanRequestProxy.getScanResults().isEmpty()); - - verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify that we don't use the same listener for multiple scan requests. - */ - @Test - public void testSuccessiveScanRequestsDontUseSameListener() { - enableScanning(); - WifiScanner.ScanListener listener1; - WifiScanner.ScanListener listener2; - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - listener1 = mScanRequestListenerArgumentCaptor.getValue(); - - // Make scan request 2. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - // Ensure that we did send a second scan request to scanner. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - listener2 = mScanRequestListenerArgumentCaptor.getValue(); - - assertNotEquals(listener1, listener2); - - verify(mWifiMetrics, times(2)).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Ensure new scan requests from the same app are rejected if there are more than - * {@link ScanRequestProxy#SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS} requests in - * {@link ScanRequestProxy#SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS} - */ - @Test - public void testSuccessiveScanRequestFromSameFgAppThrottled() { - enableScanning(); - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - // Make next scan request from the same package name & ensure that it is throttled. - assertFalse(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - validateScanResultsFailureBroadcastSent(TEST_PACKAGE_NAME_1); - - verify(mWifiMetrics, times(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1)) - .incrementExternalAppOneshotScanRequestsCount(); - verify(mWifiMetrics).incrementExternalForegroundAppOneshotScanRequestsThrottledCount(); - } - - /** - * Ensure new scan requests from the same app are rejected if there are more than - * {@link ScanRequestProxy#SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS} requests after - * {@link ScanRequestProxy#SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS} - */ - @Test - public void testSuccessiveScanRequestFromSameFgAppNotThrottled() { - enableScanning(); - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - long lastRequestMs = firstRequestMs + SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS + 1; - when(mClock.getElapsedSinceBootMillis()).thenReturn(lastRequestMs); - // Make next scan request from the same package name & ensure that it is not throttled. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - verify(mWifiMetrics, times(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1)) - .incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Ensure new scan requests from the same app with NETWORK_SETTINGS permission are not - * throttled. - */ - @Test - public void testSuccessiveScanRequestFromSameAppWithNetworkSettingsPermissionNotThrottled() { - enableScanning(); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(TEST_UID)).thenReturn(true); - - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - // Make next scan request from the same package name & ensure that it is not throttled. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - - /** - * Ensure new scan requests from the same app with NETWORK_SETUP_WIZARD permission are not - * throttled. - */ - @Test - public void testSuccessiveScanRequestFromSameAppWithNetworkSetupWizardPermissionNotThrottled() { - enableScanning(); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(TEST_UID)).thenReturn(true); - - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - // Make next scan request from the same package name & ensure that it is not throttled. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - - /** - * Ensure new scan requests from the same app are not throttled when the user turns - * off scan throttling. - */ - @Test - public void testSuccessiveScanRequestFromSameAppWhenThrottlingIsDisabledNotThrottled() { - // Triggers the scan throttle setting registration. - testEnableScanning(); - mScanRequestProxy.setScanThrottleEnabled(false); - verify(mWifiSettingsConfigStore).put(WIFI_SCAN_THROTTLE_ENABLED, false); - - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - // Make next scan request from the same package name & ensure that it is not throttled. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - - /** - * Ensure new scan requests from different apps are not throttled. - */ - @Test - public void testSuccessiveScanRequestFromDifferentFgAppsNotThrottled() { - enableScanning(); - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS / 2; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS / 2; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - // Make next scan request from both the package name & ensure that it is not throttled. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - verify(mWifiMetrics, times(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 2)) - .incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Ensure new scan requests from the same app after removal & re-install is not - * throttled. - * Verifies that we clear the scan timestamps for apps that were removed. - */ - @Test - public void testSuccessiveScanRequestFromSameAppAfterRemovalAndReinstallNotThrottled() { - enableScanning(); - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - // Now simulate removing the app. - mScanRequestProxy.clearScanRequestTimestampsForApp(TEST_PACKAGE_NAME_1, TEST_UID); - - // Make next scan request from the same package name (simulating a reinstall) & ensure that - // it is not throttled. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - verify(mWifiMetrics, times(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1)) - .incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Ensure new scan requests after removal of the app from a different user is throttled. - * The app has same the package name across users, but different UID's. Verifies that - * the cache is cleared only for the specific app for a specific user when an app is removed. - */ - @Test - public void testSuccessiveScanRequestFromSameAppAfterRemovalOnAnotherUserThrottled() { - enableScanning(); - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - // Now simulate removing the app for another user (User 1). - mScanRequestProxy.clearScanRequestTimestampsForApp( - TEST_PACKAGE_NAME_1, - UserHandle.getUid(UserHandle.USER_SYSTEM + 1, TEST_UID)); - - // Make next scan request from the same package name & ensure that is throttled. - assertFalse(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - validateScanResultsFailureBroadcastSent(TEST_PACKAGE_NAME_1); - - verify(mWifiMetrics, times(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1)) - .incrementExternalAppOneshotScanRequestsCount(); - verify(mWifiMetrics).incrementExternalForegroundAppOneshotScanRequestsThrottledCount(); - } - - /** - * Ensure scan requests from different background apps are throttled if it's before - * {@link ScanRequestProxy#SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS}. - */ - @Test - public void testSuccessiveScanRequestFromBgAppsThrottled() { - enableScanning(); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE + 1); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE + 1); - - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - // Make scan request 2 from the different package name & ensure that it is throttled. - assertFalse(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - validateScanResultsFailureBroadcastSent(TEST_PACKAGE_NAME_2); - - verify(mWifiMetrics, times(2)).incrementExternalAppOneshotScanRequestsCount(); - verify(mWifiMetrics).incrementExternalBackgroundAppOneshotScanRequestsThrottledCount(); - } - - /** - * Ensure scan requests from different background apps are not throttled if it's after - * {@link ScanRequestProxy#SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS}. - */ - @Test - public void testSuccessiveScanRequestFromBgAppsNotThrottled() { - enableScanning(); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND + 1); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND + 1); - - long firstRequestMs = 782; - when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - long secondRequestMs = - firstRequestMs + ScanRequestProxy.SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS + 1; - when(mClock.getElapsedSinceBootMillis()).thenReturn(secondRequestMs); - // Make scan request 2 from the different package name & ensure that it is throttled. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - - verify(mWifiMetrics, times(2)).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify processing of a successful scan followed by full scan results from - * internal scans. - */ - @Test - public void testFullInternalScanResultsOverwritesPreviousResults() { - enableScanning(); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Verify the scan results processing for request 1. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - // Now send results from an internal full scan request. - // Verify the scan failure processing. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas2[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount(); - } - - /** - * Verify processing of a successful scan followed by partial scan results from - * internal scans. - */ - @Test - public void testPartialInternalScanResultsDoesNotOverwritePreviousResults() { - enableScanning(); - // Make scan request 1. - assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - // Verify the scan results processing for request 1. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - validateScanResultsAvailableBroadcastSent(true); - // Validate the scan results in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - // Now send results from an internal partial scan request. - mTestScanDatas2 = ScanTestUtil.createScanDatas(new int[][]{{ 2412, 2422, 5200, 5210 }}, - new int[]{0}, - new int[]{WifiScanner.WIFI_BAND_BOTH}); - // Verify the scan failure processing. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); - // Validate the scan results from a previous successful scan in the cache. - ScanTestUtil.assertScanResultsEquals( - mTestScanDatas1[0].getResults(), - mScanRequestProxy.getScanResults().stream().toArray(ScanResult[]::new)); - - verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount(); - } - - private void validateScanSettings(WifiScanner.ScanSettings scanSettings, - boolean expectHiddenNetworks) { - validateScanSettings(scanSettings, expectHiddenNetworks, false); - } - - private void validateScanSettings(WifiScanner.ScanSettings scanSettings, - boolean expectHiddenNetworks, - boolean expectHighAccuracyType) { - assertNotNull(scanSettings); - assertEquals(WifiScanner.WIFI_BAND_ALL, scanSettings.band); - if (expectHighAccuracyType) { - assertEquals(WifiScanner.SCAN_TYPE_HIGH_ACCURACY, scanSettings.type); - } else { - assertEquals(WifiScanner.SCAN_TYPE_LOW_LATENCY, scanSettings.type); - } - assertEquals(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN - | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, scanSettings.reportEvents); - List<HiddenNetwork> hiddenNetworkList = - new ArrayList<>(); - hiddenNetworkList.addAll(TEST_HIDDEN_NETWORKS_LIST); - hiddenNetworkList.addAll(TEST_HIDDEN_NETWORKS_LIST_NS); - if (expectHiddenNetworks) { - assertEquals(hiddenNetworkList.size(), scanSettings.hiddenNetworks.size()); - for (HiddenNetwork hiddenNetwork : scanSettings.hiddenNetworks) { - validateHiddenNetworkInList(hiddenNetwork, hiddenNetworkList); - } - } else { - assertEquals(Collections.emptyList(), scanSettings.hiddenNetworks); - } - } - - private void validateHiddenNetworkInList( - HiddenNetwork expectedHiddenNetwork, - List<HiddenNetwork> hiddenNetworkList) { - for (HiddenNetwork hiddenNetwork : hiddenNetworkList) { - if (hiddenNetwork.ssid.equals(expectedHiddenNetwork.ssid)) { - return; - } - } - fail(); - } - - private void validateScanResultsAvailableBroadcastSent(boolean expectScanSuceeded) { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - ArgumentCaptor<UserHandle> userHandleCaptor = ArgumentCaptor.forClass(UserHandle.class); - mInOrder.verify(mContext).sendBroadcastAsUser( - intentCaptor.capture(), userHandleCaptor.capture()); - - assertEquals(userHandleCaptor.getValue(), UserHandle.ALL); - - Intent intent = intentCaptor.getValue(); - assertEquals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION, intent.getAction()); - assertEquals(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, intent.getFlags()); - boolean scanSucceeded = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); - assertEquals(expectScanSuceeded, scanSucceeded); - } - - private void validateScanResultsFailureBroadcastSent(String expectedPackageName) { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - ArgumentCaptor<UserHandle> userHandleCaptor = ArgumentCaptor.forClass(UserHandle.class); - mInOrder.verify(mContext).sendBroadcastAsUser( - intentCaptor.capture(), userHandleCaptor.capture()); - - assertEquals(userHandleCaptor.getValue(), UserHandle.ALL); - - Intent intent = intentCaptor.getValue(); - assertEquals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION, intent.getAction()); - assertEquals(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, intent.getFlags()); - boolean scanSucceeded = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); - assertFalse(scanSucceeded); - String packageName = intent.getPackage(); - assertEquals(expectedPackageName, packageName); - } - - private void validateScanAvailableBroadcastSent(boolean expectedScanAvailable) { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - ArgumentCaptor<UserHandle> userHandleCaptor = ArgumentCaptor.forClass(UserHandle.class); - mInOrder.verify(mContext).sendStickyBroadcastAsUser( - intentCaptor.capture(), userHandleCaptor.capture()); - - assertEquals(userHandleCaptor.getValue(), UserHandle.ALL); - - Intent intent = intentCaptor.getValue(); - assertEquals(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED, intent.getAction()); - assertEquals(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, intent.getFlags()); - boolean scanAvailable = intent.getBooleanExtra(WifiManager.EXTRA_SCAN_AVAILABLE, false); - assertEquals(expectedScanAvailable, scanAvailable); - } - - /** - * Test register two different scan result Callback, all of them will receive the event. - */ - @Test - public void testScanSuccessWithMultipleCallback() throws Exception { - mScanRequestProxy.registerScanResultsCallback(mScanResultsCallback); - mScanRequestProxy.registerScanResultsCallback(mAnotherScanResultsCallback); - testStartScanSuccess(); - // Verify the scan results processing. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - mLooper.dispatchAll(); - validateScanResultsAvailableBroadcastSent(true); - - mScanRequestProxy.unregisterScanResultsCallback(mScanResultsCallback); - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); - mLooper.dispatchAll(); - validateScanResultsAvailableBroadcastSent(true); - verify(mScanResultsCallback).onScanResultsAvailable(); - verify(mAnotherScanResultsCallback, times(2)).onScanResultsAvailable(); - } - - /** - * Verify that registering twice with same Callback will replace the first Callback. - */ - @Test - public void testReplacesOldListenerWithNewCallbackWhenRegisteringTwice() throws Exception { - mScanRequestProxy.registerScanResultsCallback(mScanResultsCallback); - mScanRequestProxy.registerScanResultsCallback(mScanResultsCallback); - mLooper.dispatchAll(); - // Verify old listener is replaced. - verify(mBinder, times(2)).linkToDeath(any(), anyInt()); - verify(mBinder).unlinkToDeath(any(), anyInt()); - testStartScanSuccess(); - // Verify the scan results processing. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - mLooper.dispatchAll(); - verify(mScanResultsCallback).onScanResultsAvailable(); - validateScanResultsAvailableBroadcastSent(true); - } - - /** - * Test registered scan result Callback will be unregistered when calling binder is died. - */ - @Test - public void testUnregisterScanResultCallbackOnBinderDied() throws Exception { - ArgumentCaptor<IBinder.DeathRecipient> drCaptor = - ArgumentCaptor.forClass(IBinder.DeathRecipient.class); - mScanRequestProxy.registerScanResultsCallback(mScanResultsCallback); - verify(mBinder).linkToDeath(drCaptor.capture(), anyInt()); - testStartScanSuccess(); - // Verify the scan results processing. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - mLooper.dispatchAll(); - validateScanResultsAvailableBroadcastSent(true); - verify(mScanResultsCallback).onScanResultsAvailable(); - drCaptor.getValue().binderDied(); - mLooper.dispatchAll(); - reset(mScanResultsCallback); - // Verify the scan results processing. - mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); - mLooper.dispatchAll(); - validateScanResultsAvailableBroadcastSent(true); - verify(mScanResultsCallback, never()).onScanResultsAvailable(); - } - - /** Test that modifying the returned scan results list does not change the original. */ - @Test - public void testGetScanResults_modifyReturnedList_doesNotChangeOriginal() { - // initialize scan results - testStartScanSuccess(); - - List<ScanResult> scanResults = mScanRequestProxy.getScanResults(); - int scanResultsOriginalSize = scanResults.size(); - - scanResults.add(new ScanResult()); - - assertThat(mScanRequestProxy.getScanResults()).hasSize(scanResultsOriginalSize); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java b/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java deleted file mode 100644 index 08addcd37..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.net.wifi.WifiConfiguration; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; - - -/** - * Unit tests for {@link com.android.server.wifi.ScanResultMatchInfoTest}. - */ -@SmallTest -public class ScanResultMatchInfoTest extends WifiBaseTest { - /** - * Tests that equivalent ScanResultMatchInfo objects are created for WifiConfigurations and - * their associated ScanResult - */ - @Test - public void testScanResultMatchesWifiConfiguration() { - WifiConfiguration conf = - WifiConfigurationTestUtil.createPskNetwork("\"PrettyFlyForAWifi\""); - ScanDetail scan = createScanDetailForNetwork(conf, "AA:AA:AA:AA:AA:AA"); - assertEquals(ScanResultMatchInfo.fromWifiConfiguration(conf), - ScanResultMatchInfo.fromScanResult(scan.getScanResult())); - - conf = WifiConfigurationTestUtil.createOpenNetwork("\"WIFIght the inevitable\""); - scan = createScanDetailForNetwork(conf, "BB:BB:BB:BB:BB:BB"); - assertEquals(ScanResultMatchInfo.fromWifiConfiguration(conf), - ScanResultMatchInfo.fromScanResult(scan.getScanResult())); - - conf = - WifiConfigurationTestUtil.createWapiPskNetwork(); - scan = createScanDetailForNetwork(conf, "AA:AA:AA:AA:AA:AA"); - assertEquals(ScanResultMatchInfo.fromWifiConfiguration(conf), - ScanResultMatchInfo.fromScanResult(scan.getScanResult())); - - conf = - WifiConfigurationTestUtil.createWapiPskNetwork(); - scan = createScanDetailForNetwork(conf, "BB:BB:BB:BB:BB:BB"); - assertEquals(ScanResultMatchInfo.fromWifiConfiguration(conf), - ScanResultMatchInfo.fromScanResult(scan.getScanResult())); - } - - /** - * Tests that multiple ScanResults with different BSSIDs will produce equivalent - * ScanResultMatchInfo objects to their associated WifiConfiguration - */ - @Test - public void testDifferentBssidScanResultsMatch() { - WifiConfiguration conf = - WifiConfigurationTestUtil.createPskNetwork("\"PrettyFlyForAWifi-5G\""); - ScanDetail scan1 = createScanDetailForNetwork(conf, "AA:AA:AA:AA:AA:AA"); - ScanDetail scan2 = createScanDetailForNetwork(conf, "BB:BB:BB:BB:BB:BB"); - assertFalse(scan1.getScanResult().BSSID.equals(scan2.getScanResult().BSSID)); - assertEquals(ScanResultMatchInfo.fromScanResult(scan1.getScanResult()), - ScanResultMatchInfo.fromScanResult(scan2.getScanResult())); - } - - /** - * Tests that ScanResultMatchInfo objects created for different SSIDs or security types are not - * equivalent - */ - @Test - public void testDifferentNetworkScanResultsDontMatch() { - WifiConfiguration psk = - WifiConfigurationTestUtil.createPskNetwork("\"Series Of Tubes\""); - WifiConfiguration open1 = - WifiConfigurationTestUtil.createOpenNetwork("\"Series Of Tubes\""); - WifiConfiguration open2 = - WifiConfigurationTestUtil.createOpenNetwork("\"Mom, Click Here For Internet\""); - ScanDetail scanOpen1 = createScanDetailForNetwork(open1, "AA:AA:AA:AA:AA:AA"); - ScanDetail scanOpen2 = createScanDetailForNetwork(open2, "BB:BB:BB:BB:BB:BB"); - ScanDetail scanPsk = createScanDetailForNetwork(psk, "CC:CC:CC:CC:CC:CC"); - assertTrue(ScanResultMatchInfo.fromScanResult(scanOpen1.getScanResult()) - != ScanResultMatchInfo.fromScanResult(scanOpen2.getScanResult())); - assertTrue(ScanResultMatchInfo.fromScanResult(scanOpen1.getScanResult()) - != ScanResultMatchInfo.fromScanResult(scanPsk.getScanResult())); - } - - /** - * Tests equality properties, reflexive, symmetric, transitive, consistent for transition mode - * network. - */ - @Test - public void testEqualityRulesForTransitionMode() { - WifiConfiguration wifiConfiguration = - WifiConfigurationTestUtil.createPskNetwork("\"Transition is Hard\""); - ScanDetail scanDetail = createScanDetailForWpa2Wpa3TransitionModeNetwork(wifiConfiguration, - "AA:BB:CC:DD:CC:BB"); - - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfiguration); - ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanDetail.getScanResult()); - ScanResultMatchInfo key3 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfiguration); - - // Test a.equals(a) - assertTrue(key1.equals(key1)); - - // Test if a.equals(b) then b.equals(a) - assertTrue(key1.equals(key2)); - assertTrue(key2.equals(key1)); - - // Test transitivity - assertTrue(key1.equals(key2)); - assertTrue(key2.equals(key3)); - assertTrue(key1.equals(key3)); - - // Test consistency - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - } - - /** - * Tests equality properties, reflexive, symmetric, transitive, consistent for PSK network. - */ - @Test - public void testEqualityRulesForPsk() { - WifiConfiguration wifiConfiguration = - WifiConfigurationTestUtil.createPskNetwork("\"Psk Tsk\""); - ScanDetail scanDetail = createScanDetailForNetwork(wifiConfiguration, - "AA:BB:CC:DD:CC:BB"); - - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfiguration); - ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanDetail.getScanResult()); - ScanResultMatchInfo key3 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfiguration); - - // Test a.equals(a) - assertTrue(key1.equals(key1)); - - // Test if a.equals(b) then b.equals(a) - assertTrue(key1.equals(key2)); - assertTrue(key2.equals(key1)); - - // Test transitivity - assertTrue(key1.equals(key2)); - assertTrue(key2.equals(key3)); - assertTrue(key1.equals(key3)); - - // Test consistency - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - } - - - /** - * Tests equality properties, reflexive, symmetric, transitive, consistent for SAE network. - */ - @Test - public void testEqualityRulesForSae() { - WifiConfiguration wifiConfiguration = - WifiConfigurationTestUtil.createSaeNetwork(); - ScanDetail scanDetail = createScanDetailForNetwork(wifiConfiguration, - "AC:AB:AD:AE:AF:FC"); - - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfiguration); - ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanDetail.getScanResult()); - ScanResultMatchInfo key3 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfiguration); - - // Test a.equals(a) - assertTrue(key1.equals(key1)); - - // Test if a.equals(b) then b.equals(a) - assertTrue(key1.equals(key2)); - assertTrue(key2.equals(key1)); - - // Test transitivity - assertTrue(key1.equals(key2)); - assertTrue(key2.equals(key3)); - assertTrue(key1.equals(key3)); - - // Test consistency - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - assertTrue(key1.equals(key2)); - } - - /** - * Tests that hashes of various configurations are equal - */ - @Test - public void testHashForTransitionMode() { - WifiConfiguration wifiConfigurationPsk = - WifiConfigurationTestUtil.createPskNetwork("\"Transition is Hard\""); - WifiConfiguration wifiConfigurationSae = - WifiConfigurationTestUtil.createSaeNetwork("\"Transition is Hard\""); - ScanDetail scanDetail = createScanDetailForWpa2Wpa3TransitionModeNetwork( - wifiConfigurationPsk, "AA:BB:CC:DD:CC:BB"); - - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationPsk); - ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanDetail.getScanResult()); - ScanResultMatchInfo key3 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationSae); - - // Assert that all hashes are equal - assertEquals(key1.hashCode(), key2.hashCode()); - assertEquals(key1.hashCode(), key3.hashCode()); - assertEquals(key2.hashCode(), key3.hashCode()); - } - - /** - * Creates a scan detail corresponding to the provided network and given BSSID - */ - private ScanDetail createScanDetailForNetwork( - WifiConfiguration configuration, String bssid) { - return WifiConfigurationTestUtil.createScanDetailForNetwork(configuration, bssid, -40, - 2402, 0, 0); - } - - /** - * Creates a scan detail corresponding to the provided network and given BSSID - */ - private ScanDetail createScanDetailForWpa2Wpa3TransitionModeNetwork( - WifiConfiguration configuration, String bssid) { - return WifiConfigurationTestUtil.createScanDetailForWpa2Wpa3TransitionModeNetwork( - configuration, bssid, -40, 2402, 0, 0); - } - - /** - * Tests equality properties for PSK to SAE upgrades - */ - @Test - public void testEqualityRulesForPskToSaeUpgrade() { - WifiConfiguration wifiConfigurationSae = - WifiConfigurationTestUtil.createSaeNetwork("\"Upgrade\""); - WifiConfiguration wifiConfigurationPsk = - WifiConfigurationTestUtil.createPskNetwork("\"Upgrade\""); - ScanDetail scanDetailSae = createScanDetailForNetwork(wifiConfigurationSae, - "AC:AB:AD:AE:AF:FC"); - - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationPsk); - ScanResultMatchInfo key2 = ScanResultMatchInfo - .fromScanResult(scanDetailSae.getScanResult()); - ScanResultMatchInfo key3 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationSae); - - // Test a.equals(a) - assertTrue(key1.matchForNetworkSelection(key1, true)); - - // Test if a.equals(b) then b.equals(a) - assertTrue(key1.matchForNetworkSelection(key2, true)); - assertTrue(key2.matchForNetworkSelection(key1, true)); - - // Test consistency - assertTrue(key1.matchForNetworkSelection(key2, true)); - assertTrue(key1.matchForNetworkSelection(key2, true)); - assertTrue(key1.matchForNetworkSelection(key2, true)); - assertTrue(key1.matchForNetworkSelection(key2, true)); - - // Test WifiConfiguration objects are not equal - assertFalse(key1.matchForNetworkSelection(key3, true)); - assertFalse(key3.matchForNetworkSelection(key1, true)); - } - - /** - * Tests equality properties for PSK to SAE upgrades when feature is disabled - */ - @Test - public void testEqualityRulesForPskToSaeUpgradeWithOverlayDisable() { - WifiConfiguration wifiConfigurationSae = - WifiConfigurationTestUtil.createSaeNetwork("\"Upgrade\""); - WifiConfiguration wifiConfigurationPsk = - WifiConfigurationTestUtil.createPskNetwork("\"Upgrade\""); - ScanDetail scanDetailSae = createScanDetailForNetwork(wifiConfigurationSae, - "AC:AB:AD:AE:AF:FC"); - - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationPsk); - ScanResultMatchInfo key2 = ScanResultMatchInfo - .fromScanResult(scanDetailSae.getScanResult()); - ScanResultMatchInfo key3 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationSae); - - // Test a.equals(a) - assertTrue(key1.matchForNetworkSelection(key1, false)); - - // Test if a.equals(b) then b.equals(a) - assertFalse(key1.matchForNetworkSelection(key2, false)); - assertFalse(key2.matchForNetworkSelection(key1, false)); - - // Test consistency - assertFalse(key1.matchForNetworkSelection(key2, false)); - assertFalse(key1.matchForNetworkSelection(key2, false)); - assertFalse(key1.matchForNetworkSelection(key2, false)); - assertFalse(key1.matchForNetworkSelection(key2, false)); - - // Test WifiConfiguration objects are not equal - assertFalse(key1.matchForNetworkSelection(key3, false)); - assertFalse(key3.matchForNetworkSelection(key1, false)); - } - /** - * Test that SAE saved network will never downgrade to a PSK AP (from scan result) - */ - @Test - public void testSaeToPskDoesNotDowngrade() { - WifiConfiguration wifiConfigurationSae = - WifiConfigurationTestUtil.createSaeNetwork("\"Downgrade\""); - WifiConfiguration wifiConfigurationPsk = - WifiConfigurationTestUtil.createPskNetwork("\"Downgrade\""); - ScanDetail scanDetailPsk = createScanDetailForNetwork(wifiConfigurationPsk, - "AC:AB:AD:AE:AF:FC"); - - ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(wifiConfigurationSae); - ScanResultMatchInfo key2 = ScanResultMatchInfo - .fromScanResult(scanDetailPsk.getScanResult()); - - // Test both a.equals(b) and b.equals(a) are false: - // i.e. SAE saved network will never downgrade to a PSK AP (from scan result) - assertFalse(key1.equals(key2)); - assertFalse(key2.equals(key1)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ScanResults.java b/tests/wifitests/src/com/android/server/wifi/ScanResults.java deleted file mode 100644 index 052b4dd2b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ScanResults.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import android.net.wifi.ScanResult; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiSsid; - -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.util.NativeUtil; - -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Random; - -/** - * Utility for creating scan results from a scan - */ -public class ScanResults { - private final ArrayList<ScanDetail> mScanDetails = new ArrayList<>(); - private final ScanData mScanData; - private final ScanData mRawScanData; - private final ScanResult[] mScanResults; - - private ScanResults(ArrayList<ScanDetail> scanDetails, ScanData scanData, - ScanResult[] scanResults) { - mScanDetails.addAll(scanDetails); - mScanData = scanData; - mRawScanData = scanData; - mScanResults = scanResults; - } - - /** - * Merge the results contained in a number of ScanResults into a single ScanResults - */ - public static ScanResults merge(int bandScanned, ScanResults... others) { - ArrayList<ScanDetail> scanDetails = new ArrayList<>(); - ArrayList<ScanResult> scanDataResults = new ArrayList<>(); - ArrayList<ScanResult> rawScanResults = new ArrayList<>(); - for (ScanResults other : others) { - scanDetails.addAll(other.getScanDetailArrayList()); - scanDataResults.addAll(Arrays.asList(other.getScanData().getResults())); - rawScanResults.addAll(Arrays.asList(other.getRawScanResults())); - } - Collections.sort(scanDataResults, SCAN_RESULT_RSSI_COMPARATOR); - int id = others[0].getScanData().getId(); - return new ScanResults(scanDetails, new ScanData(id, 0, 0, bandScanned, scanDataResults - .toArray(new ScanResult[scanDataResults.size()])), - rawScanResults.toArray(new ScanResult[rawScanResults.size()])); - } - - private static String generateBssid(Random r) { - return String.format("%02X:%02X:%02X:%02X:%02X:%02X", - r.nextInt(256), r.nextInt(256), r.nextInt(256), - r.nextInt(256), r.nextInt(256), r.nextInt(256)); - } - - public static final Comparator<ScanResult> SCAN_RESULT_RSSI_COMPARATOR = - new Comparator<ScanResult>() { - public int compare(ScanResult r1, ScanResult r2) { - return r2.level - r1.level; - } - }; - - public static ScanResult.InformationElement generateSsidIe(String ssid) { - ScanResult.InformationElement ie = new ScanResult.InformationElement(); - ie.id = ScanResult.InformationElement.EID_SSID; - ie.bytes = ssid.getBytes(Charset.forName("UTF-8")); - return ie; - } - - public static byte[] generateIERawDatafromScanResultIE(ScanResult.InformationElement[] ies) { - ArrayList<Byte> ieRawData = new ArrayList<>(); - for (int i = 0; i < ies.length; i++) { - if (ies[i].id > 255 || ies[i].bytes.length > 255) { - break; - } - ieRawData.add(BigInteger.valueOf(ies[i].id).toByteArray()[0]); - ieRawData.add(BigInteger.valueOf(ies[i].bytes.length).toByteArray()[0]); - for (int j = 0; j < ies[i].bytes.length; j++) { - ieRawData.add(ies[i].bytes[j]); - } - } - return NativeUtil.byteArrayFromArrayList(ieRawData); - } - - /** - * Generates an array of random ScanDetails with the given frequencies, seeded by the provided - * seed value and test method name and class (annotated with @Test). This method will be - * consistent between calls in the same test across runs. - * - * @param seed combined with a hash of the test method this seeds the random number generator - * @param freqs list of frequencies for the generated scan results, these will map 1 to 1 to - * to the returned scan details. Duplicates can be specified to create multiple - * ScanDetails with the same frequency. - */ - private static ScanDetail[] generateNativeResults(boolean needIE, int seed, int... freqs) { - ScanDetail[] results = new ScanDetail[freqs.length]; - // Seed the results based on the provided seed as well as the test method name - // This provides more varied scan results between individual tests that are very similar. - Random r = new Random(seed + WifiTestUtil.getTestMethod().hashCode()); - for (int i = 0; i < freqs.length; ++i) { - int freq = freqs[i]; - String ssid = new BigInteger(128, r).toString(36); - String bssid = generateBssid(r); - int rssi = r.nextInt(40) - 99; // -99 to -60 - ScanResult.InformationElement[] ie; - if (needIE) { - ie = new ScanResult.InformationElement[1]; - ie[0] = generateSsidIe(ssid); - } else { - ie = new ScanResult.InformationElement[0]; - } - List<String> anqpLines = new ArrayList<>(); - NetworkDetail nd = new NetworkDetail(bssid, ie, anqpLines, freq); - ScanDetail detail = new ScanDetail(nd, WifiSsid.createFromAsciiEncoded(ssid), - bssid, "", rssi, freq, - Long.MAX_VALUE, /* needed so that scan results aren't rejected because - they are older than scan start */ - ie, anqpLines, generateIERawDatafromScanResultIE(ie)); - results[i] = detail; - } - return results; - } - - /** - * Create scan results with no IE information. - */ - public static ScanDetail[] generateNativeResults(int seed, int... freqs) { - return generateNativeResults(true, seed, freqs); - } - - /** - * Create a ScanResults with randomly generated results seeded by the id. - * @see #generateNativeResults for more details on how results are generated - */ - public static ScanResults create(int id, int bandScanned, int... freqs) { - return create(id, bandScanned, generateNativeResults(id, freqs)); - } - - public static ScanResults create(int id, int bandScanned, - ScanDetail... nativeResults) { - return new ScanResults(id, bandScanned, -1, nativeResults); - } - - /** - * Create scan results that contain all results for the native results and - * full scan results, but limits the number of onResults results after sorting - * by RSSI - */ - public static ScanResults createOverflowing(int id, int bandScanned, int maxResults, - ScanDetail... nativeResults) { - return new ScanResults(id, bandScanned, maxResults, nativeResults); - } - - private ScanResults(int id, int bandScanned, int maxResults, ScanDetail... nativeResults) { - mScanResults = new ScanResult[nativeResults.length]; - for (int i = 0; i < nativeResults.length; ++i) { - mScanDetails.add(nativeResults[i]); - mScanResults[i] = nativeResults[i].getScanResult(); - } - ScanResult[] sortedScanResults = Arrays.copyOf(mScanResults, mScanResults.length); - Arrays.sort(sortedScanResults, SCAN_RESULT_RSSI_COMPARATOR); - mRawScanData = new ScanData(id, 0, 0, bandScanned, sortedScanResults); - if (maxResults == -1) { - mScanData = mRawScanData; - } else { - ScanResult[] reducedScanResults = Arrays.copyOf(sortedScanResults, - Math.min(sortedScanResults.length, maxResults)); - mScanData = new ScanData(id, 0, 0, bandScanned, reducedScanResults); - } - } - - public ArrayList<ScanDetail> getScanDetailArrayList() { - return mScanDetails; - } - - public ScanData getScanData() { - return mScanData; - } - - public ScanResult[] getRawScanResults() { - return mScanResults; - } - - public ScanData getRawScanData() { - return mRawScanData; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java b/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java deleted file mode 100644 index f3d834866..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import static org.junit.Assert.*; -import static org.junit.Assume.*; -import static org.mockito.Mockito.*; - -import android.net.wifi.ScanResult; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiSsid; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeDiagnosingMatcher; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * Utilities for testing Wifi Scanning - */ -public class ScanTestUtil { - - public static void setupMockChannels(WifiNative wifiNative, int[] channels24, int[] channels5, - int[] channelsDfs, int[] channels6) throws Exception { - when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ)) - .thenReturn(channels24); - when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)) - .thenReturn(channels5); - when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY)) - .thenReturn(channelsDfs); - when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ)) - .thenReturn(channels6); - } - - public static WifiScanner.ScanSettings createRequest(WifiScanner.ChannelSpec[] channels, - int period, int batch, int bssidsPerScan, int reportEvents) { - WifiScanner.ScanSettings request = new WifiScanner.ScanSettings(); - request.band = WifiScanner.WIFI_BAND_UNSPECIFIED; - request.channels = channels; - request.periodInMs = period; - request.numBssidsPerScan = bssidsPerScan; - request.maxScansToCache = batch; - request.reportEvents = reportEvents; - return request; - } - - public static WifiScanner.ScanSettings createRequest(int type, int band, int period, int batch, - int bssidsPerScan, int reportEvents) { - return createRequest(WifiScanner.SCAN_TYPE_HIGH_ACCURACY, band, period, 0, 0, - batch, bssidsPerScan, reportEvents); - } - - public static WifiScanner.ScanSettings createRequest(int band, int period, int batch, - int bssidsPerScan, int reportEvents) { - return createRequest(WifiScanner.SCAN_TYPE_HIGH_ACCURACY, band, period, 0, 0, batch, - bssidsPerScan, reportEvents); - } - - /** - * Create an exponential back off scan request if maxPeriod != period && maxPeriod != 0. - */ - public static WifiScanner.ScanSettings createRequest(int type, int band, int period, - int maxPeriod, int stepCount, int batch, int bssidsPerScan, int reportEvents) { - WifiScanner.ScanSettings request = new WifiScanner.ScanSettings(); - request.type = type; - request.band = band; - request.channels = null; - request.periodInMs = period; - request.maxPeriodInMs = maxPeriod; - request.stepCount = stepCount; - request.numBssidsPerScan = bssidsPerScan; - request.maxScansToCache = batch; - request.reportEvents = reportEvents; - return request; - } - - /** - * Builder to create WifiNative.ScanSettings objects for testing - */ - public static class NativeScanSettingsBuilder { - private final WifiNative.ScanSettings mSettings = new WifiNative.ScanSettings(); - public NativeScanSettingsBuilder() { - mSettings.scanType = WifiScanner.SCAN_TYPE_LOW_LATENCY; - mSettings.buckets = new WifiNative.BucketSettings[0]; - mSettings.num_buckets = 0; - mSettings.report_threshold_percent = 100; - } - - public NativeScanSettingsBuilder withType(int type) { - mSettings.scanType = type; - return this; - } - public NativeScanSettingsBuilder withBasePeriod(int basePeriod) { - mSettings.base_period_ms = basePeriod; - return this; - } - public NativeScanSettingsBuilder withMaxApPerScan(int maxAp) { - mSettings.max_ap_per_scan = maxAp; - return this; - } - public NativeScanSettingsBuilder withMaxScansToCache(int maxScans) { - mSettings.report_threshold_num_scans = maxScans; - return this; - } - public NativeScanSettingsBuilder withMaxPercentToCache(int percent) { - mSettings.report_threshold_percent = percent; - return this; - } - - /** - * Add the provided hidden network SSIDs to scan request. - * @param networkSSIDs List of hidden network SSIDs - * @return builder object - */ - public NativeScanSettingsBuilder withHiddenNetworkSSIDs(String[] networkSSIDs) { - mSettings.hiddenNetworks = new WifiNative.HiddenNetwork[networkSSIDs.length]; - for (int i = 0; i < networkSSIDs.length; i++) { - mSettings.hiddenNetworks[i] = new WifiNative.HiddenNetwork(); - mSettings.hiddenNetworks[i].ssid = networkSSIDs[i]; - } - return this; - } - - public NativeScanSettingsBuilder addBucketWithBand( - int period, int reportEvents, int band) { - WifiNative.BucketSettings bucket = new WifiNative.BucketSettings(); - bucket.bucket = mSettings.num_buckets; - bucket.band = band; - bucket.period_ms = period; - bucket.report_events = reportEvents; - return addBucket(bucket); - } - - public NativeScanSettingsBuilder addBucketWithChannels( - int period, int reportEvents, WifiScanner.ChannelSpec... channels) { - int[] channelFreqs = new int[channels.length]; - for (int i = 0; i < channels.length; ++i) { - channelFreqs[i] = channels[i].frequency; - } - return addBucketWithChannels(period, reportEvents, channelFreqs); - } - - public NativeScanSettingsBuilder addBucketWithChannels( - int period, int reportEvents, int... channels) { - WifiNative.BucketSettings bucket = new WifiNative.BucketSettings(); - bucket.bucket = mSettings.num_buckets; - bucket.band = WifiScanner.WIFI_BAND_UNSPECIFIED; - bucket.num_channels = channels.length; - bucket.channels = channelsToNativeSettings(channels); - bucket.period_ms = period; - bucket.report_events = reportEvents; - return addBucket(bucket); - } - - public NativeScanSettingsBuilder addBucket(WifiNative.BucketSettings bucket) { - mSettings.buckets = Arrays.copyOf(mSettings.buckets, mSettings.num_buckets + 1); - mSettings.buckets[mSettings.num_buckets] = bucket; - mSettings.num_buckets = mSettings.num_buckets + 1; - return this; - } - - public WifiNative.ScanSettings build() { - return mSettings; - } - - } - - /** - * Compute the expected native scan settings that are expected for the given - * WifiScanner.ScanSettings. - */ - public static WifiNative.ScanSettings computeSingleScanNativeSettings( - WifiScanner.ScanSettings requestSettings) { - int reportEvents = requestSettings.reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - NativeScanSettingsBuilder builder = new NativeScanSettingsBuilder() - .withBasePeriod(0) - .withMaxApPerScan(0) - .withMaxPercentToCache(0) - .withMaxScansToCache(0) - .withType(requestSettings.type); - if (requestSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - builder.addBucketWithChannels(0, reportEvents, requestSettings.channels); - } else { - builder.addBucketWithBand(0, reportEvents, requestSettings.band); - } - - return builder.build(); - } - - /** - * Compute the expected native scan settings that are expected for the given channels. - */ - public static WifiNative.ScanSettings createSingleScanNativeSettingsForChannels( - int reportEvents, WifiScanner.ChannelSpec... channels) { - return createSingleScanNativeSettingsForChannels( - WifiScanner.SCAN_TYPE_LOW_LATENCY, reportEvents, channels); - } - - /** - * Compute the expected native scan settings that are expected for the given channels & type. - */ - public static WifiNative.ScanSettings createSingleScanNativeSettingsForChannels( - int nativeScanType, int reportEvents, WifiScanner.ChannelSpec... channels) { - int actualReportEvents = reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - return new NativeScanSettingsBuilder() - .withBasePeriod(0) - .withMaxApPerScan(0) - .withMaxPercentToCache(0) - .withMaxScansToCache(0) - .addBucketWithChannels(0, actualReportEvents, channels) - .withType(nativeScanType) - .build(); - } - - public static Set<Integer> createFreqSet(int... elements) { - Set<Integer> set = new HashSet<>(); - for (int e : elements) { - set.add(e); - } - return set; - } - - public static ScanResult createScanResult(int freq) { - return new ScanResult(WifiSsid.createFromAsciiEncoded("AN SSID"), "00:00:00:00:00:00", 0L, - -1, null, "", 0, freq, 0); - } - - private static ScanData createScanData(int[] freqs, int bucketsScanned, int bandScanned) { - ScanResult[] results = new ScanResult[freqs.length]; - for (int i = 0; i < freqs.length; ++i) { - results[i] = createScanResult(freqs[i]); - } - return new ScanData(0, 0, bucketsScanned, bandScanned, results); - } - - private static ScanData createScanData(int[] freqs, int bucketsScanned) { - return createScanData(freqs, bucketsScanned, WifiScanner.WIFI_BAND_UNSPECIFIED); - } - - public static ScanData[] createScanDatas( - int[][] freqs, int[] bucketsScanned, int[] bandsScanned) { - assumeTrue(freqs.length == bucketsScanned.length); - assumeTrue(freqs.length == bandsScanned.length); - ScanData[] data = new ScanData[freqs.length]; - for (int i = 0; i < freqs.length; ++i) { - data[i] = createScanData(freqs[i], bucketsScanned[i], bandsScanned[i]); - } - return data; - } - - public static ScanData[] createScanDatas(int[][] freqs, int[] bucketsScanned) { - assumeTrue(freqs.length == bucketsScanned.length); - ScanData[] data = new ScanData[freqs.length]; - for (int i = 0; i < freqs.length; ++i) { - data[i] = createScanData(freqs[i], bucketsScanned[i]); - } - return data; - } - - public static ScanData[] createScanDatas(int[][] freqs) { - return createScanDatas(freqs, new int[freqs.length] /* defaults all 0 */); - } - - private static void assertScanResultEquals( - String prefix, ScanResult expected, ScanResult actual) { - assertEquals(prefix + "SSID", expected.SSID, actual.SSID); - assertEquals(prefix + "wifiSsid", expected.wifiSsid.toString(), actual.wifiSsid.toString()); - assertEquals(prefix + "BSSID", expected.BSSID, actual.BSSID); - assertEquals(prefix + "capabilities", expected.capabilities, actual.capabilities); - assertEquals(prefix + "level", expected.level, actual.level); - assertEquals(prefix + "frequency", expected.frequency, actual.frequency); - assertEquals(prefix + "timestamp", expected.timestamp, actual.timestamp); - assertEquals(prefix + "seen", expected.seen, actual.seen); - } - - private static void assertScanResultsEquals(String prefix, ScanResult[] expected, - ScanResult[] actual) { - assertNotNull(prefix + "expected ScanResults was null", expected); - assertNotNull(prefix + "actual ScanResults was null", actual); - assertEquals(prefix + "results.length", expected.length, actual.length); - for (int j = 0; j < expected.length; ++j) { - ScanResult expectedResult = expected[j]; - ScanResult actualResult = actual[j]; - assertScanResultEquals(prefix + "results[" + j + "]", actualResult, expectedResult); - } - } - - /** - * Asserts if the provided scan results are the same. - */ - public static void assertScanResultEquals(ScanResult expected, ScanResult actual) { - assertScanResultEquals("", expected, actual); - } - - /** - * Asserts if the provided scan result arrays are the same. - */ - public static void assertScanResultsEquals(ScanResult[] expected, ScanResult[] actual) { - assertScanResultsEquals("", expected, actual); - } - - private static void assertScanDataEquals(String prefix, ScanData expected, ScanData actual) { - assertNotNull(prefix + "expected ScanData was null", expected); - assertNotNull(prefix + "actual ScanData was null", actual); - assertEquals(prefix + "id", expected.getId(), actual.getId()); - assertEquals(prefix + "flags", expected.getFlags(), actual.getFlags()); - assertEquals(prefix + "band", expected.getBandScanned(), - actual.getBandScanned()); - assertScanResultsEquals(prefix, expected.getResults(), actual.getResults()); - } - - public static void assertScanDataEquals(ScanData expected, ScanData actual) { - assertScanDataEquals("", expected, actual); - } - - public static void assertScanDatasEquals(String prefix, ScanData[] expected, ScanData[] actual) { - assertNotNull("expected " + prefix + "ScanData[] was null", expected); - assertNotNull("actaul " + prefix + "ScanData[] was null", actual); - assertEquals(prefix + "ScanData.length", expected.length, actual.length); - for (int i = 0; i < expected.length; ++i) { - assertScanDataEquals(prefix + "ScanData[" + i + "].", expected[i], actual[i]); - } - } - - public static void assertScanDatasEquals(ScanData[] expected, ScanData[] actual) { - assertScanDatasEquals("", expected, actual); - } - - public static WifiScanner.ChannelSpec[] channelsToSpec(int... channels) { - WifiScanner.ChannelSpec[] channelSpecs = new WifiScanner.ChannelSpec[channels.length]; - for (int i = 0; i < channels.length; ++i) { - channelSpecs[i] = new WifiScanner.ChannelSpec(channels[i]); - } - return channelSpecs; - } - - public static void assertNativeScanSettingsEquals(WifiNative.ScanSettings expected, - WifiNative.ScanSettings actual) { - assertEquals("scan type", expected.scanType, actual.scanType); - assertEquals("bssids per scan", expected.max_ap_per_scan, actual.max_ap_per_scan); - assertEquals("scans to cache", expected.report_threshold_num_scans, - actual.report_threshold_num_scans); - assertEquals("percent to cache", expected.report_threshold_percent, - actual.report_threshold_percent); - assertEquals("base period", expected.base_period_ms, actual.base_period_ms); - - assertEquals("number of buckets", expected.num_buckets, actual.num_buckets); - assertNotNull("buckets was null", actual.buckets); - for (int i = 0; i < expected.buckets.length; ++i) { - assertNotNull("buckets[" + i + "] was null", actual.buckets[i]); - assertEquals("buckets[" + i + "].period", - expected.buckets[i].period_ms, actual.buckets[i].period_ms); - assertEquals("buckets[" + i + "].reportEvents", - expected.buckets[i].report_events, actual.buckets[i].report_events); - - assertEquals("buckets[" + i + "].band", - expected.buckets[i].band, actual.buckets[i].band); - if (expected.buckets[i].band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - Set<Integer> expectedChannels = new HashSet<>(); - for (WifiNative.ChannelSettings channel : expected.buckets[i].channels) { - expectedChannels.add(channel.frequency); - } - Set<Integer> actualChannels = new HashSet<>(); - for (WifiNative.ChannelSettings channel : actual.buckets[i].channels) { - actualChannels.add(channel.frequency); - } - assertEquals("channels", expectedChannels, actualChannels); - } else { - // since num_channels and channels are ignored when band is not - // WifiScanner.WIFI_BAND_UNSPECIFIED just assert that there are no channels - // the band equality was already checked above - assertEquals("buckets[" + i + "].num_channels not 0", 0, - actual.buckets[i].num_channels); - assertTrue("buckets[" + i + "].channels not null or empty", - actual.buckets[i].channels == null - || actual.buckets[i].channels.length == 0); - } - } - } - - /** - * Asserts if the provided pno settings are the same. - */ - public static void assertNativePnoSettingsEquals(WifiNative.PnoSettings expected, - WifiNative.PnoSettings actual) { - assertNotNull("expected was null", expected); - assertNotNull("actaul was null", actual); - assertEquals("min5GHzRssi", expected.min5GHzRssi, actual.min5GHzRssi); - assertEquals("min24GHzRssi", expected.min24GHzRssi, actual.min24GHzRssi); - assertEquals("min6GHzRssi", expected.min6GHzRssi, actual.min6GHzRssi); - assertEquals("isConnected", expected.isConnected, actual.isConnected); - assertNotNull("expected networkList was null", expected.networkList); - assertNotNull("actual networkList was null", actual.networkList); - assertEquals("networkList.length", expected.networkList.length, actual.networkList.length); - for (int i = 0; i < expected.networkList.length; i++) { - assertEquals("networkList[" + i + "].ssid", - expected.networkList[i].ssid, actual.networkList[i].ssid); - assertEquals("networkList[" + i + "].flags", - expected.networkList[i].flags, actual.networkList[i].flags); - assertEquals("networkList[" + i + "].auth_bit_field", - expected.networkList[i].auth_bit_field, actual.networkList[i].auth_bit_field); - } - } - - /** - * Convert a list of channel frequencies to an array of equivalent WifiNative.ChannelSettings - */ - public static WifiNative.ChannelSettings[] channelsToNativeSettings(int... channels) { - WifiNative.ChannelSettings[] channelSpecs = new WifiNative.ChannelSettings[channels.length]; - for (int i = 0; i < channels.length; ++i) { - channelSpecs[i] = new WifiNative.ChannelSettings(); - channelSpecs[i].frequency = channels[i]; - } - return channelSpecs; - } - - /** - * Matcher to check that a BucketSettings has the given band - */ - public static Matcher<WifiNative.BucketSettings> bandIs(final int expectedBand) { - return new TypeSafeDiagnosingMatcher<WifiNative.BucketSettings>() { - @Override - public boolean matchesSafely(WifiNative.BucketSettings bucketSettings, - Description mismatchDescription) { - if (bucketSettings.band != expectedBand) { - mismatchDescription - .appendText("did not have expected band ").appendValue(expectedBand) - .appendText(", was ").appendValue(bucketSettings.band); - return false; - } else { - return true; - } - } - - @Override - public void describeTo(final Description description) { - description.appendText("bucket band is ").appendValue(expectedBand); - } - }; - } - - /** - * Matcher to check that a BucketSettings has exactly the given channels - */ - public static Matcher<WifiNative.BucketSettings> channelsAre(final int... expectedChannels) { - return new TypeSafeDiagnosingMatcher<WifiNative.BucketSettings>() { - @Override - public boolean matchesSafely(WifiNative.BucketSettings bucketSettings, - Description mismatchDescription) { - if (bucketSettings.band != WifiScanner.WIFI_BAND_UNSPECIFIED) { - mismatchDescription.appendText("did not have expected unspecified band, was ") - .appendValue(bucketSettings.band); - return false; - } else if (bucketSettings.num_channels != expectedChannels.length) { - mismatchDescription - .appendText("did not have expected num_channels ") - .appendValue(expectedChannels.length) - .appendText(", was ").appendValue(bucketSettings.num_channels); - return false; - } else if (bucketSettings.channels == null) { - mismatchDescription.appendText("had null channels array"); - return false; - } else if (bucketSettings.channels.length != expectedChannels.length) { - mismatchDescription - .appendText("did not have channels array length matching excepted ") - .appendValue(expectedChannels.length) - .appendText(", was ").appendValue(bucketSettings.channels.length); - return false; - } else { - Set<Integer> foundChannelsSet = new HashSet<>(); - for (int i = 0; i < bucketSettings.channels.length; ++i) { - foundChannelsSet.add(bucketSettings.channels[i].frequency); - } - Set<Integer> expectedChannelsSet = new HashSet<>(); - for (int i = 0; i < expectedChannels.length; ++i) { - expectedChannelsSet.add(expectedChannels[i]); - } - - if (!foundChannelsSet.containsAll(expectedChannelsSet) - || foundChannelsSet.size() != expectedChannelsSet.size()) { - Set<Integer> extraChannelsSet = new HashSet<>(foundChannelsSet); - extraChannelsSet.removeAll(expectedChannelsSet); - expectedChannelsSet.removeAll(foundChannelsSet); - mismatchDescription - .appendText("does not contain expected channels ") - .appendValue(expectedChannelsSet); - if (extraChannelsSet.size() > 0) { - mismatchDescription - .appendText(", but contains extra channels ") - .appendValue(extraChannelsSet); - } - return false; - } else { - return true; - } - } - } - - @Override - public void describeTo(final Description description) { - description.appendText("bucket channels are ").appendValue(expectedChannels); - } - }; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ScoredNetworkNominatorTest.java b/tests/wifitests/src/com/android/server/wifi/ScoredNetworkNominatorTest.java deleted file mode 100644 index c9cad7dc5..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ScoredNetworkNominatorTest.java +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static com.android.server.wifi.ScoredNetworkNominator.SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE; -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE; -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.database.ContentObserver; -import android.net.NetworkKey; -import android.net.NetworkScoreManager; -import android.net.Uri; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.os.Handler; -import android.os.Looper; -import android.os.SystemClock; -import android.util.LocalLog; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiNetworkSelector.NetworkNominator.OnConnectableListener; -import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Unit tests for {@link ScoredNetworkNominator}. - */ -@SmallTest -public class ScoredNetworkNominatorTest extends WifiBaseTest { - private static final String TEST_PACKAGE_NAME = "name.package.test"; - private static final int TEST_UID = 12345; - private ContentObserver mContentObserver; - private int mThresholdQualifiedRssi2G; - private int mThresholdQualifiedRssi5G; - - @Mock private Context mContext; - @Mock private Clock mClock; - @Mock private FrameworkFacade mFrameworkFacade; - @Mock private NetworkScoreManager mNetworkScoreManager; - @Mock private PackageManager mPackageManager; - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private WifiPermissionsUtil mWifiPermissionsUtil; - @Mock private OnConnectableListener mOnConnectableListener; - @Captor private ArgumentCaptor<Collection<NetworkKey>> mNetworkKeyCollectionCaptor; - @Captor private ArgumentCaptor<WifiConfiguration> mWifiConfigCaptor; - - private WifiNetworkScoreCache mScoreCache; - private ScoredNetworkNominator mScoredNetworkNominator; - - @Before - public void setUp() throws Exception { - mThresholdQualifiedRssi2G = -73; - mThresholdQualifiedRssi5G = -70; - - MockitoAnnotations.initMocks(this); - - when(mFrameworkFacade.getStringSetting(mContext, - SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE)) - .thenReturn("test"); - ApplicationInfo appInfo = new ApplicationInfo(); - appInfo.uid = TEST_UID; - when(mPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME), anyInt())) - .thenReturn(appInfo); - when(mNetworkScoreManager.getActiveScorerPackage()) - .thenReturn(TEST_PACKAGE_NAME); - - ArgumentCaptor<ContentObserver> observerCaptor = - ArgumentCaptor.forClass(ContentObserver.class); - mScoreCache = new WifiNetworkScoreCache(mContext); - mScoredNetworkNominator = new ScoredNetworkNominator(mContext, - new Handler(Looper.getMainLooper()), mFrameworkFacade, mNetworkScoreManager, - mPackageManager, mWifiConfigManager, new LocalLog(0), mScoreCache, - mWifiPermissionsUtil); - verify(mFrameworkFacade).registerContentObserver(eq(mContext), any(Uri.class), eq(false), - observerCaptor.capture()); - mContentObserver = observerCaptor.getValue(); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); - } - - @After - public void tearDown() { - validateMockitoUsage(); - } - - @Test - public void testUpdate_recommendationsDisabled() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - String[] caps = {"[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdQualifiedRssi2G + 8}; - int[] securities = {SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = WifiNetworkSelectorTestUtil - .setupScanDetailsAndConfigStore( - ssids, bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock); - - when(mFrameworkFacade.getStringSetting(mContext, - SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE)) - .thenReturn(null); - - mContentObserver.onChange(false /* unused */); - - mScoredNetworkNominator.update(scanDetailsAndConfigs.getScanDetails()); - - verifyZeroInteractions(mNetworkScoreManager); - } - - @Test - public void testUpdate_emptyScanList() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2470}; - String[] caps = {"[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdQualifiedRssi2G + 8}; - int[] securities = {SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = WifiNetworkSelectorTestUtil - .setupScanDetailsAndConfigStore( - ssids, bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock); - - mScoredNetworkNominator.update(new ArrayList<ScanDetail>()); - - verifyZeroInteractions(mNetworkScoreManager); - } - - @Test - public void testUpdate_allNetworksUnscored() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-PSK][ESS]", "[ESS]"}; - int[] securities = {SECURITY_PSK, SECURITY_NONE}; - int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = WifiNetworkSelectorTestUtil - .setupScanDetailsAndConfigStore( - ssids, bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock); - - mScoredNetworkNominator.update(scanDetailsAndConfigs.getScanDetails()); - - verify(mNetworkScoreManager).requestScores(mNetworkKeyCollectionCaptor.capture()); - NetworkKey[] requestedScores = - mNetworkKeyCollectionCaptor.getValue().toArray(new NetworkKey[0]); - assertEquals(2, requestedScores.length); - NetworkKey expectedNetworkKey = NetworkKey.createFromScanResult( - scanDetailsAndConfigs.getScanDetails().get(0).getScanResult()); - assertEquals(expectedNetworkKey, requestedScores[0]); - expectedNetworkKey = NetworkKey.createFromScanResult( - scanDetailsAndConfigs.getScanDetails().get(1).getScanResult()); - assertEquals(expectedNetworkKey, requestedScores[1]); - } - - @Test - public void testUpdate_oneScored_oneUnscored() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-PSK][ESS]", "[ESS]"}; - int[] securities = {SECURITY_PSK, SECURITY_NONE}; - int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = WifiNetworkSelectorTestUtil - .setupScanDetailsAndConfigStore( - ssids, bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock); - - List<ScanDetail> scoredScanDetails = scanDetailsAndConfigs.getScanDetails().subList(0, 1); - Integer[] scores = {120}; - boolean[] meteredHints = {true}; - WifiNetworkSelectorTestUtil.configureScoreCache( - mScoreCache, scoredScanDetails, scores, meteredHints); - - mScoredNetworkNominator.update(scanDetailsAndConfigs.getScanDetails()); - - verify(mNetworkScoreManager).requestScores(mNetworkKeyCollectionCaptor.capture()); - - NetworkKey[] requestedScores = - mNetworkKeyCollectionCaptor.getValue().toArray(new NetworkKey[0]); - assertEquals(1, requestedScores.length); - NetworkKey expectedNetworkKey = NetworkKey.createFromScanResult( - scanDetailsAndConfigs.getScanDetails().get(1).getScanResult()); - assertEquals(expectedNetworkKey, requestedScores[0]); - } - - @Test - public void testEvaluateNetworks_recommendationsDisabled() { - when(mFrameworkFacade.getStringSetting(mContext, - SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE)) - .thenReturn(null); - - mContentObserver.onChange(false /* unused */); - - mScoredNetworkNominator.nominateNetworks(null, null, null, false, false, - mOnConnectableListener); - - verifyZeroInteractions(mWifiConfigManager, mNetworkScoreManager); - } - - @Test - public void testUpdate_externalScorerNotPermittedToSeeScanResults() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-PSK][ESS]", "[ESS]"}; - int[] securities = {SECURITY_PSK, SECURITY_NONE}; - int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10}; - - doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( - any(), any(), anyInt(), any()); - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = WifiNetworkSelectorTestUtil - .setupScanDetailsAndConfigStore( - ssids, bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock); - - mScoredNetworkNominator.update(scanDetailsAndConfigs.getScanDetails()); - - verify(mNetworkScoreManager, never()).requestScores(anyCollection()); - verify(mWifiPermissionsUtil).enforceCanAccessScanResults( - eq(TEST_PACKAGE_NAME), eq(null), eq(TEST_UID), nullable(String.class)); - } - - @Test - public void testUpdate_externalScorerNotPermittedToSeeScanResultsWithException() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-PSK][ESS]", "[ESS]"}; - int[] securities = {SECURITY_PSK, SECURITY_NONE}; - int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10}; - - doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( - any(), any(), anyInt(), any()); - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = WifiNetworkSelectorTestUtil - .setupScanDetailsAndConfigStore( - ssids, bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock); - - mScoredNetworkNominator.update(scanDetailsAndConfigs.getScanDetails()); - - verify(mNetworkScoreManager, never()).requestScores(anyCollection()); - verify(mWifiPermissionsUtil).enforceCanAccessScanResults( - eq(TEST_PACKAGE_NAME), eq(null), eq(TEST_UID), nullable(String.class)); - } - - /** - * When we have created a new ephemeral network, make sure that mOnConnectableListener - * is called. - */ - @Test - public void testEvaluateNetworks_newEphemeralNetworkMustBeReportedAsConnectable() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-PSK][ESS]", "[ESS]"}; - int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10}; - Integer[] scores = {null, 120}; - boolean[] meteredHints = {false, false}; - List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( - ssids, bssids, freqs, caps, levels, mClock); - WifiNetworkSelectorTestUtil.configureScoreCache(mScoreCache, - scanDetails, scores, meteredHints); - ScanResult scanResult = scanDetails.get(1).getScanResult(); - WifiConfiguration ephemeralNetworkConfig = WifiNetworkSelectorTestUtil - .setupEphemeralNetwork(mWifiConfigManager, 1, scanDetails.get(1), meteredHints[1]); - // No saved networks. - when(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(any(ScanDetail.class))) - .thenReturn(null); - // But when we create one, this is should be it. - when(mWifiConfigManager.addOrUpdateNetwork(any(), eq(TEST_UID), eq(TEST_PACKAGE_NAME))) - .thenReturn(new NetworkUpdateResult(1)); - // Untrusted networks allowed. - mScoredNetworkNominator.nominateNetworks(scanDetails, - null, null, false, true, mOnConnectableListener); - verify(mOnConnectableListener, atLeastOnce()) - .onConnectable(any(), mWifiConfigCaptor.capture()); - assertTrue(mWifiConfigCaptor.getAllValues().stream() - .anyMatch(c -> c.networkId == ephemeralNetworkConfig.networkId)); - } - - /** - * Don't choose available ephemeral networks if no saved networks and untrusted networks - * are not allowed. - */ - @Test - public void testEvaluateNetworks_noEphemeralNetworkWhenUntrustedNetworksNotAllowed() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-PSK][ESS]", "[ESS]"}; - int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10}; - Integer[] scores = {null, 120}; - boolean[] meteredHints = {false, true}; - - List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( - ssids, bssids, freqs, caps, levels, mClock); - WifiNetworkSelectorTestUtil.configureScoreCache(mScoreCache, - scanDetails, scores, meteredHints); - - // No saved networks. - when(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(any(ScanDetail.class))) - .thenReturn(null); - - WifiNetworkSelectorTestUtil.setupEphemeralNetwork( - mWifiConfigManager, 1, scanDetails.get(1), meteredHints[1]); - - // Untrusted networks not allowed. - mScoredNetworkNominator.nominateNetworks(scanDetails, - null, null, false, false, mOnConnectableListener); - - verify(mOnConnectableListener, never()).onConnectable(any(), any()); - } - - /** - * Choose externally scored saved network. - */ - @Test - public void testEvaluateNetworks_chooseSavedNetworkWithExternalScore() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {5200}; - String[] caps = {"[WPA2-PSK][ESS]"}; - int[] securities = {SECURITY_PSK}; - int[] levels = {mThresholdQualifiedRssi5G + 8}; - Integer[] scores = {120}; - boolean[] meteredHints = {false}; - - WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - savedConfigs[0].useExternalScores = true; - - WifiNetworkSelectorTestUtil.configureScoreCache(mScoreCache, - scanDetails, scores, meteredHints); - - mScoredNetworkNominator.nominateNetworks(scanDetails, - null, null, false, true, mOnConnectableListener); - - verify(mOnConnectableListener).onConnectable(any(), mWifiConfigCaptor.capture()); - assertEquals(mWifiConfigCaptor.getValue().networkId, savedConfigs[0].networkId); - } - - /** - * Prefer externally scored saved network over untrusted network when they have - * the same score. - */ - @Test - public void testEvaluateNetworks_nullScoredNetworks() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2470, 2437}; - String[] caps = {"[WPA2-PSK][ESS]", "[ESS]"}; - int[] securities = {SECURITY_PSK, SECURITY_NONE}; - int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 8}; - Integer[] scores = {null, null}; - boolean[] meteredHints = {false, true}; - - WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - savedConfigs[0].useExternalScores = true; - - WifiNetworkSelectorTestUtil.configureScoreCache(mScoreCache, - scanDetails, scores, meteredHints); - - mScoredNetworkNominator.nominateNetworks(scanDetails, - null, null, false, true, mOnConnectableListener); - - verify(mOnConnectableListener).onConnectable(any(), mWifiConfigCaptor.capture()); - assertEquals(mWifiConfigCaptor.getValue().networkId, savedConfigs[0].networkId); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ScoringParamsTest.java b/tests/wifitests/src/com/android/server/wifi/ScoringParamsTest.java deleted file mode 100644 index bea0a1af6..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ScoringParamsTest.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.res.Resources; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiInfo; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -/** - * Unit tests for {@link com.android.server.wifi.ScoringParams}. - */ -@SmallTest -public class ScoringParamsTest extends WifiBaseTest { - - private static final String EXPECTED_DEFAULTS = - "rssi2=-83:-80:-73:-60,rssi5=-80:-77:-70:-57,rssi6=-80:-77:-70:-57," - + "pps=0:1:100,horizon=15,nud=8,expid=0"; - - private ScoringParams mScoringParams; - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - setUpResources(mResources); - when(mContext.getResources()).thenReturn(mResources); - mScoringParams = new ScoringParams(); - } - - /** - * Check that thresholds are properly ordered, and in range. - */ - private void checkThresholds(int frequency) { - assertTrue(-127 < mScoringParams.getExitRssi(frequency)); - assertTrue(mScoringParams.getExitRssi(frequency) - <= mScoringParams.getEntryRssi(frequency)); - assertTrue(mScoringParams.getEntryRssi(frequency) - <= mScoringParams.getSufficientRssi(frequency)); - assertTrue(mScoringParams.getSufficientRssi(frequency) - <= mScoringParams.getGoodRssi(frequency)); - assertTrue(mScoringParams.getGoodRssi(frequency) < 0); - } - - /** - * Test basic constructor - */ - @Test - public void testBasicConstructor() throws Exception { - mScoringParams = new ScoringParams(); - checkThresholds(2412); - checkThresholds(5020); - checkThresholds(5935); - assertEquals(15, mScoringParams.getHorizonSeconds()); - } - - /** - * Test toString - */ - @Test - public void testToString() throws Exception { - mScoringParams = new ScoringParams(); - String expect = EXPECTED_DEFAULTS; - String actual = mScoringParams.toString(); - assertEquals(expect, actual); - } - - /** - * Test complete update - */ - @Test - public void testUpdateEverything() throws Exception { - mScoringParams = new ScoringParams(); - String params = EXPECTED_DEFAULTS.replaceAll("8", "9"); - assertTrue(mScoringParams.update(params)); - assertEquals(params, mScoringParams.toString()); - } - - /** - * Test partial update - */ - @Test - public void testPartialUpdate() throws Exception { - mScoringParams = new ScoringParams(); - String before = mScoringParams.toString(); - String partial = "rssi5=-88:-77:-66:-55"; - assertFalse(before.contains(partial)); - assertTrue(mScoringParams.update(partial)); - String after = mScoringParams.toString(); - assertTrue(after + " should contain " + partial, after.contains(partial)); - assertEquals(before.replaceAll("rssi5=[^,]*,", partial + ","), after); - } - - /** - * Test some failed updates - */ - @Test - public void testUpdateFail() throws Exception { - mScoringParams = new ScoringParams(); - String before = mScoringParams.toString(); - assertFalse(mScoringParams.update("word")); - assertFalse(mScoringParams.update("42")); - assertFalse(mScoringParams.update(" ")); - assertFalse(mScoringParams.update("horizon=flat")); - assertFalse(mScoringParams.update("horizon=+")); - assertFalse(mScoringParams.update(",,,,,,,,,,,,,,,,,,")); - assertFalse(mScoringParams.update("rssi2=-86")); - assertFalse(mScoringParams.update("rssi2=-99:-88:-77:-66:-55")); - assertFalse(mScoringParams.update("rssi5=one:two:three:four")); - assertFalse(mScoringParams.update("rssi6=one:two:three:four")); - assertFalse(mScoringParams.update("nud=-1")); - assertFalse(mScoringParams.update("nud=11")); - assertFalse(mScoringParams.update("pps=1:2:3:4")); - assertFalse(mScoringParams.update("pps=1:0:9")); - assertFalse(mScoringParams.update("pps=packets-per-second")); - assertEquals(before, mScoringParams.toString()); - } - - /** - * Duplicate keys not allowed - */ - @Test - public void testDuplicateKeysNotAllowed() throws Exception { - mScoringParams = new ScoringParams(); - String before = mScoringParams.toString(); - String partial = "rssi5=-88:-77:-66:-55"; - assertFalse(mScoringParams.update(partial + "," + partial)); - assertEquals(before, mScoringParams.toString()); - } - - /** - * Range and ordering checks for rssi values should work - */ - @Test - public void testRssiRangeChecks() throws Exception { - mScoringParams = new ScoringParams(); - String before = mScoringParams.toString(); - assertFalse("Must be negative", mScoringParams.update("rssi2=0:1:2:3")); - assertFalse("Must be ordered", mScoringParams.update("rssi5=-88:-89:-66:-55")); - assertFalse("Must be not too negative", mScoringParams.update("rssi6=-128:-77:-66:-55")); - String what = "rssi5=" + WifiInfo.INVALID_RSSI + ":-77:-66:-55"; - assertFalse(what, mScoringParams.update(what)); - assertEquals(before, mScoringParams.toString()); - } - - /** - * Range checks should catch wild values - */ - @Test - public void testScalarRangeChecks() throws Exception { - mScoringParams = new ScoringParams(); - assertTrue(mScoringParams.update("horizon=60")); - assertFalse(mScoringParams.update("horizon=61")); - assertTrue(mScoringParams.update("horizon=-9")); // Not recommended, but shouldn't break - assertFalse(mScoringParams.update("horizon=-10")); - } - - /** - * Test that nud is hooked up - */ - @Test - public void testNudKnob() throws Exception { - mScoringParams = new ScoringParams(); - assertTrue(mScoringParams.update("nud=6")); - assertEquals(6, mScoringParams.getNudKnob()); - } - - /** - * Test that expid is hooked up - */ - @Test - public void testExperimentIdentifier() throws Exception { - mScoringParams = new ScoringParams(); - assertEquals(0, mScoringParams.getExperimentIdentifier()); - assertTrue(mScoringParams.update("expid=99")); - assertEquals(99, mScoringParams.getExperimentIdentifier()); - } - - /** - * Check character set - */ - @Test - public void testBadCharacterChecks() throws Exception { - mScoringParams = new ScoringParams(); - String before = mScoringParams.toString(); - assertFalse(mScoringParams.update("\007ding\007=7")); - assertTrue(mScoringParams.update("unknown_key=14,ThatThing=987654321")); - assertEquals(before, mScoringParams.toString()); - } - - /** - * Sanitize should hide garbage characters and truncate length - */ - @Test - public void testSanitize() throws Exception { - mScoringParams = new ScoringParams(); - String longKey = "A123456789_123456789_123456789_123456789_123456789"; - String longVal = "9.99999999999999999999999999999999999999999999999"; - String param100 = longKey + "=" + longVal; - assertEquals(param100, mScoringParams.sanitize(param100)); - assertEquals(101, mScoringParams.sanitize(param100 + "00000000000").length()); - assertEquals(param100.substring(0, 90), - mScoringParams.sanitize(param100 + "00000000000").substring(0, 90)); - assertEquals("q?=???", mScoringParams.sanitize("q\b= ~[")); - assertEquals("", mScoringParams.sanitize(null)); - } - - /** - * Test that empty updates are OK - */ - @Test - public void testEmptyUpdate() throws Exception { - mScoringParams = new ScoringParams(); - String before = mScoringParams.toString(); - assertTrue(mScoringParams.update("")); - assertTrue(mScoringParams.update(null)); - assertEquals(before, mScoringParams.toString()); - } - - /** - * Tests for obtaining values from device configuration (config.xml) - */ - int mBad2GHz, mEntry2GHz, mSufficient2GHz, mGood2GHz; - int mBad5GHz, mEntry5GHz, mSufficient5GHz, mGood5GHz; - int mBad6GHz, mEntry6GHz, mSufficient6GHz, mGood6GHz; - - @Mock Context mContext; - @Spy private MockResources mResources = new MockResources(); - - private int setupIntegerResource(int resourceName, int value) { - doReturn(value).when(mResources).getInteger(resourceName); - return value; - } - - /** - * Sets up resource values for testing - * - * See frameworks/base/core/res/res/values/config.xml - */ - private void setUpResources(Resources resources) { - mBad2GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz, -88); - mEntry2GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz, -77); - mSufficient2GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz, -66); - mGood2GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz, -55); - mBad5GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz, -80); - mEntry5GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz, -70); - mSufficient5GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz, -60); - mGood5GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz, -50); - mBad6GHz = setupIntegerResource( - R.integer.config_wifiFrameworkScoreBadRssiThreshold6ghz, -80); - mEntry6GHz = setupIntegerResource( - R.integer.config_wifiFrameworkScoreEntryRssiThreshold6ghz, -70); - mSufficient6GHz = setupIntegerResource( - R.integer.config_wifiFrameworkScoreLowRssiThreshold6ghz, -60); - mGood6GHz = setupIntegerResource( - R.integer.config_wifiFrameworkScoreGoodRssiThreshold6ghz, -50); - } - - /** - * Check that we get the config.xml values, if that's what we want - */ - @Test - public void testContextConstructor() throws Exception { - mScoringParams = new ScoringParams(mContext); - - assertEquals(mBad2GHz, mScoringParams.getExitRssi(2412)); - assertEquals(mEntry2GHz, mScoringParams.getEntryRssi(2480)); - assertEquals(mSufficient2GHz, mScoringParams.getSufficientRssi(2457)); - assertEquals(mGood2GHz, mScoringParams.getGoodRssi(2442)); - assertEquals(mGood2GHz, mScoringParams.getGoodRssi(ScanResult.BAND_24_GHZ_START_FREQ_MHZ)); - - assertEquals(mBad5GHz, mScoringParams.getExitRssi(5200)); - assertEquals(mEntry5GHz, mScoringParams.getEntryRssi(5220)); - assertEquals(mSufficient5GHz, mScoringParams.getSufficientRssi(5300)); - assertEquals(mGood5GHz, mScoringParams.getGoodRssi(5745)); - assertEquals(mGood5GHz, mScoringParams.getGoodRssi(ScanResult.BAND_5_GHZ_START_FREQ_MHZ)); - - assertEquals(mBad6GHz, mScoringParams.getExitRssi(5965)); - assertEquals(mEntry6GHz, mScoringParams.getEntryRssi(6095)); - assertEquals(mSufficient6GHz, mScoringParams.getSufficientRssi(6255)); - assertEquals(mGood6GHz, mScoringParams.getGoodRssi(6275)); - assertEquals(mGood6GHz, mScoringParams.getGoodRssi(ScanResult.BAND_6_GHZ_START_FREQ_MHZ)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java b/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java deleted file mode 100644 index 3538598c3..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.mockito.Mockito.*; -import static org.mockito.MockitoAnnotations.*; - -import android.content.Context; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import java.util.concurrent.TimeUnit; - -/** - * Unit tests for {@link com.android.server.wifi.SelfRecovery}. - */ -@SmallTest -public class SelfRecoveryTest extends WifiBaseTest { - private static final int DEFAULT_MAX_RECOVERY_PER_HOUR = 2; - SelfRecovery mSelfRecovery; - MockResources mResources; - @Mock Context mContext; - @Mock ActiveModeWarden mActiveModeWarden; - @Mock Clock mClock; - - @Before - public void setUp() throws Exception { - initMocks(this); - mResources = new MockResources(); - // Default value of 2 recovery per hour. - mResources.setInteger(R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour, - DEFAULT_MAX_RECOVERY_PER_HOUR); - when(mContext.getResources()).thenReturn(mResources); - mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock); - } - - /** - * Verifies that invocations of {@link SelfRecovery#trigger(int)} with valid reasons will send - * the restart message to {@link ActiveModeWarden}. - */ - @Test - public void testValidTriggerReasonsSendMessageToWifiController() { - mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - reset(mActiveModeWarden); - - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(TimeUnit.HOURS.toMillis(1) + 1); - mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - reset(mActiveModeWarden); - } - - /** - * Verifies that invocations of {@link SelfRecovery#trigger(int)} with invalid reasons will not - * send the restart message to {@link ActiveModeWarden}. - */ - @Test - public void testInvalidTriggerReasonsDoesNotSendMessageToWifiController() { - mSelfRecovery.trigger(-1); - verifyNoMoreInteractions(mActiveModeWarden); - - mSelfRecovery.trigger(8); - verifyNoMoreInteractions(mActiveModeWarden); - } - - /** - * Verifies that a STA interface down event will trigger WifiController to disable wifi. - */ - @Test - public void testStaIfaceDownDisablesWifi() { - mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN); - verify(mActiveModeWarden).recoveryDisableWifi(); - } - - /** - * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_WIFI_NATIVE - * are limited to {@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a - * 1 hour time window. - */ - @Test - public void testTimeWindowLimiting_typicalUse() { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - // Fill up the SelfRecovery's restart time window buffer, ensure all the restart triggers - // aren't ignored - for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR; i++) { - mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - reset(mActiveModeWarden); - } - - // Verify that further attempts to trigger restarts disable wifi - mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden, never()) - .recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden).recoveryDisableWifi(); - reset(mActiveModeWarden); - - mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden, never()).recoveryRestartWifi(anyInt()); - verify(mActiveModeWarden).recoveryDisableWifi(); - reset(mActiveModeWarden); - - // Verify L.R.Watchdog can still restart things (It has its own complex limiter) - mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - reset(mActiveModeWarden); - - // Verify Sta Interface Down will still disable wifi - mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN); - verify(mActiveModeWarden).recoveryDisableWifi(); - reset(mActiveModeWarden); - - // now TRAVEL FORWARDS IN TIME and ensure that more restarts can occur - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(TimeUnit.HOURS.toMillis(1) + 1); - mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - reset(mActiveModeWarden); - - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(TimeUnit.HOURS.toMillis(1) + 1); - mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - reset(mActiveModeWarden); - } - - /** - * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_WIFI_NATIVE - * does not trigger recovery if {@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} - * is set to 0 - */ - @Test - public void testTimeWindowLimiting_NativeFailureOff() { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - mResources.setInteger(R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour, 0); - mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden, never()) - .recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden).recoveryDisableWifi(); - reset(mActiveModeWarden); - - // Verify L.R.Watchdog can still restart things (It has its own complex limiter) - mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - } - - /** - * Verifies that invocations of {@link SelfRecovery#trigger(int)} for - * REASON_LAST_RESORT_WATCHDOG are NOT limited to - * {{@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a 1 hour time window. - */ - @Test - public void testTimeWindowLimiting_lastResortWatchdog_noEffect() { - for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR * 2; i++) { - // Verify L.R.Watchdog can still restart things (It has it's own complex limiter) - mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - reset(mActiveModeWarden); - } - } - - /** - * Verifies that invocations of {@link SelfRecovery#trigger(int)} for - * REASON_STA_IFACE_DOWN are NOT limited to - * {{@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a 1 hour time window. - */ - @Test - public void testTimeWindowLimiting_staIfaceDown_noEffect() { - for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR * 2; i++) { - mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN); - verify(mActiveModeWarden).recoveryDisableWifi(); - verify(mActiveModeWarden, never()).recoveryRestartWifi(anyInt()); - reset(mActiveModeWarden); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApBackupRestoreTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApBackupRestoreTest.java deleted file mode 100644 index a1b917431..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SoftApBackupRestoreTest.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiMigration; -import android.util.BackupUtils; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.ApConfigUtil; -import com.android.server.wifi.util.SettingsMigrationDataHolder; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.SoftApBackupRestore}. - */ -@SmallTest -public class SoftApBackupRestoreTest extends WifiBaseTest { - - @Mock private Context mContext; - @Mock private SettingsMigrationDataHolder mSettingsMigrationDataHolder; - @Mock private WifiMigration.SettingsMigrationData mOemMigrationData; - private SoftApBackupRestore mSoftApBackupRestore; - private final ArrayList<MacAddress> mTestBlockedList = new ArrayList<>(); - private final ArrayList<MacAddress> mTestAllowedList = new ArrayList<>(); - private static final int LAST_WIFICOFIGURATION_BACKUP_VERSION = 3; - private static final boolean TEST_CLIENTCONTROLENABLE = false; - private static final int TEST_MAXNUMBEROFCLIENTS = 10; - private static final long TEST_SHUTDOWNTIMEOUTMILLIS = 600_000; - private static final String TEST_BLOCKED_CLIENT = "11:22:33:44:55:66"; - private static final String TEST_ALLOWED_CLIENT = "aa:bb:cc:dd:ee:ff"; - private static final String TEST_SSID = "TestAP"; - private static final String TEST_PASSPHRASE = "TestPskPassphrase"; - private static final int TEST_SECURITY = SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION; - private static final int TEST_BAND = SoftApConfiguration.BAND_5GHZ; - private static final int TEST_CHANNEL = 40; - private static final boolean TEST_HIDDEN = false; - - /** - * Asserts that the WifiConfigurations equal to SoftApConfiguration. - * This only compares the elements saved - * for softAp used. - */ - public static void assertWifiConfigurationEqualSoftApConfiguration( - WifiConfiguration backup, SoftApConfiguration restore) { - assertEquals(backup.SSID, restore.getSsid()); - assertEquals(backup.BSSID, restore.getBssid()); - assertEquals(ApConfigUtil.convertWifiConfigBandToSoftApConfigBand(backup.apBand), - restore.getBand()); - assertEquals(backup.apChannel, restore.getChannel()); - assertEquals(backup.preSharedKey, restore.getPassphrase()); - int authType = backup.getAuthType(); - if (backup.getAuthType() == WifiConfiguration.KeyMgmt.WPA2_PSK) { - assertEquals(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, restore.getSecurityType()); - } else { - assertEquals(SoftApConfiguration.SECURITY_TYPE_OPEN, restore.getSecurityType()); - } - assertEquals(backup.hiddenSSID, restore.isHiddenSsid()); - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mSettingsMigrationDataHolder.retrieveData()).thenReturn(mOemMigrationData); - when(mOemMigrationData.isSoftApTimeoutEnabled()).thenReturn(true); - - mSoftApBackupRestore = new SoftApBackupRestore(mContext, mSettingsMigrationDataHolder); - } - - @After - public void tearDown() throws Exception { - } - - /** - * Copy from WifiConfiguration for test backup/restore is backward compatible. - */ - private byte[] getBytesForBackup(WifiConfiguration wificonfig) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream(baos); - - out.writeInt(LAST_WIFICOFIGURATION_BACKUP_VERSION); - BackupUtils.writeString(out, wificonfig.SSID); - out.writeInt(wificonfig.apBand); - out.writeInt(wificonfig.apChannel); - BackupUtils.writeString(out, wificonfig.preSharedKey); - out.writeInt(wificonfig.getAuthType()); - out.writeBoolean(wificonfig.hiddenSSID); - return baos.toByteArray(); - } - - /** - * Verifies that the serialization/de-serialization for wpa2 softap config works. - */ - @Test - public void testSoftApConfigBackupAndRestoreWithWpa2Config() throws Exception { - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid("TestAP"); - configBuilder.setChannel(40, SoftApConfiguration.BAND_5GHZ); - configBuilder.setPassphrase("TestPskPassphrase", - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - configBuilder.setHiddenSsid(true); - - SoftApConfiguration config = configBuilder.build(); - - byte[] data = mSoftApBackupRestore.retrieveBackupDataFromSoftApConfiguration(config); - SoftApConfiguration restoredConfig = - mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); - - assertThat(config).isEqualTo(restoredConfig); - } - - /** - * Verifies that the serialization/de-serialization for open security softap config works. - */ - @Test - public void testSoftApConfigBackupAndRestoreWithOpenSecurityConfig() throws Exception { - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid("TestAP"); - configBuilder.setChannel(12, SoftApConfiguration.BAND_2GHZ); - configBuilder.setHiddenSsid(false); - SoftApConfiguration config = configBuilder.build(); - - byte[] data = mSoftApBackupRestore.retrieveBackupDataFromSoftApConfiguration(config); - SoftApConfiguration restoredConfig = - mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); - - assertThat(config).isEqualTo(restoredConfig); - } - - /** - * Verifies that the serialization/de-serialization for old softap config works. - */ - @Test - public void testSoftApConfigBackupAndRestoreWithOldConfig() throws Exception { - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.SSID = "TestAP"; - wifiConfig.apBand = WifiConfiguration.AP_BAND_2GHZ; - wifiConfig.apChannel = 12; - wifiConfig.hiddenSSID = true; - wifiConfig.preSharedKey = "test_pwd"; - wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK); - byte[] data = getBytesForBackup(wifiConfig); - SoftApConfiguration restoredConfig = - mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); - - assertWifiConfigurationEqualSoftApConfiguration(wifiConfig, restoredConfig); - } - - /** - * Verifies that the serialization/de-serialization for wpa3-sae softap config works. - */ - @Test - public void testSoftApConfigBackupAndRestoreWithWpa3SaeConfig() throws Exception { - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid("TestAP"); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - configBuilder.setChannel(40, SoftApConfiguration.BAND_5GHZ); - configBuilder.setPassphrase("TestPskPassphrase", - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); - configBuilder.setHiddenSsid(true); - configBuilder.setAutoShutdownEnabled(true); - SoftApConfiguration config = configBuilder.build(); - - byte[] data = mSoftApBackupRestore.retrieveBackupDataFromSoftApConfiguration(config); - SoftApConfiguration restoredConfig = - mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); - - assertThat(config).isEqualTo(restoredConfig); - } - - /** - * Verifies that the serialization/de-serialization for wpa3-sae-transition softap config. - */ - @Test - public void testSoftApConfigBackupAndRestoreWithWpa3SaeTransitionConfig() throws Exception { - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid("TestAP"); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - configBuilder.setChannel(40, SoftApConfiguration.BAND_5GHZ); - configBuilder.setPassphrase("TestPskPassphrase", - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); - configBuilder.setHiddenSsid(true); - configBuilder.setAutoShutdownEnabled(false); - SoftApConfiguration config = configBuilder.build(); - - byte[] data = mSoftApBackupRestore.retrieveBackupDataFromSoftApConfiguration(config); - SoftApConfiguration restoredConfig = - mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); - - assertThat(config).isEqualTo(restoredConfig); - } - - /** - * Verifies that the serialization/de-serialization for wpa3-sae-transition softap config. - */ - @Test - public void testSoftApConfigBackupAndRestoreWithMaxShutDownClientList() throws Exception { - mTestBlockedList.add(MacAddress.fromString(TEST_BLOCKED_CLIENT)); - mTestAllowedList.add(MacAddress.fromString(TEST_ALLOWED_CLIENT)); - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid(TEST_SSID); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - configBuilder.setChannel(40, SoftApConfiguration.BAND_5GHZ); - configBuilder.setPassphrase(TEST_PASSPHRASE, TEST_SECURITY); - configBuilder.setHiddenSsid(TEST_HIDDEN); - configBuilder.setMaxNumberOfClients(TEST_MAXNUMBEROFCLIENTS); - configBuilder.setShutdownTimeoutMillis(TEST_SHUTDOWNTIMEOUTMILLIS); - configBuilder.setClientControlByUserEnabled(TEST_CLIENTCONTROLENABLE); - configBuilder.setBlockedClientList(mTestBlockedList); - configBuilder.setAllowedClientList(mTestAllowedList); - SoftApConfiguration config = configBuilder.build(); - - byte[] data = mSoftApBackupRestore.retrieveBackupDataFromSoftApConfiguration(config); - SoftApConfiguration restoredConfig = - mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); - - assertThat(config).isEqualTo(restoredConfig); - } - - /** - * Verifies that the restore of version 5 backup data will read the auto shutdown enable/disable - * tag from {@link WifiMigration#loadFromSettings(Context)} - */ - @Test - public void testSoftApConfigRestoreFromVersion5() throws Exception { - mTestBlockedList.add(MacAddress.fromString(TEST_BLOCKED_CLIENT)); - mTestAllowedList.add(MacAddress.fromString(TEST_ALLOWED_CLIENT)); - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid(TEST_SSID); - configBuilder.setBand(TEST_BAND); - configBuilder.setChannel(TEST_CHANNEL, TEST_BAND); - configBuilder.setPassphrase(TEST_PASSPHRASE, TEST_SECURITY); - configBuilder.setHiddenSsid(TEST_HIDDEN); - configBuilder.setMaxNumberOfClients(TEST_MAXNUMBEROFCLIENTS); - configBuilder.setShutdownTimeoutMillis(TEST_SHUTDOWNTIMEOUTMILLIS); - configBuilder.setClientControlByUserEnabled(TEST_CLIENTCONTROLENABLE); - configBuilder.setBlockedClientList(mTestBlockedList); - configBuilder.setAllowedClientList(mTestAllowedList); - - // Toggle on when migrating. - when(mOemMigrationData.isSoftApTimeoutEnabled()).thenReturn(true); - SoftApConfiguration expectedConfig = configBuilder.setAutoShutdownEnabled(true).build(); - SoftApConfiguration restoredConfig = - mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData( - retrieveVersion5BackupDataFromSoftApConfiguration(expectedConfig)); - assertEquals(expectedConfig, restoredConfig); - - // Toggle off when migrating. - when(mOemMigrationData.isSoftApTimeoutEnabled()).thenReturn(false); - expectedConfig = configBuilder.setAutoShutdownEnabled(false).build(); - restoredConfig = mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData( - retrieveVersion5BackupDataFromSoftApConfiguration(expectedConfig)); - assertEquals(expectedConfig, restoredConfig); - } - - /** - * This is a copy of the old serialization code (version 5) - * - * Changes: Version = 5, AutoShutdown tag is missing. - */ - private byte[] retrieveVersion5BackupDataFromSoftApConfiguration(SoftApConfiguration config) - throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream(baos); - - out.writeInt(5); - BackupUtils.writeString(out, config.getSsid()); - out.writeInt(config.getBand()); - out.writeInt(config.getChannel()); - BackupUtils.writeString(out, config.getPassphrase()); - out.writeInt(config.getSecurityType()); - out.writeBoolean(config.isHiddenSsid()); - out.writeInt(config.getMaxNumberOfClients()); - out.writeInt((int) config.getShutdownTimeoutMillis()); - out.writeBoolean(config.isClientControlByUserEnabled()); - writeMacAddressList(out, config.getBlockedClientList()); - writeMacAddressList(out, config.getAllowedClientList()); - return baos.toByteArray(); - } - - - /** - * Verifies that the restore of version 6 backup data will read the auto shutdown with int. - */ - @Test - public void testSoftApConfigRestoreFromVersion6() throws Exception { - mTestBlockedList.add(MacAddress.fromString(TEST_BLOCKED_CLIENT)); - mTestAllowedList.add(MacAddress.fromString(TEST_ALLOWED_CLIENT)); - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid(TEST_SSID); - configBuilder.setBand(TEST_BAND); - configBuilder.setChannel(TEST_CHANNEL, TEST_BAND); - configBuilder.setPassphrase(TEST_PASSPHRASE, TEST_SECURITY); - configBuilder.setHiddenSsid(TEST_HIDDEN); - configBuilder.setMaxNumberOfClients(TEST_MAXNUMBEROFCLIENTS); - configBuilder.setShutdownTimeoutMillis(TEST_SHUTDOWNTIMEOUTMILLIS); - configBuilder.setClientControlByUserEnabled(TEST_CLIENTCONTROLENABLE); - configBuilder.setBlockedClientList(mTestBlockedList); - configBuilder.setAllowedClientList(mTestAllowedList); - - SoftApConfiguration expectedConfig = configBuilder.build(); - SoftApConfiguration restoredConfig = mSoftApBackupRestore - .retrieveSoftApConfigurationFromBackupData( - retrieveVersion6BackupDataFromSoftApConfiguration(expectedConfig)); - assertEquals(expectedConfig, restoredConfig); - } - - /** - * This is a copy of the old serialization code (version 6) - * - * Changes: Version = 6, AutoShutdown use int type - */ - private byte[] retrieveVersion6BackupDataFromSoftApConfiguration(SoftApConfiguration config) - throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream(baos); - - out.writeInt(6); - BackupUtils.writeString(out, config.getSsid()); - out.writeInt(config.getBand()); - out.writeInt(config.getChannel()); - BackupUtils.writeString(out, config.getPassphrase()); - out.writeInt(config.getSecurityType()); - out.writeBoolean(config.isHiddenSsid()); - out.writeInt(config.getMaxNumberOfClients()); - out.writeInt((int) config.getShutdownTimeoutMillis()); - out.writeBoolean(config.isClientControlByUserEnabled()); - writeMacAddressList(out, config.getBlockedClientList()); - writeMacAddressList(out, config.getAllowedClientList()); - out.writeBoolean(config.isAutoShutdownEnabled()); - return baos.toByteArray(); - } - - - private void writeMacAddressList(DataOutputStream out, List<MacAddress> macList) - throws IOException { - out.writeInt(macList.size()); - Iterator<MacAddress> iterator = macList.iterator(); - while (iterator.hasNext()) { - byte[] mac = iterator.next().toByteArray(); - out.write(mac, 0, 6); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java deleted file mode 100644 index c4c00939a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java +++ /dev/null @@ -1,2281 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - - -import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_FAILURE_REASON; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; -import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY; -import static android.net.wifi.WifiManager.SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; - -import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR; -import static com.android.server.wifi.util.ApConfigUtil.DEFAULT_AP_CHANNEL; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.NotificationManager; -import android.app.test.TestAlarmManager; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.net.MacAddress; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApConfiguration.Builder; -import android.net.wifi.SoftApInfo; -import android.net.wifi.WifiClient; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiScanner; -import android.net.wifi.nl80211.NativeWifiClient; -import android.os.UserHandle; -import android.os.test.TestLooper; -import android.provider.Settings; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.WakeupMessage; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -/** Unit tests for {@link SoftApManager}. */ -@SmallTest -public class SoftApManagerTest extends WifiBaseTest { - - private static final String TAG = "SoftApManagerTest"; - - private static final String DEFAULT_SSID = "DefaultTestSSID"; - private static final String TEST_SSID = "TestSSID"; - private static final String TEST_PASSWORD = "TestPassword"; - private static final String TEST_COUNTRY_CODE = "TestCountry"; - private static final String TEST_INTERFACE_NAME = "testif0"; - private static final String OTHER_INTERFACE_NAME = "otherif"; - private static final long TEST_DEFAULT_SHUTDOWN_TIMEOUT_MILLS = 600_000; - private static final MacAddress TEST_MAC_ADDRESS = MacAddress.fromString("22:33:44:55:66:77"); - private static final MacAddress TEST_MAC_ADDRESS_2 = MacAddress.fromString("aa:bb:cc:dd:ee:ff"); - private static final WifiClient TEST_CONNECTED_CLIENT = new WifiClient(TEST_MAC_ADDRESS); - private static final NativeWifiClient TEST_NATIVE_CLIENT = new NativeWifiClient( - TEST_MAC_ADDRESS); - private static final WifiClient TEST_CONNECTED_CLIENT_2 = new WifiClient(TEST_MAC_ADDRESS_2); - private static final NativeWifiClient TEST_NATIVE_CLIENT_2 = new NativeWifiClient( - TEST_MAC_ADDRESS_2); - private static final int TEST_AP_FREQUENCY = 2412; - private static final int TEST_AP_BANDWIDTH_FROM_IFACE_CALLBACK = - SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; - private static final int TEST_AP_BANDWIDTH_IN_SOFTAPINFO = SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; - private static final int[] EMPTY_CHANNEL_ARRAY = {}; - private SoftApConfiguration mDefaultApConfig = createDefaultApConfig(); - - private TestLooper mLooper; - private TestAlarmManager mAlarmManager; - private SoftApInfo mTestSoftApInfo; - private SoftApCapability mTestSoftApCapability; - - @Mock WifiContext mContext; - @Mock Resources mResources; - @Mock WifiNative mWifiNative; - @Mock WifiManager.SoftApCallback mCallback; - @Mock ActiveModeManager.Listener mListener; - @Mock FrameworkFacade mFrameworkFacade; - @Mock WifiApConfigStore mWifiApConfigStore; - @Mock WifiMetrics mWifiMetrics; - @Mock SarManager mSarManager; - @Mock BaseWifiDiagnostics mWifiDiagnostics; - @Mock NotificationManager mNotificationManager; - @Mock SoftApNotifier mFakeSoftApNotifier; - - final ArgumentCaptor<WifiNative.InterfaceCallback> mWifiNativeInterfaceCallbackCaptor = - ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class); - final ArgumentCaptor<WifiNative.SoftApListener> mSoftApListenerCaptor = - ArgumentCaptor.forClass(WifiNative.SoftApListener.class); - - SoftApManager mSoftApManager; - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - - when(mWifiNative.isSetMacAddressSupported(any())).thenReturn(true); - when(mWifiNative.setMacAddress(any(), any())).thenReturn(true); - when(mWifiNative.startSoftAp(eq(TEST_INTERFACE_NAME), any(), any())).thenReturn(true); - - when(mFrameworkFacade.getIntegerSetting( - mContext, Settings.Global.SOFT_AP_TIMEOUT_ENABLED, 1)).thenReturn(1); - mAlarmManager = new TestAlarmManager(); - when(mContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getSystemService(NotificationManager.class)) - .thenReturn(mNotificationManager); - when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources"); - - when(mResources.getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds)) - .thenReturn((int) TEST_DEFAULT_SHUTDOWN_TIMEOUT_MILLS); - when(mWifiNative.setCountryCodeHal( - TEST_INTERFACE_NAME, TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT))) - .thenReturn(true); - when(mWifiNative.getFactoryMacAddress(any())).thenReturn(TEST_MAC_ADDRESS); - when(mWifiApConfigStore.randomizeBssidIfUnset(any(), any())).thenAnswer( - (invocation) -> invocation.getArgument(1)); - mTestSoftApInfo = new SoftApInfo(); - mTestSoftApInfo.setFrequency(TEST_AP_FREQUENCY); - mTestSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH_IN_SOFTAPINFO); - // Default set up all features support. - long testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT - | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD - | SoftApCapability.SOFTAP_FEATURE_WPA3_SAE; - mTestSoftApCapability = new SoftApCapability(testSoftApFeature); - mTestSoftApCapability.setMaxSupportedClients(10); - } - - private SoftApConfiguration createDefaultApConfig() { - Builder defaultConfigBuilder = new SoftApConfiguration.Builder(); - defaultConfigBuilder.setSsid(DEFAULT_SSID); - return defaultConfigBuilder.build(); - } - - private SoftApManager createSoftApManager(SoftApModeConfiguration config, String countryCode) { - if (config.getSoftApConfiguration() == null) { - when(mWifiApConfigStore.getApConfiguration()).thenReturn(mDefaultApConfig); - } - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - countryCode, - mListener, - mCallback, - mWifiApConfigStore, - config, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - - return newSoftApManager; - } - - /** Verifies startSoftAp will use default config if AP configuration is not provided. */ - @Test - public void startSoftApWithoutConfig() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - } - - /** Verifies startSoftAp will use provided config and start AP. */ - @Test - public void startSoftApWithConfig() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - } - - /** - * Verifies startSoftAp will start with the hiddenSSID param set when it is set to true in the - * supplied config. - */ - @Test - public void startSoftApWithHiddenSsidTrueInConfig() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setHiddenSsid(true); - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - } - - /** - * Verifies startSoftAp will start with the password param set in the - * supplied config. - */ - @Test - public void startSoftApWithPassphraseInConfig() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setPassphrase(TEST_PASSWORD, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - } - - /** Tests softap startup if default config fails to load. **/ - @Test - public void startSoftApDefaultConfigFailedToLoad() throws Exception { - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - - when(mWifiApConfigStore.getApConfiguration()).thenReturn(null); - SoftApModeConfiguration nullApConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - TEST_COUNTRY_CODE, - mListener, - mCallback, - mWifiApConfigStore, - nullApConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - verify(mListener).onStartFailure(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> capturedIntents = intentCaptor.getAllValues(); - checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING, - WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - nullApConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_ENABLING, WifiManager.SAP_START_FAILURE_GENERAL, TEST_INTERFACE_NAME, - nullApConfig.getTargetMode()); - } - - /** - * Test that failure to retrieve the SoftApInterface name increments the corresponding metrics - * and proper state updates are sent out. - */ - @Test - public void testSetupForSoftApModeNullApInterfaceNameFailureIncrementsMetrics() - throws Exception { - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(null); - - SoftApModeConfiguration config = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, new SoftApConfiguration.Builder().build(), - mTestSoftApCapability); - - when(mWifiApConfigStore.getApConfiguration()).thenReturn(null); - SoftApModeConfiguration nullApConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - TEST_COUNTRY_CODE, - mListener, - mCallback, - mWifiApConfigStore, - nullApConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - verify(mListener).onStartFailure(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_DISABLED, WifiManager.SAP_START_FAILURE_GENERAL, null, - nullApConfig.getTargetMode()); - - verify(mWifiMetrics).incrementSoftApStartResult(false, - WifiManager.SAP_START_FAILURE_GENERAL); - } - - /** - * Test that an empty SoftApInterface name is detected as a failure and increments the - * corresponding metrics and proper state updates are sent out. - */ - @Test - public void testSetupForSoftApModeEmptyInterfaceNameFailureIncrementsMetrics() - throws Exception { - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(""); - - SoftApModeConfiguration config = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, new SoftApConfiguration.Builder().build(), - mTestSoftApCapability); - - when(mWifiApConfigStore.getApConfiguration()).thenReturn(null); - SoftApModeConfiguration nullApConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - TEST_COUNTRY_CODE, - mListener, - mCallback, - mWifiApConfigStore, - nullApConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - verify(mListener).onStartFailure(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_DISABLED, WifiManager.SAP_START_FAILURE_GENERAL, "", - nullApConfig.getTargetMode()); - - verify(mWifiMetrics).incrementSoftApStartResult(false, - WifiManager.SAP_START_FAILURE_GENERAL); - } - - /** - * Tests that the generic error is propagated and properly reported when starting softap and no - * country code is provided. - */ - @Test - public void startSoftApOn5GhzFailGeneralErrorForNoCountryCode() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - configBuilder.setSsid(TEST_SSID); - SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - null, - mListener, - mCallback, - mWifiApConfigStore, - softApConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - - verify(mWifiNative, never()).setCountryCodeHal(eq(TEST_INTERFACE_NAME), any()); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> capturedIntents = intentCaptor.getAllValues(); - checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING, - WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_ENABLING, WifiManager.SAP_START_FAILURE_GENERAL, TEST_INTERFACE_NAME, - softApConfig.getTargetMode()); - } - - /** - * Tests that the generic error is propagated and properly reported when starting softap and the - * country code cannot be set. - */ - @Test - public void startSoftApOn5GhzFailGeneralErrorForCountryCodeSetFailure() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - configBuilder.setSsid(TEST_SSID); - SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - when(mWifiNative.setCountryCodeHal( - TEST_INTERFACE_NAME, TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT))) - .thenReturn(false); - - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - TEST_COUNTRY_CODE, - mListener, - mCallback, - mWifiApConfigStore, - softApConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - - verify(mWifiNative).setCountryCodeHal( - TEST_INTERFACE_NAME, TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT)); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> capturedIntents = intentCaptor.getAllValues(); - checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING, - WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_ENABLING, WifiManager.SAP_START_FAILURE_GENERAL, TEST_INTERFACE_NAME, - softApConfig.getTargetMode()); - } - - /** - * Tests that there is no failure in starting softap in 2Ghz band when no country code is - * provided. - */ - @Test - public void startSoftApOn24GhzNoFailForNoCountryCode() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - - startSoftApAndVerifyEnabled(softApConfig, null); - verify(mWifiNative, never()).setCountryCodeHal(eq(TEST_INTERFACE_NAME), any()); - } - - /** - * Tests that there is no failure in starting softap in ANY band when no country code is - * provided. - */ - @Test - public void startSoftApOnAnyGhzNoFailForNoCountryCode() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_ANY); - configBuilder.setSsid(TEST_SSID); - SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - - startSoftApAndVerifyEnabled(softApConfig, null); - verify(mWifiNative, never()).setCountryCodeHal(eq(TEST_INTERFACE_NAME), any()); - } - - /** - * Tests that there is no failure in starting softap in 2Ghz band when country code cannot be - * set. - */ - @Test - public void startSoftApOn2GhzNoFailForCountryCodeSetFailure() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - - when(mWifiNative.setCountryCodeHal(eq(TEST_INTERFACE_NAME), any())).thenReturn(false); - - startSoftApAndVerifyEnabled(softApConfig, TEST_COUNTRY_CODE); - verify(mWifiNative).setCountryCodeHal( - TEST_INTERFACE_NAME, TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT)); - } - - /** - * Tests that there is no failure in starting softap in ANY band when country code cannot be - * set. - */ - @Test - public void startSoftApOnAnyNoFailForCountryCodeSetFailure() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_ANY); - configBuilder.setSsid(TEST_SSID); - SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - - when(mWifiNative.setCountryCodeHal(eq(TEST_INTERFACE_NAME), any())).thenReturn(false); - - startSoftApAndVerifyEnabled(softApConfig, TEST_COUNTRY_CODE); - verify(mWifiNative).setCountryCodeHal( - TEST_INTERFACE_NAME, TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT)); - } - - /** - * Tests that the NO_CHANNEL error is propagated and properly reported when starting softap and - * a valid channel cannot be determined. - */ - @Test - public void startSoftApFailNoChannel() throws Exception { - SoftApCapability noAcsCapability = new SoftApCapability(0); - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - configBuilder.setSsid(TEST_SSID); - SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - noAcsCapability); - - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)) - .thenReturn(EMPTY_CHANNEL_ARRAY); - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - when(mWifiNative.isHalStarted()).thenReturn(true); - - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - TEST_COUNTRY_CODE, - mListener, - mCallback, - mWifiApConfigStore, - softApConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> capturedIntents = intentCaptor.getAllValues(); - checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING, - WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_ENABLING, WifiManager.SAP_START_FAILURE_NO_CHANNEL, - TEST_INTERFACE_NAME, softApConfig.getTargetMode()); - } - - /** - * Tests startup when Ap Interface fails to start successfully. - */ - @Test - public void startSoftApApInterfaceFailedToStart() throws Exception { - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - when(mWifiNative.startSoftAp(eq(TEST_INTERFACE_NAME), any(), any())).thenReturn(false); - - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, mDefaultApConfig, - mTestSoftApCapability); - - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - TEST_COUNTRY_CODE, - mListener, - mCallback, - mWifiApConfigStore, - softApModeConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - verify(mListener).onStartFailure(); - verify(mWifiNative).teardownInterface(TEST_INTERFACE_NAME); - } - - /** - * Tests the handling of stop command when soft AP is not started. - */ - @Test - public void stopWhenNotStarted() throws Exception { - mSoftApManager = createSoftApManager( - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability), TEST_COUNTRY_CODE); - mSoftApManager.stop(); - mLooper.dispatchAll(); - /* Verify no state changes. */ - verify(mCallback, never()).onStateChanged(anyInt(), anyInt()); - verifyNoMoreInteractions(mListener); - verify(mSarManager, never()).setSapWifiState(anyInt()); - verify(mContext, never()).sendStickyBroadcastAsUser(any(), any()); - verify(mWifiNative, never()).teardownInterface(anyString()); - } - - /** - * Tests the handling of stop command when soft AP is started. - */ - @Test - public void stopWhenStarted() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(softApModeConfig); - - // reset to clear verified Intents for ap state change updates - reset(mContext); - - InOrder order = inOrder(mCallback, mListener, mContext); - - mSoftApManager.stop(); - assertTrue(mSoftApManager.isStopping()); - mLooper.dispatchAll(); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0); - order.verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_DISABLING, - WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); - verify(mSarManager).setSapWifiState(WifiManager.WIFI_AP_STATE_DISABLED); - verify(mWifiDiagnostics).stopLogging(TEST_INTERFACE_NAME); - order.verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_DISABLED, - WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - order.verify(mListener).onStopped(); - assertFalse(mSoftApManager.isStopping()); - } - - /** - * Verify that onDestroyed properly reports softap stop. - */ - @Test - public void cleanStopOnInterfaceDestroyed() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(softApModeConfig); - - // reset to clear verified Intents for ap state change updates - reset(mContext); - - InOrder order = inOrder(mCallback, mListener, mContext); - - mWifiNativeInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME); - - mLooper.dispatchAll(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0); - order.verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_DISABLING, - WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); - order.verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_DISABLED, - WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - order.verify(mListener).onStopped(); - assertFalse(mSoftApManager.isStopping()); - } - - /** - * Verify that onDestroyed after softap is stopped doesn't trigger a callback. - */ - @Test - public void noCallbackOnInterfaceDestroyedWhenAlreadyStopped() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(softApModeConfig); - - mSoftApManager.stop(); - mLooper.dispatchAll(); - verify(mListener).onStopped(); - - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); - - reset(mCallback); - - // now trigger interface destroyed and make sure callback doesn't get called - mWifiNativeInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - - verifyNoMoreInteractions(mCallback, mListener); - } - - /** - * Verify that onDown is handled by SoftApManager. - */ - @Test - public void testInterfaceOnDownHandled() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(softApModeConfig); - - // reset to clear verified Intents for ap state change updates - reset(mContext, mCallback, mWifiNative); - - InOrder order = inOrder(mCallback, mListener, mContext); - - mWifiNativeInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME); - - mLooper.dispatchAll(); - - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - order.verify(mListener).onStopped(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, times(3)).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> capturedIntents = intentCaptor.getAllValues(); - checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_ENABLED, WifiManager.SAP_START_FAILURE_GENERAL, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_DISABLING, - WIFI_AP_STATE_FAILED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(2), WIFI_AP_STATE_DISABLED, - WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - } - - /** - * Verify that onDown for a different interface name does not stop SoftApManager. - */ - @Test - public void testInterfaceOnDownForDifferentInterfaceDoesNotTriggerStop() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(softApModeConfig); - - // reset to clear verified Intents for ap state change updates - reset(mContext, mCallback, mWifiNative); - - InOrder order = inOrder(mCallback, mContext); - - mWifiNativeInterfaceCallbackCaptor.getValue().onDown(OTHER_INTERFACE_NAME); - - mLooper.dispatchAll(); - - verifyNoMoreInteractions(mContext, mCallback, mListener, mWifiNative); - } - - /** - * Verify that onFailure from hostapd is handled by SoftApManager. - */ - @Test - public void testHostapdOnFailureHandled() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(softApModeConfig); - - // reset to clear verified Intents for ap state change updates - reset(mContext, mCallback, mWifiNative); - - InOrder order = inOrder(mCallback, mListener, mContext); - - mSoftApListenerCaptor.getValue().onFailure(); - mLooper.dispatchAll(); - - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - order.verify(mListener).onStopped(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, times(3)).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> capturedIntents = intentCaptor.getAllValues(); - checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_ENABLED, WifiManager.SAP_START_FAILURE_GENERAL, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_DISABLING, - WIFI_AP_STATE_FAILED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(2), WIFI_AP_STATE_DISABLED, - WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - } - - @Test - public void updatesMetricsOnChannelSwitchedEvent() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - final int channelFrequency = 2437; - final int channelBandwidth = SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched(channelFrequency, - channelBandwidth); - mLooper.dispatchAll(); - - verify(mWifiMetrics).addSoftApChannelSwitchedEvent(channelFrequency, channelBandwidth, - apConfig.getTargetMode()); - } - - @Test - public void updatesMetricsOnChannelSwitchedEventDetectsBandUnsatisfiedOnBand2Ghz() - throws Exception { - SoftApConfiguration config = createDefaultApConfig(); - Builder configBuilder = new SoftApConfiguration.Builder(config); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - final int channelFrequency = 5180; - final int channelBandwidth = SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched(channelFrequency, - channelBandwidth); - mLooper.dispatchAll(); - - verify(mWifiMetrics).addSoftApChannelSwitchedEvent(channelFrequency, channelBandwidth, - apConfig.getTargetMode()); - verify(mWifiMetrics).incrementNumSoftApUserBandPreferenceUnsatisfied(); - } - - @Test - public void updatesMetricsOnChannelSwitchedEventDetectsBandUnsatisfiedOnBand5Ghz() - throws Exception { - SoftApConfiguration config = createDefaultApConfig(); - Builder configBuilder = new SoftApConfiguration.Builder(config); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - final int channelFrequency = 2437; - final int channelBandwidth = SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched(channelFrequency, - channelBandwidth); - mLooper.dispatchAll(); - - verify(mWifiMetrics).addSoftApChannelSwitchedEvent(channelFrequency, channelBandwidth, - apConfig.getTargetMode()); - verify(mWifiMetrics).incrementNumSoftApUserBandPreferenceUnsatisfied(); - } - - @Test - public void updatesMetricsOnChannelSwitchedEventDoesNotDetectBandUnsatisfiedOnBandAny() - throws Exception { - SoftApConfiguration config = createDefaultApConfig(); - Builder configBuilder = new SoftApConfiguration.Builder(config); - configBuilder.setBand(SoftApConfiguration.BAND_ANY); - - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - final int channelFrequency = 5220; - final int channelBandwidth = SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched(channelFrequency, - channelBandwidth); - mLooper.dispatchAll(); - - verify(mWifiMetrics).addSoftApChannelSwitchedEvent(channelFrequency, channelBandwidth, - apConfig.getTargetMode()); - verify(mWifiMetrics, never()).incrementNumSoftApUserBandPreferenceUnsatisfied(); - } - - /** - * If SoftApManager gets an update for the ap channal and the frequency, it will trigger - * callbacks to update softap information. - */ - @Test - public void testOnSoftApChannelSwitchedEventTriggerSoftApInfoUpdate() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched( - TEST_AP_FREQUENCY, TEST_AP_BANDWIDTH_FROM_IFACE_CALLBACK); - mLooper.dispatchAll(); - - verify(mCallback).onInfoChanged(mTestSoftApInfo); - verify(mWifiMetrics).addSoftApChannelSwitchedEvent(TEST_AP_FREQUENCY, - TEST_AP_BANDWIDTH_IN_SOFTAPINFO, apConfig.getTargetMode()); - } - - /** - * If SoftApManager gets an update for the ap channal and the frequency those are the same, - * do not trigger callbacks a second time. - */ - @Test - public void testDoesNotTriggerCallbackForSameChannelInfoUpdate() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched( - TEST_AP_FREQUENCY, TEST_AP_BANDWIDTH_FROM_IFACE_CALLBACK); - mLooper.dispatchAll(); - - // now trigger callback again, but we should have each method only called once - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched( - TEST_AP_FREQUENCY, TEST_AP_BANDWIDTH_FROM_IFACE_CALLBACK); - mLooper.dispatchAll(); - - verify(mCallback).onInfoChanged(mTestSoftApInfo); - verify(mWifiMetrics).addSoftApChannelSwitchedEvent(TEST_AP_FREQUENCY, - TEST_AP_BANDWIDTH_IN_SOFTAPINFO, apConfig.getTargetMode()); - } - - /** - * If SoftApManager gets an update for the invalid ap frequency, it will not - * trigger callbacks - */ - @Test - public void testHandlesInvalidChannelFrequency() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched( - -1, TEST_AP_BANDWIDTH_FROM_IFACE_CALLBACK); - mLooper.dispatchAll(); - - verify(mCallback, never()).onInfoChanged(any()); - verify(mWifiMetrics, never()).addSoftApChannelSwitchedEvent(anyInt(), anyInt(), - anyInt()); - } - - /** - * If softap leave started state, it should update softap inforation which frequency is 0 via - * trigger callbacks. - */ - @Test - public void testCallbackForChannelUpdateToZeroWhenLeaveSoftapStarted() throws Exception { - InOrder order = inOrder(mCallback, mWifiMetrics); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - mSoftApListenerCaptor.getValue().onSoftApChannelSwitched( - TEST_AP_FREQUENCY, TEST_AP_BANDWIDTH_FROM_IFACE_CALLBACK); - mLooper.dispatchAll(); - - order.verify(mCallback).onInfoChanged(mTestSoftApInfo); - order.verify(mWifiMetrics).addSoftApChannelSwitchedEvent(TEST_AP_FREQUENCY, - TEST_AP_BANDWIDTH_IN_SOFTAPINFO, apConfig.getTargetMode()); - - mSoftApManager.stop(); - mLooper.dispatchAll(); - - mTestSoftApInfo.setFrequency(0); - mTestSoftApInfo.setBandwidth(SoftApInfo.CHANNEL_WIDTH_INVALID); - - order.verify(mCallback).onInfoChanged(mTestSoftApInfo); - order.verify(mWifiMetrics, never()).addSoftApChannelSwitchedEvent(0, - SoftApInfo.CHANNEL_WIDTH_INVALID, apConfig.getTargetMode()); - } - - @Test - public void updatesConnectedClients() throws Exception { - InOrder order = inOrder(mCallback, mWifiMetrics); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - order.verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - order.verify(mCallback).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - } - - /** - * If SoftApManager gets an update for the number of connected clients that is the same, do not - * trigger callbacks a second time. - */ - @Test - public void testDoesNotTriggerCallbackForSameClients() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - // now trigger callback again, but we should have each method only called once - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - // Should just trigger 1 time callback, the first time will be happen when softap enable - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, false); - mLooper.dispatchAll(); - - // now trigger callback again, but we should have each method only called once - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, false); - mLooper.dispatchAll(); - - // Should just trigger 1 time callback to update to zero client. - // Should just trigger 1 time callback, the first time will be happen when softap enable - verify(mCallback, times(3)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.size() == 0) - ); - - verify(mWifiMetrics) - .addSoftApNumAssociatedStationsChangedEvent( - 0, apConfig.getTargetMode()); - - } - - @Test - public void stopDisconnectsConnectedClients() throws Exception { - InOrder order = inOrder(mCallback, mWifiMetrics); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - order.verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - order.verify(mCallback).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - - mSoftApManager.stop(); - mLooper.dispatchAll(); - - verify(mWifiNative).forceClientDisconnect(TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED); - } - - @Test - public void handlesInvalidConnectedClients() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - /* Invalid values should be ignored */ - final NativeWifiClient mInvalidClient = null; - mSoftApListenerCaptor.getValue().onConnectedClientsChanged(mInvalidClient, true); - mLooper.dispatchAll(); - verify(mCallback, never()).onConnectedClientsChanged(null); - verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent(anyInt(), - anyInt()); - } - - @Test - public void testCallbackForClientUpdateToZeroWhenLeaveSoftapStarted() throws Exception { - InOrder order = inOrder(mCallback, mWifiMetrics); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - order.verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - order.verify(mCallback).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - order.verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - mSoftApManager.stop(); - mLooper.dispatchAll(); - - order.verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - order.verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent(0, - apConfig.getTargetMode()); - // Verify timer is canceled after stop softap - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - } - - @Test - public void testClientConnectFailureWhenClientInBlcokedListAndClientAuthorizationDisabled() - throws Exception { - ArrayList<MacAddress> blockedClientList = new ArrayList<>(); - mTestSoftApCapability.setMaxSupportedClients(10); - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setClientControlByUserEnabled(false); - // Client in blocked list - blockedClientList.add(TEST_MAC_ADDRESS); - configBuilder.setBlockedClientList(blockedClientList); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - // Client is not allow verify - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - verify(mCallback, never()).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - } - - @Test - public void testClientDisconnectWhenClientInBlcokedLisUpdatedtAndClientAuthorizationDisabled() - throws Exception { - ArrayList<MacAddress> blockedClientList = new ArrayList<>(); - mTestSoftApCapability.setMaxSupportedClients(10); - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setClientControlByUserEnabled(false); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - // Client connected check - verify(mWifiNative, never()).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - reset(mCallback); - reset(mWifiNative); - // Update configuration - blockedClientList.add(TEST_MAC_ADDRESS); - configBuilder.setBlockedClientList(blockedClientList); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - // Client difconnected - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - // The callback should not trigger in configuration update case. - verify(mCallback, never()).onBlockedClientConnecting(TEST_CONNECTED_CLIENT, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - - } - - - - @Test - public void testForceClientDisconnectInvokeBecauseClientAuthorizationEnabled() - throws Exception { - mTestSoftApCapability.setMaxSupportedClients(10); - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setClientControlByUserEnabled(true); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - // Client is not allow verify - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - verify(mCallback, never()).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - } - - @Test - public void testClientConnectedAfterUpdateToAllowListwhenClientAuthorizationEnabled() - throws Exception { - mTestSoftApCapability.setMaxSupportedClients(10); - ArrayList<MacAddress> allowedClientList = new ArrayList<>(); - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setClientControlByUserEnabled(true); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - // Client is not allow verify - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - verify(mCallback, never()).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - verify(mCallback).onBlockedClientConnecting(TEST_CONNECTED_CLIENT, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - reset(mCallback); - reset(mWifiNative); - // Update configuration - allowedClientList.add(TEST_MAC_ADDRESS); - configBuilder.setAllowedClientList(allowedClientList); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - // Client connected again - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - verify(mWifiNative, never()).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - verify(mCallback).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - verify(mCallback, never()).onBlockedClientConnecting(TEST_CONNECTED_CLIENT, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - } - - @Test - public void testClientConnectedAfterUpdateToBlockListwhenClientAuthorizationEnabled() - throws Exception { - mTestSoftApCapability.setMaxSupportedClients(10); - ArrayList<MacAddress> blockedClientList = new ArrayList<>(); - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setClientControlByUserEnabled(true); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - // Client is not allow verify - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - verify(mCallback, never()).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - verify(mCallback).onBlockedClientConnecting(TEST_CONNECTED_CLIENT, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - reset(mCallback); - reset(mWifiNative); - // Update configuration - blockedClientList.add(TEST_MAC_ADDRESS); - configBuilder.setBlockedClientList(blockedClientList); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - // Client connected again - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - verify(mCallback, never()).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - verify(mCallback, never()).onBlockedClientConnecting(TEST_CONNECTED_CLIENT, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - } - - @Test - public void testConfigChangeToSmallAndClientAddBlockListCauseClientDisconnect() - throws Exception { - mTestSoftApCapability.setMaxSupportedClients(10); - ArrayList<MacAddress> allowedClientList = new ArrayList<>(); - allowedClientList.add(TEST_MAC_ADDRESS); - allowedClientList.add(TEST_MAC_ADDRESS_2); - ArrayList<MacAddress> blockedClientList = new ArrayList<>(); - - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setClientControlByUserEnabled(true); - configBuilder.setMaxNumberOfClients(2); - configBuilder.setAllowedClientList(allowedClientList); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - // Second client connect and max client set is 1. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - - verify(mCallback, times(3)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT_2)) - ); - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 2, apConfig.getTargetMode()); - reset(mCallback); - reset(mWifiNative); - // Update configuration - allowedClientList.clear(); - allowedClientList.add(TEST_MAC_ADDRESS_2); - - blockedClientList.add(TEST_MAC_ADDRESS); - configBuilder.setBlockedClientList(blockedClientList); - configBuilder.setAllowedClientList(allowedClientList); - configBuilder.setMaxNumberOfClients(1); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER); - verify(mWifiNative, never()).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS); - } - - - @Test - public void schedulesTimeoutTimerOnStart() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - verify(mResources) - .getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - - // Verify timer is scheduled - verify(mAlarmManager.getAlarmManager()).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - } - - @Test - public void schedulesTimeoutTimerOnStartWithConfigedValue() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setShutdownTimeoutMillis(50000); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - // Verify timer is scheduled - verify(mAlarmManager.getAlarmManager()).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - } - - @Test - public void cancelsTimeoutTimerOnStop() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - mSoftApManager.stop(); - mLooper.dispatchAll(); - - // Verify timer is canceled - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - } - - @Test - public void cancelsTimeoutTimerOnNewClientsConnect() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - // Verify timer is canceled - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - } - - @Test - public void schedulesTimeoutTimerWhenAllClientsDisconnect() throws Exception { - InOrder order = inOrder(mCallback, mWifiMetrics); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - order.verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - order.verify(mCallback).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged(TEST_NATIVE_CLIENT, false); - mLooper.dispatchAll(); - // Verify timer is scheduled again - verify(mAlarmManager.getAlarmManager(), times(2)).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - } - - @Test - public void stopsSoftApOnTimeoutMessage() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - doNothing().when(mFakeSoftApNotifier) - .showSoftApShutDownTimeoutExpiredNotification(); - mAlarmManager.dispatch(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG); - mLooper.dispatchAll(); - - verify(mWifiNative).teardownInterface(TEST_INTERFACE_NAME); - verify(mFakeSoftApNotifier).showSoftApShutDownTimeoutExpiredNotification(); - } - - @Test - public void cancelsTimeoutTimerOnTimeoutToggleChangeWhenNoClients() throws Exception { - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - SoftApConfiguration newConfig = new SoftApConfiguration.Builder(mDefaultApConfig) - .setAutoShutdownEnabled(false) - .build(); - mSoftApManager.updateConfiguration(newConfig); - mLooper.dispatchAll(); - - // Verify timer is canceled - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - } - - @Test - public void schedulesTimeoutTimerOnTimeoutToggleChangeWhenNoClients() throws Exception { - // start with timeout toggle disabled - mDefaultApConfig = new SoftApConfiguration.Builder(mDefaultApConfig) - .setAutoShutdownEnabled(false) - .build(); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - SoftApConfiguration newConfig = new SoftApConfiguration.Builder(mDefaultApConfig) - .setAutoShutdownEnabled(true) - .build(); - mSoftApManager.updateConfiguration(newConfig); - mLooper.dispatchAll(); - - // Verify timer is scheduled - verify(mAlarmManager.getAlarmManager()).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - } - - @Test - public void doesNotScheduleTimeoutTimerOnStartWhenTimeoutIsDisabled() throws Exception { - // start with timeout toggle disabled - mDefaultApConfig = new SoftApConfiguration.Builder(mDefaultApConfig) - .setAutoShutdownEnabled(false) - .build(); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - // Verify timer is not scheduled - verify(mAlarmManager.getAlarmManager(), never()).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - } - - @Test - public void doesNotScheduleTimeoutTimerWhenAllClientsDisconnectButTimeoutIsDisabled() - throws Exception { - // start with timeout toggle disabled - mDefaultApConfig = new SoftApConfiguration.Builder(mDefaultApConfig) - .setAutoShutdownEnabled(false) - .build(); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - // add client - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - // remove client - mSoftApListenerCaptor.getValue() - .onConnectedClientsChanged(TEST_NATIVE_CLIENT, false); - mLooper.dispatchAll(); - // Verify timer is not scheduled - verify(mAlarmManager.getAlarmManager(), never()).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - } - - @Test - public void resetsFactoryMacWhenRandomizationOff() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setBssid(null); - - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), mTestSoftApCapability); - ArgumentCaptor<MacAddress> mac = ArgumentCaptor.forClass(MacAddress.class); - when(mWifiNative.getFactoryMacAddress(TEST_INTERFACE_NAME)).thenReturn(TEST_MAC_ADDRESS); - when(mWifiNative.setMacAddress(eq(TEST_INTERFACE_NAME), mac.capture())).thenReturn(true); - - startSoftApAndVerifyEnabled(apConfig); - - assertThat(mac.getValue()).isEqualTo(TEST_MAC_ADDRESS); - } - - @Test - public void setsCustomMac() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setBssid(MacAddress.fromString("23:34:45:56:67:78")); - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - IFACE_IP_MODE_LOCAL_ONLY, configBuilder.build(), mTestSoftApCapability); - ArgumentCaptor<MacAddress> mac = ArgumentCaptor.forClass(MacAddress.class); - when(mWifiNative.setMacAddress(eq(TEST_INTERFACE_NAME), mac.capture())).thenReturn(true); - - startSoftApAndVerifyEnabled(apConfig); - - assertThat(mac.getValue()).isEqualTo(MacAddress.fromString("23:34:45:56:67:78")); - } - - @Test - public void setsCustomMacWhenSetMacNotSupport() throws Exception { - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - when(mWifiNative.isSetMacAddressSupported(any())).thenReturn(false); - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setBssid(MacAddress.fromString("23:34:45:56:67:78")); - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - IFACE_IP_MODE_LOCAL_ONLY, configBuilder.build(), mTestSoftApCapability); - ArgumentCaptor<MacAddress> mac = ArgumentCaptor.forClass(MacAddress.class); - - mSoftApManager = createSoftApManager(apConfig, TEST_COUNTRY_CODE); - mSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION); - verify(mWifiNative, never()).setMacAddress(any(), any()); - } - - @Test - public void setMacFailureWhenCustomMac() throws Exception { - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setBssid(MacAddress.fromString("23:34:45:56:67:78")); - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - IFACE_IP_MODE_LOCAL_ONLY, configBuilder.build(), mTestSoftApCapability); - ArgumentCaptor<MacAddress> mac = ArgumentCaptor.forClass(MacAddress.class); - when(mWifiNative.setMacAddress(eq(TEST_INTERFACE_NAME), mac.capture())).thenReturn(false); - - mSoftApManager = createSoftApManager(apConfig, TEST_COUNTRY_CODE); - mSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - assertThat(mac.getValue()).isEqualTo(MacAddress.fromString("23:34:45:56:67:78")); - } - - @Test - public void setMacFailureWhenRandomMac() throws Exception { - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - when(mWifiApConfigStore.getApConfiguration()).thenReturn(mDefaultApConfig); - SoftApConfiguration randomizedBssidConfig = - new SoftApConfiguration.Builder(mDefaultApConfig) - .setBssid(TEST_MAC_ADDRESS).build(); - when(mWifiApConfigStore.randomizeBssidIfUnset(any(), any())).thenReturn( - randomizedBssidConfig); - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - IFACE_IP_MODE_LOCAL_ONLY, null, mTestSoftApCapability); - ArgumentCaptor<MacAddress> mac = ArgumentCaptor.forClass(MacAddress.class); - when(mWifiNative.setMacAddress(eq(TEST_INTERFACE_NAME), mac.capture())).thenReturn(false); - mSoftApManager = createSoftApManager(apConfig, TEST_COUNTRY_CODE); - mSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - } - - @Test - public void setRandomMacWhenSetMacNotsupport() throws Exception { - when(mWifiNative.isSetMacAddressSupported(any())).thenReturn(false); - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - IFACE_IP_MODE_LOCAL_ONLY, null, mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - verify(mWifiNative, never()).setMacAddress(any(), any()); - } - - @Test - public void testForceClientDisconnectInvokeBecauseReachMaxClient() throws Exception { - mTestSoftApCapability.setMaxSupportedClients(1); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - // Second client connect and max client set is 1. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS_2, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS); - verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent( - 2, apConfig.getTargetMode()); - // Trigger connection again - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - // Verify just update metrics one time - verify(mWifiMetrics).noteSoftApClientBlocked(1); - } - - @Test - public void testCapabilityChangeToSmallCauseClientDisconnect() throws Exception { - mTestSoftApCapability.setMaxSupportedClients(2); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - // Second client connect and max client set is 1. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - - verify(mCallback, times(3)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT_2)) - ); - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 2, apConfig.getTargetMode()); - - // Trigger Capability Change - mTestSoftApCapability.setMaxSupportedClients(1); - mSoftApManager.updateCapability(mTestSoftApCapability); - mLooper.dispatchAll(); - // Verify Disconnect will trigger - verify(mWifiNative).forceClientDisconnect( - any(), any(), anyInt()); - } - - @Test - public void testCapabilityChangeNotApplyForLohsMode() throws Exception { - mTestSoftApCapability.setMaxSupportedClients(2); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null, - mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - // Second client connect and max client set is 1. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - - verify(mCallback, times(3)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT_2)) - ); - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 2, apConfig.getTargetMode()); - - // Trigger Capability Change - mTestSoftApCapability.setMaxSupportedClients(1); - mSoftApManager.updateCapability(mTestSoftApCapability); - mLooper.dispatchAll(); - // Verify Disconnect will NOT trigger even capability changed - verify(mWifiNative, never()).forceClientDisconnect( - any(), any(), anyInt()); - } - - /** Starts soft AP and verifies that it is enabled successfully. */ - protected void startSoftApAndVerifyEnabled( - SoftApModeConfiguration softApConfig) throws Exception { - startSoftApAndVerifyEnabled(softApConfig, TEST_COUNTRY_CODE); - } - - /** Starts soft AP and verifies that it is enabled successfully. */ - protected void startSoftApAndVerifyEnabled( - SoftApModeConfiguration softApConfig, String countryCode) throws Exception { - // The expected config to pass to Native - SoftApConfiguration expectedConfig = null; - // The config which base on mDefaultApConfig and generate ramdonized mac address - SoftApConfiguration randomizedBssidConfig = null; - InOrder order = inOrder(mCallback, mWifiNative); - - SoftApConfiguration config = softApConfig.getSoftApConfiguration(); - if (config == null) { - // Only generate randomized mac for default config since test case doesn't care it. - when(mWifiApConfigStore.getApConfiguration()).thenReturn(mDefaultApConfig); - randomizedBssidConfig = - new SoftApConfiguration.Builder(mDefaultApConfig) - .setBssid(TEST_MAC_ADDRESS).build(); - when(mWifiApConfigStore.randomizeBssidIfUnset(any(), any())).thenReturn( - randomizedBssidConfig); - expectedConfig = new SoftApConfiguration.Builder(randomizedBssidConfig) - .setChannel(DEFAULT_AP_CHANNEL, SoftApConfiguration.BAND_2GHZ) - .build(); - } else { - expectedConfig = new SoftApConfiguration.Builder(config) - .setChannel(DEFAULT_AP_CHANNEL, SoftApConfiguration.BAND_2GHZ) - .build(); - } - mSoftApManager = createSoftApManager(softApConfig, countryCode); - mSoftApManager.mSoftApNotifier = mFakeSoftApNotifier; - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - - when(mWifiNative.setupInterfaceForSoftApMode(any())) - .thenReturn(TEST_INTERFACE_NAME); - - - mSoftApManager.start(); - mSoftApManager.setRole(ActiveModeManager.ROLE_SOFTAP_TETHERED); - mLooper.dispatchAll(); - verify(mFakeSoftApNotifier).dismissSoftApShutDownTimeoutExpiredNotification(); - order.verify(mWifiNative).setupInterfaceForSoftApMode( - mWifiNativeInterfaceCallbackCaptor.capture()); - ArgumentCaptor<SoftApConfiguration> configCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); - order.verify(mWifiNative).startSoftAp(eq(TEST_INTERFACE_NAME), - configCaptor.capture(), mSoftApListenerCaptor.capture()); - assertThat(configCaptor.getValue()).isEqualTo(expectedConfig); - mWifiNativeInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME); - mLooper.dispatchAll(); - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0); - order.verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - verify(mSarManager).setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED); - verify(mWifiDiagnostics).startLogging(TEST_INTERFACE_NAME); - verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - List<Intent> capturedIntents = intentCaptor.getAllValues(); - checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING, - WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_ENABLED, - WIFI_AP_STATE_ENABLING, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApConfig.getTargetMode()); - verify(mListener).onStarted(); - verify(mWifiMetrics).addSoftApUpChangedEvent(true, softApConfig.getTargetMode(), - TEST_DEFAULT_SHUTDOWN_TIMEOUT_MILLS); - verify(mWifiMetrics).updateSoftApConfiguration(config == null - ? randomizedBssidConfig : config, softApConfig.getTargetMode()); - verify(mWifiMetrics).updateSoftApCapability(softApConfig.getCapability(), - softApConfig.getTargetMode()); - } - - private void checkApStateChangedBroadcast(Intent intent, int expectedCurrentState, - int expectedPrevState, int expectedErrorCode, - String expectedIfaceName, int expectedMode) { - int currentState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); - int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); - int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON, HOTSPOT_NO_ERROR); - String ifaceName = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME); - int mode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, WifiManager.IFACE_IP_MODE_UNSPECIFIED); - assertEquals(expectedCurrentState, currentState); - assertEquals(expectedPrevState, prevState); - assertEquals(expectedErrorCode, errorCode); - assertEquals(expectedIfaceName, ifaceName); - assertEquals(expectedMode, mode); - } - - @Test - public void testForceClientDisconnectNotInvokeWhenNotSupport() throws Exception { - long testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_WPA3_SAE - | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD; - SoftApCapability noClientControlCapability = new SoftApCapability(testSoftApFeature); - noClientControlCapability.setMaxSupportedClients(1); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - noClientControlCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - // Second client connect and max client set is 1. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - // feature not support thus it should not trigger disconnect - verify(mWifiNative, never()).forceClientDisconnect( - any(), any(), anyInt()); - // feature not support thus client still allow connected. - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 2, apConfig.getTargetMode()); - } - - @Test - public void testSoftApEnableFailureBecauseSetMaxClientWhenNotSupport() throws Exception { - long testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_WPA3_SAE - | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD; - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - SoftApCapability noClientControlCapability = new SoftApCapability(testSoftApFeature); - noClientControlCapability.setMaxSupportedClients(1); - SoftApConfiguration softApConfig = new SoftApConfiguration.Builder( - mDefaultApConfig).setMaxNumberOfClients(1).build(); - - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, softApConfig, - noClientControlCapability); - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - TEST_COUNTRY_CODE, - mListener, - mCallback, - mWifiApConfigStore, - apConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION); - verify(mWifiMetrics).incrementSoftApStartResult(false, - WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION); - verify(mListener).onStartFailure(); - } - - @Test - public void testSoftApEnableFailureBecauseSecurityTypeSaeSetupButSaeNotSupport() - throws Exception { - long testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT - | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD; - when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); - SoftApCapability noSaeCapability = new SoftApCapability(testSoftApFeature); - SoftApConfiguration softApConfig = new SoftApConfiguration.Builder( - mDefaultApConfig).setPassphrase(TEST_PASSWORD, - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE).build(); - - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, softApConfig, - noSaeCapability); - SoftApManager newSoftApManager = new SoftApManager(mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, - TEST_COUNTRY_CODE, - mListener, - mCallback, - mWifiApConfigStore, - apConfig, - mWifiMetrics, - mSarManager, - mWifiDiagnostics); - mLooper.dispatchAll(); - newSoftApManager.start(); - mLooper.dispatchAll(); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); - verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION); - verify(mListener).onStartFailure(); - } - - @Test - public void testConfigurationChangedApplySinceDoesNotNeedToRestart() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - // Verify timer is scheduled - verify(mAlarmManager.getAlarmManager()).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - verify(mWifiMetrics).updateSoftApConfiguration(configBuilder.build(), - WifiManager.IFACE_IP_MODE_TETHERED); - - mLooper.dispatchAll(); - - // Trigger Configuration Change - configBuilder.setShutdownTimeoutMillis(500000); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - // Verify timer is canceled at this point since timeout changed - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - // Verify timer setup again - verify(mAlarmManager.getAlarmManager(), times(2)).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - verify(mWifiMetrics).updateSoftApConfiguration(configBuilder.build(), - WifiManager.IFACE_IP_MODE_TETHERED); - - } - - @Test - public void testConfigurationChangedDoesNotApplySinceNeedToRestart() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - - SoftApModeConfiguration apConfig = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - // Verify timer is scheduled - verify(mAlarmManager.getAlarmManager()).setExact(anyInt(), anyLong(), - eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG), any(), any()); - - mLooper.dispatchAll(); - - // Trigger Configuration Change - configBuilder.setShutdownTimeoutMillis(500000); - configBuilder.setSsid(TEST_SSID + "new"); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - // Verify timer cancel will not apply since changed config need to apply via restart. - verify(mAlarmManager.getAlarmManager(), never()).cancel(any(WakeupMessage.class)); - } - - @Test - public void testConfigChangeToSmallCauseClientDisconnect() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setMaxNumberOfClients(2); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - // Second client connect and max client set is 2. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - - verify(mCallback, times(3)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT_2)) - ); - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 2, apConfig.getTargetMode()); - - // Trigger Configuration Change - configBuilder.setMaxNumberOfClients(1); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - // Verify Disconnect will trigger - verify(mWifiNative).forceClientDisconnect( - any(), any(), anyInt()); - } - - @Test - public void testConfigChangeWillTriggerUpdateMetricsAgain() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); - configBuilder.setSsid(TEST_SSID); - configBuilder.setMaxNumberOfClients(1); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, - configBuilder.build(), mTestSoftApCapability); - startSoftApAndVerifyEnabled(apConfig); - - verify(mCallback).onConnectedClientsChanged(new ArrayList<>()); - - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - - verify(mCallback, times(2)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT)) - ); - - verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent( - 1, apConfig.getTargetMode()); - // Verify timer is canceled at this point - verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class)); - - // Second client connect and max client set is 1. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - verify(mWifiNative).forceClientDisconnect( - TEST_INTERFACE_NAME, TEST_MAC_ADDRESS_2, - WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS); - - // Verify update metrics - verify(mWifiMetrics).noteSoftApClientBlocked(1); - - // Trigger Configuration Change - configBuilder.setMaxNumberOfClients(2); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - - // Second client connect and max client set is 2. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT_2, true); - mLooper.dispatchAll(); - verify(mCallback, times(3)).onConnectedClientsChanged( - Mockito.argThat((List<WifiClient> clients) -> - clients.contains(TEST_CONNECTED_CLIENT_2)) - ); - - // Trigger Configuration Change - configBuilder.setMaxNumberOfClients(1); - mSoftApManager.updateConfiguration(configBuilder.build()); - mLooper.dispatchAll(); - // Let client disconnect due to maximum number change to small. - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, false); - mLooper.dispatchAll(); - - // Trigger connection again - mSoftApListenerCaptor.getValue().onConnectedClientsChanged( - TEST_NATIVE_CLIENT, true); - mLooper.dispatchAll(); - // Verify just update metrics one time - verify(mWifiMetrics, times(2)).noteSoftApClientBlocked(1); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApNotifierTest.java deleted file mode 100644 index 3d4d23998..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SoftApNotifierTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Notification; -import android.app.NotificationManager; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Answers; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.SoftApNotifier}. - */ -@SmallTest -public class SoftApNotifierTest extends WifiBaseTest { - private static final String TEST_SSID = "Test SSID"; - - @Mock WifiContext mContext; - @Mock Resources mResources; - @Mock NotificationManager mNotificationManager; - @Mock FrameworkFacade mFrameworkFacade; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Notification.Builder mNotificationBuilder; - SoftApNotifier mSoftApNotifier; - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mContext.getSystemService(NotificationManager.class)) - .thenReturn(mNotificationManager); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources"); - mSoftApNotifier = new SoftApNotifier(mContext, mFrameworkFacade); - } - - /** - * Verify that a shutdown timeout expired notification will be generated/pushed when calling. - * - * @throws Exception - */ - @Test - public void showSoftApShutDownTimeoutExpiredNotification() throws Exception { - when(mFrameworkFacade.makeNotificationBuilder(any(), - eq(WifiService.NOTIFICATION_NETWORK_STATUS))).thenReturn(mNotificationBuilder); - mSoftApNotifier.showSoftApShutDownTimeoutExpiredNotification(); - verify(mNotificationManager).notify( - eq(mSoftApNotifier.NOTIFICATION_ID_SOFTAP_AUTO_DISABLED), any()); - ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); - verify(mFrameworkFacade).getActivity( - any(Context.class), anyInt(), intent.capture(), anyInt()); - assertEquals(mSoftApNotifier.ACTION_HOTSPOT_PREFERENCES, intent.getValue().getAction()); - } - - /** - * Verify that we don't attempt to dismiss the wrong password notification when starting a new - * connection attempt with the previous connection not resulting in a wrong password error. - * - * @throws Exception - */ - @Test - public void dismissSoftApShutDownTimeoutExpiredNotification() throws Exception { - mSoftApNotifier.dismissSoftApShutDownTimeoutExpiredNotification(); - verify(mNotificationManager).cancel(any(), - eq(mSoftApNotifier.NOTIFICATION_ID_SOFTAP_AUTO_DISABLED)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java deleted file mode 100644 index 739987106..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -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.MacAddress; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiMigration; -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.util.SettingsMigrationDataHolder; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; - -/** - * Unit tests for {@link com.android.server.wifi.SoftApStoreData}. - */ -@SmallTest -public class SoftApStoreDataTest extends WifiBaseTest { - private static final String TEST_SSID = "SSID"; - private static final String TEST_BSSID = "11:22:33:aa:bb:cc"; - private static final String TEST_PASSPHRASE = "TestPassphrase"; - private static final String TEST_WPA2_PASSPHRASE = "Wpa2Test"; - private static final int TEST_CHANNEL = 0; - private static final boolean TEST_HIDDEN = false; - private static final int TEST_BAND = SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_5GHZ; - private static final int TEST_OLD_BAND = WifiConfiguration.AP_BAND_ANY; - private static final int TEST_SECURITY = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK; - private static final boolean TEST_CLIENT_CONTROL_BY_USER = false; - private static final boolean TEST_AUTO_SHUTDOWN_ENABLED = true; - private static final int TEST_MAX_NUMBER_OF_CLIENTS = 10; - private static final long TEST_SHUTDOWN_TIMEOUT_MILLIS = 600_000; - private static final ArrayList<MacAddress> TEST_BLOCKEDLIST = new ArrayList<>(); - private static final String TEST_BLOCKED_CLIENT = "11:22:33:44:55:66"; - private static final ArrayList<MacAddress> TEST_ALLOWEDLIST = new ArrayList<>(); - private static final String TEST_ALLOWED_CLIENT = "aa:bb:cc:dd:ee:ff"; - - private static final String TEST_SOFTAP_CONFIG_XML_STRING = - "<string name=\"SSID\">" + TEST_SSID + "</string>\n" - + "<int name=\"Band\" value=\"" + TEST_OLD_BAND + "\" />\n" - + "<int name=\"Channel\" value=\"" + TEST_CHANNEL + "\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"" + TEST_HIDDEN + "\" />\n" - + "<int name=\"SecurityType\" value=\"" + TEST_SECURITY + "\" />\n" - + "<string name=\"Wpa2Passphrase\">" + TEST_WPA2_PASSPHRASE + "</string>\n"; - - private static final String TEST_SOFTAP_CONFIG_XML_STRING_WITH_NEW_BAND_DESIGN = - "<string name=\"SSID\">" + TEST_SSID + "</string>\n" - + "<int name=\"ApBand\" value=\"" + TEST_BAND + "\" />\n" - + "<int name=\"Channel\" value=\"" + TEST_CHANNEL + "\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"" + TEST_HIDDEN + "\" />\n" - + "<int name=\"SecurityType\" value=\"" + TEST_SECURITY + "\" />\n" - + "<string name=\"Passphrase\">" + TEST_PASSPHRASE + "</string>\n"; - - private static final String TEST_SOFTAP_CONFIG_XML_STRING_WITH_ALL_CONFIG = - "<string name=\"SSID\">" + TEST_SSID + "</string>\n" - + "<string name=\"Bssid\">" + TEST_BSSID + "</string>\n" - + "<int name=\"ApBand\" value=\"" + TEST_BAND + "\" />\n" - + "<int name=\"Channel\" value=\"" + TEST_CHANNEL + "\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"" + TEST_HIDDEN + "\" />\n" - + "<int name=\"SecurityType\" value=\"" + TEST_SECURITY + "\" />\n" - + "<string name=\"Passphrase\">" + TEST_PASSPHRASE + "</string>\n" - + "<int name=\"MaxNumberOfClients\" value=\"" - + TEST_MAX_NUMBER_OF_CLIENTS + "\" />\n" - + "<boolean name=\"ClientControlByUser\" value=\"" - + TEST_CLIENT_CONTROL_BY_USER + "\" />\n" - + "<boolean name=\"AutoShutdownEnabled\" value=\"" - + TEST_AUTO_SHUTDOWN_ENABLED + "\" />\n" - + "<long name=\"ShutdownTimeoutMillis\" value=\"" - + TEST_SHUTDOWN_TIMEOUT_MILLIS + "\" />\n" - + "<BlockedClientList>\n" - + "<string name=\"ClientMacAddress\">" + TEST_BLOCKED_CLIENT + "</string>\n" - + "</BlockedClientList>\n" - + "<AllowedClientList>\n" - + "<string name=\"ClientMacAddress\">" + TEST_ALLOWED_CLIENT + "</string>\n" - + "</AllowedClientList>\n"; - - private static final String TEST_SOFTAP_CONFIG_XML_STRING_WITH_ALL_CONFIG_EXCEPT_AUTO_SHUTDOWN = - "<string name=\"SSID\">" + TEST_SSID + "</string>\n" - + "<int name=\"ApBand\" value=\"" + TEST_BAND + "\" />\n" - + "<int name=\"Channel\" value=\"" + TEST_CHANNEL + "\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"" + TEST_HIDDEN + "\" />\n" - + "<int name=\"SecurityType\" value=\"" + TEST_SECURITY + "\" />\n" - + "<string name=\"Passphrase\">" + TEST_PASSPHRASE + "</string>\n" - + "<int name=\"MaxNumberOfClients\" value=\"" - + TEST_MAX_NUMBER_OF_CLIENTS + "\" />\n" - + "<boolean name=\"ClientControlByUser\" value=\"" - + TEST_CLIENT_CONTROL_BY_USER + "\" />\n" - + "<long name=\"ShutdownTimeoutMillis\" value=\"" - + TEST_SHUTDOWN_TIMEOUT_MILLIS + "\" />\n" - + "<BlockedClientList>\n" - + "<string name=\"ClientMacAddress\">" + TEST_BLOCKED_CLIENT + "</string>\n" - + "</BlockedClientList>\n" - + "<AllowedClientList>\n" - + "<string name=\"ClientMacAddress\">" + TEST_ALLOWED_CLIENT + "</string>\n" - + "</AllowedClientList>\n"; - - private static final String TEST_SOFTAP_CONFIG_XML_STRING_WITH_INT_TYPE_SHUTDOWNTIMOUTMILLIS = - "<string name=\"SSID\">" + TEST_SSID + "</string>\n" - + "<int name=\"ApBand\" value=\"" + TEST_BAND + "\" />\n" - + "<int name=\"Channel\" value=\"" + TEST_CHANNEL + "\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"" + TEST_HIDDEN + "\" />\n" - + "<int name=\"SecurityType\" value=\"" + TEST_SECURITY + "\" />\n" - + "<string name=\"Passphrase\">" + TEST_PASSPHRASE + "</string>\n" - + "<int name=\"MaxNumberOfClients\" value=\"" - + TEST_MAX_NUMBER_OF_CLIENTS + "\" />\n" - + "<boolean name=\"ClientControlByUser\" value=\"" - + TEST_CLIENT_CONTROL_BY_USER + "\" />\n" - + "<boolean name=\"AutoShutdownEnabled\" value=\"" - + TEST_AUTO_SHUTDOWN_ENABLED + "\" />\n" - + "<int name=\"ShutdownTimeoutMillis\" value=\"" - + TEST_SHUTDOWN_TIMEOUT_MILLIS + "\" />\n" - + "<BlockedClientList>\n" - + "<string name=\"ClientMacAddress\">" + TEST_BLOCKED_CLIENT + "</string>\n" - + "</BlockedClientList>\n" - + "<AllowedClientList>\n" - + "<string name=\"ClientMacAddress\">" + TEST_ALLOWED_CLIENT + "</string>\n" - + "</AllowedClientList>\n"; - - private static final String TEST_SOFTAP_CONFIG_XML_STRING_WITH_ALL_CONFIG_EXCEPT_BSSID = - "<string name=\"SSID\">" + TEST_SSID + "</string>\n" - + "<int name=\"ApBand\" value=\"" + TEST_BAND + "\" />\n" - + "<int name=\"Channel\" value=\"" + TEST_CHANNEL + "\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"" + TEST_HIDDEN + "\" />\n" - + "<int name=\"SecurityType\" value=\"" + TEST_SECURITY + "\" />\n" - + "<string name=\"Passphrase\">" + TEST_PASSPHRASE + "</string>\n" - + "<int name=\"MaxNumberOfClients\" value=\"" - + TEST_MAX_NUMBER_OF_CLIENTS + "\" />\n" - + "<boolean name=\"ClientControlByUser\" value=\"" - + TEST_CLIENT_CONTROL_BY_USER + "\" />\n" - + "<boolean name=\"AutoShutdownEnabled\" value=\"" - + TEST_AUTO_SHUTDOWN_ENABLED + "\" />\n" - + "<int name=\"ShutdownTimeoutMillis\" value=\"" - + TEST_SHUTDOWN_TIMEOUT_MILLIS + "\" />\n" - + "<BlockedClientList>\n" - + "<string name=\"ClientMacAddress\">" + TEST_BLOCKED_CLIENT + "</string>\n" - + "</BlockedClientList>\n" - + "<AllowedClientList>\n" - + "<string name=\"ClientMacAddress\">" + TEST_ALLOWED_CLIENT + "</string>\n" - + "</AllowedClientList>\n"; - - @Mock private Context mContext; - @Mock SoftApStoreData.DataSource mDataSource; - @Mock private WifiMigration.SettingsMigrationData mOemMigrationData; - @Mock private SettingsMigrationDataHolder mSettingsMigrationDataHolder; - SoftApStoreData mSoftApStoreData; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mSettingsMigrationDataHolder.retrieveData()) - .thenReturn(mOemMigrationData); - when(mOemMigrationData.isSoftApTimeoutEnabled()).thenReturn(true); - - mSoftApStoreData = new SoftApStoreData(mContext, mSettingsMigrationDataHolder, mDataSource); - TEST_BLOCKEDLIST.add(MacAddress.fromString(TEST_BLOCKED_CLIENT)); - TEST_ALLOWEDLIST.add(MacAddress.fromString(TEST_ALLOWED_CLIENT)); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - TEST_BLOCKEDLIST.clear(); - TEST_ALLOWEDLIST.clear(); - } - - /** - * Helper function for serializing configuration data to a XML block. - * - * @return byte[] of the XML data - * @throws Exception - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mSoftApStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing configuration data from a XML block. - * - * @param data XML data to parse from - * @throws Exception - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mSoftApStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - } - - /** - * Verify that parsing an empty data doesn't cause any crash and no configuration should - * be deserialized. - * - * @throws Exception - */ - @Test - public void deserializeEmptyStoreData() throws Exception { - deserializeData(new byte[0]); - verify(mDataSource, never()).fromDeserialized(any()); - } - - /** - * Verify that SoftApStoreData is written to - * {@link WifiConfigStore#STORE_FILE_SHARED_SOFTAP}. - * - * @throws Exception - */ - @Test - public void getUserStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_SHARED_SOFTAP, - mSoftApStoreData.getStoreFileId()); - } - - /** - * Verify that the store data is serialized correctly, matches the predefined test XML data. - * - * @throws Exception - */ - @Test - public void serializeSoftAp() throws Exception { - SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder(); - softApConfigBuilder.setSsid(TEST_SSID); - softApConfigBuilder.setBssid(MacAddress.fromString(TEST_BSSID)); - softApConfigBuilder.setPassphrase(TEST_PASSPHRASE, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - softApConfigBuilder.setBand(TEST_BAND); - softApConfigBuilder.setClientControlByUserEnabled(TEST_CLIENT_CONTROL_BY_USER); - softApConfigBuilder.setMaxNumberOfClients(TEST_MAX_NUMBER_OF_CLIENTS); - softApConfigBuilder.setAutoShutdownEnabled(true); - softApConfigBuilder.setShutdownTimeoutMillis(TEST_SHUTDOWN_TIMEOUT_MILLIS); - softApConfigBuilder.setAllowedClientList(TEST_ALLOWEDLIST); - softApConfigBuilder.setBlockedClientList(TEST_BLOCKEDLIST); - - when(mDataSource.toSerialize()).thenReturn(softApConfigBuilder.build()); - byte[] actualData = serializeData(); - assertEquals(TEST_SOFTAP_CONFIG_XML_STRING_WITH_ALL_CONFIG, new String(actualData)); - } - - /** - * Verify that the store data is deserialized correctly using the predefined test XML data. - * - * @throws Exception - */ - @Test - public void deserializeSoftAp() throws Exception { - deserializeData(TEST_SOFTAP_CONFIG_XML_STRING_WITH_ALL_CONFIG.getBytes()); - - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfig = softapConfigCaptor.getValue(); - assertNotNull(softApConfig); - assertEquals(softApConfig.getSsid(), TEST_SSID); - assertEquals(softApConfig.getBssid().toString(), TEST_BSSID); - assertEquals(softApConfig.getPassphrase(), TEST_PASSPHRASE); - assertEquals(softApConfig.getSecurityType(), SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertEquals(softApConfig.isHiddenSsid(), TEST_HIDDEN); - assertEquals(softApConfig.getBand(), TEST_BAND); - assertEquals(softApConfig.isClientControlByUserEnabled(), TEST_CLIENT_CONTROL_BY_USER); - assertEquals(softApConfig.getMaxNumberOfClients(), TEST_MAX_NUMBER_OF_CLIENTS); - assertTrue(softApConfig.isAutoShutdownEnabled()); - assertEquals(softApConfig.getShutdownTimeoutMillis(), TEST_SHUTDOWN_TIMEOUT_MILLIS); - assertEquals(softApConfig.getBlockedClientList(), TEST_BLOCKEDLIST); - assertEquals(softApConfig.getAllowedClientList(), TEST_ALLOWEDLIST); - } - - /** - * Verify that the store data is deserialized correctly using the predefined test XML data. - * - * @throws Exception - */ - @Test - public void deserializeOldSoftApXMLWhichShutdownTimeoutIsInt() throws Exception { - deserializeData(TEST_SOFTAP_CONFIG_XML_STRING_WITH_INT_TYPE_SHUTDOWNTIMOUTMILLIS - .getBytes()); - - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfig = softapConfigCaptor.getValue(); - assertNotNull(softApConfig); - assertEquals(softApConfig.getSsid(), TEST_SSID); - assertEquals(softApConfig.getPassphrase(), TEST_PASSPHRASE); - assertEquals(softApConfig.getSecurityType(), SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertEquals(softApConfig.isHiddenSsid(), TEST_HIDDEN); - assertEquals(softApConfig.getBand(), TEST_BAND); - assertEquals(softApConfig.isClientControlByUserEnabled(), TEST_CLIENT_CONTROL_BY_USER); - assertEquals(softApConfig.getMaxNumberOfClients(), TEST_MAX_NUMBER_OF_CLIENTS); - assertTrue(softApConfig.isAutoShutdownEnabled()); - assertEquals(softApConfig.getShutdownTimeoutMillis(), TEST_SHUTDOWN_TIMEOUT_MILLIS); - assertEquals(softApConfig.getBlockedClientList(), TEST_BLOCKEDLIST); - assertEquals(softApConfig.getAllowedClientList(), TEST_ALLOWEDLIST); - } - - /** - * Verify that the old format is deserialized correctly. - * - * @throws Exception - */ - @Test - public void deserializeOldBandSoftAp() throws Exception { - // Start with the old serialized data - deserializeData(TEST_SOFTAP_CONFIG_XML_STRING.getBytes()); - - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfig = softapConfigCaptor.getValue(); - assertNotNull(softApConfig); - assertEquals(softApConfig.getSsid(), TEST_SSID); - assertEquals(softApConfig.getPassphrase(), TEST_WPA2_PASSPHRASE); - assertEquals(softApConfig.getSecurityType(), SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertEquals(softApConfig.isHiddenSsid(), TEST_HIDDEN); - assertEquals(softApConfig.getBand(), TEST_BAND); - } - - /** - * Verify that the old format is deserialized correctly. - * - * @throws Exception - */ - @Test - public void deserializeNewBandSoftApButNoNewConfig() throws Exception { - // Start with the old serialized data - deserializeData(TEST_SOFTAP_CONFIG_XML_STRING_WITH_NEW_BAND_DESIGN.getBytes()); - - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfig = softapConfigCaptor.getValue(); - assertNotNull(softApConfig); - assertEquals(softApConfig.getSsid(), TEST_SSID); - assertEquals(softApConfig.getPassphrase(), TEST_PASSPHRASE); - assertEquals(softApConfig.getSecurityType(), SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertEquals(softApConfig.isHiddenSsid(), TEST_HIDDEN); - assertEquals(softApConfig.getBand(), TEST_BAND); - } - - /** - * Verify that the store data is serialized/deserialized correctly. - * - * @throws Exception - */ - @Test - public void serializeDeserializeSoftAp() throws Exception { - SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder(); - softApConfigBuilder.setSsid(TEST_SSID); - softApConfigBuilder.setPassphrase(TEST_PASSPHRASE, - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - softApConfigBuilder.setBand(TEST_BAND); - SoftApConfiguration softApConfig = softApConfigBuilder.build(); - - // Serialize first. - when(mDataSource.toSerialize()).thenReturn(softApConfigBuilder.build()); - byte[] serializedData = serializeData(); - - // Now deserialize first. - deserializeData(serializedData); - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfigDeserialized = softapConfigCaptor.getValue(); - assertNotNull(softApConfigDeserialized); - - assertEquals(softApConfig.getSsid(), softApConfigDeserialized.getSsid()); - assertEquals(softApConfig.getPassphrase(), - softApConfigDeserialized.getPassphrase()); - assertEquals(softApConfig.getSecurityType(), - softApConfigDeserialized.getSecurityType()); - assertEquals(softApConfig.isHiddenSsid(), softApConfigDeserialized.isHiddenSsid()); - assertEquals(softApConfig.getBand(), softApConfigDeserialized.getBand()); - assertEquals(softApConfig.getChannel(), softApConfigDeserialized.getChannel()); - } - - /** - * Verify that the stored wpa3-sae data is serialized/deserialized correctly. - * - * @throws Exception - */ - @Test - public void serializeDeserializeSoftApWpa3Sae() throws Exception { - SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder(); - softApConfigBuilder.setSsid(TEST_SSID); - softApConfigBuilder.setPassphrase(TEST_PASSPHRASE, - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); - softApConfigBuilder.setBand(TEST_BAND); - - SoftApConfiguration softApConfig = softApConfigBuilder.build(); - - // Serialize first. - when(mDataSource.toSerialize()).thenReturn(softApConfigBuilder.build()); - byte[] serializedData = serializeData(); - - // Now deserialize first. - deserializeData(serializedData); - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfigDeserialized = softapConfigCaptor.getValue(); - assertNotNull(softApConfigDeserialized); - - assertEquals(softApConfig.getSsid(), softApConfigDeserialized.getSsid()); - assertEquals(softApConfig.getPassphrase(), - softApConfigDeserialized.getPassphrase()); - assertEquals(softApConfig.getSecurityType(), - softApConfigDeserialized.getSecurityType()); - assertEquals(softApConfig.isHiddenSsid(), softApConfigDeserialized.isHiddenSsid()); - assertEquals(softApConfig.getBand(), softApConfigDeserialized.getBand()); - assertEquals(softApConfig.getChannel(), softApConfigDeserialized.getChannel()); - } - - /** - * Verify that the stored wpa3-sae-transition data is serialized/deserialized correctly. - * - * @throws Exception - */ - @Test - public void serializeDeserializeSoftApWpa3SaeTransition() throws Exception { - SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder(); - softApConfigBuilder.setSsid(TEST_SSID); - softApConfigBuilder.setPassphrase(TEST_PASSPHRASE, - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); - softApConfigBuilder.setBand(TEST_BAND); - - SoftApConfiguration softApConfig = softApConfigBuilder.build(); - - // Serialize first. - when(mDataSource.toSerialize()).thenReturn(softApConfigBuilder.build()); - byte[] serializedData = serializeData(); - - // Now deserialize first. - deserializeData(serializedData); - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfigDeserialized = softapConfigCaptor.getValue(); - assertNotNull(softApConfigDeserialized); - - assertEquals(softApConfig.getSsid(), softApConfigDeserialized.getSsid()); - assertEquals(softApConfig.getPassphrase(), - softApConfigDeserialized.getPassphrase()); - assertEquals(softApConfig.getSecurityType(), - softApConfigDeserialized.getSecurityType()); - assertEquals(softApConfig.isHiddenSsid(), softApConfigDeserialized.isHiddenSsid()); - assertEquals(softApConfig.getBand(), softApConfigDeserialized.getBand()); - assertEquals(softApConfig.getChannel(), softApConfigDeserialized.getChannel()); - } - - /** - * Verify that the store data is deserialized correctly using the predefined test XML data - * when the auto shutdown tag is retrieved from - * {@link WifiMigration.loadFromSettings(Context)}. - * - * @throws Exception - */ - @Test - public void deserializeSoftApWithNoAutoShutdownTag() throws Exception { - - // Toggle on when migrating. - when(mOemMigrationData.isSoftApTimeoutEnabled()).thenReturn(true); - deserializeData( - TEST_SOFTAP_CONFIG_XML_STRING_WITH_ALL_CONFIG_EXCEPT_AUTO_SHUTDOWN.getBytes()); - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfig = softapConfigCaptor.getValue(); - assertNotNull(softApConfig); - assertEquals(softApConfig.getSsid(), TEST_SSID); - assertTrue(softApConfig.isAutoShutdownEnabled()); - - // Toggle off when migrating. - when(mOemMigrationData.isSoftApTimeoutEnabled()).thenReturn(false); - deserializeData( - TEST_SOFTAP_CONFIG_XML_STRING_WITH_ALL_CONFIG_EXCEPT_AUTO_SHUTDOWN.getBytes()); - verify(mDataSource, times(2)).fromDeserialized(softapConfigCaptor.capture()); - softApConfig = softapConfigCaptor.getValue(); - assertNotNull(softApConfig); - assertEquals(softApConfig.getSsid(), TEST_SSID); - assertFalse(softApConfig.isAutoShutdownEnabled()); - } - - /** - * Verify that the old format is deserialized correctly. - * - * @throws Exception - */ - @Test - public void deserializeSoftApWithNoBssidTag() throws Exception { - // Start with the old serialized data - deserializeData(TEST_SOFTAP_CONFIG_XML_STRING_WITH_ALL_CONFIG_EXCEPT_BSSID.getBytes()); - ArgumentCaptor<SoftApConfiguration> softapConfigCaptor = - ArgumentCaptor.forClass(SoftApConfiguration.class); - verify(mDataSource).fromDeserialized(softapConfigCaptor.capture()); - SoftApConfiguration softApConfig = softapConfigCaptor.getValue(); - assertNotNull(softApConfig); - assertEquals(softApConfig.getSsid(), TEST_SSID); - assertEquals(softApConfig.getPassphrase(), TEST_PASSPHRASE); - assertEquals(softApConfig.getSecurityType(), SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertEquals(softApConfig.isHiddenSsid(), TEST_HIDDEN); - assertEquals(softApConfig.getBand(), TEST_BAND); - assertEquals(softApConfig.isClientControlByUserEnabled(), TEST_CLIENT_CONTROL_BY_USER); - assertEquals(softApConfig.getMaxNumberOfClients(), TEST_MAX_NUMBER_OF_CLIENTS); - assertTrue(softApConfig.isAutoShutdownEnabled()); - assertEquals(softApConfig.getShutdownTimeoutMillis(), TEST_SHUTDOWN_TIMEOUT_MILLIS); - assertEquals(softApConfig.getBlockedClientList(), TEST_BLOCKEDLIST); - assertEquals(softApConfig.getAllowedClientList(), TEST_ALLOWEDLIST); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java deleted file mode 100644 index b3b8439f4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.SsidSetStoreData}. - */ -@SmallTest -public class SsidSetStoreDataTest extends WifiBaseTest { - private static final String TEST_NOTIFIER_NAME = "TestNetwork"; - private static final String TEST_SSID1 = "SSID 1"; - private static final String TEST_SSID2 = "SSID 2"; - private static final String TEST_SSID_SET_XML_STRING = - "<set name=\"SSIDSet\">\n" - + "<string>" + TEST_SSID1 + "</string>\n" - + "<string>" + TEST_SSID2 + "</string>\n" - + "</set>\n"; - private static final byte[] TEST_SSID_SET_XML_BYTES = - TEST_SSID_SET_XML_STRING.getBytes(StandardCharsets.UTF_8); - - @Mock SsidSetStoreData.DataSource mDataSource; - SsidSetStoreData mSsidSetStoreData; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mSsidSetStoreData = new SsidSetStoreData(TEST_NOTIFIER_NAME, mDataSource); - } - - /** - * Helper function for serializing configuration data to a XML block. - * - * @return byte[] of the XML data - * @throws Exception - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mSsidSetStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing configuration data from a XML block. - * - * @param data XML data to parse from - * @throws Exception - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mSsidSetStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - } - - /** - * Verify that serializing the user store data without any configuration doesn't cause any - * crash and no data should be serialized. - * - * @throws Exception - */ - @Test - public void serializeEmptyConfigs() throws Exception { - when(mDataSource.getSsids()).thenReturn(new HashSet<String>()); - assertEquals(0, serializeData().length); - } - - /** - * Verify that parsing an empty data doesn't cause any crash and no configuration should - * be deserialized. - * - * @throws Exception - */ - @Test - public void deserializeEmptyStoreData() throws Exception { - deserializeData(new byte[0]); - verify(mDataSource, never()).setSsids(any(Set.class)); - } - - /** - * Verify that SsidSetStoreData is written to - * {@link WifiConfigStore#STORE_FILE_NAME_USER_GENERAL}. - * - * @throws Exception - */ - @Test - public void getUserStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_USER_GENERAL, - mSsidSetStoreData.getStoreFileId()); - } - - /** - * Verify that the store data is serialized correctly, matches the predefined test XML data. - * - * @throws Exception - */ - @Test - public void serializeSsidSet() throws Exception { - Set<String> ssidSet = new HashSet<>(); - ssidSet.add(TEST_SSID1); - ssidSet.add(TEST_SSID2); - when(mDataSource.getSsids()).thenReturn(ssidSet); - byte[] actualData = serializeData(); - assertTrue(Arrays.equals(TEST_SSID_SET_XML_BYTES, actualData)); - } - - /** - * Verify that the store data is deserialized correctly using the predefined test XML data. - * - * @throws Exception - */ - @Test - public void deserializeSsidSet() throws Exception { - Set<String> ssidSet = new HashSet<>(); - ssidSet.add(TEST_SSID1); - ssidSet.add(TEST_SSID2); - deserializeData(TEST_SSID_SET_XML_BYTES); - verify(mDataSource).setSsids(eq(ssidSet)); - } - - /** - * Verify that a XmlPullParserException will be thrown when parsing a SSIDSet set with an - * unknown tag. - * - * @throws Exception - */ - @Test(expected = XmlPullParserException.class) - public void parseSetWithUnknownTag() throws Exception { - String ssidSet = - "<set name=\"SSIDSet\">\n" - + "<string>" + TEST_SSID1 + "</string>\n" - + "<string>" + TEST_SSID2 + "</string>\n" - + "<Unknown>" + "badInput" + "</Unknown>" // Unknown tag. - + "</set>\n"; - deserializeData(ssidSet.getBytes(StandardCharsets.UTF_8)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java deleted file mode 100644 index 7e0c20faf..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java +++ /dev/null @@ -1,2914 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP; -import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256; -import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384; -import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO; -import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE; -import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; -import static android.net.wifi.WifiManager.WIFI_FEATURE_WAPI; -import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; -import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyShort; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.annotation.NonNull; -import android.app.test.MockAnswerUtil; -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.content.Context; -import android.hardware.wifi.V1_0.WifiChannelWidthInMhz; -import android.hardware.wifi.supplicant.V1_0.ISupplicant; -import android.hardware.wifi.supplicant.V1_0.ISupplicantIface; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback.BssidChangeReason; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; -import android.hardware.wifi.supplicant.V1_0.IfaceType; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; -import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; -import android.hardware.wifi.supplicant.V1_3.ConnectionCapabilities; -import android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback.BssTmData; -import android.hardware.wifi.supplicant.V1_3.WifiTechnology; -import android.hidl.manager.V1_0.IServiceManager; -import android.hidl.manager.V1_0.IServiceNotification; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.IHwBinder; -import android.os.RemoteException; -import android.os.test.TestLooper; -import android.text.TextUtils; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.MboOceController.BtmFrameData; -import com.android.server.wifi.SupplicantStaIfaceHal.PmkCacheStoreData; -import com.android.server.wifi.hotspot2.AnqpEvent; -import com.android.server.wifi.hotspot2.IconEvent; -import com.android.server.wifi.hotspot2.WnmData; -import com.android.server.wifi.util.NativeUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; - -/** - * Unit tests for SupplicantStaIfaceHal - */ -@SmallTest -public class SupplicantStaIfaceHalTest extends WifiBaseTest { - private static final String TAG = "SupplicantStaIfaceHalTest"; - private static final Map<Integer, String> NETWORK_ID_TO_SSID = new HashMap<Integer, String>() {{ - put(1, "\"ssid1\""); - put(2, "\"ssid2\""); - put(3, "\"ssid3\""); - }}; - private static final int SUPPLICANT_NETWORK_ID = 2; - private static final String SUPPLICANT_SSID = NETWORK_ID_TO_SSID.get(SUPPLICANT_NETWORK_ID); - private static final int ROAM_NETWORK_ID = 4; - private static final String BSSID = "fa:45:23:23:12:12"; - private static final String WLAN0_IFACE_NAME = "wlan0"; - private static final String WLAN1_IFACE_NAME = "wlan1"; - private static final String P2P_IFACE_NAME = "p2p0"; - private static final String ICON_FILE_NAME = "blahblah"; - private static final int ICON_FILE_SIZE = 72; - private static final String HS20_URL = "http://blahblah"; - private static final long PMK_CACHE_EXPIRATION_IN_SEC = 1024; - private static final byte[] CONNECTED_MAC_ADDRESS_BYTES = - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - private @Mock IServiceManager mServiceManagerMock; - private @Mock ISupplicant mISupplicantMock; - private android.hardware.wifi.supplicant.V1_1.ISupplicant mISupplicantMockV1_1; - private android.hardware.wifi.supplicant.V1_2.ISupplicant mISupplicantMockV1_2; - private android.hardware.wifi.supplicant.V1_3.ISupplicant mISupplicantMockV13; - private @Mock ISupplicantIface mISupplicantIfaceMock; - private @Mock ISupplicantStaIface mISupplicantStaIfaceMock; - private @Mock android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface - mISupplicantStaIfaceMockV1_1; - private @Mock android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - mISupplicantStaIfaceMockV1_2; - private @Mock android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - mISupplicantStaIfaceMockV13; - private @Mock Context mContext; - private @Mock WifiMonitor mWifiMonitor; - private @Mock FrameworkFacade mFrameworkFacade; - private @Mock SupplicantStaNetworkHal mSupplicantStaNetworkMock; - private @Mock WifiNative.SupplicantDeathEventHandler mSupplicantHalDeathHandler; - private @Mock Clock mClock; - private @Mock WifiMetrics mWifiMetrics; - - SupplicantStatus mStatusSuccess; - SupplicantStatus mStatusFailure; - ISupplicant.IfaceInfo mStaIface0; - ISupplicant.IfaceInfo mStaIface1; - ISupplicant.IfaceInfo mP2pIface; - ArrayList<ISupplicant.IfaceInfo> mIfaceInfoList; - ISupplicantStaIfaceCallback mISupplicantStaIfaceCallback; - android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback - mISupplicantStaIfaceCallbackV1_1; - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback - mISupplicantStaIfaceCallbackV1_2; - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback - mISupplicantStaIfaceCallbackV13 = null; - private TestLooper mLooper = new TestLooper(); - private Handler mHandler = null; - private SupplicantStaIfaceHal mDut; - private ArgumentCaptor<IHwBinder.DeathRecipient> mServiceManagerDeathCaptor = - ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); - private ArgumentCaptor<IHwBinder.DeathRecipient> mSupplicantDeathCaptor = - ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); - private ArgumentCaptor<IHwBinder.DeathRecipient> mSupplicantStaIfaceDeathCaptor = - ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); - private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor = - ArgumentCaptor.forClass(IServiceNotification.Stub.class); - private ArgumentCaptor<Long> mDeathRecipientCookieCaptor = ArgumentCaptor.forClass(Long.class); - private InOrder mInOrder; - - private class SupplicantStaIfaceHalSpy extends SupplicantStaIfaceHal { - SupplicantStaIfaceHalSpy() { - super(mContext, mWifiMonitor, mFrameworkFacade, - mHandler, mClock, mWifiMetrics); - } - - @Override - protected IServiceManager getServiceManagerMockable() throws RemoteException { - return mServiceManagerMock; - } - - @Override - protected ISupplicant getSupplicantMockable() throws RemoteException { - return mISupplicantMock; - } - - @Override - protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1() - throws RemoteException { - return mISupplicantMockV1_1; - } - - @Override - protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) { - return mISupplicantStaIfaceMock; - } - - @Override - protected android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface - getStaIfaceMockableV1_1(ISupplicantIface iface) { - return mISupplicantStaIfaceMockV1_1; - } - - @Override - protected android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - getStaIfaceMockableV1_2(ISupplicantIface iface) { - return mISupplicantStaIfaceMockV1_2; - } - - @Override - protected android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - getStaIfaceMockableV1_3(ISupplicantIface iface) { - return (mISupplicantMockV13 != null) - ? mISupplicantStaIfaceMockV13 - : null; - } - - @Override - protected SupplicantStaNetworkHal getStaNetworkMockable( - @NonNull String ifaceName, - ISupplicantStaNetwork iSupplicantStaNetwork) { - return mSupplicantStaNetworkMock; - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mStatusSuccess = createSupplicantStatus(SupplicantStatusCode.SUCCESS); - mStatusFailure = createSupplicantStatus(SupplicantStatusCode.FAILURE_UNKNOWN); - mStaIface0 = createIfaceInfo(IfaceType.STA, WLAN0_IFACE_NAME); - mStaIface1 = createIfaceInfo(IfaceType.STA, WLAN1_IFACE_NAME); - mP2pIface = createIfaceInfo(IfaceType.P2P, P2P_IFACE_NAME); - - mIfaceInfoList = new ArrayList<>(); - mIfaceInfoList.add(mStaIface0); - mIfaceInfoList.add(mStaIface1); - mIfaceInfoList.add(mP2pIface); - when(mServiceManagerMock.getTransport(anyString(), anyString())) - .thenReturn(IServiceManager.Transport.EMPTY); - when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), - any(IServiceNotification.Stub.class))).thenReturn(true); - when(mISupplicantMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaIface.getMacAddressCallback cb) { - cb.onValues(mStatusSuccess, CONNECTED_MAC_ADDRESS_BYTES); - } - }) - .when(mISupplicantStaIfaceMock) - .getMacAddress(any(ISupplicantStaIface.getMacAddressCallback.class)); - mHandler = spy(new Handler(mLooper.getLooper())); - mDut = new SupplicantStaIfaceHalSpy(); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_success() throws Exception { - executeAndValidateInitializationSequence(false, false, false, false); - } - - /** - * Tests the initialization flow, with a RemoteException occurring when 'getInterface' is called - * Ensures initialization fails. - */ - @Test - public void testInitialize_remoteExceptionFailure() throws Exception { - executeAndValidateInitializationSequence(true, false, false, false); - } - - /** - * Tests the initialization flow, with listInterfaces returning 0 interfaces. - * Ensures failure - */ - @Test - public void testInitialize_zeroInterfacesFailure() throws Exception { - executeAndValidateInitializationSequence(false, true, false, false); - } - - /** - * Tests the initialization flow, with a null interface being returned by getInterface. - * Ensures initialization fails. - */ - @Test - public void testInitialize_nullInterfaceFailure() throws Exception { - executeAndValidateInitializationSequence(false, false, true, false); - } - - /** - * Tests the initialization flow, with a callback registration failure. - * Ensures initialization fails. - */ - @Test - public void testInitialize_callbackRegistrationFailure() throws Exception { - executeAndValidateInitializationSequence(false, false, false, true); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_successV1_1() throws Exception { - setupMocksForHalV1_1(); - executeAndValidateInitializationSequenceV1_1(false, false); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_successV1_2() throws Exception { - setupMocksForHalV1_2(); - executeAndValidateInitializationSequenceV1_2(); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_successV1_3() throws Exception { - setupMocksForHalV1_3(); - executeAndValidateInitializationSequenceV1_3(); - } - - /** - * Tests the initialization flow, with a RemoteException occurring when 'getInterface' is called - * Ensures initialization fails. - */ - @Test - public void testInitialize_remoteExceptionFailureV1_1() throws Exception { - setupMocksForHalV1_1(); - executeAndValidateInitializationSequenceV1_1(true, false); - } - - /** - * Tests the initialization flow, with a null interface being returned by getInterface. - * Ensures initialization fails. - */ - @Test - public void testInitialize_nullInterfaceFailureV1_1() throws Exception { - setupMocksForHalV1_1(); - executeAndValidateInitializationSequenceV1_1(false, true); - } - - /** - * Ensures that we do not allow operations on an interface until it's setup. - */ - @Test - public void testEnsureOperationFailsUntilSetupInterfaces() throws Exception { - executeAndValidateInitializationSequence(false, false, false, false); - - // Ensure that the cancel wps operation is failed because wlan1 interface is not yet setup. - assertFalse(mDut.cancelWps(WLAN1_IFACE_NAME)); - verify(mISupplicantStaIfaceMock, never()).cancelWps(); - - // Now setup the wlan1 interface and Ensure that the cancel wps operation is successful. - assertTrue(mDut.setupIface(WLAN1_IFACE_NAME)); - when(mISupplicantStaIfaceMock.cancelWps()).thenReturn(mStatusSuccess); - assertTrue(mDut.cancelWps(WLAN1_IFACE_NAME)); - verify(mISupplicantStaIfaceMock).cancelWps(); - } - - /** - * Ensures that reject addition of an existing iface. - */ - @Test - public void testDuplicateSetupIfaceV1_1_Fails() throws Exception { - setupMocksForHalV1_1(); - executeAndValidateInitializationSequenceV1_1(false, false); - - // Trying setting up the wlan0 interface again & ensure it fails. - assertFalse(mDut.setupIface(WLAN0_IFACE_NAME)); - verifyNoMoreInteractions(mISupplicantMockV1_1); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal interface teardown. - */ - @Test - public void testTeardownInterface() throws Exception { - testInitialize_success(); - assertTrue(mDut.teardownIface(WLAN0_IFACE_NAME)); - - // Ensure that the cancel wps operation is failed because there are no interfaces setup. - assertFalse(mDut.cancelWps(WLAN0_IFACE_NAME)); - verify(mISupplicantStaIfaceMock, never()).cancelWps(); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal interface teardown. - */ - @Test - public void testTeardownInterfaceV1_1() throws Exception { - testInitialize_successV1_1(); - - when(mISupplicantMockV1_1.removeInterface(any())).thenReturn(mStatusSuccess); - assertTrue(mDut.teardownIface(WLAN0_IFACE_NAME)); - verify(mISupplicantMockV1_1).removeInterface(any()); - - // Ensure that the cancel wps operation is failed because there are no interfaces setup. - assertFalse(mDut.cancelWps(WLAN0_IFACE_NAME)); - verify(mISupplicantStaIfaceMock, never()).cancelWps(); - } - - /** - * Ensures that we reject removal of an invalid iface. - */ - @Test - public void testInvalidTeardownInterfaceV1_1_Fails() throws Exception { - assertFalse(mDut.teardownIface(WLAN0_IFACE_NAME)); - verifyNoMoreInteractions(mISupplicantMock); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal initialization - * Asserts successful initialization of second interface - */ - @Test - public void testSetupTwoInterfaces() throws Exception { - executeAndValidateInitializationSequence(false, false, false, false); - assertTrue(mDut.setupIface(WLAN1_IFACE_NAME)); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal interface teardown. - * Asserts successful initialization of second interface - */ - @Test - public void testTeardownTwoInterfaces() throws Exception { - testSetupTwoInterfaces(); - assertTrue(mDut.teardownIface(WLAN0_IFACE_NAME)); - assertTrue(mDut.teardownIface(WLAN1_IFACE_NAME)); - - // Ensure that the cancel wps operation is failed because there are no interfaces setup. - assertFalse(mDut.cancelWps(WLAN0_IFACE_NAME)); - verify(mISupplicantStaIfaceMock, never()).cancelWps(); - } - - /** - * Tests connection to a specified network with empty existing network. - */ - @Test - public void testConnectWithEmptyExistingNetwork() throws Exception { - executeAndValidateInitializationSequence(); - executeAndValidateConnectSequence(0, false); - } - - @Test - public void testConnectToNetworkWithDifferentConfigReplacesNetworkInSupplicant() - throws Exception { - executeAndValidateInitializationSequence(); - WifiConfiguration config = executeAndValidateConnectSequence( - SUPPLICANT_NETWORK_ID, false); - // Reset mocks for mISupplicantStaIfaceMock because we finished the first connection. - reset(mISupplicantStaIfaceMock); - setupMocksForConnectSequence(true /*haveExistingNetwork*/); - // Make this network different by changing SSID. - config.SSID = "AnDifferentSSID"; - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - verify(mISupplicantStaIfaceMock).removeNetwork(SUPPLICANT_NETWORK_ID); - verify(mISupplicantStaIfaceMock) - .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class)); - } - - @Test - public void connectToNetworkWithSameNetworkDoesNotRemoveNetworkFromSupplicant() - throws Exception { - executeAndValidateInitializationSequence(); - WifiConfiguration config = executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false); - // Reset mocks for mISupplicantStaIfaceMock because we finished the first connection. - reset(mISupplicantStaIfaceMock); - setupMocksForConnectSequence(true /*haveExistingNetwork*/); - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - verify(mISupplicantStaIfaceMock, never()).removeNetwork(anyInt()); - verify(mISupplicantStaIfaceMock, never()) - .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class)); - } - - @Test - public void connectToNetworkWithSameNetworkButDifferentBssidUpdatesNetworkFromSupplicant() - throws Exception { - executeAndValidateInitializationSequence(); - WifiConfiguration config = executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false); - String testBssid = "11:22:33:44:55:66"; - when(mSupplicantStaNetworkMock.setBssid(eq(testBssid))).thenReturn(true); - - // Reset mocks for mISupplicantStaIfaceMock because we finished the first connection. - reset(mISupplicantStaIfaceMock); - setupMocksForConnectSequence(true /*haveExistingNetwork*/); - // Change the BSSID and connect to the same network. - assertFalse(TextUtils.equals( - testBssid, config.getNetworkSelectionStatus().getNetworkSelectionBSSID())); - config.getNetworkSelectionStatus().setNetworkSelectionBSSID(testBssid); - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - verify(mSupplicantStaNetworkMock).setBssid(eq(testBssid)); - verify(mISupplicantStaIfaceMock, never()).removeNetwork(anyInt()); - verify(mISupplicantStaIfaceMock, never()) - .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class)); - } - - /** - * Tests connection to a specified network failure due to network add. - */ - @Test - public void testConnectFailureDueToNetworkAddFailure() throws Exception { - executeAndValidateInitializationSequence(); - setupMocksForConnectSequence(false); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public void answer(ISupplicantStaIface.addNetworkCallback cb) throws RemoteException { - cb.onValues(mStatusFailure, mock(ISupplicantStaNetwork.class)); - return; - } - }).when(mISupplicantStaIfaceMock).addNetwork( - any(ISupplicantStaIface.addNetworkCallback.class)); - - assertFalse(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration())); - } - - /** - * Tests connection to a specified network failure due to network save. - */ - @Test - public void testConnectFailureDueToNetworkSaveFailure() throws Exception { - executeAndValidateInitializationSequence(); - setupMocksForConnectSequence(true); - - when(mSupplicantStaNetworkMock.saveWifiConfiguration(any(WifiConfiguration.class))) - .thenReturn(false); - - assertFalse(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration())); - // We should have removed the existing network once before connection and once more - // on failure to save network configuration. - verify(mISupplicantStaIfaceMock, times(2)).removeNetwork(anyInt()); - } - - /** - * Tests connection to a specified network failure due to exception in network save. - */ - @Test - public void testConnectFailureDueToNetworkSaveException() throws Exception { - executeAndValidateInitializationSequence(); - setupMocksForConnectSequence(true); - - doThrow(new IllegalArgumentException("Some error!!!")) - .when(mSupplicantStaNetworkMock).saveWifiConfiguration( - any(WifiConfiguration.class)); - - assertFalse(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration())); - // We should have removed the existing network once before connection and once more - // on failure to save network configuration. - verify(mISupplicantStaIfaceMock, times(2)).removeNetwork(anyInt()); - } - - /** - * Tests connection to a specified network failure due to network select. - */ - @Test - public void testConnectFailureDueToNetworkSelectFailure() throws Exception { - executeAndValidateInitializationSequence(); - setupMocksForConnectSequence(false); - - when(mSupplicantStaNetworkMock.select()).thenReturn(false); - - assertFalse(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration())); - } - - /** - * Tests roaming to the same network as the currently connected one. - */ - @Test - public void testRoamToSameNetwork() throws Exception { - executeAndValidateInitializationSequence(); - executeAndValidateRoamSequence(true); - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration())); - } - - /** - * Tests roaming to a different network. - */ - @Test - public void testRoamToDifferentNetwork() throws Exception { - executeAndValidateInitializationSequence(); - executeAndValidateRoamSequence(false); - } - - /** - * Tests roaming failure because of unable to set bssid. - */ - @Test - public void testRoamFailureDueToBssidSet() throws Exception { - executeAndValidateInitializationSequence(); - int connectedNetworkId = 5; - executeAndValidateConnectSequence(connectedNetworkId, false); - when(mSupplicantStaNetworkMock.setBssid(anyString())).thenReturn(false); - - WifiConfiguration roamingConfig = new WifiConfiguration(); - roamingConfig.networkId = connectedNetworkId; - roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID("45:34:23:23:ab:ed"); - assertFalse(mDut.roamToNetwork(WLAN0_IFACE_NAME, roamingConfig)); - } - - /** - * Tests removal of all configured networks from wpa_supplicant. - */ - @Test - public void testRemoveAllNetworks() throws Exception { - executeAndValidateInitializationSequence(); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public void answer(ISupplicantStaIface.listNetworksCallback cb) { - cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet())); - } - }).when(mISupplicantStaIfaceMock) - .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer(int id) { - assertTrue(NETWORK_ID_TO_SSID.containsKey(id)); - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMock).removeNetwork(anyInt()); - - assertTrue(mDut.removeAllNetworks(WLAN0_IFACE_NAME)); - verify(mISupplicantStaIfaceMock, times(NETWORK_ID_TO_SSID.size())).removeNetwork(anyInt()); - } - - /** - * Remove all networks while connected, verify that the current network info is resetted. - */ - @Test - public void testRemoveAllNetworksWhileConnected() throws Exception { - String testBssid = "11:22:33:44:55:66"; - when(mSupplicantStaNetworkMock.setBssid(eq(testBssid))).thenReturn(true); - - executeAndValidateInitializationSequence(); - - // Connect to a network and verify current network is set. - executeAndValidateConnectSequence(4, false); - assertTrue(mDut.setCurrentNetworkBssid(WLAN0_IFACE_NAME, testBssid)); - verify(mSupplicantStaNetworkMock).setBssid(eq(testBssid)); - reset(mSupplicantStaNetworkMock); - - // Remove all networks and verify current network info is resetted. - assertTrue(mDut.removeAllNetworks(WLAN0_IFACE_NAME)); - assertFalse(mDut.setCurrentNetworkBssid(WLAN0_IFACE_NAME, testBssid)); - verify(mSupplicantStaNetworkMock, never()).setBssid(eq(testBssid)); - } - - /** - * Tests roaming failure because of unable to reassociate. - */ - @Test - public void testRoamFailureDueToReassociate() throws Exception { - executeAndValidateInitializationSequence(); - int connectedNetworkId = 5; - executeAndValidateConnectSequence(connectedNetworkId, false); - - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer() throws RemoteException { - return mStatusFailure; - } - }).when(mISupplicantStaIfaceMock).reassociate(); - when(mSupplicantStaNetworkMock.setBssid(anyString())).thenReturn(true); - - WifiConfiguration roamingConfig = new WifiConfiguration(); - roamingConfig.networkId = connectedNetworkId; - roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID("45:34:23:23:ab:ed"); - assertFalse(mDut.roamToNetwork(WLAN0_IFACE_NAME, roamingConfig)); - } - - /** - * Tests the retrieval of WPS NFC token. - */ - @Test - public void testGetCurrentNetworkWpsNfcConfigurationToken() throws Exception { - String token = "45adbc1"; - when(mSupplicantStaNetworkMock.getWpsNfcConfigurationToken()).thenReturn(token); - - executeAndValidateInitializationSequence(); - // Return null when not connected to the network. - assertTrue(mDut.getCurrentNetworkWpsNfcConfigurationToken(WLAN0_IFACE_NAME) == null); - verify(mSupplicantStaNetworkMock, never()).getWpsNfcConfigurationToken(); - executeAndValidateConnectSequence(4, false); - assertEquals(token, mDut.getCurrentNetworkWpsNfcConfigurationToken(WLAN0_IFACE_NAME)); - verify(mSupplicantStaNetworkMock).getWpsNfcConfigurationToken(); - } - - /** - * Tests the setting of BSSID. - */ - @Test - public void testSetCurrentNetworkBssid() throws Exception { - String bssidStr = "34:34:12:12:12:90"; - when(mSupplicantStaNetworkMock.setBssid(eq(bssidStr))).thenReturn(true); - - executeAndValidateInitializationSequence(); - // Fail when not connected to a network. - assertFalse(mDut.setCurrentNetworkBssid(WLAN0_IFACE_NAME, bssidStr)); - verify(mSupplicantStaNetworkMock, never()).setBssid(eq(bssidStr)); - executeAndValidateConnectSequence(4, false); - assertTrue(mDut.setCurrentNetworkBssid(WLAN0_IFACE_NAME, bssidStr)); - verify(mSupplicantStaNetworkMock).setBssid(eq(bssidStr)); - } - - /** - * Tests the sending identity response for the current network. - */ - @Test - public void testSetCurrentNetworkEapIdentityResponse() throws Exception { - String identity = "blah@blah.com"; - String encryptedIdentity = "blah2@blah.com"; - when(mSupplicantStaNetworkMock.sendNetworkEapIdentityResponse(eq(identity), - eq(encryptedIdentity))) - .thenReturn(true); - - executeAndValidateInitializationSequence(); - // Fail when not connected to a network. - assertFalse(mDut.sendCurrentNetworkEapIdentityResponse(WLAN0_IFACE_NAME, identity, - encryptedIdentity)); - verify(mSupplicantStaNetworkMock, never()).sendNetworkEapIdentityResponse(eq(identity), - eq(encryptedIdentity)); - executeAndValidateConnectSequence(4, false); - assertTrue(mDut.sendCurrentNetworkEapIdentityResponse(WLAN0_IFACE_NAME, identity, - encryptedIdentity)); - verify(mSupplicantStaNetworkMock).sendNetworkEapIdentityResponse(eq(identity), - eq(encryptedIdentity)); - } - - /** - * Tests the getting of anonymous identity for the current network. - */ - @Test - public void testGetCurrentNetworkEapAnonymousIdentity() throws Exception { - String anonymousIdentity = "aaa@bbb.ccc"; - when(mSupplicantStaNetworkMock.fetchEapAnonymousIdentity()) - .thenReturn(anonymousIdentity); - executeAndValidateInitializationSequence(); - - // Return null when not connected to the network. - assertEquals(null, mDut.getCurrentNetworkEapAnonymousIdentity(WLAN0_IFACE_NAME)); - executeAndValidateConnectSequence(4, false); - // Return anonymous identity for the current network. - assertEquals( - anonymousIdentity, mDut.getCurrentNetworkEapAnonymousIdentity(WLAN0_IFACE_NAME)); - } - - /** - * Tests the sending gsm auth response for the current network. - */ - @Test - public void testSetCurrentNetworkEapSimGsmAuthResponse() throws Exception { - String params = "test"; - when(mSupplicantStaNetworkMock.sendNetworkEapSimGsmAuthResponse(eq(params))) - .thenReturn(true); - - executeAndValidateInitializationSequence(); - // Fail when not connected to a network. - assertFalse(mDut.sendCurrentNetworkEapSimGsmAuthResponse(WLAN0_IFACE_NAME, params)); - verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimGsmAuthResponse(eq(params)); - executeAndValidateConnectSequence(4, false); - assertTrue(mDut.sendCurrentNetworkEapSimGsmAuthResponse(WLAN0_IFACE_NAME, params)); - verify(mSupplicantStaNetworkMock).sendNetworkEapSimGsmAuthResponse(eq(params)); - } - - /** - * Tests the sending umts auth response for the current network. - */ - @Test - public void testSetCurrentNetworkEapSimUmtsAuthResponse() throws Exception { - String params = "test"; - when(mSupplicantStaNetworkMock.sendNetworkEapSimUmtsAuthResponse(eq(params))) - .thenReturn(true); - - executeAndValidateInitializationSequence(); - // Fail when not connected to a network. - assertFalse(mDut.sendCurrentNetworkEapSimUmtsAuthResponse(WLAN0_IFACE_NAME, params)); - verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimUmtsAuthResponse(eq(params)); - executeAndValidateConnectSequence(4, false); - assertTrue(mDut.sendCurrentNetworkEapSimUmtsAuthResponse(WLAN0_IFACE_NAME, params)); - verify(mSupplicantStaNetworkMock).sendNetworkEapSimUmtsAuthResponse(eq(params)); - } - - /** - * Tests the sending umts auts response for the current network. - */ - @Test - public void testSetCurrentNetworkEapSimUmtsAutsResponse() throws Exception { - String params = "test"; - when(mSupplicantStaNetworkMock.sendNetworkEapSimUmtsAutsResponse(eq(params))) - .thenReturn(true); - - executeAndValidateInitializationSequence(); - // Fail when not connected to a network. - assertFalse(mDut.sendCurrentNetworkEapSimUmtsAutsResponse(WLAN0_IFACE_NAME, params)); - verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimUmtsAutsResponse(eq(params)); - executeAndValidateConnectSequence(4, false); - assertTrue(mDut.sendCurrentNetworkEapSimUmtsAutsResponse(WLAN0_IFACE_NAME, params)); - verify(mSupplicantStaNetworkMock).sendNetworkEapSimUmtsAutsResponse(eq(params)); - } - - /** - * Tests the setting of WPS device type. - */ - @Test - public void testSetWpsDeviceType() throws Exception { - String validDeviceTypeStr = "10-0050F204-5"; - byte[] expectedDeviceType = { 0x0, 0xa, 0x0, 0x50, (byte) 0xf2, 0x04, 0x0, 0x05}; - String invalidDeviceType1Str = "10-02050F204-5"; - String invalidDeviceType2Str = "10-0050F204-534"; - when(mISupplicantStaIfaceMock.setWpsDeviceType(any(byte[].class))) - .thenReturn(mStatusSuccess); - - executeAndValidateInitializationSequence(); - - // This should work. - assertTrue(mDut.setWpsDeviceType(WLAN0_IFACE_NAME, validDeviceTypeStr)); - verify(mISupplicantStaIfaceMock).setWpsDeviceType(eq(expectedDeviceType)); - - // This should not work - assertFalse(mDut.setWpsDeviceType(WLAN0_IFACE_NAME, invalidDeviceType1Str)); - // This should not work - assertFalse(mDut.setWpsDeviceType(WLAN0_IFACE_NAME, invalidDeviceType2Str)); - } - - /** - * Tests the setting of WPS config methods. - */ - @Test - public void testSetWpsConfigMethods() throws Exception { - String validConfigMethodsStr = "physical_display virtual_push_button"; - Short expectedConfigMethods = - WpsConfigMethods.PHY_DISPLAY | WpsConfigMethods.VIRT_PUSHBUTTON; - String invalidConfigMethodsStr = "physical_display virtual_push_button test"; - when(mISupplicantStaIfaceMock.setWpsConfigMethods(anyShort())).thenReturn(mStatusSuccess); - - executeAndValidateInitializationSequence(); - - // This should work. - assertTrue(mDut.setWpsConfigMethods(WLAN0_IFACE_NAME, validConfigMethodsStr)); - verify(mISupplicantStaIfaceMock).setWpsConfigMethods(eq(expectedConfigMethods)); - - // This should throw an illegal argument exception. - try { - assertFalse(mDut.setWpsConfigMethods(WLAN0_IFACE_NAME, invalidConfigMethodsStr)); - } catch (IllegalArgumentException e) { - return; - } - assertTrue(false); - } - - /** - * Tests the handling of ANQP done callback. - * Note: Since the ANQP element parsing methods are static, this can only test the negative test - * where all the parsing fails because the data is empty. It'll be non-trivial and unnecessary - * to test out the parsing logic here. - */ - @Test - public void testAnqpDoneCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - byte[] bssid = NativeUtil.macAddressToByteArray(BSSID); - mISupplicantStaIfaceCallback.onAnqpQueryDone( - bssid, new ISupplicantStaIfaceCallback.AnqpData(), - new ISupplicantStaIfaceCallback.Hs20AnqpData()); - - ArgumentCaptor<AnqpEvent> anqpEventCaptor = ArgumentCaptor.forClass(AnqpEvent.class); - verify(mWifiMonitor).broadcastAnqpDoneEvent( - eq(WLAN0_IFACE_NAME), anqpEventCaptor.capture()); - assertEquals( - ByteBufferReader.readInteger( - ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length), - anqpEventCaptor.getValue().getBssid()); - } - - /** - * Tests the handling of Icon done callback. - */ - @Test - public void testIconDoneCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - byte[] bssid = NativeUtil.macAddressToByteArray(BSSID); - byte[] iconData = new byte[ICON_FILE_SIZE]; - new Random().nextBytes(iconData); - mISupplicantStaIfaceCallback.onHs20IconQueryDone( - bssid, ICON_FILE_NAME, NativeUtil.byteArrayToArrayList(iconData)); - - ArgumentCaptor<IconEvent> iconEventCaptor = ArgumentCaptor.forClass(IconEvent.class); - verify(mWifiMonitor).broadcastIconDoneEvent( - eq(WLAN0_IFACE_NAME), iconEventCaptor.capture()); - assertEquals( - ByteBufferReader.readInteger( - ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length), - iconEventCaptor.getValue().getBSSID()); - assertEquals(ICON_FILE_NAME, iconEventCaptor.getValue().getFileName()); - assertArrayEquals(iconData, iconEventCaptor.getValue().getData()); - } - - /** - * Tests the handling of HS20 subscription remediation callback. - */ - @Test - public void testHs20SubscriptionRemediationCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - byte[] bssid = NativeUtil.macAddressToByteArray(BSSID); - byte osuMethod = ISupplicantStaIfaceCallback.OsuMethod.OMA_DM; - mISupplicantStaIfaceCallback.onHs20SubscriptionRemediation( - bssid, osuMethod, HS20_URL); - - ArgumentCaptor<WnmData> wnmDataCaptor = ArgumentCaptor.forClass(WnmData.class); - verify(mWifiMonitor).broadcastWnmEvent(eq(WLAN0_IFACE_NAME), wnmDataCaptor.capture()); - assertEquals( - ByteBufferReader.readInteger( - ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length), - wnmDataCaptor.getValue().getBssid()); - assertEquals(osuMethod, wnmDataCaptor.getValue().getMethod()); - assertEquals(HS20_URL, wnmDataCaptor.getValue().getUrl()); - } - - /** - * Tests the handling of HS20 deauth imminent callback. - */ - @Test - public void testHs20DeauthImminentCallbackWithEssReasonCode() throws Exception { - executeAndValidateHs20DeauthImminentCallback(true); - } - - /** - * Tests the handling of HS20 deauth imminent callback. - */ - @Test - public void testHs20DeauthImminentCallbackWithNonEssReasonCode() throws Exception { - executeAndValidateHs20DeauthImminentCallback(false); - - } - - /** - * Tests the handling of state change notification without any configured network. - */ - @Test - public void testStateChangeCallbackWithNoConfiguredNetwork() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.INACTIVE, - NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - - // Can't compare WifiSsid instances because they lack an equals. - verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( - eq(WLAN0_IFACE_NAME), eq(WifiConfiguration.INVALID_NETWORK_ID), - any(WifiSsid.class), eq(BSSID), eq(SupplicantState.INACTIVE)); - } - - /** - * Tests the handling of state change notification to associated after configuring a network. - */ - @Test - public void testStateChangeToAssociatedCallback() throws Exception { - executeAndValidateInitializationSequence(); - int frameworkNetworkId = 6; - executeAndValidateConnectSequence(frameworkNetworkId, false); - assertNotNull(mISupplicantStaIfaceCallback); - - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.ASSOCIATED, - NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - - verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( - eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), - any(WifiSsid.class), eq(BSSID), eq(SupplicantState.ASSOCIATED)); - } - - /** - * Tests the handling of state change notification to completed after configuring a network. - */ - @Test - public void testStateChangeToCompletedCallback() throws Exception { - InOrder wifiMonitorInOrder = inOrder(mWifiMonitor); - executeAndValidateInitializationSequence(); - int frameworkNetworkId = 6; - executeAndValidateConnectSequence(frameworkNetworkId, false); - assertNotNull(mISupplicantStaIfaceCallback); - - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.COMPLETED, - NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - - wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent( - eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(false), eq(BSSID)); - wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( - eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), - any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED)); - } - - /** - * Tests the handling of network disconnected notification. - */ - @Test - public void testDisconnectedCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - int reasonCode = 5; - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); - verify(mWifiMonitor).broadcastNetworkDisconnectionEvent( - eq(WLAN0_IFACE_NAME), eq(1), eq(reasonCode), eq(BSSID)); - - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); - verify(mWifiMonitor).broadcastNetworkDisconnectionEvent( - eq(WLAN0_IFACE_NAME), eq(0), eq(reasonCode), eq(BSSID)); - } - - /** - * Tests the handling of incorrect network passwords. - */ - @Test - public void testAuthFailurePasswordOnDisconnect() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - executeAndValidateConnectSequenceWithKeyMgmt( - 0, false, WifiConfiguration.KeyMgmt.WPA_PSK, null); - - int reasonCode = 3; - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); - verify(mWifiMonitor, times(0)) - .broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt()); - - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); - verify(mWifiMonitor, times(0)) - .broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt()); - - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); - - verify(mWifiMonitor).broadcastAuthenticationFailureEvent( - eq(WLAN0_IFACE_NAME), eq(WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD), eq(-1)); - } - - /** - * Tests the handling of EAP failure disconnects. - */ - @Test - public void testAuthFailureEapOnDisconnect() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - executeAndValidateConnectSequenceWithKeyMgmt( - 0, false, WifiConfiguration.KeyMgmt.WPA_EAP, null); - - int reasonCode = 3; - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); - verify(mWifiMonitor, times(0)) - .broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt()); - - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); - verify(mWifiMonitor, times(0)) - .broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt()); - - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.ASSOCIATED, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - // Ensure we don't lose our prev state with this state changed event. - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.DISCONNECTED, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); - - verify(mWifiMonitor).broadcastAuthenticationFailureEvent( - eq(WLAN0_IFACE_NAME), eq(WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE), eq(-1)); - } - - /** - * Tests the handling of incorrect network passwords for WPA3-Personal networks - */ - @Test - public void testWpa3AuthRejectionPassword() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - executeAndValidateConnectSequenceWithKeyMgmt(SUPPLICANT_NETWORK_ID, false, - WifiConfiguration.KeyMgmt.SAE, null); - - int statusCode = ISupplicantStaIfaceCallback.StatusCode.UNSPECIFIED_FAILURE; - - mISupplicantStaIfaceCallback.onAssociationRejected( - NativeUtil.macAddressToByteArray(BSSID), statusCode, false); - verify(mWifiMonitor).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME), - eq(WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD), eq(-1)); - verify(mWifiMonitor).broadcastAssociationRejectionEvent( - eq(WLAN0_IFACE_NAME), eq(statusCode), eq(false), eq(BSSID)); - } - - /** - * Tests the handling of incorrect network passwords for WEP networks. - */ - @Test - public void testWepAuthRejectionPassword() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - executeAndValidateConnectSequenceWithKeyMgmt(SUPPLICANT_NETWORK_ID, false, - WifiConfiguration.KeyMgmt.NONE, "97CA326539"); - - int statusCode = ISupplicantStaIfaceCallback.StatusCode.CHALLENGE_FAIL; - - mISupplicantStaIfaceCallback.onAssociationRejected( - NativeUtil.macAddressToByteArray(BSSID), statusCode, false); - verify(mWifiMonitor).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME), - eq(WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD), eq(-1)); - verify(mWifiMonitor).broadcastAssociationRejectionEvent( - eq(WLAN0_IFACE_NAME), eq(statusCode), eq(false), eq(BSSID)); - } - - /** - * Tests the handling of incorrect network passwords, edge case. - * - * If the network is removed during 4-way handshake, do not call it a password mismatch. - */ - @Test - public void testNetworkRemovedDuring4way() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - int reasonCode = 3; - - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - mISupplicantStaIfaceCallback.onNetworkRemoved(SUPPLICANT_NETWORK_ID); - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); - verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(), - anyInt()); - } - - /** - * Tests the handling of incorrect network passwords, edge case. - * - * If the disconnect reason is "IE in 4way differs", do not call it a password mismatch. - */ - @Test - public void testIeDiffers() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.IE_IN_4WAY_DIFFERS; - - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); - verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(), - anyInt()); - } - - /** - * Tests the handling of eap failure during disconnect. - */ - @Test - public void testEapFailure() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.IEEE_802_1X_AUTH_FAILED; - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); - verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(), - anyInt()); - } - - /** - * Tests the handling of association rejection notification. - */ - @Test - public void testAssociationRejectionCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - int statusCode = 7; - mISupplicantStaIfaceCallback.onAssociationRejected( - NativeUtil.macAddressToByteArray(BSSID), statusCode, false); - verify(mWifiMonitor).broadcastAssociationRejectionEvent( - eq(WLAN0_IFACE_NAME), eq(statusCode), eq(false), eq(BSSID)); - } - - /** - * Tests the handling of authentification timeout notification. - */ - @Test - public void testAuthenticationTimeoutCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - mISupplicantStaIfaceCallback.onAuthenticationTimeout( - NativeUtil.macAddressToByteArray(BSSID)); - verify(mWifiMonitor).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME), - eq(WifiManager.ERROR_AUTH_FAILURE_TIMEOUT), eq(-1)); - } - - /** - * Tests the handling of bssid change notification. - */ - @Test - public void testBssidChangedCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - mISupplicantStaIfaceCallback.onBssidChanged( - BssidChangeReason.ASSOC_START, NativeUtil.macAddressToByteArray(BSSID)); - verify(mWifiMonitor).broadcastTargetBssidEvent(eq(WLAN0_IFACE_NAME), eq(BSSID)); - verify(mWifiMonitor, never()).broadcastAssociatedBssidEvent( - eq(WLAN0_IFACE_NAME), eq(BSSID)); - - reset(mWifiMonitor); - mISupplicantStaIfaceCallback.onBssidChanged( - BssidChangeReason.ASSOC_COMPLETE, NativeUtil.macAddressToByteArray(BSSID)); - verify(mWifiMonitor, never()).broadcastTargetBssidEvent(eq(WLAN0_IFACE_NAME), eq(BSSID)); - verify(mWifiMonitor).broadcastAssociatedBssidEvent(eq(WLAN0_IFACE_NAME), eq(BSSID)); - - reset(mWifiMonitor); - mISupplicantStaIfaceCallback.onBssidChanged( - BssidChangeReason.DISASSOC, NativeUtil.macAddressToByteArray(BSSID)); - verify(mWifiMonitor, never()).broadcastTargetBssidEvent(eq(WLAN0_IFACE_NAME), eq(BSSID)); - verify(mWifiMonitor, never()).broadcastAssociatedBssidEvent( - eq(WLAN0_IFACE_NAME), eq(BSSID)); - } - - /** - * Tests the handling of EAP failure notification. - */ - @Test - public void testEapFailureCallback() throws Exception { - int eapFailureCode = WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED; - testInitialize_successV1_1(); - assertNotNull(mISupplicantStaIfaceCallbackV1_1); - - mISupplicantStaIfaceCallbackV1_1.onEapFailure_1_1(eapFailureCode); - verify(mWifiMonitor).broadcastAuthenticationFailureEvent( - eq(WLAN0_IFACE_NAME), eq(WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE), - eq(eapFailureCode)); - } - - /** - * Tests the handling of EAP failure notification. - */ - @Test - public void testEapFailureCallback1_3() throws Exception { - int eapFailureCode = WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED; - testInitialize_successV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - - mISupplicantStaIfaceCallbackV13.onEapFailure_1_3(eapFailureCode); - verify(mWifiMonitor).broadcastAuthenticationFailureEvent( - eq(WLAN0_IFACE_NAME), eq(WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE), - eq(eapFailureCode)); - } - - /** - * Tests the handling of Wps success notification. - */ - @Test - public void testWpsSuccessCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - mISupplicantStaIfaceCallback.onWpsEventSuccess(); - verify(mWifiMonitor).broadcastWpsSuccessEvent(eq(WLAN0_IFACE_NAME)); - } - - /** - * Tests the handling of Wps fail notification. - */ - @Test - public void testWpsFailureCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - short cfgError = ISupplicantStaIfaceCallback.WpsConfigError.MULTIPLE_PBC_DETECTED; - short errorInd = ISupplicantStaIfaceCallback.WpsErrorIndication.SECURITY_WEP_PROHIBITED; - mISupplicantStaIfaceCallback.onWpsEventFail( - NativeUtil.macAddressToByteArray(BSSID), cfgError, errorInd); - verify(mWifiMonitor).broadcastWpsFailEvent(eq(WLAN0_IFACE_NAME), - eq((int) cfgError), eq((int) errorInd)); - } - - /** - * Tests the handling of Wps fail notification. - */ - @Test - public void testWpsTimeoutCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - short cfgError = ISupplicantStaIfaceCallback.WpsConfigError.MSG_TIMEOUT; - short errorInd = ISupplicantStaIfaceCallback.WpsErrorIndication.NO_ERROR; - mISupplicantStaIfaceCallback.onWpsEventFail( - NativeUtil.macAddressToByteArray(BSSID), cfgError, errorInd); - verify(mWifiMonitor).broadcastWpsTimeoutEvent(eq(WLAN0_IFACE_NAME)); - } - - /** - * Tests the handling of Wps pbc overlap notification. - */ - @Test - public void testWpsPbcOverlapCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - mISupplicantStaIfaceCallback.onWpsEventPbcOverlap(); - verify(mWifiMonitor).broadcastWpsOverlapEvent(eq(WLAN0_IFACE_NAME)); - } - - /** - * Tests the handling of service manager death notification. - */ - @Test - public void testServiceManagerDeathCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mServiceManagerDeathCaptor.getValue()); - assertTrue(mDut.isInitializationComplete()); - assertTrue(mDut.registerDeathHandler(mSupplicantHalDeathHandler)); - - mServiceManagerDeathCaptor.getValue().serviceDied(5L); - mLooper.dispatchAll(); - - assertFalse(mDut.isInitializationComplete()); - verify(mWifiMonitor).broadcastSupplicantDisconnectionEvent(eq(WLAN0_IFACE_NAME)); - verify(mSupplicantHalDeathHandler).onDeath(); - } - - /** - * Tests the handling of supplicant death notification. - */ - @Test - public void testSupplicantDeathCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mSupplicantDeathCaptor.getValue()); - assertTrue(mDut.isInitializationComplete()); - assertTrue(mDut.registerDeathHandler(mSupplicantHalDeathHandler)); - - mSupplicantDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue()); - mLooper.dispatchAll(); - - assertFalse(mDut.isInitializationComplete()); - verify(mWifiMonitor).broadcastSupplicantDisconnectionEvent(eq(WLAN0_IFACE_NAME)); - verify(mSupplicantHalDeathHandler).onDeath(); - } - - /** - * Tests the handling of supplicant death notification. - */ - @Test - public void testSupplicantStaleDeathCallback() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mSupplicantDeathCaptor.getValue()); - assertTrue(mDut.isInitializationComplete()); - assertTrue(mDut.registerDeathHandler(mSupplicantHalDeathHandler)); - - mSupplicantDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue() - 1); - mLooper.dispatchAll(); - - assertTrue(mDut.isInitializationComplete()); - verify(mWifiMonitor, never()).broadcastSupplicantDisconnectionEvent(eq(WLAN0_IFACE_NAME)); - verify(mSupplicantHalDeathHandler, never()).onDeath(); - } - - /** - * When wpa_supplicant is dead, we could end up getting a remote exception on a hwbinder call - * and then the death notification. - */ - @Test - public void testHandleRemoteExceptionAndDeathNotification() throws Exception { - executeAndValidateInitializationSequence(); - assertTrue(mDut.registerDeathHandler(mSupplicantHalDeathHandler)); - assertTrue(mDut.isInitializationComplete()); - - // Throw remote exception on hwbinder call. - when(mISupplicantStaIfaceMock.setPowerSave(anyBoolean())) - .thenThrow(new RemoteException()); - assertFalse(mDut.setPowerSave(WLAN0_IFACE_NAME, true)); - verify(mISupplicantStaIfaceMock).setPowerSave(true); - - // Check that remote exception cleared all internal state. - assertFalse(mDut.isInitializationComplete()); - - // Ensure that further calls fail because the remote exception clears any state. - assertFalse(mDut.setPowerSave(WLAN0_IFACE_NAME, true)); - //.. No call to ISupplicantStaIface object - - // Now trigger a death notification and ensure it's handled. - assertNotNull(mSupplicantDeathCaptor.getValue()); - mSupplicantDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue()); - mLooper.dispatchAll(); - - // External death notification fires only once! - verify(mSupplicantHalDeathHandler).onDeath(); - } - - /** - * Tests the setting of log level. - */ - @Test - public void testSetLogLevel() throws Exception { - when(mISupplicantMock.setDebugParams(anyInt(), anyBoolean(), anyBoolean())) - .thenReturn(mStatusSuccess); - - // Fail before initialization is performed. - assertFalse(mDut.setLogLevel(true)); - - executeAndValidateInitializationSequence(); - - // This should work. - assertTrue(mDut.setLogLevel(true)); - verify(mISupplicantMock) - .setDebugParams(eq(ISupplicant.DebugLevel.DEBUG), eq(false), eq(false)); - } - - /** - * Tests the setting of concurrency priority. - */ - @Test - public void testConcurrencyPriority() throws Exception { - when(mISupplicantMock.setConcurrencyPriority(anyInt())).thenReturn(mStatusSuccess); - - // Fail before initialization is performed. - assertFalse(mDut.setConcurrencyPriority(false)); - - executeAndValidateInitializationSequence(); - - // This should work. - assertTrue(mDut.setConcurrencyPriority(false)); - verify(mISupplicantMock).setConcurrencyPriority(eq(IfaceType.P2P)); - assertTrue(mDut.setConcurrencyPriority(true)); - verify(mISupplicantMock).setConcurrencyPriority(eq(IfaceType.STA)); - } - - /** - * Tests the start of wps registrar. - */ - @Test - public void testStartWpsRegistrar() throws Exception { - when(mISupplicantStaIfaceMock.startWpsRegistrar(any(byte[].class), anyString())) - .thenReturn(mStatusSuccess); - - // Fail before initialization is performed. - assertFalse(mDut.startWpsRegistrar(WLAN0_IFACE_NAME, null, null)); - - executeAndValidateInitializationSequence(); - - assertFalse(mDut.startWpsRegistrar(WLAN0_IFACE_NAME, null, null)); - verify(mISupplicantStaIfaceMock, never()).startWpsRegistrar(any(byte[].class), anyString()); - - assertFalse(mDut.startWpsRegistrar(WLAN0_IFACE_NAME, new String(), "452233")); - verify(mISupplicantStaIfaceMock, never()).startWpsRegistrar(any(byte[].class), anyString()); - - assertTrue(mDut.startWpsRegistrar(WLAN0_IFACE_NAME, "45:23:12:12:12:98", "562535")); - verify(mISupplicantStaIfaceMock).startWpsRegistrar(any(byte[].class), anyString()); - } - - /** - * Tests the start of wps PBC. - */ - @Test - public void testStartWpsPbc() throws Exception { - when(mISupplicantStaIfaceMock.startWpsPbc(any(byte[].class))).thenReturn(mStatusSuccess); - String bssid = "45:23:12:12:12:98"; - byte[] bssidBytes = {0x45, 0x23, 0x12, 0x12, 0x12, (byte) 0x98}; - byte[] anyBssidBytes = {0, 0, 0, 0, 0, 0}; - - // Fail before initialization is performed. - assertFalse(mDut.startWpsPbc(WLAN0_IFACE_NAME, bssid)); - verify(mISupplicantStaIfaceMock, never()).startWpsPbc(any(byte[].class)); - - executeAndValidateInitializationSequence(); - - assertTrue(mDut.startWpsPbc(WLAN0_IFACE_NAME, bssid)); - verify(mISupplicantStaIfaceMock).startWpsPbc(eq(bssidBytes)); - - assertTrue(mDut.startWpsPbc(WLAN0_IFACE_NAME, null)); - verify(mISupplicantStaIfaceMock).startWpsPbc(eq(anyBssidBytes)); - } - - /** - * Tests country code setter - */ - @Test - public void testSetCountryCode() throws Exception { - when(mISupplicantStaIfaceMock.setCountryCode(any(byte[].class))).thenReturn(mStatusSuccess); - String testCountryCode = "US"; - - // Fail before initialization is performed. - assertFalse(mDut.setCountryCode(WLAN0_IFACE_NAME, testCountryCode)); - verify(mISupplicantStaIfaceMock, never()).setCountryCode(any(byte[].class)); - - executeAndValidateInitializationSequence(); - - assertTrue(mDut.setCountryCode(WLAN0_IFACE_NAME, testCountryCode)); - verify(mISupplicantStaIfaceMock).setCountryCode(eq(testCountryCode.getBytes())); - - // Bad input values should fail the call. - reset(mISupplicantStaIfaceMock); - - assertFalse(mDut.setCountryCode(WLAN0_IFACE_NAME, null)); - verify(mISupplicantStaIfaceMock, never()).setCountryCode(any(byte[].class)); - - assertFalse(mDut.setCountryCode(WLAN0_IFACE_NAME, "U")); - verify(mISupplicantStaIfaceMock, never()).setCountryCode(any(byte[].class)); - } - - /** - * Tests the start daemon for V1_0 service. - */ - @Test - public void testStartDaemonV1_0() throws Exception { - executeAndValidateInitializationSequence(); - assertTrue(mDut.startDaemon()); - verify(mFrameworkFacade).startSupplicant(); - } - - /** - * Tests the start daemon for V1_1 service. - */ - @Test - public void testStartDaemonV1_1() throws Exception { - setupMocksForHalV1_1(); - - executeAndValidateInitializationSequenceV1_1(false, false); - assertTrue(mDut.startDaemon()); - verify(mFrameworkFacade, never()).startSupplicant(); - } - - /** - * Tests the terminate for V1_0 service. - */ - @Test - public void testTerminateV1_0() throws Exception { - executeAndValidateInitializationSequence(); - mDut.terminate(); - verify(mFrameworkFacade).stopSupplicant(); - } - - /** - * Tests the start daemon for V1_1 service. - */ - @Test - public void testTerminateV1_1() throws Exception { - setupMocksForHalV1_1(); - - executeAndValidateInitializationSequenceV1_1(false, false); - mDut.terminate(); - verify(mFrameworkFacade, never()).stopSupplicant(); - verify(mISupplicantMockV1_1).terminate(); - } - - private class GetKeyMgmtCapabilitiesAnswer extends MockAnswerUtil.AnswerWithArguments { - private int mKeyMgmtCapabilities; - - GetKeyMgmtCapabilitiesAnswer(int keyMgmtCapabilities) { - mKeyMgmtCapabilities = keyMgmtCapabilities; - } - - public void answer(android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - .getKeyMgmtCapabilitiesCallback cb) { - cb.onValues(mStatusSuccess, mKeyMgmtCapabilities); - } - } - - private class GetKeyMgmtCapabilities_1_3Answer extends MockAnswerUtil.AnswerWithArguments { - private int mKeyMgmtCapabilities; - - GetKeyMgmtCapabilities_1_3Answer(int keyMgmtCapabilities) { - mKeyMgmtCapabilities = keyMgmtCapabilities; - } - - public void answer(android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getKeyMgmtCapabilities_1_3Callback cb) { - cb.onValues(mStatusSuccess, mKeyMgmtCapabilities); - } - } - - /** - * Test get key management capabilities API on old HAL, should return 0 (not supported) - */ - @Test - public void testGetKeyMgmtCapabilitiesOldHal() throws Exception { - setupMocksForHalV1_1(); - - executeAndValidateInitializationSequenceV1_1(false, false); - - assertTrue(mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME) == 0); - } - - /** - * Test WPA3-Personal SAE key may management support - */ - @Test - public void testGetKeyMgmtCapabilitiesWpa3Sae() throws Exception { - setupMocksForHalV1_2(); - - executeAndValidateInitializationSequenceV1_2(); - - doAnswer(new GetKeyMgmtCapabilitiesAnswer(android.hardware.wifi.supplicant.V1_2 - .ISupplicantStaNetwork.KeyMgmtMask.SAE)) - .when(mISupplicantStaIfaceMockV1_2).getKeyMgmtCapabilities(any( - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - .getKeyMgmtCapabilitiesCallback.class)); - - assertEquals(WIFI_FEATURE_WPA3_SAE, mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME)); - } - - /** - * Test WPA3-Enterprise Suite-B-192 key may management support - */ - @Test - public void testGetKeyMgmtCapabilitiesWpa3SuiteB() throws Exception { - setupMocksForHalV1_2(); - - executeAndValidateInitializationSequenceV1_2(); - - doAnswer(new GetKeyMgmtCapabilitiesAnswer(android.hardware.wifi.supplicant.V1_2 - .ISupplicantStaNetwork.KeyMgmtMask.SUITE_B_192)) - .when(mISupplicantStaIfaceMockV1_2).getKeyMgmtCapabilities(any( - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - .getKeyMgmtCapabilitiesCallback.class)); - - assertEquals(WIFI_FEATURE_WPA3_SUITE_B, - mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME)); - } - - /** - * Test Enhanced Open (OWE) key may management support - */ - @Test - public void testGetKeyMgmtCapabilitiesOwe() throws Exception { - setupMocksForHalV1_2(); - - executeAndValidateInitializationSequenceV1_2(); - - doAnswer(new GetKeyMgmtCapabilitiesAnswer(android.hardware.wifi.supplicant.V1_2 - .ISupplicantStaNetwork.KeyMgmtMask.OWE)) - .when(mISupplicantStaIfaceMockV1_2).getKeyMgmtCapabilities(any( - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - .getKeyMgmtCapabilitiesCallback.class)); - - assertEquals(WIFI_FEATURE_OWE, mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME)); - } - - /** - * Test Enhanced Open (OWE) and SAE key may management support - */ - @Test - public void testGetKeyMgmtCapabilitiesOweAndSae() throws Exception { - setupMocksForHalV1_2(); - - executeAndValidateInitializationSequenceV1_2(); - - doAnswer(new GetKeyMgmtCapabilitiesAnswer(android.hardware.wifi.supplicant.V1_2 - .ISupplicantStaNetwork.KeyMgmtMask.OWE - | android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask.SAE)) - .when(mISupplicantStaIfaceMockV1_2).getKeyMgmtCapabilities(any( - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - .getKeyMgmtCapabilitiesCallback.class)); - - assertEquals(WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE, - mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME)); - } - - /** - * Test Easy Connect (DPP) key may management support - */ - @Test - public void testGetKeyMgmtCapabilitiesDpp() throws Exception { - setupMocksForHalV1_2(); - - executeAndValidateInitializationSequenceV1_2(); - - doAnswer(new GetKeyMgmtCapabilitiesAnswer(android.hardware.wifi.supplicant.V1_2 - .ISupplicantStaNetwork.KeyMgmtMask.DPP)) - .when(mISupplicantStaIfaceMockV1_2).getKeyMgmtCapabilities(any( - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface - .getKeyMgmtCapabilitiesCallback.class)); - - assertEquals(WIFI_FEATURE_DPP, mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME)); - } - - /** - * Test WAPI key may management support - */ - @Test - public void testGetKeyMgmtCapabilitiesWapi() throws Exception { - setupMocksForHalV1_3(); - - executeAndValidateInitializationSequenceV1_3(); - - doAnswer(new GetKeyMgmtCapabilities_1_3Answer(android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.KeyMgmtMask.WAPI_PSK)) - .when(mISupplicantStaIfaceMockV13).getKeyMgmtCapabilities_1_3(any( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getKeyMgmtCapabilities_1_3Callback.class)); - - assertEquals(WIFI_FEATURE_WAPI, mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME)); - } - - /** - * Test FILS SHA256 key management support. - */ - @Test - public void testGetKeyMgmtCapabilitiesFilsSha256() throws Exception { - setupMocksForHalV1_3(); - - executeAndValidateInitializationSequenceV1_3(); - - doAnswer(new GetKeyMgmtCapabilities_1_3Answer(android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.KeyMgmtMask.FILS_SHA256)) - .when(mISupplicantStaIfaceMockV13).getKeyMgmtCapabilities_1_3(any( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getKeyMgmtCapabilities_1_3Callback.class)); - - assertEquals(WIFI_FEATURE_FILS_SHA256, - mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME)); - } - - /** - * Test FILS SHA384 key management support. - */ - @Test - public void testGetKeyMgmtCapabilitiesFilsSha384() throws Exception { - setupMocksForHalV1_3(); - - executeAndValidateInitializationSequenceV1_3(); - - doAnswer(new GetKeyMgmtCapabilities_1_3Answer(android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.KeyMgmtMask.FILS_SHA384)) - .when(mISupplicantStaIfaceMockV13).getKeyMgmtCapabilities_1_3(any( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getKeyMgmtCapabilities_1_3Callback.class)); - - assertEquals(WIFI_FEATURE_FILS_SHA384, - mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME)); - } - - /** - * Test Easy Connect (DPP) calls return failure if hal version is less than 1_2 - */ - @Test - public void testDppFailsWithOldHal() throws Exception { - assertEquals(-1, mDut.addDppPeerUri(WLAN0_IFACE_NAME, "/blah")); - assertFalse(mDut.removeDppUri(WLAN0_IFACE_NAME, 0)); - assertFalse(mDut.stopDppInitiator(WLAN0_IFACE_NAME)); - assertFalse(mDut.startDppConfiguratorInitiator(WLAN0_IFACE_NAME, - 1, 2, "Buckle", "My", "Shoe", - 3, 4)); - assertFalse(mDut.startDppEnrolleeInitiator(WLAN0_IFACE_NAME, 3, 14)); - } - - /** - * Test adding PMK cache entry to the supplicant. - */ - @Test - public void testSetPmkSuccess() throws Exception { - int testFrameworkNetworkId = 9; - long testStartSeconds = PMK_CACHE_EXPIRATION_IN_SEC / 2; - WifiConfiguration config = new WifiConfiguration(); - config.networkId = testFrameworkNetworkId; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - PmkCacheStoreData pmkCacheData = - new PmkCacheStoreData(PMK_CACHE_EXPIRATION_IN_SEC, new ArrayList<Byte>(), - MacAddress.fromBytes(CONNECTED_MAC_ADDRESS_BYTES)); - mDut.mPmkCacheEntries.put(testFrameworkNetworkId, pmkCacheData); - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartSeconds * 1000L); - - setupMocksForHalV1_3(); - setupMocksForPmkCache(); - setupMocksForConnectSequence(false); - - executeAndValidateInitializationSequenceV1_3(); - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - - verify(mSupplicantStaNetworkMock).setPmkCache(eq(pmkCacheData.data)); - verify(mISupplicantStaIfaceCallbackV13) - .onPmkCacheAdded(eq(PMK_CACHE_EXPIRATION_IN_SEC), eq(pmkCacheData.data)); - // there is only one cache entry, the next expiration alarm should be the same as - // its expiration time. - verify(mHandler).postDelayed( - /* private listener */ any(), - eq(SupplicantStaIfaceHal.PMK_CACHE_EXPIRATION_ALARM_TAG), - eq((PMK_CACHE_EXPIRATION_IN_SEC - testStartSeconds) * 1000)); - } - - /** - * Test adding PMK cache entry is not called if there is no - * valid PMK cache for a corresponding configuratoin. - */ - @Test - public void testAddPmkEntryNotCalledIfNoPmkCache() throws Exception { - int testFrameworkNetworkId = 9; - long testStartSeconds = PMK_CACHE_EXPIRATION_IN_SEC / 2; - WifiConfiguration config = new WifiConfiguration(); - config.networkId = testFrameworkNetworkId; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartSeconds * 1000L); - - setupMocksForHalV1_3(); - setupMocksForPmkCache(); - setupMocksForConnectSequence(false); - executeAndValidateInitializationSequenceV1_3(); - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - - verify(mSupplicantStaNetworkMock, never()).setPmkCache(any(ArrayList.class)); - verify(mISupplicantStaIfaceCallbackV13, never()).onPmkCacheAdded( - anyLong(), any(ArrayList.class)); - verify(mHandler, never()).postDelayed( - /* private listener */ any(), - eq(SupplicantStaIfaceHal.PMK_CACHE_EXPIRATION_ALARM_TAG), - anyLong()); - } - - /** - * Test adding PMK cache entry returns faliure if this is a psk network. - */ - @Test - public void testAddPmkEntryIsOmittedWithPskNetwork() throws Exception { - int testFrameworkNetworkId = 9; - long testStartSeconds = PMK_CACHE_EXPIRATION_IN_SEC / 2; - WifiConfiguration config = new WifiConfiguration(); - config.networkId = testFrameworkNetworkId; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - PmkCacheStoreData pmkCacheData = - new PmkCacheStoreData(PMK_CACHE_EXPIRATION_IN_SEC, new ArrayList<Byte>(), - MacAddress.fromBytes(CONNECTED_MAC_ADDRESS_BYTES)); - mDut.mPmkCacheEntries.put(testFrameworkNetworkId, pmkCacheData); - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartSeconds * 1000L); - - setupMocksForHalV1_3(); - setupMocksForPmkCache(); - setupMocksForConnectSequence(false); - executeAndValidateInitializationSequenceV1_3(); - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - - verify(mSupplicantStaNetworkMock, never()).setPmkCache(any(ArrayList.class)); - verify(mISupplicantStaIfaceCallbackV13, never()).onPmkCacheAdded( - anyLong(), any(ArrayList.class)); - verify(mHandler, never()).postDelayed( - /* private listener */ any(), - eq(SupplicantStaIfaceHal.PMK_CACHE_EXPIRATION_ALARM_TAG), - anyLong()); - } - - /** - * Test adding PMK cache entry returns faliure if HAL version is less than 1_3 - */ - @Test - public void testAddPmkEntryIsOmittedWithOldHal() throws Exception { - int testFrameworkNetworkId = 9; - long testStartSeconds = PMK_CACHE_EXPIRATION_IN_SEC / 2; - WifiConfiguration config = new WifiConfiguration(); - config.networkId = testFrameworkNetworkId; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - PmkCacheStoreData pmkCacheData = - new PmkCacheStoreData(PMK_CACHE_EXPIRATION_IN_SEC, new ArrayList<Byte>(), - MacAddress.fromBytes(CONNECTED_MAC_ADDRESS_BYTES)); - mDut.mPmkCacheEntries.put(testFrameworkNetworkId, pmkCacheData); - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartSeconds * 1000L); - - setupMocksForConnectSequence(false); - executeAndValidateInitializationSequence(); - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - - verify(mSupplicantStaNetworkMock).setPmkCache(eq(pmkCacheData.data)); - assertNull(mISupplicantStaIfaceCallbackV13); - verify(mHandler, never()).postDelayed( - /* private listener */ any(), - eq(SupplicantStaIfaceHal.PMK_CACHE_EXPIRATION_ALARM_TAG), - anyLong()); - } - - /** - * Tests the handling of assoc reject for PMK cache - */ - @Test - public void testRemovePmkEntryOnReceivingAssocReject() throws Exception { - int testFrameworkNetworkId = 9; - long testStartSeconds = PMK_CACHE_EXPIRATION_IN_SEC / 2; - WifiConfiguration config = new WifiConfiguration(); - config.networkId = testFrameworkNetworkId; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - PmkCacheStoreData pmkCacheData = - new PmkCacheStoreData(PMK_CACHE_EXPIRATION_IN_SEC, new ArrayList<Byte>(), - MacAddress.fromBytes(CONNECTED_MAC_ADDRESS_BYTES)); - mDut.mPmkCacheEntries.put(testFrameworkNetworkId, pmkCacheData); - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartSeconds * 1000L); - - setupMocksForHalV1_3(); - setupMocksForPmkCache(); - setupMocksForConnectSequence(false); - - executeAndValidateInitializationSequenceV1_3(); - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - - int statusCode = 7; - mISupplicantStaIfaceCallbackV13.onAssociationRejected( - NativeUtil.macAddressToByteArray(BSSID), statusCode, false); - - assertNull(mDut.mPmkCacheEntries.get(testFrameworkNetworkId)); - } - - /** - * Tests the PMK cache is removed and not set if MAC address is changed. - */ - @Test - public void testRemovePmkEntryOnMacAddressChanged() throws Exception { - int testFrameworkNetworkId = 9; - long testStartSeconds = PMK_CACHE_EXPIRATION_IN_SEC / 2; - WifiConfiguration config = new WifiConfiguration(); - config.networkId = testFrameworkNetworkId; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - // Assume we have a PMK cache with a different MAC address. - final byte[] previouisConnectedMacAddressBytes = - {0x00, 0x01, 0x02, 0x03, 0x04, 0x09}; - PmkCacheStoreData pmkCacheData = - new PmkCacheStoreData(PMK_CACHE_EXPIRATION_IN_SEC, new ArrayList<Byte>(), - MacAddress.fromBytes(previouisConnectedMacAddressBytes)); - mDut.mPmkCacheEntries.put(testFrameworkNetworkId, pmkCacheData); - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartSeconds * 1000L); - - setupMocksForHalV1_3(); - setupMocksForPmkCache(); - setupMocksForConnectSequence(false); - - // When MAC is not changed, PMK cache should NOT be removed. - mDut.removeNetworkCachedDataIfNeeded(testFrameworkNetworkId, - MacAddress.fromBytes(previouisConnectedMacAddressBytes)); - assertEquals(pmkCacheData, mDut.mPmkCacheEntries.get(testFrameworkNetworkId)); - - // When MAC is changed, PMK cache should be removed. - mDut.removeNetworkCachedDataIfNeeded(testFrameworkNetworkId, - MacAddress.fromBytes(CONNECTED_MAC_ADDRESS_BYTES)); - assertNull(mDut.mPmkCacheEntries.get(testFrameworkNetworkId)); - } - - /** - * Test getConnectionCapabilities - * Should fail if running HAL lower than V1_3 - */ - @Test - public void testGetConnectionCapabilitiesV1_2() throws Exception { - setupMocksForHalV1_2(); - executeAndValidateInitializationSequenceV1_2(); - WifiNative.ConnectionCapabilities cap = mDut.getConnectionCapabilities(WLAN0_IFACE_NAME); - assertEquals(ScanResult.WIFI_STANDARD_UNKNOWN, cap.wifiStandard); - } - - private class GetConnCapabilitiesAnswer extends MockAnswerUtil.AnswerWithArguments { - private ConnectionCapabilities mConnCapabilities; - - GetConnCapabilitiesAnswer(int wifiTechnology, int channelBandwidth, - int maxNumberTxSpatialStreams, int maxNumberRxSpatialStreams) { - mConnCapabilities = new ConnectionCapabilities(); - mConnCapabilities.technology = wifiTechnology; - mConnCapabilities.channelBandwidth = channelBandwidth; - mConnCapabilities.maxNumberTxSpatialStreams = maxNumberTxSpatialStreams; - mConnCapabilities.maxNumberRxSpatialStreams = maxNumberRxSpatialStreams; - } - - public void answer(android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getConnectionCapabilitiesCallback cb) { - cb.onValues(mStatusSuccess, mConnCapabilities); - } - } - - /** - * Test getConnectionCapabilities if running with HAL V1_3 - */ - @Test - public void testGetConnectionCapabilitiesV1_3() throws Exception { - setupMocksForHalV1_3(); - - executeAndValidateInitializationSequenceV1_3(); - int testWifiTechnologyHal = WifiTechnology.VHT; - int testWifiStandardWifiInfo = ScanResult.WIFI_STANDARD_11AC; - int testChannelBandwidthHal = WifiChannelWidthInMhz.WIDTH_80P80; - int testChannelBandwidth = ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; - int maxNumberTxSpatialStreams = 3; - int maxNumberRxSpatialStreams = 1; - - doAnswer(new GetConnCapabilitiesAnswer(testWifiTechnologyHal, testChannelBandwidthHal, - maxNumberTxSpatialStreams, maxNumberRxSpatialStreams)) - .when(mISupplicantStaIfaceMockV13).getConnectionCapabilities(any( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getConnectionCapabilitiesCallback.class)); - WifiNative.ConnectionCapabilities cap = mDut.getConnectionCapabilities(WLAN0_IFACE_NAME); - assertEquals(testWifiStandardWifiInfo, cap.wifiStandard); - assertEquals(testChannelBandwidth, cap.channelBandwidth); - assertEquals(maxNumberTxSpatialStreams, cap.maxNumberTxSpatialStreams); - assertEquals(maxNumberRxSpatialStreams, cap.maxNumberRxSpatialStreams); - } - - private WifiConfiguration createTestWifiConfiguration() { - WifiConfiguration config = new WifiConfiguration(); - config.networkId = SUPPLICANT_NETWORK_ID; - return config; - } - - private void executeAndValidateHs20DeauthImminentCallback(boolean isEss) throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - byte[] bssid = NativeUtil.macAddressToByteArray(BSSID); - int reasonCode = isEss ? WnmData.ESS : WnmData.ESS + 1; - int reauthDelay = 5; - mISupplicantStaIfaceCallback.onHs20DeauthImminentNotice( - bssid, reasonCode, reauthDelay, HS20_URL); - - ArgumentCaptor<WnmData> wnmDataCaptor = ArgumentCaptor.forClass(WnmData.class); - verify(mWifiMonitor).broadcastWnmEvent(eq(WLAN0_IFACE_NAME), wnmDataCaptor.capture()); - assertEquals( - ByteBufferReader.readInteger( - ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length), - wnmDataCaptor.getValue().getBssid()); - assertEquals(isEss, wnmDataCaptor.getValue().isEss()); - assertEquals(reauthDelay, wnmDataCaptor.getValue().getDelay()); - assertEquals(HS20_URL, wnmDataCaptor.getValue().getUrl()); - } - - private void executeAndValidateInitializationSequence() throws Exception { - executeAndValidateInitializationSequence(false, false, false, false); - } - - /** - * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the - * expected result. Verifies if ISupplicantStaIface manager is initialized or reset. - * Each of the arguments will cause a different failure mode when set true. - */ - private void executeAndValidateInitializationSequence(boolean causeRemoteException, - boolean getZeroInterfaces, - boolean getNullInterface, - boolean causeCallbackRegFailure) - throws Exception { - boolean shouldSucceed = - !causeRemoteException && !getZeroInterfaces && !getNullInterface - && !causeCallbackRegFailure; - // Setup callback mock answers - ArrayList<ISupplicant.IfaceInfo> interfaces; - if (getZeroInterfaces) { - interfaces = new ArrayList<>(); - } else { - interfaces = mIfaceInfoList; - } - doAnswer(new GetListInterfacesAnswer(interfaces)).when(mISupplicantMock) - .listInterfaces(any(ISupplicant.listInterfacesCallback.class)); - if (causeRemoteException) { - doThrow(new RemoteException("Some error!!!")) - .when(mISupplicantMock).getInterface(any(ISupplicant.IfaceInfo.class), - any(ISupplicant.getInterfaceCallback.class)); - } else { - doAnswer(new GetGetInterfaceAnswer(getNullInterface)) - .when(mISupplicantMock).getInterface(any(ISupplicant.IfaceInfo.class), - any(ISupplicant.getInterfaceCallback.class)); - } - /** Callback registration */ - if (causeCallbackRegFailure) { - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer(ISupplicantStaIfaceCallback cb) - throws RemoteException { - return mStatusFailure; - } - }).when(mISupplicantStaIfaceMock) - .registerCallback(any(ISupplicantStaIfaceCallback.class)); - } else { - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer(ISupplicantStaIfaceCallback cb) - throws RemoteException { - mISupplicantStaIfaceCallback = cb; - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMock) - .registerCallback(any(ISupplicantStaIfaceCallback.class)); - } - - mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantStaIfaceMock, - mWifiMonitor); - // Initialize SupplicantStaIfaceHal, should call serviceManager.registerForNotifications - assertTrue(mDut.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true); - - assertTrue(mDut.isInitializationComplete()); - assertEquals(shouldSucceed, mDut.setupIface(WLAN0_IFACE_NAME)); - mInOrder.verify(mISupplicantMock).linkToDeath(mSupplicantDeathCaptor.capture(), - mDeathRecipientCookieCaptor.capture()); - // verify: listInterfaces is called - mInOrder.verify(mISupplicantMock).listInterfaces( - any(ISupplicant.listInterfacesCallback.class)); - if (!getZeroInterfaces) { - mInOrder.verify(mISupplicantMock) - .getInterface(any(ISupplicant.IfaceInfo.class), - any(ISupplicant.getInterfaceCallback.class)); - } - if (!causeRemoteException && !getZeroInterfaces && !getNullInterface) { - mInOrder.verify(mISupplicantStaIfaceMock) - .registerCallback(any(ISupplicantStaIfaceCallback.class)); - } - } - - /** - * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the - * expected result. Verifies if ISupplicantStaIface manager is initialized or reset. - * Each of the arguments will cause a different failure mode when set true. - */ - private void executeAndValidateInitializationSequenceV1_1(boolean causeRemoteException, - boolean getNullInterface) - throws Exception { - boolean shouldSucceed = !causeRemoteException && !getNullInterface; - // Setup callback mock answers - if (causeRemoteException) { - doThrow(new RemoteException("Some error!!!")) - .when(mISupplicantMockV1_1).addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback.class)); - } else { - doAnswer(new GetAddInterfaceAnswer(getNullInterface)) - .when(mISupplicantMockV1_1).addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback.class)); - } - /** Callback registration */ - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer( - android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback cb) - throws RemoteException { - mISupplicantStaIfaceCallbackV1_1 = cb; - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMockV1_1) - .registerCallback_1_1( - any(android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback.class)); - - mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantMockV1_1, - mISupplicantStaIfaceMockV1_1, mWifiMonitor); - // Initialize SupplicantStaIfaceHal, should call serviceManager.registerForNotifications - assertTrue(mDut.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true); - - assertTrue(mDut.isInitializationComplete()); - assertTrue(mDut.setupIface(WLAN0_IFACE_NAME) == shouldSucceed); - mInOrder.verify(mISupplicantMock).linkToDeath(mSupplicantDeathCaptor.capture(), - anyLong()); - // verify: addInterface is called - mInOrder.verify(mISupplicantMockV1_1) - .addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback.class)); - if (!causeRemoteException && !getNullInterface) { - mInOrder.verify(mISupplicantStaIfaceMockV1_1) - .registerCallback_1_1( - any(android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback.class)); - } - - // Ensure we don't try to use the listInterfaces method from 1.0 version. - verify(mISupplicantMock, never()).listInterfaces( - any(ISupplicant.listInterfacesCallback.class)); - verify(mISupplicantMock, never()).getInterface(any(ISupplicant.IfaceInfo.class), - any(ISupplicant.getInterfaceCallback.class)); - } - - /** - * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the - * expected result. Verifies if ISupplicantStaIface manager is initialized or reset. - * Each of the arguments will cause a different failure mode when set true. - */ - private void executeAndValidateInitializationSequenceV1_2() - throws Exception { - // Setup callback mock answers - doAnswer(new GetAddInterfaceAnswerV1_2(false)) - .when(mISupplicantMockV1_1).addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_2.ISupplicant - .addInterfaceCallback.class)); - - /** Callback registration */ - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer( - android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback cb) - throws RemoteException { - mISupplicantStaIfaceCallbackV1_1 = cb; - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMockV1_2) - .registerCallback_1_1( - any(android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback - .class)); - - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer( - android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback cb) - throws RemoteException { - mISupplicantStaIfaceCallbackV1_2 = cb; - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMockV1_2) - .registerCallback_1_2( - any(android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback - .class)); - - mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantMockV1_1, - mISupplicantStaIfaceMockV1_2, mWifiMonitor); - // Initialize SupplicantStaIfaceHal, should call serviceManager.registerForNotifications - assertTrue(mDut.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true); - - assertTrue(mDut.isInitializationComplete()); - assertTrue(mDut.setupIface(WLAN0_IFACE_NAME)); - mInOrder.verify(mISupplicantMock).linkToDeath(mSupplicantDeathCaptor.capture(), - anyLong()); - // verify: addInterface is called - mInOrder.verify(mISupplicantMockV1_1) - .addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_2.ISupplicant - .addInterfaceCallback.class)); - - mInOrder.verify(mISupplicantStaIfaceMockV1_2) - .registerCallback_1_2( - any(android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback - .class)); - - // Ensure we don't try to use the listInterfaces method from 1.0 version. -// verify(mISupplicantMock, never()).listInterfaces( -// any(ISupplicant.listInterfacesCallback.class)); -// verify(mISupplicantMock, never()).getInterface(any(ISupplicant.IfaceInfo.class), -// any(ISupplicant.getInterfaceCallback.class)); - } - - /** - * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the - * expected result. Verifies if ISupplicantStaIface manager is initialized or reset. - * Each of the arguments will cause a different failure mode when set true. - */ - private void executeAndValidateInitializationSequenceV1_3() - throws Exception { - // Setup callback mock answers - doAnswer(new GetAddInterfaceAnswerV1_3(false)) - .when(mISupplicantMockV1_1).addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback.class)); - - /** Callback registration */ - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback cb) - throws RemoteException { - mISupplicantStaIfaceCallbackV13 = spy(cb); - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMockV13) - .registerCallback_1_3( - any(android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback - .class)); - - mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantMockV1_1, - mISupplicantStaIfaceMockV13, mWifiMonitor); - // Initialize SupplicantStaIfaceHal, should call serviceManager.registerForNotifications - assertTrue(mDut.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true); - - assertTrue(mDut.isInitializationComplete()); - assertTrue(mDut.setupIface(WLAN0_IFACE_NAME)); - mInOrder.verify(mISupplicantMock).linkToDeath(mSupplicantDeathCaptor.capture(), - anyLong()); - // verify: addInterface is called - mInOrder.verify(mISupplicantMockV1_1) - .addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback.class)); - - mInOrder.verify(mISupplicantStaIfaceMockV13) - .registerCallback_1_3( - any(android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback - .class)); - } - - private SupplicantStatus createSupplicantStatus(int code) { - SupplicantStatus status = new SupplicantStatus(); - status.code = code; - return status; - } - - /** - * Create an IfaceInfo with given type and name - */ - private ISupplicant.IfaceInfo createIfaceInfo(int type, String name) { - ISupplicant.IfaceInfo info = new ISupplicant.IfaceInfo(); - info.type = type; - info.name = name; - return info; - } - - private class GetListInterfacesAnswer extends MockAnswerUtil.AnswerWithArguments { - private ArrayList<ISupplicant.IfaceInfo> mInterfaceList; - - GetListInterfacesAnswer(ArrayList<ISupplicant.IfaceInfo> ifaces) { - mInterfaceList = ifaces; - } - - public void answer(ISupplicant.listInterfacesCallback cb) { - cb.onValues(mStatusSuccess, mInterfaceList); - } - } - - private class GetGetInterfaceAnswer extends MockAnswerUtil.AnswerWithArguments { - boolean mGetNullInterface; - - GetGetInterfaceAnswer(boolean getNullInterface) { - mGetNullInterface = getNullInterface; - } - - public void answer(ISupplicant.IfaceInfo iface, ISupplicant.getInterfaceCallback cb) { - if (mGetNullInterface) { - cb.onValues(mStatusSuccess, null); - } else { - cb.onValues(mStatusSuccess, mISupplicantIfaceMock); - } - } - } - - private class GetAddInterfaceAnswer extends MockAnswerUtil.AnswerWithArguments { - boolean mGetNullInterface; - - GetAddInterfaceAnswer(boolean getNullInterface) { - mGetNullInterface = getNullInterface; - } - - public void answer(ISupplicant.IfaceInfo iface, - android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback cb) { - if (mGetNullInterface) { - cb.onValues(mStatusSuccess, null); - } else { - cb.onValues(mStatusSuccess, mISupplicantIfaceMock); - } - } - } - - private class GetAddInterfaceAnswerV1_2 extends MockAnswerUtil.AnswerWithArguments { - boolean mGetNullInterface; - - GetAddInterfaceAnswerV1_2(boolean getNullInterface) { - mGetNullInterface = getNullInterface; - } - - public void answer(ISupplicant.IfaceInfo iface, - android.hardware.wifi.supplicant.V1_2.ISupplicant - .addInterfaceCallback cb) { - if (mGetNullInterface) { - cb.onValues(mStatusSuccess, null); - } else { - cb.onValues(mStatusSuccess, mISupplicantIfaceMock); - } - } - } - - private class GetAddInterfaceAnswerV1_3 extends MockAnswerUtil.AnswerWithArguments { - boolean mGetNullInterface; - - GetAddInterfaceAnswerV1_3(boolean getNullInterface) { - mGetNullInterface = getNullInterface; - } - - public void answer(ISupplicant.IfaceInfo iface, - android.hardware.wifi.supplicant.V1_3.ISupplicant - .addInterfaceCallback cb) { - if (mGetNullInterface) { - cb.onValues(mStatusSuccess, null); - } else { - cb.onValues(mStatusSuccess, mISupplicantIfaceMock); - } - } - } - - /** - * Setup mocks for connect sequence. - */ - private void setupMocksForConnectSequence(final boolean haveExistingNetwork) throws Exception { - final int existingNetworkId = SUPPLICANT_NETWORK_ID; - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer() throws RemoteException { - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMock).disconnect(); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public void answer(ISupplicantStaIface.listNetworksCallback cb) throws RemoteException { - if (haveExistingNetwork) { - cb.onValues(mStatusSuccess, new ArrayList<>(Arrays.asList(existingNetworkId))); - } else { - cb.onValues(mStatusSuccess, new ArrayList<>()); - } - } - }).when(mISupplicantStaIfaceMock) - .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer(int id) throws RemoteException { - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMock).removeNetwork(eq(existingNetworkId)); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public void answer(ISupplicantStaIface.addNetworkCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class)); - return; - } - }).when(mISupplicantStaIfaceMock).addNetwork( - any(ISupplicantStaIface.addNetworkCallback.class)); - when(mSupplicantStaNetworkMock.saveWifiConfiguration(any(WifiConfiguration.class))) - .thenReturn(true); - when(mSupplicantStaNetworkMock.select()).thenReturn(true); - } - - /** - * Helper function to validate the connect sequence. - */ - private void validateConnectSequence( - final boolean haveExistingNetwork, int numNetworkAdditions) throws Exception { - if (haveExistingNetwork) { - verify(mISupplicantStaIfaceMock).removeNetwork(anyInt()); - } - verify(mISupplicantStaIfaceMock, times(numNetworkAdditions)) - .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class)); - verify(mSupplicantStaNetworkMock, times(numNetworkAdditions)) - .saveWifiConfiguration(any(WifiConfiguration.class)); - verify(mSupplicantStaNetworkMock, times(numNetworkAdditions)).select(); - } - - /** - * Helper function to execute all the actions to perform connection to the network. - * - * @param newFrameworkNetworkId Framework Network Id of the new network to connect. - * @param haveExistingNetwork Removes the existing network. - * @return the WifiConfiguration object of the new network to connect. - */ - private WifiConfiguration executeAndValidateConnectSequence( - final int newFrameworkNetworkId, final boolean haveExistingNetwork) throws Exception { - return executeAndValidateConnectSequenceWithKeyMgmt(newFrameworkNetworkId, - haveExistingNetwork, WifiConfiguration.KeyMgmt.WPA_PSK, null); - } - - /** - * Helper function to execute all the actions to perform connection to the network. - * - * @param newFrameworkNetworkId Framework Network Id of the new network to connect. - * @param haveExistingNetwork Removes the existing network. - * @param keyMgmt Key management of the new network. - * @param wepKey if configurations are for a WEP network else null. - * @return the WifiConfiguration object of the new network to connect. - */ - private WifiConfiguration executeAndValidateConnectSequenceWithKeyMgmt( - final int newFrameworkNetworkId, final boolean haveExistingNetwork, - int keyMgmt, String wepKey) throws Exception { - setupMocksForConnectSequence(haveExistingNetwork); - WifiConfiguration config = new WifiConfiguration(); - config.networkId = newFrameworkNetworkId; - config.allowedKeyManagement.set(keyMgmt); - config.wepKeys[0] = wepKey; - config.wepTxKeyIndex = 0; - assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config)); - validateConnectSequence(haveExistingNetwork, 1); - return config; - } - - /** - * Setup mocks for roam sequence. - */ - private void setupMocksForRoamSequence(String roamBssid) throws Exception { - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer() throws RemoteException { - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMock).reassociate(); - when(mSupplicantStaNetworkMock.setBssid(eq(roamBssid))).thenReturn(true); - } - - /** - * Helper function to execute all the actions to perform roaming to the network. - * - * @param sameNetwork Roam to the same network or not. - */ - private void executeAndValidateRoamSequence(boolean sameNetwork) throws Exception { - int connectedNetworkId = ROAM_NETWORK_ID; - String roamBssid = BSSID; - int roamNetworkId; - if (sameNetwork) { - roamNetworkId = connectedNetworkId; - } else { - roamNetworkId = connectedNetworkId + 1; - } - executeAndValidateConnectSequence(connectedNetworkId, false); - setupMocksForRoamSequence(roamBssid); - - WifiConfiguration roamingConfig = new WifiConfiguration(); - roamingConfig.networkId = roamNetworkId; - roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID(roamBssid); - assertTrue(mDut.roamToNetwork(WLAN0_IFACE_NAME, roamingConfig)); - - if (!sameNetwork) { - validateConnectSequence(false, 2); - verify(mSupplicantStaNetworkMock, never()).setBssid(anyString()); - verify(mISupplicantStaIfaceMock, never()).reassociate(); - } else { - verify(mSupplicantStaNetworkMock).setBssid(eq(roamBssid)); - verify(mISupplicantStaIfaceMock).reassociate(); - } - } - - /** - * Helper function to set up Hal cascadingly. - */ - private void setupMocksForHalV1_1() throws Exception { - // V1_0 is set up by default, no need to do it. - when(mServiceManagerMock.getTransport(eq(android.hardware.wifi.supplicant.V1_1.ISupplicant - .kInterfaceName), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class); - } - - private void setupMocksForHalV1_2() throws Exception { - setupMocksForHalV1_1(); - when(mServiceManagerMock.getTransport(eq(android.hardware.wifi.supplicant.V1_2.ISupplicant - .kInterfaceName), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mISupplicantMockV1_2 = mock(android.hardware.wifi.supplicant.V1_2.ISupplicant.class); - } - - private void setupMocksForHalV1_3() throws Exception { - setupMocksForHalV1_2(); - when(mServiceManagerMock.getTransport(eq(android.hardware.wifi.supplicant.V1_3.ISupplicant - .kInterfaceName), anyString())) - .thenReturn(IServiceManager.Transport.HWBINDER); - mISupplicantMockV13 = mock(android.hardware.wifi.supplicant.V1_3.ISupplicant.class); - } - - private void setupMocksForPmkCache() throws Exception { - /** Callback registration */ - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public SupplicantStatus answer( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback cb) - throws RemoteException { - mISupplicantStaIfaceCallbackV13 = cb; - return mStatusSuccess; - } - }).when(mISupplicantStaIfaceMockV13) - .registerCallback_1_3( - any(android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback - .class)); - - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public boolean answer(WifiConfiguration config, Map<String, String> networkExtra) - throws Exception { - config.networkId = SUPPLICANT_NETWORK_ID; - return true; - } - }).when(mSupplicantStaNetworkMock) - .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class)); - - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public boolean answer(ArrayList<Byte> serializedData) - throws Exception { - mISupplicantStaIfaceCallbackV13.onPmkCacheAdded( - PMK_CACHE_EXPIRATION_IN_SEC, serializedData); - return true; - } - }).when(mSupplicantStaNetworkMock) - .setPmkCache(any(ArrayList.class)); - } - - private class GetWpaDriverCapabilitiesAnswer extends MockAnswerUtil.AnswerWithArguments { - private int mWpaDriverCapabilities; - - GetWpaDriverCapabilitiesAnswer(int wpaDriverCapabilities) { - mWpaDriverCapabilities = wpaDriverCapabilities; - } - - public void answer(android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getWpaDriverCapabilitiesCallback cb) { - cb.onValues(mStatusSuccess, mWpaDriverCapabilities); - } - } - - /** - * Test To get wpa driver capabilities API on old HAL, should - * return 0 (not supported) - */ - @Test - public void tetGetWpaDriverCapabilitiesOldHal() throws Exception { - setupMocksForHalV1_2(); - - executeAndValidateInitializationSequenceV1_2(); - - assertEquals(0, mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); - } - - /** - * Test Multi Band operation support (MBO). - */ - @Test - public void testGetWpaDriverCapabilitiesMbo() throws Exception { - setupMocksForHalV1_3(); - - executeAndValidateInitializationSequenceV1_3(); - - doAnswer(new GetWpaDriverCapabilitiesAnswer(android.hardware.wifi.supplicant.V1_3 - .WpaDriverCapabilitiesMask.MBO)) - .when(mISupplicantStaIfaceMockV13).getWpaDriverCapabilities(any( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getWpaDriverCapabilitiesCallback.class)); - - assertEquals(WIFI_FEATURE_MBO, mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); - } - - /** - * Test Optimized Connectivity support (OCE). - */ - @Test - public void testGetWpaDriverCapabilitiesOce() throws Exception { - setupMocksForHalV1_3(); - - executeAndValidateInitializationSequenceV1_3(); - - doAnswer(new GetWpaDriverCapabilitiesAnswer(android.hardware.wifi.supplicant.V1_3 - .WpaDriverCapabilitiesMask.MBO - | android.hardware.wifi.supplicant.V1_3 - .WpaDriverCapabilitiesMask.OCE)) - .when(mISupplicantStaIfaceMockV13).getWpaDriverCapabilities(any( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface - .getWpaDriverCapabilitiesCallback.class)); - - assertEquals(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE, - mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); - } - - /** - * Test the handling of BSS transition request callback. - */ - @Test - public void testBssTmHandlingDoneCallback() throws Exception { - setupMocksForHalV1_3(); - executeAndValidateInitializationSequenceV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - mISupplicantStaIfaceCallbackV13.onBssTmHandlingDone(new BssTmData()); - - ArgumentCaptor<BtmFrameData> btmFrameDataCaptor = - ArgumentCaptor.forClass(BtmFrameData.class); - verify(mWifiMonitor).broadcastBssTmHandlingDoneEvent( - eq(WLAN0_IFACE_NAME), btmFrameDataCaptor.capture()); - } - - /** - * Tests the configuring of FILS HLP packet in supplicant. - */ - @Test - public void testAddHlpReq() throws Exception { - byte[] dstAddr = {0x45, 0x23, 0x12, 0x12, 0x12, 0x45}; - byte[] hlpPacket = {0x00, 0x01, 0x02, 0x03, 0x04, 0x12, 0x15, 0x34, 0x55, 0x12, - 0x12, 0x45, 0x23, 0x52, 0x32, 0x16, 0x15, 0x53, 0x62, 0x32, 0x32, 0x10}; - - setupMocksForHalV1_3(); - when(mISupplicantStaIfaceMockV13.filsHlpAddRequest(any(byte[].class), - any(ArrayList.class))).thenReturn(mStatusSuccess); - - // Fail before initialization is performed. - assertFalse(mDut.addHlpReq(WLAN0_IFACE_NAME, dstAddr, hlpPacket)); - verify(mISupplicantStaIfaceMockV13, never()).filsHlpAddRequest(any(byte[].class), - any(ArrayList.class)); - - executeAndValidateInitializationSequenceV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - - ArrayList<Byte> hlpPayload = NativeUtil.byteArrayToArrayList(hlpPacket); - assertTrue(mDut.addHlpReq(WLAN0_IFACE_NAME, dstAddr, hlpPacket)); - verify(mISupplicantStaIfaceMockV13).filsHlpAddRequest(eq(dstAddr), eq(hlpPayload)); - } - - /** - * Tests the flushing of FILS HLP packet from supplicant. - */ - @Test - public void testFlushAllHlp() throws Exception { - - setupMocksForHalV1_3(); - when(mISupplicantStaIfaceMockV13.filsHlpFlushRequest()).thenReturn(mStatusSuccess); - - // Fail before initialization is performed. - assertFalse(mDut.flushAllHlp(WLAN0_IFACE_NAME)); - verify(mISupplicantStaIfaceMockV13, never()).filsHlpFlushRequest(); - - executeAndValidateInitializationSequenceV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - - assertTrue(mDut.flushAllHlp(WLAN0_IFACE_NAME)); - verify(mISupplicantStaIfaceMockV13).filsHlpFlushRequest(); - } - - /** - * Tests the handling of state change V13 notification without - * any configured network. - */ - @Test - public void testonStateChangedV13CallbackWithNoConfiguredNetwork() throws Exception { - setupMocksForHalV1_3(); - executeAndValidateInitializationSequenceV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - - mISupplicantStaIfaceCallbackV13.onStateChanged_1_3( - ISupplicantStaIfaceCallback.State.INACTIVE, - NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID), false); - - // Can't compare WifiSsid instances because they lack an equals. - verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( - eq(WLAN0_IFACE_NAME), eq(WifiConfiguration.INVALID_NETWORK_ID), - any(WifiSsid.class), eq(BSSID), eq(SupplicantState.INACTIVE)); - } - - /** - * Tests the handling of state change V13 notification to - * associated after configuring a network. - */ - @Test - public void testStateChangeV13ToAssociatedCallback() throws Exception { - setupMocksForHalV1_3(); - executeAndValidateInitializationSequenceV1_3(); - int frameworkNetworkId = 6; - executeAndValidateConnectSequence(frameworkNetworkId, false); - assertNotNull(mISupplicantStaIfaceCallbackV13); - - mISupplicantStaIfaceCallbackV13.onStateChanged_1_3( - ISupplicantStaIfaceCallback.State.ASSOCIATED, - NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID), false); - - verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( - eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), - any(WifiSsid.class), eq(BSSID), eq(SupplicantState.ASSOCIATED)); - } - - /** - * Tests the handling of state change V13 notification to - * completed after configuring a network. - */ - @Test - public void testStateChangeV13ToCompletedCallback() throws Exception { - InOrder wifiMonitorInOrder = inOrder(mWifiMonitor); - setupMocksForHalV1_3(); - executeAndValidateInitializationSequenceV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - int frameworkNetworkId = 6; - executeAndValidateConnectSequence(frameworkNetworkId, false); - - mISupplicantStaIfaceCallbackV13.onStateChanged_1_3( - ISupplicantStaIfaceCallback.State.COMPLETED, - NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID), false); - - wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent( - eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(false), eq(BSSID)); - wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( - eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), - any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED)); - } - - /** - * Tests the handling of incorrect network passwords, edge case - * when onStateChanged_1_3() is used. - * - * If the network is removed during 4-way handshake, do not call it a password mismatch. - */ - @Test - public void testNetworkRemovedDuring4wayWhenonStateChangedV13IsUsed() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - setupMocksForHalV1_3(); - executeAndValidateInitializationSequenceV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - - int reasonCode = 3; - - mISupplicantStaIfaceCallbackV13.onStateChanged_1_3( - ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID), false); - mISupplicantStaIfaceCallback.onNetworkRemoved(SUPPLICANT_NETWORK_ID); - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); - verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(), - anyInt()); - } - - /** - * Tests the handling of incorrect network passwords when - * onStateChanged_1_3() is used, edge case. - * - * If the disconnect reason is "IE in 4way differs", do not call it a password mismatch. - */ - @Test - public void testIeDiffersWhenonStateChangedV13IsUsed() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - setupMocksForHalV1_3(); - executeAndValidateInitializationSequenceV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - - int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.IE_IN_4WAY_DIFFERS; - - mISupplicantStaIfaceCallbackV13.onStateChanged_1_3( - ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID), false); - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); - verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(), - anyInt()); - } - - /** - * Tests the handling of state change V13 notification to - * completed (with FILS HLP IE sent) after configuring a - * network. - */ - @Test - public void testStateChangeV13WithFilsHlpIESentToCompletedCallback() throws Exception { - InOrder wifiMonitorInOrder = inOrder(mWifiMonitor); - setupMocksForHalV1_3(); - executeAndValidateInitializationSequenceV1_3(); - assertNotNull(mISupplicantStaIfaceCallbackV13); - int frameworkNetworkId = 6; - executeAndValidateConnectSequence(frameworkNetworkId, false); - - mISupplicantStaIfaceCallbackV13.onStateChanged_1_3( - ISupplicantStaIfaceCallback.State.COMPLETED, - NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID), true); - - wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent( - eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(true), eq(BSSID)); - wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( - eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), - any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED)); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalTest.java deleted file mode 100644 index f7fc9c2db..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalTest.java +++ /dev/null @@ -1,1828 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.content.Context; -import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback.NetworkRequestEapSimGsmAuthParams; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback.NetworkRequestEapSimUmtsAuthParams; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.os.RemoteException; -import android.text.TextUtils; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.NativeUtil; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; - -/** - * Unit tests for SupplicantStaNetworkHal - */ -@SmallTest -public class SupplicantStaNetworkHalTest extends WifiBaseTest { - private static final String IFACE_NAME = "wlan0"; - private static final Map<String, String> NETWORK_EXTRAS_VALUES = new HashMap<>(); - static { - NETWORK_EXTRAS_VALUES.put("key1", "value1"); - NETWORK_EXTRAS_VALUES.put("key2", "value2"); - } - private static final String NETWORK_EXTRAS_SERIALIZED = - "%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D"; - private static final String ANONYMOUS_IDENTITY = "aaa@bbb.cc.ddd"; - - private SupplicantStaNetworkHal mSupplicantNetwork; - private SupplicantStatus mStatusSuccess; - private SupplicantStatus mStatusFailure; - @Mock private ISupplicantStaNetwork mISupplicantStaNetworkMock; - @Mock - private android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork mISupplicantStaNetworkV12; - @Mock - private android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork mISupplicantStaNetworkV13; - @Mock private Context mContext; - @Mock private WifiMonitor mWifiMonitor; - - private SupplicantNetworkVariables mSupplicantVariables; - private MockResources mResources; - private ISupplicantStaNetworkCallback mISupplicantStaNetworkCallback; - - enum SupplicantStaNetworkVersion { - V1_0, - V1_2, - V1_3, - } - - /** - * Spy used to return the V1_2 ISupplicantStaNetwork mock object to simulate the 1.2 HAL running - * on the device. - */ - private class SupplicantStaNetworkHalSpyV1_2 extends SupplicantStaNetworkHal { - SupplicantStaNetworkHalSpyV1_2(ISupplicantStaNetwork iSupplicantStaNetwork, - String ifaceName, - Context context, WifiMonitor monitor) { - super(iSupplicantStaNetwork, ifaceName, context, monitor); - } - - @Override - protected android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - getSupplicantStaNetworkForV1_2Mockable() { - return mISupplicantStaNetworkV12; - } - } - - /** - * Spy used to return the V1_3 ISupplicantStaNetwork mock object to simulate the 1.3 HAL running - * on the device. - */ - private class SupplicantStaNetworkHalSpyV1_3 extends SupplicantStaNetworkHalSpyV1_2 { - SupplicantStaNetworkHalSpyV1_3(ISupplicantStaNetwork iSupplicantStaNetwork, - String ifaceName, - Context context, WifiMonitor monitor) { - super(iSupplicantStaNetwork, ifaceName, context, monitor); - } - - @Override - protected android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - getSupplicantStaNetworkForV1_3Mockable() { - return mISupplicantStaNetworkV13; - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mStatusSuccess = createSupplicantStatus(SupplicantStatusCode.SUCCESS); - mStatusFailure = createSupplicantStatus(SupplicantStatusCode.FAILURE_UNKNOWN); - mSupplicantVariables = new SupplicantNetworkVariables(); - setupISupplicantNetworkMock(); - - mResources = new MockResources(); - when(mContext.getResources()).thenReturn(mResources); - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_0); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testOweNetworkWifiConfigurationSaveLoad() throws Exception { - // Now expose the V1.2 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); - - WifiConfiguration config = WifiConfigurationTestUtil.createOweNetwork(); - config.updateIdentifier = "46"; - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testOpenNetworkWifiConfigurationSaveLoad() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - config.updateIdentifier = "45"; - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving/loading of WifiConfiguration to wpa_supplicant with SAE password. - */ - @Test - public void testSaePasswordNetworkWifiConfigurationSaveLoad() throws Exception { - // Now expose the V1.2 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); - - WifiConfiguration config = WifiConfigurationTestUtil.createSaeNetwork(); - testWifiConfigurationSaveLoad(config); - verify(mISupplicantStaNetworkV12).setSaePassword(any(String.class)); - verify(mISupplicantStaNetworkV12, never()) - .getSaePassword(any(android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .getSaePasswordCallback.class)); - verify(mISupplicantStaNetworkV12, never()) - .getPskPassphrase(any(ISupplicantStaNetwork.getPskPassphraseCallback.class)); - verify(mISupplicantStaNetworkV12, never()).setPsk(any(byte[].class)); - verify(mISupplicantStaNetworkV12, never()) - .getPsk(any(ISupplicantStaNetwork.getPskCallback.class)); - } - - /** - * Tests the saving/loading of WifiConfiguration to wpa_supplicant with psk passphrase. - */ - @Test - public void testPskPassphraseNetworkWifiConfigurationSaveLoad() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - config.requirePmf = true; - - // Set the new defaults - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - config.allowedGroupManagementCiphers - .set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); - testWifiConfigurationSaveLoad(config); - verify(mISupplicantStaNetworkMock).setPskPassphrase(anyString()); - verify(mISupplicantStaNetworkMock) - .getPskPassphrase(any(ISupplicantStaNetwork.getPskPassphraseCallback.class)); - verify(mISupplicantStaNetworkMock, never()).setPsk(any(byte[].class)); - verify(mISupplicantStaNetworkMock, never()) - .getPsk(any(ISupplicantStaNetwork.getPskCallback.class)); - verify(mISupplicantStaNetworkMock) - .setPairwiseCipher(ISupplicantStaNetwork.PairwiseCipherMask.CCMP); - verify(mISupplicantStaNetworkMock) - .setGroupCipher(ISupplicantStaNetwork.GroupCipherMask.CCMP); - } - - /** - * Tests the saving/loading of WifiConfiguration to wpa_supplicant with raw psk. - */ - @Test - public void testPskNetworkWifiConfigurationSaveLoad() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - config.preSharedKey = "945ef00c463c2a7c2496376b13263d1531366b46377179a4b17b393687450779"; - testWifiConfigurationSaveLoad(config); - verify(mISupplicantStaNetworkMock).setPsk(any(byte[].class)); - verify(mISupplicantStaNetworkMock) - .getPsk(any(ISupplicantStaNetwork.getPskCallback.class)); - verify(mISupplicantStaNetworkMock, never()).setPskPassphrase(anyString()); - verify(mISupplicantStaNetworkMock) - .getPskPassphrase(any(ISupplicantStaNetwork.getPskPassphraseCallback.class)); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant removes enclosing quotes of psk - * passphrase - */ - @Test - public void testPskNetworkWifiConfigurationSaveRemovesPskQuotes() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - config.preSharedKey = "\"quoted_psd\""; - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - assertEquals(mSupplicantVariables.pskPassphrase, - NativeUtil.removeEnclosingQuotes(config.preSharedKey)); - } - - /** - * Tests the saving/loading of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testWepNetworkWifiConfigurationSaveLoad() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createWepHiddenNetwork(); - config.BSSID = " *NOT USED* "; // we want the other bssid! - config.getNetworkSelectionStatus().setNetworkSelectionBSSID("34:45:19:09:45:66"); - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testEapPeapGtcNetworkWifiConfigurationSaveLoad() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createPEAPWifiEnterpriseConfigWithGTCPhase2(); - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testEapTlsNoneNetworkWifiConfigurationSaveLoad() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2(); - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testEapTlsNoneClientCertNetworkWifiConfigurationSaveLoad() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2(); - config.enterpriseConfig.setClientCertificateAlias("test_alias"); - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testEapTlsNoneClientCertNetworkWithOcspWifiConfigurationSaveLoad() - throws Exception { - // Now expose the V1.3 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_3); - - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2(); - config.enterpriseConfig.setClientCertificateAlias("test_alias"); - config.enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testEapTlsAkaNetworkWifiConfigurationSaveLoad() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithAkaPhase2(); - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving/loading of WifiConfiguration to wpa_supplicant with Suite-B-192 - */ - @Test - public void testEapSuiteBRsaNetworkWifiConfigurationSaveLoad() throws Exception { - // Now expose the V1.2 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); - - WifiConfiguration config = WifiConfigurationTestUtil.createEapSuiteBNetwork(); - config.allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_RSA); - - testWifiConfigurationSaveLoad(config); - verify(mISupplicantStaNetworkV12, never()).enableSuiteBEapOpenSslCiphers(); - verify(mISupplicantStaNetworkV12).enableTlsSuiteBEapPhase1Param(anyBoolean()); - - verify(mISupplicantStaNetworkV12, never()).setSaePassword(any(String.class)); - verify(mISupplicantStaNetworkV12, never()) - .getSaePassword(any(android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .getSaePasswordCallback.class)); - verify(mISupplicantStaNetworkV12, never()) - .getPskPassphrase(any(ISupplicantStaNetwork.getPskPassphraseCallback.class)); - verify(mISupplicantStaNetworkV12, never()).setPsk(any(byte[].class)); - verify(mISupplicantStaNetworkV12, never()) - .getPsk(any(ISupplicantStaNetwork.getPskCallback.class)); - } - - /** - * Tests the saving/loading of WifiConfiguration to wpa_supplicant with Suite-B-192 - */ - @Test - public void testEapSuiteBEcdsaNetworkWifiConfigurationSaveLoad() throws Exception { - // Now expose the V1.2 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); - - WifiConfiguration config = WifiConfigurationTestUtil.createEapSuiteBNetwork(); - config.allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA); - - testWifiConfigurationSaveLoad(config); - verify(mISupplicantStaNetworkV12).enableSuiteBEapOpenSslCiphers(); - verify(mISupplicantStaNetworkV12, never()) - .enableTlsSuiteBEapPhase1Param(any(boolean.class)); - - verify(mISupplicantStaNetworkV12, never()).setSaePassword(any(String.class)); - verify(mISupplicantStaNetworkV12, never()) - .getSaePassword(any(android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .getSaePasswordCallback.class)); - verify(mISupplicantStaNetworkV12, never()) - .getPskPassphrase(any(ISupplicantStaNetwork.getPskPassphraseCallback.class)); - verify(mISupplicantStaNetworkV12, never()).setPsk(any(byte[].class)); - verify(mISupplicantStaNetworkV12, never()) - .getPsk(any(ISupplicantStaNetwork.getPskCallback.class)); - } - - /** - * Tests the saving/loading of WifiConfiguration with FILS AKM - * to wpa_supplicant. - */ - @Test - public void testTLSWifiEnterpriseConfigWithFilsEapErp() throws Exception { - // Now expose the V1.3 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_3); - - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2(); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FILS_SHA256); - config.enterpriseConfig.setFieldValue(WifiEnterpriseConfig.EAP_ERP, "1"); - testWifiConfigurationSaveLoad(config); - // Check the supplicant variables to ensure that we have added the FILS AKM. - assertTrue((mSupplicantVariables.keyMgmtMask & android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.KeyMgmtMask.FILS_SHA256) - == android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.KeyMgmtMask.FILS_SHA256); - verify(mISupplicantStaNetworkV13).setEapErp(eq(true)); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testWapiPskNetworkWifiConfigurationSaveLoad() throws Exception { - // Now expose the V1.3 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_3); - - WifiConfiguration config = WifiConfigurationTestUtil.createWapiPskNetwork(); - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testWapiPskHexNetworkWifiConfigurationSaveLoad() throws Exception { - // Now expose the V1.3 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_3); - - WifiConfiguration config = WifiConfigurationTestUtil.createWapiPskNetwork(); - - config.preSharedKey = - "1234567890abcdef0" - + "1234567890abcdef0"; - // WAPI should accept a hex bytes whose length is not exact 32. - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the saving of WifiConfiguration to wpa_supplicant. - */ - @Test - public void testWapiCertNetworkWifiConfigurationSaveLoad() throws Exception { - // Now expose the V1.3 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_3); - - WifiConfiguration config = WifiConfigurationTestUtil.createWapiCertNetwork(); - testWifiConfigurationSaveLoad(config); - } - - /** - * Tests the failure to save ssid. - */ - @Test - public void testSsidSaveFailure() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createWepHiddenNetwork(); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> ssid) throws RemoteException { - return mStatusFailure; - } - }).when(mISupplicantStaNetworkMock).setSsid(any(ArrayList.class)); - - assertFalse(mSupplicantNetwork.saveWifiConfiguration(config)); - } - - /** - * Tests the failure to save invalid key mgmt (unknown bit set in the - * {@link WifiConfiguration#allowedKeyManagement} being saved). - */ - @Test - public void testInvalidKeyMgmtSaveFailure() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createWepHiddenNetwork(); - config.allowedKeyManagement.set(20); - try { - assertFalse(mSupplicantNetwork.saveWifiConfiguration(config)); - } catch (IllegalArgumentException e) { - return; - } - assertTrue(false); - } - - /** - * Tests the failure to save invalid bssid (less than 6 bytes in the - * {@link WifiConfiguration#BSSID} being saved). - */ - @Test - public void testInvalidBssidSaveFailure() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createWepHiddenNetwork(); - config.getNetworkSelectionStatus().setNetworkSelectionBSSID("45:34:23:12"); - try { - assertFalse(mSupplicantNetwork.saveWifiConfiguration(config)); - } catch (IllegalArgumentException e) { - return; - } - assertTrue(false); - } - - /** - * Tests the parsing of GSM auth response parameters. - */ - @Test - public void testSendNetworkEapSimGsmAuthResponseWith2KcSresPair() throws Exception { - final byte[] kc = new byte[]{0x45, 0x45, 0x32, 0x34, 0x45, 0x10, 0x34, 0x12}; - final byte[] sres = new byte[]{0x12, 0x10, 0x32, 0x23}; - // Send 2 kc/sres pair for this request. - String paramsStr = ":" + NativeUtil.hexStringFromByteArray(kc) - + ":" + NativeUtil.hexStringFromByteArray(sres) - + ":" + NativeUtil.hexStringFromByteArray(kc) - + ":" + NativeUtil.hexStringFromByteArray(sres); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer( - ArrayList<ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams> params) - throws RemoteException { - assertEquals(2, params.size()); - assertArrayEquals(kc, params.get(0).kc); - assertArrayEquals(sres, params.get(0).sres); - assertArrayEquals(kc, params.get(1).kc); - assertArrayEquals(sres, params.get(1).sres); - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapSimGsmAuthResponse(any(ArrayList.class)); - - assertTrue(mSupplicantNetwork.sendNetworkEapSimGsmAuthResponse(paramsStr)); - } - - /** - * Tests the parsing of GSM auth response parameters. - */ - @Test - public void testSendNetworkEapSimGsmAuthResponseWith3KcSresPair() throws Exception { - final byte[] kc1 = new byte[]{0x45, 0x45, 0x32, 0x34, 0x45, 0x10, 0x34, 0x12}; - final byte[] sres1 = new byte[]{0x12, 0x10, 0x32, 0x23}; - final byte[] kc2 = new byte[]{0x45, 0x34, 0x12, 0x34, 0x45, 0x10, 0x34, 0x12}; - final byte[] sres2 = new byte[]{0x12, 0x23, 0x12, 0x23}; - final byte[] kc3 = new byte[]{0x25, 0x34, 0x12, 0x14, 0x45, 0x10, 0x34, 0x12}; - final byte[] sres3 = new byte[]{0x42, 0x23, 0x22, 0x23}; - // Send 3 kc/sres pair for this request. - String paramsStr = ":" + NativeUtil.hexStringFromByteArray(kc1) - + ":" + NativeUtil.hexStringFromByteArray(sres1) - + ":" + NativeUtil.hexStringFromByteArray(kc2) - + ":" + NativeUtil.hexStringFromByteArray(sres2) - + ":" + NativeUtil.hexStringFromByteArray(kc3) - + ":" + NativeUtil.hexStringFromByteArray(sres3); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer( - ArrayList<ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams> params) - throws RemoteException { - assertEquals(3, params.size()); - assertArrayEquals(kc1, params.get(0).kc); - assertArrayEquals(sres1, params.get(0).sres); - assertArrayEquals(kc2, params.get(1).kc); - assertArrayEquals(sres2, params.get(1).sres); - assertArrayEquals(kc3, params.get(2).kc); - assertArrayEquals(sres3, params.get(2).sres); - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapSimGsmAuthResponse(any(ArrayList.class)); - - assertTrue(mSupplicantNetwork.sendNetworkEapSimGsmAuthResponse(paramsStr)); - } - - /** - * Tests the parsing of invalid GSM auth response parameters (invalid kc & sres lengths). - */ - @Test - public void testSendInvalidKcSresLenNetworkEapSimGsmAuthResponse() throws Exception { - final byte[] kc1 = new byte[]{0x45, 0x45, 0x32, 0x34, 0x45, 0x10, 0x34}; - final byte[] sres1 = new byte[]{0x12, 0x10, 0x23}; - final byte[] kc2 = new byte[]{0x45, 0x34, 0x12, 0x34, 0x45, 0x10, 0x34, 0x12}; - final byte[] sres2 = new byte[]{0x12, 0x23, 0x12, 0x23}; - // Send 2 kc/sres pair for this request. - String paramsStr = ":" + NativeUtil.hexStringFromByteArray(kc1) - + ":" + NativeUtil.hexStringFromByteArray(sres1) - + ":" + NativeUtil.hexStringFromByteArray(kc2) - + ":" + NativeUtil.hexStringFromByteArray(sres2); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer( - ArrayList<ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams> params) - throws RemoteException { - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapSimGsmAuthResponse(any(ArrayList.class)); - - assertFalse(mSupplicantNetwork.sendNetworkEapSimGsmAuthResponse(paramsStr)); - } - - /** - * Tests the parsing of invalid GSM auth response parameters (invalid number of kc/sres pairs). - */ - @Test - public void testSendInvalidKcSresPairNumNetworkEapSimGsmAuthResponse() throws Exception { - final byte[] kc = new byte[]{0x45, 0x34, 0x12, 0x34, 0x45, 0x10, 0x34, 0x12}; - final byte[] sres = new byte[]{0x12, 0x23, 0x12, 0x23}; - // Send 1 kc/sres pair for this request. - String paramsStr = ":" + NativeUtil.hexStringFromByteArray(kc) - + ":" + NativeUtil.hexStringFromByteArray(sres); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer( - ArrayList<ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams> params) - throws RemoteException { - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapSimGsmAuthResponse(any(ArrayList.class)); - - assertFalse(mSupplicantNetwork.sendNetworkEapSimGsmAuthResponse(paramsStr)); - } - - /** - * Tests the parsing of UMTS auth response parameters. - */ - @Test - public void testSendNetworkEapSimUmtsAuthResponse() throws Exception { - final byte[] ik = new byte[]{0x45, 0x45, 0x32, 0x34, 0x45, 0x10, 0x34, 0x12, 0x23, 0x34, - 0x33, 0x23, 0x34, 0x10, 0x40, 0x34}; - final byte[] ck = new byte[]{0x12, 0x10, 0x32, 0x23, 0x45, 0x10, 0x34, 0x12, 0x23, 0x34, - 0x33, 0x23, 0x34, 0x10, 0x40, 0x34}; - final byte[] res = new byte[]{0x12, 0x10, 0x32, 0x23, 0x45, 0x10, 0x34, 0x12, 0x23, 0x34}; - String paramsStr = ":" + NativeUtil.hexStringFromByteArray(ik) - + ":" + NativeUtil.hexStringFromByteArray(ck) - + ":" + NativeUtil.hexStringFromByteArray(res); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer( - ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams params) - throws RemoteException { - assertArrayEquals(ik, params.ik); - assertArrayEquals(ck, params.ck); - // Convert to arraylist before comparison. - ArrayList<Byte> resList = new ArrayList<>(); - for (byte b : res) { - resList.add(b); - } - assertEquals(resList, params.res); - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapSimUmtsAuthResponse( - any(ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams.class)); - - assertTrue(mSupplicantNetwork.sendNetworkEapSimUmtsAuthResponse(paramsStr)); - } - - /** - * Tests the parsing of invalid UMTS auth response parameters (invalid ik, ck lengths). - */ - @Test - public void testSendInvalidNetworkEapSimUmtsAuthResponse() throws Exception { - final byte[] ik = new byte[]{0x45, 0x45, 0x32, 0x34, 0x45, 0x10, 0x34, 0x12}; - final byte[] ck = new byte[]{0x12, 0x10, 0x32, 0x23, 0x45, 0x10, 0x34, 0x12, 0x23, 0x34, - 0x33, 0x23, 0x34, 0x10, 0x40}; - final byte[] res = new byte[]{0x12, 0x10, 0x32, 0x23, 0x45, 0x10, 0x34, 0x12, 0x23, 0x34}; - String paramsStr = ":" + NativeUtil.hexStringFromByteArray(ik) - + ":" + NativeUtil.hexStringFromByteArray(ck) - + ":" + NativeUtil.hexStringFromByteArray(res); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer( - ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams params) - throws RemoteException { - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapSimUmtsAuthResponse( - any(ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams.class)); - - assertFalse(mSupplicantNetwork.sendNetworkEapSimUmtsAuthResponse(paramsStr)); - } - - /** - * Tests the parsing of UMTS auts response parameters. - */ - @Test - public void testSendNetworkEapSimUmtsAutsResponse() throws Exception { - final byte[] auts = new byte[]{0x45, 0x45, 0x32, 0x34, 0x45, 0x10, 0x34, 0x12, 0x23, 0x34, - 0x33, 0x23, 0x34, 0x10}; - String paramsStr = ":" + NativeUtil.hexStringFromByteArray(auts); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(byte[] params) - throws RemoteException { - assertArrayEquals(auts, params); - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapSimUmtsAutsResponse(any(byte[].class)); - - assertTrue(mSupplicantNetwork.sendNetworkEapSimUmtsAutsResponse(paramsStr)); - } - - /** - * Tests the parsing of invalid UMTS auts response parameters (invalid auts length). - */ - @Test - public void testSendInvalidNetworkEapSimUmtsAutsResponse() throws Exception { - final byte[] auts = new byte[]{0x45, 0x45, 0x32, 0x34, 0x45, 0x10, 0x34, 0x12, 0x23}; - String paramsStr = ":" + NativeUtil.hexStringFromByteArray(auts); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(byte[] params) - throws RemoteException { - assertArrayEquals(auts, params); - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapSimUmtsAutsResponse(any(byte[].class)); - - assertFalse(mSupplicantNetwork.sendNetworkEapSimUmtsAutsResponse(paramsStr)); - } - - /** - * Tests the parsing of identity string. - */ - @Test - public void testSendNetworkEapIdentityResponse() throws Exception { - final String identityStr = "test@test.com"; - final String encryptedIdentityStr = "test2@test.com"; - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> identity) - throws RemoteException { - assertEquals(identityStr, NativeUtil.stringFromByteArrayList(identity)); - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).sendNetworkEapIdentityResponse(any(ArrayList.class)); - - assertTrue(mSupplicantNetwork.sendNetworkEapIdentityResponse(identityStr, - encryptedIdentityStr)); - verify(mISupplicantStaNetworkV12, never()).sendNetworkEapIdentityResponse_1_1( - any(ArrayList.class), any(ArrayList.class)); - - // Now expose the V1.2 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> identity, - ArrayList<Byte> encryptedIdentity) - throws RemoteException { - assertEquals(identityStr, NativeUtil.stringFromByteArrayList(identity)); - assertEquals(encryptedIdentityStr, - NativeUtil.stringFromByteArrayList(encryptedIdentity)); - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV12).sendNetworkEapIdentityResponse_1_1(any(ArrayList.class), - any(ArrayList.class)); - assertTrue(mSupplicantNetwork.sendNetworkEapIdentityResponse(identityStr, - encryptedIdentityStr)); - } - - /** - * Tests the addition of FT flags when the device supports it. - */ - @Test - public void testAddFtPskFlags() throws Exception { - mResources.setBoolean(R.bool.config_wifi_fast_bss_transition_enabled, true); - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_0); - - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - // Check the supplicant variables to ensure that we have added the FT flags. - assertTrue((mSupplicantVariables.keyMgmtMask & ISupplicantStaNetwork.KeyMgmtMask.FT_PSK) - == ISupplicantStaNetwork.KeyMgmtMask.FT_PSK); - - WifiConfiguration loadConfig = new WifiConfiguration(); - Map<String, String> networkExtras = new HashMap<>(); - assertTrue(mSupplicantNetwork.loadWifiConfiguration(loadConfig, networkExtras)); - // The FT flags should be stripped out when reading it back. - WifiConfigurationTestUtil.assertConfigurationEqualForSupplicant(config, loadConfig); - } - - /** - * Tests the addition of FT flags when the device supports it. - */ - @Test - public void testAddFtEapFlags() throws Exception { - mResources.setBoolean(R.bool.config_wifi_fast_bss_transition_enabled, true); - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_0); - - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - // Check the supplicant variables to ensure that we have added the FT flags. - assertTrue((mSupplicantVariables.keyMgmtMask & ISupplicantStaNetwork.KeyMgmtMask.FT_EAP) - == ISupplicantStaNetwork.KeyMgmtMask.FT_EAP); - - WifiConfiguration loadConfig = new WifiConfiguration(); - Map<String, String> networkExtras = new HashMap<>(); - assertTrue(mSupplicantNetwork.loadWifiConfiguration(loadConfig, networkExtras)); - // The FT flags should be stripped out when reading it back. - WifiConfigurationTestUtil.assertConfigurationEqualForSupplicant(config, loadConfig); - } - - /** - * Tests the addition of SHA256 flags (WPA_PSK_SHA256) - */ - @Test - public void testAddPskSha256Flags() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - // Now expose the V1.2 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - // Check the supplicant variables to ensure that we have added the SHA256 flags. - assertTrue((mSupplicantVariables.keyMgmtMask - & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .WPA_PSK_SHA256) == android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .KeyMgmtMask.WPA_PSK_SHA256); - - WifiConfiguration loadConfig = new WifiConfiguration(); - Map<String, String> networkExtras = new HashMap<>(); - assertTrue(mSupplicantNetwork.loadWifiConfiguration(loadConfig, networkExtras)); - // The SHA256 flags should be stripped out when reading it back. - WifiConfigurationTestUtil.assertConfigurationEqualForSupplicant(config, loadConfig); - } - - /** - * Tests the addition of SHA256 flags (WPA_EAP_SHA256) - */ - @Test - public void testAddEapSha256Flags() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - // Now expose the V1.2 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - // Check the supplicant variables to ensure that we have added the SHA256 flags. - assertTrue((mSupplicantVariables.keyMgmtMask - & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .WPA_EAP_SHA256) == android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .KeyMgmtMask.WPA_EAP_SHA256); - - WifiConfiguration loadConfig = new WifiConfiguration(); - Map<String, String> networkExtras = new HashMap<>(); - assertTrue(mSupplicantNetwork.loadWifiConfiguration(loadConfig, networkExtras)); - // The SHA256 flags should be stripped out when reading it back. - WifiConfigurationTestUtil.assertConfigurationEqualForSupplicant(config, loadConfig); - } - - /** - * Tests the addition of SHA256 flags (WPA_PSK_SHA256) is ignored on HAL v1.1 or lower - */ - @Test - public void testAddPskSha256FlagsHal1_1OrLower() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - // Check the supplicant variables to ensure that we have NOT added the SHA256 flags. - assertFalse((mSupplicantVariables.keyMgmtMask - & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .WPA_PSK_SHA256) == android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .KeyMgmtMask.WPA_PSK_SHA256); - } - - /** - * Tests the addition of SHA256 flags (WPA_EAP_SHA256) is ignored on HAL v1.1 or lower - */ - @Test - public void testAddEapSha256FlagsHal1_1OrLower() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - // Check the supplicant variables to ensure that we have NOT added the SHA256 flags. - assertFalse((mSupplicantVariables.keyMgmtMask - & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork.KeyMgmtMask - .WPA_EAP_SHA256) == android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .KeyMgmtMask.WPA_EAP_SHA256); - } - - /** - * Tests OCSP status is ignored on HAL v1.2 or lower - */ - @Test - public void testOcspStatusHal1_2OrLower() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2(); - config.enterpriseConfig.setClientCertificateAlias("test_alias"); - config.enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); - - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - // Check the supplicant variables to ensure that we have NOT change the OCSP status. - assertEquals(WifiEnterpriseConfig.OCSP_NONE, mSupplicantVariables.ocsp); - } - - /** - * Tests the retrieval of WPS NFC token. - */ - @Test - public void testGetWpsNfcConfigurationToken() throws Exception { - final ArrayList<Byte> token = new ArrayList<>(); - token.add(Byte.valueOf((byte) 0x45)); - token.add(Byte.valueOf((byte) 0x34)); - - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getWpsNfcConfigurationTokenCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, token); - } - }).when(mISupplicantStaNetworkMock) - .getWpsNfcConfigurationToken( - any(ISupplicantStaNetwork.getWpsNfcConfigurationTokenCallback.class)); - - assertEquals("4534", mSupplicantNetwork.getWpsNfcConfigurationToken()); - } - - /** - * Tests that callback registration failure triggers a failure in saving network config. - */ - @Test - public void testSaveFailureDueToCallbackReg() throws Exception { - when(mISupplicantStaNetworkMock.registerCallback(any(ISupplicantStaNetworkCallback.class))) - .thenReturn(mStatusFailure); - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertFalse(mSupplicantNetwork.saveWifiConfiguration(config)); - } - - /** - * Tests the network gsm auth callback. - */ - @Test - public void testNetworkEapGsmAuthCallback() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - assertNotNull(mISupplicantStaNetworkCallback); - - // Now trigger eap gsm callback and ensure that the event is broadcast via WifiMonitor. - NetworkRequestEapSimGsmAuthParams params = new NetworkRequestEapSimGsmAuthParams(); - Random random = new Random(); - byte[] rand1 = new byte[16]; - byte[] rand2 = new byte[16]; - byte[] rand3 = new byte[16]; - random.nextBytes(rand1); - random.nextBytes(rand2); - random.nextBytes(rand3); - params.rands.add(rand1); - params.rands.add(rand2); - params.rands.add(rand3); - - String[] expectedRands = { - NativeUtil.hexStringFromByteArray(rand1), NativeUtil.hexStringFromByteArray(rand2), - NativeUtil.hexStringFromByteArray(rand3) - }; - - mISupplicantStaNetworkCallback.onNetworkEapSimGsmAuthRequest(params); - verify(mWifiMonitor).broadcastNetworkGsmAuthRequestEvent( - eq(IFACE_NAME), eq(config.networkId), eq(config.SSID), eq(expectedRands)); - } - - /** - * Tests the network umts auth callback. - */ - @Test - public void testNetworkEapUmtsAuthCallback() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - assertNotNull(mISupplicantStaNetworkCallback); - - // Now trigger eap gsm callback and ensure that the event is broadcast via WifiMonitor. - NetworkRequestEapSimUmtsAuthParams params = new NetworkRequestEapSimUmtsAuthParams(); - Random random = new Random(); - random.nextBytes(params.autn); - random.nextBytes(params.rand); - - String[] expectedRands = { - NativeUtil.hexStringFromByteArray(params.rand), - NativeUtil.hexStringFromByteArray(params.autn) - }; - - mISupplicantStaNetworkCallback.onNetworkEapSimUmtsAuthRequest(params); - verify(mWifiMonitor).broadcastNetworkUmtsAuthRequestEvent( - eq(IFACE_NAME), eq(config.networkId), eq(config.SSID), eq(expectedRands)); - } - - /** - * Tests the network identity callback. - */ - @Test - public void testNetworkIdentityCallback() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - assertNotNull(mISupplicantStaNetworkCallback); - - // Now trigger identity request callback and ensure that the event is broadcast via - // WifiMonitor. - mISupplicantStaNetworkCallback.onNetworkEapIdentityRequest(); - verify(mWifiMonitor).broadcastNetworkIdentityRequestEvent( - eq(IFACE_NAME), eq(config.networkId), eq(config.SSID)); - } - - private void testWifiConfigurationSaveLoad(WifiConfiguration config) { - if (mSupplicantNetwork.getSupplicantStaNetworkForV1_2Mockable() == null) { - // Clear unsupported settings in HAL v1.0 - config.allowedPairwiseCiphers.clear(WifiConfiguration.PairwiseCipher.GCMP_256); - config.allowedGroupCiphers.clear(WifiConfiguration.GroupCipher.GCMP_256); - } - // Save the configuration using the default supplicant network HAL v1.0 - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - WifiConfiguration loadConfig = new WifiConfiguration(); - Map<String, String> networkExtras = new HashMap<>(); - assertTrue(mSupplicantNetwork.loadWifiConfiguration(loadConfig, networkExtras)); - WifiConfigurationTestUtil.assertConfigurationEqualForSupplicant(config, loadConfig); - assertEquals(config.getKey(), - networkExtras.get(SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY)); - assertEquals( - config.creatorUid, - Integer.parseInt(networkExtras.get( - SupplicantStaNetworkHal.ID_STRING_KEY_CREATOR_UID))); - // There is no getter for this one, so check the supplicant variable. - if (!TextUtils.isEmpty(config.updateIdentifier)) { - assertEquals(Integer.parseInt(config.updateIdentifier), - mSupplicantVariables.updateIdentifier); - } - // There is no getter for this one, so check the supplicant variable. - String oppKeyCaching = - config.enterpriseConfig.getFieldValue(WifiEnterpriseConfig.OPP_KEY_CACHING); - if (!TextUtils.isEmpty(oppKeyCaching)) { - assertEquals( - Integer.parseInt(oppKeyCaching) == 1 ? true : false, - mSupplicantVariables.eapProactiveKeyCaching); - } - // There is no getter for this one, so check the supplicant variable. - String eapErp = - config.enterpriseConfig.getFieldValue(WifiEnterpriseConfig.EAP_ERP); - if (!TextUtils.isEmpty(eapErp)) { - assertEquals( - Integer.parseInt(eapErp) == 1 ? true : false, - mSupplicantVariables.eapErp); - } - } - - /** - * Verifies that createNetworkExtra() & parseNetworkExtra correctly writes a serialized and - * URL-encoded JSON object. - */ - @Test - public void testNetworkExtra() { - assertEquals(NETWORK_EXTRAS_SERIALIZED, - SupplicantStaNetworkHal.createNetworkExtra(NETWORK_EXTRAS_VALUES)); - assertEquals(NETWORK_EXTRAS_VALUES, - SupplicantStaNetworkHal.parseNetworkExtra(NETWORK_EXTRAS_SERIALIZED)); - } - - /** - * Verifies that fetachEapAnonymousIdentity() can get the anonymous identity from supplicant. - */ - @Test - public void testFetchEapAnonymousIdentity() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig.setAnonymousIdentity(ANONYMOUS_IDENTITY); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - assertEquals(ANONYMOUS_IDENTITY, mSupplicantNetwork.fetchEapAnonymousIdentity()); - } - - /** Verifies that setPmkCache can set PMK cache - * - */ - @Test - public void testSetPmkCache() { - // Now expose the V1.3 ISupplicantStaNetwork - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_3); - - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - ArrayList<Byte> serializedData = new ArrayList<>(); - assertTrue(mSupplicantNetwork.setPmkCache(serializedData)); - assertEquals(serializedData, mSupplicantVariables.serializedPmkCache); - } - - /** - * Tests PMK cache is not set on HAL v1.2 or lower - */ - @Test - public void testSetPmkCacheHal1_2OrLower() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2(); - assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); - - ArrayList<Byte> serializedData = new ArrayList<>(); - assertFalse(mSupplicantNetwork.setPmkCache(serializedData)); - assertNull(mSupplicantVariables.serializedPmkCache); - } - - /** - * Tests the saving/loading of WifiConfiguration to wpa_supplicant with psk passphrase for - * HAL v1.2 or higher - */ - @Test - public void testPskPassphraseNetworkWifiConfigurationSaveLoad1_2OrHigher() throws Exception { - createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - config.requirePmf = true; - - // Set the new defaults - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - testWifiConfigurationSaveLoad(config); - verify(mISupplicantStaNetworkMock).setPskPassphrase(anyString()); - verify(mISupplicantStaNetworkMock) - .getPskPassphrase(any(ISupplicantStaNetwork.getPskPassphraseCallback.class)); - verify(mISupplicantStaNetworkMock, never()).setPsk(any(byte[].class)); - verify(mISupplicantStaNetworkMock, never()) - .getPsk(any(ISupplicantStaNetwork.getPskCallback.class)); - verify(mISupplicantStaNetworkV12) - .setPairwiseCipher_1_2(ISupplicantStaNetwork.PairwiseCipherMask.CCMP - | android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .PairwiseCipherMask.GCMP_256); - verify(mISupplicantStaNetworkV12) - .setGroupCipher_1_2(ISupplicantStaNetwork.GroupCipherMask.CCMP - | android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .GroupCipherMask.GCMP_256); - } - - /** - * Sets up the HIDL interface mock with all the setters/getter values. - * Note: This only sets up the mock to return success on all methods. - */ - private void setupISupplicantNetworkMock() throws Exception { - /** SSID */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> ssid) throws RemoteException { - mSupplicantVariables.ssid = ssid; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setSsid(any(ArrayList.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getSsidCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.ssid); - } - }).when(mISupplicantStaNetworkMock) - .getSsid(any(ISupplicantStaNetwork.getSsidCallback.class)); - - /** Network Id */ - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantNetwork.getIdCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.networkId); - } - }).when(mISupplicantStaNetworkMock).getId(any(ISupplicantNetwork.getIdCallback.class)); - - /** BSSID */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(byte[] bssid) throws RemoteException { - mSupplicantVariables.bssid = bssid; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setBssid(any(byte[].class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getBssidCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.bssid); - } - }).when(mISupplicantStaNetworkMock) - .getBssid(any(ISupplicantStaNetwork.getBssidCallback.class)); - - /** Scan SSID (Is Hidden Network?) */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(boolean enable) throws RemoteException { - mSupplicantVariables.scanSsid = enable; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setScanSsid(any(boolean.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getScanSsidCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.scanSsid); - } - }).when(mISupplicantStaNetworkMock) - .getScanSsid(any(ISupplicantStaNetwork.getScanSsidCallback.class)); - - /** Require PMF*/ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(boolean enable) throws RemoteException { - mSupplicantVariables.requirePmf = enable; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setRequirePmf(any(boolean.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getRequirePmfCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.requirePmf); - } - }).when(mISupplicantStaNetworkMock) - .getRequirePmf(any(ISupplicantStaNetwork.getRequirePmfCallback.class)); - - /** SAE password */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String saePassword) throws RemoteException { - mSupplicantVariables.pskPassphrase = saePassword; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV12).setSaePassword(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getPskPassphraseCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.pskPassphrase); - } - }).when(mISupplicantStaNetworkV12) - .getSaePassword(any(android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .getSaePasswordCallback.class)); - - /** PSK passphrase */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String pskPassphrase) throws RemoteException { - mSupplicantVariables.pskPassphrase = pskPassphrase; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setPskPassphrase(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getPskPassphraseCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.pskPassphrase); - } - }).when(mISupplicantStaNetworkMock) - .getPskPassphrase(any(ISupplicantStaNetwork.getPskPassphraseCallback.class)); - - /** PSK */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(byte[] psk) throws RemoteException { - mSupplicantVariables.psk = psk; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setPsk(any(byte[].class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getPskCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.psk); - } - }).when(mISupplicantStaNetworkMock) - .getPsk(any(ISupplicantStaNetwork.getPskCallback.class)); - - /** WEP keys **/ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int keyIdx, ArrayList<Byte> key) throws RemoteException { - mSupplicantVariables.wepKey[keyIdx] = key; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setWepKey(any(int.class), any(ArrayList.class)); - doAnswer(new AnswerWithArguments() { - public void answer(int keyIdx, ISupplicantStaNetwork.getWepKeyCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.wepKey[keyIdx]); - } - }).when(mISupplicantStaNetworkMock) - .getWepKey(any(int.class), any(ISupplicantStaNetwork.getWepKeyCallback.class)); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int keyIdx) throws RemoteException { - mSupplicantVariables.wepTxKeyIdx = keyIdx; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setWepTxKeyIdx(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getWepTxKeyIdxCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.wepTxKeyIdx); - } - }).when(mISupplicantStaNetworkMock) - .getWepTxKeyIdx(any(ISupplicantStaNetwork.getWepTxKeyIdxCallback.class)); - - /** allowedKeyManagement */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.keyMgmtMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setKeyMgmt(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getKeyMgmtCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.keyMgmtMask); - } - }).when(mISupplicantStaNetworkMock) - .getKeyMgmt(any(ISupplicantStaNetwork.getKeyMgmtCallback.class)); - - /** allowedKeyManagement v1.2 */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.keyMgmtMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV12).setKeyMgmt_1_2(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getKeyMgmtCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.keyMgmtMask); - } - }).when(mISupplicantStaNetworkV12) - .getKeyMgmt_1_2(any(android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .getKeyMgmt_1_2Callback.class)); - - /** allowedKeyManagement v1.3 */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.keyMgmtMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV13).setKeyMgmt_1_3(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .getKeyMgmt_1_3Callback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.keyMgmtMask); - } - }).when(mISupplicantStaNetworkV13) - .getKeyMgmt_1_3(any(android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .getKeyMgmt_1_3Callback.class)); - - /** allowedProtocols */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.protoMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setProto(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getProtoCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.protoMask); - } - }).when(mISupplicantStaNetworkMock) - .getProto(any(ISupplicantStaNetwork.getProtoCallback.class)); - - /** allowedProtocols v1.3*/ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.protoMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV13).setProto_1_3(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .getProto_1_3Callback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.protoMask); - } - }).when(mISupplicantStaNetworkV13) - .getProto_1_3(any(android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .getProto_1_3Callback.class)); - - /** allowedAuthAlgorithms */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.authAlgMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setAuthAlg(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getAuthAlgCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.authAlgMask); - } - }).when(mISupplicantStaNetworkMock) - .getAuthAlg(any(ISupplicantStaNetwork.getAuthAlgCallback.class)); - - /** allowedGroupCiphers */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.groupCipherMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setGroupCipher(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getGroupCipherCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.groupCipherMask); - } - }).when(mISupplicantStaNetworkMock) - .getGroupCipher(any(ISupplicantStaNetwork.getGroupCipherCallback.class)); - - /** allowedGroupCiphers v1.2*/ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.groupCipherMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV12).setGroupCipher_1_2(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getGroupCipherCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.groupCipherMask); - } - }).when(mISupplicantStaNetworkV12) - .getGroupCipher_1_2(any(android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork - .getGroupCipher_1_2Callback.class)); - - /** allowedGroupCiphers v1.3*/ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.groupCipherMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV13).setGroupCipher_1_3(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .getGroupCipher_1_3Callback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.groupCipherMask); - } - }).when(mISupplicantStaNetworkV13) - .getGroupCipher_1_3(any(android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .getGroupCipher_1_3Callback.class)); - - /** allowedPairwiseCiphers */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.pairwiseCipherMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setPairwiseCipher(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getPairwiseCipherCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.pairwiseCipherMask); - } - }).when(mISupplicantStaNetworkMock) - .getPairwiseCipher(any(ISupplicantStaNetwork.getPairwiseCipherCallback.class)); - - /** allowedPairwiseCiphers v1.2 */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.pairwiseCipherMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV12).setPairwiseCipher_1_2(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getPairwiseCipherCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.pairwiseCipherMask); - } - }).when(mISupplicantStaNetworkV12) - .getPairwiseCipher_1_2(any(android.hardware.wifi.supplicant.V1_2 - .ISupplicantStaNetwork.getPairwiseCipher_1_2Callback.class)); - - /** allowedPairwiseCiphers v1.3 */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int mask) throws RemoteException { - mSupplicantVariables.pairwiseCipherMask = mask; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV13).setPairwiseCipher_1_3(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .getPairwiseCipher_1_3Callback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.pairwiseCipherMask); - } - }).when(mISupplicantStaNetworkV13) - .getPairwiseCipher_1_3(any(android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.getPairwiseCipher_1_3Callback.class)); - - /** metadata: idstr */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String idStr) throws RemoteException { - mSupplicantVariables.idStr = idStr; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setIdStr(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getIdStrCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.idStr); - } - }).when(mISupplicantStaNetworkMock) - .getIdStr(any(ISupplicantStaNetwork.getIdStrCallback.class)); - - /** UpdateIdentifier */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int identifier) throws RemoteException { - mSupplicantVariables.updateIdentifier = identifier; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setUpdateIdentifier(any(int.class)); - - /** EAP method */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int method) throws RemoteException { - mSupplicantVariables.eapMethod = method; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapMethod(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapMethodCallback cb) - throws RemoteException { - // When not set, return failure. - if (mSupplicantVariables.eapMethod == -1) { - cb.onValues(mStatusFailure, mSupplicantVariables.eapMethod); - } else { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapMethod); - } - } - }).when(mISupplicantStaNetworkMock) - .getEapMethod(any(ISupplicantStaNetwork.getEapMethodCallback.class)); - - /** EAP Phase 2 method */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int method) throws RemoteException { - mSupplicantVariables.eapPhase2Method = method; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapPhase2Method(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapPhase2MethodCallback cb) - throws RemoteException { - // When not set, return failure. - if (mSupplicantVariables.eapPhase2Method == -1) { - cb.onValues(mStatusFailure, mSupplicantVariables.eapPhase2Method); - } else { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapPhase2Method); - } - } - }).when(mISupplicantStaNetworkMock) - .getEapPhase2Method(any(ISupplicantStaNetwork.getEapPhase2MethodCallback.class)); - - /** EAP Identity */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> identity) throws RemoteException { - mSupplicantVariables.eapIdentity = identity; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapIdentity(any(ArrayList.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapIdentityCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapIdentity); - } - }).when(mISupplicantStaNetworkMock) - .getEapIdentity(any(ISupplicantStaNetwork.getEapIdentityCallback.class)); - - /** EAP Anonymous Identity */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> identity) throws RemoteException { - mSupplicantVariables.eapAnonymousIdentity = identity; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapAnonymousIdentity(any(ArrayList.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapAnonymousIdentityCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapAnonymousIdentity); - } - }).when(mISupplicantStaNetworkMock) - .getEapAnonymousIdentity( - any(ISupplicantStaNetwork.getEapAnonymousIdentityCallback.class)); - - /** EAP Password */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> password) throws RemoteException { - mSupplicantVariables.eapPassword = password; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapPassword(any(ArrayList.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapPasswordCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapPassword); - } - }).when(mISupplicantStaNetworkMock) - .getEapPassword(any(ISupplicantStaNetwork.getEapPasswordCallback.class)); - - /** EAP Client Cert */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String cert) throws RemoteException { - mSupplicantVariables.eapClientCert = cert; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapClientCert(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapClientCertCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapClientCert); - } - }).when(mISupplicantStaNetworkMock) - .getEapClientCert(any(ISupplicantStaNetwork.getEapClientCertCallback.class)); - - /** EAP CA Cert */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String cert) throws RemoteException { - mSupplicantVariables.eapCACert = cert; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapCACert(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapCACertCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapCACert); - } - }).when(mISupplicantStaNetworkMock) - .getEapCACert(any(ISupplicantStaNetwork.getEapCACertCallback.class)); - - /** EAP Subject Match */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String match) throws RemoteException { - mSupplicantVariables.eapSubjectMatch = match; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapSubjectMatch(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapSubjectMatchCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapSubjectMatch); - } - }).when(mISupplicantStaNetworkMock) - .getEapSubjectMatch(any(ISupplicantStaNetwork.getEapSubjectMatchCallback.class)); - - /** EAP Engine */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(boolean enable) throws RemoteException { - mSupplicantVariables.eapEngine = enable; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapEngine(any(boolean.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapEngineCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapEngine); - } - }).when(mISupplicantStaNetworkMock) - .getEapEngine(any(ISupplicantStaNetwork.getEapEngineCallback.class)); - - /** EAP Engine ID */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String id) throws RemoteException { - mSupplicantVariables.eapEngineID = id; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapEngineID(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapEngineIDCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapEngineID); - } - }).when(mISupplicantStaNetworkMock) - .getEapEngineID(any(ISupplicantStaNetwork.getEapEngineIDCallback.class)); - - /** EAP Private Key */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String key) throws RemoteException { - mSupplicantVariables.eapPrivateKeyId = key; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapPrivateKeyId(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapPrivateKeyIdCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapPrivateKeyId); - } - }).when(mISupplicantStaNetworkMock) - .getEapPrivateKeyId(any(ISupplicantStaNetwork.getEapPrivateKeyIdCallback.class)); - - /** EAP Alt Subject Match */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String match) throws RemoteException { - mSupplicantVariables.eapAltSubjectMatch = match; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapAltSubjectMatch(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapAltSubjectMatchCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapAltSubjectMatch); - } - }).when(mISupplicantStaNetworkMock) - .getEapAltSubjectMatch( - any(ISupplicantStaNetwork.getEapAltSubjectMatchCallback.class)); - - /** EAP Domain Suffix Match */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String match) throws RemoteException { - mSupplicantVariables.eapDomainSuffixMatch = match; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapDomainSuffixMatch(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapDomainSuffixMatchCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapDomainSuffixMatch); - } - }).when(mISupplicantStaNetworkMock) - .getEapDomainSuffixMatch( - any(ISupplicantStaNetwork.getEapDomainSuffixMatchCallback.class)); - - /** EAP CA Path*/ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String path) throws RemoteException { - mSupplicantVariables.eapCAPath = path; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setEapCAPath(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantStaNetwork.getEapCAPathCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.eapCAPath); - } - }).when(mISupplicantStaNetworkMock) - .getEapCAPath(any(ISupplicantStaNetwork.getEapCAPathCallback.class)); - - /** EAP Proactive Key Caching */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(boolean enable) throws RemoteException { - mSupplicantVariables.eapProactiveKeyCaching = enable; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock).setProactiveKeyCaching(any(boolean.class)); - - /** Callback registration */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ISupplicantStaNetworkCallback cb) - throws RemoteException { - mISupplicantStaNetworkCallback = cb; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkMock) - .registerCallback(any(ISupplicantStaNetworkCallback.class)); - - /** Suite-B*/ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(boolean enable) throws RemoteException { - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV12).enableTlsSuiteBEapPhase1Param(any(boolean.class)); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer() throws RemoteException { - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV12).enableSuiteBEapOpenSslCiphers(); - - /** OCSP */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int ocsp) throws RemoteException { - mSupplicantVariables.ocsp = ocsp; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV13).setOcsp(any(int.class)); - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.getOcspCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.ocsp); - } - }).when(mISupplicantStaNetworkV13) - .getOcsp(any(android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork - .getOcspCallback.class)); - - /** PMK cache */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> serializedData) throws RemoteException { - mSupplicantVariables.serializedPmkCache = serializedData; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV13).setPmkCache(any(ArrayList.class)); - - /** WAPI Cert */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(String cert) throws RemoteException { - mSupplicantVariables.wapiCertSuite = cert; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV13).setWapiCertSuite(any(String.class)); - doAnswer(new AnswerWithArguments() { - public void answer(android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.getWapiCertSuiteCallback cb) - throws RemoteException { - cb.onValues(mStatusSuccess, mSupplicantVariables.wapiCertSuite); - } - }).when(mISupplicantStaNetworkV13) - .getWapiCertSuite(any(android.hardware.wifi.supplicant.V1_3 - .ISupplicantStaNetwork.getWapiCertSuiteCallback.class)); - - /** EAP ERP */ - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(boolean enable) throws RemoteException { - mSupplicantVariables.eapErp = enable; - return mStatusSuccess; - } - }).when(mISupplicantStaNetworkV13).setEapErp(any(boolean.class)); - } - - private SupplicantStatus createSupplicantStatus(int code) { - SupplicantStatus status = new SupplicantStatus(); - status.code = code; - return status; - } - - /** - * Need this for tests which wants to manipulate context before creating the instance. - */ - private void createSupplicantStaNetwork(SupplicantStaNetworkVersion version) { - switch (version) { - case V1_0: - mSupplicantNetwork = new SupplicantStaNetworkHal( - mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor); - break; - case V1_2: - mSupplicantNetwork = new SupplicantStaNetworkHalSpyV1_2( - mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor); - break; - case V1_3: - mSupplicantNetwork = new SupplicantStaNetworkHalSpyV1_3( - mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor); - break; - } - mSupplicantNetwork.enableVerboseLogging(true); - } - - // Private class to to store/inspect values set via the HIDL mock. - private class SupplicantNetworkVariables { - public ArrayList<Byte> ssid; - public int networkId; - public byte[/* 6 */] bssid; - public int keyMgmtMask; - public int protoMask; - public int authAlgMask; - public int groupCipherMask; - public int pairwiseCipherMask; - public boolean scanSsid; - public boolean requirePmf; - public String idStr; - public int updateIdentifier; - public String pskPassphrase; - public byte[] psk; - public ArrayList<Byte>[] wepKey = new ArrayList[4]; - public int wepTxKeyIdx; - public int eapMethod = -1; - public int eapPhase2Method = -1; - public ArrayList<Byte> eapIdentity; - public ArrayList<Byte> eapAnonymousIdentity; - public ArrayList<Byte> eapPassword; - public String eapCACert; - public String eapCAPath; - public String eapClientCert; - public String eapPrivateKeyId; - public String eapSubjectMatch; - public String eapAltSubjectMatch; - public boolean eapEngine; - public String eapEngineID; - public String eapDomainSuffixMatch; - public boolean eapProactiveKeyCaching; - public int ocsp; - public ArrayList<Byte> serializedPmkCache; - public String wapiCertSuite; - public boolean eapErp; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantStateTrackerTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantStateTrackerTest.java deleted file mode 100644 index 1b91ea1af..000000000 --- a/tests/wifitests/src/com/android/server/wifi/SupplicantStateTrackerTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.*; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.os.BatteryStatsManager; -import android.os.Handler; -import android.os.Message; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link SupplicantStateTracker}. - */ -@SmallTest -public class SupplicantStateTrackerTest extends WifiBaseTest { - - private static final String TAG = "SupplicantStateTrackerTest"; - private static final String sSSID = "\"GoogleGuest\""; - private static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID); - private static final String sBSSID = "01:02:03:04:05:06"; - - private @Mock WifiConfigManager mWcm; - private @Mock Context mContext; - private @Mock BatteryStatsManager mBatteryStats; - private Handler mHandler; - private SupplicantStateTracker mSupplicantStateTracker; - private TestLooper mLooper; - - private Message getSupplicantStateChangeMessage(int networkId, WifiSsid wifiSsid, - String bssid, SupplicantState newSupplicantState) { - return Message.obtain(null, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(networkId, wifiSsid, bssid, newSupplicantState)); - - } - - @Before - public void setUp() { - mLooper = new TestLooper(); - mHandler = new Handler(mLooper.getLooper()); - MockitoAnnotations.initMocks(this); - mSupplicantStateTracker = new SupplicantStateTracker(mContext, mWcm, mBatteryStats, - mHandler); - } - - /** - * This test verifies that the SupplicantStateTracker sends a broadcast intent upon receiving - * a message when supplicant state changes - */ - @Test - public void testSupplicantStateChangeIntent() { - BroadcastReceiver wifiBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assertTrue(action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)); - SupplicantState recvdState = - (SupplicantState) intent.getExtra(WifiManager.EXTRA_NEW_STATE, -1); - assertEquals(SupplicantState.SCANNING, recvdState); - } - }; - IntentFilter mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); - mContext.registerReceiver(wifiBroadcastReceiver, mIntentFilter); - mSupplicantStateTracker.sendMessage(getSupplicantStateChangeMessage(0, sWifiSsid, - sBSSID, SupplicantState.SCANNING)); - } - - /** - * This test verifies that the current auth status is sent in the Broadcast intent - */ - @Test - public void testAuthPassInSupplicantStateChangeIntent() { - BroadcastReceiver wifiBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assertTrue(action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)); - SupplicantState recvdState = - (SupplicantState) intent.getExtra(WifiManager.EXTRA_NEW_STATE, -1); - assertEquals(SupplicantState.AUTHENTICATING, recvdState); - boolean authStatus = - (boolean) intent.getExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1); - assertEquals(authStatus, true); - } - }; - IntentFilter mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); - mContext.registerReceiver(wifiBroadcastReceiver, mIntentFilter); - mSupplicantStateTracker.sendMessage(getSupplicantStateChangeMessage(0, sWifiSsid, - sBSSID, SupplicantState.AUTHENTICATING)); - mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); - } - - /** - * This test verifies that the current auth status is sent in the Broadcast intent - */ - @Test - public void testAuthFailedInSupplicantStateChangeIntent() { - BroadcastReceiver wifiBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assertTrue(action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)); - SupplicantState recvdState = - (SupplicantState) intent.getExtra(WifiManager.EXTRA_NEW_STATE, -1); - assertEquals(SupplicantState.AUTHENTICATING, recvdState); - boolean authStatus = - (boolean) intent.getExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1); - assertEquals(authStatus, false); - } - }; - IntentFilter mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); - mContext.registerReceiver(wifiBroadcastReceiver, mIntentFilter); - mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); - mSupplicantStateTracker.sendMessage(getSupplicantStateChangeMessage(0, sWifiSsid, - sBSSID, SupplicantState.AUTHENTICATING)); - } - - /** - * This test verifies the correct reasonCode for auth failure is sent in Broadcast - * intent. - */ - @Test - public void testReasonCodeInSupplicantStateChangeIntent() { - BroadcastReceiver wifiBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assertTrue(action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)); - SupplicantState recvdState = - (SupplicantState) intent.getExtra(WifiManager.EXTRA_NEW_STATE, -1); - assertEquals(SupplicantState.AUTHENTICATING, recvdState); - boolean authStatus = - (boolean) intent.getExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1); - assertEquals(authStatus, false); - int reasonCode = (int) - intent.getExtra(WifiManager.EXTRA_SUPPLICANT_ERROR_REASON, -1); - assertEquals(reasonCode, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); - } - }; - IntentFilter mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); - mContext.registerReceiver(wifiBroadcastReceiver, mIntentFilter); - mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, - WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1); - mSupplicantStateTracker.sendMessage(getSupplicantStateChangeMessage(0, sWifiSsid, - sBSSID, SupplicantState.AUTHENTICATING)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/TestUtil.java b/tests/wifitests/src/com/android/server/wifi/TestUtil.java deleted file mode 100644 index 2640209a1..000000000 --- a/tests/wifitests/src/com/android/server/wifi/TestUtil.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.os.PowerManager; - -import java.util.ArrayList; - -/** - * Utils for wifi tests. - */ -public class TestUtil { - /** - * Send {@link WifiManager#NETWORK_STATE_CHANGED_ACTION} broadcast. - */ - public static void sendNetworkStateChanged(BroadcastReceiver broadcastReceiver, - Context context, NetworkInfo.DetailedState detailedState) { - Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); - NetworkInfo networkInfo = new NetworkInfo(0, 0, "", ""); - networkInfo.setDetailedState(detailedState, "", ""); - intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo); - broadcastReceiver.onReceive(context, intent); - } - - /** - * Send {@link WifiManager#NETWORK_STATE_CHANGED_ACTION} broadcast. - */ - public static void sendNetworkStateChanged(BroadcastReceiver broadcastReceiver, - Context context, NetworkInfo nwInfo, WifiInfo wifiInfo) { - Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); - intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, nwInfo); - intent.putExtra(WifiManager.EXTRA_WIFI_INFO, wifiInfo); - broadcastReceiver.onReceive(context, intent); - } - - /** - * Send {@link WifiManager#SCAN_RESULTS_AVAILABLE_ACTION} broadcast. - */ - public static void sendScanResultsAvailable(BroadcastReceiver broadcastReceiver, - Context context) { - Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - broadcastReceiver.onReceive(context, intent); - } - - /** - * Send {@link WifiManager#WIFI_STATE_CHANGED} broadcast. - */ - public static void sendWifiStateChanged(BroadcastReceiver broadcastReceiver, - Context context, int wifiState) { - Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); - intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); - broadcastReceiver.onReceive(context, intent); - } - - /** - * Send {@link WifiManager#WIFI_AP_STATE_CHANGED} broadcast. - */ - public static void sendWifiApStateChanged(BroadcastReceiver broadcastReceiver, - Context context, int apState, int previousState, int error, String ifaceName, - int mode) { - Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); - intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, apState); - intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousState); - if (apState == WifiManager.WIFI_AP_STATE_FAILED) { - // only set reason number when softAP start failed - intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, error); - } - intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, ifaceName); - intent.putExtra(WifiManager.EXTRA_WIFI_AP_MODE, mode); - broadcastReceiver.onReceive(context, intent); - } - - /** - * Send {@link ConnectivityManager#ACTION_TETHER_STATE_CHANGED} broadcast. - */ - public static void sendTetherStateChanged(BroadcastReceiver broadcastReceiver, - Context context, ArrayList<String> available, ArrayList<String> active) { - Intent intent = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); - intent.putExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, available); - intent.putExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, active); - broadcastReceiver.onReceive(context, intent); - } - - public static void sendIdleModeChanged(BroadcastReceiver broadcastReceiver, Context context) { - Intent intent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - broadcastReceiver.onReceive(context, intent); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/ThroughputPredictorTest.java b/tests/wifitests/src/com/android/server/wifi/ThroughputPredictorTest.java deleted file mode 100644 index f8b0586ee..000000000 --- a/tests/wifitests/src/com/android/server/wifi/ThroughputPredictorTest.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.INVALID; -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.MAX_CHANNEL_UTILIZATION; -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.MIN_CHANNEL_UTILIZATION; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.validateMockitoUsage; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.nl80211.DeviceWiphyCapabilities; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -/** - * Unit tests for {@link com.android.server.wifi.ThroughputPredictor}. - */ -@SmallTest -public class ThroughputPredictorTest extends WifiBaseTest { - @Mock private DeviceWiphyCapabilities mDeviceCapabilities; - @Mock private Context mContext; - // For simulating the resources, we use a Spy on a MockResource - // (which is really more of a stub than a mock, in spite if its name). - // This is so that we get errors on any calls that we have not explicitly set up. - @Spy - private MockResources mResource = new MockResources(); - ThroughputPredictor mThroughputPredictor; - WifiNative.ConnectionCapabilities mConnectionCap = new WifiNative.ConnectionCapabilities(); - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mDeviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N)) - .thenReturn(true); - when(mDeviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC)) - .thenReturn(true); - when(mDeviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX)) - .thenReturn(false); - when(mDeviceCapabilities.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)) - .thenReturn(true); - when(mDeviceCapabilities.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)) - .thenReturn(true); - when(mDeviceCapabilities.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_160MHZ)) - .thenReturn(false); - when(mDeviceCapabilities.getMaxNumberTxSpatialStreams()).thenReturn(2); - when(mDeviceCapabilities.getMaxNumberRxSpatialStreams()).thenReturn(2); - - when(mResource.getBoolean( - R.bool.config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideEnable)) - .thenReturn(false); - when(mResource.getInteger( - R.integer.config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideValue)) - .thenReturn(2); - when(mContext.getResources()).thenReturn(mResource); - mThroughputPredictor = new ThroughputPredictor(mContext); - } - - /** Cleans up test. */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - @Test - public void verifyVeryLowRssi() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_20MHZ, -200, 2412, 1, - 0, 0, false); - - assertEquals(0, predictedThroughputMbps); - } - - @Test - public void verifyMaxChannelUtilizationBssLoad() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_20MHZ, 0, 2412, 1, - MAX_CHANNEL_UTILIZATION, 0, false); - - assertEquals(0, predictedThroughputMbps); - } - - @Test - public void verifyMaxChannelUtilizationLinkLayerStats() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_20MHZ, 0, 5210, 1, - INVALID, MAX_CHANNEL_UTILIZATION, false); - - assertEquals(0, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationAc5g80Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_80MHZ, 0, 5180, 2, - MIN_CHANNEL_UTILIZATION, 50, false); - - assertEquals(866, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationAc5g80Mhz2ssOverriddenTo1ss() { - when(mResource.getBoolean( - R.bool.config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideEnable)) - .thenReturn(true); - when(mResource.getInteger( - R.integer.config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideValue)) - .thenReturn(1); - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_80MHZ, 0, 5180, 2, - MIN_CHANNEL_UTILIZATION, 50, false); - - assertEquals(433, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationAx5g160Mhz4ss() { - when(mDeviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX)) - .thenReturn(true); - when(mDeviceCapabilities.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_160MHZ)) - .thenReturn(true); - when(mDeviceCapabilities.getMaxNumberTxSpatialStreams()).thenReturn(4); - when(mDeviceCapabilities.getMaxNumberRxSpatialStreams()).thenReturn(4); - - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AX, ScanResult.CHANNEL_WIDTH_160MHZ, 0, 5180, 4, - MIN_CHANNEL_UTILIZATION, INVALID, false); - - assertEquals(4803, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationAx5g160Mhz4ssOverriddenTo2ss() { - when(mResource.getBoolean( - R.bool.config_wifiFrameworkMaxNumSpatialStreamDeviceOverrideEnable)) - .thenReturn(true); - when(mDeviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX)) - .thenReturn(true); - when(mDeviceCapabilities.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_160MHZ)) - .thenReturn(true); - when(mDeviceCapabilities.getMaxNumberTxSpatialStreams()).thenReturn(4); - when(mDeviceCapabilities.getMaxNumberRxSpatialStreams()).thenReturn(4); - - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AX, ScanResult.CHANNEL_WIDTH_160MHZ, 0, 5180, 4, - MIN_CHANNEL_UTILIZATION, INVALID, false); - - assertEquals(2401, predictedThroughputMbps); - } - - - @Test - public void verifyMidRssiMinChannelUtilizationAc5g80Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_80MHZ, -50, 5180, 2, - MIN_CHANNEL_UTILIZATION, INVALID, false); - - assertEquals(866, predictedThroughputMbps); - } - - @Test - public void verifyLowRssiMinChannelUtilizationAc5g80Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_80MHZ, -80, 5180, 2, - MIN_CHANNEL_UTILIZATION, INVALID, false); - - assertEquals(41, predictedThroughputMbps); - } - - @Test - public void verifyLowRssiDefaultChannelUtilizationAc5g80Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_80MHZ, -80, 5180, 2, - INVALID, INVALID, false); - - assertEquals(31, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationAc2g20Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_20MHZ, -20, 2437, 2, - MIN_CHANNEL_UTILIZATION, INVALID, false); - - assertEquals(192, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationAc2g20Mhz2ssBluetoothConnected() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_20MHZ, -20, 2437, 2, - MIN_CHANNEL_UTILIZATION, INVALID, true); - - assertEquals(144, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationLegacy5g20Mhz() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_LEGACY, ScanResult.CHANNEL_WIDTH_20MHZ, -50, 5180, - 1, MIN_CHANNEL_UTILIZATION, INVALID, false); - - assertEquals(54, predictedThroughputMbps); - } - - @Test - public void verifyLowRssiDefaultChannelUtilizationLegacy5g20Mhz() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_LEGACY, ScanResult.CHANNEL_WIDTH_20MHZ, -80, 5180, - 2, INVALID, INVALID, false); - - assertEquals(11, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationHt2g20Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11N, ScanResult.CHANNEL_WIDTH_20MHZ, -50, 2437, 2, - MIN_CHANNEL_UTILIZATION, INVALID, false); - - assertEquals(144, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiMinChannelUtilizationHt2g20MhzIncorrectNss() { - when(mDeviceCapabilities.getMaxNumberTxSpatialStreams()).thenReturn(0); - when(mDeviceCapabilities.getMaxNumberRxSpatialStreams()).thenReturn(0); - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11N, ScanResult.CHANNEL_WIDTH_20MHZ, -50, 2437, 2, - MIN_CHANNEL_UTILIZATION, INVALID, false); - // Expect to 1SS peak rate because maxNumberSpatialStream is overridden to 1. - assertEquals(72, predictedThroughputMbps); - } - - @Test - public void verifyLowRssiDefaultChannelUtilizationHt2g20Mhz1ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11N, ScanResult.CHANNEL_WIDTH_20MHZ, -80, 2437, 1, - INVALID, INVALID, true); - - assertEquals(5, predictedThroughputMbps); - } - - @Test - public void verifyHighRssiHighChannelUtilizationAc2g20Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_20MHZ, -50, 2437, 2, - INVALID, 80, true); - - assertEquals(84, predictedThroughputMbps); - } - - @Test - public void verifyRssiBoundaryHighChannelUtilizationAc2g20Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_20MHZ, -69, 2437, 2, - INVALID, 80, true); - - assertEquals(46, predictedThroughputMbps); - } - - @Test - public void verifyRssiBoundaryHighChannelUtilizationAc5g40Mhz2ss() { - int predictedThroughputMbps = mThroughputPredictor.predictThroughput(mDeviceCapabilities, - ScanResult.WIFI_STANDARD_11AC, ScanResult.CHANNEL_WIDTH_40MHZ, -66, 5180, 2, - INVALID, 80, false); - - assertEquals(103, predictedThroughputMbps); - } - - @Test - public void verifyMaxThroughputAc40Mhz2ss() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_11AC; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_40MHZ; - mConnectionCap.maxNumberTxSpatialStreams = 2; - assertEquals(400, mThroughputPredictor.predictMaxTxThroughput(mConnectionCap)); - } - - @Test - public void verifyMaxThroughputAc80Mhz2ss() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_11AC; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_80MHZ; - mConnectionCap.maxNumberRxSpatialStreams = 2; - assertEquals(866, mThroughputPredictor.predictMaxRxThroughput(mConnectionCap)); - } - - @Test - public void verifyMaxThroughputAc80MhzIncorrectNss() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_11AC; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_80MHZ; - mConnectionCap.maxNumberRxSpatialStreams = -5; - // Expect to 1SS peak rate because maxNumberSpatialStream is overridden to 1. - assertEquals(433, mThroughputPredictor.predictMaxRxThroughput(mConnectionCap)); - } - - @Test - public void verifyMaxThroughputN20Mhz1ss() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_11N; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_20MHZ; - mConnectionCap.maxNumberRxSpatialStreams = 1; - assertEquals(72, mThroughputPredictor.predictMaxRxThroughput(mConnectionCap)); - } - - @Test - public void verifyMaxThroughputLegacy20Mhz1ss() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_LEGACY; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_80MHZ; - mConnectionCap.maxNumberRxSpatialStreams = 1; - assertEquals(54, mThroughputPredictor.predictMaxRxThroughput(mConnectionCap)); - } - - @Test - public void verifyMaxThroughputAx80Mhz2ss() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_11AX; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_80MHZ; - mConnectionCap.maxNumberRxSpatialStreams = 2; - assertEquals(1200, mThroughputPredictor.predictMaxRxThroughput(mConnectionCap)); - } - - @Test - public void verifyMaxThroughputUnknownStandard() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_UNKNOWN; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_80MHZ; - mConnectionCap.maxNumberTxSpatialStreams = 2; - assertEquals(-1, mThroughputPredictor.predictMaxTxThroughput(mConnectionCap)); - } - - @Test - public void verifyTxThroughputAc20Mhz2ssMiddleSnr() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_11AC; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_20MHZ; - mConnectionCap.maxNumberTxSpatialStreams = 2; - assertEquals(131, mThroughputPredictor.predictTxThroughput(mConnectionCap, - -50, 2437, 80)); - } - - @Test - public void verifyRxThroughputAx160Mhz4ssHighSnrInvalidUtilization() { - mConnectionCap.wifiStandard = ScanResult.WIFI_STANDARD_11AX; - mConnectionCap.channelBandwidth = ScanResult.CHANNEL_WIDTH_160MHZ; - mConnectionCap.maxNumberRxSpatialStreams = 4; - //mConnectionCap.maxNumberTxSpatialStreams = 4; - assertEquals(2881, mThroughputPredictor.predictRxThroughput(mConnectionCap, - -10, 5180, INVALID)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/UntrustedWifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/UntrustedWifiNetworkFactoryTest.java deleted file mode 100644 index 012889d4b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/UntrustedWifiNetworkFactoryTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.os.test.TestLooper; -import android.test.suitebuilder.annotation.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.UntrustedWifiNetworkFactory}. - */ -@SmallTest -public class UntrustedWifiNetworkFactoryTest extends WifiBaseTest { - @Mock WifiConnectivityManager mWifiConnectivityManager; - @Mock Context mContext; - NetworkCapabilities mNetworkCapabilities; - TestLooper mLooper; - NetworkRequest mNetworkRequest; - - private UntrustedWifiNetworkFactory mUntrustedWifiNetworkFactory; - - /** - * Setup the mocks. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mLooper = new TestLooper(); - mNetworkCapabilities = new NetworkCapabilities(); - mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); - mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); - - mUntrustedWifiNetworkFactory = new UntrustedWifiNetworkFactory( - mLooper.getLooper(), mContext, - mNetworkCapabilities, mWifiConnectivityManager); - - mNetworkRequest = new NetworkRequest.Builder() - .setCapabilities(mNetworkCapabilities) - .build(); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - /** - * Validates handling of needNetworkFor. - */ - @Test - public void testHandleNetworkRequest() { - assertFalse(mUntrustedWifiNetworkFactory.hasConnectionRequests()); - mUntrustedWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // First network request should turn on auto-join. - verify(mWifiConnectivityManager).setUntrustedConnectionAllowed(true); - assertTrue(mUntrustedWifiNetworkFactory.hasConnectionRequests()); - - // Subsequent ones should do nothing. - mUntrustedWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - verifyNoMoreInteractions(mWifiConnectivityManager); - } - - /** - * Validates handling of releaseNetwork. - */ - @Test - public void testHandleNetworkRelease() { - // Release network without a corresponding request should be ignored. - mUntrustedWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - assertFalse(mUntrustedWifiNetworkFactory.hasConnectionRequests()); - - // Now request & then release the network request - mUntrustedWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - assertTrue(mUntrustedWifiNetworkFactory.hasConnectionRequests()); - verify(mWifiConnectivityManager).setUntrustedConnectionAllowed(true); - - mUntrustedWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - assertFalse(mUntrustedWifiNetworkFactory.hasConnectionRequests()); - verify(mWifiConnectivityManager).setUntrustedConnectionAllowed(false); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/VelocityBasedConnectedScoreTest.java b/tests/wifitests/src/com/android/server/wifi/VelocityBasedConnectedScoreTest.java deleted file mode 100644 index 2f6bae47e..000000000 --- a/tests/wifitests/src/com/android/server/wifi/VelocityBasedConnectedScoreTest.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.res.Resources; -import android.net.wifi.WifiInfo; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -/** - * Unit tests for {@link com.android.server.wifi.VelocityBasedConnectedScore}. - */ -@SmallTest -public class VelocityBasedConnectedScoreTest extends WifiBaseTest { - - - class FakeClock extends Clock { - long mWallClockMillis = 1500000000000L; - int mStepMillis = 3001; - - @Override - public long getWallClockMillis() { - mWallClockMillis += mStepMillis; - return mWallClockMillis; - } - } - - FakeClock mClock; - VelocityBasedConnectedScore mVelocityBasedConnectedScore; - ScanDetailCache mScanDetailCache; - WifiInfo mWifiInfo; - int mRssiExitThreshold2GHz; - int mRssiExitThreshold5GHz; - @Mock Context mContext; - @Spy private MockResources mResources = new MockResources(); - - private int setupIntegerResource(int resourceName, int value) { - doReturn(value).when(mResources).getInteger(resourceName); - return value; - } - - /** - * Sets up resource values for testing - * - * See frameworks/base/core/res/res/values/config.xml - */ - private void setUpResources(Resources resources) { - mRssiExitThreshold2GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz, -83); - mRssiExitThreshold5GHz = setupIntegerResource( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz, -80); - } - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - setUpResources(mResources); - mWifiInfo = new WifiInfo(); - mWifiInfo.setFrequency(2412); - when(mContext.getResources()).thenReturn(mResources); - mClock = new FakeClock(); - mVelocityBasedConnectedScore = new VelocityBasedConnectedScore( - new ScoringParams(mContext), mClock); - } - - /** - * Generate a score with no updates - * - * Expect no crash, passing score - */ - @Test - public void noCrashWhenNoData() throws Exception { - int score = mVelocityBasedConnectedScore.generateScore(); - assertTrue(score > ConnectedScore.WIFI_TRANSITION_SCORE); - } - - /** - * - * Low RSSI, but some data is moving and error rate is low. - * - * Expect a score above threshold. - */ - @Test - public void allowLowRssiIfErrorRateIsLowAndSomeDataIsMoving() throws Exception { - mWifiInfo.setRssi(mRssiExitThreshold2GHz - 2); - mWifiInfo.setLinkSpeed(6); // Mbps - mWifiInfo.setSuccessfulTxPacketsPerSecond(2.1); // proportional to pps - mWifiInfo.setLostTxPacketsPerSecond(.5); - mWifiInfo.setSuccessfulRxPacketsPerSecond(2.1); - for (int i = 0; i < 10; i++) { - mVelocityBasedConnectedScore.updateUsingWifiInfo(mWifiInfo, - mClock.getWallClockMillis()); - } - int score = mVelocityBasedConnectedScore.generateScore(); - assertTrue(score > ConnectedScore.WIFI_TRANSITION_SCORE); - // If we reset, should be below threshold after the first input - mVelocityBasedConnectedScore.reset(); - mVelocityBasedConnectedScore.updateUsingWifiInfo(mWifiInfo, mClock.getWallClockMillis()); - score = mVelocityBasedConnectedScore.generateScore(); - assertTrue(score < ConnectedScore.WIFI_TRANSITION_SCORE); - } - - /** - * - * Low RSSI, and almost no data is moving. - * - * Expect a score below threshold. - */ - @Test - public void disallowLowRssiIfDataIsNotMoving() throws Exception { - mWifiInfo.setRssi(mRssiExitThreshold2GHz - 1); - mWifiInfo.setLinkSpeed(6); // Mbps - mWifiInfo.setSuccessfulTxPacketsPerSecond(.1); // proportional to pps - mWifiInfo.setLostTxPacketsPerSecond(0); - mWifiInfo.setSuccessfulRxPacketsPerSecond(.1); - for (int i = 0; i < 10; i++) { - mVelocityBasedConnectedScore.updateUsingWifiInfo(mWifiInfo, - mClock.getWallClockMillis()); - } - int score = mVelocityBasedConnectedScore.generateScore(); - assertTrue(score < ConnectedScore.WIFI_TRANSITION_SCORE); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java deleted file mode 100644 index cc7587a36..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; - -import com.google.android.collect.Sets; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.Set; - -/** - * Unit tests for {@link WakeupConfigStoreData}. - */ -@SmallTest -public class WakeupConfigStoreDataTest extends WifiBaseTest { - - @Mock private WakeupConfigStoreData.DataSource<Boolean> mActiveDataSource; - @Mock private WakeupConfigStoreData.DataSource<Boolean> mIsOnboardedDataSource; - @Mock private WakeupConfigStoreData.DataSource<Integer> mNotificationsDataSource; - @Mock private WakeupConfigStoreData.DataSource<Set<ScanResultMatchInfo>> mNetworkDataSource; - - private WakeupConfigStoreData mWakeupConfigData; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mWakeupConfigData = new WakeupConfigStoreData(mActiveDataSource, mIsOnboardedDataSource, - mNotificationsDataSource, mNetworkDataSource); - } - - /** - * Helper function for serializing configuration data to a XML block. - * - * @return byte[] of the XML data - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mWakeupConfigData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing configuration data from a XML block. - * - * @param data XML data to parse from - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mWakeupConfigData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - } - - /** - * Can correctly serialize and deserialize the empty set case. - */ - @Test - public void deserializeSerializedData_emptySet() throws Exception { - Set<ScanResultMatchInfo> networks = Collections.emptySet(); - boolean isActive = false; - boolean isOnboarded = false; - int notificationsShown = 0; - - when(mActiveDataSource.getData()).thenReturn(isActive); - when(mIsOnboardedDataSource.getData()).thenReturn(isOnboarded); - when(mNotificationsDataSource.getData()).thenReturn(notificationsShown); - when(mNetworkDataSource.getData()).thenReturn(networks); - - byte[] bytes = serializeData(); - deserializeData(bytes); - - verify(mActiveDataSource).setData(eq(isActive)); - verify(mIsOnboardedDataSource).setData(eq(isOnboarded)); - verify(mNotificationsDataSource).setData(notificationsShown); - verify(mNetworkDataSource).setData(eq(networks)); - } - - /** - * Can correctly serialize and deserialize a standard working case. - */ - @Test - public void deserializeSerializedData() throws Exception { - ScanResultMatchInfo network1 = new ScanResultMatchInfo(); - network1.networkSsid = "ssid 1"; - network1.networkType = 0; - - ScanResultMatchInfo network2 = new ScanResultMatchInfo(); - network2.networkSsid = ",.23;4@, .#,%(,"; - network2.networkType = 1; - - ScanResultMatchInfo network3 = new ScanResultMatchInfo(); - network3.networkSsid = ""; - network3.networkType = 2; - - Set<ScanResultMatchInfo> networks = Sets.newArraySet(network1, network2, network3); - boolean isActive = true; - boolean isOnboarded = false; - int notificationsShown = 1; - - when(mActiveDataSource.getData()).thenReturn(isActive); - when(mIsOnboardedDataSource.getData()).thenReturn(isOnboarded); - when(mNotificationsDataSource.getData()).thenReturn(notificationsShown); - when(mNetworkDataSource.getData()).thenReturn(networks); - - byte[] bytes = serializeData(); - deserializeData(bytes); - - verify(mActiveDataSource).setData(eq(isActive)); - verify(mIsOnboardedDataSource).setData(eq(isOnboarded)); - verify(mNotificationsDataSource).setData(notificationsShown); - verify(mNetworkDataSource).setData(eq(networks)); - } - - /** - * Verify that reset data wipes the data sources. - */ - @Test - public void resetDataWipesDataSources() { - mWakeupConfigData.resetData(); - - verify(mActiveDataSource).setData(false); - verify(mIsOnboardedDataSource).setData(false); - verify(mNotificationsDataSource).setData(0); - verify(mNetworkDataSource).setData(eq(Collections.emptySet())); - } - - /** - * Verify that hasBeenRead returns false on newly instantiated WakeupConfigStoreData. - */ - @Test - public void hasBeenReadIsFalseWhenInitialized() { - assertFalse(mWakeupConfigData.hasBeenRead()); - } - - /** - * Verify that hasBeenRead returns true after the user store has been read. - */ - @Test - public void hasBeenReadIsTrueWhenUserStoreIsLoaded() throws Exception { - mWakeupConfigData.deserializeData(null /* in */, 0 /* outerTagDepth */, - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - assertTrue(mWakeupConfigData.hasBeenRead()); - } - - /** - * Verify that WakeUpConfigStoreData is written to - * {@link WifiConfigStore#STORE_FILE_NAME_USER_GENERAL}. - * - * @throws Exception - */ - @Test - public void getUserStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_USER_GENERAL, - mWakeupConfigData.getStoreFileId()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java deleted file mode 100644 index 3ac4adc3b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.database.ContentObserver; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.os.Handler; -import android.os.test.TestLooper; -import android.provider.Settings; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * Unit tests for {@link WakeupController}. - */ -@SmallTest -public class WakeupControllerTest extends WifiBaseTest { - - private static final String SAVED_SSID = "test scan ssid"; - private static final int DFS_CHANNEL_FREQ = 5540; - - @Mock private Context mContext; - @Mock private WakeupLock mWakeupLock; - @Mock private WakeupEvaluator mWakeupEvaluator; - @Mock private WakeupOnboarding mWakeupOnboarding; - @Mock private WifiConfigStore mWifiConfigStore; - @Mock private WifiInjector mWifiInjector; - @Mock private WifiScanner mWifiScanner; - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - @Mock private FrameworkFacade mFrameworkFacade; - @Mock private WifiSettingsStore mWifiSettingsStore; - @Mock private WifiWakeMetrics mWifiWakeMetrics; - @Mock private ActiveModeWarden mActiveModeWarden; - @Mock private WifiNative mWifiNative; - @Mock private Clock mClock; - - private TestLooper mLooper; - private WakeupController mWakeupController; - private WakeupConfigStoreData mWakeupConfigStoreData; - private WifiScanner.ScanData[] mTestScanDatas; - private ScanResult mTestScanResult; - - /** Initialize objects before each test run. */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); - when(mWifiInjector.getWifiSettingsStore()).thenReturn(mWifiSettingsStore); - when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); - when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY)) - .thenReturn(new int[]{DFS_CHANNEL_FREQ}); - - when(mWifiSettingsStore.handleWifiToggled(anyBoolean())).thenReturn(true); - // Saved network needed to start wake. - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.getNetworkSelectionStatus().setHasEverConnected(true); - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(Arrays.asList(openNetwork)); - - mLooper = new TestLooper(); - - // scanlistener input - mTestScanResult = new ScanResult(); - mTestScanResult.SSID = SAVED_SSID; - mTestScanResult.capabilities = ""; - mTestScanResult.frequency = 2412; - ScanResult[] scanResults = new ScanResult[1]; - scanResults[0] = mTestScanResult; - mTestScanDatas = new WifiScanner.ScanData[1]; - int scanBand = WifiScanner.WIFI_BAND_ALL & ~WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY; - mTestScanDatas[0] = new WifiScanner.ScanData(0 /* id */, 0 /* flags */, - 0 /* bucketsScanned */, scanBand /* bandScanned */, scanResults); - } - - /** Initializes the wakeupcontroller in the given {@code enabled} state. */ - private void initializeWakeupController(boolean enabled) { - initializeWakeupController(enabled, true /* isRead */); - } - - private void initializeWakeupController(boolean enabled, boolean isRead) { - int settingsValue = enabled ? 1 : 0; - when(mFrameworkFacade.getIntegerSetting(mContext, - Settings.Global.WIFI_WAKEUP_ENABLED, 0)).thenReturn(settingsValue); - when(mWakeupOnboarding.isOnboarded()).thenReturn(true); - mWakeupController = new WakeupController(mContext, - new Handler(mLooper.getLooper()), - mWakeupLock, - mWakeupEvaluator, - mWakeupOnboarding, - mWifiConfigManager, - mWifiConfigStore, - mWifiNetworkSuggestionsManager, - mWifiWakeMetrics, - mWifiInjector, - mFrameworkFacade, - mClock); - - ArgumentCaptor<WakeupConfigStoreData> captor = - ArgumentCaptor.forClass(WakeupConfigStoreData.class); - verify(mWifiConfigStore).registerStoreData(captor.capture()); - mWakeupConfigStoreData = captor.getValue(); - if (isRead) { - readUserStore(); - } - } - - private void readUserStore() { - try { - mWakeupConfigStoreData.deserializeData(null, 0, - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - } catch (XmlPullParserException | IOException e) { - // unreachable - } - } - - private ScanResult createOpenScanResult(String ssid, int frequency) { - ScanResult scanResult = new ScanResult(); - scanResult.SSID = ssid; - scanResult.capabilities = ""; - scanResult.frequency = frequency; - return scanResult; - } - - private ScanResult createOweScanResult(String ssid, int frequency) { - ScanResult scanResult = new ScanResult(); - scanResult.SSID = ssid; - scanResult.capabilities = "OWE"; - scanResult.frequency = frequency; - return scanResult; - } - - private void verifyDoesNotEnableWifi() { - verify(mWifiSettingsStore, never()).handleWifiToggled(true /* wifiEnabled */); - } - - /** - * Verify WakeupController is enabled when the settings toggle is true. - */ - @Test - public void verifyEnabledWhenToggledOn() { - initializeWakeupController(true /* enabled */); - - assertTrue(mWakeupController.isEnabledAndReady()); - } - - /** - * Verify WakeupController is disabled when the settings toggle is false. - */ - @Test - public void verifyDisabledWhenToggledOff() { - initializeWakeupController(false /* enabled */); - - assertFalse(mWakeupController.isEnabledAndReady()); - } - - /** - * Verify WakeupController registers its store data with the WifiConfigStore on construction. - */ - @Test - public void registersWakeupConfigStoreData() { - initializeWakeupController(true /* enabled */); - verify(mWifiConfigStore).registerStoreData(any(WakeupConfigStoreData.class)); - } - - /** - * Verify that dump calls also dump the state of the WakeupLock. - */ - @Test - public void dumpIncludesWakeupLock() { - initializeWakeupController(true /* enabled */); - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - mWakeupController.dump(null, writer, null); - - verify(mWakeupLock).dump(null, writer, null); - } - - /** - * Verify that start sets the wakeup lock. - */ - @Test - public void startSetsWakeupLock() { - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - verify(mWakeupLock).setLock(any()); - verify(mWifiWakeMetrics).recordStartEvent(anyInt()); - } - - /** - * Verify that start does not record an ignored start call if the controller is not yet active. - */ - @Test - public void startDoesNotRecordIgnoredStart() { - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - verify(mWifiWakeMetrics, never()).recordIgnoredStart(); - } - - /** - * Verify that start does not set the wakeup lock when feature is disabled. - */ - @Test - public void startDoesNotSetWakeupLockWhenDisabled() { - initializeWakeupController(false /* enabled */); - mWakeupController.start(); - verify(mWakeupLock, never()).setLock(any()); - verify(mWifiWakeMetrics, never()).recordStartEvent(anyInt()); - } - - - /** - * Verify that start does not set the wakeup lock when feature is disabled. - */ - @Test - public void startDoesNotSetWakeupLockWhenNoSavedNetworksOrSuggestions() { - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(Collections.emptyList()); - initializeWakeupController(false /* enabled */); - mWakeupController.start(); - verify(mWakeupLock, never()).setLock(any()); - verify(mWifiWakeMetrics, never()).recordStartEvent(anyInt()); - } - - /** - * If the controller is already active, verify that start() is ignored and no setup is done. - */ - @Test - public void startIsIgnoredIfAlreadyActive() { - initializeWakeupController(true /* enabled */); - InOrder lockInOrder = Mockito.inOrder(mWakeupLock); - InOrder metricsInOrder = Mockito.inOrder(mWifiWakeMetrics); - - mWakeupController.start(); - lockInOrder.verify(mWakeupLock).setLock(any()); - metricsInOrder.verify(mWifiWakeMetrics).recordStartEvent(anyInt()); - - mWakeupController.stop(); - mWakeupController.start(); - metricsInOrder.verify(mWifiWakeMetrics).recordIgnoredStart(); - metricsInOrder.verify(mWifiWakeMetrics, never()).recordStartEvent(anyInt()); - lockInOrder.verify(mWakeupLock, never()).setLock(any()); - } - - /** - * Verify that start registers the scan listener on the wifi scanner. - */ - @Test - public void startRegistersScanListener() { - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - verify(mWifiScanner).registerScanListener(any(), any()); - } - - /** - * Verify that stop deregisters the scan listener from the wifi scanner. - */ - @Test - public void stopDeresgistersScanListener() { - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - mWakeupController.stop(); - verify(mWifiScanner).unregisterScanListener(any()); - } - - /** - * Verify that reset sets active to false. - * - * <p>This is accomplished by initiating another call to start and verifying that the wakeup - * lock is re-set. - */ - @Test - public void resetSetsActiveToFalse() { - initializeWakeupController(true /* enabled */); - InOrder lockInOrder = Mockito.inOrder(mWakeupLock); - InOrder metricsInOrder = Mockito.inOrder(mWifiWakeMetrics); - - mWakeupController.start(); - lockInOrder.verify(mWakeupLock).setLock(any()); - metricsInOrder.verify(mWifiWakeMetrics).recordStartEvent(anyInt()); - - mWakeupController.stop(); - mWakeupController.reset(); - metricsInOrder.verify(mWifiWakeMetrics).recordResetEvent(0 /* numScans */); - - mWakeupController.start(); - lockInOrder.verify(mWakeupLock).setLock(any()); - metricsInOrder.verify(mWifiWakeMetrics).recordStartEvent(anyInt()); - } - - /** - * Verify that the wakeup lock is initialized with the intersection of ScanResults and saved - * networks. - */ - @Test - public void startInitializesWakeupLockWithSavedScanResults() { - String ssid1 = "ssid 1"; - String ssid2 = "ssid 2"; - String quotedSsid = ScanResultUtil.createQuotedSSID(ssid1); - - // saved configs - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(quotedSsid); - openNetwork.getNetworkSelectionStatus().setHasEverConnected(true); - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - wepNetwork.getNetworkSelectionStatus().setHasEverConnected(true); - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(Arrays.asList(openNetwork, wepNetwork)); - - // scan results from most recent scan - ScanResult savedScanResult = createOpenScanResult(ssid1, 2412 /* frequency */); - ScanResult unsavedScanResult = createOpenScanResult(ssid2, 2412 /* frequency */); - - when(mWifiScanner.getSingleScanResults()) - .thenReturn(Arrays.asList(savedScanResult, unsavedScanResult)); - - // intersection of most recent scan + saved configs - Set<ScanResultMatchInfo> expectedMatchInfos = - Collections.singleton(ScanResultMatchInfo.fromScanResult(savedScanResult)); - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - verify(mWakeupLock).setLock(eq(expectedMatchInfos)); - verify(mWifiWakeMetrics).recordStartEvent(expectedMatchInfos.size()); - } - - /** - * Verify that the wakeup lock is initialized with the intersection of ScanResults and network - * suggestions. - */ - @Test - public void startInitializesWakeupLockWithNetworkSuggestions() { - String ssid1 = "ssid 1"; - String ssid2 = "ssid 2"; - String quotedSsid = ScanResultUtil.createQuotedSSID(ssid1); - - // suggestions - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(quotedSsid); - WifiNetworkSuggestion openNetworkSuggestion = - new WifiNetworkSuggestion(openNetwork, null, false, false, true, true); - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - WifiNetworkSuggestion wepNetworkSuggestion = - new WifiNetworkSuggestion(wepNetwork, null, false, false, true, true); - when(mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()) - .thenReturn(new HashSet<>(Arrays.asList( - openNetworkSuggestion, wepNetworkSuggestion))); - - // scan results from most recent scan - ScanResult savedScanResult = createOpenScanResult(ssid1, 2412 /* frequency */); - ScanResult unsavedScanResult = createOpenScanResult(ssid2, 2412 /* frequency */); - - when(mWifiScanner.getSingleScanResults()) - .thenReturn(Arrays.asList(savedScanResult, unsavedScanResult)); - - // intersection of most recent scan + saved configs - Set<ScanResultMatchInfo> expectedMatchInfos = - Collections.singleton(ScanResultMatchInfo.fromScanResult(savedScanResult)); - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - verify(mWakeupLock).setLock(eq(expectedMatchInfos)); - verify(mWifiWakeMetrics).recordStartEvent(expectedMatchInfos.size()); - } - - /** - * Verify that the wakeup lock is initialized with the intersection of ScanResults and saved - * networks/network suggestions. - */ - @Test - public void startInitializesWakeupLockWithSavedScanResultsAndNetworkSuggestions() { - String ssid1 = "ssid 1"; - String ssid2 = "ssid 2"; - String ssid3 = "ssid 3"; - String quotedSsid1 = ScanResultUtil.createQuotedSSID(ssid1); - String quotedSsid2 = ScanResultUtil.createQuotedSSID(ssid2); - - // saved config + suggestion - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(quotedSsid1); - openNetwork.getNetworkSelectionStatus().setHasEverConnected(true); - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(Arrays.asList(openNetwork)); - - WifiConfiguration oweNetwork = WifiConfigurationTestUtil.createOweNetwork(quotedSsid2); - WifiNetworkSuggestion oweNetworkSuggestion = - new WifiNetworkSuggestion(oweNetwork, null, false, false, true, true); - when(mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()) - .thenReturn(new HashSet<>(Arrays.asList(oweNetworkSuggestion))); - - // scan results from most recent scan - ScanResult savedScanResult = createOpenScanResult(ssid1, 2412 /* frequency */); - ScanResult suggestionScanResult = createOweScanResult(ssid2, 2412 /* frequency */); - ScanResult unknownScanResult = createOpenScanResult(ssid3, 2412 /* frequency */); - - when(mWifiScanner.getSingleScanResults()) - .thenReturn(Arrays.asList(savedScanResult, suggestionScanResult, - unknownScanResult)); - - // intersection of most recent scan + saved configs/suggestions - Set<ScanResultMatchInfo> expectedMatchInfos = new HashSet<ScanResultMatchInfo>() {{ - add(ScanResultMatchInfo.fromScanResult(savedScanResult)); - add(ScanResultMatchInfo.fromScanResult(suggestionScanResult)); - }}; - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - verify(mWakeupLock).setLock(eq(expectedMatchInfos)); - verify(mWifiWakeMetrics).recordStartEvent(expectedMatchInfos.size()); - } - - /** - * Verify that start filters out DFS channels. - */ - @Test - public void startFiltersOutDfsScanResults() { - String ssidDfs = "DFS scan"; - String ssid24 = "2.4 scan"; - - // saved configs - WifiConfiguration openNetworkDfs = WifiConfigurationTestUtil - .createOpenNetwork(ScanResultUtil.createQuotedSSID(ssidDfs)); - openNetworkDfs.getNetworkSelectionStatus().setHasEverConnected(true); - WifiConfiguration openNetwork24 = WifiConfigurationTestUtil - .createOpenNetwork(ScanResultUtil.createQuotedSSID(ssid24)); - openNetwork24.getNetworkSelectionStatus().setHasEverConnected(true); - - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(Arrays.asList(openNetworkDfs, openNetwork24)); - - // scan results from most recent scan - ScanResult scanResultDfs = createOpenScanResult(ssidDfs, DFS_CHANNEL_FREQ); - ScanResult scanResult24 = createOpenScanResult(ssid24, 2412 /* frequency */); - - when(mWifiScanner.getSingleScanResults()) - .thenReturn(Arrays.asList(scanResultDfs, scanResult24)); - - // should filter out scanResultDfs - Set<ScanResultMatchInfo> expectedMatchInfos = - Collections.singleton(ScanResultMatchInfo.fromScanResult(scanResult24)); - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - verify(mWakeupLock).setLock(eq(expectedMatchInfos)); - verify(mWifiWakeMetrics).recordStartEvent(expectedMatchInfos.size()); - } - - /** - * Verify that onResults updates the WakeupLock. - */ - @Test - public void onResultsUpdatesWakeupLockForSavedNetworks() { - // saved config - WifiConfiguration openNetwork = WifiConfigurationTestUtil - .createOpenNetwork(ScanResultUtil.createQuotedSSID(SAVED_SSID)); - openNetwork.getNetworkSelectionStatus().setHasEverConnected(true); - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(Collections.singletonList(openNetwork)); - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - - ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - - verify(mWifiScanner).registerScanListener(any(), scanListenerArgumentCaptor.capture()); - WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue(); - - // incoming scan results - scanListener.onResults(mTestScanDatas); - - ScanResultMatchInfo expectedMatchInfo = ScanResultMatchInfo.fromScanResult(mTestScanResult); - verify(mWakeupLock).update(eq(Collections.singleton(expectedMatchInfo))); - } - - /** - * Verify that onResults updates the WakeupLock. - */ - @Test - public void onResultsUpdatesWakeupLockForNetworkSuggestions() { - // suggestions - WifiConfiguration openNetwork = WifiConfigurationTestUtil - .createOpenNetwork(ScanResultUtil.createQuotedSSID(SAVED_SSID)); - WifiNetworkSuggestion openNetworkSuggestion = - new WifiNetworkSuggestion(openNetwork, null, false, false, true, true); - when(mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()) - .thenReturn(new HashSet<>(Collections.singletonList(openNetworkSuggestion))); - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - - ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - - verify(mWifiScanner).registerScanListener(any(), scanListenerArgumentCaptor.capture()); - WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue(); - - // incoming scan results - scanListener.onResults(mTestScanDatas); - - ScanResultMatchInfo expectedMatchInfo = ScanResultMatchInfo.fromScanResult(mTestScanResult); - verify(mWakeupLock).update(eq(Collections.singleton(expectedMatchInfo))); - } - - /** - * Verify that onResults filters out unsaved networks when updating the WakeupLock. - */ - @Test - public void onResultsUpdatesWakeupLockWithOnlySavedNetworks() { - // no matching saved configs - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - - ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - - verify(mWifiScanner).registerScanListener(any(), scanListenerArgumentCaptor.capture()); - WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue(); - - // incoming scan results - scanListener.onResults(mTestScanDatas); - - verify(mWakeupLock).update(eq(Collections.emptySet())); - } - - /** - * Verify that onResults filters out DFS channels. - */ - @Test - public void onResultsFiltersOutDfsScanResults() { - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - - ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - - verify(mWifiScanner).registerScanListener(any(), scanListenerArgumentCaptor.capture()); - WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue(); - - // incoming scan results - mTestScanResult.frequency = DFS_CHANNEL_FREQ; - scanListener.onResults(mTestScanDatas); - - verify(mWakeupLock).update(eq(Collections.emptySet())); - } - - /** - * Verify that the controller searches for viable networks during onResults when WakeupLock is - * unlocked. - */ - @Test - public void onResultsSearchesForViableNetworkWhenWakeupLockIsUnlocked() { - // unlock wakeup lock - when(mWakeupLock.isUnlocked()).thenReturn(true); - // do not find viable network - when(mWakeupEvaluator.findViableNetwork(any(), any())).thenReturn(null); - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - - ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - - verify(mWifiScanner).registerScanListener(any(), scanListenerArgumentCaptor.capture()); - WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue(); - - // incoming scan results - scanListener.onResults(mTestScanDatas); - - verify(mWakeupEvaluator).findViableNetwork(any(), any()); - verifyDoesNotEnableWifi(); - } - - /** - * Verify that the controller updates the WakeupLock even if the user is not onboarded. - */ - @Test - public void onResultsUpdatesIfNotOnboarded() { - initializeWakeupController(true /* enabled */); - when(mWakeupOnboarding.isOnboarded()).thenReturn(false); - when(mWakeupLock.isUnlocked()).thenReturn(false); - mWakeupController.start(); - - ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - - verify(mWifiScanner).registerScanListener(any(), scanListenerArgumentCaptor.capture()); - WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue(); - - // incoming scan results - scanListener.onResults(mTestScanDatas); - - verify(mWakeupLock).update(any()); - verify(mWakeupLock).isUnlocked(); - verifyDoesNotEnableWifi(); - } - - /** - * Verify that the controller enables wifi and notifies user when all criteria are met. - */ - @Test - public void onResultsEnablesWifi() { - // unlock wakeup lock - when(mWakeupLock.isUnlocked()).thenReturn(true); - // find viable network - when(mWakeupEvaluator.findViableNetwork(any(), any())).thenReturn(mTestScanResult); - - initializeWakeupController(true /* enabled */); - mWakeupController.start(); - - ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - - verify(mWifiScanner).registerScanListener(any(), scanListenerArgumentCaptor.capture()); - WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue(); - - // incoming scan results - scanListener.onResults(mTestScanDatas); - - verify(mWakeupEvaluator).findViableNetwork(any(), any()); - verify(mWifiSettingsStore).handleWifiToggled(true /* wifiEnabled */); - verify(mWifiWakeMetrics).recordWakeupEvent(1 /* numScans */); - } - - /** - * Verify that the controller will not do any work if the user store has not been read. - */ - @Test - public void controllerDoesNoWorkIfUserStoreIsNotRead() { - initializeWakeupController(true /* enabled */, false /* isRead */); - mWakeupController.start(); - - ArgumentCaptor<WifiScanner.ScanListener> scanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - - verify(mWifiScanner).registerScanListener(any(), scanListenerArgumentCaptor.capture()); - WifiScanner.ScanListener scanListener = scanListenerArgumentCaptor.getValue(); - - // incoming scan results - scanListener.onResults(mTestScanDatas); - - verify(mWakeupLock, never()).setLock(any()); - verify(mWakeupLock, never()).update(any()); - verify(mWakeupLock, never()).isUnlocked(); - verify(mWakeupOnboarding, never()).maybeShowNotification(); - verify(mWakeupEvaluator, never()).findViableNetwork(any(), any()); - } - - @Test - public void userIsNotOnboardedByInitialization() { - initializeWakeupController(true /* enabled */); - verify(mWakeupOnboarding, never()).setOnboarded(); - } - - @Test - public void userIsOnboardedBySettingChange() { - initializeWakeupController(true /* enabled */); - ArgumentCaptor<ContentObserver> argumentCaptor = - ArgumentCaptor.forClass(ContentObserver.class); - verify(mFrameworkFacade).registerContentObserver(any(), any(), eq(true), - argumentCaptor.capture()); - ContentObserver contentObserver = argumentCaptor.getValue(); - contentObserver.onChange(false /* selfChange */); - verify(mWakeupOnboarding).setOnboarded(); - } - - /** - * When Wifi disconnects from a network, and within LAST_DISCONNECT_TIMEOUT_MILLIS Wifi is - * disabled, then the last connected Wifi network should be added to the wakeup lock. - * - * This simulates when a Wifi network sporadically connects and disconnects. During the - * disconnected phase, the user forcibly disables Wifi to stop this intermittent behavior. Then, - * we should add the network to the wake lock to ensure Wifi Wake does not automatically - * reconnect to this network. - * - * Also verifies that after the above flow, when Wifi is re-enabled, then disabled again, the - * last connected network should be reset and no networks should be added to the wakeup lock. - */ - @Test - public void lastConnectedNetworkAddedToLock() { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L, - (long) (0.8 * WakeupController.LAST_DISCONNECT_TIMEOUT_MILLIS)); - ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(mTestScanResult); - when(mWifiScanner.getSingleScanResults()).thenReturn(Collections.emptyList()); - initializeWakeupController(true); - - mWakeupController.setLastDisconnectInfo(matchInfo); - mWakeupController.start(); - - verify(mWakeupLock).setLock(eq(Collections.singleton(matchInfo))); - - mWakeupController.stop(); - mWakeupController.reset(); - mWakeupController.start(); - - verify(mWakeupLock).setLock(eq(Collections.emptySet())); - } - - /** - * When Wifi disconnects from a network, and Wifi is disabled after more than - * LAST_DISCONNECT_TIMEOUT_MILLIS, the last connected Wifi network should not be added to the - * wakeup lock. - */ - @Test - public void expiredLastConnectedNetworkNotAddedToLock() { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L, - (long) (1.2 * WakeupController.LAST_DISCONNECT_TIMEOUT_MILLIS)); - ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(mTestScanResult); - when(mWifiScanner.getSingleScanResults()).thenReturn(Collections.emptyList()); - initializeWakeupController(true); - - mWakeupController.setLastDisconnectInfo(matchInfo); - mWakeupController.start(); - - verify(mWakeupLock).setLock(eq(Collections.emptySet())); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java deleted file mode 100644 index bc28ce193..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -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 android.net.wifi.ScanResult; -import android.util.ArraySet; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.ScanResultUtil; - -import com.google.android.collect.Sets; - -import org.junit.Before; -import org.junit.Test; - -import java.util.Collections; -import java.util.Set; - -/** - * Unit tests for {@link WakeupEvaluator}. - */ -@SmallTest -public class WakeupEvaluatorTest extends WifiBaseTest { - - private static final String SAVED_SSID_1 = "saved ssid 1"; - private static final String SAVED_SSID_2 = "saved ssid 2"; - private static final String UNSAVED_SSID = "unsaved ssid"; - - private static final int FREQ_24 = 2412; - private static final int FREQ_5 = 5200; - - private static final int THRESHOLD_24 = -100; - private static final int THRESHOLD_5 = -90; - private final ScoringParams mScoringParams = new ScoringParams(); - - private WakeupEvaluator mWakeupEvaluator; - - private ScanResult makeScanResult(String ssid, int frequency, int level) { - ScanResult scanResult = new ScanResult(); - scanResult.SSID = ssid; - scanResult.frequency = frequency; - scanResult.level = level; - scanResult.capabilities = "[]"; - - return scanResult; - } - - private Set<ScanResultMatchInfo> getSavedNetworks() { - Set<ScanResultMatchInfo> networks = new ArraySet<>(); - networks.add(ScanResultMatchInfo.fromWifiConfiguration( - WifiConfigurationTestUtil.createOpenNetwork( - ScanResultUtil.createQuotedSSID(SAVED_SSID_1)))); - networks.add(ScanResultMatchInfo.fromWifiConfiguration( - WifiConfigurationTestUtil.createOpenNetwork( - ScanResultUtil.createQuotedSSID(SAVED_SSID_2)))); - return networks; - } - - @Before - public void setUp() { - String params = "rssi2=-120:" + THRESHOLD_24 + ":-2:-1" + "," - + "rssi5=-120:" + THRESHOLD_5 + ":-2:-1"; - assertTrue(params, mScoringParams.update(params)); - mWakeupEvaluator = new WakeupEvaluator(mScoringParams); - } - - /** - * Verify that isBelowThreshold returns true for networks below the filter threshold. - */ - @Test - public void isBelowThreshold_returnsTrueWhenRssiIsBelowThreshold() { - ScanResult scanResult24 = makeScanResult(SAVED_SSID_1, FREQ_24, THRESHOLD_24 - 1); - assertTrue(mWakeupEvaluator.isBelowThreshold(scanResult24)); - - ScanResult scanResult5 = makeScanResult(SAVED_SSID_1, FREQ_5, THRESHOLD_5 - 1); - assertTrue(mWakeupEvaluator.isBelowThreshold(scanResult5)); - } - - /** - * Verify that isBelowThreshold returns false for networks above the filter threshold. - */ - @Test - public void isBelowThreshold_returnsFalseWhenRssiIsAboveThreshold() { - ScanResult scanResult24 = makeScanResult(SAVED_SSID_1, FREQ_24, THRESHOLD_24 + 1); - assertFalse(mWakeupEvaluator.isBelowThreshold(scanResult24)); - - ScanResult scanResult5 = makeScanResult(SAVED_SSID_1, FREQ_5, THRESHOLD_5 + 1); - assertFalse(mWakeupEvaluator.isBelowThreshold(scanResult5)); - } - - /** - * Verify that findViableNetwork does not select ScanResult that is not present in the - * WifiConfigurations. - */ - @Test - public void findViableNetwork_returnsNullWhenScanResultIsNotInSavedNetworks() { - Set<ScanResult> scanResults = Collections.singleton( - makeScanResult(UNSAVED_SSID, FREQ_24, THRESHOLD_24 + 1)); - - ScanResult scanResult = mWakeupEvaluator.findViableNetwork(scanResults, getSavedNetworks()); - - assertNull(scanResult); - } - - /** - * Verify that findViableNetwork does not select a scan result that is below the threshold. - */ - @Test - public void findViableNetwork_returnsNullWhenScanResultIsBelowThreshold() { - Set<ScanResult> scanResults = Collections.singleton( - makeScanResult(SAVED_SSID_1, FREQ_24, THRESHOLD_24 - 1)); - - ScanResult scanResult = mWakeupEvaluator.findViableNetwork(scanResults, getSavedNetworks()); - assertNull(scanResult); - } - - /** - * Verify that findViableNetwork returns a viable ScanResult. - */ - @Test - public void findViableNetwork_returnsConnectableScanResult() { - ScanResult savedScanResult = makeScanResult(SAVED_SSID_1, FREQ_24, THRESHOLD_24 + 1); - Set<ScanResult> scanResults = Collections.singleton(savedScanResult); - - ScanResult scanResult = mWakeupEvaluator.findViableNetwork(scanResults, getSavedNetworks()); - assertEquals(savedScanResult, scanResult); - } - - /** - * Verify that findViableNetwork returns the viable ScanResult with the highest RSSI. - */ - @Test - public void findViableNetwork_returnsConnectableScanResultWithHighestRssi() { - ScanResult savedScanResultLow = makeScanResult(SAVED_SSID_1, FREQ_24, THRESHOLD_24 + 1); - ScanResult savedScanResultHigh = makeScanResult(SAVED_SSID_1, FREQ_24, THRESHOLD_24 + 10); - Set<ScanResult> scanResults = Sets.newArraySet(savedScanResultLow, savedScanResultHigh); - - ScanResult scanResult = mWakeupEvaluator.findViableNetwork(scanResults, getSavedNetworks()); - assertEquals(savedScanResultHigh, scanResult); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java deleted file mode 100644 index 7c53f4985..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WakeupLockTest.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -import android.net.wifi.WifiConfiguration; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Unit tests for {@link WakeupLock}. - */ -@SmallTest -public class WakeupLockTest extends WifiBaseTest { - - private static final String SSID_1 = "ssid1"; - private static final String SSID_2 = "ssid2"; - - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private WifiWakeMetrics mWifiWakeMetrics; - @Mock private Clock mClock; - - private ScanResultMatchInfo mNetwork1; - private ScanResultMatchInfo mNetwork2; - private WakeupLock mWakeupLock; - - /** - * Initialize objects before each test run. - */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - - mNetwork1 = new ScanResultMatchInfo(); - mNetwork1.networkSsid = SSID_1; - mNetwork1.networkType = WifiConfiguration.SECURITY_TYPE_OPEN; - - mNetwork2 = new ScanResultMatchInfo(); - mNetwork2.networkSsid = SSID_2; - mNetwork2.networkType = WifiConfiguration.SECURITY_TYPE_EAP; - - mWakeupLock = new WakeupLock(mWifiConfigManager, mWifiWakeMetrics, mClock); - } - - /** - * Updates the lock enough times to evict any networks not passed in. - * - * <p>It calls update {@link WakeupLock#CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT} times with - * the given network list. It asserts that the lock isn't empty prior to each call to update. - */ - private void updateEnoughTimesToEvictWithAsserts(Collection<ScanResultMatchInfo> networks) { - for (int i = 0; i < WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT; i++) { - assertFalse("Lock empty after " + i + " scans", mWakeupLock.isUnlocked()); - mWakeupLock.update(networks); - } - } - - /** - * Updates the lock enough times to evict any networks not passed in. - * - * <p>It calls update {@link WakeupLock#CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT} times with - * the given network list. It does not make any assertions about the state of the lock. - */ - private void updateEnoughTimesToEvictWithoutAsserts(Collection<ScanResultMatchInfo> networks) { - for (int i = 0; i < WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT; i++) { - mWakeupLock.update(networks); - } - } - - /** - * Verify that calling update {@link WakeupLock#CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT} - * times sets the lock to be initialized. - */ - @Test - public void verifyInitializingLockByScans() { - List<ScanResultMatchInfo> networks = Collections.singletonList(mNetwork1); - mWakeupLock.setLock(networks); - assertFalse(mWakeupLock.isInitialized()); - - for (int i = 0; i < WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT - 1; i++) { - mWakeupLock.update(networks); - assertFalse(mWakeupLock.isInitialized()); - } - mWakeupLock.update(networks); - assertTrue(mWakeupLock.isInitialized()); - } - - /** - * Verify that calling update after {@link WakeupLock#MAX_LOCK_TIME_MILLIS} milliseconds sets - * the lock to be initialized and does not add the scans to the lock. - */ - @Test - public void verifyInitializingLockByTimeout() { - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(0L, WakeupLock.MAX_LOCK_TIME_MILLIS + 1); - mWakeupLock.setLock(Collections.emptyList()); - assertFalse(mWakeupLock.isInitialized()); - - List<ScanResultMatchInfo> networks = Collections.singletonList(mNetwork1); - mWakeupLock.update(networks); - assertTrue(mWakeupLock.isInitialized()); - assertTrue(mWakeupLock.isUnlocked()); - } - - /** - * Verify that addToLock saves to the store if it changes the contents of the lock. - */ - @Test - public void addToLockSavesToStore() { - mWakeupLock.setLock(Collections.emptyList()); - - List<ScanResultMatchInfo> networks = Collections.singletonList(mNetwork1); - mWakeupLock.update(networks); - - // want 2 invocations, once for setLock(), once for addToLock - verify(mWifiConfigManager, times(2)).saveToStore(false); - } - - /** - * Verify that the WakeupLock is not empty immediately after being initialized with networks. - */ - @Test - public void verifyNotEmptyWhenSetWithNetworkList() { - setLockAndInitializeByTimeout(Arrays.asList(mNetwork1, mNetwork2)); - assertFalse(mWakeupLock.isUnlocked()); - } - - /** - * Verify that the WakeupLock is unlocked when initialized with an empty list. - */ - @Test - public void isEmptyWhenInitializedWithEmptyList() { - setLockAndInitializeByTimeout(Collections.emptyList()); - assertTrue(mWakeupLock.isUnlocked()); - } - - /** - * Verify that setting the lock clears out previous entries. - */ - @Test - public void setLockClearsPreviousNetworks() { - setLockAndInitializeByTimeout(Collections.singletonList(mNetwork1)); - assertFalse(mWakeupLock.isUnlocked()); - - setLockAndInitializeByTimeout(Collections.emptyList()); - assertTrue(mWakeupLock.isUnlocked()); - } - - /** - * Updating the lock should evict scan results that haven't been seen in - * {@link WakeupLock#CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT} scans. - */ - @Test - public void updateShouldRemoveNetworksAfterConsecutiveMissedScans() { - setLockAndInitializeByTimeout(Collections.singletonList(mNetwork1)); - - updateEnoughTimesToEvictWithAsserts(Collections.singletonList(mNetwork2)); - - assertTrue(mWakeupLock.isUnlocked()); - } - - /** - * Ensure that missed scans must be consecutive in order to evict networks from lock. - */ - @Test - public void updateWithLockedNetworkShouldResetRequiredNumberOfScans() { - List<ScanResultMatchInfo> lockedNetworks = Collections.singletonList(mNetwork1); - List<ScanResultMatchInfo> updateNetworks = Collections.singletonList(mNetwork2); - - setLockAndInitializeByTimeout(lockedNetworks); - - // one update without network - mWakeupLock.update(updateNetworks); - // one update with network - mWakeupLock.update(lockedNetworks); - - updateEnoughTimesToEvictWithAsserts(updateNetworks); - - assertTrue(mWakeupLock.isUnlocked()); - } - - /** - * Once a network is removed from the lock, it should not be reset even if it's seen again. - */ - @Test - public void updateWithLockedNetworkAfterItIsRemovedDoesNotReset() { - List<ScanResultMatchInfo> lockedNetworks = Collections.singletonList(mNetwork1); - setLockAndInitializeByTimeout(lockedNetworks); - - updateEnoughTimesToEvictWithAsserts(Collections.emptyList()); - - assertTrue(mWakeupLock.isUnlocked()); - mWakeupLock.update(lockedNetworks); - assertTrue(mWakeupLock.isUnlocked()); - } - - /** - * Verify that networks can be incrementally removed from the lock. Their counters should be - * independent. - */ - @Test - public void networksCanBeRemovedIncrementallyFromLock() { - List<ScanResultMatchInfo> lockedNetworks = Arrays.asList(mNetwork1, mNetwork2); - setLockAndInitializeByTimeout(lockedNetworks); - - updateEnoughTimesToEvictWithAsserts(Collections.singletonList(mNetwork1)); - assertFalse(mWakeupLock.isUnlocked()); - - updateEnoughTimesToEvictWithAsserts(Collections.singletonList(mNetwork2)); - assertTrue(mWakeupLock.isUnlocked()); - } - - /** - * Verify that initializing the lock persists the SSID list to the config store. - */ - @Test - public void initializeShouldSaveSsidsToStore() { - setLockAndInitializeByTimeout(Collections.singletonList(mNetwork1)); - verify(mWifiConfigManager).saveToStore(eq(false)); - } - - /** - * Verify that update saves to store if the lock changes. - */ - @Test - public void updateShouldOnlySaveIfLockChanges() { - setLockAndInitializeByTimeout(Collections.singletonList(mNetwork1)); - updateEnoughTimesToEvictWithoutAsserts(Collections.emptyList()); - - // need exactly 2 invocations: 1 for initialize, 1 for successful update - verify(mWifiConfigManager, times(2)).saveToStore(eq(false)); - } - - /** - * Verify that update does not save to store if the lock does not change. - */ - @Test - public void updateShouldNotSaveIfLockDoesNotChange() { - List<ScanResultMatchInfo> networks = Collections.singletonList(mNetwork1); - setLockAndInitializeByTimeout(networks); - verify(mWifiConfigManager, times(1)).saveToStore(anyBoolean()); - mWakeupLock.update(networks); - } - - /** - * Verify that on unlock, records the unlock event with WifiWakeMetrics with the correct number - * of scans. - */ - @Test - public void unlockingShouldRecordEventInMetrics() { - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(0L, WakeupLock.MAX_LOCK_TIME_MILLIS + 1); - List<ScanResultMatchInfo> networks = Collections.singletonList(mNetwork1); - mWakeupLock.setLock(networks); - for (int i = 0; i < WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT; i++) { - mWakeupLock.update(Collections.emptyList()); - } - verify(mWifiWakeMetrics).recordUnlockEvent( - WakeupLock.CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT /* numScans */); - } - - private void setLockAndInitializeByTimeout(Collection<ScanResultMatchInfo> networks) { - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(0L, WakeupLock.MAX_LOCK_TIME_MILLIS + 1); - mWakeupLock.setLock(networks); - mWakeupLock.update(networks); - assertTrue(mWakeupLock.isInitialized()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupOnboardingTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupOnboardingTest.java deleted file mode 100644 index 7d9cec22b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WakeupOnboardingTest.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static com.android.server.wifi.WakeupNotificationFactory.ACTION_DISMISS_NOTIFICATION; -import static com.android.server.wifi.WakeupNotificationFactory.ACTION_OPEN_WIFI_PREFERENCES; -import static com.android.server.wifi.WakeupNotificationFactory.ACTION_TURN_OFF_WIFI_WAKE; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -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.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Handler; -import android.os.test.TestLooper; -import android.provider.Settings; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link com.android.server.wifi.WakeupOnboarding} */ -@SmallTest -public class WakeupOnboardingTest extends WifiBaseTest { - - @Mock private Context mContext; - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private FrameworkFacade mFrameworkFacade; - @Mock private WakeupNotificationFactory mWakeupNotificationFactory; - @Mock private NotificationManager mNotificationManager; - - private TestLooper mLooper; - private WakeupOnboarding mWakeupOnboarding; - - // convenience method for resetting onboarded status - private void setOnboardedStatus(boolean isOnboarded) { - mWakeupOnboarding.getIsOnboadedDataSource().setData(isOnboarded); - } - - private void setNotificationsShown(int numNotifications) { - mWakeupOnboarding.getNotificationsDataSource().setData(numNotifications); - } - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) - .thenReturn(mNotificationManager); - - mLooper = new TestLooper(); - mWakeupOnboarding = new WakeupOnboarding(mContext, mWifiConfigManager, - new Handler(mLooper.getLooper()), mFrameworkFacade, mWakeupNotificationFactory); - } - - /** - * Verify that the notification shows if the user isn't onboarded. - */ - @Test - public void showsNotificationIfNotOnboarded() { - setOnboardedStatus(false); - mWakeupOnboarding.maybeShowNotification(); - - verify(mNotificationManager).notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); - } - - /** - * Verify that the notification does not show if the user is onboarded. - */ - @Test - public void doesNotShowNotificationIfAlreadyOnboarded() { - setOnboardedStatus(true); - mWakeupOnboarding.maybeShowNotification(); - - verify(mNotificationManager, never()) - .notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); - } - - /** - * Verify that the notification does not relaunch if it's already showing. - */ - @Test - public void doesNotShowNotificationIfAlreadyShowing() { - setOnboardedStatus(false); - mWakeupOnboarding.maybeShowNotification(); - mWakeupOnboarding.maybeShowNotification(); - - InOrder inOrder = Mockito.inOrder(mNotificationManager); - inOrder.verify(mNotificationManager) - .notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); - inOrder.verifyNoMoreInteractions(); - } - - /** - * Verify that the user is onboarded when the notification is dismissed. - */ - @Test - public void dismissNotificationAction_setsOnboarded() { - setOnboardedStatus(false); - assertFalse(mWakeupOnboarding.isOnboarded()); - - mWakeupOnboarding.maybeShowNotification(); - ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(captor.capture(), any(IntentFilter.class), any(), - any(Handler.class)); - BroadcastReceiver broadcastReceiver = captor.getValue(); - - broadcastReceiver.onReceive(mContext, new Intent(ACTION_DISMISS_NOTIFICATION)); - - verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); - assertTrue(mWakeupOnboarding.isOnboarded()); - } - - /** - * Verify that the user is onboarded and Wifi Wake is turned off when the user selects the - * ACTION_TURN_OFF_WIFI_WAKE action. - */ - @Test - public void turnOffWifiWakeAction_setsOnboardedAndTurnsOffWifiWake() { - setOnboardedStatus(false); - assertFalse(mWakeupOnboarding.isOnboarded()); - - mWakeupOnboarding.maybeShowNotification(); - ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(captor.capture(), any(IntentFilter.class), any(), - any(Handler.class)); - BroadcastReceiver broadcastReceiver = captor.getValue(); - - broadcastReceiver.onReceive(mContext, new Intent(ACTION_TURN_OFF_WIFI_WAKE)); - - verify(mFrameworkFacade).setIntegerSetting(mContext, - Settings.Global.WIFI_WAKEUP_ENABLED, 0); - - verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); - assertTrue(mWakeupOnboarding.isOnboarded()); - } - - /** - * Verify that the user is onboarded and sent to WifiSettings when the user selects the - * ACTION_OPEN_WIFI_SETTINGS action. - */ - @Test - public void openWifiSettingsAction_setsOnboardedAndOpensWifiSettings() { - setOnboardedStatus(false); - assertFalse(mWakeupOnboarding.isOnboarded()); - - mWakeupOnboarding.maybeShowNotification(); - ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(captor.capture(), any(IntentFilter.class), any(), - any(Handler.class)); - BroadcastReceiver broadcastReceiver = captor.getValue(); - - broadcastReceiver.onReceive(mContext, new Intent(ACTION_OPEN_WIFI_PREFERENCES)); - - verify(mContext).startActivity(any()); - - verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); - assertTrue(mWakeupOnboarding.isOnboarded()); - } - - /** - * Verify that onStop() doesn't onboard the user. - */ - @Test - public void onStopDismissesNotificationWithoutOnboarding() { - setOnboardedStatus(false); - assertFalse(mWakeupOnboarding.isOnboarded()); - - mWakeupOnboarding.maybeShowNotification(); - mWakeupOnboarding.onStop(); - - verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); - assertFalse(mWakeupOnboarding.isOnboarded()); - } - - /** - * Verify that incrementing the notification count saves to store. - */ - @Test - public void setOnboardedSavesToStore() { - setOnboardedStatus(false); - mWakeupOnboarding.setOnboarded(); - verify(mWifiConfigManager).saveToStore(false /* forceWrite */); - assertTrue(mWakeupOnboarding.isOnboarded()); - } - - /** - * Verify that incrementing the notification count saves to store. - */ - @Test - public void incrementingNotificationCountSavesToStore() { - setOnboardedStatus(false); - setNotificationsShown(0); - mWakeupOnboarding.maybeShowNotification(); - verify(mWifiConfigManager).saveToStore(false /* forceWrite */); - } - - /** - * Verify that the notification does not show multiple times within 24 hours. - */ - @Test - public void doesNotShowMultipleNotificationsWithin24Hours() { - setOnboardedStatus(false); - setNotificationsShown(0); - - mWakeupOnboarding.maybeShowNotification(0 /* timestamp */); - mWakeupOnboarding.onStop(); - mWakeupOnboarding.maybeShowNotification(0 /* timestamp */); - - InOrder inOrder = Mockito.inOrder(mNotificationManager); - inOrder.verify(mNotificationManager) - .notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); - inOrder.verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); - inOrder.verifyNoMoreInteractions(); - } - - /** - * Verify that notification reappears after 24 hours if not onboarded. - */ - @Test - public void showsNotificationsOutsideOf24Hours() { - setOnboardedStatus(false); - setNotificationsShown(0); - - mWakeupOnboarding.maybeShowNotification(0 /* timestamp */); - assertFalse(mWakeupOnboarding.isOnboarded()); - - mWakeupOnboarding.onStop(); - mWakeupOnboarding.maybeShowNotification(WakeupOnboarding.REQUIRED_NOTIFICATION_DELAY + 1); - - verify(mNotificationManager, times(2)) - .notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); - } - - /** - * Verify that the user is onboarded after - * {@link WakeupOnboarding#NOTIFICATIONS_UNTIL_ONBOARDED} notifications are shown. - */ - @Test - public void onboardsUserAfterThreeNotifications() { - setOnboardedStatus(false); - setNotificationsShown(WakeupOnboarding.NOTIFICATIONS_UNTIL_ONBOARDED - 1); - - mWakeupOnboarding.maybeShowNotification(0 /* timestamp */); - assertTrue(mWakeupOnboarding.isOnboarded()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java deleted file mode 100644 index 90e01719f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA2_PSK; -import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -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.content.pm.ApplicationInfo; -import android.net.MacAddress; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApConfiguration.Builder; -import android.net.wifi.WifiInfo; -import android.os.Build; -import android.os.Handler; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Random; - -/** - * Unit tests for {@link com.android.server.wifi.WifiApConfigStore}. - */ -@SmallTest -public class WifiApConfigStoreTest extends WifiBaseTest { - - private static final String TAG = "WifiApConfigStoreTest"; - - private static final String TEST_DEFAULT_2G_CHANNEL_LIST = "1,2,3,4,5,6"; - private static final String TEST_DEFAULT_AP_SSID = "TestAP"; - private static final String TEST_DEFAULT_HOTSPOT_SSID = "TestShare"; - private static final int RAND_SSID_INT_MIN = 1000; - private static final int RAND_SSID_INT_MAX = 9999; - private static final String TEST_CHAR_SET_AS_STRING = "abcdefghijklmnopqrstuvwxyz0123456789"; - private static final String TEST_STRING_UTF8_WITH_30_BYTES = "智者務其實愚者爭虛名"; - private static final String TEST_STRING_UTF8_WITH_32_BYTES = "ΣωκράτηςΣωκράτης"; - private static final String TEST_STRING_UTF8_WITH_33_BYTES = "一片汪洋大海中的一條魚"; - private static final String TEST_STRING_UTF8_WITH_34_BYTES = "Ευπροσηγοροςγινου"; - private static final MacAddress TEST_RANDOMIZED_MAC = - MacAddress.fromString("d2:11:19:34:a5:20"); - - private final int mBand25G = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ; - - @Mock private Context mContext; - @Mock private WifiInjector mWifiInjector; - @Mock private WifiMetrics mWifiMetrics; - private TestLooper mLooper; - private Handler mHandler; - @Mock private BackupManagerProxy mBackupManagerProxy; - @Mock private WifiConfigStore mWifiConfigStore; - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private ActiveModeWarden mActiveModeWarden; - private Random mRandom; - private MockResources mResources; - @Mock private ApplicationInfo mMockApplInfo; - @Mock private MacAddressUtil mMacAddressUtil; - private SoftApStoreData.DataSource mDataStoreSource; - private ArrayList<Integer> mKnownGood2GChannelList; - - @Before - public void setUp() throws Exception { - mLooper = new TestLooper(); - mHandler = new Handler(mLooper.getLooper()); - MockitoAnnotations.initMocks(this); - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.P; - when(mContext.getApplicationInfo()).thenReturn(mMockApplInfo); - - /* Setup expectations for Resources to return some default settings. */ - mResources = new MockResources(); - mResources.setString(R.string.config_wifiSoftap2gChannelList, - TEST_DEFAULT_2G_CHANNEL_LIST); - mResources.setString(R.string.wifi_tether_configure_ssid_default, - TEST_DEFAULT_AP_SSID); - mResources.setString(R.string.wifi_localhotspot_configure_ssid_default, - TEST_DEFAULT_HOTSPOT_SSID); - /* Default to device that does not require ap band conversion */ - when(mActiveModeWarden.isStaApConcurrencySupported()) - .thenReturn(false); - when(mContext.getResources()).thenReturn(mResources); - - // build the known good 2G channel list: TEST_DEFAULT_2G_CHANNEL_LIST - mKnownGood2GChannelList = new ArrayList(Arrays.asList(1, 2, 3, 4, 5, 6)); - - mRandom = new Random(); - when(mWifiInjector.getMacAddressUtil()).thenReturn(mMacAddressUtil); - when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(TEST_RANDOMIZED_MAC); - } - - /** - * Helper method to create and verify actions for the ApConfigStore used in the following tests. - */ - private WifiApConfigStore createWifiApConfigStore() throws Exception { - WifiApConfigStore store = new WifiApConfigStore( - mContext, mWifiInjector, mHandler, mBackupManagerProxy, - mWifiConfigStore, mWifiConfigManager, mActiveModeWarden, mWifiMetrics); - verify(mWifiConfigStore).registerStoreData(any()); - ArgumentCaptor<SoftApStoreData.DataSource> dataStoreSourceArgumentCaptor = - ArgumentCaptor.forClass(SoftApStoreData.DataSource.class); - verify(mWifiInjector).makeSoftApStoreData(dataStoreSourceArgumentCaptor.capture()); - mDataStoreSource = dataStoreSourceArgumentCaptor.getValue(); - - return store; - } - - /** - * Generate a SoftApConfiguration based on the specified parameters. - */ - private SoftApConfiguration setupApConfig( - String ssid, String preSharedKey, int keyManagement, int band, int channel, - boolean hiddenSSID) { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid(ssid); - configBuilder.setPassphrase(preSharedKey, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - if (channel == 0) { - configBuilder.setBand(band); - } else { - configBuilder.setChannel(channel, band); - } - configBuilder.setHiddenSsid(hiddenSSID); - return configBuilder.build(); - } - - private void verifyApConfig(SoftApConfiguration config1, SoftApConfiguration config2) { - assertEquals(config1.getSsid(), config2.getSsid()); - assertEquals(config1.getPassphrase(), config2.getPassphrase()); - assertEquals(config1.getSecurityType(), config2.getSecurityType()); - assertEquals(config1.getBand(), config2.getBand()); - assertEquals(config1.getChannel(), config2.getChannel()); - assertEquals(config1.isHiddenSsid(), config2.isHiddenSsid()); - } - - private void verifyDefaultApConfig(SoftApConfiguration config, String expectedSsid, - boolean isSaeSupport) { - String[] splitSsid = config.getSsid().split("_"); - assertEquals(2, splitSsid.length); - assertEquals(expectedSsid, splitSsid[0]); - assertEquals(SoftApConfiguration.BAND_2GHZ, config.getBand()); - assertFalse(config.isHiddenSsid()); - int randomPortion = Integer.parseInt(splitSsid[1]); - assertTrue(randomPortion >= RAND_SSID_INT_MIN && randomPortion <= RAND_SSID_INT_MAX); - if (isSaeSupport) { - assertEquals(SECURITY_TYPE_WPA3_SAE_TRANSITION, config.getSecurityType()); - } else { - assertEquals(SECURITY_TYPE_WPA2_PSK, config.getSecurityType()); - } - assertEquals(15, config.getPassphrase().length()); - } - - private void verifyDefaultApConfig(SoftApConfiguration config, String expectedSsid) { - // Old test cases will just verify WPA2. - verifyDefaultApConfig(config, expectedSsid, false); - } - - private void verifyDefaultLocalOnlyApConfig(SoftApConfiguration config, String expectedSsid, - int expectedApBand, boolean isSaeSupport) { - String[] splitSsid = config.getSsid().split("_"); - assertEquals(2, splitSsid.length); - assertEquals(expectedSsid, splitSsid[0]); - assertEquals(expectedApBand, config.getBand()); - int randomPortion = Integer.parseInt(splitSsid[1]); - assertTrue(randomPortion >= RAND_SSID_INT_MIN && randomPortion <= RAND_SSID_INT_MAX); - if (isSaeSupport) { - assertEquals(SECURITY_TYPE_WPA3_SAE_TRANSITION, config.getSecurityType()); - } else { - assertEquals(SECURITY_TYPE_WPA2_PSK, config.getSecurityType()); - } - assertEquals(15, config.getPassphrase().length()); - assertFalse(config.isAutoShutdownEnabled()); - } - - private void verifyDefaultLocalOnlyApConfig(SoftApConfiguration config, String expectedSsid, - int expectedApBand) { - verifyDefaultLocalOnlyApConfig(config, expectedSsid, expectedApBand, false); - } - - /** - * AP Configuration is not specified in the config file, - * WifiApConfigStore should fallback to use the default configuration. - */ - @Test - public void initWithDefaultConfiguration() throws Exception { - WifiApConfigStore store = createWifiApConfigStore(); - verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); - verify(mWifiConfigManager).saveToStore(true); - } - - - /** - * Verify the handling of setting a null ap configuration. - * WifiApConfigStore should fallback to the default configuration when - * null ap configuration is provided. - */ - @Test - public void setNullApConfiguration() throws Exception { - /* Initialize WifiApConfigStore with existing configuration. */ - SoftApConfiguration expectedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - SoftApConfiguration.BAND_5GHZ, /* AP band (5GHz) */ - 40, /* AP channel */ - true /* Hidden SSID */); - WifiApConfigStore store = createWifiApConfigStore(); - mDataStoreSource.fromDeserialized(expectedConfig); - verifyApConfig(expectedConfig, store.getApConfiguration()); - - store.setApConfiguration(null); - verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); - verifyDefaultApConfig(mDataStoreSource.toSerialize(), TEST_DEFAULT_AP_SSID); - verify(mWifiConfigManager).saveToStore(true); - verify(mBackupManagerProxy).notifyDataChanged(); - } - - /** - * Verify AP configuration is correctly updated via setApConfiguration call. - */ - @Test - public void updateApConfiguration() throws Exception { - /* Initialize WifiApConfigStore with default configuration. */ - WifiApConfigStore store = createWifiApConfigStore(); - - verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); - verify(mWifiConfigManager).saveToStore(true); - - /* Update with a valid configuration. */ - SoftApConfiguration expectedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - SoftApConfiguration.BAND_2GHZ, /* AP band */ - 0, /* AP channel */ - true /* Hidden SSID */); - store.setApConfiguration(expectedConfig); - verifyApConfig(expectedConfig, store.getApConfiguration()); - verifyApConfig(expectedConfig, mDataStoreSource.toSerialize()); - verify(mWifiConfigManager, times(2)).saveToStore(true); - verify(mBackupManagerProxy, times(2)).notifyDataChanged(); - } - - /** - * Due to different countries capabilities, some bands are not available. - * This test verifies that a device will have apBand = - * 5GHz converted to include 2.4GHz. - */ - @Test - public void convertDevice5GhzToAny() throws Exception { - when(mActiveModeWarden.isStaApConcurrencySupported()) - .thenReturn(true); - - /* Initialize WifiApConfigStore with default configuration. */ - WifiApConfigStore store = createWifiApConfigStore(); - verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); - verify(mWifiConfigManager).saveToStore(true); - - /* Update with a valid configuration. */ - SoftApConfiguration providedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - SoftApConfiguration.BAND_5GHZ, /* AP band */ - 0, /* AP channel */ - false /* Hidden SSID */); - - SoftApConfiguration expectedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_5GHZ, /* AP band */ - 0, /* AP channel */ - false /* Hidden SSID */); - store.setApConfiguration(providedConfig); - verifyApConfig(expectedConfig, store.getApConfiguration()); - verifyApConfig(expectedConfig, mDataStoreSource.toSerialize()); - verify(mWifiConfigManager, times(2)).saveToStore(true); - verify(mBackupManagerProxy, times(2)).notifyDataChanged(); - } - - /** - * Due to different countries capabilities, some bands are not available. - * This test verifies that a device does not need to conver apBand since it already - * included 2.4G. - */ - @Test - public void deviceAnyNotConverted() throws Exception { - when(mActiveModeWarden.isStaApConcurrencySupported()) - .thenReturn(true); - - /* Initialize WifiApConfigStore with default configuration. */ - WifiApConfigStore store = createWifiApConfigStore(); - verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); - verify(mWifiConfigManager).saveToStore(true); - - /* Update with a valid configuration. */ - SoftApConfiguration expectedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - SoftApConfiguration.BAND_ANY, /* AP band */ - 0, /* AP channel */ - false /* Hidden SSID */); - store.setApConfiguration(expectedConfig); - verifyApConfig(expectedConfig, store.getApConfiguration()); - verifyApConfig(expectedConfig, mDataStoreSource.toSerialize()); - verify(mWifiConfigManager, times(2)).saveToStore(true); - verify(mBackupManagerProxy, times(2)).notifyDataChanged(); - } - - /** - * Due to different countries capabilities, some bands are not available. - * This test verifies that a device does not convert apBand because channel is specific. - */ - @Test - public void deviceWithChannelNotConverted() throws Exception { - when(mActiveModeWarden.isStaApConcurrencySupported()) - .thenReturn(true); - - /* Initialize WifiApConfigStore with default configuration. */ - WifiApConfigStore store = createWifiApConfigStore(); - verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); - verify(mWifiConfigManager).saveToStore(true); - - /* Update with a valid configuration. */ - SoftApConfiguration expectedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - SoftApConfiguration.BAND_5GHZ, /* AP band */ - 40, /* AP channel */ - false /* Hidden SSID */); - store.setApConfiguration(expectedConfig); - verifyApConfig(expectedConfig, store.getApConfiguration()); - verifyApConfig(expectedConfig, mDataStoreSource.toSerialize()); - verify(mWifiConfigManager, times(2)).saveToStore(true); - verify(mBackupManagerProxy, times(2)).notifyDataChanged(); - } - - /** - * Due to different countries capabilities, some bands are not available. - * This test verifies that a device converts a persisted ap - * config with 5GHz only set for the apBand to include 2.4GHz. - */ - @Test - public void device5GhzConvertedToAnyAtRetrieval() throws Exception { - when(mActiveModeWarden.isStaApConcurrencySupported()) - .thenReturn(true); - - SoftApConfiguration persistedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - SoftApConfiguration.BAND_5GHZ, /* AP band */ - 0, /* AP channel */ - false /* Hidden SSID */); - SoftApConfiguration expectedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - mBand25G, /* AP band */ - 0, /* AP channel */ - false /* Hidden SSID */); - - WifiApConfigStore store = createWifiApConfigStore(); - mDataStoreSource.fromDeserialized(persistedConfig); - verifyApConfig(expectedConfig, store.getApConfiguration()); - verifyApConfig(expectedConfig, mDataStoreSource.toSerialize()); - verify(mWifiConfigManager).saveToStore(true); - verify(mBackupManagerProxy).notifyDataChanged(); - } - - /** - * Due to different countries capabilities, some bands are not available. - * This test verifies that a device does not convert - * a persisted ap config with ANY since it already - * included 2.4G. - */ - @Test - public void deviceNotConvertedAtRetrieval() throws Exception { - when(mActiveModeWarden.isStaApConcurrencySupported()) - .thenReturn(true); - - SoftApConfiguration persistedConfig = setupApConfig( - "ConfiguredAP", /* SSID */ - "randomKey", /* preshared key */ - SECURITY_TYPE_WPA2_PSK, /* security type */ - SoftApConfiguration.BAND_ANY, /* AP band */ - 0, /* AP channel */ - false /* Hidden SSID */); - - WifiApConfigStore store = createWifiApConfigStore(); - mDataStoreSource.fromDeserialized(persistedConfig); - verifyApConfig(persistedConfig, store.getApConfiguration()); - verify(mWifiConfigManager, never()).saveToStore(true); - verify(mBackupManagerProxy, never()).notifyDataChanged(); - } - - /** - * Verify a proper SoftApConfiguration is generate by getDefaultApConfiguration(). - */ - @Test - public void getDefaultApConfigurationIsValid() throws Exception { - WifiApConfigStore store = createWifiApConfigStore(); - SoftApConfiguration config = store.getApConfiguration(); - assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true)); - } - - /** - * Verify a proper local only hotspot config is generated when called properly with the valid - * context. - */ - @Test - public void generateLocalOnlyHotspotConfigIsValid() { - SoftApConfiguration config = WifiApConfigStore - .generateLocalOnlyHotspotConfig(mContext, SoftApConfiguration.BAND_2GHZ, null); - verifyDefaultLocalOnlyApConfig(config, TEST_DEFAULT_HOTSPOT_SSID, - SoftApConfiguration.BAND_2GHZ); - - // verify that the config passes the validateApWifiConfiguration check - assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true)); - } - - /** - * Verify a proper local only hotspot config is generated for 5Ghz band. - */ - @Test - public void generateLocalOnlyHotspotConfigIsValid5G() { - SoftApConfiguration config = WifiApConfigStore - .generateLocalOnlyHotspotConfig(mContext, SoftApConfiguration.BAND_5GHZ, null); - verifyDefaultLocalOnlyApConfig(config, TEST_DEFAULT_HOTSPOT_SSID, - SoftApConfiguration.BAND_5GHZ); - - // verify that the config passes the validateApWifiConfiguration check - assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true)); - } - - @Test - public void generateLohsConfig_forwardsCustomMac() { - SoftApConfiguration customConfig = new SoftApConfiguration.Builder() - .setBssid(MacAddress.fromString("11:22:33:44:55:66")) - .build(); - SoftApConfiguration softApConfig = WifiApConfigStore.generateLocalOnlyHotspotConfig( - mContext, SoftApConfiguration.BAND_2GHZ, customConfig); - assertThat(softApConfig.getBssid().toString()).isNotEmpty(); - assertThat(softApConfig.getBssid()).isEqualTo( - MacAddress.fromString("11:22:33:44:55:66")); - } - - @Test - public void randomizeBssid_randomizesWhenEnabled() throws Exception { - mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, true); - SoftApConfiguration baseConfig = new SoftApConfiguration.Builder().build(); - - WifiApConfigStore store = createWifiApConfigStore(); - SoftApConfiguration config = store.randomizeBssidIfUnset(mContext, baseConfig); - - assertEquals(TEST_RANDOMIZED_MAC, config.getBssid()); - } - - @Test - public void randomizeBssid_fallbackPathWhenMacCalculationFails() throws Exception { - mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, true); - // Setup the MAC calculation to fail. - when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(null); - SoftApConfiguration baseConfig = new SoftApConfiguration.Builder().build(); - - WifiApConfigStore store = createWifiApConfigStore(); - SoftApConfiguration config = store.randomizeBssidIfUnset(mContext, baseConfig); - - // Verify that some randomized MAC address is still generated - assertNotNull(config.getBssid()); - assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, config.getBssid().toString()); - } - - @Test - public void randomizeBssid_usesFactoryMacWhenRandomizationOff() throws Exception { - mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, false); - SoftApConfiguration baseConfig = new SoftApConfiguration.Builder().build(); - - WifiApConfigStore store = createWifiApConfigStore(); - SoftApConfiguration config = store.randomizeBssidIfUnset(mContext, baseConfig); - - assertThat(config.getBssid()).isNull(); - } - - @Test - public void randomizeBssid_forwardsCustomMac() throws Exception { - mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, true); - Builder baseConfigBuilder = new SoftApConfiguration.Builder(); - baseConfigBuilder.setBssid(MacAddress.fromString("11:22:33:44:55:66")); - - WifiApConfigStore store = createWifiApConfigStore(); - SoftApConfiguration config = store.randomizeBssidIfUnset(mContext, - baseConfigBuilder.build()); - - assertThat(config.getBssid().toString()).isNotEmpty(); - assertThat(config.getBssid()).isEqualTo( - MacAddress.fromString("11:22:33:44:55:66")); - } - - /** - * Helper method to generate random SSIDs. - * - * Note: this method has limited use as a random SSID generator. The characters used in this - * method do no not cover all valid inputs. - * @param length number of characters to generate for the name - * @return String generated string of random characters - */ - private String generateRandomString(int length) { - - StringBuilder stringBuilder = new StringBuilder(length); - int index = -1; - while (stringBuilder.length() < length) { - index = mRandom.nextInt(TEST_CHAR_SET_AS_STRING.length()); - stringBuilder.append(TEST_CHAR_SET_AS_STRING.charAt(index)); - } - return stringBuilder.toString(); - } - - /** - * Verify the SSID checks in validateApWifiConfiguration. - * - * Cases to check and verify they trigger failed verification: - * null SoftApConfiguration.SSID - * empty SoftApConfiguration.SSID - * invalid WifiConfiguaration.SSID length - * - * Additionally check a valid SSID with a random (within valid ranges) length. - */ - @Test - public void testSsidVerificationInValidateApWifiConfigurationCheck() { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid(null); - assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true)); - // check a string if it's larger than 32 bytes with UTF-8 encode - // Case 1 : one byte per character (use english words and Arabic numerals) - configBuilder.setSsid(generateRandomString(WifiApConfigStore.SSID_MAX_LEN + 1)); - assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true)); - // Case 2 : two bytes per character - configBuilder.setSsid(TEST_STRING_UTF8_WITH_34_BYTES); - assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true)); - // Case 3 : three bytes per character - configBuilder.setSsid(TEST_STRING_UTF8_WITH_33_BYTES); - assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true)); - - // now check a valid SSID within 32 bytes - // Case 1 : one byte per character with random length - int validLength = WifiApConfigStore.SSID_MAX_LEN - WifiApConfigStore.SSID_MIN_LEN; - configBuilder.setSsid(generateRandomString( - mRandom.nextInt(validLength) + WifiApConfigStore.SSID_MIN_LEN)); - assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true)); - // Case 2 : two bytes per character - configBuilder.setSsid(TEST_STRING_UTF8_WITH_32_BYTES); - assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true)); - // Case 3 : three bytes per character - configBuilder.setSsid(TEST_STRING_UTF8_WITH_30_BYTES); - assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true)); - } - - /** - * Verify the Open network checks in validateApWifiConfiguration. - * - * If the configured network is open, it should not have a password set. - * - * Additionally verify a valid open network passes verification. - */ - @Test - public void testOpenNetworkConfigInValidateApWifiConfigurationCheck() { - assertTrue(WifiApConfigStore.validateApWifiConfiguration( - new SoftApConfiguration.Builder() - .setSsid(TEST_DEFAULT_HOTSPOT_SSID) - .build(), true)); - } - - /** - * Verify the WPA2_PSK network checks in validateApWifiConfiguration. - * - * If the configured network is configured with a preSharedKey, verify that the passwork is set - * and it meets length requirements. - */ - @Test - public void testWpa2PskNetworkConfigInValidateApWifiConfigurationCheck() { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setSsid(TEST_DEFAULT_HOTSPOT_SSID); - // Builder will auto check auth type and passphrase - - // test random (valid length) - int maxLen = WifiApConfigStore.PSK_MAX_LEN; - int minLen = WifiApConfigStore.PSK_MIN_LEN; - configBuilder.setPassphrase( - generateRandomString(mRandom.nextInt(maxLen - minLen) + minLen), - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true)); - } - - /** - * Verify the default configuration security when SAE support. - */ - @Test - public void testDefaultConfigurationSecurityTypeIsWpa3SaeTransitionWhenSupport() - throws Exception { - mResources.setBoolean(R.bool.config_wifi_softap_sae_supported, true); - WifiApConfigStore store = createWifiApConfigStore(); - verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID, true); - } - - /** - * Verify the LOHS default configuration security when SAE support. - */ - @Test - public void testLohsDefaultConfigurationSecurityTypeIsWpa3SaeTransitionWhenSupport() { - mResources.setBoolean(R.bool.config_wifi_softap_sae_supported, true); - SoftApConfiguration config = WifiApConfigStore - .generateLocalOnlyHotspotConfig(mContext, SoftApConfiguration.BAND_5GHZ, null); - verifyDefaultLocalOnlyApConfig(config, TEST_DEFAULT_HOTSPOT_SSID, - SoftApConfiguration.BAND_5GHZ, true); - - // verify that the config passes the validateApWifiConfiguration check - assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true)); - - } - - @Test - public void testResetToDefaultForUnsupportedConfig() throws Exception { - mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, true); - mResources.setBoolean(R.bool.config_wifi_softap_sae_supported, true); - mResources.setBoolean(R.bool.config_wifi6ghzSupport, true); - mResources.setBoolean(R.bool.config_wifi5ghzSupport, true); - - // Test all of the features support and all of the reset config are false. - String testPassphrase = "secretsecret"; - SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setPassphrase(testPassphrase, SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); - WifiApConfigStore store = createWifiApConfigStore(); - SoftApConfiguration resetedConfig = store.resetToDefaultForUnsupportedConfig( - configBuilder.build()); - assertEquals(resetedConfig, configBuilder.build()); - - verify(mWifiMetrics).noteSoftApConfigReset(configBuilder.build(), resetedConfig); - - // Test SAE not support case. - mResources.setBoolean(R.bool.config_wifi_softap_sae_supported, false); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertEquals(resetedConfig.getSecurityType(), SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - // Test force channel - configBuilder.setChannel(149, SoftApConfiguration.BAND_5GHZ); - mResources.setBoolean( - R.bool.config_wifiSoftapResetChannelConfig, true); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertEquals(resetedConfig.getChannel(), 0); - assertEquals(resetedConfig.getBand(), - SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ); - - // Test forced channel band doesn't support. - mResources.setBoolean(R.bool.config_wifi5ghzSupport, false); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertEquals(resetedConfig.getChannel(), 0); - assertEquals(resetedConfig.getBand(), - SoftApConfiguration.BAND_2GHZ); - - // Test band not support with auto channel - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertEquals(resetedConfig.getBand(), SoftApConfiguration.BAND_2GHZ); - - // Test reset hidden network - mResources.setBoolean( - R.bool.config_wifiSoftapResetHiddenConfig, true); - configBuilder.setHiddenSsid(true); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertFalse(resetedConfig.isHiddenSsid()); - - // Test auto shutdown timer - mResources.setBoolean( - R.bool.config_wifiSoftapResetAutoShutdownTimerConfig, true); - configBuilder.setShutdownTimeoutMillis(8888); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertEquals(resetedConfig.getShutdownTimeoutMillis(), 0); - - // Test max client setting when force client disconnect doesn't support - mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, false); - configBuilder.setMaxNumberOfClients(10); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertEquals(resetedConfig.getMaxNumberOfClients(), 0); - - // Test client control setting when force client disconnect doesn't support - mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, false); - ArrayList<MacAddress> blockedClientList = new ArrayList<>(); - ArrayList<MacAddress> allowedClientList = new ArrayList<>(); - blockedClientList.add(MacAddress.fromString("11:22:33:44:55:66")); - allowedClientList.add(MacAddress.fromString("aa:bb:cc:dd:ee:ff")); - configBuilder.setBlockedClientList(blockedClientList); - configBuilder.setAllowedClientList(allowedClientList); - - configBuilder.setClientControlByUserEnabled(true); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertFalse(resetedConfig.isClientControlByUserEnabled()); - // The blocked list will be clean - assertEquals(resetedConfig.getBlockedClientList().size(), 0); - // The allowed list will be keep - assertEquals(resetedConfig.getAllowedClientList(), allowedClientList); - - // Test max client setting when reset enabled but force client disconnect supported - mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, true); - mResources.setBoolean( - R.bool.config_wifiSoftapResetMaxClientSettingConfig, true); - assertEquals(resetedConfig.getMaxNumberOfClients(), 0); - - // Test client control setting when reset enabled but force client disconnect supported - mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, true); - mResources.setBoolean( - R.bool.config_wifiSoftapResetUserControlConfig, true); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertFalse(resetedConfig.isClientControlByUserEnabled()); - assertEquals(resetedConfig.getBlockedClientList().size(), 0); - assertEquals(resetedConfig.getAllowedClientList(), allowedClientList); - - // Test blocked list setting will be reset even if client control disabled - mResources.setBoolean( - R.bool.config_wifiSoftapResetUserControlConfig, true); - configBuilder.setClientControlByUserEnabled(false); - resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build()); - assertFalse(resetedConfig.isClientControlByUserEnabled()); - assertEquals(resetedConfig.getBlockedClientList().size(), 0); - assertEquals(resetedConfig.getAllowedClientList(), allowedClientList); - } - - /** - * Verify Bssid field deny to set if caller without setting permission. - */ - @Test - public void testBssidDenyIfCallerWithoutPrivileged() throws Exception { - WifiApConfigStore store = createWifiApConfigStore(); - SoftApConfiguration config = new SoftApConfiguration.Builder(store.getApConfiguration()) - .setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")).build(); - assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, false)); - } - - /** - * Verify Bssid field only allow to set if caller own setting permission. - */ - @Test - public void testBssidAllowIfCallerOwnPrivileged() throws Exception { - WifiApConfigStore store = createWifiApConfigStore(); - SoftApConfiguration config = new SoftApConfiguration.Builder(store.getApConfiguration()) - .setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")).build(); - assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java deleted file mode 100644 index e640c4232..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java +++ /dev/null @@ -1,1197 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.net.IpConfiguration; -import android.net.wifi.WifiConfiguration; -import android.os.Process; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.WifiPermissionsUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -/** - * Unit tests for {@link com.android.server.wifi.WifiBackupRestore}. - */ -@SmallTest -public class WifiBackupRestoreTest extends WifiBaseTest { - - private static final String WIFI_BACKUP_DATA_WITH_UNSUPPORTED_TAG = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiBackupData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + "<NetworkList>\n" - + "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""NONE</string>\n" - + "<string name=\"SSID\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""</string>\n" - + "<null name=\"BSSID\" />\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"1\">03</byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"1\">0f</byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"1\">06</byte-array>\n" - + "<boolean name=\"Shared\" value=\"true\" />\n" - + "<null name=\"SimSlot\" />\n" - + "</WifiConfiguration>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n" - + "</NetworkList>\n" - + "</WifiBackupData>\n"; - - // |AllowedKeyMgmt|, |AllowedProtocols|, |AllowedAuthAlgorithms|, |AllowedGroupCiphers| and - // |AllowedPairwiseCiphers| fields have invalid values in them. - // NOTE: The byte values are encoded in little endian - private static final String WIFI_BACKUP_DATA_WITH_UNSUPPORTED_VALUES_IN_BITSETS = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiBackupData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + "<NetworkList>\n" - + "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""NONE</string>\n" - + "<string name=\"SSID\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""</string>\n" - + "<null name=\"BSSID\" />\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - // Valid Value: 01 - + "<byte-array name=\"AllowedKeyMgmt\" num=\"3\">010002</byte-array>\n" - // Valid Value: 03 - + "<byte-array name=\"AllowedProtocols\" num=\"1\">13</byte-array>\n" - // Valid Value: 01 - + "<byte-array name=\"AllowedAuthAlgos\" num=\"1\">11</byte-array>\n" - // Valid Value: 0f - + "<byte-array name=\"AllowedGroupCiphers\" num=\"1\">8f</byte-array>\n" - // Valid Value: 06 - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"1\">26</byte-array>\n" - + "<boolean name=\"Shared\" value=\"true\" />\n" - + "<null name=\"SimSlot\" />\n" - + "</WifiConfiguration>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n" - + "</NetworkList>\n" - + "</WifiBackupData>\n"; - - private static final String WIFI_BACKUP_DATA_V1_0 = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiBackupData>\n" - + "<float name=\"Version\" value=\"1.0\" />\n" - + "<NetworkList>\n" - + "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""NONE</string>\n" - + "<string name=\"SSID\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""</string>\n" - + "<null name=\"BSSID\" />\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"1\">03</byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"1\">0f</byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"1\">06</byte-array>\n" - + "<boolean name=\"Shared\" value=\"true\" />\n" - + "</WifiConfiguration>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n" - + "</NetworkList>\n" - + "</WifiBackupData>\n"; - - private static final String WIFI_BACKUP_DATA_V1_1 = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiBackupData>\n" - + "<float name=\"Version\" value=\"1.1\" />\n" - + "<NetworkList>\n" - + "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""NONE</string>\n" - + "<string name=\"SSID\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""</string>\n" - + "<null name=\"BSSID\" />\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"1\">03</byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"1\">0f</byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"1\">06</byte-array>\n" - + "<boolean name=\"Shared\" value=\"true\" />\n" - + "<int name=\"MeteredOverride\" value=\"1\" />\n" - + "</WifiConfiguration>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n" - + "</NetworkList>\n" - + "</WifiBackupData>\n"; - - private static final String WIFI_BACKUP_DATA_V1_2 = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiBackupData>\n" - + "<float name=\"Version\" value=\"1.2\" />\n" - + "<NetworkList>\n" - + "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""NONE</string>\n" - + "<string name=\"SSID\">"" + WifiConfigurationTestUtil.TEST_SSID - + ""</string>\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"1\">03</byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"1\">0f</byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"1\">06</byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"true\" />\n" - + "<boolean name=\"AutoJoinEnabled\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"1\" />\n" - + "</WifiConfiguration>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n" - + "</NetworkList>\n" - + "</WifiBackupData>\n"; - - @Mock WifiPermissionsUtil mWifiPermissionsUtil; - private WifiBackupRestore mWifiBackupRestore; - private boolean mCheckDump = true; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); - mWifiBackupRestore = new WifiBackupRestore(mWifiPermissionsUtil); - // Enable verbose logging before tests to check the backup data dumps. - mWifiBackupRestore.enableVerboseLogging(1); - } - - @After - public void cleanUp() throws Exception { - if (mCheckDump) { - StringWriter stringWriter = new StringWriter(); - mWifiBackupRestore.dump( - new FileDescriptor(), new PrintWriter(stringWriter), new String[0]); - String dumpString = stringWriter.toString(); - // Ensure that the SSID was dumped out. - assertTrue("Dump: " + dumpString, - dumpString.contains(WifiConfigurationTestUtil.TEST_SSID)); - // Ensure that the password wasn't dumped out. - assertFalse("Dump: " + dumpString, - dumpString.contains(WifiConfigurationTestUtil.TEST_PSK)); - assertFalse("Dump: " + dumpString, - dumpString.contains(WifiConfigurationTestUtil.TEST_WEP_KEYS[0])); - assertFalse("Dump: " + dumpString, - dumpString.contains(WifiConfigurationTestUtil.TEST_WEP_KEYS[1])); - assertFalse("Dump: " + dumpString, - dumpString.contains(WifiConfigurationTestUtil.TEST_WEP_KEYS[2])); - assertFalse("Dump: " + dumpString, - dumpString.contains(WifiConfigurationTestUtil.TEST_WEP_KEYS[3])); - } - } - - /** - * Verify that a null network list is serialized correctly. - */ - @Test - public void testNullNetworkListBackup() { - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(null); - assertTrue(backupData != null); - assertEquals(backupData.length, 0); - // No valid data to check in dump. - mCheckDump = false; - } - - /** - * Verify that a single open network configuration is serialized & deserialized correctly. - */ - @Test - public void testSingleOpenNetworkBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createOpenNetwork()); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single open hidden network configuration is serialized & deserialized - * correctly. - */ - @Test - public void testSingleOpenHiddenNetworkBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createOpenHiddenNetwork()); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single PSK network configuration is serialized & deserialized correctly. - */ - @Test - public void testSinglePskNetworkBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createPskNetwork()); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single PSK hidden network configuration is serialized & deserialized correctly. - */ - @Test - public void testSinglePskHiddenNetworkBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createPskHiddenNetwork()); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single WEP network configuration is serialized & deserialized correctly. - */ - @Test - public void testSingleWepNetworkBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createWepNetwork()); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that restoring of configuration that contains unsupported tags works correctly - * (unsupported tags are ignored). - */ - @Test - public void testConfigurationWithUnsupportedTagsRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(createNetworkForConfigurationWithUnsupportedTag()); - - byte[] backupData = WIFI_BACKUP_DATA_WITH_UNSUPPORTED_TAG.getBytes(); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - - // No valid data to check in dump. - mCheckDump = false; - } - - /** - * Creates correct WiFiConfiguration that should be parsed out of - * {@link #WIFI_BACKUP_DATA_WITH_UNSUPPORTED_TAG} configuration which contains unsupported tag. - */ - private static WifiConfiguration createNetworkForConfigurationWithUnsupportedTag() { - final WifiConfiguration config = new WifiConfiguration(); - config.SSID = "\"" + WifiConfigurationTestUtil.TEST_SSID + "\""; - config.wepTxKeyIndex = 0; - config.hiddenSSID = false; - config.requirePmf = false; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - config.allowedProtocols.set(WifiConfiguration.Protocol.WPA); - config.allowedProtocols.set(WifiConfiguration.Protocol.RSN); - config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - config.shared = true; - - IpConfiguration ipConfiguration = new IpConfiguration(); - ipConfiguration.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - ipConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE); - config.setIpConfiguration(ipConfiguration); - - return config; - } - - /** - * Verify that restoring of configuration that contains unsupported values in bitsets works - * correctly (unsupported values are ignored). - */ - @Test - public void testConfigurationWithUnsupportedValuesInBitsetsRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(createNetworkForConfigurationWithUnsupportedValuesInBitsetsInRestore()); - - byte[] backupData = WIFI_BACKUP_DATA_WITH_UNSUPPORTED_VALUES_IN_BITSETS.getBytes(); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - - // No valid data to check in dump. - mCheckDump = false; - } - - /** - * Creates correct WiFiConfiguration that should be parsed out of - * {@link #WIFI_BACKUP_DATA_WITH_UNSUPPORTED_VALUES_IN_BITSETS} configuration which contains - * unsupported values. - * |AllowedKeyMgmt|, |AllowedProtocols|, |AllowedAuthAlgorithms|, |AllowedGroupCiphers| and - * |AllowedPairwiseCiphers| fields have invalid values in them. - */ - private static WifiConfiguration - createNetworkForConfigurationWithUnsupportedValuesInBitsetsInRestore() { - final WifiConfiguration config = new WifiConfiguration(); - config.SSID = "\"" + WifiConfigurationTestUtil.TEST_SSID + "\""; - config.wepTxKeyIndex = 0; - config.hiddenSSID = false; - config.requirePmf = false; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - config.allowedProtocols.set(WifiConfiguration.Protocol.WPA); - config.allowedProtocols.set(WifiConfiguration.Protocol.RSN); - config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - config.shared = true; - - IpConfiguration ipConfiguration = new IpConfiguration(); - ipConfiguration.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - ipConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE); - config.setIpConfiguration(ipConfiguration); - - return config; - } - - /** - * Verify that a single WEP network configuration with only 1 key is serialized & deserialized - * correctly. - */ - @Test - public void testSingleWepNetworkWithSingleKeyBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createWepNetworkWithSingleKey()); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single enterprise network configuration is not serialized. - */ - @Test - public void testSingleEnterpriseNetworkNotBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createEapNetwork()); - configurations.add(WifiConfigurationTestUtil.createEapSuiteBNetwork()); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - assertTrue(retrievedConfigurations.isEmpty()); - // No valid data to check in dump. - mCheckDump = false; - } - - /** - * Verify that a single PSK network configuration with static ip/proxy settings is serialized & - * deserialized correctly. - */ - @Test - public void testSinglePskNetworkWithStaticIpAndStaticProxyBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy()); - configurations.add(pskNetwork); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single PSK network configuration with static ip & PAC proxy settings is - * serialized & deserialized correctly. - */ - @Test - public void testSinglePskNetworkWithStaticIpAndPACProxyBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createStaticIpConfigurationWithPacProxy()); - configurations.add(pskNetwork); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single PSK network configuration with DHCP ip & PAC proxy settings is - * serialized & deserialized correctly. - */ - @Test - public void testSinglePskNetworkWithDHCPIpAndPACProxyBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy()); - configurations.add(pskNetwork); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single PSK network configuration with partial static ip settings is serialized - * & deserialized correctly. - */ - @Test - public void testSinglePskNetworkWithPartialStaticIpBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createPartialStaticIpConfigurationWithPacProxy()); - configurations.add(pskNetwork); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that multiple networks of different types are serialized and deserialized correctly. - */ - @Test - public void testMultipleNetworksAllBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createWepNetwork()); - configurations.add(WifiConfigurationTestUtil.createWepNetwork()); - configurations.add(WifiConfigurationTestUtil.createPskNetwork()); - configurations.add(WifiConfigurationTestUtil.createOpenNetwork()); - configurations.add(WifiConfigurationTestUtil.createOweNetwork()); - configurations.add(WifiConfigurationTestUtil.createSaeNetwork()); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that multiple networks of different types except enterprise ones are serialized and - * deserialized correctly - */ - @Test - public void testMultipleNetworksNonEnterpriseBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - List<WifiConfiguration> expectedConfigurations = new ArrayList<>(); - - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - configurations.add(wepNetwork); - expectedConfigurations.add(wepNetwork); - - configurations.add(WifiConfigurationTestUtil.createEapNetwork()); - configurations.add(WifiConfigurationTestUtil.createEapSuiteBNetwork()); - - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - configurations.add(pskNetwork); - expectedConfigurations.add(pskNetwork); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - configurations.add(openNetwork); - expectedConfigurations.add(openNetwork); - - WifiConfiguration saeNetwork = WifiConfigurationTestUtil.createSaeNetwork(); - configurations.add(saeNetwork); - expectedConfigurations.add(saeNetwork); - - WifiConfiguration oweNetwork = WifiConfigurationTestUtil.createOweNetwork(); - configurations.add(oweNetwork); - expectedConfigurations.add(oweNetwork); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - expectedConfigurations, retrievedConfigurations); - } - - /** - * Verify that multiple networks with different credential types and IpConfiguration types are - * serialized and deserialized correctly. - */ - @Test - public void testMultipleNetworksWithDifferentIpConfigurationsAllBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - wepNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy()); - configurations.add(wepNetwork); - - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createStaticIpConfigurationWithPacProxy()); - configurations.add(pskNetwork); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy()); - configurations.add(openNetwork); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that multiple networks of different types except the non system app created ones are - * serialized and deserialized correctly. - */ - @Test - public void testMultipleNetworksSystemAppBackupRestore() { - int systemAppUid = Process.SYSTEM_UID; - int nonSystemAppUid = Process.FIRST_APPLICATION_UID + 556; - when(mWifiPermissionsUtil.checkConfigOverridePermission(eq(systemAppUid))) - .thenReturn(true); - when(mWifiPermissionsUtil.checkConfigOverridePermission(eq(nonSystemAppUid))) - .thenReturn(false); - - List<WifiConfiguration> configurations = new ArrayList<>(); - List<WifiConfiguration> expectedConfigurations = new ArrayList<>(); - - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - wepNetwork.creatorUid = systemAppUid; - configurations.add(wepNetwork); - expectedConfigurations.add(wepNetwork); - - // These should not be in |expectedConfigurations|. - WifiConfiguration nonSystemAppWepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - nonSystemAppWepNetwork.creatorUid = nonSystemAppUid; - configurations.add(nonSystemAppWepNetwork); - - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.creatorUid = systemAppUid; - configurations.add(pskNetwork); - expectedConfigurations.add(pskNetwork); - - // These should not be in |expectedConfigurations|. - WifiConfiguration nonSystemAppPskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - nonSystemAppPskNetwork.creatorUid = nonSystemAppUid; - configurations.add(nonSystemAppPskNetwork); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - configurations.add(openNetwork); - expectedConfigurations.add(openNetwork); - - byte[] backupData = mWifiBackupRestore.retrieveBackupDataFromConfigurations(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - expectedConfigurations, retrievedConfigurations); - } - - /** - * Verify that a single open network configuration is serialized & deserialized correctly from - * old backups. - */ - @Test - public void testSingleOpenNetworkSupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createOpenNetwork()); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single open hidden network configuration is serialized & deserialized - * correctly from old backups. - */ - @Test - public void testSingleOpenHiddenNetworkSupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createOpenHiddenNetwork()); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single PSK network configuration is serialized & deserialized correctly from - * old backups. - */ - @Test - public void testSinglePskNetworkSupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createPskNetwork()); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single PSK hidden network configuration is serialized & deserialized correctly - * from old backups. - */ - @Test - public void testSinglePskHiddenNetworkSupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createPskHiddenNetwork()); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single WEP network configuration is serialized & deserialized correctly from - * old backups. - */ - @Test - public void testSingleWepNetworkSupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createWepNetwork()); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single WEP network configuration with only 1 key is serialized & deserialized - * correctly from old backups. - */ - @Test - public void testSingleWepNetworkWithSingleKeySupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createWepNetworkWithSingleKey()); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single enterprise network configuration is not serialized from old backups. - */ - @Test - public void testSingleEnterpriseNetworkNotSupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createEapNetwork()); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - assertTrue(retrievedConfigurations.isEmpty()); - } - - /** - * Verify that multiple networks with different credential types and IpConfiguration types are - * serialized and deserialized correctly from old backups - */ - @Test - public void testMultipleNetworksWithDifferentIpConfigurationsAllSupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - wepNetwork.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); - wepNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy()); - configurations.add(wepNetwork); - - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - pskNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createStaticIpConfigurationWithPacProxy()); - configurations.add(pskNetwork); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy()); - configurations.add(openNetwork); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that a single open network configuration is serialized & deserialized correctly from - * old backups with no ipconfig data. - */ - @Test - public void testSingleOpenNetworkSupplicantBackupRestoreWithNoIpConfigData() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createOpenNetwork()); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, null); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that multiple networks with different credential types are serialized and - * deserialized correctly from old backups with no ipconfig data. - */ - @Test - public void testMultipleNetworksAllSupplicantBackupRestoreWithNoIpConfigData() { - List<WifiConfiguration> configurations = new ArrayList<>(); - - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - configurations.add(wepNetwork); - - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - configurations.add(pskNetwork); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - configurations.add(openNetwork); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, null); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that multiple networks of different types except the non system app created ones are - * serialized and deserialized correctly from old backups. - */ - @Test - public void testMultipleNetworksSystemAppSupplicantBackupRestore() { - List<WifiConfiguration> configurations = new ArrayList<>(); - List<WifiConfiguration> expectedConfigurations = new ArrayList<>(); - - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - configurations.add(wepNetwork); - expectedConfigurations.add(wepNetwork); - - // These should not be in |expectedConfigurations|. - WifiConfiguration nonSystemAppWepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - nonSystemAppWepNetwork.creatorUid = Process.FIRST_APPLICATION_UID; - configurations.add(nonSystemAppWepNetwork); - - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - configurations.add(pskNetwork); - expectedConfigurations.add(pskNetwork); - - // These should not be in |expectedConfigurations|. - WifiConfiguration nonSystemAppPskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - nonSystemAppPskNetwork.creatorUid = Process.FIRST_APPLICATION_UID + 1; - configurations.add(nonSystemAppPskNetwork); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - configurations.add(openNetwork); - expectedConfigurations.add(openNetwork); - - byte[] supplicantData = createWpaSupplicantConfBackupData(configurations); - byte[] ipConfigData = createIpConfBackupData(configurations); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, ipConfigData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - expectedConfigurations, retrievedConfigurations); - } - - /** - * Verifying that backup data containing some unknown keys is properly restored. - * The backup data used here is a PII masked version of a backup data seen in a reported bug. - */ - @Test - public void testSingleNetworkSupplicantBackupRestoreWithUnknownEAPKey() { - String backupSupplicantConfNetworkBlock = "network={\n" - + "ssid=" + WifiConfigurationTestUtil.TEST_SSID + "\n" - + "psk=" + WifiConfigurationTestUtil.TEST_PSK + "\n" - + "key_mgmt=WPA-PSK WPA-PSK-SHA256\n" - + "priority=18\n" - + "id_str=\"%7B%22creatorUid%22%3A%221000%22%2C%22configKey" - + "%22%3A%22%5C%22BLAH%5C%22WPA_PSK%22%7D\"\n" - + "eapRetryCount=6\n"; - byte[] supplicantData = backupSupplicantConfNetworkBlock.getBytes(); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( - supplicantData, null); - - final WifiConfiguration expectedConfiguration = new WifiConfiguration(); - expectedConfiguration.SSID = WifiConfigurationTestUtil.TEST_SSID; - expectedConfiguration.preSharedKey = WifiConfigurationTestUtil.TEST_PSK; - expectedConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - - ArrayList<WifiConfiguration> expectedConfigurations = new ArrayList<WifiConfiguration>() {{ - add(expectedConfiguration); - }}; - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - expectedConfigurations, retrievedConfigurations); - } - - /** - * Verify that any corrupted data provided by Backup/Restore is ignored correctly. - */ - @Test - public void testCorruptBackupRestore() { - Random random = new Random(); - byte[] backupData = new byte[100]; - random.nextBytes(backupData); - - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - assertNull(retrievedConfigurations); - // No valid data to check in dump. - mCheckDump = false; - } - - /** - * Verify that restoring of configuration from a 1.0 version backup data. - */ - @Test - public void testRestoreFromV1_0BackupData() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(createNetworkForConfigurationWithV1_0Data()); - - byte[] backupData = WIFI_BACKUP_DATA_V1_0.getBytes(); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that restoring of configuration from a 1.1 version backup data. - */ - @Test - public void testRestoreFromV1_1BackupData() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(createNetworkForConfigurationWithV1_1Data()); - - byte[] backupData = WIFI_BACKUP_DATA_V1_1.getBytes(); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - } - - /** - * Verify that restoring of configuration from a 1.2 version backup data. - */ - @Test - public void testRestoreFromV1_2BackupData() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(createNetworkForConfigurationWithV1_2Data()); - - byte[] backupData = WIFI_BACKUP_DATA_V1_2.getBytes(); - List<WifiConfiguration> retrievedConfigurations = - mWifiBackupRestore.retrieveConfigurationsFromBackupData(backupData); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - configurations, retrievedConfigurations); - - // Also, assert in the reverse direction to ensure the serialization logic matches. - // Note: This will stop working when we bump up the version. Then we'll need to copy - // the below assert to the test for the latest version. - assertEquals(WIFI_BACKUP_DATA_V1_2, - new String(mWifiBackupRestore.retrieveBackupDataFromConfigurations( - retrievedConfigurations))); - } - - /** - * Creates correct WiFiConfiguration that should be parsed out of - * {@link #WIFI_BACKUP_DATA_V1_0} configuration which contains 1.0 version backup. - */ - private static WifiConfiguration createNetworkForConfigurationWithV1_0Data() { - final WifiConfiguration config = new WifiConfiguration(); - config.SSID = "\"" + WifiConfigurationTestUtil.TEST_SSID + "\""; - config.wepTxKeyIndex = 0; - config.hiddenSSID = false; - config.requirePmf = false; - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - config.allowedProtocols.set(WifiConfiguration.Protocol.WPA); - config.allowedProtocols.set(WifiConfiguration.Protocol.RSN); - config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - config.shared = true; - - IpConfiguration ipConfiguration = new IpConfiguration(); - ipConfiguration.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - ipConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE); - config.setIpConfiguration(ipConfiguration); - - return config; - } - - /** - * Creates correct WiFiConfiguration that should be parsed out of - * {@link #WIFI_BACKUP_DATA_V1_1} configuration which contains 1.1 version backup. - */ - private static WifiConfiguration createNetworkForConfigurationWithV1_1Data() { - final WifiConfiguration config = createNetworkForConfigurationWithV1_0Data(); - config.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED; - return config; - } - - /** - * Creates correct WiFiConfiguration that should be parsed out of - * {@link #WIFI_BACKUP_DATA_V1_1} configuration which contains 1.2 version backup. - */ - private static WifiConfiguration createNetworkForConfigurationWithV1_2Data() { - final WifiConfiguration config = createNetworkForConfigurationWithV1_1Data(); - config.allowAutojoin = false; - return config; - } - - /** - * Helper method to write a list of networks in wpa_supplicant.conf format to the output stream. - */ - private byte[] createWpaSupplicantConfBackupData(List<WifiConfiguration> configurations) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - OutputStreamWriter out = new OutputStreamWriter(bos); - try { - for (WifiConfiguration configuration : configurations) { - writeConfigurationToWpaSupplicantConf(out, configuration); - } - out.flush(); - return bos.toByteArray(); - } catch (IOException e) { - return null; - } - } - - /** - * Helper method to write a network in wpa_supplicant.conf format to the output stream. - * This was created using a sample wpa_supplicant.conf file. Using the raw key strings here - * (instead of consts in WifiBackupRestore). - */ - private void writeConfigurationToWpaSupplicantConf( - OutputStreamWriter out, WifiConfiguration configuration) - throws IOException { - out.write("network={\n"); - out.write(" " + "ssid=" + configuration.SSID + "\n"); - if (configuration.hiddenSSID) { - out.write(" " + "scan_ssid=1" + "\n"); - } - String allowedKeyManagement = ""; - if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { - allowedKeyManagement += "NONE"; - } - if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - allowedKeyManagement += "WPA-PSK "; - } - if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { - allowedKeyManagement += "WPA-EAP "; - } - if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) { - allowedKeyManagement += "IEEE8021X "; - } - out.write(" " + "key_mgmt=" + allowedKeyManagement + "\n"); - String allowedAuthAlgorithm = ""; - if (configuration.allowedAuthAlgorithms.get(WifiConfiguration.AuthAlgorithm.OPEN)) { - allowedAuthAlgorithm += "OPEN "; - } - if (configuration.allowedAuthAlgorithms.get(WifiConfiguration.AuthAlgorithm.SHARED)) { - allowedAuthAlgorithm += "SHARED "; - } - out.write(" " + "auth_alg=" + allowedAuthAlgorithm + "\n"); - if (configuration.preSharedKey != null) { - out.write(" " + "psk=" + configuration.preSharedKey + "\n"); - } - if (configuration.wepKeys[0] != null) { - out.write(" " + "wep_key0=" + configuration.wepKeys[0] + "\n"); - } - if (configuration.wepKeys[1] != null) { - out.write(" " + "wep_key1=" + configuration.wepKeys[1] + "\n"); - } - if (configuration.wepKeys[2] != null) { - out.write(" " + "wep_key2=" + configuration.wepKeys[2] + "\n"); - } - if (configuration.wepKeys[3] != null) { - out.write(" " + "wep_key3=" + configuration.wepKeys[3] + "\n"); - } - if (configuration.wepKeys[0] != null || configuration.wepKeys[1] != null - || configuration.wepKeys[2] != null || configuration.wepKeys[3] != null) { - out.write(" " + "wep_tx_keyidx=" + configuration.wepTxKeyIndex + "\n"); - } - Map<String, String> extras = new HashMap<>(); - extras.put(SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY, configuration.getKey()); - extras.put(SupplicantStaNetworkHal.ID_STRING_KEY_CREATOR_UID, - Integer.toString(configuration.creatorUid)); - String idString = "\"" + SupplicantStaNetworkHal.createNetworkExtra(extras) + "\""; - if (idString != null) { - out.write(" " + "id_str=" + idString + "\n"); - } - out.write("}\n"); - out.write("\n"); - } - - /** - * Helper method to write a list of networks in ipconfig.txt format to the output stream. - */ - private byte[] createIpConfBackupData(List<WifiConfiguration> configurations) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream(bos); - final int configStoreVersion = 2; - try { - // write version first. - out.writeInt(configStoreVersion); - for (WifiConfiguration configuration : configurations) { - // TODO: store configKey as a string instead of calculating its hash - IpConfigStoreTestWriter.writeConfig( - out, - String.valueOf(configuration.getKey().hashCode()), - configuration.getIpConfiguration(), - configStoreVersion); - } - out.flush(); - return bos.toByteArray(); - } catch (IOException e) { - return null; - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiBaseTest.java b/tests/wifitests/src/com/android/server/wifi/WifiBaseTest.java deleted file mode 100644 index a7fb733c7..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiBaseTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import org.junit.After; -import org.mockito.Mockito; - -/** - * Base class for Wifi unit tests that cleans up inline mocks. - */ -public abstract class WifiBaseTest { - /** - * Clean up inline mocks to prevent OutOfMemory errors. - * See https://github.com/mockito/mockito/issues/1614 - */ - @After - public final void clearInlineMocks() { - Mockito.framework().clearInlineMocks(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java deleted file mode 100644 index 9ff064ed1..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import static com.android.server.wifi.util.NativeUtil.removeEnclosingQuotes; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.net.MacAddress; -import android.net.util.MacAddressUtils; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.WifiCandidates}. - */ -@SmallTest -public class WifiCandidatesTest extends WifiBaseTest { - - @Mock ScanDetail mScanDetail1; - @Mock ScanDetail mScanDetail2; - @Mock WifiScoreCard mWifiScoreCard; - @Mock WifiScoreCard.PerBssid mPerBssid; - @Mock Context mContext; - - ScanResult mScanResult1; - ScanResult mScanResult2; - - WifiConfiguration mConfig1; - WifiConfiguration mConfig2; - - WifiCandidates mWifiCandidates; - MockResources mResources; - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mWifiCandidates = new WifiCandidates(mWifiScoreCard, mContext); - mConfig1 = WifiConfigurationTestUtil.createOpenNetwork(); - - mScanResult1 = new ScanResult(); - mScanResult1.SSID = removeEnclosingQuotes(mConfig1.SSID); - mScanResult1.capabilities = "[ESS]"; - mScanResult1.BSSID = "00:00:00:00:00:01"; - - mConfig2 = WifiConfigurationTestUtil.createEphemeralNetwork(); - mScanResult2 = new ScanResult(); - mScanResult2.SSID = removeEnclosingQuotes(mConfig2.SSID); - mScanResult2.capabilities = "[ESS]"; - - doReturn(mScanResult1).when(mScanDetail1).getScanResult(); - doReturn(mScanResult2).when(mScanDetail2).getScanResult(); - doReturn(mPerBssid).when(mWifiScoreCard).lookupBssid(any(), any()); - doReturn(50).when(mPerBssid).estimatePercentInternetAvailability(); - MockResources mResources = new MockResources(); - mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true); - doReturn(mResources).when(mContext).getResources(); - } - - /** - * Test for absence of null pointer exceptions - */ - @Test - public void testDontDieFromNulls() throws Exception { - mWifiCandidates.add(null, mConfig1, 1, 0.0, false, 100); - mWifiCandidates.add(mScanDetail1, null, 2, 0.0, false, 100); - doReturn(null).when(mScanDetail2).getScanResult(); - mWifiCandidates.add(mScanDetail2, mConfig2, 3, 1.0, true, 100); - assertFalse(mWifiCandidates.remove(null)); - - assertEquals(0, mWifiCandidates.size()); - } - - /** - * Add just one thing - */ - @Test - public void testAddJustOne() throws Exception { - assertTrue(mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100)); - - assertEquals(1, mWifiCandidates.size()); - assertEquals(0, mWifiCandidates.getFaultCount()); - assertNull(mWifiCandidates.getLastFault()); - verify(mPerBssid).setNetworkConfigId(eq(mConfig1.networkId)); - } - - /** - * Test retrieving the list of candidates. - */ - @Test - public void testGetCandidates() { - assertTrue(mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100)); - assertNotNull(mWifiCandidates.getCandidates()); - assertEquals(1, mWifiCandidates.getCandidates().size()); - } - - /** - * Make sure we catch SSID mismatch due to quoting error - */ - @Test - public void testQuotingBotch() throws Exception { - // Unfortunately ScanResult.SSID is not quoted; make sure we catch that - mScanResult1.SSID = mConfig1.SSID; - mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, true, 100); - - // Should not have added this one - assertEquals(0, mWifiCandidates.size()); - // The failure should have been recorded - assertEquals(1, mWifiCandidates.getFaultCount()); - // The record of the failure should contain the culprit - String blah = mWifiCandidates.getLastFault().toString(); - assertTrue(blah, blah.contains(mConfig1.SSID)); - - // Now check that we can clear the faults - mWifiCandidates.clearFaults(); - - assertEquals(0, mWifiCandidates.getFaultCount()); - assertNull(mWifiCandidates.getLastFault()); - } - - /** - * Test Key equals and hashCode methods - */ - @Test - public void testKeyEquivalence() throws Exception { - ScanResultMatchInfo matchInfo1 = ScanResultMatchInfo.fromWifiConfiguration(mConfig1); - ScanResultMatchInfo matchInfo1Prime = ScanResultMatchInfo.fromWifiConfiguration(mConfig1); - ScanResultMatchInfo matchInfo2 = ScanResultMatchInfo.fromWifiConfiguration(mConfig2); - assertFalse(matchInfo1 == matchInfo1Prime); // Checking assumption - MacAddress mac1 = MacAddressUtils.createRandomUnicastAddress(); - MacAddress mac2 = MacAddressUtils.createRandomUnicastAddress(); - assertNotEquals(mac1, mac2); // really tiny probability of failing here - - WifiCandidates.Key key1 = new WifiCandidates.Key(matchInfo1, mac1, 1); - - assertFalse(key1.equals(null)); - assertFalse(key1.equals((Integer) 0)); - // Same inputs should give equal results - assertEquals(key1, new WifiCandidates.Key(matchInfo1, mac1, 1)); - // Equal inputs should give equal results - assertEquals(key1, new WifiCandidates.Key(matchInfo1Prime, mac1, 1)); - // Hash codes of equal things should be equal - assertEquals(key1.hashCode(), key1.hashCode()); - assertEquals(key1.hashCode(), new WifiCandidates.Key(matchInfo1, mac1, 1).hashCode()); - assertEquals(key1.hashCode(), new WifiCandidates.Key(matchInfo1Prime, mac1, 1).hashCode()); - - // Unequal inputs should give unequal results - assertFalse(key1.equals(new WifiCandidates.Key(matchInfo2, mac1, 1))); - assertFalse(key1.equals(new WifiCandidates.Key(matchInfo1, mac2, 1))); - assertFalse(key1.equals(new WifiCandidates.Key(matchInfo1, mac1, 2))); - } - - /** - * Test toString method - */ - @Test - public void testCandidateToString() throws Exception { - doReturn(57).when(mPerBssid).estimatePercentInternetAvailability(); - mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0015001, false, 100); - WifiCandidates.Candidate c = mWifiCandidates.getGroupedCandidates() - .iterator().next().iterator().next(); - String s = c.toString(); - assertTrue(s, s.contains(" nominator = 2, ")); - assertTrue(s, s.contains(" config = " + mConfig1.networkId + ", ")); - assertTrue(s, s.contains(" lastSelectionWeight = 0.002, ")); // should be rounded - assertTrue(s, s.contains(" pInternet = 57, ")); - for (String x : s.split(",")) { - if (x.startsWith("Candidate {")) x = x.substring("Candidate {".length()); - if (x.endsWith(" }")) x = x.substring(0, x.length() - 2); - String diagnose = s + " !! " + x; - assertTrue(diagnose, x.startsWith(" ")); // space between items - assertFalse(diagnose, x.contains(" ")); // no double spaces - if (x.contains("=")) { - // Only one equals sign, if there is one - assertTrue(diagnose, x.indexOf("=") == x.lastIndexOf("=")); - assertTrue(diagnose, x.matches(" [A-Za-z]+ = [^ ]+")); - } else { - assertTrue(diagnose, x.matches(" [a-z]+")); - } - } - } - - /** - * Test that picky mode works - */ - @Test - public void testPickyMode() throws Exception { - // Set picky mode, make sure that it returns the object itself (so that - // method chaining may be used). - assertTrue(mWifiCandidates == mWifiCandidates.setPicky(true)); - try { - mScanResult1.SSID = mConfig1.SSID; // As in testQuotingBotch() - mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100); - fail("Exception not raised in picky mode"); - } catch (IllegalArgumentException e) { - assertEquals(1, mWifiCandidates.getFaultCount()); - assertEquals(e, mWifiCandidates.getLastFault()); - } - } - - /** - * Try cases where we don't overwrite existing candidates - */ - @Test - public void testNoOverwriteCases() throws Exception { - // Setup is to add the first candidate - mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100); - assertEquals(1, mWifiCandidates.size()); - - // Later nominator. Should not add. - assertFalse(mWifiCandidates.add(mScanDetail1, mConfig1, 5, 0.0, false, 100)); - assertFalse(mWifiCandidates.add(mScanDetail1, mConfig1, 5, 0.0, false, 100)); - assertEquals(0, mWifiCandidates.getFaultCount()); // Still no faults - // After all that, only one candidate should be there. - assertEquals(1, mWifiCandidates.size()); - } - - /** - * Try cases where we do overwrite existing candidates - */ - @Test - public void testOverwriteCases() throws Exception { - // Setup is to add the first candidate - mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100); - assertEquals(1, mWifiCandidates.size()); - - // Same nominator, should replace. - assertTrue(mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100)); - assertEquals(0, mWifiCandidates.getFaultCount()); // No fault - // Nominator out of order. Should replace. - assertTrue(mWifiCandidates.add(mScanDetail1, mConfig1, 1, 0.0, false, 100)); - assertEquals(0, mWifiCandidates.getFaultCount()); // But not considered a fault - // After all that, only one candidate should be there. - assertEquals(1, mWifiCandidates.size()); - } - - /** - * BSSID validation - */ - @Test - public void testBssidValidation() throws Exception { - // Null BSSID. - mScanResult1.BSSID = null; - mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100); - assertTrue("Expecting NPE, got " + mWifiCandidates.getLastFault(), - mWifiCandidates.getLastFault() instanceof NullPointerException); - // Malformed BSSID - mScanResult1.BSSID = "NotaBssid!"; - mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100); - assertTrue("Expecting IAE, got " + mWifiCandidates.getLastFault(), - mWifiCandidates.getLastFault() instanceof IllegalArgumentException); - assertEquals(0, mWifiCandidates.size()); - } - - /** - * Add candidate BSSIDs in the same network, then remove them - */ - @Test - public void testTwoBssids() throws Exception { - // Make a duplicate of the first config - mConfig2 = new WifiConfiguration(mConfig1); - // Make a second scan result, same network, different BSSID. - mScanResult2.SSID = mScanResult1.SSID; - mScanResult2.BSSID = mScanResult1.BSSID.replace('1', '2'); - // Add both - mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100); - mWifiCandidates.add(mScanDetail2, mConfig2, 2, 0.0, false, 100); - // We expect them both to be there - assertEquals(2, mWifiCandidates.size()); - // But just one group - assertEquals(1, mWifiCandidates.getGroupedCandidates().size()); - // Now remove them one at a time - WifiCandidates.Candidate c1, c2; - c1 = mWifiCandidates.getGroupedCandidates().iterator().next().iterator().next(); - assertTrue(mWifiCandidates.remove(c1)); - assertEquals(1, mWifiCandidates.size()); - assertEquals(1, mWifiCandidates.getGroupedCandidates().size()); - // Should not be able to remove the one that isn't there - assertFalse(mWifiCandidates.remove(c1)); - // Remove the other one, too - c2 = mWifiCandidates.getGroupedCandidates().iterator().next().iterator().next(); - assertTrue(mWifiCandidates.remove(c2)); - assertFalse(mWifiCandidates.remove(c2)); - assertEquals(0, mWifiCandidates.size()); - assertEquals(0, mWifiCandidates.getGroupedCandidates().size()); - } - - /** - * Test replacing a candidate with a higher scoring one - */ - @Test - public void testReplace() throws Exception { - // Make a duplicate of the first config - mConfig2 = new WifiConfiguration(mConfig1); - // And the scan result - mScanResult2.SSID = mScanResult1.SSID; - mScanResult2.BSSID = mScanResult1.BSSID; - // Try adding them both, in a known order - assertTrue(mWifiCandidates.add(mScanDetail2, mConfig2, 2, 0.0, false, 100)); - assertTrue(mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 90)); - // Only one should survive - assertEquals(1, mWifiCandidates.size()); - assertEquals(0, mWifiCandidates.getFaultCount()); - // Make sure we kept the second one - WifiCandidates.Candidate c; - c = mWifiCandidates.getGroupedCandidates().iterator().next().iterator().next(); - assertEquals(90, c.getPredictedThroughputMbps()); - } - - /** - * Tests passpiont network from same provider(FQDN) can have multiple candidates with different - * scanDetails. - */ - @Test - public void testMultiplePasspointCandidatesWithSameFQDN() { - // Create a Passpoint WifiConfig - WifiConfiguration config1 = WifiConfigurationTestUtil.createPasspointNetwork(); - mScanResult2.BSSID = mScanResult1.BSSID.replace('1', '2'); - // Add candidates with different scanDetail for same passpoint WifiConfig. - assertTrue(mWifiCandidates.add(mScanDetail1, config1, 2, 0.0, false, 100)); - assertTrue(mWifiCandidates.add(mScanDetail2, config1, 2, 0.0, false, 100)); - // Both should survive and no faults. - assertEquals(2, mWifiCandidates.size()); - assertEquals(0, mWifiCandidates.getFaultCount()); - } - - /** - * Verify CarrierOrPrivileged bit is remembered. - */ - @Test - public void testAddCarrierOrPrivilegedCandidate() { - WifiCandidates.Key key = mWifiCandidates - .keyFromScanDetailAndConfig(mScanDetail1, mConfig1); - WifiCandidates.Candidate candidate; - // Make sure the CarrierOrPrivileged false is remembered - assertTrue(mWifiCandidates.add(key, mConfig1, 0, -50, 2412, 0.0, false, false, 100)); - candidate = mWifiCandidates.getCandidates().get(0); - assertFalse(candidate.isCarrierOrPrivileged()); - mWifiCandidates.remove(candidate); - // Make sure the CarrierOrPrivileged true is remembered - assertTrue(mWifiCandidates.add(key, mConfig1, 0, -50, 2412, 0.0, false, true, 100)); - candidate = mWifiCandidates.getCandidates().get(0); - assertTrue(candidate.isCarrierOrPrivileged()); - mWifiCandidates.remove(candidate); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java deleted file mode 100644 index 750e8d46b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java +++ /dev/null @@ -1,1806 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; -import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION; -import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_CLICKED_INTENT_ACTION; -import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION; -import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.AlertDialog; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.net.Uri; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.os.Handler; -import android.os.PersistableBundle; -import android.os.test.TestLooper; -import android.telephony.CarrierConfigManager; -import android.telephony.ImsiEncryptionInfo; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.util.Base64; -import android.util.Pair; -import android.view.Window; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData; -import com.android.server.wifi.WifiCarrierInfoManager.SimAuthResponseData; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import java.security.PublicKey; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; - -/** - * Unit tests for {@link WifiCarrierInfoManager}. - */ -@SmallTest -public class WifiCarrierInfoManagerTest extends WifiBaseTest { - private WifiCarrierInfoManager mWifiCarrierInfoManager; - - private static final int DATA_SUBID = 1; - private static final int NON_DATA_SUBID = 2; - private static final int INVALID_SUBID = -1; - private static final int DATA_CARRIER_ID = 10; - private static final int PARENT_DATA_CARRIER_ID = 11; - private static final int NON_DATA_CARRIER_ID = 20; - private static final int PARENT_NON_DATA_CARRIER_ID = 21; - private static final int DEACTIVE_CARRIER_ID = 30; - private static final String MATCH_PREFIX_IMSI = "123456*"; - private static final String DATA_FULL_IMSI = "123456789123456"; - private static final String NON_DATA_FULL_IMSI = "123456987654321"; - private static final String NO_MATCH_FULL_IMSI = "654321123456789"; - private static final String NO_MATCH_PREFIX_IMSI = "654321*"; - private static final String DATA_OPERATOR_NUMERIC = "123456"; - private static final String NON_DATA_OPERATOR_NUMERIC = "123456"; - private static final String NO_MATCH_OPERATOR_NUMERIC = "654321"; - private static final String TEST_PACKAGE = "com.test12345"; - private static final String ANONYMOUS_IDENTITY = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org"; - private static final String CARRIER_NAME = "Google"; - - @Mock CarrierConfigManager mCarrierConfigManager; - @Mock WifiContext mContext; - @Mock Resources mResources; - @Mock FrameworkFacade mFrameworkFacade; - @Mock TelephonyManager mTelephonyManager; - @Mock TelephonyManager mDataTelephonyManager; - @Mock TelephonyManager mNonDataTelephonyManager; - @Mock SubscriptionManager mSubscriptionManager; - @Mock SubscriptionInfo mDataSubscriptionInfo; - @Mock SubscriptionInfo mNonDataSubscriptionInfo; - @Mock WifiConfigStore mWifiConfigStore; - @Mock WifiInjector mWifiInjector; - @Mock WifiConfigManager mWifiConfigManager; - @Mock ImsiPrivacyProtectionExemptionStoreData mImsiPrivacyProtectionExemptionStoreData; - @Mock NotificationManager mNotificationManger; - @Mock Notification.Builder mNotificationBuilder; - @Mock Notification mNotification; - @Mock AlertDialog.Builder mAlertDialogBuilder; - @Mock AlertDialog mAlertDialog; - @Mock WifiCarrierInfoManager.OnUserApproveCarrierListener mListener; - @Mock WifiMetrics mWifiMetrics; - - private List<SubscriptionInfo> mSubInfoList; - - MockitoSession mMockingSession = null; - TestLooper mLooper; - private ImsiPrivacyProtectionExemptionStoreData.DataSource mImsiDataSource; - private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) - .thenReturn(mCarrierConfigManager); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) - .thenReturn(mNotificationManger); - when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources"); - when(mFrameworkFacade.makeAlertDialogBuilder(any())) - .thenReturn(mAlertDialogBuilder); - when(mFrameworkFacade.makeNotificationBuilder(any(), anyString())) - .thenReturn(mNotificationBuilder); - when(mFrameworkFacade.getBroadcast(any(), anyInt(), any(), anyInt())) - .thenReturn(mock(PendingIntent.class)); - when(mAlertDialogBuilder.setTitle(any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setMessage(any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setPositiveButton(any(), any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setNegativeButton(any(), any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setOnDismissListener(any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setOnCancelListener(any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.create()).thenReturn(mAlertDialog); - when(mAlertDialog.getWindow()).thenReturn(mock(Window.class)); - when(mNotificationBuilder.setSmallIcon(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setTicker(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setContentTitle(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setStyle(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setContentIntent(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setDeleteIntent(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setShowWhen(anyBoolean())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setLocalOnly(anyBoolean())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setColor(anyInt())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.addAction(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.build()).thenReturn(mNotification); - when(mWifiInjector.makeImsiProtectionExemptionStoreData(any())) - .thenReturn(mImsiPrivacyProtectionExemptionStoreData); - when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager); - mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager, - mSubscriptionManager, mWifiInjector, mFrameworkFacade, mContext, mWifiConfigStore, - new Handler(mLooper.getLooper()), mWifiMetrics); - ArgumentCaptor<ImsiPrivacyProtectionExemptionStoreData.DataSource> - imsiDataSourceArgumentCaptor = - ArgumentCaptor.forClass(ImsiPrivacyProtectionExemptionStoreData.DataSource.class); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); - verify(mWifiInjector).makeImsiProtectionExemptionStoreData(imsiDataSourceArgumentCaptor - .capture()); - mImsiDataSource = imsiDataSourceArgumentCaptor.getValue(); - assertNotNull(mImsiDataSource); - mSubInfoList = new ArrayList<>(); - mSubInfoList.add(mDataSubscriptionInfo); - mSubInfoList.add(mNonDataSubscriptionInfo); - when(mTelephonyManager.createForSubscriptionId(eq(DATA_SUBID))) - .thenReturn(mDataTelephonyManager); - when(mTelephonyManager.createForSubscriptionId(eq(NON_DATA_SUBID))) - .thenReturn(mNonDataTelephonyManager); - when(mTelephonyManager.getSimState(anyInt())).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(mSubInfoList); - mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT) - .mockStatic(SubscriptionManager.class).startMocking(); - - doReturn(DATA_SUBID).when( - () -> SubscriptionManager.getDefaultDataSubscriptionId()); - doReturn(true).when( - () -> SubscriptionManager.isValidSubscriptionId(DATA_SUBID)); - doReturn(true).when( - () -> SubscriptionManager.isValidSubscriptionId(NON_DATA_SUBID)); - - when(mDataSubscriptionInfo.getCarrierId()).thenReturn(DATA_CARRIER_ID); - when(mDataSubscriptionInfo.getSubscriptionId()).thenReturn(DATA_SUBID); - when(mNonDataSubscriptionInfo.getCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataSubscriptionInfo.getSubscriptionId()).thenReturn(NON_DATA_SUBID); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(DATA_FULL_IMSI); - when(mNonDataTelephonyManager.getSubscriberId()).thenReturn(NON_DATA_FULL_IMSI); - when(mDataTelephonyManager.getSimOperator()).thenReturn(DATA_OPERATOR_NUMERIC); - when(mDataTelephonyManager.getSimCarrierIdName()).thenReturn(CARRIER_NAME); - when(mNonDataTelephonyManager.getSimCarrierIdName()).thenReturn(null); - when(mNonDataTelephonyManager.getSimOperator()) - .thenReturn(NON_DATA_OPERATOR_NUMERIC); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mNonDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mSubscriptionManager.getActiveSubscriptionIdList()) - .thenReturn(new int[]{DATA_SUBID, NON_DATA_SUBID}); - - // setup resource strings for IMSI protection notification. - when(mResources.getString(eq(R.string.wifi_suggestion_imsi_privacy_title), anyString())) - .thenAnswer(s -> "blah" + s.getArguments()[1]); - when(mResources.getString(eq(R.string.wifi_suggestion_imsi_privacy_content))) - .thenReturn("blah"); - when(mResources.getText( - eq(R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_carrier))) - .thenReturn("blah"); - when(mResources.getText( - eq(R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier))) - .thenReturn("blah"); - when(mResources.getString( - eq(R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_title))) - .thenReturn("blah"); - when(mResources.getString( - eq(R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_content), - anyString())).thenAnswer(s -> "blah" + s.getArguments()[1]); - when(mResources.getText( - eq(R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation))) - .thenReturn("blah"); - when(mResources.getText( - eq(R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation))) - .thenReturn("blah"); - mWifiCarrierInfoManager.addImsiExemptionUserApprovalListener(mListener); - mImsiDataSource.fromDeserialized(new HashMap<>()); - } - - @After - public void cleanUp() throws Exception { - if (mMockingSession != null) { - mMockingSession.finishMocking(); - } - } - - /** - * Verify that the IMSI encryption info is not updated when non - * {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} intent is received. - * - * @throws Exception - */ - @Test - public void receivedNonCarrierConfigChangedIntent() throws Exception { - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - receiver.getValue().onReceive(mContext, new Intent("dummyIntent")); - verify(mCarrierConfigManager, never()).getConfig(); - } - - private PersistableBundle generateTestCarrierConfig(boolean requiresImsiEncryption) { - PersistableBundle bundle = new PersistableBundle(); - if (requiresImsiEncryption) { - bundle.putInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, - TelephonyManager.KEY_TYPE_WLAN); - } - return bundle; - } - - private PersistableBundle generateTestCarrierConfig(boolean requiresImsiEncryption, - boolean requiresEapMethodPrefix) { - PersistableBundle bundle = generateTestCarrierConfig(requiresImsiEncryption); - if (requiresEapMethodPrefix) { - bundle.putBoolean(CarrierConfigManager.ENABLE_EAP_METHOD_PREFIX_BOOL, true); - } - return bundle; - } - - /** - * Verify getting value about that if the IMSI encryption is required or not when - * {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} intent is received. - */ - @Test - public void receivedCarrierConfigChangedIntent() throws Exception { - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(true)); - when(mCarrierConfigManager.getConfigForSubId(NON_DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - - assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(NON_DATA_SUBID)); - } - - /** - * Verify the IMSI encryption is cleared when the configuration in CarrierConfig is removed. - */ - @Test - public void imsiEncryptionRequiredInfoIsCleared() { - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(true)); - when(mCarrierConfigManager.getConfigForSubId(NON_DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(true)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - - assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(NON_DATA_SUBID)); - - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - when(mCarrierConfigManager.getConfigForSubId(NON_DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(NON_DATA_SUBID)); - } - - /** - * Verify that if the IMSI encryption is downloaded. - */ - @Test - public void availableOfImsiEncryptionInfoIsUpdated() { - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(true)); - when(mCarrierConfigManager.getConfigForSubId(NON_DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN)) - .thenReturn(null); - when(mNonDataTelephonyManager - .getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN)).thenReturn(null); - - ArgumentCaptor<ContentObserver> observerCaptor = - ArgumentCaptor.forClass(ContentObserver.class); - verify(mFrameworkFacade).registerContentObserver(eq(mContext), any(Uri.class), eq(false), - observerCaptor.capture()); - ContentObserver observer = observerCaptor.getValue(); - - observer.onChange(false); - - assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - assertFalse(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(DATA_SUBID)); - - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN)) - .thenReturn(mock(ImsiEncryptionInfo.class)); - - observer.onChange(false); - - assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - assertTrue(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(DATA_SUBID)); - } - - /** - * Verify that if the IMSI encryption information is cleared - */ - @Test - public void availableOfImsiEncryptionInfoIsCleared() { - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(true)); - when(mCarrierConfigManager.getConfigForSubId(NON_DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(true)); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN)) - .thenReturn(mock(ImsiEncryptionInfo.class)); - when(mNonDataTelephonyManager - .getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN)) - .thenReturn(mock(ImsiEncryptionInfo.class)); - - ArgumentCaptor<ContentObserver> observerCaptor = - ArgumentCaptor.forClass(ContentObserver.class); - verify(mFrameworkFacade).registerContentObserver(eq(mContext), any(Uri.class), eq(false), - observerCaptor.capture()); - ContentObserver observer = observerCaptor.getValue(); - - observer.onChange(false); - - assertTrue(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(DATA_SUBID)); - assertTrue(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(NON_DATA_SUBID)); - - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN)) - .thenReturn(null); - when(mNonDataTelephonyManager - .getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN)).thenReturn(null); - - observer.onChange(false); - - assertFalse(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(DATA_SUBID)); - assertFalse(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(NON_DATA_SUBID)); - } - - @Test - public void getSimIdentityEapSim() { - final Pair<String, String> expectedIdentity = Pair.create( - "13214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", ""); - - when(mDataTelephonyManager.getSubscriberId()).thenReturn("3214561234567890"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("321456"); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - WifiConfiguration simConfig = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM, - WifiEnterpriseConfig.Phase2.NONE); - simConfig.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(simConfig)); - - WifiConfiguration peapSimConfig = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP, - WifiEnterpriseConfig.Phase2.SIM); - peapSimConfig.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(peapSimConfig)); - } - - @Test - public void getSimIdentityEapAka() { - final Pair<String, String> expectedIdentity = Pair.create( - "03214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", ""); - when(mDataTelephonyManager.getSubscriberId()).thenReturn("3214561234567890"); - - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("321456"); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - WifiConfiguration akaConfig = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA, - WifiEnterpriseConfig.Phase2.NONE); - akaConfig.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(akaConfig)); - - WifiConfiguration peapAkaConfig = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP, - WifiEnterpriseConfig.Phase2.AKA); - peapAkaConfig.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(peapAkaConfig)); - } - - @Test - public void getSimIdentityEapAkaPrime() { - final Pair<String, String> expectedIdentity = Pair.create( - "63214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", ""); - - when(mDataTelephonyManager.getSubscriberId()).thenReturn("3214561234567890"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("321456"); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - WifiConfiguration akaPConfig = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA_PRIME, - WifiEnterpriseConfig.Phase2.NONE); - akaPConfig.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(akaPConfig)); - - WifiConfiguration peapAkaPConfig = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP, - WifiEnterpriseConfig.Phase2.AKA_PRIME); - peapAkaPConfig.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(peapAkaPConfig)); - } - - /** - * Verify that an expected identity is returned when using the encrypted identity - * encoded by RFC4648. - */ - @Test - public void getEncryptedIdentity_WithRfc4648() throws Exception { - Cipher cipher = mock(Cipher.class); - PublicKey key = null; - String imsi = "3214561234567890"; - String permanentIdentity = "03214561234567890@wlan.mnc456.mcc321.3gppnetwork.org"; - String encryptedImsi = Base64.encodeToString(permanentIdentity.getBytes(), 0, - permanentIdentity.getBytes().length, Base64.NO_WRAP); - String encryptedIdentity = "\0" + encryptedImsi; - final Pair<String, String> expectedIdentity = Pair.create(permanentIdentity, - encryptedIdentity); - - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - Cipher.class).startMocking(); - try { - when(Cipher.getInstance(anyString())).thenReturn(cipher); - when(cipher.doFinal(any(byte[].class))).thenReturn(permanentIdentity.getBytes()); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(imsi); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("321456"); - ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456", - TelephonyManager.KEY_TYPE_WLAN, null, key, null); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption( - eq(TelephonyManager.KEY_TYPE_WLAN))) - .thenReturn(info); - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA, - WifiEnterpriseConfig.Phase2.NONE); - config.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(config)); - } finally { - session.finishMocking(); - } - } - - /** - * Verify that {@code null} will be returned when IMSI encryption failed. - * - * @throws Exception - */ - @Test - public void getEncryptedIdentityFailed() throws Exception { - Cipher cipher = mock(Cipher.class); - String keyIdentifier = "key=testKey"; - String imsi = "3214561234567890"; - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - Cipher.class).startMocking(); - try { - when(Cipher.getInstance(anyString())).thenReturn(cipher); - when(cipher.doFinal(any(byte[].class))).thenThrow(BadPaddingException.class); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(imsi); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("321456"); - ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456", - TelephonyManager.KEY_TYPE_WLAN, keyIdentifier, (PublicKey) null, null); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption( - eq(TelephonyManager.KEY_TYPE_WLAN))) - .thenReturn(info); - - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA, - WifiEnterpriseConfig.Phase2.NONE); - config.carrierId = DATA_CARRIER_ID; - - assertNull(mWifiCarrierInfoManager.getSimIdentity(config)); - } finally { - session.finishMocking(); - } - } - - @Test - public void getSimIdentity2DigitMnc() { - final Pair<String, String> expectedIdentity = Pair.create( - "1321560123456789@wlan.mnc056.mcc321.3gppnetwork.org", ""); - - when(mDataTelephonyManager.getSubscriberId()).thenReturn("321560123456789"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("32156"); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM, - WifiEnterpriseConfig.Phase2.NONE); - config.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(config)); - } - - @Test - public void getSimIdentityUnknownMccMnc() { - final Pair<String, String> expectedIdentity = Pair.create( - "13214560123456789@wlan.mnc456.mcc321.3gppnetwork.org", ""); - - when(mDataTelephonyManager.getSubscriberId()).thenReturn("3214560123456789"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_UNKNOWN); - when(mDataTelephonyManager.getSimOperator()).thenReturn(null); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM, - WifiEnterpriseConfig.Phase2.NONE); - config.carrierId = DATA_CARRIER_ID; - - assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(config)); - } - - @Test - public void getSimIdentityNonTelephonyConfig() { - when(mDataTelephonyManager.getSubscriberId()).thenReturn("321560123456789"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("32156"); - - assertEquals(null, - mWifiCarrierInfoManager.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.SIM))); - assertEquals(null, - mWifiCarrierInfoManager.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.MSCHAPV2))); - assertEquals(null, - mWifiCarrierInfoManager.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.TLS, WifiEnterpriseConfig.Phase2.NONE))); - assertEquals(null, - mWifiCarrierInfoManager.getSimIdentity(new WifiConfiguration())); - } - - /** - * Produce a base64 encoded length byte + data. - */ - private static String createSimChallengeRequest(byte[] challengeValue) { - byte[] challengeLengthAndValue = new byte[challengeValue.length + 1]; - challengeLengthAndValue[0] = (byte) challengeValue.length; - for (int i = 0; i < challengeValue.length; ++i) { - challengeLengthAndValue[i + 1] = challengeValue[i]; - } - return Base64.encodeToString(challengeLengthAndValue, android.util.Base64.NO_WRAP); - } - - /** - * Produce a base64 encoded data without length. - */ - private static String create2gUsimChallengeRequest(byte[] challengeValue) { - return Base64.encodeToString(challengeValue, android.util.Base64.NO_WRAP); - } - - /** - * Produce a base64 encoded sres length byte + sres + kc length byte + kc. - */ - private static String createGsmSimAuthResponse(byte[] sresValue, byte[] kcValue) { - int overallLength = sresValue.length + kcValue.length + 2; - byte[] result = new byte[sresValue.length + kcValue.length + 2]; - int idx = 0; - result[idx++] = (byte) sresValue.length; - for (int i = 0; i < sresValue.length; ++i) { - result[idx++] = sresValue[i]; - } - result[idx++] = (byte) kcValue.length; - for (int i = 0; i < kcValue.length; ++i) { - result[idx++] = kcValue[i]; - } - return Base64.encodeToString(result, Base64.NO_WRAP); - } - - /** - * Produce a base64 encoded sres + kc without length. - */ - private static String create2gUsimAuthResponse(byte[] sresValue, byte[] kcValue) { - int overallLength = sresValue.length + kcValue.length; - byte[] result = new byte[sresValue.length + kcValue.length]; - int idx = 0; - for (int i = 0; i < sresValue.length; ++i) { - result[idx++] = sresValue[i]; - } - for (int i = 0; i < kcValue.length; ++i) { - result[idx++] = kcValue[i]; - } - return Base64.encodeToString(result, Base64.NO_WRAP); - } - - @Test - public void getGsmSimAuthResponseInvalidRequest() { - final String[] invalidRequests = { null, "", "XXXX" }; - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals("", mWifiCarrierInfoManager.getGsmSimAuthResponse(invalidRequests, config)); - } - - @Test - public void getGsmSimAuthResponseFailedSimResponse() { - final String[] failedRequests = { "5E5F" }; - when(mDataTelephonyManager.getIccAuthentication(anyInt(), anyInt(), - eq(createSimChallengeRequest(new byte[] { 0x5e, 0x5f })))).thenReturn(null); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(null, mWifiCarrierInfoManager.getGsmSimAuthResponse(failedRequests, config)); - } - - @Test - public void getGsmSimAuthResponseUsim() { - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_SIM, - createSimChallengeRequest(new byte[] { 0x1b, 0x2b }))) - .thenReturn(createGsmSimAuthResponse(new byte[] { 0x1D, 0x2C }, - new byte[] { 0x3B, 0x4A })); - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_SIM, - createSimChallengeRequest(new byte[] { 0x01, 0x22 }))) - .thenReturn(createGsmSimAuthResponse(new byte[] { 0x11, 0x11 }, - new byte[] { 0x12, 0x34 })); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(":3b4a:1d2c:1234:1111", mWifiCarrierInfoManager.getGsmSimAuthResponse( - new String[] { "1B2B", "0122" }, config)); - } - - @Test - public void getGsmSimpleSimAuthResponseInvalidRequest() { - final String[] invalidRequests = { null, "", "XXXX" }; - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals("", - mWifiCarrierInfoManager.getGsmSimpleSimAuthResponse(invalidRequests, config)); - } - - @Test - public void getGsmSimpleSimAuthResponseFailedSimResponse() { - final String[] failedRequests = { "5E5F" }; - when(mDataTelephonyManager.getIccAuthentication(anyInt(), anyInt(), - eq(createSimChallengeRequest(new byte[] { 0x5e, 0x5f })))).thenReturn(null); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(null, - mWifiCarrierInfoManager.getGsmSimpleSimAuthResponse(failedRequests, config)); - } - - @Test - public void getGsmSimpleSimAuthResponse() { - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_SIM, - TelephonyManager.AUTHTYPE_EAP_SIM, - createSimChallengeRequest(new byte[] { 0x1a, 0x2b }))) - .thenReturn(createGsmSimAuthResponse(new byte[] { 0x1D, 0x2C }, - new byte[] { 0x3B, 0x4A })); - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_SIM, - TelephonyManager.AUTHTYPE_EAP_SIM, - createSimChallengeRequest(new byte[] { 0x01, 0x23 }))) - .thenReturn(createGsmSimAuthResponse(new byte[] { 0x33, 0x22 }, - new byte[] { 0x11, 0x00 })); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(":3b4a:1d2c:1100:3322", mWifiCarrierInfoManager.getGsmSimpleSimAuthResponse( - new String[] { "1A2B", "0123" }, config)); - } - - @Test - public void getGsmSimpleSimNoLengthAuthResponseInvalidRequest() { - final String[] invalidRequests = { null, "", "XXXX" }; - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals("", mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse( - invalidRequests, config)); - } - - @Test - public void getGsmSimpleSimNoLengthAuthResponseFailedSimResponse() { - final String[] failedRequests = { "5E5F" }; - when(mDataTelephonyManager.getIccAuthentication(anyInt(), anyInt(), - eq(create2gUsimChallengeRequest(new byte[] { 0x5e, 0x5f })))).thenReturn(null); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(null, mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse( - failedRequests, config)); - } - - @Test - public void getGsmSimpleSimNoLengthAuthResponse() { - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_SIM, - TelephonyManager.AUTHTYPE_EAP_SIM, - create2gUsimChallengeRequest(new byte[] { 0x1a, 0x2b }))) - .thenReturn(create2gUsimAuthResponse(new byte[] { 0x1a, 0x2b, 0x3c, 0x4d }, - new byte[] { 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f, 0x7a, 0x1a })); - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_SIM, - TelephonyManager.AUTHTYPE_EAP_SIM, - create2gUsimChallengeRequest(new byte[] { 0x01, 0x23 }))) - .thenReturn(create2gUsimAuthResponse(new byte[] { 0x12, 0x34, 0x56, 0x78 }, - new byte[] { 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78 })); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(":1a2b3c4d5e6f7a1a:1a2b3c4d:1234567812345678:12345678", - mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse( - new String[] { "1A2B", "0123" }, config)); - } - - /** - * Produce a base64 encoded tag + res length byte + res + ck length byte + ck + ik length byte + - * ik. - */ - private static String create3GSimAuthUmtsAuthResponse(byte[] res, byte[] ck, byte[] ik) { - byte[] result = new byte[res.length + ck.length + ik.length + 4]; - int idx = 0; - result[idx++] = (byte) 0xdb; - result[idx++] = (byte) res.length; - for (int i = 0; i < res.length; ++i) { - result[idx++] = res[i]; - } - result[idx++] = (byte) ck.length; - for (int i = 0; i < ck.length; ++i) { - result[idx++] = ck[i]; - } - result[idx++] = (byte) ik.length; - for (int i = 0; i < ik.length; ++i) { - result[idx++] = ik[i]; - } - return Base64.encodeToString(result, Base64.NO_WRAP); - } - - private static String create3GSimAuthUmtsAutsResponse(byte[] auts) { - byte[] result = new byte[auts.length + 2]; - int idx = 0; - result[idx++] = (byte) 0xdc; - result[idx++] = (byte) auts.length; - for (int i = 0; i < auts.length; ++i) { - result[idx++] = auts[i]; - } - return Base64.encodeToString(result, Base64.NO_WRAP); - } - - @Test - public void get3GAuthResponseInvalidRequest() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(null, mWifiCarrierInfoManager.get3GAuthResponse( - new SimAuthRequestData(0, 0, "SSID", new String[]{"0123"}), config)); - assertEquals(null, mWifiCarrierInfoManager.get3GAuthResponse( - new SimAuthRequestData(0, 0, "SSID", new String[]{"xyz2", "1234"}), - config)); - verifyNoMoreInteractions(mDataTelephonyManager); - } - - @Test - public void get3GAuthResponseNullIccAuthentication() { - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_AKA, "AgEjAkVn")).thenReturn(null); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse( - new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}), - config); - - assertNull(response); - } - - @Test - public void get3GAuthResponseIccAuthenticationTooShort() { - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_AKA, "AgEjAkVn")) - .thenReturn(Base64.encodeToString(new byte[] {(byte) 0xdc}, Base64.NO_WRAP)); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse( - new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}), - config); - - assertNull(response); - } - - @Test - public void get3GAuthResponseBadTag() { - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_AKA, "AgEjAkVn")) - .thenReturn(Base64.encodeToString(new byte[] {0x31, 0x1, 0x2, 0x3, 0x4}, - Base64.NO_WRAP)); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse( - new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}), - config); - - assertNull(response); - } - - @Test - public void get3GAuthResponseUmtsAuth() { - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_AKA, "AgEjAkVn")) - .thenReturn(create3GSimAuthUmtsAuthResponse(new byte[] {0x11, 0x12}, - new byte[] {0x21, 0x22, 0x23}, new byte[] {0x31})); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse( - new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}), - config); - - assertNotNull(response); - assertEquals("UMTS-AUTH", response.type); - assertEquals(":31:212223:1112", response.response); - } - - @Test - public void get3GAuthResponseUmtsAuts() { - when(mDataTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_AKA, "AgEjAkVn")) - .thenReturn(create3GSimAuthUmtsAutsResponse(new byte[] {0x22, 0x33})); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse( - new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}), - config); - assertNotNull(response); - assertEquals("UMTS-AUTS", response.type); - assertEquals(":2233", response.response); - } - - /** - * Verify that anonymous identity should be a valid format based on MCC/MNC of current SIM. - */ - @Test - public void getAnonymousIdentityWithSim() { - String mccmnc = "123456"; - String expectedIdentity = ANONYMOUS_IDENTITY; - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn(mccmnc); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(expectedIdentity, - mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(config)); - } - - /** - * Verify that anonymous identity should be {@code null} when SIM is absent. - */ - @Test - public void getAnonymousIdentityWithoutSim() { - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - - assertNull(mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(config)); - } - - /** - * Verify SIM is present. - */ - @Test - public void isSimPresentWithValidSubscriptionIdList() { - SubscriptionInfo subInfo1 = mock(SubscriptionInfo.class); - when(subInfo1.getSubscriptionId()).thenReturn(DATA_SUBID); - SubscriptionInfo subInfo2 = mock(SubscriptionInfo.class); - when(subInfo2.getSubscriptionId()).thenReturn(NON_DATA_SUBID); - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Arrays.asList(subInfo1, subInfo2)); - assertTrue(mWifiCarrierInfoManager.isSimPresent(DATA_SUBID)); - } - - /** - * Verify SIM is not present. - */ - @Test - public void isSimPresentWithInvalidOrEmptySubscriptionIdList() { - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Collections.emptyList()); - - assertFalse(mWifiCarrierInfoManager.isSimPresent(DATA_SUBID)); - - SubscriptionInfo subInfo = mock(SubscriptionInfo.class); - when(subInfo.getSubscriptionId()).thenReturn(NON_DATA_SUBID); - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Arrays.asList(subInfo)); - assertFalse(mWifiCarrierInfoManager.isSimPresent(DATA_SUBID)); - } - - /** - * Verity SIM is consider not present when SIM state is not ready - */ - @Test - public void isSimPresentWithValidSubscriptionIdListWithSimStateNotReady() { - SubscriptionInfo subInfo1 = mock(SubscriptionInfo.class); - when(subInfo1.getSubscriptionId()).thenReturn(DATA_SUBID); - SubscriptionInfo subInfo2 = mock(SubscriptionInfo.class); - when(subInfo2.getSubscriptionId()).thenReturn(NON_DATA_SUBID); - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Arrays.asList(subInfo1, subInfo2)); - when(mTelephonyManager.getSimState(anyInt())) - .thenReturn(TelephonyManager.SIM_STATE_NETWORK_LOCKED); - assertFalse(mWifiCarrierInfoManager.isSimPresent(DATA_SUBID)); - } - - /** - * The active SubscriptionInfo List may be null or empty from Telephony. - */ - @Test - public void getBestMatchSubscriptionIdWithEmptyActiveSubscriptionInfoList() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null); - when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[0]); - - assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); - - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Collections.emptyList()); - - assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); - } - - /** - * The matched Subscription ID should be that of data SIM when carrier ID is not specified. - */ - @Test - public void getBestMatchSubscriptionIdForEnterpriseWithoutCarrierIdFieldForSimConfig() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(DATA_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); - } - - /** - * The matched Subscription ID should be invalid if the configuration does not require - * SIM card and the carrier ID is not specified. - */ - @Test - public void getBestMatchSubscriptionIdForEnterpriseWithoutCarrierIdFieldForNonSimConfig() { - WifiConfiguration config = new WifiConfiguration(); - - assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); - } - - /** - * If the carrier ID is specifed for EAP-SIM configuration, the corresponding Subscription ID - * should be returned. - */ - @Test - public void getBestMatchSubscriptionIdForEnterpriseWithNonDataCarrierId() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - config.carrierId = NON_DATA_CARRIER_ID; - - assertEquals(NON_DATA_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); - - config.carrierId = DATA_CARRIER_ID; - assertEquals(DATA_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); - } - - /** - * If the passpoint profile have valid carrier ID, the matching sub ID should be returned. - */ - @Test - public void getBestMatchSubscriptionIdForPasspointWithValidCarrierId() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - config.carrierId = DATA_CARRIER_ID; - WifiConfiguration spyConfig = spy(config); - doReturn(true).when(spyConfig).isPasspoint(); - - assertEquals(DATA_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(spyConfig)); - } - - /** - * If there is no matching SIM card, the matching sub ID should be invalid. - */ - @Test - public void getBestMatchSubscriptionIdForPasspointInvalidCarrierId() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - WifiConfiguration spyConfig = spy(config); - doReturn(true).when(spyConfig).isPasspoint(); - - assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(spyConfig)); - } - - /** - * The matched Subscription ID should be invalid if the SIM card for the specified carrier ID - * is absent. - */ - @Test - public void getBestMatchSubscriptionIdWithDeactiveCarrierId() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE); - config.carrierId = DEACTIVE_CARRIER_ID; - - assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); - } - - /** - * Verify that the result is null if no active SIM is matched. - */ - @Test - public void getMatchingImsiCarrierIdWithDeactiveCarrierId() { - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Collections.emptyList()); - - assertNull(mWifiCarrierInfoManager.getMatchingImsi(DEACTIVE_CARRIER_ID)); - } - - /** - * Verify that a SIM is matched with carrier ID, and it requires IMSI encryption, - * when the IMSI encryption info is not available, it should return null. - */ - @Test - public void getMatchingImsiCarrierIdWithValidCarrierIdForImsiEncryptionCheck() { - WifiCarrierInfoManager spyTu = spy(mWifiCarrierInfoManager); - doReturn(true).when(spyTu).requiresImsiEncryption(DATA_SUBID); - doReturn(false).when(spyTu).isImsiEncryptionInfoAvailable(DATA_SUBID); - - assertNull(spyTu.getMatchingImsi(DATA_CARRIER_ID)); - } - - /** - * Verify that if there is SIM card whose carrier ID is the same as the input, the correct IMSI - * and carrier ID would be returned. - */ - @Test - public void getMatchingImsiCarrierIdWithValidCarrierId() { - assertEquals(DATA_FULL_IMSI, - mWifiCarrierInfoManager.getMatchingImsi(DATA_CARRIER_ID)); - } - - /** - * Verify that if there is no SIM, it should match nothing. - */ - @Test - public void getMatchingImsiCarrierIdWithEmptyActiveSubscriptionInfoList() { - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null); - - assertNull(mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); - - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Collections.emptyList()); - - assertNull(mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); - } - - /** - * Verify that if there is no matching SIM, it should match nothing. - */ - @Test - public void getMatchingImsiCarrierIdWithNoMatchImsi() { - // data SIM is MNO. - when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); - when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); - // non data SIM is MNO. - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - - assertNull(mWifiCarrierInfoManager.getMatchingImsiCarrierId(NO_MATCH_PREFIX_IMSI)); - } - - /** - * Verify that if the matched SIM is the default data SIM and a MNO SIM, the information of it - * should be returned. - */ - @Test - public void getMatchingImsiCarrierIdForDataAndMnoSimMatch() { - // data SIM is MNO. - when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); - when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); - // non data SIM is MNO. - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - - Pair<String, Integer> ic = mWifiCarrierInfoManager - .getMatchingImsiCarrierId(MATCH_PREFIX_IMSI); - - assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), ic); - - // non data SIM is MVNO - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()) - .thenReturn(PARENT_NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - - assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), - mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); - - // non data SIM doesn't match. - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); - when(mNonDataTelephonyManager.getSimOperator()) - .thenReturn(NO_MATCH_OPERATOR_NUMERIC); - - assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), - mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); - } - - /** - * Verify that if the matched SIM is the default data SIM and a MVNO SIM, and no MNO SIM was - * matched, the information of it should be returned. - */ - @Test - public void getMatchingImsiCarrierIdForDataAndMvnoSimMatch() { - // data SIM is MVNO. - when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(PARENT_DATA_CARRIER_ID); - when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); - // non data SIM is MVNO. - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()) - .thenReturn(PARENT_NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - - Pair<String, Integer> ic = mWifiCarrierInfoManager - .getMatchingImsiCarrierId(MATCH_PREFIX_IMSI); - - assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), ic); - - // non data SIM doesn't match. - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); - when(mNonDataTelephonyManager.getSimOperator()) - .thenReturn(NO_MATCH_OPERATOR_NUMERIC); - - assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), - mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); - } - - /** - * Verify that if the matched SIM is a MNO SIM, even the default data SIM is matched as a MVNO - * SIM, the information of MNO SIM still should be returned. - */ - @Test - public void getMatchingImsiCarrierIdForNonDataAndMnoSimMatch() { - // data SIM is MVNO. - when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(PARENT_DATA_CARRIER_ID); - when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); - // non data SIM is MNO. - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - - - Pair<String, Integer> ic = mWifiCarrierInfoManager - .getMatchingImsiCarrierId(MATCH_PREFIX_IMSI); - - assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID), ic); - - // data SIM doesn't match - when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); - when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); - when(mDataTelephonyManager.getSimOperator()).thenReturn(NO_MATCH_OPERATOR_NUMERIC); - - assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID), - mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); - } - - /** - * Verify that if only a MVNO SIM is matched, the information of it should be returned. - */ - @Test - public void getMatchingImsiCarrierIdForMvnoSimMatch() { - // data SIM is MNO, but IMSI doesn't match. - when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); - when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); - when(mDataTelephonyManager.getSimOperator()).thenReturn(NO_MATCH_OPERATOR_NUMERIC); - // non data SIM is MVNO. - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()) - .thenReturn(PARENT_NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - - assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID), - mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); - } - - /** - * Verify that a SIM is matched, and it requires IMSI encryption, when the IMSI encryption - * info is not available, it should return null. - */ - @Test - public void getMatchingImsiCarrierIdForImsiEncryptionCheck() { - // data SIM is MNO. - when(mDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(DATA_CARRIER_ID); - when(mDataTelephonyManager.getSimCarrierId()).thenReturn(DATA_CARRIER_ID); - // non data SIM does not match. - when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID); - when(mNonDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI); - when(mNonDataTelephonyManager.getSimOperator()) - .thenReturn(NO_MATCH_OPERATOR_NUMERIC); - WifiCarrierInfoManager spyTu = spy(mWifiCarrierInfoManager); - doReturn(true).when(spyTu).requiresImsiEncryption(eq(DATA_SUBID)); - doReturn(false).when(spyTu).isImsiEncryptionInfoAvailable(eq(DATA_SUBID)); - - assertNull(spyTu.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI)); - } - - /** - * Verify that if there is no any SIM card, the carrier ID should be updated. - */ - @Test - public void tryUpdateCarrierIdForPasspointWithEmptyActiveSubscriptionList() { - PasspointConfiguration config = mock(PasspointConfiguration.class); - when(config.getCarrierId()).thenReturn(DATA_CARRIER_ID); - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null); - - assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config)); - - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Collections.emptyList()); - - assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config)); - } - - /** - * Verify that if the carrier ID has been assigned, it shouldn't be updated. - */ - @Test - public void tryUpdateCarrierIdForPasspointWithValidCarrieId() { - PasspointConfiguration config = mock(PasspointConfiguration.class); - when(config.getCarrierId()).thenReturn(DATA_CARRIER_ID); - - assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config)); - } - - /** - * Verify that if the passpoint profile doesn't have SIM credential, it shouldn't be updated. - */ - @Test - public void tryUpdateCarrierIdForPasspointWithNonSimCredential() { - Credential credential = mock(Credential.class); - PasspointConfiguration spyConfig = spy(new PasspointConfiguration()); - doReturn(credential).when(spyConfig).getCredential(); - when(credential.getSimCredential()).thenReturn(null); - - assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(spyConfig)); - } - - /** - * Verify that if the passpoint profile only have IMSI prefix(mccmnc*) parameter, - * it shouldn't be updated. - */ - @Test - public void tryUpdateCarrierIdForPasspointWithPrefixImsi() { - Credential credential = mock(Credential.class); - PasspointConfiguration spyConfig = spy(new PasspointConfiguration()); - doReturn(credential).when(spyConfig).getCredential(); - Credential.SimCredential simCredential = mock(Credential.SimCredential.class); - when(credential.getSimCredential()).thenReturn(simCredential); - when(simCredential.getImsi()).thenReturn(MATCH_PREFIX_IMSI); - - assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(spyConfig)); - } - - /** - * Verify that if the passpoint profile has the full IMSI and wasn't assigned valid - * carrier ID, it should be updated. - */ - @Test - public void tryUpdateCarrierIdForPasspointWithFullImsiAndActiveSim() { - Credential credential = mock(Credential.class); - PasspointConfiguration spyConfig = spy(new PasspointConfiguration()); - doReturn(credential).when(spyConfig).getCredential(); - Credential.SimCredential simCredential = mock(Credential.SimCredential.class); - when(credential.getSimCredential()).thenReturn(simCredential); - when(simCredential.getImsi()).thenReturn(DATA_FULL_IMSI); - - assertTrue(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(spyConfig)); - assertEquals(DATA_CARRIER_ID, spyConfig.getCarrierId()); - } - - /** - * Verify that if there is no SIM card matching the given IMSI, it shouldn't be updated. - */ - @Test - public void tryUpdateCarrierIdForPasspointWithFullImsiAndInactiveSim() { - Credential credential = mock(Credential.class); - PasspointConfiguration spyConfig = spy(new PasspointConfiguration()); - doReturn(credential).when(spyConfig).getCredential(); - Credential.SimCredential simCredential = mock(Credential.SimCredential.class); - when(credential.getSimCredential()).thenReturn(simCredential); - when(simCredential.getImsi()).thenReturn(NO_MATCH_PREFIX_IMSI); - - assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(spyConfig)); - } - - private void testIdentityWithSimAndEapAkaMethodPrefix(int method, String methodStr) - throws Exception { - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(true, true)); - when(mCarrierConfigManager.getConfigForSubId(NON_DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - - assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - - String mccmnc = "123456"; - String expectedIdentity = methodStr + ANONYMOUS_IDENTITY; - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn(mccmnc); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - method, WifiEnterpriseConfig.Phase2.NONE); - - assertEquals(expectedIdentity, - mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(config)); - } - - /** - * Verify that EAP Method prefix is added to the anonymous identity when required - */ - @Test - public void getAnonymousIdentityWithSimAndEapAkaMethodPrefix() throws Exception { - testIdentityWithSimAndEapAkaMethodPrefix(WifiEnterpriseConfig.Eap.AKA, "0"); - } - - /** - * Verify that EAP Method prefix is added to the anonymous identity when required - */ - @Test - public void getAnonymousIdentityWithSimAndEapSimMethodPrefix() throws Exception { - testIdentityWithSimAndEapAkaMethodPrefix(WifiEnterpriseConfig.Eap.SIM, "1"); - } - - /** - * Verify that EAP Method prefix is added to the anonymous identity when required - */ - @Test - public void getAnonymousIdentityWithSimAndEapAkaPrimeMethodPrefix() throws Exception { - testIdentityWithSimAndEapAkaMethodPrefix(WifiEnterpriseConfig.Eap.AKA_PRIME, "6"); - } - - /** - * Verify that isAnonymousAtRealmIdentity works as expected for anonymous identities with and - * without a prefix. - */ - @Test - public void testIsAnonymousAtRealmIdentity() throws Exception { - assertTrue(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity(ANONYMOUS_IDENTITY)); - assertTrue(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity("0" + ANONYMOUS_IDENTITY)); - assertTrue(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity("1" + ANONYMOUS_IDENTITY)); - assertTrue(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity("6" + ANONYMOUS_IDENTITY)); - assertFalse(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity("AKA" + ANONYMOUS_IDENTITY)); - } - - /** - * Verify when no subscription available, get carrier id for target package will return - * UNKNOWN_CARRIER_ID. - */ - @Test - public void getCarrierPrivilegeWithNoActiveSubscription() { - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null); - assertEquals(TelephonyManager.UNKNOWN_CARRIER_ID, - mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE)); - - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Collections.emptyList()); - assertEquals(TelephonyManager.UNKNOWN_CARRIER_ID, - mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE)); - } - - /** - * Verify when package has no carrier privileges, get carrier id for that package will return - * UNKNOWN_CARRIER_ID. - */ - @Test - public void getCarrierPrivilegeWithPackageHasNoPrivilege() { - SubscriptionInfo subInfo = mock(SubscriptionInfo.class); - when(subInfo.getSubscriptionId()).thenReturn(DATA_SUBID); - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Arrays.asList(subInfo)); - when(mDataTelephonyManager.checkCarrierPrivilegesForPackage(TEST_PACKAGE)) - .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS); - assertEquals(TelephonyManager.UNKNOWN_CARRIER_ID, - mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE)); - } - - /** - * Verify when package get carrier privileges from carrier, get carrier id for that package will - * return the carrier id for that carrier. - */ - @Test - public void getCarrierPrivilegeWithPackageHasPrivilege() { - SubscriptionInfo subInfo = mock(SubscriptionInfo.class); - when(subInfo.getSubscriptionId()).thenReturn(DATA_SUBID); - when(subInfo.getCarrierId()).thenReturn(DATA_CARRIER_ID); - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Arrays.asList(subInfo)); - when(mDataTelephonyManager.checkCarrierPrivilegesForPackage(TEST_PACKAGE)) - .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS); - assertEquals(DATA_CARRIER_ID, - mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE)); - } - - /** - * Verify getCarrierNameforSubId returns right value. - */ - @Test - public void getCarrierNameFromSubId() { - assertEquals(CARRIER_NAME, mWifiCarrierInfoManager.getCarrierNameforSubId(DATA_SUBID)); - assertNull(mWifiCarrierInfoManager.getCarrierNameforSubId(NON_DATA_SUBID)); - } - - @Test - public void testIsCarrierNetworkFromNonDataSim() { - WifiConfiguration config = new WifiConfiguration(); - assertFalse(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)); - config.carrierId = DATA_CARRIER_ID; - assertFalse(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)); - config.carrierId = NON_DATA_CARRIER_ID; - assertTrue(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)); - } - - @Test - public void testCheckSetClearImsiProtectionExemption() { - InOrder inOrder = inOrder(mWifiConfigManager); - assertFalse(mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID)); - mWifiCarrierInfoManager.setHasUserApprovedImsiPrivacyExemptionForCarrier(true, - DATA_CARRIER_ID); - verify(mListener).onUserAllowed(DATA_CARRIER_ID); - inOrder.verify(mWifiConfigManager).saveToStore(true); - assertTrue(mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID)); - mWifiCarrierInfoManager.clearImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID); - inOrder.verify(mWifiConfigManager).saveToStore(true); - assertFalse(mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID)); - } - - @Test - public void testSendImsiProtectionExemptionNotificationWithUserAllowed() { - // Setup carrier without IMSI privacy protection - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - // Simulate user clicking on allow in the notification. - sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION, - CARRIER_NAME, DATA_CARRIER_ID); - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - verify(mWifiMetrics).addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false); - verify(mWifiConfigManager).saveToStore(true); - assertTrue(mImsiDataSource.hasNewDataToSerialize()); - assertTrue(mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID)); - verify(mListener).onUserAllowed(DATA_CARRIER_ID); - verify(mWifiMetrics).addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false); - } - - @Test - public void testSendImsiProtectionExemptionNotificationWithUserDisallowed() { - // Setup carrier without IMSI privacy protection - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - // Simulate user clicking on disallow in the notification. - sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION, - CARRIER_NAME, DATA_CARRIER_ID); - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - verify(mAlertDialog, never()).show(); - - verify(mWifiConfigManager).saveToStore(true); - assertTrue(mImsiDataSource.hasNewDataToSerialize()); - assertFalse(mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID)); - verify(mListener, never()).onUserAllowed(DATA_CARRIER_ID); - verify(mWifiMetrics).addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_DISALLOWED_CARRIER, false); - } - - @Test - public void testSendImsiProtectionExemptionNotificationWithUserDismissal() { - // Setup carrier without IMSI privacy protection - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - //Simulate user dismissal the notification - sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISMISSED_INTENT_ACTION, - CARRIER_NAME, DATA_CARRIER_ID); - verify(mWifiMetrics).addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_DISMISS, false); - reset(mNotificationManger); - // No Notification is active, should send notification again. - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - reset(mNotificationManger); - - // As there is notification is active, should not send notification again. - sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISMISSED_INTENT_ACTION, - CARRIER_NAME, DATA_CARRIER_ID); - verifyNoMoreInteractions(mNotificationManger); - verify(mWifiConfigManager, never()).saveToStore(true); - assertFalse(mImsiDataSource.hasNewDataToSerialize()); - assertFalse(mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID)); - verify(mListener, never()).onUserAllowed(DATA_CARRIER_ID); - } - - @Test - public void testSendImsiProtectionExemptionConfirmationDialogWithUserDisallowed() { - // Setup carrier without IMSI privacy protection - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - // Simulate user clicking on the notification. - sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION, - CARRIER_NAME, DATA_CARRIER_ID); - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - validateUserApprovalDialog(CARRIER_NAME); - - // Simulate user clicking on disallow in the dialog. - ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor = - ArgumentCaptor.forClass(DialogInterface.OnClickListener.class); - verify(mAlertDialogBuilder, atLeastOnce()).setNegativeButton( - any(), clickListenerCaptor.capture()); - assertNotNull(clickListenerCaptor.getValue()); - clickListenerCaptor.getValue().onClick(mAlertDialog, 0); - mLooper.dispatchAll(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendBroadcast(intentCaptor.capture()); - assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction()); - verify(mWifiConfigManager).saveToStore(true); - assertTrue(mImsiDataSource.hasNewDataToSerialize()); - assertFalse(mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID)); - verify(mListener, never()).onUserAllowed(DATA_CARRIER_ID); - verify(mWifiMetrics).addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_DISALLOWED_CARRIER, true); - } - - @Test - public void testSendImsiProtectionExemptionConfirmationDialogWithUserDismissal() { - // Setup carrier without IMSI privacy protection - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - // Simulate user clicking on the notification. - sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION, - CARRIER_NAME, DATA_CARRIER_ID); - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - validateUserApprovalDialog(CARRIER_NAME); - - // Simulate user clicking on dismissal in the dialog. - ArgumentCaptor<DialogInterface.OnDismissListener> dismissListenerCaptor = - ArgumentCaptor.forClass(DialogInterface.OnDismissListener.class); - verify(mAlertDialogBuilder, atLeastOnce()).setOnDismissListener( - dismissListenerCaptor.capture()); - assertNotNull(dismissListenerCaptor.getValue()); - dismissListenerCaptor.getValue().onDismiss(mAlertDialog); - mLooper.dispatchAll(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendBroadcast(intentCaptor.capture()); - assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction()); - - // As no notification is active, new notification should be sent - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - - verify(mWifiConfigManager, never()).saveToStore(true); - assertFalse(mImsiDataSource.hasNewDataToSerialize()); - assertFalse(mWifiCarrierInfoManager - .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID)); - verify(mListener, never()).onUserAllowed(DATA_CARRIER_ID); - verify(mWifiMetrics).addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_DISMISS, true); - } - - @Test - public void testSendImsiProtectionExemptionDialogWithUserAllowed() { - // Setup carrier without IMSI privacy protection - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - // Simulate user clicking on the notification. - sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION, - CARRIER_NAME, DATA_CARRIER_ID); - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - validateUserApprovalDialog(CARRIER_NAME); - - // Simulate user clicking on allow in the dialog. - ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor = - ArgumentCaptor.forClass(DialogInterface.OnClickListener.class); - verify(mAlertDialogBuilder, atLeastOnce()).setPositiveButton( - any(), clickListenerCaptor.capture()); - assertNotNull(clickListenerCaptor.getValue()); - clickListenerCaptor.getValue().onClick(mAlertDialog, 0); - mLooper.dispatchAll(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendBroadcast(intentCaptor.capture()); - assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction()); - verify(mWifiConfigManager).saveToStore(true); - assertTrue(mImsiDataSource.hasNewDataToSerialize()); - verify(mListener).onUserAllowed(DATA_CARRIER_ID); - verify(mWifiMetrics).addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, true); - } - - @Test - public void testUserDataStoreIsNotLoadedNotificationWillNotBeSent() { - // reset data source to unloaded state. - mImsiDataSource.reset(); - // Setup carrier without IMSI privacy protection - when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID)) - .thenReturn(generateTestCarrierConfig(false)); - ArgumentCaptor<BroadcastReceiver> receiver = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); - - receiver.getValue().onReceive(mContext, - new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID)); - - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - verifyNoMoreInteractions(mNotificationManger); - - // Loaded user data store, notification should be sent - mImsiDataSource.fromDeserialized(new HashMap<>()); - mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID); - validateImsiProtectionNotification(CARRIER_NAME); - } - - private void validateImsiProtectionNotification(String carrierName) { - verify(mNotificationManger, atLeastOnce()).notify( - eq(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE), - eq(mNotification)); - ArgumentCaptor<CharSequence> contentCaptor = - ArgumentCaptor.forClass(CharSequence.class); - verify(mNotificationBuilder, atLeastOnce()).setContentTitle(contentCaptor.capture()); - CharSequence content = contentCaptor.getValue(); - assertNotNull(content); - assertTrue(content.toString().contains(carrierName)); - } - - private void validateUserApprovalDialog(String... anyOfExpectedAppNames) { - verify(mAlertDialog, atLeastOnce()).show(); - ArgumentCaptor<CharSequence> contentCaptor = - ArgumentCaptor.forClass(CharSequence.class); - verify(mAlertDialogBuilder, atLeastOnce()).setMessage(contentCaptor.capture()); - CharSequence content = contentCaptor.getValue(); - assertNotNull(content); - - boolean foundMatch = false; - for (int i = 0; i < anyOfExpectedAppNames.length; i++) { - foundMatch = content.toString().contains(anyOfExpectedAppNames[i]); - if (foundMatch) break; - } - assertTrue(foundMatch); - } - - private void sendBroadcastForUserActionOnImsi(String action, String carrierName, - int carrierId) { - Intent intent = new Intent() - .setAction(action) - .putExtra(WifiCarrierInfoManager.EXTRA_CARRIER_NAME, carrierName) - .putExtra(WifiCarrierInfoManager.EXTRA_CARRIER_ID, carrierId); - assertNotNull(mBroadcastReceiverCaptor.getValue()); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiChannelUtilizationTest.java b/tests/wifitests/src/com/android/server/wifi/WifiChannelUtilizationTest.java deleted file mode 100644 index bb6ff74a3..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiChannelUtilizationTest.java +++ /dev/null @@ -1,459 +0,0 @@ -/** - * Copyright (C) 2019 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.server.wifi; - -import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_STATIONARY; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; -import static com.android.server.wifi.WifiChannelUtilization.CHANNEL_STATS_CACHE_SIZE; -import static com.android.server.wifi.WifiChannelUtilization.DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; -import static com.android.server.wifi.WifiChannelUtilization.RADIO_ON_TIME_DIFF_MIN_MS; -import static com.android.server.wifi.WifiChannelUtilization.UNKNOWN_FREQ; -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.INVALID; -import static com.android.server.wifi.util.InformationElementUtil.BssLoad.MAX_CHANNEL_UTILIZATION; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.validateMockitoUsage; - -import android.content.Context; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiLinkLayerStats.ChannelStats; -import com.android.server.wifi.util.InformationElementUtil.BssLoad; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.WifiChannelUtilization}. - */ -@SmallTest -public class WifiChannelUtilizationTest extends WifiBaseTest { - private WifiChannelUtilization mWifiChannelUtilization; - @Mock private Clock mClock; - @Mock Context mContext; - MockResources mMockResources = new MockResources(); - /** - * Called before each test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mContext.getResources()).thenReturn(mMockResources); - mMockResources.setBoolean( - R.bool.config_wifiChannelUtilizationOverrideEnabled, - false); - mWifiChannelUtilization = new WifiChannelUtilization(mClock, mContext); - mWifiChannelUtilization.init(null); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - @Test - public void verifyEmptyLinkLayerStats() throws Exception { - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(null, UNKNOWN_FREQ); - assertEquals(INVALID, mWifiChannelUtilization.getUtilizationRatio(5180)); - } - - @Test - public void verifyEmptyChanStatsMap() throws Exception { - WifiLinkLayerStats llstats = new WifiLinkLayerStats(); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats, UNKNOWN_FREQ); - assertEquals(INVALID, mWifiChannelUtilization.getUtilizationRatio(5180)); - } - - @Test - public void verifyOneReadChanStatsWithShortRadioOnTime() throws Exception { - WifiLinkLayerStats llstats = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs = new ChannelStats(); - cs.frequency = freq; - cs.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 2; - cs.ccaBusyTimeMs = 2; - llstats.channelStatsMap.put(freq, cs); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats, UNKNOWN_FREQ); - assertEquals(INVALID, mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyOneReadChanStatsWithLargeCcaBusyTime() throws Exception { - WifiLinkLayerStats llstats = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs = new ChannelStats(); - cs.frequency = freq; - cs.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 2; - cs.ccaBusyTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 2 * 19 / 20; - llstats.channelStatsMap.put(freq, cs); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats, UNKNOWN_FREQ); - assertEquals(INVALID, mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyOneReadChanStatsWithLongRadioOnTime() throws Exception { - WifiLinkLayerStats llstats = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs = new ChannelStats(); - cs.frequency = freq; - cs.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS + 1; - cs.ccaBusyTimeMs = 20; - llstats.channelStatsMap.put(freq, cs); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats, freq); - assertEquals(cs.ccaBusyTimeMs * MAX_CHANNEL_UTILIZATION / cs.radioOnTimeMs, - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyOneReadChanStatsWithDiffFreq() throws Exception { - WifiLinkLayerStats llstats = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs = new ChannelStats(); - cs.frequency = freq; - cs.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS + 1; - cs.ccaBusyTimeMs = 20; - llstats.channelStatsMap.put(freq, cs); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats, 5200); - assertEquals(BssLoad.INVALID, mWifiChannelUtilization.getUtilizationRatio(5200)); - } - - @Test - public void verifyTwoReadChanStatsWithLargeTimeGap() throws Exception { - WifiLinkLayerStats llstats1 = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs1 = new ChannelStats(); - cs1.frequency = freq; - cs1.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS; - cs1.ccaBusyTimeMs = 20; - llstats1.channelStatsMap.put(freq, cs1); - long currentTimeStamp = 1 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, freq); - - WifiLinkLayerStats llstats2 = new WifiLinkLayerStats(); - ChannelStats cs2 = new ChannelStats(); - cs2.frequency = freq; - cs2.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 2 + 1; - cs2.ccaBusyTimeMs = 30; - llstats2.channelStatsMap.put(freq, cs2); - currentTimeStamp = 1 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS * 2; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats2, freq); - - assertEquals((cs2.ccaBusyTimeMs - cs1.ccaBusyTimeMs) * MAX_CHANNEL_UTILIZATION - / (cs2.radioOnTimeMs - cs1.radioOnTimeMs), - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyTwoReadChanStatsWithSmallTimeGap() throws Exception { - WifiLinkLayerStats llstats1 = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs1 = new ChannelStats(); - cs1.frequency = freq; - cs1.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS + 1; - cs1.ccaBusyTimeMs = 20; - llstats1.channelStatsMap.put(freq, cs1); - long currentTimeStamp = DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS / 2; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, UNKNOWN_FREQ); - - WifiLinkLayerStats llstats2 = new WifiLinkLayerStats(); - ChannelStats cs2 = new ChannelStats(); - cs2.frequency = freq; - cs2.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 2 + 2; - cs2.ccaBusyTimeMs = 30; - llstats2.channelStatsMap.put(freq, cs2); - currentTimeStamp = 1 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats2, UNKNOWN_FREQ); - - assertEquals((cs2.ccaBusyTimeMs - cs1.ccaBusyTimeMs) * MAX_CHANNEL_UTILIZATION - / (cs2.radioOnTimeMs - cs1.radioOnTimeMs), - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyThreeReadChanStatsRefWithSecondLast() throws Exception { - WifiLinkLayerStats llstats1 = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs1 = new ChannelStats(); - cs1.frequency = freq; - cs1.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 2; - cs1.ccaBusyTimeMs = 20; - llstats1.channelStatsMap.put(freq, cs1); - long currentTimeStamp = 1 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, UNKNOWN_FREQ); - - WifiLinkLayerStats llstats2 = new WifiLinkLayerStats(); - ChannelStats cs2 = new ChannelStats(); - cs2.frequency = freq; - cs2.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS + 4; - cs2.ccaBusyTimeMs = 30; - llstats2.channelStatsMap.put(freq, cs2); - currentTimeStamp = 2 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS * 2; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats2, UNKNOWN_FREQ); - - WifiLinkLayerStats llstats3 = new WifiLinkLayerStats(); - ChannelStats cs3 = new ChannelStats(); - cs3.frequency = freq; - cs3.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 3 / 2 + 4; - cs3.ccaBusyTimeMs = 70; - llstats3.channelStatsMap.put(freq, cs3); - currentTimeStamp = 3 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS * 3; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats3, UNKNOWN_FREQ); - - if (CHANNEL_STATS_CACHE_SIZE > 1) { - assertEquals((cs3.ccaBusyTimeMs - cs1.ccaBusyTimeMs) * MAX_CHANNEL_UTILIZATION - / (cs3.radioOnTimeMs - cs1.radioOnTimeMs), - mWifiChannelUtilization.getUtilizationRatio(freq)); - } else { - assertEquals(cs3.ccaBusyTimeMs * MAX_CHANNEL_UTILIZATION / cs3.radioOnTimeMs, - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - } - - @Test - public void verifyThreeReadChanStatsLargeTimeGap() throws Exception { - WifiLinkLayerStats llstats1 = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs1 = new ChannelStats(); - cs1.frequency = freq; - cs1.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 4; - cs1.ccaBusyTimeMs = 20; - llstats1.channelStatsMap.put(freq, cs1); - long currentTimeStamp = 1 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, UNKNOWN_FREQ); - - WifiLinkLayerStats llstats2 = new WifiLinkLayerStats(); - ChannelStats cs2 = new ChannelStats(); - cs2.frequency = freq; - cs2.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 2; - cs2.ccaBusyTimeMs = 30; - llstats2.channelStatsMap.put(freq, cs2); - currentTimeStamp = 2 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS * 2; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats2, UNKNOWN_FREQ); - - WifiLinkLayerStats llstats3 = new WifiLinkLayerStats(); - ChannelStats cs3 = new ChannelStats(); - cs3.frequency = freq; - cs3.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 3; - cs3.ccaBusyTimeMs = 70; - llstats3.channelStatsMap.put(freq, cs3); - currentTimeStamp = 3 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS * 3; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats3, UNKNOWN_FREQ); - - assertEquals((cs3.ccaBusyTimeMs - cs2.ccaBusyTimeMs) * MAX_CHANNEL_UTILIZATION - / (cs3.radioOnTimeMs - cs2.radioOnTimeMs), - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyThreeReadChanStatsSmallTimeGap() throws Exception { - WifiLinkLayerStats llstats1 = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs1 = new ChannelStats(); - cs1.frequency = freq; - cs1.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 4; - cs1.ccaBusyTimeMs = 20; - llstats1.channelStatsMap.put(freq, cs1); - - long currentTimeStamp = DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS / 4; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, UNKNOWN_FREQ); - - currentTimeStamp = DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS / 2; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, UNKNOWN_FREQ); - - WifiLinkLayerStats llstats3 = new WifiLinkLayerStats(); - ChannelStats cs3 = new ChannelStats(); - cs3.frequency = freq; - cs3.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 3; - cs3.ccaBusyTimeMs = 70; - llstats3.channelStatsMap.put(freq, cs3); - currentTimeStamp = DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats3, UNKNOWN_FREQ); - - assertEquals((cs3.ccaBusyTimeMs - cs1.ccaBusyTimeMs) * MAX_CHANNEL_UTILIZATION - / (cs3.radioOnTimeMs - cs1.radioOnTimeMs), - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyThreeReadChanStatsInitAfterOneRead() throws Exception { - WifiLinkLayerStats llstats1 = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs1 = new ChannelStats(); - cs1.frequency = freq; - cs1.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 4; - cs1.ccaBusyTimeMs = 20; - llstats1.channelStatsMap.put(freq, cs1); - - long currentTimeStamp = DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS + 1; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, UNKNOWN_FREQ); - - mWifiChannelUtilization.init(llstats1); - WifiLinkLayerStats llstats2 = new WifiLinkLayerStats(); - ChannelStats cs2 = new ChannelStats(); - cs2.frequency = freq; - cs2.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 2 + 1; - cs2.ccaBusyTimeMs = 40; - currentTimeStamp = DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS * 2 + 1; - llstats2.channelStatsMap.put(freq, cs2); - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats2, UNKNOWN_FREQ); - - assertEquals(INVALID, mWifiChannelUtilization.getUtilizationRatio(freq)); - - WifiLinkLayerStats llstats3 = new WifiLinkLayerStats(); - ChannelStats cs3 = new ChannelStats(); - cs3.frequency = freq; - cs3.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 3 + 1; - cs3.ccaBusyTimeMs = 70; - llstats3.channelStatsMap.put(freq, cs3); - currentTimeStamp = DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats3, UNKNOWN_FREQ); - - assertEquals((cs3.ccaBusyTimeMs - cs2.ccaBusyTimeMs) * MAX_CHANNEL_UTILIZATION - / (cs3.radioOnTimeMs - cs2.radioOnTimeMs), - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyThreeReadChanStatsAlwaysStationary() throws Exception { - mWifiChannelUtilization.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY); - WifiLinkLayerStats llstats1 = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs1 = new ChannelStats(); - cs1.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 8; - cs1.ccaBusyTimeMs = 10; - llstats1.channelStatsMap.put(freq, cs1); - long currentTimeStamp = 0; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, freq); - - WifiLinkLayerStats llstats2 = new WifiLinkLayerStats(); - ChannelStats cs2 = new ChannelStats(); - cs2.frequency = freq; - cs2.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 4; - cs2.ccaBusyTimeMs = 20; - llstats2.channelStatsMap.put(freq, cs2); - currentTimeStamp = 1 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats2, freq); - - WifiLinkLayerStats llstats3 = new WifiLinkLayerStats(); - ChannelStats cs3 = new ChannelStats(); - cs3.frequency = freq; - cs3.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 2; - cs3.ccaBusyTimeMs = 70; - llstats3.channelStatsMap.put(freq, cs3); - currentTimeStamp = 5 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats3, freq); - - assertEquals((cs3.ccaBusyTimeMs - cs1.ccaBusyTimeMs) * MAX_CHANNEL_UTILIZATION - / (cs3.radioOnTimeMs - cs1.radioOnTimeMs), - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyThreeReadChanStatsStationaryAfterFirstRead() throws Exception { - WifiLinkLayerStats llstats1 = new WifiLinkLayerStats(); - int freq = 5180; - ChannelStats cs1 = new ChannelStats(); - cs1.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 8; - cs1.ccaBusyTimeMs = 10; - llstats1.channelStatsMap.put(freq, cs1); - long currentTimeStamp = 0; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats1, UNKNOWN_FREQ); - - mWifiChannelUtilization.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY); - - WifiLinkLayerStats llstats2 = new WifiLinkLayerStats(); - ChannelStats cs2 = new ChannelStats(); - cs2.frequency = freq; - cs2.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS / 4; - cs2.ccaBusyTimeMs = 20; - llstats2.channelStatsMap.put(freq, cs2); - currentTimeStamp = 1 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats2, UNKNOWN_FREQ); - - WifiLinkLayerStats llstats3 = new WifiLinkLayerStats(); - ChannelStats cs3 = new ChannelStats(); - cs3.frequency = freq; - cs3.radioOnTimeMs = RADIO_ON_TIME_DIFF_MIN_MS * 2; - cs3.ccaBusyTimeMs = 70; - llstats3.channelStatsMap.put(freq, cs3); - currentTimeStamp = 5 + DEFAULT_CACHE_UPDATE_INTERVAL_MIN_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(llstats3, UNKNOWN_FREQ); - - assertEquals((cs3.ccaBusyTimeMs - cs2.ccaBusyTimeMs) * MAX_CHANNEL_UTILIZATION - / (cs3.radioOnTimeMs - cs2.radioOnTimeMs), - mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifySetGetUtilizationRatio() throws Exception { - int freq = 5180; - int utilizationRatio = 24; - mWifiChannelUtilization.setUtilizationRatio(freq, utilizationRatio); - assertEquals(utilizationRatio, mWifiChannelUtilization.getUtilizationRatio(freq)); - } - - @Test - public void verifyOverridingUtilizationRatio() throws Exception { - mMockResources.setBoolean( - R.bool.config_wifiChannelUtilizationOverrideEnabled, - true); - mMockResources.setInteger( - R.integer.config_wifiChannelUtilizationOverride2g, - 60); - mMockResources.setInteger( - R.integer.config_wifiChannelUtilizationOverride5g, - 20); - mMockResources.setInteger( - R.integer.config_wifiChannelUtilizationOverride6g, - 10); - assertEquals(60, mWifiChannelUtilization.getUtilizationRatio(2412)); - assertEquals(20, mWifiChannelUtilization.getUtilizationRatio(5810)); - assertEquals(10, mWifiChannelUtilization.getUtilizationRatio(6710)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java deleted file mode 100644 index 34567e969..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ /dev/null @@ -1,5626 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.net.IpConfiguration; -import android.net.MacAddress; -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.Process; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.test.TestLooper; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.server.wifi.WifiScoreCard.PerNetwork; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; -import com.android.server.wifi.util.LruConnectionTracker; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.WifiConfigManager}. - */ -@SmallTest -public class WifiConfigManagerTest extends WifiBaseTest { - - private static final String TEST_SSID = "\"test_ssid\""; - private static final String TEST_BSSID = "0a:08:5c:67:89:00"; - private static final long TEST_WALLCLOCK_CREATION_TIME_MILLIS = 9845637; - private static final long TEST_WALLCLOCK_UPDATE_TIME_MILLIS = 75455637; - private static final long TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS = 29457631; - private static final int TEST_CREATOR_UID = WifiConfigurationTestUtil.TEST_UID; - private static final int TEST_NO_PERM_UID = 7; - private static final int TEST_UPDATE_UID = 4; - private static final int TEST_SYSUI_UID = 56; - private static final int TEST_DEFAULT_USER = UserHandle.USER_SYSTEM; - private static final int TEST_MAX_NUM_ACTIVE_CHANNELS_FOR_PARTIAL_SCAN = 5; - private static final Integer[] TEST_FREQ_LIST = {2400, 2450, 5150, 5175, 5650}; - private static final String TEST_CREATOR_NAME = "com.wificonfigmanager.creator"; - private static final String TEST_UPDATE_NAME = "com.wificonfigmanager.update"; - private static final String TEST_NO_PERM_NAME = "com.wificonfigmanager.noperm"; - private static final String TEST_WIFI_NAME = "android.uid.system"; - private static final String TEST_DEFAULT_GW_MAC_ADDRESS = "0f:67:ad:ef:09:34"; - private static final String TEST_STATIC_PROXY_HOST_1 = "192.168.48.1"; - private static final int TEST_STATIC_PROXY_PORT_1 = 8000; - private static final String TEST_STATIC_PROXY_EXCLUSION_LIST_1 = ""; - private static final String TEST_PAC_PROXY_LOCATION_1 = "http://bleh"; - private static final String TEST_STATIC_PROXY_HOST_2 = "192.168.1.1"; - private static final int TEST_STATIC_PROXY_PORT_2 = 3000; - private static final String TEST_STATIC_PROXY_EXCLUSION_LIST_2 = ""; - private static final String TEST_PAC_PROXY_LOCATION_2 = "http://blah"; - private static final int TEST_RSSI = -50; - private static final int TEST_FREQUENCY_1 = 2412; - private static final int MAX_BLOCKED_BSSID_PER_NETWORK = 10; - private static final MacAddress TEST_RANDOMIZED_MAC = - MacAddress.fromString("d2:11:19:34:a5:20"); - private static final int DATA_SUBID = 1; - private static final String SYSUI_PACKAGE_NAME = "com.android.systemui"; - - @Mock private Context mContext; - @Mock private Clock mClock; - @Mock private UserManager mUserManager; - @Mock private SubscriptionManager mSubscriptionManager; - @Mock private TelephonyManager mTelephonyManager; - @Mock private TelephonyManager mDataTelephonyManager; - @Mock private WifiKeyStore mWifiKeyStore; - @Mock private WifiConfigStore mWifiConfigStore; - @Mock private PackageManager mPackageManager; - @Mock private WifiPermissionsUtil mWifiPermissionsUtil; - @Mock private WifiPermissionsWrapper mWifiPermissionsWrapper; - @Mock private WifiInjector mWifiInjector; - @Mock private WifiLastResortWatchdog mWifiLastResortWatchdog; - @Mock private NetworkListSharedStoreData mNetworkListSharedStoreData; - @Mock private NetworkListUserStoreData mNetworkListUserStoreData; - @Mock private RandomizedMacStoreData mRandomizedMacStoreData; - @Mock private WifiConfigManager.OnNetworkUpdateListener mWcmListener; - @Mock private FrameworkFacade mFrameworkFacade; - @Mock private DeviceConfigFacade mDeviceConfigFacade; - @Mock private MacAddressUtil mMacAddressUtil; - @Mock private BssidBlocklistMonitor mBssidBlocklistMonitor; - @Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - @Mock private WifiScoreCard mWifiScoreCard; - @Mock private PerNetwork mPerNetwork; - @Mock private WifiMetrics mWifiMetrics; - private LruConnectionTracker mLruConnectionTracker; - - private MockResources mResources; - private InOrder mContextConfigStoreMockOrder; - private InOrder mNetworkListStoreDataMockOrder; - private WifiConfigManager mWifiConfigManager; - private boolean mStoreReadTriggered = false; - private TestLooper mLooper = new TestLooper(); - private MockitoSession mSession; - private WifiCarrierInfoManager mWifiCarrierInfoManager; - - - /** - * Setup the mocks and an instance of WifiConfigManager before each test. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - // Set up the inorder for verifications. This is needed to verify that the broadcasts, - // store writes for network updates followed by network additions are in the expected order. - mContextConfigStoreMockOrder = inOrder(mContext, mWifiConfigStore); - mNetworkListStoreDataMockOrder = - inOrder(mNetworkListSharedStoreData, mNetworkListUserStoreData); - - // Set up the package name stuff & permission override. - when(mContext.getPackageManager()).thenReturn(mPackageManager); - mResources = new MockResources(); - mResources.setBoolean( - R.bool.config_wifi_only_link_same_credential_configurations, true); - mResources.setInteger( - R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels, - TEST_MAX_NUM_ACTIVE_CHANNELS_FOR_PARTIAL_SCAN); - mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, true); - mResources.setInteger(R.integer.config_wifiMaxPnoSsidCount, 16); - when(mContext.getResources()).thenReturn(mResources); - - // Setup UserManager profiles for the default user. - setupUserProfiles(TEST_DEFAULT_USER); - - doAnswer(new AnswerWithArguments() { - public String answer(int uid) throws Exception { - if (uid == TEST_CREATOR_UID) { - return TEST_CREATOR_NAME; - } else if (uid == TEST_UPDATE_UID) { - return TEST_UPDATE_NAME; - } else if (uid == TEST_SYSUI_UID) { - return SYSUI_PACKAGE_NAME; - } else if (uid == TEST_NO_PERM_UID) { - return TEST_NO_PERM_NAME; - } else if (uid == Process.WIFI_UID) { - return TEST_WIFI_NAME; - } - fail("Unexpected UID: " + uid); - return ""; - } - }).when(mPackageManager).getNameForUid(anyInt()); - - when(mContext.getSystemService(ActivityManager.class)) - .thenReturn(mock(ActivityManager.class)); - - when(mWifiKeyStore - .updateNetworkKeys(any(WifiConfiguration.class), any())) - .thenReturn(true); - - setupStoreDataForRead(new ArrayList<>(), new ArrayList<>()); - - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), any())).thenReturn(false); - when(mWifiPermissionsUtil.isProfileOwner(anyInt(), any())).thenReturn(false); - when(mWifiInjector.getWifiNetworkSuggestionsManager()) - .thenReturn(mWifiNetworkSuggestionsManager); - when(mWifiInjector.getBssidBlocklistMonitor()).thenReturn(mBssidBlocklistMonitor); - when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); - when(mWifiInjector.getWifiLastResortWatchdog().shouldIgnoreSsidUpdate()) - .thenReturn(false); - when(mWifiInjector.getMacAddressUtil()).thenReturn(mMacAddressUtil); - when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(true); - when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(TEST_RANDOMIZED_MAC); - when(mWifiScoreCard.lookupNetwork(any())).thenReturn(mPerNetwork); - - mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager, - mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class), - mock(WifiContext.class), mock(WifiConfigStore.class), mock(Handler.class), - mWifiMetrics); - mLruConnectionTracker = new LruConnectionTracker(100, mContext); - createWifiConfigManager(); - mWifiConfigManager.addOnNetworkUpdateListener(mWcmListener); - // static mocking - mSession = ExtendedMockito.mockitoSession() - .mockStatic(WifiConfigStore.class, withSettings().lenient()) - .strictness(Strictness.LENIENT) - .startMocking(); - when(WifiConfigStore.createUserFiles(anyInt(), anyBoolean())).thenReturn(mock(List.class)); - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - if (mSession != null) { - mSession.finishMocking(); - } - } - - /** - * Verifies that network retrieval via - * {@link WifiConfigManager#getConfiguredNetworks()} and - * {@link WifiConfigManager#getConfiguredNetworksWithPasswords()} works even if we have not - * yet loaded data from store. - */ - @Test - public void testGetConfiguredNetworksBeforeLoadFromStore() { - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - assertTrue(mWifiConfigManager.getConfiguredNetworksWithPasswords().isEmpty()); - } - - /** - * Verifies that network addition via - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} fails if we have not - * yet loaded data from store. - */ - @Test - public void testAddNetworkIsRejectedBeforeLoadFromStore() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - assertFalse( - mWifiConfigManager.addOrUpdateNetwork(openNetwork, TEST_CREATOR_UID).isSuccess()); - } - - /** - * Verifies the {@link WifiConfigManager#saveToStore(boolean)} is rejected until the store has - * been read first using {@link WifiConfigManager#loadFromStore()}. - */ - @Test - public void testSaveToStoreIsRejectedBeforeLoadFromStore() throws Exception { - assertFalse(mWifiConfigManager.saveToStore(true)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - - assertTrue(mWifiConfigManager.loadFromStore()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).read(); - - assertTrue(mWifiConfigManager.saveToStore(true)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean()); - } - - /** - * Verify that a randomized MAC address is generated even if the KeyStore operation fails. - */ - @Test - public void testRandomizedMacIsGeneratedEvenIfKeyStoreFails() { - when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(null); - - // Try adding a network. - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - verifyAddNetworkToWifiConfigManager(openNetwork); - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - - // Verify that we have attempted to generate the MAC address twice (1 retry) - verify(mMacAddressUtil, times(2)).calculatePersistentMac(any(), any()); - assertEquals(1, retrievedNetworks.size()); - - // Verify that despite KeyStore returning null, we are still getting a valid MAC address. - assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, - retrievedNetworks.get(0).getRandomizedMacAddress().toString()); - } - - /** - * Verifies the addition of a single network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - */ - @Test - public void testAddSingleOpenNetwork() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - // Ensure that the newly added network is disabled. - assertEquals(WifiConfiguration.Status.DISABLED, retrievedNetworks.get(0).status); - } - - /** - * Verifies the addition of a WAPI-PSK network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - */ - @Test - public void testAddWapiPskNetwork() { - WifiConfiguration wapiPskNetwork = WifiConfigurationTestUtil.createWapiPskNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(wapiPskNetwork); - - verifyAddNetworkToWifiConfigManager(wapiPskNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - // Ensure that the newly added network is disabled. - assertEquals(WifiConfiguration.Status.DISABLED, retrievedNetworks.get(0).status); - } - - /** - * Verifies the addition of a WAPI-PSK network with hex bytes using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - */ - @Test - public void testAddWapiPskHexNetwork() { - WifiConfiguration wapiPskNetwork = WifiConfigurationTestUtil.createWapiPskNetwork(); - wapiPskNetwork.preSharedKey = - "123456780abcdef0123456780abcdef0"; - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(wapiPskNetwork); - - verifyAddNetworkToWifiConfigManager(wapiPskNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - // Ensure that the newly added network is disabled. - assertEquals(WifiConfiguration.Status.DISABLED, retrievedNetworks.get(0).status); - } - - /** - * Verifies the addition of a WAPI-CERT network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - */ - @Test - public void testAddWapiCertNetwork() { - WifiConfiguration wapiCertNetwork = WifiConfigurationTestUtil.createWapiCertNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(wapiCertNetwork); - - verifyAddNetworkToWifiConfigManager(wapiCertNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - // Ensure that the newly added network is disabled. - assertEquals(WifiConfiguration.Status.DISABLED, retrievedNetworks.get(0).status); - } - - /** - * Verifies the addition of a single network when the corresponding ephemeral network exists. - */ - @Test - public void testAddSingleOpenNetworkWhenCorrespondingEphemeralNetworkExists() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - WifiConfiguration ephemeralNetwork = new WifiConfiguration(openNetwork); - ephemeralNetwork.ephemeral = true; - - verifyAddEphemeralNetworkToWifiConfigManager(ephemeralNetwork); - - NetworkUpdateResult result = addNetworkToWifiConfigManager(openNetwork); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - - verifyNetworkRemoveBroadcast(); - verifyNetworkAddBroadcast(); - - // Verify that the config store write was triggered with this new configuration. - verifyNetworkInConfigStoreData(openNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - // Ensure that the newly added network is disabled. - assertEquals(WifiConfiguration.Status.DISABLED, retrievedNetworks.get(0).status); - } - - /** - * Verifies the addition of an ephemeral network when the corresponding ephemeral network - * exists. - */ - @Test - public void testAddEphemeralNetworkWhenCorrespondingEphemeralNetworkExists() throws Exception { - WifiConfiguration ephemeralNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - ephemeralNetwork.ephemeral = true; - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(ephemeralNetwork); - - WifiConfiguration ephemeralNetwork2 = new WifiConfiguration(ephemeralNetwork); - verifyAddEphemeralNetworkToWifiConfigManager(ephemeralNetwork); - - NetworkUpdateResult result = addNetworkToWifiConfigManager(ephemeralNetwork2); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - verifyNetworkUpdateBroadcast(); - - // Ensure that the write was not invoked for ephemeral network addition. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - } - - /** - * Verifies when adding a new network with already saved MAC, the saved MAC gets set to the - * internal WifiConfiguration. - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - */ - @Test - public void testAddingNetworkWithMatchingMacAddressOverridesField() { - int prevMappingSize = mWifiConfigManager.getRandomizedMacAddressMappingSize(); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - Map<String, String> randomizedMacAddressMapping = new HashMap<>(); - final String randMac = "12:23:34:45:56:67"; - randomizedMacAddressMapping.put(openNetwork.getKey(), randMac); - assertNotEquals(randMac, openNetwork.getRandomizedMacAddress()); - when(mRandomizedMacStoreData.getMacMapping()).thenReturn(randomizedMacAddressMapping); - - // reads XML data storage - //mWifiConfigManager.loadFromStore(); - verifyAddNetworkToWifiConfigManager(openNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - assertEquals(randMac, retrievedNetworks.get(0).getRandomizedMacAddress().toString()); - // Verify that for networks that we already have randomizedMacAddressMapping saved - // we are still correctly writing into the WifiConfigStore. - assertEquals(prevMappingSize + 1, mWifiConfigManager.getRandomizedMacAddressMappingSize()); - } - - /** - * Verifies that when a network is added, removed, and then added back again, its randomized - * MAC address doesn't change. - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - */ - @Test - public void testRandomizedMacAddressIsPersistedOverForgetNetwork() { - int prevMappingSize = mWifiConfigManager.getRandomizedMacAddressMappingSize(); - // Create and add an open network - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(openNetwork); - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - - // Gets the randomized MAC address of the network added. - final String randMac = retrievedNetworks.get(0).getRandomizedMacAddress().toString(); - // This MAC should be different from the default, uninitialized randomized MAC. - assertNotEquals(openNetwork.getRandomizedMacAddress().toString(), randMac); - - // Remove the added network - verifyRemoveNetworkFromWifiConfigManager(openNetwork); - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - - // Adds the network back again and verify randomized MAC address stays the same. - verifyAddNetworkToWifiConfigManager(openNetwork); - retrievedNetworks = mWifiConfigManager.getConfiguredNetworksWithPasswords(); - assertEquals(randMac, retrievedNetworks.get(0).getRandomizedMacAddress().toString()); - // Verify that we are no longer persisting the randomized MAC address with WifiConfigStore. - assertEquals(prevMappingSize, mWifiConfigManager.getRandomizedMacAddressMappingSize()); - } - - /** - * Verifies that when a network is read from xml storage, it is assigned a randomized MAC - * address if it doesn't have one yet. Then try removing the network and then add it back - * again and verify the randomized MAC didn't change. - */ - @Test - public void testRandomizedMacAddressIsGeneratedForConfigurationReadFromStore() - throws Exception { - // Create and add an open network - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - final String defaultMac = openNetwork.getRandomizedMacAddress().toString(); - List<WifiConfiguration> sharedConfigList = new ArrayList<>(); - sharedConfigList.add(openNetwork); - - // Setup xml storage - setupStoreDataForRead(sharedConfigList, new ArrayList<>()); - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - // Gets the randomized MAC address of the network added. - final String randMac = retrievedNetworks.get(0).getRandomizedMacAddress().toString(); - // This MAC should be different from the default, uninitialized randomized MAC. - assertNotEquals(defaultMac, randMac); - - assertTrue(mWifiConfigManager.removeNetwork( - openNetwork.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - - // Adds the network back again and verify randomized MAC address stays the same. - mWifiConfigManager.addOrUpdateNetwork(openNetwork, TEST_CREATOR_UID); - retrievedNetworks = mWifiConfigManager.getConfiguredNetworksWithPasswords(); - assertEquals(randMac, retrievedNetworks.get(0).getRandomizedMacAddress().toString()); - } - - /** - * Verifies the modification of a single network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - */ - @Test - public void testUpdateSingleOpenNetwork() { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - reset(mWcmListener); - - // Now change BSSID for the network. - assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); - // Change the trusted bit. - openNetwork.trusted = false; - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(openNetwork); - - // Now verify that the modification has been effective. - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - verify(mWcmListener).onNetworkUpdated( - wifiConfigCaptor.capture(), wifiConfigCaptor.capture()); - WifiConfiguration newConfig = wifiConfigCaptor.getAllValues().get(1); - WifiConfiguration oldConfig = wifiConfigCaptor.getAllValues().get(0); - assertEquals(openNetwork.networkId, newConfig.networkId); - assertFalse(newConfig.trusted); - assertEquals(TEST_BSSID, newConfig.BSSID); - assertEquals(openNetwork.networkId, oldConfig.networkId); - assertTrue(oldConfig.trusted); - assertNull(oldConfig.BSSID); - } - - /** - * Verifies the modification of a single network will remove its bssid from - * the blocklist. - */ - @Test - public void testUpdateSingleOpenNetworkInBlockList() { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - reset(mWcmListener); - - // mock the simplest bssid block list - Map<String, String> mBssidStatusMap = new ArrayMap<>(); - doAnswer(new AnswerWithArguments() { - public void answer(String ssid) { - mBssidStatusMap.entrySet().removeIf(e -> e.getValue().equals(ssid)); - } - }).when(mBssidBlocklistMonitor).clearBssidBlocklistForSsid( - anyString()); - doAnswer(new AnswerWithArguments() { - public int answer(String ssid) { - return (int) mBssidStatusMap.entrySet().stream() - .filter(e -> e.getValue().equals(ssid)).count(); - } - }).when(mBssidBlocklistMonitor).updateAndGetNumBlockedBssidsForSsid( - anyString()); - // add bssid to the blocklist - mBssidStatusMap.put(TEST_BSSID, openNetwork.SSID); - mBssidStatusMap.put("aa:bb:cc:dd:ee:ff", openNetwork.SSID); - - // Now change BSSID for the network. - assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); - // Change the trusted bit. - openNetwork.trusted = false; - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(openNetwork); - - // Now verify that the modification has been effective. - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - verify(mWcmListener).onNetworkUpdated( - wifiConfigCaptor.capture(), wifiConfigCaptor.capture()); - WifiConfiguration newConfig = wifiConfigCaptor.getAllValues().get(1); - WifiConfiguration oldConfig = wifiConfigCaptor.getAllValues().get(0); - assertEquals(openNetwork.networkId, newConfig.networkId); - assertFalse(newConfig.trusted); - assertEquals(TEST_BSSID, newConfig.BSSID); - assertEquals(openNetwork.networkId, oldConfig.networkId); - assertTrue(oldConfig.trusted); - assertNull(oldConfig.BSSID); - - assertEquals(0, mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid( - openNetwork.SSID)); - } - - /** - * Verifies that the device owner could modify other other fields in the Wificonfiguration - * but not the macRandomizationSetting field. - */ - @Test - public void testCannotUpdateMacRandomizationSettingWithoutPermission() { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), any())).thenReturn(true); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - - verifyAddNetworkToWifiConfigManager(openNetwork); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - reset(mWcmListener); - - // Change BSSID for the network and verify success - assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); - NetworkUpdateResult networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); - assertNotEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); - - // Now change the macRandomizationSetting and verify failure - openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); - assertEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); - } - - /** - * Verifies that mac randomization settings could be modified by a caller with NETWORK_SETTINGS - * permission. - */ - @Test - public void testCanUpdateMacRandomizationSettingWithNetworkSettingPermission() { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - // Verify user action event is not logged when the network is added - verify(mWifiMetrics, never()).logUserActionEvent(anyInt(), anyBoolean(), anyBoolean()); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - reset(mWcmListener); - - // Now change the macRandomizationSetting and verify success - openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - NetworkUpdateResult networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); - assertNotEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); - verify(mWifiMetrics).logUserActionEvent( - UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF, openNetwork.networkId); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - } - - /** - * Verifies that mac randomization settings could be modified by a caller with - * NETWORK_SETUP_WIZARD permission. - */ - @Test - public void testCanUpdateMacRandomizationSettingWithSetupWizardPermission() { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), any())).thenReturn(true); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - reset(mWcmListener); - - // Now change the macRandomizationSetting and verify success - openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - NetworkUpdateResult networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); - assertNotEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - } - - /** - * Verify that the mac randomization setting could be modified by the creator of a passpoint - * network. - */ - @Test - public void testCanUpdateMacRandomizationSettingWithPasspointCreatorUid() throws Exception { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), any())).thenReturn(false); - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - // Disable MAC randomization and verify this is added in successfully. - passpointNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(passpointNetwork); - - verifyAddPasspointNetworkToWifiConfigManager(passpointNetwork); - // Ensure that configured network list is not empty. - assertFalse(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - - // Ensure that this is not returned in the saved network list. - assertTrue(mWifiConfigManager.getSavedNetworks(Process.WIFI_UID).isEmpty()); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(passpointNetwork.networkId, wifiConfigCaptor.getValue().networkId); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - } - - - /** - * Verifies the addition of a single ephemeral network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} and verifies that - * the {@link WifiConfigManager#getSavedNetworks(int)} does not return this network. - */ - @Test - public void testAddSingleEphemeralNetwork() throws Exception { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration ephemeralNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - ephemeralNetwork.ephemeral = true; - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(ephemeralNetwork); - - verifyAddEphemeralNetworkToWifiConfigManager(ephemeralNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - // Ensure that this is not returned in the saved network list. - assertTrue(mWifiConfigManager.getSavedNetworks(Process.WIFI_UID).isEmpty()); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(ephemeralNetwork.networkId, wifiConfigCaptor.getValue().networkId); - } - - private void addSinglePasspointNetwork(boolean isHomeProviderNetwork) throws Exception { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - passpointNetwork.isHomeProviderNetwork = isHomeProviderNetwork; - - verifyAddPasspointNetworkToWifiConfigManager(passpointNetwork); - // Ensure that configured network list is not empty. - assertFalse(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - - // Ensure that this is not returned in the saved network list. - assertTrue(mWifiConfigManager.getSavedNetworks(Process.WIFI_UID).isEmpty()); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(passpointNetwork.networkId, wifiConfigCaptor.getValue().networkId); - assertEquals(passpointNetwork.isHomeProviderNetwork, - wifiConfigCaptor.getValue().isHomeProviderNetwork); - } - - /** - * Verifies the addition of a single home Passpoint network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} and verifies that - * the {@link WifiConfigManager#getSavedNetworks(int)} ()} does not return this network. - */ - @Test - public void testAddSingleHomePasspointNetwork() throws Exception { - addSinglePasspointNetwork(true); - } - - /** - * Verifies the addition of a single roaming Passpoint network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} and verifies that - * the {@link WifiConfigManager#getSavedNetworks(int)} ()} does not return this network. - */ - @Test - public void testAddSingleRoamingPasspointNetwork() throws Exception { - addSinglePasspointNetwork(false); - } - - /** - * Verifies the addition of 2 networks (1 normal and 1 ephemeral) using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} and ensures that - * the ephemeral network configuration is not persisted in config store. - */ - @Test - public void testAddMultipleNetworksAndEnsureEphemeralNetworkNotPersisted() { - WifiConfiguration ephemeralNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - ephemeralNetwork.ephemeral = true; - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - assertTrue(addNetworkToWifiConfigManager(ephemeralNetwork).isSuccess()); - assertTrue(addNetworkToWifiConfigManager(openNetwork).isSuccess()); - - // The open network addition should trigger a store write. - Pair<List<WifiConfiguration>, List<WifiConfiguration>> networkListStoreData = - captureWriteNetworksListStoreData(); - List<WifiConfiguration> networkList = new ArrayList<>(); - networkList.addAll(networkListStoreData.first); - networkList.addAll(networkListStoreData.second); - assertFalse(isNetworkInConfigStoreData(ephemeralNetwork, networkList)); - assertTrue(isNetworkInConfigStoreData(openNetwork, networkList)); - } - - /** - * Verifies the addition of a single suggestion network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int, String)} and verifies - * that the {@link WifiConfigManager#getSavedNetworks()} does not return this network. - */ - @Test - public void testAddSingleSuggestionNetwork() throws Exception { - WifiConfiguration suggestionNetwork = WifiConfigurationTestUtil.createEapNetwork(); - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - suggestionNetwork.ephemeral = true; - suggestionNetwork.fromWifiNetworkSuggestion = true; - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(suggestionNetwork); - - verifyAddSuggestionOrRequestNetworkToWifiConfigManager(suggestionNetwork); - verify(mWifiKeyStore, never()).updateNetworkKeys(any(), any()); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - // Ensure that this is not returned in the saved network list. - assertTrue(mWifiConfigManager.getSavedNetworks(Process.WIFI_UID).isEmpty()); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(suggestionNetwork.networkId, wifiConfigCaptor.getValue().networkId); - assertTrue(mWifiConfigManager - .removeNetwork(suggestionNetwork.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - verify(mWifiKeyStore, never()).removeKeys(any()); - } - - /** - * Verifies the addition of a single specifier network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int, String)} and verifies - * that the {@link WifiConfigManager#getSavedNetworks()} does not return this network. - */ - @Test - public void testAddSingleSpecifierNetwork() throws Exception { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration suggestionNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - suggestionNetwork.ephemeral = true; - suggestionNetwork.fromWifiNetworkSpecifier = true; - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(suggestionNetwork); - - verifyAddSuggestionOrRequestNetworkToWifiConfigManager(suggestionNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - // Ensure that this is not returned in the saved network list. - assertTrue(mWifiConfigManager.getSavedNetworks(Process.WIFI_UID).isEmpty()); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(suggestionNetwork.networkId, wifiConfigCaptor.getValue().networkId); - } - - /** - * Verifies that the modification of a single open network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} with a UID which - * has no permission to modify the network fails. - */ - @Test - public void testUpdateSingleOpenNetworkFailedDueToPermissionDenied() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - - // Now change BSSID of the network. - assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); - - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - - // Update the same configuration and ensure that the operation failed. - NetworkUpdateResult result = updateNetworkToWifiConfigManager(openNetwork); - assertTrue(result.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID); - } - - /** - * Verifies that the modification of a single open network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} with the creator UID - * should always succeed. - */ - @Test - public void testUpdateSingleOpenNetworkSuccessWithCreatorUID() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - - // Now change BSSID of the network. - assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); - - // Update the same configuration using the creator UID. - NetworkUpdateResult result = - mWifiConfigManager.addOrUpdateNetwork(openNetwork, TEST_CREATOR_UID); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - - // Now verify that the modification has been effective. - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - } - - /** - * Verifies the addition of a single PSK network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} and verifies that - * {@link WifiConfigManager#getSavedNetworks()} masks the password. - */ - @Test - public void testAddSinglePskNetwork() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(pskNetwork); - - verifyAddNetworkToWifiConfigManager(pskNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - List<WifiConfiguration> retrievedSavedNetworks = mWifiConfigManager.getSavedNetworks( - Process.WIFI_UID); - assertEquals(retrievedSavedNetworks.size(), 1); - assertEquals(retrievedSavedNetworks.get(0).getKey(), pskNetwork.getKey()); - assertPasswordsMaskedInWifiConfiguration(retrievedSavedNetworks.get(0)); - } - - /** - * Verifies the addition of a single WEP network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} and verifies that - * {@link WifiConfigManager#getSavedNetworks()} masks the password. - */ - @Test - public void testAddSingleWepNetwork() { - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(wepNetwork); - - verifyAddNetworkToWifiConfigManager(wepNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - List<WifiConfiguration> retrievedSavedNetworks = mWifiConfigManager.getSavedNetworks( - Process.WIFI_UID); - assertEquals(retrievedSavedNetworks.size(), 1); - assertEquals(retrievedSavedNetworks.get(0).getKey(), wepNetwork.getKey()); - assertPasswordsMaskedInWifiConfiguration(retrievedSavedNetworks.get(0)); - } - - /** - * Verifies the modification of an IpConfiguration using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - */ - @Test - public void testUpdateIpConfiguration() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - - // Now change BSSID of the network. - assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); - - // Update the same configuration and ensure that the IP configuration change flags - // are not set. - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(openNetwork); - - // Configure mock DevicePolicyManager to give Profile Owner permission so that we can modify - // proxy settings on a configuration - when(mWifiPermissionsUtil.isProfileOwner(anyInt(), any())).thenReturn(true); - - // Change the IpConfiguration now and ensure that the IP configuration flags are set now. - assertAndSetNetworkIpConfiguration( - openNetwork, - WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy()); - verifyUpdateNetworkToWifiConfigManagerWithIpChange(openNetwork); - - // Now verify that all the modifications have been effective. - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - } - - /** - * Verifies the removal of a single network using - * {@link WifiConfigManager#removeNetwork(int)} - */ - @Test - public void testRemoveSingleOpenNetwork() { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - verifyAddNetworkToWifiConfigManager(openNetwork); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - reset(mWcmListener); - - // Ensure that configured network list is not empty. - assertFalse(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - - verifyRemoveNetworkFromWifiConfigManager(openNetwork); - // Ensure that configured network list is empty now. - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - verify(mWcmListener).onNetworkRemoved(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - } - - /** - * Verifies the removal of an ephemeral network using - * {@link WifiConfigManager#removeNetwork(int)} - */ - @Test - public void testRemoveSingleEphemeralNetwork() throws Exception { - WifiConfiguration ephemeralNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - ephemeralNetwork.ephemeral = true; - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - - verifyAddEphemeralNetworkToWifiConfigManager(ephemeralNetwork); - // Ensure that configured network list is not empty. - assertFalse(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(ephemeralNetwork.networkId, wifiConfigCaptor.getValue().networkId); - verifyRemoveEphemeralNetworkFromWifiConfigManager(ephemeralNetwork); - // Ensure that configured network list is empty now. - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - verify(mWcmListener).onNetworkRemoved(wifiConfigCaptor.capture()); - assertEquals(ephemeralNetwork.networkId, wifiConfigCaptor.getValue().networkId); - } - - /** - * Verifies the removal of a Passpoint network using - * {@link WifiConfigManager#removeNetwork(int)} - */ - @Test - public void testRemoveSinglePasspointNetwork() throws Exception { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - - verifyAddPasspointNetworkToWifiConfigManager(passpointNetwork); - // Ensure that configured network list is not empty. - assertFalse(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); - assertEquals(passpointNetwork.networkId, wifiConfigCaptor.getValue().networkId); - - verifyRemovePasspointNetworkFromWifiConfigManager(passpointNetwork); - // Ensure that configured network list is empty now. - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - verify(mWcmListener).onNetworkRemoved(wifiConfigCaptor.capture()); - assertEquals(passpointNetwork.networkId, wifiConfigCaptor.getValue().networkId); - } - - /** - * Verify that a Passpoint network that's added by an app with {@link #TEST_CREATOR_UID} can - * be removed by WiFi Service with {@link Process#WIFI_UID}. - * - * @throws Exception - */ - @Test - public void testRemovePasspointNetworkAddedByOther() throws Exception { - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - - // Passpoint network is added using TEST_CREATOR_UID. - verifyAddPasspointNetworkToWifiConfigManager(passpointNetwork); - // Ensure that configured network list is not empty. - assertFalse(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - - assertTrue(mWifiConfigManager.removeNetwork( - passpointNetwork.networkId, Process.WIFI_UID, null)); - - // Verify keys are not being removed. - verify(mWifiKeyStore, never()).removeKeys(any(WifiEnterpriseConfig.class)); - verifyNetworkRemoveBroadcast(); - // Ensure that the write was not invoked for Passpoint network remove. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - - } - /** - * Verifies the addition & update of multiple networks using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} and the - * removal of networks using - * {@link WifiConfigManager#removeNetwork(int)} - */ - @Test - public void testAddUpdateRemoveMultipleNetworks() { - List<WifiConfiguration> networks = new ArrayList<>(); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - networks.add(openNetwork); - networks.add(pskNetwork); - networks.add(wepNetwork); - - verifyAddNetworkToWifiConfigManager(openNetwork); - verifyAddNetworkToWifiConfigManager(pskNetwork); - verifyAddNetworkToWifiConfigManager(wepNetwork); - - // Now verify that all the additions has been effective. - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - // Modify all the 3 configurations and update it to WifiConfigManager. - assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); - assertAndSetNetworkBSSID(pskNetwork, TEST_BSSID); - assertAndSetNetworkIpConfiguration( - wepNetwork, - WifiConfigurationTestUtil.createStaticIpConfigurationWithPacProxy()); - - // Configure mock DevicePolicyManager to give Profile Owner permission so that we can modify - // proxy settings on a configuration - when(mWifiPermissionsUtil.isProfileOwner(anyInt(), any())).thenReturn(true); - - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(openNetwork); - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(pskNetwork); - verifyUpdateNetworkToWifiConfigManagerWithIpChange(wepNetwork); - // Now verify that all the modifications has been effective. - retrievedNetworks = mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - // Now remove all 3 networks. - verifyRemoveNetworkFromWifiConfigManager(openNetwork); - verifyRemoveNetworkFromWifiConfigManager(pskNetwork); - verifyRemoveNetworkFromWifiConfigManager(wepNetwork); - - // Ensure that configured network list is empty now. - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - } - - /** - * Verifies the update of network status using - * {@link WifiConfigManager#updateNetworkSelectionStatus(int, int)}. - */ - @Test - public void testNetworkSelectionStatus() { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - int networkId = result.getNetworkId(); - // First set it to enabled. - verifyUpdateNetworkSelectionStatus( - networkId, NetworkSelectionStatus.DISABLED_NONE, 0); - - // Now set it to temporarily disabled. The threshold for association rejection is 5, so - // disable it 5 times to actually mark it temporarily disabled. - int assocRejectReason = NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION; - int assocRejectThreshold = - WifiConfigManager.getNetworkSelectionDisableThreshold(assocRejectReason); - for (int i = 1; i <= assocRejectThreshold; i++) { - verifyUpdateNetworkSelectionStatus(result.getNetworkId(), assocRejectReason, i); - } - verify(mWcmListener).onNetworkTemporarilyDisabled(wifiConfigCaptor.capture(), - eq(NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION)); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - // Now set it to permanently disabled. - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER, 0); - verify(mWcmListener).onNetworkPermanentlyDisabled( - wifiConfigCaptor.capture(), eq(NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - // Now set it back to enabled. - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_NONE, 0); - verify(mWcmListener, times(2)) - .onNetworkEnabled(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - } - - /** - * Verifies the update of network status using - * {@link WifiConfigManager#updateNetworkSelectionStatus(int, int)}. - */ - @Test - public void testNetworkSelectionStatusTemporarilyDisabledDueToNoInternet() { - ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - int networkId = result.getNetworkId(); - // First set it to enabled. - verifyUpdateNetworkSelectionStatus( - networkId, NetworkSelectionStatus.DISABLED_NONE, 0); - - // Now set it to temporarily disabled. The threshold for no internet is 1, so - // disable it once to actually mark it temporarily disabled. - verifyUpdateNetworkSelectionStatus(result.getNetworkId(), - NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY, 1); - verify(mWcmListener).onNetworkTemporarilyDisabled( - wifiConfigCaptor.capture(), - eq(NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY)); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - // Now set it back to enabled. - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_NONE, 0); - verify(mWcmListener, times(2)) - .onNetworkEnabled(wifiConfigCaptor.capture()); - assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); - } - - /** - * Verifies the update of network status using - * {@link WifiConfigManager#updateNetworkSelectionStatus(int, int)} and ensures that - * enabling a network clears out all the temporary disable counters. - */ - @Test - public void testNetworkSelectionStatusEnableClearsDisableCounters() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - // First set it to enabled. - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_NONE, 0); - - // Now set it to temporarily disabled 2 times for 2 different reasons. - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION, 1); - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION, 2); - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE, 1); - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE, 2); - - // Now set it back to enabled. - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_NONE, 0); - - // Ensure that the counters have all been reset now. - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION, 1); - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE, 1); - } - - private void verifyDisableNetwork(NetworkUpdateResult result, int reason) { - // First set it to enabled. - verifyUpdateNetworkSelectionStatus( - result.getNetworkId(), NetworkSelectionStatus.DISABLED_NONE, 0); - - int disableThreshold = - WifiConfigManager.getNetworkSelectionDisableThreshold(reason); - for (int i = 1; i <= disableThreshold; i++) { - verifyUpdateNetworkSelectionStatus(result.getNetworkId(), reason, i); - } - } - - private void verifyNetworkIsEnabledAfter(int networkId, long timeout) { - // try enabling this network 1 second earlier than the expected timeout. This - // should fail and the status should remain temporarily disabled. - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeout - 1); - assertFalse(mWifiConfigManager.tryEnableNetwork(networkId)); - NetworkSelectionStatus retrievedStatus = - mWifiConfigManager.getConfiguredNetwork(networkId).getNetworkSelectionStatus(); - assertTrue(retrievedStatus.isNetworkTemporaryDisabled()); - - // Now advance time by the timeout for association rejection and ensure that the - // network is now enabled. - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeout); - assertTrue(mWifiConfigManager.tryEnableNetwork(networkId)); - retrievedStatus = mWifiConfigManager.getConfiguredNetwork(networkId) - .getNetworkSelectionStatus(); - assertTrue(retrievedStatus.isNetworkEnabled()); - } - - /** - * Verifies the enabling of temporarily disabled network using - * {@link WifiConfigManager#tryEnableNetwork(int)}. - */ - @Test - public void testTryEnableNetwork() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - // Verify exponential backoff on the disable duration based on number of BSSIDs in the - // BSSID blocklist - long multiplier = 1; - int disableReason = NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION; - long timeout = 0; - for (int i = 1; i < MAX_BLOCKED_BSSID_PER_NETWORK + 1; i++) { - verifyDisableNetwork(result, disableReason); - int numBssidsInBlocklist = i; - when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(anyString())) - .thenReturn(numBssidsInBlocklist); - timeout = WifiConfigManager.getNetworkSelectionDisableTimeoutMillis(disableReason) - * multiplier; - multiplier *= 2; - verifyNetworkIsEnabledAfter(result.getNetworkId(), - TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS + timeout); - } - - // Verify one last time that the disable duration is capped at some maximum. - verifyDisableNetwork(result, disableReason); - when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(anyString())) - .thenReturn(MAX_BLOCKED_BSSID_PER_NETWORK + 1); - verifyNetworkIsEnabledAfter(result.getNetworkId(), - TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS + timeout); - } - - /** - * Verifies that when no BSSIDs for a network is inside the BSSID blocklist then we - * re-enable a network. - */ - @Test - public void testTryEnableNetworkNoBssidsInBlocklist() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - int disableReason = NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION; - - // Verify that with 0 BSSIDs in blocklist we enable the network immediately - verifyDisableNetwork(result, disableReason); - when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(anyString())).thenReturn(0); - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS); - assertTrue(mWifiConfigManager.tryEnableNetwork(result.getNetworkId())); - NetworkSelectionStatus retrievedStatus = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()) - .getNetworkSelectionStatus(); - assertTrue(retrievedStatus.isNetworkEnabled()); - } - - /** - * Verifies the enabling of network using - * {@link WifiConfigManager#enableNetwork(int, boolean, int)} and - * {@link WifiConfigManager#disableNetwork(int, int)}. - */ - @Test - public void testEnableDisableNetwork() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - assertTrue(mWifiConfigManager.enableNetwork( - result.getNetworkId(), false, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - NetworkSelectionStatus retrievedStatus = retrievedNetwork.getNetworkSelectionStatus(); - assertTrue(retrievedStatus.isNetworkEnabled()); - verifyUpdateNetworkStatus(retrievedNetwork, WifiConfiguration.Status.ENABLED); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(eq(true)); - - // Now set it disabled. - assertTrue(mWifiConfigManager.disableNetwork( - result.getNetworkId(), TEST_CREATOR_UID, TEST_CREATOR_NAME)); - retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - retrievedStatus = retrievedNetwork.getNetworkSelectionStatus(); - assertTrue(retrievedStatus.isNetworkPermanentlyDisabled()); - verifyUpdateNetworkStatus(retrievedNetwork, WifiConfiguration.Status.DISABLED); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(eq(true)); - } - - /** - * Verifies the enabling of network using - * {@link WifiConfigManager#enableNetwork(int, boolean, int)} with a UID which - * has no permission to modify the network fails.. - */ - @Test - public void testEnableNetworkFailedDueToPermissionDenied() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - assertEquals(WifiConfiguration.INVALID_NETWORK_ID, - mWifiConfigManager.getLastSelectedNetwork()); - - // Now try to set it enable with |TEST_UPDATE_UID|, it should fail and the network - // should remain disabled. - assertFalse(mWifiConfigManager.enableNetwork( - result.getNetworkId(), true, TEST_UPDATE_UID, TEST_UPDATE_NAME)); - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - NetworkSelectionStatus retrievedStatus = retrievedNetwork.getNetworkSelectionStatus(); - assertFalse(retrievedStatus.isNetworkEnabled()); - assertEquals(WifiConfiguration.Status.DISABLED, retrievedNetwork.status); - - // Set last selected network even if the app has no permission to enable it. - assertEquals(result.getNetworkId(), mWifiConfigManager.getLastSelectedNetwork()); - } - - /** - * Verifies the enabling of network using - * {@link WifiConfigManager#disableNetwork(int, int)} with a UID which - * has no permission to modify the network fails.. - */ - @Test - public void testDisableNetworkFailedDueToPermissionDenied() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - assertTrue(mWifiConfigManager.enableNetwork( - result.getNetworkId(), true, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - - assertEquals(result.getNetworkId(), mWifiConfigManager.getLastSelectedNetwork()); - - // Now try to set it disabled with |TEST_UPDATE_UID|, it should fail and the network - // should remain enabled. - assertFalse(mWifiConfigManager.disableNetwork( - result.getNetworkId(), TEST_UPDATE_UID, TEST_CREATOR_NAME)); - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - NetworkSelectionStatus retrievedStatus = retrievedNetwork.getNetworkSelectionStatus(); - assertTrue(retrievedStatus.isNetworkEnabled()); - assertEquals(WifiConfiguration.Status.ENABLED, retrievedNetwork.status); - - // Clear the last selected network even if the app has no permission to disable it. - assertEquals(WifiConfiguration.INVALID_NETWORK_ID, - mWifiConfigManager.getLastSelectedNetwork()); - } - - /** - * Verifies the allowance/disallowance of autojoin to a network using - * {@link WifiConfigManager#allowAutojoin(int, boolean)} - */ - @Test - public void testAllowDisallowAutojoin() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - assertTrue(mWifiConfigManager.allowAutojoin( - result.getNetworkId(), true)); - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - assertTrue(retrievedNetwork.allowAutojoin); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(eq(true)); - - // Now set it disallow auto-join. - assertTrue(mWifiConfigManager.allowAutojoin( - result.getNetworkId(), false)); - retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - assertFalse(retrievedNetwork.allowAutojoin); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(eq(true)); - } - - /** - * Verifies the updation of network's connectUid using - * {@link WifiConfigManager#updateLastConnectUid(int, int)}. - */ - @Test - public void testUpdateLastConnectUid() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - assertTrue( - mWifiConfigManager.updateLastConnectUid( - result.getNetworkId(), TEST_CREATOR_UID)); - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - assertEquals(TEST_CREATOR_UID, retrievedNetwork.lastConnectUid); - } - - /** - * Verifies that any configuration update attempt with an null config is gracefully - * handled. - * This invokes {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)}. - */ - @Test - public void testAddOrUpdateNetworkWithNullConfig() { - NetworkUpdateResult result = mWifiConfigManager.addOrUpdateNetwork(null, TEST_CREATOR_UID); - assertFalse(result.isSuccess()); - } - - /** - * Verifies that attempting to remove a network without any configs stored will return false. - * This tests the case where we have not loaded any configs, potentially due to a pending store - * read. - * This invokes {@link WifiConfigManager#removeNetwork(int)}. - */ - @Test - public void testRemoveNetworkWithEmptyConfigStore() { - int networkId = new Random().nextInt(); - assertFalse(mWifiConfigManager.removeNetwork( - networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - } - - /** - * Verifies that any configuration removal attempt with an invalid networkID is gracefully - * handled. - * This invokes {@link WifiConfigManager#removeNetwork(int)}. - */ - @Test - public void testRemoveNetworkWithInvalidNetworkId() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - verifyAddNetworkToWifiConfigManager(openNetwork); - - // Change the networkID to an invalid one. - openNetwork.networkId++; - assertFalse(mWifiConfigManager.removeNetwork( - openNetwork.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - } - - /** - * Verifies that any configuration update attempt with an invalid networkID is gracefully - * handled. - * This invokes {@link WifiConfigManager#enableNetwork(int, boolean, int)}, - * {@link WifiConfigManager#disableNetwork(int, int)}, - * {@link WifiConfigManager#updateNetworkSelectionStatus(int, int)} and - * {@link WifiConfigManager#updateLastConnectUid(int, int)}. - */ - @Test - public void testChangeConfigurationWithInvalidNetworkId() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - assertFalse(mWifiConfigManager.enableNetwork( - result.getNetworkId() + 1, false, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - assertFalse(mWifiConfigManager.disableNetwork( - result.getNetworkId() + 1, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - assertFalse(mWifiConfigManager.updateNetworkSelectionStatus( - result.getNetworkId() + 1, NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)); - assertFalse(mWifiConfigManager.updateLastConnectUid( - result.getNetworkId() + 1, TEST_CREATOR_UID)); - } - - /** - * Verifies multiple modification of a single network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)}. - * This test is basically checking if the apps can reset some of the fields of the config after - * addition. The fields being reset in this test are the |preSharedKey| and |wepKeys|. - * 1. Create an open network initially. - * 2. Modify the added network config to a WEP network config with all the 4 keys set. - * 3. Modify the added network config to a WEP network config with only 1 key set. - * 4. Modify the added network config to a PSK network config. - */ - @Test - public void testMultipleUpdatesSingleNetwork() { - WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(network); - - // Now add |wepKeys| to the network. We don't need to update the |allowedKeyManagement| - // fields for open to WEP conversion. - String[] wepKeys = - Arrays.copyOf(WifiConfigurationTestUtil.TEST_WEP_KEYS, - WifiConfigurationTestUtil.TEST_WEP_KEYS.length); - int wepTxKeyIdx = WifiConfigurationTestUtil.TEST_WEP_TX_KEY_INDEX; - assertAndSetNetworkWepKeysAndTxIndex(network, wepKeys, wepTxKeyIdx); - - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(network); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - - // Now empty out 3 of the |wepKeys[]| and ensure that those keys have been reset correctly. - for (int i = 1; i < network.wepKeys.length; i++) { - wepKeys[i] = ""; - } - wepTxKeyIdx = 0; - assertAndSetNetworkWepKeysAndTxIndex(network, wepKeys, wepTxKeyIdx); - - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(network); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - - // Now change the config to a PSK network config by resetting the remaining |wepKey[0]| - // field and setting the |preSharedKey| and |allowedKeyManagement| fields. - wepKeys[0] = ""; - wepTxKeyIdx = -1; - assertAndSetNetworkWepKeysAndTxIndex(network, wepKeys, wepTxKeyIdx); - network.allowedKeyManagement.clear(); - network.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - assertAndSetNetworkPreSharedKey(network, WifiConfigurationTestUtil.TEST_PSK); - - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(network); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - } - - /** - * Verifies the modification of a WifiEnteriseConfig using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)}. - */ - @Test - public void testUpdateWifiEnterpriseConfig() { - WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); - verifyAddNetworkToWifiConfigManager(network); - - // Set the |password| field in WifiEnterpriseConfig and modify the config to PEAP/GTC. - network.enterpriseConfig = - WifiConfigurationTestUtil.createPEAPWifiEnterpriseConfigWithGTCPhase2(); - assertAndSetNetworkEnterprisePassword(network, "test"); - - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(network); - network.enterpriseConfig.setCaPath(WifiConfigurationTestUtil.TEST_CA_CERT_PATH); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - - // Reset the |password| field in WifiEnterpriseConfig and modify the config to TLS/None. - network.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - network.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); - assertAndSetNetworkEnterprisePassword(network, ""); - - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(network); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - } - - /** - * Verifies the modification of a single network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} by passing in nulls - * in all the publicly exposed fields. - */ - @Test - public void testUpdateSingleNetworkWithNullValues() { - WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); - verifyAddNetworkToWifiConfigManager(network); - - // Save a copy of the original network for comparison. - WifiConfiguration originalNetwork = new WifiConfiguration(network); - - // Now set all the public fields to null and try updating the network. - network.allowedAuthAlgorithms.clear(); - network.allowedProtocols.clear(); - network.allowedKeyManagement.clear(); - network.allowedPairwiseCiphers.clear(); - network.allowedGroupCiphers.clear(); - network.enterpriseConfig = null; - - // Update the network. - NetworkUpdateResult result = updateNetworkToWifiConfigManager(network); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertFalse(result.isNewNetwork()); - - // Verify no changes to the original network configuration. - verifyNetworkUpdateBroadcast(); - verifyNetworkInConfigStoreData(originalNetwork); - assertFalse(result.hasIpChanged()); - assertFalse(result.hasProxyChanged()); - - // Copy over the updated debug params to the original network config before comparison. - originalNetwork.lastUpdateUid = network.lastUpdateUid; - originalNetwork.lastUpdateName = network.lastUpdateName; - - // Now verify that there was no change to the network configurations. - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - originalNetwork, - mWifiConfigManager.getConfiguredNetworkWithPassword(originalNetwork.networkId)); - } - - /** - * Verifies the addition of a single network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} by passing in null - * in IpConfiguraion fails. - */ - @Test - public void testAddSingleNetworkWithNullIpConfigurationFails() { - WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); - network.setIpConfiguration(null); - NetworkUpdateResult result = - mWifiConfigManager.addOrUpdateNetwork(network, TEST_CREATOR_UID); - assertFalse(result.isSuccess()); - } - - /** - * Verifies that the modification of a single network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} does not modify - * existing configuration if there is a failure. - */ - @Test - public void testUpdateSingleNetworkFailureDoesNotModifyOriginal() { - WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); - network.enterpriseConfig = - WifiConfigurationTestUtil.createPEAPWifiEnterpriseConfigWithGTCPhase2(); - verifyAddNetworkToWifiConfigManager(network); - - // Save a copy of the original network for comparison. - WifiConfiguration originalNetwork = new WifiConfiguration(network); - - // Now modify the network's EAP method. - network.enterpriseConfig = - WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2(); - - // Fail this update because of cert installation failure. - when(mWifiKeyStore - .updateNetworkKeys(any(WifiConfiguration.class), any(WifiConfiguration.class))) - .thenReturn(false); - NetworkUpdateResult result = - mWifiConfigManager.addOrUpdateNetwork(network, TEST_UPDATE_UID); - assertTrue(result.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID); - - // Now verify that there was no change to the network configurations. - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - originalNetwork, - mWifiConfigManager.getConfiguredNetworkWithPassword(originalNetwork.networkId)); - } - - /** - * Verifies the matching of networks with different encryption types with the - * corresponding scan detail using - * {@link WifiConfigManager#getConfiguredNetworkForScanDetailAndCache(ScanDetail)}. - * The test also verifies that the provided scan detail was cached, - */ - @Test - public void testMatchScanDetailToNetworksAndCache() { - // Create networks of different types and ensure that they're all matched using - // the corresponding ScanDetail correctly. - verifyAddSingleNetworkAndMatchScanDetailToNetworkAndCache( - WifiConfigurationTestUtil.createOpenNetwork()); - verifyAddSingleNetworkAndMatchScanDetailToNetworkAndCache( - WifiConfigurationTestUtil.createWepNetwork()); - verifyAddSingleNetworkAndMatchScanDetailToNetworkAndCache( - WifiConfigurationTestUtil.createPskNetwork()); - verifyAddSingleNetworkAndMatchScanDetailToNetworkAndCache( - WifiConfigurationTestUtil.createEapNetwork()); - verifyAddSingleNetworkAndMatchScanDetailToNetworkAndCache( - WifiConfigurationTestUtil.createSaeNetwork()); - verifyAddSingleNetworkAndMatchScanDetailToNetworkAndCache( - WifiConfigurationTestUtil.createOweNetwork()); - verifyAddSingleNetworkAndMatchScanDetailToNetworkAndCache( - WifiConfigurationTestUtil.createEapSuiteBNetwork()); - } - - /** - * Verifies that scan details with wrong SSID/authentication types are not matched using - * {@link WifiConfigManager#getConfiguredNetworkForScanDetailAndCache(ScanDetail)} - * to the added networks. - */ - @Test - public void testNoMatchScanDetailToNetwork() { - // First create networks of different types. - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(); - WifiConfiguration saeNetwork = WifiConfigurationTestUtil.createSaeNetwork(); - WifiConfiguration oweNetwork = WifiConfigurationTestUtil.createOweNetwork(); - WifiConfiguration eapSuiteBNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork(); - - // Now add them to WifiConfigManager. - verifyAddNetworkToWifiConfigManager(openNetwork); - verifyAddNetworkToWifiConfigManager(wepNetwork); - verifyAddNetworkToWifiConfigManager(pskNetwork); - verifyAddNetworkToWifiConfigManager(eapNetwork); - verifyAddNetworkToWifiConfigManager(saeNetwork); - verifyAddNetworkToWifiConfigManager(oweNetwork); - verifyAddNetworkToWifiConfigManager(eapSuiteBNetwork); - - // Now create dummy scan detail corresponding to the networks. - ScanDetail openNetworkScanDetail = createScanDetailForNetwork(openNetwork); - ScanDetail wepNetworkScanDetail = createScanDetailForNetwork(wepNetwork); - ScanDetail pskNetworkScanDetail = createScanDetailForNetwork(pskNetwork); - ScanDetail eapNetworkScanDetail = createScanDetailForNetwork(eapNetwork); - ScanDetail saeNetworkScanDetail = createScanDetailForNetwork(saeNetwork); - ScanDetail oweNetworkScanDetail = createScanDetailForNetwork(oweNetwork); - ScanDetail eapSuiteBNetworkScanDetail = createScanDetailForNetwork(eapSuiteBNetwork); - - // Now mix and match parameters from different scan details. - openNetworkScanDetail.getScanResult().SSID = - wepNetworkScanDetail.getScanResult().SSID; - wepNetworkScanDetail.getScanResult().capabilities = - pskNetworkScanDetail.getScanResult().capabilities; - pskNetworkScanDetail.getScanResult().capabilities = - eapNetworkScanDetail.getScanResult().capabilities; - eapNetworkScanDetail.getScanResult().capabilities = - saeNetworkScanDetail.getScanResult().capabilities; - saeNetworkScanDetail.getScanResult().capabilities = - oweNetworkScanDetail.getScanResult().capabilities; - oweNetworkScanDetail.getScanResult().capabilities = - eapSuiteBNetworkScanDetail.getScanResult().capabilities; - eapSuiteBNetworkScanDetail.getScanResult().capabilities = - openNetworkScanDetail.getScanResult().capabilities; - - - // Try to lookup a saved network using the modified scan details. All of these should fail. - assertNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - openNetworkScanDetail)); - assertNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - wepNetworkScanDetail)); - assertNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - pskNetworkScanDetail)); - assertNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - eapNetworkScanDetail)); - assertNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - saeNetworkScanDetail)); - assertNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - oweNetworkScanDetail)); - assertNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - eapSuiteBNetworkScanDetail)); - - // All the cache's should be empty as well. - assertNull(mWifiConfigManager.getScanDetailCacheForNetwork(openNetwork.networkId)); - assertNull(mWifiConfigManager.getScanDetailCacheForNetwork(wepNetwork.networkId)); - assertNull(mWifiConfigManager.getScanDetailCacheForNetwork(pskNetwork.networkId)); - assertNull(mWifiConfigManager.getScanDetailCacheForNetwork(eapNetwork.networkId)); - assertNull(mWifiConfigManager.getScanDetailCacheForNetwork(saeNetwork.networkId)); - assertNull(mWifiConfigManager.getScanDetailCacheForNetwork(oweNetwork.networkId)); - assertNull(mWifiConfigManager.getScanDetailCacheForNetwork(eapSuiteBNetwork.networkId)); - } - - /** - * Verifies that ScanDetail added for a network is cached correctly with network ID - */ - @Test - public void testUpdateScanDetailForNetwork() { - // First add the provided network. - WifiConfiguration testNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(testNetwork); - - // Now create a dummy scan detail corresponding to the network. - ScanDetail scanDetail = createScanDetailForNetwork(testNetwork); - ScanResult scanResult = scanDetail.getScanResult(); - - mWifiConfigManager.updateScanDetailForNetwork(result.getNetworkId(), scanDetail); - - // Now retrieve the scan detail cache and ensure that the new scan detail is in cache. - ScanDetailCache retrievedScanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(result.getNetworkId()); - assertEquals(1, retrievedScanDetailCache.size()); - ScanResult retrievedScanResult = retrievedScanDetailCache.getScanResult(scanResult.BSSID); - - ScanTestUtil.assertScanResultEquals(scanResult, retrievedScanResult); - } - - /** - * Verifies that ScanDetail added for a network is cached correctly without network ID - */ - @Test - public void testUpdateScanDetailCacheFromScanDetail() { - // First add the provided network. - WifiConfiguration testNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(testNetwork); - - // Now create a dummy scan detail corresponding to the network. - ScanDetail scanDetail = createScanDetailForNetwork(testNetwork); - ScanResult scanResult = scanDetail.getScanResult(); - - mWifiConfigManager.updateScanDetailCacheFromScanDetail(scanDetail); - - // Now retrieve the scan detail cache and ensure that the new scan detail is in cache. - ScanDetailCache retrievedScanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(result.getNetworkId()); - assertEquals(1, retrievedScanDetailCache.size()); - ScanResult retrievedScanResult = retrievedScanDetailCache.getScanResult(scanResult.BSSID); - - ScanTestUtil.assertScanResultEquals(scanResult, retrievedScanResult); - } - - /** - * Verifies that scan detail cache is trimmed down when the size of the cache for a network - * exceeds {@link WifiConfigManager#SCAN_CACHE_ENTRIES_MAX_SIZE}. - */ - @Test - public void testScanDetailCacheTrimForNetwork() { - // Add a single network. - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(openNetwork); - - ScanDetailCache scanDetailCache; - String testBssidPrefix = "00:a5:b8:c9:45:"; - - // Modify |BSSID| field in the scan result and add copies of scan detail - // |SCAN_CACHE_ENTRIES_MAX_SIZE| times. - int scanDetailNum = 1; - for (; scanDetailNum <= WifiConfigManager.SCAN_CACHE_ENTRIES_MAX_SIZE; scanDetailNum++) { - // Create dummy scan detail caches with different BSSID for the network. - ScanDetail scanDetail = - createScanDetailForNetwork( - openNetwork, String.format("%s%02x", testBssidPrefix, scanDetailNum)); - assertNotNull( - mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail)); - - // The size of scan detail cache should keep growing until it hits - // |SCAN_CACHE_ENTRIES_MAX_SIZE|. - scanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(openNetwork.networkId); - assertEquals(scanDetailNum, scanDetailCache.size()); - } - - // Now add the |SCAN_CACHE_ENTRIES_MAX_SIZE + 1| entry. This should trigger the trim. - ScanDetail scanDetail = - createScanDetailForNetwork( - openNetwork, String.format("%s%02x", testBssidPrefix, scanDetailNum)); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail)); - - // Retrieve the scan detail cache and ensure that the size was trimmed down to - // |SCAN_CACHE_ENTRIES_TRIM_SIZE + 1|. The "+1" is to account for the new entry that - // was added after the trim. - scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork(openNetwork.networkId); - assertEquals(WifiConfigManager.SCAN_CACHE_ENTRIES_TRIM_SIZE + 1, scanDetailCache.size()); - } - - /** - * Verifies that hasEverConnected is false for a newly added network. - */ - @Test - public void testAddNetworkHasEverConnectedFalse() { - verifyAddNetworkHasEverConnectedFalse(WifiConfigurationTestUtil.createOpenNetwork()); - } - - /** - * Verifies that hasEverConnected is false for a newly added network even when new config has - * mistakenly set HasEverConnected to true. - */ - @Test - public void testAddNetworkOverridesHasEverConnectedWhenTrueInNewConfig() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.getNetworkSelectionStatus().setHasEverConnected(true); - verifyAddNetworkHasEverConnectedFalse(openNetwork); - } - - /** - * Verify that the |HasEverConnected| is set when - * {@link WifiConfigManager#updateNetworkAfterConnect(int)} is invoked. - */ - @Test - public void testUpdateConfigAfterConnectHasEverConnectedTrue() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkHasEverConnectedFalse(openNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(openNetwork.networkId); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |preSharedKey| is updated. - */ - @Test - public void testUpdatePreSharedKeyClearsHasEverConnected() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkHasEverConnectedFalse(pskNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(pskNetwork.networkId); - - // Now update the same network with a different psk. - String newPsk = "\"newpassword\""; - assertFalse(pskNetwork.preSharedKey.equals(newPsk)); - pskNetwork.preSharedKey = newPsk; - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(pskNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |wepKeys| is updated. - */ - @Test - public void testUpdateWepKeysClearsHasEverConnected() { - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - verifyAddNetworkHasEverConnectedFalse(wepNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(wepNetwork.networkId); - - // Now update the same network with a different wep. - assertFalse(wepNetwork.wepKeys[0].equals("newpassword")); - wepNetwork.wepKeys[0] = "newpassword"; - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(wepNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |wepTxKeyIndex| is updated. - */ - @Test - public void testUpdateWepTxKeyClearsHasEverConnected() { - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - verifyAddNetworkHasEverConnectedFalse(wepNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(wepNetwork.networkId); - - // Now update the same network with a different wep. - assertFalse(wepNetwork.wepTxKeyIndex == 3); - wepNetwork.wepTxKeyIndex = 3; - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(wepNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |allowedKeyManagement| is - * updated. - */ - @Test - public void testUpdateAllowedKeyManagementClearsHasEverConnected() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkHasEverConnectedFalse(pskNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(pskNetwork.networkId); - - assertFalse(pskNetwork.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)); - pskNetwork.allowedKeyManagement.clear(); - pskNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - pskNetwork.requirePmf = true; - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(pskNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |allowedProtocol| is - * updated. - */ - @Test - public void testUpdateProtocolsClearsHasEverConnected() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkHasEverConnectedFalse(pskNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(pskNetwork.networkId); - - assertFalse(pskNetwork.allowedProtocols.get(WifiConfiguration.Protocol.OSEN)); - pskNetwork.allowedProtocols.set(WifiConfiguration.Protocol.OSEN); - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(pskNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |allowedAuthAlgorithms| is - * updated. - */ - @Test - public void testUpdateAllowedAuthAlgorithmsClearsHasEverConnected() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkHasEverConnectedFalse(pskNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(pskNetwork.networkId); - - assertFalse(pskNetwork.allowedAuthAlgorithms.get(WifiConfiguration.AuthAlgorithm.LEAP)); - pskNetwork.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.LEAP); - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(pskNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |allowedPairwiseCiphers| is - * updated. - */ - @Test - public void testUpdateAllowedPairwiseCiphersClearsHasEverConnected() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkHasEverConnectedFalse(pskNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(pskNetwork.networkId); - - assertFalse(pskNetwork.allowedPairwiseCiphers.get(WifiConfiguration.PairwiseCipher.NONE)); - pskNetwork.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.NONE); - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(pskNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |allowedGroup| is - * updated. - */ - @Test - public void testUpdateAllowedGroupCiphersClearsHasEverConnected() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkHasEverConnectedFalse(pskNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(pskNetwork.networkId); - - assertTrue(pskNetwork.allowedGroupCiphers.get(WifiConfiguration.GroupCipher.WEP104)); - pskNetwork.allowedGroupCiphers.clear(WifiConfiguration.GroupCipher.WEP104); - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(pskNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |hiddenSSID| is - * updated. - */ - @Test - public void testUpdateHiddenSSIDClearsHasEverConnected() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkHasEverConnectedFalse(pskNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(pskNetwork.networkId); - - assertFalse(pskNetwork.hiddenSSID); - pskNetwork.hiddenSSID = true; - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(pskNetwork); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |requirePMF| is - * updated. - */ - @Test - public void testUpdateRequirePMFClearsHasEverConnected() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkHasEverConnectedFalse(pskNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(pskNetwork.networkId); - - assertFalse(pskNetwork.requirePmf); - pskNetwork.requirePmf = true; - - NetworkUpdateResult result = - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(pskNetwork); - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - assertFalse("Updating network credentials config must clear hasEverConnected.", - retrievedNetwork.getNetworkSelectionStatus().hasEverConnected()); - assertTrue(result.hasCredentialChanged()); - } - - /** - * Verifies that hasEverConnected is cleared when a network config |enterpriseConfig| is - * updated. - */ - @Test - public void testUpdateEnterpriseConfigClearsHasEverConnected() { - WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(); - eapNetwork.enterpriseConfig = - WifiConfigurationTestUtil.createPEAPWifiEnterpriseConfigWithGTCPhase2(); - verifyAddNetworkHasEverConnectedFalse(eapNetwork); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(eapNetwork.networkId); - - assertFalse(eapNetwork.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS); - eapNetwork.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(eapNetwork); - } - - /** - * Verifies that if the app sends back the masked passwords in an update, we ignore it. - */ - @Test - public void testUpdateIgnoresMaskedPasswords() { - WifiConfiguration someRandomNetworkWithAllMaskedFields = - WifiConfigurationTestUtil.createPskNetwork(); - someRandomNetworkWithAllMaskedFields.wepKeys = WifiConfigurationTestUtil.TEST_WEP_KEYS; - someRandomNetworkWithAllMaskedFields.preSharedKey = WifiConfigurationTestUtil.TEST_PSK; - someRandomNetworkWithAllMaskedFields.enterpriseConfig.setPassword( - WifiConfigurationTestUtil.TEST_EAP_PASSWORD); - - NetworkUpdateResult result = - verifyAddNetworkToWifiConfigManager(someRandomNetworkWithAllMaskedFields); - - // All of these passwords must be masked in this retrieved network config. - WifiConfiguration retrievedNetworkWithMaskedPassword = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - assertPasswordsMaskedInWifiConfiguration(retrievedNetworkWithMaskedPassword); - // Ensure that the passwords are present internally. - WifiConfiguration retrievedNetworkWithPassword = - mWifiConfigManager.getConfiguredNetworkWithPassword(result.getNetworkId()); - assertEquals(someRandomNetworkWithAllMaskedFields.preSharedKey, - retrievedNetworkWithPassword.preSharedKey); - assertEquals(someRandomNetworkWithAllMaskedFields.wepKeys, - retrievedNetworkWithPassword.wepKeys); - assertEquals(someRandomNetworkWithAllMaskedFields.enterpriseConfig.getPassword(), - retrievedNetworkWithPassword.enterpriseConfig.getPassword()); - - // Now update the same network config using the masked config. - verifyUpdateNetworkToWifiConfigManager(retrievedNetworkWithMaskedPassword); - - // Retrieve the network config with password and ensure that they have not been overwritten - // with *. - retrievedNetworkWithPassword = - mWifiConfigManager.getConfiguredNetworkWithPassword(result.getNetworkId()); - assertEquals(someRandomNetworkWithAllMaskedFields.preSharedKey, - retrievedNetworkWithPassword.preSharedKey); - assertEquals(someRandomNetworkWithAllMaskedFields.wepKeys, - retrievedNetworkWithPassword.wepKeys); - assertEquals(someRandomNetworkWithAllMaskedFields.enterpriseConfig.getPassword(), - retrievedNetworkWithPassword.enterpriseConfig.getPassword()); - } - - /** - * Verifies that randomized MAC address is masked out when we return - * external configs except when explicitly asked for MAC address. - */ - @Test - public void testGetConfiguredNetworksMasksRandomizedMac() { - int targetUidConfigNonCreator = TEST_CREATOR_UID + 100; - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(config); - - // Verify that randomized MAC address is masked when obtaining saved networks from - // invalid UID - List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(Process.INVALID_UID); - assertEquals(1, configs.size()); - assertRandomizedMacAddressMaskedInWifiConfiguration(configs.get(0)); - - // Verify that randomized MAC address is unmasked when obtaining saved networks from - // system UID - configs = mWifiConfigManager.getSavedNetworks(Process.WIFI_UID); - assertEquals(1, configs.size()); - String macAddress = configs.get(0).getRandomizedMacAddress().toString(); - assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, macAddress); - - // Verify that randomized MAC address is masked when obtaining saved networks from - // (carrier app) non-creator of the config - configs = mWifiConfigManager.getSavedNetworks(targetUidConfigNonCreator); - assertEquals(1, configs.size()); - assertRandomizedMacAddressMaskedInWifiConfiguration(configs.get(0)); - - // Verify that randomized MAC address is unmasked when obtaining saved networks from - // (carrier app) creator of the config - configs = mWifiConfigManager.getSavedNetworks(TEST_CREATOR_UID); - assertEquals(1, configs.size()); - assertEquals(macAddress, configs.get(0).getRandomizedMacAddress().toString()); - - // Verify that randomized MAC address is unmasked when getting list of privileged (with - // password) configurations - WifiConfiguration configWithRandomizedMac = mWifiConfigManager - .getConfiguredNetworkWithPassword(result.getNetworkId()); - assertEquals(macAddress, configs.get(0).getRandomizedMacAddress().toString()); - - // Ensure that the MAC address is present when asked for config with MAC address. - configWithRandomizedMac = mWifiConfigManager - .getConfiguredNetworkWithoutMasking(result.getNetworkId()); - assertEquals(macAddress, configs.get(0).getRandomizedMacAddress().toString()); - } - - /** - * Verify that the aggressive randomization whitelist works for passpoints. (by checking FQDN) - */ - @Test - public void testShouldUseAggressiveRandomizationPasspoint() { - WifiConfiguration c = WifiConfigurationTestUtil.createPasspointNetwork(); - // Adds SSID to the whitelist. - Set<String> ssidList = new HashSet<>(); - ssidList.add(c.SSID); - when(mDeviceConfigFacade.getAggressiveMacRandomizationSsidAllowlist()) - .thenReturn(ssidList); - - // Verify that if for passpoint networks we don't check for the SSID to be in the whitelist - assertFalse(mWifiConfigManager.shouldUseAggressiveRandomization(c)); - - // instead we check for the FQDN - ssidList.clear(); - ssidList.add(c.FQDN); - assertTrue(mWifiConfigManager.shouldUseAggressiveRandomization(c)); - } - - /** - * Verify that when DeviceConfigFacade#isEnhancedMacRandomizationEnabled returns true, any - * networks that already use randomized MAC use enhanced MAC randomization instead. - */ - @Test - public void testEnhanecedMacRandomizationIsEnabledGlobally() { - when(mFrameworkFacade.getIntegerSetting(eq(mContext), - eq(WifiConfigManager.ENHANCED_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG), - anyInt())).thenReturn(1); - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(mWifiConfigManager.shouldUseAggressiveRandomization(config)); - - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - assertFalse(mWifiConfigManager.shouldUseAggressiveRandomization(config)); - } - - /** - * Verifies that getRandomizedMacAndUpdateIfNeeded updates the randomized MAC address and - * |randomizedMacExpirationTimeMs| correctly. - * - * Then verify that getRandomizedMacAndUpdateIfNeeded sets the randomized MAC back to the - * persistent MAC. - */ - @Test - public void testRandomizedMacUpdateAndRestore() { - setUpWifiConfigurationForAggressiveRandomization(); - // get the aggressive randomized MAC address. - WifiConfiguration config = getFirstInternalWifiConfiguration(); - final MacAddress aggressiveMac = config.getRandomizedMacAddress(); - assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, aggressiveMac.toString()); - assertEquals(TEST_WALLCLOCK_CREATION_TIME_MILLIS - + WifiConfigManager.AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS, - config.randomizedMacExpirationTimeMs); - - // verify the new randomized mac should be different from the original mac. - when(mClock.getWallClockMillis()).thenReturn(TEST_WALLCLOCK_CREATION_TIME_MILLIS - + WifiConfigManager.AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS + 1); - MacAddress aggressiveMac2 = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config); - - // verify internal WifiConfiguration has MacAddress updated correctly by comparing the - // MAC address from internal WifiConfiguration with the value returned by API. - config = getFirstInternalWifiConfiguration(); - assertEquals(aggressiveMac2, config.getRandomizedMacAddress()); - assertNotEquals(aggressiveMac, aggressiveMac2); - - // Now disable aggressive randomization and verify the randomized MAC is changed back to - // the persistent MAC. - Set<String> blacklist = new HashSet<>(); - blacklist.add(config.SSID); - when(mDeviceConfigFacade.getAggressiveMacRandomizationSsidBlocklist()) - .thenReturn(blacklist); - MacAddress persistentMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config); - - // verify internal WifiConfiguration has MacAddress updated correctly by comparing the - // MAC address from internal WifiConfiguration with the value returned by API. - config = getFirstInternalWifiConfiguration(); - assertEquals(persistentMac, config.getRandomizedMacAddress()); - assertNotEquals(persistentMac, aggressiveMac); - assertNotEquals(persistentMac, aggressiveMac2); - } - - /** - * Verifies that the updateRandomizedMacExpireTime method correctly updates the - * |randomizedMacExpirationTimeMs| field of the given WifiConfiguration. - */ - @Test - public void testUpdateRandomizedMacExpireTime() { - setUpWifiConfigurationForAggressiveRandomization(); - WifiConfiguration config = getFirstInternalWifiConfiguration(); - when(mClock.getWallClockMillis()).thenReturn(0L); - - // verify that |AGGRESSIVE_MAC_REFRESH_MS_MIN| is honored as the lower bound. - long dhcpLeaseTimeInSeconds = (WifiConfigManager.AGGRESSIVE_MAC_REFRESH_MS_MIN / 1000) - 1; - mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpLeaseTimeInSeconds); - config = getFirstInternalWifiConfiguration(); - assertEquals(WifiConfigManager.AGGRESSIVE_MAC_REFRESH_MS_MIN, - config.randomizedMacExpirationTimeMs); - - // verify that |AGGRESSIVE_MAC_REFRESH_MS_MAX| is honored as the upper bound. - dhcpLeaseTimeInSeconds = (WifiConfigManager.AGGRESSIVE_MAC_REFRESH_MS_MAX / 1000) + 1; - mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpLeaseTimeInSeconds); - config = getFirstInternalWifiConfiguration(); - assertEquals(WifiConfigManager.AGGRESSIVE_MAC_REFRESH_MS_MAX, - config.randomizedMacExpirationTimeMs); - - // finally verify setting a valid value between the upper and lower bounds. - dhcpLeaseTimeInSeconds = (WifiConfigManager.AGGRESSIVE_MAC_REFRESH_MS_MIN / 1000) + 5; - mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpLeaseTimeInSeconds); - config = getFirstInternalWifiConfiguration(); - assertEquals(WifiConfigManager.AGGRESSIVE_MAC_REFRESH_MS_MIN + 5000, - config.randomizedMacExpirationTimeMs); - } - - /** - * Verifies that the expiration time of the currently used aggressive MAC is set to the - * maximum of some predefined time and the remaining DHCP lease duration at disconnect. - */ - @Test - public void testRandomizedMacExpirationTimeUpdatedAtDisconnect() { - setUpWifiConfigurationForAggressiveRandomization(); - WifiConfiguration config = getFirstInternalWifiConfiguration(); - when(mClock.getWallClockMillis()).thenReturn(0L); - - // First set the DHCP expiration time to be longer than the predefined time. - long dhcpLeaseTimeInSeconds = (WifiConfigManager.AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS - / 1000) + 1; - mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpLeaseTimeInSeconds); - config = getFirstInternalWifiConfiguration(); - long expirationTime = config.randomizedMacExpirationTimeMs; - assertEquals(WifiConfigManager.AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS + 1000, - expirationTime); - - // Verify that network disconnect does not update the expiration time since the remaining - // lease duration is greater. - mWifiConfigManager.updateNetworkAfterDisconnect(config.networkId); - config = getFirstInternalWifiConfiguration(); - assertEquals(expirationTime, config.randomizedMacExpirationTimeMs); - - // Simulate time moving forward, then verify that a network disconnection updates the - // MAC address expiration time correctly. - when(mClock.getWallClockMillis()).thenReturn(5000L); - mWifiConfigManager.updateNetworkAfterDisconnect(config.networkId); - config = getFirstInternalWifiConfiguration(); - assertEquals(WifiConfigManager.AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS + 5000, - config.randomizedMacExpirationTimeMs); - } - - /** - * Verifies that the randomized MAC address is not updated when insufficient time have past - * since the previous update. - */ - @Test - public void testRandomizedMacIsNotUpdatedDueToTimeConstraint() { - setUpWifiConfigurationForAggressiveRandomization(); - // get the persistent randomized MAC address. - WifiConfiguration config = getFirstInternalWifiConfiguration(); - final MacAddress aggressiveMac = config.getRandomizedMacAddress(); - assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, aggressiveMac.toString()); - assertEquals(TEST_WALLCLOCK_CREATION_TIME_MILLIS - + WifiConfigManager.AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS, - config.randomizedMacExpirationTimeMs); - - // verify that the randomized MAC is unchanged. - when(mClock.getWallClockMillis()).thenReturn(TEST_WALLCLOCK_CREATION_TIME_MILLIS - + WifiConfigManager.AGGRESSIVE_MAC_WAIT_AFTER_DISCONNECT_MS); - MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config); - assertEquals(aggressiveMac, newMac); - } - - /** - * Verifies that aggressive randomization SSID lists from DeviceConfig and overlay are being - * combined together properly. - */ - @Test - public void testPerDeviceAggressiveRandomizationSsids() { - // This will add the SSID to allowlist using DeviceConfig. - setUpWifiConfigurationForAggressiveRandomization(); - WifiConfiguration config = getFirstInternalWifiConfiguration(); - MacAddress aggressiveMac = config.getRandomizedMacAddress(); - - // add to aggressive randomization blocklist using overlay. - mResources.setStringArray(R.array.config_wifi_aggressive_randomization_ssid_blocklist, - new String[] {config.SSID}); - MacAddress persistentMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config); - // verify that now the persistent randomized MAC is used. - assertNotEquals(aggressiveMac, persistentMac); - } - - private WifiConfiguration getFirstInternalWifiConfiguration() { - List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(Process.WIFI_UID); - assertEquals(1, configs.size()); - return configs.get(0); - } - - private void setUpWifiConfigurationForAggressiveRandomization() { - // sets up a WifiConfiguration for aggressive randomization. - WifiConfiguration c = WifiConfigurationTestUtil.createOpenNetwork(); - // Adds the WifiConfiguration to aggressive randomization whitelist. - Set<String> ssidList = new HashSet<>(); - ssidList.add(c.SSID); - when(mDeviceConfigFacade.getAggressiveMacRandomizationSsidAllowlist()) - .thenReturn(ssidList); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(c); - mWifiConfigManager.updateNetworkAfterDisconnect(result.getNetworkId()); - - // Verify the MAC address is valid, and is NOT calculated from the (SSID + security type) - assertTrue(WifiConfiguration.isValidMacAddressForRandomization( - getFirstInternalWifiConfiguration().getRandomizedMacAddress())); - verify(mMacAddressUtil, never()).calculatePersistentMac(any(), any()); - } - - /** - * Verifies that macRandomizationSetting is not masked out when MAC randomization is supported. - */ - @Test - public void testGetConfiguredNetworksNotMaskMacRandomizationSetting() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(config); - - // Verify macRandomizationSetting is not masked out when feature is supported. - List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(Process.WIFI_UID); - assertEquals(1, configs.size()); - assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT, - configs.get(0).macRandomizationSetting); - } - - /** - * Verifies that macRandomizationSetting is masked out to WifiConfiguration.RANDOMIZATION_NONE - * when MAC randomization is not supported on the device. - */ - @Test - public void testGetConfiguredNetworksMasksMacRandomizationSetting() { - mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, false); - createWifiConfigManager(); - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(config); - - // Verify macRandomizationSetting is masked out when feature is unsupported. - List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(Process.WIFI_UID); - assertEquals(1, configs.size()); - assertEquals(WifiConfiguration.RANDOMIZATION_NONE, configs.get(0).macRandomizationSetting); - } - - /** - * Verifies that passwords are masked out when we return external configs except when - * explicitly asked for them. - */ - @Test - public void testGetConfiguredNetworksMasksPasswords() { - WifiConfiguration networkWithPasswords = WifiConfigurationTestUtil.createPskNetwork(); - networkWithPasswords.wepKeys = WifiConfigurationTestUtil.TEST_WEP_KEYS; - networkWithPasswords.preSharedKey = WifiConfigurationTestUtil.TEST_PSK; - networkWithPasswords.enterpriseConfig.setPassword( - WifiConfigurationTestUtil.TEST_EAP_PASSWORD); - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(networkWithPasswords); - - // All of these passwords must be masked in this retrieved network config. - WifiConfiguration retrievedNetworkWithMaskedPassword = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - assertPasswordsMaskedInWifiConfiguration(retrievedNetworkWithMaskedPassword); - - // Ensure that the passwords are present when asked for configs with passwords. - WifiConfiguration retrievedNetworkWithPassword = - mWifiConfigManager.getConfiguredNetworkWithPassword(result.getNetworkId()); - assertEquals(networkWithPasswords.preSharedKey, retrievedNetworkWithPassword.preSharedKey); - assertEquals(networkWithPasswords.wepKeys, retrievedNetworkWithPassword.wepKeys); - assertEquals(networkWithPasswords.enterpriseConfig.getPassword(), - retrievedNetworkWithPassword.enterpriseConfig.getPassword()); - - retrievedNetworkWithPassword = - mWifiConfigManager.getConfiguredNetworkWithoutMasking(result.getNetworkId()); - assertEquals(networkWithPasswords.preSharedKey, retrievedNetworkWithPassword.preSharedKey); - assertEquals(networkWithPasswords.wepKeys, retrievedNetworkWithPassword.wepKeys); - assertEquals(networkWithPasswords.enterpriseConfig.getPassword(), - retrievedNetworkWithPassword.enterpriseConfig.getPassword()); - } - - /** - * Verifies the linking of networks when they have the same default GW Mac address in - * {@link WifiConfigManager#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}. - */ - @Test - public void testNetworkLinkUsingGwMacAddress() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - verifyAddNetworkToWifiConfigManager(network2); - verifyAddNetworkToWifiConfigManager(network3); - - // Set the same default GW mac address for all of the networks. - assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress( - network1.networkId, TEST_DEFAULT_GW_MAC_ADDRESS)); - assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress( - network2.networkId, TEST_DEFAULT_GW_MAC_ADDRESS)); - assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress( - network3.networkId, TEST_DEFAULT_GW_MAC_ADDRESS)); - - // Now create dummy scan detail corresponding to the networks. - ScanDetail networkScanDetail1 = createScanDetailForNetwork(network1); - ScanDetail networkScanDetail2 = createScanDetailForNetwork(network2); - ScanDetail networkScanDetail3 = createScanDetailForNetwork(network3); - - // Now save all these scan details corresponding to each of this network and expect - // all of these networks to be linked with each other. - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail1)); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail2)); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail3)); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : retrievedNetworks) { - assertEquals(2, network.linkedConfigurations.size()); - for (WifiConfiguration otherNetwork : retrievedNetworks) { - if (otherNetwork == network) { - continue; - } - assertNotNull(network.linkedConfigurations.get(otherNetwork.getKey())); - } - } - } - - /** - * Verifies the linking of networks when they have scan results with same first 16 ASCII of - * bssid in - * {@link WifiConfigManager#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}. - */ - @Test - public void testNetworkLinkUsingBSSIDMatch() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - verifyAddNetworkToWifiConfigManager(network2); - verifyAddNetworkToWifiConfigManager(network3); - - // Create scan results with bssid which is different in only the last char. - ScanDetail networkScanDetail1 = createScanDetailForNetwork(network1, "af:89:56:34:56:67"); - ScanDetail networkScanDetail2 = createScanDetailForNetwork(network2, "af:89:56:34:56:68"); - ScanDetail networkScanDetail3 = createScanDetailForNetwork(network3, "af:89:56:34:56:69"); - - // Now save all these scan details corresponding to each of this network and expect - // all of these networks to be linked with each other. - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail1)); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail2)); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail3)); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : retrievedNetworks) { - assertEquals(2, network.linkedConfigurations.size()); - for (WifiConfiguration otherNetwork : retrievedNetworks) { - if (otherNetwork == network) { - continue; - } - assertNotNull(network.linkedConfigurations.get(otherNetwork.getKey())); - } - } - } - - /** - * Verifies the linking of networks does not happen for non WPA networks when they have scan - * results with same first 16 ASCII of bssid in - * {@link WifiConfigManager#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}. - */ - @Test - public void testNoNetworkLinkUsingBSSIDMatchForNonWpaNetworks() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - verifyAddNetworkToWifiConfigManager(network2); - - // Create scan results with bssid which is different in only the last char. - ScanDetail networkScanDetail1 = createScanDetailForNetwork(network1, "af:89:56:34:56:67"); - ScanDetail networkScanDetail2 = createScanDetailForNetwork(network2, "af:89:56:34:56:68"); - - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail1)); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail2)); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : retrievedNetworks) { - assertNull(network.linkedConfigurations); - } - } - - /** - * Verifies the linking of networks does not happen for networks with more than - * {@link WifiConfigManager#LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES} scan - * results with same first 16 ASCII of bssid in - * {@link WifiConfigManager#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}. - */ - @Test - public void testNoNetworkLinkUsingBSSIDMatchForNetworksWithHighScanDetailCacheSize() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - verifyAddNetworkToWifiConfigManager(network2); - - // Create 7 scan results with bssid which is different in only the last char. - String test_bssid_base = "af:89:56:34:56:6"; - int scan_result_num = 0; - for (; scan_result_num < WifiConfigManager.LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES + 1; - scan_result_num++) { - ScanDetail networkScanDetail = - createScanDetailForNetwork( - network1, test_bssid_base + Integer.toString(scan_result_num)); - assertNotNull( - mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail)); - } - - // Now add 1 scan result to the other network with bssid which is different in only the - // last char. - ScanDetail networkScanDetail2 = - createScanDetailForNetwork( - network2, test_bssid_base + Integer.toString(scan_result_num++)); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail2)); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : retrievedNetworks) { - assertNull(network.linkedConfigurations); - } - } - - /** - * Verifies the linking of networks when they have scan results with same first 16 ASCII of - * bssid in {@link WifiConfigManager#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)} - * and then subsequently delinked when the networks have default gateway set which do not match. - */ - @Test - public void testNetworkLinkUsingBSSIDMatchAndThenUnlinkDueToGwMacAddress() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - verifyAddNetworkToWifiConfigManager(network2); - - // Create scan results with bssid which is different in only the last char. - ScanDetail networkScanDetail1 = createScanDetailForNetwork(network1, "af:89:56:34:56:67"); - ScanDetail networkScanDetail2 = createScanDetailForNetwork(network2, "af:89:56:34:56:68"); - - // Now save all these scan details corresponding to each of this network and expect - // all of these networks to be linked with each other. - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail1)); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - networkScanDetail2)); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : retrievedNetworks) { - assertEquals(1, network.linkedConfigurations.size()); - for (WifiConfiguration otherNetwork : retrievedNetworks) { - if (otherNetwork == network) { - continue; - } - assertNotNull(network.linkedConfigurations.get(otherNetwork.getKey())); - } - } - - // Now Set different GW mac address for both the networks and ensure they're unlinked. - assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress( - network1.networkId, "de:ad:fe:45:23:34")); - assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress( - network2.networkId, "ad:de:fe:45:23:34")); - - // Add some dummy scan results again to re-evaluate the linking of networks. - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - createScanDetailForNetwork(network1, "af:89:56:34:45:67"))); - assertNotNull(mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - createScanDetailForNetwork(network1, "af:89:56:34:45:68"))); - - retrievedNetworks = mWifiConfigManager.getConfiguredNetworks(); - for (WifiConfiguration network : retrievedNetworks) { - assertNull(network.linkedConfigurations); - } - } - - /** - * Verifies the foreground user switch using {@link WifiConfigManager#handleUserSwitch(int)} - * and ensures that any shared private networks networkId is not changed. - * Test scenario: - * 1. Load the shared networks from shared store and user 1 store. - * 2. Switch to user 2 and ensure that the shared network's Id is not changed. - */ - @Test - public void testHandleUserSwitchDoesNotChangeSharedNetworksId() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - int appId = 674; - long currentTimeMs = 67823; - when(mClock.getWallClockMillis()).thenReturn(currentTimeMs); - - // Create 3 networks. 1 for user1, 1 for user2 and 1 shared. - final WifiConfiguration user1Network = WifiConfigurationTestUtil.createPskNetwork(); - user1Network.shared = false; - user1Network.creatorUid = UserHandle.getUid(user1, appId); - final WifiConfiguration user2Network = WifiConfigurationTestUtil.createPskNetwork(); - user2Network.shared = false; - user2Network.creatorUid = UserHandle.getUid(user2, appId); - final WifiConfiguration sharedNetwork1 = WifiConfigurationTestUtil.createPskNetwork(); - final WifiConfiguration sharedNetwork2 = WifiConfigurationTestUtil.createPskNetwork(); - - // Set up the store data that is loaded initially. - List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork1); - add(sharedNetwork2); - } - }; - List<WifiConfiguration> user1Networks = new ArrayList<WifiConfiguration>() { - { - add(user1Network); - } - }; - setupStoreDataForRead(sharedNetworks, user1Networks); - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - - // Fetch the network ID's assigned to the shared networks initially. - int sharedNetwork1Id = WifiConfiguration.INVALID_NETWORK_ID; - int sharedNetwork2Id = WifiConfiguration.INVALID_NETWORK_ID; - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - for (WifiConfiguration network : retrievedNetworks) { - if (network.getKey().equals(sharedNetwork1.getKey())) { - sharedNetwork1Id = network.networkId; - } else if (network.getKey().equals(sharedNetwork2.getKey())) { - sharedNetwork2Id = network.networkId; - } - } - assertTrue(sharedNetwork1Id != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(sharedNetwork2Id != WifiConfiguration.INVALID_NETWORK_ID); - assertFalse(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(TEST_SSID)); - - // Set up the user 2 store data that is loaded at user switch. - List<WifiConfiguration> user2Networks = new ArrayList<WifiConfiguration>() { - { - add(user2Network); - } - }; - setupStoreDataForUserRead(user2Networks, new HashMap<>()); - // Now switch the user to user 2 and ensure that shared network's IDs have not changed. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - mWifiConfigManager.handleUserSwitch(user2); - verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class)); - - // Again fetch the network ID's assigned to the shared networks and ensure they have not - // changed. - int updatedSharedNetwork1Id = WifiConfiguration.INVALID_NETWORK_ID; - int updatedSharedNetwork2Id = WifiConfiguration.INVALID_NETWORK_ID; - retrievedNetworks = mWifiConfigManager.getConfiguredNetworksWithPasswords(); - for (WifiConfiguration network : retrievedNetworks) { - if (network.getKey().equals(sharedNetwork1.getKey())) { - updatedSharedNetwork1Id = network.networkId; - } else if (network.getKey().equals(sharedNetwork2.getKey())) { - updatedSharedNetwork2Id = network.networkId; - } - } - assertEquals(sharedNetwork1Id, updatedSharedNetwork1Id); - assertEquals(sharedNetwork2Id, updatedSharedNetwork2Id); - assertFalse(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(TEST_SSID)); - } - - /** - * Verifies the foreground user switch using {@link WifiConfigManager#handleUserSwitch(int)} - * and ensures that any old user private networks are not visible anymore. - * Test scenario: - * 1. Load the shared networks from shared store and user 1 store. - * 2. Switch to user 2 and ensure that the user 1's private network has been removed. - */ - @Test - public void testHandleUserSwitchRemovesOldUserPrivateNetworks() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - int appId = 674; - - // Create 3 networks. 1 for user1, 1 for user2 and 1 shared. - final WifiConfiguration user1Network = WifiConfigurationTestUtil.createPskNetwork(); - user1Network.shared = false; - user1Network.creatorUid = UserHandle.getUid(user1, appId); - final WifiConfiguration user2Network = WifiConfigurationTestUtil.createPskNetwork(); - user2Network.shared = false; - user2Network.creatorUid = UserHandle.getUid(user2, appId); - final WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - - // Set up the store data that is loaded initially. - List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork); - } - }; - List<WifiConfiguration> user1Networks = new ArrayList<WifiConfiguration>() { - { - add(user1Network); - } - }; - setupStoreDataForRead(sharedNetworks, user1Networks); - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - - // Fetch the network ID assigned to the user 1 network initially. - int user1NetworkId = WifiConfiguration.INVALID_NETWORK_ID; - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - for (WifiConfiguration network : retrievedNetworks) { - if (network.getKey().equals(user1Network.getKey())) { - user1NetworkId = network.networkId; - } - } - - // Set up the user 2 store data that is loaded at user switch. - List<WifiConfiguration> user2Networks = new ArrayList<WifiConfiguration>() { - { - add(user2Network); - } - }; - setupStoreDataForUserRead(user2Networks, new HashMap<>()); - // Now switch the user to user 2 and ensure that user 1's private network has been removed. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user1Network.creatorUid)) - .thenReturn(false); - Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2); - verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class)); - assertTrue((removedNetworks.size() == 1) && (removedNetworks.contains(user1NetworkId))); - verify(mWcmListener).onNetworkRemoved(any()); - - // Set the expected networks to be |sharedNetwork| and |user2Network|. - List<WifiConfiguration> expectedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork); - add(user2Network); - } - }; - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - expectedNetworks, mWifiConfigManager.getConfiguredNetworksWithPasswords()); - - // Send another user switch indication with the same user 2. This should be ignored and - // hence should not remove any new networks. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - removedNetworks = mWifiConfigManager.handleUserSwitch(user2); - assertTrue(removedNetworks.isEmpty()); - } - - @Test - public void testHandleUserSwitchRemovesOldUserEphemeralNetworks() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - int appId = 674; - - // Create 2 networks. 1 ephemeral network for user1 and 1 shared. - final WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - - // Set up the store data that is loaded initially. - List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork); - } - }; - setupStoreDataForRead(sharedNetworks, Collections.EMPTY_LIST); - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - - WifiConfiguration ephemeralNetwork = WifiConfigurationTestUtil.createEphemeralNetwork(); - verifyAddEphemeralNetworkToWifiConfigManager(ephemeralNetwork); - - // Fetch the network ID assigned to the user 1 network initially. - int ephemeralNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - for (WifiConfiguration network : retrievedNetworks) { - if (network.getKey().equals(ephemeralNetwork.getKey())) { - ephemeralNetworkId = network.networkId; - } - } - - // Now switch the user to user 2 and ensure that user 1's private network has been removed. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2); - verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class)); - assertTrue((removedNetworks.size() == 1)); - assertTrue(removedNetworks.contains(ephemeralNetworkId)); - verifyNetworkRemoveBroadcast(); - verify(mWcmListener).onNetworkRemoved(any()); - - - // Set the expected networks to be |sharedNetwork|. - List<WifiConfiguration> expectedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork); - } - }; - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - expectedNetworks, mWifiConfigManager.getConfiguredNetworksWithPasswords()); - - // Send another user switch indication with the same user 2. This should be ignored and - // hence should not remove any new networks. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - removedNetworks = mWifiConfigManager.handleUserSwitch(user2); - assertTrue(removedNetworks.isEmpty()); - } - - /** - * Verifies the foreground user switch using {@link WifiConfigManager#handleUserSwitch(int)} - * and ensures that user switch from a user with no private networks is handled. - * Test scenario: - * 1. Load the shared networks from shared store and emptu user 1 store. - * 2. Switch to user 2 and ensure that no private networks were removed. - */ - @Test - public void testHandleUserSwitchWithNoOldUserPrivateNetworks() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - int appId = 674; - - // Create 2 networks. 1 for user2 and 1 shared. - final WifiConfiguration user2Network = WifiConfigurationTestUtil.createPskNetwork(); - user2Network.shared = false; - user2Network.creatorUid = UserHandle.getUid(user2, appId); - final WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - - // Set up the store data that is loaded initially. - List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork); - } - }; - setupStoreDataForRead(sharedNetworks, new ArrayList<>()); - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - - // Set up the user 2 store data that is loaded at user switch. - List<WifiConfiguration> user2Networks = new ArrayList<WifiConfiguration>() { - { - add(user2Network); - } - }; - setupStoreDataForUserRead(user2Networks, new HashMap<>()); - // Now switch the user to user 2 and ensure that no private network has been removed. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2); - verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class)); - assertTrue(removedNetworks.isEmpty()); - } - - /** - * Verifies the foreground user switch using {@link WifiConfigManager#handleUserSwitch(int)} - * and ensures that any non current user private networks are moved to shared store file. - * This test simulates the following test case: - * 1. Loads the shared networks from shared store at bootup. - * 2. Load the private networks from user store on user 1 unlock. - * 3. Switch to user 2 and ensure that the user 2's private network has been moved to user 2's - * private store file. - */ - @Test - public void testHandleUserSwitchPushesOtherPrivateNetworksToSharedStore() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user1); - - int appId = 674; - - // Create 3 networks. 1 for user1, 1 for user2 and 1 shared. - final WifiConfiguration user1Network = WifiConfigurationTestUtil.createPskNetwork(); - user1Network.shared = false; - user1Network.creatorUid = UserHandle.getUid(user1, appId); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(user1Network.creatorUid)) - .thenReturn(false); - - final WifiConfiguration user2Network = WifiConfigurationTestUtil.createPskNetwork(); - user2Network.shared = false; - user2Network.creatorUid = UserHandle.getUid(user2, appId); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(user2Network.creatorUid)) - .thenReturn(false); - - final WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - - // Set up the shared store data that is loaded at bootup. User 2's private network - // is still in shared store because they have not yet logged-in after upgrade. - List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork); - add(user2Network); - } - }; - setupStoreDataForRead(sharedNetworks, new ArrayList<>()); - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - - // Set up the user store data that is loaded at user unlock. - List<WifiConfiguration> userNetworks = new ArrayList<WifiConfiguration>() { - { - add(user1Network); - } - }; - setupStoreDataForUserRead(userNetworks, new HashMap<>()); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user2Network.creatorUid)) - .thenReturn(false); - mWifiConfigManager.handleUserUnlock(user1); - verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class)); - // Capture the written data for the user 1 and ensure that it corresponds to what was - // setup. - Pair<List<WifiConfiguration>, List<WifiConfiguration>> writtenNetworkList = - captureWriteNetworksListStoreData(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - sharedNetworks, writtenNetworkList.first); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - userNetworks, writtenNetworkList.second); - - // Now switch the user to user2 and ensure that user 2's private network has been moved to - // the user store. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user1Network.creatorUid)) - .thenReturn(true).thenReturn(false); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user2Network.creatorUid)) - .thenReturn(false).thenReturn(true); - mWifiConfigManager.handleUserSwitch(user2); - // Set the expected network list before comparing. user1Network should be in shared data. - // Note: In the real world, user1Network will no longer be visible now because it should - // already be in user1's private store file. But, we're purposefully exposing it - // via |loadStoreData| to test if other user's private networks are pushed to shared store. - List<WifiConfiguration> expectedSharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork); - add(user1Network); - } - }; - List<WifiConfiguration> expectedUserNetworks = new ArrayList<WifiConfiguration>() { - { - add(user2Network); - } - }; - // Capture the first written data triggered for saving the old user's network - // configurations. - writtenNetworkList = captureWriteNetworksListStoreData(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - sharedNetworks, writtenNetworkList.first); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - userNetworks, writtenNetworkList.second); - - // Now capture the next written data triggered after the switch and ensure that user 2's - // network is now in user store data. - writtenNetworkList = captureWriteNetworksListStoreData(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - expectedSharedNetworks, writtenNetworkList.first); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - expectedUserNetworks, writtenNetworkList.second); - } - - /** - * Verify that unlocking an user that owns a legacy Passpoint configuration (which is stored - * temporarily in the share store) will migrate it to PasspointManager and removed from - * the list of configured networks. - * - * @throws Exception - */ - @Test - public void testHandleUserUnlockRemovePasspointConfigFromSharedConfig() throws Exception { - int user1 = TEST_DEFAULT_USER; - int appId = 674; - - final WifiConfiguration passpointConfig = - WifiConfigurationTestUtil.createPasspointNetwork(); - passpointConfig.creatorUid = UserHandle.getUid(user1, appId); - passpointConfig.isLegacyPasspointConfig = true; - - // Set up the shared store data to contain one legacy Passpoint configuration. - List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(passpointConfig); - } - }; - setupStoreDataForRead(sharedNetworks, new ArrayList<>()); - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - assertEquals(1, mWifiConfigManager.getConfiguredNetworks().size()); - - // Unlock the owner of the legacy Passpoint configuration, verify it is removed from - // the configured networks (migrated to PasspointManager). - setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashMap<>()); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(passpointConfig.creatorUid)) - .thenReturn(false); - mWifiConfigManager.handleUserUnlock(user1); - verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class)); - Pair<List<WifiConfiguration>, List<WifiConfiguration>> writtenNetworkList = - captureWriteNetworksListStoreData(); - assertTrue(writtenNetworkList.first.isEmpty()); - assertTrue(writtenNetworkList.second.isEmpty()); - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - } - - /** - * Verifies the foreground user switch using {@link WifiConfigManager#handleUserSwitch(int)} - * and {@link WifiConfigManager#handleUserUnlock(int)} and ensures that the new store is - * read immediately if the user is unlocked during the switch. - */ - @Test - public void testHandleUserSwitchWhenUnlocked() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - // Set up the internal data first. - assertTrue(mWifiConfigManager.loadFromStore()); - - setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>()); - // user2 is unlocked and switched to foreground. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - mWifiConfigManager.handleUserSwitch(user2); - // Ensure that the read was invoked. - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .switchUserStoresAndRead(any(List.class)); - } - - /** - * Verifies the foreground user switch using {@link WifiConfigManager#handleUserSwitch(int)} - * and {@link WifiConfigManager#handleUserUnlock(int)} and ensures that the new store is not - * read until the user is unlocked. - */ - @Test - public void testHandleUserSwitchWhenLocked() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - // Set up the internal data first. - assertTrue(mWifiConfigManager.loadFromStore()); - - // user2 is locked and switched to foreground. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(false); - mWifiConfigManager.handleUserSwitch(user2); - - // Ensure that the read was not invoked. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - // Now try unlocking some other user (user1), this should be ignored. - mWifiConfigManager.handleUserUnlock(user1); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>()); - // Unlock the user2 and ensure that we read the data now. - mWifiConfigManager.handleUserUnlock(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .switchUserStoresAndRead(any(List.class)); - } - - /** - * Verifies that the user stop handling using {@link WifiConfigManager#handleUserStop(int)} - * and ensures that the store is written only when the foreground user is stopped. - */ - @Test - public void testHandleUserStop() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - // Set up the internal data first. - assertTrue(mWifiConfigManager.loadFromStore()); - - // Try stopping background user2 first, this should not do anything. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(false); - mWifiConfigManager.handleUserStop(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - // Now try stopping the foreground user1, this should trigger a write to store. - mWifiConfigManager.handleUserStop(user1); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean()); - } - - /** - * Verifies that the user stop handling using {@link WifiConfigManager#handleUserStop(int)} - * and ensures that the shared data is not lost when the foreground user is stopped. - */ - @Test - public void testHandleUserStopDoesNotClearSharedData() throws Exception { - int user1 = TEST_DEFAULT_USER; - - // - // Setup the database for the user before initiating stop. - // - int appId = 674; - // Create 2 networks. 1 for user1, and 1 shared. - final WifiConfiguration user1Network = WifiConfigurationTestUtil.createPskNetwork(); - user1Network.shared = false; - user1Network.creatorUid = UserHandle.getUid(user1, appId); - final WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - - // Set up the store data that is loaded initially. - List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(sharedNetwork); - } - }; - List<WifiConfiguration> user1Networks = new ArrayList<WifiConfiguration>() { - { - add(user1Network); - } - }; - setupStoreDataForRead(sharedNetworks, user1Networks); - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - - // Ensure that we have 2 networks in the database before the stop. - assertEquals(2, mWifiConfigManager.getConfiguredNetworks().size()); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user1Network.creatorUid)) - .thenReturn(false); - mWifiConfigManager.handleUserStop(user1); - - // Ensure that we only have 1 shared network in the database after the stop. - assertEquals(1, mWifiConfigManager.getConfiguredNetworks().size()); - assertEquals(sharedNetwork.SSID, mWifiConfigManager.getConfiguredNetworks().get(0).SSID); - } - - /** - * Verifies the foreground user unlock via {@link WifiConfigManager#handleUserUnlock(int)} - * results in a store read after bootup. - */ - @Test - public void testHandleUserUnlockAfterBootup() throws Exception { - int user1 = TEST_DEFAULT_USER; - - // Set up the internal data first. - assertTrue(mWifiConfigManager.loadFromStore()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>()); - // Unlock the user1 (default user) for the first time and ensure that we read the data. - mWifiConfigManager.handleUserUnlock(user1); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .switchUserStoresAndRead(any(List.class)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean()); - } - - /** - * Verifies that the store read after bootup received after - * foreground user unlock via {@link WifiConfigManager#handleUserUnlock(int)} - * results in a user store read. - */ - @Test - public void testHandleBootupAfterUserUnlock() throws Exception { - int user1 = TEST_DEFAULT_USER; - - // Unlock the user1 (default user) for the first time and ensure that we don't read the - // data. - mWifiConfigManager.handleUserUnlock(user1); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashMap<>()); - // Read from store now. - assertTrue(mWifiConfigManager.loadFromStore()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .setUserStores(any(List.class)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).read(); - } - - /** - * Verifies that the store read after bootup received after - * a user switch via {@link WifiConfigManager#handleUserSwitch(int)} - * results in a user store read. - */ - @Test - public void testHandleBootupAfterUserSwitch() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - // Switch from user1 to user2 and ensure that we don't read or write any data - // (need to wait for loadFromStore invocation). - mWifiConfigManager.handleUserSwitch(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - // Now load from the store. - assertTrue(mWifiConfigManager.loadFromStore()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).read(); - - // Unlock the user2 and ensure that we read from the user store. - setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>()); - mWifiConfigManager.handleUserUnlock(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .switchUserStoresAndRead(any(List.class)); - } - - /** - * Verifies that the store read after bootup received after - * a previous user unlock and user switch via {@link WifiConfigManager#handleUserSwitch(int)} - * results in a user store read. - */ - @Test - public void testHandleBootupAfterPreviousUserUnlockAndSwitch() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - // Unlock the user1 (default user) for the first time and ensure that we don't read the data - // (need to wait for loadFromStore invocation). - mWifiConfigManager.handleUserUnlock(user1); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - // Switch from user1 to user2 and ensure that we don't read or write any data - // (need to wait for loadFromStore invocation). - mWifiConfigManager.handleUserSwitch(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - // Now load from the store. - assertTrue(mWifiConfigManager.loadFromStore()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).read(); - - // Unlock the user2 and ensure that we read from the user store. - setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>()); - mWifiConfigManager.handleUserUnlock(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .switchUserStoresAndRead(any(List.class)); - } - - /** - * Verifies that the store read after bootup received after - * a user switch and unlock of a previous user via {@link WifiConfigManager# - * handleUserSwitch(int)} results in a user store read. - */ - @Test - public void testHandleBootupAfterUserSwitchAndPreviousUserUnlock() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - // Switch from user1 to user2 and ensure that we don't read or write any data - // (need to wait for loadFromStore invocation). - mWifiConfigManager.handleUserSwitch(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - // Unlock the user1 for the first time and ensure that we don't read the data - mWifiConfigManager.handleUserUnlock(user1); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - - // Now load from the store. - assertTrue(mWifiConfigManager.loadFromStore()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).read(); - - // Unlock the user2 and ensure that we read from the user store. - setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>()); - mWifiConfigManager.handleUserUnlock(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .switchUserStoresAndRead(any(List.class)); - } - - /** - * Verifies the foreground user unlock via {@link WifiConfigManager#handleUserUnlock(int)} does - * not always result in a store read unless the user had switched or just booted up. - */ - @Test - public void testHandleUserUnlockWithoutSwitchOrBootup() throws Exception { - int user1 = TEST_DEFAULT_USER; - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - // Set up the internal data first. - assertTrue(mWifiConfigManager.loadFromStore()); - - setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>()); - // user2 is unlocked and switched to foreground. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - mWifiConfigManager.handleUserSwitch(user2); - // Ensure that the read was invoked. - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .switchUserStoresAndRead(any(List.class)); - - // Unlock the user2 again and ensure that we don't read the data now. - mWifiConfigManager.handleUserUnlock(user2); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .switchUserStoresAndRead(any(List.class)); - } - - /** - * Verifies the private network addition using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - * by a non foreground user is rejected. - */ - @Test - public void testAddNetworkUsingBackgroundUserUId() throws Exception { - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - int creatorUid = UserHandle.getUid(user2, 674); - - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(creatorUid)).thenReturn(false); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(creatorUid)).thenReturn(false); - - // Create a network for user2 try adding it. This should be rejected. - final WifiConfiguration user2Network = WifiConfigurationTestUtil.createPskNetwork(); - NetworkUpdateResult result = addNetworkToWifiConfigManager(user2Network, creatorUid); - assertFalse(result.isSuccess()); - } - - /** - * Verifies the private network addition using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} - * by SysUI is always accepted. - */ - @Test - public void testAddNetworkUsingSysUiUid() throws Exception { - // Set up the user profiles stuff. Needed for |WifiConfigurationUtil.isVisibleToAnyProfile| - int user2 = TEST_DEFAULT_USER + 1; - setupUserProfiles(user2); - - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(false); - mWifiConfigManager.handleUserSwitch(user2); - - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(TEST_SYSUI_UID)).thenReturn(true); - - // Create a network for user2 try adding it. This should be rejected. - final WifiConfiguration user2Network = WifiConfigurationTestUtil.createPskNetwork(); - NetworkUpdateResult result = addNetworkToWifiConfigManager(user2Network, TEST_SYSUI_UID); - assertTrue(result.isSuccess()); - } - - /** - * Verifies the loading of networks using {@link WifiConfigManager#loadFromStore()} - * attempts to read from the stores even when the store files are not present. - */ - @Test - public void testFreshInstallLoadFromStore() throws Exception { - assertTrue(mWifiConfigManager.loadFromStore()); - - verify(mWifiConfigStore).read(); - - assertTrue(mWifiConfigManager.getConfiguredNetworksWithPasswords().isEmpty()); - } - - /** - * Verifies the loading of networks using {@link WifiConfigManager#loadFromStore()} - * attempts to read from the stores even if the store files are not present and the - * user unlock already comes in. - */ - @Test - public void testFreshInstallLoadFromStoreAfterUserUnlock() throws Exception { - int user1 = TEST_DEFAULT_USER; - - // Unlock the user1 (default user) for the first time and ensure that we don't read the - // data. - mWifiConfigManager.handleUserUnlock(user1); - verify(mWifiConfigStore, never()).read(); - - // Read from store now. - assertTrue(mWifiConfigManager.loadFromStore()); - - // Ensure that the read was invoked. - verify(mWifiConfigStore).read(); - } - - /** - * Verifies the user switch using {@link WifiConfigManager#handleUserSwitch(int)} is handled - * when the store files (new or legacy) are not present. - */ - @Test - public void testHandleUserSwitchAfterFreshInstall() throws Exception { - int user2 = TEST_DEFAULT_USER + 1; - - assertTrue(mWifiConfigManager.loadFromStore()); - verify(mWifiConfigStore).read(); - - setupStoreDataForUserRead(new ArrayList<>(), new HashMap<>()); - // Now switch the user to user 2. - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true); - mWifiConfigManager.handleUserSwitch(user2); - // Ensure that the read was invoked. - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .switchUserStoresAndRead(any(List.class)); - } - - /** - * Verifies that the last user selected network parameter is set when - * {@link WifiConfigManager#enableNetwork(int, boolean, int)} with disableOthers flag is set - * to true and cleared when either {@link WifiConfigManager#disableNetwork(int, int)} or - * {@link WifiConfigManager#removeNetwork(int, int)} is invoked using the same network ID. - */ - @Test - public void testLastSelectedNetwork() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(67L); - assertTrue(mWifiConfigManager.enableNetwork( - result.getNetworkId(), true, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - assertEquals(result.getNetworkId(), mWifiConfigManager.getLastSelectedNetwork()); - assertEquals(67, mWifiConfigManager.getLastSelectedTimeStamp()); - - // Now disable the network and ensure that the last selected flag is cleared. - assertTrue(mWifiConfigManager.disableNetwork( - result.getNetworkId(), TEST_CREATOR_UID, TEST_CREATOR_NAME)); - assertEquals( - WifiConfiguration.INVALID_NETWORK_ID, mWifiConfigManager.getLastSelectedNetwork()); - - // Enable it again and remove the network to ensure that the last selected flag was cleared. - assertTrue(mWifiConfigManager.enableNetwork( - result.getNetworkId(), true, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - assertEquals(result.getNetworkId(), mWifiConfigManager.getLastSelectedNetwork()); - assertEquals(openNetwork.getKey(), mWifiConfigManager.getLastSelectedNetworkConfigKey()); - - assertTrue(mWifiConfigManager.removeNetwork( - result.getNetworkId(), TEST_CREATOR_UID, TEST_CREATOR_NAME)); - assertEquals( - WifiConfiguration.INVALID_NETWORK_ID, mWifiConfigManager.getLastSelectedNetwork()); - } - - /** - * Verifies that all the networks for the provided app is removed when - * {@link WifiConfigManager#removeNetworksForApp(ApplicationInfo)} is invoked. - */ - @Test - public void testRemoveNetworksForApp() throws Exception { - when(mPackageManager.getNameForUid(TEST_CREATOR_UID)).thenReturn(TEST_CREATOR_NAME); - - verifyRemoveNetworksForApp(); - } - - /** - * Verifies that all the networks for the provided app is removed when - * {@link WifiConfigManager#removeNetworksForApp(ApplicationInfo)} is invoked. - */ - @Test - public void testRemoveNetworksForAppUsingSharedUid() throws Exception { - when(mPackageManager.getNameForUid(TEST_CREATOR_UID)) - .thenReturn(TEST_CREATOR_NAME + ":" + TEST_CREATOR_UID); - - verifyRemoveNetworksForApp(); - } - - /** - * Verifies that all the networks for the provided user is removed when - * {@link WifiConfigManager#removeNetworksForUser(int)} is invoked. - */ - @Test - public void testRemoveNetworksForUser() throws Exception { - verifyAddNetworkToWifiConfigManager(WifiConfigurationTestUtil.createOpenNetwork()); - verifyAddNetworkToWifiConfigManager(WifiConfigurationTestUtil.createPskNetwork()); - verifyAddNetworkToWifiConfigManager(WifiConfigurationTestUtil.createWepNetwork()); - - assertFalse(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - - assertEquals(3, mWifiConfigManager.removeNetworksForUser(TEST_DEFAULT_USER).size()); - - // Ensure all the networks are removed now. - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - } - - /** - * Verifies that the connect choice is removed from all networks when - * {@link WifiConfigManager#removeNetwork(int, int)} is invoked. - */ - @Test - public void testRemoveNetworkRemovesConnectChoice() throws Exception { - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - verifyAddNetworkToWifiConfigManager(network2); - verifyAddNetworkToWifiConfigManager(network3); - - // Set connect choice of network 2 over network 1. - assertTrue( - mWifiConfigManager.setNetworkConnectChoice( - network1.networkId, network2.getKey())); - - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(network1.networkId); - assertEquals( - network2.getKey(), - retrievedNetwork.getNetworkSelectionStatus().getConnectChoice()); - - // Remove network 3 and ensure that the connect choice on network 1 is not removed. - assertTrue(mWifiConfigManager.removeNetwork( - network3.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(network1.networkId); - assertEquals( - network2.getKey(), - retrievedNetwork.getNetworkSelectionStatus().getConnectChoice()); - - // Now remove network 2 and ensure that the connect choice on network 1 is removed.. - assertTrue(mWifiConfigManager.removeNetwork( - network2.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(network1.networkId); - assertNotEquals( - network2.getKey(), - retrievedNetwork.getNetworkSelectionStatus().getConnectChoice()); - - // This should have triggered 2 buffered writes. 1 for setting the connect choice, 1 for - // clearing it after network removal. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, times(2)).write(eq(false)); - } - - /** - * Disabling autojoin should clear associated connect choice links. - */ - @Test - public void testDisableAutojoinRemovesConnectChoice() throws Exception { - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createPskNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - verifyAddNetworkToWifiConfigManager(network2); - verifyAddNetworkToWifiConfigManager(network3); - - // Set connect choice of network 2 over network 1 and network 3. - assertTrue( - mWifiConfigManager.setNetworkConnectChoice( - network1.networkId, network2.getKey())); - assertTrue( - mWifiConfigManager.setNetworkConnectChoice( - network3.networkId, network2.getKey())); - - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(network3.networkId); - assertEquals( - network2.getKey(), - retrievedNetwork.getNetworkSelectionStatus().getConnectChoice()); - - // Disable network 3 - assertTrue(mWifiConfigManager.allowAutojoin(network3.networkId, false)); - // Ensure that the connect choice on network 3 is removed. - retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(network3.networkId); - assertEquals( - null, - retrievedNetwork.getNetworkSelectionStatus().getConnectChoice()); - // Ensure that the connect choice on network 1 is not removed. - retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(network1.networkId); - assertEquals( - network2.getKey(), - retrievedNetwork.getNetworkSelectionStatus().getConnectChoice()); - } - - /** - * Verifies that all the ephemeral and passpoint networks are removed when - * {@link WifiConfigManager#removeAllEphemeralOrPasspointConfiguredNetworks()} is invoked. - */ - @Test - public void testRemoveAllEphemeralOrPasspointConfiguredNetworks() throws Exception { - WifiConfiguration savedOpenNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration ephemeralNetwork = WifiConfigurationTestUtil.createEphemeralNetwork(); - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - - verifyAddNetworkToWifiConfigManager(savedOpenNetwork); - verifyAddEphemeralNetworkToWifiConfigManager(ephemeralNetwork); - verifyAddPasspointNetworkToWifiConfigManager(passpointNetwork); - - List<WifiConfiguration> expectedConfigsBeforeRemove = new ArrayList<WifiConfiguration>() {{ - add(savedOpenNetwork); - add(ephemeralNetwork); - add(passpointNetwork); - }}; - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - expectedConfigsBeforeRemove, mWifiConfigManager.getConfiguredNetworks()); - - assertTrue(mWifiConfigManager.removeAllEphemeralOrPasspointConfiguredNetworks()); - - List<WifiConfiguration> expectedConfigsAfterRemove = new ArrayList<WifiConfiguration>() {{ - add(savedOpenNetwork); - }}; - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - expectedConfigsAfterRemove, mWifiConfigManager.getConfiguredNetworks()); - - // No more ephemeral or passpoint networks to remove now. - assertFalse(mWifiConfigManager.removeAllEphemeralOrPasspointConfiguredNetworks()); - } - - /** - * Verifies that Passpoint network corresponding with given config key (FQDN) is removed. - * - * @throws Exception - */ - @Test - public void testRemovePasspointConfiguredNetwork() throws Exception { - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - verifyAddPasspointNetworkToWifiConfigManager(passpointNetwork); - - assertTrue(mWifiConfigManager.removePasspointConfiguredNetwork( - passpointNetwork.getKey())); - } - - /** - * Verifies that suggested network corresponding with given config key is removed. - * - * @throws Exception - */ - @Test - public void testRemoveSuggestionConfiguredNetwork() throws Exception { - WifiConfiguration suggestedNetwork = WifiConfigurationTestUtil.createEphemeralNetwork(); - suggestedNetwork.fromWifiNetworkSuggestion = true; - verifyAddEphemeralNetworkToWifiConfigManager(suggestedNetwork); - - assertTrue(mWifiConfigManager.removeSuggestionConfiguredNetwork( - suggestedNetwork.getKey())); - } - - /** - * Verifies that the modification of a single network using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} and ensures that any - * updates to the network config in - * {@link WifiKeyStore#updateNetworkKeys(WifiConfiguration, WifiConfiguration)} is reflected - * in the internal database. - */ - @Test - public void testUpdateSingleNetworkWithKeysUpdate() { - WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); - network.enterpriseConfig = - WifiConfigurationTestUtil.createPEAPWifiEnterpriseConfigWithGTCPhase2(); - verifyAddNetworkToWifiConfigManager(network); - - // Now verify that network configurations match before we make any change. - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, - mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - - // Modify the network ca_cert field in updateNetworkKeys method during a network - // config update. - final String newCaCertAlias = "test"; - assertNotEquals(newCaCertAlias, network.enterpriseConfig.getCaCertificateAlias()); - - doAnswer(new AnswerWithArguments() { - public boolean answer(WifiConfiguration newConfig, WifiConfiguration existingConfig) { - newConfig.enterpriseConfig.setCaCertificateAlias(newCaCertAlias); - return true; - } - }).when(mWifiKeyStore).updateNetworkKeys( - any(WifiConfiguration.class), any(WifiConfiguration.class)); - - verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(network); - - // Now verify that the keys update is reflected in the configuration fetched from internal - // db. - network.enterpriseConfig.setCaCertificateAlias(newCaCertAlias); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, - mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - } - - /** - * Verifies that the dump method prints out all the saved network details with passwords masked. - * {@link WifiConfigManager#dump(FileDescriptor, PrintWriter, String[])}. - */ - @Test - public void testDump() { - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(); - eapNetwork.enterpriseConfig.setPassword("blah"); - - verifyAddNetworkToWifiConfigManager(pskNetwork); - verifyAddNetworkToWifiConfigManager(eapNetwork); - - StringWriter stringWriter = new StringWriter(); - mWifiConfigManager.dump( - new FileDescriptor(), new PrintWriter(stringWriter), new String[0]); - String dumpString = stringWriter.toString(); - - // Ensure that the network SSIDs were dumped out. - assertTrue(dumpString.contains(pskNetwork.SSID)); - assertTrue(dumpString.contains(eapNetwork.SSID)); - - // Ensure that the network passwords were not dumped out. - assertFalse(dumpString.contains(pskNetwork.preSharedKey)); - assertFalse(dumpString.contains(eapNetwork.enterpriseConfig.getPassword())); - } - - /** - * Verifies the ordering of network list generated using - * {@link WifiConfigManager#retrieveHiddenNetworkList()}. - */ - @Test - public void testRetrieveHiddenList() { - // Create and add 3 networks. - WifiConfiguration network1 = WifiConfigurationTestUtil.createWepHiddenNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskHiddenNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - verifyAddNetworkToWifiConfigManager(network2); - verifyAddNetworkToWifiConfigManager(network3); - mWifiConfigManager.updateNetworkAfterConnect(network3.networkId); - - // Now set scan results of network2 to set the corresponding - // {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} field. - assertTrue(mWifiConfigManager.setNetworkCandidateScanResult(network2.networkId, - createScanDetailForNetwork(network2).getScanResult(), 54)); - - // Retrieve the hidden network list & verify the order of the networks returned. - List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks = - mWifiConfigManager.retrieveHiddenNetworkList(); - assertEquals(3, hiddenNetworks.size()); - assertEquals(network3.SSID, hiddenNetworks.get(0).ssid); - assertEquals(network2.SSID, hiddenNetworks.get(1).ssid); - assertEquals(network1.SSID, hiddenNetworks.get(2).ssid); - } - - /** - * Verifies the addition of network configurations using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} with same SSID and - * default key mgmt does not add duplicate network configs. - */ - @Test - public void testAddMultipleNetworksWithSameSSIDAndDefaultKeyMgmt() { - final String ssid = "\"test_blah\""; - // Add a network with the above SSID and default key mgmt and ensure it was added - // successfully. - WifiConfiguration network1 = new WifiConfiguration(); - network1.SSID = ssid; - NetworkUpdateResult result = addNetworkToWifiConfigManager(network1); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - assertEquals(1, retrievedNetworks.size()); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network1, retrievedNetworks.get(0)); - - // Now add a second network with the same SSID and default key mgmt and ensure that it - // didn't add a new duplicate network. - WifiConfiguration network2 = new WifiConfiguration(); - network2.SSID = ssid; - result = addNetworkToWifiConfigManager(network2); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertFalse(result.isNewNetwork()); - - retrievedNetworks = mWifiConfigManager.getConfiguredNetworksWithPasswords(); - assertEquals(1, retrievedNetworks.size()); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network2, retrievedNetworks.get(0)); - } - - /** - * Verifies the addition of network configurations using - * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} with same SSID and - * different key mgmt should add different network configs. - */ - @Test - public void testAddMultipleNetworksWithSameSSIDAndDifferentKeyMgmt() { - final String ssid = "\"test_blah\""; - // Add a network with the above SSID and WPA_PSK key mgmt and ensure it was added - // successfully. - WifiConfiguration network1 = new WifiConfiguration(); - network1.SSID = ssid; - network1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - network1.preSharedKey = "\"test_blah\""; - NetworkUpdateResult result = addNetworkToWifiConfigManager(network1); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - assertEquals(1, retrievedNetworks.size()); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network1, retrievedNetworks.get(0)); - - // Now add a second network with the same SSID and NONE key mgmt and ensure that it - // does add a new network. - WifiConfiguration network2 = new WifiConfiguration(); - network2.SSID = ssid; - network2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - result = addNetworkToWifiConfigManager(network2); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - - retrievedNetworks = mWifiConfigManager.getConfiguredNetworksWithPasswords(); - assertEquals(2, retrievedNetworks.size()); - List<WifiConfiguration> networks = Arrays.asList(network1, network2); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - } - - /** - * Verifies that adding a network with a proxy, without having permission OVERRIDE_WIFI_CONFIG, - * holding device policy, or profile owner policy fails. - */ - @Test - public void testAddNetworkWithProxyFails() { - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - false, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithStaticProxy(), - false, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - } - - /** - * Verifies that adding a network with a PAC or STATIC proxy with permission - * OVERRIDE_WIFI_CONFIG is successful - */ - @Test - public void testAddNetworkWithProxyWithConfOverride() { - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - true, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - true, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithStaticProxy(), - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - } - - /** - * Verifies that adding a network with a PAC or STATIC proxy, while holding policy - * {@link DeviceAdminInfo.USES_POLICY_PROFILE_OWNER} is successful - */ - @Test - public void testAddNetworkWithProxyAsProfileOwner() { - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithStaticProxy(), - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - } - /** - * Verifies that adding a network with a PAC or STATIC proxy, while holding policy - * {@link DeviceAdminInfo.USES_POLICY_DEVICE_OWNER} is successful - */ - @Test - public void testAddNetworkWithProxyAsDeviceOwner() { - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - true, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - true, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithStaticProxy(), - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - } - - /** - * Verifies that adding a network with a PAC or STATIC proxy, while having the - * {@link android.Manifest.permission#NETWORK_MANAGED_PROVISIONING} permission is successful - */ - @Test - public void testAddNetworkWithProxyWithNetworkManagedPermission() { - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withNetworkSetupWizard - true, // withNetworkManagedProvisioning - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withNetworkSetupWizard - true, // withNetworkManagedProvisioning - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithStaticProxy(), - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - } - - /** - * Verifies that updating a network (that has no proxy) and adding a PAC or STATIC proxy fails - * without being able to override configs, or holding Device or Profile owner policies. - */ - @Test - public void testUpdateNetworkAddProxyFails() { - WifiConfiguration network = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(network); - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - false, // assertSuccess - result.getNetworkId()); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithStaticProxy(), - false, // assertSuccess - result.getNetworkId()); // Update networkID - } - /** - * Verifies that updating a network and adding a proxy is successful in the cases where app can - * override configs, holds policy {@link DeviceAdminInfo.USES_POLICY_PROFILE_OWNER}, - * and holds policy {@link DeviceAdminInfo.USES_POLICY_DEVICE_OWNER}, and that it fails - * otherwise. - */ - @Test - public void testUpdateNetworkAddProxyWithPermissionAndSystem() { - // Testing updating network with uid permission OVERRIDE_WIFI_CONFIG - WifiConfiguration network = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - NetworkUpdateResult result = addNetworkToWifiConfigManager(network, TEST_CREATOR_UID); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - true, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - true, // assertSuccess - result.getNetworkId()); // Update networkID - - network = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - result = addNetworkToWifiConfigManager(network, TEST_CREATOR_UID); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withNetworkSetupWizard - false, false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - true, // assertSuccess - result.getNetworkId()); // Update networkID - - // Testing updating network with proxy while holding Profile Owner policy - network = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - result = addNetworkToWifiConfigManager(network, TEST_NO_PERM_UID); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - true, // assertSuccess - result.getNetworkId()); // Update networkID - - // Testing updating network with proxy while holding Device Owner Policy - network = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - result = addNetworkToWifiConfigManager(network, TEST_NO_PERM_UID); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - true, // withDeviceOwnerPolicy - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(), - true, // assertSuccess - result.getNetworkId()); // Update networkID - } - - /** - * Verifies that updating a network that has a proxy without changing the proxy, can succeed - * without proxy specific permissions. - */ - @Test - public void testUpdateNetworkUnchangedProxy() { - IpConfiguration ipConf = WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy(); - // First create a WifiConfiguration with proxy - NetworkUpdateResult result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - // Update the network while using the same ipConf, and no proxy specific permissions - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf, - true, // assertSuccess - result.getNetworkId()); // Update networkID - } - - /** - * Verifies that updating a network with a different proxy succeeds in the cases where app can - * override configs, holds policy {@link DeviceAdminInfo.USES_POLICY_PROFILE_OWNER}, - * and holds policy {@link DeviceAdminInfo.USES_POLICY_DEVICE_OWNER}, and that it fails - * otherwise. - */ - @Test - public void testUpdateNetworkDifferentProxy() { - // Create two proxy configurations of the same type, but different values - IpConfiguration ipConf1 = - WifiConfigurationTestUtil.createDHCPIpConfigurationWithSpecificProxy( - WifiConfigurationTestUtil.STATIC_PROXY_SETTING, - TEST_STATIC_PROXY_HOST_1, - TEST_STATIC_PROXY_PORT_1, - TEST_STATIC_PROXY_EXCLUSION_LIST_1, - TEST_PAC_PROXY_LOCATION_1); - IpConfiguration ipConf2 = - WifiConfigurationTestUtil.createDHCPIpConfigurationWithSpecificProxy( - WifiConfigurationTestUtil.STATIC_PROXY_SETTING, - TEST_STATIC_PROXY_HOST_2, - TEST_STATIC_PROXY_PORT_2, - TEST_STATIC_PROXY_EXCLUSION_LIST_2, - TEST_PAC_PROXY_LOCATION_2); - - // Update with Conf Override - NetworkUpdateResult result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - true, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf1, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - true, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf2, - true, // assertSuccess - result.getNetworkId()); // Update networkID - - // Update as Device Owner - result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - true, // withDeviceOwnerPolicy - ipConf1, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - true, // withDeviceOwnerPolicy - ipConf2, - true, // assertSuccess - result.getNetworkId()); // Update networkID - - // Update as Profile Owner - result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf1, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf2, - true, // assertSuccess - result.getNetworkId()); // Update networkID - - // Update with no permissions (should fail) - result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf1, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf2, - false, // assertSuccess - result.getNetworkId()); // Update networkID - } - /** - * Verifies that updating a network removing its proxy succeeds in the cases where app can - * override configs, holds policy {@link DeviceAdminInfo.USES_POLICY_PROFILE_OWNER}, - * and holds policy {@link DeviceAdminInfo.USES_POLICY_DEVICE_OWNER}, and that it fails - * otherwise. - */ - @Test - public void testUpdateNetworkRemoveProxy() { - // Create two different IP configurations, one with a proxy and another without. - IpConfiguration ipConf1 = - WifiConfigurationTestUtil.createDHCPIpConfigurationWithSpecificProxy( - WifiConfigurationTestUtil.STATIC_PROXY_SETTING, - TEST_STATIC_PROXY_HOST_1, - TEST_STATIC_PROXY_PORT_1, - TEST_STATIC_PROXY_EXCLUSION_LIST_1, - TEST_PAC_PROXY_LOCATION_1); - IpConfiguration ipConf2 = - WifiConfigurationTestUtil.createDHCPIpConfigurationWithSpecificProxy( - WifiConfigurationTestUtil.NONE_PROXY_SETTING, - TEST_STATIC_PROXY_HOST_2, - TEST_STATIC_PROXY_PORT_2, - TEST_STATIC_PROXY_EXCLUSION_LIST_2, - TEST_PAC_PROXY_LOCATION_2); - - // Update with Conf Override - NetworkUpdateResult result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - true, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf1, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - true, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf2, - true, // assertSuccess - result.getNetworkId()); // Update networkID - - // Update as Device Owner - result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - true, // withDeviceOwnerPolicy - ipConf1, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - true, // withDeviceOwnerPolicy - ipConf2, - true, // assertSuccess - result.getNetworkId()); // Update networkID - - // Update as Profile Owner - result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf1, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf2, - true, // assertSuccess - result.getNetworkId()); // Update networkID - - // Update with no permissions (should fail) - result = verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - true, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf1, - true, // assertSuccess - WifiConfiguration.INVALID_NETWORK_ID); // Update networkID - verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - false, // withNetworkSettings - false, // withProfileOwnerPolicy - false, // withDeviceOwnerPolicy - ipConf2, - false, // assertSuccess - result.getNetworkId()); // Update networkID - } - - /** - * Verifies that the app specified BSSID is converted and saved in lower case. - */ - @Test - public void testAppSpecifiedBssidIsSavedInLowerCase() { - final String bssid = "0A:08:5C:BB:89:6D"; // upper case - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.BSSID = bssid; - - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - WifiConfiguration retrievedNetwork = mWifiConfigManager.getConfiguredNetwork( - result.getNetworkId()); - - assertNotEquals(retrievedNetwork.BSSID, bssid); - assertEquals(retrievedNetwork.BSSID, bssid.toLowerCase()); - } - - /** - * Verifies that the method resetSimNetworks updates SIM presence status and SIM configs. - */ - @Test - public void testResetSimNetworks() { - String expectedIdentity = "13214561234567890@wlan.mnc456.mcc321.3gppnetwork.org"; - when(mDataTelephonyManager.getSubscriberId()).thenReturn("3214561234567890"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("321456"); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - List<SubscriptionInfo> subList = new ArrayList<>() {{ - add(mock(SubscriptionInfo.class)); - }}; - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subList); - when(mSubscriptionManager.getActiveSubscriptionIdList()) - .thenReturn(new int[]{DATA_SUBID}); - - WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); - WifiConfiguration simNetwork = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - WifiConfiguration peapSimNetwork = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.SIM); - network.enterpriseConfig.setIdentity("identity1"); - network.enterpriseConfig.setAnonymousIdentity("anonymous_identity1"); - simNetwork.enterpriseConfig.setIdentity("identity2"); - simNetwork.enterpriseConfig.setAnonymousIdentity("anonymous_identity2"); - peapSimNetwork.enterpriseConfig.setIdentity("identity3"); - peapSimNetwork.enterpriseConfig.setAnonymousIdentity("anonymous_identity3"); - verifyAddNetworkToWifiConfigManager(network); - verifyAddNetworkToWifiConfigManager(simNetwork); - verifyAddNetworkToWifiConfigManager(peapSimNetwork); - MockitoSession mockSession = ExtendedMockito.mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID); - when(SubscriptionManager.isValidSubscriptionId(anyInt())).thenReturn(true); - - // SIM was removed, resetting SIM Networks - mWifiConfigManager.resetSimNetworks(); - - // Verify SIM configs are reset and non-SIM configs are not changed. - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, - mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - WifiConfiguration retrievedSimNetwork = - mWifiConfigManager.getConfiguredNetwork(simNetwork.networkId); - assertEquals("", retrievedSimNetwork.enterpriseConfig.getAnonymousIdentity()); - assertEquals("", retrievedSimNetwork.enterpriseConfig.getIdentity()); - WifiConfiguration retrievedPeapSimNetwork = - mWifiConfigManager.getConfiguredNetwork(peapSimNetwork.networkId); - assertEquals(expectedIdentity, retrievedPeapSimNetwork.enterpriseConfig.getIdentity()); - assertNotEquals("", retrievedPeapSimNetwork.enterpriseConfig.getAnonymousIdentity()); - - mockSession.finishMocking(); - } - - /** - * {@link WifiConfigManager#resetSimNetworks()} should reset all non-PEAP SIM networks, no - * matter if {@link WifiCarrierInfoManager#getSimIdentity()} returns null or not. - */ - @Test - public void testResetSimNetworks_getSimIdentityNull_shouldResetAllNonPeapSimIdentities() { - when(mDataTelephonyManager.getSubscriberId()).thenReturn(""); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn(""); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - List<SubscriptionInfo> subList = new ArrayList<>() {{ - add(mock(SubscriptionInfo.class)); - }}; - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subList); - when(mSubscriptionManager.getActiveSubscriptionIdList()) - .thenReturn(new int[]{DATA_SUBID}); - - WifiConfiguration peapSimNetwork = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.SIM); - peapSimNetwork.enterpriseConfig.setIdentity("identity_peap"); - peapSimNetwork.enterpriseConfig.setAnonymousIdentity("anonymous_identity_peap"); - verifyAddNetworkToWifiConfigManager(peapSimNetwork); - - WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); - network.enterpriseConfig.setIdentity("identity"); - network.enterpriseConfig.setAnonymousIdentity("anonymous_identity"); - verifyAddNetworkToWifiConfigManager(network); - - WifiConfiguration simNetwork = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - simNetwork.enterpriseConfig.setIdentity("identity_eap_sim"); - simNetwork.enterpriseConfig.setAnonymousIdentity("anonymous_identity_eap_sim"); - verifyAddNetworkToWifiConfigManager(simNetwork); - MockitoSession mockSession = ExtendedMockito.mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID); - when(SubscriptionManager.isValidSubscriptionId(anyInt())).thenReturn(true); - - // SIM was removed, resetting SIM Networks - mWifiConfigManager.resetSimNetworks(); - - // EAP non-SIM network should be unchanged - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, mWifiConfigManager.getConfiguredNetworkWithPassword(network.networkId)); - // EAP-SIM network should have identity & anonymous identity reset - WifiConfiguration retrievedSimNetwork = - mWifiConfigManager.getConfiguredNetwork(simNetwork.networkId); - assertEquals("", retrievedSimNetwork.enterpriseConfig.getAnonymousIdentity()); - assertEquals("", retrievedSimNetwork.enterpriseConfig.getIdentity()); - // PEAP network should have unchanged identity & anonymous identity - WifiConfiguration retrievedPeapSimNetwork = - mWifiConfigManager.getConfiguredNetwork(peapSimNetwork.networkId); - assertEquals("identity_peap", retrievedPeapSimNetwork.enterpriseConfig.getIdentity()); - assertEquals("anonymous_identity_peap", - retrievedPeapSimNetwork.enterpriseConfig.getAnonymousIdentity()); - - mockSession.finishMocking(); - } - - /** - * Verifies that SIM configs are reset on {@link WifiConfigManager#loadFromStore()}. - */ - @Test - public void testLoadFromStoreResetsSimIdentity() { - when(mDataTelephonyManager.getSubscriberId()).thenReturn("3214561234567890"); - when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); - when(mDataTelephonyManager.getSimOperator()).thenReturn("321456"); - when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null); - - WifiConfiguration simNetwork = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - simNetwork.enterpriseConfig.setIdentity("identity"); - simNetwork.enterpriseConfig.setAnonymousIdentity("anonymous_identity"); - - WifiConfiguration peapSimNetwork = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE); - peapSimNetwork.enterpriseConfig.setIdentity("identity"); - peapSimNetwork.enterpriseConfig.setAnonymousIdentity("anonymous_identity"); - - // Set up the store data. - List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() { - { - add(simNetwork); - add(peapSimNetwork); - } - }; - setupStoreDataForRead(sharedNetworks, new ArrayList<>()); - - // read from store now - assertTrue(mWifiConfigManager.loadFromStore()); - - // assert that the expected identities are reset - WifiConfiguration retrievedSimNetwork = - mWifiConfigManager.getConfiguredNetwork(simNetwork.networkId); - assertEquals("", retrievedSimNetwork.enterpriseConfig.getIdentity()); - assertEquals("", retrievedSimNetwork.enterpriseConfig.getAnonymousIdentity()); - - WifiConfiguration retrievedPeapNetwork = - mWifiConfigManager.getConfiguredNetwork(peapSimNetwork.networkId); - assertEquals("identity", retrievedPeapNetwork.enterpriseConfig.getIdentity()); - assertEquals("anonymous_identity", - retrievedPeapNetwork.enterpriseConfig.getAnonymousIdentity()); - } - - /** - * Verifies the deletion of ephemeral network using - * {@link WifiConfigManager#userTemporarilyDisabledNetwork(String)}. - */ - @Test - public void testUserDisableNetwork() throws Exception { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - verifyAddNetworkToWifiConfigManager(openNetwork); - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - verifyExpiryOfTimeout(openNetwork); - } - - /** - * Verifies the disconnection of Passpoint network using - * {@link WifiConfigManager#userTemporarilyDisabledNetwork(String)}. - */ - @Test - public void testDisablePasspointNetwork() throws Exception { - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - - verifyAddPasspointNetworkToWifiConfigManager(passpointNetwork); - - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(passpointNetwork); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - verifyExpiryOfTimeout(passpointNetwork); - } - - /** - * Verifies the disconnection of Passpoint network using - * {@link WifiConfigManager#userTemporarilyDisabledNetwork(String)} and ensures that any user - * choice set over other networks is removed. - */ - @Test - public void testDisablePasspointNetworkRemovesUserChoice() throws Exception { - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - - verifyAddNetworkToWifiConfigManager(savedNetwork); - verifyAddPasspointNetworkToWifiConfigManager(passpointNetwork); - - // Set connect choice of passpoint network over saved network. - assertTrue( - mWifiConfigManager.setNetworkConnectChoice( - savedNetwork.networkId, passpointNetwork.getKey())); - - WifiConfiguration retrievedSavedNetwork = - mWifiConfigManager.getConfiguredNetwork(savedNetwork.networkId); - assertEquals( - passpointNetwork.getKey(), - retrievedSavedNetwork.getNetworkSelectionStatus().getConnectChoice()); - - // Disable the passpoint network & ensure the user choice is now removed from saved network. - mWifiConfigManager.userTemporarilyDisabledNetwork(passpointNetwork.FQDN, TEST_UPDATE_UID); - - retrievedSavedNetwork = mWifiConfigManager.getConfiguredNetwork(savedNetwork.networkId); - assertNull(retrievedSavedNetwork.getNetworkSelectionStatus().getConnectChoice()); - } - - @Test - public void testUserEnableDisabledNetwork() { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - verifyAddNetworkToWifiConfigManager(openNetwork); - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - - mWifiConfigManager.userTemporarilyDisabledNetwork(openNetwork.SSID, TEST_UPDATE_UID); - assertTrue(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(openNetwork.SSID)); - mWifiConfigManager.userEnabledNetwork(retrievedNetworks.get(0).networkId); - assertFalse(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(openNetwork.SSID)); - verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_DISCONNECT_WIFI), - anyInt()); - } - - @Test - public void testUserAddOrUpdateSavedNetworkEnableNetwork() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(openNetwork); - mWifiConfigManager.userTemporarilyDisabledNetwork(openNetwork.SSID, TEST_UPDATE_UID); - assertTrue(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(openNetwork.SSID)); - - verifyAddNetworkToWifiConfigManager(openNetwork); - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - assertFalse(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(openNetwork.SSID)); - } - - @Test - public void testUserAddPasspointNetworkEnableNetwork() { - WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - List<WifiConfiguration> networks = new ArrayList<>(); - networks.add(passpointNetwork); - mWifiConfigManager.userTemporarilyDisabledNetwork(passpointNetwork.FQDN, TEST_UPDATE_UID); - assertTrue(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(passpointNetwork.FQDN)); - // Add new passpoint network will enable the network. - NetworkUpdateResult result = addNetworkToWifiConfigManager(passpointNetwork); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - - List<WifiConfiguration> retrievedNetworks = - mWifiConfigManager.getConfiguredNetworksWithPasswords(); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - networks, retrievedNetworks); - assertFalse(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(passpointNetwork.FQDN)); - - mWifiConfigManager.userTemporarilyDisabledNetwork(passpointNetwork.FQDN, TEST_UPDATE_UID); - assertTrue(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(passpointNetwork.FQDN)); - // Update a existing passpoint network will not enable network. - result = addNetworkToWifiConfigManager(passpointNetwork); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertFalse(result.isNewNetwork()); - assertTrue(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(passpointNetwork.FQDN)); - } - - private void verifyExpiryOfTimeout(WifiConfiguration config) { - // Disable the ephemeral network. - long disableTimeMs = 546643L; - long currentTimeMs = disableTimeMs; - when(mClock.getWallClockMillis()).thenReturn(currentTimeMs); - String network = config.isPasspoint() ? config.FQDN : config.SSID; - mWifiConfigManager.userTemporarilyDisabledNetwork(network, TEST_UPDATE_UID); - // Before timer is triggered, timer will not expiry will enable network. - currentTimeMs = disableTimeMs - + WifiConfigManager.USER_DISCONNECT_NETWORK_BLOCK_EXPIRY_MS + 1; - when(mClock.getWallClockMillis()).thenReturn(currentTimeMs); - assertTrue(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(network)); - for (int i = 0; i < WifiConfigManager.SCAN_RESULT_MISSING_COUNT_THRESHOLD; i++) { - mWifiConfigManager.updateUserDisabledList(new ArrayList<>()); - } - // Before the expiry of timeout. - currentTimeMs = currentTimeMs - + WifiConfigManager.USER_DISCONNECT_NETWORK_BLOCK_EXPIRY_MS - 1; - when(mClock.getWallClockMillis()).thenReturn(currentTimeMs); - assertTrue(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(network)); - - // After the expiry of timeout. - currentTimeMs = currentTimeMs - + WifiConfigManager.USER_DISCONNECT_NETWORK_BLOCK_EXPIRY_MS + 1; - when(mClock.getWallClockMillis()).thenReturn(currentTimeMs); - assertFalse(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(network)); - } - - private NetworkUpdateResult verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - boolean withNetworkSettings, - boolean withProfileOwnerPolicy, - boolean withDeviceOwnerPolicy, - IpConfiguration ipConfiguration, - boolean assertSuccess, - int networkId) { - return verifyAddOrUpdateNetworkWithProxySettingsAndPermissions(withNetworkSettings, - false, false, withProfileOwnerPolicy, withDeviceOwnerPolicy, ipConfiguration, - assertSuccess, networkId); - } - - private NetworkUpdateResult verifyAddOrUpdateNetworkWithProxySettingsAndPermissions( - boolean withNetworkSettings, - boolean withNetworkSetupWizard, - boolean withNetworkManagedProvisioning, - boolean withProfileOwnerPolicy, - boolean withDeviceOwnerPolicy, - IpConfiguration ipConfiguration, - boolean assertSuccess, - int networkId) { - WifiConfiguration network; - if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { - network = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - } else { - network = mWifiConfigManager.getConfiguredNetwork(networkId); - } - network.setIpConfiguration(ipConfiguration); - when(mWifiPermissionsUtil.isDeviceOwner(anyInt(), any())) - .thenReturn(withDeviceOwnerPolicy); - when(mWifiPermissionsUtil.isProfileOwner(anyInt(), any())) - .thenReturn(withProfileOwnerPolicy); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())) - .thenReturn(withNetworkSettings); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())) - .thenReturn(withNetworkSetupWizard); - when(mWifiPermissionsUtil.checkNetworkManagedProvisioningPermission(anyInt())) - .thenReturn(withNetworkManagedProvisioning); - int uid = withNetworkSettings || withNetworkSetupWizard || withNetworkManagedProvisioning - ? TEST_CREATOR_UID - : TEST_NO_PERM_UID; - NetworkUpdateResult result = addNetworkToWifiConfigManager(network, uid); - assertEquals(assertSuccess, result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - return result; - } - - private void createWifiConfigManager() { - mWifiConfigManager = - new WifiConfigManager( - mContext, mClock, mUserManager, mWifiCarrierInfoManager, - mWifiKeyStore, mWifiConfigStore, - mWifiPermissionsUtil, mWifiPermissionsWrapper, mWifiInjector, - mNetworkListSharedStoreData, mNetworkListUserStoreData, - mRandomizedMacStoreData, - mFrameworkFacade, new Handler(mLooper.getLooper()), mDeviceConfigFacade, - mWifiScoreCard, mLruConnectionTracker); - mWifiConfigManager.enableVerboseLogging(1); - } - - /** - * This method sets defaults in the provided WifiConfiguration object if not set - * so that it can be used for comparison with the configuration retrieved from - * WifiConfigManager. - */ - private void setDefaults(WifiConfiguration configuration) { - if (configuration.allowedProtocols.isEmpty()) { - configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); - configuration.allowedProtocols.set(WifiConfiguration.Protocol.WPA); - } - if (configuration.allowedKeyManagement.isEmpty()) { - configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - } - if (configuration.allowedPairwiseCiphers.isEmpty()) { - configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); - } - if (configuration.allowedGroupCiphers.isEmpty()) { - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); - } - if (configuration.allowedGroupManagementCiphers.isEmpty()) { - configuration.allowedGroupManagementCiphers - .set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); - } - if (configuration.getIpAssignment() == IpConfiguration.IpAssignment.UNASSIGNED) { - configuration.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - } - if (configuration.getProxySettings() == IpConfiguration.ProxySettings.UNASSIGNED) { - configuration.setProxySettings(IpConfiguration.ProxySettings.NONE); - } - configuration.status = WifiConfiguration.Status.DISABLED; - configuration.getNetworkSelectionStatus().setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); - configuration.getNetworkSelectionStatus().setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER); - } - - /** - * Modifies the provided configuration with creator uid and package name. - */ - private void setCreationDebugParams(WifiConfiguration configuration, int uid, - String packageName) { - configuration.creatorUid = configuration.lastUpdateUid = uid; - configuration.creatorName = configuration.lastUpdateName = packageName; - } - - /** - * Modifies the provided configuration with update uid and package name. - */ - private void setUpdateDebugParams(WifiConfiguration configuration) { - configuration.lastUpdateUid = TEST_UPDATE_UID; - configuration.lastUpdateName = TEST_UPDATE_NAME; - } - - /** - * Modifies the provided WifiConfiguration with the specified bssid value. Also, asserts that - * the existing |BSSID| field is not the same value as the one being set - */ - private void assertAndSetNetworkBSSID(WifiConfiguration configuration, String bssid) { - assertNotEquals(bssid, configuration.BSSID); - configuration.BSSID = bssid; - } - - /** - * Modifies the provided WifiConfiguration with the specified |IpConfiguration| object. Also, - * asserts that the existing |mIpConfiguration| field is not the same value as the one being set - */ - private void assertAndSetNetworkIpConfiguration( - WifiConfiguration configuration, IpConfiguration ipConfiguration) { - assertNotEquals(ipConfiguration, configuration.getIpConfiguration()); - configuration.setIpConfiguration(ipConfiguration); - } - - /** - * Modifies the provided WifiConfiguration with the specified |wepKeys| value and - * |wepTxKeyIndex|. - */ - private void assertAndSetNetworkWepKeysAndTxIndex( - WifiConfiguration configuration, String[] wepKeys, int wepTxKeyIdx) { - assertNotEquals(wepKeys, configuration.wepKeys); - assertNotEquals(wepTxKeyIdx, configuration.wepTxKeyIndex); - configuration.wepKeys = Arrays.copyOf(wepKeys, wepKeys.length); - configuration.wepTxKeyIndex = wepTxKeyIdx; - } - - /** - * Modifies the provided WifiConfiguration with the specified |preSharedKey| value. - */ - private void assertAndSetNetworkPreSharedKey( - WifiConfiguration configuration, String preSharedKey) { - assertNotEquals(preSharedKey, configuration.preSharedKey); - configuration.preSharedKey = preSharedKey; - } - - /** - * Modifies the provided WifiConfiguration with the specified enteprise |password| value. - */ - private void assertAndSetNetworkEnterprisePassword( - WifiConfiguration configuration, String password) { - assertNotEquals(password, configuration.enterpriseConfig.getPassword()); - configuration.enterpriseConfig.setPassword(password); - } - - /** - * Helper method to capture the networks list store data that will be written by - * WifiConfigStore.write() method. - */ - private Pair<List<WifiConfiguration>, List<WifiConfiguration>> - captureWriteNetworksListStoreData() { - try { - ArgumentCaptor<ArrayList> sharedConfigsCaptor = - ArgumentCaptor.forClass(ArrayList.class); - ArgumentCaptor<ArrayList> userConfigsCaptor = - ArgumentCaptor.forClass(ArrayList.class); - mNetworkListStoreDataMockOrder.verify(mNetworkListSharedStoreData) - .setConfigurations(sharedConfigsCaptor.capture()); - mNetworkListStoreDataMockOrder.verify(mNetworkListUserStoreData) - .setConfigurations(userConfigsCaptor.capture()); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean()); - return Pair.create(sharedConfigsCaptor.getValue(), userConfigsCaptor.getValue()); - } catch (Exception e) { - fail("Exception encountered during write " + e); - } - return null; - } - - /** - * Returns whether the provided network was in the store data or not. - */ - private boolean isNetworkInConfigStoreData(WifiConfiguration configuration) { - Pair<List<WifiConfiguration>, List<WifiConfiguration>> networkListStoreData = - captureWriteNetworksListStoreData(); - if (networkListStoreData == null) { - return false; - } - List<WifiConfiguration> networkList = new ArrayList<>(); - networkList.addAll(networkListStoreData.first); - networkList.addAll(networkListStoreData.second); - return isNetworkInConfigStoreData(configuration, networkList); - } - - /** - * Returns whether the provided network was in the store data or not. - */ - private boolean isNetworkInConfigStoreData( - WifiConfiguration configuration, List<WifiConfiguration> networkList) { - boolean foundNetworkInStoreData = false; - for (WifiConfiguration retrievedConfig : networkList) { - if (retrievedConfig.getKey().equals(configuration.getKey())) { - foundNetworkInStoreData = true; - break; - } - } - return foundNetworkInStoreData; - } - - /** - * Setup expectations for WifiNetworksListStoreData and DeletedEphemeralSsidsStoreData - * after WifiConfigStore#read. - */ - private void setupStoreDataForRead(List<WifiConfiguration> sharedConfigurations, - List<WifiConfiguration> userConfigurations) { - when(mNetworkListSharedStoreData.getConfigurations()) - .thenReturn(sharedConfigurations); - when(mNetworkListUserStoreData.getConfigurations()).thenReturn(userConfigurations); - } - - /** - * Setup expectations for WifiNetworksListStoreData and DeletedEphemeralSsidsStoreData - * after WifiConfigStore#switchUserStoresAndRead. - */ - private void setupStoreDataForUserRead(List<WifiConfiguration> userConfigurations, - Map<String, Long> deletedEphemeralSsids) { - when(mNetworkListUserStoreData.getConfigurations()).thenReturn(userConfigurations); - } - - /** - * Verifies that the provided network was not present in the last config store write. - */ - private void verifyNetworkNotInConfigStoreData(WifiConfiguration configuration) { - assertFalse(isNetworkInConfigStoreData(configuration)); - } - - /** - * Verifies that the provided network was present in the last config store write. - */ - private void verifyNetworkInConfigStoreData(WifiConfiguration configuration) { - assertTrue(isNetworkInConfigStoreData(configuration)); - } - - private void assertPasswordsMaskedInWifiConfiguration(WifiConfiguration configuration) { - if (!TextUtils.isEmpty(configuration.preSharedKey)) { - assertEquals(WifiConfigManager.PASSWORD_MASK, configuration.preSharedKey); - } - if (configuration.wepKeys != null) { - for (int i = 0; i < configuration.wepKeys.length; i++) { - if (!TextUtils.isEmpty(configuration.wepKeys[i])) { - assertEquals(WifiConfigManager.PASSWORD_MASK, configuration.wepKeys[i]); - } - } - } - if (!TextUtils.isEmpty(configuration.enterpriseConfig.getPassword())) { - assertEquals( - WifiConfigManager.PASSWORD_MASK, - configuration.enterpriseConfig.getPassword()); - } - } - - private void assertRandomizedMacAddressMaskedInWifiConfiguration( - WifiConfiguration configuration) { - MacAddress defaultMac = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); - MacAddress randomizedMacAddress = configuration.getRandomizedMacAddress(); - if (randomizedMacAddress != null) { - assertEquals(defaultMac, randomizedMacAddress); - } - } - - /** - * Verifies that the network was present in the network change broadcast and returns the - * change reason. - */ - private int verifyNetworkInBroadcastAndReturnReason() { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - mContextConfigStoreMockOrder.verify(mContext).sendBroadcastAsUser( - intentCaptor.capture(), - eq(UserHandle.ALL), - eq(android.Manifest.permission.ACCESS_WIFI_STATE)); - - Intent intent = intentCaptor.getValue(); - - WifiConfiguration retrievedConfig = - (WifiConfiguration) intent.getExtra(WifiManager.EXTRA_WIFI_CONFIGURATION); - assertNull(retrievedConfig); - - return intent.getIntExtra(WifiManager.EXTRA_CHANGE_REASON, -1); - } - - /** - * Verifies that we sent out an add broadcast with the provided network. - */ - private void verifyNetworkAddBroadcast() { - assertEquals( - verifyNetworkInBroadcastAndReturnReason(), - WifiManager.CHANGE_REASON_ADDED); - } - - /** - * Verifies that we sent out an update broadcast with the provided network. - */ - private void verifyNetworkUpdateBroadcast() { - assertEquals( - verifyNetworkInBroadcastAndReturnReason(), - WifiManager.CHANGE_REASON_CONFIG_CHANGE); - } - - /** - * Verifies that we sent out a remove broadcast with the provided network. - */ - private void verifyNetworkRemoveBroadcast() { - assertEquals( - verifyNetworkInBroadcastAndReturnReason(), - WifiManager.CHANGE_REASON_REMOVED); - } - - private void verifyWifiConfigStoreRead() { - assertTrue(mWifiConfigManager.loadFromStore()); - mContextConfigStoreMockOrder.verify(mContext).sendBroadcastAsUser( - any(Intent.class), - any(UserHandle.class), - eq(android.Manifest.permission.ACCESS_WIFI_STATE)); - } - - private void triggerStoreReadIfNeeded() { - // Trigger a store read if not already done. - if (!mStoreReadTriggered) { - verifyWifiConfigStoreRead(); - mStoreReadTriggered = true; - } - } - - /** - * Adds the provided configuration to WifiConfigManager with uid = TEST_CREATOR_UID. - */ - private NetworkUpdateResult addNetworkToWifiConfigManager(WifiConfiguration configuration) { - return addNetworkToWifiConfigManager(configuration, TEST_CREATOR_UID, null); - } - - /** - * Adds the provided configuration to WifiConfigManager with uid specified. - */ - private NetworkUpdateResult addNetworkToWifiConfigManager(WifiConfiguration configuration, - int uid) { - return addNetworkToWifiConfigManager(configuration, uid, null); - } - - /** - * Adds the provided configuration to WifiConfigManager and modifies the provided configuration - * with creator/update uid, package name and time. This also sets defaults for fields not - * populated. - * These fields are populated internally by WifiConfigManager and hence we need - * to modify the configuration before we compare the added network with the retrieved network. - * This method also triggers a store read if not already done. - */ - private NetworkUpdateResult addNetworkToWifiConfigManager(WifiConfiguration configuration, - int uid, - @Nullable String packageName) { - clearInvocations(mContext, mWifiConfigStore, mNetworkListSharedStoreData, - mNetworkListUserStoreData); - triggerStoreReadIfNeeded(); - when(mClock.getWallClockMillis()).thenReturn(TEST_WALLCLOCK_CREATION_TIME_MILLIS); - NetworkUpdateResult result = - mWifiConfigManager.addOrUpdateNetwork(configuration, uid, packageName); - setDefaults(configuration); - setCreationDebugParams( - configuration, uid, packageName != null ? packageName : TEST_CREATOR_NAME); - configuration.networkId = result.getNetworkId(); - return result; - } - - /** - * Add network to WifiConfigManager and ensure that it was successful. - */ - private NetworkUpdateResult verifyAddNetworkToWifiConfigManager( - WifiConfiguration configuration) { - NetworkUpdateResult result = addNetworkToWifiConfigManager(configuration); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - assertTrue(result.hasIpChanged()); - assertTrue(result.hasProxyChanged()); - - verifyNetworkAddBroadcast(); - // Verify that the config store write was triggered with this new configuration. - verifyNetworkInConfigStoreData(configuration); - return result; - } - - /** - * Add ephemeral network to WifiConfigManager and ensure that it was successful. - */ - private NetworkUpdateResult verifyAddEphemeralNetworkToWifiConfigManager( - WifiConfiguration configuration) throws Exception { - NetworkUpdateResult result = addNetworkToWifiConfigManager(configuration); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - assertTrue(result.hasIpChanged()); - assertTrue(result.hasProxyChanged()); - - verifyNetworkAddBroadcast(); - // Ensure that the write was not invoked for ephemeral network addition. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - return result; - } - - /** - * Add ephemeral network to WifiConfigManager and ensure that it was successful. - */ - private NetworkUpdateResult verifyAddSuggestionOrRequestNetworkToWifiConfigManager( - WifiConfiguration configuration) throws Exception { - NetworkUpdateResult result = - addNetworkToWifiConfigManager(configuration, TEST_CREATOR_UID, TEST_CREATOR_NAME); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - assertTrue(result.hasIpChanged()); - assertTrue(result.hasProxyChanged()); - - verifyNetworkAddBroadcast(); - // Ensure that the write was not invoked for ephemeral network addition. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - return result; - } - - /** - * Add Passpoint network to WifiConfigManager and ensure that it was successful. - */ - private NetworkUpdateResult verifyAddPasspointNetworkToWifiConfigManager( - WifiConfiguration configuration) throws Exception { - NetworkUpdateResult result = addNetworkToWifiConfigManager(configuration); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertTrue(result.isNewNetwork()); - assertTrue(result.hasIpChanged()); - assertTrue(result.hasProxyChanged()); - - // Verify keys are not being installed. - verify(mWifiKeyStore, never()).updateNetworkKeys(any(WifiConfiguration.class), - any(WifiConfiguration.class)); - verifyNetworkAddBroadcast(); - // Ensure that the write was not invoked for Passpoint network addition. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - return result; - } - - /** - * Updates the provided configuration to WifiConfigManager and modifies the provided - * configuration with update uid, package name and time. - * These fields are populated internally by WifiConfigManager and hence we need - * to modify the configuration before we compare the added network with the retrieved network. - */ - private NetworkUpdateResult updateNetworkToWifiConfigManager(WifiConfiguration configuration) { - clearInvocations(mContext, mWifiConfigStore, mNetworkListSharedStoreData, - mNetworkListUserStoreData); - when(mClock.getWallClockMillis()).thenReturn(TEST_WALLCLOCK_UPDATE_TIME_MILLIS); - NetworkUpdateResult result = - mWifiConfigManager.addOrUpdateNetwork(configuration, TEST_UPDATE_UID); - setUpdateDebugParams(configuration); - return result; - } - - /** - * Update network to WifiConfigManager config change and ensure that it was successful. - */ - private NetworkUpdateResult verifyUpdateNetworkToWifiConfigManager( - WifiConfiguration configuration) { - NetworkUpdateResult result = updateNetworkToWifiConfigManager(configuration); - assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); - assertFalse(result.isNewNetwork()); - - verifyNetworkUpdateBroadcast(); - // Verify that the config store write was triggered with this new configuration. - verifyNetworkInConfigStoreData(configuration); - return result; - } - - /** - * Update network to WifiConfigManager without IP config change and ensure that it was - * successful. - */ - private NetworkUpdateResult verifyUpdateNetworkToWifiConfigManagerWithoutIpChange( - WifiConfiguration configuration) { - NetworkUpdateResult result = verifyUpdateNetworkToWifiConfigManager(configuration); - assertFalse(result.hasIpChanged()); - assertFalse(result.hasProxyChanged()); - return result; - } - - /** - * Update network to WifiConfigManager with IP config change and ensure that it was - * successful. - */ - private NetworkUpdateResult verifyUpdateNetworkToWifiConfigManagerWithIpChange( - WifiConfiguration configuration) { - NetworkUpdateResult result = verifyUpdateNetworkToWifiConfigManager(configuration); - assertTrue(result.hasIpChanged()); - assertTrue(result.hasProxyChanged()); - return result; - } - - /** - * Removes network from WifiConfigManager and ensure that it was successful. - */ - private void verifyRemoveNetworkFromWifiConfigManager( - WifiConfiguration configuration) { - assertTrue(mWifiConfigManager.removeNetwork( - configuration.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - - verifyNetworkRemoveBroadcast(); - // Verify if the config store write was triggered without this new configuration. - verifyNetworkNotInConfigStoreData(configuration); - verify(mBssidBlocklistMonitor, atLeastOnce()).handleNetworkRemoved(configuration.SSID); - } - - /** - * Removes ephemeral network from WifiConfigManager and ensure that it was successful. - */ - private void verifyRemoveEphemeralNetworkFromWifiConfigManager( - WifiConfiguration configuration) throws Exception { - assertTrue(mWifiConfigManager.removeNetwork( - configuration.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - - verifyNetworkRemoveBroadcast(); - // Ensure that the write was not invoked for ephemeral network remove. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - } - - /** - * Removes Passpoint network from WifiConfigManager and ensure that it was successful. - */ - private void verifyRemovePasspointNetworkFromWifiConfigManager( - WifiConfiguration configuration) throws Exception { - assertTrue(mWifiConfigManager.removeNetwork( - configuration.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME)); - - // Verify keys are not being removed. - verify(mWifiKeyStore, never()).removeKeys(any(WifiEnterpriseConfig.class)); - verifyNetworkRemoveBroadcast(); - // Ensure that the write was not invoked for Passpoint network remove. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); - } - - /** - * Verifies the provided network's public status and ensures that the network change broadcast - * has been sent out. - */ - private void verifyUpdateNetworkStatus(WifiConfiguration configuration, int status) { - assertEquals(status, configuration.status); - verifyNetworkUpdateBroadcast(); - } - - /** - * Verifies the network's selection status update. - * - * For temporarily disabled reasons, the method ensures that the status has changed only if - * disable reason counter has exceeded the threshold. - * - * For permanently disabled/enabled reasons, the method ensures that the public status has - * changed and the network change broadcast has been sent out. - */ - private void verifyUpdateNetworkSelectionStatus( - int networkId, int reason, int temporaryDisableReasonCounter) { - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS); - - // Fetch the current status of the network before we try to update the status. - WifiConfiguration retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(networkId); - NetworkSelectionStatus currentStatus = retrievedNetwork.getNetworkSelectionStatus(); - int currentDisableReason = currentStatus.getNetworkSelectionDisableReason(); - - // First set the status to the provided reason. - assertTrue(mWifiConfigManager.updateNetworkSelectionStatus(networkId, reason)); - - // Now fetch the network configuration and verify the new status of the network. - retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(networkId); - - NetworkSelectionStatus retrievedStatus = retrievedNetwork.getNetworkSelectionStatus(); - int retrievedDisableReason = retrievedStatus.getNetworkSelectionDisableReason(); - long retrievedDisableTime = retrievedStatus.getDisableTime(); - int retrievedDisableReasonCounter = retrievedStatus.getDisableReasonCounter(reason); - int disableReasonThreshold = - WifiConfigManager.getNetworkSelectionDisableThreshold(reason); - - if (reason == NetworkSelectionStatus.DISABLED_NONE) { - assertEquals(reason, retrievedDisableReason); - assertTrue(retrievedStatus.isNetworkEnabled()); - assertEquals( - NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP, - retrievedDisableTime); - verifyUpdateNetworkStatus(retrievedNetwork, WifiConfiguration.Status.ENABLED); - } else if (reason < NetworkSelectionStatus.PERMANENTLY_DISABLED_STARTING_INDEX) { - // For temporarily disabled networks, we need to ensure that the current status remains - // until the threshold is crossed. - assertEquals(temporaryDisableReasonCounter, retrievedDisableReasonCounter); - if (retrievedDisableReasonCounter < disableReasonThreshold) { - assertEquals(currentDisableReason, retrievedDisableReason); - assertEquals( - currentStatus.getNetworkSelectionStatus(), - retrievedStatus.getNetworkSelectionStatus()); - } else { - assertEquals(reason, retrievedDisableReason); - assertTrue(retrievedStatus.isNetworkTemporaryDisabled()); - assertEquals( - TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS, retrievedDisableTime); - } - } else if (reason < NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX) { - assertEquals(reason, retrievedDisableReason); - assertTrue(retrievedStatus.isNetworkPermanentlyDisabled()); - assertEquals( - NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP, - retrievedDisableTime); - verifyUpdateNetworkStatus(retrievedNetwork, WifiConfiguration.Status.DISABLED); - } - } - - /** - * Creates a scan detail corresponding to the provided network and given BSSID, level &frequency - * values. - */ - private ScanDetail createScanDetailForNetwork( - WifiConfiguration configuration, String bssid, int level, int frequency) { - return WifiConfigurationTestUtil.createScanDetailForNetwork(configuration, bssid, level, - frequency, mClock.getUptimeSinceBootMillis(), mClock.getWallClockMillis()); - } - /** - * Creates a scan detail corresponding to the provided network and BSSID value. - */ - private ScanDetail createScanDetailForNetwork(WifiConfiguration configuration, String bssid) { - return createScanDetailForNetwork(configuration, bssid, 0, 0); - } - - /** - * Creates a scan detail corresponding to the provided network and fixed BSSID value. - */ - private ScanDetail createScanDetailForNetwork(WifiConfiguration configuration) { - return createScanDetailForNetwork(configuration, TEST_BSSID); - } - - /** - * Adds the provided network and then creates a scan detail corresponding to the network. The - * method then creates a ScanDetail corresponding to the network and ensures that the network - * is properly matched using - * {@link WifiConfigManager#getConfiguredNetworkForScanDetailAndCache(ScanDetail)} and also - * verifies that the provided scan detail was cached, - */ - private void verifyAddSingleNetworkAndMatchScanDetailToNetworkAndCache( - WifiConfiguration network) { - // First add the provided network. - verifyAddNetworkToWifiConfigManager(network); - - // Now create a dummy scan detail corresponding to the network. - ScanDetail scanDetail = createScanDetailForNetwork(network); - ScanResult scanResult = scanDetail.getScanResult(); - - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail); - // Retrieve the network with password data for comparison. - retrievedNetwork = - mWifiConfigManager.getConfiguredNetworkWithPassword(retrievedNetwork.networkId); - - WifiConfigurationTestUtil.assertConfigurationEqualForConfigManagerAddOrUpdate( - network, retrievedNetwork); - - // Now retrieve the scan detail cache and ensure that the new scan detail is in cache. - ScanDetailCache retrievedScanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(network.networkId); - assertEquals(1, retrievedScanDetailCache.size()); - ScanResult retrievedScanResult = retrievedScanDetailCache.getScanResult(scanResult.BSSID); - - ScanTestUtil.assertScanResultEquals(scanResult, retrievedScanResult); - } - - /** - * Adds a new network and verifies that the |HasEverConnected| flag is set to false. - */ - private void verifyAddNetworkHasEverConnectedFalse(WifiConfiguration network) { - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(network); - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - assertFalse("Adding a new network should not have hasEverConnected set to true.", - retrievedNetwork.getNetworkSelectionStatus().hasEverConnected()); - } - - /** - * Updates an existing network with some credential change and verifies that the - * |HasEverConnected| flag is set to false. - */ - private void verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse( - WifiConfiguration network) { - NetworkUpdateResult result = verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(network); - WifiConfiguration retrievedNetwork = - mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); - assertFalse("Updating network credentials config should clear hasEverConnected.", - retrievedNetwork.getNetworkSelectionStatus().hasEverConnected()); - assertTrue(result.hasCredentialChanged()); - } - - /** - * Updates an existing network after connection using - * {@link WifiConfigManager#updateNetworkAfterConnect(int)} and asserts that the - * |HasEverConnected| flag is set to true. - */ - private void verifyUpdateNetworkAfterConnectHasEverConnectedTrue(int networkId) { - assertTrue(mWifiConfigManager.updateNetworkAfterConnect(networkId)); - WifiConfiguration retrievedNetwork = mWifiConfigManager.getConfiguredNetwork(networkId); - assertTrue("hasEverConnected expected to be true after connection.", - retrievedNetwork.getNetworkSelectionStatus().hasEverConnected()); - assertEquals(0, mLruConnectionTracker.getAgeIndexOfNetwork(retrievedNetwork)); - } - - /** - * Sets up a user profiles for WifiConfigManager testing. - * - * @param userId Id of the user. - */ - private void setupUserProfiles(int userId) { - when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(userId))).thenReturn(true); - } - - private void verifyRemoveNetworksForApp() { - verifyAddNetworkToWifiConfigManager(WifiConfigurationTestUtil.createOpenNetwork()); - verifyAddNetworkToWifiConfigManager(WifiConfigurationTestUtil.createPskNetwork()); - verifyAddNetworkToWifiConfigManager(WifiConfigurationTestUtil.createWepNetwork()); - - assertFalse(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - - ApplicationInfo app = new ApplicationInfo(); - app.uid = TEST_CREATOR_UID; - app.packageName = TEST_CREATOR_NAME; - assertEquals(3, mWifiConfigManager.removeNetworksForApp(app).size()); - - // Ensure all the networks are removed now. - assertTrue(mWifiConfigManager.getConfiguredNetworks().isEmpty()); - } - - /** - * Verifies SSID blacklist consistent with Watchdog trigger. - * - * Expected behavior: A SSID won't gets blacklisted if there only signle SSID - * be observed and Watchdog trigger is activated. - */ - @Test - public void verifyConsistentWatchdogAndSsidBlacklist() { - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - - when(mWifiInjector.getWifiLastResortWatchdog().shouldIgnoreSsidUpdate()) - .thenReturn(true); - - int networkId = result.getNetworkId(); - // First set it to enabled. - verifyUpdateNetworkSelectionStatus( - networkId, NetworkSelectionStatus.DISABLED_NONE, 0); - - int assocRejectReason = NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION; - int assocRejectThreshold = - WifiConfigManager.getNetworkSelectionDisableThreshold(assocRejectReason); - for (int i = 1; i <= assocRejectThreshold; i++) { - assertFalse(mWifiConfigManager.updateNetworkSelectionStatus( - networkId, assocRejectReason)); - } - - assertFalse(mWifiConfigManager.getConfiguredNetwork(networkId) - .getNetworkSelectionStatus().isNetworkTemporaryDisabled()); - } - - /** - * Verifies that isInFlakyRandomizationSsidHotlist returns true if the network's SSID is in - * the hotlist and the network is using randomized MAC. - */ - @Test - public void testFlakyRandomizationSsidHotlist() { - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); - int networkId = result.getNetworkId(); - - // should return false when there is nothing in the hotlist - assertFalse(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(networkId)); - - // add the network's SSID to the hotlist and verify the method returns true - Set<String> ssidHotlist = new HashSet<>(); - ssidHotlist.add(openNetwork.SSID); - when(mDeviceConfigFacade.getRandomizationFlakySsidHotlist()).thenReturn(ssidHotlist); - assertTrue(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(networkId)); - - // Now change the macRandomizationSetting to "trusted" and then verify - // isInFlakyRandomizationSsidHotlist returns false - openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - NetworkUpdateResult networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); - assertNotEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); - assertFalse(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(networkId)); - } - - /** - * Verifies that findScanRssi returns valid RSSI when scan was done recently - */ - @Test - public void testFindScanRssiRecentScan() { - // First add the provided network. - WifiConfiguration testNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(testNetwork); - - when(mClock.getWallClockMillis()).thenReturn(TEST_WALLCLOCK_CREATION_TIME_MILLIS); - ScanDetail scanDetail = createScanDetailForNetwork(testNetwork, TEST_BSSID, - TEST_RSSI, TEST_FREQUENCY_1); - ScanResult scanResult = scanDetail.getScanResult(); - - mWifiConfigManager.updateScanDetailCacheFromScanDetail(scanDetail); - when(mClock.getWallClockMillis()).thenReturn(TEST_WALLCLOCK_CREATION_TIME_MILLIS + 2000); - assertEquals(mWifiConfigManager.findScanRssi(result.getNetworkId(), 5000), TEST_RSSI); - } - - /** - * Verifies that findScanRssi returns INVALID_RSSI when scan was done a long time ago - */ - @Test - public void testFindScanRssiOldScan() { - // First add the provided network. - WifiConfiguration testNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(testNetwork); - - when(mClock.getWallClockMillis()).thenReturn(TEST_WALLCLOCK_CREATION_TIME_MILLIS); - ScanDetail scanDetail = createScanDetailForNetwork(testNetwork, TEST_BSSID, - TEST_RSSI, TEST_FREQUENCY_1); - ScanResult scanResult = scanDetail.getScanResult(); - - mWifiConfigManager.updateScanDetailCacheFromScanDetail(scanDetail); - when(mClock.getWallClockMillis()).thenReturn(TEST_WALLCLOCK_CREATION_TIME_MILLIS + 15000); - assertEquals(mWifiConfigManager.findScanRssi(result.getNetworkId(), 5000), - WifiInfo.INVALID_RSSI); - } - - /** - * Verify when save to store, isMostRecentlyConnected flag will be set. - */ - @Test - public void testMostRecentlyConnectedNetwork() { - WifiConfiguration testNetwork1 = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(testNetwork1); - WifiConfiguration testNetwork2 = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(testNetwork2); - mWifiConfigManager.updateNetworkAfterConnect(testNetwork2.networkId); - mWifiConfigManager.saveToStore(true); - Pair<List<WifiConfiguration>, List<WifiConfiguration>> networkStoreData = - captureWriteNetworksListStoreData(); - List<WifiConfiguration> sharedNetwork = networkStoreData.first; - assertFalse(sharedNetwork.get(0).isMostRecentlyConnected); - assertTrue(sharedNetwork.get(1).isMostRecentlyConnected); - } - - /** - * Verify scan comparator gives the most recently connected network highest priority - */ - @Test - public void testScanComparator() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(network1); - WifiConfiguration network2 = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(network2); - WifiConfiguration network3 = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(network3); - WifiConfiguration network4 = WifiConfigurationTestUtil.createOpenNetwork(); - verifyAddNetworkToWifiConfigManager(network4); - - // Connect two network in order, network3 --> network2 - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(network3.networkId); - verifyUpdateNetworkAfterConnectHasEverConnectedTrue(network2.networkId); - // Set network4 {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} to true. - assertTrue(mWifiConfigManager.setNetworkCandidateScanResult(network4.networkId, - createScanDetailForNetwork(network4).getScanResult(), 54)); - List<WifiConfiguration> networkList = mWifiConfigManager.getConfiguredNetworks(); - // Expected order should be based on connection order and last qualified selection. - Collections.sort(networkList, mWifiConfigManager.getScanListComparator()); - assertEquals(network2.SSID, networkList.get(0).SSID); - assertEquals(network3.SSID, networkList.get(1).SSID); - assertEquals(network4.SSID, networkList.get(2).SSID); - assertEquals(network1.SSID, networkList.get(3).SSID); - // Remove network to check the age index changes. - mWifiConfigManager.removeNetwork(network3.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME); - assertEquals(Integer.MAX_VALUE, mLruConnectionTracker.getAgeIndexOfNetwork(network3)); - assertEquals(0, mLruConnectionTracker.getAgeIndexOfNetwork(network2)); - mWifiConfigManager.removeNetwork(network2.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME); - assertEquals(Integer.MAX_VALUE, mLruConnectionTracker.getAgeIndexOfNetwork(network2)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java deleted file mode 100644 index 671076bf5..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.test.MockAnswerUtil; -import android.app.test.TestAlarmManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.MacAddress; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiMigration; -import android.net.wifi.util.HexEncoding; -import android.os.Handler; -import android.os.UserHandle; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.server.wifi.WifiConfigStore.StoreData; -import com.android.server.wifi.WifiConfigStore.StoreFile; -import com.android.server.wifi.util.ArrayUtils; -import com.android.server.wifi.util.EncryptedData; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.XmlUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.stubbing.Answer; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - -/** - * Unit tests for {@link com.android.server.wifi.WifiConfigStore}. - */ -@SmallTest -public class WifiConfigStoreTest extends WifiBaseTest { - private static final String TEST_USER_DATA = "UserData"; - private static final String TEST_SHARE_DATA = "ShareData"; - private static final String TEST_CREATOR_NAME = "CreatorName"; - private static final MacAddress TEST_RANDOMIZED_MAC = - MacAddress.fromString("da:a1:19:c4:26:fa"); - - private static final String TEST_DATA_XML_STRING_FORMAT = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"3\" />\n" - + "<NetworkList>\n" - + "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">%s</string>\n" - + "<string name=\"SSID\">%s</string>\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"%s\" />\n" - + "<boolean name=\"AutoJoinEnabled\" value=\"true\" />\n" - + "<boolean name=\"Trusted\" value=\"true\" />\n" - + "<null name=\"BSSID\" />\n" - + "<int name=\"Status\" value=\"2\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<int name=\"MeteredOverride\" value=\"0\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"CreatorUid\" value=\"%d\" />\n" - + "<string name=\"CreatorName\">%s</string>\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n" - + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n" - + "<string name=\"RandomizedMacAddress\">%s</string>\n" - + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n" - + "<int name=\"CarrierId\" value=\"-1\" />\n" - + "<boolean name=\"IsMostRecentlyConnected\" value=\"false\" />\n" - + "</WifiConfiguration>\n" - + "<NetworkStatus>\n" - + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" - + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" - + "<null name=\"ConnectChoice\" />\n" - + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" - + "</NetworkStatus>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n" - + "</NetworkList>\n" - + "</WifiConfigStoreData>\n"; - - private static final String TEST_DATA_XML_STRING_FORMAT_V1_WITH_ONE_DATA_SOURCE = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + "<%s/>n" - + "</WifiConfigStoreData>\n"; - private static final String TEST_DATA_XML_STRING_FORMAT_V1_WITH_TWO_DATA_SOURCE = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + "<%s/>n" - + "<%s/>n" - + "</WifiConfigStoreData>\n"; - private static final String TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"2\" />\n" - + "<Integrity>\n" - + "<byte-array name=\"EncryptedData\" num=\"48\">%s</byte-array>\n" - + "<byte-array name=\"IV\" num=\"12\">%s</byte-array>\n" - + "</Integrity>\n" - + "<%s />\n" - + "</WifiConfigStoreData>\n"; - private static final String TEST_DATA_XML_STRING_FORMAT_V3_WITH_ONE_DATA_SOURCE = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"3\" />\n" - + "<%s />\n" - + "</WifiConfigStoreData>\n"; - // Test mocks - @Mock private Context mContext; - @Mock private PackageManager mPackageManager; - private TestAlarmManager mAlarmManager; - private TestLooper mLooper; - @Mock private Clock mClock; - @Mock private WifiMetrics mWifiMetrics; - @Mock private WifiConfigStoreEncryptionUtil mEncryptionUtil; - private MockStoreFile mSharedStore; - private MockStoreFile mSharedSoftApStore; - private MockStoreFile mUserStore; - private MockStoreFile mUserNetworkSuggestionsStore; - private List<StoreFile> mUserStores = new ArrayList<StoreFile>(); - private MockStoreData mSharedStoreData; - private MockStoreData mUserStoreData; - private MockitoSession mSession; - - /** - * Test instance of WifiConfigStore. - */ - private WifiConfigStore mWifiConfigStore; - - /** - * Setup mocks before the test starts. - */ - private void setupMocks() throws Exception { - MockitoAnnotations.initMocks(this); - mAlarmManager = new TestAlarmManager(); - mLooper = new TestLooper(); - when(mContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME); - when(mEncryptionUtil.encrypt(any(byte[].class))) - .thenReturn(new EncryptedData(new byte[0], new byte[0])); - when(mEncryptionUtil.decrypt(any(EncryptedData.class))) - .thenReturn(new byte[0]); - mSharedStore = new MockStoreFile(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - mSharedSoftApStore = new MockStoreFile(WifiConfigStore.STORE_FILE_SHARED_SOFTAP); - mUserStore = new MockStoreFile(WifiConfigStore.STORE_FILE_USER_GENERAL); - mUserNetworkSuggestionsStore = - new MockStoreFile(WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS); - mUserStores.add(mUserStore); - mUserStores.add(mUserNetworkSuggestionsStore); - - mSharedStoreData = new MockStoreData(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - mUserStoreData = new MockStoreData(WifiConfigStore.STORE_FILE_USER_GENERAL); - - mSession = ExtendedMockito.mockitoSession() - .mockStatic(WifiMigration.class, withSettings().lenient()) - .startMocking(); - when(WifiMigration.convertAndRetrieveSharedConfigStoreFile(anyInt())).thenReturn(null); - when(WifiMigration.convertAndRetrieveUserConfigStoreFile(anyInt(), any())).thenReturn(null); - } - - /** - * Setup the test environment. - */ - @Before - public void setUp() throws Exception { - setupMocks(); - - mWifiConfigStore = new WifiConfigStore(mContext, new Handler(mLooper.getLooper()), mClock, - mWifiMetrics, Arrays.asList(mSharedStore, mSharedSoftApStore)); - // Enable verbose logging before tests. - mWifiConfigStore.enableVerboseLogging(true); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - if (mSession != null) { - mSession.finishMocking(); - } - } - - /** - * Verify that no write occurs if there is {@link StoreData} registered for any - * {@link StoreFile}. - * - * @throws Exception - */ - @Test - public void testWriteWithNoStoreData() throws Exception { - // Perform force write to both share and user store file. - mWifiConfigStore.setUserStores(mUserStores); - mWifiConfigStore.write(true); - - assertFalse(mSharedStore.isStoreWritten()); - assertFalse(mUserStore.isStoreWritten()); - assertFalse(mUserNetworkSuggestionsStore.isStoreWritten()); - - verify(mWifiMetrics, never()).noteWifiConfigStoreWriteDuration(anyInt()); - } - - /** - * Tests the write API with the force flag set to true. - * Expected behavior: This should trigger an immediate write to the store files and no alarms - * should be started. - */ - @Test - public void testForceWrite() throws Exception { - // Register data container. - mWifiConfigStore.registerStoreData(mSharedStoreData); - mWifiConfigStore.registerStoreData(mUserStoreData); - - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - mWifiConfigStore.write(true); - - assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); - assertTrue(mSharedStore.isStoreWritten()); - assertTrue(mUserStore.isStoreWritten()); - assertFalse(mUserNetworkSuggestionsStore.isStoreWritten()); - - verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt()); - } - - /** - * Tests the write API with the force flag set to false. - * Expected behavior: This should set an alarm to write to the store files. - */ - @Test - public void testBufferedWrite() throws Exception { - // Register data container. - mWifiConfigStore.registerStoreData(mSharedStoreData); - mWifiConfigStore.registerStoreData(mUserStoreData); - - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - mWifiConfigStore.write(false); - - assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); - assertFalse(mSharedStore.isStoreWritten()); - assertFalse(mUserStore.isStoreWritten()); - assertFalse(mUserNetworkSuggestionsStore.isStoreWritten()); - - // Now send the alarm and ensure that the writes happen. - mAlarmManager.dispatch(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG); - mLooper.dispatchAll(); - assertTrue(mSharedStore.isStoreWritten()); - assertTrue(mUserStore.isStoreWritten()); - assertFalse(mUserNetworkSuggestionsStore.isStoreWritten()); - - verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt()); - } - - /** - * Tests the force write after a buffered write. - * Expected behaviour: The force write should override the previous buffered write and stop the - * buffer write alarms. - */ - @Test - public void testForceWriteAfterBufferedWrite() throws Exception { - // Register a test data container with bogus data. - mWifiConfigStore.registerStoreData(mSharedStoreData); - mWifiConfigStore.registerStoreData(mUserStoreData); - - mSharedStoreData.setData("abcds"); - mUserStoreData.setData("asdfa"); - - // Perform buffered write for both user and share store file. - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - mWifiConfigStore.write(false); - - assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); - assertFalse(mSharedStore.isStoreWritten()); - assertFalse(mUserStore.isStoreWritten()); - - // Update the container with new set of data. The send a force write and ensure that the - // writes have been performed and alarms have been stopped and updated data are written. - mUserStoreData.setData(TEST_USER_DATA); - mSharedStoreData.setData(TEST_SHARE_DATA); - mWifiConfigStore.write(true); - - assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); - assertTrue(mSharedStore.isStoreWritten()); - assertTrue(mUserStore.isStoreWritten()); - - // Verify correct data are loaded to the data container after a read. - mWifiConfigStore.read(); - assertEquals(TEST_USER_DATA, mUserStoreData.getData()); - assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData()); - } - - /** - * Tests the force write with no new data after a buffered write. - * Expected behaviour: The force write should flush the previous buffered write and stop the - * buffer write alarms. - */ - @Test - public void testForceWriteWithNoNewDataAfterBufferedWrite() throws Exception { - // Register a test data container with bogus data. - mWifiConfigStore.registerStoreData(mSharedStoreData); - mWifiConfigStore.registerStoreData(mUserStoreData); - - mSharedStoreData.setData("abcds"); - mUserStoreData.setData("asdfa"); - - // Perform buffered write for both user and share store file. - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - mWifiConfigStore.write(false); - - assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); - assertFalse(mSharedStore.isStoreWritten()); - assertFalse(mUserStore.isStoreWritten()); - - // Containers have no new data. - mUserStoreData.setHasAnyNewData(false); - mSharedStoreData.setHasAnyNewData(false); - mWifiConfigStore.write(true); - - assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); - assertTrue(mSharedStore.isStoreWritten()); - assertTrue(mUserStore.isStoreWritten()); - - // Verify correct data are loaded to the data container after a read. - mWifiConfigStore.read(); - assertEquals("abcds", mSharedStoreData.getData()); - assertEquals("asdfa", mUserStoreData.getData()); - } - - - /** - * Tests the read API behaviour after a write to the store files. - * Expected behaviour: The read should return the same data that was last written. - */ - @Test - public void testReadAfterWrite() throws Exception { - // Register data container. - mWifiConfigStore.registerStoreData(mSharedStoreData); - mWifiConfigStore.registerStoreData(mUserStoreData); - - // Read both share and user config store. - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - - // Verify no data is read. - assertNull(mUserStoreData.getData()); - assertNull(mSharedStoreData.getData()); - - // Write share and user data. - mUserStoreData.setData(TEST_USER_DATA); - mSharedStoreData.setData(TEST_SHARE_DATA); - mWifiConfigStore.write(true); - - // Read and verify the data content in the data container. - mWifiConfigStore.read(); - assertEquals(TEST_USER_DATA, mUserStoreData.getData()); - assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData()); - - verify(mWifiMetrics, times(2)).noteWifiConfigStoreReadDuration(anyInt()); - verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt()); - } - - /** - * Tests the read API behaviour when the shared store file is empty and the user store - * is not yet visible (user not yet unlocked). - * Expected behaviour: The read should return an empty store data instance when the file not - * found exception is raised. - */ - @Test - public void testReadWithNoSharedStoreFileAndUserStoreNotVisible() throws Exception { - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - - // Reading the mock store without a write should simulate the file not found case because - // |readRawData| would return null. - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - mWifiConfigStore.read(); - - // Ensure that we got the call to deserialize empty shared data, but no user data. - verify(sharedStoreData).resetData(); - verify(sharedStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); - verify(userStoreData, never()).resetData(); - verify(userStoreData, never()).deserializeData(any(), anyInt(), anyInt(), any()); - } - - /** - * Tests the read API behaviour when there are no user/shared store files on the device. - * Expected behaviour: The read should return an empty store data instance when the file not - * found exception is raised. - */ - @Test - public void testReadWithNoStoreFiles() throws Exception { - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - - // Reading the mock store without a write should simulate the file not found case because - // |readRawData| would return null. - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - mWifiConfigStore.read(); - - // Ensure that we got the call to deserialize empty shared & user data. - verify(userStoreData).resetData(); - verify(userStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); - verify(sharedStoreData).resetData(); - verify(sharedStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); - } - - /** - * Tests the read API behaviour after a write to the shared store file when the user - * store file is null. - * Expected behaviour: The read should return the same data that was last written. - */ - @Test - public void testReadAfterWriteWithNoUserStore() throws Exception { - // Setup data container. - mWifiConfigStore.registerStoreData(mSharedStoreData); - mSharedStoreData.setData(TEST_SHARE_DATA); - - // Perform write for the share store file. - mWifiConfigStore.write(true); - mWifiConfigStore.read(); - // Verify data content for both user and share data. - assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData()); - } - - /** - * Verifies that a read operation will reset the data in the data container, to avoid - * any stale data from previous read. - * - * @throws Exception - */ - @Test - public void testReadWillResetStoreData() throws Exception { - // Register and setup store data. - mWifiConfigStore.registerStoreData(mSharedStoreData); - mWifiConfigStore.registerStoreData(mUserStoreData); - - // Perform force write with empty data content to both user and share store file. - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - mWifiConfigStore.write(true); - - // Setup data container with some value. - mUserStoreData.setData(TEST_USER_DATA); - mSharedStoreData.setData(TEST_SHARE_DATA); - - // Perform read of both user and share store file and verify data in the data container - // is in sync (empty) with what is in the file. - mWifiConfigStore.read(); - assertNull(mSharedStoreData.getData()); - assertNull(mUserStoreData.getData()); - } - - /** - * Verify that a store file contained WiFi configuration store data (network list and - * deleted ephemeral SSID list) using the predefined test XML data is read and parsed - * correctly. - * - * @throws Exception - */ - @Test - public void testReadWifiConfigStoreData() throws Exception { - // Setup network list. - NetworkListStoreData networkList = new NetworkListUserStoreData(mContext); - mWifiConfigStore.registerStoreData(networkList); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.creatorName = TEST_CREATOR_NAME; - openNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); - openNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); - List<WifiConfiguration> userConfigs = new ArrayList<>(); - userConfigs.add(openNetwork); - - // Setup user store XML bytes. - String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT, - openNetwork.getKey().replaceAll("\"", """), - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName, - openNetwork.getRandomizedMacAddress()); - byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8); - mUserStore.storeRawDataToWrite(xmlBytes); - - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore( - userConfigs, networkList.getConfigurations()); - } - - /** - * Verify that the WiFi configuration store data containing network list and deleted - * ephemeral SSID list are serialized correctly, matches the predefined test XML data. - * - * @throws Exception - */ - @Test - public void testWriteWifiConfigStoreData() throws Exception { - // Setup user store. - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - - // Setup network list store data. - NetworkListStoreData networkList = new NetworkListUserStoreData(mContext); - mWifiConfigStore.registerStoreData(networkList); - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.creatorName = TEST_CREATOR_NAME; - openNetwork.setIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); - openNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); - List<WifiConfiguration> userConfigs = new ArrayList<>(); - userConfigs.add(openNetwork); - networkList.setConfigurations(userConfigs); - - // Setup expected XML bytes. - String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT, - openNetwork.getKey().replaceAll("\"", """), - openNetwork.SSID.replaceAll("\"", """), - openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName, - openNetwork.getRandomizedMacAddress()); - - mWifiConfigStore.write(true); - // Verify the user store content. - assertEquals(xmlString, new String(mUserStore.getStoreBytes())); - } - - /** - * Verify that a store file contained WiFi configuration store data (network list and - * deleted ephemeral SSID list) using the predefined test XML data is read and parsed - * correctly. - * - * @throws Exception - */ - @Test - public void testReadWifiConfigStoreDataIndicateClientsThatThereIsNoDataForThem() - throws Exception { - // Set both the user store & shared store files. - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - - String storeData1Name = "test1"; - String storeData2Name = "test2"; - StoreData storeData1 = mock(StoreData.class); - StoreData storeData2 = mock(StoreData.class); - - assertTrue(mWifiConfigStore.registerStoreData(storeData1)); - assertTrue(mWifiConfigStore.registerStoreData(storeData2)); - - String fileContentsXmlStringWithOnlyStoreData1 = - String.format(TEST_DATA_XML_STRING_FORMAT_V1_WITH_ONE_DATA_SOURCE, storeData1Name); - String fileContentsXmlStringWithOnlyStoreData2 = - String.format(TEST_DATA_XML_STRING_FORMAT_V1_WITH_ONE_DATA_SOURCE, storeData2Name); - String fileContentsXmlStringWithStoreData1AndStoreData2 = - String.format(TEST_DATA_XML_STRING_FORMAT_V1_WITH_TWO_DATA_SOURCE, - storeData1Name, storeData2Name); - - // Scenario 1: StoreData1 in shared store file. - when(storeData1.getName()).thenReturn(storeData1Name); - when(storeData2.getName()).thenReturn(storeData2Name); - when(storeData1.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(storeData2.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - mSharedStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData1.getBytes()); - mUserStore.storeRawDataToWrite(null); - - mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); - verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); - verify(storeData2).deserializeData(eq(null), anyInt(), anyInt(), any()); - reset(storeData1, storeData2); - - // Scenario 2: StoreData2 in user store file. - when(storeData1.getName()).thenReturn(storeData1Name); - when(storeData2.getName()).thenReturn(storeData2Name); - when(storeData1.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(storeData2.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - mSharedStore.storeRawDataToWrite(null); - mUserStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData2.getBytes()); - - mWifiConfigStore.read(); - verify(storeData1).deserializeData(eq(null), anyInt(), anyInt(), any()); - verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); - verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); - reset(storeData1, storeData2); - - // Scenario 3: StoreData1 in shared store file & StoreData2 in user store file. - when(storeData1.getName()).thenReturn(storeData1Name); - when(storeData2.getName()).thenReturn(storeData2Name); - when(storeData1.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(storeData2.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - mSharedStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData1.getBytes()); - mUserStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData2.getBytes()); - - mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); - verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); - verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); - verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); - reset(storeData1, storeData2); - - // Scenario 4: StoreData1 & StoreData2 in shared store file. - when(storeData1.getName()).thenReturn(storeData1Name); - when(storeData2.getName()).thenReturn(storeData2Name); - when(storeData1.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(storeData2.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - mSharedStore.storeRawDataToWrite( - fileContentsXmlStringWithStoreData1AndStoreData2.getBytes()); - mUserStore.storeRawDataToWrite(null); - - mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); - verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); - verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); - verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); - reset(storeData1, storeData2); - } - - /** - * Tests the write API behavior when all the store data's registered for a given store file - * has no new data to write. - * Expected behaviour: The write should not trigger a new file write for that specific store - * file. - */ - @Test - public void testWriteWithNoNewData() throws Exception { - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.hasNewDataToSerialize()).thenReturn(true); - when(sharedStoreData.getName()).thenReturn("sharedStoreData"); - - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.hasNewDataToSerialize()).thenReturn(true); - when(userStoreData.getName()).thenReturn("userStoreData"); - - StoreData userStoreNetworkSuggestionsData = - mock(StoreData.class); - when(userStoreNetworkSuggestionsData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS); - when(userStoreNetworkSuggestionsData.hasNewDataToSerialize()).thenReturn(false); - when(userStoreNetworkSuggestionsData.getName()) - .thenReturn("userStoreNetworkSuggestionsData"); - - assertTrue(mWifiConfigStore.registerStoreData(sharedStoreData)); - assertTrue(mWifiConfigStore.registerStoreData(userStoreData)); - assertTrue(mWifiConfigStore.registerStoreData(userStoreNetworkSuggestionsData)); - - // Write both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Now trigger a write. - mWifiConfigStore.write(true); - - verify(sharedStoreData).hasNewDataToSerialize(); - verify(userStoreData).hasNewDataToSerialize(); - verify(userStoreNetworkSuggestionsData).hasNewDataToSerialize(); - - // Verify that we serialized data from the first 2 data source, but not from the last one. - verify(sharedStoreData).serializeData(any(), any()); - verify(userStoreData).serializeData(any(), any()); - verify(userStoreNetworkSuggestionsData, never()).serializeData(any(), any()); - } - - /** - * Verify that we gracefully skip unknown section when reading an user store file. - */ - @Test - public void testReadUserStoreContainedUnknownSection() throws Exception { - String storeFileData = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + "<UnknownTag>\n" // No StoreData registered to handle this tag. - + "</UnknownTag>\n" - + "</WifiConfigStoreData>\n"; - mUserStore.storeRawDataToWrite(storeFileData.getBytes(StandardCharsets.UTF_8)); - mWifiConfigStore.switchUserStoresAndRead(mUserStores); - } - - /** - * Verify that we gracefully skip unknown section when reading a shared store file. - */ - @Test - public void testReadShareStoreContainedUnknownSection() throws Exception { - String storeFileData = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + "<UnknownTag>\n" // No StoreData registered to handle this tag. - + "</UnknownTag>\n" - + "</WifiConfigStoreData>\n"; - mSharedStore.storeRawDataToWrite(storeFileData.getBytes(StandardCharsets.UTF_8)); - mWifiConfigStore.read(); - } - - /** - * Tests the read API behaviour when the config store file is version 1. - * Expected behaviour: The read should be successful and send the data to the corresponding - * {@link StoreData} instance. - */ - @Test - public void testReadVersion1StoreFile() throws Exception { - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Now store some content in the shared and user data files. - mUserStore.storeRawDataToWrite( - String.format(TEST_DATA_XML_STRING_FORMAT_V1_WITH_ONE_DATA_SOURCE, - TEST_USER_DATA).getBytes()); - mSharedStore.storeRawDataToWrite( - String.format(TEST_DATA_XML_STRING_FORMAT_V1_WITH_ONE_DATA_SOURCE, - TEST_SHARE_DATA).getBytes()); - - // Read and verify the data content in the store file (metadata stripped out) has been sent - // to the corresponding store data when integrity check passes. - mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData( - any(XmlPullParser.class), anyInt(), - eq(WifiConfigStore.INITIAL_CONFIG_STORE_DATA_VERSION), any()); - verify(userStoreData, times(1)).deserializeData( - any(XmlPullParser.class), anyInt(), - eq(WifiConfigStore.INITIAL_CONFIG_STORE_DATA_VERSION), any()); - } - - /** - * Tests the read API behaviour to ensure that the integrity data is parsed from the file. - */ - @Test - public void testReadVersion2StoreFile() throws Exception { - byte[] encryptedData = new byte[0]; - byte[] iv = new byte[0]; - Random random = new Random(); - random.nextBytes(encryptedData); - random.nextBytes(iv); - - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - when(sharedStoreData.hasNewDataToSerialize()).thenReturn(true); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - when(userStoreData.hasNewDataToSerialize()).thenReturn(true); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Now store some content in the shared and user data files with encrypted data from above. - mUserStore.storeRawDataToWrite( - String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(encryptedData), - HexEncoding.encodeToString(iv), - TEST_USER_DATA).getBytes()); - mSharedStore.storeRawDataToWrite( - String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(encryptedData), - HexEncoding.encodeToString(iv), - TEST_SHARE_DATA).getBytes()); - - // Read and verify the data content in the store file (metadata stripped out) has been sent - // to the corresponding store data. - mWifiConfigStore.read(); - verify(sharedStoreData, times(1)) - .deserializeData(any(XmlPullParser.class), anyInt(), - eq(WifiConfigStore.INTEGRITY_CONFIG_STORE_DATA_VERSION), any()); - verify(userStoreData, times(1)) - .deserializeData(any(XmlPullParser.class), anyInt(), - eq(WifiConfigStore.INTEGRITY_CONFIG_STORE_DATA_VERSION), any()); - } - - /** - * Tests the complete migration path all the way from reading from the migration stream to - * parsing the XML data and sending it to the appropriate registered data sources. - */ - @Test - public void testMigration() throws Exception { - // Setup both shared & user store migrations. - StoreFile sharedStoreFile1 = mock(StoreFile.class); - when(sharedStoreFile1.getFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - StoreFile sharedStoreFile2 = mock(StoreFile.class); - when(sharedStoreFile2.getFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_SOFTAP); - StoreFile userStoreFile1 = mock(StoreFile.class); - when(userStoreFile1.getFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - StoreFile userStoreFile2 = mock(StoreFile.class); - when(userStoreFile2.getFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS); - mWifiConfigStore = new WifiConfigStore(mContext, new Handler(mLooper.getLooper()), mClock, - mWifiMetrics, Arrays.asList(sharedStoreFile1, sharedStoreFile2)); - mWifiConfigStore.setUserStores(Arrays.asList(userStoreFile1, userStoreFile2)); - - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Migration data - InputStream sharedStream1 = mock(InputStream.class); - InputStream sharedStream2 = mock(InputStream.class); - InputStream userStream1 = mock(InputStream.class); - InputStream userStream2 = mock(InputStream.class); - when(WifiMigration.convertAndRetrieveSharedConfigStoreFile( - WifiMigration.STORE_FILE_SHARED_GENERAL)) - .thenReturn(sharedStream1); - when(WifiMigration.convertAndRetrieveSharedConfigStoreFile( - WifiMigration.STORE_FILE_SHARED_SOFTAP)) - .thenReturn(sharedStream2); - when(WifiMigration.convertAndRetrieveUserConfigStoreFile( - eq(WifiMigration.STORE_FILE_USER_GENERAL), any())) - .thenReturn(userStream1); - when(WifiMigration.convertAndRetrieveUserConfigStoreFile( - eq(WifiMigration.STORE_FILE_USER_NETWORK_SUGGESTIONS), any())) - .thenReturn(userStream2); - - byte[] sharedStoreXmlBytes = - String.format(TEST_DATA_XML_STRING_FORMAT_V3_WITH_ONE_DATA_SOURCE, - TEST_SHARE_DATA).getBytes(); - byte[] userStoreXmlBytes = - String.format(TEST_DATA_XML_STRING_FORMAT_V3_WITH_ONE_DATA_SOURCE, - TEST_USER_DATA).getBytes(); - when(sharedStream1.available()) - .thenReturn(sharedStoreXmlBytes.length) // first time return file contents, then 0. - .thenReturn(0); - when(sharedStream2.available()) - .thenReturn(sharedStoreXmlBytes.length) // first time return file contents, then 0. - .thenReturn(0); - when(userStream1.available()) - .thenReturn(userStoreXmlBytes.length) // first time return file contents, then 0. - .thenReturn(0); - when(userStream2.available()) - .thenReturn(userStoreXmlBytes.length) // first time return file contents, then 0. - .thenReturn(0); - Answer sharedStreamReadAnswer = new MockAnswerUtil.AnswerWithArguments() { - public int answer(byte[] b, int off, int len) { - System.arraycopy(sharedStoreXmlBytes, 0, b, 0, sharedStoreXmlBytes.length); - return sharedStoreXmlBytes.length; - } - }; - Answer userStreamReadAnswer = new MockAnswerUtil.AnswerWithArguments() { - public int answer(byte[] b, int off, int len) { - System.arraycopy(userStoreXmlBytes, 0, b, 0, userStoreXmlBytes.length); - return userStoreXmlBytes.length; - } - }; - when(sharedStream1.read(any(byte[].class), anyInt(), anyInt())) - .thenAnswer(sharedStreamReadAnswer) // first time return file contents, then 0. - .thenReturn(0); - when(sharedStream2.read(any(byte[].class), anyInt(), anyInt())) - .thenAnswer(sharedStreamReadAnswer) // first time return file contents, then 0. - .thenReturn(0); - when(userStream1.read(any(byte[].class), anyInt(), anyInt())) - .thenAnswer(userStreamReadAnswer) // first time return file contents, then 0. - .thenReturn(0); - when(userStream2.read(any(byte[].class), anyInt(), anyInt())) - .thenAnswer(userStreamReadAnswer) // first time return file contents, then 0. - .thenReturn(0); - - // Trigger read. - mWifiConfigStore.read(); - - // Verify that we read the data out of all the migration streams & we didn't read - // from the files on disk. - verify(sharedStream1, times(2)).available(); - verify(sharedStream1, times(2)).read(any(), anyInt(), anyInt()); - verify(sharedStream2, times(2)).available(); - verify(sharedStream2, times(2)).read(any(), anyInt(), anyInt()); - verify(userStream1, times(2)).available(); - verify(userStream1, times(2)).read(any(), anyInt(), anyInt()); - verify(userStream2, times(2)).available(); - verify(userStream2, times(2)).read(any(), anyInt(), anyInt()); - - // Verify that we correctly deserialized the data and sent it to the corresponding sources. - verify(sharedStoreData, times(1)) - .deserializeData(any(XmlPullParser.class), anyInt(), - eq(WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION), any()); - verify(userStoreData, times(1)) - .deserializeData(any(XmlPullParser.class), anyInt(), - eq(WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION), any()); - - // Verify we did not read from the real store files. - verify(sharedStoreFile1, never()).readRawData(); - verify(sharedStoreFile2, never()).readRawData(); - verify(userStoreFile1, never()).readRawData(); - verify(userStoreFile2, never()).readRawData(); - } - - /** - * Mock Store File to redirect all file writes from WifiConfigStore to local buffers. - * This can be used to examine the data output by WifiConfigStore. - */ - private class MockStoreFile extends StoreFile { - private byte[] mStoreBytes; - private boolean mStoreWritten; - - MockStoreFile(@WifiConfigStore.StoreFileId int fileId) { - super(new File("MockStoreFile"), fileId, UserHandle.ALL, mEncryptionUtil); - } - - @Override - public byte[] readRawData() { - return mStoreBytes; - } - - @Override - public void storeRawDataToWrite(byte[] data) { - mStoreBytes = data; - mStoreWritten = false; - } - - @Override - public void writeBufferedRawData() { - if (!ArrayUtils.isEmpty(mStoreBytes)) { - mStoreWritten = true; - } - } - - public byte[] getStoreBytes() { - return mStoreBytes; - } - - public boolean isStoreWritten() { - return mStoreWritten; - } - } - - /** - * Mock data container for providing test data for the store file. - */ - private class MockStoreData implements StoreData { - private static final String XML_TAG_TEST_HEADER = "TestHeader"; - private static final String XML_TAG_TEST_DATA = "TestData"; - - private @WifiConfigStore.StoreFileId int mFileId; - private String mData; - private boolean mHasAnyNewData = true; - - MockStoreData(@WifiConfigStore.StoreFileId int fileId) { - mFileId = fileId; - } - - @Override - public void serializeData(XmlSerializer out, WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mData); - } - - @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, int version, - WifiConfigStoreEncryptionUtil encryptionUtil) - throws XmlPullParserException, IOException { - if (in == null) { - return; - } - mData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA); - } - - @Override - public void resetData() { - mData = null; - } - - @Override - public boolean hasNewDataToSerialize() { - return mHasAnyNewData; - } - - @Override - public String getName() { - return XML_TAG_TEST_HEADER; - } - - @Override - public @WifiConfigStore.StoreFileId int getStoreFileId() { - return mFileId; - } - - public String getData() { - return mData; - } - - public void setData(String data) { - mData = data; - } - - public void setHasAnyNewData(boolean hasAnyNewData) { - mHasAnyNewData = hasAnyNewData; - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java deleted file mode 100644 index 589a30a8a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java +++ /dev/null @@ -1,875 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.*; - -import android.net.InetAddresses; -import android.net.IpConfiguration; -import android.net.LinkAddress; -import android.net.ProxyInfo; -import android.net.StaticIpConfiguration; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiSsid; -import android.text.TextUtils; - -import java.net.InetAddress; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.List; - -/** - * Helper for creating and populating WifiConfigurations in unit tests. - */ -public class WifiConfigurationTestUtil { - /** - * These values are used to describe AP's security setting. One AP can support multiple of them, - * only if there is no conflict. - */ - public static final int SECURITY_NONE = 0; - public static final int SECURITY_WEP = 1 << 0; - public static final int SECURITY_PSK = 1 << 1; - public static final int SECURITY_EAP = 1 << 2; - public static final int SECURITY_SAE = 1 << 3; - public static final int SECURITY_OWE = 1 << 4; - public static final int SECURITY_EAP_SUITE_B = 1 << 5; - public static final int SECURITY_WAPI_PSK = 1 << 6; - public static final int SECURITY_WAPI_CERT = 1 << 7; - - /** - * These values are used to describe ip configuration parameters for a network. - */ - public static final int STATIC_IP_ASSIGNMENT = 0; - public static final int DHCP_IP_ASSIGNMENT = 1; - public static final int STATIC_PROXY_SETTING = 0; - public static final int PAC_PROXY_SETTING = 1; - public static final int NONE_PROXY_SETTING = 2; - - /** - * These are constants used to generate predefined WifiConfiguration objects. - */ - public static final int TEST_NETWORK_ID = -1; - public static final int TEST_UID = 5; - public static final String TEST_SSID = "WifiConfigurationTestSSID"; - public static final String TEST_PSK = "\"WifiConfigurationTestUtilPsk\""; - public static final String[] TEST_WEP_KEYS = - {"\"WifiConfigurationTestUtilWep1\"", "\"WifiConfigurationTestUtilWep2\"", - "45342312ab", "45342312ab45342312ab34ac12"}; - public static final String TEST_EAP_PASSWORD = "WifiConfigurationTestUtilEapPassword"; - public static final int TEST_WEP_TX_KEY_INDEX = 1; - public static final String TEST_FQDN = "WifiConfigurationTestUtilFQDN"; - public static final String TEST_PROVIDER_FRIENDLY_NAME = - "WifiConfigurationTestUtilFriendlyName"; - public static final String TEST_STATIC_IP_LINK_ADDRESS = "192.168.48.2"; - public static final int TEST_STATIC_IP_LINK_PREFIX_LENGTH = 8; - public static final String TEST_STATIC_IP_GATEWAY_ADDRESS = "192.168.48.1"; - public static final String[] TEST_STATIC_IP_DNS_SERVER_ADDRESSES = - new String[]{"192.168.48.1", "192.168.48.10"}; - public static final String TEST_STATIC_PROXY_HOST = "192.168.48.1"; - public static final int TEST_STATIC_PROXY_PORT = 8000; - public static final String TEST_STATIC_PROXY_EXCLUSION_LIST = ""; - public static final String TEST_PAC_PROXY_LOCATION = "http://"; - public static final String TEST_CA_CERT_ALIAS = "WifiConfigurationTestUtilCaCertAlias"; - public static final String TEST_CA_CERT_SUITE_B_ALIAS = "SuiteBCaCertAlias"; - public static final String TEST_CA_CERT_PATH = "caPath"; - public static final String TEST_DOM_SUBJECT_MATCH = "domSubjectMatch"; - - private static final int MAX_SSID_LENGTH = 32; - /** - * Index used to assign unique SSIDs for the generation of predefined WifiConfiguration objects. - */ - private static int sNetworkIndex = 0; - - /** - * Construct a {@link android.net.wifi.WifiConfiguration}. - * @param networkId the configuration's networkId - * @param uid the configuration's creator uid - * @param ssid the configuration's ssid - * @param shared whether the configuration is shared with other users on the device - * @param enabled whether the configuration is enabled - * @param fqdn the configuration's FQDN (Hotspot 2.0 only) - * @param providerFriendlyName the configuration's provider's friendly name (Hotspot 2.0 only) - * @return the constructed {@link android.net.wifi.WifiConfiguration} - */ - public static WifiConfiguration generateWifiConfig(int networkId, int uid, String ssid, - boolean shared, boolean enabled, String fqdn, String providerFriendlyName) { - final WifiConfiguration config = new WifiConfiguration(); - config.SSID = ssid; - config.networkId = networkId; - config.creatorUid = uid; - config.shared = shared; - config.status = enabled ? WifiConfiguration.Status.ENABLED - : WifiConfiguration.Status.DISABLED; - config.FQDN = fqdn; - config.providerFriendlyName = providerFriendlyName; - if (config.FQDN != null) { - int uniqueId = config.FQDN.hashCode() + config.networkId + config.creatorUid; - // Generate a Passpoint unique id locally for the test - config.setPasspointUniqueId(config.FQDN + "_" + uniqueId); - } - return config; - } - - /** - * Construct a {@link android.net.wifi.WifiConfiguration}. - * @param networkId the configuration's networkId - * @param uid the configuration's creator uid - * @param ssid the configuration's ssid - * @param shared whether the configuration is shared with other users on the device - * @param enabled whether the configuration is enabled - * @param fqdn the configuration's FQDN (Hotspot 2.0 only) - * @param providerFriendlyName the configuration's provider's friendly name (Hotspot 2.0 only) - * @param security the configuration's security type - * @return the constructed {@link android.net.wifi.WifiConfiguration} - */ - public static WifiConfiguration generateWifiConfig(int networkId, int uid, String ssid, - boolean shared, boolean enabled, String fqdn, String providerFriendlyName, - int security) { - WifiConfiguration config = generateWifiConfig(networkId, uid, ssid, shared, enabled, fqdn, - providerFriendlyName); - - if ((security == SECURITY_NONE) || ((security & SECURITY_WEP) != 0)) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - } else { - if ((security & SECURITY_PSK) != 0) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - } - - if ((security & SECURITY_SAE) != 0) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - config.requirePmf = true; - } - - if ((security & SECURITY_OWE) != 0) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); - config.requirePmf = true; - } - - if ((security & SECURITY_EAP) != 0) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); - config.enterpriseConfig.setCaPath(TEST_CA_CERT_PATH); - config.enterpriseConfig.setDomainSuffixMatch(TEST_DOM_SUBJECT_MATCH); - } - - if ((security & SECURITY_EAP_SUITE_B) != 0) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192); - config.requirePmf = true; - } - - if ((security & SECURITY_WAPI_PSK) != 0) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK); - } - - if ((security & SECURITY_WAPI_CERT) != 0) { - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT); - } - - } - return config; - } - - /** - * Construct a {@link android.net.IpConfiguration }. - * @param ipAssignmentType One of {@link #STATIC_IP_ASSIGNMENT} or {@link #DHCP_IP_ASSIGNMENT}. - * @param proxySettingType One of {@link #STATIC_PROXY_SETTING} or {@link #PAC_PROXY_SETTING} or - * {@link #NONE_PROXY_SETTING}. - * @param linkAddress static ip address string. - * @param linkPrefixLength static ip address prefix length. - * @param gatewayAddress static gateway address. - * @param dnsServerAddresses list of dns servers for static ip configuration. - * @param proxyHost Static proxy server address. - * @param proxyPort Static proxy server port. - * @param proxyExclusionList Static proxy exclusion list. - * @param pacProxyPath Pac proxy server path. - * @return the constructed {@link android.net.IpConfiguration} - */ - public static IpConfiguration generateIpConfig( - int ipAssignmentType, int proxySettingType, String linkAddress, int linkPrefixLength, - String gatewayAddress, String[] dnsServerAddresses, String proxyHost, - int proxyPort, String proxyExclusionList, String pacProxyPath) { - StaticIpConfiguration staticIpConfiguration = null; - ProxyInfo proxyInfo = null; - IpConfiguration.IpAssignment ipAssignment = IpConfiguration.IpAssignment.UNASSIGNED; - IpConfiguration.ProxySettings proxySettings = IpConfiguration.ProxySettings.UNASSIGNED; - - if (ipAssignmentType == STATIC_IP_ASSIGNMENT) { - staticIpConfiguration = new StaticIpConfiguration(); - if (!TextUtils.isEmpty(linkAddress)) { - LinkAddress linkAddr = - new LinkAddress( - InetAddresses.parseNumericAddress(linkAddress), linkPrefixLength); - staticIpConfiguration.ipAddress = linkAddr; - } - - if (!TextUtils.isEmpty(gatewayAddress)) { - InetAddress gatewayAddr = - InetAddresses.parseNumericAddress(gatewayAddress); - staticIpConfiguration.gateway = gatewayAddr; - } - if (dnsServerAddresses != null) { - for (String dnsServerAddress : dnsServerAddresses) { - if (!TextUtils.isEmpty(dnsServerAddress)) { - staticIpConfiguration.dnsServers.add( - InetAddresses.parseNumericAddress(dnsServerAddress)); - } - - } - } - ipAssignment = IpConfiguration.IpAssignment.STATIC; - } else if (ipAssignmentType == DHCP_IP_ASSIGNMENT) { - ipAssignment = IpConfiguration.IpAssignment.DHCP; - } - - if (proxySettingType == STATIC_PROXY_SETTING) { - proxyInfo = new ProxyInfo(proxyHost, proxyPort, proxyExclusionList); - proxySettings = IpConfiguration.ProxySettings.STATIC; - } else if (proxySettingType == PAC_PROXY_SETTING) { - proxyInfo = new ProxyInfo(pacProxyPath); - proxySettings = IpConfiguration.ProxySettings.PAC; - } else if (proxySettingType == NONE_PROXY_SETTING) { - proxySettings = IpConfiguration.ProxySettings.NONE; - } - return new IpConfiguration(ipAssignment, proxySettings, staticIpConfiguration, proxyInfo); - } - - /** - * Create a new SSID for the the network being created. - */ - private static String createNewSSID() { - String ssid = TEST_SSID + sNetworkIndex++; - assertTrue(ssid.length() <= MAX_SSID_LENGTH); - return "\"" + ssid + "\""; - } - - /** - * Helper methods to generate predefined WifiConfiguration objects of the required type. These - * use a static index to avoid duplicate configurations. - */ - public static WifiConfiguration createOweNetwork() { - return createOweNetwork(createNewSSID()); - } - - public static WifiConfiguration createOweNetwork(String ssid) { - return generateWifiConfig(TEST_NETWORK_ID, TEST_UID, ssid, true, true, null, - null, SECURITY_OWE); - } - - public static WifiConfiguration createOpenNetwork() { - return createOpenNetwork(createNewSSID()); - } - - public static WifiConfiguration createOpenNetwork(String ssid) { - return generateWifiConfig(TEST_NETWORK_ID, TEST_UID, ssid, true, true, null, - null, SECURITY_NONE); - } - - public static WifiConfiguration createEphemeralNetwork() { - WifiConfiguration configuration = createOpenNetwork(); - configuration.ephemeral = true; - return configuration; - } - - public static WifiConfiguration createOpenHiddenNetwork() { - WifiConfiguration configuration = createOpenNetwork(); - configuration.hiddenSSID = true; - return configuration; - } - - public static WifiConfiguration createSaeNetwork() { - return createSaeNetwork(createNewSSID()); - } - - public static WifiConfiguration createPskNetwork() { - return createPskNetwork(createNewSSID()); - } - - public static WifiConfiguration createPskNetwork(String ssid) { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, ssid, true, true, null, - null, SECURITY_PSK); - configuration.preSharedKey = TEST_PSK; - return configuration; - } - - public static WifiConfiguration createSaeNetwork(String ssid) { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, ssid, true, true, null, - null, SECURITY_SAE); - - // SAE password uses the same member. - configuration.preSharedKey = TEST_PSK; - configuration.requirePmf = true; - return configuration; - } - - public static WifiConfiguration createPskHiddenNetwork() { - WifiConfiguration configuration = createPskNetwork(); - configuration.hiddenSSID = true; - return configuration; - } - - public static WifiConfiguration createWepNetwork() { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, null, - null, SECURITY_WEP); - configuration.wepKeys = TEST_WEP_KEYS; - configuration.wepTxKeyIndex = TEST_WEP_TX_KEY_INDEX; - return configuration; - } - - public static WifiConfiguration createWepHiddenNetwork() { - WifiConfiguration configuration = createWepNetwork(); - configuration.hiddenSSID = true; - return configuration; - } - - public static WifiConfiguration createWepNetworkWithSingleKey() { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, null, - null, SECURITY_WEP); - configuration.wepKeys[0] = TEST_WEP_KEYS[0]; - configuration.wepTxKeyIndex = 0; - return configuration; - } - - - public static WifiConfiguration createEapNetwork() { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, - null, null, SECURITY_EAP); - return configuration; - } - - public static WifiConfiguration createEapNetwork(String ssid) { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, ssid, true, true, - null, null, SECURITY_EAP); - return configuration; - } - - - public static WifiConfiguration createEapNetwork(int eapMethod, int phase2Method) { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, - null, null, SECURITY_EAP); - configuration.enterpriseConfig.setEapMethod(eapMethod); - configuration.enterpriseConfig.setPhase2Method(phase2Method); - return configuration; - } - - public static WifiConfiguration createEapSuiteBNetwork() { - return createEapSuiteBNetwork(WifiConfiguration.SuiteBCipher.ECDHE_RSA); - } - - public static WifiConfiguration createEapSuiteBNetwork(int signatureType) { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, - null, null, SECURITY_EAP_SUITE_B); - - configuration.requirePmf = true; - configuration.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - configuration.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); - - if (signatureType == WifiConfiguration.SuiteBCipher.ECDHE_ECDSA) { - configuration.enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT); - configuration.enterpriseConfig.setClientKeyEntryWithCertificateChain( - FakeKeys.CLIENT_SUITE_B_ECC_KEY, - new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT}); - } else { - configuration.enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT); - configuration.enterpriseConfig.setClientKeyEntryWithCertificateChain( - FakeKeys.CLIENT_SUITE_B_RSA3072_KEY, - new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT}); - } - return configuration; - } - - public static WifiConfiguration createPasspointNetwork() { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, - TEST_FQDN, TEST_PROVIDER_FRIENDLY_NAME, SECURITY_EAP); - return configuration; - } - - public static WifiConfiguration createWapiPskNetwork() { - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, null, - null, SECURITY_WAPI_PSK); - configuration.preSharedKey = TEST_PSK; - return configuration; - } - - public static WifiConfiguration createWapiCertNetwork() { - WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); - enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.WAPI_CERT); - enterpriseConfig.setWapiCertSuite("wapiCertSuite"); - WifiConfiguration configuration = - generateWifiConfig(TEST_NETWORK_ID, TEST_UID, createNewSSID(), true, true, null, - null, SECURITY_WAPI_CERT); - configuration.enterpriseConfig = enterpriseConfig; - return configuration; - } - - public static IpConfiguration createStaticIpConfigurationWithPacProxy() { - return generateIpConfig( - STATIC_IP_ASSIGNMENT, PAC_PROXY_SETTING, - TEST_STATIC_IP_LINK_ADDRESS, TEST_STATIC_IP_LINK_PREFIX_LENGTH, - TEST_STATIC_IP_GATEWAY_ADDRESS, TEST_STATIC_IP_DNS_SERVER_ADDRESSES, - TEST_STATIC_PROXY_HOST, TEST_STATIC_PROXY_PORT, TEST_STATIC_PROXY_EXCLUSION_LIST, - TEST_PAC_PROXY_LOCATION); - } - - public static IpConfiguration createStaticIpConfigurationWithStaticProxy() { - return generateIpConfig( - STATIC_IP_ASSIGNMENT, STATIC_PROXY_SETTING, - TEST_STATIC_IP_LINK_ADDRESS, TEST_STATIC_IP_LINK_PREFIX_LENGTH, - TEST_STATIC_IP_GATEWAY_ADDRESS, TEST_STATIC_IP_DNS_SERVER_ADDRESSES, - TEST_STATIC_PROXY_HOST, TEST_STATIC_PROXY_PORT, TEST_STATIC_PROXY_EXCLUSION_LIST, - TEST_PAC_PROXY_LOCATION); - } - - public static IpConfiguration createPartialStaticIpConfigurationWithPacProxy() { - return generateIpConfig( - STATIC_IP_ASSIGNMENT, PAC_PROXY_SETTING, - TEST_STATIC_IP_LINK_ADDRESS, TEST_STATIC_IP_LINK_PREFIX_LENGTH, - null, null, - TEST_STATIC_PROXY_HOST, TEST_STATIC_PROXY_PORT, TEST_STATIC_PROXY_EXCLUSION_LIST, - TEST_PAC_PROXY_LOCATION); - } - - public static IpConfiguration createDHCPIpConfigurationWithPacProxy() { - return generateIpConfig( - DHCP_IP_ASSIGNMENT, PAC_PROXY_SETTING, - TEST_STATIC_IP_LINK_ADDRESS, TEST_STATIC_IP_LINK_PREFIX_LENGTH, - TEST_STATIC_IP_GATEWAY_ADDRESS, TEST_STATIC_IP_DNS_SERVER_ADDRESSES, - TEST_STATIC_PROXY_HOST, TEST_STATIC_PROXY_PORT, TEST_STATIC_PROXY_EXCLUSION_LIST, - TEST_PAC_PROXY_LOCATION); - } - - public static IpConfiguration createDHCPIpConfigurationWithStaticProxy() { - return generateIpConfig( - DHCP_IP_ASSIGNMENT, STATIC_PROXY_SETTING, - TEST_STATIC_IP_LINK_ADDRESS, TEST_STATIC_IP_LINK_PREFIX_LENGTH, - TEST_STATIC_IP_GATEWAY_ADDRESS, TEST_STATIC_IP_DNS_SERVER_ADDRESSES, - TEST_STATIC_PROXY_HOST, TEST_STATIC_PROXY_PORT, TEST_STATIC_PROXY_EXCLUSION_LIST, - TEST_PAC_PROXY_LOCATION); - } - - public static IpConfiguration createDHCPIpConfigurationWithNoProxy() { - return generateIpConfig( - DHCP_IP_ASSIGNMENT, NONE_PROXY_SETTING, - TEST_STATIC_IP_LINK_ADDRESS, TEST_STATIC_IP_LINK_PREFIX_LENGTH, - TEST_STATIC_IP_GATEWAY_ADDRESS, TEST_STATIC_IP_DNS_SERVER_ADDRESSES, - TEST_STATIC_PROXY_HOST, TEST_STATIC_PROXY_PORT, TEST_STATIC_PROXY_EXCLUSION_LIST, - TEST_PAC_PROXY_LOCATION); - } - - /** - * Creates an IP configuration with specific parameters. - * @param proxySetting Must be one of {@link WifiConfigurationTestUtil#STATIC_PROXY_SETTING}, - * {@link WifiConfigurationTestUtil#PAC_PROXY_SETTING}, - * {@link WifiConfigurationTestUtil#NONE_PROXY_SETTING} - */ - public static IpConfiguration createDHCPIpConfigurationWithSpecificProxy( - int proxySetting, - String staticProxyHost, - int staticProxyPort, - String staticProxyExclusionList, - String pacProxyLocation) { - return generateIpConfig( - DHCP_IP_ASSIGNMENT, proxySetting, - TEST_STATIC_IP_LINK_ADDRESS, TEST_STATIC_IP_LINK_PREFIX_LENGTH, - TEST_STATIC_IP_GATEWAY_ADDRESS, TEST_STATIC_IP_DNS_SERVER_ADDRESSES, - staticProxyHost, staticProxyPort, staticProxyExclusionList, - pacProxyLocation); - } - - // TODO: These enterprise configurations may need more parameters set. - public static WifiEnterpriseConfig createPEAPWifiEnterpriseConfigWithGTCPhase2() { - WifiEnterpriseConfig config = new WifiEnterpriseConfig(); - config.setEapMethod(WifiEnterpriseConfig.Eap.PEAP); - config.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC); - config.setCaCertificateAliases(new String[] {TEST_CA_CERT_ALIAS + "PEAP"}); - config.setCaCertificates(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); - config.setDomainSuffixMatch(TEST_DOM_SUBJECT_MATCH); - return config; - } - - public static WifiEnterpriseConfig createTLSWifiEnterpriseConfigWithNonePhase2() { - WifiEnterpriseConfig config = new WifiEnterpriseConfig(); - config.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - config.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); - config.setCaCertificateAliases(new String[] {TEST_CA_CERT_ALIAS + "TLS"}); - config.setCaCertificates(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); - config.setDomainSuffixMatch(TEST_DOM_SUBJECT_MATCH); - return config; - } - - public static WifiEnterpriseConfig createTLSWifiEnterpriseConfigWithAkaPhase2() { - WifiEnterpriseConfig config = new WifiEnterpriseConfig(); - config.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - config.setPhase2Method(WifiEnterpriseConfig.Phase2.AKA); - config.setDomainSuffixMatch(TEST_DOM_SUBJECT_MATCH); - return config; - } - - /** - * Gets scan result capabilities for a particular network configuration. - */ - public static String getScanResultCapsForNetwork(WifiConfiguration configuration) { - String caps; - if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - caps = "[RSN-PSK-CCMP]"; - } else if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) - || configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) { - caps = "[RSN-EAP-CCMP]"; - } else if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE) - && WifiConfigurationUtil.hasAnyValidWepKey(configuration.wepKeys)) { - caps = "[WEP]"; - } else if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { - caps = "[RSN-SAE-CCMP]"; - } else if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) { - caps = "[RSN-OWE-CCMP]"; - } else if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) { - caps = "[RSN-SUITE-B-192-CCMP]"; - } else if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK)) { - caps = "[WAPI-WAPI-PSK-SMS4]"; - } else if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_CERT)) { - caps = "[WAPI-WAPI-CERT-SMS4]"; - } else { - caps = "[]"; - } - return caps; - } - - /** - * Gets scan result capabilities for a WPA2/WPA3-Transition mode network configuration - */ - public static String getScanResultCapsForWpa2Wpa3TransitionNetwork() { - String caps = "[RSN-PSK+SAE-CCMP]"; - return caps; - } - - /** - * Creates a scan detail corresponding to the provided network and given BSSID, etc. - */ - public static ScanDetail createScanDetailForNetwork( - WifiConfiguration configuration, String bssid, int level, int frequency, - long tsf, long seen) { - String caps = getScanResultCapsForNetwork(configuration); - WifiSsid ssid = WifiSsid.createFromAsciiEncoded(configuration.getPrintableSsid()); - return new ScanDetail(ssid, bssid, caps, level, frequency, tsf, seen); - } - - /** - * Creates a scan detail corresponding to the provided network and given BSSID, but sets - * the capabilities to WPA2/WPA3-Transition mode network. - */ - public static ScanDetail createScanDetailForWpa2Wpa3TransitionModeNetwork( - WifiConfiguration configuration, String bssid, int level, int frequency, - long tsf, long seen) { - String caps = getScanResultCapsForWpa2Wpa3TransitionNetwork(); - WifiSsid ssid = WifiSsid.createFromAsciiEncoded(configuration.getPrintableSsid()); - return new ScanDetail(ssid, bssid, caps, level, frequency, tsf, seen); - } - - /** - * Asserts that the 2 WifiConfigurations are equal in the elements saved for both backup/restore - * and config store. - */ - private static void assertCommonConfigurationElementsEqual( - WifiConfiguration expected, WifiConfiguration actual) { - assertNotNull(expected); - assertNotNull(actual); - assertEquals(expected.SSID, actual.SSID); - assertEquals(expected.BSSID, actual.BSSID); - assertEquals(expected.preSharedKey, actual.preSharedKey); - assertEquals(expected.wepKeys, actual.wepKeys); - assertEquals(expected.wepTxKeyIndex, actual.wepTxKeyIndex); - assertEquals(expected.hiddenSSID, actual.hiddenSSID); - assertEquals(expected.requirePmf, actual.requirePmf); - assertEquals(expected.allowedKeyManagement, actual.allowedKeyManagement); - assertEquals(expected.allowedProtocols, actual.allowedProtocols); - assertEquals(expected.allowedAuthAlgorithms, actual.allowedAuthAlgorithms); - assertEquals(expected.allowedGroupCiphers, actual.allowedGroupCiphers); - assertEquals(expected.allowedPairwiseCiphers, actual.allowedPairwiseCiphers); - assertEquals(expected.shared, actual.shared); - assertEquals(expected.getIpConfiguration(), actual.getIpConfiguration()); - } - - - /** - * Asserts that the 2 WifiConfigurations are equal. This only compares the elements saved - * for softAp used. - */ - public static void assertConfigurationEqualForSoftAp( - WifiConfiguration expected, WifiConfiguration actual) { - assertEquals(expected.SSID, actual.SSID); - assertEquals(expected.BSSID, actual.BSSID); - assertEquals(expected.apBand, actual.apBand); - assertEquals(expected.apChannel, actual.apChannel); - assertEquals(expected.preSharedKey, actual.preSharedKey); - assertEquals(expected.getAuthType(), actual.getAuthType()); - assertEquals(expected.hiddenSSID, actual.hiddenSSID); - } - - /** - * Asserts that the 2 WifiConfigurations are equal. This only compares the elements saved - * for backup/restore. - */ - public static void assertConfigurationEqualForBackup( - WifiConfiguration expected, WifiConfiguration actual) { - assertCommonConfigurationElementsEqual(expected, actual); - assertEquals(expected.meteredOverride, actual.meteredOverride); - } - - /** - * Asserts that the 2 WifiConfigurations are equal. This compares all the elements saved for - * config store. - */ - public static void assertConfigurationEqualForConfigStore( - WifiConfiguration expected, WifiConfiguration actual) { - assertCommonConfigurationElementsEqual(expected, actual); - assertEquals(expected.status, actual.status); - assertEquals(expected.FQDN, actual.FQDN); - assertEquals(expected.providerFriendlyName, actual.providerFriendlyName); - assertTrue(Arrays.equals(expected.roamingConsortiumIds, actual.roamingConsortiumIds)); - assertEquals(expected.linkedConfigurations, actual.linkedConfigurations); - assertEquals(expected.defaultGwMacAddress, actual.defaultGwMacAddress); - assertEquals(expected.validatedInternetAccess, actual.validatedInternetAccess); - assertEquals(expected.noInternetAccessExpected, actual.noInternetAccessExpected); - assertEquals(expected.meteredHint, actual.meteredHint); - assertEquals(expected.meteredOverride, actual.meteredOverride); - assertEquals(expected.useExternalScores, actual.useExternalScores); - assertEquals(0, actual.numAssociation); - assertEquals(expected.creatorUid, actual.creatorUid); - assertEquals(expected.creatorName, actual.creatorName); - assertEquals(expected.lastUpdateUid, actual.lastUpdateUid); - assertEquals(expected.lastUpdateName, actual.lastUpdateName); - assertEquals(expected.lastConnectUid, actual.lastConnectUid); - assertEquals(expected.isLegacyPasspointConfig, actual.isLegacyPasspointConfig); - assertEquals(expected.getRandomizedMacAddress(), actual.getRandomizedMacAddress()); - assertEquals(expected.macRandomizationSetting, actual.macRandomizationSetting); - assertNetworkSelectionStatusEqualForConfigStore( - expected.getNetworkSelectionStatus(), actual.getNetworkSelectionStatus()); - assertWifiEnterpriseConfigEqualForConfigStore( - expected.enterpriseConfig, actual.enterpriseConfig); - } - - /** - * Asserts that the 2 WifiConfigurations are equal. This compares all the elements that are - * saved into internal database by WifiConfigurationManager for network additions/updates. - */ - public static void assertConfigurationEqualForConfigManagerAddOrUpdate( - WifiConfiguration expected, WifiConfiguration actual) { - assertCommonConfigurationElementsEqual(expected, actual); - assertEquals(expected.FQDN, actual.FQDN); - assertEquals(expected.providerFriendlyName, actual.providerFriendlyName); - assertEquals(expected.noInternetAccessExpected, actual.noInternetAccessExpected); - assertEquals(expected.meteredHint, actual.meteredHint); - assertEquals(expected.meteredOverride, actual.meteredOverride); - assertEquals(expected.useExternalScores, actual.useExternalScores); - assertEquals(expected.ephemeral, actual.ephemeral); - assertEquals(expected.osu, actual.osu); - assertEquals(expected.trusted, actual.trusted); - assertEquals(expected.fromWifiNetworkSuggestion, actual.fromWifiNetworkSuggestion); - assertEquals(expected.fromWifiNetworkSpecifier, actual.fromWifiNetworkSpecifier); - assertEquals(expected.creatorUid, actual.creatorUid); - assertEquals(expected.creatorName, actual.creatorName); - assertEquals(expected.lastUpdateUid, actual.lastUpdateUid); - assertEquals(expected.lastUpdateName, actual.lastUpdateName); - assertNetworkSelectionStatusEqualForConfigStore( - expected.getNetworkSelectionStatus(), actual.getNetworkSelectionStatus()); - assertWifiEnterpriseConfigEqualForConfigStore( - expected.enterpriseConfig, actual.enterpriseConfig); - } - - /** - * Asserts that the 2 WifiConfigurations are equal. This compares all the elements that are - * saved into wpa_supplicant by SupplicantStaNetwork. - */ - public static void assertConfigurationEqualForSupplicant( - WifiConfiguration expected, WifiConfiguration actual) { - assertNotNull(expected); - assertNotNull(actual); - assertEquals(expected.SSID, actual.SSID); - assertEquals(expected.getNetworkSelectionStatus().getNetworkSelectionBSSID(), - actual.getNetworkSelectionStatus().getNetworkSelectionBSSID()); - assertEquals(expected.preSharedKey, actual.preSharedKey); - assertEquals(expected.wepKeys, actual.wepKeys); - assertEquals(expected.wepTxKeyIndex, actual.wepTxKeyIndex); - assertEquals(expected.hiddenSSID, actual.hiddenSSID); - assertEquals(expected.requirePmf, actual.requirePmf); - assertEquals(expected.allowedKeyManagement, actual.allowedKeyManagement); - assertEquals(expected.allowedProtocols, actual.allowedProtocols); - assertEquals(expected.allowedAuthAlgorithms, actual.allowedAuthAlgorithms); - assertEquals(expected.allowedGroupCiphers, actual.allowedGroupCiphers); - assertEquals(expected.allowedPairwiseCiphers, actual.allowedPairwiseCiphers); - assertWifiEnterpriseConfigEqualForConfigStore( - expected.enterpriseConfig, actual.enterpriseConfig); - } - - /** - * Asserts that the 2 WifiConfigurations are equal. This is a generic version of the comparator - * which is used in QNS tests for comparing the network selections. - * This importantly checks that the networkId's of the 2 configs are equal. - */ - public static void assertConfigurationEqual( - WifiConfiguration expected, WifiConfiguration actual) { - assertCommonConfigurationElementsEqual(expected, actual); - assertEquals(expected.networkId, actual.networkId); - assertEquals(expected.ephemeral, actual.ephemeral); - assertEquals(expected.fromWifiNetworkSuggestion, actual.fromWifiNetworkSuggestion); - assertEquals(expected.fromWifiNetworkSpecifier, actual.fromWifiNetworkSpecifier); - assertEquals(expected.trusted, actual.trusted); - } - - /** - * Assert that the 2 NetworkSelectionStatus's are equal. This compares all the elements saved - * for config store. - */ - public static void assertNetworkSelectionStatusEqualForConfigStore( - NetworkSelectionStatus expected, NetworkSelectionStatus actual) { - if (expected.isNetworkTemporaryDisabled()) { - // Temporarily disabled networks are enabled when persisted. - assertEquals( - NetworkSelectionStatus.NETWORK_SELECTION_ENABLED, - actual.getNetworkSelectionStatus()); - assertEquals( - NetworkSelectionStatus.DISABLED_NONE, - actual.getNetworkSelectionDisableReason()); - } else { - assertEquals(expected.getNetworkSelectionStatus(), actual.getNetworkSelectionStatus()); - assertEquals( - expected.getNetworkSelectionDisableReason(), - actual.getNetworkSelectionDisableReason()); - } - assertEquals(expected.getConnectChoice(), actual.getConnectChoice()); - assertEquals(expected.hasEverConnected(), actual.hasEverConnected()); - } - - /** - * Assert that the 2 WifiEnterpriseConfig's are equal. This compares all the elements saved - * for config store. - */ - public static void assertWifiEnterpriseConfigEqualForConfigStore( - WifiEnterpriseConfig expected, WifiEnterpriseConfig actual) { - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY), - actual.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY), - actual.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY), - actual.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY), - actual.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY), - actual.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY), - actual.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY), - actual.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY), - actual.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY), - actual.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY), - actual.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY), - actual.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY), - actual.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.REALM_KEY), - actual.getFieldValue(WifiEnterpriseConfig.REALM_KEY)); - assertEquals(expected.getFieldValue(WifiEnterpriseConfig.PLMN_KEY), - actual.getFieldValue(WifiEnterpriseConfig.PLMN_KEY)); - assertEquals(expected.getEapMethod(), actual.getEapMethod()); - assertEquals(expected.getPhase2Method(), actual.getPhase2Method()); - } - - /** - * Asserts that the 2 lists of WifiConfigurations are equal. This compares all the elements - * saved for backup/restore. - */ - public static void assertConfigurationsEqualForBackup( - List<WifiConfiguration> expected, List<WifiConfiguration> actual) { - assertEquals(expected.size(), actual.size()); - for (WifiConfiguration expectedConfiguration : expected) { - String expectedConfigKey = expectedConfiguration.getKey(); - boolean didCompare = false; - for (WifiConfiguration actualConfiguration : actual) { - String actualConfigKey = actualConfiguration.getKey(); - if (actualConfigKey.equals(expectedConfigKey)) { - assertConfigurationEqualForBackup( - expectedConfiguration, actualConfiguration); - didCompare = true; - } - } - assertTrue(didCompare); - } - } - - /** - * Asserts that the 2 lists of WifiConfigurations are equal. This compares all the elements - * that are saved into internal database by WifiConfigurationManager for network - * additions/updates. - */ - public static void assertConfigurationsEqualForConfigManagerAddOrUpdate( - List<WifiConfiguration> expected, List<WifiConfiguration> actual) { - assertEquals(expected.size(), actual.size()); - for (WifiConfiguration expectedConfiguration : expected) { - String expectedConfigKey = expectedConfiguration.getKey(); - boolean didCompare = false; - for (WifiConfiguration actualConfiguration : actual) { - String actualConfigKey = actualConfiguration.getKey(); - if (actualConfigKey.equals(expectedConfigKey)) { - assertConfigurationEqualForConfigManagerAddOrUpdate( - expectedConfiguration, actualConfiguration); - didCompare = true; - } - } - assertTrue(didCompare); - } - } - - /** - * Asserts that the 2 lists of WifiConfigurations are equal. This compares all the elements - * saved for config store. - */ - public static void assertConfigurationsEqualForConfigStore( - List<WifiConfiguration> expected, List<WifiConfiguration> actual) { - assertEquals(expected.size(), actual.size()); - for (WifiConfiguration expectedConfiguration : expected) { - String expectedConfigKey = expectedConfiguration.getKey(); - boolean didCompare = false; - for (WifiConfiguration actualConfiguration : actual) { - String actualConfigKey = actualConfiguration.getKey(); - if (actualConfigKey.equals(expectedConfigKey)) { - assertConfigurationEqualForConfigStore( - expectedConfiguration, actualConfiguration); - didCompare = true; - } - } - assertTrue(didCompare); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java deleted file mode 100644 index 0dd5b1214..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java +++ /dev/null @@ -1,1064 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiEnterpriseConfig.OCSP_NONE; -import static android.net.wifi.WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS; - -import static org.junit.Assert.*; - -import android.content.pm.UserInfo; -import android.net.IpConfiguration; -import android.net.MacAddress; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiNetworkSpecifier; -import android.net.wifi.WifiScanner; -import android.os.PatternMatcher; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; - -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.WifiConfigurationUtil}. - */ -@SmallTest -public class WifiConfigurationUtilTest extends WifiBaseTest { - static final int CURRENT_USER_ID = 0; - static final int CURRENT_USER_MANAGED_PROFILE_USER_ID = 10; - static final int OTHER_USER_ID = 11; - static final int TEST_UID = 10000; - static final String TEST_PACKAGE = "com.test"; - static final String TEST_SSID = "test_ssid"; - static final String TEST_SSID_1 = "test_ssid_1"; - static final String TEST_BSSID = "aa:aa:11:22:cc:dd"; - static final String TEST_BSSID_1 = "11:22:11:22:cc:dd"; - static final List<UserInfo> PROFILES = Arrays.asList( - new UserInfo(CURRENT_USER_ID, "owner", 0), - new UserInfo(CURRENT_USER_MANAGED_PROFILE_USER_ID, "managed profile", 0)); - - /** - * Verify that new WifiEnterpriseConfig is detected. - */ - @Test - public void testEnterpriseConfigAdded() { - EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0}); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged( - null, eapConfig.enterpriseConfig)); - } - - /** - * Verify WifiEnterpriseConfig eap change is detected. - */ - @Test - public void testEnterpriseConfigEapChangeDetected() { - EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS); - EnterpriseConfig peapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.PEAP); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig, - peapConfig.enterpriseConfig)); - } - - /** - * Verify WifiEnterpriseConfig phase2 method change is detected. - */ - @Test - public void testEnterpriseConfigPhase2ChangeDetected() { - EnterpriseConfig eapConfig = - new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2); - EnterpriseConfig papConfig = - new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.PAP); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig, - papConfig.enterpriseConfig)); - } - - /** - * Verify WifiEnterpriseConfig added Certificate is detected. - */ - @Test - public void testCaCertificateAddedDetected() { - EnterpriseConfig eapConfigNoCerts = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password"); - - EnterpriseConfig eapConfig1Cert = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0}); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged( - eapConfigNoCerts.enterpriseConfig, eapConfig1Cert.enterpriseConfig)); - } - - /** - * Verify WifiEnterpriseConfig Certificate change is detected. - */ - @Test - public void testDifferentCaCertificateDetected() { - EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0}); - - EnterpriseConfig eapConfigNewCert = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT1}); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig, - eapConfigNewCert.enterpriseConfig)); - } - - /** - * Verify WifiEnterpriseConfig added Certificate changes are detected. - */ - @Test - public void testCaCertificateChangesDetected() { - EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0}); - - EnterpriseConfig eapConfigAddedCert = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig, - eapConfigAddedCert.enterpriseConfig)); - } - - /** - * Verify that WifiEnterpriseConfig does not detect changes for identical configs. - */ - @Test - public void testWifiEnterpriseConfigNoChanges() { - EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); - - // Just to be clear that check is not against the same object - EnterpriseConfig eapConfigSame = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); - - assertFalse(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig, - eapConfigSame.enterpriseConfig)); - } - - /** - * Verify that the validate method successfully validates good WifiConfigurations with ASCII - * values. - */ - @Test - public void testValidatePositiveCases_Ascii() { - assertTrue(WifiConfigurationUtil.validate( - WifiConfigurationTestUtil.createOpenNetwork(), - WifiConfigurationUtil.VALIDATE_FOR_ADD)); - assertTrue(WifiConfigurationUtil.validate( - WifiConfigurationTestUtil.createPskNetwork(), - WifiConfigurationUtil.VALIDATE_FOR_ADD)); - assertTrue(WifiConfigurationUtil.validate( - WifiConfigurationTestUtil.createWepNetwork(), - WifiConfigurationUtil.VALIDATE_FOR_ADD)); - assertTrue(WifiConfigurationUtil.validate( - WifiConfigurationTestUtil.createEapNetwork(), - WifiConfigurationUtil.VALIDATE_FOR_ADD)); - assertTrue(WifiConfigurationUtil.validate( - WifiConfigurationTestUtil.createOweNetwork(), - WifiConfigurationUtil.VALIDATE_FOR_ADD)); - assertTrue(WifiConfigurationUtil.validate( - WifiConfigurationTestUtil.createSaeNetwork(), - WifiConfigurationUtil.VALIDATE_FOR_ADD)); - assertTrue(WifiConfigurationUtil.validate( - WifiConfigurationTestUtil.createEapSuiteBNetwork(), - WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method successfully validates good WifiConfigurations with hex - * values. - */ - @Test - public void testValidatePositiveCases_Hex() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - config.SSID = "abcd1234555a"; - config.preSharedKey = "abcd123455151234556788990034556667332345667322344556676743233445"; - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method validates WifiConfiguration with masked psk string only for - * an update. - */ - @Test - public void testValidatePositiveCases_MaskedPskString() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.preSharedKey = WifiConfigurationUtil.PASSWORD_MASK; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - assertTrue(WifiConfigurationUtil.validate( - config, WifiConfigurationUtil.VALIDATE_FOR_UPDATE)); - } - - /** - * Verify that the validate method validates WifiConfiguration with null ssid only for an - * update. - */ - @Test - public void testValidatePositiveCases_OnlyUpdateIgnoresNullSsid() { - WifiConfiguration config = new WifiConfiguration(); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - assertTrue(WifiConfigurationUtil.validate( - config, WifiConfigurationUtil.VALIDATE_FOR_UPDATE)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad ssid length. - */ - @Test - public void testValidateNegativeCases_BadAsciiSsidLength() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.SSID = "\"abcdfefeeretretyetretetetetetrertertrsreqwrwe\""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - config.SSID = "\"\""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad ssid length. - */ - @Test - public void testValidateNegativeCases_BadUtf8SsidLength() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.SSID = "\"가하아너너ㅓ저저ㅓ어아아다자저ㅓ더타아어어러두어\""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - config.SSID = "\"\""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed ssid - * string. - */ - @Test - public void testValidateNegativeCases_MalformedAsciiSsidString() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.SSID = "\"ab"; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad ssid length. - */ - @Test - public void testValidateNegativeCases_BadHexSsidLength() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.SSID = "abcdfe012345632423343543453456464545656464545646454ace34534545634535"; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - config.SSID = ""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed ssid - * string. - */ - @Test - public void testValidateNegativeCases_MalformedHexSsidString() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.SSID = "hello"; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad psk length. - */ - @Test - public void testValidateNegativeCases_BadAsciiPskLength() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.preSharedKey = "\"abcdffeeretretyetreteteteabe34tetrertertrsraaaaaaaaaaa345eqwrweewq" - + "weqe\""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - config.preSharedKey = "\"454\""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad sae length. - */ - @Test - public void testValidateNegativeCases_BadAsciiSaeLength() { - WifiConfiguration config = WifiConfigurationTestUtil.createSaeNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.preSharedKey = "\"abcdffeeretretyetreteteteabe34tetrertertrsraaaaaaaaaaa345eqwrweewq" - + "weqe\""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - config.preSharedKey = "\"\""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed psk - * string. - */ - @Test - public void testValidateNegativeCases_MalformedAsciiPskString() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.preSharedKey = "\"abcdfefeeretrety"; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed sae - * string. - */ - @Test - public void testValidateNegativeCases_MalformedAsciiSaeString() { - WifiConfiguration config = WifiConfigurationTestUtil.createSaeNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.preSharedKey = "\"abcdfefeeretrety"; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad psk length. - */ - @Test - public void testValidateNegativeCases_BadHexPskLength() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.preSharedKey = "abcd123456788990013453445345465465476546"; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - config.preSharedKey = ""; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed psk - * string. - */ - @Test - public void testValidateNegativeCases_MalformedHexPskString() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.preSharedKey = "adbdfgretrtyrtyrty"; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed sae - * string. - */ - @Test - public void testValidateNegativeCases_MalformedHexSaeString() { - WifiConfiguration config = WifiConfigurationTestUtil.createSaeNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.preSharedKey = "adbdfgretrtyrtyrty"; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad key mgmt values. - */ - @Test - public void testValidateNegativeCases_BadKeyMgmtPskEap() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad key mgmt values. - */ - @Test - public void testValidateNegativeCases_BadKeyMgmtOpenPsk() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad key mgmt values. - */ - @Test - public void testValidateNegativeCases_BadKeyMgmt() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad ipconfiguration - * values. - */ - @Test - public void testValidateNegativeCases_BadIpconfiguration() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - IpConfiguration ipConfig = - WifiConfigurationTestUtil.createStaticIpConfigurationWithPacProxy(); - config.setIpConfiguration(ipConfig); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - ipConfig.setStaticIpConfiguration(null); - config.setIpConfiguration(ipConfig); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad KeyMgmt value. - */ - @Test - public void testValidateNegativeCases_InvalidKeyMgmt() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FT_EAP + 1); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad KeyMgmt value. - */ - @Test - public void testValidateNegativeCases_InvalidKeyMgmtWithPreSharedKey() { - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedKeyManagement.clear(); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OSEN); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - // Verify we reset the KeyMgmt - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)); - assertFalse(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OSEN)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad Protocol value. - */ - @Test - public void testValidateNegativeCases_InvalidProtocol() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedProtocols.set(4); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad AuthAlgorithm - * value. - */ - @Test - public void testValidateNegativeCases_InvalidAuthAlgorithm() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.LEAP + 3); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad GroupCipher - * value. - */ - @Test - public void testValidateNegativeCases_InvalidGroupCipher() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GTK_NOT_USED + 3); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with bad PairwiseCipher - * value. - */ - @Test - public void testValidateNegativeCases_InvalidPairwiseCipher() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP + 3); - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed sae - * string. - */ - @Test - public void testValidateNegativeCases_SaeMissingPmf() { - WifiConfiguration config = WifiConfigurationTestUtil.createSaeNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.requirePmf = false; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed owe - * string. - */ - @Test - public void testValidateNegativeCases_OweMissingPmf() { - WifiConfiguration config = WifiConfigurationTestUtil.createOweNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.requirePmf = false; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method fails to validate WifiConfiguration with malformed suiteb - * string. - */ - @Test - public void testValidateNegativeCases_SuitebMissingPmf() { - WifiConfiguration config = WifiConfigurationTestUtil.createEapSuiteBNetwork(); - assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - - config.requirePmf = false; - assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); - } - - /** - * Verify that the validate method successfully validates good WifiNetworkSpecifier with - * only ssid pattern set. - */ - @Test - public void testValidateNetworkSpecifierPositiveCases_SsidPattern() { - WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( - new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), - WifiConfigurationTestUtil.createOpenNetwork()); - assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); - } - - /** - * Verify that the validate method successfully validates good WifiNetworkSpecifier with - * only bssid pattern set. - */ - @Test - public void testValidateNetworkSpecifierPositiveCases_BssidPattern() { - WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( - new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB), - Pair.create(MacAddress.fromString(TEST_BSSID), MacAddress.BROADCAST_ADDRESS), - WifiConfigurationTestUtil.createOpenNetwork()); - assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); - } - - /** - * Verify that the validate method successfully validates good WifiNetworkSpecifier with - * both ssid & bssid patterns set. - */ - @Test - public void testValidateNetworkSpecifierPositiveCases_BothSsidPatternAndBssidPattern() { - WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( - new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), - Pair.create(MacAddress.fromString(TEST_BSSID), MacAddress.BROADCAST_ADDRESS), - WifiConfigurationTestUtil.createOpenNetwork()); - assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); - } - - /** - * Verify that the validate method fails to validate WifiNetworkSpecifier with no - * ssid/bssid info. - */ - @Test - public void testValidateNetworkSpecifierNegativeCases_NoSsidBssid() { - WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( - new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB), - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); - } - - /** - * Verify that the validate method fails to validate WifiNetworkSpecifier with invalid SSID - * match pattern. - */ - @Test - public void testValidateNetworkSpecifierNegativeCases_MatchNoneSsidPattern() { - WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( - new PatternMatcher("", PatternMatcher.PATTERN_LITERAL), - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); - } - - /** - * Verify that the validate method fails to validate WifiNetworkSpecifier with illegal - * pattern. - */ - @Test - public void testValidateNetworkSpecifierNegativeCases_MatchNoneBssidPattern() { - WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( - new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), - Pair.create(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS), - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); - } - - /** - * Verify that the validate method fails to validate WifiNetworkSpecifier with illegal - * pattern. - */ - @Test - public void testValidateNetworkSpecifierNegativeCases_InvalidBssidPattern() { - WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( - new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), - Pair.create(MacAddress.fromString(TEST_BSSID), WifiManager.ALL_ZEROS_MAC_ADDRESS), - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); - } - - /** - * Verify that the validate method fails to validate WifiNetworkSpecifier with SSID pattern - * for hidden network. - */ - @Test - public void testValidateNetworkSpecifierNegativeCases_NoSsidPatternForHiddenNetwork() { - WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( - new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_PREFIX), - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), - WifiConfigurationTestUtil.createOpenHiddenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); - } - - /** - * Verify the instance of {@link android.net.wifi.WifiScanner.PnoSettings.PnoNetwork} created - * for an open network using {@link WifiConfigurationUtil#createPnoNetwork( - * WifiConfiguration)}. - */ - @Test - public void testCreatePnoNetworkWithOpenNetwork() { - WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork(); - WifiScanner.PnoSettings.PnoNetwork pnoNetwork = - WifiConfigurationUtil.createPnoNetwork(network); - assertEquals(network.SSID, pnoNetwork.ssid); - assertEquals( - WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND - | WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND, pnoNetwork.flags); - assertEquals(WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_OPEN, pnoNetwork.authBitField); - } - - /** - * Verify the instance of {@link android.net.wifi.WifiScanner.PnoSettings.PnoNetwork} created - * for an open hidden network using {@link WifiConfigurationUtil#createPnoNetwork( - * WifiConfiguration)}. - */ - @Test - public void testCreatePnoNetworkWithOpenHiddenNetwork() { - WifiConfiguration network = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - WifiScanner.PnoSettings.PnoNetwork pnoNetwork = - WifiConfigurationUtil.createPnoNetwork(network); - assertEquals(network.SSID, pnoNetwork.ssid); - assertEquals( - WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND - | WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND - | WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN, pnoNetwork.flags); - assertEquals(WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_OPEN, pnoNetwork.authBitField); - } - - /** - * Verify the instance of {@link android.net.wifi.WifiScanner.PnoSettings.PnoNetwork} created - * for a PSK network using {@link WifiConfigurationUtil#createPnoNetwork(WifiConfiguration) - * }. - */ - @Test - public void testCreatePnoNetworkWithPskNetwork() { - WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork(); - WifiScanner.PnoSettings.PnoNetwork pnoNetwork = - WifiConfigurationUtil.createPnoNetwork(network); - assertEquals(network.SSID, pnoNetwork.ssid); - assertEquals( - WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND - | WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND, pnoNetwork.flags); - assertEquals(WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_PSK, pnoNetwork.authBitField); - } - - /** - * Verify that WifiConfigurationUtil.isSameNetwork returns true when two WifiConfiguration - * objects have the same parameters. - */ - @Test - public void testIsSameNetworkReturnsTrueOnSameNetwork() { - WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID); - WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID); - assertTrue(WifiConfigurationUtil.isSameNetwork(network, network1)); - } - - /** - * Verify that WifiConfigurationUtil.isSameNetwork returns true when two WifiConfiguration - * objects have the same parameters but different network selection BSSID's. - */ - @Test - public void testIsSameNetworkReturnsTrueOnSameNetworkWithDifferentBSSID() { - WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID); - network.getNetworkSelectionStatus().setNetworkSelectionBSSID(TEST_BSSID); - WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID); - network1.getNetworkSelectionStatus().setNetworkSelectionBSSID(TEST_BSSID_1); - assertTrue(WifiConfigurationUtil.isSameNetwork(network, network1)); - } - - /** - * Verify that WifiConfigurationUtil.isSameNetwork returns false when two WifiConfiguration - * objects have the different SSIDs. - */ - @Test - public void testIsSameNetworkReturnsFalseOnDifferentSSID() { - WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID); - WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID_1); - assertFalse(WifiConfigurationUtil.isSameNetwork(network, network1)); - } - - /** - * Verify that WifiConfigurationUtil.isSameNetwork returns false when two WifiConfiguration - * objects have the different security type. - */ - @Test - public void testIsSameNetworkReturnsFalseOnDifferentSecurityType() { - WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID); - WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(TEST_SSID); - assertFalse(WifiConfigurationUtil.isSameNetwork(network, network1)); - } - - /** - * Verify that WifiConfigurationUtil.isSameNetwork returns false when two WifiConfiguration - * objects have the different EAP identity. - */ - @Test - public void testIsSameNetworkReturnsFalseOnDifferentEapIdentity() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(TEST_SSID); - WifiConfiguration network2 = WifiConfigurationTestUtil.createEapNetwork(TEST_SSID); - network1.enterpriseConfig.setIdentity("Identity1"); - network2.enterpriseConfig.setIdentity("Identity2"); - assertFalse(WifiConfigurationUtil.isSameNetwork(network1, network2)); - } - - /** - * Verify that WifiConfigurationUtil.isSameNetwork returns false when two WifiConfiguration - * objects have the different EAP anonymous identity. - */ - @Test - public void testIsSameNetworkReturnsFalseOnDifferentEapAnonymousIdentity() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(TEST_SSID); - WifiConfiguration network2 = WifiConfigurationTestUtil.createEapNetwork(TEST_SSID); - network1.enterpriseConfig.setAnonymousIdentity("Identity1"); - network2.enterpriseConfig.setAnonymousIdentity("Identity2"); - assertFalse(WifiConfigurationUtil.isSameNetwork(network1, network2)); - } - - /** - * Verify that WifiConfigurationUtil.isSameNetwork returns true when two WifiConfiguration - * objects have the different EAP anonymous(pseudonym) identity in EAP-SIM. - */ - @Test - public void testIsSameNetworkReturnsTrueOnDifferentEapAnonymousIdentityInEapSim() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(TEST_SSID); - WifiConfiguration network2 = WifiConfigurationTestUtil.createEapNetwork(TEST_SSID); - network1.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); - network2.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); - network1.enterpriseConfig.setAnonymousIdentity("Identity1"); - network2.enterpriseConfig.setAnonymousIdentity("Identity2"); - assertTrue(WifiConfigurationUtil.isSameNetwork(network1, network2)); - } - - /** - * Verify the instance of {@link android.net.wifi.WifiScanner.PnoSettings.PnoNetwork} created - * for a EAP network using {@link WifiConfigurationUtil#createPnoNetwork(WifiConfiguration) - * }. - */ - @Test - public void testCreatePnoNetworkWithEapNetwork() { - WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork(); - WifiScanner.PnoSettings.PnoNetwork pnoNetwork = - WifiConfigurationUtil.createPnoNetwork(network); - assertEquals(network.SSID, pnoNetwork.ssid); - assertEquals( - WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND - | WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND, pnoNetwork.flags); - assertEquals(WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_EAPOL, pnoNetwork.authBitField); - } - - /** - * Verify that the generalized - * {@link com.android.server.wifi.WifiConfigurationUtil.WifiConfigurationComparator} - * can be used to sort a List given a 'compareNetworkWithSameStatus' method. - */ - @Test - public void testPnoListComparator() { - List<WifiConfiguration> networks = new ArrayList<>(); - final WifiConfiguration enabledNetwork1 = WifiConfigurationTestUtil.createEapNetwork(); - enabledNetwork1.getNetworkSelectionStatus().setNetworkSelectionStatus( - WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); - final WifiConfiguration enabledNetwork2 = WifiConfigurationTestUtil.createEapNetwork(); - enabledNetwork2.getNetworkSelectionStatus().setNetworkSelectionStatus( - WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); - final WifiConfiguration tempDisabledNetwork1 = WifiConfigurationTestUtil.createEapNetwork(); - tempDisabledNetwork1.getNetworkSelectionStatus().setNetworkSelectionStatus( - WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - final WifiConfiguration tempDisabledNetwork2 = WifiConfigurationTestUtil.createEapNetwork(); - tempDisabledNetwork2.getNetworkSelectionStatus().setNetworkSelectionStatus( - WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - WifiConfiguration permDisabledNetwork = WifiConfigurationTestUtil.createEapNetwork(); - permDisabledNetwork.getNetworkSelectionStatus().setNetworkSelectionStatus( - WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); - - // Add all the networks to the list. - networks.add(tempDisabledNetwork1); - networks.add(enabledNetwork1); - networks.add(permDisabledNetwork); - networks.add(tempDisabledNetwork2); - networks.add(enabledNetwork2); - - // Prefer |enabledNetwork1| over |enabledNetwork2| and |tempDisabledNetwork1| over - // |tempDisabledNetwork2|. - WifiConfigurationUtil.WifiConfigurationComparator comparator = - new WifiConfigurationUtil.WifiConfigurationComparator() { - @Override - public int compareNetworksWithSameStatus( - WifiConfiguration a, WifiConfiguration b) { - if (a == enabledNetwork1 && b == enabledNetwork2) { - return -1; - } else if (b == enabledNetwork1 && a == enabledNetwork2) { - return 1; - } else if (a == tempDisabledNetwork1 && b == tempDisabledNetwork2) { - return -1; - } else if (b == tempDisabledNetwork1 && a == tempDisabledNetwork2) { - return 1; - } - return 0; - } - }; - Collections.sort(networks, comparator); - - // Now ensure that the networks were sorted correctly. - assertEquals(enabledNetwork1, networks.get(0)); - assertEquals(enabledNetwork2, networks.get(1)); - assertEquals(tempDisabledNetwork1, networks.get(2)); - assertEquals(tempDisabledNetwork2, networks.get(3)); - assertEquals(permDisabledNetwork, networks.get(4)); - } - - /** - * Verifies that when the existing configuration is null and macRandomizationSetting in the - * newConfig is the default value, then hasMacRandomizationSettingsChanged returns false. - */ - @Test - public void testHasMacRandomizationSettingsChangedNullExistingConfigDefaultNewConfig() { - WifiConfiguration newConfig = new WifiConfiguration(); - assertFalse(WifiConfigurationUtil.hasMacRandomizationSettingsChanged(null, newConfig)); - } - - /** - * Verifies that when the existing configuration is null and macRandomizationSetting in the - * newConfig is not the default value, then hasMacRandomizationSettingsChanged returns true. - */ - @Test - public void testHasMacRandomizationSettingsChangedNullExistingConfigModifiedNewConfig() { - WifiConfiguration newConfig = new WifiConfiguration(); - newConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - assertTrue(WifiConfigurationUtil.hasMacRandomizationSettingsChanged(null, newConfig)); - } - - /** - * Verifies that when macRandomizationSetting in the newConfig is different from existingConfig - * hasMacRandomizationSettingsChanged returns true. - */ - @Test - public void testHasMacRandomizationSettingsChangedFieldsDifferent() { - WifiConfiguration existingConfig = new WifiConfiguration(); - WifiConfiguration newConfig = new WifiConfiguration(); - newConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - assertTrue(WifiConfigurationUtil.hasMacRandomizationSettingsChanged( - existingConfig, newConfig)); - } - - /** - * Verifies that when macRandomizationSetting in the newConfig is the same as existingConfig - * hasMacRandomizationSettingsChanged returns false. - */ - @Test - public void testHasMacRandomizationSettingsChangedFieldsSame() { - WifiConfiguration existingConfig = new WifiConfiguration(); - existingConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - WifiConfiguration newConfig = new WifiConfiguration(); - newConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - assertFalse(WifiConfigurationUtil.hasMacRandomizationSettingsChanged( - existingConfig, newConfig)); - } - - private static class EnterpriseConfig { - public String eap; - public String phase2; - public String identity; - public String password; - public X509Certificate[] caCerts; - public WifiEnterpriseConfig enterpriseConfig; - - EnterpriseConfig(int eapMethod) { - enterpriseConfig = new WifiEnterpriseConfig(); - enterpriseConfig.setEapMethod(eapMethod); - eap = WifiEnterpriseConfig.Eap.strings[eapMethod]; - } - - public EnterpriseConfig setPhase2(int phase2Method) { - enterpriseConfig.setPhase2Method(phase2Method); - phase2 = "auth=" + WifiEnterpriseConfig.Phase2.strings[phase2Method]; - return this; - } - - public EnterpriseConfig setIdentity(String identity, String password) { - enterpriseConfig.setIdentity(identity); - enterpriseConfig.setPassword(password); - this.identity = identity; - this.password = password; - return this; - } - - public EnterpriseConfig setCaCerts(X509Certificate[] certs) { - enterpriseConfig.setCaCertificates(certs); - caCerts = certs; - return this; - } - } - - /** - * Verify WifiEnterpriseConfig CA Certificate alias changes are detected. - */ - @Test - public void testCaCertificateAliasChangesDetected() { - EnterpriseConfig eapConfig1 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password"); - eapConfig1.enterpriseConfig.setCaCertificateAlias("ALIAS_1"); - - EnterpriseConfig eapConfig2 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password"); - eapConfig2.enterpriseConfig.setCaCertificateAlias("ALIAS_2"); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig1.enterpriseConfig, - eapConfig2.enterpriseConfig)); - } - - /** - * Verify WifiEnterpriseConfig Client Certificate alias changes are detected. - */ - @Test - public void testClientCertificateAliasChangesDetected() { - EnterpriseConfig eapConfig1 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TLS); - eapConfig1.enterpriseConfig.setCaCertificateAlias("ALIAS_1"); - eapConfig1.enterpriseConfig.setClientCertificateAlias("CLIENT_ALIAS_1"); - - EnterpriseConfig eapConfig2 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS); - eapConfig2.enterpriseConfig.setCaCertificateAlias("ALIAS_1"); - eapConfig2.enterpriseConfig.setClientCertificateAlias("CLIENT_ALIAS_2"); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig1.enterpriseConfig, - eapConfig2.enterpriseConfig)); - } - - /** - * Verify WifiEnterpriseConfig OCSP changes are detected. - */ - @Test - public void testOcspChangesDetected() { - EnterpriseConfig eapConfig1 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0}); - eapConfig1.enterpriseConfig.setOcsp(OCSP_NONE); - - EnterpriseConfig eapConfig2 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0}); - eapConfig2.enterpriseConfig.setOcsp(OCSP_REQUIRE_CERT_STATUS); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig1.enterpriseConfig, - eapConfig2.enterpriseConfig)); - } - - /** - * Verify WifiEnterpriseConfig subject match changes are detected. - */ - @Test - public void testSubjectMatchChangesDetected() { - EnterpriseConfig eapConfig1 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0}); - eapConfig1.enterpriseConfig.setAltSubjectMatch("domain1.com"); - - EnterpriseConfig eapConfig2 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS) - .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2) - .setIdentity("username", "password") - .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0}); - eapConfig1.enterpriseConfig.setAltSubjectMatch("domain2.com"); - - assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig1.enterpriseConfig, - eapConfig2.enterpriseConfig)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java deleted file mode 100644 index bd74f51bc..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static android.net.wifi.WifiManager.WIFI_FEATURE_CONTROL_ROAMING; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; - -import androidx.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; - -/** - * Unit tests for {@link com.android.server.wifi.WifiConnectivityHelper}. - */ -@SmallTest -public class WifiConnectivityHelperTest extends WifiBaseTest { - /** Sets up test. */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - setupWifiNative(); - - mWifiConnectivityHelper = new WifiConnectivityHelper(mWifiNative); - } - - /** Cleans up test. */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - private WifiConnectivityHelper mWifiConnectivityHelper; - @Mock private WifiNative mWifiNative; - @Captor ArgumentCaptor<WifiNative.RoamingConfig> mRoamingConfigCaptor; - private int mFeatureSetValue; - private static final String TAG = "WifiConnectivityHelperTest"; - private static final int MAX_BSSID_BLACKLIST_SIZE = 16; - private static final int MAX_SSID_WHITELIST_SIZE = 8; - - private void setupWifiNative() { - // Return firmware roaming feature as supported by default. - when(mWifiNative.getSupportedFeatureSet(any())) - .thenReturn((long) WIFI_FEATURE_CONTROL_ROAMING); - - doAnswer(new AnswerWithArguments() { - public boolean answer(String ifaceName, WifiNative.RoamingCapabilities roamCap) - throws Exception { - roamCap.maxBlacklistSize = MAX_BSSID_BLACKLIST_SIZE; - roamCap.maxWhitelistSize = MAX_SSID_WHITELIST_SIZE; - return true; - }}).when(mWifiNative).getRoamingCapabilities(any(), anyObject()); - - when(mWifiNative.configureRoaming(any(), anyObject())).thenReturn(true); - } - - private ArrayList<String> buildBssidBlacklist(int size) { - ArrayList<String> bssidBlacklist = new ArrayList<String>(); - - for (int i = 0; i < size; i++) { - StringBuilder bssid = new StringBuilder("11:22:33:44:55:66"); - bssid.setCharAt(16, (char) ('0' + i)); - bssidBlacklist.add(bssid.toString()); - } - - return bssidBlacklist; - } - - private ArrayList<String> buildSsidWhitelist(int size) { - ArrayList<String> ssidWhitelist = new ArrayList<String>(); - - for (int i = 0; i < size; i++) { - StringBuilder ssid = new StringBuilder("\"Test_Ap_0\""); - ssid.setCharAt(9, (char) ('0' + i)); - ssidWhitelist.add(ssid.toString()); - } - - return ssidWhitelist; - } - - /** - * When WifiNative has WIFI_FEATURE_CONTROL_ROAMING set, verify that - * WifiConnectivityHelper#isFirmwareRoamingSupported returns true. - */ - @Test - public void returnFirmwareRoamingSupported() { - //By default WifiNative has WIFI_FEATURE_CONTROL_ROAMING set in its feature set. - assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - assertTrue(mWifiConnectivityHelper.isFirmwareRoamingSupported()); - } - - /** - * When WifiNative doesn't have WIFI_FEATURE_CONTROL_ROAMING set, verify that - * WifiConnectivityHelper#isFirmwareRoamingSupported returns false. - */ - @Test - public void returnFirmwareRoamingNotSupported() { - when(mWifiNative.getSupportedFeatureSet(any())) - .thenReturn((long) ~WIFI_FEATURE_CONTROL_ROAMING); - assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - assertFalse(mWifiConnectivityHelper.isFirmwareRoamingSupported()); - } - - /** - * Verify that correct firmware roaming capability values are returned if querying - * WifiNative for roaming capability succeeded. - */ - @Test - public void verifyFirmwareRoamingCapabilityWithSuccessfulNativeCall() { - assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - assertTrue(mWifiConnectivityHelper.isFirmwareRoamingSupported()); - assertEquals(MAX_BSSID_BLACKLIST_SIZE, mWifiConnectivityHelper.getMaxNumBlacklistBssid()); - assertEquals(MAX_SSID_WHITELIST_SIZE, mWifiConnectivityHelper.getMaxNumWhitelistSsid()); - } - - /** - * Verify that firmware roaming is set to not supported if WifiNative returned firmware roaming - * is supported but failed to return roaming capabilities. Firmware roaming capabilty values - * should be reset to INVALID_LIST_SIZE. - */ - @Test - public void verifyFirmwareRoamingCapabilityWithFailureNativeCall() { - doAnswer(new AnswerWithArguments() { - public boolean answer(String ifaceName, WifiNative.RoamingCapabilities roamCap) - throws Exception { - return false; - }}).when(mWifiNative).getRoamingCapabilities(any(), anyObject()); - assertFalse(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - assertFalse(mWifiConnectivityHelper.isFirmwareRoamingSupported()); - assertEquals(WifiConnectivityHelper.INVALID_LIST_SIZE, - mWifiConnectivityHelper.getMaxNumBlacklistBssid()); - assertEquals(WifiConnectivityHelper.INVALID_LIST_SIZE, - mWifiConnectivityHelper.getMaxNumWhitelistSsid()); - } - - /** - * Verify that firmware roaming is set to not supported if WifiNative returned firmware roaming - * is supported but returned invalid max BSSID balcklist size. Firmware roaming capabilty values - * should be reset to INVALID_LIST_SIZE. - */ - @Test - public void verifyFirmwareRoamingCapabilityWithInvalidMaxBssidBlacklistSize() { - doAnswer(new AnswerWithArguments() { - public boolean answer(String ifaceName, WifiNative.RoamingCapabilities roamCap) - throws Exception { - roamCap.maxBlacklistSize = -5; - roamCap.maxWhitelistSize = MAX_SSID_WHITELIST_SIZE; - return true; - }}).when(mWifiNative).getRoamingCapabilities(any(), anyObject()); - assertFalse(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - assertFalse(mWifiConnectivityHelper.isFirmwareRoamingSupported()); - assertEquals(WifiConnectivityHelper.INVALID_LIST_SIZE, - mWifiConnectivityHelper.getMaxNumBlacklistBssid()); - assertEquals(WifiConnectivityHelper.INVALID_LIST_SIZE, - mWifiConnectivityHelper.getMaxNumWhitelistSsid()); - } - - /** - * Verify that firmware roaming is set to not supported if WifiNative returned firmware roaming - * is supported but returned invalid max SSID whitelist size. Firmware roaming capabilty values - * should be reset to INVALID_LIST_SIZE. - */ - @Test - public void verifyFirmwareRoamingCapabilityWithInvalidMaxSsidWhitelistSize() { - doAnswer(new AnswerWithArguments() { - public boolean answer(String ifaceName, WifiNative.RoamingCapabilities roamCap) - throws Exception { - roamCap.maxBlacklistSize = MAX_BSSID_BLACKLIST_SIZE; - roamCap.maxWhitelistSize = -2; - return true; - }}).when(mWifiNative).getRoamingCapabilities(any(), anyObject()); - assertFalse(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - assertFalse(mWifiConnectivityHelper.isFirmwareRoamingSupported()); - assertEquals(WifiConnectivityHelper.INVALID_LIST_SIZE, - mWifiConnectivityHelper.getMaxNumBlacklistBssid()); - assertEquals(WifiConnectivityHelper.INVALID_LIST_SIZE, - mWifiConnectivityHelper.getMaxNumWhitelistSsid()); - } - - /** - * Verify that correct size BSSID blacklist and SSID whitelist are accepted. - */ - @Test - public void verifySetFirmwareRoamingConfigurationWithGoodInput() { - assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - ArrayList<String> blacklist = buildBssidBlacklist(MAX_BSSID_BLACKLIST_SIZE); - ArrayList<String> whitelist = buildSsidWhitelist(MAX_SSID_WHITELIST_SIZE); - assertTrue(mWifiConnectivityHelper.setFirmwareRoamingConfiguration(blacklist, whitelist)); - - blacklist = buildBssidBlacklist(MAX_BSSID_BLACKLIST_SIZE - 2); - whitelist = buildSsidWhitelist(MAX_SSID_WHITELIST_SIZE - 3); - assertTrue(mWifiConnectivityHelper.setFirmwareRoamingConfiguration(blacklist, whitelist)); - } - - /** - * Verify that null BSSID blacklist or SSID whitelist is rejected. - */ - @Test - public void verifySetFirmwareRoamingConfigurationWithNullInput() { - assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - ArrayList<String> blacklist = buildBssidBlacklist(MAX_BSSID_BLACKLIST_SIZE); - ArrayList<String> whitelist = buildSsidWhitelist(MAX_SSID_WHITELIST_SIZE); - assertFalse(mWifiConnectivityHelper.setFirmwareRoamingConfiguration(null, whitelist)); - assertFalse(mWifiConnectivityHelper.setFirmwareRoamingConfiguration(blacklist, null)); - } - - /** - * Verify that incorrect size BSSID blacklist is rejected. - */ - @Test - public void verifySetFirmwareRoamingConfigurationWithIncorrectBlacklist() { - assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - ArrayList<String> blacklist = buildBssidBlacklist(MAX_BSSID_BLACKLIST_SIZE + 1); - ArrayList<String> whitelist = buildSsidWhitelist(MAX_SSID_WHITELIST_SIZE); - assertFalse(mWifiConnectivityHelper.setFirmwareRoamingConfiguration(blacklist, whitelist)); - } - - /** - * Verify that incorrect size SSID whitelist is rejected. - */ - @Test - public void verifySetFirmwareRoamingConfigurationWithIncorrectWhitelist() { - assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - ArrayList<String> blacklist = buildBssidBlacklist(MAX_BSSID_BLACKLIST_SIZE); - ArrayList<String> whitelist = buildSsidWhitelist(MAX_SSID_WHITELIST_SIZE + 1); - assertFalse(mWifiConnectivityHelper.setFirmwareRoamingConfiguration(blacklist, whitelist)); - } - - /** - * Verify that empty BSSID blacklist and SSID whitelist are sent to WifiNative - * to reset the firmware roaming configuration. - */ - @Test - public void verifySetFirmwareRoamingConfigurationWithEmptyBlacklistAndWhitelist() { - assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); - ArrayList<String> blacklist = buildBssidBlacklist(0); - ArrayList<String> whitelist = buildSsidWhitelist(0); - assertTrue(mWifiConnectivityHelper.setFirmwareRoamingConfiguration(blacklist, whitelist)); - verify(mWifiNative).configureRoaming(any(), mRoamingConfigCaptor.capture()); - assertEquals(0, mRoamingConfigCaptor.getValue().blacklistBssids.size()); - assertEquals(0, mRoamingConfigCaptor.getValue().whitelistSsids.size()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java deleted file mode 100644 index 38d2e8275..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java +++ /dev/null @@ -1,3246 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE; -import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.argThat; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.app.test.TestAlarmManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.MacAddress; -import android.net.NetworkScoreManager; -import android.net.wifi.ScanResult; -import android.net.wifi.ScanResult.InformationElement; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.PnoScanListener; -import android.net.wifi.WifiScanner.PnoSettings; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiScanner.ScanListener; -import android.net.wifi.WifiScanner.ScanSettings; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.Handler; -import android.os.Process; -import android.os.SystemClock; -import android.os.WorkSource; -import android.os.test.TestLooper; -import android.util.LocalLog; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.util.LruConnectionTracker; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.Captor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.stream.Collectors; - -/** - * Unit tests for {@link com.android.server.wifi.WifiConnectivityManager}. - */ -@SmallTest -public class WifiConnectivityManagerTest extends WifiBaseTest { - /** - * Called before each test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mResources = new MockResources(); - setUpResources(mResources); - mAlarmManager = new TestAlarmManager(); - mContext = mockContext(); - mLocalLog = new LocalLog(512); - mClientModeImpl = mockClientModeImpl(); - mWifiConfigManager = mockWifiConfigManager(); - mWifiInfo = getWifiInfo(); - mScanData = mockScanData(); - mWifiScanner = mockWifiScanner(); - mWifiConnectivityHelper = mockWifiConnectivityHelper(); - mWifiNS = mockWifiNetworkSelector(); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); - when(mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList()) - .thenReturn(new ArrayList<>()); - when(mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()) - .thenReturn(new HashSet<>()); - when(mWifiInjector.getBssidBlocklistMonitor()).thenReturn(mBssidBlocklistMonitor); - when(mWifiInjector.getWifiChannelUtilizationScan()).thenReturn(mWifiChannelUtilization); - when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard); - when(mWifiInjector.getWifiNetworkSuggestionsManager()) - .thenReturn(mWifiNetworkSuggestionsManager); - when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager); - when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) - .thenReturn(new ArrayList<>()); - mWifiConnectivityManager = createConnectivityManager(); - verify(mWifiConfigManager).addOnNetworkUpdateListener( - mNetworkUpdateListenerCaptor.capture()); - verify(mWifiNetworkSuggestionsManager).addOnSuggestionUpdateListener( - mSuggestionUpdateListenerCaptor.capture()); - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - mWifiConnectivityManager.setWifiEnabled(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); - mMinPacketRateActiveTraffic = mResources.getInteger( - R.integer.config_wifiFrameworkMinPacketPerSecondActiveTraffic); - when(mWifiLastResortWatchdog.shouldIgnoreBssidUpdate(anyString())).thenReturn(false); - mLruConnectionTracker = new LruConnectionTracker(100, mContext); - Comparator<WifiConfiguration> comparator = - Comparator.comparingInt(mLruConnectionTracker::getAgeIndexOfNetwork); - when(mWifiConfigManager.getScanListComparator()).thenReturn(comparator); - } - - private void setUpResources(MockResources resources) { - resources.setBoolean( - R.bool.config_wifi_framework_enable_associated_network_selection, true); - resources.setInteger( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz, -60); - resources.setInteger( - R.integer.config_wifiFrameworkMinPacketPerSecondActiveTraffic, 16); - resources.setIntArray( - R.array.config_wifiConnectedScanIntervalScheduleSec, - VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC); - resources.setIntArray( - R.array.config_wifiDisconnectedScanIntervalScheduleSec, - VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE_SEC); - resources.setIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, - SCHEDULE_EMPTY_SEC); - resources.setInteger( - R.integer.config_wifiHighMovementNetworkSelectionOptimizationScanDelayMs, - HIGH_MVMT_SCAN_DELAY_MS); - resources.setInteger( - R.integer.config_wifiHighMovementNetworkSelectionOptimizationRssiDelta, - HIGH_MVMT_RSSI_DELTA); - resources.setInteger(R.integer.config_wifiInitialPartialScanChannelCacheAgeMins, - CHANNEL_CACHE_AGE_MINS); - resources.setInteger(R.integer.config_wifiMovingPnoScanIntervalMillis, - MOVING_PNO_SCAN_INTERVAL_MILLIS); - resources.setInteger(R.integer.config_wifiStationaryPnoScanIntervalMillis, - STATIONARY_PNO_SCAN_INTERVAL_MILLIS); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - verify(mScoringParams, atLeast(0)).getEntryRssi(anyInt()); - verifyNoMoreInteractions(mScoringParams); - validateMockitoUsage(); - } - - private Context mContext; - private TestAlarmManager mAlarmManager; - private TestLooper mLooper = new TestLooper(); - private WifiConnectivityManager mWifiConnectivityManager; - private WifiNetworkSelector mWifiNS; - private ClientModeImpl mClientModeImpl; - private WifiScanner mWifiScanner; - private WifiConnectivityHelper mWifiConnectivityHelper; - private ScanData mScanData; - private WifiConfigManager mWifiConfigManager; - private WifiInfo mWifiInfo; - private LocalLog mLocalLog; - private LruConnectionTracker mLruConnectionTracker; - @Mock private WifiInjector mWifiInjector; - @Mock private NetworkScoreManager mNetworkScoreManager; - @Mock private Clock mClock; - @Mock private WifiLastResortWatchdog mWifiLastResortWatchdog; - @Mock private OpenNetworkNotifier mOpenNetworkNotifier; - @Mock private WifiMetrics mWifiMetrics; - @Mock private WifiNetworkScoreCache mScoreCache; - @Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - @Mock private BssidBlocklistMonitor mBssidBlocklistMonitor; - @Mock private WifiChannelUtilization mWifiChannelUtilization; - @Mock private ScoringParams mScoringParams; - @Mock private WifiScoreCard mWifiScoreCard; - @Mock private PasspointManager mPasspointManager; - @Mock private WifiScoreCard.PerNetwork mPerNetwork; - @Mock private WifiScoreCard.PerNetwork mPerNetwork1; - @Mock private PasspointConfiguration mPasspointConfiguration; - @Mock private WifiConfiguration mSuggestionConfig; - @Mock private WifiNetworkSuggestion mWifiNetworkSuggestion; - @Mock WifiCandidates.Candidate mCandidate1; - @Mock WifiCandidates.Candidate mCandidate2; - private List<WifiCandidates.Candidate> mCandidateList; - @Captor ArgumentCaptor<ScanResult> mCandidateScanResultCaptor; - @Captor ArgumentCaptor<ArrayList<String>> mBssidBlacklistCaptor; - @Captor ArgumentCaptor<ArrayList<String>> mSsidWhitelistCaptor; - @Captor ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener> - mNetworkUpdateListenerCaptor; - @Captor ArgumentCaptor<WifiNetworkSuggestionsManager.OnSuggestionUpdateListener> - mSuggestionUpdateListenerCaptor; - private MockResources mResources; - private int mMinPacketRateActiveTraffic; - - private static final int CANDIDATE_NETWORK_ID = 0; - private static final String CANDIDATE_SSID = "\"AnSsid\""; - private static final String CANDIDATE_BSSID = "6c:f3:7f:ae:8c:f3"; - private static final String CANDIDATE_BSSID_2 = "6c:f3:7f:ae:8d:f3"; - private static final String INVALID_SCAN_RESULT_BSSID = "6c:f3:7f:ae:8c:f4"; - private static final int TEST_FREQUENCY = 2420; - private static final long CURRENT_SYSTEM_TIME_MS = 1000; - private static final int MAX_BSSID_BLACKLIST_SIZE = 16; - private static final int[] VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC = {10, 30, 50}; - private static final int[] VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC = {15, 35, 55}; - private static final int[] VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE_SEC = {25, 40, 60}; - private static final int[] SCHEDULE_EMPTY_SEC = {}; - private static final int[] INVALID_SCHEDULE_NEGATIVE_VALUES_SEC = {10, -10, 20}; - private static final int[] INVALID_SCHEDULE_ZERO_VALUES_SEC = {10, 0, 20}; - private static final int MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC = 60; - private static final int[] DEFAULT_SINGLE_SCAN_SCHEDULE_SEC = {20, 40, 80, 160}; - private static final int MAX_SCAN_INTERVAL_IN_DEFAULT_SCHEDULE_SEC = 160; - private static final int TEST_FREQUENCY_1 = 2412; - private static final int TEST_FREQUENCY_2 = 5180; - private static final int TEST_FREQUENCY_3 = 5240; - private static final int TEST_CURRENT_CONNECTED_FREQUENCY = 2427; - private static final int HIGH_MVMT_SCAN_DELAY_MS = 10000; - private static final int HIGH_MVMT_RSSI_DELTA = 10; - private static final String TEST_FQDN = "FQDN"; - private static final String TEST_SSID = "SSID"; - private static final int TEMP_BSSID_BLOCK_DURATION_MS = 10 * 1000; // 10 seconds - private static final int TEST_CONNECTED_NETWORK_ID = 55; - private static final int CHANNEL_CACHE_AGE_MINS = 14400; - private static final int MOVING_PNO_SCAN_INTERVAL_MILLIS = 20_000; - private static final int STATIONARY_PNO_SCAN_INTERVAL_MILLIS = 60_000; - - Context mockContext() { - Context context = mock(Context.class); - - when(context.getResources()).thenReturn(mResources); - when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn( - mAlarmManager.getAlarmManager()); - when(context.getPackageManager()).thenReturn(mock(PackageManager.class)); - - return context; - } - - ScanData mockScanData() { - ScanData scanData = mock(ScanData.class); - - when(scanData.getBandScanned()).thenReturn(WifiScanner.WIFI_BAND_ALL); - - return scanData; - } - - WifiScanner mockWifiScanner() { - WifiScanner scanner = mock(WifiScanner.class); - ArgumentCaptor<ScanListener> allSingleScanListenerCaptor = - ArgumentCaptor.forClass(ScanListener.class); - - doNothing().when(scanner).registerScanListener( - any(), allSingleScanListenerCaptor.capture()); - - ScanData[] scanDatas = new ScanData[1]; - scanDatas[0] = mScanData; - - // do a synchronous answer for the ScanListener callbacks - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, ScanListener listener, - WorkSource workSource) throws Exception { - listener.onResults(scanDatas); - }}).when(scanner).startBackgroundScan(anyObject(), anyObject(), anyObject()); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - listener.onResults(scanDatas); - // WCM processes scan results received via onFullResult (even though they're the - // same as onResult for single scans). - if (mScanData != null && mScanData.getResults() != null) { - for (int i = 0; i < mScanData.getResults().length; i++) { - allSingleScanListenerCaptor.getValue().onFullResult( - mScanData.getResults()[i]); - } - } - allSingleScanListenerCaptor.getValue().onResults(scanDatas); - }}).when(scanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - - // This unfortunately needs to be a somewhat valid scan result, otherwise - // |ScanDetailUtil.toScanDetail| raises exceptions. - final ScanResult[] scanResults = new ScanResult[1]; - scanResults[0] = new ScanResult(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID), - CANDIDATE_SSID, CANDIDATE_BSSID, 1245, 0, "some caps", - -78, 2450, 1025, 22, 33, 20, 0, 0, true); - scanResults[0].informationElements = new InformationElement[1]; - scanResults[0].informationElements[0] = new InformationElement(); - scanResults[0].informationElements[0].id = InformationElement.EID_SSID; - scanResults[0].informationElements[0].bytes = - CANDIDATE_SSID.getBytes(StandardCharsets.UTF_8); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, PnoSettings pnoSettings, - Executor executor, PnoScanListener listener) throws Exception { - listener.onPnoNetworkFound(scanResults); - }}).when(scanner).startDisconnectedPnoScan( - anyObject(), anyObject(), anyObject(), anyObject()); - - return scanner; - } - - WifiConnectivityHelper mockWifiConnectivityHelper() { - WifiConnectivityHelper connectivityHelper = mock(WifiConnectivityHelper.class); - - when(connectivityHelper.isFirmwareRoamingSupported()).thenReturn(false); - when(connectivityHelper.getMaxNumBlacklistBssid()).thenReturn(MAX_BSSID_BLACKLIST_SIZE); - - return connectivityHelper; - } - - ClientModeImpl mockClientModeImpl() { - ClientModeImpl stateMachine = mock(ClientModeImpl.class); - - when(stateMachine.isConnected()).thenReturn(false); - when(stateMachine.isDisconnected()).thenReturn(true); - when(stateMachine.isSupplicantTransientState()).thenReturn(false); - - return stateMachine; - } - - WifiNetworkSelector mockWifiNetworkSelector() { - WifiNetworkSelector ns = mock(WifiNetworkSelector.class); - - WifiConfiguration candidate = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - candidate.BSSID = ClientModeImpl.SUPPLICANT_BSSID_ANY; - ScanResult candidateScanResult = new ScanResult(); - candidateScanResult.SSID = CANDIDATE_SSID; - candidateScanResult.BSSID = CANDIDATE_BSSID; - candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - - when(mWifiConfigManager.getConfiguredNetwork(CANDIDATE_NETWORK_ID)).thenReturn(candidate); - MacAddress macAddress = MacAddress.fromString(CANDIDATE_BSSID); - WifiCandidates.Key key = new WifiCandidates.Key(mock(ScanResultMatchInfo.class), - macAddress, 0); - when(mCandidate1.getKey()).thenReturn(key); - when(mCandidate1.getScanRssi()).thenReturn(-40); - when(mCandidate1.getFrequency()).thenReturn(TEST_FREQUENCY); - when(mCandidate2.getKey()).thenReturn(key); - when(mCandidate2.getScanRssi()).thenReturn(-60); - mCandidateList = new ArrayList<WifiCandidates.Candidate>(); - mCandidateList.add(mCandidate1); - when(ns.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean())).thenReturn(mCandidateList); - when(ns.selectNetwork(any())) - .then(new AnswerWithArguments() { - public WifiConfiguration answer(List<WifiCandidates.Candidate> candidateList) { - if (candidateList == null || candidateList.size() == 0) { - return null; - } - return candidate; - } - }); - return ns; - } - - WifiInfo getWifiInfo() { - WifiInfo wifiInfo = new WifiInfo(); - - wifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); - wifiInfo.setBSSID(null); - wifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); - - return wifiInfo; - } - - WifiConfigManager mockWifiConfigManager() { - WifiConfigManager wifiConfigManager = mock(WifiConfigManager.class); - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - List<WifiConfiguration> networkList = new ArrayList<>(); - networkList.add(config); - when(wifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null); - when(wifiConfigManager.getSavedNetworks(anyInt())).thenReturn(networkList); - - return wifiConfigManager; - } - - WifiConnectivityManager createConnectivityManager() { - return new WifiConnectivityManager(mContext, - mScoringParams, - mClientModeImpl, mWifiInjector, mWifiConfigManager, mWifiNetworkSuggestionsManager, - mWifiInfo, mWifiNS, mWifiConnectivityHelper, - mWifiLastResortWatchdog, mOpenNetworkNotifier, - mWifiMetrics, new Handler(mLooper.getLooper()), mClock, - mLocalLog, mWifiScoreCard); - } - - void setWifiStateConnected() { - // Prep for setting WiFi to connected state - WifiConfiguration connectedWifiConfiguration = new WifiConfiguration(); - connectedWifiConfiguration.networkId = TEST_CONNECTED_NETWORK_ID; - when(mClientModeImpl.getCurrentWifiConfiguration()).thenReturn(connectedWifiConfiguration); - - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - } - - /** - * Wifi enters disconnected state while screen is on. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the - * expected candidate network ID and BSSID. - */ - @Test - public void enterWifiDisconnectedStateWhenScreenOn() { - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to disconnected state - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Wifi enters connected state while screen is on. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the - * expected candidate network ID and BSSID. - */ - @Test - public void enterWifiConnectedStateWhenScreenOn() { - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to connected state - setWifiStateConnected(); - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Screen turned on while WiFi in disconnected state. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the - * expected candidate network ID and BSSID. - */ - @Test - public void turnScreenOnWhenWifiInDisconnectedState() { - // Set WiFi to disconnected state - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - verify(mClientModeImpl, atLeastOnce()).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Screen turned on while WiFi in connected state. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the - * expected candidate network ID and BSSID. - */ - @Test - public void turnScreenOnWhenWifiInConnectedState() { - // Set WiFi to connected state - setWifiStateConnected(); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - verify(mClientModeImpl, atLeastOnce()).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Screen turned on while WiFi in connected state but - * auto roaming is disabled. - * - * Expected behavior: WifiConnectivityManager doesn't invoke - * ClientModeImpl.startConnectToNetwork() because roaming - * is turned off. - */ - @Test - public void turnScreenOnWhenWifiInConnectedStateRoamingDisabled() { - // Turn off auto roaming - mResources.setBoolean( - R.bool.config_wifi_framework_enable_associated_network_selection, false); - mWifiConnectivityManager = createConnectivityManager(); - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - - // Set WiFi to connected state - setWifiStateConnected(); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - verify(mClientModeImpl, times(0)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Multiple back to back connection attempts within the rate interval should be rate limited. - * - * Expected behavior: WifiConnectivityManager calls ClientModeImpl.startConnectToNetwork() - * with the expected candidate network ID and BSSID for only the expected number of times within - * the given interval. - */ - @Test - public void connectionAttemptRateLimitedWhenScreenOff() { - int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; - int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; - int numAttempts = 0; - int connectionAttemptIntervals = timeInterval / maxAttemptRate; - - mWifiConnectivityManager.handleScreenStateChanged(false); - - // First attempt the max rate number of connections within the rate interval. - long currentTimeStamp = 0; - for (int attempt = 0; attempt < maxAttemptRate; attempt++) { - currentTimeStamp += connectionAttemptIntervals; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - numAttempts++; - } - // Now trigger another connection attempt before the rate interval, this should be - // skipped because we've crossed rate limit. - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Verify that we attempt to connect upto the rate. - verify(mClientModeImpl, times(numAttempts)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Multiple back to back connection attempts outside the rate interval should not be rate - * limited. - * - * Expected behavior: WifiConnectivityManager calls ClientModeImpl.startConnectToNetwork() - * with the expected candidate network ID and BSSID for only the expected number of times within - * the given interval. - */ - @Test - public void connectionAttemptNotRateLimitedWhenScreenOff() { - int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; - int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; - int numAttempts = 0; - int connectionAttemptIntervals = timeInterval / maxAttemptRate; - - mWifiConnectivityManager.handleScreenStateChanged(false); - - // First attempt the max rate number of connections within the rate interval. - long currentTimeStamp = 0; - for (int attempt = 0; attempt < maxAttemptRate; attempt++) { - currentTimeStamp += connectionAttemptIntervals; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - numAttempts++; - } - // Now trigger another connection attempt after the rate interval, this should not be - // skipped because we should've evicted the older attempt. - when(mClock.getElapsedSinceBootMillis()).thenReturn( - currentTimeStamp + connectionAttemptIntervals * 2); - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - numAttempts++; - - // Verify that all the connection attempts went through - verify(mClientModeImpl, times(numAttempts)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Multiple back to back connection attempts after a force connectivity scan should not be rate - * limited. - * - * Expected behavior: WifiConnectivityManager calls ClientModeImpl.startConnectToNetwork() - * with the expected candidate network ID and BSSID for only the expected number of times within - * the given interval. - */ - @Test - public void connectionAttemptNotRateLimitedWhenScreenOffForceConnectivityScan() { - int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; - int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; - int numAttempts = 0; - int connectionAttemptIntervals = timeInterval / maxAttemptRate; - - mWifiConnectivityManager.handleScreenStateChanged(false); - - // First attempt the max rate number of connections within the rate interval. - long currentTimeStamp = 0; - for (int attempt = 0; attempt < maxAttemptRate; attempt++) { - currentTimeStamp += connectionAttemptIntervals; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - numAttempts++; - } - - mWifiConnectivityManager.forceConnectivityScan(new WorkSource()); - - for (int attempt = 0; attempt < maxAttemptRate; attempt++) { - currentTimeStamp += connectionAttemptIntervals; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - numAttempts++; - } - - // Verify that all the connection attempts went through - verify(mClientModeImpl, times(numAttempts)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Multiple back to back connection attempts after a user selection should not be rate limited. - * - * Expected behavior: WifiConnectivityManager calls ClientModeImpl.startConnectToNetwork() - * with the expected candidate network ID and BSSID for only the expected number of times within - * the given interval. - */ - @Test - public void connectionAttemptNotRateLimitedWhenScreenOffAfterUserSelection() { - int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; - int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; - int numAttempts = 0; - int connectionAttemptIntervals = timeInterval / maxAttemptRate; - - mWifiConnectivityManager.handleScreenStateChanged(false); - - // First attempt the max rate number of connections within the rate interval. - long currentTimeStamp = 0; - for (int attempt = 0; attempt < maxAttemptRate; attempt++) { - currentTimeStamp += connectionAttemptIntervals; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - numAttempts++; - } - - mWifiConnectivityManager.setUserConnectChoice(CANDIDATE_NETWORK_ID); - mWifiConnectivityManager.prepareForForcedConnection(CANDIDATE_NETWORK_ID); - - for (int attempt = 0; attempt < maxAttemptRate; attempt++) { - currentTimeStamp += connectionAttemptIntervals; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - numAttempts++; - } - - // Verify that all the connection attempts went through - verify(mClientModeImpl, times(numAttempts)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * PNO retry for low RSSI networks. - * - * Expected behavior: WifiConnectivityManager doubles the low RSSI - * network retry delay value after QNS skips the PNO scan results - * because of their low RSSI values. - */ - @Test - public void pnoRetryForLowRssiNetwork() { - when(mWifiNS.selectNetwork(any())).thenReturn(null); - - // Set screen to off - mWifiConnectivityManager.handleScreenStateChanged(false); - - // Get the current retry delay value - int lowRssiNetworkRetryDelayStartValue = mWifiConnectivityManager - .getLowRssiNetworkRetryDelay(); - - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Get the retry delay value after QNS didn't select a - // network candicate from the PNO scan results. - int lowRssiNetworkRetryDelayAfterPnoValue = mWifiConnectivityManager - .getLowRssiNetworkRetryDelay(); - - assertEquals(lowRssiNetworkRetryDelayStartValue * 2, - lowRssiNetworkRetryDelayAfterPnoValue); - } - - /** - * Ensure that the watchdog bite increments the "Pno bad" metric. - * - * Expected behavior: WifiConnectivityManager detects that the PNO scan failed to find - * a candidate while watchdog single scan did. - */ - @Test - public void watchdogBitePnoBadIncrementsMetrics() { - // Set screen to off - mWifiConnectivityManager.handleScreenStateChanged(false); - - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Now fire the watchdog alarm and verify the metrics were incremented. - mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG); - mLooper.dispatchAll(); - - verify(mWifiMetrics).incrementNumConnectivityWatchdogPnoBad(); - verify(mWifiMetrics, never()).incrementNumConnectivityWatchdogPnoGood(); - } - - /** - * Ensure that the watchdog bite increments the "Pno good" metric. - * - * Expected behavior: WifiConnectivityManager detects that the PNO scan failed to find - * a candidate which was the same with watchdog single scan. - */ - @Test - public void watchdogBitePnoGoodIncrementsMetrics() { - // Qns returns no candidate after watchdog single scan. - when(mWifiNS.selectNetwork(any())).thenReturn(null); - - // Set screen to off - mWifiConnectivityManager.handleScreenStateChanged(false); - - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Now fire the watchdog alarm and verify the metrics were incremented. - mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG); - mLooper.dispatchAll(); - - verify(mWifiMetrics).incrementNumConnectivityWatchdogPnoGood(); - verify(mWifiMetrics, never()).incrementNumConnectivityWatchdogPnoBad(); - } - - /** - * Verify that 2 scans that are sufficiently far apart are required to initiate a connection - * when the high mobility scanning optimization is enabled. - */ - @Test - public void testHighMovementNetworkSelection() { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - // Enable high movement optimization - mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled, - true); - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - - // Set WiFi to disconnected state to trigger scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mLooper.dispatchAll(); - - // Verify there is no connection due to currently having no cached candidates. - verify(mClientModeImpl, never()).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - - // Move time forward but do not cross HIGH_MVMT_SCAN_DELAY_MS yet. - when(mClock.getElapsedSinceBootMillis()).thenReturn(HIGH_MVMT_SCAN_DELAY_MS - 1L); - // Set WiFi to disconnected state to trigger scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mLooper.dispatchAll(); - - // Verify we still don't connect because not enough time have passed since the candidates - // were cached. - verify(mClientModeImpl, never()).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - - // Move time past HIGH_MVMT_SCAN_DELAY_MS. - when(mClock.getElapsedSinceBootMillis()).thenReturn((long) HIGH_MVMT_SCAN_DELAY_MS); - // Set WiFi to disconnected state to trigger scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mLooper.dispatchAll(); - - // Verify a candidate if found this time. - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - verify(mWifiMetrics, times(2)).incrementNumHighMovementConnectionSkipped(); - verify(mWifiMetrics).incrementNumHighMovementConnectionStarted(); - } - - /** - * Verify that the device is initiating partial scans to verify AP stability in the high - * movement mobility state. - */ - @Test - public void testHighMovementTriggerPartialScan() { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - // Enable high movement optimization - mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled, - true); - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - - // Set WiFi to disconnected state to trigger scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mLooper.dispatchAll(); - // Verify there is no connection due to currently having no cached candidates. - verify(mClientModeImpl, never()).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - - // Move time forward and verify that a delayed partial scan is scheduled. - when(mClock.getElapsedSinceBootMillis()).thenReturn(HIGH_MVMT_SCAN_DELAY_MS + 1L); - mAlarmManager.dispatch(WifiConnectivityManager.DELAYED_PARTIAL_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - - verify(mWifiScanner).startScan((ScanSettings) argThat(new WifiPartialScanSettingMatcher()), - any(), any(), any()); - } - - private class WifiPartialScanSettingMatcher implements ArgumentMatcher<ScanSettings> { - @Override - public boolean matches(ScanSettings scanSettings) { - return scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED - && scanSettings.channels[0].frequency == TEST_FREQUENCY; - } - } - - /** - * Verify that when there are we obtain more than one valid candidates from scan results and - * network connection fails, connection is immediately retried on the remaining candidates. - */ - @Test - public void testRetryConnectionOnFailure() { - // Setup WifiNetworkSelector to return 2 valid candidates from scan results - MacAddress macAddress = MacAddress.fromString(CANDIDATE_BSSID_2); - WifiCandidates.Key key = new WifiCandidates.Key(mock(ScanResultMatchInfo.class), - macAddress, 0); - WifiCandidates.Candidate otherCandidate = mock(WifiCandidates.Candidate.class); - when(otherCandidate.getKey()).thenReturn(key); - List<WifiCandidates.Candidate> candidateList = new ArrayList<>(); - candidateList.add(mCandidate1); - candidateList.add(otherCandidate); - when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean())).thenReturn(candidateList); - - // Set WiFi to disconnected state to trigger scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mLooper.dispatchAll(); - // Verify a connection starting - verify(mWifiNS).selectNetwork((List<WifiCandidates.Candidate>) - argThat(new WifiCandidatesListSizeMatcher(2))); - verify(mClientModeImpl).startConnectToNetwork(anyInt(), anyInt(), any()); - - // Simulate the connection failing - mWifiConnectivityManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, CANDIDATE_BSSID, - CANDIDATE_SSID); - // Verify the failed BSSID is added to blocklist - verify(mBssidBlocklistMonitor).blockBssidForDurationMs(eq(CANDIDATE_BSSID), - eq(CANDIDATE_SSID), anyLong(), anyInt(), anyInt()); - // Verify another connection starting - verify(mWifiNS).selectNetwork((List<WifiCandidates.Candidate>) - argThat(new WifiCandidatesListSizeMatcher(1))); - verify(mClientModeImpl, times(2)).startConnectToNetwork(anyInt(), anyInt(), any()); - - // Simulate the second connection also failing - mWifiConnectivityManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, CANDIDATE_BSSID_2, - CANDIDATE_SSID); - // Verify there are no more connections - verify(mWifiNS).selectNetwork((List<WifiCandidates.Candidate>) - argThat(new WifiCandidatesListSizeMatcher(0))); - verify(mClientModeImpl, times(2)).startConnectToNetwork(anyInt(), anyInt(), any()); - } - - private class WifiCandidatesListSizeMatcher implements - ArgumentMatcher<List<WifiCandidates.Candidate>> { - int mSize; - WifiCandidatesListSizeMatcher(int size) { - mSize = size; - } - @Override - public boolean matches(List<WifiCandidates.Candidate> candidateList) { - return candidateList.size() == mSize; - } - } - - /** - * Verify that the cached candidates become cleared after a period of time. - */ - @Test - public void testRetryConnectionOnFailureCacheTimeout() { - // Setup WifiNetworkSelector to return 2 valid candidates from scan results - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - MacAddress macAddress = MacAddress.fromString(CANDIDATE_BSSID_2); - WifiCandidates.Key key = new WifiCandidates.Key(mock(ScanResultMatchInfo.class), - macAddress, 0); - WifiCandidates.Candidate otherCandidate = mock(WifiCandidates.Candidate.class); - when(otherCandidate.getKey()).thenReturn(key); - List<WifiCandidates.Candidate> candidateList = new ArrayList<>(); - candidateList.add(mCandidate1); - candidateList.add(otherCandidate); - when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean())).thenReturn(candidateList); - - // Set WiFi to disconnected state to trigger scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mLooper.dispatchAll(); - // Verify a connection starting - verify(mWifiNS).selectNetwork((List<WifiCandidates.Candidate>) - argThat(new WifiCandidatesListSizeMatcher(2))); - verify(mClientModeImpl).startConnectToNetwork(anyInt(), anyInt(), any()); - - // Simulate the connection failing after the cache timeout period. - when(mClock.getElapsedSinceBootMillis()).thenReturn(TEMP_BSSID_BLOCK_DURATION_MS + 1L); - mWifiConnectivityManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, CANDIDATE_BSSID, - CANDIDATE_SSID); - // verify there are no additional connections. - verify(mClientModeImpl).startConnectToNetwork(anyInt(), anyInt(), any()); - } - - /** - * Verify that in the high movement mobility state, when the RSSI delta of a BSSID from - * 2 consecutive scans becomes greater than a threshold, the candidate get ignored from - * network selection. - */ - @Test - public void testHighMovementRssiFilter() { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - // Enable high movement optimization - mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled, - true); - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - - // Set WiFi to disconnected state to trigger scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mLooper.dispatchAll(); - - // Verify there is no connection due to currently having no cached candidates. - verify(mClientModeImpl, never()).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - - // Move time past HIGH_MVMT_SCAN_DELAY_MS. - when(mClock.getElapsedSinceBootMillis()).thenReturn((long) HIGH_MVMT_SCAN_DELAY_MS); - - // Mock the current Candidate to have RSSI over the filter threshold - mCandidateList.clear(); - mCandidateList.add(mCandidate2); - - // Set WiFi to disconnected state to trigger scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mLooper.dispatchAll(); - - // Verify connect is not started. - verify(mClientModeImpl, never()).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - verify(mWifiMetrics, times(2)).incrementNumHighMovementConnectionSkipped(); - } - - /** - * {@link OpenNetworkNotifier} handles scan results on network selection. - * - * Expected behavior: ONA handles scan results - */ - @Test - public void wifiDisconnected_noConnectionCandidate_openNetworkNotifierScanResultsHandled() { - // no connection candidate selected - when(mWifiNS.selectNetwork(any())).thenReturn(null); - - List<ScanDetail> expectedOpenNetworks = new ArrayList<>(); - expectedOpenNetworks.add( - new ScanDetail( - new ScanResult(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID), - CANDIDATE_SSID, CANDIDATE_BSSID, 1245, 0, "some caps", -78, 2450, - 1025, 22, 33, 20, 0, 0, true), null)); - - when(mWifiNS.getFilteredScanDetailsForOpenUnsavedNetworks()) - .thenReturn(expectedOpenNetworks); - - // Set WiFi to disconnected state to trigger PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - verify(mOpenNetworkNotifier).handleScanResults(expectedOpenNetworks); - } - - /** - * When wifi is connected, {@link OpenNetworkNotifier} handles the Wi-Fi connected behavior. - * - * Expected behavior: ONA handles connected behavior - */ - @Test - public void wifiConnected_openNetworkNotifierHandlesConnection() { - // Set WiFi to connected state - mWifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID)); - mWifiConnectivityManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, CANDIDATE_BSSID, CANDIDATE_SSID); - verify(mOpenNetworkNotifier).handleWifiConnected(CANDIDATE_SSID); - } - - /** - * When wifi is connected, {@link OpenNetworkNotifier} handles connection state - * change. - * - * Expected behavior: ONA does not clear pending notification. - */ - @Test - public void wifiDisconnected_openNetworkNotifierDoesNotClearPendingNotification() { - // Set WiFi to disconnected state - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - verify(mOpenNetworkNotifier, never()).clearPendingNotification(anyBoolean()); - } - - /** - * When a Wi-Fi connection attempt ends, {@link OpenNetworkNotifier} handles the connection - * failure. A failure code that is not {@link WifiMetrics.ConnectionEvent#FAILURE_NONE} - * represents a connection failure. - * - * Expected behavior: ONA handles connection failure. - */ - @Test - public void wifiConnectionEndsWithFailure_openNetworkNotifierHandlesConnectionFailure() { - mWifiConnectivityManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, CANDIDATE_BSSID, - CANDIDATE_SSID); - - verify(mOpenNetworkNotifier).handleConnectionFailure(); - } - - /** - * When a Wi-Fi connection attempt ends, {@link OpenNetworkNotifier} does not handle connection - * failure after a successful connection. {@link WifiMetrics.ConnectionEvent#FAILURE_NONE} - * represents a successful connection. - * - * Expected behavior: ONA does nothing. - */ - @Test - public void wifiConnectionEndsWithSuccess_openNetworkNotifierDoesNotHandleConnectionFailure() { - mWifiConnectivityManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, CANDIDATE_BSSID, CANDIDATE_SSID); - - verify(mOpenNetworkNotifier, never()).handleConnectionFailure(); - } - - /** - * When Wi-Fi is disabled, clear the pending notification and reset notification repeat delay. - * - * Expected behavior: clear pending notification and reset notification repeat delay - * */ - @Test - public void openNetworkNotifierClearsPendingNotificationOnWifiDisabled() { - mWifiConnectivityManager.setWifiEnabled(false); - - verify(mOpenNetworkNotifier).clearPendingNotification(true /* resetRepeatDelay */); - } - - /** - * Verify that the ONA controller tracks screen state changes. - */ - @Test - public void openNetworkNotifierTracksScreenStateChanges() { - mWifiConnectivityManager.handleScreenStateChanged(false); - - verify(mOpenNetworkNotifier).handleScreenStateChanged(false); - - mWifiConnectivityManager.handleScreenStateChanged(true); - - verify(mOpenNetworkNotifier).handleScreenStateChanged(true); - } - - /** - * Verify that if configuration for single scan schedule is empty, default - * schedule is being used. - */ - @Test - public void checkPeriodicScanIntervalWhenDisconnectedWithEmptySchedule() throws Exception { - mResources.setIntArray(R.array.config_wifiDisconnectedScanIntervalScheduleSec, - SCHEDULE_EMPTY_SEC); - - checkWorkingWithDefaultSchedule(); - } - - /** - * Verify that if configuration for single scan schedule has zero values, default - * schedule is being used. - */ - @Test - public void checkPeriodicScanIntervalWhenDisconnectedWithZeroValuesSchedule() { - mResources.setIntArray( - R.array.config_wifiDisconnectedScanIntervalScheduleSec, - INVALID_SCHEDULE_ZERO_VALUES_SEC); - - checkWorkingWithDefaultSchedule(); - } - - /** - * Verify that if configuration for single scan schedule has negative values, default - * schedule is being used. - */ - @Test - public void checkPeriodicScanIntervalWhenDisconnectedWithNegativeValuesSchedule() { - mResources.setIntArray( - R.array.config_wifiDisconnectedScanIntervalScheduleSec, - INVALID_SCHEDULE_NEGATIVE_VALUES_SEC); - - checkWorkingWithDefaultSchedule(); - } - - private void checkWorkingWithDefaultSchedule() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - mWifiConnectivityManager = createConnectivityManager(); - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - mWifiConnectivityManager.setWifiEnabled(true); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max periodic scan interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_DEFAULT_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set WiFi to disconnected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(DEFAULT_SINGLE_SCAN_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - - currentTimeStamp += firstIntervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Now fire the first periodic scan alarm timer - mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - - // Get the second periodic scan interval - long secondIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - - // Verify the intervals are exponential back off - assertEquals(DEFAULT_SINGLE_SCAN_SCHEDULE_SEC[1] * 1000, secondIntervalMs); - - currentTimeStamp += secondIntervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Make sure we eventually stay at the maximum scan interval. - long intervalMs = 0; - for (int i = 0; i < 5; i++) { - mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - intervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - currentTimeStamp += intervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - } - - assertEquals(DEFAULT_SINGLE_SCAN_SCHEDULE_SEC[DEFAULT_SINGLE_SCAN_SCHEDULE_SEC.length - 1] - * 1000, intervalMs); - } - - /** - * Verify that scan interval for screen on and wifi disconnected scenario - * is in the exponential backoff fashion. - * - * Expected behavior: WifiConnectivityManager doubles periodic - * scan interval. - */ - @Test - public void checkPeriodicScanIntervalWhenDisconnected() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max periodic scan interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set WiFi to disconnected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - - currentTimeStamp += firstIntervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Now fire the first periodic scan alarm timer - mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - - // Get the second periodic scan interval - long secondIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - - // Verify the intervals are exponential back off - assertEquals(VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE_SEC[1] * 1000, secondIntervalMs); - - currentTimeStamp += secondIntervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Make sure we eventually stay at the maximum scan interval. - long intervalMs = 0; - for (int i = 0; i < 5; i++) { - mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - intervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - currentTimeStamp += intervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - } - - assertEquals(VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE_SEC[ - VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE_SEC.length - 1] * 1000, intervalMs); - } - - /** - * Verify that scan interval for screen on and wifi connected scenario - * is in the exponential backoff fashion. - * - * Expected behavior: WifiConnectivityManager doubles periodic - * scan interval. - */ - @Test - public void checkPeriodicScanIntervalWhenConnected() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set WiFi to connected state to trigger periodic scan - setWifiStateConnected(); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - - currentTimeStamp += firstIntervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Now fire the first periodic scan alarm timer - mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - - // Get the second periodic scan interval - long secondIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - - // Verify the intervals are exponential back off - assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC[1] * 1000, secondIntervalMs); - - currentTimeStamp += secondIntervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Make sure we eventually stay at the maximum scan interval. - long intervalMs = 0; - for (int i = 0; i < 5; i++) { - mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - intervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - currentTimeStamp += intervalMs; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - } - - assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC[ - VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC.length - 1] * 1000, intervalMs); - } - - /** - * When screen on and single saved network schedule is set - * If we have multiple saved networks, the regular connected state scan schedule is used - */ - @Test - public void checkScanScheduleForMultipleSavedNetwork() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - mResources.setIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, - VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC); - - WifiConfiguration wifiConfiguration1 = new WifiConfiguration(); - WifiConfiguration wifiConfiguration2 = new WifiConfiguration(); - wifiConfiguration1.status = WifiConfiguration.Status.CURRENT; - List<WifiConfiguration> wifiConfigurationList = new ArrayList<WifiConfiguration>(); - wifiConfigurationList.add(wifiConfiguration1); - wifiConfigurationList.add(wifiConfiguration2); - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(wifiConfigurationList); - - // Set firmware roaming to enabled - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set WiFi to connected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - } - - /** - * When screen on and single saved network schedule is set - * If we have a single saved network (connected network), - * no passpoint or suggestion networks. - * the single-saved-network connected state scan schedule is used - */ - @Test - public void checkScanScheduleForSingleSavedNetworkConnected() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - mResources.setIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, - VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC); - - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.networkId = TEST_CONNECTED_NETWORK_ID; - List<WifiConfiguration> wifiConfigurationList = new ArrayList<WifiConfiguration>(); - wifiConfigurationList.add(wifiConfiguration); - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(wifiConfigurationList); - - // Set firmware roaming to enabled - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set WiFi to connected state to trigger periodic scan - setWifiStateConnected(); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - } - - /** - * When screen on and single saved network schedule is set - * If we have a single saved network (not connected network), - * no passpoint or suggestion networks. - * the regular connected state scan schedule is used - */ - @Test - public void checkScanScheduleForSingleSavedNetwork() { - int testSavedNetworkId = TEST_CONNECTED_NETWORK_ID + 1; - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - mResources.setIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, - VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC); - - // Set firmware roaming to enabled - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.status = WifiConfiguration.Status.ENABLED; - wifiConfiguration.networkId = testSavedNetworkId; - List<WifiConfiguration> wifiConfigurationList = new ArrayList<WifiConfiguration>(); - wifiConfigurationList.add(wifiConfiguration); - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(wifiConfigurationList); - - // Set WiFi to connected state to trigger periodic scan - setWifiStateConnected(); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - } - - /** - * When screen on and single saved network schedule is set - * If we have a single passpoint network (connected network), - * and no saved or suggestion networks the single-saved-network - * connected state scan schedule is used. - */ - @Test - public void checkScanScheduleForSinglePasspointNetworkConnected() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - mResources.setIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, - VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC); - - // Prepare for a single passpoint network - WifiConfiguration config = new WifiConfiguration(); - config.networkId = TEST_CONNECTED_NETWORK_ID; - String passpointKey = "PASSPOINT_KEY"; - when(mWifiConfigManager.getConfiguredNetwork(passpointKey)).thenReturn(config); - List<PasspointConfiguration> passpointNetworks = new ArrayList<PasspointConfiguration>(); - passpointNetworks.add(mPasspointConfiguration); - when(mPasspointConfiguration.getUniqueId()).thenReturn(passpointKey); - when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) - .thenReturn(passpointNetworks); - - // Prepare for no saved networks - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(new ArrayList<>()); - - // Set firmware roaming to enabled - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set WiFi to connected state to trigger periodic scan - setWifiStateConnected(); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - } - - /** - * When screen on and single saved network schedule is set - * If we have a single suggestion network (connected network), - * and no saved network or passpoint networks the single-saved-network - * connected state scan schedule is used - */ - @Test - public void checkScanScheduleForSingleSuggestionsNetworkConnected() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - mResources.setIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, - VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC); - - // Prepare for a single suggestions network - WifiConfiguration config = new WifiConfiguration(); - config.networkId = TEST_CONNECTED_NETWORK_ID; - String networkKey = "NETWORK_KEY"; - when(mWifiConfigManager.getConfiguredNetwork(networkKey)).thenReturn(config); - when(mSuggestionConfig.getKey()).thenReturn(networkKey); - when(mWifiNetworkSuggestion.getWifiConfiguration()).thenReturn(mSuggestionConfig); - Set<WifiNetworkSuggestion> suggestionNetworks = new HashSet<WifiNetworkSuggestion>(); - suggestionNetworks.add(mWifiNetworkSuggestion); - when(mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()) - .thenReturn(suggestionNetworks); - - // Prepare for no saved networks - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(new ArrayList<>()); - - // Set firmware roaming to enabled - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set WiFi to connected state to trigger periodic scan - setWifiStateConnected(); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - } - - /** - * When screen on and single saved network schedule is set - * If we have a single suggestion network (connected network), - * and saved network/passpoint networks the regular - * connected state scan schedule is used - */ - @Test - public void checkScanScheduleForSavedPasspointSuggestionNetworkConnected() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - mResources.setIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, - VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC); - - // Prepare for a single suggestions network - WifiConfiguration config = new WifiConfiguration(); - config.networkId = TEST_CONNECTED_NETWORK_ID; - String networkKey = "NETWORK_KEY"; - when(mWifiConfigManager.getConfiguredNetwork(networkKey)).thenReturn(config); - when(mSuggestionConfig.getKey()).thenReturn(networkKey); - when(mWifiNetworkSuggestion.getWifiConfiguration()).thenReturn(mSuggestionConfig); - Set<WifiNetworkSuggestion> suggestionNetworks = new HashSet<WifiNetworkSuggestion>(); - suggestionNetworks.add(mWifiNetworkSuggestion); - when(mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()) - .thenReturn(suggestionNetworks); - - // Prepare for a single passpoint network - WifiConfiguration passpointConfig = new WifiConfiguration(); - String passpointKey = "PASSPOINT_KEY"; - when(mWifiConfigManager.getConfiguredNetwork(passpointKey)).thenReturn(passpointConfig); - List<PasspointConfiguration> passpointNetworks = new ArrayList<PasspointConfiguration>(); - passpointNetworks.add(mPasspointConfiguration); - when(mPasspointConfiguration.getUniqueId()).thenReturn(passpointKey); - when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) - .thenReturn(passpointNetworks); - - // Set firmware roaming to enabled - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set WiFi to connected state to trigger periodic scan - setWifiStateConnected(); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - } - - /** - * Remove network will trigger update scan and meet single network requirement. - * Verify before disconnect finished, will not trigger single network scan schedule. - */ - @Test - public void checkScanScheduleForCurrentConnectedNetworkIsNull() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - mResources.setIntArray( - R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, - VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE_SEC); - - // Set firmware roaming to enabled - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set up single saved network - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.networkId = TEST_CONNECTED_NETWORK_ID; - List<WifiConfiguration> wifiConfigurationList = new ArrayList<WifiConfiguration>(); - wifiConfigurationList.add(wifiConfiguration); - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(wifiConfigurationList); - - // Set WiFi to connected state. - setWifiStateConnected(); - // Simulate remove network, disconnect not finished. - when(mClientModeImpl.getCurrentWifiConfiguration()).thenReturn(null); - mNetworkUpdateListenerCaptor.getValue().onNetworkRemoved(null); - - // Get the first periodic scan interval - long firstIntervalMs = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) - - currentTimeStamp; - assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC[0] * 1000, firstIntervalMs); - } - - /** - * When screen on trigger a disconnected state change event then a connected state - * change event back to back to verify that the minium scan interval is enforced. - * - * Expected behavior: WifiConnectivityManager start the second periodic single - * scan after the first one by first interval in connected scanning schedule. - */ - @Test - public void checkMinimumPeriodicScanIntervalWhenScreenOnAndConnected() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for max scanning interval in schedule so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - long scanForDisconnectedTimeStamp = currentTimeStamp; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set WiFi to disconnected state which triggers a scan immediately - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - verify(mWifiScanner, times(1)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); - - // Set up time stamp for when entering CONNECTED state - currentTimeStamp += 2000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set WiFi to connected state to trigger its periodic scan - setWifiStateConnected(); - - // The very first scan triggered for connected state is actually via the alarm timer - // and it obeys the minimum scan interval - long firstScanForConnectedTimeStamp = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); - - // Verify that the first scan for connected state is scheduled after the scan for - // disconnected state by first interval in connected scanning schedule. - assertEquals(scanForDisconnectedTimeStamp + VALID_CONNECTED_SINGLE_SCAN_SCHEDULE_SEC[0] - * 1000, firstScanForConnectedTimeStamp); - } - - /** - * When screen on trigger a connected state change event then a disconnected state - * change event back to back to verify that a scan is fired immediately for the - * disconnected state change event. - * - * Expected behavior: WifiConnectivityManager directly starts the periodic immediately - * for the disconnected state change event. The second scan for disconnected state is - * via alarm timer. - */ - @Test - public void scanImmediatelyWhenScreenOnAndDisconnected() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for maximum scanning interval in schedule so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - long scanForConnectedTimeStamp = currentTimeStamp; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set WiFi to connected state to trigger the periodic scan - setWifiStateConnected(); - - verify(mWifiScanner, times(1)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); - - // Set up the time stamp for when entering DISCONNECTED state - currentTimeStamp += 2000; - long enteringDisconnectedStateTimeStamp = currentTimeStamp; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set WiFi to disconnected state to trigger its periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Verify the very first scan for DISCONNECTED state is fired immediately - verify(mWifiScanner, times(2)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); - long secondScanForDisconnectedTimeStamp = mAlarmManager - .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); - - // Verify that the second scan is scheduled after entering DISCONNECTED state by first - // interval in disconnected scanning schedule. - assertEquals(enteringDisconnectedStateTimeStamp - + VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE_SEC[0] * 1000, - secondScanForDisconnectedTimeStamp); - } - - /** - * When screen on trigger a connection state change event and a forced connectivity - * scan event back to back to verify that the minimum scan interval is not applied - * in this scenario. - * - * Expected behavior: WifiConnectivityManager starts the second periodic single - * scan immediately. - */ - @Test - public void checkMinimumPeriodicScanIntervalNotEnforced() { - long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Wait for maximum interval in scanning schedule so that any impact triggered - // by screen state change can settle - currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE_SEC * 1000; - long firstScanTimeStamp = currentTimeStamp; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Set WiFi to connected state to trigger the periodic scan - setWifiStateConnected(); - - // Set the second scan attempt time stamp - currentTimeStamp += 2000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); - - // Allow untrusted networks so WifiConnectivityManager starts a periodic scan - // immediately. - mWifiConnectivityManager.setUntrustedConnectionAllowed(true); - - // Get the second periodic scan actual time stamp. Note, this scan is not - // started from the AlarmManager. - long secondScanTimeStamp = mWifiConnectivityManager.getLastPeriodicSingleScanTimeStamp(); - - // Verify that the second scan is fired immediately - assertEquals(secondScanTimeStamp, currentTimeStamp); - } - - /** - * Verify that we perform full band scan in the following two cases - * 1) Current RSSI is low, no active stream, network is insufficient - * 2) Current RSSI is high, no active stream, and a long time since last network selection - * 3) Current RSSI is high, no active stream, and a short time since last network selection, - * internet status is not acceptable - * - * Expected behavior: WifiConnectivityManager does full band scan in both cases - */ - @Test - public void verifyFullBandScanWhenConnected() { - mResources.setInteger( - R.integer.config_wifiConnectedHighRssiScanMinimumWindowSizeSec, 600); - - // Verify case 1 - when(mWifiNS.isNetworkSufficient(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasActiveStream(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasSufficientLinkQuality(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasInternetOrExpectNoInternet(eq(mWifiInfo))).thenReturn(true); - - final List<Integer> channelList = new ArrayList<>(); - channelList.add(TEST_FREQUENCY_1); - channelList.add(TEST_FREQUENCY_2); - channelList.add(TEST_FREQUENCY_3); - WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); - configuration.networkId = TEST_CONNECTED_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) - .thenReturn(configuration); - when(mClientModeImpl.getCurrentWifiConfiguration()) - .thenReturn(configuration); - when(mWifiScoreCard.lookupNetwork(configuration.SSID)).thenReturn(mPerNetwork); - when(mPerNetwork.getFrequencies(anyLong())).thenReturn(new ArrayList<>()); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, ScanListener listener, - WorkSource workSource) throws Exception { - assertEquals(settings.band, WifiScanner.WIFI_BAND_ALL); - assertNull(settings.channels); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to connected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - - verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - - // Verify case 2 - when(mWifiNS.isNetworkSufficient(eq(mWifiInfo))).thenReturn(true); - when(mWifiNS.hasActiveStream(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasSufficientLinkQuality(eq(mWifiInfo))).thenReturn(true); - when(mWifiNS.hasInternetOrExpectNoInternet(eq(mWifiInfo))).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(600_000L + 1L); - mWifiConnectivityManager.handleScreenStateChanged(true); - // Set WiFi to connected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - verify(mWifiScanner, times(2)).startScan(anyObject(), anyObject(), anyObject(), - anyObject()); - - // Verify case 3 - when(mWifiNS.isNetworkSufficient(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasActiveStream(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasSufficientLinkQuality(eq(mWifiInfo))).thenReturn(true); - when(mWifiNS.hasInternetOrExpectNoInternet(eq(mWifiInfo))).thenReturn(false); - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - mWifiConnectivityManager.handleScreenStateChanged(true); - // Set WiFi to connected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - verify(mWifiScanner, times(2)).startScan(anyObject(), anyObject(), anyObject(), - anyObject()); - } - - /** - * Verify that we perform partial scan when the current RSSI is low, - * Tx/Rx success rates are high, and when the currently connected network is present - * in scan cache in WifiConfigManager. - * WifiConnectivityManager does partial scan only when firmware roaming is not supported. - * - * Expected behavior: WifiConnectivityManager does partial scan. - */ - @Test - public void checkPartialScanRequestedWithLowRssiAndActiveStreamWithoutFwRoaming() { - when(mWifiNS.isNetworkSufficient(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasActiveStream(eq(mWifiInfo))).thenReturn(true); - when(mWifiNS.hasSufficientLinkQuality(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasInternetOrExpectNoInternet(eq(mWifiInfo))).thenReturn(true); - - mResources.setInteger( - R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels, - 10); - - WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); - configuration.networkId = TEST_CONNECTED_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) - .thenReturn(configuration); - List<Integer> channelList = linkScoreCardFreqsToNetwork(configuration).get(0); - when(mClientModeImpl.getCurrentWifiConfiguration()) - .thenReturn(configuration); - - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - assertEquals(settings.band, WifiScanner.WIFI_BAND_UNSPECIFIED); - assertEquals(settings.channels.length, channelList.size()); - for (int chanIdx = 0; chanIdx < settings.channels.length; chanIdx++) { - assertTrue(channelList.contains(settings.channels[chanIdx].frequency)); - } - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to connected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - - verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - } - - /** - * Verify that we perform partial scan when the current RSSI is high, - * Tx/Rx success rates are low, and when the currently connected network is present - * in scan cache in WifiConfigManager. - * WifiConnectivityManager does partial scan only when firmware roaming is not supported. - * - * Expected behavior: WifiConnectivityManager does partial scan. - */ - @Test - public void checkPartialScanRequestedWithHighRssiNoActiveStreamWithoutFwRoaming() { - when(mWifiNS.isNetworkSufficient(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasActiveStream(eq(mWifiInfo))).thenReturn(false); - when(mWifiNS.hasSufficientLinkQuality(eq(mWifiInfo))).thenReturn(true); - when(mWifiNS.hasInternetOrExpectNoInternet(eq(mWifiInfo))).thenReturn(true); - - mResources.setInteger( - R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels, - 10); - - WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); - configuration.networkId = TEST_CONNECTED_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) - .thenReturn(configuration); - List<Integer> channelList = linkScoreCardFreqsToNetwork(configuration).get(0); - - when(mClientModeImpl.getCurrentWifiConfiguration()) - .thenReturn(configuration); - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - assertEquals(settings.band, WifiScanner.WIFI_BAND_UNSPECIFIED); - assertEquals(settings.channels.length, channelList.size()); - for (int chanIdx = 0; chanIdx < settings.channels.length; chanIdx++) { - assertTrue(channelList.contains(settings.channels[chanIdx].frequency)); - } - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to connected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - - verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - } - - - /** - * Verify that we fall back to full band scan when the currently connected network's tx/rx - * success rate is high, RSSI is also high but the currently connected network - * is not present in scan cache in WifiConfigManager. - * This is simulated by returning an empty hashset in |makeChannelList|. - * - * Expected behavior: WifiConnectivityManager does full band scan. - */ - @Test - public void checkSingleScanSettingsWhenConnectedWithHighDataRateNotInCache() { - when(mWifiNS.isNetworkSufficient(eq(mWifiInfo))).thenReturn(true); - when(mWifiNS.hasActiveStream(eq(mWifiInfo))).thenReturn(true); - when(mWifiNS.hasSufficientLinkQuality(eq(mWifiInfo))).thenReturn(true); - when(mWifiNS.hasInternetOrExpectNoInternet(eq(mWifiInfo))).thenReturn(true); - - WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); - configuration.networkId = TEST_CONNECTED_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) - .thenReturn(configuration); - List<Integer> channelList = linkScoreCardFreqsToNetwork(configuration).get(0); - - when(mClientModeImpl.getCurrentWifiConfiguration()) - .thenReturn(new WifiConfiguration()); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - assertEquals(settings.band, WifiScanner.WIFI_BAND_ALL); - assertNull(settings.channels); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to connected state to trigger periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_CONNECTED); - - verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - } - - /** - * Verify that we retry connectivity scan up to MAX_SCAN_RESTART_ALLOWED times - * when Wifi somehow gets into a bad state and fails to scan. - * - * Expected behavior: WifiConnectivityManager schedules connectivity scan - * MAX_SCAN_RESTART_ALLOWED times. - */ - @Test - public void checkMaximumScanRetry() { - // Set screen to ON - mWifiConnectivityManager.handleScreenStateChanged(true); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - listener.onFailure(-1, "ScanFailure"); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - - // Set WiFi to disconnected state to trigger the single scan based periodic scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Fire the alarm timer 2x timers - for (int i = 0; i < (WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED * 2); i++) { - mAlarmManager.dispatch(WifiConnectivityManager.RESTART_SINGLE_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - } - - // Verify that the connectivity scan has been retried for MAX_SCAN_RESTART_ALLOWED - // times. Note, WifiScanner.startScan() is invoked MAX_SCAN_RESTART_ALLOWED + 1 times. - // The very first scan is the initial one, and the other MAX_SCAN_RESTART_ALLOWED - // are the retrial ones. - verify(mWifiScanner, times(WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED + 1)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); - } - - /** - * Verify that a successful scan result resets scan retry counter - * - * Steps - * 1. Trigger a scan that fails - * 2. Let the retry succeed - * 3. Trigger a scan again and have it and all subsequent retries fail - * 4. Verify that there are MAX_SCAN_RESTART_ALLOWED + 3 startScan calls. (2 are from the - * original scans, and MAX_SCAN_RESTART_ALLOWED + 1 from retries) - */ - @Test - public void verifyScanFailureCountIsResetAfterOnResult() { - // Setup WifiScanner to fail - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - listener.onFailure(-1, "ScanFailure"); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - - mWifiConnectivityManager.forceConnectivityScan(null); - // make the retry succeed - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - listener.onResults(null); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - mAlarmManager.dispatch(WifiConnectivityManager.RESTART_SINGLE_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - - // Verify that startScan is called once for the original scan, plus once for the retry. - // The successful retry should have now cleared the restart count - verify(mWifiScanner, times(2)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); - - // Now force a new scan and verify we retry MAX_SCAN_RESTART_ALLOWED times - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - listener.onFailure(-1, "ScanFailure"); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); - mWifiConnectivityManager.forceConnectivityScan(null); - // Fire the alarm timer 2x timers - for (int i = 0; i < (WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED * 2); i++) { - mAlarmManager.dispatch(WifiConnectivityManager.RESTART_SINGLE_SCAN_TIMER_TAG); - mLooper.dispatchAll(); - } - - // Verify that the connectivity scan has been retried for MAX_SCAN_RESTART_ALLOWED + 3 - // times. Note, WifiScanner.startScan() is invoked 2 times by the first part of this test, - // and additionally MAX_SCAN_RESTART_ALLOWED + 1 times from forceConnectivityScan and - // subsequent retries. - verify(mWifiScanner, times(WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED + 3)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); - } - - /** - * Listen to scan results not requested by WifiConnectivityManager and - * act on them. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the - * expected candidate network ID and BSSID. - */ - @Test - public void listenToAllSingleScanResults() { - ScanSettings settings = new ScanSettings(); - ScanListener scanListener = mock(ScanListener.class); - - // Request a single scan outside of WifiConnectivityManager. - mWifiScanner.startScan(settings, mock(Executor.class), scanListener, WIFI_WORK_SOURCE); - - // Verify that WCM receives the scan results and initiates a connection - // to the network. - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Verify that a forced connectivity scan waits for full band scan - * results. - * - * Expected behavior: WifiConnectivityManager doesn't invoke - * ClientModeImpl.startConnectToNetwork() when full band scan - * results are not available. - */ - @Test - public void waitForFullBandScanResults() { - // Set WiFi to connected state. - setWifiStateConnected(); - - // Set up as partial scan results. - when(mScanData.getBandScanned()).thenReturn(WifiScanner.WIFI_BAND_5_GHZ); - - // Force a connectivity scan which enables WifiConnectivityManager - // to wait for full band scan results. - mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - - // No roaming because no full band scan results. - verify(mClientModeImpl, times(0)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - - // Set up as full band scan results. - when(mScanData.getBandScanned()).thenReturn(WifiScanner.WIFI_BAND_ALL); - - // Force a connectivity scan which enables WifiConnectivityManager - // to wait for full band scan results. - mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - - // Roaming attempt because full band scan results are available. - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Verify when new scanResults are available, UserDisabledList will be updated. - */ - @Test - public void verifyUserDisabledListUpdated() { - mResources.setBoolean( - R.bool.config_wifi_framework_use_single_radio_chain_scan_results_network_selection, - true); - verify(mWifiConfigManager, never()).updateUserDisabledList(anyList()); - Set<String> updateNetworks = new HashSet<>(); - mScanData = createScanDataWithDifferentRadioChainInfos(); - int i = 0; - for (ScanResult scanResult : mScanData.getResults()) { - scanResult.SSID = TEST_SSID + i; - updateNetworks.add(ScanResultUtil.createQuotedSSID(scanResult.SSID)); - i++; - } - updateNetworks.add(TEST_FQDN); - mScanData.getResults()[0].setFlag(ScanResult.FLAG_PASSPOINT_NETWORK); - HashMap<String, Map<Integer, List<ScanResult>>> passpointNetworks = new HashMap<>(); - passpointNetworks.put(TEST_FQDN, new HashMap<>()); - when(mPasspointManager.getAllMatchingPasspointProfilesForScanResults(any())) - .thenReturn(passpointNetworks); - - mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - ArgumentCaptor<ArrayList<String>> listArgumentCaptor = - ArgumentCaptor.forClass(ArrayList.class); - verify(mWifiConfigManager).updateUserDisabledList(listArgumentCaptor.capture()); - assertEquals(updateNetworks, new HashSet<>(listArgumentCaptor.getValue())); - } - - /** - * Verify that a blacklisted BSSID becomes available only after - * BSSID_BLACKLIST_EXPIRE_TIME_MS. - */ - @Test - public void verifyBlacklistRefreshedAfterScanResults() { - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - InOrder inOrder = inOrder(mBssidBlocklistMonitor); - // Force a connectivity scan - inOrder.verify(mBssidBlocklistMonitor, never()) - .updateAndGetBssidBlocklistForSsid(anyString()); - mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - - inOrder.verify(mBssidBlocklistMonitor).tryEnablingBlockedBssids(any()); - inOrder.verify(mBssidBlocklistMonitor).updateAndGetBssidBlocklistForSsid(anyString()); - } - - /** - * Verify that BSSID blacklist gets cleared when exiting Wifi client mode. - */ - @Test - public void clearBssidBlocklistWhenExitingWifiClientMode() { - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Verify the BSSID blacklist is cleared at start up. - verify(mBssidBlocklistMonitor).clearBssidBlocklist(); - // Exit Wifi client mode. - mWifiConnectivityManager.setWifiEnabled(false); - - // Verify the BSSID blacklist is cleared again. - verify(mBssidBlocklistMonitor, times(2)).clearBssidBlocklist(); - // Verify WifiNetworkSelector is informed of the disable. - verify(mWifiNS).resetOnDisable(); - } - - /** - * Verify that BSSID blacklist gets cleared when preparing for a forced connection - * initiated by user/app. - */ - @Test - public void clearBssidBlocklistWhenPreparingForForcedConnection() { - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - // Prepare for a forced connection attempt. - WifiConfiguration currentNetwork = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(currentNetwork); - mWifiConnectivityManager.prepareForForcedConnection(1); - verify(mBssidBlocklistMonitor).clearBssidBlocklistForSsid(CANDIDATE_SSID); - } - - /** - * When WifiConnectivityManager is on and Wifi client mode is enabled, framework - * queries firmware via WifiConnectivityHelper to check if firmware roaming is - * supported and its capability. - * - * Expected behavior: WifiConnectivityManager#setWifiEnabled calls into - * WifiConnectivityHelper#getFirmwareRoamingInfo - */ - @Test - public void verifyGetFirmwareRoamingInfoIsCalledWhenEnableWiFiAndWcmOn() { - // WifiConnectivityManager is on by default - mWifiConnectivityManager.setWifiEnabled(true); - verify(mWifiConnectivityHelper).getFirmwareRoamingInfo(); - } - - /** - * When WifiConnectivityManager is off, verify that framework does not - * query firmware via WifiConnectivityHelper to check if firmware roaming is - * supported and its capability when enabling Wifi client mode. - * - * Expected behavior: WifiConnectivityManager#setWifiEnabled does not call into - * WifiConnectivityHelper#getFirmwareRoamingInfo - */ - @Test - public void verifyGetFirmwareRoamingInfoIsNotCalledWhenEnableWiFiAndWcmOff() { - reset(mWifiConnectivityHelper); - mWifiConnectivityManager.setAutoJoinEnabledExternal(false); - mWifiConnectivityManager.setWifiEnabled(true); - verify(mWifiConnectivityHelper, times(0)).getFirmwareRoamingInfo(); - } - - /* - * Firmware supports controlled roaming. - * Connect to a network which doesn't have a config specified BSSID. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the - * expected candidate network ID, and the BSSID value should be - * 'any' since firmware controls the roaming. - */ - @Test - public void useAnyBssidToConnectWhenFirmwareRoamingOnAndConfigHasNoBssidSpecified() { - // Firmware controls roaming - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to disconnected state - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, ClientModeImpl.SUPPLICANT_BSSID_ANY); - } - - /* - * Firmware supports controlled roaming. - * Connect to a network which has a config specified BSSID. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the - * expected candidate network ID, and the BSSID value should be - * the config specified one. - */ - @Test - public void useConfigSpecifiedBssidToConnectWhenFirmwareRoamingOn() { - // Firmware controls roaming - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set up the candidate configuration such that it has a BSSID specified. - WifiConfiguration candidate = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - candidate.BSSID = CANDIDATE_BSSID; // config specified - ScanResult candidateScanResult = new ScanResult(); - candidateScanResult.SSID = CANDIDATE_SSID; - candidateScanResult.BSSID = CANDIDATE_BSSID; - candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - when(mWifiNS.selectNetwork(any())).thenReturn(candidate); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to disconnected state - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /* - * Firmware does not support controlled roaming. - * Connect to a network which doesn't have a config specified BSSID. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the expected candidate network ID, - * and the BSSID value should be the candidate scan result specified. - */ - @Test - public void useScanResultBssidToConnectWhenFirmwareRoamingOffAndConfigHasNoBssidSpecified() { - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to disconnected state - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /* - * Firmware does not support controlled roaming. - * Connect to a network which has a config specified BSSID. - * - * Expected behavior: WifiConnectivityManager calls - * ClientModeImpl.startConnectToNetwork() with the expected candidate network ID, - * and the BSSID value should be the config specified one. - */ - @Test - public void useConfigSpecifiedBssidToConnectionWhenFirmwareRoamingOff() { - // Set up the candidate configuration such that it has a BSSID specified. - WifiConfiguration candidate = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - candidate.BSSID = CANDIDATE_BSSID; // config specified - ScanResult candidateScanResult = new ScanResult(); - candidateScanResult.SSID = CANDIDATE_SSID; - candidateScanResult.BSSID = CANDIDATE_BSSID; - candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - when(mWifiNS.selectNetwork(any())).thenReturn(candidate); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to disconnected state - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - verify(mClientModeImpl).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /** - * Firmware does not support controlled roaming. - * WiFi in connected state, framework triggers roaming. - * - * Expected behavior: WifiConnectivityManager invokes - * ClientModeImpl.startRoamToNetwork(). - */ - @Test - public void frameworkInitiatedRoaming() { - // Mock the currently connected network which has the same networkID and - // SSID as the one to be selected. - WifiConfiguration currentNetwork = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(currentNetwork); - - // Set WiFi to connected state - setWifiStateConnected(); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - verify(mClientModeImpl).startRoamToNetwork(eq(CANDIDATE_NETWORK_ID), - mCandidateScanResultCaptor.capture()); - assertEquals(mCandidateScanResultCaptor.getValue().BSSID, CANDIDATE_BSSID); - } - - /** - * Firmware supports controlled roaming. - * WiFi in connected state, framework does not trigger roaming - * as it's handed off to the firmware. - * - * Expected behavior: WifiConnectivityManager doesn't invoke - * ClientModeImpl.startRoamToNetwork(). - */ - @Test - public void noFrameworkRoamingIfConnectedAndFirmwareRoamingSupported() { - // Mock the currently connected network which has the same networkID and - // SSID as the one to be selected. - WifiConfiguration currentNetwork = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(currentNetwork); - - // Firmware controls roaming - when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); - - // Set WiFi to connected state - setWifiStateConnected(); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - verify(mClientModeImpl, times(0)).startRoamToNetwork(anyInt(), anyObject()); - } - - /* - * Wifi in disconnected state. Drop the connection attempt if the recommended - * network configuration has a BSSID specified but the scan result BSSID doesn't - * match it. - * - * Expected behavior: WifiConnectivityManager doesn't invoke - * ClientModeImpl.startConnectToNetwork(). - */ - @Test - public void dropConnectAttemptIfConfigSpecifiedBssidDifferentFromScanResultBssid() { - // Set up the candidate configuration such that it has a BSSID specified. - WifiConfiguration candidate = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - candidate.BSSID = CANDIDATE_BSSID; // config specified - ScanResult candidateScanResult = new ScanResult(); - candidateScanResult.SSID = CANDIDATE_SSID; - // Set up the scan result BSSID to be different from the config specified one. - candidateScanResult.BSSID = INVALID_SCAN_RESULT_BSSID; - candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - when(mWifiNS.selectNetwork(any())).thenReturn(candidate); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - // Set WiFi to disconnected state - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - verify(mClientModeImpl, times(0)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - } - - /* - * Wifi in connected state. Drop the roaming attempt if the recommended - * network configuration has a BSSID specified but the scan result BSSID doesn't - * match it. - * - * Expected behavior: WifiConnectivityManager doesn't invoke - * ClientModeImpl.startRoamToNetwork(). - */ - @Test - public void dropRoamingAttemptIfConfigSpecifiedBssidDifferentFromScanResultBssid() { - // Mock the currently connected network which has the same networkID and - // SSID as the one to be selected. - WifiConfiguration currentNetwork = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(currentNetwork); - - // Set up the candidate configuration such that it has a BSSID specified. - WifiConfiguration candidate = generateWifiConfig( - 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); - candidate.BSSID = CANDIDATE_BSSID; // config specified - ScanResult candidateScanResult = new ScanResult(); - candidateScanResult.SSID = CANDIDATE_SSID; - // Set up the scan result BSSID to be different from the config specified one. - candidateScanResult.BSSID = INVALID_SCAN_RESULT_BSSID; - candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - when(mWifiNS.selectNetwork(any())).thenReturn(candidate); - - // Set WiFi to connected state - setWifiStateConnected(); - - // Set screen to on - mWifiConnectivityManager.handleScreenStateChanged(true); - - verify(mClientModeImpl, times(0)).startRoamToNetwork(anyInt(), anyObject()); - } - - /** - * Dump local log buffer. - * - * Expected behavior: Logs dumped from WifiConnectivityManager.dump() - * contain the message we put in mLocalLog. - */ - @Test - public void dumpLocalLog() { - final String localLogMessage = "This is a message from the test"; - mLocalLog.log(localLogMessage); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiConnectivityManager.dump(new FileDescriptor(), pw, new String[]{}); - assertTrue(sw.toString().contains(localLogMessage)); - } - - /** - * Dump ONA controller. - * - * Expected behavior: {@link OpenNetworkNotifier#dump(FileDescriptor, PrintWriter, - * String[])} is invoked. - */ - @Test - public void dumpNotificationController() { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiConnectivityManager.dump(new FileDescriptor(), pw, new String[]{}); - - verify(mOpenNetworkNotifier).dump(any(), any(), any()); - } - - /** - * Create scan data with different radio chain infos: - * First scan result has null radio chain info (No DBS support). - * Second scan result has empty radio chain info (No DBS support). - * Third scan result has 1 radio chain info (DBS scan). - * Fourth scan result has 2 radio chain info (non-DBS scan). - */ - private ScanData createScanDataWithDifferentRadioChainInfos() { - // Create 4 scan results. - ScanData[] scanDatas = - ScanTestUtil.createScanDatas(new int[][]{{5150, 5175, 2412, 2400}}, new int[]{0}); - // WCM barfs if the scan result does not have an IE. - scanDatas[0].getResults()[0].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[1].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[2].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[3].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[0].radioChainInfos = null; - scanDatas[0].getResults()[1].radioChainInfos = new ScanResult.RadioChainInfo[0]; - scanDatas[0].getResults()[2].radioChainInfos = new ScanResult.RadioChainInfo[1]; - scanDatas[0].getResults()[3].radioChainInfos = new ScanResult.RadioChainInfo[2]; - - return scanDatas[0]; - } - - /** - * If |config_wifi_framework_use_single_radio_chain_scan_results_network_selection| flag is - * false, WifiConnectivityManager should filter scan results which contain scans from a single - * radio chain (i.e DBS scan). - * Note: - * a) ScanResult with no radio chain indicates a lack of DBS support on the device. - * b) ScanResult with 2 radio chain info indicates a scan done using both the radio chains - * on a DBS supported device. - * - * Expected behavior: WifiConnectivityManager invokes - * {@link WifiNetworkSelector#selectNetwork(List, HashSet, WifiInfo, boolean, boolean, boolean)} - * after filtering out the scan results obtained via DBS scan. - */ - @Test - public void filterScanResultsWithOneRadioChainInfoForNetworkSelectionIfConfigDisabled() { - mResources.setBoolean( - R.bool.config_wifi_framework_use_single_radio_chain_scan_results_network_selection, - false); - when(mWifiNS.selectNetwork(any())).thenReturn(null); - mWifiConnectivityManager = createConnectivityManager(); - - mScanData = createScanDataWithDifferentRadioChainInfos(); - - // Capture scan details which were sent to network selector. - final List<ScanDetail> capturedScanDetails = new ArrayList<>(); - doAnswer(new AnswerWithArguments() { - public List<WifiCandidates.Candidate> answer( - List<ScanDetail> scanDetails, Set<String> bssidBlacklist, WifiInfo wifiInfo, - boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) - throws Exception { - capturedScanDetails.addAll(scanDetails); - return null; - }}).when(mWifiNS).getCandidatesFromScan( - any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); - - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - // Set WiFi to disconnected state with screen on which triggers a scan immediately. - mWifiConnectivityManager.setWifiEnabled(true); - mWifiConnectivityManager.handleScreenStateChanged(true); - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // We should have filtered out the 3rd scan result. - assertEquals(3, capturedScanDetails.size()); - List<ScanResult> capturedScanResults = - capturedScanDetails.stream().map(ScanDetail::getScanResult) - .collect(Collectors.toList()); - - assertEquals(3, capturedScanResults.size()); - assertTrue(capturedScanResults.contains(mScanData.getResults()[0])); - assertTrue(capturedScanResults.contains(mScanData.getResults()[1])); - assertFalse(capturedScanResults.contains(mScanData.getResults()[2])); - assertTrue(capturedScanResults.contains(mScanData.getResults()[3])); - } - - /** - * If |config_wifi_framework_use_single_radio_chain_scan_results_network_selection| flag is - * true, WifiConnectivityManager should not filter scan results which contain scans from a - * single radio chain (i.e DBS scan). - * Note: - * a) ScanResult with no radio chain indicates a lack of DBS support on the device. - * b) ScanResult with 2 radio chain info indicates a scan done using both the radio chains - * on a DBS supported device. - * - * Expected behavior: WifiConnectivityManager invokes - * {@link WifiNetworkSelector#selectNetwork(List, HashSet, WifiInfo, boolean, boolean, boolean)} - * after filtering out the scan results obtained via DBS scan. - */ - @Test - public void dontFilterScanResultsWithOneRadioChainInfoForNetworkSelectionIfConfigEnabled() { - mResources.setBoolean( - R.bool.config_wifi_framework_use_single_radio_chain_scan_results_network_selection, - true); - when(mWifiNS.selectNetwork(any())).thenReturn(null); - mWifiConnectivityManager = createConnectivityManager(); - - mScanData = createScanDataWithDifferentRadioChainInfos(); - - // Capture scan details which were sent to network selector. - final List<ScanDetail> capturedScanDetails = new ArrayList<>(); - doAnswer(new AnswerWithArguments() { - public List<WifiCandidates.Candidate> answer( - List<ScanDetail> scanDetails, Set<String> bssidBlacklist, WifiInfo wifiInfo, - boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) - throws Exception { - capturedScanDetails.addAll(scanDetails); - return null; - }}).when(mWifiNS).getCandidatesFromScan( - any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); - - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - // Set WiFi to disconnected state with screen on which triggers a scan immediately. - mWifiConnectivityManager.setWifiEnabled(true); - mWifiConnectivityManager.handleScreenStateChanged(true); - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // We should not filter any of the scan results. - assertEquals(4, capturedScanDetails.size()); - List<ScanResult> capturedScanResults = - capturedScanDetails.stream().map(ScanDetail::getScanResult) - .collect(Collectors.toList()); - - assertEquals(4, capturedScanResults.size()); - assertTrue(capturedScanResults.contains(mScanData.getResults()[0])); - assertTrue(capturedScanResults.contains(mScanData.getResults()[1])); - assertTrue(capturedScanResults.contains(mScanData.getResults()[2])); - assertTrue(capturedScanResults.contains(mScanData.getResults()[3])); - } - - /** - * Verify the various auto join enable/disable sequences when auto join is disabled externally. - * - * Expected behavior: Autojoin is turned on as a long as there is - * - Auto join is enabled externally - * And - * - No specific network request being processed. - * And - * - Pending generic Network request for trusted wifi connection. - * OR - * - Pending generic Network request for untrused wifi connection. - */ - @Test - public void verifyEnableAndDisableAutoJoinWhenExternalAutoJoinIsDisabled() { - mWifiConnectivityManager = createConnectivityManager(); - - // set wifi on & disconnected to trigger pno scans when auto-join is enabled. - mWifiConnectivityManager.setWifiEnabled(true); - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Disable externally. - mWifiConnectivityManager.setAutoJoinEnabledExternal(false); - - // Enable trusted connection. This should NOT trigger a pno scan for auto-join. - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); - - // End of processing a specific request. This should NOT trigger a new pno scan for - // auto-join. - mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false); - verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); - - // Enable untrusted connection. This should NOT trigger a pno scan for auto-join. - mWifiConnectivityManager.setUntrustedConnectionAllowed(true); - verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); - } - - /** - * Verify the various auto join enable/disable sequences when auto join is enabled externally. - * - * Expected behavior: Autojoin is turned on as a long as there is - * - Auto join is enabled externally - * And - * - No specific network request being processed. - * And - * - Pending generic Network request for trusted wifi connection. - * OR - * - Pending generic Network request for untrused wifi connection. - */ - @Test - public void verifyEnableAndDisableAutoJoin() { - mWifiConnectivityManager = createConnectivityManager(); - - // set wifi on & disconnected to trigger pno scans when auto-join is enabled. - mWifiConnectivityManager.setWifiEnabled(true); - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - - // Enable trusted connection. This should trigger a pno scan for auto-join. - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any()); - - // Start of processing a specific request. This should stop any pno scan for auto-join. - mWifiConnectivityManager.setSpecificNetworkRequestInProgress(true); - verify(mWifiScanner).stopPnoScan(any()); - - // End of processing a specific request. This should now trigger a new pno scan for - // auto-join. - mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false); - verify(mWifiScanner, times(2)).startDisconnectedPnoScan(any(), any(), any(), any()); - - // Disable trusted connection. This should stop any pno scan for auto-join. - mWifiConnectivityManager.setTrustedConnectionAllowed(false); - verify(mWifiScanner, times(2)).stopPnoScan(any()); - - // Enable untrusted connection. This should trigger a pno scan for auto-join. - mWifiConnectivityManager.setUntrustedConnectionAllowed(true); - verify(mWifiScanner, times(3)).startDisconnectedPnoScan(any(), any(), any(), any()); - } - - /** - * Change device mobility state in the middle of a PNO scan. PNO scan should stop, then restart - * with the updated scan period. - */ - @Test - public void changeDeviceMobilityStateDuringScan() { - mWifiConnectivityManager.setWifiEnabled(true); - - // starts a PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - - ArgumentCaptor<ScanSettings> scanSettingsCaptor = ArgumentCaptor.forClass( - ScanSettings.class); - InOrder inOrder = inOrder(mWifiScanner); - - inOrder.verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); - assertEquals(scanSettingsCaptor.getValue().periodInMs, MOVING_PNO_SCAN_INTERVAL_MILLIS); - - // initial connectivity state uses moving PNO scan interval, now set it to stationary - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - - inOrder.verify(mWifiScanner).stopPnoScan(any()); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); - assertEquals(scanSettingsCaptor.getValue().periodInMs, STATIONARY_PNO_SCAN_INTERVAL_MILLIS); - verify(mScoringParams, times(2)).getEntryRssi(ScanResult.BAND_6_GHZ_START_FREQ_MHZ); - verify(mScoringParams, times(2)).getEntryRssi(ScanResult.BAND_5_GHZ_START_FREQ_MHZ); - verify(mScoringParams, times(2)).getEntryRssi(ScanResult.BAND_24_GHZ_START_FREQ_MHZ); - } - - /** - * Change device mobility state in the middle of a PNO scan, but it is changed to another - * mobility state with the same scan period. Original PNO scan should continue. - */ - @Test - public void changeDeviceMobilityStateDuringScanWithSameScanPeriod() { - mWifiConnectivityManager.setWifiEnabled(true); - - // starts a PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - - ArgumentCaptor<ScanSettings> scanSettingsCaptor = ArgumentCaptor.forClass( - ScanSettings.class); - InOrder inOrder = inOrder(mWifiScanner); - inOrder.verify(mWifiScanner, never()).stopPnoScan(any()); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); - assertEquals(scanSettingsCaptor.getValue().periodInMs, MOVING_PNO_SCAN_INTERVAL_MILLIS); - - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT); - - inOrder.verifyNoMoreInteractions(); - } - - /** - * Device is already connected, setting device mobility state should do nothing since no PNO - * scans are running. Then, when PNO scan is started afterwards, should use the new scan period. - */ - @Test - public void setDeviceMobilityStateBeforePnoScan() { - // ensure no PNO scan running - mWifiConnectivityManager.setWifiEnabled(true); - setWifiStateConnected(); - - // initial connectivity state uses moving PNO scan interval, now set it to stationary - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - - // no scans should start or stop because no PNO scan is running - verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); - verify(mWifiScanner, never()).stopPnoScan(any()); - - // starts a PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - - ArgumentCaptor<ScanSettings> scanSettingsCaptor = ArgumentCaptor.forClass( - ScanSettings.class); - - verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); - // check that now the PNO scan uses the stationary interval, even though it was set before - // the PNO scan started - assertEquals(scanSettingsCaptor.getValue().periodInMs, STATIONARY_PNO_SCAN_INTERVAL_MILLIS); - } - - /** - * Tests the metrics collection of PNO scans through changes to device mobility state and - * starting and stopping of PNO scans. - */ - @Test - public void deviceMobilityStateMetricsChangeStateAndStopStart() { - InOrder inOrder = inOrder(mWifiMetrics); - - mWifiConnectivityManager = createConnectivityManager(); - mWifiConnectivityManager.setWifiEnabled(true); - - // change mobility state while no PNO scans running - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT); - inOrder.verify(mWifiMetrics).enterDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT); - - // starts a PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - inOrder.verify(mWifiMetrics).logPnoScanStart(); - - // change to High Movement, which has the same scan interval as Low Movement - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - inOrder.verify(mWifiMetrics).logPnoScanStop(); - inOrder.verify(mWifiMetrics).enterDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - inOrder.verify(mWifiMetrics).logPnoScanStart(); - - // change to Stationary, which has a different scan interval from High Movement - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - inOrder.verify(mWifiMetrics).logPnoScanStop(); - inOrder.verify(mWifiMetrics).enterDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - inOrder.verify(mWifiMetrics).logPnoScanStart(); - - // stops PNO scan - mWifiConnectivityManager.setTrustedConnectionAllowed(false); - inOrder.verify(mWifiMetrics).logPnoScanStop(); - - // change mobility state while no PNO scans running - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - inOrder.verify(mWifiMetrics).enterDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - - inOrder.verifyNoMoreInteractions(); - } - - /** - * Verify that WifiChannelUtilization is updated - */ - @Test - public void verifyWifiChannelUtilizationRefreshedAfterScanResults() { - WifiLinkLayerStats llstats = new WifiLinkLayerStats(); - when(mClientModeImpl.getWifiLinkLayerStats()).thenReturn(llstats); - - // Force a connectivity scan - mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - - verify(mWifiChannelUtilization).refreshChannelStatsAndChannelUtilization( - llstats, WifiChannelUtilization.UNKNOWN_FREQ); - } - - /** - * Verify that WifiChannelUtilization is initialized properly - */ - @Test - public void verifyWifiChannelUtilizationInitAfterWifiToggle() { - verify(mWifiChannelUtilization, times(1)).init(null); - WifiLinkLayerStats llstats = new WifiLinkLayerStats(); - when(mClientModeImpl.getWifiLinkLayerStats()).thenReturn(llstats); - - mWifiConnectivityManager.setWifiEnabled(false); - mWifiConnectivityManager.setWifiEnabled(true); - verify(mWifiChannelUtilization, times(1)).init(llstats); - } - - /** - * Verify that WifiChannelUtilization sets mobility state correctly - */ - @Test - public void verifyWifiChannelUtilizationSetMobilityState() { - WifiLinkLayerStats llstats = new WifiLinkLayerStats(); - when(mClientModeImpl.getWifiLinkLayerStats()).thenReturn(llstats); - - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - verify(mWifiChannelUtilization).setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); - mWifiConnectivityManager.setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - verify(mWifiChannelUtilization).setDeviceMobilityState( - WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); - } - - /** - * Verify that WifiNetworkSelector sets bluetoothConnected correctly - */ - @Test - public void verifyWifiNetworkSelectorSetBluetoothConnected() { - mWifiConnectivityManager.setBluetoothConnected(true); - verify(mWifiNS).setBluetoothConnected(true); - mWifiConnectivityManager.setBluetoothConnected(false); - verify(mWifiNS).setBluetoothConnected(false); - } - - /** - * Verify that WifiChannelUtilization is updated - */ - @Test - public void verifyForceConnectivityScan() { - // Auto-join enabled - mWifiConnectivityManager.setAutoJoinEnabledExternal(true); - mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - verify(mWifiScanner).startScan(any(), any(), any(), any()); - - // Auto-join disabled - mWifiConnectivityManager.setAutoJoinEnabledExternal(false); - mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - verify(mWifiScanner, times(2)).startScan(any(), any(), any(), any()); - - // Wifi disabled, no new scans - mWifiConnectivityManager.setWifiEnabled(false); - mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - verify(mWifiScanner, times(2)).startScan(any(), any(), any(), any()); - } - - /** - * Verify no network is network selection disabled, auto-join disabled using. - * {@link WifiConnectivityManager#retrievePnoNetworkList()}. - */ - @Test - public void testRetrievePnoList() { - // Create and add 3 networks. - WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - List<WifiConfiguration> networkList = new ArrayList<>(); - networkList.add(network1); - networkList.add(network2); - networkList.add(network3); - mLruConnectionTracker.addNetwork(network3); - mLruConnectionTracker.addNetwork(network2); - mLruConnectionTracker.addNetwork(network1); - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(networkList); - // Retrieve the Pno network list & verify. - List<WifiScanner.PnoSettings.PnoNetwork> pnoNetworks = - mWifiConnectivityManager.retrievePnoNetworkList(); - verify(mWifiNetworkSuggestionsManager).getAllScanOptimizationSuggestionNetworks(); - assertEquals(3, pnoNetworks.size()); - assertEquals(network1.SSID, pnoNetworks.get(0).ssid); - assertEquals(network2.SSID, pnoNetworks.get(1).ssid); - assertEquals(network3.SSID, pnoNetworks.get(2).ssid); - - // Now permanently disable |network3|. This should remove network 3 from the list. - network3.getNetworkSelectionStatus().setNetworkSelectionStatus( - WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - - // Retrieve the Pno network list & verify. - pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); - assertEquals(2, pnoNetworks.size()); - assertEquals(network1.SSID, pnoNetworks.get(0).ssid); - assertEquals(network2.SSID, pnoNetworks.get(1).ssid); - - // Now set network1 autojoin disabled. This should remove network 1 from the list. - network1.allowAutojoin = false; - // Retrieve the Pno network list & verify. - pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); - assertEquals(1, pnoNetworks.size()); - assertEquals(network2.SSID, pnoNetworks.get(0).ssid); - } - - /** - * Verifies frequencies are populated correctly for pno networks. - * {@link WifiConnectivityManager#retrievePnoNetworkList()}. - */ - @Test - public void testRetrievePnoListFrequencies() { - // Create 2 networks. - WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - List<WifiConfiguration> networkList = new ArrayList<>(); - networkList.add(network1); - networkList.add(network2); - mLruConnectionTracker.addNetwork(network2); - mLruConnectionTracker.addNetwork(network1); - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(networkList); - // Retrieve the Pno network list and verify. - // Frequencies should be empty since no scan results have been received yet. - List<WifiScanner.PnoSettings.PnoNetwork> pnoNetworks = - mWifiConnectivityManager.retrievePnoNetworkList(); - assertEquals(2, pnoNetworks.size()); - assertEquals(network1.SSID, pnoNetworks.get(0).ssid); - assertEquals(network2.SSID, pnoNetworks.get(1).ssid); - assertEquals("frequencies should be empty", 0, pnoNetworks.get(0).frequencies.length); - assertEquals("frequencies should be empty", 0, pnoNetworks.get(1).frequencies.length); - - //Set up wifiScoreCard to get frequency. - List<Integer> channelList = Arrays - .asList(TEST_FREQUENCY_1, TEST_FREQUENCY_2, TEST_FREQUENCY_3); - when(mWifiScoreCard.lookupNetwork(network1.SSID)).thenReturn(mPerNetwork); - when(mWifiScoreCard.lookupNetwork(network2.SSID)).thenReturn(mPerNetwork1); - when(mPerNetwork.getFrequencies(anyLong())).thenReturn(channelList); - when(mPerNetwork1.getFrequencies(anyLong())).thenReturn(new ArrayList<>()); - - //Set config_wifiPnoFrequencyCullingEnabled false, should ignore get frequency. - mResources.setBoolean(R.bool.config_wifiPnoFrequencyCullingEnabled, false); - pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); - assertEquals(2, pnoNetworks.size()); - assertEquals(network1.SSID, pnoNetworks.get(0).ssid); - assertEquals(network2.SSID, pnoNetworks.get(1).ssid); - assertEquals("frequencies should be empty", 0, pnoNetworks.get(0).frequencies.length); - assertEquals("frequencies should be empty", 0, pnoNetworks.get(1).frequencies.length); - - // Set config_wifiPnoFrequencyCullingEnabled false, should get the right frequency. - mResources.setBoolean(R.bool.config_wifiPnoFrequencyCullingEnabled, true); - pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); - assertEquals(2, pnoNetworks.size()); - assertEquals(network1.SSID, pnoNetworks.get(0).ssid); - assertEquals(network2.SSID, pnoNetworks.get(1).ssid); - assertEquals(3, pnoNetworks.get(0).frequencies.length); - Arrays.sort(pnoNetworks.get(0).frequencies); - assertEquals(TEST_FREQUENCY_1, pnoNetworks.get(0).frequencies[0]); - assertEquals(TEST_FREQUENCY_2, pnoNetworks.get(0).frequencies[1]); - assertEquals(TEST_FREQUENCY_3, pnoNetworks.get(0).frequencies[2]); - assertEquals("frequencies should be empty", 0, pnoNetworks.get(1).frequencies.length); - } - - - /** - * Verifies the ordering of network list generated using - * {@link WifiConnectivityManager#retrievePnoNetworkList()}. - */ - @Test - public void testRetrievePnoListOrder() { - //Create 3 networks. - WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createOpenHiddenNetwork(); - mLruConnectionTracker.addNetwork(network1); - mLruConnectionTracker.addNetwork(network2); - mLruConnectionTracker.addNetwork(network3); - List<WifiConfiguration> networkList = new ArrayList<>(); - networkList.add(network1); - networkList.add(network2); - networkList.add(network3); - when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(networkList); - List<WifiScanner.PnoSettings.PnoNetwork> pnoNetworks = - mWifiConnectivityManager.retrievePnoNetworkList(); - assertEquals(3, pnoNetworks.size()); - assertEquals(network3.SSID, pnoNetworks.get(0).ssid); - assertEquals(network2.SSID, pnoNetworks.get(1).ssid); - assertEquals(network1.SSID, pnoNetworks.get(2).ssid); - } - - private List<List<Integer>> linkScoreCardFreqsToNetwork(WifiConfiguration... configs) { - List<List<Integer>> results = new ArrayList<>(); - int i = 0; - for (WifiConfiguration config : configs) { - List<Integer> channelList = Arrays.asList(TEST_FREQUENCY_1 + i, TEST_FREQUENCY_2 + i, - TEST_FREQUENCY_3 + i); - WifiScoreCard.PerNetwork perNetwork = mock(WifiScoreCard.PerNetwork.class); - when(mWifiScoreCard.lookupNetwork(config.SSID)).thenReturn(perNetwork); - when(perNetwork.getFrequencies(anyLong())).thenReturn(channelList); - results.add(channelList); - i++; - } - return results; - } - - /** - * Verify that the length of frequency set will not exceed the provided max value - */ - @Test - public void testFetchChannelSetForPartialScanMaxCount() { - WifiConfiguration configuration1 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration configuration2 = WifiConfigurationTestUtil.createOpenNetwork(); - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(Arrays.asList(configuration1, configuration2)); - - List<List<Integer>> freqs = linkScoreCardFreqsToNetwork(configuration1, configuration2); - - mLruConnectionTracker.addNetwork(configuration2); - mLruConnectionTracker.addNetwork(configuration1); - - assertEquals(new HashSet<>(freqs.get(0)), mWifiConnectivityManager - .fetchChannelSetForPartialScan(3, CHANNEL_CACHE_AGE_MINS)); - } - - /** - * Verifies the creation of channel list using - * {@link WifiConnectivityManager#fetchChannelSetForNetworkForPartialScan(int)}. - */ - @Test - public void testFetchChannelSetForNetwork() { - WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); - configuration.networkId = TEST_CONNECTED_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) - .thenReturn(configuration); - List<List<Integer>> freqs = linkScoreCardFreqsToNetwork(configuration); - - assertEquals(new HashSet<>(freqs.get(0)), mWifiConnectivityManager - .fetchChannelSetForNetworkForPartialScan(configuration.networkId)); - } - - /** - * Verifies the creation of channel list using - * {@link WifiConnectivityManager#fetchChannelSetForNetworkForPartialScan(int)} and - * ensures that the frequenecy of the currently connected network is in the returned - * channel set. - */ - @Test - public void testFetchChannelSetForNetworkIncludeCurrentNetwork() { - WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); - configuration.networkId = TEST_CONNECTED_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) - .thenReturn(configuration); - linkScoreCardFreqsToNetwork(configuration); - - mWifiInfo.setFrequency(TEST_CURRENT_CONNECTED_FREQUENCY); - - // Currently connected network frequency 2427 is not in the TEST_FREQ_LIST - Set<Integer> freqs = mWifiConnectivityManager.fetchChannelSetForNetworkForPartialScan( - configuration.networkId); - - assertTrue(freqs.contains(2427)); - } - - /** - * Verifies the creation of channel list using - * {@link WifiConnectivityManager#fetchChannelSetForNetworkForPartialScan(int)} and - * ensures that the list size does not exceed the max configured for the device. - */ - @Test - public void testFetchChannelSetForNetworkIsLimitedToConfiguredSize() { - // Need to recreate the WifiConfigManager instance for this test to modify the config - // value which is read only in the constructor. - int maxListSize = 2; - mResources.setInteger( - R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels, - maxListSize); - - WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); - configuration.networkId = TEST_CONNECTED_NETWORK_ID; - when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) - .thenReturn(configuration); - List<List<Integer>> freqs = linkScoreCardFreqsToNetwork(configuration); - // Ensure that the fetched list size is limited. - Set<Integer> results = mWifiConnectivityManager.fetchChannelSetForNetworkForPartialScan( - configuration.networkId); - assertEquals(maxListSize, results.size()); - assertFalse(results.contains(freqs.get(0).get(2))); - } - - @Test - public void restartPnoScanForNetworkChanges() { - mWifiConnectivityManager.setWifiEnabled(true); - - // starts a PNO scan - mWifiConnectivityManager.handleConnectionStateChanged( - WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - mWifiConnectivityManager.setTrustedConnectionAllowed(true); - - InOrder inOrder = inOrder(mWifiScanner); - - inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any()); - - // Add or update suggestions. - mSuggestionUpdateListenerCaptor.getValue().onSuggestionsAddedOrUpdated( - Arrays.asList(mWifiNetworkSuggestion)); - // Ensure that we restarted PNO. - inOrder.verify(mWifiScanner).stopPnoScan(any()); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any()); - - // Add saved network - mNetworkUpdateListenerCaptor.getValue().onNetworkAdded(new WifiConfiguration()); - // Ensure that we restarted PNO. - inOrder.verify(mWifiScanner).stopPnoScan(any()); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java deleted file mode 100644 index 6fb035462..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Locale; - -/** - * Unit tests for {@link com.android.server.wifi.WifiCountryCode}. - */ -@SmallTest -public class WifiCountryCodeTest extends WifiBaseTest { - - private static final String TAG = "WifiCountryCodeTest"; - private String mDefaultCountryCode = "US"; - private String mTelephonyCountryCode = "JP"; - private boolean mRevertCountryCodeOnCellularLoss = true; - @Mock Context mContext; - MockResources mResources = new MockResources(); - @Mock TelephonyManager mTelephonyManager; - @Mock Handler mHandler; - @Mock WifiNative mWifiNative; - private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - private WifiCountryCode mWifiCountryCode; - - /** - * Setup test. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mWifiNative.setCountryCode(any(), anyString())).thenReturn(true); - when(mContext.getSystemService(Context.TELEPHONY_SERVICE)) - .thenReturn(mTelephonyManager); - - createWifiCountryCode(); - } - - private void createWifiCountryCode() { - mResources.setBoolean(R.bool.config_wifi_revert_country_code_on_cellular_loss, - mRevertCountryCodeOnCellularLoss); - when(mContext.getResources()).thenReturn(mResources); - mWifiCountryCode = new WifiCountryCode( - mContext, - mHandler, - mWifiNative, - mDefaultCountryCode); - verify(mContext, atLeastOnce()).registerReceiver( - mBroadcastReceiverCaptor.capture(), any(), any(), any()); - } - - private void sendCountryCodeChangedBroadcast(String countryCode) { - Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED); - intent.putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, countryCode); - assertNotNull(mBroadcastReceiverCaptor.getValue()); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - } - - /** - * Test if we do not receive country code from Telephony. - * @throws Exception - */ - @Test - public void useDefaultCountryCode() throws Exception { - // Supplicant started. - mWifiCountryCode.setReadyForChange(true); - // Wifi get L2 connected. - mWifiCountryCode.setReadyForChange(false); - verify(mWifiNative).setCountryCode(any(), anyString()); - assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCodeSentToDriver()); - } - - /** - * Test that we read the country code from telephony at bootup. - * @throws Exception - */ - @Test - public void useTelephonyCountryCodeOnBootup() throws Exception { - when(mTelephonyManager.getNetworkCountryIso()).thenReturn(mTelephonyCountryCode); - // Supplicant started. - mWifiCountryCode.setReadyForChange(true); - // Wifi get L2 connected. - mWifiCountryCode.setReadyForChange(false); - verify(mWifiNative).setCountryCode(any(), anyString()); - assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCountryCodeSentToDriver()); - } - - /** - * Test if we receive country code from Telephony before supplicant starts. - * @throws Exception - */ - @Test - public void useTelephonyCountryCodeOnChange() throws Exception { - sendCountryCodeChangedBroadcast(mTelephonyCountryCode); - assertEquals(null, mWifiCountryCode.getCountryCodeSentToDriver()); - // Supplicant started. - mWifiCountryCode.setReadyForChange(true); - // Wifi get L2 connected. - mWifiCountryCode.setReadyForChange(false); - verify(mWifiNative).setCountryCode(any(), anyString()); - assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCountryCodeSentToDriver()); - } - - /** - * Test if we receive country code from Telephony after supplicant starts. - * @throws Exception - */ - @Test - public void telephonyCountryCodeChangeAfterSupplicantStarts() throws Exception { - // Supplicant starts. - mWifiCountryCode.setReadyForChange(true); - assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCodeSentToDriver()); - // Telephony country code arrives. - sendCountryCodeChangedBroadcast(mTelephonyCountryCode); - // Wifi get L2 connected. - mWifiCountryCode.setReadyForChange(false); - verify(mWifiNative, times(2)).setCountryCode(any(), anyString()); - assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCountryCodeSentToDriver()); - } - - /** - * Test if we receive country code from Telephony after we get L2 connected. - * @throws Exception - */ - @Test - public void telephonyCountryCodeChangeAfterL2Connected() throws Exception { - // Supplicant starts. - mWifiCountryCode.setReadyForChange(true); - // Wifi get L2 connected. - mWifiCountryCode.setReadyForChange(false); - // Telephony country code arrives. - sendCountryCodeChangedBroadcast(mTelephonyCountryCode); - // Telephony coutry code won't be applied at this time. - assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCodeSentToDriver()); - mWifiCountryCode.setReadyForChange(true); - // Telephony coutry is applied after supplicant is ready. - verify(mWifiNative, times(2)).setCountryCode(any(), anyString()); - assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCountryCodeSentToDriver()); - } - - /** - * Test if we can reset to the default country code when phone is out of service, when - * |config_wifi_revert_country_code_on_cellular_loss| is set to true; - * Telephony service calls |setCountryCode| with an empty string when phone is out of service. - * In this case we should fall back to the default country code. - * @throws Exception - */ - @Test - public void resetCountryCodeWhenOutOfService() throws Exception { - assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCode()); - sendCountryCodeChangedBroadcast(mTelephonyCountryCode); - assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCountryCode()); - // Out of service. - sendCountryCodeChangedBroadcast(""); - assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCode()); - } - - /** - * Test if we can keep using the last known country code when phone is out of service, when - * |config_wifi_revert_country_code_on_cellular_loss| is set to false; - * Telephony service calls |setCountryCode| with an empty string when phone is out of service. - * In this case we should keep using the last known country code. - * @throws Exception - */ - @Test - public void doNotResetCountryCodeWhenOutOfService() throws Exception { - // Refresh mWifiCountryCode with |config_wifi_revert_country_code_on_cellular_loss| - // setting to false. - mRevertCountryCodeOnCellularLoss = false; - createWifiCountryCode(); - - assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCode()); - sendCountryCodeChangedBroadcast(mTelephonyCountryCode); - assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCountryCode()); - // Out of service. - sendCountryCodeChangedBroadcast(""); - assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCountryCode()); - } - - /** - * Tests that we always use the US locale for converting the provided country code regardless - * of the system locale set. - */ - @Test - public void useUSLocaleForConversionToUpperCase() { - String oemCountryCodeLower = "us"; - String oemCountryCodeUpper = "US"; - String telephonyCountryCodeLower = "il"; - String telephonyCountryCodeUpper = "IL"; - - mDefaultCountryCode = oemCountryCodeLower; - createWifiCountryCode(); - - // Set the default locale to "tr" (Non US). - Locale.setDefault(new Locale("tr")); - - // Trigger a country code change using the OEM country code. - mWifiCountryCode.setReadyForChange(true); - verify(mWifiNative).setCountryCode(any(), eq(oemCountryCodeUpper)); - - // Now trigger a country code change using the telephony country code. - sendCountryCodeChangedBroadcast(telephonyCountryCodeLower); - verify(mWifiNative).setCountryCode(any(), eq(telephonyCountryCodeUpper)); - } - /** - * Verifies that dump() does not fail - */ - @Test - public void dumpDoesNotFail() { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - - mRevertCountryCodeOnCellularLoss = false; - createWifiCountryCode(); - - mWifiCountryCode.dump(null, pw, null); - String dumpCountryCodeStr = sw.toString(); - - assertTrue(dumpCountryCodeStr.contains("mDriverCountryCode")); - assertTrue(dumpCountryCodeStr.contains("mTelephonyCountryCode")); - assertTrue(dumpCountryCodeStr.contains("mDefaultCountryCode")); - assertTrue(dumpCountryCodeStr.contains("mTelephonyCountryTimestamp")); - assertTrue(dumpCountryCodeStr.contains("mDriverCountryTimestamp")); - assertTrue(dumpCountryCodeStr.contains("mReadyTimestamp")); - assertTrue(dumpCountryCodeStr.contains("mReady")); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java b/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java deleted file mode 100644 index de1e5cb4e..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.lenient; -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.wifi.WifiInfo; -import android.os.Handler; -import android.os.test.TestLooper; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -/** - * Unit tests for {@link com.android.server.wifi.WifiDataStall}. - */ -@SmallTest -public class WifiDataStallTest extends WifiBaseTest { - private static final int TEST_MIN_TX_BAD = 1; - private static final int TEST_MIN_TX_SUCCESS_WITHOUT_RX = 1; - private static final long TEST_WIFI_BYTES = - WifiDataStall.MAX_MS_DELTA_FOR_DATA_STALL * 1000 / 8; - - @Mock Context mContext; - MockResources mMockResources = new MockResources(); - @Mock FrameworkFacade mFrameworkFacade; - @Mock WifiChannelUtilization mWifiChannelUtilization; - @Mock WifiMetrics mWifiMetrics; - WifiDataStall mWifiDataStall; - @Mock Clock mClock; - @Mock DeviceConfigFacade mDeviceConfigFacade; - @Mock WifiInfo mWifiInfo; - @Mock TelephonyManager mTelephonyManager; - @Mock Handler mHandler; - @Mock ThroughputPredictor mThroughputPredictor; - @Mock WifiNative.ConnectionCapabilities mCapabilities; - - private final WifiLinkLayerStats mOldLlStats = new WifiLinkLayerStats(); - private final WifiLinkLayerStats mNewLlStats = new WifiLinkLayerStats(); - private MockitoSession mSession; - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - // Ensure Looper exists - // Required by TelephonyManager.listen() - TestLooper looper = new TestLooper(); - when(mContext.getResources()).thenReturn(mMockResources); - when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); - - mMockResources.setInteger( - R.integer.config_wifiPollRssiIntervalMilliseconds, - 3000); - mMockResources.setInteger( - R.integer.config_wifiDataStallMinTxBad, TEST_MIN_TX_BAD); - mMockResources.setInteger( - R.integer.config_wifiDataStallMinTxSuccessWithoutRx, - TEST_MIN_TX_SUCCESS_WITHOUT_RX); - when(mDeviceConfigFacade.getDataStallDurationMs()).thenReturn( - DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - when(mDeviceConfigFacade.getDataStallTxTputThrKbps()).thenReturn( - DeviceConfigFacade.DEFAULT_DATA_STALL_TX_TPUT_THR_KBPS); - when(mDeviceConfigFacade.getDataStallRxTputThrKbps()).thenReturn( - DeviceConfigFacade.DEFAULT_DATA_STALL_RX_TPUT_THR_KBPS); - when(mDeviceConfigFacade.getDataStallTxPerThr()).thenReturn( - DeviceConfigFacade.DEFAULT_DATA_STALL_TX_PER_THR); - when(mDeviceConfigFacade.getDataStallCcaLevelThr()).thenReturn( - DeviceConfigFacade.DEFAULT_DATA_STALL_CCA_LEVEL_THR); - when(mDeviceConfigFacade.getTxTputSufficientLowThrKbps()).thenReturn( - DeviceConfigFacade.DEFAULT_TX_TPUT_SUFFICIENT_THR_LOW_KBPS); - when(mDeviceConfigFacade.getTxTputSufficientHighThrKbps()).thenReturn( - DeviceConfigFacade.DEFAULT_TX_TPUT_SUFFICIENT_THR_HIGH_KBPS); - when(mDeviceConfigFacade.getRxTputSufficientLowThrKbps()).thenReturn( - DeviceConfigFacade.DEFAULT_RX_TPUT_SUFFICIENT_THR_LOW_KBPS); - when(mDeviceConfigFacade.getRxTputSufficientHighThrKbps()).thenReturn( - DeviceConfigFacade.DEFAULT_RX_TPUT_SUFFICIENT_THR_HIGH_KBPS); - when(mDeviceConfigFacade.getTputSufficientRatioThrNum()).thenReturn( - DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM); - when(mDeviceConfigFacade.getTputSufficientRatioThrDen()).thenReturn( - DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_RATIO_THR_DEN); - when(mDeviceConfigFacade.getTxPktPerSecondThr()).thenReturn( - DeviceConfigFacade.DEFAULT_TX_PACKET_PER_SECOND_THR); - when(mDeviceConfigFacade.getRxPktPerSecondThr()).thenReturn( - DeviceConfigFacade.DEFAULT_RX_PACKET_PER_SECOND_THR); - when(mDeviceConfigFacade.getTxLinkSpeedLowThresholdMbps()).thenReturn( - DeviceConfigFacade.DEFAULT_TX_LINK_SPEED_LOW_THRESHOLD_MBPS); - when(mDeviceConfigFacade.getRxLinkSpeedLowThresholdMbps()).thenReturn( - DeviceConfigFacade.DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS); - - when(mWifiInfo.getLinkSpeed()).thenReturn(10); - when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(10); - when(mWifiInfo.getFrequency()).thenReturn(5850); - when(mWifiInfo.getBSSID()).thenReturn("5G_WiFi"); - - mWifiDataStall = new WifiDataStall(mFrameworkFacade, mWifiMetrics, mContext, - mDeviceConfigFacade, mWifiChannelUtilization, mClock, mHandler, - mThroughputPredictor); - mOldLlStats.txmpdu_be = 1000; - mOldLlStats.retries_be = 1000; - mOldLlStats.lostmpdu_be = 3000; - mOldLlStats.rxmpdu_be = 4000; - mOldLlStats.timeStampInMs = 10000; - - mNewLlStats.txmpdu_be = 2 * mOldLlStats.txmpdu_be; - mNewLlStats.retries_be = 10 * mOldLlStats.retries_be; - mNewLlStats.lostmpdu_be = mOldLlStats.lostmpdu_be; - mNewLlStats.rxmpdu_be = mOldLlStats.rxmpdu_be + 100; - mNewLlStats.timeStampInMs = mOldLlStats.timeStampInMs - + WifiDataStall.MAX_MS_DELTA_FOR_DATA_STALL - 1; - when(mWifiChannelUtilization.getUtilizationRatio(anyInt())).thenReturn(10); - when(mThroughputPredictor.predictTxThroughput(any(), anyInt(), anyInt(), anyInt())) - .thenReturn(50); - when(mThroughputPredictor.predictRxThroughput(any(), anyInt(), anyInt(), anyInt())) - .thenReturn(150); - mWifiDataStall.init(); - mWifiDataStall.setConnectionCapabilities(mCapabilities); - setUpWifiBytes(1, 1); - } - - private void setUpWifiBytes(long txBytes, long rxBytes) { - lenient().when(mFrameworkFacade.getTotalTxBytes()).thenReturn(txBytes); - lenient().when(mFrameworkFacade.getTotalRxBytes()).thenReturn(rxBytes); - lenient().when(mFrameworkFacade.getMobileTxBytes()).thenReturn((long) 0); - lenient().when(mFrameworkFacade.getMobileRxBytes()).thenReturn((long) 0); - } - - /** - * Verify that LinkLayerStats for WifiIsUnusableEvent is correctly updated - */ - private void verifyUpdateWifiIsUnusableLinkLayerStats() { - verify(mWifiMetrics).updateWifiIsUnusableLinkLayerStats( - mNewLlStats.txmpdu_be - mOldLlStats.txmpdu_be, - mNewLlStats.retries_be - mOldLlStats.retries_be, - mNewLlStats.lostmpdu_be - mOldLlStats.lostmpdu_be, - mNewLlStats.rxmpdu_be - mOldLlStats.rxmpdu_be, - mNewLlStats.timeStampInMs - mOldLlStats.timeStampInMs); - } - - private PhoneStateListener mockPhoneStateListener() { - PhoneStateListener dataConnectionStateListener = null; - /* Capture the PhoneStateListener */ - ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_DATA_CONNECTION_STATE)); - dataConnectionStateListener = phoneStateListenerCaptor.getValue(); - assertNotNull(dataConnectionStateListener); - return dataConnectionStateListener; - } - - /** - * Test cellular data connection is on and then off - */ - @Test - public void testCellularDataConnectionOnOff() throws Exception { - mWifiDataStall.disablePhoneStateListener(); - mWifiDataStall.enablePhoneStateListener(); - PhoneStateListener phoneStateListener = mockPhoneStateListener(); - phoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, - TelephonyManager.NETWORK_TYPE_LTE); - assertEquals(true, mWifiDataStall.isCellularDataAvailable()); - phoneStateListener.onDataConnectionStateChanged( - TelephonyManager.DATA_DISCONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - assertEquals(false, mWifiDataStall.isCellularDataAvailable()); - mWifiDataStall.disablePhoneStateListener(); - verify(mTelephonyManager, times(1)).listen(phoneStateListener, - PhoneStateListener.LISTEN_NONE); - mWifiDataStall.disablePhoneStateListener(); - verify(mTelephonyManager, times(1)).listen(phoneStateListener, - PhoneStateListener.LISTEN_NONE); - } - - /** - * Verify throughput when Rx link speed is unavailable. - * Also verify the logging of channel utilization and throughput. - */ - @Test - public void verifyThroughputNoRxLinkSpeed() throws Exception { - mWifiDataStall.checkDataStallAndThroughputSufficiency(null, mNewLlStats, mWifiInfo); - verify(mWifiMetrics).incrementChannelUtilizationCount(10, 5850); - verify(mWifiMetrics).incrementThroughputKbpsCount(50_000, 150_000, 5850); - assertEquals(50_000, mWifiDataStall.getTxThroughputKbps()); - assertEquals(150_000, mWifiDataStall.getRxThroughputKbps()); - when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(-1); - mWifiDataStall.checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo); - assertEquals(960, mWifiDataStall.getTxThroughputKbps()); - assertEquals(-1, mWifiDataStall.getRxThroughputKbps()); - verify(mWifiMetrics).incrementThroughputKbpsCount(960, -1, 5850); - } - - /** - * Verify there is a Tx data stall from high Tx PER and low Tx throughput - */ - @Test - public void verifyDataStallTxFailure() throws Exception { - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verify(mWifiMetrics).incrementThroughputKbpsCount(960, 9609, 5850); - verifyUpdateWifiIsUnusableLinkLayerStats(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(false, mWifiDataStall.isThroughputSufficient()); - assertEquals(960, mWifiDataStall.getTxThroughputKbps()); - assertEquals(9609, mWifiDataStall.getRxThroughputKbps()); - verify(mWifiMetrics).logWifiIsUnusableEvent(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); - } - - /** - * Verify there is no data stall if tx tput is above the threshold and Tx per is low - */ - @Test - public void verifyNoDataStallTxFailureWhenTxTputIsHigh() throws Exception { - when(mWifiInfo.getLinkSpeed()).thenReturn(867); - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - mNewLlStats.retries_be = mOldLlStats.retries_be; - - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verifyUpdateWifiIsUnusableLinkLayerStats(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(true, mWifiDataStall.isThroughputSufficient()); - assertEquals(833132, mWifiDataStall.getTxThroughputKbps()); - assertEquals(9609, mWifiDataStall.getRxThroughputKbps()); - verify(mWifiMetrics, never()).logWifiIsUnusableEvent( - WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); - } - - /** - * Verify there is no data stall from tx failures if tx is not consecutively bad - */ - @Test - public void verifyNoDataStallWhenTxFailureIsNotConsecutive() throws Exception { - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(true, mWifiDataStall.isThroughputSufficient()); - verifyUpdateWifiIsUnusableLinkLayerStats(); - - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - mNewLlStats.retries_be = 2 * mOldLlStats.retries_be; - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(true, mWifiDataStall.isThroughputSufficient()); - verify(mWifiMetrics, never()).logWifiIsUnusableEvent( - WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); - } - - /** - * Verify there is a data stall when Rx tput is low - */ - @Test - public void verifyDataStallRxFailure() throws Exception { - when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(1); - mNewLlStats.retries_be = 2 * mOldLlStats.retries_be; - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verifyUpdateWifiIsUnusableLinkLayerStats(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(false, mWifiDataStall.isThroughputSufficient()); - assertEquals(4804, mWifiDataStall.getTxThroughputKbps()); - assertEquals(960, mWifiDataStall.getRxThroughputKbps()); - verify(mWifiMetrics).logWifiIsUnusableEvent( - WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX); - } - - /** - * Verify there is no data stall and throughput is sufficient if there is no sufficient traffic - */ - @Test - public void verifyNoDataStallTrafficLow() throws Exception { - when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(1); - mNewLlStats.txmpdu_be = mOldLlStats.txmpdu_be + 1; - mNewLlStats.retries_be = mOldLlStats.retries_be + 1; - mNewLlStats.lostmpdu_be = mOldLlStats.lostmpdu_be + 1; - mNewLlStats.rxmpdu_be = mOldLlStats.rxmpdu_be + 1; - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verifyUpdateWifiIsUnusableLinkLayerStats(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(true, mWifiDataStall.isThroughputSufficient()); - assertEquals(9128, mWifiDataStall.getTxThroughputKbps()); - assertEquals(-1, mWifiDataStall.getRxThroughputKbps()); - verify(mWifiMetrics, never()).logWifiIsUnusableEvent(anyInt()); - } - - /** - * Verify there is a data stall from low tx and rx throughput - */ - @Test - public void verifyDataStallBothTxRxFailure() throws Exception { - // 1st poll with low tx and rx throughput - when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(1); - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verifyUpdateWifiIsUnusableLinkLayerStats(); - assertEquals(960, mWifiDataStall.getTxThroughputKbps()); - assertEquals(960, mWifiDataStall.getRxThroughputKbps()); - - // 2nd poll with low tx and rx throughput - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(false, mWifiDataStall.isThroughputSufficient()); - assertEquals(960, mWifiDataStall.getTxThroughputKbps()); - assertEquals(960, mWifiDataStall.getRxThroughputKbps()); - verify(mWifiMetrics).logWifiIsUnusableEvent(WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH); - - // 3rd poll with low tx/rx traffic and throughput - when(mWifiInfo.getLinkSpeed()).thenReturn(1); - when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(1); - mNewLlStats.txmpdu_be = mOldLlStats.txmpdu_be + 1; - mNewLlStats.retries_be = mOldLlStats.retries_be + 1; - mNewLlStats.lostmpdu_be = mOldLlStats.lostmpdu_be + 1; - mNewLlStats.rxmpdu_be = mOldLlStats.rxmpdu_be + 1; - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + 2 * DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(false, mWifiDataStall.isThroughputSufficient()); - assertEquals(960, mWifiDataStall.getTxThroughputKbps()); - assertEquals(960, mWifiDataStall.getRxThroughputKbps()); - - // 4th poll with low tx/rx traffic, high throughput and unknown channel utilization - when(mWifiChannelUtilization.getUtilizationRatio(anyInt())).thenReturn(-1); - when(mWifiInfo.getLinkSpeed()).thenReturn(10); - when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(10); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + 2 * DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(true, mWifiDataStall.isThroughputSufficient()); - assertEquals(8943, mWifiDataStall.getTxThroughputKbps()); - assertEquals(9414, mWifiDataStall.getRxThroughputKbps()); - } - - /** - * Verify that we can change the duration of evaluating Wifi conditions - * to trigger data stall from DeviceConfigFacade - */ - @Test - public void verifyDataStallDurationDeviceConfigChange() throws Exception { - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - when(mDeviceConfigFacade.getDataStallDurationMs()).thenReturn( - DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS + 1); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verifyUpdateWifiIsUnusableLinkLayerStats(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(false, mWifiDataStall.isThroughputSufficient()); - verify(mWifiMetrics, never()).logWifiIsUnusableEvent( - WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); - } - - /** - * Verify that we can change the threshold of Tx packet error rate to trigger a data stall - * from DeviceConfigFacade - */ - @Test - public void verifyDataStallTxPerThrDeviceConfigChange() throws Exception { - when(mClock.getElapsedSinceBootMillis()).thenReturn(10L); - when(mDeviceConfigFacade.getDataStallTxPerThr()).thenReturn( - DeviceConfigFacade.DEFAULT_DATA_STALL_TX_PER_THR + 1); - when(mDeviceConfigFacade.getDataStallTxTputThrKbps()).thenReturn(800); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verifyUpdateWifiIsUnusableLinkLayerStats(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 10L + DeviceConfigFacade.DEFAULT_DATA_STALL_DURATION_MS); - setUpWifiBytes(TEST_WIFI_BYTES, TEST_WIFI_BYTES); - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - assertEquals(false, mWifiDataStall.isThroughputSufficient()); - verify(mWifiMetrics, never()).logWifiIsUnusableEvent( - WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); - } - - /** - * Verify there is no data stall when there are no new tx/rx failures - */ - @Test - public void verifyNoDataStallWhenNoFail() throws Exception { - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verify(mWifiMetrics, never()).resetWifiIsUnusableLinkLayerStats(); - verifyUpdateWifiIsUnusableLinkLayerStats(); - verify(mWifiMetrics, never()).logWifiIsUnusableEvent(anyInt()); - } - - /** - * Verify there is no data stall when the time difference between - * two WifiLinkLayerStats is too big. - */ - @Test - public void verifyNoDataStallBigTimeGap() throws Exception { - mNewLlStats.lostmpdu_be = mOldLlStats.lostmpdu_be + TEST_MIN_TX_BAD; - mNewLlStats.timeStampInMs = mOldLlStats.timeStampInMs - + WifiDataStall.MAX_MS_DELTA_FOR_DATA_STALL + 1; - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verifyUpdateWifiIsUnusableLinkLayerStats(); - verify(mWifiMetrics, never()).logWifiIsUnusableEvent(anyInt()); - } - - /** - * Verify that metrics get reset when there is a reset in WifiLinkLayerStats - */ - @Test - public void verifyReset() throws Exception { - mNewLlStats.lostmpdu_be = mOldLlStats.lostmpdu_be - 1; - assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiDataStall - .checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo)); - verify(mWifiMetrics).resetWifiIsUnusableLinkLayerStats(); - verify(mWifiMetrics, never()).updateWifiIsUnusableLinkLayerStats( - anyLong(), anyLong(), anyLong(), anyLong(), anyLong()); - verify(mWifiMetrics, never()).logWifiIsUnusableEvent(anyInt()); - } - - /** - * Check incrementConnectionDuration under various conditions - */ - @Test - public void testIncrementConnectionDuration() throws Exception { - mWifiDataStall.enablePhoneStateListener(); - PhoneStateListener phoneStateListener = mockPhoneStateListener(); - phoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, - TelephonyManager.NETWORK_TYPE_LTE); - assertEquals(true, mWifiDataStall.isCellularDataAvailable()); - mNewLlStats.timeStampInMs = mOldLlStats.timeStampInMs + 1000; - // Expect 1st throughput sufficiency check to return true - // because it hits mLastTxBytes == 0 || mLastRxBytes == 0 - mWifiDataStall.checkDataStallAndThroughputSufficiency( - mOldLlStats, mNewLlStats, mWifiInfo); - verify(mWifiMetrics, times(1)).incrementConnectionDuration( - 1000, true, true); - - // Expect 2nd throughput sufficiency check to return false - mWifiDataStall.checkDataStallAndThroughputSufficiency( - mOldLlStats, mNewLlStats, mWifiInfo); - verify(mWifiMetrics, times(1)).incrementConnectionDuration( - 1000, false, true); - - - mNewLlStats.timeStampInMs = mOldLlStats.timeStampInMs + 2000; - phoneStateListener.onDataConnectionStateChanged( - TelephonyManager.DATA_DISCONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - assertEquals(false, mWifiDataStall.isCellularDataAvailable()); - mWifiDataStall.checkDataStallAndThroughputSufficiency( - mOldLlStats, mNewLlStats, mWifiInfo); - verify(mWifiMetrics, times(1)).incrementConnectionDuration( - 2000, false, false); - - // Expect this update to be ignored by connection duration counters due to its - // too large poll interval - mNewLlStats.timeStampInMs = mOldLlStats.timeStampInMs + 10000; - mWifiDataStall.checkDataStallAndThroughputSufficiency( - mOldLlStats, mNewLlStats, mWifiInfo); - verify(mWifiMetrics, never()).incrementConnectionDuration( - 10000, false, false); - mWifiDataStall.disablePhoneStateListener(); - } - - /** - * Check statsd logging - */ - @Test - public void testWifiStatsLogWrite() throws Exception { - mWifiDataStall.enableVerboseLogging(true); - mWifiDataStall.enablePhoneStateListener(); - PhoneStateListener phoneStateListener = mockPhoneStateListener(); - phoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, - TelephonyManager.NETWORK_TYPE_LTE); - // static mocking for WifiStatsLog - mSession = ExtendedMockito.mockitoSession() - .strictness(Strictness.LENIENT) - .mockStatic(WifiStatsLog.class) - .startMocking(); - mNewLlStats.timeStampInMs = mOldLlStats.timeStampInMs + 3000; - when(mWifiInfo.getFrequency()).thenReturn(5850); - mWifiDataStall.checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo); - ExtendedMockito.verify(() -> WifiStatsLog.write( - WifiStatsLog.WIFI_HEALTH_STAT_REPORTED, 3000, true, true, - WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_5G_HIGH)); - - mNewLlStats.timeStampInMs = mOldLlStats.timeStampInMs + 2000; - when(mWifiInfo.getFrequency()).thenReturn(6850); - mWifiDataStall.checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo); - ExtendedMockito.verify(() -> WifiStatsLog.write( - WifiStatsLog.WIFI_HEALTH_STAT_REPORTED, 2000, true, true, - WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_6G_MIDDLE)); - - mNewLlStats.timeStampInMs = mOldLlStats.timeStampInMs + 1000; - when(mWifiInfo.getFrequency()).thenReturn(1850); - mWifiDataStall.checkDataStallAndThroughputSufficiency(mOldLlStats, mNewLlStats, mWifiInfo); - ExtendedMockito.verify(() -> WifiStatsLog.write( - WifiStatsLog.WIFI_HEALTH_STAT_REPORTED, 1000, true, true, - WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__UNKNOWN)); - mSession.finishMocking(); - mWifiDataStall.disablePhoneStateListener(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java deleted file mode 100644 index e72f80887..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java +++ /dev/null @@ -1,1076 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.AdditionalMatchers.gt; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.contains; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.content.Context; -import android.os.BugreportManager; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.io.ByteArrayInputStream; -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.regex.Pattern; - -/** - * Unit tests for {@link WifiDiagnostics}. - */ -@SmallTest -public class WifiDiagnosticsTest extends WifiBaseTest { - @Mock WifiNative mWifiNative; - @Mock BuildProperties mBuildProperties; - @Mock Context mContext; - @Mock WifiInjector mWifiInjector; - @Mock DeviceConfigFacade mDeviceConfigFacade; - @Spy FakeWifiLog mLog; - @Mock LastMileLogger mLastMileLogger; - @Mock Runtime mJavaRuntime; - @Mock Process mExternalProcess; - @Mock WifiMetrics mWifiMetrics; - @Mock Clock mClock; - @Mock BugreportManager mBugreportManager; - @Mock WifiScoreCard mWifiScoreCard; - private long mBootTimeMs = 0L; - MockResources mResources; - WifiDiagnostics mWifiDiagnostics; - - private static final String FAKE_RING_BUFFER_NAME = "fake-ring-buffer"; - private static final String STA_IF_NAME = "wlan0"; - private static final String AP_IF_NAME = "wlan1"; - private static final int SMALL_RING_BUFFER_SIZE_KB = 32; - private static final int LARGE_RING_BUFFER_SIZE_KB = 1024; - private static final int BYTES_PER_KBYTE = 1024; - private static final int ALERT_REASON_CODE = 1; - private static final byte[] ALERT_DATA = {0 , 4, 5}; - /** Mock resource for fatal firmware alert list */ - private static final int[] FATAL_FW_ALERT_LIST = {256, 257, 258}; - /** Mock a non fatal firmware alert */ - private static final int NON_FATAL_FW_ALERT = 0; - private static final int BUG_REPORT_MIN_WINDOW_MS = 3600_000; - - private WifiNative.RingBufferStatus mFakeRbs; - /** - * Returns the data that we would dump in a bug report, for our ring buffer. - * @return a 2-D byte array, where the first dimension is the record number, and the second - * dimension is the byte index within that record. - */ - private final byte[][] getLoggerRingBufferData() throws Exception { - return mWifiDiagnostics.getBugReports().get(0).ringBuffers.get(FAKE_RING_BUFFER_NAME); - } - - /** - * Initializes common state (e.g. mocks) needed by test cases. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mFakeRbs = new WifiNative.RingBufferStatus(); - mFakeRbs.name = FAKE_RING_BUFFER_NAME; - WifiNative.RingBufferStatus[] ringBufferStatuses = new WifiNative.RingBufferStatus[] { - mFakeRbs - }; - - when(mWifiNative.getRingBufferStatus()).thenReturn(ringBufferStatuses); - when(mBuildProperties.isEngBuild()).thenReturn(false); - when(mBuildProperties.isUserdebugBuild()).thenReturn(false); - when(mBuildProperties.isUserBuild()).thenReturn(true); - when(mExternalProcess.getInputStream()).thenReturn(new ByteArrayInputStream(new byte[0])); - when(mExternalProcess.getErrorStream()).thenReturn(new ByteArrayInputStream(new byte[0])); - when(mJavaRuntime.exec(anyString())).thenReturn(mExternalProcess); - - mResources = new MockResources(); - mResources.setInteger(R.integer.config_wifi_logger_ring_buffer_default_size_limit_kb, - SMALL_RING_BUFFER_SIZE_KB); - mResources.setInteger(R.integer.config_wifi_logger_ring_buffer_verbose_size_limit_kb, - LARGE_RING_BUFFER_SIZE_KB); - mResources.setIntArray(R.array.config_wifi_fatal_firmware_alert_error_code_list, - FATAL_FW_ALERT_LIST); - mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, true); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getSystemService(BugreportManager.class)).thenReturn(mBugreportManager); - when(mWifiInjector.makeLog(anyString())).thenReturn(mLog); - when(mWifiInjector.getJavaRuntime()).thenReturn(mJavaRuntime); - when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); - when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade); - when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard); - when(mDeviceConfigFacade.getBugReportMinWindowMs()).thenReturn(BUG_REPORT_MIN_WINDOW_MS); - // needed to for the loop in WifiDiagnostics.readLogcatStreamLinesWithTimeout(). - doAnswer(new AnswerWithArguments() { - public long answer() throws Exception { - mBootTimeMs += WifiDiagnostics.LOGCAT_READ_TIMEOUT_MILLIS / 2; - return mBootTimeMs; - } - }).when(mClock).getElapsedSinceBootMillis(); - mWifiDiagnostics = new WifiDiagnostics( - mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock); - mWifiNative.enableVerboseLogging(0); - } - - /** Verifies that startLogging() registers a logging event handler. */ - @Test - public void startLoggingRegistersLogEventHandler() throws Exception { - mWifiDiagnostics.enableVerboseLogging(false); - mWifiDiagnostics.startLogging(STA_IF_NAME); - verify(mWifiNative).setLoggingEventHandler(anyObject()); - } - - /** - * Verifies that a failure to set the logging event handler does not prevent a future - * startLogging() from setting the logging event handler. - */ - @Test - public void startLoggingRegistersLogEventHandlerIfPriorAttemptFailed() - throws Exception { - final boolean verbosityToggle = false; // even default mode registers handler - - when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(false); - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - verify(mWifiNative).setLoggingEventHandler(anyObject()); - mWifiDiagnostics.stopLogging(STA_IF_NAME); - reset(mWifiNative); - - when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - verify(mWifiNative).setLoggingEventHandler(anyObject()); - } - - /** Verifies that startLogging() does not make redundant calls to setLoggingEventHandler(). */ - @Test - public void startLoggingDoesNotRegisterLogEventHandlerIfPriorAttemptSucceeded() - throws Exception { - when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); - mWifiDiagnostics.enableVerboseLogging(false); - mWifiDiagnostics.startLogging(STA_IF_NAME); - verify(mWifiNative).setLoggingEventHandler(anyObject()); - reset(mWifiNative); - - mWifiDiagnostics.enableVerboseLogging(false); - mWifiDiagnostics.startLogging(STA_IF_NAME); - verify(mWifiNative, never()).setLoggingEventHandler(anyObject()); - } - - /** - * Verifies that startLogging() restarts HAL ringbuffers. - * - * Specifically: verifies that startLogging() - * a) stops any ring buffer logging that might be already running, - * b) instructs WifiNative to enable ring buffers of the appropriate log level. - */ - @Test - public void startLoggingStopsAndRestartsRingBufferLoggingInVerboseMode() throws Exception { - final boolean verbosityToggle = true; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - verify(mWifiNative).startLoggingRingBuffer( - eq(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(), - eq(FAKE_RING_BUFFER_NAME)); - verify(mWifiNative).startLoggingRingBuffer( - eq(WifiDiagnostics.VERBOSE_LOG_WITH_WAKEUP), anyInt(), anyInt(), anyInt(), - eq(FAKE_RING_BUFFER_NAME)); - } - - @Test - public void startLoggingStopsAndThenStartRingBufferLoggingInNormalMode() throws Exception { - final boolean verbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - verify(mWifiNative).startLoggingRingBuffer( - eq(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(), - eq(FAKE_RING_BUFFER_NAME)); - verify(mWifiNative).startLoggingRingBuffer( - gt(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(), - anyString()); - } - - /** Verifies that, if a log handler was registered, then stopLogging() resets it. */ - @Test - public void stopLoggingResetsLogHandlerIfHandlerWasRegistered() throws Exception { - final boolean verbosityToggle = false; // even default mode registers handler - - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); - mWifiDiagnostics.startLogging(STA_IF_NAME); - reset(mWifiNative); - - mWifiDiagnostics.stopLogging(STA_IF_NAME); - verify(mWifiNative).resetLogHandler(); - } - - /** Verifies that, if a log handler is not registered, stopLogging() skips resetLogHandler(). */ - @Test - public void stopLoggingOnlyResetsLogHandlerIfHandlerWasRegistered() throws Exception { - mWifiDiagnostics.stopLogging(STA_IF_NAME); - verify(mWifiNative, never()).resetLogHandler(); - } - - /** Verifies that stopLogging() remembers that we've reset the log handler. */ - @Test - public void multipleStopLoggingCallsOnlyResetLogHandlerOnce() throws Exception { - final boolean verbosityToggle = false; // even default mode registers handler - - when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - reset(mWifiNative); - - when(mWifiNative.resetLogHandler()).thenReturn(true); - mWifiDiagnostics.stopLogging(STA_IF_NAME); - verify(mWifiNative).resetLogHandler(); - reset(mWifiNative); - - mWifiDiagnostics.stopLogging(STA_IF_NAME); - verify(mWifiNative, never()).resetLogHandler(); - } - - /** - * Verifies that we capture ring-buffer data. - */ - @Test - public void canCaptureAndStoreRingBufferData() throws Exception { - final boolean verbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - - final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]; - mWifiDiagnostics.onRingBufferData(mFakeRbs, data); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - - byte[][] ringBufferData = getLoggerRingBufferData(); - assertEquals(1, ringBufferData.length); - assertArrayEquals(data, ringBufferData[0]); - } - - /** - * Verifies that we discard extraneous ring-buffer data. - */ - @Ignore("TODO(b/36811399): re-enabled this @Test") - @Test - public void loggerDiscardsExtraneousData() throws Exception { - final boolean verbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - - final byte[] data1 = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]; - final byte[] data2 = {1, 2, 3}; - mWifiDiagnostics.onRingBufferData(mFakeRbs, data1); - mWifiDiagnostics.onRingBufferData(mFakeRbs, data2); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - - byte[][] ringBufferData = getLoggerRingBufferData(); - assertEquals(1, ringBufferData.length); - assertArrayEquals(data2, ringBufferData[0]); - } - - // Verifies that startPktFateMonitoring(any()) reports failure to start packet fate - @Test - public void startPktFateMonitoringReportsStartFailures() { - when(mWifiNative.startPktFateMonitoring(any())).thenReturn(false); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - verify(mLog).wC(contains("Failed")); - } - - /** - * Verifies that, when verbose mode is not enabled, - * reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED) still fetches packet fates. - */ - @Test - public void reportConnectionFailureIsIgnoredWithoutVerboseMode() { - final boolean verbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - verify(mWifiNative).getTxPktFates(any(), anyObject()); - verify(mWifiNative).getRxPktFates(any(), anyObject()); - } - - /** - * Verifies that, when verbose mode is enabled, reportConnectionFailure() fetches packet fates. - */ - @Test - public void reportConnectionFailureFetchesFatesInVerboseMode() { - final boolean verbosityToggle = true; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - verify(mWifiNative).getTxPktFates(any(), anyObject()); - verify(mWifiNative).getRxPktFates(any(), anyObject()); - } - - @Test - public void reportConnectionEventPropagatesStartToLastMileLogger() { - final boolean verbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED); - verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED); - } - - @Test - public void reportConnectionEventPropagatesSuccessToLastMileLogger() { - final boolean verbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); - verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); - } - - @Test - public void reportConnectionEventPropagatesFailureToLastMileLogger() { - final boolean verbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - } - - /** - * Verifies that we are propagating the CONNECTION_EVENT_TIMEOUT event to LastMileLogger. - */ - @Test - public void reportConnectionEventPropagatesTimeoutToLastMileLogger() { - final boolean verbosityToggle = true; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT); - verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT); - } - - /** - * Verifies that we try to fetch TX fates, even if fetching RX fates failed. - */ - @Test - public void loggerFetchesTxFatesEvenIfFetchingRxFatesFails() { - final boolean verbosityToggle = true; - when(mWifiNative.getRxPktFates(any(), anyObject())).thenReturn(false); - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - verify(mWifiNative).getTxPktFates(any(), anyObject()); - verify(mWifiNative).getRxPktFates(any(), anyObject()); - } - - /** - * Verifies that we try to fetch RX fates, even if fetching TX fates failed. - */ - @Test - public void loggerFetchesRxFatesEvenIfFetchingTxFatesFails() { - final boolean verbosityToggle = true; - when(mWifiNative.getTxPktFates(any(), anyObject())).thenReturn(false); - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - verify(mWifiNative).getTxPktFates(any(), anyObject()); - verify(mWifiNative).getRxPktFates(any(), anyObject()); - } - - /** Verifies that dump() fetches the latest fates. */ - @Test - public void dumpFetchesFates() { - final boolean verbosityToggle = false; - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); - verify(mWifiNative).getTxPktFates(any(), anyObject()); - verify(mWifiNative).getRxPktFates(any(), anyObject()); - } - - /** - * Verifies that dump() doesn't crash, or generate garbage, in the case where we haven't fetched - * any fates. - */ - @Test - public void dumpSucceedsWhenNoFatesHaveNotBeenFetched() { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); - - String fateDumpString = sw.toString(); - assertTrue(fateDumpString.contains("Last failed")); - // Verify dump terminator is present - assertTrue(fateDumpString.contains( - "--------------------------------------------------------------------")); - } - - /** - * Verifies that dump() doesn't crash, or generate garbage, in the case where the fates that - * the HAL-provided fates are empty. - */ - @Test - public void dumpSucceedsWhenFatesHaveBeenFetchedButAreEmpty() { - final boolean verbosityToggle = true; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - verify(mWifiNative).getTxPktFates(any(), anyObject()); - verify(mWifiNative).getRxPktFates(any(), anyObject()); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); - - String fateDumpString = sw.toString(); - assertTrue(fateDumpString.contains("Last failed")); - // Verify dump terminator is present - assertTrue(fateDumpString.contains( - "--------------------------------------------------------------------")); - } - - private String getDumpString(boolean verbose) { - mWifiDiagnostics.enableVerboseLogging(verbose); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiNative.enableVerboseLogging(verbose ? 1 : 0); - when(mWifiNative.getTxPktFates(any(), anyObject())).then(new AnswerWithArguments() { - public boolean answer(String ifaceName, WifiNative.TxFateReport[] fates) { - fates[0] = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_ACKED, 2, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - fates[1] = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - return true; - } - }); - when(mWifiNative.getRxPktFates(any(), anyObject())).then(new AnswerWithArguments() { - public boolean answer(String ifaceName, WifiNative.RxFateReport[] fates) { - fates[0] = new WifiNative.RxFateReport( - WifiLoggerHal.RX_PKT_FATE_SUCCESS, 3, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - fates[1] = new WifiNative.RxFateReport( - WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - return true; - } - }); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); - return sw.toString(); - } - - /** - * Verifies that dump() shows both TX, and RX fates in only table form, when verbose - * logging is not enabled. - */ - @Test - public void dumpShowsTxAndRxFates() { - final boolean verbosityToggle = false; - String dumpString = getDumpString(verbosityToggle); - assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); - assertTrue(Pattern.compile("0 .* TX ").matcher(dumpString).find()); - assertTrue(Pattern.compile("1 .* RX ").matcher(dumpString).find()); - assertTrue(Pattern.compile("2 .* TX ").matcher(dumpString).find()); - assertTrue(Pattern.compile("3 .* RX ").matcher(dumpString).find()); - assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP")); - assertFalse(dumpString.contains("Frame bytes")); - } - - /** - * Verifies that dump() shows both TX, and RX fates in table and verbose forms, when verbose - * logging is enabled. - */ - @Test - public void dumpShowsTxAndRxFatesVerbose() { - final boolean verbosityToggle = true; - String dumpString = getDumpString(verbosityToggle); - assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); - assertTrue(Pattern.compile("0 .* TX ").matcher(dumpString).find()); - assertTrue(Pattern.compile("1 .* RX ").matcher(dumpString).find()); - assertTrue(Pattern.compile("2 .* TX ").matcher(dumpString).find()); - assertTrue(Pattern.compile("3 .* RX ").matcher(dumpString).find()); - assertTrue(dumpString.contains("VERBOSE PACKET FATE DUMP")); - assertTrue(dumpString.contains("Frame bytes")); - } - - /** - * Verifies that dump() outputs frames in timestamp order, even though the HAL provided the - * data out-of-order (order is specified in getDumpString()). - */ - @Test - public void dumpIsSortedByTimestamp() { - final boolean verbosityToggle = true; - String dumpString = getDumpString(verbosityToggle); - assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); - assertTrue(Pattern.compile( - "0 .* TX .*\n" + - "1 .* RX .*\n" + - "2 .* TX .*\n" + - "3 .* RX " - ).matcher(dumpString).find()); - - int expected_index_of_verbose_frame_0 = dumpString.indexOf( - "Frame direction: TX\nFrame timestamp: 0\n"); - int expected_index_of_verbose_frame_1 = dumpString.indexOf( - "Frame direction: RX\nFrame timestamp: 1\n"); - int expected_index_of_verbose_frame_2 = dumpString.indexOf( - "Frame direction: TX\nFrame timestamp: 2\n"); - int expected_index_of_verbose_frame_3 = dumpString.indexOf( - "Frame direction: RX\nFrame timestamp: 3\n"); - assertFalse(-1 == expected_index_of_verbose_frame_0); - assertFalse(-1 == expected_index_of_verbose_frame_1); - assertFalse(-1 == expected_index_of_verbose_frame_2); - assertFalse(-1 == expected_index_of_verbose_frame_3); - assertTrue(expected_index_of_verbose_frame_0 < expected_index_of_verbose_frame_1); - assertTrue(expected_index_of_verbose_frame_1 < expected_index_of_verbose_frame_2); - assertTrue(expected_index_of_verbose_frame_2 < expected_index_of_verbose_frame_3); - } - - /** Verifies that eng builds do not show fate detail outside of verbose mode. */ - @Test - public void dumpOmitsFateDetailInEngBuildsOutsideOfVerboseMode() throws Exception { - final boolean verbosityToggle = false; - when(mBuildProperties.isEngBuild()).thenReturn(true); - when(mBuildProperties.isUserdebugBuild()).thenReturn(false); - when(mBuildProperties.isUserBuild()).thenReturn(false); - String dumpString = getDumpString(verbosityToggle); - assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP")); - assertFalse(dumpString.contains("Frame bytes")); - } - - /** Verifies that userdebug builds do not show fate detail outside of verbose mode. */ - @Test - public void dumpOmitsFateDetailInUserdebugBuildsOutsideOfVerboseMode() throws Exception { - final boolean verbosityToggle = false; - when(mBuildProperties.isUserdebugBuild()).thenReturn(true); - when(mBuildProperties.isEngBuild()).thenReturn(false); - when(mBuildProperties.isUserBuild()).thenReturn(false); - String dumpString = getDumpString(verbosityToggle); - assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP")); - assertFalse(dumpString.contains("Frame bytes")); - } - - /** - * Verifies that, if verbose is disabled after fetching fates, the dump does not include - * verbose fate logs. - */ - @Test - public void dumpOmitsFatesIfVerboseIsDisabledAfterFetch() { - final boolean verbosityToggle = true; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME); - when(mWifiNative.getTxPktFates(any(), anyObject())).then(new AnswerWithArguments() { - public boolean answer(String ifaceName, WifiNative.TxFateReport[] fates) { - fates[0] = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - return true; - } - }); - when(mWifiNative.getRxPktFates(any(), anyObject())).then(new AnswerWithArguments() { - public boolean answer(String ifaceName, WifiNative.RxFateReport[] fates) { - fates[0] = new WifiNative.RxFateReport( - WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - return true; - } - }); - mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); - verify(mWifiNative).getTxPktFates(any(), anyObject()); - verify(mWifiNative).getRxPktFates(any(), anyObject()); - - final boolean newVerbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(newVerbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); - - String fateDumpString = sw.toString(); - assertFalse(fateDumpString.contains("VERBOSE PACKET FATE DUMP")); - assertFalse(fateDumpString.contains("Frame bytes")); - } - - /** Verifies that the default size of our ring buffers is small. */ - @Ignore("TODO(b/36811399): re-enable this @Test") - @Test - public void ringBufferSizeIsSmallByDefault() throws Exception { - final boolean verbosityToggle = false; - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.onRingBufferData( - mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - assertEquals(0, getLoggerRingBufferData().length); - } - - /** Verifies that we use small ring buffers by default, on userdebug builds. */ - @Ignore("TODO(b/36811399): re-enable this @Test") - @Test - public void ringBufferSizeIsSmallByDefaultOnUserdebugBuilds() throws Exception { - final boolean verbosityToggle = false; - when(mBuildProperties.isUserdebugBuild()).thenReturn(true); - when(mBuildProperties.isEngBuild()).thenReturn(false); - when(mBuildProperties.isUserBuild()).thenReturn(false); - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.onRingBufferData( - mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - assertEquals(0, getLoggerRingBufferData().length); - } - - /** Verifies that we use small ring buffers by default, on eng builds. */ - @Ignore("TODO(b/36811399): re-enable this @Test") - @Test - public void ringBufferSizeIsSmallByDefaultOnEngBuilds() throws Exception { - final boolean verbosityToggle = false; - when(mBuildProperties.isEngBuild()).thenReturn(true); - when(mBuildProperties.isUserdebugBuild()).thenReturn(false); - when(mBuildProperties.isUserBuild()).thenReturn(false); - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.onRingBufferData( - mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - assertEquals(0, getLoggerRingBufferData().length); - } - - /** Verifies that we use large ring buffers when initially started in verbose mode. */ - @Test - public void ringBufferSizeIsLargeInVerboseMode() throws Exception { - final boolean verbosityToggle = true; - - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.onRingBufferData( - mFakeRbs, new byte[LARGE_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - assertEquals(1, getLoggerRingBufferData().length); - } - - /** Verifies that we use large ring buffers when switched from normal to verbose mode. */ - @Test - public void startLoggingGrowsRingBuffersIfNeeded() throws Exception { - mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.onRingBufferData( - mFakeRbs, new byte[LARGE_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - assertEquals(1, getLoggerRingBufferData().length); - } - - /** Verifies that we use small ring buffers when switched from verbose to normal mode. */ - @Ignore("TODO(b/36811399): re-enabled this @Test") - @Test - public void startLoggingShrinksRingBuffersIfNeeded() throws Exception { - - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.onRingBufferData( - mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); - - // Existing data is nuked (too large). - mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - assertEquals(0, getLoggerRingBufferData().length); - - // New data must obey limit as well. - mWifiDiagnostics.onRingBufferData( - mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - assertEquals(0, getLoggerRingBufferData().length); - } - - /** - * Verifies that we capture a bugreport & store alert data when WifiNative invokes - * the alert callback. - */ - @Test - public void onWifiAlertCapturesBugreportAndLogsMetrics() throws Exception { - mWifiDiagnostics.onWifiAlert(ALERT_REASON_CODE, ALERT_DATA); - - assertEquals(1, mWifiDiagnostics.getAlertReports().size()); - WifiDiagnostics.BugReport alertReport = mWifiDiagnostics.getAlertReports().get(0); - assertEquals(ALERT_REASON_CODE, alertReport.errorCode); - assertArrayEquals(ALERT_DATA, alertReport.alertData); - - verify(mWifiMetrics).logFirmwareAlert(ALERT_REASON_CODE); - verify(mWifiScoreCard).noteFirmwareAlert(ALERT_REASON_CODE); - } - - /** Verifies that we skip the firmware and driver dumps if verbose is not enabled. */ - @Test - public void captureBugReportSkipsFirmwareAndDriverDumpsByDefault() { - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative, never()).getFwMemoryDump(); - verify(mWifiNative, never()).getDriverStateDump(); - } - - /** Verifies that we capture the firmware and driver dumps if verbose is enabled. */ - @Test - public void captureBugReportTakesFirmwareAndDriverDumpsInVerboseMode() { - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative).getFwMemoryDump(); - verify(mWifiNative).getDriverStateDump(); - } - - /** Verifies that the dump includes driver state, if driver state was provided by HAL. */ - @Test - public void dumpIncludesDriverStateDumpIfAvailable() { - when(mWifiNative.getDriverStateDump()).thenReturn(new byte[]{0, 1, 2}); - - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative).getDriverStateDump(); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); - assertTrue(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER)); - } - - /** Verifies that the dump skips driver state, if driver state was not provided by HAL. */ - @Test - public void dumpOmitsDriverStateDumpIfUnavailable() { - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative).getDriverStateDump(); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); - assertFalse(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER)); - } - - /** Verifies that the dump omits driver state, if verbose was disabled after capture. */ - @Test - public void dumpOmitsDriverStateDumpIfVerboseDisabledAfterCapture() { - when(mWifiNative.getDriverStateDump()).thenReturn(new byte[]{0, 1, 2}); - - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative).getDriverStateDump(); - - mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); - assertFalse(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER)); - } - - /** Verifies that the dump includes firmware dump, if firmware dump was provided by HAL. */ - @Test - public void dumpIncludesFirmwareMemoryDumpIfAvailable() { - when(mWifiNative.getFwMemoryDump()).thenReturn(new byte[]{0, 1, 2}); - - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative).getFwMemoryDump(); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); - assertTrue(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER)); - } - - /** Verifies that the dump skips firmware memory, if firmware memory was not provided by HAL. */ - @Test - public void dumpOmitsFirmwareMemoryDumpIfUnavailable() { - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative).getFwMemoryDump(); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); - assertFalse(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER)); - } - - /** Verifies that the dump omits firmware memory, if verbose was disabled after capture. */ - @Test - public void dumpOmitsFirmwareMemoryDumpIfVerboseDisabledAfterCapture() { - when(mWifiNative.getFwMemoryDump()).thenReturn(new byte[]{0, 1, 2}); - - mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative).getFwMemoryDump(); - - mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */); - mWifiDiagnostics.startLogging(STA_IF_NAME); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); - assertFalse(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER)); - } - - @Test - public void dumpRequestsLastMileLoggerDump() { - mWifiDiagnostics.dump( - new FileDescriptor(), new PrintWriter(new StringWriter()), new String[]{}); - verify(mLastMileLogger).dump(anyObject()); - } - - @Test - public void takeBugReportCallsActivityManagerOnUserDebug() { - when(mBuildProperties.isUserBuild()).thenReturn(false); - mWifiDiagnostics.takeBugReport("", ""); - verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any()); - } - - @Test - public void takeBugReportSwallowsExceptions() { - when(mBuildProperties.isUserBuild()).thenReturn(false); - doThrow(new RuntimeException()).when(mBugreportManager).requestBugreport( - any(), any(), any()); - mWifiDiagnostics.takeBugReport("", ""); - verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any()); - } - - @Test - public void takeBugReportDoesNothingOnUserBuild() { - when(mBuildProperties.isUserBuild()).thenReturn(true); - mWifiDiagnostics.takeBugReport("", ""); - verify(mBugreportManager, never()).requestBugreport(any(), any(), any()); - } - - @Test - public void tryTakeBugReportTwiceWithInsufficientTimeGap() { - when(mBuildProperties.isUserBuild()).thenReturn(false); - // 1st attempt should succeed - when(mClock.getWallClockMillis()).thenReturn(10L); - mWifiDiagnostics.takeBugReport("", ""); - verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any()); - // 2nd attempt should fail - when(mClock.getWallClockMillis()).thenReturn(BUG_REPORT_MIN_WINDOW_MS - 20L); - mWifiDiagnostics.takeBugReport("", ""); - verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any()); - } - - @Test - public void takeBugReportDoesNothingWhenConfigOverlayDisabled() { - when(mBuildProperties.isUserBuild()).thenReturn(false); - mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, false); - mWifiDiagnostics = new WifiDiagnostics( - mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock); - - mWifiDiagnostics.takeBugReport("", ""); - verify(mBugreportManager, never()).requestBugreport(any(), any(), any()); - } - - /** Verifies that we flush HAL ringbuffer when capture bugreport. */ - @Test - public void captureBugReportFlushRingBufferData() { - when(mBuildProperties.isUserBuild()).thenReturn(false); - when(mWifiNative.flushRingBufferData()).thenReturn(true); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - verify(mWifiNative).flushRingBufferData(); - } - - /** Verifies that we flush HAL ringbuffer when detecting fatal firmware alert. */ - @Test - public void captureAlertFlushRingBufferData() { - when(mBuildProperties.isUserBuild()).thenReturn(false); - when(mWifiNative.flushRingBufferData()).thenReturn(true); - /** captureAlertData with mock fatal firmware alert*/ - mWifiDiagnostics.captureAlertData(FATAL_FW_ALERT_LIST[0], ALERT_DATA); - verify(mWifiNative).flushRingBufferData(); - } - - /** Verifies that we don't flush HAL ringbuffer when detecting non fatal firmware alert. */ - @Test - public void captureNonAlertFlushRingBufferData() { - when(mBuildProperties.isUserBuild()).thenReturn(false); - when(mWifiNative.flushRingBufferData()).thenReturn(true); - /** captureAlertData with mock non fatal firmware alert*/ - mWifiDiagnostics.captureAlertData(NON_FATAL_FW_ALERT, ALERT_DATA); - verify(mWifiNative, never()).flushRingBufferData(); - } - - /** - * Verifies that we can capture ring-buffer data in SoftAp mode - */ - @Test - public void canCaptureAndStoreRingBufferDataInSoftApMode() throws Exception { - final boolean verbosityToggle = false; - - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(AP_IF_NAME); - - final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]; - mWifiDiagnostics.onRingBufferData(mFakeRbs, data); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - - byte[][] ringBufferData = getLoggerRingBufferData(); - assertEquals(1, ringBufferData.length); - assertArrayEquals(data, ringBufferData[0]); - } - - /** - * Verifies that we capture ring-buffer data in Station + SoftAp - * Concurrency mode. - */ - @Test - public void canCaptureAndStoreRingBufferDataInConcurrencyMode() throws Exception { - final boolean verbosityToggle = false; - - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.startLogging(AP_IF_NAME); - - final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]; - mWifiDiagnostics.onRingBufferData(mFakeRbs, data); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - - byte[][] ringBufferData = getLoggerRingBufferData(); - assertEquals(1, ringBufferData.length); - assertArrayEquals(data, ringBufferData[0]); - } - - /** - * Verifies that we can continue to capture ring-buffer data - * after WiFi station is turned off in concurrency mode. - */ - @Test - public void canCaptureAndStoreRingBufferDataAfterStaIsTurnedOffInConcurrencyMode() - throws Exception { - final boolean verbosityToggle = false; - final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]; - - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.startLogging(AP_IF_NAME); - - mWifiDiagnostics.onRingBufferData(mFakeRbs, data); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - - byte[][] ringBufferData0 = getLoggerRingBufferData(); - assertEquals(1, ringBufferData0.length); - assertArrayEquals(data, ringBufferData0[0]); - - mWifiDiagnostics.stopLogging(STA_IF_NAME); - - mWifiDiagnostics.onRingBufferData(mFakeRbs, data); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - - byte[][] ringBufferData1 = getLoggerRingBufferData(); - assertEquals(1, ringBufferData1.length); - assertArrayEquals(data, ringBufferData1[0]); - } - - /** - * Verifies that we can continue to capture ring-buffer data - * after SoftAp is turned off in concurrency mode. - */ - @Test - public void canCaptureAndStoreRingBufferDataAfterSoftApIsTurnedOffInConcurrencyMode() - throws Exception { - final boolean verbosityToggle = false; - final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]; - - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - mWifiDiagnostics.startLogging(STA_IF_NAME); - mWifiDiagnostics.startLogging(AP_IF_NAME); - - mWifiDiagnostics.onRingBufferData(mFakeRbs, data); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - - byte[][] ringBufferData0 = getLoggerRingBufferData(); - assertEquals(1, ringBufferData0.length); - assertArrayEquals(data, ringBufferData0[0]); - - mWifiDiagnostics.stopLogging(AP_IF_NAME); - - mWifiDiagnostics.onRingBufferData(mFakeRbs, data); - mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); - - byte[][] ringBufferData1 = getLoggerRingBufferData(); - assertEquals(1, ringBufferData1.length); - assertArrayEquals(data, ringBufferData1[0]); - } - - /** Verifies that stoplogging on both the interfaces clean up - * all the resources. - */ - @Test - public void verifyStopLoggingOnAllInterfacesClearTheResources() throws Exception { - final boolean verbosityToggle = false; - - mWifiDiagnostics.enableVerboseLogging(verbosityToggle); - when(mWifiNative.setLoggingEventHandler(any())).thenReturn(true); - when(mWifiNative.resetLogHandler()).thenReturn(true); - - mWifiDiagnostics.startLogging(STA_IF_NAME); - verify(mWifiNative).setLoggingEventHandler(any()); - - mWifiDiagnostics.startLogging(AP_IF_NAME); - - mWifiDiagnostics.stopLogging(STA_IF_NAME); - verify(mWifiNative, never()).resetLogHandler(); - - mWifiDiagnostics.stopLogging(AP_IF_NAME); - - verify(mWifiNative).resetLogHandler(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java deleted file mode 100644 index c679954b1..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.android.server.wifi.DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; -import static com.android.server.wifi.WifiScoreCard.TS_NONE; -import static com.android.server.wifi.util.NativeUtil.hexStringFromByteArray; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.app.test.TestAlarmManager; -import android.content.Context; -import android.content.pm.ModuleInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.net.MacAddress; -import android.net.wifi.ScanResult.InformationElement; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiScanner.ScanListener; -import android.net.wifi.WifiScanner.ScanSettings; -import android.net.wifi.WifiSsid; -import android.os.Build; -import android.os.Handler; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.server.wifi.WifiConfigManager.OnNetworkUpdateListener; -import com.android.server.wifi.WifiHealthMonitor.ScanStats; -import com.android.server.wifi.WifiHealthMonitor.WifiSoftwareBuildInfo; -import com.android.server.wifi.WifiHealthMonitor.WifiSystemInfoStats; -import com.android.server.wifi.WifiScoreCard.PerNetwork; -import com.android.server.wifi.proto.WifiScoreCardProto.SystemInfoStats; -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics; - - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.WifiHealthMonitor}. - */ -@SmallTest -public class WifiHealthMonitorTest extends WifiBaseTest { - - static final WifiSsid TEST_SSID_1 = WifiSsid.createFromAsciiEncoded("Joe's Place"); - static final WifiSsid TEST_SSID_2 = WifiSsid.createFromAsciiEncoded("Poe's Place"); - static final MacAddress TEST_BSSID_1 = MacAddress.fromString("aa:bb:cc:dd:ee:ff"); - private static final long CURRENT_ELAPSED_TIME_MS = 1000; - - private WifiScoreCard mWifiScoreCard; - private WifiHealthMonitor mWifiHealthMonitor; - private MockitoSession mSession; - - @Mock - Clock mClock; - @Mock - WifiScoreCard.MemoryStore mMemoryStore; - @Mock - WifiInjector mWifiInjector; - @Mock - Context mContext; - @Mock - DeviceConfigFacade mDeviceConfigFacade; - @Mock - WifiNative mWifiNative; - @Mock - PackageManager mPackageManager; - @Mock - PackageInfo mPackageInfo; - @Mock - ModuleInfo mModuleInfo; - - private final ArrayList<String> mKeys = new ArrayList<>(); - private final ArrayList<WifiScoreCard.BlobListener> mBlobListeners = new ArrayList<>(); - private final ArrayList<byte[]> mBlobs = new ArrayList<>(); - - private ScanSettings mScanSettings = new ScanSettings(); - private WifiConfigManager mWifiConfigManager; - private long mMilliSecondsSinceBoot; - private ExtendedWifiInfo mWifiInfo; - private WifiConfiguration mWifiConfig; - private String mDriverVersion; - private String mFirmwareVersion; - private static final long MODULE_VERSION = 1L; - private TestAlarmManager mAlarmManager; - private TestLooper mLooper = new TestLooper(); - private List<WifiConfiguration> mConfiguredNetworks; - private WifiScanner mWifiScanner; - private ScanData mScanData; - private ScanListener mScanListener; - private OnNetworkUpdateListener mOnNetworkUpdateListener; - - private void millisecondsPass(long ms) { - mMilliSecondsSinceBoot += ms; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mMilliSecondsSinceBoot); - when(mClock.getWallClockMillis()).thenReturn(mMilliSecondsSinceBoot + 1_500_000_000_000L); - } - - /** - * Sets up for unit test. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mKeys.clear(); - mBlobListeners.clear(); - mBlobs.clear(); - mConfiguredNetworks = new ArrayList<>(); - mMilliSecondsSinceBoot = 0; - mWifiInfo = new ExtendedWifiInfo(mock(Context.class)); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - mWifiInfo.setSSID(TEST_SSID_1); - // Add 1st configuration - mWifiConfig = new WifiConfiguration(); - mWifiConfig.SSID = mWifiInfo.getSSID(); - mConfiguredNetworks.add(mWifiConfig); - // Add 2nd configuration - mWifiInfo.setSSID(TEST_SSID_2); - mWifiConfig = new WifiConfiguration(); - mWifiConfig.SSID = mWifiInfo.getSSID(); - mConfiguredNetworks.add(mWifiConfig); - - millisecondsPass(0); - - mDriverVersion = "build 1.1"; - mFirmwareVersion = "HW 1.1"; - when(mPackageInfo.getLongVersionCode()).thenReturn(MODULE_VERSION); - when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(mPackageInfo); - when(mPackageManager.getModuleInfo(anyString(), anyInt())).thenReturn(mModuleInfo); - when(mModuleInfo.getPackageName()).thenReturn("WifiAPK"); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - - mWifiConfigManager = mockConfigManager(); - - mWifiScoreCard = new WifiScoreCard(mClock, "some seed", mDeviceConfigFacade); - mAlarmManager = new TestAlarmManager(); - when(mContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - - mScanData = mockScanData(); - mWifiScanner = mockWifiScanner(WifiScanner.WIFI_BAND_ALL); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); - when(mWifiNative.getDriverVersion()).thenReturn(mDriverVersion); - when(mWifiNative.getFirmwareVersion()).thenReturn(mFirmwareVersion); - when(mDeviceConfigFacade.getConnectionFailureHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getConnectionFailureCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_COUNT_MIN); - when(mDeviceConfigFacade.getAssocRejectionHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getAssocRejectionCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_ASSOC_REJECTION_COUNT_MIN); - when(mDeviceConfigFacade.getAssocTimeoutHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getAssocTimeoutCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_ASSOC_TIMEOUT_COUNT_MIN); - when(mDeviceConfigFacade.getAuthFailureHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getAuthFailureCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_AUTH_FAILURE_COUNT_MIN); - when(mDeviceConfigFacade.getShortConnectionNonlocalHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getShortConnectionNonlocalCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_SHORT_CONNECTION_NONLOCAL_COUNT_MIN); - when(mDeviceConfigFacade.getDisconnectionNonlocalHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getDisconnectionNonlocalCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_DISCONNECTION_NONLOCAL_COUNT_MIN); - when(mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM); - when(mDeviceConfigFacade.getHealthMonitorRatioThrNumerator()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR); - when(mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT); - when(mDeviceConfigFacade.getHealthMonitorShortConnectionDurationThrMs()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_SHORT_CONNECTION_DURATION_THR_MS); - when(mDeviceConfigFacade.getAbnormalDisconnectionReasonCodeMask()).thenReturn( - DeviceConfigFacade.DEFAULT_ABNORMAL_DISCONNECTION_REASON_CODE_MASK); - when(mDeviceConfigFacade.getHealthMonitorRssiPollValidTimeMs()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_RSSI_POLL_VALID_TIME_MS); - when(mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS); - when(mDeviceConfigFacade.getNonstationaryScanRssiValidTimeMs()).thenReturn( - DeviceConfigFacade.DEFAULT_NONSTATIONARY_SCAN_RSSI_VALID_TIME_MS); - when(mDeviceConfigFacade.getStationaryScanRssiValidTimeMs()).thenReturn( - DeviceConfigFacade.DEFAULT_STATIONARY_SCAN_RSSI_VALID_TIME_MS); - mWifiHealthMonitor = new WifiHealthMonitor(mContext, mWifiInjector, mClock, - mWifiConfigManager, mWifiScoreCard, new Handler(mLooper.getLooper()), mWifiNative, - "some seed", mDeviceConfigFacade); - } - - private WifiConfigManager mockConfigManager() { - WifiConfigManager wifiConfigManager = mock(WifiConfigManager.class); - when(wifiConfigManager.getConfiguredNetworks()).thenReturn(mConfiguredNetworks); - when(wifiConfigManager.findScanRssi(anyInt(), anyInt())) - .thenReturn(-53); - - doAnswer(new AnswerWithArguments() { - public void answer(OnNetworkUpdateListener listener) throws Exception { - mOnNetworkUpdateListener = listener; - } - }).when(wifiConfigManager).addOnNetworkUpdateListener(anyObject()); - - doAnswer(new AnswerWithArguments() { - public boolean answer(int networkId, int uid, String packageName) throws Exception { - mOnNetworkUpdateListener.onNetworkRemoved(mWifiConfig); - return true; - } - }).when(wifiConfigManager).removeNetwork(anyInt(), anyInt(), anyString()); - - doAnswer(new AnswerWithArguments() { - public NetworkUpdateResult answer(WifiConfiguration config, int uid) throws Exception { - mOnNetworkUpdateListener.onNetworkAdded(config); - return new NetworkUpdateResult(1); - } - }).when(wifiConfigManager).addOrUpdateNetwork(any(), anyInt()); - - return wifiConfigManager; - } - - ScanData mockScanData() { - ScanData[] scanDatas = - ScanTestUtil.createScanDatas(new int[][]{{5150, 5175, 2412, 2437}}, new int[]{0}); - // Scan result does require to have an IE. - scanDatas[0].getResults()[0].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[1].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[2].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[3].informationElements = new InformationElement[0]; - - return scanDatas[0]; - } - - ScanData mockScanDataAbove2GOnly() { - ScanData[] scanDatas = - ScanTestUtil.createScanDatas(new int[][]{{5150, 5175, 5500, 5845}}, new int[]{0}); - // Scan result does require to have an IE. - scanDatas[0].getResults()[0].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[1].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[2].informationElements = new InformationElement[0]; - scanDatas[0].getResults()[3].informationElements = new InformationElement[0]; - - return scanDatas[0]; - } - - WifiScanner mockWifiScanner(@WifiScanner.WifiBand int wifiBand) { - WifiScanner scanner = mock(WifiScanner.class); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanListener listener) throws Exception { - mScanListener = listener; - } - }).when(scanner).registerScanListener(anyObject()); - - ScanData[] scanDatas = new ScanData[1]; - scanDatas[0] = mock(ScanData.class); - when(scanDatas[0].getBandScanned()).thenReturn(wifiBand); - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, ScanListener listener) throws Exception { - if (mScanData != null && mScanData.getResults() != null) { - for (int i = 0; i < mScanData.getResults().length; i++) { - listener.onFullResult( - mScanData.getResults()[i]); - } - } - listener.onResults(scanDatas); - } - }).when(scanner).startScan(anyObject(), anyObject()); - - return scanner; - } - - - private void makeNetworkConnectionExample() { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(5000); - mWifiInfo.setRssi(-55); - mWifiScoreCard.noteValidationSuccess(mWifiInfo); - millisecondsPass(1000); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - millisecondsPass(2000); - int disconnectionReason = 0; - mWifiScoreCard.noteNonlocalDisconnect(disconnectionReason); - millisecondsPass(10); - mWifiScoreCard.resetConnectionState(); - } - - private void makeRecentStatsWithSufficientConnectionAttempt() { - for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { - makeNetworkConnectionExample(); - } - } - - private byte[] makeSerializedExample() { - // Install a dummy memoryStore - // trigger extractCurrentSoftwareBuildInfo() call to update currSoftwareBuildInfo - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - mWifiHealthMonitor.setWifiEnabled(true); - assertEquals(MODULE_VERSION, mWifiHealthMonitor.getWifiStackVersion()); - millisecondsPass(5000); - mWifiScanner.startScan(mScanSettings, mScanListener); - mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - // serialized now has currSoftwareBuildInfo and scan results - return mWifiHealthMonitor.getWifiSystemInfoStats().toSystemInfoStats().toByteArray(); - } - - private void makeSwBuildChangeExample(String firmwareVersion) { - byte[] serialized = makeSerializedExample(); - // Install a real MemoryStore object, which records read requests - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(new WifiScoreCard.MemoryStore() { - @Override - public void read(String key, String name, WifiScoreCard.BlobListener listener) { - mBlobListeners.add(listener); - } - - @Override - public void write(String key, String name, byte[] value) { - mKeys.add(key); - mBlobs.add(value); - } - - @Override - public void setCluster(String key, String cluster) { - } - - @Override - public void removeCluster(String cluster) { - } - }); - mBlobListeners.get(0).onBlobRetrieved(serialized); - - // Change current FW version - when(mWifiNative.getFirmwareVersion()).thenReturn(firmwareVersion); - } - - /** - * Test read and write around SW change. - */ - @Test - public void testReadWriteAndSWChange() throws Exception { - String firmwareVersion = "HW 1.2"; - makeSwBuildChangeExample(firmwareVersion); - mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - // Now it should detect SW change, disable WiFi to trigger write - mWifiHealthMonitor.setWifiEnabled(false); - - // Check current and previous FW version of WifiSystemInfoStats - WifiSystemInfoStats wifiSystemInfoStats = mWifiHealthMonitor.getWifiSystemInfoStats(); - assertEquals(firmwareVersion, wifiSystemInfoStats.getCurrSoftwareBuildInfo() - .getWifiFirmwareVersion()); - assertEquals(mFirmwareVersion, wifiSystemInfoStats.getPrevSoftwareBuildInfo() - .getWifiFirmwareVersion()); - assertEquals(MODULE_VERSION, mWifiHealthMonitor.getWifiStackVersion()); - - // Check write - String writtenHex = hexStringFromByteArray(mBlobs.get(mKeys.size() - 1)); - String currFirmwareVersionHex = hexStringFromByteArray( - firmwareVersion.getBytes(StandardCharsets.UTF_8)); - String prevFirmwareVersionHex = hexStringFromByteArray( - mFirmwareVersion.getBytes(StandardCharsets.UTF_8)); - assertTrue(writtenHex, writtenHex.contains(currFirmwareVersionHex)); - assertTrue(writtenHex, writtenHex.contains(prevFirmwareVersionHex)); - } - - /** - * Test serialization and deserialization of WifiSystemInfoStats. - */ - @Test - public void testSerializationDeserialization() throws Exception { - // Install a dummy memoryStore - // trigger extractCurrentSoftwareBuildInfo() call to update currSoftwareBuildInfo - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - mWifiHealthMonitor.setWifiEnabled(true); - millisecondsPass(5000); - mWifiScanner.startScan(mScanSettings, mScanListener); - mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - WifiSystemInfoStats wifiSystemInfoStats = mWifiHealthMonitor.getWifiSystemInfoStats(); - // serialized now has currSoftwareBuildInfo and recent scan info - byte[] serialized = wifiSystemInfoStats.toSystemInfoStats().toByteArray(); - SystemInfoStats systemInfoStats = SystemInfoStats.parseFrom(serialized); - WifiSoftwareBuildInfo currSoftwareBuildInfoFromMemory = wifiSystemInfoStats - .fromSoftwareBuildInfo(systemInfoStats.getCurrSoftwareBuildInfo()); - assertEquals(MODULE_VERSION, currSoftwareBuildInfoFromMemory.getWifiStackVersion()); - assertEquals(mDriverVersion, currSoftwareBuildInfoFromMemory.getWifiDriverVersion()); - assertEquals(mFirmwareVersion, currSoftwareBuildInfoFromMemory.getWifiFirmwareVersion()); - assertEquals(Build.DISPLAY, currSoftwareBuildInfoFromMemory.getOsBuildVersion()); - assertEquals(1_500_000_005_000L, systemInfoStats.getLastScanTimeMs()); - assertEquals(2, systemInfoStats.getNumBssidLastScan2G()); - assertEquals(2, systemInfoStats.getNumBssidLastScanAbove2G()); - } - - /** - * Check alarm timing of a multi-day run. - */ - @Test - public void testTimerMultiDayRun() throws Exception { - long currentWallClockTimeMs = 23 * 3600_000; - long currentElapsedTimeMs = CURRENT_ELAPSED_TIME_MS; - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(currentWallClockTimeMs); - int expectedWaitHours = WifiHealthMonitor.DAILY_DETECTION_HOUR - - calendar.get(Calendar.HOUR_OF_DAY); - if (expectedWaitHours <= 0) expectedWaitHours += 24; - - // day 1 - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentElapsedTimeMs); - when(mClock.getWallClockMillis()).thenReturn(currentWallClockTimeMs); - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - long waitTimeMs = mAlarmManager - .getTriggerTimeMillis(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG) - - currentElapsedTimeMs; - assertEquals(expectedWaitHours * 3600_000, waitTimeMs); - currentElapsedTimeMs += 24 * 3600_000 + 1; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentElapsedTimeMs); - mAlarmManager.dispatch(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - waitTimeMs = mAlarmManager - .getTriggerTimeMillis(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG) - - currentElapsedTimeMs; - assertEquals(24 * 3600_000, waitTimeMs); - // day 2 - currentElapsedTimeMs += 24 * 3600_000 - 1; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentElapsedTimeMs); - mAlarmManager.dispatch(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - waitTimeMs = mAlarmManager - .getTriggerTimeMillis(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG) - - currentElapsedTimeMs; - assertEquals(24 * 3600_000, waitTimeMs); - } - - /** - * Check the alarm timing with a different wall clock time - */ - @Test - public void testTimerWith() throws Exception { - long currentWallClockTimeMs = 7 * 3600_000; - long currentElapsedTimeMs = CURRENT_ELAPSED_TIME_MS; - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(currentWallClockTimeMs); - int expectedWaitHours = WifiHealthMonitor.DAILY_DETECTION_HOUR - - calendar.get(Calendar.HOUR_OF_DAY); - if (expectedWaitHours <= 0) expectedWaitHours += 24; - - // day 1 - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentElapsedTimeMs); - when(mClock.getWallClockMillis()).thenReturn(currentWallClockTimeMs); - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - long waitTimeMs = mAlarmManager - .getTriggerTimeMillis(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG) - - currentElapsedTimeMs; - assertEquals(expectedWaitHours * 3600_000, waitTimeMs); - } - - /** - * Check stats with two daily detections. - */ - @Test - public void testTwoDailyDetections() throws Exception { - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - // day 1 - makeRecentStatsWithSufficientConnectionAttempt(); - mAlarmManager.dispatch(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - // day 2 - makeRecentStatsWithSufficientConnectionAttempt(); - mAlarmManager.dispatch(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertEquals(DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT * 2, - perNetwork.getStatsCurrBuild().getCount(WifiScoreCard.CNT_CONNECTION_ATTEMPT)); - } - - /** - * Check proto after one daily detection with high non-local disconnection rate - */ - @Test - public void testBuildProto() throws Exception { - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - makeRecentStatsWithSufficientConnectionAttempt(); - mAlarmManager.dispatch(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - - // First call of buildProto - HealthMonitorMetrics healthMetrics = mWifiHealthMonitor.buildProto(); - assertEquals(0, healthMetrics.failureStatsIncrease.cntAssocRejection); - assertEquals(0, healthMetrics.failureStatsIncrease.cntAssocTimeout); - assertEquals(0, healthMetrics.failureStatsIncrease.cntAuthFailure); - assertEquals(0, healthMetrics.failureStatsIncrease.cntConnectionFailure); - assertEquals(0, healthMetrics.failureStatsIncrease.cntDisconnectionNonlocal); - assertEquals(0, healthMetrics.failureStatsIncrease.cntShortConnectionNonlocal); - assertEquals(0, healthMetrics.failureStatsHigh.cntAssocRejection); - assertEquals(0, healthMetrics.failureStatsHigh.cntAssocTimeout); - assertEquals(0, healthMetrics.failureStatsHigh.cntAuthFailure); - assertEquals(0, healthMetrics.failureStatsHigh.cntConnectionFailure); - assertEquals(1, healthMetrics.failureStatsHigh.cntDisconnectionNonlocal); - assertEquals(1, healthMetrics.failureStatsHigh.cntShortConnectionNonlocal); - assertEquals(1, healthMetrics.numNetworkSufficientRecentStatsOnly); - assertEquals(0, healthMetrics.numNetworkSufficientRecentPrevStats); - - // Second call of buildProto - healthMetrics = mWifiHealthMonitor.buildProto(); - // Second call should result in an empty proto - assertEquals(null, healthMetrics); - } - - /** - * Test FailureStats class - */ - @Test - public void testFailureStats() throws Exception { - WifiHealthMonitor.FailureStats failureStats = new WifiHealthMonitor.FailureStats(); - failureStats.setCount(WifiHealthMonitor.REASON_AUTH_FAILURE, 10); - failureStats.incrementCount(WifiHealthMonitor.REASON_AUTH_FAILURE); - - String expectedString = "authentication failure: 11 "; - String unexpectedString = - WifiHealthMonitor.FAILURE_REASON_NAME[WifiHealthMonitor.REASON_ASSOC_REJECTION]; - assertEquals(11, failureStats.getCount(WifiHealthMonitor.REASON_AUTH_FAILURE)); - assertEquals(true, failureStats.toString().contains(expectedString)); - assertEquals(false, failureStats.toString().contains(unexpectedString)); - } - - /** - * Check statsd logging after one daily detection with high non-local disconnection rate - */ - @Test - public void testWifiStatsLogWrite() throws Exception { - // static mocking for WifiStatsLog - mSession = ExtendedMockito.mockitoSession() - .strictness(Strictness.LENIENT) - .mockStatic(WifiStatsLog.class) - .startMocking(); - - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - makeRecentStatsWithSufficientConnectionAttempt(); - mAlarmManager.dispatch(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - - ExtendedMockito.verify(() -> WifiStatsLog.write( - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__ABNORMALITY_TYPE__SIMPLY_HIGH, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__FAILURE_TYPE__FAILURE_NON_LOCAL_DISCONNECTION, - 1)); - - ExtendedMockito.verify(() -> WifiStatsLog.write( - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__ABNORMALITY_TYPE__SIMPLY_HIGH, - WifiStatsLog.WIFI_FAILURE_STAT_REPORTED__FAILURE_TYPE__FAILURE_SHORT_CONNECTION_DUE_TO_NON_LOCAL_DISCONNECTION, - 1)); - mSession.finishMocking(); - } - - /** - * test stats after a SW build change - */ - @Test - public void testAfterSwBuildChange() throws Exception { - // Day 1 - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - makeRecentStatsWithSufficientConnectionAttempt(); - mAlarmManager.dispatch(WifiHealthMonitor.DAILY_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - - // Day 2 - String firmwareVersion = "HW 1.2"; - makeSwBuildChangeExample(firmwareVersion); - // Disable WiFi before post-boot-detection - mWifiHealthMonitor.setWifiEnabled(false); - mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - // Skip SW build change detection - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertEquals(DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT * 1, - perNetwork.getStatsCurrBuild().getCount(WifiScoreCard.CNT_CONNECTION_ATTEMPT)); - assertEquals(DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT * 0, - perNetwork.getStatsPrevBuild().getCount(WifiScoreCard.CNT_CONNECTION_ATTEMPT)); - - // Day 3 - mWifiHealthMonitor.setWifiEnabled(true); - mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - // Finally detect SW build change - assertEquals(0, - perNetwork.getStatsCurrBuild().getCount(WifiScoreCard.CNT_CONNECTION_ATTEMPT)); - assertEquals(DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT * 1, - perNetwork.getStatsPrevBuild().getCount(WifiScoreCard.CNT_CONNECTION_ATTEMPT)); - } - - /** - * Installing a MemoryStore after startup should issue reads. - */ - @Test - public void testReadAfterDelayedMemoryStoreInstallation() throws Exception { - makeNetworkConnectionExample(); - assertEquals(2, mConfiguredNetworks.size()); - mWifiScoreCard.installMemoryStore(mMemoryStore); - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - - // 1 for WifiSystemInfoStats, 1 for requestReadBssid and 2 for requestReadNetwork - verify(mMemoryStore, times(4)).read(any(), any(), any()); - } - - /** - * Installing a MemoryStore during startup should issue a proper number of reads. - */ - @Test - public void testReadAfterStartupMemoryStoreInstallation() throws Exception { - mWifiScoreCard.installMemoryStore(mMemoryStore); - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - makeNetworkConnectionExample(); - assertEquals(2, mConfiguredNetworks.size()); - - // 1 for WifiSystemInfoStats, 1 for requestReadBssid and 2 for requestReadNetwork - verify(mMemoryStore, times(4)).read(any(), any(), any()); - } - - /** - * Installing a MemoryStore twice should not cause crash. - */ - @Test - public void testInstallMemoryStoreTwiceNoCrash() throws Exception { - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - makeNetworkConnectionExample(); - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); - } - - /** - * Check if scan results are reported correctly after full band scan. - */ - @Test - public void testFullBandScan() throws Exception { - millisecondsPass(5000); - mWifiHealthMonitor.setWifiEnabled(true); - mWifiScanner.startScan(mScanSettings, mScanListener); - ScanStats scanStats = mWifiHealthMonitor.getWifiSystemInfoStats().getCurrScanStats(); - assertEquals(1_500_000_005_000L, scanStats.getLastScanTimeMs()); - assertEquals(2, scanStats.getNumBssidLastScanAbove2g()); - assertEquals(2, scanStats.getNumBssidLastScan2g()); - } - - /** - * Check if scan results are reported correctly after 2G only scan. - */ - @Test - public void test2GScan() throws Exception { - mWifiScanner = mockWifiScanner(WifiScanner.WIFI_BAND_24_GHZ); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); - millisecondsPass(5000); - mWifiHealthMonitor.setWifiEnabled(true); - mWifiScanner.startScan(mScanSettings, mScanListener); - ScanStats scanStats = mWifiHealthMonitor.getWifiSystemInfoStats().getCurrScanStats(); - assertEquals(TS_NONE, scanStats.getLastScanTimeMs()); - assertEquals(0, scanStats.getNumBssidLastScanAbove2g()); - assertEquals(0, scanStats.getNumBssidLastScan2g()); - } - - @Test - public void testClearReallyDoesClearTheState() throws Exception { - byte[] init = mWifiHealthMonitor.getWifiSystemInfoStats() - .toSystemInfoStats().toByteArray(); - byte[] serialized = makeSerializedExample(); - assertNotEquals(0, serialized.length); - mWifiHealthMonitor.clear(); - byte[] leftovers = mWifiHealthMonitor.getWifiSystemInfoStats() - .toSystemInfoStats().toByteArray(); - assertEquals(init.length, leftovers.length); - } - - @Test - public void testPostBootAbnormalScanDetection() throws Exception { - // Serialized has the last scan result - byte [] serialized = makeSerializedExample(); - // Startup DUT again to mimic reboot - setUp(); - // Install a real MemoryStore object, which records read requests - mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(new WifiScoreCard.MemoryStore() { - @Override - public void read(String key, String name, WifiScoreCard.BlobListener listener) { - mBlobListeners.add(listener); - } - - @Override - public void write(String key, String name, byte[] value) { - mKeys.add(key); - mBlobs.add(value); - } - - @Override - public void setCluster(String key, String cluster) { - } - - @Override - public void removeCluster(String cluster) { - } - }); - mBlobListeners.get(0).onBlobRetrieved(serialized); - - SystemInfoStats systemInfoStats = SystemInfoStats.parseFrom(serialized); - assertEquals(1_500_000_005_000L, systemInfoStats.getLastScanTimeMs()); - assertEquals(2, systemInfoStats.getNumBssidLastScan2G()); - assertEquals(2, systemInfoStats.getNumBssidLastScanAbove2G()); - - // Add Above2G only scan data - mScanData = mockScanDataAbove2GOnly(); - mWifiScanner = mockWifiScanner(WifiScanner.WIFI_BAND_ALL); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); - millisecondsPass(5000); - mWifiHealthMonitor.setWifiEnabled(true); - mWifiScanner.startScan(mScanSettings, mScanListener); - - mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); - mLooper.dispatchAll(); - - // It should detect abnormal scan failure now. - assertEquals(4, mWifiHealthMonitor.getWifiSystemInfoStats().getScanFailure()); - } - - /** - * Test when remove a saved network will remove network from the WifiScoreCard. - */ - @Test - public void testRemoveSavedNetwork() { - makeNetworkConnectionExample(); - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertNotNull(perNetwork); - - // Now remove the network - mWifiConfigManager.removeNetwork(1, 1, "some package"); - perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertNull(perNetwork); - } - - /** - * Test when remove a suggestion network will not remove network from the WifiScoreCard. - */ - @Test - public void testRemoveSuggestionNetwork() throws Exception { - mWifiConfig.fromWifiNetworkSuggestion = true; - makeNetworkConnectionExample(); - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertNotNull(perNetwork); - - // Now remove the network - mWifiConfigManager.removeNetwork(1, 1, "some package"); - perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertNotNull(perNetwork); - } - - @Test - public void testAddNetwork() throws Exception { - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertNull(perNetwork); - - // Now add network - mWifiConfigManager.addOrUpdateNetwork(mWifiConfig, 1); - perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertNotNull(perNetwork); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiInjectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiInjectorTest.java deleted file mode 100644 index 6af10d0c4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiInjectorTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link WifiInjector}. */ -@SmallTest -public class WifiInjectorTest extends WifiBaseTest { - - @Mock private WifiContext mContext; - private WifiInjector mInjector; - - /** - * Method to initialize mocks for tests. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - - /** - * Test that attempting to get the instance of the WifiInjector throws an IllegalStateException - * if it is not initialized. - */ - @Test(expected = IllegalStateException.class) - public void testGetInstanceWithUninitializedWifiInjector() { - WifiInjector.getInstance(); - } - - /** - * Test that attempting to call the WifiInjector a second time throws an exception. - */ - @Test(expected = IllegalStateException.class) - public void testShouldNotBeAbleToCreateMoreThanOneWifiInjector() { - try { - WifiInjector willThrowNullPointerException = new WifiInjector(mContext); - } catch (NullPointerException e) { - } - WifiInjector shouldThrowIllegalStateException = new WifiInjector(mContext); - } - - /** - * Test that a WifiInjector cannot be created with a null Context. - */ - @Test(expected = IllegalStateException.class) - public void testShouldNotCreateWifiInjectorWithNullContext() { - new WifiInjector(null); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java deleted file mode 100644 index f6cae66db..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.AdditionalMatchers.aryEq; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.validateMockitoUsage; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; - -import androidx.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.security.KeyStore; -import java.security.cert.X509Certificate; - -/** - * Unit tests for {@link com.android.server.wifi.WifiConfigManager}. - */ -@SmallTest -public class WifiKeyStoreTest extends WifiBaseTest { - @Mock private WifiEnterpriseConfig mWifiEnterpriseConfig; - @Mock private KeyStore mKeyStore; - - private WifiKeyStore mWifiKeyStore; - private static final String TEST_KEY_ID = "blah"; - private static final String USER_CERT_ALIAS = "aabbccddee"; - private static final String USER_CA_CERT_ALIAS = "aacccddd"; - private static final String [] USER_CA_CERT_ALIASES = {"aacccddd", "bbbccccaaa"}; - private static final String TEST_PACKAGE_NAME = "TestApp"; - - /** - * Setup the mocks and an instance of WifiConfigManager before each test. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mWifiKeyStore = new WifiKeyStore(mKeyStore); - - when(mWifiEnterpriseConfig.getClientCertificateAlias()).thenReturn(USER_CERT_ALIAS); - when(mWifiEnterpriseConfig.getCaCertificateAlias()).thenReturn(USER_CA_CERT_ALIAS); - when(mWifiEnterpriseConfig.getCaCertificateAliases()) - .thenReturn(USER_CA_CERT_ALIASES); - when(mWifiEnterpriseConfig.getClientPrivateKey()).thenReturn(FakeKeys.RSA_KEY1); - when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn(FakeKeys.CLIENT_CERT); - when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_CERT0); - when(mWifiEnterpriseConfig.getClientCertificateChain()) - .thenReturn(new X509Certificate[] {FakeKeys.CLIENT_CERT}); - when(mWifiEnterpriseConfig.getCaCertificates()) - .thenReturn(new X509Certificate[] {FakeKeys.CA_CERT0}); - when(mWifiEnterpriseConfig.getKeyId(any())).thenReturn(TEST_KEY_ID); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - /** - * Verifies that keys and certs are removed when they were installed by an app. - */ - @Test - public void testRemoveKeysForAppInstalledCerts() throws Exception { - when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(true); - when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(true); - mWifiKeyStore.removeKeys(mWifiEnterpriseConfig); - - // Method calls the KeyStore#delete method 4 times, user key, user cert, and 2 CA cert - verify(mKeyStore).deleteEntry(USER_CERT_ALIAS); - verify(mKeyStore).deleteEntry(USER_CA_CERT_ALIASES[0]); - } - - /** - * Verifies that keys and certs are removed when they were installed by an app and not removed - * when CA certs are installed by the user. - */ - @Test - public void testRemoveKeysForMixedInstalledCerts1() throws Exception { - when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(true); - when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(false); - mWifiKeyStore.removeKeys(mWifiEnterpriseConfig); - - // Method calls the KeyStore#deleteEntry method: user key and user cert - verify(mKeyStore).deleteEntry(USER_CERT_ALIAS); - verifyNoMoreInteractions(mKeyStore); - } - - /** - * Verifies that keys and certs are not removed when they were installed by the user and - * removed when CA certs are installed by the app. - */ - @Test - public void testRemoveKeysForMixedInstalledCerts2() throws Exception { - when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(false); - when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(true); - mWifiKeyStore.removeKeys(mWifiEnterpriseConfig); - - // Method calls the KeyStore#delete method 2 times: 2 CA certs - verify(mKeyStore).deleteEntry(USER_CA_CERT_ALIASES[0]); - verify(mKeyStore).deleteEntry(USER_CA_CERT_ALIASES[1]); - verifyNoMoreInteractions(mKeyStore); - } - - /** - * Verifies that keys and certs are not removed when they were installed by the user. - */ - @Test - public void testRemoveKeysForUserInstalledCerts() { - when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(false); - when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(false); - mWifiKeyStore.removeKeys(mWifiEnterpriseConfig); - verifyNoMoreInteractions(mKeyStore); - } - - /** - * Verifies that keys and certs are added when they were installed by an app and verifies the - * alias used. - */ - @Test - public void testAddKeysForAppInstalledCerts() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); - config.enterpriseConfig = mWifiEnterpriseConfig; - assertTrue(mWifiKeyStore.updateNetworkKeys(config, null)); - - String expectedAlias = config.getKeyIdForCredentials(null); - String expectedCaAlias = expectedAlias + "_0"; - // Method calls the KeyStore#delete method 4 times, user key, user cert, and 2 CA cert - verify(mKeyStore).setKeyEntry( - eq(expectedAlias), eq(FakeKeys.RSA_KEY1), eq(null), - aryEq(new X509Certificate[] {FakeKeys.CLIENT_CERT})); - verify(mKeyStore).setCertificateEntry(eq(expectedCaAlias), eq(FakeKeys.CA_CERT0)); - verify(mWifiEnterpriseConfig).setClientCertificateAlias(eq(expectedAlias)); - verify(mWifiEnterpriseConfig).setCaCertificateAliases( - aryEq(new String[] {expectedCaAlias})); - } - - /** - * Add two same network credential one is from user saved, the other is from suggestion. - * Both oh them should be installed successfully and has different alias, and will not override - * each other. - */ - @Test - public void testAddRemoveFromBothSavedAndSuggestionNetwork() throws Exception { - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapNetwork(); - WifiConfiguration suggestionNetwork = new WifiConfiguration(savedNetwork); - savedNetwork.enterpriseConfig = mWifiEnterpriseConfig; - suggestionNetwork.enterpriseConfig = mWifiEnterpriseConfig; - suggestionNetwork.fromWifiNetworkSuggestion = true; - suggestionNetwork.creatorName = TEST_PACKAGE_NAME; - - assertTrue(mWifiKeyStore.updateNetworkKeys(savedNetwork, null)); - assertTrue(mWifiKeyStore.updateNetworkKeys(suggestionNetwork, null)); - - String savedNetworkAlias = savedNetwork.getKeyIdForCredentials(null); - String savedNetworkCaAlias = savedNetworkAlias + "_0"; - - String suggestionNetworkAlias = suggestionNetwork.getKeyIdForCredentials(null); - String suggestionNetworkCaAlias = suggestionNetworkAlias + "_0"; - - assertNotEquals(savedNetworkAlias, suggestionNetworkAlias); - - verify(mKeyStore).setKeyEntry( - eq(savedNetworkAlias), eq(FakeKeys.RSA_KEY1), eq(null), - aryEq(new X509Certificate[] {FakeKeys.CLIENT_CERT})); - verify(mKeyStore).setCertificateEntry(eq(savedNetworkCaAlias), eq(FakeKeys.CA_CERT0)); - verify(mWifiEnterpriseConfig).setClientCertificateAlias(eq(savedNetworkAlias)); - verify(mWifiEnterpriseConfig).setCaCertificateAliases( - aryEq(new String[] {savedNetworkCaAlias})); - - verify(mKeyStore).setKeyEntry( - eq(suggestionNetworkAlias), eq(FakeKeys.RSA_KEY1), eq(null), - aryEq(new X509Certificate[] {FakeKeys.CLIENT_CERT})); - verify(mKeyStore).setCertificateEntry(eq(suggestionNetworkCaAlias), eq(FakeKeys.CA_CERT0)); - verify(mWifiEnterpriseConfig).setClientCertificateAlias(eq(suggestionNetworkAlias)); - verify(mWifiEnterpriseConfig).setCaCertificateAliases( - aryEq(new String[] {suggestionNetworkCaAlias})); - } - - @Test - public void test_remove_empty_alias_enterprise_config() throws Exception { - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapNetwork(); - WifiConfiguration suggestionNetwork = new WifiConfiguration(savedNetwork); - suggestionNetwork.fromWifiNetworkSuggestion = true; - suggestionNetwork.creatorName = TEST_PACKAGE_NAME; - mWifiKeyStore.removeKeys(savedNetwork.enterpriseConfig); - mWifiKeyStore.removeKeys(suggestionNetwork.enterpriseConfig); - verify(mKeyStore, never()).deleteEntry(any()); - } - - /** - * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 correctly when CA and client - * certificates are of RSA 3072 type and the network is Suite-B. - */ - @Test - public void testConfigureSuiteBRsa3072() throws Exception { - when(mWifiEnterpriseConfig.getCaCertificateAliases()) - .thenReturn(new String[]{USER_CA_CERT_ALIAS}); - when(mWifiEnterpriseConfig.getClientPrivateKey()) - .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY); - when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_SUITE_B_RSA3072_CERT); - when(mWifiEnterpriseConfig.getClientCertificateChain()) - .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT}); - when(mWifiEnterpriseConfig.getCaCertificates()) - .thenReturn(new X509Certificate[]{FakeKeys.CA_SUITE_B_RSA3072_CERT}); - when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn( - FakeKeys.CA_SUITE_B_RSA3072_CERT); - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork( - WifiConfiguration.SuiteBCipher.ECDHE_RSA); - savedNetwork.enterpriseConfig = mWifiEnterpriseConfig; - assertTrue(mWifiKeyStore.updateNetworkKeys(savedNetwork, null)); - assertTrue(savedNetwork.allowedSuiteBCiphers.get(WifiConfiguration.SuiteBCipher.ECDHE_RSA)); - } - - /** - * Test configuring WPA3-Enterprise in 192-bit mode for ECDSA correctly when CA and client - * certificates are of ECDSA type and the network is Suite-B. - */ - @Test - public void testConfigureSuiteBEcdsa() throws Exception { - when(mWifiEnterpriseConfig.getCaCertificateAliases()) - .thenReturn(new String[]{USER_CA_CERT_ALIAS}); - when(mWifiEnterpriseConfig.getClientPrivateKey()) - .thenReturn(FakeKeys.CLIENT_SUITE_B_ECC_KEY); - when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn( - FakeKeys.CLIENT_SUITE_B_ECDSA_CERT); - when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_SUITE_B_ECDSA_CERT); - when(mWifiEnterpriseConfig.getClientCertificateChain()) - .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_ECDSA_CERT}); - when(mWifiEnterpriseConfig.getCaCertificates()) - .thenReturn(new X509Certificate[]{FakeKeys.CA_SUITE_B_ECDSA_CERT}); - when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn( - FakeKeys.CLIENT_SUITE_B_ECDSA_CERT); - when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn( - FakeKeys.CA_SUITE_B_ECDSA_CERT); - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork( - WifiConfiguration.SuiteBCipher.ECDHE_ECDSA); - savedNetwork.enterpriseConfig = mWifiEnterpriseConfig; - assertTrue(mWifiKeyStore.updateNetworkKeys(savedNetwork, null)); - assertTrue( - savedNetwork.allowedSuiteBCiphers.get(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA)); - } - - /** - * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 fails when CA and client - * certificates are not of the same type. - */ - @Test - public void testConfigurationFailureSuiteB() throws Exception { - // Create a configuration with RSA client cert and ECDSA CA cert - when(mWifiEnterpriseConfig.getClientPrivateKey()) - .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY); - when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_SUITE_B_ECDSA_CERT); - when(mWifiEnterpriseConfig.getClientCertificateChain()) - .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT}); - when(mWifiEnterpriseConfig.getCaCertificates()) - .thenReturn(new X509Certificate[]{FakeKeys.CA_SUITE_B_ECDSA_CERT}); - when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn( - FakeKeys.CA_SUITE_B_ECDSA_CERT); - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork( - WifiConfiguration.SuiteBCipher.ECDHE_ECDSA); - savedNetwork.enterpriseConfig = mWifiEnterpriseConfig; - assertFalse(mWifiKeyStore.updateNetworkKeys(savedNetwork, null)); - } - - /** - * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 fails when CA is RSA but not - * with the required security - */ - @Test - public void testConfigurationFailureSuiteBNon3072Rsa() throws Exception { - // Create a configuration with RSA client cert and weak RSA CA cert - when(mWifiEnterpriseConfig.getClientPrivateKey()) - .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY); - when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_CERT0); - when(mWifiEnterpriseConfig.getClientCertificateChain()) - .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT}); - when(mWifiEnterpriseConfig.getCaCertificates()) - .thenReturn(new X509Certificate[]{FakeKeys.CA_CERT0}); - when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn( - FakeKeys.CA_CERT0); - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork( - WifiConfiguration.SuiteBCipher.ECDHE_RSA); - savedNetwork.enterpriseConfig = mWifiEnterpriseConfig; - assertFalse(mWifiKeyStore.updateNetworkKeys(savedNetwork, null)); - } - - /** - * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 fails when one CA in the list - * is RSA but not with the required security - */ - @Test - public void testConfigurationFailureSuiteBNon3072RsaInList() throws Exception { - // Create a configuration with RSA client cert and weak RSA CA cert - when(mWifiEnterpriseConfig.getClientPrivateKey()) - .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY); - when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_SUITE_B_RSA3072_CERT); - when(mWifiEnterpriseConfig.getClientCertificateChain()) - .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT}); - when(mWifiEnterpriseConfig.getCaCertificates()) - .thenReturn( - new X509Certificate[]{FakeKeys.CA_SUITE_B_RSA3072_CERT, FakeKeys.CA_CERT0}); - when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn( - FakeKeys.CA_SUITE_B_RSA3072_CERT); - when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[1]))).thenReturn( - FakeKeys.CA_CERT0); - when(mWifiEnterpriseConfig.getCaCertificateAliases()) - .thenReturn(USER_CA_CERT_ALIASES); - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork( - WifiConfiguration.SuiteBCipher.ECDHE_RSA); - savedNetwork.enterpriseConfig = mWifiEnterpriseConfig; - assertFalse(mWifiKeyStore.updateNetworkKeys(savedNetwork, null)); - } - - /** - * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 fails when one CA in the list - * is RSA and the other is ECDSA - */ - @Test - public void testConfigurationFailureSuiteBRsaAndEcdsaInList() throws Exception { - // Create a configuration with RSA client cert and weak RSA CA cert - when(mWifiEnterpriseConfig.getClientPrivateKey()) - .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY); - when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_SUITE_B_RSA3072_CERT); - when(mWifiEnterpriseConfig.getClientCertificateChain()) - .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT}); - when(mWifiEnterpriseConfig.getCaCertificates()) - .thenReturn( - new X509Certificate[]{FakeKeys.CA_SUITE_B_RSA3072_CERT, - FakeKeys.CA_SUITE_B_ECDSA_CERT}); - when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn( - FakeKeys.CLIENT_SUITE_B_RSA3072_CERT); - when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn( - FakeKeys.CA_SUITE_B_RSA3072_CERT); - when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[1]))).thenReturn( - FakeKeys.CA_SUITE_B_ECDSA_CERT); - when(mWifiEnterpriseConfig.getCaCertificateAliases()) - .thenReturn(USER_CA_CERT_ALIASES); - WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork( - WifiConfiguration.SuiteBCipher.ECDHE_RSA); - savedNetwork.enterpriseConfig = mWifiEnterpriseConfig; - assertFalse(mWifiKeyStore.updateNetworkKeys(savedNetwork, null)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java b/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java deleted file mode 100644 index b463f906d..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java +++ /dev/null @@ -1,2356 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.*; -import static org.mockito.MockitoAnnotations.*; - -import android.content.Context; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.test.TestLooper; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.WifiLastResortWatchdog}. - */ -@SmallTest -public class WifiLastResortWatchdogTest extends WifiBaseTest { - @Mock WifiInjector mWifiInjector; - @Mock WifiMetrics mWifiMetrics; - @Mock SelfRecovery mSelfRecovery; - @Mock ClientModeImpl mClientModeImpl; - @Mock Clock mClock; - @Mock WifiInfo mWifiInfo; - @Mock Context mContext; - @Mock DeviceConfigFacade mDeviceConfigFacade; - - private WifiLastResortWatchdog mLastResortWatchdog; - private MockResources mResources; - private String[] mSsids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""}; - private String[] mBssids = {"aa:bb:cc:dd:ee:ff", "00:11:22:33:44:55", "a0:b0:c0:d0:e0:f0", - "01:23:45:67:89:ab"}; - private int[] mFrequencies = {2437, 5180, 5180, 2437}; - private String[] mCaps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", - "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - private int[] mLevels = {-60, -86, -50, -62}; - private boolean[] mIsEphemeral = {false, false, false, false}; - private boolean[] mHasEverConnected = {false, false, false, false}; - private TestLooper mLooper; - private static final String TEST_NETWORK_SSID = "\"test_ssid\""; - private static final int DEFAULT_ABNORMAL_CONNECTION_DURATION_MS = 30000; - - @Before - public void setUp() throws Exception { - initMocks(this); - mLooper = new TestLooper(); - when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); - when(mDeviceConfigFacade.isAbnormalConnectionBugreportEnabled()).thenReturn(true); - when(mDeviceConfigFacade.getAbnormalConnectionDurationMs()).thenReturn( - DEFAULT_ABNORMAL_CONNECTION_DURATION_MS); - mResources = new MockResources(); - mResources.setBoolean(R.bool.config_wifi_watchdog_enabled, true); - when(mContext.getResources()).thenReturn(mResources); - createWifiLastResortWatchdog(); - when(mClientModeImpl.getWifiInfo()).thenReturn(mWifiInfo); - when(mWifiInfo.getSSID()).thenReturn(TEST_NETWORK_SSID); - } - - private void createWifiLastResortWatchdog() { - WifiThreadRunner wifiThreadRunner = new WifiThreadRunner(new Handler(mLooper.getLooper())); - mLastResortWatchdog = new WifiLastResortWatchdog(mWifiInjector, mContext, mClock, - mWifiMetrics, mClientModeImpl, mLooper.getLooper(), mDeviceConfigFacade, - wifiThreadRunner); - mLastResortWatchdog.setBugReportProbability(1); - } - - private List<Pair<ScanDetail, WifiConfiguration>> createFilteredQnsCandidates(String[] ssids, - String[] bssids, int[] frequencies, String[] caps, int[] levels, - boolean[] isEphemeral) { - List<Pair<ScanDetail, WifiConfiguration>> candidates = new ArrayList<>(); - long timeStamp = System.currentTimeMillis(); - for (int index = 0; index < ssids.length; index++) { - String ssid = ssids[index].replaceAll("^\"+", "").replaceAll("\"+$", ""); - ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), - bssids[index], caps[index], levels[index], frequencies[index], timeStamp, - 0); - WifiConfiguration config = null; - if (!isEphemeral[index]) { - config = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); - when(networkSelectionStatus.hasEverConnected()).thenReturn(true); - } - candidates.add(Pair.create(scanDetail, config)); - } - return candidates; - } - - private List<Pair<ScanDetail, WifiConfiguration>> createFilteredQnsCandidates(String[] ssids, - String[] bssids, int[] frequencies, String[] caps, int[] levels, - boolean[] isEphemeral, boolean[] hasEverConnected) { - List<Pair<ScanDetail, WifiConfiguration>> candidates = - new ArrayList<Pair<ScanDetail, WifiConfiguration>>(); - long timeStamp = System.currentTimeMillis(); - for (int index = 0; index < ssids.length; index++) { - String ssid = ssids[index].replaceAll("^\"+", "").replaceAll("\"+$", ""); - ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), - bssids[index], caps[index], levels[index], frequencies[index], timeStamp, - 0); - WifiConfiguration config = null; - if (!isEphemeral[index]) { - config = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); - when(networkSelectionStatus.hasEverConnected()) - .thenReturn(hasEverConnected[index]); - } - candidates.add(Pair.create(scanDetail, config)); - } - return candidates; - } - - private void assertFailureCountEquals( - String bssid, int associationRejections, int authenticationFailures, int dhcpFailures) { - assertEquals(associationRejections, mLastResortWatchdog.getFailureCount(bssid, - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION)); - assertEquals(authenticationFailures, mLastResortWatchdog.getFailureCount(bssid, - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION)); - assertEquals(dhcpFailures, mLastResortWatchdog.getFailureCount(bssid, - WifiLastResortWatchdog.FAILURE_CODE_DHCP)); - } - - /** - * Case #1: Test aging works in available network buffering - * This test simulates 4 networks appearing in a scan result, and then only the first 2 - * appearing in successive scans results. - * Expected Behavior: - * 4 networks appear in recentAvailalbeNetworks, after N=MAX_BSSID_AGE scans, only 2 remain - */ - @Test - public void testAvailableNetworkBuffering_ageCullingWorks() throws Exception { - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral); - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); - - // Repeatedly buffer candidates 1 & 2, MAX_BSSID_AGE - 1 times - candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 2), - Arrays.copyOfRange(mBssids, 0, 2), - Arrays.copyOfRange(mFrequencies, 0, 2), - Arrays.copyOfRange(mCaps, 0, 2), - Arrays.copyOfRange(mLevels, 0, 2), - Arrays.copyOfRange(mIsEphemeral, 0, 2)); - for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE - 1; i++) { - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[0]).age, 0); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[1]).age, 0); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[2]).age, - i + 1); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[3]).age, - i + 1); - } - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); - - // One more buffering should age and cull candidates 2 & 3 - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 2); - }; - - /** - * Case #2: Culling of old networks - * Part 1: - * This test starts with 4 networks seen, it then buffers N=MAX_BSSID_AGE empty scans - * Expected behaviour: All networks are culled from recentAvailableNetworks - * - * Part 2: - * Buffer some more empty scans just to make sure nothing breaks - */ - @Test - public void testAvailableNetworkBuffering_emptyBufferWithEmptyScanResults() throws Exception { - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral); - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); - - // Repeatedly buffer with no candidates - candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 0), - Arrays.copyOfRange(mBssids, 0, 0), - Arrays.copyOfRange(mFrequencies, 0, 0), - Arrays.copyOfRange(mCaps, 0, 0), - Arrays.copyOfRange(mLevels, 0, 0), - Arrays.copyOfRange(mIsEphemeral, 0, 0)); - for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { - mLastResortWatchdog.updateAvailableNetworks(candidates); - } - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 0); - for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { - mLastResortWatchdog.updateAvailableNetworks(candidates); - } - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 0); - }; - - /** - * Case 3: Adding more networks over time - * In this test, each successive (4 total) scan result buffers one more network. - * Expected behavior: recentAvailableNetworks grows with number of scan results - */ - @Test - public void testAvailableNetworkBuffering_addNewNetworksOverTime() throws Exception { - List<Pair<ScanDetail, WifiConfiguration>> candidates; - // Buffer (i) scan results with each successive scan result - for (int i = 1; i <= mSsids.length; i++) { - candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, i), - Arrays.copyOfRange(mBssids, 0, i), - Arrays.copyOfRange(mFrequencies, 0, i), - Arrays.copyOfRange(mCaps, 0, i), - Arrays.copyOfRange(mLevels, 0, i), - Arrays.copyOfRange(mIsEphemeral, 0, i)); - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), i); - for (int j = 0; j < i; j++) { - assertEquals( - mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[j]).age, 0); - } - } - }; - - /** - * Case 4: Test buffering with ephemeral networks & toString() - * This test is the same as Case 1, but it also includes ephemeral networks. toString is also - * smoke tested at various places in this test - * Expected behaviour: 4 networks added initially (2 ephemeral). After MAX_BSSID_AGE more - * bufferings, 2 are culled (leaving 1 ephemeral, one normal). toString method should execute - * without breaking anything. - */ - @Test - public void testAvailableNetworkBuffering_multipleNetworksSomeEphemeral() throws Exception { - boolean[] isEphemeral = {true, false, true, false}; - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, isEphemeral); - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); - - // Repeatedly buffer candidates 1 & 2, MAX_BSSID_AGE - 1 times - candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 2), - Arrays.copyOfRange(mBssids, 0, 2), - Arrays.copyOfRange(mFrequencies, 0, 2), - Arrays.copyOfRange(mCaps, 0, 2), - Arrays.copyOfRange(mLevels, 0, 2), - Arrays.copyOfRange(isEphemeral, 0, 2)); - for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE - 1; i++) { - mLastResortWatchdog.updateAvailableNetworks(candidates); - mLastResortWatchdog.toString(); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[0]).age, 0); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[1]).age, 0); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[2]).age, - i + 1); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[3]).age, - i + 1); - } - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); - - // One more buffering should age and cull candidates 2 & 3 - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 2); - mLastResortWatchdog.toString(); - }; - - /** - * Case 5: Test failure counting, incrementing a specific BSSID - * Test has 4 networks buffered, increment each different failure type on one of them - * Expected behaviour: See failure counts for the specific failures rise to the appropriate - * level for the specific network - */ - @Test - public void testFailureCounting_countFailuresForSingleBssid() throws Exception { - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).associationRejection); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).authenticationFailure); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).dhcpFailure); - } - assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - assertFailureCountEquals(mBssids[3], 0, 0, 0); - } - - /** - * Case 6: Test failure counting, incrementing a specific BSSID, with some ephemeral networks - * Almost identical to test case 5. - * Test has 4 networks buffered (two are ephemeral), increment each different failure type on - * one of them. - * Expected behavior: See failure counts for the specific failures rise to the appropriate - * level for the specific network - */ - @Test - public void testFailureCounting_countFailuresForSingleBssidWithEphemeral() throws Exception { - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - boolean[] mIsEphemeral = {false, true, false, true}; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).associationRejection, i + 1); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).authenticationFailure, i + 1); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).dhcpFailure, i + 1); - } - assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - assertFailureCountEquals(mBssids[3], 0, 0, 0); - } - - /** - * Case 7: Test failure counting, incrementing a specific BSSID but with the wrong SSID given - * Test has 4 networks buffered, increment each different failure type on one of them but using - * the wrong ssid. - * Expected behavior: Failure counts will remain at zero for all networks - */ - @Test - public void testFailureCounting_countFailuresForSingleBssidWrongSsid() throws Exception { - String badSsid = "ItHertzWhenIP"; - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(badSsid, mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(badSsid, mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(badSsid, mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - - // Ensure all networks still have zero failure count - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - } - - /** - * Case 8: Test failure counting, increment a bssid that does not exist - * Test has 4 networks buffered, increment each failure type, but using the wrong bssid - * Expected behavior: Failure counts will remain at zero for all networks - */ - @Test - public void testFailureCounting_countFailuresForNonexistentBssid() throws Exception { - String badBssid = "a0:b0:c0:d0:ee:ff"; - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], badBssid, - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], badBssid, - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], badBssid, - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - - // Ensure all networks still have zero failure count - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - } - - /** - * Case 9: Test Failure Counting, using the "Any" BSSID - * Test has 4 buffered networks, two of which share the same SSID (different mBssids) - * Each failure type is incremented for the shared SSID, but with BSSID "any" - * Expected Behavior: Both networks increment their counts in tandem - */ - @Test - public void testFailureCounting_countFailuresForAnyBssid() throws Exception { - String[] ssids = {"\"test1\"", "\"test2\"", "\"test1\"", "\"test4\""}; - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - assertFailureCountEquals(mBssids[0], associationRejections, authenticationFailures, - dhcpFailures); - assertFailureCountEquals(mBssids[1], 0, 0, 0); - assertFailureCountEquals(mBssids[2], associationRejections, authenticationFailures, - dhcpFailures); - assertFailureCountEquals(mBssids[3], 0, 0, 0); - } - - /** - * Case 10: Test Failure Counting, using the "Any" BSSID for nonexistent SSID - * Test has 4 buffered networks, two of which share the same SSID (different mBssids) - * Each failure type is incremented for a bad SSID (doesn't exist), but with BSSID "any" - * Expected Behavior: No Failures counted - */ - @Test - public void testFailureCounting_countFailuresForAnyBssidNonexistentSsid() throws Exception { - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - String badSsid = "DropItLikeIt'sHotSpot"; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - badSsid, WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - badSsid, WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - badSsid, WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - // Check that all network failure counts are still zero - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - } - - /** - * Case 11: Test Failure Counting, over failure Threshold check - * Test has 4 buffered networks, cause FAILURE_THRESHOLD failures for each failure type to one - * of each network (leaving one unfailed). - * Expected Behavior: 3 of the Available Networks report OverFailureThreshold - */ - @Test - public void testFailureCounting_failureOverThresholdCheck() throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[0])); - assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[1])); - assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[2])); - assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[3])); - } - - /** - * Case 12: Test Failure Counting, under failure Threshold check - * Test has 4 buffered networks, cause FAILURE_THRESHOLD - 1 failures for each failure type to - * one of each network (leaving one unfailed). - * Expected Behavior: 0 of the Available Networks report OverFailureThreshold - */ - @Test - public void testFailureCounting_failureUnderThresholdCheck() throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[0])); - assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[1])); - assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[2])); - assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[3])); - } - - /** - * Case 13: Test Failure Counting, available network buffering does not affect counts - * In this test: - * 4 networks are buffered - * Some number of failures are counted - * networks are buffered again - * Expected Behavior: Failure counts are not modified by buffering - */ - @Test - public void testAvailableNetworkBuffering_doesNotAffectFailureCounts() throws Exception { - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).associationRejection); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).authenticationFailure); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).dhcpFailure); - } - // Check Each Network has appropriate failure count - assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - assertFailureCountEquals(mBssids[3], 0, 0, 0); - - // Re-buffer all networks - for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { - mLastResortWatchdog.updateAvailableNetworks(candidates); - } - - // Check Each Network still has appropriate failure count - assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - assertFailureCountEquals(mBssids[3], 0, 0, 0); - } - - /** - * Case 14: Test Failure Counting, culling of an old network will remove its failure counts - * In this test: - * 4 networks are buffered - * Some number of failures are counted for all networks - * 3 of the networks are buffered until the 4th dies of old age - * The 4th network is re-buffered - * Expected Behavior: Failure counts for the 4th network are cleared after re-buffering - */ - @Test - public void testAvailableNetworkBuffering_rebufferWipesCounts() throws Exception { - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).associationRejection); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).authenticationFailure); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).dhcpFailure); - } - // Check Each Network has appropriate failure count - assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - assertFailureCountEquals(mBssids[3], 0, 0, 0); - - // Re-buffer all networks except 'test1' until it dies of old age - candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 1, 4), - Arrays.copyOfRange(mBssids, 1, 4), - Arrays.copyOfRange(mFrequencies, 1, 4), - Arrays.copyOfRange(mCaps, 1, 4), - Arrays.copyOfRange(mLevels, 1, 4), - Arrays.copyOfRange(mIsEphemeral, 1, 4)); - for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { - mLastResortWatchdog.updateAvailableNetworks(candidates); - } - assertEquals(3, mLastResortWatchdog.getRecentAvailableNetworks().size()); - // Re-buffer All networks, with 'test1' again - candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Check Each Network has appropriate failure count (network 1 should be zero'd) - assertFailureCountEquals(mBssids[0], 0, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - assertFailureCountEquals(mBssids[3], 0, 0, 0); - } - - /** - * Case 26: Test Failure Counting, null failure incrementation - * In this test: - * 4 networks are buffered - * Attempt to increment failures with null BSSID & SSID - * Expected behavior: Nothing breaks, no counts incremented - */ - @Test - public void testFailureCounting_nullInputsNoBreaky() { - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(null, mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], null, - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(null, null, - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - } - - /** - * Case 27: Test Failure Counting, test all failures are counted across SSID - * In this test there are 8 networks, - * the first 4 networks have unique SSIDs amongst themselves, - * the last 4 networks share these SSIDs respectively, so there are 2 networks per SSID - * In this test we increment failure counts for the 'test1' ssid for a specific BSSID, and for - * the 'test2' ssid for BSSID_ANY. - * Expected behaviour: Failure counts for both networks on the same SSID are mirrored via both - * incrementation methods - */ - @Test - public void testFailureCounting_countFailuresAcrossSsids() throws Exception { - String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\"", - "\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""}; - String[] bssids = {"00:11:22:33:44:55", "01:23:45:67:89:ab", "aa:bb:cc:dd:ee:ff", - "ff:ee:dd:cc:bb:aa", "66:77:88:99:aa:bb", "cc:dd:ee:ff:00:01", "02:03:04:05:06:07", - "08:09:aa:bb:cc:dd"}; - int[] frequencies = {2437, 5180, 5180, 2437, 2437, 5180, 5180, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", - "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", - "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60, -86, -50, -62, -60, -86, -50, -62}; - boolean[] isEphemeral = {false, false, false, false, false, false, false, false}; - boolean[] hasEverConnected = {false, false, false, false, false, false, false, - false}; - int firstNetFails = 13; - int secondNetFails = 8; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - //Increment failure count for the first test network ssid & bssid - for (int i = 0; i < firstNetFails; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - //Increment failure count for the first test network ssid & BSSID_ANY - for (int i = 0; i < secondNetFails; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[1], WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[1], WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[1], WifiLastResortWatchdog.BSSID_ANY, - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - assertFailureCountEquals(bssids[0], firstNetFails, firstNetFails, firstNetFails); - assertFailureCountEquals(bssids[1], secondNetFails, secondNetFails, secondNetFails); - assertFailureCountEquals(bssids[2], 0, 0, 0); - assertFailureCountEquals(bssids[3], 0, 0, 0); - assertFailureCountEquals(bssids[4], firstNetFails, firstNetFails, firstNetFails); - assertFailureCountEquals(bssids[5], secondNetFails, secondNetFails, secondNetFails); - assertFailureCountEquals(bssids[6], 0, 0, 0); - assertFailureCountEquals(bssids[7], 0, 0, 0); - } - - /** - * Case 15: Test failure counting, ensure failures still counted while connected - * Although failures should not occur while wifi is connected, race conditions are a thing, and - * I'd like the count to be incremented even while connected (Later test verifies that this - * can't cause a trigger though) - * Expected behavior: Failure counts increment like normal - */ - @Test - public void testFailureCounting_wifiIsConnectedDoesNotAffectCounting() throws Exception { - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - - // Set Watchdogs internal wifi state tracking to 'connected' - mLastResortWatchdog.connectedStateTransition(true); - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).associationRejection); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).authenticationFailure); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() - .get(mBssids[net]).dhcpFailure); - } - assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - assertFailureCountEquals(mBssids[3], 0, 0, 0); - } - - /** - * Case 16: Test Failure Counting, entering ConnectedState clears all failure counts - * 4 Networks are buffered, cause various failures to 3 of them. Transition to ConnectedState - * Expected behavior: After transitioning, failure counts are reset to 0 - */ - @Test - public void testFailureCounting_enteringWifiConnectedStateClearsCounts() throws Exception { - int associationRejections = 5; - int authenticationFailures = 9; - int dhcpFailures = 11; - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - - // Check that we have Failures - assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - - // Transition to 'ConnectedState' - mLastResortWatchdog.connectedStateTransition(true); - - // Check that we have no failures - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - } - - /** - * Case 17: Test Trigger Condition, only some networks over threshold - * We have 4 buffered networks, increment failure counts on 3 of them, until all 3 are over - * threshold. - * Expected Behavior: Watchdog does not trigger - */ - @Test - public void testTriggerCondition_someNetworksOverFailureThreshold_allHaveEverConnected() - throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; - boolean[] hasEverConnected = {true, true, true, true}; - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Increment failure count for 3 networks and failure types, asserting each time that it - // does not trigger, with only 3 over threshold - boolean watchdogTriggered = false; - int net = 0; - for (int i = 0; i < associationRejections; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(false, watchdogTriggered); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(false, watchdogTriggered); - } - - // Check that we have Failures - assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); - assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); - assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); - - // Add one more failure to one of the already over threshold networks, assert that it - // does not trigger - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - - /** - * Case 18: Test Trigger Condition, watchdog fires once, then deactivates - * In this test we have 4 networks, which we have connected to in the past. Failures are - * incremented until all networks but one are over failure threshold, and then a few more times. - * - * Expected behavior: The watchdog triggers once as soon as all failures are over threshold, - * but stops triggering for subsequent failures - */ - @Test - public void testTriggerCondition_allNetworksOverFailureThreshold_allHaveEverConnected() - throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; - boolean[] hasEverConnected = {true, true, true, true}; - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Bring 3 of the 4 networks over failure Threshold without triggering watchdog - boolean watchdogTriggered = false; - int net = 0; - for (int i = 0; i < associationRejections; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(false, watchdogTriggered); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(false, watchdogTriggered); - } - - // Bring the remaining unfailed network upto 1 less than the failure threshold - net = 3; - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - // Increment failure count once more, check that watchdog triggered this time - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(true, watchdogTriggered); - - // Increment failure count 5 more times, watchdog should not trigger - for (int i = 0; i < 5; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - } - - /** - * Case 19: Test Trigger Condition, all networks over failure threshold, one has ever connected - * In this test we have 4 networks, only one has connected in the past. Failures are - * incremented until all networks but one are over failure threshold, and then a few more times. - * - * Expected behavior: The watchdog triggers once as soon as all failures are over threshold, - * but stops triggering for subsequent failures - */ - @Test - public void testTriggerCondition_allNetworksOverFailureThreshold_oneHaveEverConnected() - throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; - boolean[] hasEverConnected = {false, true, false, false}; - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Bring 3 of the 4 networks over failure Threshold without triggering watchdog - boolean watchdogTriggered = false; - int net = 0; - for (int i = 0; i < associationRejections; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(false, watchdogTriggered); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(false, watchdogTriggered); - } - - // Bring the remaining unfailed network upto 1 less than the failure threshold - net = 3; - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - // Increment failure count once more, check that watchdog triggered this time - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(true, watchdogTriggered); - - // Increment failure count 5 more times, watchdog should not trigger - for (int i = 0; i < 5; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - } - - /** - * Case 20: Test Trigger Condition, all networks over failure threshold, 0 have ever connected - * In this test we have 4 networks, none have ever connected. Failures are - * incremented until all networks but one are over failure threshold, and then a few more times. - * - * Expected behavior: The watchdog does not trigger - */ - @Test - public void testTriggerCondition_allNetworksOverFailureThreshold_zeroHaveEverConnected() - throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Count failures on all 4 networks until all of them are over the failure threshold - boolean watchdogTriggered = false; - int net = 0; - for (int i = 0; i < associationRejections; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(false, watchdogTriggered); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(false, watchdogTriggered); - } - net = 3; - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - } - - /** - * Case 21: Test Trigger Condition, Conditions right to trigger, but wifi is connected - * In this test we have 4 networks, all have connected in the past - * incremented until all networks but one are over failure threshold, and then a few more times. - * - * Expected behavior: The watchdog does not trigger - */ - @Test - public void testTriggerCondition_allNetworksOverFailureThreshold_isConnected() - throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Set Watchdogs internal wifi state tracking to 'connected' - mLastResortWatchdog.connectedStateTransition(true); - - // Count failures on all 4 networks until all of them are over the failure threshold - boolean watchdogTriggered = false; - int net = 0; - for (int i = 0; i < associationRejections; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - net = 1; - for (int i = 0; i < authenticationFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(false, watchdogTriggered); - } - net = 2; - for (int i = 0; i < dhcpFailures; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(false, watchdogTriggered); - } - net = 3; - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - } - - private void incrementFailuresUntilTrigger(String[] ssids, String[] bssids) { - // Bring 3 of the 4 networks over failure Threshold without triggering watchdog - boolean watchdogTriggered = false; - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - for (int j = 0; j < ssids.length - 1; j++) { - watchdogTriggered = mLastResortWatchdog - .noteConnectionFailureAndTriggerIfNeeded(ssids[j], bssids[j], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - } - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; i++) { - watchdogTriggered = mLastResortWatchdog - .noteConnectionFailureAndTriggerIfNeeded(ssids[ssids.length - 1], - bssids[ssids.length - 1], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - - // Increment failure count once more, check that watchdog triggered this time - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[ssids.length - 1], bssids[ssids.length - 1], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(true, watchdogTriggered); - verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_LAST_RESORT_WATCHDOG)); - reset(mSelfRecovery); - } - - /** - * Case 22: Test enabling/disabling of Watchdog Trigger, disabled after triggering - * In this test, we have 4 networks. Increment failures until Watchdog triggers. Increment some - * more failures. - * Expected behavior: Watchdog trigger gets deactivated after triggering, and stops triggering - */ - @Test - public void testTriggerEnabling_disabledAfterTriggering() throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; - boolean[] hasEverConnected = {false, true, false, false}; - - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - incrementFailuresUntilTrigger(mSsids, mBssids); - - // Increment failure count 5 more times, watchdog should not trigger - for (int i = 0; i < 5; i++) { - boolean watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[3], mBssids[3], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - } - - /** - * Case 23: Test enabling/disabling of Watchdog Trigger, trigger re-enabled after connecting - * In this test, we have 4 networks. Increment failures until Watchdog triggers and deactivates, - * transition wifi to connected state, then increment failures until all networks over threshold - * Expected behavior: Watchdog able to trigger again after transitioning to and from connected - * state - */ - @Test - public void testTriggerEnabling_enabledAfterConnecting() throws Exception { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; - boolean[] hasEverConnected = {false, true, false, false}; - boolean watchdogTriggered; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - incrementFailuresUntilTrigger(mSsids, mBssids); - - // Increment failure count 5 more times, ensure trigger is deactivated - for (int i = 0; i < 5; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[3], mBssids[3], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(false, watchdogTriggered); - } - - // transition Watchdog wifi state tracking to 'connected' then back to 'disconnected' - mLastResortWatchdog.connectedStateTransition(true); - mLastResortWatchdog.connectedStateTransition(false); - - // Fail 3/4 networks until they're over threshold - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[1], mBssids[1], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(false, watchdogTriggered); - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[2], mBssids[2], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - assertEquals(false, watchdogTriggered); - } - - // Bring the remaining unfailed network upto 1 less than the failure threshold - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[3], mBssids[3], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(false, watchdogTriggered); - } - // Increment failure count once more, check that watchdog triggered this time - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[3], mBssids[3], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - assertEquals(true, watchdogTriggered); - } - - /** - * Case 24: Test enabling/disabling of Watchdog Trigger, trigger re-enabled after - * timeout mechanism with new network available. - * In this test, we have 3 networks. Increment failures until Watchdog triggers and deactivates, - * we then buffer a new network (network 4), then increment failures until all networks over - * threshold Expected behavior: Watchdog able to trigger again after discovering a new network - */ - @Test - public void testTriggerEnabling_enabledAfterNewNetwork() { - int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; - int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; - int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; - boolean[] hasEverConnected = {false, true, false, false}; - boolean watchdogTriggered; - - final long timeAtFailure = 100; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeAtFailure); - - // Buffer potential candidates 1,2,3 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates( - Arrays.copyOfRange(mSsids, 0, 3), - Arrays.copyOfRange(mBssids, 0, 3), - Arrays.copyOfRange(mFrequencies, 0, 3), - Arrays.copyOfRange(mCaps, 0, 3), - Arrays.copyOfRange(mLevels, 0, 3), - Arrays.copyOfRange(mIsEphemeral, 0, 3), - Arrays.copyOfRange(hasEverConnected, 0, 3)); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - incrementFailuresUntilTrigger(Arrays.copyOfRange(mSsids, 0, 3), - Arrays.copyOfRange(mBssids, 0, 3)); - - // Increment failure count 5 more times, ensure trigger is deactivated - for (int i = 0; i < 5; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[2], mBssids[2], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - mLastResortWatchdog.updateAvailableNetworks(candidates); - assertEquals(false, watchdogTriggered); - } - - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(timeAtFailure + WifiLastResortWatchdog.LAST_TRIGGER_TIMEOUT_MILLIS); - - candidates = createFilteredQnsCandidates(mSsids, mBssids, mFrequencies, mCaps, mLevels, - mIsEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - incrementFailuresUntilTrigger(mSsids, mBssids); - } - - /** - * Case 28: Test Metrics collection - * Setup 5 networks (unique SSIDs). Fail them until watchdog triggers, with 1 network failing - * association, 1 failing authentication, 2 failing dhcp and one failing both authentication and - * dhcp, (over threshold for all these failures) - * Expected behavior: Metrics are updated as follows - * Triggers++ - * # of Networks += 5 - * Triggers with Bad association++ - * Triggers with Bad authentication++ - * Triggers with Bad dhcp++ - * Number of networks with bad association += 1 - * Number of networks with bad authentication += 2 - * Number of networks with bad dhcp += 3 - */ - @Test - public void testMetricsCollection() { - String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\"", "\"test5\""}; - String[] bssids = {"aa:bb:cc:dd:ee:ff", "00:11:22:33:44:55", "a0:b0:c0:d0:e0:f0", - "01:23:45:67:89:ab", "00:01:02:03:04:05"}; - int[] frequencies = {2437, 5180, 5180, 2437, 2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", - "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60, -86, -50, -62, -60}; - boolean[] isEphemeral = {false, false, false, false, false}; - boolean[] hasEverConnected = {true, false, false, false, false}; - // Buffer potential candidates 1,2,3,4 & 5 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - long timeAtFailure = 100; - long timeAtReconnect = 5000; - long expectedDuration = timeAtReconnect - timeAtFailure; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeAtFailure, timeAtReconnect); - - //Increment failure counts - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[1], bssids[1], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[2], bssids[2], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[3], bssids[3], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[4], bssids[4], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[4], bssids[4], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Verify relevant WifiMetrics calls were made once with appropriate arguments - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - verify(mWifiMetrics, times(1)).addCountToNumLastResortWatchdogAvailableNetworksTotal(5); - verify(mWifiMetrics, times(1)) - .addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(2); - verify(mWifiMetrics, times(1)) - .incrementNumLastResortWatchdogTriggersWithBadAuthentication(); - verify(mWifiMetrics, times(1)) - .addCountToNumLastResortWatchdogBadAssociationNetworksTotal(1); - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggersWithBadAssociation(); - verify(mWifiMetrics, times(1)).addCountToNumLastResortWatchdogBadDhcpNetworksTotal(3); - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggersWithBadDhcp(); - - // set connection to ssids[0]/bssids[0] - when(mWifiInfo.getSSID()).thenReturn(ssids[0]); - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - - // Simulate wifi connecting after triggering - mLastResortWatchdog.connectedStateTransition(true); - - // Verify that WifiMetrics counted this as a Watchdog success - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); - verify(mWifiMetrics, times(1)).setWatchdogSuccessTimeDurationMs(eq(expectedDuration)); - - // Verify takeBugReport is called - mLooper.dispatchAll(); - verify(mClientModeImpl, times(1)).takeBugReport(anyString(), anyString()); - - // Simulate wifi disconnecting - mLastResortWatchdog.connectedStateTransition(false); - - // Verify that WifiMetrics has still only counted one success - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); - verify(mWifiMetrics, times(1)).setWatchdogSuccessTimeDurationMs(eq(expectedDuration)); - // Verify takeBugReport not called again - mLooper.dispatchAll(); - verify(mClientModeImpl, times(1)).takeBugReport(anyString(), anyString()); - - // Remove the fifth network from candidates - candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 4), - Arrays.copyOfRange(mBssids, 0, 4), - Arrays.copyOfRange(mFrequencies, 0, 4), - Arrays.copyOfRange(mCaps, 0, 4), - Arrays.copyOfRange(mLevels, 0, 4), - Arrays.copyOfRange(mIsEphemeral, 0, 4)); - - // Age out the fifth network - for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { - mLastResortWatchdog.updateAvailableNetworks(candidates); - } - - timeAtFailure = 10100; - timeAtReconnect = 15000; - expectedDuration = timeAtReconnect - timeAtFailure; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeAtFailure, timeAtReconnect); - - //Increment failure counts - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[1], bssids[1], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[2], bssids[2], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[3], bssids[3], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // increment the timer to enable Watchdog - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(timeAtFailure + WifiLastResortWatchdog.LAST_TRIGGER_TIMEOUT_MILLIS); - - // Add network #5 back into the candidates - candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - - // LastResortWatchdog should reactivate if there is a new network (#5) - // available and time interval after last Watchdog trigger is over - // LAST_TRIGGER_TIMEOUT_MILLIS. - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Simulate wifi connecting - mLastResortWatchdog.connectedStateTransition(true); - - // Verify that WifiMetrics did not count another success, as the connection could be due - // to the newly available network #5 - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); - verify(mWifiMetrics, times(1)).setWatchdogSuccessTimeDurationMs(eq(expectedDuration)); - } - - /** - * Case 21: Test config updates where new config is null. - * Create a scan result with an associated config and update the available networks list. - * Repeat this with a second scan result where the config is null. - * Expected behavior: The stored config should not be lost overwritten. - */ - @Test - public void testUpdateNetworkWithNullConfig() { - List<Pair<ScanDetail, WifiConfiguration>> candidates = - new ArrayList<Pair<ScanDetail, WifiConfiguration>>(); - String ssid = mSsids[0].replaceAll("^\"+", "").replaceAll("\"+$", ""); - ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), - mBssids[0], mCaps[0], mLevels[0], mFrequencies[0], System.currentTimeMillis(), 0); - WifiConfiguration config = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); - when(networkSelectionStatus.hasEverConnected()) - .thenReturn(true); - candidates.add(Pair.create(scanDetail, config)); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - candidates.clear(); - - candidates.add(Pair.create(scanDetail, null)); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - boolean watchdogTriggered = false; - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - assertEquals(true, watchdogTriggered); - } - - /** - * Case 22: Test config updates where hasEverConnected goes from false to true. - * Create a scan result with an associated config and update the available networks list. - * Repeat this with a second scan result where the config value for hasEverConnected - * is true. - * Expected behavior: The stored config should not be lost overwritten. - */ - @Test - public void testUpdateNetworkWithHasEverConnectedTrue() { - List<Pair<ScanDetail, WifiConfiguration>> candidates = - new ArrayList<Pair<ScanDetail, WifiConfiguration>>(); - String ssid = mSsids[0].replaceAll("^\"+", "").replaceAll("\"+$", ""); - ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), - mBssids[0], mCaps[0], mLevels[0], mFrequencies[0], System.currentTimeMillis(), 0); - WifiConfiguration configHasEverConnectedFalse = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatusFalse = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(configHasEverConnectedFalse.getNetworkSelectionStatus()) - .thenReturn(networkSelectionStatusFalse); - when(networkSelectionStatusFalse.hasEverConnected()) - .thenReturn(false); - candidates.add(Pair.create(scanDetail, configHasEverConnectedFalse)); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - boolean watchdogTriggered = false; - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - assertEquals(false, watchdogTriggered); - - candidates.clear(); - - WifiConfiguration configHasEverConnectedTrue = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatusTrue = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(configHasEverConnectedTrue.getNetworkSelectionStatus()) - .thenReturn(networkSelectionStatusTrue); - when(networkSelectionStatusTrue.hasEverConnected()) - .thenReturn(true); - candidates.add(Pair.create(scanDetail, configHasEverConnectedTrue)); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - assertEquals(true, watchdogTriggered); - } - - /** - * Case 23: Test config updates where hasEverConnected goes from true to false. - * Create a scan result with an associated config and update the available networks list. - * Repeat this with a second scan result where hasEverConnected is false. - * Expected behavior: The stored config should not be lost overwritten. - */ - @Test - public void testUpdateNetworkWithHasEverConnectedFalse() { - List<Pair<ScanDetail, WifiConfiguration>> candidates = - new ArrayList<Pair<ScanDetail, WifiConfiguration>>(); - String ssid = mSsids[0].replaceAll("^\"+", "").replaceAll("\"+$", ""); - ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), - mBssids[0], mCaps[0], mLevels[0], mFrequencies[0], System.currentTimeMillis(), 0); - - WifiConfiguration configHasEverConnectedTrue = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatusTrue = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(configHasEverConnectedTrue.getNetworkSelectionStatus()) - .thenReturn(networkSelectionStatusTrue); - when(networkSelectionStatusTrue.hasEverConnected()) - .thenReturn(true); - candidates.add(Pair.create(scanDetail, configHasEverConnectedTrue)); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - boolean watchdogTriggered = false; - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - assertEquals(true, watchdogTriggered); - - candidates.clear(); - - WifiConfiguration configHasEverConnectedFalse = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatusFalse = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(configHasEverConnectedFalse.getNetworkSelectionStatus()) - .thenReturn(networkSelectionStatusFalse); - when(networkSelectionStatusFalse.hasEverConnected()) - .thenReturn(false); - candidates.add(Pair.create(scanDetail, configHasEverConnectedFalse)); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - assertEquals(false, watchdogTriggered); - } - - /** - * Case 24: Check toString method for accurate hasEverConnected value in - * AvailableNetworkFailureCount objects. - * Create an AvailableNetworkFailureCount instance and check output of toString method. - * Expected behavior: String contains HasEverConnected setting or null_config if there is not - * an associated config. - */ - @Test - public void testHasEverConnectedValueInAvailableNetworkFailureCountToString() { - // Check with HasEverConnected true - WifiConfiguration configHasEverConnectedTrue = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatusTrue = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(configHasEverConnectedTrue.getNetworkSelectionStatus()) - .thenReturn(networkSelectionStatusTrue); - when(networkSelectionStatusTrue.hasEverConnected()).thenReturn(true); - WifiLastResortWatchdog.AvailableNetworkFailureCount withConfigHECTrue = - new WifiLastResortWatchdog.AvailableNetworkFailureCount(configHasEverConnectedTrue); - String output = withConfigHECTrue.toString(); - assertTrue(output.contains("HasEverConnected: true")); - - // check with HasEverConnected false - WifiConfiguration configHasEverConnectedFalse = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatusFalse = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(configHasEverConnectedFalse.getNetworkSelectionStatus()) - .thenReturn(networkSelectionStatusFalse); - when(networkSelectionStatusFalse.hasEverConnected()).thenReturn(false); - WifiLastResortWatchdog.AvailableNetworkFailureCount withConfigHECFalse = - new WifiLastResortWatchdog.AvailableNetworkFailureCount( - configHasEverConnectedFalse); - output = withConfigHECFalse.toString(); - assertTrue(output.contains("HasEverConnected: false")); - - // Check with a null config - WifiLastResortWatchdog.AvailableNetworkFailureCount withNullConfig = - new WifiLastResortWatchdog.AvailableNetworkFailureCount(null); - output = withNullConfig.toString(); - assertTrue(output.contains("HasEverConnected: null_config")); - } - - /** - * Test metrics incrementing connection failure count after watchdog has already been triggered - */ - @Test - public void testIncrementingWatchdogConnectionFailuresAfterTrigger() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"04:03:02:01:00:0f"}; - int[] frequencies = {2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60}; - boolean[] isEphemeral = {false}; - boolean[] hasEverConnected = {true}; - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - //Increment failure counts - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Verify relevant WifiMetrics calls were made once with appropriate arguments - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - - // Verify that failure count after trigger is not incremented yet - verify(mWifiMetrics, never()).incrementWatchdogTotalConnectionFailureCountAfterTrigger(); - - // Fail 1 more time and verify this time it's counted - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - verify(mWifiMetrics, times(1)).incrementWatchdogTotalConnectionFailureCountAfterTrigger(); - } - - /** - * Test that LRWD success is only declared when the first connection after restarting wifi - * is successful. - * - * First tests the failure case: check success metric is not incremented when the first - * connection is a failure. - * Then test state transition and the success case: check success metric is incremented - * when the first connection is a success. - */ - @Test - public void testWatchdogAssumesSuccessOnlyIfFirstConnectionAfterRestartSucceeds() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"04:03:02:01:00:0f"}; - int[] frequencies = {2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60}; - boolean[] isEphemeral = {false}; - boolean[] hasEverConnected = {true}; - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - //Increment failure counts - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Verify watchdog has triggered a restart - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - - // Fail 1 more time and verify this time it's counted - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - - // Simulate wifi connecting after triggering - mLastResortWatchdog.connectedStateTransition(true); - // Verify takeBugReport is not called again - mLooper.dispatchAll(); - verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); - verify(mWifiMetrics, never()).incrementNumLastResortWatchdogSuccesses(); - - // Simulate wifi disconnecting - mLastResortWatchdog.connectedStateTransition(false); - - // set connection to ssids[0]/bssids[0] - when(mWifiInfo.getSSID()).thenReturn(ssids[0]); - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - - // Test another round, and this time successfully connect after restart trigger - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Verify watchdog has triggered a restart - verify(mWifiMetrics, times(2)).incrementNumLastResortWatchdogTriggers(); - // Simulate wifi connecting after triggering - mLastResortWatchdog.connectedStateTransition(true); - // Verify takeBugReport is not called again - mLooper.dispatchAll(); - verify(mClientModeImpl, times(1)).takeBugReport(anyString(), anyString()); - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); - } - - /** - * If the user changes the configuration and then we have a successful connection, don't - * trigger bugreport. - * Tests this specific path: - * 1. watchdog triggers restart - * 2. wifi configuration changes - * 3. wifi successfully connects immedietly after - * Expected result: bugreport should not trigger - */ - @Test - public void testWatchdogVerifiesAtLeastOneNetworkIsConnectedBeforeTriggeringBugreport() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"04:03:02:01:00:0f"}; - int[] frequencies = {2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60}; - boolean[] isEphemeral = {false}; - boolean[] hasEverConnected = {true}; - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - //Increment failure counts - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Verify watchdog has triggered a restart - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - - // Simulate user changing the configuration - when(candidates.get(0).second.getNetworkSelectionStatus().hasEverConnected()) - .thenReturn(false); - - mLastResortWatchdog.connectedStateTransition(true); - // Verify takeBugReport is not called again - mLooper.dispatchAll(); - verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); - verify(mWifiMetrics, never()).incrementNumLastResortWatchdogSuccesses(); - } - - /** - * Test Failure Counting, over failure Threshold check with mixture reason. - * Test has 4 buffered networks, cause FAILURE_THRESHOLD failures for mixture failure type - * (leaving one unfailed). - * Expected Behavior: 3 of the Available Networks report OverFailureThreshold - */ - @Test - public void testMixtureFailureCounting_failureOverThresholdCheck() throws Exception { - int associationRejections = 3; - int authenticationFailures = 4; - int dhcpFailures = 5; - // Buffer potential candidates 1,2,3 & 4 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, - mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - //Increment failure count for each network and failure type - int net = 0; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - net = 1; - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - net = 2; - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], - WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - - assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[0])); - assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[1])); - assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[2])); - assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[3])); - } - - /** - * Test Metrics collection with Mixture Reason. - * Setup 1 networks. Fail them until watchdog triggers - * with 2 authenticationFailures and 5 dhcpFailures. - * Expected behavior: Metrics are updated as follows - * Triggers++ - * # of Networks += 1 - * Triggers with Bad dhcp++ - * Number of networks with bad dhcp += 1 - */ - @Test - public void testMetricsCollectionWithMixtureReason() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"04:03:02:01:00:0f"}; - int[] frequencies = {2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60}; - boolean[] isEphemeral = {false}; - boolean[] hasEverConnected = {true}; - int authenticationFailures = 2; - int dhcpFailures = 5; - - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - //Increment failure counts - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - for (int i = 0; i < dhcpFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_DHCP); - } - - // Verify relevant WifiMetrics calls were made once with appropriate arguments - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - verify(mWifiMetrics, times(1)).addCountToNumLastResortWatchdogAvailableNetworksTotal(1); - verify(mWifiMetrics, never()) - .addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(anyInt()); - verify(mWifiMetrics, never()) - .incrementNumLastResortWatchdogTriggersWithBadAuthentication(); - verify(mWifiMetrics, never()) - .addCountToNumLastResortWatchdogBadAssociationNetworksTotal(anyInt()); - verify(mWifiMetrics, never()).incrementNumLastResortWatchdogTriggersWithBadAssociation(); - verify(mWifiMetrics, times(1)).addCountToNumLastResortWatchdogBadDhcpNetworksTotal(1); - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggersWithBadDhcp(); - } - - /** - * Test Watchdog with time based logic. - * - * After Watchdog has triggered once and still fail to connect, - * Watchdog will not be allowed to work in 2 hours. - * Expected result: Watchdog won't be trigger again - */ - @Test - public void testWatchdogWithTimeBasedLogic() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"04:03:02:01:00:0f"}; - int[] frequencies = {2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60}; - boolean[] isEphemeral = {false}; - boolean[] hasEverConnected = {true}; - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - final long timeAtFailure = 100; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeAtFailure); - - incrementFailuresUntilTrigger(ssids, bssids); - - // Verify watchdog has triggered a restart - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - - // Age out network - candidates = new ArrayList<>(); - for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { - mLastResortWatchdog.updateAvailableNetworks(candidates); - } - assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 0); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeAtFailure + (300 * 1000)); - - // network back into the candidates - candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < mSsids.length; i++) { - assertFailureCountEquals(mBssids[i], 0, 0, 0); - } - - // Increment failure counts - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Watchdog should not be triggerred since time based logic. - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - } - - /** - * Test that LRWD success is only declared when connected back to same SSID. - * - * First tests the failure case: check success metric is not incremented when the first - * connection on different SSID. - * Then test state transition and the success case: check success metric is incremented - * when the first connection on same SSID. - */ - @Test - public void testWatchdogAssumesSuccessOnlyIfConnectedOnSameSsid() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"04:03:02:01:00:0f"}; - int[] frequencies = {2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60}; - boolean[] isEphemeral = {false}; - boolean[] hasEverConnected = {true}; - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - //Increment failure counts - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Verify watchdog has triggered a restart - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - - // Simulate wifi connecting after triggering - mLastResortWatchdog.connectedStateTransition(true); - // Verify takeBugReport is not called because connected on different SSID - mLooper.dispatchAll(); - verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); - verify(mWifiMetrics, never()).incrementNumLastResortWatchdogSuccesses(); - - // Simulate wifi disconnecting - mLastResortWatchdog.connectedStateTransition(false); - - // set connection to ssids[0]/bssids[0] - when(mWifiInfo.getSSID()).thenReturn(ssids[0]); - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - - // Test another round, and this time successfully connect after restart trigger - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Verify watchdog has triggered a restart - verify(mWifiMetrics, times(2)).incrementNumLastResortWatchdogTriggers(); - // Simulate wifi connecting after triggering - mLastResortWatchdog.connectedStateTransition(true); - // Verify takeBugReport is called because connected back on same SSID - mLooper.dispatchAll(); - verify(mClientModeImpl, times(1)).takeBugReport(anyString(), anyString()); - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); - } - - /** - * Verifies that when a connection takes too long (time difference between - * StaEvent.TYPE_CMD_START_CONNECT and StaEvent.TYPE_NETWORK_CONNECTION_EVENT) a bugreport is - * taken. - */ - @Test - public void testAbnormalConnectionTimeTriggersBugreport() throws Exception { - // first verifies that bugreports are not taken when connection takes less than - // DEFAULT_ABNORMAL_CONNECTION_DURATION_MS - when(mClock.getElapsedSinceBootMillis()).thenReturn(1L); - mLastResortWatchdog.noteStartConnectTime(); - mLooper.dispatchAll(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - (long) DEFAULT_ABNORMAL_CONNECTION_DURATION_MS); - Handler handler = mLastResortWatchdog.getHandler(); - handler.sendMessage( - handler.obtainMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null)); - mLooper.dispatchAll(); - verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); - - // Now verify that bugreport is taken - mLastResortWatchdog.noteStartConnectTime(); - mLooper.dispatchAll(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 2L * DEFAULT_ABNORMAL_CONNECTION_DURATION_MS + 1); - handler.sendMessage( - handler.obtainMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null)); - mLooper.dispatchAll(); - verify(mClientModeImpl).takeBugReport(anyString(), anyString()); - - // Verify additional connections (without more TYPE_CMD_START_CONNECT) don't trigger more - // bugreports. - when(mClock.getElapsedSinceBootMillis()).thenReturn( - 4L * DEFAULT_ABNORMAL_CONNECTION_DURATION_MS); - handler.sendMessage( - handler.obtainMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null)); - mLooper.dispatchAll(); - verify(mClientModeImpl).takeBugReport(anyString(), anyString()); - } - - /** - * Changes the abnormal connection duration to a new value, and then verify that a bugreport is - * taken for a connection that takes longer than the new threshold. - * @throws Exception - */ - @Test - public void testGServicesSetDuration() throws Exception { - final int testDurationMs = 10 * 1000; // 10 seconds - when(mDeviceConfigFacade.getAbnormalConnectionDurationMs()).thenReturn(testDurationMs); - - // verifies that bugreport is taken for connections that take longer than |testDurationMs|. - when(mClock.getElapsedSinceBootMillis()).thenReturn(1L); - mLastResortWatchdog.noteStartConnectTime(); - mLooper.dispatchAll(); - when(mClock.getElapsedSinceBootMillis()).thenReturn((long) testDurationMs + 2); - Handler handler = mLastResortWatchdog.getHandler(); - handler.sendMessage( - handler.obtainMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null)); - mLooper.dispatchAll(); - verify(mClientModeImpl).takeBugReport(anyString(), anyString()); - } - - /** - * Verifies that bugreports are not triggered even when conditions are met after the - * applicable flag is changed to false. - * @throws Exception - */ - @Test - public void testGServicesFlagDisable() throws Exception { - when(mDeviceConfigFacade.isAbnormalConnectionBugreportEnabled()).thenReturn(false); - - // verifies that bugreports are not taken. - when(mClock.getElapsedSinceBootMillis()).thenReturn(1L); - mLastResortWatchdog.noteStartConnectTime(); - mLooper.dispatchAll(); - when(mClock.getElapsedSinceBootMillis()).thenReturn( - (long) DEFAULT_ABNORMAL_CONNECTION_DURATION_MS + 2); - Handler handler = mLastResortWatchdog.getHandler(); - handler.sendMessage( - handler.obtainMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null)); - mLooper.dispatchAll(); - verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); - } - - /** - * Verifies that bugreports are not triggered if device connected back to a new BSSID - * after recovery. - */ - @Test - public void testNotTriggerBugreportIfConnectedToNewBssid() { - int associationRejections = 4; - int authenticationFailures = 3; - String[] ssids = {"\"test1\"", "\"test1\"", "\"test1\""}; - String[] bssids = {"aa:bb:cc:dd:ee:ff", "00:11:22:33:44:55", "a0:b0:c0:d0:e0:f0"}; - int[] frequencies = {2437, 5180, 5180}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60, -86, -50}; - boolean[] isEphemeral = {false, false, false}; - boolean[] hasEverConnected = {true, true, true}; - // Buffer potential candidates 1,2,& 3 - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - long timeAtFailure = 100; - long timeAtReconnect = 5000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeAtFailure, timeAtReconnect); - - //Increment failure counts - for (int i = 0; i < associationRejections; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(ssids[1], bssids[1], - WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - for (int i = 0; i < authenticationFailures; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(ssids[2], bssids[2], - WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); - } - - // Verify watchdog has triggered a restart - verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); - - // set connection to ssids[0]/bssids[0] - when(mWifiInfo.getSSID()).thenReturn(ssids[0]); - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - - // Simulate wifi connecting after triggering - mLastResortWatchdog.connectedStateTransition(true); - - // Verify takeBugReport is not called - mLooper.dispatchAll(); - verify(mWifiMetrics, never()).incrementNumLastResortWatchdogSuccesses(); - verify(mClientModeImpl, never()).takeBugReport(anyString(), anyString()); - } - - /** - * Test recovery won't be triggered when feature is not enabled. - */ - @Test - public void testWatchdogFeatureNotEnabled() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"04:03:02:01:00:0f"}; - int[] frequencies = {2437}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {-60}; - boolean[] isEphemeral = {false}; - boolean[] hasEverConnected = {true}; - - // Set watchdog feature disabled - mResources.setBoolean(R.bool.config_wifi_watchdog_enabled, false); - createWifiLastResortWatchdog(); - - List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, - bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); - mLastResortWatchdog.updateAvailableNetworks(candidates); - - // Ensure new networks have zero'ed failure counts - for (int i = 0; i < ssids.length; i++) { - assertFailureCountEquals(bssids[i], 0, 0, 0); - } - - // Increment failure counts - for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { - mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( - ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); - } - - // Verify watchdog never trigger recovery - verify(mWifiMetrics, never()).incrementNumLastResortWatchdogTriggers(); - // Verify watchdog still trigger bugreport - mLooper.dispatchAll(); - verify(mClientModeImpl, times(1)).takeBugReport(anyString(), anyString()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiLinkLayerStatsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiLinkLayerStatsTest.java deleted file mode 100644 index b18d80b39..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiLinkLayerStatsTest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2017 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; - -import android.content.Context; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; - -import java.util.Random; - -/** - * Unit tests for {@link com.android.server.wifi.WifiLinkLayerStats}. - */ -@SmallTest -public class WifiLinkLayerStatsTest extends WifiBaseTest { - - ExtendedWifiInfo mWifiInfo; - WifiLinkLayerStats mWifiLinkLayerStats; - Random mRandom = new Random(); - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - mWifiInfo = new ExtendedWifiInfo(mock(Context.class)); - mWifiLinkLayerStats = new WifiLinkLayerStats(); - } - - /** - * Increments the counters - * - * The values are carved up among the 4 classes (be, bk, vi, vo) so the totals come out right. - */ - private void bumpCounters(WifiLinkLayerStats s, int txg, int txr, int txb, int rxg) { - int a = mRandom.nextInt(31); - int b = mRandom.nextInt(31); - int m0 = a & b; - int m1 = a & ~b; - int m2 = ~a & b; - int m3 = ~a & ~b; - assertEquals(-1, m0 + m1 + m2 + m3); - - s.rxmpdu_be += rxg & m0; - s.txmpdu_be += txg & m0; - s.lostmpdu_be += txb & m0; - s.retries_be += txr & m0; - - s.rxmpdu_bk += rxg & m1; - s.txmpdu_bk += txg & m1; - s.lostmpdu_bk += txb & m1; - s.retries_bk += txr & m1; - - s.rxmpdu_vi += rxg & m2; - s.txmpdu_vi += txg & m2; - s.lostmpdu_vi += txb & m2; - s.retries_vi += txr & m2; - - s.rxmpdu_vo += rxg & m3; - s.txmpdu_vo += txg & m3; - s.lostmpdu_vo += txb & m3; - s.retries_vo += txr & m3; - } - - /** - * - * Check that average rates converge to the right values - * - * Check that the total packet counts are correct - * - */ - @Test - public void checkThatAverageRatesConvergeToTheRightValuesAndTotalsAreRight() throws Exception { - int txg = mRandom.nextInt(1000); - int txr = mRandom.nextInt(100); - int txb = mRandom.nextInt(100); - int rxg = mRandom.nextInt(1000); - int n = 3 * 5; // Time constant is 3 seconds, 5 times time constant should get 99% there - for (int i = 0; i < n; i++) { - bumpCounters(mWifiLinkLayerStats, txg, txr, txb, rxg); - mWifiLinkLayerStats.timeStampInMs += 1000; - mWifiInfo.updatePacketRates(mWifiLinkLayerStats, mWifiLinkLayerStats.timeStampInMs); - } - // assertEquals(double, double, double) takes a tolerance as the third argument - assertEquals((double) txg, mWifiInfo.getSuccessfulTxPacketsPerSecond(), txg * 0.02); - assertEquals((double) txr, mWifiInfo.getRetriedTxPacketsPerSecond(), txr * 0.02); - assertEquals((double) txb, mWifiInfo.getLostTxPacketsPerSecond(), txb * 0.02); - assertEquals((double) rxg, mWifiInfo.getSuccessfulRxPacketsPerSecond(), rxg * 0.02); - - assertEquals(mWifiInfo.txSuccess, n * txg); - assertEquals(mWifiInfo.txRetries, n * txr); - assertEquals(mWifiInfo.txBad, n * txb); - assertEquals(mWifiInfo.rxSuccess, n * rxg); - } - - /** - * A single packet in a short period of time should have small effect - */ - @Test - public void aSinglePacketInAShortPeriodOfTimeShouldHaveSmallEffect() throws Exception { - bumpCounters(mWifiLinkLayerStats, 999999999, 999999999, 999999999, 99999999); - mWifiLinkLayerStats.timeStampInMs = 999999999; - mWifiInfo.updatePacketRates(mWifiLinkLayerStats, mWifiLinkLayerStats.timeStampInMs); - assertEquals(0.0, mWifiInfo.getSuccessfulTxPacketsPerSecond(), 0.0001); - bumpCounters(mWifiLinkLayerStats, 1, 1, 1, 1); - mWifiLinkLayerStats.timeStampInMs += 1; - mWifiInfo.updatePacketRates(mWifiLinkLayerStats, mWifiLinkLayerStats.timeStampInMs); - assertEquals(0.33, mWifiInfo.getSuccessfulTxPacketsPerSecond(), 0.01); - } - - /** - * Check for bad interactions with the alternative updatePacketRates method - */ - @Test - public void afterSourceSwitchTheRatesShouldGetReset() throws Exception { - // Do some updates using link layer stats - bumpCounters(mWifiLinkLayerStats, 999, 999, 999, 999); - mWifiLinkLayerStats.timeStampInMs = 999999999; - mWifiInfo.updatePacketRates(mWifiLinkLayerStats, mWifiLinkLayerStats.timeStampInMs); - assertEquals(0.0, mWifiInfo.getSuccessfulTxPacketsPerSecond(), 0.0001); - assertEquals(0.0, mWifiInfo.getSuccessfulRxPacketsPerSecond(), 0.0001); - bumpCounters(mWifiLinkLayerStats, 1_000_000_000, 777000, 66600, 1_000_100_000); - mWifiLinkLayerStats.timeStampInMs += 10_000; - mWifiInfo.updatePacketRates(mWifiLinkLayerStats, mWifiLinkLayerStats.timeStampInMs); - assertTrue("" + mWifiInfo + " " + mWifiLinkLayerStats, - mWifiInfo.getSuccessfulTxPacketsPerSecond() > 0.95e+8); - assertTrue("" + mWifiInfo + " " + mWifiLinkLayerStats, - mWifiInfo.getSuccessfulRxPacketsPerSecond() > 0.95e+8); - // Now update with traffic counters - mWifiLinkLayerStats.timeStampInMs += 10_000; - mWifiInfo.updatePacketRates(2_000_000_000L, 2_000_000_000L, - mWifiLinkLayerStats.timeStampInMs); - // Despite the increase, the rates should be zero after the change in source - assertEquals(0.0, mWifiInfo.getSuccessfulTxPacketsPerSecond(), 0.0001); - assertEquals(0.0, mWifiInfo.getSuccessfulRxPacketsPerSecond(), 0.0001); - assertEquals(0, mWifiInfo.txBad); - assertEquals(0, mWifiInfo.txRetries); - // Make sure that updates from this source work, too - mWifiLinkLayerStats.timeStampInMs += 10_000; - mWifiInfo.updatePacketRates(3_000_000_000L, 3_000_000_000L, - mWifiLinkLayerStats.timeStampInMs); - assertTrue(mWifiInfo.getSuccessfulTxPacketsPerSecond() > 0.95e+8); - assertTrue(mWifiInfo.getSuccessfulRxPacketsPerSecond() > 0.95e+8); - // Switch back to using link layer stats - mWifiLinkLayerStats.timeStampInMs += 10_000; - bumpCounters(mWifiLinkLayerStats, 1_000_000_000, 777000, 66600, 1_000_100_000); - mWifiInfo.updatePacketRates(mWifiLinkLayerStats, mWifiLinkLayerStats.timeStampInMs); - assertEquals(0.0, mWifiInfo.getSuccessfulTxPacketsPerSecond(), 0.0001); - assertEquals(0.0, mWifiInfo.getSuccessfulRxPacketsPerSecond(), 0.0001); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java deleted file mode 100644 index 40c47f4bf..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java +++ /dev/null @@ -1,1394 +0,0 @@ -/* - * Copyright (C) 2010 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.server.wifi; - -import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.ActivityManager; -import android.content.Context; -import android.net.wifi.WifiManager; -import android.os.BatteryStatsManager; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.WorkSource; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.NoSuchElementException; - -/** Unit tests for {@link WifiLockManager}. */ -@SmallTest -public class WifiLockManagerTest extends WifiBaseTest { - - private static final int DEFAULT_TEST_UID_1 = 52; - private static final int DEFAULT_TEST_UID_2 = 53; - private static final int DEFAULT_TEST_UID_3 = 54; - private static final int DEFAULT_TEST_UID_4 = 55; - private static final int WIFI_LOCK_MODE_INVALID = -1; - private static final String TEST_WIFI_LOCK_TAG = "TestTag"; - private static final String INTERFACE_NAME = "IfaceName"; - - private ActivityManager.OnUidImportanceListener mUidImportanceListener; - - WifiLockManager mWifiLockManager; - @Mock Clock mClock; - @Mock BatteryStatsManager mBatteryStats; - @Mock IBinder mBinder; - @Mock IBinder mBinder2; - WorkSource mWorkSource; - WorkSource mChainedWorkSource; - @Mock Context mContext; - @Mock ClientModeImpl mClientModeImpl; - @Mock FrameworkFacade mFrameworkFacade; - @Mock ActivityManager mActivityManager; - @Mock WifiMetrics mWifiMetrics; - @Mock WifiNative mWifiNative; - TestLooper mLooper; - Handler mHandler; - - /** - * Method to setup a WifiLockManager for the tests. - * The WifiLockManager uses mocks for BatteryStats and Context. - */ - @Before - public void setUp() { - mWorkSource = new WorkSource(DEFAULT_TEST_UID_1); - mChainedWorkSource = new WorkSource(); - mChainedWorkSource.createWorkChain() - .addNode(DEFAULT_TEST_UID_1, "tag1") - .addNode(DEFAULT_TEST_UID_2, "tag2"); - - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - mHandler = new Handler(mLooper.getLooper()); - when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager); - when(mWifiNative.getClientInterfaceName()).thenReturn(INTERFACE_NAME); - - mWifiLockManager = new WifiLockManager(mContext, mBatteryStats, - mClientModeImpl, mFrameworkFacade, mHandler, mWifiNative, mClock, mWifiMetrics); - } - - private void acquireWifiLockSuccessful(int lockMode, String tag, IBinder binder, WorkSource ws) - throws Exception { - ArgumentCaptor<IBinder.DeathRecipient> deathRecipient = - ArgumentCaptor.forClass(IBinder.DeathRecipient.class); - mWifiLockManager.updateWifiClientConnected(true); - assertTrue(mWifiLockManager.acquireWifiLock(lockMode, tag, binder, ws)); - assertThat(mWifiLockManager.getStrongestLockMode(), - not(WifiManager.WIFI_MODE_NO_LOCKS_HELD)); - InOrder inOrder = inOrder(binder, mBatteryStats); - - inOrder.verify(binder).linkToDeath(deathRecipient.capture(), eq(0)); - inOrder.verify(mBatteryStats).reportFullWifiLockAcquiredFromSource(ws); - } - - private void captureUidImportanceListener() { - ArgumentCaptor<ActivityManager.OnUidImportanceListener> uidImportanceListener = - ArgumentCaptor.forClass(ActivityManager.OnUidImportanceListener.class); - - verify(mActivityManager).addOnUidImportanceListener(uidImportanceListener.capture(), - anyInt()); - mUidImportanceListener = uidImportanceListener.getValue(); - assertNotNull(mUidImportanceListener); - } - - private void releaseWifiLockSuccessful(IBinder binder) throws Exception { - ArgumentCaptor<IBinder.DeathRecipient> deathRecipient = - ArgumentCaptor.forClass(IBinder.DeathRecipient.class); - - assertTrue(mWifiLockManager.releaseWifiLock(binder)); - InOrder inOrder = inOrder(binder, mBatteryStats); - inOrder.verify(binder).unlinkToDeath(deathRecipient.capture(), eq(0)); - inOrder.verify(mBatteryStats).reportFullWifiLockReleasedFromSource(any(WorkSource.class)); - } - - private void releaseWifiLockSuccessful_noBatteryStats(IBinder binder) throws Exception { - ArgumentCaptor<IBinder.DeathRecipient> deathRecipient = - ArgumentCaptor.forClass(IBinder.DeathRecipient.class); - - assertTrue(mWifiLockManager.releaseWifiLock(binder)); - InOrder inOrder = inOrder(binder, mBatteryStats); - inOrder.verify(binder).unlinkToDeath(deathRecipient.capture(), eq(0)); - } - - private void releaseLowLatencyWifiLockSuccessful(IBinder binder) throws Exception { - ArgumentCaptor<IBinder.DeathRecipient> deathRecipient = - ArgumentCaptor.forClass(IBinder.DeathRecipient.class); - - assertTrue(mWifiLockManager.releaseWifiLock(binder)); - InOrder inOrder = inOrder(binder, mBatteryStats); - inOrder.verify(binder).unlinkToDeath(deathRecipient.capture(), eq(0)); - inOrder.verify(mBatteryStats).reportFullWifiLockReleasedFromSource(any(WorkSource.class)); - } - - /** - * Test to check that a new WifiLockManager should not be holding any locks. - */ - @Test - public void newWifiLockManagerShouldNotHaveAnyLocks() { - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode()); - } - - /** - * Test that a call to acquireWifiLock with valid parameters works. - * - * Steps: call acquireWifiLock on the empty WifiLockManager. - * Expected: A subsequent call to getStrongestLockMode should reflect the type of the lock we - * just added - */ - @Test - public void acquireWifiLockWithValidParamsShouldSucceed() throws Exception { - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, mWifiLockManager.getStrongestLockMode()); - } - - /** - * Test that a call to acquireWifiLock will not succeed if there is already a lock for the same - * binder instance. - * - * Steps: call acquireWifiLock twice - * Expected: Second call should return false - */ - @Test - public void secondCallToAcquireWifiLockWithSameBinderShouldFail() throws Exception { - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - assertFalse(mWifiLockManager.acquireWifiLock( - WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource)); - } - - /** - * After acquiring a lock, we should be able to remove it. - * - * Steps: acquire a WifiLock and then remove it. - * Expected: Since a single lock was added, removing it should leave the WifiLockManager without - * any locks. We should not see any errors. - */ - @Test - public void releaseWifiLockShouldSucceed() throws Exception { - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource); - releaseWifiLockSuccessful(mBinder); - verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode()); - } - - /** - * Releasing locks for one caller should not release locks for a different caller. - * - * Steps: acquire locks for two callers and remove locks for one. - * Expected: locks for remaining caller should still be active. - */ - @Test - public void releaseLocksForOneCallerNotImpactOtherCallers() throws Exception { - IBinder toReleaseBinder = mock(IBinder.class); - WorkSource toReleaseWS = new WorkSource(DEFAULT_TEST_UID_1); - WorkSource toKeepWS = new WorkSource(DEFAULT_TEST_UID_2); - - acquireWifiLockSuccessful( - WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", toReleaseBinder, toReleaseWS); - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, toKeepWS); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, mWifiLockManager.getStrongestLockMode()); - releaseWifiLockSuccessful(toReleaseBinder); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, mWifiLockManager.getStrongestLockMode()); - releaseWifiLockSuccessful(mBinder); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode()); - } - - /** - * Attempting to release a lock that we do not hold should return false. - * - * Steps: release a WifiLock - * Expected: call to releaseWifiLock should return false. - */ - @Test - public void releaseWifiLockWithoutAcquireWillReturnFalse() { - assertFalse(mWifiLockManager.releaseWifiLock(mBinder)); - } - - /** - * Test used to verify call for getStrongestLockMode. - * - * Steps: The test first checks the return value for no held locks and then proceeds to test - * with a single lock of each type. - * Expected: getStrongestLockMode should reflect the type of lock we just added. - * Note: getStrongestLockMode should not reflect deprecated lock types - */ - @Test - public void checkForProperValueForGetStrongestLockMode() throws Exception { - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode()); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, mWifiLockManager.getStrongestLockMode()); - releaseWifiLockSuccessful(mBinder); - - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL, "", - mBinder, mWorkSource)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode()); - releaseWifiLockSuccessful(mBinder); - - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, "", - mBinder, mWorkSource)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode()); - } - - /** - * We should be able to create a merged WorkSource holding WorkSources for all active locks. - * - * Steps: call createMergedWorkSource and verify it is empty, add a lock and call again, it - * should have one entry. - * Expected: the first call should return a worksource with size 0 and the second should be size - * 1. - */ - @Test - public void createMergedWorkSourceShouldSucceed() throws Exception { - WorkSource checkMWS = mWifiLockManager.createMergedWorkSource(); - assertEquals(0, checkMWS.size()); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource); - checkMWS = mWifiLockManager.createMergedWorkSource(); - assertEquals(1, checkMWS.size()); - } - - /** - * Checks that WorkChains are preserved when merged WorkSources are created. - */ - @Test - public void createMergedworkSourceWithChainsShouldSucceed() throws Exception { - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource); - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder2, - mChainedWorkSource); - - WorkSource merged = mWifiLockManager.createMergedWorkSource(); - assertEquals(1, merged.size()); - assertEquals(1, merged.getWorkChains().size()); - } - - /** - * A smoke test for acquiring, updating and releasing WifiLocks with chained WorkSources. - */ - @Test - public void smokeTestLockLifecycleWithChainedWorkSource() throws Exception { - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, - mChainedWorkSource); - - WorkSource updated = new WorkSource(); - updated.set(mChainedWorkSource); - updated.createWorkChain().addNode( - DEFAULT_TEST_UID_1, "chain2"); - - mWifiLockManager.updateWifiLockWorkSource(mBinder, updated); - InOrder inOrder = inOrder(mBatteryStats); - inOrder.verify(mBatteryStats).reportFullWifiLockAcquiredFromSource(eq(updated)); - inOrder.verify(mBatteryStats).reportFullWifiLockReleasedFromSource(mChainedWorkSource); - - releaseWifiLockSuccessful(mBinder); - } - - /** - * Test the ability to update a WifiLock WorkSource with a new WorkSource. - * - * Steps: acquire a WifiLock with the default test worksource, then attempt to update it. - * Expected: Verify calls to release the original WorkSource and acquire with the new one to - * BatteryStats. - */ - @Test - public void testUpdateWifiLockWorkSourceCalledWithWorkSource() throws Exception { - WorkSource newWorkSource = new WorkSource(DEFAULT_TEST_UID_2); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource); - - mWifiLockManager.updateWifiLockWorkSource(mBinder, newWorkSource); - InOrder inOrder = inOrder(mBatteryStats); - inOrder.verify(mBatteryStats).reportFullWifiLockAcquiredFromSource(eq(newWorkSource)); - inOrder.verify(mBatteryStats).reportFullWifiLockReleasedFromSource(mWorkSource); - } - - /** - * Test the ability to update a WifiLock WorkSource with the callers UID. - * - * Steps: acquire a WifiLock with the default test worksource, then attempt to update it. - * Expected: Verify calls to release the original WorkSource and acquire with the new one to - * BatteryStats. - */ - @Test - public void testUpdateWifiLockWorkSourceCalledWithUID() throws Exception { - WorkSource newWorkSource = new WorkSource(Binder.getCallingUid()); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", mBinder, mWorkSource); - - mWifiLockManager.updateWifiLockWorkSource(mBinder, newWorkSource); - InOrder inOrder = inOrder(mBatteryStats); - inOrder.verify(mBatteryStats).reportFullWifiLockAcquiredFromSource(eq(newWorkSource)); - inOrder.verify(mBatteryStats).reportFullWifiLockReleasedFromSource(mWorkSource); - } - - /** - * Test an attempt to update a WifiLock that is not allocated. - * - * Steps: call updateWifiLockWorkSource - * Expected: catch an IllegalArgumentException - */ - @Test(expected = IllegalArgumentException.class) - public void testUpdateWifiLockWorkSourceCalledWithoutActiveLock() throws Exception { - mWifiLockManager.updateWifiLockWorkSource(mBinder, null); - } - - /** - * Test when acquiring a hi-perf lock, - * WifiLockManager calls to disable power save mechanism. - */ - @Test - public void testHiPerfLockAcquireCauseDisablePS() throws Exception { - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - verify(mClientModeImpl).setPowerSave(false); - } - - /** - * Test when releasing a hi-perf lock, - * WifiLockManager calls to enable power save mechanism. - */ - @Test - public void testHiPerfLockReleaseCauseEnablePS() throws Exception { - InOrder inOrder = inOrder(mClientModeImpl); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - releaseWifiLockSuccessful(mBinder); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - } - - /** - * Test when acquiring two hi-perf locks, then releasing them. - * WifiLockManager calls to disable/enable power save mechanism only once. - */ - @Test - public void testHiPerfLockAcquireReleaseTwice() throws Exception { - InOrder inOrder = inOrder(mClientModeImpl); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - // Acquire the first lock - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - // Now acquire another lock - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder2, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - // Release the first lock - releaseWifiLockSuccessful(mBinder); - verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - // Release the second lock - releaseWifiLockSuccessful(mBinder2); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - } - - /** - * Test when acquiring/releasing deprecated locks does not result in any action . - */ - @Test - public void testFullScanOnlyAcquireRelease() throws Exception { - IBinder fullLockBinder = mock(IBinder.class); - WorkSource fullLockWS = new WorkSource(DEFAULT_TEST_UID_1); - IBinder scanOnlyLockBinder = mock(IBinder.class); - WorkSource scanOnlyLockWS = new WorkSource(DEFAULT_TEST_UID_2); - - InOrder inOrder = inOrder(mClientModeImpl); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - // Acquire the first lock as FULL - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL, "", - fullLockBinder, fullLockWS)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - // Now acquire another lock with SCAN-ONLY - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, "", - scanOnlyLockBinder, scanOnlyLockWS)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - // Release the FULL lock - releaseWifiLockSuccessful_noBatteryStats(fullLockBinder); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - // Release the SCAN-ONLY lock - releaseWifiLockSuccessful_noBatteryStats(scanOnlyLockBinder); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - } - - /** - * Test failure case when setPowerSave() fails, during acquisition of hi-perf lock - * Note, the lock is still acquired despite the failure in setPowerSave(). - * On any new lock activity, the setPowerSave() will be attempted if still needed. - */ - @Test - public void testHiPerfLockAcquireFail() throws Exception { - IBinder fullLockBinder = mock(IBinder.class); - WorkSource fullLockWS = new WorkSource(DEFAULT_TEST_UID_1); - - InOrder inOrder = inOrder(mClientModeImpl); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(false); - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - // Now attempting adding some other lock, WifiLockManager should retry setPowerSave() - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL, "", - fullLockBinder, fullLockWS)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - } - - /** - * Test failure case when setPowerSave() fails, during release of hi-perf lock - * Note, the lock is still released despite the failure in setPowerSave(). - * On any new lock activity, the setPowerSave() will be re-attempted if still needed. - */ - @Test - public void testHiPerfLockReleaseFail() throws Exception { - IBinder fullLockBinder = mock(IBinder.class); - WorkSource fullLockWS = new WorkSource(DEFAULT_TEST_UID_1); - - InOrder inOrder = inOrder(mClientModeImpl); - when(mClientModeImpl.setPowerSave(false)).thenReturn(true); - when(mClientModeImpl.setPowerSave(true)).thenReturn(false); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - releaseWifiLockSuccessful(mBinder); - verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics, never()).addWifiLockActiveSession(anyInt(), anyLong()); - - // Now attempting adding some other lock, WifiLockManager should retry setPowerSave() - when(mClientModeImpl.setPowerSave(true)).thenReturn(true); - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL, "", - fullLockBinder, fullLockWS)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - } - - /** - * Test when forcing hi-perf mode, that it overrides apps requests - * until it is no longer forced. - */ - @Test - public void testForceHiPerf() throws Exception { - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - InOrder inOrder = inOrder(mClientModeImpl); - mWifiLockManager.updateWifiClientConnected(true); - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, "", - mBinder, mWorkSource)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - assertTrue(mWifiLockManager.forceHiPerfMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - assertTrue(mWifiLockManager.forceHiPerfMode(false)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - } - - /** - * Test when forcing hi-perf mode, and aquire/release of hi-perf locks - */ - @Test - public void testForceHiPerfAcqRelHiPerf() throws Exception { - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - InOrder inOrder = inOrder(mClientModeImpl); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - assertTrue(mWifiLockManager.forceHiPerfMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - releaseWifiLockSuccessful(mBinder); - verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - assertTrue(mWifiLockManager.forceHiPerfMode(false)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - } - - /** - * Test when trying to force hi-perf to true twice back to back - */ - @Test - public void testForceHiPerfTwice() throws Exception { - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - mWifiLockManager.updateWifiClientConnected(true); - InOrder inOrder = inOrder(mClientModeImpl); - - assertTrue(mWifiLockManager.forceHiPerfMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - assertTrue(mWifiLockManager.forceHiPerfMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - } - - /** - * Test when failure when forcing hi-perf mode - */ - @Test - public void testForceHiPerfFailure() throws Exception { - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(false); - mWifiLockManager.updateWifiClientConnected(true); - InOrder inOrder = inOrder(mClientModeImpl); - - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, "", - mBinder, mWorkSource)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - - assertFalse(mWifiLockManager.forceHiPerfMode(true)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - } - - /** - * Test if a foreground app acquires a low-latency lock, and screen is on, - * then that lock becomes the strongest lock even with presence of other locks. - */ - @Test - public void testForegroundAppAcquireLowLatencyScreenOn() throws Exception { - // Set screen on, and app foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder2, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - } - - /** - * Test if foreground app acquires a low-latency lock, and screen is off, - * then that lock becomes ineffective. - */ - @Test - public void testForegroundAppAcquireLowLatencyScreenOff() throws Exception { - // Set screen off, and app is foreground - mWifiLockManager.handleScreenStateChanged(false); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - "", mBinder, mWorkSource)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - } - - /** - * Test if an app in background acquires a low-latency lock, and screen is on, - * then that lock becomes ineffective. - */ - @Test - public void testBackgroundAppAcquireLowLatencyScreenOn() throws Exception { - // Set screen on, and app is background - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false); - - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - "", mBinder, mWorkSource)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - } - - /** - * Test when acquiring a low-latency lock from a foreground app, and screen is on, then, - * WifiLockManager calls to enable low-latency mechanism for devices supporting this. - */ - @Test - public void testLatencyLockAcquireCauseLlEnableNew() throws Exception { - // Set screen on, and app foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - - verify(mClientModeImpl).setLowLatencyMode(true); - verify(mClientModeImpl).setPowerSave(false); - } - - /** - * Test when acquiring a low-latency lock from a foreground app, and screen is on, then, - * WifiLockManager calls to disable power save, when low-latency mechanism is not supported. - */ - @Test - public void testLatencyLockAcquireCauseLL_enableLegacy() throws Exception { - // Set screen on, and app foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_TX_POWER_LIMIT); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - - verify(mClientModeImpl).setPowerSave(false); - verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - } - - /** - * Test when releasing an acquired low-latency lock, - * WifiLockManager calls to disable low-latency mechanism. - */ - @Test - public void testLatencyLockReleaseCauseLlDisable() throws Exception { - // Set screen on, and app foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - // Make sure setLowLatencyMode() is successful - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - InOrder inOrder = inOrder(mClientModeImpl); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - releaseLowLatencyWifiLockSuccessful(mBinder); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(false); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY), - anyLong()); - } - - /** - * Test when acquire of low-latency lock fails to enable low-latency mode, - * then release will not result in calling to disable low-latency. - */ - @Test - public void testLatencyLockReleaseFailure() throws Exception { - InOrder inOrder = inOrder(mClientModeImpl); - - // Set screen on, and app is foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - // Fail the call to ClientModeImpl - when(mClientModeImpl.setLowLatencyMode(true)).thenReturn(false); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - - releaseLowLatencyWifiLockSuccessful(mBinder); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - } - - /** - * Test when acquire of low-latency lock succeeds in enable low latency - * but fails to disable power save, then low latency mode is reverted - */ - @Test - public void testLatencyfail2DisablePowerSave() throws Exception { - InOrder inOrder = inOrder(mClientModeImpl); - - // Set screen on, and app is foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - // Succeed to setLowLatencyMode() - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - // Fail to setPowerSave() - when(mClientModeImpl.setPowerSave(false)).thenReturn(false); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - inOrder.verify(mClientModeImpl).setLowLatencyMode(false); - } - - /** - * Test when a low-latency lock is acquired (foreground app, screen-on), - * then, screen go off, then low-latency mode is turned off. - */ - @Test - public void testLatencyLockGoScreenOff() throws Exception { - // Set screen on, app foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - // Make sure setLowLatencyMode() is successful - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - InOrder inOrder = inOrder(mClientModeImpl); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - mWifiLockManager.handleScreenStateChanged(false); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(false); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY), - anyLong()); - } - - /** - * Test when a low-latency lock is acquired (foreground app, screen-on), - * then, app goes to background, then low-latency mode is turned off. - */ - @Test - public void testLatencyLockGoBackground() throws Exception { - // Initially, set screen on, app foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - // Make sure setLowLatencyMode() is successful - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - InOrder inOrder = inOrder(mClientModeImpl); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - captureUidImportanceListener(); - - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - /* App going to background */ - mUidImportanceListener.onUidImportance(DEFAULT_TEST_UID_1, - ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND); - mLooper.dispatchAll(); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(false); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY), - anyLong()); - } - - /** - * Test when a low-latency lock is acquired (background app, screen-on), - * then, lock is only effective when app goes to foreground. - */ - @Test - public void testLatencyLockGoForeground() throws Exception { - // Initially, set screen on, and app background - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - // Make sure setLowLatencyMode() is successful - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - - mWifiLockManager.updateWifiClientConnected(true); - - InOrder inOrder = inOrder(mClientModeImpl); - - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - "", mBinder, mWorkSource)); - captureUidImportanceListener(); - - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - /* App going to foreground */ - mUidImportanceListener.onUidImportance(DEFAULT_TEST_UID_1, - ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); - mLooper.dispatchAll(); - - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - } - - /** - * Test when both low-latency lock and hi-perf lock are acquired - * then, hi-perf is active when app is in background , while low-latency - * is active when app is in foreground (and screen on). - */ - @Test - public void testLatencyHiPerfLocks() throws Exception { - // Initially, set screen on, and app background - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - mWifiLockManager.updateWifiClientConnected(true); - - // Make sure setLowLatencyMode()/setPowerSave() is successful - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - InOrder inOrder = inOrder(mClientModeImpl); - - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - "", mBinder, mWorkSource)); - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - "", mBinder2, mWorkSource)); - captureUidImportanceListener(); - - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - /* App going to foreground */ - mUidImportanceListener.onUidImportance(DEFAULT_TEST_UID_1, - ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); - mLooper.dispatchAll(); - - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - } - - /** - * Test when forcing low-latency mode, that it overrides apps requests - * until it is no longer forced. - */ - @Test - public void testForceLowLatency() throws Exception { - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - InOrder inOrder = inOrder(mClientModeImpl); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - assertTrue(mWifiLockManager.forceLowLatencyMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - assertTrue(mWifiLockManager.forceLowLatencyMode(false)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(false); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY), - anyLong()); - } - - /** - * Test when forcing low-latency mode, that it is effective even if screen is off. - */ - @Test - public void testForceLowLatencyScreenOff() throws Exception { - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - mWifiLockManager.handleScreenStateChanged(false); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - mWifiLockManager.updateWifiClientConnected(true); - - InOrder inOrder = inOrder(mClientModeImpl); - - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - assertTrue(mWifiLockManager.forceLowLatencyMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - mWifiLockManager.handleScreenStateChanged(true); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - mWifiLockManager.handleScreenStateChanged(false); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - } - - /** - * Test when forcing low-latency mode, and aquire/release of low-latency locks - */ - @Test - public void testForceLowLatencyAcqRelLowLatency() throws Exception { - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - InOrder inOrder = inOrder(mClientModeImpl); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - assertTrue(mWifiLockManager.forceLowLatencyMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - releaseLowLatencyWifiLockSuccessful(mBinder); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - - assertTrue(mWifiLockManager.forceLowLatencyMode(false)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(false); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY), - anyLong()); - } - - /** - * Test when trying to force low-latency to true twice back to back - */ - @Test - public void testForceLowLatencyTwice() throws Exception { - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - mWifiLockManager.updateWifiClientConnected(true); - - InOrder inOrder = inOrder(mClientModeImpl); - - assertTrue(mWifiLockManager.forceLowLatencyMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - assertTrue(mWifiLockManager.forceLowLatencyMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl, never()).setLowLatencyMode(anyBoolean()); - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - } - - /** - * Test when forcing hi-perf mode then forcing low-latency mode - */ - @Test - public void testForceHiPerfLowLatency() throws Exception { - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - mWifiLockManager.updateWifiClientConnected(true); - InOrder inOrder = inOrder(mClientModeImpl); - - assertTrue(mWifiLockManager.forceHiPerfMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - assertTrue(mWifiLockManager.forceLowLatencyMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - } - - /** - * Test when forcing low-latency mode then forcing high-perf mode - */ - @Test - public void testForceLowLatencyHiPerf() throws Exception { - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - mWifiLockManager.updateWifiClientConnected(true); - - InOrder inOrder = inOrder(mClientModeImpl); - - assertTrue(mWifiLockManager.forceLowLatencyMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - inOrder.verify(mClientModeImpl).setPowerSave(false); - - assertTrue(mWifiLockManager.forceHiPerfMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(false); - inOrder.verify(mClientModeImpl).setPowerSave(true); - verify(mWifiMetrics).addWifiLockActiveSession(eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY), - anyLong()); - inOrder.verify(mClientModeImpl).setPowerSave(false); - } - - /** - * Test when failure when forcing low-latency mode - */ - @Test - public void testForceLowLatencyFailure() throws Exception { - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(false); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - InOrder inOrder = inOrder(mClientModeImpl); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - - assertFalse(mWifiLockManager.forceLowLatencyMode(true)); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, - mWifiLockManager.getStrongestLockMode()); - inOrder.verify(mClientModeImpl).setLowLatencyMode(true); - // Since setLowLatencyMode() failed, no call to setPowerSave() - inOrder.verify(mClientModeImpl, never()).setPowerSave(anyBoolean()); - } - - /** - * Test acquiring locks while device is not connected - * Expected: No locks are effective, and no call to other classes - */ - @Test - public void testAcquireLockWhileDisconnected() throws Exception { - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource)); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode()); - verify(mBatteryStats, never()).reportFullWifiLockAcquiredFromSource(any()); - } - - /** - * Test acquiring locks while device is not connected, then connecting to an AP - * Expected: Upon Connection, lock becomes effective - */ - @Test - public void testAcquireLockWhileDisconnectedConnect() throws Exception { - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource)); - mWifiLockManager.updateWifiClientConnected(true); - - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, mWifiLockManager.getStrongestLockMode()); - verify(mBatteryStats).reportFullWifiLockAcquiredFromSource(eq(mWorkSource)); - } - - /** - * Test acquiring locks while device is connected, then disconnecting from the AP - * Expected: Upon disconnection, lock becomes ineffective - */ - @Test - public void testAcquireLockWhileConnectedDisconnect() throws Exception { - // Set screen on, and app foreground - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource); - mWifiLockManager.updateWifiClientConnected(false); - - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, mWifiLockManager.getStrongestLockMode()); - verify(mBatteryStats).reportFullWifiLockReleasedFromSource(mWorkSource); - } - - /** - * Test that reporting of metrics for hi-perf lock acquistion is correct for both acquisition - * time and active time. - */ - @Test - public void testHighPerfLockMetrics() throws Exception { - long acquireTime = 1000; - long activationTime = 2000; - long deactivationTime = 3000; - long releaseTime = 4000; - - // Make sure setPowerSave() is successful - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - InOrder inOrder = inOrder(mWifiMetrics); - - // Acquire the lock - when(mClock.getElapsedSinceBootMillis()).thenReturn(acquireTime); - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource)); - - // Activate the lock - when(mClock.getElapsedSinceBootMillis()).thenReturn(activationTime); - mWifiLockManager.updateWifiClientConnected(true); - - // Deactivate the lock - when(mClock.getElapsedSinceBootMillis()).thenReturn(deactivationTime); - mWifiLockManager.updateWifiClientConnected(false); - - inOrder.verify(mWifiMetrics).addWifiLockActiveSession( - eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - eq(deactivationTime - activationTime)); - - // Release the lock - when(mClock.getElapsedSinceBootMillis()).thenReturn(releaseTime); - releaseWifiLockSuccessful_noBatteryStats(mBinder); - - inOrder.verify(mWifiMetrics).addWifiLockAcqSession( - eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - eq(releaseTime - acquireTime)); - } - - /** - * Test that reporting of metrics for low-latency lock acquistion is correct for - * both acquisition time and active time. - */ - @Test - public void testLowLatencyLockMetrics() throws Exception { - long acquireTime = 1000; - long activationTime = 2000; - long deactivationTime = 3000; - long releaseTime = 4000; - - // Make sure setLowLatencyMode()/setPowerSave() is successful - when(mClientModeImpl.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeImpl.setPowerSave(anyBoolean())).thenReturn(true); - - // Set condition for activation of low-latency (except connection to AP) - mWifiLockManager.handleScreenStateChanged(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mWifiNative.getSupportedFeatureSet(INTERFACE_NAME)) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); - - InOrder inOrder = inOrder(mWifiMetrics); - - // Acquire the lock - when(mClock.getElapsedSinceBootMillis()).thenReturn(acquireTime); - assertTrue(mWifiLockManager.acquireWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", - mBinder, mWorkSource)); - - // Activate the lock - when(mClock.getElapsedSinceBootMillis()).thenReturn(activationTime); - mWifiLockManager.updateWifiClientConnected(true); - - // Deactivate the lock - when(mClock.getElapsedSinceBootMillis()).thenReturn(deactivationTime); - mWifiLockManager.updateWifiClientConnected(false); - - inOrder.verify(mWifiMetrics).addWifiLockActiveSession( - eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY), - eq(deactivationTime - activationTime)); - - // Release the lock - when(mClock.getElapsedSinceBootMillis()).thenReturn(releaseTime); - releaseWifiLockSuccessful_noBatteryStats(mBinder); - - inOrder.verify(mWifiMetrics).addWifiLockAcqSession( - eq(WifiManager.WIFI_MODE_FULL_LOW_LATENCY), - eq(releaseTime - acquireTime)); - } - - /** - * Verfies that dump() does not fail when no locks are held. - */ - @Test - public void dumpDoesNotFailWhenNoLocksAreHeld() { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiLockManager.dump(pw); - - String wifiLockManagerDumpString = sw.toString(); - assertTrue(wifiLockManagerDumpString.contains( - "Locks acquired: 0 full high perf, 0 full low latency")); - assertTrue(wifiLockManagerDumpString.contains( - "Locks released: 0 full high perf, 0 full low latency")); - assertTrue(wifiLockManagerDumpString.contains("Locks held:")); - assertFalse(wifiLockManagerDumpString.contains("WifiLock{")); - } - - /** - * Verifies that dump() contains lock information when there are locks held. - */ - @Test - public void dumpOutputsCorrectInformationWithActiveLocks() throws Exception { - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TEST_WIFI_LOCK_TAG, - mBinder, mWorkSource); - releaseWifiLockSuccessful(mBinder); - verify(mWifiMetrics).addWifiLockAcqSession(eq(WifiManager.WIFI_MODE_FULL_HIGH_PERF), - anyLong()); - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TEST_WIFI_LOCK_TAG, - mBinder, mWorkSource); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiLockManager.dump(pw); - - String wifiLockManagerDumpString = sw.toString(); - assertTrue(wifiLockManagerDumpString.contains( - "Locks acquired: 2 full high perf, 0 full low latency")); - assertTrue(wifiLockManagerDumpString.contains( - "Locks released: 1 full high perf, 0 full low latency")); - assertTrue(wifiLockManagerDumpString.contains("Locks held:")); - assertTrue(wifiLockManagerDumpString.contains( - "WifiLock{" + TEST_WIFI_LOCK_TAG + " type=" + WifiManager.WIFI_MODE_FULL_HIGH_PERF - + " uid=" + Binder.getCallingUid() + " workSource=WorkSource{" - + DEFAULT_TEST_UID_1 + "}")); - } - - /** - * Verify that an Exception in unlinkDeathRecipient is caught. - */ - @Test - public void testUnlinkDeathRecipiientCatchesException() throws Exception { - acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "", - mBinder, mWorkSource); - assertEquals(WifiManager.WIFI_MODE_FULL_HIGH_PERF, mWifiLockManager.getStrongestLockMode()); - - doThrow(new NoSuchElementException()).when(mBinder).unlinkToDeath(any(), anyInt()); - releaseLowLatencyWifiLockSuccessful(mBinder); - assertEquals(WifiManager.WIFI_MODE_NO_LOCKS_HELD, - mWifiLockManager.getStrongestLockMode()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java deleted file mode 100644 index b69b30208..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java +++ /dev/null @@ -1,5169 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT; -import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT; -import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_STATIONARY; -import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN; - -import static com.android.server.wifi.WifiMetricsTestUtil.assertDeviceMobilityStatePnoScanStatsEqual; -import static com.android.server.wifi.WifiMetricsTestUtil.assertExperimentProbeCountsEqual; -import static com.android.server.wifi.WifiMetricsTestUtil.assertHistogramBucketsEqual; -import static com.android.server.wifi.WifiMetricsTestUtil.assertKeyCountsEqual; -import static com.android.server.wifi.WifiMetricsTestUtil.assertLinkProbeFailureReasonCountsEqual; -import static com.android.server.wifi.WifiMetricsTestUtil.assertLinkProbeStaEventsEqual; -import static com.android.server.wifi.WifiMetricsTestUtil.buildDeviceMobilityStatePnoScanStats; -import static com.android.server.wifi.WifiMetricsTestUtil.buildExperimentProbeCounts; -import static com.android.server.wifi.WifiMetricsTestUtil.buildHistogramBucketInt32; -import static com.android.server.wifi.WifiMetricsTestUtil.buildInt32Count; -import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureReasonCount; -import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureStaEvent; -import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeSuccessStaEvent; -import static com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.TYPE_LINK_PROBE; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -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.EAPConstants; -import android.net.wifi.IOnWifiUsabilityStatsListener; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SupplicantState; -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.WifiSsid; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.ProvisioningCallback; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.test.TestLooper; -import android.telephony.TelephonyManager; -import android.util.Base64; -import android.util.Pair; -import android.util.SparseIntArray; - -import androidx.test.filters.MediumTest; -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.server.wifi.aware.WifiAwareMetrics; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.hotspot2.PasspointMatch; -import com.android.server.wifi.hotspot2.PasspointProvider; -import com.android.server.wifi.p2p.WifiP2pMetrics; -import com.android.server.wifi.proto.WifiStatsLog; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorFailureStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HistogramBucketInt32; -import com.android.server.wifi.proto.nano.WifiMetricsProto.Int32Count; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason; -import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions; -import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.PnoScanMetrics; -import com.android.server.wifi.proto.nano.WifiMetricsProto.SoftApConnectedClientsEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiRadioUsage; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry; -import com.android.server.wifi.rtt.RttMetrics; -import com.android.server.wifi.util.ExternalCallbackTracker; -import com.android.server.wifi.util.InformationElementUtil; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import java.io.ByteArrayOutputStream; -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Unit tests for {@link com.android.server.wifi.WifiMetrics}. - */ -@SmallTest -public class WifiMetricsTest extends WifiBaseTest { - - WifiMetrics mWifiMetrics; - WifiMetricsProto.WifiLog mDecodedProto; - TestLooper mTestLooper; - Random mRandom = new Random(); - private static final int TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER = 2; - private static final int TEST_NETWORK_ID = 42; - private MockitoSession mSession; - @Mock Context mContext; - MockResources mResources; - @Mock FrameworkFacade mFacade; - @Mock Clock mClock; - @Mock ScoringParams mScoringParams; - @Mock WifiConfigManager mWcm; - @Mock BssidBlocklistMonitor mBssidBlocklistMonitor; - @Mock PasspointManager mPpm; - @Mock WifiNetworkSelector mWns; - @Mock WifiPowerMetrics mWifiPowerMetrics; - @Mock WifiDataStall mWifiDataStall; - @Mock WifiHealthMonitor mWifiHealthMonitor; - @Mock IBinder mAppBinder; - @Mock IOnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener; - @Mock ExternalCallbackTracker<IOnWifiUsabilityStatsListener> mListenerTracker; - @Mock WifiP2pMetrics mWifiP2pMetrics; - @Mock DppMetrics mDppMetrics; - @Mock WifiScoreCard mWifiScoreCard; - @Mock WifiScoreCard.PerNetwork mPerNetwork; - @Mock WifiScoreCard.NetworkConnectionStats mNetworkConnectionStats; - @Mock WifiConfiguration mWifiConfig; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mDecodedProto = null; - when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0); - mTestLooper = new TestLooper(); - mResources = new MockResources(); - when(mContext.getResources()).thenReturn(mResources); - mWifiMetrics = new WifiMetrics(mContext, mFacade, mClock, mTestLooper.getLooper(), - new WifiAwareMetrics(mClock), new RttMetrics(mClock), mWifiPowerMetrics, - mWifiP2pMetrics, mDppMetrics); - mWifiMetrics.setWifiConfigManager(mWcm); - mWifiMetrics.setBssidBlocklistMonitor(mBssidBlocklistMonitor); - mWifiMetrics.setPasspointManager(mPpm); - mWifiMetrics.setScoringParams(mScoringParams); - mWifiMetrics.setWifiNetworkSelector(mWns); - mWifiMetrics.setWifiDataStall(mWifiDataStall); - mWifiMetrics.setWifiHealthMonitor(mWifiHealthMonitor); - mWifiMetrics.setWifiScoreCard(mWifiScoreCard); - when(mWifiScoreCard.lookupNetwork(anyString())).thenReturn(mPerNetwork); - when(mPerNetwork.getRecentStats()).thenReturn(mNetworkConnectionStats); - } - - /** - * Test that startConnectionEvent and endConnectionEvent can be called repeatedly and out of - * order. Only tests no exception occurs. Creates 3 ConnectionEvents. - */ - @Test - public void startAndEndConnectionEventSucceeds() throws Exception { - //Start and end Connection event - mWifiMetrics.startConnectionEvent(null, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, - WifiMetricsProto.ConnectionEvent.HLF_DHCP, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - //end Connection event without starting one - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, - WifiMetricsProto.ConnectionEvent.HLF_DHCP, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - //start two ConnectionEvents in a row - mWifiMetrics.startConnectionEvent(null, "BLUE", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.startConnectionEvent(null, "GREEN", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - } - - private static final long TEST_RECORD_DURATION_SEC = 12 * 60 * 60; - private static final long TEST_RECORD_DURATION_MILLIS = TEST_RECORD_DURATION_SEC * 1000; - /** - * Simulate how dumpsys gets the proto from mWifiMetrics, filter the proto bytes out and - * deserialize them into mDecodedProto - */ - public void dumpProtoAndDeserialize() throws Exception { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS); - //Test proto dump, by passing in proto arg option - String[] args = {WifiMetrics.PROTO_DUMP_ARG}; - mWifiMetrics.dump(null, writer, args); - writer.flush(); - Pattern pattern = Pattern.compile( - "(?<=WifiMetrics:\\n)([\\s\\S]*)(?=EndWifiMetrics)"); - Matcher matcher = pattern.matcher(stream.toString()); - assertTrue("Proto Byte string found in WifiMetrics.dump():\n" + stream.toString(), - matcher.find()); - String protoByteString = matcher.group(1); - byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT); - mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes); - } - - /** - * Gets the 'clean dump' proto bytes from mWifiMetrics & deserializes it into - * mDecodedProto - */ - public void cleanDumpProtoAndDeserialize() throws Exception { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS); - //Test proto dump, by passing in proto arg option - String[] args = {WifiMetrics.PROTO_DUMP_ARG, WifiMetrics.CLEAN_DUMP_ARG}; - mWifiMetrics.dump(null, writer, args); - writer.flush(); - String protoByteString = stream.toString(); - byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT); - mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes); - } - - /** Verifies that dump() includes the expected header */ - @Test - public void stateDumpIncludesHeader() throws Exception { - assertStringContains(getStateDump(), "WifiMetrics"); - } - - /** Verifies that dump() includes correct alert count when there are no alerts. */ - @Test - public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception { - assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()"); - } - - /** Verifies that dump() includes correct alert count when there is one alert. */ - @Test - public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception { - mWifiMetrics.logFirmwareAlert(1); - assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)"); - } - - /** Verifies that dump() includes correct alert count when there are multiple alerts. */ - @Test - public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception { - mWifiMetrics.logFirmwareAlert(1); - mWifiMetrics.logFirmwareAlert(1); - mWifiMetrics.logFirmwareAlert(16); - assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)"); - } - - @Test - public void testDumpProtoAndDeserialize() throws Exception { - setAndIncrementMetrics(); - dumpProtoAndDeserialize(); - verify(mWifiP2pMetrics).consolidateProto(); - assertDeserializedMetricsCorrect(); - } - - private static final int NUM_OPEN_NETWORKS = 2; - private static final int NUM_LEGACY_PERSONAL_NETWORKS = 3; - private static final int NUM_LEGACY_ENTERPRISE_NETWORKS = 5; - private static final int NUM_ENHANCED_OPEN_NETWORKS = 1; - private static final int NUM_WPA3_PERSONAL_NETWORKS = 4; - private static final int NUM_WPA3_ENTERPRISE_NETWORKS = 6; - private static final int NUM_WAPI_PERSONAL_NETWORKS = 4; - private static final int NUM_WAPI_ENTERPRISE_NETWORKS = 6; - private static final int NUM_SAVED_NETWORKS = NUM_OPEN_NETWORKS + NUM_LEGACY_PERSONAL_NETWORKS - + NUM_LEGACY_ENTERPRISE_NETWORKS + NUM_ENHANCED_OPEN_NETWORKS - + NUM_WPA3_PERSONAL_NETWORKS + NUM_WPA3_ENTERPRISE_NETWORKS - + NUM_WAPI_PERSONAL_NETWORKS + NUM_WAPI_ENTERPRISE_NETWORKS; - private static final int NUM_HIDDEN_NETWORKS = NUM_OPEN_NETWORKS; - private static final int NUM_PASSPOINT_NETWORKS = NUM_LEGACY_ENTERPRISE_NETWORKS; - private static final int NUM_NETWORKS_ADDED_BY_USER = 0; - private static final int NUM_NETWORKS_ADDED_BY_APPS = NUM_SAVED_NETWORKS - - NUM_NETWORKS_ADDED_BY_USER; - private static final boolean TEST_VAL_IS_LOCATION_ENABLED = true; - private static final boolean IS_SCANNING_ALWAYS_ENABLED = true; - private static final boolean IS_VERBOSE_LOGGING_ENABLED = true; - private static final boolean IS_ENHANCED_MAC_RANDOMIZATION_FORCE_ENABLED = true; - private static final boolean IS_WIFI_WAKE_ENABLED = true; - private static final int NUM_EMPTY_SCAN_RESULTS = 19; - private static final int NUM_NON_EMPTY_SCAN_RESULTS = 23; - private static final int NUM_SCAN_UNKNOWN = 1; - private static final int NUM_SCAN_SUCCESS = 2; - private static final int NUM_SCAN_FAILURE_INTERRUPTED = 3; - private static final int NUM_SCAN_FAILURE_INVALID_CONFIGURATION = 5; - private static final int NUM_WIFI_UNKNOWN_SCREEN_OFF = 3; - private static final int NUM_WIFI_UNKNOWN_SCREEN_ON = 5; - private static final int NUM_WIFI_ASSOCIATED_SCREEN_OFF = 7; - private static final int NUM_WIFI_ASSOCIATED_SCREEN_ON = 11; - private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD = 11; - private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_BAD = 12; - private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD = 13; - private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD = 14; - private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS = 1; - private static final int NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL = 2; - private static final int NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL = 3; - private static final int NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL = 4; - private static final int NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL = 5; - private static final int NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL = 6; - private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION = 7; - private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION = 8; - private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP = 9; - private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER = 10; - private static final int NUM_LAST_RESORT_WATCHDOG_SUCCESSES = 5; - private static final int WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER = 6; - private static final int RSSI_POLL_FREQUENCY = 5150; - private static final int NUM_RSSI_LEVELS_TO_INCREMENT = 20; - private static final int NUM_OPEN_NETWORK_SCAN_RESULTS = 1; - private static final int NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS = 4; - private static final int NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS = 1; - private static final int NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS = 2; - private static final int NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS = 1; - private static final int NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS = 1; - private static final int NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS = 2; - private static final int NUM_HIDDEN_NETWORK_SCAN_RESULTS = 1; - private static final int NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS = 1; - private static final int NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS = 2; - private static final int NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS = 1; - private static final int NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS = - NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS + NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS - + NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS; - private static final int NUM_SCANS = 5; - private static final int NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT = 4; - private static final int NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS = 15; - private static final int NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 10; - private static final int NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 16; - // Look at buildMockScanDetailList, this number needs to match the mocked results - private static final int NUM_TOTAL_SCAN_RESULTS = NUM_OPEN_NETWORK_SCAN_RESULTS - + NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS + NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS - + NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS + NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS - + NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS + NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS - + NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS; - private static final int MIN_RSSI_LEVEL = -127; - private static final int MAX_RSSI_LEVEL = 0; - private static final int WIFI_SCORE_RANGE_MIN = 0; - private static final int NUM_WIFI_SCORES_TO_INCREMENT = 20; - private static final int WIFI_SCORE_RANGE_MAX = 60; - private static final int NUM_OUT_OF_BOUND_ENTRIES = 10; - private static final int MAX_NUM_SOFTAP_RETURN_CODES = 3; - private static final int NUM_SOFTAP_START_SUCCESS = 3; - private static final int NUM_SOFTAP_FAILED_GENERAL_ERROR = 2; - private static final int NUM_SOFTAP_FAILED_NO_CHANNEL = 1; - private static final int NUM_HAL_CRASHES = 11; - private static final int NUM_WIFICOND_CRASHES = 12; - private static final int NUM_SUPPLICANT_CRASHES = 23; - private static final int NUM_HOSTAPD_CRASHES = 7; - private static final int NUM_WIFI_ON_FAILURE_DUE_TO_HAL = 13; - private static final int NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND = 14; - private static final int NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT = 20; - private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL = 23; - private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND = 19; - private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD = 31; - private static final int NUM_SOFTAP_INTERFACE_DOWN = 65; - private static final int NUM_CLIENT_INTERFACE_DOWN = 12; - private static final int NUM_PASSPOINT_PROVIDERS = 7; - private static final int NUM_PASSPOINT_PROVIDER_INSTALLATION = 5; - private static final int NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS = 4; - private static final int NUM_PASSPOINT_PROVIDER_UNINSTALLATION = 3; - private static final int NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS = 2; - private static final int NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED = 1; - private static final int NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA = 2; - private static final int NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA = 3; - private static final int NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE = 4; - private static final int NUM_EAP_SIM_TYPE = 1; - private static final int NUM_EAP_TTLS_TYPE = 2; - private static final int NUM_EAP_TLS_TYPE = 3; - private static final int NUM_EAP_AKA_TYPE = 4; - private static final int NUM_EAP_AKA_PRIME_TYPE = 5; - private static final SparseIntArray SAVED_PASSPOINT_PROVIDERS_TYPE = new SparseIntArray(); - static { - SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_SIM, NUM_EAP_SIM_TYPE); - SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TTLS, NUM_EAP_TTLS_TYPE); - SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TLS, NUM_EAP_TLS_TYPE); - SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA, NUM_EAP_AKA_TYPE); - SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA_PRIME, NUM_EAP_AKA_PRIME_TYPE); - } - - private static final int NUM_PARTIAL_SCAN_RESULTS = 73; - private static final int NUM_PNO_SCAN_ATTEMPTS = 20; - private static final int NUM_PNO_SCAN_FAILED = 5; - private static final int NUM_PNO_FOUND_NETWORK_EVENTS = 10; - private static final int NUM_RADIO_MODE_CHANGE_TO_MCC = 4; - private static final int NUM_RADIO_MODE_CHANGE_TO_SCC = 13; - private static final int NUM_RADIO_MODE_CHANGE_TO_SBS = 19; - private static final int NUM_RADIO_MODE_CHANGE_TO_DBS = 34; - private static final int NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED = 14; - private static final long NUM_WATCHDOG_SUCCESS_DURATION_MS = 65; - private static final long WIFI_POWER_METRICS_LOGGING_DURATION = 280; - private static final long WIFI_POWER_METRICS_SCAN_TIME = 33; - private static final boolean WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING = true; - private static final boolean LINK_SPEED_COUNTS_LOGGING_SETTING = true; - private static final int DATA_STALL_MIN_TX_BAD_SETTING = 5; - private static final int DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING = 75; - private static final int NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS = 4; - private static final int NUM_ADD_OR_UPDATE_NETWORK_CALLS = 5; - private static final int NUM_ENABLE_NETWORK_CALLS = 6; - private static final long NUM_IP_RENEWAL_FAILURE = 7; - private static final int NUM_NETWORK_ABNORMAL_ASSOC_REJECTION = 2; - private static final int NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY = 4; - private static final int NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS = 5; - private static final int NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE = 3; - private static final long WIFI_MAINLINE_MODULE_VERSION = 123456L; - - /** Number of notifications per "Connect to Network" notification type. */ - private static final int[] NUM_CONNECT_TO_NETWORK_NOTIFICATIONS = {0, 10, 20, 30, 40}; - /** Number of notifications per "Connect to Network notification type and action type. */ - private static final int[][] NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS = { - {0, 1, 2, 3, 4}, - {10, 11, 12, 13, 14}, - {20, 21, 22, 23, 24}, - {30, 31, 32, 33, 34}, - {40, 41, 42, 43, 44}}; - private static final int SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST = 10; - private static final boolean IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = true; - private static final int NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND = 5; - private static final int NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES = 8; - private static final String OPEN_NET_NOTIFIER_TAG = OpenNetworkNotifier.TAG; - - private static final int NUM_SOFT_AP_EVENT_ENTRIES = 3; - private static final int NUM_SOFT_AP_ASSOCIATED_STATIONS = 3; - private static final int SOFT_AP_CHANNEL_FREQUENCY = 2437; - private static final int SOFT_AP_CHANNEL_BANDWIDTH = SoftApConnectedClientsEvent.BANDWIDTH_20; - private static final int SOFT_AP_MAX_CLIENT_SETTING = 10; - private static final int SOFT_AP_MAX_CLIENT_CAPABILITY = 16; - private static final long SOFT_AP_SHUTDOWN_TIMEOUT_SETTING = 10_000; - private static final long SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING = 600_000; - private static final boolean SOFT_AP_CLIENT_CONTROL_ENABLE = true; - private static final boolean IS_MAC_RANDOMIZATION_ON = true; - private static final int NUM_LINK_SPEED_LEVELS_TO_INCREMENT = 30; - private static final int TEST_RSSI_LEVEL = -80; - private static final int MAX_SUPPORTED_TX_LINK_SPEED_MBPS = 144; - private static final int MAX_SUPPORTED_RX_LINK_SPEED_MBPS = 190; - - private static final long NUM_MBO_SUPPORTED_NETWORKS_SCAN_RESULTS = 4; - private static final long NUM_MBO_CELL_DATA_AWARE_NETWORKS_SCAN_RESULTS = 2; - private static final long NUM_OCE_SUPPORTED_NETWORKS_SCAN_RESULTS = 2; - private static final long NUM_FILS_SUPPORTED_NETWORKS_SCAN_RESULTS = 2; - private static final long NUM_11AX_NETWORKS_SCAN_RESULTS = 3; - private static final long NUM_6G_NETWORKS_SCAN_RESULTS = 2; - private static final long NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND = 3; - private static final long NUM_CONNECT_TO_MBO_SUPPORTED_NETWORKS = 4; - private static final long NUM_CONNECT_TO_OCE_SUPPORTED_NETWORKS = 3; - private static final long NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST = 2; - private static final long NUM_MBO_CELLULAR_SWITCH_REQUEST = 3; - private static final long NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY = 3; - private static final long NUM_CONNECT_REQUEST_WITH_FILS_AKM = 4; - private static final long NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION = 3; - - public static final int FEATURE_MBO = 1 << 0; - public static final int FEATURE_MBO_CELL_DATA_AWARE = 1 << 1; - public static final int FEATURE_OCE = 1 << 2; - public static final int FEATURE_11AX = 1 << 3; - public static final int FEATURE_6G = 1 << 4; - - private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease, - String capabilities, int supportedFeatures) { - ScanDetail mockScanDetail = mock(ScanDetail.class); - NetworkDetail mockNetworkDetail = mock(NetworkDetail.class); - ScanResult mockScanResult = mock(ScanResult.class); - when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail); - when(mockScanDetail.getScanResult()).thenReturn(mockScanResult); - when(mockNetworkDetail.isHiddenBeaconFrame()).thenReturn(hidden); - when(mockNetworkDetail.getHSRelease()).thenReturn(hSRelease); - mockScanResult.capabilities = capabilities; - if ((supportedFeatures & FEATURE_MBO) != 0) { - when(mockNetworkDetail.isMboSupported()).thenReturn(true); - } - if ((supportedFeatures & FEATURE_MBO_CELL_DATA_AWARE) != 0) { - when(mockNetworkDetail.isMboCellularDataAware()).thenReturn(true); - } - if ((supportedFeatures & FEATURE_OCE) != 0) { - when(mockNetworkDetail.isOceSupported()).thenReturn(true); - } - if ((supportedFeatures & FEATURE_11AX) != 0) { - when(mockNetworkDetail.getWifiMode()) - .thenReturn(InformationElementUtil.WifiMode.MODE_11AX); - } - if ((supportedFeatures & FEATURE_6G) != 0) { - when(mockScanResult.is6GHz()).thenReturn(true); - } - return mockScanDetail; - } - - private ScanDetail buildMockScanDetail(String ssid, String bssid, boolean isOpen, - boolean isSaved, boolean isProvider, boolean isWeakRssi) { - ScanDetail mockScanDetail = mock(ScanDetail.class); - NetworkDetail mockNetworkDetail = mock(NetworkDetail.class); - ScanResult scanResult = new ScanResult(); - scanResult.SSID = ssid; - scanResult.BSSID = bssid; - when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail); - when(mockScanDetail.getScanResult()).thenReturn(scanResult); - when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(isWeakRssi); - scanResult.capabilities = isOpen ? "" : "PSK"; - if (isSaved) { - when(mWcm.getConfiguredNetworkForScanDetail(eq(mockScanDetail))) - .thenReturn(mock(WifiConfiguration.class)); - } - if (isProvider) { - PasspointProvider provider = mock(PasspointProvider.class); - List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = new ArrayList<>(); - matchedProviders.add(Pair.create(provider, null)); - when(mockNetworkDetail.isInterworking()).thenReturn(true); - when(mPpm.matchProvider(eq(scanResult), eq(false))).thenReturn(matchedProviders); - } - return mockScanDetail; - } - - private ScanDetail buildMockScanDetailPasspoint(String ssid, String bssid, long hessid, - int anqpDomainId, NetworkDetail.HSRelease hsRelease, boolean weakSignal) { - ScanDetail mockScanDetail = mock(ScanDetail.class); - NetworkDetail mockNetworkDetail = mock(NetworkDetail.class); - ScanResult scanResult = new ScanResult(); - scanResult.SSID = ssid; - scanResult.BSSID = bssid; - scanResult.hessid = hessid; - scanResult.capabilities = "PSK"; - when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail); - when(mockScanDetail.getScanResult()).thenReturn(scanResult); - when(mockNetworkDetail.getHSRelease()).thenReturn(hsRelease); - when(mockNetworkDetail.getAnqpDomainID()).thenReturn(anqpDomainId); - when(mockNetworkDetail.isInterworking()).thenReturn(true); - when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(weakSignal); - return mockScanDetail; - } - - private List<ScanDetail> buildMockScanDetailList() { - List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>(); - mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]", 0)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]", FEATURE_11AX)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]", 0)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]", FEATURE_MBO)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]", - FEATURE_11AX | FEATURE_6G)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]", 0)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]", - FEATURE_MBO | FEATURE_MBO_CELL_DATA_AWARE)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-OWE-CCMP]", - FEATURE_MBO | FEATURE_MBO_CELL_DATA_AWARE | FEATURE_OCE)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-EAP-SUITE-B-192]", - FEATURE_11AX | FEATURE_6G)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-PSK-SMS4-SMS4]", 0)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0)); - mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0)); - // Number of scans of R2 networks must be equal to NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS - mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2, - "[WPA-EAP-CCMP+EAP-FILS-SHA256-CCMP]", FEATURE_MBO | FEATURE_OCE)); - mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2, - "[WPA2-EAP+FT/EAP-CCMP+EAP-FILS-SHA256-CCMP]", 0)); - // Number of scans of R1 networks must be equal to NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS - mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1, - "[WPA-EAP-CCMP]", 0)); - // Number of scans of R3 networks must be equal to NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS - mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R3, - "[WPA-EAP-CCMP]", 0)); - return mockScanDetails; - } - - private List<WifiConfiguration> buildSavedNetworkList() { - List<WifiConfiguration> testSavedNetworks = new ArrayList<WifiConfiguration>(); - for (int i = 0; i < NUM_OPEN_NETWORKS; i++) { - testSavedNetworks.add(WifiConfigurationTestUtil.createOpenHiddenNetwork()); - } - for (int i = 0; i < NUM_LEGACY_PERSONAL_NETWORKS; i++) { - testSavedNetworks.add(WifiConfigurationTestUtil.createPskNetwork()); - } - for (int i = 0; i < NUM_LEGACY_ENTERPRISE_NETWORKS; i++) { - // Passpoint networks are counted in both Passpoint and Enterprise counters - testSavedNetworks.add(WifiConfigurationTestUtil.createPasspointNetwork()); - } - for (int i = 0; i < NUM_ENHANCED_OPEN_NETWORKS; i++) { - testSavedNetworks.add(WifiConfigurationTestUtil.createOweNetwork()); - } - for (int i = 0; i < NUM_WPA3_PERSONAL_NETWORKS; i++) { - testSavedNetworks.add(WifiConfigurationTestUtil.createSaeNetwork()); - } - for (int i = 0; i < NUM_WPA3_ENTERPRISE_NETWORKS; i++) { - testSavedNetworks.add(WifiConfigurationTestUtil.createEapSuiteBNetwork()); - } - for (int i = 0; i < NUM_WAPI_PERSONAL_NETWORKS; i++) { - testSavedNetworks.add(WifiConfigurationTestUtil.createWapiPskNetwork()); - } - for (int i = 0; i < NUM_WAPI_ENTERPRISE_NETWORKS; i++) { - testSavedNetworks.add(WifiConfigurationTestUtil.createWapiCertNetwork()); - } - testSavedNetworks.get(0).macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - return testSavedNetworks; - } - - private PasspointProvider createMockProvider(int eapType, boolean validateForR2) { - PasspointProvider provider = mock(PasspointProvider.class); - PasspointConfiguration config = mock(PasspointConfiguration.class); - Credential credential = new Credential(); - - switch (eapType) { - case EAPConstants.EAP_TLS: - credential.setCertCredential(new Credential.CertificateCredential()); - break; - case EAPConstants.EAP_TTLS: - credential.setUserCredential(new Credential.UserCredential()); - break; - case EAPConstants.EAP_AKA: - case EAPConstants.EAP_AKA_PRIME: - case EAPConstants.EAP_SIM: - Credential.SimCredential simCredential = new Credential.SimCredential(); - simCredential.setEapType(eapType); - credential.setSimCredential(simCredential); - break; - } - when(provider.getConfig()).thenReturn(config); - when(config.getCredential()).thenReturn(credential); - when(config.validateForR2()).thenReturn(validateForR2); - return provider; - } - - /** - * Set simple metrics, increment others - */ - public void setAndIncrementMetrics() throws Exception { - Map<String, PasspointProvider> providers = new HashMap<>(); - mWifiMetrics.updateSavedNetworks(buildSavedNetworkList()); - mWifiMetrics.updateSavedPasspointProfiles(NUM_PASSPOINT_PROVIDERS, - NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED); - for (int i = 0; i < SAVED_PASSPOINT_PROVIDERS_TYPE.size(); i++) { - int eapType = SAVED_PASSPOINT_PROVIDERS_TYPE.keyAt(i); - int count = SAVED_PASSPOINT_PROVIDERS_TYPE.valueAt(i); - for (int j = 0; j < count; j++) { - providers.put(Integer.toString(eapType) + j, createMockProvider(eapType, false)); - } - for (int j = count; j < count * 2; j++) { - providers.put(Integer.toString(eapType) + j, createMockProvider(eapType, true)); - } - } - mWifiMetrics.updateSavedPasspointProfilesInfo(providers); - - mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED); - mWifiMetrics.setIsScanningAlwaysEnabled(IS_SCANNING_ALWAYS_ENABLED); - mWifiMetrics.setVerboseLoggingEnabled(IS_VERBOSE_LOGGING_ENABLED); - mWifiMetrics.setEnhancedMacRandomizationForceEnabled( - IS_ENHANCED_MAC_RANDOMIZATION_FORCE_ENABLED); - mWifiMetrics.setWifiWakeEnabled(IS_WIFI_WAKE_ENABLED); - - for (int i = 0; i < NUM_EMPTY_SCAN_RESULTS; i++) { - mWifiMetrics.incrementEmptyScanResultCount(); - } - for (int i = 0; i < NUM_NON_EMPTY_SCAN_RESULTS; i++) { - mWifiMetrics.incrementNonEmptyScanResultCount(); - } - mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, - NUM_SCAN_UNKNOWN); - mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS, - NUM_SCAN_SUCCESS); - mWifiMetrics.incrementScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED, - NUM_SCAN_FAILURE_INTERRUPTED); - mWifiMetrics.incrementScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, - NUM_SCAN_FAILURE_INVALID_CONFIGURATION); - for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_OFF; i++) { - mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, - false); - } - for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_ON; i++) { - mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, - true); - } - for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_OFF; i++) { - mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, - false); - } - for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_ON; i++) { - mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, - true); - } - for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD; i++) { - mWifiMetrics.incrementNumConnectivityWatchdogPnoGood(); - } - for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_BAD; i++) { - mWifiMetrics.incrementNumConnectivityWatchdogPnoBad(); - } - for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD; i++) { - mWifiMetrics.incrementNumConnectivityWatchdogBackgroundGood(); - } - for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD; i++) { - mWifiMetrics.incrementNumConnectivityWatchdogBackgroundBad(); - } - for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS; i++) { - mWifiMetrics.incrementNumLastResortWatchdogTriggers(); - } - mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal( - NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL); - mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal( - NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL); - mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal( - NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL); - mWifiMetrics.addCountToNumLastResortWatchdogBadOtherNetworksTotal( - NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL); - mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal( - NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL); - for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION; i++) { - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation(); - } - for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION; i++) { - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication(); - } - for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP; i++) { - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp(); - } - for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER; i++) { - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadOther(); - } - for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_SUCCESSES; i++) { - mWifiMetrics.incrementNumLastResortWatchdogSuccesses(); - } - for (int i = 0; i < WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER; i++) { - mWifiMetrics.incrementWatchdogTotalConnectionFailureCountAfterTrigger(); - } - for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) { - for (int j = 0; j <= i; j++) { - mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL + i); - } - } - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL - i); - } - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MAX_RSSI_LEVEL + i); - } - - // Test alert-reason clamping. - mWifiMetrics.logFirmwareAlert(WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1); - mWifiMetrics.logFirmwareAlert(WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1); - // Simple cases for alert reason. - mWifiMetrics.logFirmwareAlert(1); - mWifiMetrics.logFirmwareAlert(1); - mWifiMetrics.logFirmwareAlert(1); - mWifiMetrics.logFirmwareAlert(2); - List<ScanDetail> mockScanDetails = buildMockScanDetailList(); - for (int i = 0; i < NUM_SCANS; i++) { - mWifiMetrics.countScanResults(mockScanDetails); - } - // increment connectivity scan metrics - for (int i = 0; i < NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT; i++) { - mWifiMetrics.incrementConnectivityOneshotScanCount(); - } - for (int i = 0; i < NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS; i++) { - mWifiMetrics.incrementExternalAppOneshotScanRequestsCount(); - } - for (int i = 0; i < NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) { - mWifiMetrics.incrementExternalForegroundAppOneshotScanRequestsThrottledCount(); - } - for (int i = 0; i < NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) { - mWifiMetrics.incrementExternalBackgroundAppOneshotScanRequestsThrottledCount(); - } - for (int score = 0; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) { - for (int offset = 0; offset <= score; offset++) { - mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN + score); - } - } - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN - i); - } - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MAX + i); - } - for (int score = 0; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) { - for (int offset = 0; offset <= score; offset++) { - mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MIN + score, 15); - } - } - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MIN - i, 15); - } - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MAX + i, 15); - } - - // increment soft ap start return codes - for (int i = 0; i < NUM_SOFTAP_START_SUCCESS; i++) { - mWifiMetrics.incrementSoftApStartResult(true, 0); - } - for (int i = 0; i < NUM_SOFTAP_FAILED_GENERAL_ERROR; i++) { - mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL); - } - for (int i = 0; i < NUM_SOFTAP_FAILED_NO_CHANNEL; i++) { - mWifiMetrics.incrementSoftApStartResult(false, - WifiManager.SAP_START_FAILURE_NO_CHANNEL); - } - for (int i = 0; i < NUM_HAL_CRASHES; i++) { - mWifiMetrics.incrementNumHalCrashes(); - } - for (int i = 0; i < NUM_WIFICOND_CRASHES; i++) { - mWifiMetrics.incrementNumWificondCrashes(); - } - for (int i = 0; i < NUM_SUPPLICANT_CRASHES; i++) { - mWifiMetrics.incrementNumSupplicantCrashes(); - } - for (int i = 0; i < NUM_HOSTAPD_CRASHES; i++) { - mWifiMetrics.incrementNumHostapdCrashes(); - } - for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_HAL; i++) { - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); - } - for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND; i++) { - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); - } - for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT; i++) { - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); - } - for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL; i++) { - mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); - } - for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND; i++) { - mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond(); - } - for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD; i++) { - mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); - } - for (int i = 0; i < NUM_SOFTAP_INTERFACE_DOWN; i++) { - mWifiMetrics.incrementNumSoftApInterfaceDown(); - } - for (int i = 0; i < NUM_CLIENT_INTERFACE_DOWN; i++) { - mWifiMetrics.incrementNumClientInterfaceDown(); - } - for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALLATION; i++) { - mWifiMetrics.incrementNumPasspointProviderInstallation(); - } - for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS; i++) { - mWifiMetrics.incrementNumPasspointProviderInstallSuccess(); - } - for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALLATION; i++) { - mWifiMetrics.incrementNumPasspointProviderUninstallation(); - } - for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS; i++) { - mWifiMetrics.incrementNumPasspointProviderUninstallSuccess(); - } - for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA; i++) { - mWifiMetrics.incrementNumPasspointProviderWithNoRootCa(); - } - for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA; i++) { - mWifiMetrics.incrementNumPasspointProviderWithSelfSignedRootCa(); - } - for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE; i++) { - mWifiMetrics.incrementNumPasspointProviderWithSubscriptionExpiration(); - } - for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_MCC; i++) { - mWifiMetrics.incrementNumRadioModeChangeToMcc(); - } - for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SCC; i++) { - mWifiMetrics.incrementNumRadioModeChangeToScc(); - } - for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SBS; i++) { - mWifiMetrics.incrementNumRadioModeChangeToSbs(); - } - for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_DBS; i++) { - mWifiMetrics.incrementNumRadioModeChangeToDbs(); - } - for (int i = 0; i < NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED; i++) { - mWifiMetrics.incrementNumSoftApUserBandPreferenceUnsatisfied(); - } - - // increment pno scan metrics - for (int i = 0; i < NUM_PNO_SCAN_ATTEMPTS; i++) { - mWifiMetrics.incrementPnoScanStartAttemptCount(); - } - for (int i = 0; i < NUM_PNO_SCAN_FAILED; i++) { - mWifiMetrics.incrementPnoScanFailedCount(); - } - for (int i = 0; i < NUM_PNO_FOUND_NETWORK_EVENTS; i++) { - mWifiMetrics.incrementPnoFoundNetworkEventCount(); - } - for (int i = 0; i < NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE; i++) { - mWifiMetrics.incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware(); - } - - // set and increment "connect to network" notification metrics - for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATIONS.length; i++) { - int count = NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[i]; - for (int j = 0; j < count; j++) { - mWifiMetrics.incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, i); - } - } - for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS.length; i++) { - int[] actions = NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS[i]; - for (int j = 0; j < actions.length; j++) { - int count = actions[j]; - for (int k = 0; k < count; k++) { - mWifiMetrics.incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, - i, j); - } - } - } - mWifiMetrics.setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG, - SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST); - mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG, - IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON); - for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) { - mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG); - } - for (int i = 0; i < NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND; i++) { - mWifiMetrics.incrementNumNetworkConnectMessageFailedToSend(OPEN_NET_NOTIFIER_TAG); - } - - addSoftApEventsToMetrics(); - - for (int i = 0; i < NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS; i++) { - mWifiMetrics.incrementOneshotScanWithDfsCount(); - } - for (int i = 0; i < NUM_ADD_OR_UPDATE_NETWORK_CALLS; i++) { - mWifiMetrics.incrementNumAddOrUpdateNetworkCalls(); - } - for (int i = 0; i < NUM_ENABLE_NETWORK_CALLS; i++) { - mWifiMetrics.incrementNumEnableNetworkCalls(); - } - for (int i = 0; i < NUM_IP_RENEWAL_FAILURE; i++) { - mWifiMetrics.incrementIpRenewalFailure(); - } - - mWifiMetrics.setWatchdogSuccessTimeDurationMs(NUM_WATCHDOG_SUCCESS_DURATION_MS); - mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, - IS_MAC_RANDOMIZATION_ON); - - addWifiPowerMetrics(); - - addWifiHealthMetrics(); - - mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, - WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING); - mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, - LINK_SPEED_COUNTS_LOGGING_SETTING); - mResources.setInteger(R.integer.config_wifiDataStallMinTxBad, - DATA_STALL_MIN_TX_BAD_SETTING); - mResources.setInteger(R.integer.config_wifiDataStallMinTxSuccessWithoutRx, - DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING); - - for (int i = 0; i < NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND; i++) { - mWifiMetrics.incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd(); - } - for (int i = 0; i < NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST; i++) { - mWifiMetrics.incrementForceScanCountDueToSteeringRequest(); - } - for (int i = 0; i < NUM_MBO_CELLULAR_SWITCH_REQUEST; i++) { - mWifiMetrics.incrementMboCellularSwitchRequestCount(); - } - for (int i = 0; i < NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY; i++) { - mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay(); - } - for (int i = 0; i < NUM_CONNECT_REQUEST_WITH_FILS_AKM; i++) { - mWifiMetrics.incrementConnectRequestWithFilsAkmCount(); - } - for (int i = 0; i < NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION; i++) { - mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount(); - } - } - - private void addWifiPowerMetrics() { - WifiRadioUsage wifiRadioUsage = new WifiRadioUsage(); - wifiRadioUsage.loggingDurationMs = WIFI_POWER_METRICS_LOGGING_DURATION; - wifiRadioUsage.scanTimeMs = WIFI_POWER_METRICS_SCAN_TIME; - when(mWifiPowerMetrics.buildWifiRadioUsageProto()).thenReturn(wifiRadioUsage); - } - - private void addWifiHealthMetrics() { - HealthMonitorMetrics metrics = new HealthMonitorMetrics(); - metrics.failureStatsIncrease = new HealthMonitorFailureStats(); - metrics.failureStatsDecrease = new HealthMonitorFailureStats(); - metrics.failureStatsHigh = new HealthMonitorFailureStats(); - metrics.failureStatsIncrease.cntAssocRejection = NUM_NETWORK_ABNORMAL_ASSOC_REJECTION; - metrics.numNetworkSufficientRecentStatsOnly = NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY; - metrics.numNetworkSufficientRecentPrevStats = NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS; - when(mWifiHealthMonitor.buildProto()).thenReturn(metrics); - when(mWifiHealthMonitor.getWifiStackVersion()).thenReturn(WIFI_MAINLINE_MODULE_VERSION); - } - - private void addSoftApEventsToMetrics() { - // Total number of events recorded is NUM_SOFT_AP_EVENT_ENTRIES in both modes - - mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_TETHERED, - SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING); - mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS, - WifiManager.IFACE_IP_MODE_TETHERED); - mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS, - WifiManager.IFACE_IP_MODE_UNSPECIFIED); // Should be dropped. - mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_TETHERED, - SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING); - // Channel switch info should be added to the last Soft AP UP event in the list - mWifiMetrics.addSoftApChannelSwitchedEvent(SOFT_AP_CHANNEL_FREQUENCY, - SOFT_AP_CHANNEL_BANDWIDTH, WifiManager.IFACE_IP_MODE_TETHERED); - SoftApConfiguration testSoftApConfig = new SoftApConfiguration.Builder() - .setSsid("Test_Metric_SSID") - .setMaxNumberOfClients(SOFT_AP_MAX_CLIENT_SETTING) - .setShutdownTimeoutMillis(SOFT_AP_SHUTDOWN_TIMEOUT_SETTING) - .setClientControlByUserEnabled(SOFT_AP_CLIENT_CONTROL_ENABLE) - .build(); - mWifiMetrics.updateSoftApConfiguration(testSoftApConfig, - WifiManager.IFACE_IP_MODE_TETHERED); - SoftApCapability testSoftApCapability = new SoftApCapability(0); - testSoftApCapability.setMaxSupportedClients(SOFT_AP_MAX_CLIENT_CAPABILITY); - mWifiMetrics.updateSoftApCapability(testSoftApCapability, - WifiManager.IFACE_IP_MODE_TETHERED); - - mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_LOCAL_ONLY, - SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING); - mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS, - WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - // Should be dropped. - mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR, - SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING); - mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_LOCAL_ONLY, - SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING); - } - - private void verifySoftApEventsStoredInProto() { - assertEquals(NUM_SOFT_AP_EVENT_ENTRIES, - mDecodedProto.softApConnectedClientsEventsTethered.length); - assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP, - mDecodedProto.softApConnectedClientsEventsTethered[0].eventType); - assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[0].numConnectedClients); - assertEquals(SOFT_AP_CHANNEL_FREQUENCY, - mDecodedProto.softApConnectedClientsEventsTethered[0].channelFrequency); - assertEquals(SOFT_AP_CHANNEL_BANDWIDTH, - mDecodedProto.softApConnectedClientsEventsTethered[0].channelBandwidth); - assertEquals(SOFT_AP_MAX_CLIENT_SETTING, - mDecodedProto.softApConnectedClientsEventsTethered[0] - .maxNumClientsSettingInSoftapConfiguration); - assertEquals(SOFT_AP_MAX_CLIENT_CAPABILITY, - mDecodedProto.softApConnectedClientsEventsTethered[0] - .maxNumClientsSettingInSoftapCapability); - assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_SETTING, - mDecodedProto.softApConnectedClientsEventsTethered[0] - .shutdownTimeoutSettingInSoftapConfiguration); - assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, - mDecodedProto.softApConnectedClientsEventsTethered[0] - .defaultShutdownTimeoutSetting); - assertEquals(SOFT_AP_CLIENT_CONTROL_ENABLE, - mDecodedProto.softApConnectedClientsEventsTethered[0].clientControlIsEnabled); - - assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED, - mDecodedProto.softApConnectedClientsEventsTethered[1].eventType); - assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS, - mDecodedProto.softApConnectedClientsEventsTethered[1].numConnectedClients); - assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN, - mDecodedProto.softApConnectedClientsEventsTethered[2].eventType); - assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[2].numConnectedClients); - - assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP, - mDecodedProto.softApConnectedClientsEventsLocalOnly[0].eventType); - assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[0].numConnectedClients); - assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED, - mDecodedProto.softApConnectedClientsEventsLocalOnly[1].eventType); - assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS, - mDecodedProto.softApConnectedClientsEventsLocalOnly[1].numConnectedClients); - assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN, - mDecodedProto.softApConnectedClientsEventsLocalOnly[2].eventType); - assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[2].numConnectedClients); - } - - /** - * Assert that values in deserializedWifiMetrics match those set in 'setAndIncrementMetrics' - */ - public void assertDeserializedMetricsCorrect() throws Exception { - assertEquals("mDecodedProto.numSavedNetworks == NUM_SAVED_NETWORKS", - NUM_SAVED_NETWORKS, mDecodedProto.numSavedNetworks); - assertEquals("mDecodedProto.numSavedNetworksWithMacRandomization == NUM_SAVED_NETWORKS-1", - NUM_SAVED_NETWORKS - 1, mDecodedProto.numSavedNetworksWithMacRandomization); - assertEquals("mDecodedProto.numOpenNetworks == NUM_OPEN_NETWORKS", - NUM_OPEN_NETWORKS, mDecodedProto.numOpenNetworks); - assertEquals("mDecodedProto.numLegacyPersonalNetworks == NUM_LEGACY_PERSONAL_NETWORKS", - NUM_LEGACY_PERSONAL_NETWORKS, mDecodedProto.numLegacyPersonalNetworks); - assertEquals( - "mDecodedProto.numLegacyEnterpriseNetworks == NUM_LEGACY_ENTERPRISE_NETWORKS", - NUM_LEGACY_ENTERPRISE_NETWORKS, mDecodedProto.numLegacyEnterpriseNetworks); - assertEquals("mDecodedProto.numEnhancedOpenNetworks == NUM_ENHANCED_OPEN_NETWORKS", - NUM_ENHANCED_OPEN_NETWORKS, mDecodedProto.numEnhancedOpenNetworks); - assertEquals("mDecodedProto.numWpa3PersonalNetworks == NUM_WPA3_PERSONAL_NETWORKS", - NUM_WPA3_PERSONAL_NETWORKS, mDecodedProto.numWpa3PersonalNetworks); - assertEquals("mDecodedProto.numWpa3EnterpriseNetworks == NUM_WPA3_ENTERPRISE_NETWORKS", - NUM_WPA3_ENTERPRISE_NETWORKS, mDecodedProto.numWpa3EnterpriseNetworks); - assertEquals("mDecodedProto.numWapiPersonalNetworks == NUM_WAPI_PERSONAL_NETWORKS", - NUM_WAPI_PERSONAL_NETWORKS, mDecodedProto.numWapiPersonalNetworks); - assertEquals("mDecodedProto.numWapiEnterpriseNetworks == NUM_WAPI_ENTERPRISE_NETWORKS", - NUM_WAPI_ENTERPRISE_NETWORKS, mDecodedProto.numWapiEnterpriseNetworks); - assertEquals("mDecodedProto.numNetworksAddedByUser == NUM_NETWORKS_ADDED_BY_USER", - NUM_NETWORKS_ADDED_BY_USER, mDecodedProto.numNetworksAddedByUser); - assertEquals(NUM_HIDDEN_NETWORKS, mDecodedProto.numHiddenNetworks); - assertEquals(NUM_PASSPOINT_NETWORKS, mDecodedProto.numPasspointNetworks); - assertEquals("mDecodedProto.numNetworksAddedByApps == NUM_NETWORKS_ADDED_BY_APPS", - NUM_NETWORKS_ADDED_BY_APPS, mDecodedProto.numNetworksAddedByApps); - assertEquals("mDecodedProto.isLocationEnabled == TEST_VAL_IS_LOCATION_ENABLED", - TEST_VAL_IS_LOCATION_ENABLED, mDecodedProto.isLocationEnabled); - assertEquals("mDecodedProto.isScanningAlwaysEnabled == IS_SCANNING_ALWAYS_ENABLED", - IS_SCANNING_ALWAYS_ENABLED, mDecodedProto.isScanningAlwaysEnabled); - assertEquals(IS_VERBOSE_LOGGING_ENABLED, mDecodedProto.isVerboseLoggingEnabled); - assertEquals(IS_ENHANCED_MAC_RANDOMIZATION_FORCE_ENABLED, - mDecodedProto.isEnhancedMacRandomizationForceEnabled); - assertEquals(IS_WIFI_WAKE_ENABLED, mDecodedProto.isWifiWakeEnabled); - assertEquals("mDecodedProto.numEmptyScanResults == NUM_EMPTY_SCAN_RESULTS", - NUM_EMPTY_SCAN_RESULTS, mDecodedProto.numEmptyScanResults); - assertEquals("mDecodedProto.numNonEmptyScanResults == NUM_NON_EMPTY_SCAN_RESULTS", - NUM_NON_EMPTY_SCAN_RESULTS, mDecodedProto.numNonEmptyScanResults); - assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, NUM_SCAN_UNKNOWN); - assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_SUCCESS, NUM_SCAN_SUCCESS); - assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED, - NUM_SCAN_FAILURE_INTERRUPTED); - assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, - NUM_SCAN_FAILURE_INVALID_CONFIGURATION); - assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false, - NUM_WIFI_UNKNOWN_SCREEN_OFF); - assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true, - NUM_WIFI_UNKNOWN_SCREEN_ON); - assertSystemStateEntryEquals( - WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false, NUM_WIFI_ASSOCIATED_SCREEN_OFF); - assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true, - NUM_WIFI_ASSOCIATED_SCREEN_ON); - assertEquals(NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD, - mDecodedProto.numConnectivityWatchdogPnoGood); - assertEquals(NUM_CONNECTIVITY_WATCHDOG_PNO_BAD, - mDecodedProto.numConnectivityWatchdogPnoBad); - assertEquals(NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD, - mDecodedProto.numConnectivityWatchdogBackgroundGood); - assertEquals(NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD, - mDecodedProto.numConnectivityWatchdogBackgroundBad); - assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS, - mDecodedProto.numLastResortWatchdogTriggers); - assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL, - mDecodedProto.numLastResortWatchdogBadAssociationNetworksTotal); - assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL, - mDecodedProto.numLastResortWatchdogBadAuthenticationNetworksTotal); - assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL, - mDecodedProto.numLastResortWatchdogBadDhcpNetworksTotal); - assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL, - mDecodedProto.numLastResortWatchdogBadOtherNetworksTotal); - assertEquals(NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL, - mDecodedProto.numLastResortWatchdogAvailableNetworksTotal); - assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION, - mDecodedProto.numLastResortWatchdogTriggersWithBadAssociation); - assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION, - mDecodedProto.numLastResortWatchdogTriggersWithBadAuthentication); - assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP, - mDecodedProto.numLastResortWatchdogTriggersWithBadDhcp); - assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER, - mDecodedProto.numLastResortWatchdogTriggersWithBadOther); - assertEquals(NUM_LAST_RESORT_WATCHDOG_SUCCESSES, - mDecodedProto.numLastResortWatchdogSuccesses); - assertEquals(WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER, - mDecodedProto.watchdogTotalConnectionFailureCountAfterTrigger); - assertEquals(TEST_RECORD_DURATION_SEC, - mDecodedProto.recordDurationSec); - for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) { - assertEquals(RSSI_POLL_FREQUENCY, - mDecodedProto.rssiPollRssiCount[i].frequency); - assertEquals(MIN_RSSI_LEVEL + i, mDecodedProto.rssiPollRssiCount[i].rssi); - assertEquals(i + 1, mDecodedProto.rssiPollRssiCount[i].count); - } - StringBuilder sb_rssi = new StringBuilder(); - sb_rssi.append("Number of RSSIs = " + mDecodedProto.rssiPollRssiCount.length); - assertTrue(sb_rssi.toString(), (mDecodedProto.rssiPollRssiCount.length - <= (MAX_RSSI_LEVEL - MIN_RSSI_LEVEL + 1))); - assertEquals(2, mDecodedProto.alertReasonCount[0].count); // Clamped reasons. - assertEquals(3, mDecodedProto.alertReasonCount[1].count); - assertEquals(1, mDecodedProto.alertReasonCount[2].count); - assertEquals(3, mDecodedProto.alertReasonCount.length); - assertEquals(NUM_TOTAL_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numTotalScanResults); - assertEquals(NUM_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numOpenNetworkScanResults); - assertEquals(NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numLegacyPersonalNetworkScanResults); - assertEquals(NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numLegacyEnterpriseNetworkScanResults); - assertEquals(NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numEnhancedOpenNetworkScanResults); - assertEquals(NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numWpa3PersonalNetworkScanResults); - assertEquals(NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numWpa3EnterpriseNetworkScanResults); - assertEquals(NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numWapiPersonalNetworkScanResults); - assertEquals(NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numWapiEnterpriseNetworkScanResults); - assertEquals(NUM_HIDDEN_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numHiddenNetworkScanResults); - assertEquals(NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numHotspot2R1NetworkScanResults); - assertEquals(NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numHotspot2R2NetworkScanResults); - assertEquals(NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numHotspot2R3NetworkScanResults); - - assertEquals(NUM_MBO_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numMboSupportedNetworkScanResults); - assertEquals(NUM_MBO_CELL_DATA_AWARE_NETWORKS_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numMboCellularDataAwareNetworkScanResults); - assertEquals(NUM_OCE_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numOceSupportedNetworkScanResults); - assertEquals(NUM_FILS_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.numFilsSupportedNetworkScanResults); - assertEquals(NUM_11AX_NETWORKS_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.num11AxNetworkScanResults); - assertEquals(NUM_6G_NETWORKS_SCAN_RESULTS * NUM_SCANS, - mDecodedProto.num6GNetworkScanResults); - assertEquals(NUM_SCANS, - mDecodedProto.numScans); - assertEquals(NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT, - mDecodedProto.numConnectivityOneshotScans); - assertEquals(NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS, - mDecodedProto.numExternalAppOneshotScanRequests); - assertEquals(NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED, - mDecodedProto.numExternalForegroundAppOneshotScanRequestsThrottled); - assertEquals(NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED, - mDecodedProto.numExternalBackgroundAppOneshotScanRequestsThrottled); - - for (int score_index = 0; score_index < NUM_WIFI_SCORES_TO_INCREMENT; score_index++) { - assertEquals(WIFI_SCORE_RANGE_MIN + score_index, - mDecodedProto.wifiScoreCount[score_index].score); - assertEquals(WIFI_SCORE_RANGE_MIN + score_index + 1, - mDecodedProto.wifiScoreCount[score_index].count); - assertEquals(WIFI_SCORE_RANGE_MIN + score_index, - mDecodedProto.wifiUsabilityScoreCount[score_index].score); - assertEquals(WIFI_SCORE_RANGE_MIN + score_index + 1, - mDecodedProto.wifiUsabilityScoreCount[score_index].count); - } - StringBuilder sb_wifi_score = new StringBuilder(); - sb_wifi_score.append("Number of wifi_scores = " + mDecodedProto.wifiScoreCount.length); - assertTrue(sb_wifi_score.toString(), (mDecodedProto.wifiScoreCount.length - <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1))); - StringBuilder sb_wifi_limits = new StringBuilder(); - sb_wifi_limits.append("Wifi Score limit is " + ConnectedScore.WIFI_MAX_SCORE - + ">= " + WIFI_SCORE_RANGE_MAX); - assertTrue(sb_wifi_limits.toString(), - ConnectedScore.WIFI_MAX_SCORE <= WIFI_SCORE_RANGE_MAX); - StringBuilder sb_wifi_usability_score = new StringBuilder(); - sb_wifi_usability_score.append("Number of wifi_usability_scores = " - + mDecodedProto.wifiUsabilityScoreCount.length); - assertTrue(sb_wifi_usability_score.toString(), (mDecodedProto.wifiUsabilityScoreCount.length - <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1))); - StringBuilder sb_wifi_usablity_limits = new StringBuilder(); - sb_wifi_limits.append("Wifi Usability Score limit is " + ConnectedScore.WIFI_MAX_SCORE - + ">= " + WIFI_SCORE_RANGE_MAX); - assertTrue(sb_wifi_limits.toString(), - ConnectedScore.WIFI_MAX_SCORE <= WIFI_SCORE_RANGE_MAX); - assertEquals(MAX_NUM_SOFTAP_RETURN_CODES, mDecodedProto.softApReturnCode.length); - assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY, - mDecodedProto.softApReturnCode[0].startResult); - assertEquals(NUM_SOFTAP_START_SUCCESS, mDecodedProto.softApReturnCode[0].count); - assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR, - mDecodedProto.softApReturnCode[1].startResult); - assertEquals(NUM_SOFTAP_FAILED_GENERAL_ERROR, - mDecodedProto.softApReturnCode[1].count); - assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL, - mDecodedProto.softApReturnCode[2].startResult); - assertEquals(NUM_SOFTAP_FAILED_NO_CHANNEL, - mDecodedProto.softApReturnCode[2].count); - assertEquals(NUM_HAL_CRASHES, mDecodedProto.numHalCrashes); - assertEquals(NUM_WIFICOND_CRASHES, mDecodedProto.numWificondCrashes); - assertEquals(NUM_SUPPLICANT_CRASHES, mDecodedProto.numSupplicantCrashes); - assertEquals(NUM_HOSTAPD_CRASHES, mDecodedProto.numHostapdCrashes); - assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_HAL, - mDecodedProto.numSetupClientInterfaceFailureDueToHal); - assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND, - mDecodedProto.numSetupClientInterfaceFailureDueToWificond); - assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT, - mDecodedProto.numSetupClientInterfaceFailureDueToSupplicant); - assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL, - mDecodedProto.numSetupSoftApInterfaceFailureDueToHal); - assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND, - mDecodedProto.numSetupSoftApInterfaceFailureDueToWificond); - assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD, - mDecodedProto.numSetupSoftApInterfaceFailureDueToHostapd); - assertEquals(NUM_CLIENT_INTERFACE_DOWN, mDecodedProto.numClientInterfaceDown); - assertEquals(NUM_SOFTAP_INTERFACE_DOWN, mDecodedProto.numSoftApInterfaceDown); - assertEquals(NUM_PASSPOINT_PROVIDERS, mDecodedProto.numPasspointProviders); - assertPasspointProfileTypeCount(mDecodedProto.installedPasspointProfileTypeForR1); - assertPasspointProfileTypeCount(mDecodedProto.installedPasspointProfileTypeForR2); - assertEquals(NUM_PASSPOINT_PROVIDER_INSTALLATION, - mDecodedProto.numPasspointProviderInstallation); - assertEquals(NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS, - mDecodedProto.numPasspointProviderInstallSuccess); - assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALLATION, - mDecodedProto.numPasspointProviderUninstallation); - assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS, - mDecodedProto.numPasspointProviderUninstallSuccess); - assertEquals(NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED, - mDecodedProto.numPasspointProvidersSuccessfullyConnected); - assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA, - mDecodedProto.numPasspointProviderWithNoRootCa); - assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA, - mDecodedProto.numPasspointProviderWithSelfSignedRootCa); - assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE, - mDecodedProto.numPasspointProviderWithSubscriptionExpiration); - assertEquals(NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE, - mDecodedProto.numBssidDifferentSelectionBetweenFrameworkAndFirmware); - - assertEquals(NUM_RADIO_MODE_CHANGE_TO_MCC, mDecodedProto.numRadioModeChangeToMcc); - assertEquals(NUM_RADIO_MODE_CHANGE_TO_SCC, mDecodedProto.numRadioModeChangeToScc); - assertEquals(NUM_RADIO_MODE_CHANGE_TO_SBS, mDecodedProto.numRadioModeChangeToSbs); - assertEquals(NUM_RADIO_MODE_CHANGE_TO_DBS, mDecodedProto.numRadioModeChangeToDbs); - assertEquals(NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED, - mDecodedProto.numSoftApUserBandPreferenceUnsatisfied); - - PnoScanMetrics pno_metrics = mDecodedProto.pnoScanMetrics; - assertNotNull(pno_metrics); - assertEquals(NUM_PNO_SCAN_ATTEMPTS, pno_metrics.numPnoScanAttempts); - assertEquals(NUM_PNO_SCAN_FAILED, pno_metrics.numPnoScanFailed); - assertEquals(NUM_PNO_FOUND_NETWORK_EVENTS, pno_metrics.numPnoFoundNetworkEvents); - - for (ConnectToNetworkNotificationAndActionCount notificationCount - : mDecodedProto.connectToNetworkNotificationCount) { - assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[notificationCount.notification], - notificationCount.count); - assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN, - notificationCount.recommender); - } - for (ConnectToNetworkNotificationAndActionCount notificationActionCount - : mDecodedProto.connectToNetworkNotificationActionCount) { - assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS - [notificationActionCount.notification] - [notificationActionCount.action], - notificationActionCount.count); - assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN, - notificationActionCount.recommender); - } - - assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST, - mDecodedProto.openNetworkRecommenderBlacklistSize); - assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, - mDecodedProto.isWifiNetworksAvailableNotificationOn); - assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES, - mDecodedProto.numOpenNetworkRecommendationUpdates); - assertEquals(NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND, - mDecodedProto.numOpenNetworkConnectMessageFailedToSend); - - verifySoftApEventsStoredInProto(); - - assertEquals(NUM_WATCHDOG_SUCCESS_DURATION_MS, - mDecodedProto.watchdogTriggerToConnectionSuccessDurationMs); - assertEquals(IS_MAC_RANDOMIZATION_ON, mDecodedProto.isMacRandomizationOn); - assertEquals(WIFI_POWER_METRICS_LOGGING_DURATION, - mDecodedProto.wifiRadioUsage.loggingDurationMs); - assertEquals(WIFI_POWER_METRICS_SCAN_TIME, - mDecodedProto.wifiRadioUsage.scanTimeMs); - assertEquals(WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING, - mDecodedProto.experimentValues.wifiIsUnusableLoggingEnabled); - assertEquals(LINK_SPEED_COUNTS_LOGGING_SETTING, - mDecodedProto.experimentValues.linkSpeedCountsLoggingEnabled); - assertEquals(DATA_STALL_MIN_TX_BAD_SETTING, - mDecodedProto.experimentValues.wifiDataStallMinTxBad); - assertEquals(DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING, - mDecodedProto.experimentValues.wifiDataStallMinTxSuccessWithoutRx); - assertEquals(NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS, - mDecodedProto.numOneshotHasDfsChannelScans); - assertEquals(NUM_ADD_OR_UPDATE_NETWORK_CALLS, mDecodedProto.numAddOrUpdateNetworkCalls); - assertEquals(NUM_ENABLE_NETWORK_CALLS, mDecodedProto.numEnableNetworkCalls); - assertEquals(NUM_IP_RENEWAL_FAILURE, mDecodedProto.numIpRenewalFailure); - assertEquals(NUM_NETWORK_ABNORMAL_ASSOC_REJECTION, - mDecodedProto.healthMonitorMetrics.failureStatsIncrease.cntAssocRejection); - assertEquals(0, - mDecodedProto.healthMonitorMetrics.failureStatsIncrease.cntAssocTimeout); - assertEquals(NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY, - mDecodedProto.healthMonitorMetrics.numNetworkSufficientRecentStatsOnly); - assertEquals(NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS, - mDecodedProto.healthMonitorMetrics.numNetworkSufficientRecentPrevStats); - assertEquals(NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND, - mDecodedProto.numBssidFilteredDueToMboAssocDisallowInd); - assertEquals(NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST, - mDecodedProto.numForceScanDueToSteeringRequest); - assertEquals(NUM_MBO_CELLULAR_SWITCH_REQUEST, - mDecodedProto.numMboCellularSwitchRequest); - assertEquals(NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY, - mDecodedProto.numSteeringRequestIncludingMboAssocRetryDelay); - assertEquals(NUM_CONNECT_REQUEST_WITH_FILS_AKM, - mDecodedProto.numConnectRequestWithFilsAkm); - assertEquals(NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION, - mDecodedProto.numL2ConnectionThroughFilsAuthentication); - assertEquals(WIFI_MAINLINE_MODULE_VERSION, mDecodedProto.mainlineModuleVersion); - - } - - /** - * Assert deserialized metrics Scan Return Entry equals count - */ - public void assertScanReturnEntryEquals(int returnCode, int count) { - for (int i = 0; i < mDecodedProto.scanReturnEntries.length; i++) { - if (mDecodedProto.scanReturnEntries[i].scanReturnCode == returnCode) { - assertEquals(count, mDecodedProto.scanReturnEntries[i].scanResultsCount); - return; - } - } - assertEquals(null, count); - } - - /** - * Assert deserialized metrics SystemState entry equals count - */ - public void assertSystemStateEntryEquals(int state, boolean screenOn, int count) { - for (int i = 0; i < mDecodedProto.wifiSystemStateEntries.length; i++) { - if (mDecodedProto.wifiSystemStateEntries[i].wifiState == state - && mDecodedProto.wifiSystemStateEntries[i].isScreenOn == screenOn) { - assertEquals(count, mDecodedProto.wifiSystemStateEntries[i].wifiStateCount); - return; - } - } - assertEquals(null, count); - } - - /** - * Test the number of Passpoint provision with the failure code are collected correctly - * - * @throws Exception - */ - @Test - public void testPasspointProvisionMetrics() throws Exception { - //Increment count for provisioning success. - mWifiMetrics.incrementPasspointProvisionSuccess(); - - // Increment count for provisioning unavailable - mWifiMetrics.incrementPasspointProvisionFailure( - ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE); - mWifiMetrics.incrementPasspointProvisionFailure( - ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE); - - // Increment count for server connection failure - mWifiMetrics.incrementPasspointProvisionFailure( - ProvisioningCallback.OSU_FAILURE_AP_CONNECTION); - - // Dump proto and deserialize - dumpProtoAndDeserialize(); - - assertEquals(mDecodedProto.passpointProvisionStats.numProvisionSuccess, 1); - assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount.length, 2); - assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].failureCode, - PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION); - assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].count, 1); - assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].failureCode, - PasspointProvisionStats.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE); - assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].count, 2); - } - - /** - * Combination of all other WifiMetrics unit tests, an internal-integration test, or functional - * test - */ - @Test - public void setMetricsSerializeDeserializeAssertMetricsSame() throws Exception { - setAndIncrementMetrics(); - startAndEndConnectionEventSucceeds(); - dumpProtoAndDeserialize(); - assertDeserializedMetricsCorrect(); - assertEquals("mDecodedProto.connectionEvent.length", - 2, mDecodedProto.connectionEvent.length); - //<TODO> test individual connectionEvents for correctness, - // check scanReturnEntries & wifiSystemStateEntries counts and individual elements - // pending their implementation</TODO> - } - - /** - * Test that score breach events are properly generated - */ - @Test - public void testScoreBeachEvents() throws Exception { - int upper = WifiMetrics.LOW_WIFI_SCORE + 7; - int mid = WifiMetrics.LOW_WIFI_SCORE; - int lower = WifiMetrics.LOW_WIFI_SCORE - 8; - mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); - for (int score = upper; score >= mid; score--) mWifiMetrics.incrementWifiScoreCount(score); - mWifiMetrics.incrementWifiScoreCount(mid + 1); - mWifiMetrics.incrementWifiScoreCount(lower); // First breach - for (int score = lower; score <= mid; score++) mWifiMetrics.incrementWifiScoreCount(score); - mWifiMetrics.incrementWifiScoreCount(mid - 1); - mWifiMetrics.incrementWifiScoreCount(upper); // Second breach - - dumpProtoAndDeserialize(); - - assertEquals(2, mDecodedProto.staEventList.length); - assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[0].type); - assertEquals(lower, mDecodedProto.staEventList[0].lastScore); - assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[1].type); - assertEquals(upper, mDecodedProto.staEventList[1].lastScore); - } - - /** - * Test that Wifi usability score breach events are properly generated - */ - @Test - public void testWifiUsabilityScoreBreachEvents() throws Exception { - int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7; - int mid = WifiMetrics.LOW_WIFI_USABILITY_SCORE; - int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8; - mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); - for (int score = upper; score >= mid; score--) { - mWifiMetrics.incrementWifiUsabilityScoreCount(1, score, 15); - } - mWifiMetrics.incrementWifiUsabilityScoreCount(1, mid + 1, 15); - mWifiMetrics.incrementWifiUsabilityScoreCount(1, lower, 15); // First breach - for (int score = lower; score <= mid; score++) { - mWifiMetrics.incrementWifiUsabilityScoreCount(1, score, 15); - } - mWifiMetrics.incrementWifiUsabilityScoreCount(1, mid - 1, 15); - mWifiMetrics.incrementWifiUsabilityScoreCount(1, upper, 15); // Second breach - - dumpProtoAndDeserialize(); - - assertEquals(2, mDecodedProto.staEventList.length); - assertEquals(StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, mDecodedProto.staEventList[0].type); - assertEquals(lower, mDecodedProto.staEventList[0].lastWifiUsabilityScore); - assertEquals(StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, mDecodedProto.staEventList[1].type); - assertEquals(upper, mDecodedProto.staEventList[1].lastWifiUsabilityScore); - } - - private static final String SSID = "red"; - private static final int CONFIG_DTIM = 3; - private static final int NETWORK_DETAIL_WIFIMODE = 5; - private static final int NETWORK_DETAIL_DTIM = 7; - private static final int SCAN_RESULT_LEVEL = -30; - /** - * Test that WifiMetrics is correctly getting data from ScanDetail and WifiConfiguration - */ - @Test - public void testScanDetailAndWifiConfigurationUsage() throws Exception { - //Setup mock configs and scan details - NetworkDetail networkDetail = mock(NetworkDetail.class); - when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE); - when(networkDetail.getSSID()).thenReturn(SSID); - when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM); - ScanResult scanResult = mock(ScanResult.class); - scanResult.level = SCAN_RESULT_LEVEL; - scanResult.capabilities = "EAP"; - WifiConfiguration config = mock(WifiConfiguration.class); - config.SSID = "\"" + SSID + "\""; - config.dtimInterval = CONFIG_DTIM; - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - config.allowedKeyManagement = new BitSet(); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - config.enterpriseConfig = new WifiEnterpriseConfig(); - config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); - config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2); - config.enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); - WifiConfiguration.NetworkSelectionStatus networkSelectionStat = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(networkSelectionStat.getCandidate()).thenReturn(scanResult); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat); - ScanDetail scanDetail = mock(ScanDetail.class); - when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); - when(scanDetail.getScanResult()).thenReturn(scanResult); - when(networkDetail.isMboSupported()).thenReturn(true); - when(networkDetail.isOceSupported()).thenReturn(true); - - config.networkId = TEST_NETWORK_ID; - mWifiMetrics.setNominatorForNetwork(TEST_NETWORK_ID, - WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL); - - //Create a connection event using only the config - mWifiMetrics.startConnectionEvent(config, "Red", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - //Change configuration to open without randomization - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - scanResult.capabilities = ""; - //Create a connection event using the config and a scan detail - mWifiMetrics.startConnectionEvent(config, "Green", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.setConnectionScanDetail(scanDetail); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - //Dump proto from mWifiMetrics and deserialize it to mDecodedProto - dumpProtoAndDeserialize(); - - //Check that the correct values are being flowed through - assertEquals(2, mDecodedProto.connectionEvent.length); - assertEquals(CONFIG_DTIM, mDecodedProto.connectionEvent[0].routerFingerprint.dtim); - assertEquals(WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE, - mDecodedProto.connectionEvent[0].routerFingerprint.authentication); - assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TTLS, - mDecodedProto.connectionEvent[0].routerFingerprint.eapMethod); - assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAPV2, - mDecodedProto.connectionEvent[0].routerFingerprint.authPhase2Method); - assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUIRE_CERT_STATUS, - mDecodedProto.connectionEvent[0].routerFingerprint.ocspType); - assertEquals(SCAN_RESULT_LEVEL, mDecodedProto.connectionEvent[0].signalStrength); - assertEquals(NETWORK_DETAIL_DTIM, mDecodedProto.connectionEvent[1].routerFingerprint.dtim); - assertEquals(WifiMetricsProto.RouterFingerPrint.AUTH_OPEN, - mDecodedProto.connectionEvent[1].routerFingerprint.authentication); - assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNKNOWN, - mDecodedProto.connectionEvent[1].routerFingerprint.eapMethod); - assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_NONE, - mDecodedProto.connectionEvent[1].routerFingerprint.authPhase2Method); - assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE, - mDecodedProto.connectionEvent[1].routerFingerprint.ocspType); - assertEquals(SCAN_RESULT_LEVEL, mDecodedProto.connectionEvent[1].signalStrength); - assertEquals(NETWORK_DETAIL_WIFIMODE, - mDecodedProto.connectionEvent[1].routerFingerprint.routerTechnology); - assertTrue(mDecodedProto.connectionEvent[0].useRandomizedMac); - assertFalse(mDecodedProto.connectionEvent[1].useRandomizedMac); - assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL, - mDecodedProto.connectionEvent[0].connectionNominator); - assertEquals(1, mDecodedProto.numConnectToNetworkSupportingMbo); - assertEquals(1, mDecodedProto.numConnectToNetworkSupportingOce); - } - - /** - * Tests that the mapping from networkId to nominatorId is not cleared. - */ - @Test - public void testNetworkToNominatorNotCleared() throws Exception { - //Setup mock configs and scan details - NetworkDetail networkDetail = mock(NetworkDetail.class); - when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE); - when(networkDetail.getSSID()).thenReturn(SSID); - when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM); - ScanResult scanResult = mock(ScanResult.class); - scanResult.level = SCAN_RESULT_LEVEL; - WifiConfiguration config = mock(WifiConfiguration.class); - config.SSID = "\"" + SSID + "\""; - config.dtimInterval = CONFIG_DTIM; - config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - config.allowedKeyManagement = new BitSet(); - WifiConfiguration.NetworkSelectionStatus networkSelectionStat = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(networkSelectionStat.getCandidate()).thenReturn(scanResult); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat); - ScanDetail scanDetail = mock(ScanDetail.class); - when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); - when(scanDetail.getScanResult()).thenReturn(scanResult); - - config.networkId = TEST_NETWORK_ID; - mWifiMetrics.setNominatorForNetwork(TEST_NETWORK_ID, - WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER); - - // dump() calls clear() internally - mWifiMetrics.dump(null, new PrintWriter(new StringWriter()), - new String[]{WifiMetrics.PROTO_DUMP_ARG}); - - // Create a connection event using only the config - mWifiMetrics.startConnectionEvent(config, "Red", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - dumpProtoAndDeserialize(); - - assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER, - mDecodedProto.connectionEvent[0].connectionNominator); - } - - /** - * Test that WifiMetrics is serializing/deserializing association time out events. - */ - @Test - public void testMetricsAssociationTimedOut() throws Exception { - mWifiMetrics.startConnectionEvent(null, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - //Dump proto and deserialize - //This should clear all the metrics in mWifiMetrics, - dumpProtoAndDeserialize(); - //Check there is only 1 connection events - assertEquals(1, mDecodedProto.connectionEvent.length); - assertEquals(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - mDecodedProto.connectionEvent[0].level2FailureCode); - assertEquals(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, - mDecodedProto.connectionEvent[0].level2FailureReason); - } - - /** - * Verify the logging of number of blocked BSSIDs in ConnectionEvent. - */ - @Test - public void testMetricNumBssidInBlocklist() throws Exception { - WifiConfiguration config = mock(WifiConfiguration.class); - config.SSID = "\"" + SSID + "\""; - config.allowedKeyManagement = new BitSet(); - when(config.getNetworkSelectionStatus()).thenReturn( - mock(WifiConfiguration.NetworkSelectionStatus.class)); - when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(eq(config.SSID))) - .thenReturn(3); - mWifiMetrics.startConnectionEvent(config, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - dumpProtoAndDeserialize(); - - assertEquals(1, mDecodedProto.connectionEvent.length); - assertEquals(3, mDecodedProto.connectionEvent[0].numBssidInBlocklist); - } - - /** - * Verify the ConnectionEvent is labeled with networkType open network correctly. - */ - @Test - public void testConnectionNetworkTypeOpen() throws Exception { - WifiConfiguration config = mock(WifiConfiguration.class); - config.SSID = "\"" + SSID + "\""; - config.allowedKeyManagement = new BitSet(); - when(config.getNetworkSelectionStatus()).thenReturn( - mock(WifiConfiguration.NetworkSelectionStatus.class)); - when(config.isOpenNetwork()).thenReturn(true); - mWifiMetrics.startConnectionEvent(config, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - dumpProtoAndDeserialize(); - - assertEquals(1, mDecodedProto.connectionEvent.length); - assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_OPEN, - mDecodedProto.connectionEvent[0].networkType); - assertFalse(mDecodedProto.connectionEvent[0].isOsuProvisioned); - } - - /** - * Verify the ConnectionEvent is labeled with networkType Passpoint correctly. - */ - @Test - public void testConnectionNetworkTypePasspoint() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork(); - mWifiMetrics.startConnectionEvent(config, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - dumpProtoAndDeserialize(); - - assertEquals(1, mDecodedProto.connectionEvent.length); - assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT, - mDecodedProto.connectionEvent[0].networkType); - assertFalse(mDecodedProto.connectionEvent[0].isOsuProvisioned); - } - - /** - * Verify the ConnectionEvent is created with correct creatorUid. - */ - @Test - public void testConnectionCreatorUid() throws Exception { - WifiConfiguration config = mock(WifiConfiguration.class); - config.SSID = "\"" + SSID + "\""; - config.allowedKeyManagement = new BitSet(); - when(config.getNetworkSelectionStatus()).thenReturn( - mock(WifiConfiguration.NetworkSelectionStatus.class)); - - // First network is created by the user - config.fromWifiNetworkSuggestion = false; - mWifiMetrics.startConnectionEvent(config, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - // Second network is created by a carrier app - config.fromWifiNetworkSuggestion = true; - config.carrierId = 123; - mWifiMetrics.startConnectionEvent(config, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - // Third network is created by an unknown app - config.fromWifiNetworkSuggestion = true; - config.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; - mWifiMetrics.startConnectionEvent(config, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - dumpProtoAndDeserialize(); - - assertEquals(3, mDecodedProto.connectionEvent.length); - assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_USER, - mDecodedProto.connectionEvent[0].networkCreator); - assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER, - mDecodedProto.connectionEvent[1].networkCreator); - assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN, - mDecodedProto.connectionEvent[2].networkCreator); - } - - /** - * Test that WifiMetrics is serializing/deserializing authentication failure events. - */ - @Test - public void testMetricsAuthenticationFailureReason() throws Exception { - mWifiMetrics.startConnectionEvent(null, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD); - - //Dump proto and deserialize - //This should clear all the metrics in mWifiMetrics, - dumpProtoAndDeserialize(); - //Check there is only 1 connection events - assertEquals(1, mDecodedProto.connectionEvent.length); - assertEquals(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, - mDecodedProto.connectionEvent[0].level2FailureCode); - //Check the authentication failure reason - assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD, - mDecodedProto.connectionEvent[0].level2FailureReason); - } - - /** - * Test the logging of BssidBlocklistStats. - */ - @Test - public void testBssidBlocklistMetrics() throws Exception { - for (int i = 0; i < 3; i++) { - mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(i); - } - mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(2); - mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled, - true); - mWifiMetrics.incrementNumHighMovementConnectionStarted(); - mWifiMetrics.incrementNumHighMovementConnectionSkipped(); - mWifiMetrics.incrementNumHighMovementConnectionSkipped(); - dumpProtoAndDeserialize(); - - Int32Count[] expectedHistogram = { - buildInt32Count(0, 1), - buildInt32Count(1, 1), - buildInt32Count(2, 2), - }; - assertKeyCountsEqual(expectedHistogram, - mDecodedProto.bssidBlocklistStats.networkSelectionFilteredBssidCount); - assertEquals(true, mDecodedProto.bssidBlocklistStats - .highMovementMultipleScansFeatureEnabled); - assertEquals(1, mDecodedProto.bssidBlocklistStats.numHighMovementConnectionStarted); - assertEquals(2, mDecodedProto.bssidBlocklistStats.numHighMovementConnectionSkipped); - } - - /** - * Test that WifiMetrics is being cleared after dumping via proto - */ - @Test - public void testMetricsClearedAfterProtoRequested() throws Exception { - // Create 3 ConnectionEvents - mWifiMetrics.startConnectionEvent(null, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiMetrics.startConnectionEvent(null, "YELLOW", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiMetrics.startConnectionEvent(null, "GREEN", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiMetrics.startConnectionEvent(null, "ORANGE", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - //Dump proto and deserialize - //This should clear all the metrics in mWifiMetrics, - dumpProtoAndDeserialize(); - //Check there are 4 connection events - assertEquals(4, mDecodedProto.connectionEvent.length); - assertEquals(0, mDecodedProto.rssiPollRssiCount.length); - assertEquals(0, mDecodedProto.alertReasonCount.length); - - // Create 2 ConnectionEvents - mWifiMetrics.startConnectionEvent(null, "BLUE", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiMetrics.startConnectionEvent(null, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - //Dump proto and deserialize - dumpProtoAndDeserialize(); - //Check there are only 2 connection events - assertEquals(2, mDecodedProto.connectionEvent.length); - } - - /** - * Test logging to statsd when a connection event finishes. - */ - @Test - public void testLogWifiConnectionResultStatsd() throws Exception { - // static mocking for WifiStatsLog - mSession = ExtendedMockito.mockitoSession() - .strictness(Strictness.LENIENT) - .mockStatic(WifiStatsLog.class) - .startMocking(); - - WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - ScanResult scanResult = mock(ScanResult.class); - scanResult.level = -55; - when(networkSelectionStatus.getCandidate()).thenReturn(scanResult); - network.setNetworkSelectionStatus(networkSelectionStatus); - - // Start and end Connection event - mWifiMetrics.startConnectionEvent(network, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, - WifiMetricsProto.ConnectionEvent.HLF_DHCP, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - ExtendedMockito.verify(() -> WifiStatsLog.write( - WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED, false, - WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_GENERAL, - -55)); - mSession.finishMocking(); - } - - /** - * Test that current ongoing ConnectionEvent is not cleared and logged - * when proto is dumped - */ - @Test - public void testCurrentConnectionEventNotClearedAfterProtoRequested() throws Exception { - // Create 2 complete ConnectionEvents and 1 ongoing un-ended ConnectionEvent - mWifiMetrics.startConnectionEvent(null, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiMetrics.startConnectionEvent(null, "YELLOW", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - mWifiMetrics.startConnectionEvent(null, "GREEN", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - - // Dump proto and deserialize - // This should clear the metrics in mWifiMetrics, - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.connectionEvent.length); - - // End the ongoing ConnectionEvent - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - - dumpProtoAndDeserialize(); - assertEquals(1, mDecodedProto.connectionEvent.length); - } - - /** - * Tests that after setting metrics values they can be serialized and deserialized with the - * $ adb shell dumpsys wifi wifiMetricsProto clean - */ - @Test - public void testClearMetricsDump() throws Exception { - setAndIncrementMetrics(); - startAndEndConnectionEventSucceeds(); - cleanDumpProtoAndDeserialize(); - assertDeserializedMetricsCorrect(); - assertEquals("mDecodedProto.connectionEvent.length", - 2, mDecodedProto.connectionEvent.length); - } - - private static final int NUM_REPEATED_DELTAS = 7; - private static final int REPEATED_DELTA = 0; - private static final int SINGLE_GOOD_DELTA = 1; - private static final int SINGLE_TIMEOUT_DELTA = 2; - private static final int NUM_REPEATED_BOUND_DELTAS = 2; - private static final int MAX_DELTA_LEVEL = 127; - private static final int MIN_DELTA_LEVEL = -127; - private static final int ARBITRARY_DELTA_LEVEL = 20; - - /** - * Sunny day RSSI delta logging scenario. - * Logs one rssi delta value multiple times - * Logs a different delta value a single time - */ - @Test - public void testRssiDeltasSuccessfulLogging() throws Exception { - // Generate some repeated deltas - for (int i = 0; i < NUM_REPEATED_DELTAS; i++) { - generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); - } - // Generate a single delta - generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_GOOD_DELTA, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.rssiPollDeltaCount.length); - // Check the repeated deltas - assertEquals(NUM_REPEATED_DELTAS, mDecodedProto.rssiPollDeltaCount[0].count); - assertEquals(REPEATED_DELTA, mDecodedProto.rssiPollDeltaCount[0].rssi); - // Check the single delta - assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count); - assertEquals(SINGLE_GOOD_DELTA, mDecodedProto.rssiPollDeltaCount[1].rssi); - } - - /** - * Tests that Rssi Delta events whose scanResult and Rssi Poll come too far apart, timeout, - * and are not logged. - */ - @Test - public void testRssiDeltasTimeout() throws Exception { - // Create timed out rssi deltas - generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1); - generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_TIMEOUT_DELTA, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); - } - - /** - * Tests the exact inclusive boundaries of RSSI delta logging. - */ - @Test - public void testRssiDeltaSuccessfulLoggingExactBounds() throws Exception { - generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); - generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.rssiPollDeltaCount.length); - assertEquals(MIN_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi); - assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count); - assertEquals(MAX_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[1].rssi); - assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count); - } - - /** - * Tests the exact exclusive boundaries of RSSI delta logging. - * This test ensures that too much data is not generated. - */ - @Test - public void testRssiDeltaOutOfBounds() throws Exception { - generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL + 1, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); - generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL - 1, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); - } - - /** - * This test ensures no rssi Delta is logged after an unsuccessful ConnectionEvent - */ - @Test - public void testUnsuccesfulConnectionEventRssiDeltaIsNotLogged() throws Exception { - generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, - false, // successfulConnectionEvent - true, // completeConnectionEvent - true, // useValidScanResult - true // dontDeserializeBeforePoll - ); - - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); - } - - /** - * This test ensures rssi Deltas can be logged during a ConnectionEvent - */ - @Test - public void testIncompleteConnectionEventRssiDeltaIsLogged() throws Exception { - generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, - true, // successfulConnectionEvent - false, // completeConnectionEvent - true, // useValidScanResult - true // dontDeserializeBeforePoll - ); - dumpProtoAndDeserialize(); - assertEquals(1, mDecodedProto.rssiPollDeltaCount.length); - assertEquals(ARBITRARY_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi); - assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count); - } - - /** - * This test ensures that no delta is logged for a null ScanResult Candidate - */ - @Test - public void testRssiDeltaNotLoggedForNullCandidateScanResult() throws Exception { - generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, - true, // successfulConnectionEvent - true, // completeConnectionEvent - false, // useValidScanResult - true // dontDeserializeBeforePoll - ); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); - } - - /** - * This test ensures that Rssi Deltas are not logged over a 'clear()' call (Metrics Serialized) - */ - @Test - public void testMetricsSerializedDuringRssiDeltaEventLogsNothing() throws Exception { - generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, - WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, - true, // successfulConnectionEvent - true, // completeConnectionEvent - true, // useValidScanResult - false // dontDeserializeBeforePoll - ); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); - } - - private static final int DEAUTH_REASON = 7; - private static final int ASSOC_STATUS = 11; - private static final int ASSOC_TIMEOUT = 1; - private static final int LOCAL_GEN = 1; - private static final int AUTH_FAILURE_REASON = WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD; - private static final int NUM_TEST_STA_EVENTS = 19; - private static final String sSSID = "\"SomeTestSsid\""; - private static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID); - private static final String sBSSID = "01:02:03:04:05:06"; - - private final StateChangeResult mStateDisconnected = - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED); - private final StateChangeResult mStateCompleted = - new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED); - // Test bitmasks of supplicant state changes - private final int mSupBm1 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state); - private final int mSupBm2 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state) - | WifiMetrics.supplicantStateToBit(mStateCompleted.state); - // An invalid but interesting wifiConfiguration that exercises the StaEvent.ConfigInfo encoding - private final WifiConfiguration mTestWifiConfig = createComplexWifiConfig(); - // <msg.what> <msg.arg1> <msg.arg2> - private int[][] mTestStaMessageInts = { - {WifiMonitor.ASSOCIATION_REJECTION_EVENT, ASSOC_TIMEOUT, ASSOC_STATUS}, - {WifiMonitor.AUTHENTICATION_FAILURE_EVENT, AUTH_FAILURE_REASON, -1}, - {WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0}, - {WifiMonitor.NETWORK_DISCONNECTION_EVENT, LOCAL_GEN, DEAUTH_REASON}, - {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}, - {WifiMonitor.ASSOCIATED_BSSID_EVENT, 0, 0}, - {WifiMonitor.TARGET_BSSID_EVENT, 0, 0}, - {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}, - {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0} - }; - private Object[] mTestStaMessageObjs = { - null, - null, - null, - null, - mStateDisconnected, - null, - null, - mStateDisconnected, - mStateCompleted - }; - // Values used to generate the StaEvent log calls from ClientModeImpl - // <StaEvent.Type>, <StaEvent.FrameworkDisconnectReason>, <1|0>(testWifiConfiguration, null) - private int[][] mTestStaLogInts = { - {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, 0, 0}, - {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, 0, 0}, - {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, 0, 0}, - {StaEvent.TYPE_CMD_START_CONNECT, 0, 1}, - {StaEvent.TYPE_CMD_START_ROAM, 0, 1}, - {StaEvent.TYPE_CONNECT_NETWORK, 0, 1}, - {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, 0, 0}, - {StaEvent.TYPE_FRAMEWORK_DISCONNECT, StaEvent.DISCONNECT_API, 0}, - {StaEvent.TYPE_SCORE_BREACH, 0, 0}, - {StaEvent.TYPE_MAC_CHANGE, 0, 1}, - {StaEvent.TYPE_WIFI_ENABLED, 0, 0}, - {StaEvent.TYPE_WIFI_DISABLED, 0, 0}, - {StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, 0, 0} - }; - // Values used to generate the StaEvent log calls from WifiMonitor - // <type>, <reason>, <status>, <local_gen>, - // <auth_fail_reason>, <assoc_timed_out> <supplicantStateChangeBitmask> <1|0>(has ConfigInfo) - private int[][] mExpectedValues = { - {StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT, -1, ASSOC_STATUS, 0, - /**/ 0, ASSOC_TIMEOUT, 0, 0}, /**/ - {StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT, -1, -1, 0, - /**/StaEvent.AUTH_FAILURE_WRONG_PSWD, 0, 0, 0}, /**/ - {StaEvent.TYPE_NETWORK_CONNECTION_EVENT, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT, DEAUTH_REASON, -1, LOCAL_GEN, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_CMD_ASSOCIATED_BSSID, -1, -1, 0, - /**/ 0, 0, mSupBm1, 0}, /**/ - {StaEvent.TYPE_CMD_TARGET_BSSID, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, -1, -1, 0, - /**/ 0, 0, mSupBm2, 0}, /**/ - {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_CMD_START_CONNECT, -1, -1, 0, - /**/ 0, 0, 0, 1}, /**/ - {StaEvent.TYPE_CMD_START_ROAM, -1, -1, 0, - /**/ 0, 0, 0, 1}, /**/ - {StaEvent.TYPE_CONNECT_NETWORK, -1, -1, 0, - /**/ 0, 0, 0, 1}, /**/ - {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_FRAMEWORK_DISCONNECT, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_SCORE_BREACH, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_MAC_CHANGE, -1, -1, 0, - /**/ 0, 0, 0, 1}, /**/ - {StaEvent.TYPE_WIFI_ENABLED, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_WIFI_DISABLED, -1, -1, 0, - /**/ 0, 0, 0, 0}, /**/ - {StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, -1, -1, 0, - /**/ 0, 0, 0, 0} /**/ - }; - - /** - * Generates events from all the rows in mTestStaMessageInts, and then mTestStaLogInts - */ - private void generateStaEvents(WifiMetrics wifiMetrics) { - Handler handler = wifiMetrics.getHandler(); - for (int i = 0; i < mTestStaMessageInts.length; i++) { - int[] mia = mTestStaMessageInts[i]; - handler.sendMessage( - handler.obtainMessage(mia[0], mia[1], mia[2], mTestStaMessageObjs[i])); - } - mTestLooper.dispatchAll(); - wifiMetrics.setScreenState(true); - when(mWifiDataStall.isCellularDataAvailable()).thenReturn(true); - wifiMetrics.setAdaptiveConnectivityState(true); - for (int i = 0; i < mTestStaLogInts.length; i++) { - int[] lia = mTestStaLogInts[i]; - wifiMetrics.logStaEvent(lia[0], lia[1], lia[2] == 1 ? mTestWifiConfig : null); - } - } - private void verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog) { - assertNotNull(mTestWifiConfig); - assertEquals(NUM_TEST_STA_EVENTS, wifiLog.staEventList.length); - int j = 0; // De-serialized event index - for (int i = 0; i < mTestStaMessageInts.length; i++) { - StaEvent event = wifiLog.staEventList[j]; - int[] mia = mTestStaMessageInts[i]; - int[] evs = mExpectedValues[j]; - if (mia[0] != WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT) { - assertEquals(evs[0], event.type); - assertEquals(evs[1], event.reason); - assertEquals(evs[2], event.status); - assertEquals(evs[3] == 1 ? true : false, event.localGen); - assertEquals(evs[4], event.authFailureReason); - assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut); - assertEquals(evs[6], event.supplicantStateChangesBitmask); - assertConfigInfoEqualsWifiConfig( - evs[7] == 1 ? mTestWifiConfig : null, event.configInfo); - j++; - } - } - for (int i = 0; i < mTestStaLogInts.length; i++) { - StaEvent event = wifiLog.staEventList[j]; - int[] evs = mExpectedValues[j]; - assertEquals(evs[0], event.type); - assertEquals(evs[1], event.reason); - assertEquals(evs[2], event.status); - assertEquals(evs[3] == 1 ? true : false, event.localGen); - assertEquals(evs[4], event.authFailureReason); - assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut); - assertEquals(evs[6], event.supplicantStateChangesBitmask); - assertConfigInfoEqualsWifiConfig( - evs[7] == 1 ? mTestWifiConfig : null, event.configInfo); - assertEquals(true, event.screenOn); - assertEquals(true, event.isCellularDataAvailable); - assertEquals(true, event.isAdaptiveConnectivityEnabled); - j++; - } - assertEquals(mExpectedValues.length, j); - } - - /** - * Generate StaEvents of each type, ensure all the different values are logged correctly, - * and that they survive serialization & de-serialization - */ - @Test - public void testStaEventsLogSerializeDeserialize() throws Exception { - generateStaEvents(mWifiMetrics); - dumpProtoAndDeserialize(); - verifyDeserializedStaEvents(mDecodedProto); - } - - /** - * Ensure the number of StaEvents does not exceed MAX_STA_EVENTS by generating lots of events - * and checking how many are deserialized - */ - @Test - public void testStaEventBounding() throws Exception { - for (int i = 0; i < (WifiMetrics.MAX_STA_EVENTS + 10); i++) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT); - } - dumpProtoAndDeserialize(); - assertEquals(WifiMetrics.MAX_STA_EVENTS, mDecodedProto.staEventList.length); - } - - /** - * Tests that link probe StaEvents do not exceed - * {@link WifiMetrics#MAX_LINK_PROBE_STA_EVENTS}. - */ - @Test - public void testLinkProbeStaEventBounding() throws Exception { - for (int i = 0; i < WifiMetrics.MAX_LINK_PROBE_STA_EVENTS; i++) { - mWifiMetrics.logLinkProbeSuccess(0, 0, 0, 0); - mWifiMetrics.logLinkProbeFailure(0, 0, 0, 0); - } - for (int i = 0; i < 10; i++) { - mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT); - } - - dumpProtoAndDeserialize(); - - long numLinkProbeStaEvents = Arrays.stream(mDecodedProto.staEventList) - .filter(event -> event.type == TYPE_LINK_PROBE) - .count(); - assertEquals(WifiMetrics.MAX_LINK_PROBE_STA_EVENTS, numLinkProbeStaEvents); - assertEquals(WifiMetrics.MAX_LINK_PROBE_STA_EVENTS + 10, mDecodedProto.staEventList.length); - } - - /** - * Test the logging of UserActionEvent with a valid network ID - */ - @Test - public void testLogUserActionEventValidNetworkId() throws Exception { - int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI; - int testNetworkId = 0; - long testStartTimeMillis = 123123L; - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis); - WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork(); - config.ephemeral = true; - when(mWcm.getConfiguredNetwork(testNetworkId)).thenReturn(config); - - mWifiMetrics.logUserActionEvent(testEventType, testNetworkId); - dumpProtoAndDeserialize(); - - WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents; - assertEquals(1, userActionEvents.length); - assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, - userActionEvents[0].eventType); - assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis); - assertEquals(true, userActionEvents[0].targetNetworkInfo.isEphemeral); - assertEquals(true, userActionEvents[0].targetNetworkInfo.isPasspoint); - - // Verify that there are no disabled WifiConfiguration and BSSIDs - NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason; - assertEquals(NetworkDisableReason.REASON_UNKNOWN, networkDisableReason.disableReason); - assertEquals(false, networkDisableReason.configTemporarilyDisabled); - assertEquals(false, networkDisableReason.configPermanentlyDisabled); - assertEquals(0, networkDisableReason.bssidDisableReasons.length); - } - - /** - * Verify the WifiStatus field in a UserActionEvent is populated correctly. - * @throws Exception - */ - @Test - public void testLogWifiStatusInUserActionEvent() throws Exception { - // setups WifiStatus for information - int expectedRssi = -55; - int testNetworkId = 1; - int expectedTx = 1234; - int expectedRx = 2345; - - WifiInfo wifiInfo = mock(WifiInfo.class); - when(wifiInfo.getRssi()).thenReturn(expectedRssi); - when(wifiInfo.getNetworkId()).thenReturn(testNetworkId); - mWifiMetrics.handlePollResult(wifiInfo); - mWifiMetrics.incrementThroughputKbpsCount(expectedTx, expectedRx, RSSI_POLL_FREQUENCY); - mWifiMetrics.setNominatorForNetwork(testNetworkId, - WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE); - - // generate a user action event and then verify fields - int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI; - mWifiMetrics.logUserActionEvent(testEventType, testNetworkId); - dumpProtoAndDeserialize(); - - WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents; - assertEquals(1, userActionEvents.length); - assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, - userActionEvents[0].eventType); - assertEquals(expectedRssi, userActionEvents[0].wifiStatus.lastRssi); - assertEquals(expectedTx, userActionEvents[0].wifiStatus.estimatedTxKbps); - assertEquals(expectedRx, userActionEvents[0].wifiStatus.estimatedRxKbps); - assertTrue(userActionEvents[0].wifiStatus.isStuckDueToUserConnectChoice); - } - - /** - * verify NetworkDisableReason is populated properly when there exists a disabled - * WifiConfiguration and BSSID. - */ - @Test - public void testNetworkDisableReasonInUserActionEvent() throws Exception { - // Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION - WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus(); - status.setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - status.setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION); - when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig); - - // Also setup the same BSSID level failure - Set<Integer> testBssidBlocklistReasons = new HashSet<>(); - testBssidBlocklistReasons.add(BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION); - when(mBssidBlocklistMonitor.getFailureReasonsForSsid(anyString())) - .thenReturn(testBssidBlocklistReasons); - - // Logging the user action event - mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, - TEST_NETWORK_ID); - dumpProtoAndDeserialize(); - - WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents; - assertEquals(1, userActionEvents.length); - assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, - userActionEvents[0].eventType); - NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason; - assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION, - networkDisableReason.disableReason); - assertEquals(true, networkDisableReason.configTemporarilyDisabled); - assertEquals(false, networkDisableReason.configPermanentlyDisabled); - assertEquals(1, networkDisableReason.bssidDisableReasons.length); - assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION, - networkDisableReason.bssidDisableReasons[0]); - } - - /** - * verify that auto-join disable overrides any other disable reasons in NetworkDisableReason. - */ - @Test - public void testNetworkDisableReasonDisableAutojoinInUserActionEvent() throws Exception { - // Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION - WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork(); - NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus(); - status.setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - status.setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION); - when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig); - - // Disable autojoin - testConfig.allowAutojoin = false; - - // Logging the user action event - mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, - TEST_NETWORK_ID); - dumpProtoAndDeserialize(); - - WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents; - NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason; - assertEquals(NetworkDisableReason.REASON_AUTO_JOIN_DISABLED, - networkDisableReason.disableReason); - assertEquals(false, networkDisableReason.configTemporarilyDisabled); - assertEquals(true, networkDisableReason.configPermanentlyDisabled); - } - - /** - * Test the logging of UserActionEvent with invalid network ID - */ - @Test - public void testLogUserActionEventInvalidNetworkId() throws Exception { - int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI; - int testNetworkId = 0; - long testStartTimeMillis = 123123L; - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis); - when(mWcm.getConfiguredNetwork(testNetworkId)).thenReturn(null); - - mWifiMetrics.logUserActionEvent(testEventType, testNetworkId); - dumpProtoAndDeserialize(); - - WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents; - assertEquals(1, userActionEvents.length); - assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, - userActionEvents[0].eventType); - assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis); - assertNull(userActionEvents[0].targetNetworkInfo); - } - - /** - * Test the logging of UserActionEvent for Adaptive Connectivity toggle - */ - @Test - public void testLogUserActionEventForAdaptiveConnectivity() throws Exception { - long testStartTimeMillis = 123123L; - boolean adaptiveConnectivityEnabled = true; - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis); - mWifiMetrics.logUserActionEvent( - mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType( - adaptiveConnectivityEnabled)); - long testStartTimeMillis2 = 200000L; - boolean adaptiveConnectivityEnabled2 = false; - when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis2); - mWifiMetrics.logUserActionEvent( - mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType( - adaptiveConnectivityEnabled2)); - dumpProtoAndDeserialize(); - - WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents; - assertEquals(2, userActionEvents.length); - assertEquals(WifiMetricsProto.UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_ON, - userActionEvents[0].eventType); - assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis); - assertEquals(WifiMetricsProto.UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_OFF, - userActionEvents[1].eventType); - assertEquals(testStartTimeMillis2, userActionEvents[1].startTimeMillis); - } - - /** - * Verify that the max length of the UserActionEvent list is limited to MAX_USER_ACTION_EVENTS. - */ - @Test - public void testLogUserActionEventCapped() throws Exception { - for (int i = 0; i < WifiMetrics.MAX_USER_ACTION_EVENTS + 1; i++) { - mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, 0); - } - dumpProtoAndDeserialize(); - assertEquals(WifiMetrics.MAX_USER_ACTION_EVENTS, mDecodedProto.userActionEvents.length); - } - - /** - * Ensure WifiMetrics doesn't cause a null pointer exception when called with null args - */ - @Test - public void testDumpNullArg() { - mWifiMetrics.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null); - } - - /** - * Test the generation of 'NumConnectableNetwork' histograms from two scans of different - * ScanDetails produces the correct histogram values, and relevant bounds are observed - */ - @MediumTest - @Test - public void testNumConnectableNetworksGeneration() throws Exception { - List<ScanDetail> scan = new ArrayList<ScanDetail>(); - // ssid, bssid, isOpen, isSaved, isProvider, isWeakRssi) - scan.add(buildMockScanDetail("PASSPOINT_1", "bssid0", false, false, true, false)); - scan.add(buildMockScanDetail("PASSPOINT_2", "bssid1", false, false, true, false)); - scan.add(buildMockScanDetail("SSID_B", "bssid2", true, true, false, false)); - scan.add(buildMockScanDetail("SSID_B", "bssid3", true, true, false, false)); - scan.add(buildMockScanDetail("SSID_C", "bssid4", true, false, false, false)); - scan.add(buildMockScanDetail("SSID_D", "bssid5", false, true, false, false)); - scan.add(buildMockScanDetail("SSID_E", "bssid6", false, true, false, false)); - scan.add(buildMockScanDetail("SSID_F", "bssid7", false, false, false, false)); - scan.add(buildMockScanDetail("SSID_G_WEAK", "bssid9", false, false, false, true)); - scan.add(buildMockScanDetail("SSID_H_WEAK", "bssid10", false, false, false, true)); - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - scan.add(buildMockScanDetail("SSID_B", "bssid8", true, true, false, false)); - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - for (int i = 0; i < NUM_PARTIAL_SCAN_RESULTS; i++) { - mWifiMetrics.incrementAvailableNetworksHistograms(scan, false); - } - dumpProtoAndDeserialize(); - verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1, a(7), a(2)); - verifyHist(mDecodedProto.totalBssidsInScanHistogram, 2, a(8, 9), a(1, 1)); - verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1, a(2), a(2)); - verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 2, a(3, 4), a(1, 1)); - verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1, a(3), a(2)); - verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 2, a(4, 5), a(1, 1)); - verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1, a(4), a(2)); - verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 2, a(5, 6), a(1, 1)); - verifyHist(mDecodedProto.availableSavedPasspointProviderProfilesInScanHistogram, 1, - a(2), a(2)); - verifyHist(mDecodedProto.availableSavedPasspointProviderBssidsInScanHistogram, 1, - a(2), a(2)); - assertEquals(2, mDecodedProto.fullBandAllSingleScanListenerResults); - assertEquals(NUM_PARTIAL_SCAN_RESULTS, mDecodedProto.partialAllSingleScanListenerResults); - - // Check Bounds - scan.clear(); - int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET, - WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET) + 5; - for (int i = 0; i < lotsOfSSids; i++) { - scan.add(buildMockScanDetail("SSID_" + i, "bssid_" + i, true, true, false, false)); - } - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - dumpProtoAndDeserialize(); - verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1, - a(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET), a(1)); - verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1, - a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1)); - verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1, - a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1)); - verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1, - a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1)); - scan.clear(); - int lotsOfBssids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET, - WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET) + 5; - for (int i = 0; i < lotsOfBssids; i++) { - scan.add(buildMockScanDetail("SSID", "bssid_" + i, true, true, false, false)); - } - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - dumpProtoAndDeserialize(); - verifyHist(mDecodedProto.totalBssidsInScanHistogram, 1, - a(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET), a(1)); - verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 1, - a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1)); - verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 1, - a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1)); - verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 1, - a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1)); - } - - /** - * Test that Hotspot 2.0 (Passpoint) scan results are collected correctly and that relevant - * bounds are observed. - */ - @Test - public void testObservedHotspotAps() throws Exception { - List<ScanDetail> scan = new ArrayList<ScanDetail>(); - // 2 R1 (Unknown AP isn't counted) passpoint APs belonging to a single provider: hessid1 - long hessid1 = 10; - int anqpDomainId1 = 5; - scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX", "00:02:03:04:05:06", hessid1, - anqpDomainId1, NetworkDetail.HSRelease.R1, true)); - scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY", "01:02:03:04:05:06", hessid1, - anqpDomainId1, NetworkDetail.HSRelease.R1, true)); - scan.add(buildMockScanDetailPasspoint("PASSPOINT_XYZ", "02:02:03:04:05:06", hessid1, - anqpDomainId1, NetworkDetail.HSRelease.Unknown, true)); - // 2 R2 passpoint APs belonging to a single provider: hessid2 - long hessid2 = 12; - int anqpDomainId2 = 6; - scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid2, - anqpDomainId2, NetworkDetail.HSRelease.R2, true)); - scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid2, - anqpDomainId2, NetworkDetail.HSRelease.R2, true)); - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - scan = new ArrayList<ScanDetail>(); - // 3 R2 passpoint APs belonging to a single provider: hessid3 (in next scan) - long hessid3 = 15; - int anqpDomainId3 = 8; - scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3, - anqpDomainId3, NetworkDetail.HSRelease.R2, true)); - scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3, - anqpDomainId3, NetworkDetail.HSRelease.R2, false)); - scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid3, - anqpDomainId3, NetworkDetail.HSRelease.R2, true)); - // 2 R3 Passpoint APs belonging to a single provider: hessid4 - long hessid4 = 17; - int anqpDomainId4 = 2; - scan.add(buildMockScanDetailPasspoint("PASSPOINT_R3", "0C:02:03:04:05:01", hessid4, - anqpDomainId4, NetworkDetail.HSRelease.R3, true)); - scan.add(buildMockScanDetailPasspoint("PASSPOINT_R3_2", "0C:02:03:04:05:02", hessid4, - anqpDomainId4, NetworkDetail.HSRelease.R3, true)); - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - dumpProtoAndDeserialize(); - - verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 2, a(0, 2), a(1, 1)); - verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 2, a(2, 3), a(1, 1)); - verifyHist(mDecodedProto.observedHotspotR3ApsInScanHistogram, 2, a(0, 2), a(1, 1)); - verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 2, a(0, 1), a(1, 1)); - verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1, a(1), a(2)); - verifyHist(mDecodedProto.observedHotspotR3EssInScanHistogram, 2, a(0, 1), a(1, 1)); - verifyHist(mDecodedProto.observedHotspotR1ApsPerEssInScanHistogram, 1, a(2), a(1)); - verifyHist(mDecodedProto.observedHotspotR2ApsPerEssInScanHistogram, 2, a(2, 3), a(1, 1)); - verifyHist(mDecodedProto.observedHotspotR3ApsPerEssInScanHistogram, 1, a(2), a(1)); - - // check bounds - scan.clear(); - int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET, - WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET) + 5; - for (int i = 0; i < lotsOfSSids; i++) { - scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX" + i, "00:02:03:04:05:06", i, - i + 10, NetworkDetail.HSRelease.R1, true)); - scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY" + i, "AA:02:03:04:05:06", 1000 * i, - i + 10, NetworkDetail.HSRelease.R2, false)); - scan.add(buildMockScanDetailPasspoint("PASSPOINT_XZ" + i, "0B:02:03:04:05:06", 101 * i, - i + 10, NetworkDetail.HSRelease.R3, false)); - } - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - dumpProtoAndDeserialize(); - verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 1, - a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1)); - verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 1, - a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1)); - verifyHist(mDecodedProto.observedHotspotR3ApsInScanHistogram, 1, - a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1)); - verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 1, - a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1)); - verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1, - a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1)); - verifyHist(mDecodedProto.observedHotspotR3EssInScanHistogram, 1, - a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1)); - } - - /** - * Test that IEEE 802.11mc scan results are collected correctly and that relevant - * bounds are observed. - */ - @Test - public void testObserved80211mcAps() throws Exception { - ScanDetail mockScanDetailNon80211mc = mock(ScanDetail.class); - ScanDetail mockScanDetail80211mc = mock(ScanDetail.class); - NetworkDetail mockNetworkDetailNon80211mc = mock(NetworkDetail.class); - NetworkDetail mockNetworkDetail80211mc = mock(NetworkDetail.class); - when(mockNetworkDetail80211mc.is80211McResponderSupport()).thenReturn(true); - ScanResult mockScanResult = mock(ScanResult.class); - mockScanResult.capabilities = ""; - when(mockScanDetailNon80211mc.getNetworkDetail()).thenReturn(mockNetworkDetailNon80211mc); - when(mockScanDetail80211mc.getNetworkDetail()).thenReturn(mockNetworkDetail80211mc); - when(mockScanDetailNon80211mc.getScanResult()).thenReturn(mockScanResult); - when(mockScanDetail80211mc.getScanResult()).thenReturn(mockScanResult); - when(mWns.isSignalTooWeak(eq(mockScanDetail80211mc.getScanResult()))).thenReturn(true); - List<ScanDetail> scan = new ArrayList<ScanDetail>(); - - // 4 scans (a few non-802.11mc supporting APs on each) - // scan1: no 802.11mc supporting APs - - scan.add(mockScanDetailNon80211mc); - scan.add(mockScanDetailNon80211mc); - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - - // scan2: 2 802.11mc supporting APs - scan.clear(); - scan.add(mockScanDetailNon80211mc); - scan.add(mockScanDetail80211mc); - scan.add(mockScanDetail80211mc); - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - - // scan3: 100 802.11mc supporting APs (> limit) - scan.clear(); - scan.add(mockScanDetailNon80211mc); - scan.add(mockScanDetailNon80211mc); - scan.add(mockScanDetailNon80211mc); - for (int i = 0; i < 100; ++i) { - scan.add(mockScanDetail80211mc); - } - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - - // scan4: 2 802.11mc supporting APs - scan.clear(); - scan.add(mockScanDetailNon80211mc); - scan.add(mockScanDetail80211mc); - scan.add(mockScanDetail80211mc); - scan.add(mockScanDetailNon80211mc); - mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); - - dumpProtoAndDeserialize(); - - verifyHist(mDecodedProto.observed80211McSupportingApsInScanHistogram, 3, - a(0, 2, WifiMetrics.MAX_TOTAL_80211MC_APS_BUCKET), a(1, 2, 1)); - } - - /** - * Test Open Network Notification blacklist size and feature state are not cleared when proto - * is dumped. - */ - @Test - public void testOpenNetworkNotificationBlacklistSizeAndFeatureStateNotCleared() - throws Exception { - mWifiMetrics.setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG, - SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST); - mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG, - IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON); - for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) { - mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG); - } - - // This should clear most metrics in mWifiMetrics - dumpProtoAndDeserialize(); - assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST, - mDecodedProto.openNetworkRecommenderBlacklistSize); - assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, - mDecodedProto.isWifiNetworksAvailableNotificationOn); - assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES, - mDecodedProto.numOpenNetworkRecommendationUpdates); - - // Check that blacklist size and feature state persist on next dump but - // others do not. - dumpProtoAndDeserialize(); - assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST, - mDecodedProto.openNetworkRecommenderBlacklistSize); - assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, - mDecodedProto.isWifiNetworksAvailableNotificationOn); - assertEquals(0, mDecodedProto.numOpenNetworkRecommendationUpdates); - } - - /** - * Check network selector id - */ - @Test - public void testNetworkSelectorExperimentId() throws Exception { - final int id = 42888888; - mWifiMetrics.setNetworkSelectorExperimentId(id); - mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - dumpProtoAndDeserialize(); - assertEquals(id, mDecodedProto.connectionEvent[0].networkSelectorExperimentId); - } - - /** - * Check pmk cache - */ - @Test - public void testConnectionWithPmkCache() throws Exception { - mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.setConnectionPmkCache(true); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - dumpProtoAndDeserialize(); - assertEquals(true, mDecodedProto.connectionEvent[0].routerFingerprint.pmkCacheEnabled); - } - - /** - * Check max supported link speed and consecutive connection failure count - */ - @Test - public void testConnectionMaxSupportedLinkSpeedConsecutiveFailureCnt() throws Exception { - mWifiMetrics.setScreenState(true); - when(mNetworkConnectionStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE)) - .thenReturn(2); - mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(MAX_SUPPORTED_TX_LINK_SPEED_MBPS, - MAX_SUPPORTED_RX_LINK_SPEED_MBPS); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - dumpProtoAndDeserialize(); - assertEquals(MAX_SUPPORTED_TX_LINK_SPEED_MBPS, mDecodedProto.connectionEvent[0] - .routerFingerprint.maxSupportedTxLinkSpeedMbps); - assertEquals(MAX_SUPPORTED_RX_LINK_SPEED_MBPS, mDecodedProto.connectionEvent[0] - .routerFingerprint.maxSupportedRxLinkSpeedMbps); - assertEquals(2, mDecodedProto.connectionEvent[0].numConsecutiveConnectionFailure); - assertEquals(true, mDecodedProto.connectionEvent[0].screenOn); - } - - /** - * Check ScoringParams - */ - @Test - public void testExperimentId() throws Exception { - final int id = 42; - final String expectId = "x" + id; - when(mScoringParams.getExperimentIdentifier()).thenReturn(id); - dumpProtoAndDeserialize(); - assertEquals(expectId, mDecodedProto.scoreExperimentId); - } - - /** - * Check ScoringParams default case - */ - @Test - public void testDefaultExperimentId() throws Exception { - final int id = 0; - final String expectId = ""; - when(mScoringParams.getExperimentIdentifier()).thenReturn(id); - dumpProtoAndDeserialize(); - assertEquals(expectId, mDecodedProto.scoreExperimentId); - } - - /** short hand for instantiating an anonymous int array, instead of 'new int[]{a1, a2, ...}' */ - private int[] a(int... element) { - return element; - } - - private void verifyHist(WifiMetricsProto.NumConnectableNetworksBucket[] hist, int size, - int[] keys, int[] counts) throws Exception { - assertEquals(size, hist.length); - for (int i = 0; i < keys.length; i++) { - assertEquals(keys[i], hist[i].numConnectableNetworks); - assertEquals(counts[i], hist[i].count); - } - } - - /** - * Generate an RSSI delta event by creating a connection event and an RSSI poll within - * 'interArrivalTime' milliseconds of each other. - * Event will not be logged if interArrivalTime > mWifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS - * successfulConnectionEvent, completeConnectionEvent, useValidScanResult and - * dontDeserializeBeforePoll - * each create an anomalous condition when set to false. - */ - private void generateRssiDelta(int scanRssi, int rssiDelta, - long interArrivalTime, boolean successfulConnectionEvent, - boolean completeConnectionEvent, boolean useValidScanResult, - boolean dontDeserializeBeforePoll) throws Exception { - when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0); - ScanResult scanResult = null; - if (useValidScanResult) { - scanResult = mock(ScanResult.class); - scanResult.level = scanRssi; - } - WifiConfiguration config = mock(WifiConfiguration.class); - WifiConfiguration.NetworkSelectionStatus networkSelectionStat = - mock(WifiConfiguration.NetworkSelectionStatus.class); - config.allowedKeyManagement = new BitSet(); - when(networkSelectionStat.getCandidate()).thenReturn(scanResult); - when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat); - mWifiMetrics.startConnectionEvent(config, "TestNetwork", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - if (completeConnectionEvent) { - if (successfulConnectionEvent) { - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - } else { - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - } - } - when(mClock.getElapsedSinceBootMillis()).thenReturn(interArrivalTime); - if (!dontDeserializeBeforePoll) { - dumpProtoAndDeserialize(); - } - mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, scanRssi + rssiDelta); - } - - /** - * Generate an RSSI delta event, with all extra conditions set to true. - */ - private void generateRssiDelta(int scanRssi, int rssiDelta, - long interArrivalTime) throws Exception { - generateRssiDelta(scanRssi, rssiDelta, interArrivalTime, true, true, true, true); - } - - private void assertStringContains( - String actualString, String expectedSubstring) { - assertTrue("Expected text not found in: " + actualString, - actualString.contains(expectedSubstring)); - } - - private String getStateDump() { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - String[] args = new String[0]; - mWifiMetrics.dump(null, writer, args); - writer.flush(); - return stream.toString(); - } - - private static final int TEST_ALLOWED_KEY_MANAGEMENT = 83; - private static final int TEST_ALLOWED_PROTOCOLS = 22; - private static final int TEST_ALLOWED_AUTH_ALGORITHMS = 11; - private static final int TEST_ALLOWED_PAIRWISE_CIPHERS = 67; - private static final int TEST_ALLOWED_GROUP_CIPHERS = 231; - private static final int TEST_CANDIDATE_LEVEL = -80; - private static final int TEST_CANDIDATE_FREQ = 2345; - - private WifiConfiguration createComplexWifiConfig() { - WifiConfiguration config = new WifiConfiguration(); - config.SSID = SSID; - config.allowedKeyManagement = intToBitSet(TEST_ALLOWED_KEY_MANAGEMENT); - config.allowedProtocols = intToBitSet(TEST_ALLOWED_PROTOCOLS); - config.allowedAuthAlgorithms = intToBitSet(TEST_ALLOWED_AUTH_ALGORITHMS); - config.allowedPairwiseCiphers = intToBitSet(TEST_ALLOWED_PAIRWISE_CIPHERS); - config.allowedGroupCiphers = intToBitSet(TEST_ALLOWED_GROUP_CIPHERS); - config.hiddenSSID = true; - config.ephemeral = true; - config.getNetworkSelectionStatus().setHasEverConnected(true); - ScanResult candidate = new ScanResult(); - candidate.level = TEST_CANDIDATE_LEVEL; - candidate.frequency = TEST_CANDIDATE_FREQ; - config.getNetworkSelectionStatus().setCandidate(candidate); - return config; - } - - private void assertConfigInfoEqualsWifiConfig(WifiConfiguration config, - StaEvent.ConfigInfo info) { - if (config == null && info == null) return; - assertEquals(config.allowedKeyManagement, intToBitSet(info.allowedKeyManagement)); - assertEquals(config.allowedProtocols, intToBitSet(info.allowedProtocols)); - assertEquals(config.allowedAuthAlgorithms, intToBitSet(info.allowedAuthAlgorithms)); - assertEquals(config.allowedPairwiseCiphers, intToBitSet(info.allowedPairwiseCiphers)); - assertEquals(config.allowedGroupCiphers, intToBitSet(info.allowedGroupCiphers)); - assertEquals(config.hiddenSSID, info.hiddenSsid); - assertEquals(config.ephemeral, info.isEphemeral); - assertEquals(config.getNetworkSelectionStatus().hasEverConnected(), - info.hasEverConnected); - assertEquals(config.getNetworkSelectionStatus().getCandidate().level, info.scanRssi); - assertEquals(config.getNetworkSelectionStatus().getCandidate().frequency, info.scanFreq); - } - - /** - * Sets the values of bitSet to match an int mask - */ - private static BitSet intToBitSet(int mask) { - BitSet bitSet = new BitSet(); - for (int bitIndex = 0; mask > 0; mask >>>= 1, bitIndex++) { - if ((mask & 1) != 0) bitSet.set(bitIndex); - } - return bitSet; - } - - private static final int NUM_UNUSABLE_EVENT = 5; - private static final int NUM_UNUSABLE_EVENT_TIME_THROTTLE = 3; - - /** - * Values used to generate WifiIsUnusableEvent - * <WifiIsUnusableEvent.TriggerType>, <last_score>, <tx_success_delta>, <tx_retries_delta>, - * <tx_bad_delta>, <rx_success_delta>, <packet_update_time_delta>, <firmware_alert_code>, - * <last_wifi_usability_score>, <mobile_tx_bytes>, <mobile_rx_bytes>, <total_tx_bytes>, - * <total_rx_bytes>, - */ - private int[][] mTestUnusableEvents = { - {WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, 60, 60, 50, 40, 30, 1000, -1, 51, - 11, 12, 13, 14}, - {WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX, 55, 40, 30, 0, 0, 500, -1, 52, - 15, 16, 17, 18}, - {WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH, 60, 90, 30, 30, 0, 1000, -1, 53, - 19, 20, 21, 22}, - {WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, 55, 55, 30, 15, 10, 1000, 4, 54, - 23, 24, 25, 26}, - {WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST, 50, 56, 28, 17, 12, 1000, -1, 45, - 27, 28, 29, 30} - }; - - /** - * Generate all WifiIsUnusableEvents from mTestUnusableEvents - */ - private void generateAllUnusableEvents(WifiMetrics wifiMetrics) { - for (int i = 0; i < mTestUnusableEvents.length; i++) { - generateUnusableEventAtGivenTime(i, i * (WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1000)); - } - } - - /** - * Generate a WifiIsUnusableEvent at the given timestamp with data from - * mTestUnusableEvents[index] - */ - private void generateUnusableEventAtGivenTime(int index, long eventTime) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime); - int[] trigger = mTestUnusableEvents[index]; - when(mFacade.getMobileTxBytes()).thenReturn((long) trigger[9]); - when(mFacade.getMobileRxBytes()).thenReturn((long) trigger[10]); - when(mFacade.getTotalTxBytes()).thenReturn((long) trigger[11]); - when(mFacade.getTotalRxBytes()).thenReturn((long) trigger[12]); - mWifiMetrics.incrementWifiScoreCount(trigger[1]); - mWifiMetrics.incrementWifiUsabilityScoreCount(1, trigger[8], 15); - mWifiMetrics.updateWifiIsUnusableLinkLayerStats(trigger[2], trigger[3], trigger[4], - trigger[5], trigger[6]); - mWifiMetrics.setScreenState(true); - switch(trigger[0]) { - case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX: - case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX: - case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH: - mWifiMetrics.logWifiIsUnusableEvent(trigger[0]); - break; - case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT: - mWifiMetrics.logWifiIsUnusableEvent(trigger[0], trigger[7]); - break; - case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST: - mWifiMetrics.logWifiIsUnusableEvent(trigger[0]); - break; - default: - break; - } - } - - /** - * Verify that WifiIsUnusableEvent in wifiLog matches mTestUnusableEvents - */ - private void verifyDeserializedUnusableEvents(WifiMetricsProto.WifiLog wifiLog) { - assertEquals(NUM_UNUSABLE_EVENT, wifiLog.wifiIsUnusableEventList.length); - for (int i = 0; i < mTestUnusableEvents.length; i++) { - WifiIsUnusableEvent event = wifiLog.wifiIsUnusableEventList[i]; - verifyUnusableEvent(event, i); - } - } - - /** - * Verify that the given WifiIsUnusableEvent matches mTestUnusableEvents - * at given index - */ - private void verifyUnusableEvent(WifiIsUnusableEvent event, int index) { - int[] expectedValues = mTestUnusableEvents[index]; - assertEquals(expectedValues[0], event.type); - assertEquals(expectedValues[1], event.lastScore); - assertEquals(expectedValues[2], event.txSuccessDelta); - assertEquals(expectedValues[3], event.txRetriesDelta); - assertEquals(expectedValues[4], event.txBadDelta); - assertEquals(expectedValues[5], event.rxSuccessDelta); - assertEquals(expectedValues[6], event.packetUpdateTimeDelta); - assertEquals(expectedValues[7], event.firmwareAlertCode); - assertEquals(expectedValues[8], event.lastWifiUsabilityScore); - assertEquals(true, event.screenOn); - assertEquals(expectedValues[9], event.mobileTxBytes); - assertEquals(expectedValues[10], event.mobileRxBytes); - assertEquals(expectedValues[11], event.totalTxBytes); - assertEquals(expectedValues[12], event.totalRxBytes); - } - - /** - * Verify that no WifiIsUnusableEvent is generated when it is disabled in the settings - */ - @Test - public void testNoUnusableEventLogWhenDisabled() throws Exception { - mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, false); - generateAllUnusableEvents(mWifiMetrics); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiIsUnusableEventList.length); - } - - /** - * Generate WifiIsUnusableEvent and verify that they are logged correctly - */ - @Test - public void testUnusableEventLogSerializeDeserialize() throws Exception { - mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true); - generateAllUnusableEvents(mWifiMetrics); - dumpProtoAndDeserialize(); - verifyDeserializedUnusableEvents(mDecodedProto); - } - - /** - * Verify that the number of WifiIsUnusableEvents does not exceed MAX_UNUSABLE_EVENTS - */ - @Test - public void testUnusableEventBounding() throws Exception { - mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true); - for (int i = 0; i < (WifiMetrics.MAX_UNUSABLE_EVENTS + 2); i++) { - generateAllUnusableEvents(mWifiMetrics); - } - dumpProtoAndDeserialize(); - assertEquals(WifiMetrics.MAX_UNUSABLE_EVENTS, mDecodedProto.wifiIsUnusableEventList.length); - } - - /** - * Verify that we don't generate new WifiIsUnusableEvent from data stalls - * until MIN_DATA_STALL_WAIT_MS has passed since the last data stall WifiIsUnusableEvent - */ - @Test - public void testUnusableEventTimeThrottleForDataStall() throws Exception { - mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true); - generateUnusableEventAtGivenTime(0, 0); - // should be time throttled - generateUnusableEventAtGivenTime(1, 1); - generateUnusableEventAtGivenTime(2, WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1000); - // no time throttle for firmware alert - generateUnusableEventAtGivenTime(3, WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1001); - dumpProtoAndDeserialize(); - assertEquals(NUM_UNUSABLE_EVENT_TIME_THROTTLE, - mDecodedProto.wifiIsUnusableEventList.length); - verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[0], 0); - verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[1], 2); - verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[2], 3); - } - - /** - * Verify that LinkSpeedCounts is correctly logged in metrics - */ - @Test - public void testLinkSpeedCounts() throws Exception { - mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true); - for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) { - for (int j = 0; j <= i; j++) { - mWifiMetrics.incrementLinkSpeedCount( - WifiMetrics.MIN_LINK_SPEED_MBPS + i, TEST_RSSI_LEVEL); - } - } - dumpProtoAndDeserialize(); - assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT, mDecodedProto.linkSpeedCounts.length); - for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) { - assertEquals("Incorrect link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i, - mDecodedProto.linkSpeedCounts[i].linkSpeedMbps); - assertEquals("Incorrect count of link speed", - i + 1, mDecodedProto.linkSpeedCounts[i].count); - assertEquals("Incorrect sum of absolute values of rssi values", - Math.abs(TEST_RSSI_LEVEL) * (i + 1), - mDecodedProto.linkSpeedCounts[i].rssiSumDbm); - assertEquals("Incorrect sum of squares of rssi values", - TEST_RSSI_LEVEL * TEST_RSSI_LEVEL * (i + 1), - mDecodedProto.linkSpeedCounts[i].rssiSumOfSquaresDbmSq); - } - } - - /** - * Verify that Tx and Rx per-band LinkSpeedCounts are correctly logged in metrics - */ - @Test - public void testTxRxLinkSpeedBandCounts() throws Exception { - mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true); - for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) { - for (int j = 0; j <= i; j++) { - mWifiMetrics.incrementTxLinkSpeedBandCount( - WifiMetrics.MIN_LINK_SPEED_MBPS + i, RSSI_POLL_FREQUENCY); - mWifiMetrics.incrementRxLinkSpeedBandCount( - WifiMetrics.MIN_LINK_SPEED_MBPS + i + 1, RSSI_POLL_FREQUENCY); - } - } - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.txLinkSpeedCount2G.length); - assertEquals(0, mDecodedProto.rxLinkSpeedCount2G.length); - assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT, - mDecodedProto.txLinkSpeedCount5GLow.length); - assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT, - mDecodedProto.rxLinkSpeedCount5GLow.length); - assertEquals(0, mDecodedProto.txLinkSpeedCount5GMid.length); - assertEquals(0, mDecodedProto.rxLinkSpeedCount5GMid.length); - assertEquals(0, mDecodedProto.txLinkSpeedCount5GHigh.length); - assertEquals(0, mDecodedProto.rxLinkSpeedCount5GHigh.length); - for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) { - assertEquals("Incorrect Tx link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i, - mDecodedProto.txLinkSpeedCount5GLow[i].key); - assertEquals("Incorrect Rx link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i + 1, - mDecodedProto.rxLinkSpeedCount5GLow[i].key); - assertEquals("Incorrect count of Tx link speed", - i + 1, mDecodedProto.txLinkSpeedCount5GLow[i].count); - assertEquals("Incorrect count of Rx link speed", - i + 1, mDecodedProto.rxLinkSpeedCount5GLow[i].count); - } - } - - /** - * Verify that LinkSpeedCounts is not logged when disabled in settings - */ - @Test - public void testNoLinkSpeedCountsWhenDisabled() throws Exception { - mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, false); - for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) { - for (int j = 0; j <= i; j++) { - mWifiMetrics.incrementLinkSpeedCount( - WifiMetrics.MIN_LINK_SPEED_MBPS + i, TEST_RSSI_LEVEL); - mWifiMetrics.incrementTxLinkSpeedBandCount( - WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY); - mWifiMetrics.incrementRxLinkSpeedBandCount( - WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY); - } - } - dumpProtoAndDeserialize(); - assertEquals("LinkSpeedCounts should not be logged when disabled in settings", - 0, mDecodedProto.linkSpeedCounts.length); - assertEquals("Tx LinkSpeedCounts should not be logged when disabled in settings", - 0, mDecodedProto.txLinkSpeedCount5GLow.length); - assertEquals("Rx LinkSpeedCounts should not be logged when disabled in settings", - 0, mDecodedProto.rxLinkSpeedCount5GLow.length); - } - - /** - * Verify that LinkSpeedCounts is not logged when the link speed value is lower than - * MIN_LINK_SPEED_MBPS or when the rssi value is outside of - * [MIN_RSSI_LEVEL, MAX_RSSI_LEVEL] - */ - @Test - public void testNoLinkSpeedCountsForOutOfBoundValues() throws Exception { - mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true); - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementLinkSpeedCount( - WifiMetrics.MIN_LINK_SPEED_MBPS - i, MIN_RSSI_LEVEL); - mWifiMetrics.incrementTxLinkSpeedBandCount( - WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY); - mWifiMetrics.incrementRxLinkSpeedBandCount( - WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY); - } - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementLinkSpeedCount( - WifiMetrics.MIN_LINK_SPEED_MBPS, MIN_RSSI_LEVEL - i); - } - for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { - mWifiMetrics.incrementLinkSpeedCount( - WifiMetrics.MIN_LINK_SPEED_MBPS, MAX_RSSI_LEVEL + i); - } - dumpProtoAndDeserialize(); - assertEquals("LinkSpeedCounts should not be logged for out of bound values", - 0, mDecodedProto.linkSpeedCounts.length); - assertEquals("Tx LinkSpeedCounts should not be logged for out of bound values", - 0, mDecodedProto.txLinkSpeedCount5GLow.length); - assertEquals("Rx LinkSpeedCounts should not be logged for out of bound values", - 0, mDecodedProto.rxLinkSpeedCount5GLow.length); - } - - private int nextRandInt() { - return mRandom.nextInt(1000); - } - - private WifiLinkLayerStats nextRandomStats(WifiLinkLayerStats current) { - WifiLinkLayerStats out = new WifiLinkLayerStats(); - out.timeStampInMs = current.timeStampInMs + nextRandInt(); - - out.rxmpdu_be = current.rxmpdu_be + nextRandInt(); - out.txmpdu_be = current.txmpdu_be + nextRandInt(); - out.lostmpdu_be = current.lostmpdu_be + nextRandInt(); - out.retries_be = current.retries_be + nextRandInt(); - - out.rxmpdu_bk = current.rxmpdu_bk + nextRandInt(); - out.txmpdu_bk = current.txmpdu_bk + nextRandInt(); - out.lostmpdu_bk = current.lostmpdu_bk + nextRandInt(); - out.retries_bk = current.retries_bk + nextRandInt(); - - out.rxmpdu_vi = current.rxmpdu_vi + nextRandInt(); - out.txmpdu_vi = current.txmpdu_vi + nextRandInt(); - out.lostmpdu_vi = current.lostmpdu_vi + nextRandInt(); - out.retries_vi = current.retries_vi + nextRandInt(); - - out.rxmpdu_vo = current.rxmpdu_vo + nextRandInt(); - out.txmpdu_vo = current.txmpdu_vo + nextRandInt(); - out.lostmpdu_vo = current.lostmpdu_vo + nextRandInt(); - out.retries_vo = current.retries_vo + nextRandInt(); - - out.on_time = current.on_time + nextRandInt(); - out.tx_time = current.tx_time + nextRandInt(); - out.rx_time = current.rx_time + nextRandInt(); - out.on_time_scan = current.on_time_scan + nextRandInt(); - out.on_time_nan_scan = current.on_time_nan_scan + nextRandInt(); - out.on_time_background_scan = current.on_time_background_scan + nextRandInt(); - out.on_time_roam_scan = current.on_time_roam_scan + nextRandInt(); - out.on_time_pno_scan = current.on_time_pno_scan + nextRandInt(); - out.on_time_hs20_scan = current.on_time_hs20_scan + nextRandInt(); - return out; - } - - private void assertWifiLinkLayerUsageHasDiff(WifiLinkLayerStats oldStats, - WifiLinkLayerStats newStats) { - assertEquals(newStats.timeStampInMs - oldStats.timeStampInMs, - mDecodedProto.wifiLinkLayerUsageStats.loggingDurationMs); - assertEquals(newStats.on_time - oldStats.on_time, - mDecodedProto.wifiLinkLayerUsageStats.radioOnTimeMs); - assertEquals(newStats.tx_time - oldStats.tx_time, - mDecodedProto.wifiLinkLayerUsageStats.radioTxTimeMs); - assertEquals(newStats.rx_time - oldStats.rx_time, - mDecodedProto.wifiLinkLayerUsageStats.radioRxTimeMs); - assertEquals(newStats.on_time_scan - oldStats.on_time_scan, - mDecodedProto.wifiLinkLayerUsageStats.radioScanTimeMs); - assertEquals(newStats.on_time_nan_scan - oldStats.on_time_nan_scan, - mDecodedProto.wifiLinkLayerUsageStats.radioNanScanTimeMs); - assertEquals(newStats.on_time_background_scan - oldStats.on_time_background_scan, - mDecodedProto.wifiLinkLayerUsageStats.radioBackgroundScanTimeMs); - assertEquals(newStats.on_time_roam_scan - oldStats.on_time_roam_scan, - mDecodedProto.wifiLinkLayerUsageStats.radioRoamScanTimeMs); - assertEquals(newStats.on_time_pno_scan - oldStats.on_time_pno_scan, - mDecodedProto.wifiLinkLayerUsageStats.radioPnoScanTimeMs); - assertEquals(newStats.on_time_hs20_scan - oldStats.on_time_hs20_scan, - mDecodedProto.wifiLinkLayerUsageStats.radioHs20ScanTimeMs); - - } - - /** - * Verify that WifiMetrics is counting link layer usage correctly when given a series of - * valid input. - * @throws Exception - */ - @Test - public void testWifiLinkLayerUsageStats() throws Exception { - WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats()); - WifiLinkLayerStats stat2 = nextRandomStats(stat1); - WifiLinkLayerStats stat3 = nextRandomStats(stat2); - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1); - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2); - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat3); - dumpProtoAndDeserialize(); - - // After 2 increments, the counters should have difference between |stat1| and |stat3| - assertWifiLinkLayerUsageHasDiff(stat1, stat3); - } - - /** - * Verify that null input is handled and wifi link layer usage stats are not incremented. - * @throws Exception - */ - @Test - public void testWifiLinkLayerUsageStatsNullInput() throws Exception { - WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats()); - WifiLinkLayerStats stat2 = null; - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1); - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2); - dumpProtoAndDeserialize(); - - // Counter should be zero - assertWifiLinkLayerUsageHasDiff(stat1, stat1); - } - - /** - * Verify that when the new data appears to be bad link layer usage stats are not being - * incremented and the buffered WifiLinkLayerStats get cleared. - * @throws Exception - */ - @Test - public void testWifiLinkLayerUsageStatsChipReset() throws Exception { - WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats()); - WifiLinkLayerStats stat2 = nextRandomStats(stat1); - stat2.on_time = stat1.on_time - 1; - WifiLinkLayerStats stat3 = nextRandomStats(stat2); - WifiLinkLayerStats stat4 = nextRandomStats(stat3); - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1); - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2); - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat3); - mWifiMetrics.incrementWifiLinkLayerUsageStats(stat4); - dumpProtoAndDeserialize(); - - // Should only count the difference between |stat3| and |stat4| - assertWifiLinkLayerUsageHasDiff(stat3, stat4); - } - - private void assertUsabilityStatsAssignment(WifiInfo info, WifiLinkLayerStats stats, - WifiUsabilityStatsEntry usabilityStats) { - assertEquals(info.getRssi(), usabilityStats.rssi); - assertEquals(info.getLinkSpeed(), usabilityStats.linkSpeedMbps); - assertEquals(info.getRxLinkSpeedMbps(), usabilityStats.rxLinkSpeedMbps); - assertEquals(stats.timeStampInMs, usabilityStats.timeStampMs); - assertEquals(stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo, - usabilityStats.totalTxSuccess); - assertEquals(stats.retries_be + stats.retries_bk + stats.retries_vi + stats.retries_vo, - usabilityStats.totalTxRetries); - assertEquals(stats.lostmpdu_be + stats.lostmpdu_bk + stats.lostmpdu_vi + stats.lostmpdu_vo, - usabilityStats.totalTxBad); - assertEquals(stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo, - usabilityStats.totalRxSuccess); - assertEquals(stats.on_time, usabilityStats.totalRadioOnTimeMs); - assertEquals(stats.tx_time, usabilityStats.totalRadioTxTimeMs); - assertEquals(stats.rx_time, usabilityStats.totalRadioRxTimeMs); - assertEquals(stats.on_time_scan, usabilityStats.totalScanTimeMs); - assertEquals(stats.on_time_nan_scan, usabilityStats.totalNanScanTimeMs); - assertEquals(stats.on_time_background_scan, usabilityStats.totalBackgroundScanTimeMs); - assertEquals(stats.on_time_roam_scan, usabilityStats.totalRoamScanTimeMs); - assertEquals(stats.on_time_pno_scan, usabilityStats.totalPnoScanTimeMs); - assertEquals(stats.on_time_hs20_scan, usabilityStats.totalHotspot2ScanTimeMs); - assertEquals(stats.beacon_rx, usabilityStats.totalBeaconRx); - } - - // Simulate adding a LABEL_GOOD WifiUsabilityStats - private WifiLinkLayerStats addGoodWifiUsabilityStats(WifiLinkLayerStats start) { - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - WifiLinkLayerStats stats = start; - for (int i = 0; i < WifiMetrics.NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD; i++) { - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats); - stats = nextRandomStats(stats); - } - return stats; - } - - // Simulate adding a LABEL_BAD WifiUsabilityStats - private WifiLinkLayerStats addBadWifiUsabilityStats(WifiLinkLayerStats start) { - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - WifiLinkLayerStats stats1 = start; - WifiLinkLayerStats stats2 = nextRandomStats(stats1); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2); - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - return nextRandomStats(stats2); - } - - /** - * Verify that updateWifiUsabilityStatsEntries correctly converts the inputs into - * a WifiUsabilityStatsEntry Object and then stores it. - * - * Verify that the converted metrics proto contains pairs of WifiUsabilityStats with - * LABEL_GOOD and LABEL_BAD - * @throws Exception - */ - @Test - public void testUpdateWifiUsabilityStatsEntries() throws Exception { - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - when(info.getRxLinkSpeedMbps()).thenReturn(nextRandInt()); - when(info.getBSSID()).thenReturn("Wifi"); - when(info.getFrequency()).thenReturn(5745); - - WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats()); - WifiLinkLayerStats stats2 = nextRandomStats(stats1); - mWifiMetrics.incrementWifiScoreCount(60); - mWifiMetrics.incrementWifiUsabilityScoreCount(2, 55, 15); - mWifiMetrics.logLinkProbeSuccess(nextRandInt(), nextRandInt(), nextRandInt(), 12); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1); - mWifiMetrics.incrementWifiScoreCount(58); - mWifiMetrics.incrementWifiUsabilityScoreCount(3, 56, 15); - mWifiMetrics.logLinkProbeFailure(nextRandInt(), nextRandInt(), - nextRandInt(), nextRandInt()); - mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT); - - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2); - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - - // Add 2 LABEL_GOOD but only 1 should remain in the converted proto - WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats2)); - statsGood.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS; - addGoodWifiUsabilityStats(statsGood); - - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length); - assertEquals(WifiUsabilityStats.LABEL_GOOD, mDecodedProto.wifiUsabilityStatsList[0].label); - assertEquals(WifiUsabilityStats.LABEL_BAD, mDecodedProto.wifiUsabilityStatsList[1].label); - assertUsabilityStatsAssignment(info, stats1, - mDecodedProto.wifiUsabilityStatsList[1].stats[0]); - assertUsabilityStatsAssignment(info, stats2, - mDecodedProto.wifiUsabilityStatsList[1].stats[1]); - - assertEquals(2, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumToFramework); - assertEquals(3, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumToFramework); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumInsideFramework); - assertEquals(1, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumInsideFramework); - assertEquals(60, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiScore); - assertEquals(58, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiScore); - assertEquals(55, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiUsabilityScore); - assertEquals(56, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiUsabilityScore); - assertEquals(15, mDecodedProto.wifiUsabilityStatsList[1].stats[0].predictionHorizonSec); - assertEquals(true, mDecodedProto.wifiUsabilityStatsList[1].stats[0].isSameBssidAndFreq); - assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS, - mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeStatusSinceLastUpdate); - assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE, - mDecodedProto.wifiUsabilityStatsList[1].stats[1].probeStatusSinceLastUpdate); - assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE, - mDecodedProto.wifiUsabilityStatsList[0].stats[0].probeStatusSinceLastUpdate); - assertEquals(12, - mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeElapsedTimeSinceLastUpdateMs); - assertEquals(Integer.MAX_VALUE, mDecodedProto.wifiUsabilityStatsList[1] - .stats[1].probeElapsedTimeSinceLastUpdateMs); - assertEquals(-1, mDecodedProto.wifiUsabilityStatsList[0] - .stats[0].probeElapsedTimeSinceLastUpdateMs); - assertEquals(DEVICE_MOBILITY_STATE_HIGH_MVMT, mDecodedProto.wifiUsabilityStatsList[1] - .stats[mDecodedProto.wifiUsabilityStatsList[1].stats.length - 1] - .deviceMobilityState); - } - - /** - * Verify that when there are no WifiUsability events the generated proto also contains no - * such information. - * @throws Exception - */ - @Test - public void testWifiUsabilityStatsZeroEvents() throws Exception { - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that we discard a WifiUsabilityStats with LABEL_GOOD if there is no corresponding - * LABEL_BAD - * @throws Exception - */ - @Test - public void testWifiUsabilityStatsIgnoreSingleLabelGood() throws Exception { - addGoodWifiUsabilityStats(new WifiLinkLayerStats()); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that we discard a WifiUsabilityStats with LABEL_BAD if there is no corresponding - * LABEL_GOOD - * @throws Exception - */ - @Test - public void testWifiUsabilityStatsIgnoreSingleLabelBad() throws Exception { - addBadWifiUsabilityStats(new WifiLinkLayerStats()); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that the buffer for WifiUsabilityStats does not exceed the max length. - * Do this by trying to add more WifiUsabilityStats than the max length and then - * verifying that the decoded proto's length does not exceed the max length. - * - * Also verify that the length for the list of WifiUsabilityStatsEntry is capped. - * @throws Exception - */ - @Test - public void testWifiUsabilityStatsBufferSizeIsCapped() throws Exception { - // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit - WifiLinkLayerStats stats = new WifiLinkLayerStats(); - for (int j = 0; j < WifiMetrics.MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE + 1; j++) { - stats = addGoodWifiUsabilityStats(stats); - stats = addBadWifiUsabilityStats(stats); - stats.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS; - } - dumpProtoAndDeserialize(); - assertEquals(2 * WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD, - mDecodedProto.wifiUsabilityStatsList.length); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD; i++) { - assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE, - mDecodedProto.wifiUsabilityStatsList[2 * i].stats.length); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList[2 * i + 1].stats.length); - } - } - - /** - * Verify that LABEL_GOOD stats are not generated more frequently than - * |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS| - * @throws Exception - */ - @Test - public void testWifiUsabilityStatsLabelGoodHasMinimumPeriod() throws Exception { - // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit - WifiLinkLayerStats stats = new WifiLinkLayerStats(); - for (int j = 0; j < 2; j++) { - stats = addGoodWifiUsabilityStats(stats); - stats = addBadWifiUsabilityStats(stats); - } - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_BAD stats are not generated more frequently than |MIN_DATA_STALL_WAIT_MS| - * @throws Exception - */ - @Test - public void testWifiUsabilityStatsLabelBadNotGeneratedGapLessThanMinimum() throws Exception { - // simulate adding two LABEL_GOOD WifiUsabilityStats - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - WifiLinkLayerStats stats1 = new WifiLinkLayerStats(); - WifiLinkLayerStats stats2 = new WifiLinkLayerStats(); - stats1 = addGoodWifiUsabilityStats(stats1); - stats2.timeStampInMs = stats1.timeStampInMs - + WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS; - addGoodWifiUsabilityStats(stats2); - - WifiLinkLayerStats stats3 = new WifiLinkLayerStats(); - WifiLinkLayerStats stats4 = new WifiLinkLayerStats(); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) { - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3); - stats3 = nextRandomStats(stats3); - } - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3); - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) { - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4); - stats4 = nextRandomStats(stats4); - } - stats4.timeStampInMs = stats3.timeStampInMs - 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS; - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4); - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_BAD stats are generated if timestamp gap is larger than - * |MIN_DATA_STALL_WAIT_MS| - * @throws Exception - */ - @Test - public void testWifiUsabilityStatsLabelBadGeneratedGapLargerThanMinimum() throws Exception { - // simulate adding two LABEL_GOOD WifiUsabilityStats - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - WifiLinkLayerStats stats1 = new WifiLinkLayerStats(); - WifiLinkLayerStats stats2 = new WifiLinkLayerStats(); - stats1 = addGoodWifiUsabilityStats(stats1); - stats2.timeStampInMs = stats1.timeStampInMs - + WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS; - addGoodWifiUsabilityStats(stats2); - - WifiLinkLayerStats stats3 = new WifiLinkLayerStats(); - WifiLinkLayerStats stats4 = new WifiLinkLayerStats(); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) { - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3); - stats3 = nextRandomStats(stats3); - } - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3); - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) { - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4); - stats4 = nextRandomStats(stats4); - } - stats4.timeStampInMs = stats3.timeStampInMs + 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS; - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4); - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - dumpProtoAndDeserialize(); - assertEquals(4, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Tests device mobility state metrics as states are changed. - */ - @Test - public void testDeviceMobilityStateMetrics_changeState() throws Exception { - // timeMs is initialized to 0 by the setUp() method - long timeMs = 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY); - - timeMs += 2000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_LOW_MVMT); - - dumpProtoAndDeserialize(); - - DeviceMobilityStatePnoScanStats[] expected = { - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 1000, 0), - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_STATIONARY, 1, 2000, 0), - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_LOW_MVMT, 1, 0, 0) - }; - - assertDeviceMobilityStatePnoScanStatsEqual( - expected, mDecodedProto.mobilityStatePnoStatsList); - } - - /** - * Tests device mobility state metrics as PNO scans are started and stopped. - */ - @Test - public void testDeviceMobilityStateMetrics_startStopPnoScans() throws Exception { - long timeMs = 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.logPnoScanStart(); - - timeMs += 2000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.logPnoScanStop(); - mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY); - mWifiMetrics.logPnoScanStart(); - - timeMs += 4000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.logPnoScanStop(); - - timeMs += 8000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT); - - dumpProtoAndDeserialize(); - - DeviceMobilityStatePnoScanStats[] expected = { - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, - 1, 1000 + 2000, 2000), - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_STATIONARY, - 1, 4000 + 8000, 4000), - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_HIGH_MVMT, 1, 0, 0) - }; - - assertDeviceMobilityStatePnoScanStatsEqual( - expected, mDecodedProto.mobilityStatePnoStatsList); - } - - /** - * Tests that the initial state is set up correctly. - */ - @Test - public void testDeviceMobilityStateMetrics_initialState() throws Exception { - dumpProtoAndDeserialize(); - - DeviceMobilityStatePnoScanStats[] expected = { - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 0, 0) - }; - - assertDeviceMobilityStatePnoScanStatsEqual( - expected, mDecodedProto.mobilityStatePnoStatsList); - } - - /** - * Tests that logPnoScanStart() updates the total duration in addition to the PNO duration. - */ - @Test - public void testDeviceMobilityStateMetrics_startPnoScansUpdatesTotalDuration() - throws Exception { - long timeMs = 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.logPnoScanStart(); - - dumpProtoAndDeserialize(); - - DeviceMobilityStatePnoScanStats[] expected = { - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 1000, 0) - }; - - assertDeviceMobilityStatePnoScanStatsEqual( - expected, mDecodedProto.mobilityStatePnoStatsList); - } - - /** - * Tests that logPnoScanStop() updates the total duration in addition to the PNO duration. - */ - @Test - public void testDeviceMobilityStateMetrics_stopPnoScansUpdatesTotalDuration() - throws Exception { - long timeMs = 1000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.logPnoScanStart(); - - timeMs += 2000; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - mWifiMetrics.logPnoScanStop(); - - dumpProtoAndDeserialize(); - - DeviceMobilityStatePnoScanStats[] expected = { - buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, - 1, 1000 + 2000, 2000) - }; - - assertDeviceMobilityStatePnoScanStatsEqual( - expected, mDecodedProto.mobilityStatePnoStatsList); - } - - /** - * Verify that clients should be notified of activity in case Wifi stats get updated. - */ - @Test - public void testClientNotification() throws RemoteException { - // Register Client for verification. - ArgumentCaptor<android.net.wifi.WifiUsabilityStatsEntry> usabilityStats = - ArgumentCaptor.forClass(android.net.wifi.WifiUsabilityStatsEntry.class); - mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener, - TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - - WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats()); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats); - - // Client should get the stats. - verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(), - usabilityStats.capture()); - assertEquals(usabilityStats.getValue().getTotalRadioOnTimeMillis(), linkLayerStats.on_time); - assertEquals(usabilityStats.getValue().getTotalTxBad(), linkLayerStats.lostmpdu_be - + linkLayerStats.lostmpdu_bk + linkLayerStats.lostmpdu_vi - + linkLayerStats.lostmpdu_vo); - assertEquals(usabilityStats.getValue().getTimeStampMillis(), linkLayerStats.timeStampInMs); - assertEquals(usabilityStats.getValue().getTotalRoamScanTimeMillis(), - linkLayerStats.on_time_roam_scan); - } - - /** - * Verify that remove client should be handled - */ - @Test - public void testRemoveClient() throws RemoteException { - // Register Client for verification. - mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener, - TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - mWifiMetrics.removeOnWifiUsabilityListener(TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - verify(mAppBinder).unlinkToDeath(any(), anyInt()); - - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats()); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats); - - verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(), - anyBoolean(), any()); - } - - /** - * Verify that WifiMetrics adds for death notification on adding client. - */ - @Test - public void testAddsForBinderDeathOnAddClient() throws Exception { - mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener, - TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - } - - /** - * Verify that client fails to get message when listener add failed. - */ - @Test - public void testAddsListenerFailureOnLinkToDeath() throws Exception { - doThrow(new RemoteException()) - .when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener, - TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats()); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats); - - // Client should not get any message listener add failed. - verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(), - anyBoolean(), any()); - } - - /** - * Verify that the label and the triggerType of Wifi usability stats are saved correctly - * during firmware alert is triggered. - * @throws Exception - */ - @Test - public void verifyFirmwareAlertUpdatesWifiUsabilityMetrics() throws Exception { - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - long eventTimeMs = nextRandInt(); - when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs); - WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats()); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1); - - // Add 1 LABEL_GOOD - WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1)); - // Firmware alert occurs - mWifiMetrics.logFirmwareAlert(2); - - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length); - - WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList; - assertEquals(WifiUsabilityStats.LABEL_GOOD, statsList[0].label); - assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label); - assertEquals(WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, statsList[1].triggerType); - assertEquals(eventTimeMs, statsList[1].timeStampMs); - assertEquals(2, statsList[1].firmwareAlertCode); - } - - /** - * Verify that the label and the triggerType of Wifi usability stats are saved correctly - * during Wifi data stall is triggered. - * @throws Exception - */ - @Test - public void verifyWifiDataStallUpdatesWifiUsabilityMetrics() throws Exception { - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - long eventTimeMs = nextRandInt(); - when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs); - WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats()); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1); - - // Add 1 LABEL_GOOD - WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1)); - // Wifi data stall occurs - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1); - - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length); - WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList; - assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label); - assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, statsList[1].triggerType); - assertEquals(-1, statsList[1].firmwareAlertCode); - assertEquals(eventTimeMs, statsList[1].timeStampMs); - } - - /** - * Test the generation of 'WifiConfigStoreIODuration' read histograms. - */ - @Test - public void testWifiConfigStoreReadDurationsHistogramGeneration() throws Exception { - mWifiMetrics.noteWifiConfigStoreReadDuration(10); - mWifiMetrics.noteWifiConfigStoreReadDuration(20); - mWifiMetrics.noteWifiConfigStoreReadDuration(100); - mWifiMetrics.noteWifiConfigStoreReadDuration(90); - mWifiMetrics.noteWifiConfigStoreReadDuration(130); - mWifiMetrics.noteWifiConfigStoreReadDuration(250); - mWifiMetrics.noteWifiConfigStoreReadDuration(600); - - dumpProtoAndDeserialize(); - - assertEquals(5, mDecodedProto.wifiConfigStoreIo.readDurations.length); - assertEquals(0, mDecodedProto.wifiConfigStoreIo.writeDurations.length); - - assertEquals(Integer.MIN_VALUE, - mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeStartMs); - assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeEndMs); - assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[0].count); - - assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeStartMs); - assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeEndMs); - assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[1].count); - - assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeStartMs); - assertEquals(150, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeEndMs); - assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[2].count); - - assertEquals(200, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeStartMs); - assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeEndMs); - assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[3].count); - - assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeStartMs); - assertEquals(Integer.MAX_VALUE, - mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeEndMs); - assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[4].count); - } - - /** - * Test the generation of 'WifiConfigStoreIODuration' write histograms. - */ - @Test - public void testWifiConfigStoreWriteDurationsHistogramGeneration() throws Exception { - mWifiMetrics.noteWifiConfigStoreWriteDuration(10); - mWifiMetrics.noteWifiConfigStoreWriteDuration(40); - mWifiMetrics.noteWifiConfigStoreWriteDuration(60); - mWifiMetrics.noteWifiConfigStoreWriteDuration(90); - mWifiMetrics.noteWifiConfigStoreWriteDuration(534); - mWifiMetrics.noteWifiConfigStoreWriteDuration(345); - - dumpProtoAndDeserialize(); - - assertEquals(0, mDecodedProto.wifiConfigStoreIo.readDurations.length); - assertEquals(3, mDecodedProto.wifiConfigStoreIo.writeDurations.length); - - assertEquals(Integer.MIN_VALUE, - mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeStartMs); - assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeEndMs); - assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[0].count); - - assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeStartMs); - assertEquals(100, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeEndMs); - assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[1].count); - - assertEquals(300, mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeStartMs); - assertEquals(Integer.MAX_VALUE, - mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeEndMs); - assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[2].count); - } - - /** - * Test link probe metrics. - */ - @Test - public void testLogLinkProbeMetrics() throws Exception { - mWifiMetrics.logLinkProbeSuccess(10000, -75, 50, 5); - mWifiMetrics.logLinkProbeFailure(30000, -80, 10, - WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK); - mWifiMetrics.logLinkProbeSuccess(3000, -71, 160, 12); - mWifiMetrics.logLinkProbeFailure(40000, -80, 6, - WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK); - mWifiMetrics.logLinkProbeSuccess(5000, -73, 160, 10); - mWifiMetrics.logLinkProbeFailure(2000, -78, 6, - WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_TIMEOUT); - - dumpProtoAndDeserialize(); - - StaEvent[] expected = { - buildLinkProbeSuccessStaEvent(5), - buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK), - buildLinkProbeSuccessStaEvent(12), - buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK), - buildLinkProbeSuccessStaEvent(10), - buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT) - }; - assertLinkProbeStaEventsEqual(expected, mDecodedProto.staEventList); - - LinkProbeStats linkProbeStats = mDecodedProto.linkProbeStats; - - Int32Count[] expectedSuccessRssiHistogram = { - buildInt32Count(-75, 1), - buildInt32Count(-73, 1), - buildInt32Count(-71, 1), - }; - assertKeyCountsEqual(expectedSuccessRssiHistogram, - linkProbeStats.successRssiCounts); - - Int32Count[] expectedFailureRssiHistogram = { - buildInt32Count(-80, 2), - buildInt32Count(-78, 1), - }; - assertKeyCountsEqual(expectedFailureRssiHistogram, - linkProbeStats.failureRssiCounts); - - Int32Count[] expectedSuccessLinkSpeedHistogram = { - buildInt32Count(50, 1), - buildInt32Count(160, 2) - }; - assertKeyCountsEqual(expectedSuccessLinkSpeedHistogram, - linkProbeStats.successLinkSpeedCounts); - - Int32Count[] expectedFailureLinkSpeedHistogram = { - buildInt32Count(6, 2), - buildInt32Count(10, 1) - }; - assertKeyCountsEqual(expectedFailureLinkSpeedHistogram, - linkProbeStats.failureLinkSpeedCounts); - - HistogramBucketInt32[] expectedSuccessTimeSinceLastTxSuccessSecondsHistogram = { - buildHistogramBucketInt32(Integer.MIN_VALUE, 5, 1), - buildHistogramBucketInt32(5, 15, 2) - }; - assertHistogramBucketsEqual(expectedSuccessTimeSinceLastTxSuccessSecondsHistogram, - linkProbeStats.successSecondsSinceLastTxSuccessHistogram); - - HistogramBucketInt32[] expectedFailureTimeSinceLastTxSuccessSecondsHistogram = { - buildHistogramBucketInt32(Integer.MIN_VALUE, 5, 1), - buildHistogramBucketInt32(15, 45, 2) - }; - assertHistogramBucketsEqual(expectedFailureTimeSinceLastTxSuccessSecondsHistogram, - linkProbeStats.failureSecondsSinceLastTxSuccessHistogram); - - HistogramBucketInt32[] expectedSuccessElapsedTimeMsHistogram = { - buildHistogramBucketInt32(5, 10, 1), - buildHistogramBucketInt32(10, 15, 2), - }; - assertHistogramBucketsEqual(expectedSuccessElapsedTimeMsHistogram, - linkProbeStats.successElapsedTimeMsHistogram); - - LinkProbeFailureReasonCount[] expectedFailureReasonCount = { - buildLinkProbeFailureReasonCount( - LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK, 2), - buildLinkProbeFailureReasonCount( - LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT, 1), - }; - assertLinkProbeFailureReasonCountsEqual(expectedFailureReasonCount, - linkProbeStats.failureReasonCounts); - } - - /** - * Tests counting the number of link probes triggered per day for each experiment. - */ - @Test - public void testIncrementLinkProbeExperimentProbeCount() throws Exception { - String experimentId1 = "screenOnDelay=6000,noTxDelay=3000,delayBetweenProbes=9000," - + "rssiThreshold=-70,linkSpeedThreshold=15,"; - mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId1); - - String experimentId2 = "screenOnDelay=9000,noTxDelay=12000,delayBetweenProbes=15000," - + "rssiThreshold=-72,linkSpeedThreshold=20,"; - mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId2); - mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId2); - - dumpProtoAndDeserialize(); - - ExperimentProbeCounts[] actual = mDecodedProto.linkProbeStats.experimentProbeCounts; - - ExperimentProbeCounts[] expected = { - buildExperimentProbeCounts(experimentId1, 1), - buildExperimentProbeCounts(experimentId2, 2) - }; - - assertExperimentProbeCountsEqual(expected, actual); - } - - /** - * Tests logNetworkSelectionDecision() - */ - @Test - public void testLogNetworkSelectionDecision() throws Exception { - mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 6); - mWifiMetrics.logNetworkSelectionDecision(1, 2, false, 1); - mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 6); - mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 2); - mWifiMetrics.logNetworkSelectionDecision(3, 2, false, 15); - mWifiMetrics.logNetworkSelectionDecision(1, 2, false, 6); - mWifiMetrics.logNetworkSelectionDecision(1, 4, true, 2); - - dumpProtoAndDeserialize(); - - assertEquals(3, mDecodedProto.networkSelectionExperimentDecisionsList.length); - - NetworkSelectionExperimentDecisions exp12 = - findUniqueNetworkSelectionExperimentDecisions(1, 2); - Int32Count[] exp12SameExpected = { - buildInt32Count(2, 1), - buildInt32Count(6, 2) - }; - assertKeyCountsEqual(exp12SameExpected, exp12.sameSelectionNumChoicesCounter); - Int32Count[] exp12DiffExpected = { - buildInt32Count(1, 1), - buildInt32Count(6, 1) - }; - assertKeyCountsEqual(exp12DiffExpected, exp12.differentSelectionNumChoicesCounter); - - NetworkSelectionExperimentDecisions exp32 = - findUniqueNetworkSelectionExperimentDecisions(3, 2); - Int32Count[] exp32SameExpected = {}; - assertKeyCountsEqual(exp32SameExpected, exp32.sameSelectionNumChoicesCounter); - Int32Count[] exp32DiffExpected = { - buildInt32Count( - WifiMetrics.NetworkSelectionExperimentResults.MAX_CHOICES, 1) - }; - assertKeyCountsEqual(exp32DiffExpected, exp32.differentSelectionNumChoicesCounter); - - NetworkSelectionExperimentDecisions exp14 = - findUniqueNetworkSelectionExperimentDecisions(1, 4); - Int32Count[] exp14SameExpected = { - buildInt32Count(2, 1) - }; - assertKeyCountsEqual(exp14SameExpected, exp14.sameSelectionNumChoicesCounter); - Int32Count[] exp14DiffExpected = {}; - assertKeyCountsEqual(exp14DiffExpected, exp14.differentSelectionNumChoicesCounter); - } - - /** - * Test the generation of 'WifiNetworkRequestApiLog' message. - */ - @Test - public void testWifiNetworkRequestApiLog() throws Exception { - mWifiMetrics.incrementNetworkRequestApiNumRequest(); - mWifiMetrics.incrementNetworkRequestApiNumRequest(); - mWifiMetrics.incrementNetworkRequestApiNumRequest(); - - mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(7); - mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(0); - mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(1); - - mWifiMetrics.incrementNetworkRequestApiNumConnectSuccess(); - - mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass(); - mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass(); - - mWifiMetrics.incrementNetworkRequestApiNumUserReject(); - - mWifiMetrics.incrementNetworkRequestApiNumApps(); - - dumpProtoAndDeserialize(); - - assertEquals(3, mDecodedProto.wifiNetworkRequestApiLog.numRequest); - assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numConnectSuccess); - assertEquals(2, mDecodedProto.wifiNetworkRequestApiLog.numUserApprovalBypass); - assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numUserReject); - assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numApps); - - HistogramBucketInt32[] expectedNetworkMatchSizeHistogram = { - buildHistogramBucketInt32(0, 1, 1), - buildHistogramBucketInt32(1, 5, 1), - buildHistogramBucketInt32(5, 10, 1) - }; - assertHistogramBucketsEqual(expectedNetworkMatchSizeHistogram, - mDecodedProto.wifiNetworkRequestApiLog.networkMatchSizeHistogram); - } - - /** - * Test the generation of 'WifiNetworkSuggestionApiLog' message. - */ - @Test - public void testWifiNetworkSuggestionApiLog() throws Exception { - mWifiMetrics.incrementNetworkSuggestionApiNumModification(); - mWifiMetrics.incrementNetworkSuggestionApiNumModification(); - mWifiMetrics.incrementNetworkSuggestionApiNumModification(); - mWifiMetrics.incrementNetworkSuggestionApiNumModification(); - - mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess(); - mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess(); - - mWifiMetrics.incrementNetworkSuggestionApiNumConnectFailure(); - - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED); - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED); - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED); - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED); - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED); - mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING); - - - mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{ - add(5); - add(100); - add(50); - add(120); - }}); - // Second update should overwrite the prevous write. - mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{ - add(7); - add(110); - add(40); - add(60); - }}); - - mWifiMetrics.incrementNetworkSuggestionUserRevokePermission(); - mWifiMetrics.incrementNetworkSuggestionUserRevokePermission(); - - dumpProtoAndDeserialize(); - - assertEquals(4, mDecodedProto.wifiNetworkSuggestionApiLog.numModification); - assertEquals(2, mDecodedProto.wifiNetworkSuggestionApiLog.numConnectSuccess); - assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.numConnectFailure); - - HistogramBucketInt32[] expectedNetworkListSizeHistogram = { - buildHistogramBucketInt32(5, 20, 1), - buildHistogramBucketInt32(20, 50, 1), - buildHistogramBucketInt32(50, 100, 1), - buildHistogramBucketInt32(100, 500, 1), - }; - assertHistogramBucketsEqual(expectedNetworkListSizeHistogram, - mDecodedProto.wifiNetworkSuggestionApiLog.networkListSizeHistogram); - - assertEquals(3, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType.length); - assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_CARRIER_PRIVILEGED, - mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[0].appType); - assertEquals(2, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[0].count); - assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_NETWORK_PROVISIONING, - mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[1].appType); - assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[1].count); - assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_NON_PRIVILEGED, - mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[2].appType); - assertEquals(3, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[2].count); - } - - /** - * Test the generation of 'UserReactionToApprovalUiEvent' message. - */ - @Test - public void testUserReactionToApprovalUiEvent() throws Exception { - mWifiMetrics.addUserApprovalSuggestionAppUiReaction(1, true); - mWifiMetrics.addUserApprovalSuggestionAppUiReaction(2, false); - - mWifiMetrics.addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, true); - mWifiMetrics.addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_DISMISS, false); - mWifiMetrics.addUserApprovalCarrierUiReaction( - WifiCarrierInfoManager.ACTION_USER_DISALLOWED_CARRIER, false); - - dumpProtoAndDeserialize(); - - assertEquals(2, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction.length); - assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_ALLOWED, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[0] - .userAction); - assertEquals(true, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[0] - .isDialog); - assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISALLOWED, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[1] - .userAction); - assertEquals(false, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[1] - .isDialog); - - assertEquals(3, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction.length); - assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_ALLOWED, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[0] - .userAction); - assertEquals(true, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[0] - .isDialog); - assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISMISS, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[1] - .userAction); - assertEquals(false, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[1] - .isDialog); - assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISALLOWED, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[2] - .userAction); - assertEquals(false, - mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[2] - .isDialog); - } - - private NetworkSelectionExperimentDecisions findUniqueNetworkSelectionExperimentDecisions( - int experiment1Id, int experiment2Id) { - NetworkSelectionExperimentDecisions result = null; - for (NetworkSelectionExperimentDecisions d - : mDecodedProto.networkSelectionExperimentDecisionsList) { - if (d.experiment1Id == experiment1Id && d.experiment2Id == experiment2Id) { - assertNull("duplicate found!", result); - result = d; - } - } - assertNotNull("not found!", result); - return result; - } - - /** - * Verify that the label and the triggerType of Wifi usability stats are saved correctly - * during IP reachability lost message is received. - * @throws Exception - */ - @Test - public void verifyIpReachabilityLostUpdatesWifiUsabilityMetrics() throws Exception { - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - long eventTimeMs = nextRandInt(); - when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs); - WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats()); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1); - - // Add 1 LABEL_GOOD - WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1)); - // IP reachability lost occurs - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1); - - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length); - WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList; - assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label); - assertEquals(WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, statsList[1].triggerType); - assertEquals(eventTimeMs, statsList[1].timeStampMs); - } - - /** - * Test the WifiLock active session statistics - */ - @Test - public void testWifiLockActiveSession() throws Exception { - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 100000); - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000); - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000000); - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 1000); - - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 90000); - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 900000); - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 9000); - mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 20000000); - - dumpProtoAndDeserialize(); - - assertEquals(10111000, mDecodedProto.wifiLockStats.highPerfActiveTimeMs); - assertEquals(20999000, mDecodedProto.wifiLockStats.lowLatencyActiveTimeMs); - - HistogramBucketInt32[] expectedHighPerfHistogram = { - buildHistogramBucketInt32(1, 10, 1), - buildHistogramBucketInt32(10, 60, 1), - buildHistogramBucketInt32(60, 600, 1), - buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1), - }; - - HistogramBucketInt32[] expectedLowLatencyHistogram = { - buildHistogramBucketInt32(1, 10, 1), - buildHistogramBucketInt32(60, 600, 1), - buildHistogramBucketInt32(600, 3600, 1), - buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1), - }; - - assertHistogramBucketsEqual(expectedHighPerfHistogram, - mDecodedProto.wifiLockStats.highPerfActiveSessionDurationSecHistogram); - - assertHistogramBucketsEqual(expectedLowLatencyHistogram, - mDecodedProto.wifiLockStats.lowLatencyActiveSessionDurationSecHistogram); - } - - /** - * Test the WifiLock acquisition session statistics - */ - @Test - public void testWifiLockAcqSession() throws Exception { - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 100000); - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000); - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000000); - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 1000); - - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 90000); - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 900000); - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 9000); - mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 20000000); - - dumpProtoAndDeserialize(); - - HistogramBucketInt32[] expectedHighPerfHistogram = { - buildHistogramBucketInt32(1, 10, 1), - buildHistogramBucketInt32(10, 60, 1), - buildHistogramBucketInt32(60, 600, 1), - buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1), - }; - - HistogramBucketInt32[] expectedLowLatencyHistogram = { - buildHistogramBucketInt32(1, 10, 1), - buildHistogramBucketInt32(60, 600, 1), - buildHistogramBucketInt32(600, 3600, 1), - buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1), - }; - - assertHistogramBucketsEqual(expectedHighPerfHistogram, - mDecodedProto.wifiLockStats.highPerfLockAcqDurationSecHistogram); - - assertHistogramBucketsEqual(expectedLowLatencyHistogram, - mDecodedProto.wifiLockStats.lowLatencyLockAcqDurationSecHistogram); - } - - /** - * Verify that LABEL_GOOD stats are generated if Wifi score breaches low and there - * is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis - * @throws Exception - */ - @Test - public void testGoodStatsAreGeneratedByWifiScoreBreachLow() throws Exception { - // The elapsed time falls into the interval for adding good stats - createTestForDataCollectionByScoreBreach( - WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1, - false, true); - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking - * time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis - * @throws Exception - */ - @Test - public void testGoodStatsAreNotGeneratedByWifiScoreBreachLow() throws Exception { - // The elapsed time is shorter than necessary to add good stats - createTestForDataCollectionByScoreBreach( - WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS - 1, - false, true); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking - * time is greater than VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS - * @throws Exception - */ - @Test - public void testGoodStatsAreNotGeneratedIfWifiScoreBreachExpires() throws Exception { - // The Wifi score breaching expires for adding good stats - createTestForDataCollectionByScoreBreach( - WifiMetrics.VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS + 1, - false, true); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and there is - * WifiIsUnusableEvent occured within MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis - * @throws Exception - */ - @Test - public void testGoodStatsAreNotGeneratedIfBadEventOccured() throws Exception { - // The elapsed time falls into the interval for adding good stats and bad event occurs - createTestForDataCollectionByScoreBreach( - WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1, - true, true); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_GOOD stats are generated if Wifi usability score breaches low and there - * is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis - * @throws Exception - */ - @Test - public void testGoodStatsAreGeneratedByWifiUsabilityScoreBreachLow() throws Exception { - // The elapsed time falls into the interval for adding good stats - createTestForDataCollectionByScoreBreach( - WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1, - false, false); - dumpProtoAndDeserialize(); - assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and - * the checking time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis - * @throws Exception - */ - @Test - public void testGoodStatsAreNotGeneratedByWifiUsabilityScoreBreachLow() throws Exception { - // The elapsed time is shorter than necessary to add good stats - createTestForDataCollectionByScoreBreach( - WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS - 1, - false, false); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and - * the checking time is greater than VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS - * @throws Exception - */ - @Test - public void testGoodStatsAreNotGeneratedIfWifiUsabilityScoreBreachExpires() throws Exception { - // The Wifi usability score breaching expires for adding good stats - createTestForDataCollectionByScoreBreach( - WifiMetrics.VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS + 1, - false, false); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and there - * is WifiIsUnusableEvent occured within MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis - * @throws Exception - */ - @Test - public void testGoodStatsAreNotGeneratedIfBadEventOccuredForUsabilityScore() throws Exception { - // The elapsed time falls into the interval for adding good stats and bad event occurs - createTestForDataCollectionByScoreBreach( - WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1, - true, false); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Verify that incrementNumWifiToggles increments the corrects fields based on input. - */ - @Test - public void testIncrementNumWifiToggles() throws Exception { - mWifiMetrics.incrementNumWifiToggles(true, true); - for (int i = 0; i < 2; i++) { - mWifiMetrics.incrementNumWifiToggles(true, false); - } - for (int i = 0; i < 3; i++) { - mWifiMetrics.incrementNumWifiToggles(false, true); - } - for (int i = 0; i < 4; i++) { - mWifiMetrics.incrementNumWifiToggles(false, false); - } - dumpProtoAndDeserialize(); - assertEquals(1, mDecodedProto.wifiToggleStats.numToggleOnPrivileged); - assertEquals(2, mDecodedProto.wifiToggleStats.numToggleOffPrivileged); - assertEquals(3, mDecodedProto.wifiToggleStats.numToggleOnNormal); - assertEquals(4, mDecodedProto.wifiToggleStats.numToggleOffNormal); - } - - /** - * Verify metered stats are counted properly for saved and ephemeral networks. - */ - @Test - public void testMeteredNetworkMetrics() throws Exception { - // Test without metered override - WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(); - WifiConfiguration config1 = WifiConfigurationTestUtil.createPskNetwork(); - config.fromWifiNetworkSuggestion = false; - config1.fromWifiNetworkSuggestion = true; - mWifiMetrics.addMeteredStat(config, false); - mWifiMetrics.addMeteredStat(config1, true); - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numMetered); - assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numUnmetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered); - assertEquals(1, mDecodedProto.meteredNetworkStatsSuggestion.numMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered); - - // Test with metered override - config = WifiConfigurationTestUtil.createPskNetwork(); - config1 = WifiConfigurationTestUtil.createPskNetwork(); - config.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED; - config1.meteredOverride = WifiConfiguration.METERED_OVERRIDE_NOT_METERED; - mWifiMetrics.addMeteredStat(config, true); - mWifiMetrics.addMeteredStat(config1, true); - dumpProtoAndDeserialize(); - assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numMetered); - assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numUnmetered); - assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered); - assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered); - } - - /** - * Verify that the same network does not get counted twice - */ - @Test - public void testMeteredNetworkMetricsNoDoubleCount() throws Exception { - WifiConfiguration config = new WifiConfiguration(); - config.ephemeral = false; - mWifiMetrics.addMeteredStat(config, false); - mWifiMetrics.addMeteredStat(config, true); - mWifiMetrics.addMeteredStat(config, true); - dumpProtoAndDeserialize(); - assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numUnmetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered); - assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered); - } - - /** - * Create a test to verify data collection logic triggered by score breaching low - * @param elapsedTimeAfterBreach The elapsed time after score breaches low - * @param isThereBadEvent Whether there is a bad event happened after score breaches low - * @param isWifiScore Whether it is Wifi score or not that breaches the threshold - */ - private void createTestForDataCollectionByScoreBreach( - long elapsedTimeAfterBreach, boolean isThereBadEvent, boolean isWifiScore) { - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - WifiLinkLayerStats stats2 = new WifiLinkLayerStats(); - mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); - - addOneBadWifiUsabilityStats(info); - if (isWifiScore) { - stats2 = wifiScoreBreachesLow(info, stats2); - } else { - stats2 = wifiUsabilityScoreBreachesLow(info, stats2); - } - if (isThereBadEvent) { - mWifiMetrics.logWifiIsUnusableEvent(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1); - } - when(mClock.getElapsedSinceBootMillis()).thenReturn(elapsedTimeAfterBreach); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2); - } - - // Simulate adding one LABEL_BAD WifiUsabilityStats - private void addOneBadWifiUsabilityStats(WifiInfo info) { - WifiLinkLayerStats stats1 = new WifiLinkLayerStats(); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1); - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - } - - // Simulate that Wifi score breaches low - private WifiLinkLayerStats wifiScoreBreachesLow(WifiInfo info, WifiLinkLayerStats stats2) { - int upper = WifiMetrics.LOW_WIFI_SCORE + 7; - int lower = WifiMetrics.LOW_WIFI_SCORE - 8; - mWifiMetrics.incrementWifiScoreCount(upper); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2); - stats2 = nextRandomStats(stats2); - long timeMs = 0; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - // Wifi score breaches low - mWifiMetrics.incrementWifiScoreCount(lower); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2); - stats2 = nextRandomStats(stats2); - return stats2; - } - - // Simulate that Wifi usability score breaches low - private WifiLinkLayerStats wifiUsabilityScoreBreachesLow(WifiInfo info, - WifiLinkLayerStats stats2) { - int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7; - int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8; - mWifiMetrics.incrementWifiUsabilityScoreCount(1, upper, 30); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2); - stats2 = nextRandomStats(stats2); - long timeMs = 0; - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - // Wifi usability score breaches low - mWifiMetrics.incrementWifiUsabilityScoreCount(2, lower, 30); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2); - stats2 = nextRandomStats(stats2); - return stats2; - } - - /** - * Verify the counts of passpoint profile type are correct. - * @param profileTypes type and count of installed passpoint profiles - */ - private void assertPasspointProfileTypeCount(PasspointProfileTypeCount[] profileTypes) { - for (PasspointProfileTypeCount passpointProfileType : profileTypes) { - switch(passpointProfileType.eapMethodType) { - case PasspointProfileTypeCount.TYPE_EAP_AKA: - assertEquals(NUM_EAP_AKA_TYPE, passpointProfileType.count); - break; - case PasspointProfileTypeCount.TYPE_EAP_AKA_PRIME: - assertEquals(NUM_EAP_AKA_PRIME_TYPE, passpointProfileType.count); - break; - case PasspointProfileTypeCount.TYPE_EAP_SIM: - assertEquals(NUM_EAP_SIM_TYPE, passpointProfileType.count); - break; - case PasspointProfileTypeCount.TYPE_EAP_TLS: - assertEquals(NUM_EAP_TLS_TYPE, passpointProfileType.count); - break; - case PasspointProfileTypeCount.TYPE_EAP_TTLS: - assertEquals(NUM_EAP_TTLS_TYPE, passpointProfileType.count); - break; - default: - fail("unknown type counted"); - } - } - } - - /** - * Verify that the LABEL_BAD Wifi usability stats are not saved if screen state is off. - * @throws Exception - */ - @Test - public void verifyLabelBadStatsAreNotSavedIfScreenIsOff() throws Exception { - mWifiMetrics.setScreenState(false); - WifiInfo info = mock(WifiInfo.class); - when(info.getRssi()).thenReturn(nextRandInt()); - when(info.getLinkSpeed()).thenReturn(nextRandInt()); - WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats()); - mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1); - - // Add 1 LABEL_GOOD - WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1)); - // IP reachability lost occurs - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1); - // Wifi data stall occurs - mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD, - WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1); - // Firmware alert occurs - mWifiMetrics.logFirmwareAlert(2); - - dumpProtoAndDeserialize(); - assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length); - } - - /** - * Test the logging of connection duration stats - */ - @Test - public void testConnectionDurationStats() throws Exception { - for (int i = 0; i < 2; i++) { - mWifiMetrics.incrementConnectionDuration(5000, false, true); - mWifiMetrics.incrementConnectionDuration(3000, true, true); - mWifiMetrics.incrementConnectionDuration(1000, false, false); - mWifiMetrics.incrementConnectionDuration(500, true, false); - } - dumpProtoAndDeserialize(); - - assertEquals(6000, - mDecodedProto.connectionDurationStats.totalTimeSufficientThroughputMs); - assertEquals(10000, - mDecodedProto.connectionDurationStats.totalTimeInsufficientThroughputMs); - assertEquals(3000, - mDecodedProto.connectionDurationStats.totalTimeCellularDataOffMs); - } - - /** - * Test the logging of isExternalWifiScorerOn - */ - @Test - public void testIsExternalWifiScorerOn() throws Exception { - mWifiMetrics.setIsExternalWifiScorerOn(true); - dumpProtoAndDeserialize(); - assertEquals(true, mDecodedProto.isExternalWifiScorerOn); - } - - /* - * Test the logging of Wi-Fi off - */ - @Test - public void testWifiOff() throws Exception { - // if not deferred, timeout and duration should be ignored. - mWifiMetrics.noteWifiOff(false, false, 0); - mWifiMetrics.noteWifiOff(false, true, 999); - - // deferred, not timed out - mWifiMetrics.noteWifiOff(true, false, 0); - mWifiMetrics.noteWifiOff(true, false, 1000); - - // deferred and timed out - mWifiMetrics.noteWifiOff(true, true, 2000); - mWifiMetrics.noteWifiOff(true, true, 2000); - mWifiMetrics.noteWifiOff(true, true, 4000); - - dumpProtoAndDeserialize(); - - assertEquals(7, - mDecodedProto.wifiOffMetrics.numWifiOff); - assertEquals(5, - mDecodedProto.wifiOffMetrics.numWifiOffDeferring); - assertEquals(3, - mDecodedProto.wifiOffMetrics.numWifiOffDeferringTimeout); - - Int32Count[] expectedHistogram = { - buildInt32Count(0, 1), - buildInt32Count(1000, 1), - buildInt32Count(2000, 2), - buildInt32Count(4000, 1), - }; - assertKeyCountsEqual(expectedHistogram, - mDecodedProto.wifiOffMetrics.wifiOffDeferringTimeHistogram); - } - - /* - * Test the logging of Wi-Fi off - */ - @Test - public void testSoftApConfigLimitationMetrics() throws Exception { - SoftApConfiguration originalConfig = new SoftApConfiguration.Builder() - .setSsid("TestSSID").build(); - SoftApConfiguration needToResetCongig = new SoftApConfiguration.Builder(originalConfig) - .setPassphrase("TestPassphreas", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) - .setClientControlByUserEnabled(true) - .setMaxNumberOfClients(10) - .build(); - mWifiMetrics.noteSoftApConfigReset(originalConfig, needToResetCongig); - - mWifiMetrics.noteSoftApClientBlocked(5); - mWifiMetrics.noteSoftApClientBlocked(5); - mWifiMetrics.noteSoftApClientBlocked(5); - mWifiMetrics.noteSoftApClientBlocked(8); - - dumpProtoAndDeserialize(); - - assertEquals(1, - mDecodedProto.softApConfigLimitationMetrics.numSecurityTypeResetToDefault); - assertEquals(1, - mDecodedProto.softApConfigLimitationMetrics.numMaxClientSettingResetToDefault); - assertEquals(1, - mDecodedProto.softApConfigLimitationMetrics.numClientControlByUserResetToDefault); - - Int32Count[] expectedHistogram = { - buildInt32Count(5, 3), - buildInt32Count(8, 1), - }; - assertKeyCountsEqual(expectedHistogram, - mDecodedProto.softApConfigLimitationMetrics.maxClientSettingWhenReachHistogram); - } - - /** - * Test the logging of channel utilization - */ - @Test - public void testChannelUtilization() throws Exception { - mWifiMetrics.incrementChannelUtilizationCount(180, 2412); - mWifiMetrics.incrementChannelUtilizationCount(150, 2412); - mWifiMetrics.incrementChannelUtilizationCount(230, 2412); - mWifiMetrics.incrementChannelUtilizationCount(20, 5510); - mWifiMetrics.incrementChannelUtilizationCount(50, 5510); - - dumpProtoAndDeserialize(); - - HistogramBucketInt32[] expected2GHistogram = { - buildHistogramBucketInt32(150, 175, 1), - buildHistogramBucketInt32(175, 200, 1), - buildHistogramBucketInt32(225, Integer.MAX_VALUE, 1), - }; - - HistogramBucketInt32[] expectedAbove2GHistogram = { - buildHistogramBucketInt32(Integer.MIN_VALUE, 25, 1), - buildHistogramBucketInt32(50, 75, 1), - }; - - assertHistogramBucketsEqual(expected2GHistogram, - mDecodedProto.channelUtilizationHistogram.utilization2G); - assertHistogramBucketsEqual(expectedAbove2GHistogram, - mDecodedProto.channelUtilizationHistogram.utilizationAbove2G); - } - - /** - * Test the logging of Tx and Rx throughput - */ - @Test - public void testThroughput() throws Exception { - mWifiMetrics.incrementThroughputKbpsCount(500, 800, 2412); - mWifiMetrics.incrementThroughputKbpsCount(5_000, 4_000, 2412); - mWifiMetrics.incrementThroughputKbpsCount(54_000, 48_000, 2412); - mWifiMetrics.incrementThroughputKbpsCount(50_000, 49_000, 5510); - mWifiMetrics.incrementThroughputKbpsCount(801_000, 790_000, 5510); - mWifiMetrics.incrementThroughputKbpsCount(1100_000, 1200_000, 5510); - mWifiMetrics.incrementThroughputKbpsCount(1599_000, 1800_000, 6120); - dumpProtoAndDeserialize(); - - HistogramBucketInt32[] expectedTx2GHistogramMbps = { - buildHistogramBucketInt32(Integer.MIN_VALUE, 1, 1), - buildHistogramBucketInt32(5, 10, 1), - buildHistogramBucketInt32(50, 100, 1), - }; - - HistogramBucketInt32[] expectedRx2GHistogramMbps = { - buildHistogramBucketInt32(Integer.MIN_VALUE, 1, 1), - buildHistogramBucketInt32(1, 5, 1), - buildHistogramBucketInt32(25, 50, 1), - }; - - HistogramBucketInt32[] expectedTxAbove2GHistogramMbps = { - buildHistogramBucketInt32(50, 100, 1), - buildHistogramBucketInt32(800, 1200, 2), - buildHistogramBucketInt32(1200, 1600, 1), - }; - - HistogramBucketInt32[] expectedRxAbove2GHistogramMbps = { - buildHistogramBucketInt32(25, 50, 1), - buildHistogramBucketInt32(600, 800, 1), - buildHistogramBucketInt32(1200, 1600, 1), - buildHistogramBucketInt32(1600, Integer.MAX_VALUE, 1), - }; - - assertHistogramBucketsEqual(expectedTx2GHistogramMbps, - mDecodedProto.throughputMbpsHistogram.tx2G); - assertHistogramBucketsEqual(expectedTxAbove2GHistogramMbps, - mDecodedProto.throughputMbpsHistogram.txAbove2G); - assertHistogramBucketsEqual(expectedRx2GHistogramMbps, - mDecodedProto.throughputMbpsHistogram.rx2G); - assertHistogramBucketsEqual(expectedRxAbove2GHistogramMbps, - mDecodedProto.throughputMbpsHistogram.rxAbove2G); - } - - /** - * Test the Initial partial scan statistics - */ - @Test - public void testInitPartialScan() throws Exception { - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.reportInitialPartialScan(4, true); - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.reportInitialPartialScan(2, false); - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.reportInitialPartialScan(1, false); - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.reportInitialPartialScan(7, true); - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.reportInitialPartialScan(15, false); - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.reportInitialPartialScan(2, true); - mWifiMetrics.incrementInitialPartialScanCount(); - mWifiMetrics.reportInitialPartialScan(10, true); - - dumpProtoAndDeserialize(); - - assertEquals(9, mDecodedProto.initPartialScanStats.numScans); - assertEquals(4, mDecodedProto.initPartialScanStats.numSuccessScans); - assertEquals(3, mDecodedProto.initPartialScanStats.numFailureScans); - - HistogramBucketInt32[] expectedSuccessScanHistogram = { - buildHistogramBucketInt32(1, 3, 1), - buildHistogramBucketInt32(3, 5, 1), - buildHistogramBucketInt32(5, 10, 1), - buildHistogramBucketInt32(10, Integer.MAX_VALUE, 1), - }; - - HistogramBucketInt32[] expectedFailureScanHistogram = { - buildHistogramBucketInt32(1, 3, 2), - buildHistogramBucketInt32(10, Integer.MAX_VALUE, 1), - }; - - assertHistogramBucketsEqual(expectedSuccessScanHistogram, - mDecodedProto.initPartialScanStats.successfulScanChannelCountHistogram); - - assertHistogramBucketsEqual(expectedFailureScanHistogram, - mDecodedProto.initPartialScanStats.failedScanChannelCountHistogram); - } - - /** - * Test overlapping and non-overlapping connection events return overlapping duration correctly - */ - @Test - public void testOverlappingConnectionEvent() throws Exception { - // Connection event 1 - when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0); - mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); - when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 1000); - // Connection event 2 overlaps with 1 - assertEquals(1000, mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE)); - - // Connection event 2 ends - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 2000); - // Connection event 3 doesn't overlap with 2 - assertEquals(0, mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork", - WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE)); - } - - @Test - public void testCarrierWifiConnectionEvent() throws Exception { - mWifiMetrics.incrementNumOfCarrierWifiConnectionSuccess(); - for (int i = 0; i < 2; i++) { - mWifiMetrics.incrementNumOfCarrierWifiConnectionAuthFailure(); - } - for (int i = 0; i < 3; i++) { - mWifiMetrics.incrementNumOfCarrierWifiConnectionNonAuthFailure(); - } - - dumpProtoAndDeserialize(); - - assertEquals(1, mDecodedProto.carrierWifiMetrics.numConnectionSuccess); - assertEquals(2, mDecodedProto.carrierWifiMetrics.numConnectionAuthFailure); - assertEquals(3, mDecodedProto.carrierWifiMetrics.numConnectionNonAuthFailure); - } - - /** - * Verify the ConnectionEvent is labeled with networkType Passpoint correctly and that the OSU - * provisioned flag is set to true. - */ - @Test - public void testConnectionNetworkTypePasspointFromOsu() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork(); - config.updateIdentifier = "7"; - mWifiMetrics.startConnectionEvent(config, "RED", - WifiMetricsProto.ConnectionEvent.ROAM_NONE); - mWifiMetrics.endConnectionEvent( - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); - dumpProtoAndDeserialize(); - - assertEquals(1, mDecodedProto.connectionEvent.length); - assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT, - mDecodedProto.connectionEvent[0].networkType); - assertTrue(mDecodedProto.connectionEvent[0].isOsuProvisioned); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTestUtil.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTestUtil.java deleted file mode 100644 index 2be553840..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTestUtil.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static org.junit.Assert.assertEquals; - -import android.net.wifi.WifiManager; - -import com.android.server.wifi.proto.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HistogramBucketInt32; -import com.android.server.wifi.proto.nano.WifiMetricsProto.Int32Count; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts; -import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount; -import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; - -import java.util.Arrays; -import java.util.Comparator; - -/** - * Utility functions for {@link WifiMetricsTest}. - */ -public class WifiMetricsTestUtil { - - /** - * Asserts that the two arrays are equal, reporting any difference between them. - * Note: The order of buckets in each array must match! - */ - public static void assertHistogramBucketsEqual(HistogramBucketInt32[] expected, - HistogramBucketInt32[] actual) { - assertEquals("Number of buckets do not match!", expected.length, actual.length); - - for (int i = 0; i < expected.length; i++) { - HistogramBucketInt32 expectedBucket = expected[i]; - HistogramBucketInt32 actualBucket = actual[i]; - - assertEquals(String.format("Bucket[%d].start does not match!", i), - expectedBucket.start, actualBucket.start); - assertEquals(String.format("Bucket[%d].end does not match!", i), - expectedBucket.end, actualBucket.end); - assertEquals(String.format("Bucket[%d].count does not match!", i), - expectedBucket.count, actualBucket.count); - } - } - - /** - * The constructor we wish HistogramBucketInt32 had. - */ - public static HistogramBucketInt32 buildHistogramBucketInt32(int start, int end, int count) { - HistogramBucketInt32 bucket = new HistogramBucketInt32(); - bucket.start = start; - bucket.end = end; - bucket.count = count; - return bucket; - } - - /** - * Asserts that the two arrays are equal, reporting any difference between them. - * Note: The order of key counts in each array must match! - */ - public static void assertKeyCountsEqual(Int32Count[] expected, Int32Count[] actual) { - assertEquals("Number of key counts do not match!", expected.length, actual.length); - - for (int i = 0; i < expected.length; i++) { - Int32Count expectedKeyCount = expected[i]; - Int32Count actualKeyCount = actual[i]; - - assertEquals(String.format("KeyCount[%d].key does not match!", i), - expectedKeyCount.key, actualKeyCount.key); - assertEquals(String.format("KeyCount[%d].count does not match!", i), - expectedKeyCount.count, actualKeyCount.count); - } - } - - /** - * The constructor we wish Int32Count had. - */ - public static Int32Count buildInt32Count(int key, int count) { - Int32Count keyCount = new Int32Count(); - keyCount.key = key; - keyCount.count = count; - return keyCount; - } - - /** - * Asserts that the two arrays are equal (ignoring order), - * reporting any difference between them. - */ - public static void assertLinkProbeFailureReasonCountsEqual( - LinkProbeFailureReasonCount[] expected, LinkProbeFailureReasonCount[] actual) { - assertEquals("Number of LinkProbeFailureReasonCounts do not match!", - expected.length, actual.length); - - Arrays.sort(expected, Comparator.comparingInt(x -> x.failureReason)); - Arrays.sort(actual, Comparator.comparingInt(x -> x.failureReason)); - - for (int i = 0; i < expected.length; i++) { - LinkProbeFailureReasonCount expectedFailureReasonCount = expected[i]; - LinkProbeFailureReasonCount actualFailureReasonCount = actual[i]; - - assertEquals(String.format( - "LinkProbeFailureReasonCount[%d].failureReason does not match!", i), - expectedFailureReasonCount.failureReason, - actualFailureReasonCount.failureReason); - assertEquals(String.format("LinkProbeFailureReasonCount[%d].count does not match!", i), - expectedFailureReasonCount.count, actualFailureReasonCount.count); - } - } - - /** - * The constructor we wish LinkProbeFailureReasonCount had. - */ - public static LinkProbeFailureReasonCount buildLinkProbeFailureReasonCount(int failureReason, - int count) { - LinkProbeFailureReasonCount failureReasonCount = new LinkProbeFailureReasonCount(); - failureReasonCount.failureReason = failureReason; - failureReasonCount.count = count; - return failureReasonCount; - } - - /** - * The constructor we wish DeviceMobilityStatePnoScanStats had. - */ - public static DeviceMobilityStatePnoScanStats buildDeviceMobilityStatePnoScanStats( - @WifiManager.DeviceMobilityState int deviceMobilityState, int numTimesEnteredState, - long totalDurationMs, long pnoDurationMs) { - DeviceMobilityStatePnoScanStats stats = new DeviceMobilityStatePnoScanStats(); - stats.deviceMobilityState = deviceMobilityState; - stats.numTimesEnteredState = numTimesEnteredState; - stats.totalDurationMs = totalDurationMs; - stats.pnoDurationMs = pnoDurationMs; - return stats; - } - - /** - * Asserts that the two arrays are equal (ignoring order), - * reporting any difference between them. - */ - public static void assertDeviceMobilityStatePnoScanStatsEqual( - DeviceMobilityStatePnoScanStats[] expected, DeviceMobilityStatePnoScanStats[] actual) { - - assertEquals("Number of DeviceMobilityStatePnoScanStats do not match!", - expected.length, actual.length); - - Arrays.sort(expected, Comparator.comparingInt(x -> x.deviceMobilityState)); - Arrays.sort(actual, Comparator.comparingInt(x -> x.deviceMobilityState)); - - for (int i = 0; i < expected.length; i++) { - DeviceMobilityStatePnoScanStats expectedStats = expected[i]; - DeviceMobilityStatePnoScanStats actualStats = actual[i]; - - assertEquals(String.format( - "DeviceMobilityStatePnoScanStats[%d].deviceMobilityState does not match!", i), - expectedStats.deviceMobilityState, actualStats.deviceMobilityState); - assertEquals(String.format( - "DeviceMobilityStatePnoScanStats[%d].numTimesEnteredState does not match!", i), - expectedStats.numTimesEnteredState, actualStats.numTimesEnteredState); - assertEquals(String.format( - "DeviceMobilityStatePnoScanStats[%d].totalDurationMs does not match!", i), - expectedStats.totalDurationMs, actualStats.totalDurationMs); - assertEquals(String.format( - "DeviceMobilityStatePnoScanStats[%d].pnoDurationMs does not match!", i), - expectedStats.pnoDurationMs, actualStats.pnoDurationMs); - } - } - - /** - * Creates a StaEvent of type TYPE_LINK_PROBE that was successful. - */ - public static StaEvent buildLinkProbeSuccessStaEvent(int elapsedTimeMs) { - StaEvent probe = new StaEvent(); - probe.type = StaEvent.TYPE_LINK_PROBE; - probe.linkProbeWasSuccess = true; - probe.linkProbeSuccessElapsedTimeMs = elapsedTimeMs; - return probe; - } - - /** - * Creates a StaEvent of type TYPE_LINK_PROBE that failed. - */ - public static StaEvent buildLinkProbeFailureStaEvent(int reason) { - StaEvent probe = new StaEvent(); - probe.type = StaEvent.TYPE_LINK_PROBE; - probe.linkProbeWasSuccess = false; - probe.linkProbeFailureReason = reason; - return probe; - } - - /** - * Asserts that the two arrays are equal, reporting any difference between them. - * Note that the order must match. - */ - public static void assertLinkProbeStaEventsEqual(StaEvent[] expected, StaEvent[] actual) { - assertEquals("Number of StaEvents do not match!", expected.length, actual.length); - - for (int i = 0; i < expected.length; i++) { - StaEvent expectedEvent = expected[i]; - StaEvent actualEvent = actual[i]; - - assertEquals(String.format("expected StaEvent[%d].type != TYPE_LINK_PROBE", i), - StaEvent.TYPE_LINK_PROBE, expectedEvent.type); - assertEquals(String.format("actual StaEvent[%d].type != TYPE_LINK_PROBE", i), - StaEvent.TYPE_LINK_PROBE, actualEvent.type); - assertEquals(String.format("StaEvent[%d].linkProbeWasSuccess does not match!", i), - expectedEvent.linkProbeWasSuccess, actualEvent.linkProbeWasSuccess); - if (expectedEvent.linkProbeWasSuccess) { - assertEquals(String.format( - "StaEvent[%d].linkProbeSuccessElapsedTimeMs does not match!", i), - expectedEvent.linkProbeSuccessElapsedTimeMs, - actualEvent.linkProbeSuccessElapsedTimeMs); - } else { - assertEquals(String.format( - "StaEvent[%d].linkProbeFailureReason does not match!", i), - expectedEvent.linkProbeFailureReason, actualEvent.linkProbeFailureReason); - } - } - } - - /** - * The constructor we wish ExperimentProbeCounts had. - */ - public static ExperimentProbeCounts buildExperimentProbeCounts( - String experimentId, int probeCount) { - ExperimentProbeCounts counts = new ExperimentProbeCounts(); - counts.experimentId = experimentId; - counts.probeCount = probeCount; - return counts; - } - - /** - * Asserts that the two arrays are equal (ignoring order), - * reporting any difference between them. - */ - public static void assertExperimentProbeCountsEqual( - ExperimentProbeCounts[] expected, ExperimentProbeCounts[] actual) { - - assertEquals("Number of ExperimentProbeCounts do not match!", - expected.length, actual.length); - - Arrays.sort(expected, Comparator.comparing(x -> x.experimentId)); - Arrays.sort(actual, Comparator.comparing(x -> x.experimentId)); - - for (int i = 0; i < expected.length; i++) { - ExperimentProbeCounts expectedCounts = expected[i]; - ExperimentProbeCounts actualCounts = actual[i]; - - assertEquals(String.format( - "ExperimentProbeCounts[%d].experimentId does not match!", i), - expectedCounts.experimentId, actualCounts.experimentId); - assertEquals(String.format( - "ExperimentProbeCounts[%d].probeCount does not match!", i), - expectedCounts.probeCount, actualCounts.probeCount); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java deleted file mode 100644 index c4acd73c2..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback.WpsConfigError; -import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback.WpsErrorIndication; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.Message; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.MboOceController.BtmFrameData; -import com.android.server.wifi.hotspot2.AnqpEvent; -import com.android.server.wifi.hotspot2.IconEvent; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -/** - * Unit tests for {@link com.android.server.wifi.WifiMonitor}. - */ -@SmallTest -public class WifiMonitorTest extends WifiBaseTest { - private static final String WLAN_IFACE_NAME = "wlan0"; - private static final String SECOND_WLAN_IFACE_NAME = "wlan1"; - private static final String[] GSM_AUTH_DATA = { "45adbc", "fead45", "0x3452"}; - private static final String[] UMTS_AUTH_DATA = { "fead45", "0x3452"}; - private static final String BSSID = "fe:45:23:12:12:0a"; - private static final int NETWORK_ID = 5; - private static final String SSID = "\"test124\""; - private WifiMonitor mWifiMonitor; - private TestLooper mLooper; - private Handler mHandlerSpy; - private Handler mSecondHandlerSpy; - - @Before - public void setUp() throws Exception { - mWifiMonitor = new WifiMonitor(mock(WifiInjector.class)); - mLooper = new TestLooper(); - mHandlerSpy = spy(new Handler(mLooper.getLooper())); - mSecondHandlerSpy = spy(new Handler(mLooper.getLooper())); - mWifiMonitor.setMonitoring(WLAN_IFACE_NAME, true); - } - - /** - * Broadcast WPS failure event test. - */ - @Test - public void testBroadcastWpsEventFailDueToErrorTkipOnlyProhibhited() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_FAIL_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsFailEvent( - WLAN_IFACE_NAME, WpsConfigError.NO_ERROR, - WpsErrorIndication.SECURITY_TKIP_ONLY_PROHIBITED); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_FAIL_EVENT, messageCaptor.getValue().what); - assertEquals(WifiManager.WPS_TKIP_ONLY_PROHIBITED, messageCaptor.getValue().arg1); - } - - /** - * Broadcast WPS failure event test. - */ - @Test - public void testBroadcastWpsEventFailDueToErrorWepProhibhited() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_FAIL_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsFailEvent( - WLAN_IFACE_NAME, WpsConfigError.NO_ERROR, - WpsErrorIndication.SECURITY_WEP_PROHIBITED); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_FAIL_EVENT, messageCaptor.getValue().what); - assertEquals(WifiManager.WPS_WEP_PROHIBITED, messageCaptor.getValue().arg1); - } - - /** - * Broadcast WPS failure event test. - */ - @Test - public void testBroadcastWpsEventFailDueToConfigAuthError() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_FAIL_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsFailEvent( - WLAN_IFACE_NAME, WpsConfigError.DEV_PASSWORD_AUTH_FAILURE, - WpsErrorIndication.NO_ERROR); - - mLooper.dispatchAll(); - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_FAIL_EVENT, messageCaptor.getValue().what); - assertEquals(WifiManager.WPS_AUTH_FAILURE, messageCaptor.getValue().arg1); - } - - /** - * Broadcast WPS failure event test. - */ - @Test - public void testBroadcastWpsEventFailDueToConfigPbcOverlapError() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_FAIL_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsFailEvent( - WLAN_IFACE_NAME, WpsConfigError.MULTIPLE_PBC_DETECTED, - WpsErrorIndication.NO_ERROR); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_FAIL_EVENT, messageCaptor.getValue().what); - assertEquals(WifiManager.WPS_OVERLAP_ERROR, messageCaptor.getValue().arg1); - } - - /** - * Broadcast WPS failure event test. - */ - @Test - public void testBroadcastWpsEventFailDueToConfigError() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_FAIL_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsFailEvent( - WLAN_IFACE_NAME, WpsConfigError.MSG_TIMEOUT, - WpsErrorIndication.NO_ERROR); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_FAIL_EVENT, messageCaptor.getValue().what); - assertEquals(WifiManager.ERROR, messageCaptor.getValue().arg1); - assertEquals(WpsConfigError.MSG_TIMEOUT, messageCaptor.getValue().arg2); - } - - /** - * Broadcast WPS success event test. - */ - @Test - public void testBroadcastWpsEventSuccess() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_SUCCESS_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsSuccessEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_SUCCESS_EVENT, messageCaptor.getValue().what); - } - - /** - * Broadcast WPS overlap event test. - */ - @Test - public void testBroadcastWpsEventOverlap() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_OVERLAP_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsOverlapEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_OVERLAP_EVENT, messageCaptor.getValue().what); - } - - /** - * Broadcast WPS timeout event test. - */ - @Test - public void testBroadcastWpsEventTimeout() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_TIMEOUT_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsTimeoutEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_TIMEOUT_EVENT, messageCaptor.getValue().what); - } - - /** - * Broadcast ANQP done event test. - */ - @Test - public void testBroadcastAnqpDoneEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.ANQP_DONE_EVENT, mHandlerSpy); - long bssid = 5; - mWifiMonitor.broadcastAnqpDoneEvent(WLAN_IFACE_NAME, new AnqpEvent(bssid, null)); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.ANQP_DONE_EVENT, messageCaptor.getValue().what); - assertEquals(bssid, ((AnqpEvent) messageCaptor.getValue().obj).getBssid()); - assertNull(((AnqpEvent) messageCaptor.getValue().obj).getElements()); - } - - /** - * Broadcast Icon event test. - */ - @Test - public void testBroadcastIconDoneEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.RX_HS20_ANQP_ICON_EVENT, mHandlerSpy); - long bssid = 5; - String fileName = "test"; - int fileSize = 0; - mWifiMonitor.broadcastIconDoneEvent( - WLAN_IFACE_NAME, new IconEvent(bssid, fileName, fileSize, null)); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.RX_HS20_ANQP_ICON_EVENT, messageCaptor.getValue().what); - assertEquals(bssid, ((IconEvent) messageCaptor.getValue().obj).getBSSID()); - assertEquals(fileName, ((IconEvent) messageCaptor.getValue().obj).getFileName()); - assertEquals(fileSize, ((IconEvent) messageCaptor.getValue().obj).getSize()); - assertNull(((IconEvent) messageCaptor.getValue().obj).getData()); - } - - /** - * Broadcast network Gsm auth request test. - */ - @Test - public void testBroadcastNetworkGsmAuthRequestEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUP_REQUEST_SIM_AUTH, mHandlerSpy); - int networkId = NETWORK_ID; - String ssid = SSID; - String[] data = GSM_AUTH_DATA; - mWifiMonitor.broadcastNetworkGsmAuthRequestEvent(WLAN_IFACE_NAME, networkId, ssid, data); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUP_REQUEST_SIM_AUTH, messageCaptor.getValue().what); - WifiCarrierInfoManager.SimAuthRequestData authData = - (WifiCarrierInfoManager.SimAuthRequestData) messageCaptor.getValue().obj; - assertEquals(networkId, authData.networkId); - assertEquals(ssid, authData.ssid); - assertEquals(WifiEnterpriseConfig.Eap.SIM, authData.protocol); - assertArrayEquals(data, authData.data); - } - - /** - * Broadcast network Umts auth request test. - */ - @Test - public void testBroadcastNetworkUmtsAuthRequestEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUP_REQUEST_SIM_AUTH, mHandlerSpy); - int networkId = NETWORK_ID; - String ssid = SSID; - String[] data = UMTS_AUTH_DATA; - mWifiMonitor.broadcastNetworkUmtsAuthRequestEvent(WLAN_IFACE_NAME, networkId, ssid, data); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUP_REQUEST_SIM_AUTH, messageCaptor.getValue().what); - WifiCarrierInfoManager.SimAuthRequestData authData = - (WifiCarrierInfoManager.SimAuthRequestData) messageCaptor.getValue().obj; - assertEquals(networkId, authData.networkId); - assertEquals(ssid, authData.ssid); - assertEquals(WifiEnterpriseConfig.Eap.AKA, authData.protocol); - assertArrayEquals(data, authData.data); - } - - /** - * Broadcast pno scan results event test. - */ - @Test - public void testBroadcastPnoScanResultsEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.PNO_SCAN_RESULTS_EVENT, mHandlerSpy); - mWifiMonitor.broadcastPnoScanResultEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.PNO_SCAN_RESULTS_EVENT, messageCaptor.getValue().what); - } - - /** - * Broadcast Scan results event test. - */ - @Test - public void testBroadcastScanResultsEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SCAN_RESULTS_EVENT, mHandlerSpy); - mWifiMonitor.broadcastScanResultEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SCAN_RESULTS_EVENT, messageCaptor.getValue().what); - } - - /** - * Broadcast Scan failed event test. - */ - @Test - public void testBroadcastScanFailedEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SCAN_FAILED_EVENT, mHandlerSpy); - mWifiMonitor.broadcastScanFailedEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - - assertEquals(WifiMonitor.SCAN_FAILED_EVENT, messageCaptor.getValue().what); - } - - /** - * Broadcast authentication failure test. - */ - @Test - public void testBroadcastAuthenticationFailureEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, mHandlerSpy); - int reason = WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD; - mWifiMonitor.broadcastAuthenticationFailureEvent(WLAN_IFACE_NAME, reason, -1); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, messageCaptor.getValue().what); - assertEquals(reason, messageCaptor.getValue().arg1); - } - - /** - * Broadcast authentication failure test (EAP Error). - */ - @Test - public void testBroadcastAuthenticationFailureEapErrorEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, mHandlerSpy); - int reason = WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE; - int errorCode = WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED; - mWifiMonitor.broadcastAuthenticationFailureEvent(WLAN_IFACE_NAME, reason, errorCode); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, messageCaptor.getValue().what); - assertEquals(reason, messageCaptor.getValue().arg1); - assertEquals(errorCode, messageCaptor.getValue().arg2); - } - - /** - * Broadcast association rejection test. - */ - @Test - public void testBroadcastAssociationRejectionEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.ASSOCIATION_REJECTION_EVENT, mHandlerSpy); - int status = 5; - String bssid = BSSID; - mWifiMonitor.broadcastAssociationRejectionEvent(WLAN_IFACE_NAME, status, false, bssid); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.ASSOCIATION_REJECTION_EVENT, messageCaptor.getValue().what); - assertEquals(0, messageCaptor.getValue().arg1); - assertEquals(status, messageCaptor.getValue().arg2); - assertEquals(bssid, (String) messageCaptor.getValue().obj); - } - - /** - * Broadcast associated bssid test. - */ - @Test - public void testBroadcastAssociatedBssidEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.ASSOCIATED_BSSID_EVENT, mHandlerSpy); - String bssid = BSSID; - mWifiMonitor.broadcastAssociatedBssidEvent(WLAN_IFACE_NAME, bssid); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.ASSOCIATED_BSSID_EVENT, messageCaptor.getValue().what); - assertEquals(bssid, (String) messageCaptor.getValue().obj); - } - - /** - * Broadcast network connection test. - */ - @Test - public void testBroadcastNetworkConnectionEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.NETWORK_CONNECTION_EVENT, mHandlerSpy); - int networkId = NETWORK_ID; - String bssid = BSSID; - mWifiMonitor.broadcastNetworkConnectionEvent(WLAN_IFACE_NAME, networkId, false, bssid); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.NETWORK_CONNECTION_EVENT, messageCaptor.getValue().what); - assertEquals(networkId, messageCaptor.getValue().arg1); - assertEquals(0, messageCaptor.getValue().arg2); - assertEquals(bssid, (String) messageCaptor.getValue().obj); - } - - /** - * Broadcast network disconnection test. - */ - @Test - public void testBroadcastNetworkDisconnectionEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.NETWORK_DISCONNECTION_EVENT, mHandlerSpy); - int local = 1; - int reason = 5; - String bssid = BSSID; - mWifiMonitor.broadcastNetworkDisconnectionEvent(WLAN_IFACE_NAME, local, reason, bssid); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.NETWORK_DISCONNECTION_EVENT, messageCaptor.getValue().what); - assertEquals(local, messageCaptor.getValue().arg1); - assertEquals(reason, messageCaptor.getValue().arg2); - assertEquals(bssid, (String) messageCaptor.getValue().obj); - } - - /** - * Broadcast supplicant state change test. - */ - @Test - public void testBroadcastSupplicantStateChangeEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, mHandlerSpy); - int networkId = NETWORK_ID; - WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(SSID); - String bssid = BSSID; - SupplicantState newState = SupplicantState.ASSOCIATED; - mWifiMonitor.broadcastSupplicantStateChangeEvent( - WLAN_IFACE_NAME, networkId, wifiSsid, bssid, newState); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, messageCaptor.getValue().what); - StateChangeResult result = (StateChangeResult) messageCaptor.getValue().obj; - assertEquals(networkId, result.networkId); - assertEquals(wifiSsid, result.wifiSsid); - assertEquals(bssid, result.BSSID); - assertEquals(newState, result.state); - } - - /** - * Broadcast supplicant connection test. - */ - @Test - public void testBroadcastSupplicantConnectionEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUP_CONNECTION_EVENT, mHandlerSpy); - mWifiMonitor.broadcastSupplicantConnectionEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUP_CONNECTION_EVENT, messageCaptor.getValue().what); - } - /** - * Broadcast supplicant disconnection test. - */ - @Test - public void testBroadcastSupplicantDisconnectionEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUP_DISCONNECTION_EVENT, mHandlerSpy); - mWifiMonitor.broadcastSupplicantDisconnectionEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUP_DISCONNECTION_EVENT, messageCaptor.getValue().what); - } - /** - * Broadcast message to two handlers test. - */ - @Test - public void testBroadcastEventToTwoHandlers() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUP_CONNECTION_EVENT, mHandlerSpy); - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUP_CONNECTION_EVENT, mSecondHandlerSpy); - mWifiMonitor.broadcastSupplicantConnectionEvent(WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUP_CONNECTION_EVENT, messageCaptor.getValue().what); - verify(mSecondHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUP_CONNECTION_EVENT, messageCaptor.getValue().what); - } - /** - * Broadcast message when iface is null. - */ - @Test - public void testBroadcastEventWhenIfaceIsNull() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUP_DISCONNECTION_EVENT, mHandlerSpy); - mWifiMonitor.broadcastSupplicantDisconnectionEvent(null); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUP_DISCONNECTION_EVENT, messageCaptor.getValue().what); - } - /** - * Broadcast message when iface handler is null. - */ - @Test - public void testBroadcastEventWhenIfaceHandlerIsNull() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.SUP_DISCONNECTION_EVENT, mHandlerSpy); - mWifiMonitor.broadcastSupplicantDisconnectionEvent(SECOND_WLAN_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.SUP_DISCONNECTION_EVENT, messageCaptor.getValue().what); - } - - @Test - public void testDeregisterHandlerNotCrash() { - mWifiMonitor.deregisterHandler(null, 0, null); - } - - /** - * Register a handler, send an event and then verify that the event is handled. - * Unregister the handler, send an event and then verify the event is not handled. - */ - @Test - public void testDeregisterHandlerRemovesHandler() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_FAIL_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsFailEvent( - WLAN_IFACE_NAME, WpsConfigError.NO_ERROR, - WpsErrorIndication.SECURITY_TKIP_ONLY_PROHIBITED); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy, times(1)).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.WPS_FAIL_EVENT, messageCaptor.getValue().what); - assertEquals(WifiManager.WPS_TKIP_ONLY_PROHIBITED, messageCaptor.getValue().arg1); - mWifiMonitor.deregisterHandler( - WLAN_IFACE_NAME, WifiMonitor.WPS_FAIL_EVENT, mHandlerSpy); - mWifiMonitor.broadcastWpsFailEvent( - WLAN_IFACE_NAME, WpsConfigError.NO_ERROR, - WpsErrorIndication.SECURITY_TKIP_ONLY_PROHIBITED); - mLooper.dispatchAll(); - - verify(mHandlerSpy, times(1)).handleMessage(messageCaptor.capture()); - } - - /** - * Broadcast Bss transition request frame handling event test. - */ - @Test - public void testBroadcastBssTmHandlingDoneEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, mHandlerSpy); - mWifiMonitor.broadcastBssTmHandlingDoneEvent(WLAN_IFACE_NAME, new BtmFrameData()); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, messageCaptor.getValue().what); - } - - /** - * Broadcast fils network connection test. - */ - @Test - public void testBroadcastFilsNetworkConnectionEvent() { - mWifiMonitor.registerHandler( - WLAN_IFACE_NAME, WifiMonitor.NETWORK_CONNECTION_EVENT, mHandlerSpy); - int networkId = NETWORK_ID; - String bssid = BSSID; - mWifiMonitor.broadcastNetworkConnectionEvent(WLAN_IFACE_NAME, networkId, true, bssid); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiMonitor.NETWORK_CONNECTION_EVENT, messageCaptor.getValue().what); - assertEquals(networkId, messageCaptor.getValue().arg1); - assertEquals(1, messageCaptor.getValue().arg2); - assertEquals(bssid, (String) messageCaptor.getValue().obj); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java deleted file mode 100644 index f64016136..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.os.BatteryStatsManager; -import android.os.Binder; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.WorkSource; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.WifiConfigStoreData}. - */ -@SmallTest -public class WifiMulticastLockManagerTest extends WifiBaseTest { - private static final String WL_1_TAG = "Wakelock-1"; - private static final String WL_2_TAG = "Wakelock-2"; - - @Mock WifiMulticastLockManager.FilterController mHandler; - @Mock BatteryStatsManager mBatteryStats; - WifiMulticastLockManager mManager; - - /** - * Initialize |WifiMulticastLockManager| instance before each test. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mManager = new WifiMulticastLockManager(mHandler, mBatteryStats); - } - - /** - * Test behavior when no locks are held. - */ - @Test - public void noLocks() { - assertFalse(mManager.isMulticastEnabled()); - mManager.initializeFiltering(); - verify(mHandler, times(1)).startFilteringMulticastPackets(); - } - - /** - * Test behavior when one lock is aquired then released. - */ - @Test - public void oneLock() throws RemoteException { - IBinder binder = mock(IBinder.class); - mManager.acquireLock(binder, WL_1_TAG); - assertTrue(mManager.isMulticastEnabled()); - verify(mHandler).stopFilteringMulticastPackets(); - mManager.initializeFiltering(); - verify(mHandler, times(0)).startFilteringMulticastPackets(); - ArgumentCaptor<WorkSource> wsCaptor = ArgumentCaptor.forClass(WorkSource.class); - verify(mBatteryStats).reportWifiMulticastEnabled(wsCaptor.capture()); - assertNotNull(wsCaptor.getValue()); - assertEquals(Binder.getCallingUid(), wsCaptor.getValue().getAttributionUid()); - verify(mBatteryStats, times(0)).reportWifiMulticastDisabled(any()); - - mManager.releaseLock(WL_1_TAG); - verify(mBatteryStats).reportWifiMulticastDisabled(wsCaptor.capture()); - assertNotNull(wsCaptor.getValue()); - assertEquals(Binder.getCallingUid(), wsCaptor.getValue().getAttributionUid()); - assertFalse(mManager.isMulticastEnabled()); - } - - /** - * Test behavior when one lock is aquired then released with the wrong tag. - */ - @Test - public void oneLock_wrongName() throws RemoteException { - IBinder binder = mock(IBinder.class); - mManager.acquireLock(binder, WL_1_TAG); - assertTrue(mManager.isMulticastEnabled()); - verify(mHandler).stopFilteringMulticastPackets(); - mManager.initializeFiltering(); - verify(mHandler, never()).startFilteringMulticastPackets(); - verify(mBatteryStats).reportWifiMulticastEnabled(any()); - verify(mBatteryStats, never()).reportWifiMulticastDisabled(any()); - - mManager.releaseLock(WL_2_TAG); - verify(mBatteryStats, never()).reportWifiMulticastDisabled(any()); - assertTrue(mManager.isMulticastEnabled()); - } - - /** - * Test behavior when multiple locks are aquired then released in nesting order. - */ - @Test - public void multipleLocksInOrder() throws RemoteException { - IBinder binder = mock(IBinder.class); - - InOrder inOrderHandler = inOrder(mHandler); - InOrder inOrderBatteryStats = inOrder(mBatteryStats); - - mManager.acquireLock(binder, WL_1_TAG); - inOrderHandler.verify(mHandler).stopFilteringMulticastPackets(); - inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any()); - assertTrue(mManager.isMulticastEnabled()); - - mManager.acquireLock(binder, WL_2_TAG); - inOrderHandler.verify(mHandler).stopFilteringMulticastPackets(); - inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any()); - assertTrue(mManager.isMulticastEnabled()); - - mManager.initializeFiltering(); - inOrderHandler.verify(mHandler, never()).startFilteringMulticastPackets(); - - mManager.releaseLock(WL_2_TAG); - inOrderHandler.verify(mHandler, never()).startFilteringMulticastPackets(); - inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any()); - assertTrue(mManager.isMulticastEnabled()); - - mManager.releaseLock(WL_1_TAG); - inOrderHandler.verify(mHandler).startFilteringMulticastPackets(); - inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any()); - assertFalse(mManager.isMulticastEnabled()); - } - - /** - * Test behavior when multiple locks are aquired then released out of nesting order. - */ - @Test - public void multipleLocksOutOfOrder() throws RemoteException { - IBinder binder = mock(IBinder.class); - - InOrder inOrderHandler = inOrder(mHandler); - InOrder inOrderBatteryStats = inOrder(mBatteryStats); - - mManager.acquireLock(binder, WL_1_TAG); - inOrderHandler.verify(mHandler).stopFilteringMulticastPackets(); - inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any()); - assertTrue(mManager.isMulticastEnabled()); - - mManager.acquireLock(binder, WL_2_TAG); - inOrderHandler.verify(mHandler).stopFilteringMulticastPackets(); - inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any()); - assertTrue(mManager.isMulticastEnabled()); - - mManager.initializeFiltering(); - inOrderHandler.verify(mHandler, never()).startFilteringMulticastPackets(); - - mManager.releaseLock(WL_1_TAG); - inOrderHandler.verify(mHandler, never()).startFilteringMulticastPackets(); - inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any()); - assertTrue(mManager.isMulticastEnabled()); - - mManager.releaseLock(WL_2_TAG); - inOrderHandler.verify(mHandler).startFilteringMulticastPackets(); - inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any()); - assertFalse(mManager.isMulticastEnabled()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java deleted file mode 100644 index 7d76eacee..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java +++ /dev/null @@ -1,1566 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiScanner; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.os.Handler; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; -import com.android.server.wifi.WifiNative.SupplicantDeathEventHandler; -import com.android.server.wifi.WifiNative.VendorHalDeathEventHandler; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.NetdWrapper.NetdEventObserver; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Arrays; -import java.util.HashSet; - -/** - * Unit tests for the interface management operations in - * {@link com.android.server.wifi.WifiNative}. - */ -@SmallTest -public class WifiNativeInterfaceManagementTest extends WifiBaseTest { - private static final String IFACE_NAME_0 = "mockWlan0"; - private static final String IFACE_NAME_1 = "mockWlan1"; - - @Mock private WifiVendorHal mWifiVendorHal; - @Mock private WifiNl80211Manager mWificondControl; - @Mock private SupplicantStaIfaceHal mSupplicantStaIfaceHal; - @Mock private HostapdHal mHostapdHal; - @Mock private WifiMonitor mWifiMonitor; - @Mock private NetdWrapper mNetdWrapper; - @Mock private PropertyService mPropertyService; - @Mock private WifiMetrics mWifiMetrics; - @Mock private WifiInjector mWifiInjector; - - @Mock private WifiNative.StatusListener mStatusListener; - @Mock private WifiNative.InterfaceCallback mIfaceCallback0; - @Mock private WifiNative.InterfaceCallback mIfaceCallback1; - private TestLooper mLooper; - - private ArgumentCaptor<VendorHalDeathEventHandler> mWifiVendorHalDeathHandlerCaptor = - ArgumentCaptor.forClass(VendorHalDeathEventHandler.class); - private ArgumentCaptor<Runnable> mWificondDeathHandlerCaptor = - ArgumentCaptor.forClass(Runnable.class); - private ArgumentCaptor<WifiNative.VendorHalRadioModeChangeEventHandler> - mWifiVendorHalRadioModeChangeHandlerCaptor = - ArgumentCaptor.forClass(WifiNative.VendorHalRadioModeChangeEventHandler.class); - private ArgumentCaptor<SupplicantDeathEventHandler> mSupplicantDeathHandlerCaptor = - ArgumentCaptor.forClass(SupplicantDeathEventHandler.class); - private ArgumentCaptor<WifiNative.HostapdDeathEventHandler> mHostapdDeathHandlerCaptor = - ArgumentCaptor.forClass(WifiNative.HostapdDeathEventHandler.class); - private ArgumentCaptor<NetdEventObserver> mNetworkObserverCaptor0 = - ArgumentCaptor.forClass(NetdEventObserver.class); - private ArgumentCaptor<NetdEventObserver> mNetworkObserverCaptor1 = - ArgumentCaptor.forClass(NetdEventObserver.class); - private ArgumentCaptor<InterfaceDestroyedListener> mIfaceDestroyedListenerCaptor0 = - ArgumentCaptor.forClass(InterfaceDestroyedListener.class); - private ArgumentCaptor<InterfaceDestroyedListener> mIfaceDestroyedListenerCaptor1 = - ArgumentCaptor.forClass(InterfaceDestroyedListener.class); - private InOrder mInOrder; - - private WifiNative mWifiNative; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - - // Setup mocks for the positive single interface cases, individual tests can modify the - // mocks for negative or multi-interface tests. - when(mWifiVendorHal.initialize(mWifiVendorHalDeathHandlerCaptor.capture())) - .thenReturn(true); - doNothing().when(mWifiVendorHal).registerRadioModeChangeHandler( - mWifiVendorHalRadioModeChangeHandlerCaptor.capture()); - when(mWifiVendorHal.isVendorHalSupported()).thenReturn(true); - when(mWifiVendorHal.startVendorHal()).thenReturn(true); - when(mWifiVendorHal.createStaIface(any())).thenReturn(IFACE_NAME_0); - when(mWifiVendorHal.createApIface(any())).thenReturn(IFACE_NAME_0); - when(mWifiVendorHal.removeStaIface(any())).thenReturn(true); - when(mWifiVendorHal.removeApIface(any())).thenReturn(true); - - when(mWificondControl.setupInterfaceForClientMode(any(), any(), any(), any())).thenReturn( - true); - when(mWificondControl.setupInterfaceForSoftApMode(any())).thenReturn(true); - when(mWificondControl.tearDownClientInterface(any())).thenReturn(true); - when(mWificondControl.tearDownSoftApInterface(any())).thenReturn(true); - when(mWificondControl.tearDownInterfaces()).thenReturn(true); - when(mWificondControl.registerApCallback(any(), any(), any())).thenReturn(true); - - when(mSupplicantStaIfaceHal.registerDeathHandler(mSupplicantDeathHandlerCaptor.capture())) - .thenReturn(true); - when(mSupplicantStaIfaceHal.deregisterDeathHandler()).thenReturn(true); - when(mSupplicantStaIfaceHal.initialize()).thenReturn(true); - when(mSupplicantStaIfaceHal.isInitializationStarted()).thenReturn(false); - when(mSupplicantStaIfaceHal.isInitializationComplete()).thenReturn(true); - when(mSupplicantStaIfaceHal.startDaemon()).thenReturn(true); - when(mSupplicantStaIfaceHal.setupIface(any())).thenReturn(true); - when(mSupplicantStaIfaceHal.teardownIface(any())).thenReturn(true); - - when(mHostapdHal.registerDeathHandler(mHostapdDeathHandlerCaptor.capture())) - .thenReturn(true); - when(mHostapdHal.deregisterDeathHandler()).thenReturn(true); - when(mHostapdHal.initialize()).thenReturn(true); - when(mHostapdHal.isInitializationStarted()).thenReturn(false); - when(mHostapdHal.isInitializationComplete()).thenReturn(true); - when(mHostapdHal.startDaemon()).thenReturn(true); - when(mHostapdHal.addAccessPoint(any(), any(), any())).thenReturn(true); - when(mHostapdHal.removeAccessPoint(any())).thenReturn(true); - - when(mWifiInjector.makeNetdWrapper()).thenReturn(mNetdWrapper); - - mInOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, mHostapdHal, - mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mWifiMetrics); - - mWifiNative = new WifiNative( - mWifiVendorHal, mSupplicantStaIfaceHal, mHostapdHal, mWificondControl, - mWifiMonitor, mPropertyService, mWifiMetrics, - new Handler(mLooper.getLooper()), null, mWifiInjector); - mWifiNative.initialize(); - mWifiNative.registerStatusListener(mStatusListener); - - mInOrder.verify(mWifiVendorHal).initialize(any()); - mInOrder.verify(mWificondControl).setOnServiceDeadCallback( - mWificondDeathHandlerCaptor.capture()); - mInOrder.verify(mWificondControl).tearDownInterfaces(); - mInOrder.verify(mWifiVendorHal).registerRadioModeChangeHandler(any()); - } - - @After - public void tearDown() throws Exception { - verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, - mHostapdHal, mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, - mWifiMetrics); - } - - /** - * Verifies the setup of a single client interface. - */ - @Test - public void testSetupClientInterface() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertEquals(IFACE_NAME_0, mWifiNative.getClientInterfaceName()); - } - - /** - * Verifies the setup of a single client interface (for scan). - */ - @Test - public void testSetupClientInterfaceForScan() throws Exception { - executeAndValidateSetupClientInterfaceForScan( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertEquals(IFACE_NAME_0, mWifiNative.getClientInterfaceName()); - verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, - mHostapdHal, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mWifiMetrics); - } - - /** - * Verifies the setup of a single softAp interface. - */ - @Test - public void testSetupSoftApInterface() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertNull(mWifiNative.getClientInterfaceName()); - } - - /** - * Verifies the setup & teardown of a single client interface. - */ - @Test - public void testSetupAndTeardownClientInterface() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertEquals(IFACE_NAME_0, mWifiNative.getClientInterfaceName()); - executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0, - mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue()); - } - - /** - * Verifies the setup & teardown of a single client interface (for scan). - */ - @Test - public void testSetupAndTeardownClientInterfaceForScan() throws Exception { - executeAndValidateSetupClientInterfaceForScan( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertEquals(IFACE_NAME_0, mWifiNative.getClientInterfaceName()); - executeAndValidateTeardownClientInterfaceForScan(false, false, IFACE_NAME_0, - mIfaceCallback0, mIfaceDestroyedListenerCaptor0.getValue(), - mNetworkObserverCaptor0.getValue()); - verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, - mHostapdHal, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mWifiMetrics); - } - - /** - * Verifies the setup & teardown of a single softAp interface. - */ - @Test - public void testSetupAndTeardownSoftApInterface() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertNull(mWifiNative.getClientInterfaceName()); - executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0, - mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue()); - } - - /** - * Verifies the setup & teardown of a client & softAp interface. - * - * Sequence tested: - * a) Setup client interface. - * b) Setup softAp interface. - * c) Teardown client interface. - * d) Teardown softAp interface. - */ - @Test - public void testSetupAndTeardownClientAndSoftApInterface_Seq1() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - executeAndValidateSetupSoftApInterface( - true, false, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1, - mNetworkObserverCaptor1); - assertEquals(IFACE_NAME_0, mWifiNative.getClientInterfaceName()); - executeAndValidateTeardownClientInterface(false, true, IFACE_NAME_0, mIfaceCallback0, - mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue()); - executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_1, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); - } - - /** - * Verifies the setup & teardown of a client & softAp interface. - * - * Sequence tested: - * a) Setup client interface. - * b) Setup softAp interface. - * c) Teardown softAp interface. - * d) Teardown client interface. - */ - @Test - public void testSetupAndTeardownClientAndSoftApInterface_Seq2() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - executeAndValidateSetupSoftApInterface( - true, false, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1, - mNetworkObserverCaptor1); - assertEquals(IFACE_NAME_0, mWifiNative.getClientInterfaceName()); - executeAndValidateTeardownSoftApInterface(true, false, IFACE_NAME_1, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); - executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0, - mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue()); - } - - /** - * Verifies the setup & teardown of a client & softAp interface. - * - * Sequence tested: - * a) Setup softAp interface. - * b) Setup client interface. - * c) Teardown softAp interface. - * d) Teardown client interface. - */ - @Test - public void testSetupAndTeardownClientAndSoftApInterface_Seq3() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - executeAndValidateSetupClientInterface( - false, true, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1, - mNetworkObserverCaptor1); - assertEquals(IFACE_NAME_1, mWifiNative.getClientInterfaceName()); - executeAndValidateTeardownSoftApInterface(true, false, IFACE_NAME_0, mIfaceCallback0, - mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue()); - executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_1, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); - } - - /** - * Verifies the setup & teardown of a client & softAp interface. - * - * Sequence tested: - * a) Setup softAp interface. - * b) Setup client interface. - * c) Teardown client interface. - * d) Teardown softAp interface. - */ - @Test - public void testSetupAndTeardownClientAndSoftApInterface_Seq4() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - executeAndValidateSetupClientInterface( - false, true, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1, - mNetworkObserverCaptor1); - assertEquals(IFACE_NAME_1, mWifiNative.getClientInterfaceName()); - executeAndValidateTeardownClientInterface(false, true, IFACE_NAME_1, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); - executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0, - mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue()); - } - - /** - * Verifies the setup of a client & softAp interface & then initiate teardown of all active - * interfaces. - * - * Sequence tested: - * a) Setup softAp interface. - * b) Setup client interface. - * c) Teardown all active interfaces. - */ - @Test - public void testTeardownAllInterfaces() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - executeAndValidateSetupClientInterface( - false, true, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1, - mNetworkObserverCaptor1); - - // Assert that a client & softap interface is present. - assertNotNull(mWifiNative.getClientInterfaceName()); - assertNotNull(mWifiNative.getSoftApInterfaceName()); - - mWifiNative.teardownAllInterfaces(); - - // Note: This is not using InOrder because order of interface deletion cannot be - // predetermined. - - // Verify STA removal - verify(mWifiMonitor).stopMonitoring(IFACE_NAME_1); - verify(mNetdWrapper).unregisterObserver(mNetworkObserverCaptor1.getValue()); - verify(mSupplicantStaIfaceHal).teardownIface(IFACE_NAME_1); - verify(mWificondControl).tearDownClientInterface(IFACE_NAME_1); - verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); - verify(mSupplicantStaIfaceHal).terminate(); - verify(mIfaceCallback1).onDestroyed(IFACE_NAME_1); - - // Verify AP removal - verify(mNetdWrapper).unregisterObserver(mNetworkObserverCaptor0.getValue()); - verify(mHostapdHal).removeAccessPoint(IFACE_NAME_0); - verify(mWificondControl).tearDownSoftApInterface(IFACE_NAME_0); - verify(mHostapdHal).deregisterDeathHandler(); - verify(mHostapdHal).terminate(); - - // Verify we stopped HAL & wificond - verify(mWificondControl, times(2)).tearDownInterfaces(); // first time at initialize - verify(mWifiVendorHal).stopVendorHal(); - verify(mIfaceCallback0).onDestroyed(IFACE_NAME_0); - - verify(mWifiVendorHal, atLeastOnce()).isVendorHalSupported(); - - // Assert that the client & softap interface is no more there. - assertNull(mWifiNative.getClientInterfaceName()); - assertNull(mWifiNative.getSoftApInterfaceName()); - } - - /** - * Verifies the setup of a client interface and then a SoftAp interface which would - * destroy the Client interface. This is what would happen on older devices which do not - * support concurrent interfaces. - */ - @Test - public void testSetupClientAndSoftApInterfaceCausesClientInterfaceTeardown() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - // Trigger the STA interface teardown when AP interface is created. - // The iface name will remain the same. - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public String answer(InterfaceDestroyedListener destroyedListener) { - mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); - return IFACE_NAME_0; - } - }).when(mWifiVendorHal).createApIface(any()); - - assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1)); - - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface(mIfaceDestroyedListenerCaptor1.capture()); - // Creation of AP interface should trigger the STA interface destroy - validateOnDestroyedClientInterface( - false, true, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue()); - // Now continue with rest of AP interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - - // Execute a teardown of the interface to ensure that the new iface removal works. - executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); - } - - /** - * Verifies the setup of a client interface and then a SoftAp interface which would - * destroy the Client interface. This is what would happen on older devices which do not - * support concurrent interfaces. - */ - @Test - public void testSetupSoftApAndClientInterfaceCausesSoftApInterfaceTeardown() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - // Trigger the AP interface teardown when STA interface is created. - // The iface name will remain the same. - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public String answer(InterfaceDestroyedListener destroyedListener) { - mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); - return IFACE_NAME_0; - } - }).when(mWifiVendorHal).createStaIface(any()); - - assertEquals(IFACE_NAME_0, - mWifiNative.setupInterfaceForClientInConnectivityMode(mIfaceCallback1)); - - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - mIfaceDestroyedListenerCaptor1.capture()); - // Creation of STA interface should trigger the AP interface destroy. - validateOnDestroyedSoftApInterface( - true, false, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue()); - // Now continue with rest of STA interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(IFACE_NAME_0), any(), - any(), any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).clearInterfaceAddresses(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true); - mInOrder.verify(mNetdWrapper).disableIpv6(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - - // Execute a teardown of the interface to ensure that the new iface removal works. - executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_0, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); - } - - /** - * Verifies the setup of a client interface and trigger an interface down event. - * This should be ignored since interface is considered to be down before setup. - */ - @Test - public void testSetupClientInterfaceAndTriggerInterfaceDown() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, false, mNetworkObserverCaptor0.getValue()); - } - - /** - * Verifies the setup of a client interface and trigger an interface up event. - */ - @Test - public void testSetupClientInterfaceAndTriggerInterfaceUp() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, true, mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mIfaceCallback0).onUp(IFACE_NAME_0); - } - - /** - * Verifies the setup of a client interface and trigger an interface up event, followed by a - * down event. - */ - @Test - public void testSetupClientInterfaceAndTriggerInterfaceUpFollowedByDown() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, true, mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mIfaceCallback0).onUp(IFACE_NAME_0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, false, mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mIfaceCallback0).onDown(IFACE_NAME_0); - mInOrder.verify(mWifiMetrics).incrementNumClientInterfaceDown(); - } - - /** - * Verifies the setup of a softap interface and trigger an interface up event, followed by a - * down event. - */ - @Test - public void testSetupSoftApInterfaceAndTriggerInterfaceUpFollowedByDown() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, true, mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mIfaceCallback0).onUp(IFACE_NAME_0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, false, mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mIfaceCallback0).onDown(IFACE_NAME_0); - mInOrder.verify(mWifiMetrics).incrementNumSoftApInterfaceDown(); - } - - /** - * Verifies the setup of a client interface and trigger an interface up event, followed by - * link down/up events. The link state change events should be ignored since we only care for - * interface state changes. - */ - @Test - public void testSetupClientInterfaceAndTriggerInterfaceUpFollowedByLinkDownAndUp() - throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, true, mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mIfaceCallback0).onUp(IFACE_NAME_0); - - // Trigger a link down, with the interface still up. - // Should not trigger the external iface callback. - mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, false); - mLooper.dispatchAll(); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - - // Now trigger a link up, with the interface still up. - // Should not trigger the external iface callback. - mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, true); - mLooper.dispatchAll(); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - } - - /** - * Verifies the setup of a client interface and trigger an interface up event, followed by - * link down/up events. The link state change events should be ignored since we only care for - * interface state changes. - */ - @Test - public void testSetupSoftApInterfaceAndTriggerInterfaceUpFollowedByLinkDownAndUp() - throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, true, mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mIfaceCallback0).onUp(IFACE_NAME_0); - - // Trigger a link down, with the interface still up. - // Should not trigger the external iface callback. - mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, false); - mLooper.dispatchAll(); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - - // Now trigger a link up, with the interface still up. - // Should not trigger the external iface callback. - mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, true); - mLooper.dispatchAll(); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - } - - /** - * Verifies the setup of a client interface and trigger an interface up event twice. - * The second interface up event should be masked. - */ - @Test - public void testSetupClientInterfaceAndTriggerInterfaceUpTwice() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, true, mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mIfaceCallback0).onUp(IFACE_NAME_0); - - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, true, mNetworkObserverCaptor0.getValue()); - } - - /** - * Verifies the setup of a client interface and trigger an interface up event on a different - * interface. - */ - @Test - public void testSetupClientInterfaceAndTriggerInterfaceUpOnAnInvalidIface() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_1, true); - mLooper.dispatchAll(); - } - - /** - * Verifies that interface down on a destroyed interface is ignored. - * The test triggers - * a) Setup of a client interface - * b) Setup of a SoftAp interface which would destroy the Client interface. - * This is what would happen on older devices which do not support concurrent interfaces. - * c) Once the client interface is destroyed, trigger an interface up event on the old - * network observer. This should be ignored. - * d) Trigger an interface down event on the new network observer. This should trigger an - * interface up event to external clients. - * e) Remove the new SoftAp interface. - */ - @Test - public void testSetupClientInterfaceAndTriggerInterfaceUpOnDestroyedIface() throws Exception { - // Step (a) - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - // Step (b) - // Trigger the STA interface teardown when AP interface is created. - // The iface name will remain the same. - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public String answer(InterfaceDestroyedListener destroyedListener) { - mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); - return IFACE_NAME_0; - } - }).when(mWifiVendorHal).createApIface(any()); - - assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1)); - - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface(mIfaceDestroyedListenerCaptor1.capture()); - // Creation of AP interface should trigger the STA interface destroy - validateOnDestroyedClientInterface( - false, true, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue()); - // Now continue with rest of AP interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - - // Step (c) - Iface up on old iface, ignored! - mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, true); - mLooper.dispatchAll(); - - // Step (d) - Iface up on new iface, handled! - executeAndValidateInterfaceStateChange( - IFACE_NAME_0, true, mNetworkObserverCaptor1.getValue()); - mInOrder.verify(mIfaceCallback1).onUp(IFACE_NAME_0); - - // Execute a teardown of the softap interface to ensure that the new iface removal works. - executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); - } - - /** - * Verifies the setup of a client interface and wificond death handling. - */ - @Test - public void testSetupClientInterfaceAndWicondDied() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - // Trigger wificond death - mWificondDeathHandlerCaptor.getValue().run(); - - mInOrder.verify(mWifiMetrics).incrementNumWificondCrashes(); - - verify(mStatusListener).onStatusChanged(false); - verify(mStatusListener).onStatusChanged(true); - } - - /** - * Verifies the setup of a soft ap interface and vendor HAL death handling. - */ - @Test - public void testSetupSoftApInterfaceAndVendorHalDied() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - // Trigger vendor HAL death - mWifiVendorHalDeathHandlerCaptor.getValue().onDeath(); - - mInOrder.verify(mWifiMetrics).incrementNumHalCrashes(); - - verify(mStatusListener).onStatusChanged(false); - verify(mStatusListener).onStatusChanged(true); - } - - /** - * Verifies the setup of a client interface and supplicant HAL death handling. - */ - @Test - public void testSetupClientInterfaceAndSupplicantDied() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - // Trigger wificond death - mSupplicantDeathHandlerCaptor.getValue().onDeath(); - - mInOrder.verify(mWifiMetrics).incrementNumSupplicantCrashes(); - - verify(mStatusListener).onStatusChanged(false); - verify(mStatusListener).onStatusChanged(true); - } - - /** - * Verifies the setup of a soft ap interface and hostapd death handling. - */ - @Test - public void testStartSoftApAndHostapdDied() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - // Start softap - assertTrue(mWifiNative.startSoftAp(IFACE_NAME_0, new SoftApConfiguration.Builder().build(), - mock(WifiNative.SoftApListener.class))); - - mInOrder.verify(mWificondControl).registerApCallback(any(), any(), any()); - mInOrder.verify(mHostapdHal).addAccessPoint(any(), any(), any()); - - // Trigger vendor HAL death - mHostapdDeathHandlerCaptor.getValue().onDeath(); - - mInOrder.verify(mWifiMetrics).incrementNumHostapdCrashes(); - - verify(mStatusListener).onStatusChanged(false); - verify(mStatusListener).onStatusChanged(true); - } - - /** - * Verifies failure handling in setup of a client interface. - */ - @Test - public void testSetupClientInterfaceFailureInStartHal() throws Exception { - when(mWifiVendorHal.startVendorHal()).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToHal(); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies failure handling in setup of a client interface. - */ - @Test - public void testSetupClientInterfaceFailureInStartSupplicant() throws Exception { - when(mSupplicantStaIfaceHal.startDaemon()).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToSupplicant(); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies failure handling in setup of a client interface. - */ - @Test - public void testSetupClientInterfaceFailureInHalCreateStaIface() throws Exception { - when(mWifiVendorHal.createStaIface(any())).thenReturn(null); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToHal(); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies failure handling in setup of a client interface. - */ - @Test - public void testSetupClientInterfaceFailureInWificondSetupInterfaceForClientMode() - throws Exception { - when(mWificondControl.setupInterfaceForClientMode(any(), any(), any(), any())).thenReturn( - false); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - mIfaceDestroyedListenerCaptor0.capture()); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(any(), any(), any(), any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeStaIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToWificond(); - - // Trigger the HAL interface destroyed callback to verify the whole removal sequence. - mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); - validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0, - null); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies failure handling in setup of a client interface. - */ - @Test - public void testSetupClientInterfaceFailureInSupplicantSetupIface() throws Exception { - when(mSupplicantStaIfaceHal.setupIface(any())).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - mIfaceDestroyedListenerCaptor0.capture()); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(any(), any(), any(), any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeStaIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToSupplicant(); - - // Trigger the HAL interface destroyed callback to verify the whole removal sequence. - mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); - validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0, - null); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies failure handling in setup of a softAp interface. - */ - @Test - public void testSetupSoftApInterfaceFailureInStartHal() throws Exception { - when(mWifiVendorHal.startVendorHal()).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHal(); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies failure handling in setup of a softAp interface. - */ - @Test - public void testSetupSoftApInterfaceFailureInStartHostapd() throws Exception { - when(mHostapdHal.startDaemon()).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHostapd(); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies failure handling in setup of a softAp interface. - */ - @Test - public void testSetupSoftApInterfaceFailureInHalCreateApIface() throws Exception { - when(mWifiVendorHal.createApIface(any())).thenReturn(null); - assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHal(); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies failure handling in setup of a softAp interface. - */ - @Test - public void testSetupSoftApInterfaceFailureInWificondSetupInterfaceForSoftapMode() - throws Exception { - when(mWificondControl.setupInterfaceForSoftApMode(any())).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface(mIfaceDestroyedListenerCaptor0.capture()); - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeApIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToWificond(); - - // Trigger the HAL interface destroyed callback to verify the whole removal sequence. - mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); - validateOnDestroyedSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0, - null); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); - } - - /** - * Verifies the interface state query API. - */ - @Test - public void testIsInterfaceUp() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - - when(mNetdWrapper.isInterfaceUp(IFACE_NAME_0)).thenReturn(true); - assertTrue(mWifiNative.isInterfaceUp(IFACE_NAME_0)); - - when(mNetdWrapper.isInterfaceUp(IFACE_NAME_0)).thenReturn(false); - assertFalse(mWifiNative.isInterfaceUp(IFACE_NAME_0)); - - verify(mNetdWrapper, times(3)).isInterfaceUp(IFACE_NAME_0); - } - - /** - * Verifies that the interface name is null when there are no interfaces setup. - */ - @Test - public void testGetClientInterfaceNameWithNoInterfacesSetup() throws Exception { - assertNull(mWifiNative.getClientInterfaceName()); - } - - /** - * Verifies that the interface name is null when there are no client interfaces setup. - */ - @Test - public void testGetClientInterfaceNameWithNoClientInterfaceSetup() throws Exception { - executeAndValidateSetupSoftApInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertNull(mWifiNative.getClientInterfaceName()); - } - - /** - * Verifies that the interface name is not null when there is one client interface setup. - */ - @Test - public void testGetClientInterfaceNameWithOneClientInterfaceSetup() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertEquals(IFACE_NAME_0, mWifiNative.getClientInterfaceName()); - } - - /** - * Verifies that the interface name is not null when there are more than one client interfaces - * setup. - */ - @Test - public void testGetClientInterfaceNameWithMoreThanOneClientInterfaceSetup() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - executeAndValidateSetupClientInterface( - true, false, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1, - mNetworkObserverCaptor1); - String interfaceName = mWifiNative.getClientInterfaceName(); - assertNotNull(interfaceName); - assertTrue(interfaceName.equals(IFACE_NAME_0) || interfaceName.equals(IFACE_NAME_1)); - } - - /* - * Verifies the setup of a client interface and then a SoftAp interface which would - * destroy the Client interface. This is what would happen on older devices which do not - * support the vendor HAL. - */ - @Test - public void testSetupClientAndSoftApInterfaceCausesClientInterfaceTeardownWithNoVendorHal() - throws Exception { - when(mWifiVendorHal.isVendorHalSupported()).thenReturn(false); - when(mPropertyService.getString(any(), any())).thenReturn(IFACE_NAME_0); - - // First setup a STA interface and verify. - assertEquals(IFACE_NAME_0, - mWifiNative.setupInterfaceForClientInConnectivityMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(IFACE_NAME_0), any(), - any(), any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor0.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).clearInterfaceAddresses(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true); - mInOrder.verify(mNetdWrapper).disableIpv6(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - - // Now setup an AP interface. - assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1)); - - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - // Creation of AP interface should trigger the STA interface destroy - verify(mWifiMonitor).stopMonitoring(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).unregisterObserver( - mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mSupplicantStaIfaceHal).teardownIface(IFACE_NAME_0); - mInOrder.verify(mWificondControl).tearDownClientInterface(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); - mInOrder.verify(mSupplicantStaIfaceHal).terminate(); - mInOrder.verify(mIfaceCallback0).onDestroyed(IFACE_NAME_0); - // Now continue with rest of AP interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - } - - /** - * Verifies the setup of a client interface and then a SoftAp interface which would - * destroy the Client interface. This is what would happen on older devices which do not - * support the vendor HAL. - */ - @Test - public void testSetupSoftApAndClientInterfaceCausesSoftApInterfaceTeardownWithNoVendorHal() - throws Exception { - when(mWifiVendorHal.isVendorHalSupported()).thenReturn(false); - when(mPropertyService.getString(any(), any())).thenReturn(IFACE_NAME_0); - - // First setup an AP interface and verify. - assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor0.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - - // Now setup a STA interface. - assertEquals(IFACE_NAME_0, - mWifiNative.setupInterfaceForClientInConnectivityMode(mIfaceCallback1)); - - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - // Creation of STA interface should trigger the AP interface destroy. - mInOrder.verify(mNetdWrapper).unregisterObserver( - mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mHostapdHal).removeAccessPoint(IFACE_NAME_0); - mInOrder.verify(mWificondControl).tearDownSoftApInterface(IFACE_NAME_0); - mInOrder.verify(mHostapdHal).deregisterDeathHandler(); - mInOrder.verify(mHostapdHal).terminate(); - mInOrder.verify(mIfaceCallback0).onDestroyed(IFACE_NAME_0); - // Now continue with rest of STA interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(IFACE_NAME_0), any(), - any(), any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).clearInterfaceAddresses(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true); - mInOrder.verify(mNetdWrapper).disableIpv6(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - } - - /** - * Verifies the handling of radio mode change callbacks. - */ - @Test - public void testRadioModeChangeCallback() { - WifiNative.VendorHalRadioModeChangeEventHandler handler = - mWifiVendorHalRadioModeChangeHandlerCaptor.getValue(); - - handler.onMcc(WifiScanner.WIFI_BAND_5_GHZ); - mInOrder.verify(mWifiMetrics).incrementNumRadioModeChangeToMcc(); - - handler.onScc(WifiScanner.WIFI_BAND_24_GHZ); - mInOrder.verify(mWifiMetrics).incrementNumRadioModeChangeToScc(); - - handler.onSbs(WifiScanner.WIFI_BAND_24_GHZ); - mInOrder.verify(mWifiMetrics).incrementNumRadioModeChangeToSbs(); - - handler.onDbs(); - mInOrder.verify(mWifiMetrics).incrementNumRadioModeChangeToDbs(); - } - - /** - * Verifies the switch of existing client interface in connectivity mode to scan mode. - */ - @Test - public void testSwitchClientInterfaceToScanMode() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertTrue(mWifiNative.switchClientInterfaceToScanMode(IFACE_NAME_0)); - - mInOrder.verify(mSupplicantStaIfaceHal).teardownIface(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); - mInOrder.verify(mSupplicantStaIfaceHal).terminate(); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - } - - /** - * Verifies that a switch to scan mode when already in scan mode is rejected. - */ - @Test - public void testSwitchClientInterfaceToScanModeFailsWhenAlreadyInScanMode() throws Exception { - executeAndValidateSetupClientInterfaceForScan( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertTrue(mWifiNative.switchClientInterfaceToScanMode(IFACE_NAME_0)); - } - - /** - * Verifies the switch of existing client interface in scan mode to connectivity mode. - */ - @Test - public void testSwitchClientInterfaceToConnectivityMode() throws Exception { - executeAndValidateSetupClientInterfaceForScan( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertTrue(mWifiNative.switchClientInterfaceToConnectivityMode(IFACE_NAME_0)); - - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); - } - - /** - * Verifies that a switch to connectivity mode when already in connectivity mode is rejected. - */ - @Test - public void testSwitchClientInterfaceToConnectivityModeFailsWhenAlreadyInConnectivityMode() - throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertTrue(mWifiNative.switchClientInterfaceToConnectivityMode(IFACE_NAME_0)); - } - - /** - * Verifies the setup of two client interfaces. - */ - @Test - public void testSetupTwoClientInterfaces() throws Exception { - executeAndValidateSetupClientInterface( - false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0); - assertEquals(new HashSet<>(Arrays.asList(IFACE_NAME_0)), - mWifiNative.getClientInterfaceNames()); - - executeAndValidateSetupClientInterface( - true, false, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1, - mNetworkObserverCaptor1); - assertEquals(new HashSet<>(Arrays.asList(IFACE_NAME_0, IFACE_NAME_1)), - mWifiNative.getClientInterfaceNames()); - } - - - private void executeAndValidateSetupClientInterface( - boolean existingStaIface, boolean existingApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - when(mWifiVendorHal.createStaIface(any())).thenReturn(ifaceName); - assertEquals(ifaceName, mWifiNative.setupInterfaceForClientInConnectivityMode(callback)); - - validateSetupClientInterface( - existingStaIface, existingApIface, ifaceName, destroyedListenerCaptor, - networkObserverCaptor); - } - - private void validateSetupClientInterface( - boolean existingStaIface, boolean existingApIface, - String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - if (!existingStaIface && !existingApIface) { - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - } - if (!existingStaIface) { - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - } - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - destroyedListenerCaptor.capture()); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(ifaceName), any(), any(), - any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(ifaceName); - mInOrder.verify(mNetdWrapper).registerObserver(networkObserverCaptor.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(ifaceName); - mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); - mInOrder.verify(mNetdWrapper).clearInterfaceAddresses(ifaceName); - mInOrder.verify(mNetdWrapper).setInterfaceIpv6PrivacyExtensions(ifaceName, true); - mInOrder.verify(mNetdWrapper).disableIpv6(ifaceName); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); - } - - private void executeAndValidateTeardownClientInterface( - boolean anyOtherStaIface, boolean anyOtherApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - InterfaceDestroyedListener destroyedListener, - NetdEventObserver networkObserver) throws Exception { - mWifiNative.teardownInterface(ifaceName); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeStaIface(ifaceName); - - // Now trigger the HalDeviceManager destroy callback to initiate the rest of the teardown. - destroyedListener.onDestroyed(ifaceName); - - validateOnDestroyedClientInterface( - anyOtherStaIface, anyOtherApIface, ifaceName, callback, networkObserver); - } - - private void validateOnDestroyedClientInterface( - boolean anyOtherStaIface, boolean anyOtherApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - NetdEventObserver networkObserver) throws Exception { - mInOrder.verify(mWifiMonitor).stopMonitoring(ifaceName); - if (networkObserver != null) { - mInOrder.verify(mNetdWrapper).unregisterObserver(networkObserver); - } - mInOrder.verify(mSupplicantStaIfaceHal).teardownIface(ifaceName); - mInOrder.verify(mWificondControl).tearDownClientInterface(ifaceName); - - if (!anyOtherStaIface) { - mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); - mInOrder.verify(mSupplicantStaIfaceHal).terminate(); - } - if (!anyOtherStaIface && !anyOtherApIface) { - mInOrder.verify(mWificondControl).tearDownInterfaces(); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).stopVendorHal(); - } - mInOrder.verify(callback).onDestroyed(ifaceName); - } - - private void executeAndValidateSetupClientInterfaceForScan( - boolean existingStaIface, boolean existingApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - when(mWifiVendorHal.createStaIface(any())).thenReturn(ifaceName); - assertEquals(ifaceName, mWifiNative.setupInterfaceForClientInScanMode(callback)); - - validateSetupClientInterfaceForScan( - existingStaIface, existingApIface, ifaceName, destroyedListenerCaptor, - networkObserverCaptor); - } - - private void validateSetupClientInterfaceForScan( - boolean existingStaIface, boolean existingApIface, - String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - if (!existingStaIface && !existingApIface) { - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - } - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - destroyedListenerCaptor.capture()); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(ifaceName), any(), any(), - any()); - mInOrder.verify(mNetdWrapper).registerObserver(networkObserverCaptor.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(ifaceName); - mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); - } - - private void executeAndValidateTeardownClientInterfaceForScan( - boolean anyOtherStaIface, boolean anyOtherApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - InterfaceDestroyedListener destroyedListener, - NetdEventObserver networkObserver) throws Exception { - mWifiNative.teardownInterface(ifaceName); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeStaIface(ifaceName); - - // Now trigger the HalDeviceManager destroy callback to initiate the rest of the teardown. - destroyedListener.onDestroyed(ifaceName); - - validateOnDestroyedClientInterfaceForScan( - anyOtherStaIface, anyOtherApIface, ifaceName, callback, networkObserver); - } - - private void validateOnDestroyedClientInterfaceForScan( - boolean anyOtherStaIface, boolean anyOtherApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - NetdEventObserver networkObserver) throws Exception { - mInOrder.verify(mWifiMonitor).stopMonitoring(ifaceName); - if (networkObserver != null) { - mInOrder.verify(mNetdWrapper).unregisterObserver(networkObserver); - } - mInOrder.verify(mWificondControl).tearDownClientInterface(ifaceName); - - if (!anyOtherStaIface && !anyOtherApIface) { - mInOrder.verify(mWificondControl).tearDownInterfaces(); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).stopVendorHal(); - } - mInOrder.verify(callback).onDestroyed(ifaceName); - } - - private void executeAndValidateSetupSoftApInterface( - boolean existingStaIface, boolean existingApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - when(mWifiVendorHal.createApIface(any())).thenReturn(ifaceName); - assertEquals(ifaceName, mWifiNative.setupInterfaceForSoftApMode(callback)); - - validateSetupSoftApInterface( - existingStaIface, existingApIface, ifaceName, destroyedListenerCaptor, - networkObserverCaptor); - } - - private void validateSetupSoftApInterface( - boolean existingStaIface, boolean existingApIface, - String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - if (!existingStaIface && !existingApIface) { - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - } - if (!existingApIface) { - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - } - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface(destroyedListenerCaptor.capture()); - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(ifaceName); - mInOrder.verify(mNetdWrapper).registerObserver(networkObserverCaptor.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedKeyMgmtCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); - } - - private void executeAndValidateTeardownSoftApInterface( - boolean anyOtherStaIface, boolean anyOtherApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - InterfaceDestroyedListener destroyedListener, - NetdEventObserver networkObserver) throws Exception { - mWifiNative.teardownInterface(ifaceName); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeApIface(ifaceName); - - // Now trigger the HalDeviceManager destroy callback to initiate the rest of the teardown. - destroyedListener.onDestroyed(ifaceName); - - validateOnDestroyedSoftApInterface( - anyOtherStaIface, anyOtherApIface, ifaceName, callback, networkObserver); - } - - private void validateOnDestroyedSoftApInterface( - boolean anyOtherStaIface, boolean anyOtherApIface, - String ifaceName, @Mock WifiNative.InterfaceCallback callback, - NetdEventObserver networkObserver) throws Exception { - if (networkObserver != null) { - mInOrder.verify(mNetdWrapper).unregisterObserver(networkObserver); - } - mInOrder.verify(mHostapdHal).removeAccessPoint(ifaceName); - mInOrder.verify(mWificondControl).tearDownSoftApInterface(ifaceName); - - if (!anyOtherApIface) { - mInOrder.verify(mHostapdHal).deregisterDeathHandler(); - mInOrder.verify(mHostapdHal).terminate(); - } - if (!anyOtherStaIface && !anyOtherApIface) { - mInOrder.verify(mWificondControl).tearDownInterfaces(); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).stopVendorHal(); - } - mInOrder.verify(callback).onDestroyed(ifaceName); - } - - private void executeAndValidateInterfaceStateChange( - String ifaceName, boolean up, NetdEventObserver networkObserver) throws Exception { - when(mNetdWrapper.isInterfaceUp(ifaceName)).thenReturn(up); - networkObserver.interfaceLinkStateChanged(ifaceName, up); - mLooper.dispatchAll(); - mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java deleted file mode 100644 index 46a3de86a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiScanner; -import android.net.wifi.nl80211.NativeScanResult; -import android.net.wifi.nl80211.RadioChainInfo; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.net.wifi.nl80211.WifiNl80211Manager.SendMgmtFrameCallback; -import android.os.Handler; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.util.NativeUtil; -import com.android.server.wifi.util.NetdWrapper; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.AdditionalMatchers; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.regex.Pattern; - -/** - * Unit tests for {@link com.android.server.wifi.WifiNative}. - */ -@SmallTest -public class WifiNativeTest extends WifiBaseTest { - private static final String WIFI_IFACE_NAME = "mockWlan"; - private static final long FATE_REPORT_DRIVER_TIMESTAMP_USEC = 12345; - private static final byte[] FATE_REPORT_FRAME_BYTES = new byte[] { - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7}; - private static final WifiNative.TxFateReport TX_FATE_REPORT = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_SENT, - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - FATE_REPORT_FRAME_BYTES - ); - private static final WifiNative.RxFateReport RX_FATE_REPORT = new WifiNative.RxFateReport( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - FATE_REPORT_FRAME_BYTES - ); - private static final FrameTypeMapping[] FRAME_TYPE_MAPPINGS = new FrameTypeMapping[] { - new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown", "N/A"), - new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data", "Ethernet"), - new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management", - "802.11 Mgmt"), - new FrameTypeMapping((byte) 42, "42", "N/A") - }; - private static final FateMapping[] TX_FATE_MAPPINGS = new FateMapping[] { - new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID, - "firmware dropped (invalid frame)"), - new FateMapping( - WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"), - new FateMapping( - WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID, - "driver dropped (invalid frame)"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS, - "driver dropped (no bufs)"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"), - new FateMapping((byte) 42, "42") - }; - private static final FateMapping[] RX_FATE_MAPPINGS = new FateMapping[] { - new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, - "firmware dropped (invalid frame)"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID, - "driver dropped (invalid frame)"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"), - new FateMapping((byte) 42, "42") - }; - private static final WifiNl80211Manager.SignalPollResult SIGNAL_POLL_RESULT = - new WifiNl80211Manager.SignalPollResult(-60, 12, 6, 5240); - - private static final Set<Integer> SCAN_FREQ_SET = - new HashSet<Integer>() {{ - add(2410); - add(2450); - add(5050); - add(5200); - }}; - private static final String TEST_QUOTED_SSID_1 = "\"testSsid1\""; - private static final String TEST_QUOTED_SSID_2 = "\"testSsid2\""; - private static final int[] TEST_FREQUENCIES_1 = {}; - private static final int[] TEST_FREQUENCIES_2 = {2500, 5124}; - private static final List<String> SCAN_HIDDEN_NETWORK_SSID_SET = - new ArrayList<String>() {{ - add(TEST_QUOTED_SSID_1); - add(TEST_QUOTED_SSID_2); - }}; - private static final List<byte[]> SCAN_HIDDEN_NETWORK_BYTE_SSID_SET = - new ArrayList<byte[]>() {{ - add(NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_1))); - add(NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_2))); - }}; - - private static final WifiNative.PnoSettings TEST_PNO_SETTINGS = - new WifiNative.PnoSettings() {{ - isConnected = false; - periodInMs = 6000; - networkList = new WifiNative.PnoNetwork[2]; - networkList[0] = new WifiNative.PnoNetwork(); - networkList[1] = new WifiNative.PnoNetwork(); - networkList[0].ssid = TEST_QUOTED_SSID_1; - networkList[1].ssid = TEST_QUOTED_SSID_2; - networkList[0].frequencies = TEST_FREQUENCIES_1; - networkList[1].frequencies = TEST_FREQUENCIES_2; - }}; - private static final MacAddress TEST_MAC_ADDRESS = MacAddress.fromString("ee:33:a2:94:10:92"); - - private static final String TEST_MAC_ADDRESS_STR = "f4:f5:e8:51:9e:09"; - private static final String TEST_BSSID_STR = "a8:bd:27:5b:33:72"; - private static final int TEST_MCS_RATE = 5; - private static final int TEST_SEQUENCE_NUM = 0x66b0; - - private static final byte[] TEST_SSID = - new byte[] {'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'}; - private static final byte[] TEST_BSSID = - new byte[] {(byte) 0x12, (byte) 0xef, (byte) 0xa1, - (byte) 0x2c, (byte) 0x97, (byte) 0x8b}; - // This the IE buffer which is consistent with TEST_SSID. - private static final byte[] TEST_INFO_ELEMENT_SSID = - new byte[] { - // Element ID for SSID. - (byte) 0x00, - // Length of the SSID: 0x0b or 11. - (byte) 0x0b, - // This is string "GoogleGuest" - 'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'}; - // RSN IE data indicating EAP key management. - private static final byte[] TEST_INFO_ELEMENT_RSN = - new byte[] { - // Element ID for RSN. - (byte) 0x30, - // Length of the element data. - (byte) 0x18, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, - (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, (byte) 0x01, (byte) 0x00, - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; - - private static final int TEST_FREQUENCY = 2456; - private static final int TEST_SIGNAL_MBM = -4500; - private static final long TEST_TSF = 34455441; - private static final int TEST_CAPABILITY = 0b0000_0000_0010_0100; - private static final boolean TEST_ASSOCIATED = true; - private static final NativeScanResult MOCK_NATIVE_SCAN_RESULT = createMockNativeScanResult(); - private static NativeScanResult createMockNativeScanResult() { - NativeScanResult result = new NativeScanResult(); - result.ssid = TEST_SSID; - result.bssid = TEST_BSSID; - result.infoElement = TEST_INFO_ELEMENT_SSID; - result.frequency = TEST_FREQUENCY; - result.signalMbm = TEST_SIGNAL_MBM; - result.tsf = TEST_TSF; - result.capability = TEST_CAPABILITY; - result.associated = TEST_ASSOCIATED; - result.radioChainInfos = new ArrayList<>(); - return result; - } - - private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_1 = new RadioChainInfo(1, -89); - private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_2 = new RadioChainInfo(0, -78); - - @Mock private WifiVendorHal mWifiVendorHal; - @Mock private WifiNl80211Manager mWificondControl; - @Mock private SupplicantStaIfaceHal mStaIfaceHal; - @Mock private HostapdHal mHostapdHal; - @Mock private WifiMonitor mWifiMonitor; - @Mock private PropertyService mPropertyService; - @Mock private WifiMetrics mWifiMetrics; - @Mock private Handler mHandler; - @Mock private SendMgmtFrameCallback mSendMgmtFrameCallback; - @Mock private Random mRandom; - @Mock private WifiInjector mWifiInjector; - @Mock private NetdWrapper mNetdWrapper; - - ArgumentCaptor<WifiNl80211Manager.ScanEventCallback> mScanCallbackCaptor = - ArgumentCaptor.forClass(WifiNl80211Manager.ScanEventCallback.class); - - private WifiNative mWifiNative; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mWifiVendorHal.initialize(any())).thenReturn(true); - when(mWifiVendorHal.isVendorHalSupported()).thenReturn(true); - when(mWifiVendorHal.startVendorHal()).thenReturn(true); - when(mWifiVendorHal.startVendorHalSta()).thenReturn(true); - when(mWifiVendorHal.startVendorHalAp()).thenReturn(true); - when(mWifiVendorHal.createStaIface(any())).thenReturn(WIFI_IFACE_NAME); - - when(mWificondControl.setupInterfaceForClientMode(any(), any(), any(), any())).thenReturn( - true); - - when(mStaIfaceHal.registerDeathHandler(any())).thenReturn(true); - when(mStaIfaceHal.isInitializationComplete()).thenReturn(true); - when(mStaIfaceHal.initialize()).thenReturn(true); - when(mStaIfaceHal.startDaemon()).thenReturn(true); - when(mStaIfaceHal.setupIface(any())).thenReturn(true); - - when(mWifiInjector.makeNetdWrapper()).thenReturn(mNetdWrapper); - - mWifiNative = new WifiNative( - mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl, - mWifiMonitor, mPropertyService, mWifiMetrics, - mHandler, mRandom, mWifiInjector); - mWifiNative.initialize(); - } - - /** - * Verifies that TxFateReport's constructor sets all of the TxFateReport fields. - */ - @Test - public void testTxFateReportCtorSetsFields() { - WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_SENT, // non-zero value - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - WifiLoggerHal.FRAME_TYPE_ETHERNET_II, // non-zero value - FATE_REPORT_FRAME_BYTES - ); - assertEquals(WifiLoggerHal.TX_PKT_FATE_SENT, fateReport.mFate); - assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType); - assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes); - } - - /** - * Verifies that RxFateReport's constructor sets all of the RxFateReport fields. - */ - @Test - public void testRxFateReportCtorSetsFields() { - WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, // non-zero value - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - WifiLoggerHal.FRAME_TYPE_ETHERNET_II, // non-zero value - FATE_REPORT_FRAME_BYTES - ); - assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, fateReport.mFate); - assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType); - assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes); - } - - /** - * Verifies the hashCode methods for HiddenNetwork and PnoNetwork classes - */ - @Test - public void testHashCode() { - WifiNative.HiddenNetwork hiddenNet1 = new WifiNative.HiddenNetwork(); - hiddenNet1.ssid = new String("sametext"); - - WifiNative.HiddenNetwork hiddenNet2 = new WifiNative.HiddenNetwork(); - hiddenNet2.ssid = new String("sametext"); - - assertTrue(hiddenNet1.equals(hiddenNet2)); - assertEquals(hiddenNet1.hashCode(), hiddenNet2.hashCode()); - - WifiNative.PnoNetwork pnoNet1 = new WifiNative.PnoNetwork(); - pnoNet1.ssid = new String("sametext"); - pnoNet1.flags = 2; - pnoNet1.auth_bit_field = 4; - pnoNet1.frequencies = TEST_FREQUENCIES_2; - - WifiNative.PnoNetwork pnoNet2 = new WifiNative.PnoNetwork(); - pnoNet2.ssid = new String("sametext"); - pnoNet2.flags = 2; - pnoNet2.auth_bit_field = 4; - pnoNet2.frequencies = TEST_FREQUENCIES_2; - - assertTrue(pnoNet1.equals(pnoNet2)); - assertEquals(pnoNet1.hashCode(), pnoNet2.hashCode()); - } - - // Support classes for test{Tx,Rx}FateReportToString. - private static class FrameTypeMapping { - byte mTypeNumber; - String mExpectedTypeText; - String mExpectedProtocolText; - FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText) { - this.mTypeNumber = typeNumber; - this.mExpectedTypeText = expectedTypeText; - this.mExpectedProtocolText = expectedProtocolText; - } - } - private static class FateMapping { - byte mFateNumber; - String mExpectedText; - FateMapping(byte fateNumber, String expectedText) { - this.mFateNumber = fateNumber; - this.mExpectedText = expectedText; - } - } - - /** - * Verifies that FateReport.getTableHeader() prints the right header. - */ - @Test - public void testFateReportTableHeader() { - final String header = WifiNative.FateReport.getTableHeader(); - assertEquals( - "\nTime usec Walltime Direction Fate " - + "Protocol Type Result\n" - + "--------- -------- --------- ---- " - + "-------- ---- ------\n", header); - } - - /** - * Verifies that TxFateReport.toTableRowString() includes the information we care about. - */ - @Test - public void testTxFateReportToTableRowString() { - WifiNative.TxFateReport fateReport = TX_FATE_REPORT; - assertTrue( - fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches( - FATE_REPORT_DRIVER_TIMESTAMP_USEC + " " // timestamp - + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} " // walltime - + "TX " // direction - + "sent " // fate - + "Ethernet " // type - + "N/A " // protocol - + "N/A" // result - ) - ); - - for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) { - fateReport = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_SENT, - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - frameTypeMapping.mTypeNumber, - FATE_REPORT_FRAME_BYTES - ); - assertTrue( - fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches( - FATE_REPORT_DRIVER_TIMESTAMP_USEC + " " // timestamp - + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} " // walltime - + "TX " // direction - + "sent " // fate - + frameTypeMapping.mExpectedProtocolText + " " // type - + "N/A " // protocol - + "N/A" // result - ) - ); - } - - for (FateMapping fateMapping : TX_FATE_MAPPINGS) { - fateReport = new WifiNative.TxFateReport( - fateMapping.mFateNumber, - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - FATE_REPORT_FRAME_BYTES - ); - assertTrue( - fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches( - FATE_REPORT_DRIVER_TIMESTAMP_USEC + " " // timestamp - + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} " // walltime - + "TX " // direction - + Pattern.quote(fateMapping.mExpectedText) + " " // fate - + "802.11 Mgmt " // type - + "N/A " // protocol - + "N/A" // result - ) - ); - } - } - - /** - * Verifies that TxFateReport.toVerboseStringWithPiiAllowed() includes the information we care - * about. - */ - @Test - public void testTxFateReportToVerboseStringWithPiiAllowed() { - WifiNative.TxFateReport fateReport = TX_FATE_REPORT; - - String verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); - assertTrue(verboseFateString.contains("Frame direction: TX")); - assertTrue(verboseFateString.contains("Frame timestamp: 12345")); - assertTrue(verboseFateString.contains("Frame fate: sent")); - assertTrue(verboseFateString.contains("Frame type: data")); - assertTrue(verboseFateString.contains("Frame protocol: Ethernet")); - assertTrue(verboseFateString.contains("Frame protocol type: N/A")); - assertTrue(verboseFateString.contains("Frame length: 16")); - assertTrue(verboseFateString.contains( - "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump - // TODO(quiche): uncomment this, once b/27975149 is fixed. - // assertTrue(verboseFateString.contains("abcdefgh........")); // hex dump - - for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) { - fateReport = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_SENT, - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - frameTypeMapping.mTypeNumber, - FATE_REPORT_FRAME_BYTES - ); - verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); - assertTrue(verboseFateString.contains("Frame type: " - + frameTypeMapping.mExpectedTypeText)); - } - - for (FateMapping fateMapping : TX_FATE_MAPPINGS) { - fateReport = new WifiNative.TxFateReport( - fateMapping.mFateNumber, - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - FATE_REPORT_FRAME_BYTES - ); - verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); - assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText)); - } - } - - /** - * Verifies that RxFateReport.toTableRowString() includes the information we care about. - */ - @Test - public void testRxFateReportToTableRowString() { - WifiNative.RxFateReport fateReport = RX_FATE_REPORT; - assertTrue( - fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches( - FATE_REPORT_DRIVER_TIMESTAMP_USEC + " " // timestamp - + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} " // walltime - + "RX " // direction - + Pattern.quote("firmware dropped (invalid frame) ") // fate - + "Ethernet " // type - + "N/A " // protocol - + "N/A" // result - ) - ); - - // FrameTypeMappings omitted, as they're the same as for TX. - - for (FateMapping fateMapping : RX_FATE_MAPPINGS) { - fateReport = new WifiNative.RxFateReport( - fateMapping.mFateNumber, - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - FATE_REPORT_FRAME_BYTES - ); - assertTrue( - fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches( - FATE_REPORT_DRIVER_TIMESTAMP_USEC + " " // timestamp - + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} " // walltime - + "RX " // direction - + Pattern.quote(fateMapping.mExpectedText) + " " // fate - + "802.11 Mgmt " // type - + "N/A " // protocol - + "N/A" // result - ) - ); - } - } - - /** - * Verifies that RxFateReport.toVerboseStringWithPiiAllowed() includes the information we care - * about. - */ - @Test - public void testRxFateReportToVerboseStringWithPiiAllowed() { - WifiNative.RxFateReport fateReport = RX_FATE_REPORT; - - String verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); - assertTrue(verboseFateString.contains("Frame direction: RX")); - assertTrue(verboseFateString.contains("Frame timestamp: 12345")); - assertTrue(verboseFateString.contains("Frame fate: firmware dropped (invalid frame)")); - assertTrue(verboseFateString.contains("Frame type: data")); - assertTrue(verboseFateString.contains("Frame protocol: Ethernet")); - assertTrue(verboseFateString.contains("Frame protocol type: N/A")); - assertTrue(verboseFateString.contains("Frame length: 16")); - assertTrue(verboseFateString.contains( - "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump - // TODO(quiche): uncomment this, once b/27975149 is fixed. - // assertTrue(verboseFateString.contains("abcdefgh........")); // hex dump - - // FrameTypeMappings omitted, as they're the same as for TX. - - for (FateMapping fateMapping : RX_FATE_MAPPINGS) { - fateReport = new WifiNative.RxFateReport( - fateMapping.mFateNumber, - FATE_REPORT_DRIVER_TIMESTAMP_USEC, - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - FATE_REPORT_FRAME_BYTES - ); - verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); - assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText)); - } - } - - /** - * Verifies that startPktFateMonitoring returns false when HAL is not started. - */ - @Test - public void testStartPktFateMonitoringReturnsFalseWhenHalIsNotStarted() { - assertFalse(mWifiNative.isHalStarted()); - assertFalse(mWifiNative.startPktFateMonitoring(WIFI_IFACE_NAME)); - } - - /** - * Verifies that getTxPktFates returns error when HAL is not started. - */ - @Test - public void testGetTxPktFatesReturnsErrorWhenHalIsNotStarted() { - WifiNative.TxFateReport[] fateReports = null; - assertFalse(mWifiNative.isHalStarted()); - assertFalse(mWifiNative.getTxPktFates(WIFI_IFACE_NAME, fateReports)); - } - - /** - * Verifies that getRxPktFates returns error when HAL is not started. - */ - @Test - public void testGetRxPktFatesReturnsErrorWhenHalIsNotStarted() { - WifiNative.RxFateReport[] fateReports = null; - assertFalse(mWifiNative.isHalStarted()); - assertFalse(mWifiNative.getRxPktFates(WIFI_IFACE_NAME, fateReports)); - } - - // TODO(quiche): Add tests for the success cases (when HAL has been started). Specifically: - // - testStartPktFateMonitoringCallsHalIfHalIsStarted() - // - testGetTxPktFatesCallsHalIfHalIsStarted() - // - testGetRxPktFatesCallsHalIfHalIsStarted() - // - // Adding these tests is difficult to do at the moment, because we can't mock out the HAL - // itself. Also, we can't mock out the native methods, because those methods are private. - // b/28005116. - - /** Verifies that getDriverStateDumpNative returns null when HAL is not started. */ - @Test - public void testGetDriverStateDumpReturnsNullWhenHalIsNotStarted() { - assertEquals(null, mWifiNative.getDriverStateDump()); - } - - // TODO(b/28005116): Add test for the success case of getDriverStateDump(). - - /** - * Verifies client mode + scan success. - */ - @Test - public void testClientModeScanSuccess() { - mWifiNative.setupInterfaceForClientInConnectivityMode(null); - verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), - mScanCallbackCaptor.capture(), any()); - - mScanCallbackCaptor.getValue().onScanResultReady(); - verify(mWifiMonitor).broadcastScanResultEvent(WIFI_IFACE_NAME); - } - - /** - * Verifies client mode + scan failure. - */ - @Test - public void testClientModeScanFailure() { - mWifiNative.setupInterfaceForClientInConnectivityMode(null); - verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), - mScanCallbackCaptor.capture(), any()); - - mScanCallbackCaptor.getValue().onScanFailed(); - verify(mWifiMonitor).broadcastScanFailedEvent(WIFI_IFACE_NAME); - } - - /** - * Verifies client mode + PNO scan success. - */ - @Test - public void testClientModePnoScanSuccess() { - mWifiNative.setupInterfaceForClientInConnectivityMode(null); - verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), - any(), mScanCallbackCaptor.capture()); - - mScanCallbackCaptor.getValue().onScanResultReady(); - verify(mWifiMonitor).broadcastPnoScanResultEvent(WIFI_IFACE_NAME); - verify(mWifiMetrics).incrementPnoFoundNetworkEventCount(); - } - - /** - * Verifies client mode + PNO scan failure. - */ - @Test - public void testClientModePnoScanFailure() { - mWifiNative.setupInterfaceForClientInConnectivityMode(null); - verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), - any(), mScanCallbackCaptor.capture()); - - mScanCallbackCaptor.getValue().onScanFailed(); - verify(mWifiMetrics).incrementPnoScanFailedCount(); - } - - /** - * Verifies scan mode + scan success. - */ - @Test - public void testScanModeScanSuccess() { - mWifiNative.setupInterfaceForClientInScanMode(null); - verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), - mScanCallbackCaptor.capture(), any()); - - mScanCallbackCaptor.getValue().onScanResultReady(); - verify(mWifiMonitor).broadcastScanResultEvent(WIFI_IFACE_NAME); - } - - /** - * Verifies scan mode + scan failure. - */ - @Test - public void testScanModeScanFailure() { - mWifiNative.setupInterfaceForClientInScanMode(null); - verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), - mScanCallbackCaptor.capture(), any()); - - mScanCallbackCaptor.getValue().onScanFailed(); - verify(mWifiMonitor).broadcastScanFailedEvent(WIFI_IFACE_NAME); - } - - /** - * Verifies scan mode + PNO scan success. - */ - @Test - public void testScanModePnoScanSuccess() { - mWifiNative.setupInterfaceForClientInScanMode(null); - verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), - any(), mScanCallbackCaptor.capture()); - - mScanCallbackCaptor.getValue().onScanResultReady(); - verify(mWifiMonitor).broadcastPnoScanResultEvent(WIFI_IFACE_NAME); - verify(mWifiMetrics).incrementPnoFoundNetworkEventCount(); - } - - /** - * Verifies scan mode + PNO scan failure. - */ - @Test - public void testScanModePnoScanFailure() { - mWifiNative.setupInterfaceForClientInScanMode(null); - verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), - any(), mScanCallbackCaptor.capture()); - - mScanCallbackCaptor.getValue().onScanFailed(); - verify(mWifiMetrics).incrementPnoScanFailedCount(); - } - - - /** - * Verifies that signalPoll() calls underlying WificondControl. - */ - @Test - public void testSignalPoll() throws Exception { - when(mWificondControl.signalPoll(WIFI_IFACE_NAME)) - .thenReturn(SIGNAL_POLL_RESULT); - - WifiNl80211Manager.SignalPollResult pollResult = mWifiNative.signalPoll(WIFI_IFACE_NAME); - assertEquals(SIGNAL_POLL_RESULT.currentRssiDbm, pollResult.currentRssiDbm); - assertEquals(SIGNAL_POLL_RESULT.txBitrateMbps, pollResult.txBitrateMbps); - assertEquals(SIGNAL_POLL_RESULT.associationFrequencyMHz, - pollResult.associationFrequencyMHz); - assertEquals(SIGNAL_POLL_RESULT.rxBitrateMbps, pollResult.rxBitrateMbps); - - verify(mWificondControl).signalPoll(WIFI_IFACE_NAME); - } - - /** - * Verifies that scan() calls underlying WificondControl. - */ - @Test - public void testScan() throws Exception { - mWifiNative.scan(WIFI_IFACE_NAME, WifiScanner.SCAN_TYPE_HIGH_ACCURACY, SCAN_FREQ_SET, - SCAN_HIDDEN_NETWORK_SSID_SET); - ArgumentCaptor<List<byte[]>> ssidSetCaptor = ArgumentCaptor.forClass(List.class); - verify(mWificondControl).startScan( - eq(WIFI_IFACE_NAME), eq(WifiScanner.SCAN_TYPE_HIGH_ACCURACY), - eq(SCAN_FREQ_SET), ssidSetCaptor.capture()); - List<byte[]> ssidSet = ssidSetCaptor.getValue(); - assertArrayEquals(ssidSet.toArray(), SCAN_HIDDEN_NETWORK_BYTE_SSID_SET.toArray()); - } - - /** - * Verifies that startPnoscan() calls underlying WificondControl. - */ - @Test - public void testStartPnoScanOnRequestProcessed() throws Exception { - mWifiNative.startPnoScan(WIFI_IFACE_NAME, TEST_PNO_SETTINGS); - - ArgumentCaptor<WifiNl80211Manager.PnoScanRequestCallback> captor = - ArgumentCaptor.forClass(WifiNl80211Manager.PnoScanRequestCallback.class); - verify(mWificondControl).startPnoScan(eq(WIFI_IFACE_NAME), - eq(TEST_PNO_SETTINGS.toNativePnoSettings()), any(), captor.capture()); - captor.getValue().onPnoRequestSucceeded(); - verify(mWifiMetrics).incrementPnoScanStartAttemptCount(); - } - - /** - * Verifies that startPnoscan() calls underlying WificondControl. - */ - @Test - public void testStartPnoScanOnRequestFailed() throws Exception { - mWifiNative.startPnoScan(WIFI_IFACE_NAME, TEST_PNO_SETTINGS); - - ArgumentCaptor<WifiNl80211Manager.PnoScanRequestCallback> captor = - ArgumentCaptor.forClass(WifiNl80211Manager.PnoScanRequestCallback.class); - verify(mWificondControl).startPnoScan(eq(WIFI_IFACE_NAME), - eq(TEST_PNO_SETTINGS.toNativePnoSettings()), any(), captor.capture()); - captor.getValue().onPnoRequestFailed(); - verify(mWifiMetrics).incrementPnoScanStartAttemptCount(); - verify(mWifiMetrics).incrementPnoScanFailedCount(); - } - - /** - * Verifies that stopPnoscan() calls underlying WificondControl. - */ - @Test - public void testStopPnoScan() throws Exception { - mWifiNative.stopPnoScan(WIFI_IFACE_NAME); - verify(mWificondControl).stopPnoScan(WIFI_IFACE_NAME); - } - - /** - * Verifies that getScanResults() can parse NativeScanResult from wificond correctly, - */ - @Test - public void testGetScanResults() { - // Mock the returned array of NativeScanResult. - List<NativeScanResult> mockScanResults = Arrays.asList(MOCK_NATIVE_SCAN_RESULT); - when(mWificondControl.getScanResults(anyString(), anyInt())).thenReturn(mockScanResults); - - ArrayList<ScanDetail> returnedScanResults = mWifiNative.getScanResults(WIFI_IFACE_NAME); - assertEquals(mockScanResults.size(), returnedScanResults.size()); - // Since NativeScanResult is organized differently from ScanResult, this only checks - // a few fields. - for (int i = 0; i < mockScanResults.size(); i++) { - assertArrayEquals(mockScanResults.get(i).getSsid(), - returnedScanResults.get(i).getScanResult().SSID.getBytes()); - assertEquals(mockScanResults.get(i).getFrequencyMhz(), - returnedScanResults.get(i).getScanResult().frequency); - assertEquals(mockScanResults.get(i).getTsf(), - returnedScanResults.get(i).getScanResult().timestamp); - } - } - - /** - * Verifies that getScanResults() can parse NativeScanResult from wificond correctly, - * when there is radio chain info. - */ - @Test - public void testGetScanResultsWithRadioChainInfo() throws Exception { - // Mock the returned array of NativeScanResult. - NativeScanResult nativeScanResult = createMockNativeScanResult(); - // Add radio chain info - List<RadioChainInfo> nativeRadioChainInfos = Arrays.asList( - MOCK_NATIVE_RADIO_CHAIN_INFO_1, MOCK_NATIVE_RADIO_CHAIN_INFO_2); - nativeScanResult.radioChainInfos = nativeRadioChainInfos; - List<NativeScanResult> mockScanResults = Arrays.asList(nativeScanResult); - - when(mWificondControl.getScanResults(anyString(), anyInt())).thenReturn(mockScanResults); - - ArrayList<ScanDetail> returnedScanResults = mWifiNative.getScanResults(WIFI_IFACE_NAME); - assertEquals(mockScanResults.size(), returnedScanResults.size()); - // Since NativeScanResult is organized differently from ScanResult, this only checks - // a few fields. - for (int i = 0; i < mockScanResults.size(); i++) { - assertArrayEquals(mockScanResults.get(i).getSsid(), - returnedScanResults.get(i).getScanResult().SSID.getBytes()); - assertEquals(mockScanResults.get(i).getFrequencyMhz(), - returnedScanResults.get(i).getScanResult().frequency); - assertEquals(mockScanResults.get(i).getTsf(), - returnedScanResults.get(i).getScanResult().timestamp); - ScanResult.RadioChainInfo[] scanRcis = returnedScanResults.get( - i).getScanResult().radioChainInfos; - assertEquals(nativeRadioChainInfos.size(), scanRcis.length); - for (int j = 0; j < scanRcis.length; ++j) { - assertEquals(nativeRadioChainInfos.get(j).getChainId(), scanRcis[j].id); - assertEquals(nativeRadioChainInfos.get(j).getLevelDbm(), scanRcis[j].level); - } - } - } - - /** - * Verifies that connectToNetwork() calls underlying WificondControl and SupplicantStaIfaceHal. - */ - @Test - public void testConnectToNetwork() throws Exception { - WifiConfiguration config = mock(WifiConfiguration.class); - mWifiNative.connectToNetwork(WIFI_IFACE_NAME, config); - // connectToNetwork() should abort ongoing scan before connection. - verify(mWificondControl).abortScan(WIFI_IFACE_NAME); - verify(mStaIfaceHal).connectToNetwork(WIFI_IFACE_NAME, config); - } - - /** - * Verifies that roamToNetwork() calls underlying WificondControl and SupplicantStaIfaceHal. - */ - @Test - public void testRoamToNetwork() throws Exception { - WifiConfiguration config = mock(WifiConfiguration.class); - mWifiNative.roamToNetwork(WIFI_IFACE_NAME, config); - // roamToNetwork() should abort ongoing scan before connection. - verify(mWificondControl).abortScan(WIFI_IFACE_NAME); - verify(mStaIfaceHal).roamToNetwork(WIFI_IFACE_NAME, config); - } - - /** - * Verifies that setMacAddress() calls underlying WifiVendorHal. - */ - @Test - public void testSetMacAddress() throws Exception { - mWifiNative.setMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS); - verify(mStaIfaceHal).disconnect(WIFI_IFACE_NAME); - verify(mWifiVendorHal).setMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS); - } - - /** - * Verifies that isSetMacAddressSupported() calls underlying WifiVendorHal. - */ - @Test - public void testIsSetMacAddressSupported() throws Exception { - mWifiNative.isSetMacAddressSupported(WIFI_IFACE_NAME); - verify(mWifiVendorHal).isSetMacAddressSupported(WIFI_IFACE_NAME); - } - - /** - * Test that selectTxPowerScenario() calls into WifiVendorHal (success case) - */ - @Test - public void testSelectTxPowerScenario_success() throws Exception { - when(mWifiVendorHal.selectTxPowerScenario(any(SarInfo.class))).thenReturn(true); - SarInfo sarInfo = new SarInfo(); - assertTrue(mWifiNative.selectTxPowerScenario(sarInfo)); - verify(mWifiVendorHal).selectTxPowerScenario(sarInfo); - } - - /** - * Test that selectTxPowerScenario() calls into WifiVendorHal (failure case) - */ - @Test - public void testSelectTxPowerScenario_failure() throws Exception { - when(mWifiVendorHal.selectTxPowerScenario(any(SarInfo.class))).thenReturn(false); - SarInfo sarInfo = new SarInfo(); - assertFalse(mWifiNative.selectTxPowerScenario(sarInfo)); - verify(mWifiVendorHal).selectTxPowerScenario(sarInfo); - } - - /** - * Test that setPowerSave() with true, results in calling into SupplicantStaIfaceHal - */ - @Test - public void testSetPowerSaveTrue() throws Exception { - mWifiNative.setPowerSave(WIFI_IFACE_NAME, true); - verify(mStaIfaceHal).setPowerSave(WIFI_IFACE_NAME, true); - } - - /** - * Test that setPowerSave() with false, results in calling into SupplicantStaIfaceHal - */ - @Test - public void testSetPowerSaveFalse() throws Exception { - mWifiNative.setPowerSave(WIFI_IFACE_NAME, false); - verify(mStaIfaceHal).setPowerSave(WIFI_IFACE_NAME, false); - } - - /** - * Test that setLowLatencyMode() with true, results in calling into WifiVendorHal - */ - @Test - public void testLowLatencyModeTrue() throws Exception { - when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(true); - assertTrue(mWifiNative.setLowLatencyMode(true)); - verify(mWifiVendorHal).setLowLatencyMode(true); - } - - /** - * Test that setLowLatencyMode() with false, results in calling into WifiVendorHal - */ - @Test - public void testLowLatencyModeFalse() throws Exception { - when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(true); - assertTrue(mWifiNative.setLowLatencyMode(false)); - verify(mWifiVendorHal).setLowLatencyMode(false); - } - - /** - * Test that setLowLatencyMode() returns with failure when WifiVendorHal fails. - */ - @Test - public void testSetLowLatencyModeFail() throws Exception { - final boolean lowLatencyMode = true; - when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(false); - assertFalse(mWifiNative.setLowLatencyMode(lowLatencyMode)); - verify(mWifiVendorHal).setLowLatencyMode(lowLatencyMode); - } - - @Test - public void testGetFactoryMacAddress() throws Exception { - when(mWifiVendorHal.getFactoryMacAddress(any())).thenReturn(MacAddress.BROADCAST_ADDRESS); - assertNotNull(mWifiNative.getFactoryMacAddress(WIFI_IFACE_NAME)); - verify(mWifiVendorHal).getFactoryMacAddress(any()); - } - - /** - * Test that flushRingBufferData(), results in calling into WifiVendorHal - */ - @Test - public void testFlushRingBufferDataTrue() throws Exception { - when(mWifiVendorHal.flushRingBufferData()).thenReturn(true); - assertTrue(mWifiNative.flushRingBufferData()); - verify(mWifiVendorHal).flushRingBufferData(); - } - - /** - * Tests that WifiNative#sendMgmtFrame() calls WificondControl#sendMgmtFrame() - */ - @Test - public void testSendMgmtFrame() { - mWifiNative.sendMgmtFrame(WIFI_IFACE_NAME, FATE_REPORT_FRAME_BYTES, - mSendMgmtFrameCallback, TEST_MCS_RATE); - - verify(mWificondControl).sendMgmtFrame(eq(WIFI_IFACE_NAME), - AdditionalMatchers.aryEq(FATE_REPORT_FRAME_BYTES), eq(TEST_MCS_RATE), - any(), eq(mSendMgmtFrameCallback)); - } - - /** - * Tests that probeLink() generates the correct frame and calls WificondControl#sendMgmtFrame(). - */ - @Test - public void testProbeLinkSuccess() { - byte[] expectedFrame = { - 0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, - 0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09, - (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66, - 0x00, 0x00 - }; - - when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(TEST_MAC_ADDRESS_STR); - - when(mRandom.nextInt()).thenReturn(TEST_SEQUENCE_NUM); - - mWifiNative.probeLink(WIFI_IFACE_NAME, MacAddress.fromString(TEST_BSSID_STR), - mSendMgmtFrameCallback, TEST_MCS_RATE); - - verify(mSendMgmtFrameCallback, never()).onFailure(anyInt()); - verify(mWificondControl).sendMgmtFrame(eq(WIFI_IFACE_NAME), - AdditionalMatchers.aryEq(expectedFrame), eq(TEST_MCS_RATE), - any(), eq(mSendMgmtFrameCallback)); - } - - /** - * Tests that probeLink() triggers the failure callback when it cannot get the sender MAC - * address. - */ - @Test - public void testProbeLinkFailureCannotGetSenderMac() { - when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(null); - - mWifiNative.probeLink(WIFI_IFACE_NAME, MacAddress.fromString(TEST_BSSID_STR), - mSendMgmtFrameCallback, TEST_MCS_RATE); - - verify(mSendMgmtFrameCallback).onFailure( - WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN); - verify(mWificondControl, never()).sendMgmtFrame(any(), any(), anyInt(), any(), any()); - } - - /** - * Tests that probeLink() triggers the failure callback when it cannot get the BSSID. - */ - @Test - public void testProbeLinkFailureCannotGetBssid() { - when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(TEST_MAC_ADDRESS_STR); - - mWifiNative.probeLink(WIFI_IFACE_NAME, null, mSendMgmtFrameCallback, TEST_MCS_RATE); - - verify(mSendMgmtFrameCallback).onFailure( - WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN); - verify(mWificondControl, never()).sendMgmtFrame(any(), any(), anyInt(), any(), any()); - } - - /** - * Tests that WifiNative#addHlpReq() calls - * SupplicantStaIfaceHal#addHlpReq() - */ - @Test - public void testaddHlpReq() { - byte[] hlpPacket = { - 0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, - 0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09, - (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66, - 0x00, 0x00 - }; - mWifiNative.addHlpReq(WIFI_IFACE_NAME, TEST_MAC_ADDRESS, hlpPacket); - - verify(mStaIfaceHal).addHlpReq(eq(WIFI_IFACE_NAME), - eq(TEST_MAC_ADDRESS.toByteArray()), eq(hlpPacket)); - } - - /** - * Tests that WifiNative#flushAllHlp() calls - * SupplicantStaIfaceHal#flushAllHlp() - */ - @Test - public void testflushAllHlp() { - mWifiNative.flushAllHlp(WIFI_IFACE_NAME); - - verify(mStaIfaceHal).flushAllHlp(eq(WIFI_IFACE_NAME)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java deleted file mode 100644 index f6621a698..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ /dev/null @@ -1,3124 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; -import static android.net.NetworkFactory.CMD_REQUEST_NETWORK; - -import static com.android.server.wifi.WifiNetworkFactory.PERIODIC_SCAN_INTERVAL_MS; -import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.app.AlarmManager; -import android.app.AlarmManager.OnAlarmListener; -import android.app.AppOpsManager; -import android.companion.CompanionDeviceManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.MacAddress; -import android.net.NetworkCapabilities; -import android.net.NetworkProvider; -import android.net.NetworkRequest; -import android.net.wifi.IActionListener; -import android.net.wifi.INetworkRequestMatchCallback; -import android.net.wifi.INetworkRequestUserSelectionCallback; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiNetworkSpecifier; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ScanListener; -import android.net.wifi.WifiScanner.ScanSettings; -import android.net.wifi.WifiSsid; -import android.os.Binder; -import android.os.IBinder; -import android.os.Message; -import android.os.PatternMatcher; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.WorkSource; -import android.os.test.TestLooper; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Pair; -import android.util.Xml; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.WifiNetworkFactory.AccessPoint; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.ScanResultUtil; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.WifiNetworkFactory}. - */ -@SmallTest -public class WifiNetworkFactoryTest extends WifiBaseTest { - private static final int TEST_NETWORK_ID_1 = 104; - private static final int TEST_UID_1 = 10423; - private static final int TEST_UID_2 = 10424; - private static final int TEST_CALLBACK_IDENTIFIER = 123; - private static final String TEST_PACKAGE_NAME_1 = "com.test.networkrequest.1"; - private static final String TEST_PACKAGE_NAME_2 = "com.test.networkrequest.2"; - private static final String TEST_APP_NAME = "app"; - private static final String TEST_SSID_1 = "test1234"; - private static final String TEST_SSID_2 = "test12345678"; - private static final String TEST_SSID_3 = "abc1234"; - private static final String TEST_SSID_4 = "abc12345678"; - private static final String TEST_BSSID_1 = "12:34:23:23:45:ac"; - private static final String TEST_BSSID_2 = "12:34:23:32:12:67"; - private static final String TEST_BSSID_3 = "45:34:34:12:bb:dd"; - private static final String TEST_BSSID_4 = "45:34:34:56:ee:ff"; - private static final String TEST_BSSID_1_2_OUI = "12:34:23:00:00:00"; - private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00"; - private static final String TEST_WPA_PRESHARED_KEY = "\"password123\""; - - @Mock Context mContext; - @Mock ActivityManager mActivityManager; - @Mock AlarmManager mAlarmManager; - @Mock AppOpsManager mAppOpsManager; - @Mock CompanionDeviceManager mCompanionDeviceManager; - @Mock Clock mClock; - @Mock WifiInjector mWifiInjector; - @Mock WifiConnectivityManager mWifiConnectivityManager; - @Mock WifiConfigManager mWifiConfigManager; - @Mock WifiConfigStore mWifiConfigStore; - @Mock WifiPermissionsUtil mWifiPermissionsUtil; - @Mock WifiScanner mWifiScanner; - @Mock PackageManager mPackageManager; - @Mock IBinder mAppBinder; - @Mock INetworkRequestMatchCallback mNetworkRequestMatchCallback; - @Mock ClientModeImpl mClientModeImpl; - @Mock ConnectivityManager mConnectivityManager; - @Mock WifiMetrics mWifiMetrics; - @Mock NetworkProvider mNetworkProvider; - NetworkCapabilities mNetworkCapabilities; - TestLooper mLooper; - NetworkRequest mNetworkRequest; - WifiScanner.ScanData[] mTestScanDatas; - WifiConfiguration mSelectedNetwork; - ArgumentCaptor<ScanSettings> mScanSettingsArgumentCaptor = - ArgumentCaptor.forClass(ScanSettings.class); - ArgumentCaptor<WorkSource> mWorkSourceArgumentCaptor = - ArgumentCaptor.forClass(WorkSource.class); - ArgumentCaptor<INetworkRequestUserSelectionCallback> mNetworkRequestUserSelectionCallback = - ArgumentCaptor.forClass(INetworkRequestUserSelectionCallback.class); - ArgumentCaptor<OnAlarmListener> mPeriodicScanListenerArgumentCaptor = - ArgumentCaptor.forClass(OnAlarmListener.class); - ArgumentCaptor<OnAlarmListener> mConnectionTimeoutAlarmListenerArgumentCaptor = - ArgumentCaptor.forClass(OnAlarmListener.class); - ArgumentCaptor<ScanListener> mScanListenerArgumentCaptor = - ArgumentCaptor.forClass(ScanListener.class); - ArgumentCaptor<IActionListener> mConnectListenerArgumentCaptor = - ArgumentCaptor.forClass(IActionListener.class); - InOrder mInOrder; - - private WifiNetworkFactory mWifiNetworkFactory; - private NetworkRequestStoreData.DataSource mDataSource; - private NetworkRequestStoreData mNetworkRequestStoreData; - - /** - * Setup the mocks. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mLooper = new TestLooper(); - mNetworkCapabilities = new NetworkCapabilities(); - mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); - mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - mTestScanDatas = ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 } }); - - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))) - .thenReturn(mConnectivityManager); - when(mContext.getSystemService(CompanionDeviceManager.class)) - .thenReturn(mCompanionDeviceManager); - when(mPackageManager.getNameForUid(TEST_UID_1)).thenReturn(TEST_PACKAGE_NAME_1); - when(mPackageManager.getNameForUid(TEST_UID_2)).thenReturn(TEST_PACKAGE_NAME_2); - when(mPackageManager.getApplicationInfoAsUser(any(), anyInt(), any())) - .thenReturn(new ApplicationInfo()); - when(mPackageManager.getApplicationLabel(any())).thenReturn(TEST_APP_NAME); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); - when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl); - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), anyString())) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID_1)); - when(mWifiScanner.getSingleScanResults()).thenReturn(Collections.emptyList()); - - mWifiNetworkFactory = new WifiNetworkFactory(mLooper.getLooper(), mContext, - mNetworkCapabilities, mActivityManager, mAlarmManager, mAppOpsManager, - mClock, mWifiInjector, mWifiConnectivityManager, - mWifiConfigManager, mWifiConfigStore, mWifiPermissionsUtil, mWifiMetrics); - - ArgumentCaptor<NetworkRequestStoreData.DataSource> dataSourceArgumentCaptor = - ArgumentCaptor.forClass(NetworkRequestStoreData.DataSource.class); - verify(mWifiInjector).makeNetworkRequestStoreData(dataSourceArgumentCaptor.capture()); - mDataSource = dataSourceArgumentCaptor.getValue(); - assertNotNull(mDataSource); - mNetworkRequestStoreData = new NetworkRequestStoreData(mDataSource); - - // Register factory with connectivity manager. - mWifiNetworkFactory.register(); - ArgumentCaptor<NetworkProvider> networkProviderArgumentCaptor = - ArgumentCaptor.forClass(NetworkProvider.class); - verify(mConnectivityManager).registerNetworkProvider( - networkProviderArgumentCaptor.capture()); - mNetworkProvider = networkProviderArgumentCaptor.getValue(); - assertNotNull(mNetworkProvider); - mLooper.dispatchAll(); - - mNetworkRequest = new NetworkRequest.Builder() - .setCapabilities(mNetworkCapabilities) - .build(); - - // Setup with wifi on. - mWifiNetworkFactory.setWifiState(true); - mWifiNetworkFactory.enableVerboseLogging(1); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - /** - * Validates handling of needNetworkFor. - */ - @Test - public void testHandleNetworkRequestWithNoSpecifier() { - assertFalse(mWifiNetworkFactory.hasConnectionRequests()); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // First network request should turn on auto-join. - verify(mWifiConnectivityManager).setTrustedConnectionAllowed(true); - assertTrue(mWifiNetworkFactory.hasConnectionRequests()); - - // Subsequent ones should do nothing. - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - verifyNoMoreInteractions(mWifiConnectivityManager); - } - - /** - * Validates handling of releaseNetwork. - */ - @Test - public void testHandleNetworkReleaseWithNoSpecifier() { - // Release network with out a corresponding request should be ignored. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - assertFalse(mWifiNetworkFactory.hasConnectionRequests()); - - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - assertTrue(mWifiNetworkFactory.hasConnectionRequests()); - verify(mWifiConnectivityManager).setTrustedConnectionAllowed(true); - - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - assertFalse(mWifiNetworkFactory.hasConnectionRequests()); - verify(mWifiConnectivityManager).setTrustedConnectionAllowed(false); - } - - /** - * Validates handling of acceptNetwork for requests with no network specifier. - */ - @Test - public void testHandleAcceptNetworkRequestWithNoSpecifier() { - assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - } - - /** - * Validates handling of acceptNetwork with a network specifier with invalid uid/package name. - */ - @Test - public void testHandleAcceptNetworkRequestFromWithInvalidSpecifier() throws Exception { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_GONE); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(TEST_UID_1)) - .thenReturn(true); - doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString()); - - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - - assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - mLooper.dispatchAll(); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Validates handling of acceptNetwork with a network specifier with internet capability. - */ - @Test - public void testHandleAcceptNetworkRequestFromWithInternetCapability() throws Exception { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND); - - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mNetworkRequest.networkCapabilities.addCapability( - NetworkCapabilities.NET_CAPABILITY_INTERNET); - - assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - mLooper.dispatchAll(); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from a non foreground - * app/service. - */ - @Test - public void testHandleAcceptNetworkRequestFromNonFgAppOrSvcWithSpecifier() throws Exception { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE + 1); - - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - - assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - mLooper.dispatchAll(); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from a foreground - * app. - */ - @Test - public void testHandleAcceptNetworkRequestFromFgAppWithSpecifier() { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND); - - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - - assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from apps holding - * NETWORK_SETTINGS. - */ - @Test - public void testHandleAcceptNetworkRequestFromNetworkSettingAppWithSpecifier() { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_GONE); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(TEST_UID_1)) - .thenReturn(true); - - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - - assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from a foreground - * app. - */ - @Test - public void testHandleAcceptNetworkRequestFromFgAppWithSpecifierWithPendingRequestFromFgSvc() { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(IMPORTANCE_FOREGROUND); - - // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Make request 2 which will be accepted because a fg app request can - // override a fg service request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from a foreground - * app. - */ - @Test - public void testHandleAcceptNetworkRequestFromFgSvcWithSpecifierWithPendingRequestFromFgSvc() { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE); - - // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Make request 2 which will be accepted because a fg service request can - // override an existing fg service request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from a foreground - * app. - */ - @Test - public void testHandleAcceptNetworkRequestFromFgAppWithSpecifierWithPendingRequestFromFgApp() { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(IMPORTANCE_FOREGROUND); - - // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Make request 2 which will be accepted because a fg app request can - // override an existing fg app request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from a foreground - * service when we're in the midst of processing a request from a foreground app. - */ - @Test - public void testHandleAcceptNetworkRequestFromFgSvcWithSpecifierWithPendingRequestFromFgApp() - throws Exception { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE); - - // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Make request 2 which will be rejected because a fg service request cannot - // override a fg app request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - mLooper.dispatchAll(); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from a foreground - * app when we're connected to a request from a foreground app. - */ - @Test - public void - testHandleAcceptNetworkRequestFromFgAppWithSpecifierWithConnectedRequestFromFgApp() - throws Exception { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(IMPORTANCE_FOREGROUND); - - // Connect to request 1 - sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - - // Make request 2 which will be accepted because a fg app request can - // override an existing fg app request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - } - - /** - * Validates handling of acceptNetwork with a network specifier from a foreground - * service when we're connected to a request from a foreground app. - */ - @Test - public void - testHandleAcceptNetworkRequestFromFgSvcWithSpecifierWithConnectedRequestFromFgApp() - throws Exception { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND); - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_2)) - .thenReturn(IMPORTANCE_FOREGROUND_SERVICE); - - // Connect to request 1 - sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - - // Make request 2 which will be rejected because a fg service request cannot - // override a fg app request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - mLooper.dispatchAll(); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Verify handling of new network request with network specifier. - */ - @Test - public void testHandleNetworkRequestWithSpecifier() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Verify UI start. - validateUiStartParams(true); - - // Verify scan settings. - verify(mWifiScanner).startScan(mScanSettingsArgumentCaptor.capture(), any(), any(), - mWorkSourceArgumentCaptor.capture()); - validateScanSettings(null); - - verify(mWifiMetrics).incrementNetworkRequestApiNumRequest(); - } - - /** - * Validates handling of new network request with network specifier with internet capability. - */ - @Test - public void testHandleNetworkRequestWithSpecifierAndInternetCapability() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mNetworkRequest.networkCapabilities.addCapability( - NetworkCapabilities.NET_CAPABILITY_INTERNET); - - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mLooper.dispatchAll(); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Verify handling of new network request with network specifier for a hidden network. - */ - @Test - public void testHandleNetworkRequestWithSpecifierForHiddenNetwork() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Verify UI start. - validateUiStartParams(true); - - // Verify scan settings. - verify(mWifiScanner).startScan(mScanSettingsArgumentCaptor.capture(), any(), any(), - mWorkSourceArgumentCaptor.capture()); - validateScanSettings( - ((WifiNetworkSpecifier) mNetworkCapabilities.getNetworkSpecifier()) - .ssidPatternMatcher.getPath()); - - verify(mWifiMetrics).incrementNetworkRequestApiNumRequest(); - } - - /** - * Verify handling of new network request with network specifier for a non-hidden network - * after processing a previous hidden network requst. - * Validates that the scan settings was properly reset between the 2 request - * {@link ScanSettings#hiddenNetworks} - */ - @Test - public void testHandleNetworkRequestWithSpecifierAfterPreviousHiddenNetworkRequest() { - // Hidden request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - // Verify scan settings. - verify(mWifiScanner, times(1)).startScan(mScanSettingsArgumentCaptor.capture(), any(), - any(), mWorkSourceArgumentCaptor.capture()); - validateScanSettings( - ((WifiNetworkSpecifier) mNetworkCapabilities.getNetworkSpecifier()) - .ssidPatternMatcher.getPath()); - - // Release request 1. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - - // Regular request 2. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - // Verify scan settings. - verify(mWifiScanner, times(2)).startScan(mScanSettingsArgumentCaptor.capture(), any(), - any(), mWorkSourceArgumentCaptor.capture()); - validateScanSettings(null); - - verify(mWifiMetrics, times(2)).incrementNetworkRequestApiNumRequest(); - } - - /** - * Verify handling of release of the active network request with network specifier. - */ - @Test - public void testHandleNetworkReleaseWithSpecifier() { - // Make a generic request first to ensure that we re-enable auto-join after release. - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - - // Make the network request with specifier. - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - verify(mWifiScanner).startScan(any(), any(), any(), any()); - - // Release the network request. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - // Verify that we did not trigger a disconnect because we've not yet connected. - verify(mClientModeImpl, never()).disconnectCommand(); - // Re-enable connectivity manager . - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - - verify(mWifiMetrics).incrementNetworkRequestApiNumRequest(); - } - - /** - * Verify the periodic scan to find a network matching the network specifier. - * Simulates the case where the network is not found in any of the scan results. - */ - @Test - public void testPeriodicScanNetworkRequestWithSpecifier() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - verifyPeriodicScans(0, - PERIODIC_SCAN_INTERVAL_MS, // 10s - PERIODIC_SCAN_INTERVAL_MS, // 10s - PERIODIC_SCAN_INTERVAL_MS, // 10s - PERIODIC_SCAN_INTERVAL_MS); // 10s - } - - /** - * Verify the periodic scan back off to find a network matching the network specifier - * is cancelled when the active network request is released. - */ - @Test - public void testPeriodicScanCancelOnReleaseNetworkRequestWithSpecifier() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - verifyPeriodicScans(0, - PERIODIC_SCAN_INTERVAL_MS, // 10s - PERIODIC_SCAN_INTERVAL_MS); // 10s - - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - // Cancel the alarm set for the next scan. - verify(mAlarmManager).cancel(any(OnAlarmListener.class)); - } - - /** - * Verify the periodic scan back off to find a network matching the network specifier - * is cancelled when the user selects a network. - */ - @Test - public void testPeriodicScanCancelOnUserSelectNetwork() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( - mNetworkRequestUserSelectionCallback.capture()); - - verifyPeriodicScans(0, - PERIODIC_SCAN_INTERVAL_MS, // 10s - PERIODIC_SCAN_INTERVAL_MS); // 10s - - // Now trigger user selection to one of the network. - mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - mSelectedNetwork.SSID = "\"" + TEST_SSID_1 + "\""; - sendUserSelectionSelect(mNetworkRequestUserSelectionCallback.getValue(), mSelectedNetwork); - mLooper.dispatchAll(); - - // Cancel the alarm set for the next scan. - verify(mAlarmManager).cancel(mPeriodicScanListenerArgumentCaptor.getValue()); - } - - - /** - * Verify callback registration/unregistration. - */ - @Test - public void testHandleCallbackRegistrationAndUnregistration() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - //Ensure that we register the user selection callback using the newly registered callback. - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( - any(INetworkRequestUserSelectionCallback.class)); - - mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); - - verifyNoMoreInteractions(mNetworkRequestMatchCallback); - } - - /** - * Verify callback registration when the active request has already been released.. - */ - @Test - public void testHandleCallbackRegistrationWithNoActiveRequest() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - //Ensure that we trigger the onAbort callback & nothing else. - verify(mNetworkRequestMatchCallback).onAbort(); - - mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); - - verifyNoMoreInteractions(mNetworkRequestMatchCallback); - } - - /** - * Verify network specifier matching for a specifier containing a specific SSID match using - * 4 WPA_PSK scan results, each with unique SSID. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidMatch() throws Exception { - // Setup scan data for open networks. - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(true); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); - // We only expect 1 network match in this case. - validateScanResults(matchedScanResultsCaptor.getValue(), mTestScanDatas[0].getResults()[0]); - - verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResultsCaptor.getValue().size()); - } - - /** - * Verify network specifier matching for a specifier containing a specific SSID match using - * 4 WPA_PSK + SAE transition scan results, each with unique SSID. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidMatchForSaeTransitionScanResult() - throws Exception { - setupScanData(SCAN_RESULT_TYPE_WPA_PSK_SAE_TRANSITION, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(true); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); - // We only expect 1 network match in this case. - validateScanResults(matchedScanResultsCaptor.getValue(), mTestScanDatas[0].getResults()[0]); - - verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResultsCaptor.getValue().size()); - } - - /** - * Verify network specifier matching for a specifier containing a Prefix SSID match using - * 4 open scan results, each with unique SSID. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingPrefixSsidMatch() throws Exception { - // Setup scan data for open networks. - setupScanData(SCAN_RESULT_TYPE_OPEN, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_PREFIX); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(false); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); - // We expect 2 scan result matches in this case. - validateScanResults(matchedScanResultsCaptor.getValue(), - mTestScanDatas[0].getResults()[0], mTestScanDatas[0].getResults()[1]); - - verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResultsCaptor.getValue().size()); - } - - /** - * Verify network specifier matching for a specifier containing a specific BSSID match using - * 4 WPA_PSK scan results, each with unique SSID. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralBssidMatch() throws Exception { - // Setup scan data for open networks. - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(TEST_BSSID_1), MacAddress.BROADCAST_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(true); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); - // We only expect 1 scan result match in this case. - validateScanResults(matchedScanResultsCaptor.getValue(), mTestScanDatas[0].getResults()[0]); - - verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResultsCaptor.getValue().size()); - } - - /** - * Verify network specifier matching for a specifier containing a prefix BSSID match using - * 4 WPA_EAP scan results, each with unique SSID. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingOuiPrefixBssidMatch() throws Exception { - // Setup scan data for open networks. - setupScanData(SCAN_RESULT_TYPE_WPA_EAP, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(TEST_BSSID_1_2_OUI), - MacAddress.fromString(TEST_BSSID_OUI_MASK)); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(false); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); - // We expect 2 scan result matches in this case. - validateScanResults(matchedScanResultsCaptor.getValue(), - mTestScanDatas[0].getResults()[0], mTestScanDatas[0].getResults()[1]); - - verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResultsCaptor.getValue().size()); - } - - /** - * Verify network specifier matching for a specifier containing a specific SSID match using - * 4 WPA_PSK scan results, 3 of which have the same SSID. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidMatchWithMultipleBssidMatches() - throws Exception { - // Setup scan data for open networks. - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_1, TEST_SSID_1, TEST_SSID_2); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(true); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); - // We expect 3 scan result matches in this case. - validateScanResults(matchedScanResultsCaptor.getValue(), - mTestScanDatas[0].getResults()[0], mTestScanDatas[0].getResults()[1], - mTestScanDatas[0].getResults()[2]); - - verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResultsCaptor.getValue().size()); - } - - /** - * Verify network specifier match failure for a specifier containing a specific SSID match using - * 4 WPA_PSK scan results, 2 of which SSID_1 and the other 2 SSID_2. But, none of the scan - * results' SSID match the one requested in the specifier. - */ - @Test - public void testNetworkSpecifierMatchFailUsingLiteralSsidMatchWhenSsidNotFound() - throws Exception { - // Setup scan data for open networks. - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_1, TEST_SSID_2, TEST_SSID_2); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_3, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(true); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - // We expect no network match in this case. - verify(mNetworkRequestMatchCallback, never()).onMatch(any()); - - // Don't increment metrics until we have a match - verify(mWifiMetrics, never()).incrementNetworkRequestApiMatchSizeHistogram(anyInt()); - } - - /** - * Verify network specifier match failure for a specifier containing a specific SSID match using - * 4 open scan results, each with unique SSID. But, none of the scan - * results' key mgmt match the one requested in the specifier. - */ - @Test - public void testNetworkSpecifierMatchFailUsingLiteralSsidMatchWhenKeyMgmtDiffers() - throws Exception { - // Setup scan data for open networks. - setupScanData(SCAN_RESULT_TYPE_OPEN, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(true); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - // We expect no network match in this case. - verify(mNetworkRequestMatchCallback, never()).onMatch(any()); - } - - /** - * Verify handling of stale user selection (previous request released). - */ - @Test - public void testNetworkSpecifierHandleUserSelectionConnectToNetworkWithoutActiveRequest() - throws Exception { - sendNetworkRequestAndSetupForUserSelection(); - - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - - // Now release the active network request. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - // Re-enable connectivity manager (if it was disabled). - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - - // Now trigger user selection to some network. - WifiConfiguration selectedNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - sendUserSelectionSelect(networkRequestUserSelectionCallback, selectedNetwork); - mLooper.dispatchAll(); - - // Verify we did not attempt to trigger a connection or disable connectivity manager. - verifyNoMoreInteractions(mClientModeImpl, mWifiConnectivityManager); - } - - /** - * Verify handling of stale user selection (new request replacing the previous request). - */ - @Test - public void testNetworkSpecifierHandleUserSelectionConnectToNetworkWithDifferentActiveRequest() - throws Exception { - sendNetworkRequestAndSetupForUserSelection(); - - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - - // Now send another network request. - mWifiNetworkFactory.needNetworkFor(new NetworkRequest(mNetworkRequest), 0); - - // Now trigger user selection to some network. - WifiConfiguration selectedNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - sendUserSelectionSelect(networkRequestUserSelectionCallback, selectedNetwork); - mLooper.dispatchAll(); - - // Verify we did not attempt to trigger a connection or disable connectivity manager. - verifyNoMoreInteractions(mClientModeImpl, mWifiConnectivityManager, mWifiConfigManager); - } - - /** - * Verify handling of user selection to trigger connection to a network. - */ - @Test - public void testNetworkSpecifierHandleUserSelectionConnectToNetwork() throws Exception { - sendNetworkRequestAndSetupForUserSelection(); - - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - - // Now trigger user selection to one of the network. - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[0].SSID + "\""; - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Cancel periodic scans. - verify(mAlarmManager).cancel(any(OnAlarmListener.class)); - // Disable connectivity manager - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(true); - - validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID); - verify(mWifiMetrics).setNominatorForNetwork(anyInt(), - eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER)); - - - } - - /** - * Verify when number of user approved access points exceed the capacity, framework should trim - * the Set by removing the least recently used elements. - */ - @Test - public void testNetworkSpecifierHandleUserSelectionConnectToNetworkExceedApprovedListCapacity() - throws Exception { - int userApproveAccessPointCapacity = mWifiNetworkFactory.NUM_OF_ACCESS_POINT_LIMIT_PER_APP; - int numOfApPerSsid = userApproveAccessPointCapacity / 2 + 1; - String[] testIds = new String[]{TEST_SSID_1, TEST_SSID_2}; - - // Setup up scan data - setupScanDataSameSsidWithDiffBssid(SCAN_RESULT_TYPE_WPA_PSK, numOfApPerSsid, testIds); - - // Setup network specifier for WPA-PSK networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_PREFIX); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createPskNetwork(); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - // request network, trigger scan and get matched set. - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( - mNetworkRequestUserSelectionCallback.capture()); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - - // Now trigger user selection to one of the network. - mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[0].SSID + "\""; - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Verifier num of Approved access points. - assertEquals(mWifiNetworkFactory.mUserApprovedAccessPointMap - .get(TEST_PACKAGE_NAME_1).size(), numOfApPerSsid); - - // Now trigger user selection to another network with different SSID. - mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[numOfApPerSsid].SSID + "\""; - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Verify triggered trim when user Approved Access Points exceed capacity. - Set<AccessPoint> userApprovedAccessPoints = mWifiNetworkFactory.mUserApprovedAccessPointMap - .get(TEST_PACKAGE_NAME_1); - assertEquals(userApprovedAccessPoints.size(), userApproveAccessPointCapacity); - long numOfSsid1Aps = userApprovedAccessPoints - .stream() - .filter(a->a.ssid.equals(TEST_SSID_1)) - .count(); - assertEquals(numOfSsid1Aps, userApproveAccessPointCapacity - numOfApPerSsid); - } - - /** - * Verify handling of user selection to trigger connection to an existing saved network. - */ - @Test - public void testNetworkSpecifierHandleUserSelectionConnectToExistingSavedNetwork() - throws Exception { - sendNetworkRequestAndSetupForUserSelection(); - - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - - mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[0].SSID + "\""; - mSelectedNetwork.shared = false; - - // Have a saved network with the same configuration. - WifiConfiguration matchingSavedNetwork = new WifiConfiguration(mSelectedNetwork); - matchingSavedNetwork.networkId = TEST_NETWORK_ID_1; - when(mWifiConfigManager.getConfiguredNetwork(mSelectedNetwork.getKey())) - .thenReturn(matchingSavedNetwork); - - // Now trigger user selection to one of the network. - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Cancel periodic scans. - verify(mAlarmManager).cancel(any(OnAlarmListener.class)); - // Disable connectivity manager - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(true); - - // verify we don't try to add the network to WifiConfigManager. - verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), anyString()); - - verify(mClientModeImpl).disconnectCommand(); - verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class), - mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify handling of user selection to trigger connection to a network. Ensure we fill - * up the BSSID field. - */ - @Test - public void - testNetworkSpecifierHandleUserSelectionConnectToNetworkUsingLiteralSsidAndBssidMatch() - throws Exception { - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Make a specific AP request. - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( - mNetworkRequestUserSelectionCallback.capture()); - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - // Now trigger user selection to the network. - mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult); - mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\""; - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Verify WifiConfiguration params. - validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID); - verify(mWifiMetrics).setNominatorForNetwork(anyInt(), - eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER)); - - verify(mClientModeImpl).disconnectCommand(); - verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class), - mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify handling of user selection to trigger connection to a network. Ensure we fill - * up the BSSID field with scan result for highest RSSI. - */ - @Test - public void - testNetworkSpecifierHandleUserSelectionConnectToNetworkMultipleBssidMatches() - throws Exception { - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_1, TEST_SSID_1, TEST_SSID_4); - - // Make a ssid pattern request which matches 3 scan results - 0, 1, 2. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( - mNetworkRequestUserSelectionCallback.capture()); - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - // Scan result 2 has the highest RSSI, so that should be picked. - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[2]; - - // Now trigger user selection to the network. - mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult); - mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\""; - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Verify WifiConfiguration params. - validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID); - verify(mWifiMetrics).setNominatorForNetwork(anyInt(), - eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER)); - - verify(mClientModeImpl).disconnectCommand(); - verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class), - mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify handling of user selection to trigger connection to a network when the selected bssid - * is no longer seen in scan results within the cache expiry duration. Ensure we fill up the - * BSSID field. - */ - @Test - public void - testNetworkSpecifierHandleUserSelectionConnectToNetworkMissingBssidInLatest() - throws Exception { - WifiScanner.ScanData[] scanDatas1 = - ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }}); - setupScanData(scanDatas1, SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - // Modify the next set of scan results to simulate missing |TEST_SSID_1| ScanResult. - WifiScanner.ScanData[] scanDatas2 = - ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }}); - setupScanData(scanDatas2, SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_2, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Make a specific AP request. - ScanResult matchingScanResult = scanDatas1[0].getResults()[0]; - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( - mNetworkRequestUserSelectionCallback.capture()); - verifyPeriodicScans( - 0L, - new PeriodicScanParams(0, scanDatas1), - new PeriodicScanParams(PERIODIC_SCAN_INTERVAL_MS, scanDatas2)); - - // Now trigger user selection to the network. - mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult); - mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\""; - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Verify WifiConfiguration params. - validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID); - verify(mWifiMetrics).setNominatorForNetwork(anyInt(), - eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER)); - - verify(mClientModeImpl).disconnectCommand(); - verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class), - mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify handling of user selection to trigger connection to a network when the selected bssid - * is no longer seen in scan results beyond the cache expiry duration. Ensure we don't fill up - * the BSSID field. - */ - @Test - public void - testNetworkSpecifierHandleUserSelectionConnectToNetworkStaleMissingBssidInLatest() - throws Exception { - WifiScanner.ScanData[] scanDatas1 = - ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }}); - setupScanData(scanDatas1, SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - // Modify the next set of scan results to simulate missing |TEST_SSID_1| ScanResult. - WifiScanner.ScanData[] scanDatas2 = - ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }}); - setupScanData(scanDatas2, SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_2, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Make a specific AP request. - ScanResult matchingScanResult = scanDatas1[0].getResults()[0]; - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( - mNetworkRequestUserSelectionCallback.capture()); - - long nowMs = WifiNetworkFactory.CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS + 1; - scanDatas2[0].getResults()[0].timestamp = nowMs; - scanDatas2[0].getResults()[1].timestamp = nowMs; - scanDatas2[0].getResults()[2].timestamp = nowMs; - scanDatas2[0].getResults()[3].timestamp = nowMs; - verifyPeriodicScans( - nowMs, - new PeriodicScanParams(0, scanDatas1), - new PeriodicScanParams(PERIODIC_SCAN_INTERVAL_MS, scanDatas2)); - - // Now trigger user selection to the network. - mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult); - mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\""; - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Verify WifiConfiguration params. - validateConnectParams(mSelectedNetwork.SSID, null); - verify(mWifiMetrics).setNominatorForNetwork(anyInt(), - eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER)); - - verify(mClientModeImpl).disconnectCommand(); - verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class), - mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify handling of user selection to reject the request. - */ - @Test - public void testNetworkSpecifierHandleUserSelectionReject() throws Exception { - sendNetworkRequestAndSetupForUserSelection(); - - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - - // Now trigger user rejection. - networkRequestUserSelectionCallback.reject(); - mLooper.dispatchAll(); - - // Cancel periodic scans. - verify(mAlarmManager).cancel(any(OnAlarmListener.class)); - // Verify we reset the network request handling. - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - - verify(mWifiMetrics).incrementNetworkRequestApiNumUserReject(); - - // Verify we did not attempt to trigger a connection. - verifyNoMoreInteractions(mClientModeImpl, mWifiConfigManager); - } - - /** - * Verify handling of connection timeout. - * The timeouts should trigger connection retries until we hit the max. - */ - @Test - public void testNetworkSpecifierHandleConnectionTimeout() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Simulate connection timeout beyond the retry limit to trigger the failure handling. - for (int i = 0; i <= WifiNetworkFactory.USER_SELECTED_NETWORK_CONNECT_RETRY_MAX; i++) { - mConnectionTimeoutAlarmListenerArgumentCaptor.getValue().onAlarm(); - mLooper.dispatchAll(); - } - - mInOrder = inOrder(mAlarmManager, mClientModeImpl); - validateConnectionRetryAttempts(true); - - // Fail the request after all the retries are exhausted. - verify(mNetworkRequestMatchCallback).onAbort(); - // Verify that we sent the connection failure callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // Verify we reset the network request handling. - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Verify handling of connection trigger failure. - * The trigger failures should trigger connection retries until we hit the max. - */ - @Test - public void testNetworkSpecifierHandleConnectionTriggerFailure() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Send failure message beyond the retry limit to trigger the failure handling. - for (int i = 0; i <= WifiNetworkFactory.USER_SELECTED_NETWORK_CONNECT_RETRY_MAX; i++) { - assertNotNull(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - mConnectListenerArgumentCaptor.getValue().onFailure(WifiManager.ERROR); - } - mLooper.dispatchAll(); - - mInOrder = inOrder(mAlarmManager, mClientModeImpl); - validateConnectionRetryAttempts(false); - - // Fail the request after all the retries are exhausted. - verify(mNetworkRequestMatchCallback).onAbort(); - // Verify that we sent the connection failure callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // verify we canceled the timeout alarm. - mInOrder.verify(mAlarmManager).cancel( - mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - // Verify we reset the network request handling. - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Verify handling of connection failure. - * The connection failures should trigger connection retries until we hit the max. - */ - @Test - public void testNetworkSpecifierHandleConnectionFailure() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - assertNotNull(mSelectedNetwork); - - // Send network connection failure indication beyond the retry limit to trigger the failure - // handling. - for (int i = 0; i <= WifiNetworkFactory.USER_SELECTED_NETWORK_CONNECT_RETRY_MAX; i++) { - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, mSelectedNetwork); - mLooper.dispatchAll(); - } - - mInOrder = inOrder(mAlarmManager, mClientModeImpl); - validateConnectionRetryAttempts(false); - - verify(mNetworkRequestMatchCallback).onAbort(); - // Verify that we sent the connection failure callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // verify we canceled the timeout alarm. - mInOrder.verify(mAlarmManager).cancel( - mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - // Verify we reset the network request handling. - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Verify handling of connection failure to a different network. - */ - @Test - public void testNetworkSpecifierHandleConnectionFailureToWrongNetwork() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Send network connection failure to a different network indication. - assertNotNull(mSelectedNetwork); - WifiConfiguration connectedNetwork = new WifiConfiguration(mSelectedNetwork); - connectedNetwork.SSID += "test"; - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, connectedNetwork); - - // Verify that we did not send the connection failure callback. - verify(mNetworkRequestMatchCallback, never()).onUserSelectionConnectFailure(any()); - // verify we canceled the timeout alarm. - verify(mAlarmManager, never()) - .cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - // Verify we don't reset the network request handling. - verify(mWifiConnectivityManager, never()) - .setSpecificNetworkRequestInProgress(false); - - // Send network connection failure indication beyond the retry limit to trigger the failure - // handling. - for (int i = 0; i <= WifiNetworkFactory.USER_SELECTED_NETWORK_CONNECT_RETRY_MAX; i++) { - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, mSelectedNetwork); - mLooper.dispatchAll(); - } - - mInOrder = inOrder(mAlarmManager, mClientModeImpl); - validateConnectionRetryAttempts(false); - - // Verify that we sent the connection failure callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // verify we canceled the timeout alarm. - mInOrder.verify(mAlarmManager).cancel( - mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - // Verify we reset the network request handling. - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); - } - - /** - * Verify handling of connection success. - */ - @Test - public void testNetworkSpecifierHandleConnectionSuccess() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - - // Verify that we sent the connection success callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // verify we canceled the timeout alarm. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - verify(mWifiMetrics).incrementNetworkRequestApiNumConnectSuccess(); - } - - /** - * Verify that we ignore connection success events after the first one (may be triggered by a - * roam event) - */ - @Test - public void testNetworkSpecifierDuplicateHandleConnectionSuccess() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - - // Verify that we sent the connection success callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // verify we canceled the timeout alarm. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - verify(mWifiMetrics).incrementNetworkRequestApiNumConnectSuccess(); - - // Send second network connection success indication which should be ignored. - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - verifyNoMoreInteractions(mNetworkRequestMatchCallback); - } - - /** - * Verify that we ignore any connection failure events after the first connection success (may - * be triggered by a disconnect). - * Note: The disconnect handling will be done via the NetworkAgent. - */ - @Test - public void testNetworkSpecifierHandleConnectionFailureAfterSuccess() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - - // Verify that we sent the connection success callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // verify we canceled the timeout alarm. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - verify(mWifiMetrics).incrementNetworkRequestApiNumConnectSuccess(); - - // Send a network connection failure indication which should be ignored (beyond the retry - // limit to trigger the failure handling). - for (int i = 0; i <= WifiNetworkFactory.USER_SELECTED_NETWORK_CONNECT_RETRY_MAX; i++) { - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, mSelectedNetwork); - mLooper.dispatchAll(); - } - // Verify that we ignore the second connection failure callback. - verifyNoMoreInteractions(mNetworkRequestMatchCallback); - } - - /** - * Verify handling of connection success to a different network. - */ - @Test - public void testNetworkSpecifierHandleConnectionSuccessToWrongNetwork() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Send network connection success to a different network indication. - assertNotNull(mSelectedNetwork); - WifiConfiguration connectedNetwork = new WifiConfiguration(mSelectedNetwork); - connectedNetwork.SSID += "test"; - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectedNetwork); - - // verify that we did not send out the success callback and did not stop the alarm timeout. - verify(mNetworkRequestMatchCallback, never()).onUserSelectionConnectSuccess(any()); - verify(mAlarmManager, never()) - .cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - // Send network connection success to the correct network indication. - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - - // Verify that we sent the connection success callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // verify we canceled the timeout alarm. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - } - - /** - * Verify handling of request release after starting connection to the network. - */ - @Test - public void testHandleNetworkReleaseWithSpecifierAfterConnectionStart() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - assertNotNull(mSelectedNetwork); - - // Now release the network request. - WifiConfiguration wcmNetwork = new WifiConfiguration(mSelectedNetwork); - wcmNetwork.networkId = TEST_NETWORK_ID_1; - wcmNetwork.creatorUid = TEST_UID_1; - wcmNetwork.creatorName = TEST_PACKAGE_NAME_1; - wcmNetwork.shared = false; - wcmNetwork.fromWifiNetworkSpecifier = true; - wcmNetwork.ephemeral = true; - when(mWifiConfigManager.getConfiguredNetwork(wcmNetwork.getKey())) - .thenReturn(wcmNetwork); - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - // verify we canceled the timeout alarm. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - // Verify that we triggered a disconnect. - verify(mClientModeImpl, times(2)).disconnectCommand(); - verify(mWifiConfigManager).removeNetwork( - TEST_NETWORK_ID_1, TEST_UID_1, TEST_PACKAGE_NAME_1); - // Re-enable connectivity manager . - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - } - - /** - * Verify handling of request release after connecting to the network. - */ - @Test - public void testHandleNetworkReleaseWithSpecifierAfterConnectionSuccess() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - - // Verify that we sent the connection success callback. - verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess( - argThat(new WifiConfigMatcher(mSelectedNetwork))); - // verify we canceled the timeout alarm. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - // Now release the network request. - WifiConfiguration wcmNetwork = new WifiConfiguration(mSelectedNetwork); - wcmNetwork.networkId = TEST_NETWORK_ID_1; - wcmNetwork.creatorUid = TEST_UID_1; - wcmNetwork.creatorName = TEST_PACKAGE_NAME_1; - wcmNetwork.shared = false; - wcmNetwork.fromWifiNetworkSpecifier = true; - wcmNetwork.ephemeral = true; - when(mWifiConfigManager.getConfiguredNetwork(wcmNetwork.getKey())) - .thenReturn(wcmNetwork); - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - // Verify that we triggered a disconnect. - verify(mClientModeImpl, times(2)).disconnectCommand(); - verify(mWifiConfigManager).removeNetwork( - TEST_NETWORK_ID_1, TEST_UID_1, TEST_PACKAGE_NAME_1); - // Re-enable connectivity manager . - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - } - - /** - * Verify we return the correct UID when processing network request with network specifier. - */ - @Test - public void testHandleNetworkRequestWithSpecifierGetUid() throws Exception { - assertEquals(Integer.valueOf(Process.INVALID_UID), - mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName( - new WifiConfiguration()).first); - assertTrue(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName( - new WifiConfiguration()).second.isEmpty()); - - sendNetworkRequestAndSetupForConnectionStatus(); - assertNotNull(mSelectedNetwork); - - // connected to a different network. - WifiConfiguration connectedNetwork = new WifiConfiguration(mSelectedNetwork); - connectedNetwork.SSID += "test"; - assertEquals(Integer.valueOf(Process.INVALID_UID), - mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName( - new WifiConfiguration()).first); - assertTrue(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName( - new WifiConfiguration()).second.isEmpty()); - - // connected to the correct network. - connectedNetwork = new WifiConfiguration(mSelectedNetwork); - assertEquals(Integer.valueOf(TEST_UID_1), - mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName( - connectedNetwork).first); - assertEquals(TEST_PACKAGE_NAME_1, - mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName( - connectedNetwork).second); - } - - /** - * Verify handling for new network request while processing another one. - */ - @Test - public void testHandleNewNetworkRequestWithSpecifierWhenScanning() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Register callback. - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration(any()); - - NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); - // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mLooper.dispatchAll(); - - verify(mNetworkRequestMatchCallback).onAbort(); - verify(mWifiScanner, times(2)).getSingleScanResults(); - verify(mWifiScanner, times(2)).startScan(any(), any(), any(), any()); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(oldRequest)); - - // Remove the stale request1 & ensure nothing happens. - mWifiNetworkFactory.releaseNetworkFor(oldRequest); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager, mNetworkRequestMatchCallback); - - // Remove the active request2 & ensure auto-join is re-enabled. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - } - - /** - * Verify handling for new network request while processing another one. - */ - @Test - public void testHandleNewNetworkRequestWithSpecifierAfterMatch() throws Exception { - sendNetworkRequestAndSetupForUserSelection(); - WifiNetworkSpecifier specifier1 = - (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); - - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - - NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); - // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Ignore stale callbacks. - WifiConfiguration selectedNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - sendUserSelectionSelect(networkRequestUserSelectionCallback, selectedNetwork); - mLooper.dispatchAll(); - - verify(mNetworkRequestMatchCallback).onAbort(); - verify(mWifiScanner, times(2)).getSingleScanResults(); - verify(mWifiScanner, times(2)).startScan(any(), any(), any(), any()); - verify(mAlarmManager).cancel(mPeriodicScanListenerArgumentCaptor.getValue()); - verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(oldRequest)); - - // Remove the stale request1 & ensure nothing happens. - mWifiNetworkFactory.releaseNetworkFor(oldRequest); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager, mNetworkRequestMatchCallback); - - // Remove the active request2 & ensure auto-join is re-enabled. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - } - - /** - * Verify handling for new network request while processing another one. - */ - @Test - public void testHandleNewNetworkRequestWithSpecifierAfterConnect() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - WifiNetworkSpecifier specifier1 = - (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); - - NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); - // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - verify(mNetworkRequestMatchCallback).onAbort(); - verify(mWifiConnectivityManager, times(1)).setSpecificNetworkRequestInProgress(true); - verify(mWifiScanner, times(2)).getSingleScanResults(); - verify(mWifiScanner, times(2)).startScan(any(), any(), any(), any()); - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - // Remove the stale request1 & ensure nothing happens. - mWifiNetworkFactory.releaseNetworkFor(oldRequest); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager, mNetworkRequestMatchCallback); - - // Remove the active request2 & ensure auto-join is re-enabled. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - } - - /** - * Verify handling for new network request while processing another one. - */ - @Test - public void testHandleNewNetworkRequestWithSpecifierAfterConnectionSuccess() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - WifiNetworkSpecifier specifier1 = - (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); - - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - // Cancel the connection timeout. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); - // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - verify(mWifiConnectivityManager, times(1)).setSpecificNetworkRequestInProgress(true); - verify(mWifiScanner, times(2)).getSingleScanResults(); - verify(mWifiScanner, times(2)).startScan(any(), any(), any(), any()); - // we shouldn't disconnect until the user accepts the next request. - verify(mClientModeImpl, times(1)).disconnectCommand(); - - // Remove the connected request1 & ensure we disconnect. - mWifiNetworkFactory.releaseNetworkFor(oldRequest); - verify(mClientModeImpl, times(2)).disconnectCommand(); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager); - - // Now remove the active request2 & ensure auto-join is re-enabled. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager); - } - - /** - * Verify handling for new network request while processing another one. - */ - @Test - public void testHandleNewNetworkRequestWithSpecifierWhichUserSelectedAfterConnectionSuccess() - throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); - WifiNetworkSpecifier specifier1 = - (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); - - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - // Cancel the connection timeout. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - // Send second request & we simulate the user selecting the request & connecting to it. - reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager); - sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_2); - WifiNetworkSpecifier specifier2 = - (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - // Cancel the connection timeout. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - // We shouldn't explicitly disconnect, the new connection attempt will implicitly disconnect - // from the connected network. - verify(mClientModeImpl, times(2)).disconnectCommand(); - - // Remove the stale request1 & ensure nothing happens (because it was replaced by the - // second request) - mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager); - - // Now remove the rejected request2, ensure we disconnect & re-enable auto-join. - mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - verify(mClientModeImpl, times(3)).disconnectCommand(); - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager); - } - - /** - * Verify handling for new network request while processing another one. - */ - @Test - public void testHandleNewNetworkRequestWithSpecifierWhichUserRejectedAfterConnectionSuccess() - throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); - WifiNetworkSpecifier specifier1 = - (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); - - // Send network connection success indication. - assertNotNull(mSelectedNetwork); - mWifiNetworkFactory.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); - // Cancel the connection timeout. - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - - // Send second request & we simulate the user rejecting the request. - reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager); - sendNetworkRequestAndSetupForUserSelection(TEST_SSID_2); - WifiNetworkSpecifier specifier2 = - (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); - mNetworkRequestUserSelectionCallback.getValue().reject(); - mLooper.dispatchAll(); - // cancel periodic scans. - verify(mAlarmManager).cancel(mPeriodicScanListenerArgumentCaptor.getValue()); - - // we shouldn't disconnect/re-enable auto-join until the connected request is released. - verify(mWifiConnectivityManager, never()).setSpecificNetworkRequestInProgress(false); - verify(mClientModeImpl, times(1)).disconnectCommand(); - - // Remove the connected request1 & ensure we disconnect & ensure auto-join is re-enabled. - mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - verify(mClientModeImpl, times(2)).disconnectCommand(); - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager); - - // Now remove the rejected request2 & ensure nothing happens - mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - - verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, - mAlarmManager); - } - - /** - * Verify handling of screen state changes while triggering periodic scans to find matching - * networks. - */ - @Test - public void testNetworkSpecifierHandleScreenStateChangedWhileScanning() throws Exception { - sendNetworkRequestAndSetupForUserSelection(); - - // Turn off screen. - mWifiNetworkFactory.handleScreenStateChanged(false); - - // 1. Cancel the scan timer. - mInOrder.verify(mAlarmManager).cancel( - mPeriodicScanListenerArgumentCaptor.getValue()); - // 2. Simulate the scan results from an ongoing scan, ensure no more scans are scheduled. - mScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas); - - // Ensure no more interactions. - mInOrder.verifyNoMoreInteractions(); - - // Now, turn the screen on. - mWifiNetworkFactory.handleScreenStateChanged(true); - - // Verify that we resumed periodic scanning. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - - /** - * Verify handling of screen state changes after the active network request was released. - */ - @Test - public void testNetworkSpecifierHandleScreenStateChangedWithoutActiveRequest() - throws Exception { - sendNetworkRequestAndSetupForUserSelection(); - // Now release the active network request. - mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - // Cancel the scan timer on release. - mInOrder.verify(mAlarmManager).cancel( - mPeriodicScanListenerArgumentCaptor.getValue()); - - // Turn off screen. - mWifiNetworkFactory.handleScreenStateChanged(false); - - // Now, turn the screen on. - mWifiNetworkFactory.handleScreenStateChanged(true); - - // Ensure that we did not pause or resume scanning. - mInOrder.verifyNoMoreInteractions(); - } - - /** - * Verify handling of screen state changes after user selected a network to connect to. - */ - @Test - public void testNetworkSpecifierHandleScreenStateChangedAfterUserSelection() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // Turn off screen. - mWifiNetworkFactory.handleScreenStateChanged(false); - - // Now, turn the screen on. - mWifiNetworkFactory.handleScreenStateChanged(true); - - // Ensure that we did not pause or resume scanning. - mInOrder.verifyNoMoreInteractions(); - } - - /** - * Verify we don't accept specific network request when wifi is off. - */ - @Test - public void testHandleAcceptNetworkRequestWithSpecifierWhenWifiOff() throws Exception { - when(mActivityManager.getPackageImportance(TEST_PACKAGE_NAME_1)) - .thenReturn(IMPORTANCE_FOREGROUND); - - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - - // set wifi off. - mWifiNetworkFactory.setWifiState(false); - assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - - // set wifi on. - mWifiNetworkFactory.setWifiState(true); - assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest, 0)); - } - - /** - * Verify handling of new network request with network specifier when wifi is off. - */ - @Test - public void testHandleNetworkRequestWithSpecifierWhenWifiOff() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - - // set wifi off - mWifiNetworkFactory.setWifiState(false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - verify(mWifiScanner, never()).startScan(any(), any(), any(), any()); - - // set wifi on - mWifiNetworkFactory.setWifiState(true); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - - /** - * Verify wifi toggle off when scanning. - */ - @Test - public void testHandleNetworkRequestWithSpecifierWifiOffWhenScanning() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Register callback. - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration(any()); - - verify(mWifiScanner).startScan(any(), any(), any(), any()); - - // toggle wifi off & verify we aborted ongoing request. - mWifiNetworkFactory.setWifiState(false); - verify(mNetworkRequestMatchCallback).onAbort(); - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - } - - /** - * Verify wifi toggle off after connection attempt is started. - */ - @Test - public void testHandleNetworkRequestWithSpecifierWifiOffAfterConnect() throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(); - - // toggle wifi off & verify we aborted ongoing request. - mWifiNetworkFactory.setWifiState(false); - verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - verify(mNetworkRequestMatchCallback).onAbort(); - verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); - } - - /** - * Verify handling of new network request with network specifier when wifi is off & then on. - * Note: Unlike the other unit tests, this test invokes the top level - * {@link NetworkFactory#CMD_REQUEST_NETWORK} to simulate the full flow. - */ - @Test - public void testFullHandleNetworkRequestWithSpecifierWhenWifiOff() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); - - // set wifi off - mWifiNetworkFactory.setWifiState(false); - // Add the request, should do nothing. - Message message = Message.obtain(); - message.what = CMD_REQUEST_NETWORK; - message.obj = mNetworkRequest; - mWifiNetworkFactory.sendMessage(message); - mLooper.dispatchAll(); - verify(mWifiScanner, never()).startScan(any(), any(), any(), any()); - - // set wifi on - mWifiNetworkFactory.setWifiState(true); - mLooper.dispatchAll(); - // Should trigger a re-evaluation of existing requests and the pending request will be - // processed now. - verify(mWifiScanner).startScan(any(), any(), any(), any()); - } - - /** - * Verify that we don't bypass user approval for a specific request for an access point that was - * approved previously, but then the user forgot it sometime after. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchApprovedNForgot() - throws Exception { - // 1. First request (no user approval bypass) - sendNetworkRequestAndSetupForConnectionStatus(); - - mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); - reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager, mClientModeImpl); - - // 2. Simulate user forgeting the network. - when(mWifiConfigManager.isNetworkTemporarilyDisabledByUser( - ScanResultUtil.createQuotedSSID(mTestScanDatas[0].getResults()[0].SSID))) - .thenReturn(true); - - // 3. Second request for the same access point (user approval bypass). - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, - WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - // Verify we triggered the match callback. - matchedScanResultsCaptor = ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - assertNotNull(matchedScanResultsCaptor.getValue()); - validateScanResults(matchedScanResultsCaptor.getValue(), matchingScanResult); - // Verify that we did not send a connection attempt to ClientModeImpl. - verify(mClientModeImpl, never()).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify that we don't bypass user approval for a specific request for an access point that was - * not approved previously. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchNotApproved() - throws Exception { - // 1. First request (no user approval bypass) - sendNetworkRequestAndSetupForConnectionStatus(); - - mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); - reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager, mClientModeImpl); - - // 2. Second request for a different access point (but same network). - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_1, TEST_SSID_3, TEST_SSID_4); - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[1]; - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - // Verify we triggered the match callback. - matchedScanResultsCaptor = ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - assertNotNull(matchedScanResultsCaptor.getValue()); - validateScanResults(matchedScanResultsCaptor.getValue(), matchingScanResult); - // Verify that we did not send a connection attempt to ClientModeImpl. - verify(mClientModeImpl, never()).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify that we don't bypass user approval for a specific request for a network - * (not access point) that was approved previously. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidMatchApproved() - throws Exception { - // 1. First request (no user approval bypass) - sendNetworkRequestAndSetupForConnectionStatus(); - - mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); - reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager, mClientModeImpl); - - // 2. Second request for the same network (but not specific access point) - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - // match-all. - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - // Verify we triggered the match callback. - matchedScanResultsCaptor = ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - assertNotNull(matchedScanResultsCaptor.getValue()); - validateScanResults(matchedScanResultsCaptor.getValue(), matchingScanResult); - // Verify that we did not send a connection attempt to ClientModeImpl. - verify(mClientModeImpl, never()).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify the we don't bypass user approval for a specific request for an access point that was - * already approved previously, but was then removed (app uninstalled, user deleted it from - * notification, from tests, etc). - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchAfterApprovalsRemove() - throws Exception { - // 1. First request (no user approval bypass) - sendNetworkRequestAndSetupForConnectionStatus(); - - mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); - reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager, mClientModeImpl); - - // 2. Remove all approvals for the app. - mWifiNetworkFactory.removeUserApprovedAccessPointsForApp(TEST_PACKAGE_NAME_1); - - // 3. Second request for the same access point - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - // Verify we triggered the match callback. - matchedScanResultsCaptor = ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - assertNotNull(matchedScanResultsCaptor.getValue()); - validateScanResults(matchedScanResultsCaptor.getValue(), matchingScanResult); - // Verify that we did not send a connection attempt to ClientModeImpl. - verify(mClientModeImpl, never()).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify the we don't bypass user approval for a specific request for an access point that was - * already approved previously, but then the user perform network settings reset. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchAfterClear() - throws Exception { - // 1. First request (no user approval bypass) - sendNetworkRequestAndSetupForConnectionStatus(); - - mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); - reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager, mClientModeImpl); - - // 2. Remove all approvals. - mWifiNetworkFactory.clear(); - - // 3. Second request for the same access point - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - // Verify we triggered the match callback. - matchedScanResultsCaptor = ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - assertNotNull(matchedScanResultsCaptor.getValue()); - validateScanResults(matchedScanResultsCaptor.getValue(), matchingScanResult); - // Verify that we did not send a connection attempt to ClientModeImpl. - verify(mClientModeImpl, never()).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify the config store save for store user approval. - */ - @Test - public void testNetworkSpecifierUserApprovalConfigStoreSave() - throws Exception { - sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); - - // Verify config store interactions. - verify(mWifiConfigManager).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - - Map<String, Set<AccessPoint>> approvedAccessPointsMapToWrite = mDataSource.toSerialize(); - assertEquals(1, approvedAccessPointsMapToWrite.size()); - assertTrue(approvedAccessPointsMapToWrite.keySet().contains(TEST_PACKAGE_NAME_1)); - Set<AccessPoint> approvedAccessPointsToWrite = - approvedAccessPointsMapToWrite.get(TEST_PACKAGE_NAME_1); - Set<AccessPoint> expectedApprovedAccessPoints = - new HashSet<AccessPoint>() {{ - add(new AccessPoint(TEST_SSID_1, MacAddress.fromString(TEST_BSSID_1), - WifiConfiguration.SECURITY_TYPE_PSK)); - }}; - assertEquals(expectedApprovedAccessPoints, approvedAccessPointsToWrite); - // Ensure that the new data flag has been reset after read. - assertFalse(mDataSource.hasNewDataToSerialize()); - } - - /** - * Verify the config store load for store user approval. - */ - @Test - public void testNetworkSpecifierUserApprovalConfigStoreLoad() - throws Exception { - Map<String, Set<AccessPoint>> approvedAccessPointsMapToRead = new HashMap<>(); - Set<AccessPoint> approvedAccessPoints = - new HashSet<AccessPoint>() {{ - add(new AccessPoint(TEST_SSID_1, MacAddress.fromString(TEST_BSSID_1), - WifiConfiguration.SECURITY_TYPE_PSK)); - }}; - approvedAccessPointsMapToRead.put(TEST_PACKAGE_NAME_1, approvedAccessPoints); - mDataSource.fromDeserialized(approvedAccessPointsMapToRead); - - // The new network request should bypass user approval for the same access point. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(TEST_BSSID_1), - MacAddress.BROADCAST_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - // Ensure we triggered a connect without issuing any scans. - verify(mWifiScanner, never()).startScan(any(), any(), any(), any()); - - // Verify we did not trigger the match callback. - verify(mNetworkRequestMatchCallback, never()).onMatch(anyList()); - // Verify that we sent a connection attempt to ClientModeImpl - verify(mClientModeImpl).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - } - - /** - * Verify the config store save and load could preserve the elements order. - */ - @Test - public void testStoreConfigSaveAndLoadPreserveOrder() throws Exception { - LinkedHashSet<AccessPoint> approvedApSet = new LinkedHashSet<>(); - approvedApSet.add(new AccessPoint(TEST_SSID_1, - MacAddress.fromString(TEST_BSSID_1), WifiConfiguration.SECURITY_TYPE_PSK)); - approvedApSet.add(new AccessPoint(TEST_SSID_2, - MacAddress.fromString(TEST_BSSID_2), WifiConfiguration.SECURITY_TYPE_PSK)); - approvedApSet.add(new AccessPoint(TEST_SSID_3, - MacAddress.fromString(TEST_BSSID_3), WifiConfiguration.SECURITY_TYPE_PSK)); - approvedApSet.add(new AccessPoint(TEST_SSID_4, - MacAddress.fromString(TEST_BSSID_4), WifiConfiguration.SECURITY_TYPE_PSK)); - mWifiNetworkFactory.mUserApprovedAccessPointMap.put(TEST_PACKAGE_NAME_1, - new LinkedHashSet<>(approvedApSet)); - // Save config. - byte[] xmlData = serializeData(); - mWifiNetworkFactory.mUserApprovedAccessPointMap.clear(); - // Load config. - deserializeData(xmlData); - - LinkedHashSet<AccessPoint> storedApSet = mWifiNetworkFactory - .mUserApprovedAccessPointMap.get(TEST_PACKAGE_NAME_1); - // Check load config success and order preserved. - assertNotNull(storedApSet); - assertArrayEquals(approvedApSet.toArray(), storedApSet.toArray()); - } - - /** - * Verify the user approval bypass for a specific request for an access point that was already - * approved previously and the scan result is present in the cached scan results. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchApproved() - throws Exception { - // 1. First request (no user approval bypass) - sendNetworkRequestAndSetupForConnectionStatus(); - - mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); - reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager, mClientModeImpl); - - // 2. Second request for the same access point (user approval bypass). - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, - WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Verify we did not trigger the UI for the second request. - verify(mContext, times(1)).startActivityAsUser(any(), any()); - // Verify we did not trigger a scan. - verify(mWifiScanner, never()).startScan(any(), any(), any(), any()); - // Verify we did not trigger the match callback. - verify(mNetworkRequestMatchCallback, never()).onMatch(anyList()); - // Verify that we sent a connection attempt to ClientModeImpl - verify(mClientModeImpl).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - - verify(mWifiMetrics).incrementNetworkRequestApiNumUserApprovalBypass(); - } - - /** - * Verify the user approval bypass for a specific request for an access point that was already - * approved previously via CDM and the scan result is present in the cached scan results. - */ - @Test - public void - testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchApprovedViaCDM() - throws Exception { - // Setup scan data for WPA-PSK networks. - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Choose the matching scan result. - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - - // Setup CDM approval for the scan result. - when(mCompanionDeviceManager.isDeviceAssociatedForWifiConnection( - TEST_PACKAGE_NAME_1, - MacAddress.fromString(matchingScanResult.BSSID), - UserHandle.getUserHandleForUid(TEST_UID_1))).thenReturn(true); - - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, - WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Verify we did not trigger the UI for the second request. - verify(mContext, never()).startActivityAsUser(any(), any()); - // Verify we did not trigger a scan. - verify(mWifiScanner, never()).startScan(any(), any(), any(), any()); - // Verify we did not trigger the match callback. - verify(mNetworkRequestMatchCallback, never()).onMatch(anyList()); - // Verify that we sent a connection attempt to ClientModeImpl - verify(mClientModeImpl).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - - verify(mWifiMetrics).incrementNetworkRequestApiNumUserApprovalBypass(); - } - - /** - * Verify the user approval bypass for a specific request for an access point that was already - * approved previously via shell command and the scan result is present in the cached scan - * results. - */ - @Test - public void - testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchApprovedViaShell() - throws Exception { - // Setup scan data for WPA-PSK networks. - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Choose the matching scan result. - ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; - - // Setup shell approval for the scan result. - mWifiNetworkFactory.setUserApprovedApp(TEST_PACKAGE_NAME_1, true); - - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(MacAddress.fromString(matchingScanResult.BSSID), - MacAddress.BROADCAST_ADDRESS); - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, - WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - // Verify we did not trigger the UI for the second request. - verify(mContext, never()).startActivityAsUser(any(), any()); - // Verify we did not trigger a scan. - verify(mWifiScanner, never()).startScan(any(), any(), any(), any()); - // Verify we did not trigger the match callback. - verify(mNetworkRequestMatchCallback, never()).onMatch(anyList()); - // Verify that we sent a connection attempt to ClientModeImpl - verify(mClientModeImpl).connect(eq(null), anyInt(), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - - verify(mWifiMetrics).incrementNetworkRequestApiNumUserApprovalBypass(); - } - - /** - * Verify network specifier matching for a specifier containing a specific SSID match using - * 4 WPA_PSK scan results, each with unique SSID when the UI callback registration is delayed. - */ - @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidMatchCallbackRegistrationDelayed() - throws Exception { - // Setup scan data for open networks. - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Setup network specifier for open networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); - - validateUiStartParams(true); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - // Ensure we did not send any match callbacks, until the callback is registered - verify(mNetworkRequestMatchCallback, never()).onMatch(any()); - - // Register the callback & ensure we triggered the on match callback. - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); - // We only expect 1 network match in this case. - validateScanResults(matchedScanResultsCaptor.getValue(), mTestScanDatas[0].getResults()[0]); - - verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResultsCaptor.getValue().size()); - } - - private void sendNetworkRequestAndSetupForConnectionStatus() throws RemoteException { - sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); - } - - // Helper method to setup the necessary pre-requisite steps for tracking connection status. - private void sendNetworkRequestAndSetupForConnectionStatus(String targetSsid) - throws RemoteException { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - - sendNetworkRequestAndSetupForUserSelection(targetSsid); - - INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = - mNetworkRequestUserSelectionCallback.getValue(); - assertNotNull(networkRequestUserSelectionCallback); - - // Now trigger user selection to one of the network. - mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); - mSelectedNetwork.SSID = "\"" + targetSsid + "\""; - sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); - mLooper.dispatchAll(); - - // Cancel the periodic scan timer. - mInOrder.verify(mAlarmManager).cancel(mPeriodicScanListenerArgumentCaptor.getValue()); - // Disable connectivity manager - verify(mWifiConnectivityManager, atLeastOnce()).setSpecificNetworkRequestInProgress(true); - // Increment the number of unique apps. - verify(mWifiMetrics).incrementNetworkRequestApiNumApps(); - - verify(mClientModeImpl, atLeastOnce()).disconnectCommand(); - verify(mClientModeImpl, atLeastOnce()).connect(eq(null), eq(TEST_NETWORK_ID_1), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); - - // Start the connection timeout alarm. - mInOrder.verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), - eq((long) WifiNetworkFactory.NETWORK_CONNECTION_TIMEOUT_MS), any(), - mConnectionTimeoutAlarmListenerArgumentCaptor.capture(), any()); - assertNotNull(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - } - - private void sendNetworkRequestAndSetupForUserSelection() throws RemoteException { - sendNetworkRequestAndSetupForUserSelection(TEST_SSID_1); - } - - // Helper method to setup the necessary pre-requisite steps for user selection. - private void sendNetworkRequestAndSetupForUserSelection(String targetSsid) - throws RemoteException { - // Setup scan data for WPA-PSK networks. - setupScanData(SCAN_RESULT_TYPE_WPA_PSK, - TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); - - // Setup network specifier for WPA-PSK networks. - PatternMatcher ssidPatternMatch = - new PatternMatcher(targetSsid, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createPskNetwork(); - wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - attachWifiNetworkSpecifierAndAppInfo( - ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); - mWifiNetworkFactory.needNetworkFor(new NetworkRequest(mNetworkRequest), 0); - - validateUiStartParams(true); - - mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, - TEST_CALLBACK_IDENTIFIER); - verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( - mNetworkRequestUserSelectionCallback.capture()); - - verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - - verify(mNetworkRequestMatchCallback, atLeastOnce()).onMatch(anyList()); - } - - private void verifyPeriodicScans(long...expectedIntervalsInSeconds) { - PeriodicScanParams[] periodicScanParams = - new PeriodicScanParams[expectedIntervalsInSeconds.length]; - for (int i = 0; i < expectedIntervalsInSeconds.length; i++) { - periodicScanParams[i] = - new PeriodicScanParams(expectedIntervalsInSeconds[i], mTestScanDatas); - } - verifyPeriodicScans(0L, periodicScanParams); - } - - private static class PeriodicScanParams { - public final long expectedIntervalInSeconds; - public final WifiScanner.ScanData[] scanDatas; - - PeriodicScanParams(long expectedIntervalInSeconds, WifiScanner.ScanData[] scanDatas) { - this.expectedIntervalInSeconds = expectedIntervalInSeconds; - this.scanDatas = scanDatas; - } - } - - // Simulates the periodic scans performed to find a matching network. - // a) Start scan - // b) Scan results received. - // c) Set alarm for next scan at the expected interval. - // d) Alarm fires, go to step a) again and repeat. - private void verifyPeriodicScans(long nowMs, PeriodicScanParams... scanParams) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(nowMs); - - OnAlarmListener alarmListener = null; - ScanListener scanListener = null; - - mInOrder = inOrder(mWifiScanner, mAlarmManager); - - // Before we start scans, ensure that we look at the latest cached scan results. - mInOrder.verify(mWifiScanner).getSingleScanResults(); - - for (int i = 0; i < scanParams.length - 1; i++) { - long expectedCurrentIntervalInMs = scanParams[i].expectedIntervalInSeconds; - long expectedNextIntervalInMs = scanParams[i + 1].expectedIntervalInSeconds; - - // First scan is immediately fired, so need for the alarm to fire. - if (expectedCurrentIntervalInMs != 0) { - // Fire the alarm and ensure that we started the next scan. - alarmListener.onAlarm(); - } - mInOrder.verify(mWifiScanner).startScan( - any(), any(), mScanListenerArgumentCaptor.capture(), any()); - scanListener = mScanListenerArgumentCaptor.getValue(); - assertNotNull(scanListener); - - // Now trigger the scan results callback and verify the alarm set for the next scan. - scanListener.onResults(scanParams[i].scanDatas); - - mInOrder.verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), - eq(expectedNextIntervalInMs + nowMs), any(), - mPeriodicScanListenerArgumentCaptor.capture(), any()); - alarmListener = mPeriodicScanListenerArgumentCaptor.getValue(); - assertNotNull(alarmListener); - } - - mInOrder.verifyNoMoreInteractions(); - } - - private void attachDefaultWifiNetworkSpecifierAndAppInfo(int uid, boolean isHidden) { - PatternMatcher ssidPatternMatch = - new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); - Pair<MacAddress, MacAddress> bssidPatternMatch = - Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); - WifiConfiguration wifiConfiguration; - if (isHidden) { - wifiConfiguration = WifiConfigurationTestUtil.createPskHiddenNetwork(); - } else { - wifiConfiguration = WifiConfigurationTestUtil.createPskNetwork(); - } - String packageName = null; - if (uid == TEST_UID_1) { - packageName = TEST_PACKAGE_NAME_1; - } else if (uid == TEST_UID_2) { - packageName = TEST_PACKAGE_NAME_2; - } else { - fail(); - } - attachWifiNetworkSpecifierAndAppInfo(ssidPatternMatch, bssidPatternMatch, wifiConfiguration, - uid, packageName); - } - - private void attachWifiNetworkSpecifierAndAppInfo( - PatternMatcher ssidPatternMatch, Pair<MacAddress, MacAddress> bssidPatternMatch, - WifiConfiguration wifiConfiguration, int uid, String packageName) { - mNetworkCapabilities.setRequestorUid(uid); - mNetworkCapabilities.setRequestorPackageName(packageName); - mNetworkCapabilities.setNetworkSpecifier( - new WifiNetworkSpecifier(ssidPatternMatch, bssidPatternMatch, wifiConfiguration)); - mNetworkRequest = new NetworkRequest.Builder() - .setCapabilities(mNetworkCapabilities) - .build(); - } - - private static final int SCAN_RESULT_TYPE_OPEN = 0; - private static final int SCAN_RESULT_TYPE_WPA_PSK = 1; - private static final int SCAN_RESULT_TYPE_WPA_EAP = 2; - private static final int SCAN_RESULT_TYPE_WPA_PSK_SAE_TRANSITION = 3; - - private String getScanResultCapsForType(int scanResultType) { - switch (scanResultType) { - case SCAN_RESULT_TYPE_OPEN: - return WifiConfigurationTestUtil.getScanResultCapsForNetwork( - WifiConfigurationTestUtil.createOpenNetwork()); - case SCAN_RESULT_TYPE_WPA_PSK: - return WifiConfigurationTestUtil.getScanResultCapsForNetwork( - WifiConfigurationTestUtil.createPskNetwork()); - case SCAN_RESULT_TYPE_WPA_EAP: - return WifiConfigurationTestUtil.getScanResultCapsForNetwork( - WifiConfigurationTestUtil.createEapNetwork()); - case SCAN_RESULT_TYPE_WPA_PSK_SAE_TRANSITION: - return WifiConfigurationTestUtil.getScanResultCapsForWpa2Wpa3TransitionNetwork(); - } - fail("Invalid scan result type " + scanResultType); - return ""; - } - - private void setupScanData(int scanResultType, String ssid1, String ssid2, String ssid3, - String ssid4) { - setupScanData(mTestScanDatas, scanResultType, ssid1, ssid2, ssid3, ssid4); - } - - // Helper method to setup the scan data for verifying the matching algo. - private void setupScanData(WifiScanner.ScanData[] testScanDatas, int scanResultType, - String ssid1, String ssid2, String ssid3, String ssid4) { - // 4 scan results, - assertEquals(1, testScanDatas.length); - ScanResult[] scanResults = testScanDatas[0].getResults(); - assertEquals(4, scanResults.length); - - String caps = getScanResultCapsForType(scanResultType); - - // Scan results have increasing RSSI. - scanResults[0].SSID = ssid1; - scanResults[0].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid1); - scanResults[0].BSSID = TEST_BSSID_1; - scanResults[0].capabilities = caps; - scanResults[0].level = -45; - scanResults[1].SSID = ssid2; - scanResults[1].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid2); - scanResults[1].BSSID = TEST_BSSID_2; - scanResults[1].capabilities = caps; - scanResults[1].level = -35; - scanResults[2].SSID = ssid3; - scanResults[2].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid3); - scanResults[2].BSSID = TEST_BSSID_3; - scanResults[2].capabilities = caps; - scanResults[2].level = -25; - scanResults[3].SSID = ssid4; - scanResults[3].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid4); - scanResults[3].BSSID = TEST_BSSID_4; - scanResults[3].capabilities = caps; - scanResults[3].level = -15; - } - - private void validateScanResults( - List<ScanResult> actualScanResults, ScanResult...expectedScanResults) { - assertEquals(expectedScanResults.length, actualScanResults.size()); - for (int i = 0; i < expectedScanResults.length; i++) { - ScanResult expectedScanResult = expectedScanResults[i]; - ScanResult actualScanResult = actualScanResults.stream() - .filter(x -> x.BSSID.equals(expectedScanResult.BSSID)) - .findFirst() - .orElse(null); - ScanTestUtil.assertScanResultEquals(expectedScanResult, actualScanResult); - } - } - - private void validateConnectionRetryAttempts(boolean onTimeout) { - for (int i = 0; i < WifiNetworkFactory.USER_SELECTED_NETWORK_CONNECT_RETRY_MAX; i++) { - if (!onTimeout) { - // Cancel the existing connection timeout. - mInOrder.verify(mAlarmManager).cancel( - mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - } - - // Trigger new connection. - mInOrder.verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), - any(Binder.class), mConnectListenerArgumentCaptor.capture(), anyInt(), - anyInt()); - - // Start the new connection timeout alarm. - mInOrder.verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), - eq((long) WifiNetworkFactory.NETWORK_CONNECTION_TIMEOUT_MS), any(), - mConnectionTimeoutAlarmListenerArgumentCaptor.capture(), any()); - assertNotNull(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); - } - } - - private void validateScanSettings(@Nullable String hiddenSsid) { - ScanSettings scanSettings = mScanSettingsArgumentCaptor.getValue(); - assertNotNull(scanSettings); - assertEquals(WifiScanner.WIFI_BAND_ALL, scanSettings.band); - assertEquals(WifiScanner.SCAN_TYPE_HIGH_ACCURACY, scanSettings.type); - assertEquals(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, scanSettings.reportEvents); - if (hiddenSsid == null) { - assertEquals(Collections.emptyList(), scanSettings.hiddenNetworks); - } else { - assertNotNull(scanSettings.hiddenNetworks.get(0)); - assertEquals(scanSettings.hiddenNetworks.get(0).ssid, addEnclosingQuotes(hiddenSsid)); - } - WorkSource workSource = mWorkSourceArgumentCaptor.getValue(); - assertNotNull(workSource); - assertEquals(TEST_UID_1, workSource.getUid(0)); - } - - class WifiConfigMatcher implements ArgumentMatcher<WifiConfiguration> { - private final WifiConfiguration mConfig; - - WifiConfigMatcher(WifiConfiguration config) { - assertNotNull(config); - mConfig = config; - mConfig.shared = false; - } - - @Override - public boolean matches(WifiConfiguration otherConfig) { - if (otherConfig == null) return false; - return mConfig.getKey().equals(otherConfig.getKey()); - } - } - - private void validateUiStartParams(boolean expectedIsReqForSingeNetwork) { - ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()).startActivityAsUser( - intentArgumentCaptor.capture(), eq(UserHandle.getUserHandleForUid(TEST_UID_1))); - Intent intent = intentArgumentCaptor.getValue(); - assertNotNull(intent); - assertEquals(intent.getAction(), WifiNetworkFactory.UI_START_INTENT_ACTION); - assertTrue(intent.getCategories().contains(WifiNetworkFactory.UI_START_INTENT_CATEGORY)); - assertEquals(intent.getStringExtra(WifiNetworkFactory.UI_START_INTENT_EXTRA_APP_NAME), - TEST_APP_NAME); - assertEquals(expectedIsReqForSingeNetwork, intent.getBooleanExtra( - WifiNetworkFactory.UI_START_INTENT_EXTRA_REQUEST_IS_FOR_SINGLE_NETWORK, false)); - assertTrue((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0); - assertTrue((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0); - } - - private void validateConnectParams(String ssid, String bssid) { - ArgumentCaptor<WifiConfiguration> wifiConfigurationCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - verify(mWifiConfigManager).addOrUpdateNetwork( - wifiConfigurationCaptor.capture(), eq(TEST_UID_1), eq(TEST_PACKAGE_NAME_1)); - WifiConfiguration network = wifiConfigurationCaptor.getValue(); - assertNotNull(network); - WifiConfiguration expectedWifiConfiguration = - new WifiConfiguration(((WifiNetworkSpecifier) mNetworkRequest.networkCapabilities - .getNetworkSpecifier()).wifiConfiguration); - expectedWifiConfiguration.SSID = ssid; - expectedWifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; - expectedWifiConfiguration.BSSID = bssid; - expectedWifiConfiguration.ephemeral = true; - expectedWifiConfiguration.shared = false; - expectedWifiConfiguration.fromWifiNetworkSpecifier = true; - WifiConfigurationTestUtil.assertConfigurationEqual(expectedWifiConfiguration, network); - } - - /** - * Create a test scan data for target SSID list with specified number and encryption type - * @param scanResultType network encryption type - * @param nums Number of results with different BSSIDs for one SSID - * @param ssids target SSID list - */ - private void setupScanDataSameSsidWithDiffBssid(int scanResultType, int nums, String[] ssids) { - String baseBssid = "11:34:56:78:90:"; - int[] freq = new int[nums * ssids.length]; - for (int i = 0; i < nums; i++) { - freq[i] = 2417 + i; - } - mTestScanDatas = ScanTestUtil.createScanDatas(new int[][]{ freq }); - assertEquals(1, mTestScanDatas.length); - ScanResult[] scanResults = mTestScanDatas[0].getResults(); - assertEquals(nums * ssids.length, scanResults.length); - String caps = getScanResultCapsForType(scanResultType); - for (int i = 0; i < ssids.length; i++) { - for (int j = i * nums; j < (i + 1) * nums; j++) { - scanResults[j].SSID = ssids[i]; - scanResults[j].BSSID = baseBssid + Integer.toHexString(16 + j); - scanResults[j].capabilities = caps; - scanResults[j].level = -45; - } - } - } - - /** - * Helper function for serializing configuration data to a XML block. - * - * @return byte[] of the XML data - * @throws Exception - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for parsing configuration data from a XML block. - * - * @param data XML data to parse from - * @throws Exception - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - } - - private void sendUserSelectionSelect(INetworkRequestUserSelectionCallback callback, - WifiConfiguration selectedNetwork) throws RemoteException { - WifiConfiguration selectedNetworkinCb = new WifiConfiguration(); - // only copy over the ssid - selectedNetworkinCb.SSID = selectedNetwork.SSID; - callback.select(selectedNetworkinCb); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkScoreCacheTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkScoreCacheTest.java deleted file mode 100644 index ced2fc961..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkScoreCacheTest.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.NetworkKey; -import android.net.RssiCurve; -import android.net.ScoredNetwork; -import android.net.WifiKey; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.HandlerThread; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.wifi.WifiNetworkScoreCache.CacheListener; - -import com.google.common.collect.ImmutableList; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** Unit tests for {@link WifiNetworkScoreCache}. */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class WifiNetworkScoreCacheTest { - - public static final String SSID = "ssid"; - public static final String SSID2 = "ssid2"; - public static final String SSID3 = "ssid3"; - public static final String FORMATTED_SSID = "\"" + SSID + "\""; - public static final String FORMATTED_SSID2 = "\"" + SSID2 + "\""; - public static final String FORMATTED_SSID3 = "\"" + SSID3 + "\""; - public static final String BSSID = "AA:AA:AA:AA:AA:AA"; - - public static final WifiKey VALID_KEY = new WifiKey(FORMATTED_SSID, BSSID); - - public static final ScanResult VALID_SCAN_RESULT = buildScanResult(SSID, BSSID); - - @Mock - private Context mMockApplicationContext; - @Mock - private Context mMockContext; // isn't used, can be null - @Mock - private RssiCurve mMockRssiCurve; - - - private CacheListener mCacheListener; - private CountDownLatch mLatch; - private Handler mHandler; - private List<ScoredNetwork> mUpdatedNetworksCaptor; - private ScoredNetwork mValidScoredNetwork; - private WifiNetworkScoreCache mScoreCache; - - private static ScanResult buildScanResult(String ssid, String bssid) { - return new ScanResult( - WifiSsid.createFromAsciiEncoded(ssid), - bssid, - "" /* caps */, - 0 /* level */, - 0 /* frequency */, - 0 /* tsf */, - 0 /* distCm */, - 0 /* distSdCm*/); - } - - private static ScoredNetwork buildScoredNetwork(WifiKey key, RssiCurve curve) { - return new ScoredNetwork(new NetworkKey(key), curve); - } - - // Called from setup - private void initializeCacheWithValidScoredNetwork() { - mScoreCache.onScoresUpdated(ImmutableList.of(mValidScoredNetwork)); - } - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - when(mMockContext.getApplicationContext()).thenReturn(mMockApplicationContext); - - mValidScoredNetwork = buildScoredNetwork(VALID_KEY, mMockRssiCurve); - mScoreCache = new WifiNetworkScoreCache(mMockContext); - initializeCacheWithValidScoredNetwork(); - - HandlerThread thread = new HandlerThread("WifiNetworkScoreCacheTest Handler Thread"); - thread.start(); - mHandler = new Handler(thread.getLooper()); - mLatch = new CountDownLatch(1); - mCacheListener = new CacheListener(mHandler) { - @Override - public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) { - mUpdatedNetworksCaptor = updatedNetworks; - mLatch.countDown(); - } - }; - } - - - @Test - public void isScoredNetworkShouldReturnTrueAfterUpdateScoresIsCalled() { - assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue(); - } - - @Test - public void isScoredNetworkShouldReturnFalseAfterClearScoresIsCalled() { - mScoreCache.onScoresInvalidated(); - assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isFalse(); - } - - @Test - public void onScoresUpdatedShouldAddNewNetwork() { - WifiKey key2 = new WifiKey("\"ssid2\"", BSSID); - ScoredNetwork network2 = buildScoredNetwork(key2, mMockRssiCurve); - ScanResult result2 = buildScanResult("ssid2", BSSID); - - mScoreCache.onScoresUpdated(ImmutableList.of(network2)); - - assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue(); - assertThat(mScoreCache.isScoredNetwork(result2)).isTrue(); - } - - @Test - public void hasScoreCurveShouldReturnTrue() { - assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isTrue(); - } - - @Test - public void hasScoreCurveShouldReturnFalseWhenNoCachedNetwork() { - ScanResult unscored = buildScanResult("fake", BSSID); - assertThat(mScoreCache.hasScoreCurve(unscored)).isFalse(); - } - - @Test - public void hasScoreCurveShouldReturnFalseWhenScoredNetworkHasNoCurve() { - ScoredNetwork noCurve = buildScoredNetwork(VALID_KEY, null /* rssiCurve */); - mScoreCache.onScoresUpdated(ImmutableList.of(noCurve)); - - assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse(); - } - - @Test - public void getMeteredHintShouldReturnFalse() { - assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isFalse(); - } - - @Test - public void getMeteredHintShouldReturnTrue() { - ScoredNetwork network = new ScoredNetwork( - new NetworkKey(VALID_KEY), mMockRssiCurve, true /* metered Hint */); - mScoreCache.onScoresUpdated(ImmutableList.of(network)); - - assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isTrue(); - } - - @Test - public void onScoresUpdatedShouldInvokeCacheListener_networkCacheUpdated() { - mScoreCache = new WifiNetworkScoreCache(mMockContext, mCacheListener); - initializeCacheWithValidScoredNetwork(); - - try { - mLatch.await(1, TimeUnit.SECONDS); // wait for listener to be executed - } catch (InterruptedException e) { - fail("Interrupted Exception while waiting for listener to be invoked."); - } - // One network should be updated. - assertThat(mUpdatedNetworksCaptor.size()).isEqualTo(1); - assertThat(mUpdatedNetworksCaptor.get(0)).isEqualTo(mValidScoredNetwork); - } - - @Test - public void leastRecentlyUsedScore_shouldBeEvictedFromCache() { - mScoreCache = new WifiNetworkScoreCache(mMockContext, mCacheListener, 2 /* maxCacheSize */); - - ScoredNetwork network1 = mValidScoredNetwork; - ScoredNetwork network2 = buildScoredNetwork( - new WifiKey(FORMATTED_SSID2, BSSID), mMockRssiCurve); - ScoredNetwork network3 = buildScoredNetwork( - new WifiKey(FORMATTED_SSID3, BSSID), mMockRssiCurve); - mScoreCache.onScoresUpdated(ImmutableList.of(network1)); - mScoreCache.onScoresUpdated(ImmutableList.of(network2)); - - // First score should be evicted because max cache size has been reached. - mScoreCache.onScoresUpdated(ImmutableList.of(network3)); - - assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID2, BSSID))).isTrue(); - assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID3, BSSID))).isTrue(); - assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java deleted file mode 100644 index 1507e9c55..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java +++ /dev/null @@ -1,1647 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; - -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP; -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE; -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; -import static com.android.server.wifi.WifiNetworkSelector.experimentIdFromIdentifier; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; -import android.net.wifi.WifiInfo; -import android.os.SystemClock; -import android.util.LocalLog; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.WifiNetworkSelector}. - */ -@SmallTest -public class WifiNetworkSelectorTest extends WifiBaseTest { - private static final int RSSI_BUMP = 1; - private static final int DUMMY_NOMINATOR_ID_1 = -2; // lowest index - private static final int DUMMY_NOMINATOR_ID_2 = -1; - private static final int WAIT_JUST_A_MINUTE = 60_000; - private static final HashSet<String> EMPTY_BLACKLIST = new HashSet<>(); - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - setupContext(); - setupResources(); - setupWifiConfigManager(); - setupWifiInfo(); - - mScoringParams = new ScoringParams(); - setupThresholds(); - - mLocalLog = new LocalLog(512); - - mWifiNetworkSelector = new WifiNetworkSelector(mContext, - mWifiScoreCard, - mScoringParams, - mWifiConfigManager, mClock, - mLocalLog, - mWifiMetrics, - mWifiNative, - mThroughputPredictor); - - mWifiNetworkSelector.registerNetworkNominator(mDummyNominator); - mDummyNominator.setNominatorToSelectCandidate(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); - when(mWifiScoreCard.lookupBssid(any(), any())).thenReturn(mPerBssid); - mCompatibilityScorer = new CompatibilityScorer(mScoringParams); - mScoreCardBasedScorer = new ScoreCardBasedScorer(mScoringParams); - mThroughputScorer = new ThroughputScorer(mScoringParams); - when(mWifiNative.getClientInterfaceName()).thenReturn("wlan0"); - if (WifiNetworkSelector.PRESET_CANDIDATE_SCORER_NAME.equals( - mThroughputScorer.getIdentifier())) { - mWifiNetworkSelector.registerCandidateScorer(mThroughputScorer); - } else { - mWifiNetworkSelector.registerCandidateScorer(mCompatibilityScorer); - } - } - - /** Cleans up test. */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - /** - * Nominates all networks. - */ - public class AllNetworkNominator implements WifiNetworkSelector.NetworkNominator { - private static final String NAME = "AllNetworkNominator"; - private final ScanDetailsAndWifiConfigs mScanDetailsAndWifiConfigs; - - public AllNetworkNominator(ScanDetailsAndWifiConfigs scanDetailsAndWifiConfigs) { - mScanDetailsAndWifiConfigs = scanDetailsAndWifiConfigs; - } - - @Override - public @NominatorId int getId() { - return WifiNetworkSelector.NetworkNominator.NOMINATOR_ID_SAVED; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public void update(List<ScanDetail> scanDetails) {} - - @Override - public void nominateNetworks(List<ScanDetail> scanDetails, - WifiConfiguration currentNetwork, String currentBssid, boolean connected, - boolean untrustedNetworkAllowed, - @NonNull OnConnectableListener onConnectableListener) { - List<ScanDetail> myScanDetails = mScanDetailsAndWifiConfigs.getScanDetails(); - WifiConfiguration[] configs = mScanDetailsAndWifiConfigs.getWifiConfigs(); - for (int i = 0; i < configs.length; i++) { - onConnectableListener.onConnectable(myScanDetails.get(i), configs[i]); - } - } - } - - - /** - * All this dummy network Nominator does is to pick the specified network in the scan results. - */ - public class DummyNetworkNominator implements WifiNetworkSelector.NetworkNominator { - private static final String NAME = "DummyNetworkNominator"; - - private boolean mNominatorShouldSelectCandidate = true; - - private int mNetworkIndexToReturn; - private int mNominatorIdToReturn; - - public DummyNetworkNominator(int networkIndexToReturn, int nominatorIdToReturn) { - mNetworkIndexToReturn = networkIndexToReturn; - mNominatorIdToReturn = nominatorIdToReturn; - } - - public DummyNetworkNominator() { - this(0, DUMMY_NOMINATOR_ID_1); - } - - public int getNetworkIndexToReturn() { - return mNetworkIndexToReturn; - } - - public void setNetworkIndexToReturn(int networkIndexToReturn) { - mNetworkIndexToReturn = networkIndexToReturn; - } - - @Override - public @NominatorId int getId() { - return mNominatorIdToReturn; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public void update(List<ScanDetail> scanDetails) {} - - /** - * Sets whether the nominator should return a candidate for connection or null. - */ - public void setNominatorToSelectCandidate(boolean shouldSelectCandidate) { - mNominatorShouldSelectCandidate = shouldSelectCandidate; - } - - /** - * This NetworkNominator can be configured to return a candidate or null. If returning a - * candidate, the first entry in the provided scanDetails will be selected. This requires - * that the mock WifiConfigManager be set up to return a WifiConfiguration for the first - * scanDetail entry, through - * {@link WifiNetworkSelectorTestUtil#setupScanDetailsAndConfigStore}. - */ - @Override - public void nominateNetworks(List<ScanDetail> scanDetails, - WifiConfiguration currentNetwork, String currentBssid, boolean connected, - boolean untrustedNetworkAllowed, - @NonNull OnConnectableListener onConnectableListener) { - if (!mNominatorShouldSelectCandidate) { - return; - } - for (ScanDetail scanDetail : scanDetails) { - WifiConfiguration config = - mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail); - mWifiConfigManager.setNetworkCandidateScanResult( - config.networkId, scanDetail.getScanResult(), 100); - } - ScanDetail scanDetailToReturn = scanDetails.get(mNetworkIndexToReturn); - WifiConfiguration configToReturn = - mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - scanDetailToReturn); - assertNotNull("Saved network must not be null", configToReturn); - onConnectableListener.onConnectable(scanDetailToReturn, configToReturn); - } - } - - private WifiNetworkSelector mWifiNetworkSelector = null; - private DummyNetworkNominator mDummyNominator = new DummyNetworkNominator(); - @Mock private WifiConfigManager mWifiConfigManager; - @Mock private Context mContext; - @Mock private WifiScoreCard mWifiScoreCard; - @Mock private WifiScoreCard.PerBssid mPerBssid; - @Mock private WifiCandidates.CandidateScorer mCandidateScorer; - @Mock private WifiMetrics mWifiMetrics; - @Mock private WifiNative mWifiNative; - @Mock private WifiNetworkSelector.NetworkNominator mNetworkNominator; - - // For simulating the resources, we use a Spy on a MockResource - // (which is really more of a stub than a mock, in spite if its name). - // This is so that we get errors on any calls that we have not explicitly set up. - @Spy private MockResources mResource = new MockResources(); - @Mock private WifiInfo mWifiInfo; - @Mock private Clock mClock; - @Mock private NetworkDetail mNetworkDetail; - @Mock private ThroughputPredictor mThroughputPredictor; - private ScoringParams mScoringParams; - private LocalLog mLocalLog; - private int mThresholdMinimumRssi2G; - private int mThresholdMinimumRssi5G; - private int mThresholdQualifiedRssi2G; - private int mThresholdQualifiedRssi5G; - private int mMinPacketRateActiveTraffic; - private int mSufficientDurationAfterUserSelection; - private CompatibilityScorer mCompatibilityScorer; - private ScoreCardBasedScorer mScoreCardBasedScorer; - private ThroughputScorer mThroughputScorer; - - private void setupContext() { - when(mContext.getResources()).thenReturn(mResource); - } - - private int setupIntegerResource(int resourceName, int value) { - doReturn(value).when(mResource).getInteger(resourceName); - return value; - } - - private void setupResources() { - doReturn(true).when(mResource).getBoolean( - R.bool.config_wifi_framework_enable_associated_network_selection); - mMinPacketRateActiveTraffic = setupIntegerResource( - R.integer.config_wifiFrameworkMinPacketPerSecondActiveTraffic, 16); - mSufficientDurationAfterUserSelection = setupIntegerResource( - R.integer.config_wifiSufficientDurationAfterUserSelectionMilliseconds, - WAIT_JUST_A_MINUTE); - doReturn(false).when(mResource).getBoolean(R.bool.config_wifi11axSupportOverride); - } - - private void setupThresholds() { - mThresholdMinimumRssi2G = mScoringParams.getEntryRssi( - ScanResult.BAND_24_GHZ_START_FREQ_MHZ); - mThresholdMinimumRssi5G = mScoringParams.getEntryRssi(ScanResult.BAND_5_GHZ_START_FREQ_MHZ); - - mThresholdQualifiedRssi2G = mScoringParams.getSufficientRssi( - ScanResult.BAND_24_GHZ_START_FREQ_MHZ); - mThresholdQualifiedRssi5G = mScoringParams.getSufficientRssi( - ScanResult.BAND_5_GHZ_START_FREQ_MHZ); - } - - private void setupWifiInfo() { - // simulate a disconnected state - when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.DISCONNECTED); - when(mWifiInfo.is24GHz()).thenReturn(true); - when(mWifiInfo.is5GHz()).thenReturn(false); - when(mWifiInfo.getFrequency()).thenReturn(2400); - when(mWifiInfo.getRssi()).thenReturn(-70); - when(mWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID); - when(mWifiInfo.getBSSID()).thenReturn(null); - } - - private void setupWifiConfigManager() { - setupWifiConfigManager(WifiConfiguration.INVALID_NETWORK_ID); - } - - private void setupWifiConfigManager(int networkId) { - when(mWifiConfigManager.getLastSelectedNetwork()) - .thenReturn(networkId); - } - - /** - * No network selection if scan result is empty. - * - * ClientModeImpl is in disconnected state. - * scanDetails is empty. - * - * Expected behavior: no network recommended by Network Selector - */ - @Test - public void emptyScanResults() { - String[] ssids = new String[0]; - String[] bssids = new String[0]; - int[] freqs = new int[0]; - String[] caps = new String[0]; - int[] levels = new int[0]; - int[] securities = new int[0]; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - assertEquals("Expect null configuration", null, candidate); - assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); - } - - - /** - * No network selection if the RSSI values in scan result are too low. - * - * ClientModeImpl is in disconnected state. - * scanDetails contains a 2.4GHz and a 5GHz network, but both with RSSI lower than - * the threshold - * - * Expected behavior: no network recommended by Network Selector - */ - @Test - public void verifyMinimumRssiThreshold() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G - 1, mThresholdMinimumRssi5G - 1}; - int[] securities = {SECURITY_PSK, SECURITY_EAP}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - assertEquals("Expect null configuration", null, candidate); - assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); - } - - /** - * No network selection if WiFi is connected and it is too short - * from last network selection. Instead, update scanDetailCache. - * - * ClientModeImpl is in connected state. - * scanDetails contains two valid networks. - * Perform a network selection right after the first one. - * - * Expected behavior: no network recommended by Network Selector, update scanDetailCache instead - */ - @Test - public void verifyMinimumTimeGapWhenConnected() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; - int[] securities = {SECURITY_PSK, SECURITY_EAP}; - - // Make a network selection. - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000); - - // Do another network selection with CMI in CONNECTED state. - candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, true, false, false); - candidate = mWifiNetworkSelector.selectNetwork(candidates); - - assertEquals("Expect null configuration", null, candidate); - assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); - - verify(mWifiConfigManager, atLeast(2)).updateScanDetailCacheFromScanDetail(any()); - } - - /** - * Perform network selection if WiFi is disconnected even if it is too short from last - * network selection. - * - * ClientModeImpl is in disconnected state. - * scanDetails contains two valid networks. - * Perform a network selection right after the first one. - * - * Expected behavior: the first network is recommended by Network Selector - */ - @Test - public void verifyNoMinimumTimeGapWhenDisconnected() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; - int[] securities = {SECURITY_EAP, SECURITY_EAP}; - - // Make a network selection. - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - HashSet<String> blacklist = new HashSet<String>(); - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000); - - // Do another network selection with CMI in DISCONNECTED state. - candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - candidate = mWifiNetworkSelector.selectNetwork(candidates); - - ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); - WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); - WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, - chosenScanResult, candidate); - } - - /** - * New network selection is performed if the currently connected network - * has low RSSI value. - * - * ClientModeImpl is connected to a low RSSI 5GHz network. - * scanDetails contains a valid networks. - * Perform a network selection after the first one. - * - * Expected behavior: the first network is recommended by Network Selector - */ - @Test - public void lowRssi5GNetworkIsNotSufficient() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {5180}; - String[] caps = {"[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdQualifiedRssi5G - 2}; - int[] securities = {SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - - // connect to test1 - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); - when(mWifiInfo.getNetworkId()).thenReturn(0); - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - when(mWifiInfo.is24GHz()).thenReturn(false); - when(mWifiInfo.is5GHz()).thenReturn(true); - when(mWifiInfo.getFrequency()).thenReturn(5000); - when(mWifiInfo.getRssi()).thenReturn(levels[0]); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); - - // Do another network selection. - candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, true, false, false); - candidate = mWifiNetworkSelector.selectNetwork(candidates); - - ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); - WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, - chosenScanResult, candidate); - } - - /** - * New network selection is performed if the currently connected network - * has no internet access although it has active traffic and high RSSI - * - * ClientModeImpl is connected to a network with no internet connectivity. - * scanDetails contains a valid networks. - * Perform a network selection after the first one. - * - * Expected behavior: the first network is recommended by Network Selector - */ - @Test - public void noInternetAccessNetworkIsNotSufficient() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {5180}; - String[] caps = {"[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdQualifiedRssi5G + 5}; - int[] securities = {SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - - // connect to test1 - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); - when(mWifiInfo.getNetworkId()).thenReturn(0); - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - when(mWifiInfo.is24GHz()).thenReturn(false); - when(mWifiInfo.is5GHz()).thenReturn(true); - when(mWifiInfo.getFrequency()).thenReturn(5000); - when(mWifiInfo.getRssi()).thenReturn(levels[0]); - when(mWifiInfo.getSuccessfulTxPacketsPerSecond()) - .thenReturn(mMinPacketRateActiveTraffic - 1.0); - when(mWifiInfo.getSuccessfulRxPacketsPerSecond()) - .thenReturn(mMinPacketRateActiveTraffic + 1.0); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); - - // Increment the network's no internet access reports. - savedConfigs[0].numNoInternetAccessReports = 5; - - // Do another network selection. - candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, true, false, false); - candidate = mWifiNetworkSelector.selectNetwork(candidates); - - ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); - WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, - chosenScanResult, candidate); - } - /** - * Ensure that network selector update's network selection status for all configured - * networks before performing network selection. - * - * Expected behavior: the first network is recommended by Network Selector - */ - @Test - public void updateConfiguredNetworks() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 2457}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + 20, mThresholdMinimumRssi2G + RSSI_BUMP}; - int[] securities = {SECURITY_EAP, SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); - - // Do network selection. - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, true, false, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - verify(mWifiMetrics).incrementNetworkSelectionFilteredBssidCount(0); - - verify(mWifiConfigManager).getConfiguredNetworks(); - verify(mWifiConfigManager, times(savedConfigs.length)).tryEnableNetwork(anyInt()); - verify(mWifiConfigManager, times(savedConfigs.length)) - .clearNetworkCandidateScanResult(anyInt()); - verify(mWifiMetrics, atLeastOnce()).addMeteredStat(any(), anyBoolean()); - } - - /** - * Blacklisted BSSID is filtered out for network selection. - * - * ClientModeImpl is disconnected. - * scanDetails contains a network which is blacklisted. - * - * Expected behavior: no network recommended by Network Selector - */ - @Test - public void filterOutBlacklistedBssid() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {5180}; - String[] caps = {"[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdQualifiedRssi5G + 8}; - int[] securities = {SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - blacklist.add(bssids[0]); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - verify(mWifiMetrics).incrementNetworkSelectionFilteredBssidCount(1); - assertEquals("Expect null configuration", null, candidate); - assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); - } - - /** - * Wifi network selector doesn't recommend any network if the currently connected one - * doesn't show up in the scan results. - * - * ClientModeImpl is under connected state and 2.4GHz test1 is connected. - * The second scan results contains only test2 which now has a stronger RSSI than test1. - * Test1 is not in the second scan results. - * - * Expected behavior: no network recommended by Network Selector - */ - @Test - public void noSelectionWhenCurrentNetworkNotInScanResults() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 2457}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + 20, mThresholdMinimumRssi2G + RSSI_BUMP}; - int[] securities = {SECURITY_EAP, SECURITY_PSK}; - - // Make a network selection to connect to test1. - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - - when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); - when(mWifiInfo.getNetworkId()).thenReturn(0); - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - when(mWifiInfo.is24GHz()).thenReturn(true); - when(mWifiInfo.getScore()).thenReturn(ConnectedScore.WIFI_TRANSITION_SCORE); - when(mWifiInfo.is5GHz()).thenReturn(false); - when(mWifiInfo.getFrequency()).thenReturn(2400); - when(mWifiInfo.getRssi()).thenReturn(levels[0]); - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); - - // Prepare the second scan results which have no test1. - String[] ssidsNew = {"\"test2\""}; - String[] bssidsNew = {"6c:f3:7f:ae:8c:f4"}; - int[] freqsNew = {2457}; - String[] capsNew = {"[WPA2-EAP-CCMP][ESS]"}; - int[] levelsNew = {mThresholdMinimumRssi2G + 40}; - scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(ssidsNew, bssidsNew, - freqsNew, capsNew, levelsNew, mClock); - candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, true, false, false); - candidate = mWifiNetworkSelector.selectNetwork(candidates); - - // The second network selection is skipped since current connected network is - // missing from the scan results. - assertEquals("Expect null configuration", null, candidate); - assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); - verify(mWifiConfigManager, atLeast(1)).updateScanDetailCacheFromScanDetail(any()); - } - - /** - * Ensures that setting the user connect choice updates the - * NetworkSelectionStatus#mConnectChoice for all other WifiConfigurations in range in the last - * round of network selection. - * - * Expected behavior: WifiConfiguration.NetworkSelectionStatus#mConnectChoice is set to - * test1's configkey for test2. test3's WifiConfiguration is unchanged. - */ - @Test - public void setUserConnectChoice() { - String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"}; - int[] freqs = {2437, 5180, 5181}; - String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP, - mThresholdMinimumRssi5G + RSSI_BUMP}; - int[] securities = {SECURITY_PSK, SECURITY_EAP, SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - - WifiConfiguration selectedWifiConfig = scanDetailsAndConfigs.getWifiConfigs()[0]; - selectedWifiConfig.getNetworkSelectionStatus() - .setCandidate(scanDetailsAndConfigs.getScanDetails().get(0).getScanResult()); - selectedWifiConfig.getNetworkSelectionStatus().setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); - selectedWifiConfig.getNetworkSelectionStatus().setConnectChoice("bogusKey"); - - WifiConfiguration configInLastNetworkSelection = scanDetailsAndConfigs.getWifiConfigs()[1]; - configInLastNetworkSelection.getNetworkSelectionStatus() - .setSeenInLastQualifiedNetworkSelection(true); - - WifiConfiguration configNotInLastNetworkSelection = - scanDetailsAndConfigs.getWifiConfigs()[2]; - - assertTrue(mWifiNetworkSelector.setUserConnectChoice(selectedWifiConfig.networkId)); - - verify(mWifiConfigManager).updateNetworkSelectionStatus(selectedWifiConfig.networkId, - NetworkSelectionStatus.DISABLED_NONE); - verify(mWifiConfigManager).clearNetworkConnectChoice(selectedWifiConfig.networkId); - verify(mWifiConfigManager).setNetworkConnectChoice(configInLastNetworkSelection.networkId, - selectedWifiConfig.getKey()); - verify(mWifiConfigManager, never()).setNetworkConnectChoice( - configNotInLastNetworkSelection.networkId, selectedWifiConfig.getKey()); - } - - /** - * Wifi network selector stays with current network if current network is not nominated - * but has the higher score - */ - @Test - public void includeCurrentNetworkWhenCurrentNetworkNotNominated() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5120}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + 10, mThresholdMinimumRssi2G + 20}; - int[] securities = {SECURITY_EAP, SECURITY_PSK}; - // VHT cap IE - byte[] iesBytes = {(byte) 0x92, (byte) 0x01, (byte) 0x80, (byte) 0x33, (byte) 0xaa, - (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0xaa, (byte) 0xff, (byte) 0x00, - (byte) 0x00}; - byte[][] iesByteStream = {iesBytes, iesBytes}; - // Make a network selection to connect to test1. - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock, iesByteStream); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - assertEquals(2, scanDetails.size()); - HashSet<String> blocklist = new HashSet<String>(); - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blocklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - - when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); - when(mWifiInfo.getNetworkId()).thenReturn(0); // 0 is current network - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - when(mWifiInfo.is24GHz()).thenReturn(true); - when(mWifiInfo.getScore()).thenReturn(ConnectedScore.WIFI_TRANSITION_SCORE); - when(mWifiInfo.is5GHz()).thenReturn(false); - when(mWifiInfo.getFrequency()).thenReturn(2400); - when(mWifiInfo.getRssi()).thenReturn(levels[0]); - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); - - when(mThroughputPredictor.predictThroughput(any(), anyInt(), anyInt(), anyInt(), - anyInt(), anyInt(), anyInt(), anyInt(), anyBoolean())).thenReturn(100); - // Force to return 2nd network in the network nominator - mDummyNominator.setNetworkIndexToReturn(1); - - candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blocklist, mWifiInfo, true, false, false); - assertEquals(2, candidates.size()); - assertEquals(100, candidates.get(0).getPredictedThroughputMbps()); - } - - /** - * If two qualified networks, test1 and test2, are in range when the user selects test2 over - * test1, WifiNetworkSelector will override the NetworkSelector's choice to connect to test1 - * with test2. - * - * Expected behavior: test2 is the recommended network - */ - @Test - public void userConnectChoiceOverridesNetworkNominators() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; - int[] securities = {SECURITY_PSK, SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - - // DummyNominator always selects the first network in the list. - WifiConfiguration networkSelectorChoice = scanDetailsAndConfigs.getWifiConfigs()[0]; - networkSelectorChoice.getNetworkSelectionStatus() - .setSeenInLastQualifiedNetworkSelection(true); - - WifiConfiguration userChoice = scanDetailsAndConfigs.getWifiConfigs()[1]; - userChoice.getNetworkSelectionStatus() - .setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult()); - - // With no user choice set, networkSelectorChoice should be chosen. - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - - ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class); - verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId), - nominatorIdCaptor.capture()); - // unknown because DummyNominator does not have a nominator ID - // getValue() returns the argument from the *last* call - assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN, - nominatorIdCaptor.getValue().intValue()); - - WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); - - assertTrue(mWifiNetworkSelector.setUserConnectChoice(userChoice.networkId)); - - // After user connect choice is set, userChoice should override networkSelectorChoice. - candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - candidate = mWifiNetworkSelector.selectNetwork(candidates); - - verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId), - nominatorIdCaptor.capture()); - // getValue() returns the argument from the *last* call - assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE, - nominatorIdCaptor.getValue().intValue()); - WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate); - } - - /** - * Tests when multiple Nominators nominate the same candidate, any one of the nominator IDs is - * acceptable. - */ - @Test - public void testMultipleNominatorsSetsNominatorIdCorrectly() { - // first dummy Nominator is registered in setup, returns index 0 - // register a second network Nominator that also returns index 0, but with a different ID - mWifiNetworkSelector.registerNetworkNominator(new DummyNetworkNominator(0, - WifiNetworkSelector.NetworkNominator.NOMINATOR_ID_SCORED)); - // register a third network Nominator that also returns index 0, but with a different ID - mWifiNetworkSelector.registerNetworkNominator(new DummyNetworkNominator(0, - WifiNetworkSelector.NetworkNominator.NOMINATOR_ID_SAVED)); - - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; - int[] securities = {SECURITY_PSK, SECURITY_PSK}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<>(); - - // DummyNominator always selects the first network in the list. - WifiConfiguration networkSelectorChoice = scanDetailsAndConfigs.getWifiConfigs()[0]; - networkSelectorChoice.getNetworkSelectionStatus() - .setSeenInLastQualifiedNetworkSelection(true); - - WifiConfiguration userChoice = scanDetailsAndConfigs.getWifiConfigs()[1]; - userChoice.getNetworkSelectionStatus() - .setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult()); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - - ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class); - verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId), - nominatorIdCaptor.capture()); - - for (int nominatorId : nominatorIdCaptor.getAllValues()) { - assertThat(nominatorId, is(oneOf( - WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN, - WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED, - WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED))); - } - verify(mWifiMetrics, atLeastOnce()).setNetworkSelectorExperimentId(anyInt()); - } - - /** - * Wifi network selector performs network selection when current network has high - * quality but no active stream - * - * Expected behavior: network selection is performed - */ - @Test - public void testNoActiveStream() { - // Rssi after connected. - when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1); - when(mWifiInfo.getSuccessfulTxPacketsPerSecond()).thenReturn(0.0); - when(mWifiInfo.getSuccessfulRxPacketsPerSecond()).thenReturn(0.0); - - testStayOrTryToSwitch( - // Parameters for network1: - mThresholdQualifiedRssi2G + 1 /* rssi before connected */, - false /* not a 5G network */, - false /* not open network */, - false /* not a osu */, - // Parameters for network2: - mThresholdQualifiedRssi5G + 1 /* rssi */, - true /* a 5G network */, - false /* not open network */, - // Should try to switch. - true); - } - - /** - * Wifi network selector skips network selection when current network is osu and has low RSSI - * - * Expected behavior: network selection is skipped - */ - @Test - public void testOsuIsSufficient() { - // Rssi after connected. - when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G - 1); - when(mWifiInfo.getSuccessfulTxPacketsPerSecond()).thenReturn(0.0); - when(mWifiInfo.getSuccessfulRxPacketsPerSecond()).thenReturn(0.0); - - testStayOrTryToSwitch( - // Parameters for network1: - mThresholdQualifiedRssi5G - 1 /* rssi before connected */, - false /* not a 5G network */, - false /* not open network */, - true /* osu */, - // Parameters for network2: - mThresholdQualifiedRssi5G + 1 /* rssi */, - true /* a 5G network */, - false /* not open network */, - // Should not try to switch. - false); - } - - /** - * Wifi network selector will not perform network selection when current network has high - * quality and active stream - * - * - * Expected behavior: network selection is not performed - */ - @Test - public void testSufficientLinkQualityActiveStream() { - // Rssi after connected. - when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G + 1); - when(mWifiInfo.getSuccessfulTxPacketsPerSecond()) - .thenReturn(mMinPacketRateActiveTraffic - 1.0); - when(mWifiInfo.getSuccessfulRxPacketsPerSecond()) - .thenReturn(mMinPacketRateActiveTraffic * 2.0); - - testStayOrTryToSwitch( - mThresholdQualifiedRssi5G + 1 /* rssi before connected */, - true /* a 5G network */, - false /* not open network */, - // Should not try to switch. - false); - } - - /** - * New network selection is not performed if the currently connected network - * was recently selected. - */ - @Test - public void networkIsSufficientWhenRecentlyUserSelected() { - // Approximate mClock.getElapsedSinceBootMillis value mocked by testStayOrTryToSwitch - long millisSinceBoot = SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000; - when(mWifiConfigManager.getLastSelectedTimeStamp()) - .thenReturn(millisSinceBoot - - WAIT_JUST_A_MINUTE - + 1000); - setupWifiConfigManager(0); // testStayOrTryToSwitch first connects to network 0 - // Rssi after connected. - when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1); - // No streaming traffic. - when(mWifiInfo.getSuccessfulTxPacketsPerSecond()).thenReturn(0.0); - when(mWifiInfo.getSuccessfulRxPacketsPerSecond()).thenReturn(0.0); - - testStayOrTryToSwitch( - mThresholdQualifiedRssi2G + 1 /* rssi before connected */, - false /* not a 5G network */, - false /* not open network */, - // Should not try to switch. - false); - } - - /** - * New network selection is performed if the currently connected network has bad rssi. - * - * Expected behavior: Network Selector perform network selection after connected - * to the first one. - */ - @Test - public void testBadRssi() { - // Rssi after connected. - when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G - 1); - when(mWifiInfo.getSuccessfulTxPacketsPerSecond()) - .thenReturn(mMinPacketRateActiveTraffic + 1.0); - when(mWifiInfo.getSuccessfulRxPacketsPerSecond()) - .thenReturn(mMinPacketRateActiveTraffic - 1.0); - - testStayOrTryToSwitch( - mThresholdQualifiedRssi2G + 1 /* rssi before connected */, - false /* not a 5G network */, - false /* not open network */, - // Should try to switch. - true); - } - - /** - * This is a meta-test that given two scan results of various types, will - * determine whether or not network selection should be performed. - * - * It sets up two networks, connects to the first, and then ensures that - * both are available in the scan results for the NetworkSelector. - */ - private void testStayOrTryToSwitch( - int rssiNetwork1, boolean is5GHzNetwork1, boolean isOpenNetwork1, - boolean isFirstNetworkOsu, - int rssiNetwork2, boolean is5GHzNetwork2, boolean isOpenNetwork2, - boolean shouldSelect) { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {is5GHzNetwork1 ? 5180 : 2437, is5GHzNetwork2 ? 5180 : 2437}; - String[] caps = {isOpenNetwork1 ? "[ESS]" : "[WPA2-PSK][ESS]", - isOpenNetwork2 ? "[ESS]" : "[WPA2-PSK][ESS]"}; - int[] levels = {rssiNetwork1, rssiNetwork2}; - int[] securities = {isOpenNetwork1 ? SECURITY_NONE : SECURITY_PSK, - isOpenNetwork2 ? SECURITY_NONE : SECURITY_PSK}; - testStayOrTryToSwitchImpl(ssids, bssids, freqs, caps, levels, securities, isFirstNetworkOsu, - shouldSelect); - } - - /** - * This is a meta-test that given one scan results, will - * determine whether or not network selection should be performed. - * - * It sets up one network, connects to it, and then ensures that it is in - * the scan results for the NetworkSelector. - */ - private void testStayOrTryToSwitch( - int rssi, boolean is5GHz, boolean isOpenNetwork, - boolean shouldSelect) { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {is5GHz ? 5180 : 2437}; - String[] caps = {isOpenNetwork ? "[ESS]" : "[WPA2-PSK][ESS]"}; - int[] levels = {rssi}; - int[] securities = {isOpenNetwork ? SECURITY_NONE : SECURITY_PSK}; - testStayOrTryToSwitchImpl(ssids, bssids, freqs, caps, levels, securities, false, - shouldSelect); - } - - private void testStayOrTryToSwitchImpl(String[] ssids, String[] bssids, int[] freqs, - String[] caps, int[] levels, int[] securities, boolean isFirstNetworkOsu, - boolean shouldSelect) { - // Make a network selection to connect to test1. - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - HashSet<String> blacklist = new HashSet<String>(); - // DummyNetworkNominator always return the first network in the scan results - // for connection, so this should connect to the first network. - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, true); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - assertNotNull("Result should be not null", candidate); - WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, - scanDetails.get(0).getScanResult(), candidate); - - when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); - when(mWifiInfo.getNetworkId()).thenReturn(0); - when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - when(mWifiInfo.is24GHz()).thenReturn(!ScanResult.is5GHz(freqs[0])); - when(mWifiInfo.is5GHz()).thenReturn(ScanResult.is5GHz(freqs[0])); - when(mWifiInfo.getFrequency()).thenReturn(freqs[0]); - if (isFirstNetworkOsu) { - WifiConfiguration[] configs = scanDetailsAndConfigs.getWifiConfigs(); - // Force 1st network to OSU - configs[0].osu = true; - when(mWifiConfigManager.getConfiguredNetwork(mWifiInfo.getNetworkId())) - .thenReturn(configs[0]); - } - - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); - - candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, true, false, false); - candidate = mWifiNetworkSelector.selectNetwork(candidates); - - // DummyNetworkNominator always return the first network in the scan results - // for connection, so if network selection is performed, the first network should - // be returned as candidate. - if (shouldSelect) { - assertNotNull("Result should be not null", candidate); - WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, - scanDetails.get(0).getScanResult(), candidate); - } else { - assertEquals("Expect null configuration", null, candidate); - } - } - - /** - * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out - * networks that are not open after network selection is made. - * - * Expected behavior: return open networks only - */ - @Test - public void getfilterOpenUnsavedNetworks_filtersForOpenNetworks() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; - mDummyNominator.setNominatorToSelectCandidate(false); - - List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( - ssids, bssids, freqs, caps, levels, mClock); - HashSet<String> blacklist = new HashSet<>(); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); - expectedOpenUnsavedNetworks.add(scanDetails.get(1)); - assertEquals("Expect open unsaved networks", - expectedOpenUnsavedNetworks, - mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks()); - } - - /** - * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out - * saved networks after network selection is made. This should return an empty list when there - * are no unsaved networks available. - * - * Expected behavior: return unsaved networks only. Return empty list if there are no unsaved - * networks. - */ - @Test - public void getfilterOpenUnsavedNetworks_filtersOutSavedNetworks() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP}; - int[] securities = {SECURITY_NONE}; - mDummyNominator.setNominatorToSelectCandidate(false); - - List<ScanDetail> unSavedScanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( - ssids, bssids, freqs, caps, levels, mClock); - HashSet<String> blacklist = new HashSet<>(); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - unSavedScanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - assertEquals("Expect open unsaved networks", - unSavedScanDetails, - mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks()); - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> savedScanDetails = scanDetailsAndConfigs.getScanDetails(); - - candidates = mWifiNetworkSelector.getCandidatesFromScan( - savedScanDetails, blacklist, mWifiInfo, false, true, false); - candidate = mWifiNetworkSelector.selectNetwork(candidates); - // Saved networks are filtered out. - assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty()); - } - - /** - * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out - * bssid blacklisted networks. - * - * Expected behavior: do not return blacklisted network - */ - @Test - public void getfilterOpenUnsavedNetworks_filtersOutBlacklistedNetworks() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[ESS]", "[ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; - mDummyNominator.setNominatorToSelectCandidate(false); - - List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( - ssids, bssids, freqs, caps, levels, mClock); - HashSet<String> blacklist = new HashSet<>(); - blacklist.add(bssids[0]); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); - expectedOpenUnsavedNetworks.add(scanDetails.get(1)); - assertEquals("Expect open unsaved networks", - expectedOpenUnsavedNetworks, - mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks()); - } - - /** - * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should return - * empty list when there are no open networks after network selection is made. - * - * Expected behavior: return empty list - */ - @Test - public void getfilterOpenUnsavedNetworks_returnsEmptyListWhenNoOpenNetworksPresent() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; - mDummyNominator.setNominatorToSelectCandidate(false); - - List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( - ssids, bssids, freqs, caps, levels, mClock); - HashSet<String> blacklist = new HashSet<>(); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty()); - } - - /** - * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should return - * empty list when no network selection has been made. - * - * Expected behavior: return empty list - */ - @Test - public void getfilterOpenUnsavedNetworks_returnsEmptyListWhenNoNetworkSelectionMade() { - assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty()); - } - - /** - * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} for device that - * supports enhanced open networks, should filter out networks that are not open and not - * enhanced open after network selection is made. - * - * Expected behavior: return open and enhanced open networks only - */ - @Test - public void getfilterOpenUnsavedNetworks_filtersForOpenAndOweNetworksOweSupported() { - String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"}; - int[] freqs = {2437, 5180, 2414}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]", "[RSN-OWE-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP, - mThresholdMinimumRssi2G + RSSI_BUMP}; - mDummyNominator.setNominatorToSelectCandidate(false); - when(mWifiNative.getSupportedFeatureSet(anyString())) - .thenReturn(new Long(WIFI_FEATURE_OWE)); - - List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( - ssids, bssids, freqs, caps, levels, mClock); - HashSet<String> blacklist = new HashSet<>(); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); - expectedOpenUnsavedNetworks.add(scanDetails.get(1)); - expectedOpenUnsavedNetworks.add(scanDetails.get(2)); - assertEquals("Expect open unsaved networks", - expectedOpenUnsavedNetworks, - mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks()); - } - - /** - * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} for device that - * does not support enhanced open networks, should filter out both networks that are not open - * and enhanced open after network selection is made. - * - * Expected behavior: return open networks only - */ - @Test - public void getfilterOpenUnsavedNetworks_filtersForOpenAndOweNetworksOweNotSupported() { - String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"}; - int[] freqs = {2437, 5180, 2414}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]", "[RSN-OWE-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP, - mThresholdMinimumRssi2G + RSSI_BUMP}; - mDummyNominator.setNominatorToSelectCandidate(false); - when(mWifiNative.getSupportedFeatureSet(anyString())) - .thenReturn(new Long(~WIFI_FEATURE_OWE)); - - List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( - ssids, bssids, freqs, caps, levels, mClock); - HashSet<String> blacklist = new HashSet<>(); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); - expectedOpenUnsavedNetworks.add(scanDetails.get(1)); - assertEquals("Expect open unsaved networks", - expectedOpenUnsavedNetworks, - mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks()); - } - - /** - * Test that registering a new CandidateScorer causes it to be used - */ - @Test - public void testCandidateScorerUse() throws Exception { - String myid = "Mock CandidateScorer"; - when(mCandidateScorer.getIdentifier()).thenReturn(myid); - setupWifiConfigManager(13); - - int experimentId = experimentIdFromIdentifier(myid); - assertTrue("" + myid, 42000000 <= experimentId && experimentId <= 42999999); - String diagnose = "" + mScoringParams + " // " + experimentId; - assertTrue(diagnose, mScoringParams.update("expid=" + experimentId)); - assertEquals(experimentId, mScoringParams.getExperimentIdentifier()); - - mWifiNetworkSelector.registerCandidateScorer(mCandidateScorer); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - setUpTwoNetworks(-35, -40), - EMPTY_BLACKLIST, mWifiInfo, false, true, true); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - - verify(mCandidateScorer, atLeastOnce()).scoreCandidates(any()); - } - - /** - * Tests that no metrics are recorded if there is only a single legacy scorer. - */ - @Test - public void testCandidateScorerMetrics_onlyOneScorer() { - testNoActiveStream(); - - verify(mWifiMetrics, never()).logNetworkSelectionDecision( - anyInt(), anyInt(), anyBoolean(), anyInt()); - } - - private static final WifiCandidates.CandidateScorer NULL_SCORER = - new WifiCandidates.CandidateScorer() { - @Override - public String getIdentifier() { - return "NULL_SCORER"; - } - - @Override - public WifiCandidates.ScoredCandidate scoreCandidates( - Collection<WifiCandidates.Candidate> group) { - return new WifiCandidates.ScoredCandidate(0, 0, false, null); - } - }; - - private List<ScanDetail> setUpTwoNetworks(int rssiNetwork1, int rssiNetwork2) { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {5180, 2437}; - String[] caps = {"[ESS]", "[ESS]"}; - int[] levels = {rssiNetwork1, rssiNetwork2}; - int[] securities = {SECURITY_NONE, SECURITY_NONE}; - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - return scanDetailsAndConfigs.getScanDetails(); - } - - /** - * Tests that metrics are recorded for 3 scorers. - */ - @Test - public void testCandidateScorerMetrics_threeScorers() { - mWifiNetworkSelector.registerCandidateScorer(mCompatibilityScorer); - mWifiNetworkSelector.registerCandidateScorer(NULL_SCORER); - - // add a second NetworkNominator that returns the second network in the scan list - mWifiNetworkSelector.registerNetworkNominator( - new DummyNetworkNominator(1, DUMMY_NOMINATOR_ID_2)); - - int compatibilityExpId = experimentIdFromIdentifier(mCompatibilityScorer.getIdentifier()); - mScoringParams.update("expid=" + compatibilityExpId); - assertEquals(compatibilityExpId, mScoringParams.getExperimentIdentifier()); - - testNoActiveStream(); - - int nullScorerId = experimentIdFromIdentifier(NULL_SCORER.getIdentifier()); - - // Wanted 2 times since testNoActiveStream() calls - // WifiNetworkSelector.selectNetwork() twice - verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(nullScorerId, - compatibilityExpId, false, 2); - - int expid = CompatibilityScorer.COMPATIBILITY_SCORER_DEFAULT_EXPID; - verify(mWifiMetrics, atLeastOnce()).setNetworkSelectorExperimentId(eq(expid)); - } - - /** - * Tests that metrics are recorded for two scorers. - */ - @Test - public void testCandidateScorerMetricsThroughputScorer() { - if (WifiNetworkSelector.PRESET_CANDIDATE_SCORER_NAME.equals( - mThroughputScorer.getIdentifier())) { - mWifiNetworkSelector.registerCandidateScorer(mCompatibilityScorer); - return; //TODO(b/142081306) temporarily disabled - } else { - mWifiNetworkSelector.registerCandidateScorer(mThroughputScorer); - } - - // add a second NetworkNominator that returns the second network in the scan list - mWifiNetworkSelector.registerNetworkNominator( - new DummyNetworkNominator(1, DUMMY_NOMINATOR_ID_2)); - - testNoActiveStream(); - - int throughputExpId = experimentIdFromIdentifier(mThroughputScorer.getIdentifier()); - int compatibilityExpId = experimentIdFromIdentifier(mCompatibilityScorer.getIdentifier()); - - // Wanted 2 times since testNoActiveStream() calls - // WifiNetworkSelector.selectNetwork() twice - if (WifiNetworkSelector.PRESET_CANDIDATE_SCORER_NAME.equals( - mThroughputScorer.getIdentifier())) { - verify(mWifiMetrics, times(2)).logNetworkSelectionDecision( - compatibilityExpId, throughputExpId, true, 2); - } else { - verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(throughputExpId, - compatibilityExpId, true, 2); - } - } - - /** - * Tests that passpoint network candidate will update SSID with the latest scanDetail. - */ - @Test - public void testPasspointCandidateUpdateWithLatestScanDetail() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1}; - int[] securities = {SECURITY_EAP, SECURITY_EAP}; - HashSet<String> blacklist = new HashSet<>(); - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] configs = scanDetailsAndConfigs.getWifiConfigs(); - WifiConfiguration existingConfig = WifiConfigurationTestUtil.createPasspointNetwork(); - existingConfig.SSID = ssids[1]; - // Matched wifiConfig is an passpoint network with SSID from last scan. - when(mWifiConfigManager.getConfiguredNetwork(configs[0].networkId)) - .thenReturn(existingConfig); - mWifiNetworkSelector.registerNetworkNominator( - new DummyNetworkNominator(0, DUMMY_NOMINATOR_ID_2)); - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, true); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - // Check if the wifiConfig is updated with the latest - verify(mWifiConfigManager).addOrUpdateNetwork(existingConfig, - existingConfig.creatorUid, existingConfig.creatorName); - assertEquals(ssids[0], candidate.SSID); - } - - @Test - public void testIsFromCarrierOrPrivilegedApp() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 5180}; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1}; - int[] securities = {SECURITY_EAP, SECURITY_EAP}; - HashSet<String> blacklist = new HashSet<>(); - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration[] configs = scanDetailsAndConfigs.getWifiConfigs(); - // Mark one of the networks as carrier privileged. - configs[0].fromWifiNetworkSuggestion = true; - configs[0].carrierId = 5; - mWifiNetworkSelector.registerNetworkNominator( - new AllNetworkNominator(scanDetailsAndConfigs)); - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, true); - // Expect one privileged and one regular candidate. - assertEquals(2, candidates.size()); - boolean foundCarrierOrPrivilegedAppCandidate = false; - boolean foundNotCarrierOrPrivilegedAppCandidate = false; - for (WifiCandidates.Candidate candidate : candidates) { - if (candidate.isCarrierOrPrivileged()) { - foundCarrierOrPrivilegedAppCandidate = true; - } else { - foundNotCarrierOrPrivilegedAppCandidate = true; - } - } - assertTrue(foundCarrierOrPrivilegedAppCandidate); - assertTrue(foundNotCarrierOrPrivilegedAppCandidate); - } - - /** - * Test that network which are not accepting new connections(MBO - * association disallowed attribute in beacons/probe responses) - * are filtered out from network selection. - * - * NetworkDetail contain the parsed association disallowed - * reason code. - * - * Expected behavior: no network recommended by Network Selector - */ - @Test - public void filterMboApAdvertisingAssociationDisallowedAttr() { - String[] ssids = {"\"test1\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3"}; - int[] freqs = {5180}; - String[] caps = {"[WPA2-PSK][ESS]"}; - int[] levels = {mThresholdQualifiedRssi5G + 8}; - int[] securities = {SECURITY_PSK}; - // MBO-OCE IE with association disallowed attribute. - byte[][] iesByteStream = {{(byte) 0xdd, (byte) 0x0a, - (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x16, - (byte) 0x01, (byte) 0x01, (byte) 0x40, - (byte) 0x04, (byte) 0x01, (byte) 0x03}}; - HashSet<String> blacklist = new HashSet<String>(); - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock, iesByteStream); - List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetails, blacklist, mWifiInfo, false, true, false); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); - verify(mWifiMetrics, times(1)) - .incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd(); - assertEquals("Expect null configuration", null, candidate); - assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); - } - - @Test - public void resetOnDisableCallsClearLastSelectedNetwork() { - mWifiNetworkSelector.resetOnDisable(); - verify(mWifiConfigManager).clearLastSelectedNetwork(); - assertEquals(0, mWifiNetworkSelector.getKnownMeteredNetworkIds().size()); - } - - @Test - public void meteredStickyness() { - String[] ssids = {"\"test1\"", "\"test2\""}; - String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; - int[] freqs = {2437, 2412}; - String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi2G + 1}; - int[] securities = {SECURITY_PSK, SECURITY_EAP}; - - ScanDetailsAndWifiConfigs scanDetailsAndConfigs = - WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, - freqs, caps, levels, securities, mWifiConfigManager, mClock); - - // Nominate all of these networks - mWifiNetworkSelector.registerNetworkNominator( - new AllNetworkNominator(scanDetailsAndConfigs)); - - // Check setup - assertEquals(0, mWifiNetworkSelector.getKnownMeteredNetworkIds().size()); - - // No metered networks, expect no sticky bits - runNetworkSelectionWith(scanDetailsAndConfigs); - assertEquals(0, mWifiNetworkSelector.getKnownMeteredNetworkIds().size()); - - // Encountering a metered network should get recorded - scanDetailsAndConfigs.getWifiConfigs()[1].meteredHint = true; - runNetworkSelectionWith(scanDetailsAndConfigs); - HashSet<Integer> expect = new HashSet<>(); - expect.add(scanDetailsAndConfigs.getWifiConfigs()[1].networkId); - assertEquals(expect, mWifiNetworkSelector.getKnownMeteredNetworkIds()); - - // Override to unmetered should cause sticky removal - // Make the other one metered this time, using hint - scanDetailsAndConfigs.getWifiConfigs()[1].meteredOverride = - WifiConfiguration.METERED_OVERRIDE_NOT_METERED; - scanDetailsAndConfigs.getWifiConfigs()[0].meteredHint = true; - runNetworkSelectionWith(scanDetailsAndConfigs); - expect.clear(); - expect.add(scanDetailsAndConfigs.getWifiConfigs()[0].networkId); - assertEquals(expect, mWifiNetworkSelector.getKnownMeteredNetworkIds()); - - // Override to metered should also cause sticky removal - scanDetailsAndConfigs.getWifiConfigs()[0].meteredOverride = - WifiConfiguration.METERED_OVERRIDE_METERED; - runNetworkSelectionWith(scanDetailsAndConfigs); - assertEquals(0, mWifiNetworkSelector.getKnownMeteredNetworkIds().size()); - - // Need to make sticky list nonempty - scanDetailsAndConfigs.getWifiConfigs()[0].meteredOverride = - WifiConfiguration.METERED_OVERRIDE_NONE; - scanDetailsAndConfigs.getWifiConfigs()[0].meteredHint = true; - runNetworkSelectionWith(scanDetailsAndConfigs); - assertEquals(1, mWifiNetworkSelector.getKnownMeteredNetworkIds().size()); - // Toggling wifi off should clear the sticky bits - mWifiNetworkSelector.resetOnDisable(); - assertEquals(0, mWifiNetworkSelector.getKnownMeteredNetworkIds().size()); - } - - private void runNetworkSelectionWith(ScanDetailsAndWifiConfigs scanDetailsAndConfigs) { - List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( - scanDetailsAndConfigs.getScanDetails(), - new HashSet<>(), // blocklist - mWifiInfo, // wifiInfo - false, // connected - true, // disconnected - true // untrustedNetworkAllowed - ); - WifiConfiguration wifiConfiguration = mWifiNetworkSelector.selectNetwork(candidates); - assertNotNull(wifiConfiguration); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java deleted file mode 100644 index 6f98f6a7d..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_SAE; -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_WAPI_PSK; -import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.net.NetworkKey; -import android.net.RssiCurve; -import android.net.ScoredNetwork; -import android.net.WifiKey; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiSsid; -import android.text.TextUtils; - -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.util.InformationElementUtil; -import com.android.server.wifi.util.NativeUtil; -import com.android.server.wifi.util.ScanResultUtil; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Helper for WifiNetworkSelector unit tests. - */ -public class WifiNetworkSelectorTestUtil { - private static final String TAG = "WifiNetworkSelectorTestUtil"; - /** - * A class that holds a list of scanDetail and their associated WifiConfiguration. - */ - public static class ScanDetailsAndWifiConfigs { - List<ScanDetail> mScanDetails; - WifiConfiguration[] mWifiConfigs; - - ScanDetailsAndWifiConfigs(List<ScanDetail> scanDetails, WifiConfiguration[] configs) { - mScanDetails = scanDetails; - mWifiConfigs = configs; - } - - List<ScanDetail> getScanDetails() { - return mScanDetails; - } - - WifiConfiguration[] getWifiConfigs() { - return mWifiConfigs; - } - } - - /** - * Build a list of ScanDetail based on the caller supplied network SSID, BSSID, - * frequency, capability and RSSI level information. Create the corresponding - * WifiConfiguration for these networks and set up the mocked WifiConfigManager. - * - * @param ssids an array of SSIDs - * @param bssids an array of BSSIDs - * @param freqs an array of the network's frequency - * @param caps an array of the network's capability - * @param levels an array of the network's RSSI levels - * @param securities an array of the network's security setting - * @param wifiConfigManager the mocked WifiConfigManager - * @return the constructed ScanDetail list and WifiConfiguration array - */ - public static ScanDetailsAndWifiConfigs setupScanDetailsAndConfigStore(String[] ssids, - String[] bssids, int[] freqs, String[] caps, int[] levels, int[] securities, - WifiConfigManager wifiConfigManager, Clock clock) { - List<ScanDetail> scanDetails = buildScanDetails(ssids, bssids, freqs, caps, levels, clock); - - WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, securities); - - addWifiConfigAndLinkScanResult(wifiConfigManager, savedConfigs, scanDetails); - - return new ScanDetailsAndWifiConfigs(scanDetails, savedConfigs); - } - - public static ScanDetailsAndWifiConfigs setupScanDetailsAndConfigStore(String[] ssids, - String[] bssids, int[] freqs, String[] caps, int[] levels, - int[] securities, WifiConfigManager wifiConfigManager, Clock clock, - byte[][] iesByteStream) { - - if (iesByteStream == null) { - throw new IllegalArgumentException("Null ies"); - } - - List<ScanDetail> scanDetails = buildScanDetailsWithNetworkDetails(ssids, bssids, freqs, - caps, levels, iesByteStream, clock); - - WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, securities); - - addWifiConfigAndLinkScanResult(wifiConfigManager, savedConfigs, scanDetails); - - return new ScanDetailsAndWifiConfigs(scanDetails, savedConfigs); - } - - /** - * Build a list of ScanDetail based on the caller supplied network SSID, BSSID, - * frequency and RSSI level information. Create the EAP-SIM authticated - * WifiConfiguration for these networks and set up the mocked WifiConfigManager. - * - * @param ssids an array of SSIDs - * @param bssids an array of BSSIDs - * @param freqs an array of the network's frequency - * @param levels an array of the network's RSSI levels - * @param wifiConfigManager the mocked WifiConfigManager - * @return the constructed ScanDetail list and WifiConfiguration array - */ - public static ScanDetailsAndWifiConfigs setupScanDetailsAndConfigForEapSimNetwork( - String[] ssids, - String[] bssids, int[] freqs, int[] levels, - WifiConfigManager wifiConfigManager, Clock clock) { - assertNotNull(ssids); - String[] caps = new String[ssids.length]; - for (int i = 0; i < ssids.length; i++) { - caps[i] = "[EAP][ESS]"; - } - List<ScanDetail> scanDetails = buildScanDetails(ssids, bssids, freqs, caps, levels, clock); - WifiConfiguration[] savedConfigs = new WifiConfiguration[ssids.length]; - Set<String> ssidSet = new HashSet<>(); - for (int i = 0; i < ssids.length; i++) { - // do not allow duplicated ssid - assertFalse(ssidSet.contains(ssids[i])); - ssidSet.add(ssids[i]); - savedConfigs[i] = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - savedConfigs[i].SSID = ssids[i]; - savedConfigs[i].networkId = i; - } - - addWifiConfigAndLinkScanResult(wifiConfigManager, savedConfigs, scanDetails); - - return new ScanDetailsAndWifiConfigs(scanDetails, savedConfigs); - } - - private static void addWifiConfigAndLinkScanResult(WifiConfigManager wifiConfigManager, - WifiConfiguration[] configs, List<ScanDetail> scanDetails) { - checkConsistencyOfScanDetailsAndWifiConfigs(scanDetails, configs); - prepareConfigStore(wifiConfigManager, configs); - scanResultLinkConfiguration(wifiConfigManager, configs, scanDetails); - } - - private static void checkConsistencyOfScanDetailsAndWifiConfigs( - List<ScanDetail> scanDetails, - WifiConfiguration[] savedConfigs) { - assertEquals(scanDetails.size(), savedConfigs.length); - for (int i = 0; i < savedConfigs.length; i++) { - ScanResult scanResult = scanDetails.get(i).getScanResult(); - WifiConfiguration config = savedConfigs[i]; - assertEquals("Problem in entry " + i, - ScanResultMatchInfo.fromScanResult(scanResult), - ScanResultMatchInfo.fromWifiConfiguration(config)); - } - } - - /** - * Verify whether the WifiConfiguration chosen by WifiNetworkSelector matches - * with the chosen scan result. - * - * @param chosenScanResult the chosen scan result - * @param chosenCandidate the chosen configuration - */ - public static void verifySelectedScanResult(WifiConfigManager wifiConfigManager, - ScanResult chosenScanResult, WifiConfiguration chosenCandidate) { - verify(wifiConfigManager, atLeastOnce()).setNetworkCandidateScanResult( - eq(chosenCandidate.networkId), eq(chosenScanResult), anyInt()); - } - - - /** - * Build a list of scanDetails based on the caller supplied network SSID, BSSID, - * frequency, capability and RSSI level information. - * - * @param ssids an array of SSIDs - * @param bssids an array of BSSIDs - * @param freqs an array of the network's frequency - * @param caps an array of the network's capability - * @param levels an array of the network's RSSI levels - * @return the constructed list of ScanDetail - */ - public static List<ScanDetail> buildScanDetails(String[] ssids, String[] bssids, int[] freqs, - String[] caps, int[] levels, Clock clock) { - List<ScanDetail> scanDetailList = new ArrayList<ScanDetail>(); - - long timeStamp = clock.getElapsedSinceBootMillis(); - for (int index = 0; index < ssids.length; index++) { - byte[] ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssids[index])); - ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromByteArray(ssid), - bssids[index], caps[index], levels[index], freqs[index], timeStamp, 0); - scanDetailList.add(scanDetail); - } - return scanDetailList; - } - - /** - * Build a list of scanDetails along with network details based - * on the caller supplied network SSID, BSSID, frequency, - * capability, byte stream of IEs and RSSI level information. - * - * @param ssids an array of SSIDs - * @param bssids an array of BSSIDs - * @param freqs an array of the network's frequency - * @param caps an array of the network's capability - * @param levels an array of the network's RSSI levels - * @return the constructed list of ScanDetail - */ - public static List<ScanDetail> buildScanDetailsWithNetworkDetails(String[] ssids, - String[] bssids, int[] freqs, - String[] caps, int[] levels, byte[][] iesByteStream, Clock clock) { - List<ScanDetail> scanDetailList = new ArrayList<ScanDetail>(); - - long timeStamp = clock.getElapsedSinceBootMillis(); - for (int index = 0; index < ssids.length; index++) { - byte[] ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssids[index])); - ScanResult.InformationElement[] ies = - InformationElementUtil.parseInformationElements(iesByteStream[index]); - NetworkDetail nd = new NetworkDetail(bssids[index], ies, new ArrayList<String>(), - freqs[index]); - ScanDetail scanDetail = new ScanDetail(nd, WifiSsid.createFromByteArray(ssid), - bssids[index], caps[index], levels[index], freqs[index], timeStamp, - ies, new ArrayList<String>(), - ScanResults.generateIERawDatafromScanResultIE(ies)); - scanDetailList.add(scanDetail); - } - return scanDetailList; - } - - /** - * Generate an array of {@link android.net.wifi.WifiConfiguration} based on the caller - * supplied network SSID and security information. - * - * @param ssids an array of SSIDs - * @param securities an array of the network's security setting - * @return the constructed array of {@link android.net.wifi.WifiConfiguration} - */ - public static WifiConfiguration[] generateWifiConfigurations(String[] ssids, - int[] securities) { - if (ssids == null || securities == null || ssids.length != securities.length) { - throw new IllegalArgumentException(); - } - - Map<String, Integer> netIdMap = new HashMap<>(); - int netId = 0; - - WifiConfiguration[] configs = new WifiConfiguration[ssids.length]; - for (int index = 0; index < ssids.length; index++) { - String configKey = ssids[index] + Integer.toString(securities[index]); - Integer id; - - id = netIdMap.get(configKey); - if (id == null) { - id = new Integer(netId); - netIdMap.put(configKey, id); - netId++; - } - - configs[index] = generateWifiConfig(id.intValue(), 0, ssids[index], false, true, null, - null, securities[index]); - if (securities[index] == SECURITY_PSK || securities[index] == SECURITY_SAE - || securities[index] == SECURITY_WAPI_PSK) { - configs[index].preSharedKey = "\"PA55W0RD\""; // needed to validate with PSK - } - if (!WifiConfigurationUtil.validate(configs[index], true)) { - throw new IllegalArgumentException("Invalid generated config: " + configs[index]); - } - } - - return configs; - } - - /** - * Add the Configurations to WifiConfigManager (WifiConfigureStore can take them out according - * to the networkd ID) and setup the WifiConfigManager mocks for these networks. - * This simulates the WifiConfigManager class behaviour. - * - * @param wifiConfigManager the mocked WifiConfigManager - * @param configs input configuration need to be added to WifiConfigureStore - */ - private static void prepareConfigStore(final WifiConfigManager wifiConfigManager, - final WifiConfiguration[] configs) { - when(wifiConfigManager.getConfiguredNetwork(anyInt())) - .then(new AnswerWithArguments() { - public WifiConfiguration answer(int netId) { - for (WifiConfiguration config : configs) { - if (netId == config.networkId) { - return new WifiConfiguration(config); - } - } - return null; - } - }); - when(wifiConfigManager.getConfiguredNetwork(anyString())) - .then(new AnswerWithArguments() { - public WifiConfiguration answer(String configKey) { - for (WifiConfiguration config : configs) { - if (TextUtils.equals(config.getKey(), configKey)) { - return new WifiConfiguration(config); - } - } - return null; - } - }); - when(wifiConfigManager.getConfiguredNetworks()) - .then(new AnswerWithArguments() { - public List<WifiConfiguration> answer() { - List<WifiConfiguration> savedNetworks = new ArrayList<>(); - for (int netId = 0; netId < configs.length; netId++) { - savedNetworks.add(new WifiConfiguration(configs[netId])); - } - return savedNetworks; - } - }); - when(wifiConfigManager.clearNetworkCandidateScanResult(anyInt())) - .then(new AnswerWithArguments() { - public boolean answer(int netId) { - if (netId >= 0 && netId < configs.length) { - configs[netId].getNetworkSelectionStatus().setCandidate(null); - configs[netId].getNetworkSelectionStatus() - .setCandidateScore(Integer.MIN_VALUE); - configs[netId].getNetworkSelectionStatus() - .setSeenInLastQualifiedNetworkSelection(false); - return true; - } else { - return false; - } - } - }); - when(wifiConfigManager.setNetworkCandidateScanResult( - anyInt(), any(ScanResult.class), anyInt())) - .then(new AnswerWithArguments() { - public boolean answer(int netId, ScanResult scanResult, int score) { - if (netId >= 0 && netId < configs.length) { - configs[netId].getNetworkSelectionStatus().setCandidate(scanResult); - configs[netId].getNetworkSelectionStatus().setCandidateScore(score); - configs[netId].getNetworkSelectionStatus() - .setSeenInLastQualifiedNetworkSelection(true); - return true; - } else { - return false; - } - } - }); - when(wifiConfigManager.clearNetworkConnectChoice(anyInt())) - .then(new AnswerWithArguments() { - public boolean answer(int netId) { - if (netId >= 0 && netId < configs.length) { - configs[netId].getNetworkSelectionStatus().setConnectChoice(null); - return true; - } else { - return false; - } - } - }); - when(wifiConfigManager.setNetworkConnectChoice(anyInt(), anyString())) - .then(new AnswerWithArguments() { - public boolean answer(int netId, String configKey) { - if (netId >= 0 && netId < configs.length) { - configs[netId].getNetworkSelectionStatus().setConnectChoice(configKey); - return true; - } else { - return false; - } - } - }); - } - - - /** - * Link scan results to the saved configurations. - * - * The shorter of the 2 input params will be used to loop over so the inputs don't - * need to be of equal length. If there are more scan details then configs the remaining scan - * details will be associated with a NULL config. - * - * @param wifiConfigManager the mocked WifiConfigManager - * @param configs saved configurations - * @param scanDetails come in scan results - */ - private static void scanResultLinkConfiguration(WifiConfigManager wifiConfigManager, - WifiConfiguration[] configs, List<ScanDetail> scanDetails) { - if (configs == null || scanDetails == null) { - return; - } - - if (scanDetails.size() <= configs.length) { - for (int i = 0; i < scanDetails.size(); i++) { - ScanDetail scanDetail = scanDetails.get(i); - when(wifiConfigManager.getConfiguredNetworkForScanDetailAndCache(eq(scanDetail))) - .thenReturn(configs[i]); - } - } else { - for (int i = 0; i < configs.length; i++) { - ScanDetail scanDetail = scanDetails.get(i); - when(wifiConfigManager.getConfiguredNetworkForScanDetailAndCache(eq(scanDetail))) - .thenReturn(configs[i]); - } - - // associated the remaining scan details with a NULL config. - for (int i = configs.length; i < scanDetails.size(); i++) { - when(wifiConfigManager.getConfiguredNetworkForScanDetailAndCache( - eq(scanDetails.get(i)))).thenReturn(null); - } - } - } - - - /** - * Configure the score cache for externally scored networks - * - * @param scoreCache Wifi network score cache to be configured - * @param scanDetails a list of ScanDetail - * @param scores scores of the networks - * @param meteredHints hints of if the networks are metered - */ - public static void configureScoreCache(WifiNetworkScoreCache scoreCache, - List<ScanDetail> scanDetails, Integer[] scores, boolean[] meteredHints) { - List<ScoredNetwork> networks = new ArrayList<>(); - - for (int i = 0; i < scanDetails.size(); i++) { - ScanDetail scanDetail = scanDetails.get(i); - ScanResult scanResult = scanDetail.getScanResult(); - WifiKey wifiKey = new WifiKey("\"" + scanResult.SSID + "\"", scanResult.BSSID); - NetworkKey ntwkKey = new NetworkKey(wifiKey); - RssiCurve rssiCurve; - - if (scores != null) { // fixed score - byte rssiScore; - Integer score = scores[i]; - - if (scores[i] == null) { - rssiScore = WifiNetworkScoreCache.INVALID_NETWORK_SCORE; - } else { - rssiScore = scores[i].byteValue(); - } - rssiCurve = new RssiCurve(-100, 100, new byte[] {rssiScore}); - } else { - rssiCurve = new RssiCurve(-80, 20, new byte[] {-10, 0, 10, 20, 30, 40}); - } - ScoredNetwork scoredNetwork = new ScoredNetwork(ntwkKey, rssiCurve, meteredHints[i]); - - networks.add(scoredNetwork); - } - - scoreCache.onScoresUpdated(networks); - } - - /** - * Setup WifiConfigManager mock for ephemeral networks. - * - * @param wifiConfigManager WifiConfigManager mock - * @param networkId ID of the ephemeral network - * @param scanDetail scanDetail of the ephemeral network - * @param meteredHint flag to indidate if the network has meteredHint - */ - public static WifiConfiguration setupEphemeralNetwork(WifiConfigManager wifiConfigManager, - int networkId, ScanDetail scanDetail, boolean meteredHint) { - // Return the correct networkID for ephemeral network addition. - when(wifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) - .thenReturn(new NetworkUpdateResult(networkId)); - final WifiConfiguration config = - ScanResultUtil.createNetworkFromScanResult(scanDetail.getScanResult()); - config.ephemeral = true; - config.trusted = false; - config.networkId = networkId; - config.meteredHint = meteredHint; - - when(wifiConfigManager.getConfiguredNetworkForScanDetailAndCache(eq(scanDetail))) - .thenReturn(new WifiConfiguration(config)); - when(wifiConfigManager.getConfiguredNetwork(eq(networkId))) - .then(new AnswerWithArguments() { - public WifiConfiguration answer(int netId) { - return new WifiConfiguration(config); - } - }); - when(wifiConfigManager.setNetworkCandidateScanResult( - eq(networkId), any(ScanResult.class), anyInt())) - .then(new AnswerWithArguments() { - public boolean answer(int netId, ScanResult scanResult, int score) { - config.getNetworkSelectionStatus().setCandidate(scanResult); - config.getNetworkSelectionStatus().setCandidateScore(score); - config.getNetworkSelectionStatus() - .setSeenInLastQualifiedNetworkSelection(true); - return true; - } - }); - when(wifiConfigManager.updateNetworkSelectionStatus(eq(networkId), - eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE))) - .then(new AnswerWithArguments() { - public boolean answer(int netId, int status) { - config.getNetworkSelectionStatus().setNetworkSelectionStatus( - WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE); - return true; - } - }); - return config; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java deleted file mode 100644 index fd27dcc06..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ /dev/null @@ -1,4184 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; -import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE; -import static android.app.AppOpsManager.MODE_ALLOWED; -import static android.app.AppOpsManager.MODE_IGNORED; -import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; -import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION; -import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION; -import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.*; - -import android.app.ActivityManager; -import android.app.AlertDialog; -import android.app.AppOpsManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.net.NetworkScoreManager; -import android.net.util.MacAddressUtils; -import android.net.wifi.EAPConstants; -import android.net.wifi.ISuggestionConnectionStatusListener; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.os.Handler; -import android.os.IBinder; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.test.TestLooper; -import android.telephony.TelephonyManager; -import android.test.suitebuilder.annotation.SmallTest; -import android.view.LayoutInflater; -import android.view.Window; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; -import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.util.LruConnectionTracker; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Unit tests for {@link com.android.server.wifi.WifiNetworkSuggestionsManager}. - */ -@SmallTest -public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { - - private static final String TEST_PACKAGE_1 = "com.test12345"; - private static final String TEST_PACKAGE_2 = "com.test54321"; - private static final String TEST_APP_NAME_1 = "test12345"; - private static final String TEST_APP_NAME_2 = "test54321"; - private static final String TEST_FEATURE = "testFeature"; - private static final String TEST_BSSID = "00:11:22:33:44:55"; - private static final String TEST_FQDN = "FQDN"; - private static final String TEST_FRIENDLY_NAME = "test_friendly_name"; - private static final String TEST_REALM = "realm.test.com"; - private static final String TEST_CARRIER_NAME = "test_carrier"; - private static final int TEST_UID_1 = 5667; - private static final int TEST_UID_2 = 4537; - private static final int NETWORK_CALLBACK_ID = 1100; - private static final int VALID_CARRIER_ID = 100; - private static final int TEST_SUBID = 1; - private static final int TEST_NETWORK_ID = 110; - private static final int TEST_CARRIER_ID = 1911; - private static final String TEST_IMSI = "123456*"; - - private @Mock WifiContext mContext; - private @Mock Resources mResources; - private @Mock AppOpsManager mAppOpsManager; - private @Mock NotificationManager mNotificationManger; - private @Mock NetworkScoreManager mNetworkScoreManager; - private @Mock PackageManager mPackageManager; - private @Mock WifiPermissionsUtil mWifiPermissionsUtil; - private @Mock WifiInjector mWifiInjector; - private @Mock FrameworkFacade mFrameworkFacade; - private @Mock WifiConfigStore mWifiConfigStore; - private @Mock WifiConfigManager mWifiConfigManager; - private @Mock NetworkSuggestionStoreData mNetworkSuggestionStoreData; - private @Mock WifiMetrics mWifiMetrics; - private @Mock WifiCarrierInfoManager mWifiCarrierInfoManager; - private @Mock PasspointManager mPasspointManager; - private @Mock ISuggestionConnectionStatusListener mListener; - private @Mock IBinder mBinder; - private @Mock ActivityManager mActivityManager; - private @Mock WifiScoreCard mWifiScoreCard; - private @Mock WifiKeyStore mWifiKeyStore; - private @Mock AlertDialog.Builder mAlertDialogBuilder; - private @Mock AlertDialog mAlertDialog; - private @Mock Notification.Builder mNotificationBuilder; - private @Mock Notification mNotification; - private @Mock LruConnectionTracker mLruConnectionTracker; - private @Mock UserManager mUserManager; - private TestLooper mLooper; - private ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor = - ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class); - private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - private ArgumentCaptor<WifiCarrierInfoManager.OnUserApproveCarrierListener> - mUserApproveCarrierListenerArgumentCaptor = ArgumentCaptor.forClass( - WifiCarrierInfoManager.OnUserApproveCarrierListener.class); - - private InOrder mInorder; - - private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - private NetworkSuggestionStoreData.DataSource mDataSource; - - /** - * Setup the mocks. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - - mInorder = inOrder(mContext, mWifiPermissionsUtil); - - when(mWifiInjector.makeNetworkSuggestionStoreData(any())) - .thenReturn(mNetworkSuggestionStoreData); - when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade); - when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager); - when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard); - when(mAlertDialogBuilder.setTitle(any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setMessage(any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setPositiveButton(any(), any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setNegativeButton(any(), any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setOnDismissListener(any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.setOnCancelListener(any())).thenReturn(mAlertDialogBuilder); - when(mAlertDialogBuilder.create()).thenReturn(mAlertDialog); - when(mAlertDialog.getWindow()).thenReturn(mock(Window.class)); - when(mNotificationBuilder.setSmallIcon(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setTicker(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setContentTitle(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setStyle(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setDeleteIntent(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setShowWhen(anyBoolean())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setLocalOnly(anyBoolean())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.setColor(anyInt())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.addAction(any())).thenReturn(mNotificationBuilder); - when(mNotificationBuilder.build()).thenReturn(mNotification); - when(mFrameworkFacade.makeAlertDialogBuilder(any())) - .thenReturn(mAlertDialogBuilder); - when(mFrameworkFacade.makeNotificationBuilder(any(), anyString())) - .thenReturn(mNotificationBuilder); - when(mFrameworkFacade.getBroadcast(any(), anyInt(), any(), anyInt())) - .thenReturn(mock(PendingIntent.class)); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager); - when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) - .thenReturn(mNotificationManger); - when(mContext.getSystemService(NetworkScoreManager.class)).thenReturn(mNetworkScoreManager); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager); - when(mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE)) - .thenReturn(mock(LayoutInflater.class)); - when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources"); - when(mActivityManager.isLowRamDevice()).thenReturn(false); - when(mActivityManager.getPackageImportance(any())).thenReturn( - IMPORTANCE_FOREGROUND_SERVICE); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(true); - - // setup resource strings for notification. - when(mResources.getString(eq(R.string.wifi_suggestion_title), anyString())) - .thenAnswer(s -> "blah" + s.getArguments()[1]); - when(mResources.getString(eq(R.string.wifi_suggestion_content), anyString())) - .thenAnswer(s -> "blah" + s.getArguments()[1]); - when(mResources.getText(eq(R.string.wifi_suggestion_action_allow_app))) - .thenReturn("blah"); - when(mResources.getText(eq(R.string.wifi_suggestion_action_disallow_app))) - .thenReturn("blah"); - - - // Our app Info. Needed for notification builder. - ApplicationInfo ourAppInfo = new ApplicationInfo(); - when(mContext.getApplicationInfo()).thenReturn(ourAppInfo); - // test app info - ApplicationInfo appInfO1 = new ApplicationInfo(); - when(mPackageManager.getApplicationInfoAsUser(eq(TEST_PACKAGE_1), eq(0), any())) - .thenReturn(appInfO1); - when(mPackageManager.getApplicationLabel(appInfO1)).thenReturn(TEST_APP_NAME_1); - ApplicationInfo appInfO2 = new ApplicationInfo(); - when(mPackageManager.getApplicationInfoAsUser(eq(TEST_PACKAGE_2), eq(0), any())) - .thenReturn(appInfO2); - when(mPackageManager.getApplicationLabel(appInfO2)).thenReturn(TEST_APP_NAME_2); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(any())).thenReturn( - TelephonyManager.UNKNOWN_CARRIER_ID); - - when(mWifiKeyStore.updateNetworkKeys(any(), any())).thenReturn(true); - - mWifiNetworkSuggestionsManager = - new WifiNetworkSuggestionsManager(mContext, new Handler(mLooper.getLooper()), - mWifiInjector, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore, - mWifiMetrics, mWifiCarrierInfoManager, mWifiKeyStore, - mLruConnectionTracker); - verify(mContext).getResources(); - verify(mContext).getSystemService(Context.APP_OPS_SERVICE); - verify(mContext).getSystemService(Context.NOTIFICATION_SERVICE); - verify(mContext).getPackageManager(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); - - ArgumentCaptor<NetworkSuggestionStoreData.DataSource> dataSourceArgumentCaptor = - ArgumentCaptor.forClass(NetworkSuggestionStoreData.DataSource.class); - - verify(mWifiInjector).makeNetworkSuggestionStoreData(dataSourceArgumentCaptor.capture()); - mDataSource = dataSourceArgumentCaptor.getValue(); - assertNotNull(mDataSource); - mDataSource.fromDeserialized(Collections.EMPTY_MAP); - - verify(mWifiCarrierInfoManager).addImsiExemptionUserApprovalListener( - mUserApproveCarrierListenerArgumentCaptor.capture()); - - mWifiNetworkSuggestionsManager.enableVerboseLogging(1); - } - - /** - * Verify successful addition of network suggestions. - */ - @Test - public void testAddNetworkSuggestionsSuccess() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - dummyConfiguration, passpointConfiguration, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class), - anyInt(), anyString(), eq(true), eq(true))).thenReturn(true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - verify(mPasspointManager).addOrUpdateProvider( - passpointConfiguration, TEST_UID_2, TEST_PACKAGE_2, true, true); - verify(mWifiMetrics, times(2)) - .incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED); - Set<WifiNetworkSuggestion> allNetworkSuggestions = - mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - Set<WifiNetworkSuggestion> expectedAllNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - }}; - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - - verify(mWifiMetrics, times(2)).incrementNetworkSuggestionApiNumModification(); - ArgumentCaptor<List<Integer>> maxSizesCaptor = ArgumentCaptor.forClass(List.class); - verify(mWifiMetrics, times(2)).noteNetworkSuggestionApiListSizeHistogram( - maxSizesCaptor.capture()); - assertNotNull(maxSizesCaptor.getValue()); - assertEquals(maxSizesCaptor.getValue(), new ArrayList<Integer>() {{ add(1); add(1); }}); - } - - /** - * Verify successful removal of network suggestions. - */ - @Test - public void testRemoveNetworkSuggestionsSuccess() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.setPasspointUniqueId(passpointConfiguration.getUniqueId()); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - dummyConfiguration, passpointConfiguration, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class), - anyInt(), anyString(), eq(true), eq(true))).thenReturn(true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - - // Now remove all of them. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList1, - TEST_UID_1, TEST_PACKAGE_1)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList2, - TEST_UID_2, TEST_PACKAGE_2)); - verify(mPasspointManager).removeProvider(eq(TEST_UID_2), eq(false), - eq(passpointConfiguration.getUniqueId()), isNull()); - verify(mWifiScoreCard).removeNetwork(anyString()); - verify(mLruConnectionTracker).removeNetwork(any()); - - assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); - - verify(mWifiMetrics, times(4)).incrementNetworkSuggestionApiNumModification(); - ArgumentCaptor<List<Integer>> maxSizesCaptor = ArgumentCaptor.forClass(List.class); - verify(mWifiMetrics, times(4)).noteNetworkSuggestionApiListSizeHistogram( - maxSizesCaptor.capture()); - assertNotNull(maxSizesCaptor.getValue()); - assertEquals(maxSizesCaptor.getValue(), new ArrayList<Integer>() {{ add(1); add(1); }}); - } - - /** - * Add or remove suggestion before user data store loaded will fail. - */ - @Test - public void testAddRemoveSuggestionBeforeUserDataLoaded() { - // Clear the data source, and user data store is not loaded - mDataSource.reset(); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = Arrays.asList(networkSuggestion); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1)); - } - - @Test - public void testAddRemoveEnterpriseNetworkSuggestion() { - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createEapNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createEapNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - }}; - when(mWifiKeyStore.updateNetworkKeys(eq(networkSuggestion1.wifiConfiguration), any())) - .thenReturn(true); - when(mWifiKeyStore.updateNetworkKeys(eq(networkSuggestion2.wifiConfiguration), any())) - .thenReturn(false); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - Set<WifiNetworkSuggestion> allNetworkSuggestions = - mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - assertEquals(1, allNetworkSuggestions.size()); - WifiNetworkSuggestion removingSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createEapNetwork(), null, false, false, true, true); - removingSuggestion.wifiConfiguration.SSID = networkSuggestion1.wifiConfiguration.SSID; - // Remove with the networkSuggestion from external. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove( - new ArrayList<WifiNetworkSuggestion>() {{ add(removingSuggestion); }}, - TEST_UID_1, TEST_PACKAGE_1)); - // Make sure remove the keyStore with the internal config - verify(mWifiKeyStore).removeKeys(networkSuggestion1.wifiConfiguration.enterpriseConfig); - verify(mLruConnectionTracker).removeNetwork(any()); - } - - @Test - public void testAddInsecureEnterpriseNetworkSuggestion() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createEapNetwork(), null, false, false, true, true); - networkSuggestion.wifiConfiguration.enterpriseConfig.setCaPath(null); - List<WifiNetworkSuggestion> networkSuggestionList = Arrays.asList(networkSuggestion); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createEapNetwork(), null, false, false, true, true); - networkSuggestion.wifiConfiguration.enterpriseConfig.setDomainSuffixMatch(""); - networkSuggestionList = Arrays.asList(networkSuggestion); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - } - - /** - * Verify successful removal of all network suggestions. - */ - @Test - public void testRemoveAllNetworkSuggestionsSuccess() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - dummyConfiguration, passpointConfiguration, false, false, true, true); - - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class), - anyInt(), anyString(), eq(true), eq(true))).thenReturn(true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - - // Now remove all of them by sending an empty list. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(new ArrayList<>(), TEST_UID_1, - TEST_PACKAGE_1)); - verify(mLruConnectionTracker).removeNetwork(any()); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(new ArrayList<>(), TEST_UID_2, - TEST_PACKAGE_2)); - verify(mPasspointManager).removeProvider(eq(TEST_UID_2), eq(false), - eq(passpointConfiguration.getUniqueId()), isNull()); - - assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); - } - - /** - * Verify successful replace (add,remove, add) of network suggestions. - */ - @Test - public void testReplaceNetworkSuggestionsSuccess() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - Set<WifiNetworkSuggestion> allNetworkSuggestions = - mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - Set<WifiNetworkSuggestion> expectedAllNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - } - - /** - * Verify that modify networks that are already active is allowed. - */ - @Test - public void testAddNetworkSuggestionsSuccessOnInPlaceModificationWhenNotInWcm() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - // Assert that the original config was not metered. - assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE, - networkSuggestion.wifiConfiguration.meteredOverride); - - // Nothing in WCM. - when(mWifiConfigManager.getConfiguredNetwork(networkSuggestion.wifiConfiguration.getKey())) - .thenReturn(null); - - // Modify the original suggestion to mark it metered. - networkSuggestion.wifiConfiguration.meteredOverride = - WifiConfiguration.METERED_OVERRIDE_METERED; - - // Replace attempt should success. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiConfiguration.METERED_OVERRIDE_METERED, - mWifiNetworkSuggestionsManager - .get(TEST_PACKAGE_1, TEST_UID_1).get(0).wifiConfiguration.meteredOverride); - // Verify we did not update config in WCM. - verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), any()); - } - - /** - * Verify that modify networks that are already active and is cached in WifiConfigManager is - * allowed and also updates the cache in WifiConfigManager. - */ - @Test - public void testAddNetworkSuggestionsSuccessOnInPlaceModificationWhenInWcm() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - // Assert that the original config was not metered. - assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE, - networkSuggestion.wifiConfiguration.meteredOverride); - verify(mWifiMetrics).incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED); - reset(mWifiMetrics); - // Store the original WifiConfiguration from WifiConfigManager. - WifiConfiguration configInWcm = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - configInWcm.creatorUid = TEST_UID_1; - configInWcm.creatorName = TEST_PACKAGE_1; - configInWcm.fromWifiNetworkSuggestion = true; - setupGetConfiguredNetworksFromWcm(configInWcm); - - // Modify the original suggestion to mark it metered. - networkSuggestion.wifiConfiguration.meteredOverride = - WifiConfiguration.METERED_OVERRIDE_METERED; - - when(mWifiConfigManager.addOrUpdateNetwork(any(), eq(TEST_UID_1), eq(TEST_PACKAGE_1))) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - // Replace attempt should success. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiConfiguration.METERED_OVERRIDE_METERED, - mWifiNetworkSuggestionsManager - .get(TEST_PACKAGE_1, TEST_UID_1).get(0).wifiConfiguration.meteredOverride); - verify(mWifiMetrics, never()).incrementNetworkSuggestionApiUsageNumOfAppInType(anyInt()); - // Verify we did update config in WCM. - ArgumentCaptor<WifiConfiguration> configCaptor = - ArgumentCaptor.forClass(WifiConfiguration.class); - verify(mWifiConfigManager).addOrUpdateNetwork( - configCaptor.capture(), eq(TEST_UID_1), eq(TEST_PACKAGE_1)); - assertNotNull(configCaptor.getValue()); - assertEquals(WifiConfiguration.METERED_OVERRIDE_METERED, - configCaptor.getValue().meteredOverride); - } - - /** - * Verify that an attempt to add networks beyond the max per app is rejected. - */ - @Test - public void testAddNetworkSuggestionsFailureOnExceedsMaxPerApp() { - // Add the max per app first. - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - for (int i = 0; i < WifiManager.NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM; i++) { - networkSuggestionList.add(new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true)); - } - // The first add should succeed. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - List<WifiNetworkSuggestion> originalNetworkSuggestionsList = networkSuggestionList; - - // Now add 3 more. - networkSuggestionList = new ArrayList<>(); - for (int i = 0; i < 3; i++) { - networkSuggestionList.add(new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true)); - } - // The second add should fail. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - // Now remove 3 of the initially added ones. - networkSuggestionList = new ArrayList<>(); - for (int i = 0; i < 3; i++) { - networkSuggestionList.add(originalNetworkSuggestionsList.get(i)); - } - // The remove should succeed. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1)); - - // Now add 2 more. - networkSuggestionList = new ArrayList<>(); - for (int i = 0; i < 2; i++) { - networkSuggestionList.add(new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true)); - } - // This add should now succeed. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - } - - /** - * Verify that an attempt to remove an invalid set of network suggestions is rejected. - */ - @Test - public void testRemoveNetworkSuggestionsFailureOnInvalid() { - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - // Remove should fail because the network list is different. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList2, TEST_UID_1, - TEST_PACKAGE_1)); - } - - /** - * Verify a successful lookup of a single network suggestion matching the provided scan detail. - */ - @Test - public void - testGetNetworkSuggestionsForScanDetailSuccessWithOneMatchForCarrierProvisioningApp() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - // This app should be pre-approved. No need to explicitly call - // |setHasUserApprovedForApp(true, TEST_PACKAGE_1)| - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - verify(mWifiMetrics).incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING); - ScanDetail scanDetail = createScanDetailForNetwork(networkSuggestion.wifiConfiguration); - - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify add or remove suggestion list with null object will result error code. - */ - @Test - public void testAddRemoveNetworkSuggestionWithNullObject() { - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, - mWifiNetworkSuggestionsManager.add(Collections.singletonList(null), - TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(Collections.singletonList(networkSuggestion), - TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, - mWifiNetworkSuggestionsManager.remove(Collections.singletonList(null), - TEST_UID_1, TEST_PACKAGE_1)); - } - - /** - * Verify a successful lookup of a single network suggestion matching the provided scan detail. - */ - @Test - public void testGetNetworkSuggestionsForScanDetailSuccessWithOneMatch() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - ScanDetail scanDetail = createScanDetailForNetwork(networkSuggestion.wifiConfiguration); - - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify a successful lookup of multiple network suggestions matching the provided scan detail. - */ - @Test - public void testGetNetworkSuggestionsForScanDetailSuccessWithMultipleMatch() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - // Reuse the same network credentials to ensure they both match. - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - - ScanDetail scanDetail = createScanDetailForNetwork(networkSuggestion1.wifiConfiguration); - - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify a successful lookup of a single network suggestion matching the provided scan detail. - */ - @Test - public void testGetNetworkSuggestionsForScanDetailSuccessWithBssidOneMatch() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail = createScanDetailForNetwork(wifiConfiguration); - wifiConfiguration.BSSID = scanDetail.getBSSIDString(); - - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify a successful lookup of multiple network suggestions matching the provided scan detail. - */ - @Test - public void testGetNetworkSuggestionsForScanDetailSuccessWithBssidMultipleMatch() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail = createScanDetailForNetwork(wifiConfiguration); - wifiConfiguration.BSSID = scanDetail.getBSSIDString(); - - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - // Reuse the same network credentials to ensure they both match. - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify a successful lookup of multiple network suggestions matching the provided scan detail. - */ - @Test - public void - testGetNetworkSuggestionsForScanDetailSuccessWithBssidMultipleMatchFromSamePackage() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail = createScanDetailForNetwork(wifiConfiguration); - wifiConfiguration.BSSID = scanDetail.getBSSIDString(); - - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - // Reuse the same network credentials to ensure they both match. - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify a successful lookup of multiple network suggestions matching the provided scan detail. - */ - @Test - public void - testGetNetworkSuggestionsForScanDetailSuccessWithBssidAndWithoutBssidMultipleMatch() { - WifiConfiguration wifiConfiguration1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail = createScanDetailForNetwork(wifiConfiguration1); - WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1); - wifiConfiguration2.BSSID = scanDetail.getBSSIDString(); - - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration1, null, false, false, true, true); - // Reuse the same network credentials to ensure they both match. - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration2, null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - - // Now change the bssid of the scan result to a different value, now only the general - // (without bssid) suggestion. - scanDetail.getScanResult().BSSID = MacAddressUtils.createRandomUnicastAddress().toString(); - matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify failure to lookup any network suggestion matching the provided scan detail when the - * app providing the suggestion has not been approved. - */ - @Test - public void testGetNetworkSuggestionsForScanDetailFailureOnAppNotApproved() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE_1)); - - ScanDetail scanDetail = createScanDetailForNetwork(networkSuggestion.wifiConfiguration); - - assertNull(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail)); - } - - /** - * Verify failure to lookup any network suggestion matching the provided scan detail. - */ - @Test - public void testGetNetworkSuggestionsForScanDetailFailureOnSuggestionRemoval() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - ScanDetail scanDetail = createScanDetailForNetwork(wifiConfiguration); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - - // add the suggestion & ensure lookup works. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - assertNotNull(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - scanDetail)); - - // remove the suggestion & ensure lookup fails. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(Collections.EMPTY_LIST, TEST_UID_1, - TEST_PACKAGE_1)); - assertNull(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail)); - } - - /** - * Verify failure to lookup any network suggestion matching the provided scan detail. - */ - @Test - public void testGetNetworkSuggestionsForScanDetailFailureOnWrongNetwork() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - // Create a scan result corresponding to a different network. - ScanDetail scanDetail = createScanDetailForNetwork( - WifiConfigurationTestUtil.createPskNetwork()); - - assertNull(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail)); - } - - /** - * Verify a successful lookup of a single network suggestion matching the connected network. - * a) The corresponding network suggestion has the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app holds location permission. - * This should trigger a broadcast to the app. - * This should not trigger a connection failure callback to the app. - */ - @Test - public void testOnNetworkConnectionSuccessWithOneMatch() throws Exception { - assertTrue(mWifiNetworkSuggestionsManager - .registerSuggestionConnectionStatusListener(mBinder, mListener, - NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1)); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - // Simulate connecting to the network. - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_PACKAGE_1; - connectNetwork.creatorUid = TEST_UID_1; - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectSuccess(); - - // Verify that the correct broadcast was sent out. - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults(eq(TEST_PACKAGE_1), - eq(TEST_FEATURE), eq(TEST_UID_1), nullable(String.class)); - validatePostConnectionBroadcastSent(TEST_PACKAGE_1, networkSuggestion); - - // Verify no more broadcast were sent out. - mInorder.verifyNoMoreInteractions(); - } - - @Test - public void testOnNetworkConnectionSuccessWithOneMatchFromCarrierPrivilegedApp() { - assertTrue(mWifiNetworkSuggestionsManager - .registerSuggestionConnectionStatusListener(mBinder, mListener, - NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1)); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1)) - .thenReturn(TEST_CARRIER_ID); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createPskNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE_1)); - - // Simulate connecting to the network. - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_PACKAGE_1; - connectNetwork.creatorUid = TEST_UID_1; - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectSuccess(); - - // Verify that the correct broadcast was sent out. - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults(eq(TEST_PACKAGE_1), - eq(TEST_FEATURE), eq(TEST_UID_1), nullable(String.class)); - validatePostConnectionBroadcastSent(TEST_PACKAGE_1, networkSuggestion); - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1)); - verify(mWifiConfigManager).removeSuggestionConfiguredNetwork(anyString()); - mInorder.verify(mWifiPermissionsUtil).doesUidBelongToCurrentUser(eq(TEST_UID_1)); - - // Verify no more broadcast were sent out. - mInorder.verifyNoMoreInteractions(); - } - - /** - * Verify if a user saved network connected and it can match suggestions. Only the - * carrier-privileged suggestor app can receive the broadcast if - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set to true. - */ - @Test - public void testOnSavedOpenNetworkConnectionSuccessWithMultipleMatch() throws Exception { - assertTrue(mWifiNetworkSuggestionsManager - .registerSuggestionConnectionStatusListener(mBinder, mListener, - NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1)); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(true); - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - new WifiConfiguration(config), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - new WifiConfiguration(config), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - - // Simulate connecting to the user saved open network. - WifiConfiguration connectNetwork = new WifiConfiguration(config); - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectSuccess(); - // Verify that the correct broadcast was sent out. - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults(eq(TEST_PACKAGE_1), - eq(TEST_FEATURE), eq(TEST_UID_1), nullable(String.class)); - validatePostConnectionBroadcastSent(TEST_PACKAGE_1, networkSuggestion1); - - // Verify no more broadcast were sent out. - mInorder.verifyNoMoreInteractions(); - } - - @Test - public void testOnNetworkConnectionFailureWithOneMatchButCallbackOnBinderDied() - throws Exception { - ArgumentCaptor<IBinder.DeathRecipient> drCaptor = - ArgumentCaptor.forClass(IBinder.DeathRecipient.class); - assertTrue(mWifiNetworkSuggestionsManager - .registerSuggestionConnectionStatusListener(mBinder, mListener, - NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1)); - verify(mBinder).linkToDeath(drCaptor.capture(), anyInt()); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - // Simulate binder was died. - drCaptor.getValue().binderDied(); - mLooper.dispatchAll(); - verify(mBinder).unlinkToDeath(any(), anyInt()); - // Simulate connecting to the network. - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, - connectNetwork, TEST_BSSID); - - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectFailure(); - // Verify no connection failure event was sent out. - mInorder.verify(mWifiPermissionsUtil, never()).enforceCanAccessScanResults( - eq(TEST_PACKAGE_1), eq(TEST_FEATURE), eq(TEST_UID_1), nullable(String.class)); - verify(mListener, never()).onConnectionStatus(any(), anyInt()); - - // Verify no more broadcast were sent out. - mInorder.verify(mContext, never()).sendBroadcastAsUser( - any(), any()); - } - - /** - * Verify a successful lookup of a single network suggestion matching the current network - * connection failure. - * a) The corresponding network suggestion has the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app holds location permission. - * This should trigger a connection failure callback to the app - */ - @Test - public void testOnNetworkConnectionFailureWithOneMatch() throws Exception { - assertTrue(mWifiNetworkSuggestionsManager - .registerSuggestionConnectionStatusListener(mBinder, mListener, - NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1)); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - // Simulate connecting to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, connectNetwork, TEST_BSSID); - - // Verify right callback were sent out. - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults(eq(TEST_PACKAGE_1), - eq(TEST_FEATURE), eq(TEST_UID_1), nullable(String.class)); - verify(mListener) - .onConnectionStatus(networkSuggestion, - WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING); - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectFailure(); - - // Verify no more broadcast were sent out. - mInorder.verify(mContext, never()).sendBroadcastAsUser( - any(), any()); - } - - /** - * Verify a successful lookup of multiple network suggestion matching the connected network. - * a) The corresponding network suggestion has the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app holds location permission. - * This should trigger a broadcast to all the apps. - */ - @Test - public void testOnNetworkConnectionSuccessWithMultipleMatch() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion1.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_PACKAGE_1; - connectNetwork.creatorUid = TEST_UID_1; - - // Simulate connecting to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectSuccess(); - - ArgumentCaptor<String> packageNameCaptor = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<String> featureIdCaptor = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<Integer> uidCaptor = ArgumentCaptor.forClass(Integer.class); - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults( - packageNameCaptor.capture(), featureIdCaptor.capture(), uidCaptor.capture(), - nullable(String.class)); - assertEquals(TEST_FEATURE, featureIdCaptor.getValue()); - assertEquals(packageNameCaptor.getValue(), TEST_PACKAGE_1); - assertEquals(Integer.valueOf(TEST_UID_1), uidCaptor.getValue()); - validatePostConnectionBroadcastSent(TEST_PACKAGE_1, networkSuggestion1); - - // Verify no more broadcast were sent out. - mInorder.verifyNoMoreInteractions(); - } - - /** - * Verify a successful lookup of multiple network suggestion matching the connected network. - * a) The corresponding network suggestion has the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app holds location permission. - * This should trigger a broadcast to all the apps. - */ - @Test - public void testOnNetworkConnectionSuccessWithBssidMultipleMatch() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - wifiConfiguration.BSSID = TEST_BSSID; - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion1.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_PACKAGE_1; - connectNetwork.creatorUid = TEST_UID_1; - // Simulate connecting to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectSuccess(); - - // Verify that the correct broadcasts were sent out. - ArgumentCaptor<String> packageNameCaptor = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<String> featureIdCaptor = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<Integer> uidCaptor = ArgumentCaptor.forClass(Integer.class); - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults( - packageNameCaptor.capture(), featureIdCaptor.capture(), uidCaptor.capture(), - nullable(String.class)); - assertEquals(TEST_FEATURE, featureIdCaptor.getValue()); - assertEquals(packageNameCaptor.getValue(), TEST_PACKAGE_1); - assertEquals(Integer.valueOf(TEST_UID_1), uidCaptor.getValue()); - validatePostConnectionBroadcastSent(TEST_PACKAGE_1, networkSuggestion1); - - // Verify no more broadcast were sent out. - mInorder.verifyNoMoreInteractions(); - } - - /** - * Verify a successful lookup of multiple network suggestion matching the connected network. - * a) The corresponding network suggestion has the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app holds location permission. - * This should trigger a broadcast to all the apps. - */ - @Test - public void testOnNetworkConnectionSuccessWithBssidAndWithoutBssidMultipleMatch() { - WifiConfiguration wifiConfiguration1 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1); - wifiConfiguration2.BSSID = TEST_BSSID; - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration1, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration2, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion1.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_PACKAGE_1; - connectNetwork.creatorUid = TEST_UID_1; - - // Simulate connecting to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectSuccess(); - - // Verify that the correct broadcasts were sent out. - ArgumentCaptor<String> packageNameCaptor = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<String> featureIdCaptor = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<Integer> uidCaptor = ArgumentCaptor.forClass(Integer.class); - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults( - packageNameCaptor.capture(), featureIdCaptor.capture(), uidCaptor.capture(), - nullable(String.class)); - assertEquals(TEST_FEATURE, featureIdCaptor.getValue()); - assertEquals(packageNameCaptor.getValue(), TEST_PACKAGE_1); - assertEquals(Integer.valueOf(TEST_UID_1), uidCaptor.getValue()); - validatePostConnectionBroadcastSent(TEST_PACKAGE_1, networkSuggestion1); - - // Verify no more broadcast were sent out. - mInorder.verifyNoMoreInteractions(); - } - - /** - * Verify a successful lookup of a single network suggestion matching the connected network. - * a) The corresponding network suggestion has the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app holds location permission. - * c) App has not been approved by the user. - * This should not trigger a broadcast to the app. - */ - @Test - public void testOnNetworkConnectionWhenAppNotApproved() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - verify(mWifiPermissionsUtil, times(2)) - .checkNetworkCarrierProvisioningPermission(TEST_UID_1); - assertFalse(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE_1)); - - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - - // Simulate connecting to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - // Verify no broadcast was sent out. - mInorder.verify(mWifiPermissionsUtil, never()).enforceCanAccessScanResults( - anyString(), nullable(String.class), anyInt(), nullable(String.class)); - mInorder.verify(mContext, never()).sendBroadcastAsUser( - any(), any()); - } - - /** - * Verify a successful lookup of a single network suggestion matching the connected network. - * a) The corresponding network suggestion does not have the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app holds location permission. - * This should not trigger a broadcast to the app. - */ - @Test - public void testOnNetworkConnectionWhenIsAppInteractionRequiredNotSet() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - verify(mWifiPermissionsUtil, times(2)) - .checkNetworkCarrierProvisioningPermission(TEST_UID_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - - // Simulate connecting to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - // Verify no broadcast was sent out. - mInorder.verify(mWifiPermissionsUtil, never()).enforceCanAccessScanResults( - anyString(), nullable(String.class), anyInt(), nullable(String.class)); - mInorder.verify(mContext, never()).sendBroadcastAsUser( - any(), any()); - } - - /** - * Verify a successful lookup of a single network suggestion matching the connected network. - * a) The corresponding network suggestion has the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app does not hold location permission. - * This should not trigger a broadcast to the app. - */ - @Test - public void testOnNetworkConnectionWhenAppDoesNotHoldLocationPermission() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - verify(mWifiPermissionsUtil, times(2)) - .checkNetworkCarrierProvisioningPermission(TEST_UID_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( - eq(TEST_PACKAGE_1), eq(TEST_FEATURE), eq(TEST_UID_1), nullable(String.class)); - - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - - // Simulate connecting to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults(eq(TEST_PACKAGE_1), - eq(TEST_FEATURE), eq(TEST_UID_1), nullable(String.class)); - - // Verify no broadcast was sent out. - mInorder.verifyNoMoreInteractions(); - } - - /** - * Verify triggering of config store write after successful addition of network suggestions. - */ - @Test - public void testAddNetworkSuggestionsConfigStoreWrite() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - // Verify config store interactions. - verify(mWifiConfigManager).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - - Map<String, PerAppInfo> networkSuggestionsMapToWrite = mDataSource.toSerialize(); - assertEquals(1, networkSuggestionsMapToWrite.size()); - assertTrue(networkSuggestionsMapToWrite.keySet().contains(TEST_PACKAGE_1)); - assertFalse(networkSuggestionsMapToWrite.get(TEST_PACKAGE_1).hasUserApproved); - Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestionsToWrite = - networkSuggestionsMapToWrite.get(TEST_PACKAGE_1).extNetworkSuggestions; - Set<WifiNetworkSuggestion> expectedAllNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(expectedAllNetworkSuggestions, - extNetworkSuggestionsToWrite - .stream() - .collect(Collectors.mapping( - n -> n.wns, - Collectors.toSet()))); - - // Ensure that the new data flag has been reset after read. - assertFalse(mDataSource.hasNewDataToSerialize()); - } - - /** - * Verify triggering of config store write after successful removal of network suggestions. - */ - @Test - public void testRemoveNetworkSuggestionsConfigStoreWrite() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1)); - - // Verify config store interactions. - verify(mWifiConfigManager, times(2)).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - - // Expect a single app entry with no active suggestions. - Map<String, PerAppInfo> networkSuggestionsMapToWrite = mDataSource.toSerialize(); - assertEquals(1, networkSuggestionsMapToWrite.size()); - assertTrue(networkSuggestionsMapToWrite.keySet().contains(TEST_PACKAGE_1)); - assertFalse(networkSuggestionsMapToWrite.get(TEST_PACKAGE_1).hasUserApproved); - assertTrue( - networkSuggestionsMapToWrite.get(TEST_PACKAGE_1).extNetworkSuggestions.isEmpty()); - - // Ensure that the new data flag has been reset after read. - assertFalse(mDataSource.hasNewDataToSerialize()); - } - - /** - * Verify handling of initial config store read. - */ - @Test - public void testNetworkSuggestionsConfigStoreLoad() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - PerAppInfo appInfo = new PerAppInfo(TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - appInfo.hasUserApproved = true; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - dummyConfiguration, passpointConfiguration, false, false, true, true); - appInfo.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion, appInfo, true)); - appInfo.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion1, appInfo, true)); - mDataSource.fromDeserialized(new HashMap<String, PerAppInfo>() {{ - put(TEST_PACKAGE_1, appInfo); - }}); - - Set<WifiNetworkSuggestion> allNetworkSuggestions = - mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - Set<WifiNetworkSuggestion> expectedAllNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - add(networkSuggestion1); - }}; - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - - // Ensure we can lookup the network. - ScanDetail scanDetail = createScanDetailForNetwork(networkSuggestion.wifiConfiguration); - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - - // Ensure we can lookup the passpoint network. - WifiConfiguration connectNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - connectNetwork.FQDN = TEST_FQDN; - connectNetwork.providerFriendlyName = TEST_FRIENDLY_NAME; - connectNetwork.setPasspointUniqueId(passpointConfiguration.getUniqueId()); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_PACKAGE_1; - connectNetwork.creatorUid = TEST_UID_1; - - matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager - .getNetworkSuggestionsForWifiConfiguration(connectNetwork, null); - Set<ExtendedWifiNetworkSuggestion> expectedMatchingExtNetworkSuggestions = - new HashSet<ExtendedWifiNetworkSuggestion>() {{ - add(ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion1, appInfo, true)); - }}; - assertEquals(expectedMatchingExtNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify handling of config store read after user switch. - */ - @Test - public void testNetworkSuggestionsConfigStoreLoadAfterUserSwitch() { - // Read the store initially. - PerAppInfo appInfo1 = new PerAppInfo(TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - appInfo1.hasUserApproved = true; - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - appInfo1.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion1, appInfo1, true)); - mDataSource.fromDeserialized(new HashMap<String, PerAppInfo>() {{ - put(TEST_PACKAGE_1, appInfo1); - }}); - - - // Now simulate user switch. - mDataSource.reset(); - PerAppInfo appInfo2 = new PerAppInfo(TEST_UID_2, TEST_PACKAGE_2, TEST_FEATURE); - appInfo2.hasUserApproved = true; - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - appInfo2.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion2, appInfo2, true)); - mDataSource.fromDeserialized(new HashMap<String, PerAppInfo>() {{ - put(TEST_PACKAGE_2, appInfo2); - }}); - - Set<WifiNetworkSuggestion> allNetworkSuggestions = - mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - Set<WifiNetworkSuggestion> expectedAllNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - - // Ensure we can lookup the new network. - ScanDetail scanDetail2 = createScanDetailForNetwork(networkSuggestion2.wifiConfiguration); - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail2); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - - // Ensure that the previous network can no longer be looked up. - ScanDetail scanDetail1 = createScanDetailForNetwork(networkSuggestion1.wifiConfiguration); - assertNull(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail1)); - } - - /** - * Verify that we will disconnect from the network if the only network suggestion matching the - * connected network is removed. - */ - @Test - public void - testRemoveNetworkSuggestionsMatchingConnectionSuccessWithOneMatch() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - // Simulate connecting to the network. - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - // Now remove the network suggestion and ensure we did trigger a disconnect. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1)); - verify(mWifiConfigManager).removeSuggestionConfiguredNetwork( - networkSuggestion.wifiConfiguration.getKey()); - } - - /** - * Verify that we will disconnect from network when App removed all its suggestions by remove - * empty list. - */ - @Test - public void - testRemoveAllNetworkSuggestionsMatchingConnectionSuccessWithOneMatch() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - // Simulate connecting to the network. - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - // Now remove all network suggestion and ensure we did trigger a disconnect. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(new ArrayList<>(), TEST_UID_1, - TEST_PACKAGE_1)); - verify(mWifiConfigManager).removeSuggestionConfiguredNetwork( - networkSuggestion.wifiConfiguration.getKey()); - } - - - /** - * Verify that we do not disconnect from the network if removed suggestions is not currently - * connected. Verify that we do disconnect from the network is removed suggestions is currently - * connected. - */ - @Test - public void testRemoveAppMatchingConnectionSuccessWithMultipleMatch() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - - // Simulate connecting to the network. - WifiConfiguration connectNetwork = - new WifiConfiguration(wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - // Now remove the current connected app and ensure we did trigger a disconnect. - mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1); - verify(mWifiConfigManager).removeSuggestionConfiguredNetwork( - networkSuggestion1.wifiConfiguration.getKey()); - - // Now remove the other app and ensure we did not trigger a disconnect. - mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_2); - verify(mWifiConfigManager).removeSuggestionConfiguredNetwork(anyString()); - } - - /** - * Verify that we do not disconnect from the network if there are no network suggestion matching - * the connected network when one of the app is removed. - */ - @Test - public void testRemoveAppNotMatchingConnectionSuccess() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - // Simulate connecting to some other network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiConfigurationTestUtil.createEapNetwork(), TEST_BSSID); - - // Now remove the app and ensure we did not trigger a disconnect. - mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1); - verify(mWifiConfigManager, never()).removeSuggestionConfiguredNetwork(anyString()); - } - - /** - * Verify that we do not disconnect from the network if there are no network suggestion matching - * the connected network when one of them is removed. - */ - @Test - public void testRemoveNetworkSuggestionsNotMatchingConnectionSuccessAfterConnectionFailure() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - WifiConfiguration connectNetwork = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - // Simulate failing connection to the network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_DHCP, connectNetwork, TEST_BSSID); - - // Simulate connecting to some other network. - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, - WifiConfigurationTestUtil.createEapNetwork(), TEST_BSSID); - - // Now remove the app and ensure we did not trigger a disconnect. - mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1); - verify(mWifiConfigManager, never()).removeSuggestionConfiguredNetwork(anyString()); - } - - /** - * Verify that we start tracking app-ops on first network suggestion add & stop tracking on the - * last network suggestion remove. - */ - @Test - public void testAddRemoveNetworkSuggestionsStartStopAppOpsWatch() { - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - mInorder = inOrder(mAppOpsManager); - - // Watch app-ops changes on first add. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mInorder.verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), - eq(TEST_PACKAGE_1), mAppOpChangedListenerCaptor.capture()); - - // Nothing happens on second add. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - // Now remove first add, nothing happens. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1)); - // Stop watching app-ops changes on last remove. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList2, TEST_UID_1, - TEST_PACKAGE_1)); - assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); - mInorder.verify(mAppOpsManager).stopWatchingMode(mAppOpChangedListenerCaptor.getValue()); - - mInorder.verifyNoMoreInteractions(); - } - - /** - * Verify app-ops disable/enable after suggestions add. - */ - @Test - public void testAppOpsChangeAfterSuggestionsAdd() { - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - Set<WifiNetworkSuggestion> allNetworkSuggestions = - mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - Set<WifiNetworkSuggestion> expectedAllNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - - verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE_1), - mAppOpChangedListenerCaptor.capture()); - AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); - assertNotNull(listener); - - // allow change wifi state. - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, - TEST_PACKAGE_1)) - .thenReturn(MODE_ALLOWED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); - mLooper.dispatchAll(); - allNetworkSuggestions = mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - - // disallow change wifi state & ensure we remove the app from database. - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, - TEST_PACKAGE_1)) - .thenReturn(MODE_IGNORED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); - mLooper.dispatchAll(); - verify(mAppOpsManager).stopWatchingMode(mAppOpChangedListenerCaptor.getValue()); - assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); - verify(mWifiMetrics).incrementNetworkSuggestionUserRevokePermission(); - } - - /** - * Verify app-ops disable/enable after config store load. - */ - @Test - public void testAppOpsChangeAfterConfigStoreLoad() { - PerAppInfo appInfo = new PerAppInfo(TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - appInfo.extNetworkSuggestions.add( - ExtendedWifiNetworkSuggestion.fromWns(networkSuggestion, appInfo, true)); - mDataSource.fromDeserialized(new HashMap<String, PerAppInfo>() {{ - put(TEST_PACKAGE_1, appInfo); - }}); - - Set<WifiNetworkSuggestion> allNetworkSuggestions = - mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - Set<WifiNetworkSuggestion> expectedAllNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - - verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE_1), - mAppOpChangedListenerCaptor.capture()); - AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); - assertNotNull(listener); - - // allow change wifi state. - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, - TEST_PACKAGE_1)) - .thenReturn(MODE_ALLOWED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); - mLooper.dispatchAll(); - allNetworkSuggestions = mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - - // disallow change wifi state & ensure we remove all the suggestions for that app. - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, - TEST_PACKAGE_1)) - .thenReturn(MODE_IGNORED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); - mLooper.dispatchAll(); - assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); - } - - /** - * Verify app-ops disable with wrong uid to package mapping. - */ - @Test - public void testAppOpsChangeWrongUid() { - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - Set<WifiNetworkSuggestion> allNetworkSuggestions = - mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - Set<WifiNetworkSuggestion> expectedAllNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - - verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE_1), - mAppOpChangedListenerCaptor.capture()); - AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); - assertNotNull(listener); - - // disallow change wifi state & ensure we don't remove all the suggestions for that app. - doThrow(new SecurityException()).when(mAppOpsManager).checkPackage( - eq(TEST_UID_1), eq(TEST_PACKAGE_1)); - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, - TEST_PACKAGE_1)) - .thenReturn(MODE_IGNORED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); - mLooper.dispatchAll(); - allNetworkSuggestions = mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); - assertEquals(expectedAllNetworkSuggestions, allNetworkSuggestions); - } - - /** - * Verify that we stop tracking the package on its removal. - */ - @Test - public void testRemoveApp() { - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - - // Remove all suggestions from TEST_PACKAGE_1 & TEST_PACKAGE_2, we should continue to track. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2)); - - assertTrue(mDataSource.hasNewDataToSerialize()); - Map<String, PerAppInfo> networkSuggestionsMapToWrite = mDataSource.toSerialize(); - assertEquals(2, networkSuggestionsMapToWrite.size()); - assertTrue(networkSuggestionsMapToWrite.keySet().contains(TEST_PACKAGE_1)); - assertTrue(networkSuggestionsMapToWrite.keySet().contains(TEST_PACKAGE_2)); - assertTrue( - networkSuggestionsMapToWrite.get(TEST_PACKAGE_1).extNetworkSuggestions.isEmpty()); - assertTrue( - networkSuggestionsMapToWrite.get(TEST_PACKAGE_2).extNetworkSuggestions.isEmpty()); - - // Now remove TEST_PACKAGE_1, continue to track TEST_PACKAGE_2. - mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1); - assertTrue(mDataSource.hasNewDataToSerialize()); - networkSuggestionsMapToWrite = mDataSource.toSerialize(); - assertEquals(1, networkSuggestionsMapToWrite.size()); - assertTrue(networkSuggestionsMapToWrite.keySet().contains(TEST_PACKAGE_2)); - assertTrue( - networkSuggestionsMapToWrite.get(TEST_PACKAGE_2).extNetworkSuggestions.isEmpty()); - - // Now remove TEST_PACKAGE_2. - mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_2); - assertTrue(mDataSource.hasNewDataToSerialize()); - networkSuggestionsMapToWrite = mDataSource.toSerialize(); - assertTrue(networkSuggestionsMapToWrite.isEmpty()); - - // Verify that we stopped watching these apps for app-ops changes. - verify(mAppOpsManager, times(2)).stopWatchingMode(any()); - } - - - /** - * Verify that we stop tracking all packages & it's suggestions on network settings reset. - */ - @Test - public void testClear() { - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - - // Remove all suggestions from TEST_PACKAGE_1 & TEST_PACKAGE_2, we should continue to track. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2)); - - assertTrue(mDataSource.hasNewDataToSerialize()); - Map<String, PerAppInfo> networkSuggestionsMapToWrite = mDataSource.toSerialize(); - assertEquals(2, networkSuggestionsMapToWrite.size()); - assertTrue(networkSuggestionsMapToWrite.keySet().contains(TEST_PACKAGE_1)); - assertTrue(networkSuggestionsMapToWrite.keySet().contains(TEST_PACKAGE_2)); - assertTrue( - networkSuggestionsMapToWrite.get(TEST_PACKAGE_1).extNetworkSuggestions.isEmpty()); - assertTrue( - networkSuggestionsMapToWrite.get(TEST_PACKAGE_2).extNetworkSuggestions.isEmpty()); - - // Now clear everything. - mWifiNetworkSuggestionsManager.clear(); - assertTrue(mDataSource.hasNewDataToSerialize()); - networkSuggestionsMapToWrite = mDataSource.toSerialize(); - assertTrue(networkSuggestionsMapToWrite.isEmpty()); - - // Verify that we stopped watching these apps for app-ops changes. - verify(mAppOpsManager, times(2)).stopWatchingMode(any()); - } - - /** - * Verify user dismissal notification when first time add suggestions and dismissal the user - * approval notification when framework gets scan results. - */ - @Test - public void testUserApprovalNotificationDismissalWhenGetScanResult() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - validateUserApprovalNotification(TEST_APP_NAME_1); - // Simulate user dismissal notification. - sendBroadcastForUserActionOnApp( - NOTIFICATION_USER_DISMISSED_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); - reset(mNotificationManger); - verify(mWifiMetrics).addUserApprovalSuggestionAppUiReaction( - WifiNetworkSuggestionsManager.ACTION_USER_DISMISS, false); - // Simulate finding the network in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - - validateUserApprovalNotification(TEST_APP_NAME_1); - - // Simulate user dismissal notification. - sendBroadcastForUserActionOnApp( - NOTIFICATION_USER_DISMISSED_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); - - reset(mNotificationManger); - // We should resend the notification next time the network is found in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - - validateUserApprovalNotification(TEST_APP_NAME_1); - verifyNoMoreInteractions(mNotificationManger); - } - - /** - * Verify user dismissal notification when first time add suggestions and click on allow on - * the user approval notification when framework gets scan results. - */ - @Test - public void testUserApprovalNotificationClickOnAllowWhenGetScanResult() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - validateUserApprovalNotification(TEST_APP_NAME_1); - - // Simulate user dismissal notification. - sendBroadcastForUserActionOnApp( - NOTIFICATION_USER_DISMISSED_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); - reset(mNotificationManger); - - // Simulate finding the network in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - - validateUserApprovalNotification(TEST_APP_NAME_1); - - // Simulate user clicking on allow in the notification. - sendBroadcastForUserActionOnApp( - NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); - // Cancel the notification. - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - - // Verify config store interactions. - verify(mWifiConfigManager, times(2)).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - verify(mWifiMetrics).addUserApprovalSuggestionAppUiReaction( - WifiNetworkSuggestionsManager.ACTION_USER_ALLOWED_APP, false); - - reset(mNotificationManger); - // We should not resend the notification next time the network is found in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - verifyNoMoreInteractions(mNotificationManger); - } - - /** - * Verify user dismissal notification when first time add suggestions and click on disallow on - * the user approval notification when framework gets scan results. - */ - @Test - public void testUserApprovalNotificationClickOnDisallowWhenGetScanResult() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), - eq(TEST_PACKAGE_1), mAppOpChangedListenerCaptor.capture()); - validateUserApprovalNotification(TEST_APP_NAME_1); - - // Simulate user dismissal notification. - sendBroadcastForUserActionOnApp( - NOTIFICATION_USER_DISMISSED_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); - reset(mNotificationManger); - - // Simulate finding the network in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - - validateUserApprovalNotification(TEST_APP_NAME_1); - - // Simulate user clicking on disallow in the notification. - sendBroadcastForUserActionOnApp( - NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); - // Ensure we turn off CHANGE_WIFI_STATE app-ops. - verify(mAppOpsManager).setMode( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1, MODE_IGNORED); - // Cancel the notification. - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - - // Verify config store interactions. - verify(mWifiConfigManager, times(2)).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - verify(mWifiMetrics).addUserApprovalSuggestionAppUiReaction( - WifiNetworkSuggestionsManager.ACTION_USER_DISALLOWED_APP, false); - - reset(mNotificationManger); - - // Now trigger the app-ops callback to ensure we remove all of their suggestions. - AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); - assertNotNull(listener); - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, - TEST_PACKAGE_1)) - .thenReturn(MODE_IGNORED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); - mLooper.dispatchAll(); - assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); - - // Assuming the user re-enabled the app again & added the same suggestions back. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - // We should resend the notification when the network is again found in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - - validateUserApprovalNotification(TEST_APP_NAME_1); - verifyNoMoreInteractions(mNotificationManger); - } - - /** - * Verify that we don't send a new notification when a pending notification is active. - */ - @Test - public void testUserApprovalNotificationWhilePreviousNotificationActive() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - // Simulate finding the network in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - - validateUserApprovalNotification(TEST_APP_NAME_1); - - reset(mNotificationManger); - // We should not resend the notification next time the network is found in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - - verifyNoMoreInteractions(mNotificationManger); - } - - /** - * Verify get network suggestion return the right result - * 1. App never suggested, should return empty list. - * 2. App has network suggestions, return all its suggestion. - * 3. App suggested and remove them all, should return empty list. - */ - @Test - public void testGetNetworkSuggestions() { - // test App never suggested. - List<WifiNetworkSuggestion> storedNetworkSuggestionListPerApp = - mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1); - assertEquals(storedNetworkSuggestionListPerApp.size(), 0); - - // App add network suggestions then get stored suggestions. - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOweNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion3 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createSaeNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion4 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createPskNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion1); - networkSuggestionList.add(networkSuggestion2); - networkSuggestionList.add(networkSuggestion3); - networkSuggestionList.add(networkSuggestion4); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - storedNetworkSuggestionListPerApp = - mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1); - assertEquals(new HashSet<>(networkSuggestionList), - new HashSet<>(storedNetworkSuggestionListPerApp)); - - // App remove all network suggestions, expect empty list. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(new ArrayList<>(), TEST_UID_1, - TEST_PACKAGE_1)); - storedNetworkSuggestionListPerApp = - mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1); - assertEquals(storedNetworkSuggestionListPerApp.size(), 0); - } - - /** - * Verify get hidden networks from All user approve network suggestions - */ - @Test - public void testGetHiddenNetworks() { - - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - WifiNetworkSuggestion hiddenNetworkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createPskHiddenNetwork(), null, true, false, true, true); - WifiNetworkSuggestion hiddenNetworkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createPskHiddenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - add(hiddenNetworkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(hiddenNetworkSuggestion2); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(false, TEST_PACKAGE_2); - List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks = - mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList(); - assertEquals(1, hiddenNetworks.size()); - assertEquals(hiddenNetworkSuggestion1.wifiConfiguration.SSID, hiddenNetworks.get(0).ssid); - } - - /** - * Verify handling of user clicking allow on the user approval dialog when first time - * add suggestions. - */ - @Test - public void testUserApprovalDialogClickOnAllowDuringAddingSuggestionsFromFgApp() { - // Fg app - when(mActivityManager.getPackageImportance(any())).thenReturn(IMPORTANCE_FOREGROUND); - - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - validateUserApprovalDialog(TEST_APP_NAME_1); - - // Simulate user clicking on allow in the dialog. - ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor = - ArgumentCaptor.forClass(DialogInterface.OnClickListener.class); - verify(mAlertDialogBuilder, atLeastOnce()).setPositiveButton( - any(), clickListenerCaptor.capture()); - assertNotNull(clickListenerCaptor.getValue()); - clickListenerCaptor.getValue().onClick(mAlertDialog, 0); - mLooper.dispatchAll(); - - // Verify config store interactions. - verify(mWifiConfigManager, times(2)).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - verify(mWifiMetrics).addUserApprovalSuggestionAppUiReaction( - WifiNetworkSuggestionsManager.ACTION_USER_ALLOWED_APP, true); - - // We should not resend the notification next time the network is found in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - verifyNoMoreInteractions(mNotificationManger); - } - - /** - * Verify handling of user clicking Disallow on the user approval dialog when first time - * add suggestions. - */ - @Test - public void testUserApprovalDialogClickOnDisallowWhenAddSuggestionsFromFgApp() { - // Fg app - when(mActivityManager.getPackageImportance(any())).thenReturn(IMPORTANCE_FOREGROUND); - - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), - eq(TEST_PACKAGE_1), mAppOpChangedListenerCaptor.capture()); - validateUserApprovalDialog(TEST_APP_NAME_1); - - // Simulate user clicking on disallow in the dialog. - ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor = - ArgumentCaptor.forClass(DialogInterface.OnClickListener.class); - verify(mAlertDialogBuilder, atLeastOnce()).setNegativeButton( - any(), clickListenerCaptor.capture()); - assertNotNull(clickListenerCaptor.getValue()); - clickListenerCaptor.getValue().onClick(mAlertDialog, 0); - mLooper.dispatchAll(); - // Ensure we turn off CHANGE_WIFI_STATE app-ops. - verify(mAppOpsManager).setMode( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1, MODE_IGNORED); - - // Verify config store interactions. - verify(mWifiConfigManager, times(2)).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - verify(mWifiMetrics).addUserApprovalSuggestionAppUiReaction( - WifiNetworkSuggestionsManager.ACTION_USER_DISALLOWED_APP, true); - - // Now trigger the app-ops callback to ensure we remove all of their suggestions. - AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); - assertNotNull(listener); - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, - TEST_PACKAGE_1)) - .thenReturn(MODE_IGNORED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); - mLooper.dispatchAll(); - assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); - - // Assuming the user re-enabled the app again & added the same suggestions back. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - validateUserApprovalDialog(TEST_APP_NAME_1); - verifyNoMoreInteractions(mNotificationManger); - } - - /** - * Verify handling of dismissal of the user approval dialog when first time - * add suggestions. - */ - @Test - public void testUserApprovalDialiogDismissDuringAddingSuggestionsFromFgApp() { - // Fg app - when(mActivityManager.getPackageImportance(any())).thenReturn(IMPORTANCE_FOREGROUND); - - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - validateUserApprovalDialog(TEST_APP_NAME_1); - - // Simulate user clicking on allow in the dialog. - ArgumentCaptor<DialogInterface.OnDismissListener> dismissListenerCaptor = - ArgumentCaptor.forClass(DialogInterface.OnDismissListener.class); - verify(mAlertDialogBuilder, atLeastOnce()).setOnDismissListener( - dismissListenerCaptor.capture()); - assertNotNull(dismissListenerCaptor.getValue()); - dismissListenerCaptor.getValue().onDismiss(mAlertDialog); - mLooper.dispatchAll(); - - // Verify no new config store or app-op interactions. - verify(mWifiConfigManager).saveToStore(true); // 1 already done for add - verify(mAppOpsManager, never()).setMode(any(), anyInt(), any(), anyInt()); - verify(mWifiMetrics).addUserApprovalSuggestionAppUiReaction( - WifiNetworkSuggestionsManager.ACTION_USER_DISMISS, true); - - // We should resend the notification next time the network is found in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - validateUserApprovalNotification(TEST_APP_NAME_1); - } - - @Test - public void testAddNetworkSuggestions_activeFgScorer_doesNotRequestForApproval() { - // Fg app - when(mActivityManager.getPackageImportance(any())).thenReturn(IMPORTANCE_FOREGROUND); - // Active scorer - when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_PACKAGE_1); - - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - verifyZeroInteractions(mAlertDialog); - verifyZeroInteractions(mNotificationManger); - } - - @Test - public void testAddNetworkSuggestions_activeBgScorer_doesNotRequestForApproval() { - // Bg app - when(mActivityManager.getPackageImportance(any())).thenReturn(IMPORTANCE_SERVICE); - // Active scorer - when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_PACKAGE_1); - - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - verifyZeroInteractions(mAlertDialog); - verifyZeroInteractions(mNotificationManger); - } - - /** - * Verify handling of user clicking allow on the user approval notification when first time - * add suggestions. - */ - @Test - public void testUserApprovalNotificationClickOnAllowDuringAddingSuggestionsFromNonFgApp() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - validateUserApprovalNotification(TEST_APP_NAME_1); - - // Simulate user clicking on allow in the notification. - sendBroadcastForUserActionOnApp( - NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); - // Cancel the notification. - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - - // Verify config store interactions. - verify(mWifiConfigManager, times(2)).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - - reset(mNotificationManger); - // We should not resend the notification next time the network is found in scan results. - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - verifyNoMoreInteractions(mNotificationManger); - } - - @Test - public void getNetworkSuggestionsForScanDetail_exemptsActiveScorerFromUserApproval() { - when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_PACKAGE_1); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); - - verifyZeroInteractions(mNotificationManger); - verifyZeroInteractions(mAlertDialog); - } - - /** - * Verify handling of user clicking Disallow on the user approval notification when first time - * add suggestions. - */ - @Test - public void testUserApprovalNotificationClickOnDisallowWhenAddSuggestionsFromNonFgApp() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), - eq(TEST_PACKAGE_1), mAppOpChangedListenerCaptor.capture()); - validateUserApprovalNotification(TEST_APP_NAME_1); - - // Simulate user clicking on disallow in the notification. - sendBroadcastForUserActionOnApp( - NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); - // Ensure we turn off CHANGE_WIFI_STATE app-ops. - verify(mAppOpsManager).setMode( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1, MODE_IGNORED); - // Cancel the notification. - verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); - - // Verify config store interactions. - verify(mWifiConfigManager, times(2)).saveToStore(true); - assertTrue(mDataSource.hasNewDataToSerialize()); - - reset(mNotificationManger); - - // Now trigger the app-ops callback to ensure we remove all of their suggestions. - AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); - assertNotNull(listener); - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, - TEST_PACKAGE_1)) - .thenReturn(MODE_IGNORED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); - mLooper.dispatchAll(); - assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); - - // Assuming the user re-enabled the app again & added the same suggestions back. - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - validateUserApprovalNotification(TEST_APP_NAME_1); - verifyNoMoreInteractions(mNotificationManger); - } - - /** - * Verify a successful lookup of a single passpoint network suggestion matching the - * connected network. - * a) The corresponding network suggestion has the - * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. - * b) The app holds location permission. - * This should trigger a broadcast to the app. - */ - @Test - public void testOnPasspointNetworkConnectionSuccessWithOneMatch() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - dummyConfiguration, passpointConfiguration, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - when(mPasspointManager.addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), - anyBoolean())).thenReturn(true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - - // Simulate connecting to the network. - WifiConfiguration connectNetwork = WifiConfigurationTestUtil.createPasspointNetwork(); - connectNetwork.FQDN = TEST_FQDN; - connectNetwork.providerFriendlyName = TEST_FRIENDLY_NAME; - connectNetwork.fromWifiNetworkSuggestion = true; - connectNetwork.ephemeral = true; - connectNetwork.creatorName = TEST_APP_NAME_1; - connectNetwork.creatorUid = TEST_UID_1; - connectNetwork.setPasspointUniqueId(passpointConfiguration.getUniqueId()); - - verify(mWifiMetrics, never()).incrementNetworkSuggestionApiNumConnectSuccess(); - mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( - WifiMetrics.ConnectionEvent.FAILURE_NONE, connectNetwork, TEST_BSSID); - - verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectSuccess(); - - // Verify that the correct broadcast was sent out. - mInorder.verify(mWifiPermissionsUtil).enforceCanAccessScanResults(eq(TEST_PACKAGE_1), - eq(TEST_FEATURE), eq(TEST_UID_1), nullable(String.class)); - validatePostConnectionBroadcastSent(TEST_PACKAGE_1, networkSuggestion); - - // Verify no more broadcast were sent out. - mInorder.verifyNoMoreInteractions(); - } - - /** - * Creates a scan detail corresponding to the provided network values. - */ - private ScanDetail createScanDetailForNetwork(WifiConfiguration configuration) { - return WifiConfigurationTestUtil.createScanDetailForNetwork(configuration, - MacAddressUtils.createRandomUnicastAddress().toString(), -45, 0, 0, 0); - } - - private void validatePostConnectionBroadcastSent( - String expectedPackageName, WifiNetworkSuggestion expectedNetworkSuggestion) { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - ArgumentCaptor<UserHandle> userHandleCaptor = ArgumentCaptor.forClass(UserHandle.class); - mInorder.verify(mContext, calls(1)).sendBroadcastAsUser( - intentCaptor.capture(), userHandleCaptor.capture()); - - assertEquals(userHandleCaptor.getValue(), UserHandle.SYSTEM); - - Intent intent = intentCaptor.getValue(); - assertEquals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION, - intent.getAction()); - String packageName = intent.getPackage(); - WifiNetworkSuggestion networkSuggestion = - intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_SUGGESTION); - assertEquals(expectedPackageName, packageName); - assertEquals(expectedNetworkSuggestion, networkSuggestion); - } - - private void validateUserApprovalDialog(String... anyOfExpectedAppNames) { - verify(mAlertDialog, atLeastOnce()).show(); - ArgumentCaptor<CharSequence> contentCaptor = - ArgumentCaptor.forClass(CharSequence.class); - verify(mAlertDialogBuilder, atLeastOnce()).setMessage(contentCaptor.capture()); - CharSequence content = contentCaptor.getValue(); - assertNotNull(content); - - boolean foundMatch = false; - for (int i = 0; i < anyOfExpectedAppNames.length; i++) { - foundMatch = content.toString().contains(anyOfExpectedAppNames[i]); - if (foundMatch) break; - } - assertTrue(foundMatch); - } - - private void validateUserApprovalNotification(String... anyOfExpectedAppNames) { - verify(mNotificationManger, atLeastOnce()).notify( - eq(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE), - eq(mNotification)); - ArgumentCaptor<Notification.BigTextStyle> contentCaptor = - ArgumentCaptor.forClass(Notification.BigTextStyle.class); - verify(mNotificationBuilder, atLeastOnce()).setStyle(contentCaptor.capture()); - Notification.BigTextStyle content = contentCaptor.getValue(); - assertNotNull(content); - - boolean foundMatch = false; - for (int i = 0; i < anyOfExpectedAppNames.length; i++) { - foundMatch = content.getBigText().toString().contains(anyOfExpectedAppNames[i]); - if (foundMatch) break; - } - assertTrue(foundMatch); - } - - private void sendBroadcastForUserActionOnApp(String action, String packageName, int uid) { - Intent intent = new Intent() - .setAction(action) - .putExtra(WifiNetworkSuggestionsManager.EXTRA_PACKAGE_NAME, packageName) - .putExtra(WifiNetworkSuggestionsManager.EXTRA_UID, uid); - assertNotNull(mBroadcastReceiverCaptor.getValue()); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - } - - @Test - public void testAddSuggestionWithValidCarrierIdWithCarrierProvisionPermission() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - config.carrierId = VALID_CARRIER_ID; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - config, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(true); - - int status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - - assertEquals(status, WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - verify(mWifiMetrics).incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING); - } - - @Test - public void testAddSuggestionWithValidCarrierIdWithoutCarrierProvisionPermission() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - config.carrierId = VALID_CARRIER_ID; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - config, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(false); - - int status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - - assertEquals(status, - WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED); - } - - @Test - public void testAddSuggestionWithDefaultCarrierIdWithoutCarrierProvisionPermission() { - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - config, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(false); - - int status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - - assertEquals(status, WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - } - - /** - * Verify we return the network suggestion matches the target FQDN and user already approved. - */ - @Test - public void testGetPasspointSuggestionFromFqdnWithUserApproval() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, - passpointConfiguration, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class), - anyInt(), anyString(), eq(true), eq(true))).thenReturn(true); - assertEquals(mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE), WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - Set<ExtendedWifiNetworkSuggestion> ewns = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForFqdn(TEST_FQDN); - assertEquals(1, ewns.size()); - assertEquals(networkSuggestion, ewns.iterator().next().wns); - } - - /** - * Verify we return no network suggestion with matched target FQDN but user not approved. - */ - @Test - public void testGetPasspointSuggestionFromFqdnWithoutUserApproval() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, - passpointConfiguration, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - dummyConfiguration.creatorUid = TEST_UID_1; - when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class), - anyInt(), anyString(), eq(true), eq(true))).thenReturn(true); - assertEquals(mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE), WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - Set<ExtendedWifiNetworkSuggestion> ewns = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForFqdn(TEST_FQDN); - assertNull(ewns); - } - - @Test - public void getNetworkSuggestionsForFqdn_activeScorer_doesNotRequestForUserApproval() { - when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_PACKAGE_1); - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, - passpointConfiguration, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = Arrays.asList(networkSuggestion); - dummyConfiguration.creatorUid = TEST_UID_1; - when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class), - anyInt(), anyString(), eq(true), eq(true))).thenReturn(true); - assertEquals(mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE), WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - - Set<ExtendedWifiNetworkSuggestion> ewns = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForFqdn(TEST_FQDN); - - assertEquals(1, ewns.size()); - verifyZeroInteractions(mAlertDialog); - verifyZeroInteractions(mNotificationManger); - } - - /** - * Verify return true when allow user manually connect and user approved the app - */ - @Test - public void testIsPasspointSuggestionSharedWithUserSetToTrue() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, - passpointConfiguration, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - dummyConfiguration.creatorUid = TEST_UID_1; - when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class), - anyInt(), anyString(), eq(true), eq(true))).thenReturn(true); - assertEquals(mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE), WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(false, TEST_PACKAGE_1); - assertFalse(mWifiNetworkSuggestionsManager - .isPasspointSuggestionSharedWithUser(dummyConfiguration)); - - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - assertTrue(mWifiNetworkSuggestionsManager - .isPasspointSuggestionSharedWithUser(dummyConfiguration)); - dummyConfiguration.meteredHint = true; - when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(dummyConfiguration)) - .thenReturn(true); - assertFalse(mWifiNetworkSuggestionsManager - .isPasspointSuggestionSharedWithUser(dummyConfiguration)); - } - - /** - * Verify return true when disallow user manually connect and user approved the app - */ - @Test - public void testIsPasspointSuggestionSharedWithUserSetToFalse() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfiguration, - passpointConfiguration, true, false, false, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class), - anyInt(), anyString(), eq(true), eq(true))).thenReturn(true); - assertEquals(mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE), WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(false, TEST_PACKAGE_1); - assertFalse(mWifiNetworkSuggestionsManager - .isPasspointSuggestionSharedWithUser(dummyConfiguration)); - - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - assertFalse(mWifiNetworkSuggestionsManager - .isPasspointSuggestionSharedWithUser(dummyConfiguration)); - } - - /** - * test getWifiConfigForMatchedNetworkSuggestionsSharedWithUser. - * - app without user approval will not be returned. - * - open network will not be returned. - * - suggestion doesn't allow user manually connect will not be return. - * - Multiple duplicate ScanResults will only return single matched config. - */ - @Test - public void testGetWifiConfigForMatchedNetworkSuggestionsSharedWithUser() { - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createPskNetwork(), null, false, false, false, true); - WifiNetworkSuggestion networkSuggestion3 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createPskNetwork(), null, false, false, true, true); - List<ScanResult> scanResults = new ArrayList<>(); - scanResults.add( - createScanDetailForNetwork(networkSuggestion1.wifiConfiguration).getScanResult()); - scanResults.add( - createScanDetailForNetwork(networkSuggestion2.wifiConfiguration).getScanResult()); - - // Create two same ScanResult for networkSuggestion3 - ScanResult scanResult1 = createScanDetailForNetwork(networkSuggestion3.wifiConfiguration) - .getScanResult(); - ScanResult scanResult2 = new ScanResult(scanResult1); - scanResults.add(scanResult1); - scanResults.add(scanResult2); - - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - add(networkSuggestion3); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - setupGetConfiguredNetworksFromWcm(networkSuggestion1.wifiConfiguration, - networkSuggestion2.wifiConfiguration, networkSuggestion3.wifiConfiguration); - // When app is not approved, empty list will be returned - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(false, TEST_PACKAGE_1); - List<WifiConfiguration> wifiConfigurationList = mWifiNetworkSuggestionsManager - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults); - assertEquals(0, wifiConfigurationList.size()); - // App is approved, only allow user connect, not open network will return. - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - wifiConfigurationList = mWifiNetworkSuggestionsManager - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults); - assertEquals(1, wifiConfigurationList.size()); - assertEquals(networkSuggestion3.wifiConfiguration, wifiConfigurationList.get(0)); - } - - private void assertSuggestionsEquals(Set<WifiNetworkSuggestion> expectedSuggestions, - Set<ExtendedWifiNetworkSuggestion> actualExtSuggestions) { - Set<WifiNetworkSuggestion> actualSuggestions = actualExtSuggestions.stream() - .map(ewns -> ewns.wns) - .collect(Collectors.toSet()); - assertEquals(expectedSuggestions, actualSuggestions); - } - - private void setupGetConfiguredNetworksFromWcm(WifiConfiguration...configs) { - for (int i = 0; i < configs.length; i++) { - WifiConfiguration config = configs[i]; - when(mWifiConfigManager.getConfiguredNetwork(config.getKey())).thenReturn(config); - } - } - - /** - * Verify error code returns when add SIM-based network from app has no carrier privileges. - */ - @Test - public void testAddSimCredentialNetworkWithoutCarrierPrivileges() { - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM, - WifiEnterpriseConfig.Phase2.NONE); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - config, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(false); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1)) - .thenReturn(TelephonyManager.UNKNOWN_CARRIER_ID); - int status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED, status); - verify(mNotificationManger, never()).notify(anyInt(), any()); - assertEquals(0, mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).size()); - verify(mWifiMetrics, never()).incrementNetworkSuggestionApiUsageNumOfAppInType(anyInt()); - } - - /** - * Verify success when add SIM-based network from app has carrier privileges. - */ - @Test - public void testAddSimCredentialNetworkWithCarrierPrivileges() { - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM, - WifiEnterpriseConfig.Phase2.NONE); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - config, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(false); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1)) - .thenReturn(VALID_CARRIER_ID); - int status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, status); - verify(mNotificationManger, never()).notify(anyInt(), any()); - assertEquals(1, mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).size()); - verify(mWifiMetrics).incrementNetworkSuggestionApiUsageNumOfAppInType( - WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED); - } - - /** - * Verify success when add SIM-based network from app has carrier provision permission. - */ - @Test - public void testAddSimCredentialNetworkWithCarrierProvisionPermission() { - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM, - WifiEnterpriseConfig.Phase2.NONE); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - config, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(true); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1)) - .thenReturn(TelephonyManager.UNKNOWN_CARRIER_ID); - int status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - assertEquals(status, WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - verify(mNotificationManger, never()).notify(anyInt(), any()); - assertEquals(1, mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).size()); - } - - /** - * Verify matched SIM-based network will return when imsi protection is available. - */ - @Test - public void testMatchSimBasedNetworkWithImsiProtection() { - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM, - WifiEnterpriseConfig.Phase2.NONE); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - config, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(false); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1)) - .thenReturn(VALID_CARRIER_ID); - when(mWifiCarrierInfoManager.getMatchingSubId(VALID_CARRIER_ID)).thenReturn(TEST_SUBID); - when(mWifiCarrierInfoManager.isSimPresent(TEST_SUBID)).thenReturn(true); - when(mWifiCarrierInfoManager.requiresImsiEncryption(TEST_SUBID)).thenReturn(true); - when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(TEST_SUBID)).thenReturn(true); - ScanDetail scanDetail = createScanDetailForNetwork(config); - int status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, status); - - Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = - mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(scanDetail); - Set<WifiNetworkSuggestion> expectedMatchingNetworkSuggestions = - new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - verify(mNotificationManger, never()).notify(anyInt(), any()); - assertSuggestionsEquals(expectedMatchingNetworkSuggestions, matchingExtNetworkSuggestions); - } - - /** - * Verify when SIM changes, the app loses carrier privilege. Suggestions from this app will be - * removed. If this app suggests again, it will be considered as normal suggestor. - */ - @Test - public void testSimStateChangeWillResetCarrierPrivilegedApp() { - WifiConfiguration config = - WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.SIM, - WifiEnterpriseConfig.Phase2.NONE); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - config, null, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>(); - networkSuggestionList.add(networkSuggestion); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) - .thenReturn(false); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1)) - .thenReturn(VALID_CARRIER_ID); - int status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, status); - verify(mNotificationManger, never()).notify(anyInt(), any()); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1)) - .thenReturn(TelephonyManager.UNKNOWN_CARRIER_ID); - mWifiNetworkSuggestionsManager.resetCarrierPrivilegedApps(); - assertEquals(0, mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).size()); - verify(mWifiConfigManager, times(2)).saveToStore(true); - status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED, status); - networkSuggestionList.clear(); - networkSuggestionList.add(new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true)); - status = mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, status); - verify(mNotificationManger).notify(anyInt(), any()); - } - - /** - * Verify set AllowAutoJoin on suggestion network . - */ - @Test - public void testSetAllowAutoJoinOnSuggestionNetwork() { - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - // No matching will return false. - assertFalse(mWifiNetworkSuggestionsManager - .allowNetworkSuggestionAutojoin(networkSuggestion.wifiConfiguration, false)); - verify(mWifiConfigManager, never()).saveToStore(true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - verify(mWifiConfigManager, times(2)).saveToStore(true); - reset(mWifiConfigManager); - WifiConfiguration configuration = - new WifiConfiguration(networkSuggestion.wifiConfiguration); - configuration.fromWifiNetworkSuggestion = true; - configuration.ephemeral = true; - configuration.creatorName = TEST_PACKAGE_1; - configuration.creatorUid = TEST_UID_1; - - assertTrue(mWifiNetworkSuggestionsManager - .allowNetworkSuggestionAutojoin(configuration, false)); - verify(mWifiConfigManager).saveToStore(true); - Set<ExtendedWifiNetworkSuggestion> matchedSuggestions = mWifiNetworkSuggestionsManager - .getNetworkSuggestionsForWifiConfiguration(configuration, - TEST_BSSID); - for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestions) { - assertFalse(ewns.isAutojoinEnabled); - } - } - - /** - * Verify set AllowAutoJoin on passpoint suggestion network. - */ - @Test - public void testSetAllowAutoJoinOnPasspointSuggestionNetwork() { - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - dummyConfiguration, passpointConfiguration, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - when(mPasspointManager.addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), - anyBoolean())).thenReturn(true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - verify(mWifiConfigManager, times(2)).saveToStore(true); - reset(mWifiConfigManager); - // Create WifiConfiguration for Passpoint network. - WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork(); - config.FQDN = TEST_FQDN; - config.providerFriendlyName = TEST_FRIENDLY_NAME; - config.setPasspointUniqueId(passpointConfiguration.getUniqueId()); - config.fromWifiNetworkSuggestion = true; - config.ephemeral = true; - config.creatorName = TEST_PACKAGE_1; - config.creatorUid = TEST_UID_1; - // When update PasspointManager is failure, will return false. - when(mPasspointManager.enableAutojoin(anyString(), isNull(), anyBoolean())) - .thenReturn(false); - assertFalse(mWifiNetworkSuggestionsManager - .allowNetworkSuggestionAutojoin(config, false)); - verify(mWifiConfigManager, never()).saveToStore(true); - - // When update PasspointManager is success, will return true and persist suggestion. - when(mPasspointManager.enableAutojoin(anyString(), isNull(), anyBoolean())) - .thenReturn(true); - assertTrue(mWifiNetworkSuggestionsManager - .allowNetworkSuggestionAutojoin(config, false)); - verify(mWifiConfigManager).saveToStore(true); - Set<ExtendedWifiNetworkSuggestion> matchedSuggestions = mWifiNetworkSuggestionsManager - .getNetworkSuggestionsForWifiConfiguration(config, TEST_BSSID); - for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestions) { - assertFalse(ewns.isAutojoinEnabled); - } - } - - /** - * Verify that both passpoint configuration and non passpoint configuration could match - * the ScanResults. - */ - @Test - public void getMatchingScanResultsTestWithPasspointAndNonPasspointMatch() { - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.FQDN = TEST_FQDN; - PasspointConfiguration mockPasspoint = mock(PasspointConfiguration.class); - WifiNetworkSuggestion passpointSuggestion = new WifiNetworkSuggestion( - dummyConfiguration, mockPasspoint, false, false, true, true); - WifiNetworkSuggestion nonPasspointSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), - null, false, false, true, true); - List<WifiNetworkSuggestion> suggestions = new ArrayList<>() {{ - add(passpointSuggestion); - add(nonPasspointSuggestion); - }}; - ScanResult passpointScanResult = new ScanResult(); - passpointScanResult.wifiSsid = WifiSsid.createFromAsciiEncoded("passpoint"); - List<ScanResult> ppSrList = new ArrayList<>() {{ - add(passpointScanResult); - }}; - ScanResult nonPasspointScanResult = new ScanResult(); - nonPasspointScanResult.wifiSsid = WifiSsid.createFromAsciiEncoded( - nonPasspointSuggestion.wifiConfiguration.SSID); - List<ScanResult> nonPpSrList = new ArrayList<>() {{ - add(nonPasspointScanResult); - }}; - List<ScanResult> allSrList = new ArrayList<>() {{ - add(passpointScanResult); - add(nonPasspointScanResult); - add(null); - }}; - when(mPasspointManager.getMatchingScanResults(eq(mockPasspoint), eq(allSrList))) - .thenReturn(ppSrList); - ScanResultMatchInfo mockMatchInfo = mock(ScanResultMatchInfo.class); - ScanResultMatchInfo nonPasspointMi = new ScanResultMatchInfo(); - nonPasspointMi.networkSsid = nonPasspointSuggestion.wifiConfiguration.SSID; - MockitoSession session = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT) - .mockStatic(ScanResultMatchInfo.class).startMocking(); - try { - doReturn(nonPasspointMi).when( - () -> ScanResultMatchInfo.fromWifiConfiguration( - nonPasspointSuggestion.wifiConfiguration)); - doReturn(nonPasspointMi).when( - () -> ScanResultMatchInfo.fromScanResult(nonPasspointScanResult)); - doReturn(mockMatchInfo).when( - () -> ScanResultMatchInfo.fromScanResult(passpointScanResult)); - Map<WifiNetworkSuggestion, List<ScanResult>> result = - mWifiNetworkSuggestionsManager.getMatchingScanResults(suggestions, allSrList); - assertEquals(2, result.size()); - assertEquals(1, result.get(nonPasspointSuggestion).size()); - } finally { - session.finishMocking(); - } - } - - /** - * Verify that the wifi configuration doesn't match anything - */ - @Test - public void getMatchingScanResultsTestWithMatchNothing() { - WifiNetworkSuggestion nonPasspointSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), - null, false, false, true, true); - List<WifiNetworkSuggestion> suggestions = new ArrayList<>() {{ - add(nonPasspointSuggestion); - }}; - ScanResult nonPasspointScanResult = new ScanResult(); - nonPasspointScanResult.wifiSsid = WifiSsid.createFromAsciiEncoded("non-passpoint"); - List<ScanResult> allSrList = new ArrayList<>() {{ - add(nonPasspointScanResult); - }}; - - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - ScanResultMatchInfo.class).startMocking(); - ScanResultMatchInfo mockMatchInfo = mock(ScanResultMatchInfo.class); - ScanResultMatchInfo miFromConfig = new ScanResultMatchInfo(); - miFromConfig.networkSsid = nonPasspointSuggestion.wifiConfiguration.SSID; - try { - when(ScanResultMatchInfo.fromWifiConfiguration(any(WifiConfiguration.class))) - .thenReturn(miFromConfig); - when(ScanResultMatchInfo.fromScanResult(eq(nonPasspointScanResult))) - .thenReturn(mockMatchInfo); - Map<WifiNetworkSuggestion, List<ScanResult>> result = - mWifiNetworkSuggestionsManager.getMatchingScanResults(suggestions, allSrList); - assertEquals(1, result.size()); - assertEquals(0, result.get(nonPasspointSuggestion).size()); - } finally { - session.finishMocking(); - } - } - - /** - * Verify that the wifi configuration doesn't match anything if the Wificonfiguration - * is invalid. - */ - @Test - public void getMatchingScanResultsTestWithInvalidWifiConfiguration() { - WifiNetworkSuggestion nonPasspointSuggestion = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), - null, false, false, true, true); - List<WifiNetworkSuggestion> suggestions = new ArrayList<>() {{ - add(nonPasspointSuggestion); - }}; - ScanResult nonPasspointScanResult = new ScanResult(); - nonPasspointScanResult.wifiSsid = WifiSsid.createFromAsciiEncoded("non-passpoint"); - List<ScanResult> allSrList = new ArrayList<>() {{ - add(nonPasspointScanResult); - }}; - - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - ScanResultMatchInfo.class).startMocking(); - try { - when(ScanResultMatchInfo.fromWifiConfiguration(any(WifiConfiguration.class))) - .thenReturn(null); - - Map<WifiNetworkSuggestion, List<ScanResult>> result = - mWifiNetworkSuggestionsManager.getMatchingScanResults(suggestions, allSrList); - assertEquals(1, result.size()); - assertEquals(0, result.get(nonPasspointSuggestion).size()); - } finally { - session.finishMocking(); - } - } - - /** - * Verify when matching a SIM-Based network without IMSI protection, framework will mark it - * auto-join disable and send notification. If user click on allow, will restore the auto-join - * config. - */ - @Test - public void testSendImsiProtectionNotificationOnUserAllowed() { - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1)) - .thenReturn(TEST_CARRIER_ID); - when(mWifiCarrierInfoManager.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(TEST_SUBID); - when(mWifiCarrierInfoManager.getCarrierNameforSubId(TEST_SUBID)) - .thenReturn(TEST_CARRIER_NAME); - when(mWifiCarrierInfoManager.requiresImsiEncryption(TEST_SUBID)).thenReturn(false); - when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID)) - .thenReturn(false); - when(mPasspointManager.addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), - anyBoolean())).thenReturn(true); - - WifiConfiguration eapSimConfig = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - PasspointConfiguration passpointConfiguration = - createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, TEST_REALM); - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.setPasspointUniqueId(passpointConfiguration.getUniqueId()); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - eapSimConfig, null, true, false, true, true); - WifiNetworkSuggestion passpointSuggestion = new WifiNetworkSuggestion( - dummyConfiguration, passpointConfiguration, true, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - Arrays.asList(networkSuggestion, passpointSuggestion); - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - - verifyNoMoreInteractions(mNotificationManger); - Set<ExtendedWifiNetworkSuggestion> matchedSuggestion = mWifiNetworkSuggestionsManager - .getNetworkSuggestionsForScanDetail(createScanDetailForNetwork(eapSimConfig)); - verify(mWifiCarrierInfoManager) - .sendImsiProtectionExemptionNotificationIfRequired(TEST_CARRIER_ID); - for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestion) { - assertFalse(ewns.isAutojoinEnabled); - } - - // Simulate user approved carrier - mUserApproveCarrierListenerArgumentCaptor.getValue().onUserAllowed(TEST_CARRIER_ID); - when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID)) - .thenReturn(true); - verify(mPasspointManager).enableAutojoin(anyString(), any(), anyBoolean()); - matchedSuggestion = mWifiNetworkSuggestionsManager - .getNetworkSuggestionsForScanDetail(createScanDetailForNetwork(eapSimConfig)); - - for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestion) { - assertTrue(ewns.isAutojoinEnabled); - } - } - - /** - * Verify adding invalid suggestions will return right error reason code. - */ - @Test - public void testAddInvalidNetworkSuggestions() { - WifiConfiguration invalidConfig = WifiConfigurationTestUtil.createOpenNetwork(); - invalidConfig.SSID = ""; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(invalidConfig, - null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, - mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); - } - - /** - * Verify adding invalid passpoint suggestions will return right error reason code. - */ - @Test - public void testAddInvalidPasspointNetworkSuggestions() { - PasspointConfiguration passpointConfiguration = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - passpointConfiguration.setHomeSp(homeSp); - WifiConfiguration dummyConfig = new WifiConfiguration(); - dummyConfig.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(dummyConfig, - passpointConfiguration, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, - mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); - } - - /** - * Verify getAllScanOptimizationSuggestionNetworks will only return user approved, - * non-passpoint network. - */ - @Test - public void testGetPnoAvailableSuggestions() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createOpenNetwork(); - PasspointConfiguration passpointConfiguration = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - WifiConfiguration dummyConfig = new WifiConfiguration(); - dummyConfig.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion = - new WifiNetworkSuggestion(network1, null, false, false, true, true); - WifiNetworkSuggestion passpointSuggestion = new WifiNetworkSuggestion(dummyConfig, - passpointConfiguration, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion); - add(passpointSuggestion); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); - assertTrue(mWifiNetworkSuggestionsManager - .getAllScanOptimizationSuggestionNetworks().isEmpty()); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - List<WifiConfiguration> pnoNetwork = - mWifiNetworkSuggestionsManager.getAllScanOptimizationSuggestionNetworks(); - assertEquals(1, pnoNetwork.size()); - assertEquals(network1.SSID, pnoNetwork.get(0).SSID); - } - - @Test - public void getAllScanOptimizationSuggestionNetworks_returnsActiveScorerWithoutUserApproval() { - when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_PACKAGE_1); - WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion = - new WifiNetworkSuggestion(network, null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = Arrays.asList(networkSuggestion); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(false, TEST_PACKAGE_1); - - List<WifiConfiguration> networks = - mWifiNetworkSuggestionsManager.getAllScanOptimizationSuggestionNetworks(); - - assertEquals(1, networks.size()); - } - - /** - * Verify if a suggestion is mostRecently connected, flag will be persist. - */ - @Test - public void testIsMostRecentlyConnectedSuggestion() { - WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion = - new WifiNetworkSuggestion(network, null, false, false, true, true); - List<WifiNetworkSuggestion> networkSuggestionList = Arrays.asList(networkSuggestion); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager - .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE)); - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - when(mLruConnectionTracker.isMostRecentlyConnected(any())).thenReturn(true); - Map<String, PerAppInfo> suggestionStore = new HashMap<>(mDataSource.toSerialize()); - PerAppInfo perAppInfo = suggestionStore.get(TEST_PACKAGE_1); - ExtendedWifiNetworkSuggestion ewns = perAppInfo.extNetworkSuggestions.iterator().next(); - assertTrue(ewns.wns.wifiConfiguration.isMostRecentlyConnected); - mDataSource.fromDeserialized(suggestionStore); - verify(mLruConnectionTracker).addNetwork(any()); - reset(mLruConnectionTracker); - - when(mLruConnectionTracker.isMostRecentlyConnected(any())).thenReturn(false); - suggestionStore = mDataSource.toSerialize(); - perAppInfo = suggestionStore.get(TEST_PACKAGE_1); - ewns = perAppInfo.extNetworkSuggestions.iterator().next(); - assertFalse(ewns.wns.wifiConfiguration.isMostRecentlyConnected); - mDataSource.fromDeserialized(suggestionStore); - verify(mLruConnectionTracker, never()).addNetwork(any()); - } - - @Test - public void testOnSuggestionUpdateListener() { - WifiNetworkSuggestionsManager.OnSuggestionUpdateListener listener = - mock(WifiNetworkSuggestionsManager.OnSuggestionUpdateListener.class); - mWifiNetworkSuggestionsManager.addOnSuggestionUpdateListener(listener); - - WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN); - dummyConfiguration.FQDN = TEST_FQDN; - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - verify(listener).onSuggestionsAddedOrUpdated(networkSuggestionList1); - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1)); - verify(listener).onSuggestionsRemoved(networkSuggestionList1); - } - - @Test - public void testShouldNotBeIgnoredBySecureSuggestionFromSameCarrierWithoutSameOpenSuggestion() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())) - .thenReturn(true); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, true); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Without same open suggestion in the framework, should not be ignored. - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion2); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testShouldNotBeIgnoredBySecureSuggestionFromSameCarrierWithoutSecureSuggestion() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())) - .thenReturn(true); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, true); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Without secure suggestion in the framework, should not be ignored. - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion1); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testShouldNotBeIgnoredWithoutCarrierProvisioningPermission() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(true); - when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(anyString())) - .thenReturn(TEST_CARRIER_ID); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, true); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Without CarrierProvisioningPermission, should not be ignored. - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion1, suggestion2); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testShouldNotBeIgnoredBySecureSuggestionFromDifferentCarrierId() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())) - .thenReturn(true); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = VALID_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, true); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Open and secure suggestions have different carrierId, should not be ignored. - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion1, suggestion2); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testShouldNotBeIgnoredBySecureSuggestionFromSameCarrierWithAutojoinDisabled() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())) - .thenReturn(true); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, false); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Secure suggestions is auto-join disabled, should not be ignored. - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion1, suggestion2); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testShouldNotBeIgnoredBySecureSuggestionFromSameCarrierWithDifferentMeterness() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())) - .thenReturn(true); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - network2.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED; - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, true); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Secure suggestions is auto-join disabled, should not be ignored. - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion1, suggestion2); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testShouldNotBeIgnoredBySecureSuggestionFromSameCarrierWithNetworkDisabled() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())) - .thenReturn(true); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, true); - - WifiConfiguration wcmConfig = new WifiConfiguration(network2); - WifiConfiguration.NetworkSelectionStatus status = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(status.isNetworkEnabled()).thenReturn(false); - wcmConfig.setNetworkSelectionStatus(status); - when(mWifiConfigManager.getConfiguredNetwork(network2.getKey())).thenReturn(wcmConfig); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Secure suggestions is auto-join disabled, should not be ignored. - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion1, suggestion2); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testShouldNotBeIgnoredBySecureSuggestionFromSameCarrierWithOverlayFalse() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())) - .thenReturn(true); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, true); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Both open and secure suggestions with same carrierId, - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion1, suggestion2); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testShouldBeIgnoredBySecureSuggestionFromSameCarrier() { - when(mResources.getBoolean( - R.bool.config_wifiIgnoreOpenSavedNetworkWhenSecureSuggestionAvailable)) - .thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())) - .thenReturn(true); - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - ScanDetail scanDetail1 = createScanDetailForNetwork(network1); - network1.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion( - network1, null, false, false, true, true); - WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); - ScanDetail scanDetail2 = createScanDetailForNetwork(network2); - network2.carrierId = TEST_CARRIER_ID; - WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion( - network2, null, false, false, true, true); - - List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2); - // Both open and secure suggestions with same carrierId, - List<WifiNetworkSuggestion> suggestionList = Arrays.asList(suggestion1, suggestion2); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(suggestionList, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertTrue(mWifiNetworkSuggestionsManager - .shouldBeIgnoredBySecureSuggestionFromSameCarrier(network1, scanDetails)); - } - - @Test - public void testUnregisterSuggestionConnectionStatusListenerNeverRegistered() { - int listenerIdentifier = 1234; - mWifiNetworkSuggestionsManager.unregisterSuggestionConnectionStatusListener( - listenerIdentifier, TEST_PACKAGE_1, TEST_UID_1); - } - - /** - * Verify that we only return user approved suggestions. - */ - @Test - public void testGetApprovedNetworkSuggestions() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - // Reuse the same network credentials to ensure they both match. - WifiNetworkSuggestion networkSuggestion2 = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - - List<WifiNetworkSuggestion> networkSuggestionList1 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}; - List<WifiNetworkSuggestion> networkSuggestionList2 = - new ArrayList<WifiNetworkSuggestion>() {{ - add(networkSuggestion2); - }}; - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2, - TEST_PACKAGE_2, TEST_FEATURE)); - - // nothing approved, return empty. - assertTrue(mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions().isEmpty()); - - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); - // only app 1 approved. - assertEquals(new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - }}, - mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()); - - mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_2); - // both app 1 & 2 approved. - assertEquals(new HashSet<WifiNetworkSuggestion>() {{ - add(networkSuggestion1); - add(networkSuggestion2); - }}, - mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()); - } - - /** - * Verify when calling API from background user will fail. - */ - @Test - public void testCallingFromBackgroundUserWillFailed() { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork(); - WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( - wifiConfiguration, null, false, false, true, true); - - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(Arrays.asList(networkSuggestion), TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - // When switch the user to background - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(TEST_UID_1)).thenReturn(false); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, - mWifiNetworkSuggestionsManager.add(Arrays.asList(networkSuggestion), TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, - mWifiNetworkSuggestionsManager.remove(Arrays.asList(networkSuggestion), TEST_UID_1, - TEST_PACKAGE_1)); - assertTrue(mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).isEmpty()); - assertFalse(mWifiNetworkSuggestionsManager.registerSuggestionConnectionStatusListener( - mBinder, mListener, NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1)); - - // When switch the user back to foreground - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(TEST_UID_1)).thenReturn(true); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.add(Arrays.asList(networkSuggestion), TEST_UID_1, - TEST_PACKAGE_1, TEST_FEATURE)); - assertFalse(mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).isEmpty()); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiNetworkSuggestionsManager.remove(Arrays.asList(networkSuggestion), TEST_UID_1, - TEST_PACKAGE_1)); - assertTrue(mWifiNetworkSuggestionsManager.registerSuggestionConnectionStatusListener( - mBinder, mListener, NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1)); - } - - /** - * Helper function for creating a test configuration with user credential. - * - * @return {@link PasspointConfiguration} - */ - private PasspointConfiguration createTestConfigWithUserCredential(String fqdn, - String friendlyName) { - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - homeSp.setFriendlyName(friendlyName); - config.setHomeSp(homeSp); - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put("en", friendlyName); - friendlyNames.put("kr", friendlyName + 1); - friendlyNames.put("jp", friendlyName + 2); - config.setServiceFriendlyNames(friendlyNames); - Credential credential = new Credential(); - credential.setRealm(TEST_REALM); - credential.setCaCertificate(FakeKeys.CA_CERT0); - Credential.UserCredential userCredential = new Credential.UserCredential(); - userCredential.setUsername("username"); - userCredential.setPassword("password"); - userCredential.setEapType(EAPConstants.EAP_TTLS); - userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP); - credential.setUserCredential(userCredential); - config.setCredential(credential); - return config; - } - - /** - * Helper function for creating a test configuration with SIM credential. - * - * @return {@link PasspointConfiguration} - */ - private PasspointConfiguration createTestConfigWithSimCredential(String fqdn, String imsi, - String realm) { - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - homeSp.setFriendlyName(TEST_FRIENDLY_NAME); - config.setHomeSp(homeSp); - Credential credential = new Credential(); - credential.setRealm(realm); - Credential.SimCredential simCredential = new Credential.SimCredential(); - simCredential.setImsi(imsi); - simCredential.setEapType(EAPConstants.EAP_SIM); - credential.setSimCredential(simCredential); - config.setCredential(credential); - return config; - } - - private WifiConfiguration createDummyWifiConfigurationForPasspoint(String fqdn) { - WifiConfiguration config = new WifiConfiguration(); - config.FQDN = fqdn; - return config; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiPowerMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiPowerMetricsTest.java deleted file mode 100644 index 6db0e38c8..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiPowerMetricsTest.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; - -import android.os.BatteryStatsManager; -import android.os.connectivity.WifiBatteryStats; -import android.text.format.DateUtils; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiPowerStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiRadioUsage; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; - -/** - * Unit tests for {@link com.android.server.wifi.WifiPowerMetrics}. - */ -@SmallTest -public class WifiPowerMetricsTest extends WifiBaseTest { - @Mock - BatteryStatsManager mBatteryStats; - WifiPowerMetrics mWifiPowerMetrics; - - private static final long DEFAULT_VALUE = 0; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mWifiPowerMetrics = new WifiPowerMetrics(mBatteryStats); - } - - /** - * Tests that WifiRadioUsage has its fields set according to the corresponding fields in - * WifiBatteryStats - * @throws Exception - */ - @Test - public void testBuildWifiRadioUsageProto() throws Exception { - final long loggingDuration = 280; - final long scanTime = 23; - WifiBatteryStats wifiBatteryStats = mock(WifiBatteryStats.class); - when(wifiBatteryStats.getLoggingDurationMillis()).thenReturn(loggingDuration); - when(wifiBatteryStats.getScanTimeMillis()).thenReturn(scanTime); - when(mBatteryStats.getWifiBatteryStats()).thenReturn(wifiBatteryStats); - WifiRadioUsage wifiRadioUsage = mWifiPowerMetrics.buildWifiRadioUsageProto(); - verify(mBatteryStats).getWifiBatteryStats(); - assertEquals("loggingDurationMs must match with field from WifiBatteryStats", - loggingDuration, wifiRadioUsage.loggingDurationMs); - assertEquals("scanTimeMs must match with field from WifiBatteryStats", - scanTime, wifiRadioUsage.scanTimeMs); - } - - /** - * Tests that WifiRadioUsage has its fields set to the |DEFAULT_VALUE| when BatteryStatsManager - * returns null - * @throws Exception - */ - @Test - public void testBuildWifiRadioUsageProtoNull() throws Exception { - when(mBatteryStats.getWifiBatteryStats()).thenReturn(null); - WifiRadioUsage wifiRadioUsage = mWifiPowerMetrics.buildWifiRadioUsageProto(); - verify(mBatteryStats).getWifiBatteryStats(); - assertEquals("loggingDurationMs must be default value when getWifiBatteryStats returns " - + "null", DEFAULT_VALUE, wifiRadioUsage.loggingDurationMs); - assertEquals("scanTimeMs must be default value when getWifiBatteryStats returns null", - DEFAULT_VALUE, wifiRadioUsage.scanTimeMs); - } - - /** - * Tests that dump() pulls data from BatteryStatsManager - * @throws Exception - */ - @Test - public void testDumpCallsAppropriateMethods() throws Exception { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - mWifiPowerMetrics.dump(writer); - verify(mBatteryStats, atLeastOnce()).getWifiBatteryStats(); - } - - /** - * Tests that WifiPowerStats has its fields set according to the corresponding fields in - * WifiBatteryStats - * @throws Exception - */ - @Test - public void testBuildProto() throws Exception { - final long monitoredRailEnergyConsumedMaMs = 12000; - final long numBytesTx = 65000; - final long numBytesRx = 4560000; - final long numPacketsTx = 3456; - final long numPacketsRx = 5436456; - final long txTimeMs = 2300; - final long rxTimeMs = 343258; - final long idleTimeMs = 32322233; - final long scanTimeMs = 345566; - final long sleepTimeMs = 323270343; - final double monitoredRailEnergyConsumedMah = monitoredRailEnergyConsumedMaMs - / ((double) DateUtils.HOUR_IN_MILLIS); - WifiBatteryStats wifiBatteryStats = mock(WifiBatteryStats.class); - when(wifiBatteryStats.getEnergyConsumedMaMillis()) - .thenReturn(monitoredRailEnergyConsumedMaMs); - when(wifiBatteryStats.getNumBytesTx()).thenReturn(numBytesTx); - when(wifiBatteryStats.getNumBytesRx()).thenReturn(numBytesRx); - when(wifiBatteryStats.getNumPacketsTx()).thenReturn(numPacketsTx); - when(wifiBatteryStats.getNumPacketsRx()).thenReturn(numPacketsRx); - when(wifiBatteryStats.getTxTimeMillis()).thenReturn(txTimeMs); - when(wifiBatteryStats.getRxTimeMillis()).thenReturn(rxTimeMs); - when(wifiBatteryStats.getIdleTimeMillis()).thenReturn(idleTimeMs); - when(wifiBatteryStats.getScanTimeMillis()).thenReturn(scanTimeMs); - when(wifiBatteryStats.getSleepTimeMillis()).thenReturn(sleepTimeMs); - - when(mBatteryStats.getWifiBatteryStats()).thenReturn(wifiBatteryStats); - WifiPowerStats wifiPowerStats = mWifiPowerMetrics.buildProto(); - verify(mBatteryStats).getWifiBatteryStats(); - assertEquals("monitoredRailEnergyConsumedMah must match with field from WifiPowerStats", - monitoredRailEnergyConsumedMah, wifiPowerStats.monitoredRailEnergyConsumedMah, - 0.01); - assertEquals("numBytesTx must match with field from WifiBatteryStats", - numBytesTx, wifiPowerStats.numBytesTx); - assertEquals("numBytesRx must match with field from WifiBatteryStats", - numBytesRx, wifiPowerStats.numBytesRx); - assertEquals("numPacketsTx must match with field from WifiBatteryStats", - numPacketsTx, wifiPowerStats.numPacketsTx); - assertEquals("numPacketsRx must match with field from WifiBatteryStats", - numPacketsRx, wifiPowerStats.numPacketsRx); - assertEquals("txTimeMs must match with field from WifiBatteryStats", - txTimeMs, wifiPowerStats.txTimeMs); - assertEquals("rxTimeMs must match with field from WifiBatteryStats", - rxTimeMs, wifiPowerStats.rxTimeMs); - assertEquals("idleTimeMs must match with field from WifiBatteryStats", - idleTimeMs, wifiPowerStats.idleTimeMs); - assertEquals("scanTimeMs must match with field from WifiBatteryStats", - scanTimeMs, wifiPowerStats.scanTimeMs); - assertEquals("sleepTimeMs must match with field from WifiBatteryStats", - sleepTimeMs, wifiPowerStats.sleepTimeMs); - } - - /** - * Tests that WifiPowerStats has its fields set to the |DEFAULT_VALUE| when BatteryStatsManager - * returns null - * @throws Exception - */ - @Test - public void testBuildProtoNull() throws Exception { - when(mBatteryStats.getWifiBatteryStats()).thenReturn(null); - WifiPowerStats wifiPowerStats = mWifiPowerMetrics.buildProto(); - verify(mBatteryStats).getWifiBatteryStats(); - assertEquals("monitoredRailEnergyConsumedMah must be default value when getWifiBatteryStats" - + " returns null", DEFAULT_VALUE, wifiPowerStats.monitoredRailEnergyConsumedMah, - 0.01); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibilityTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibilityTest.java deleted file mode 100644 index 2caa813c6..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiScanAlwaysAvailableSettingsCompatibilityTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import static com.android.server.wifi.WifiScanAlwaysAvailableSettingsCompatibility.SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE; - -import static org.junit.Assert.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.validateMockitoUsage; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.os.Handler; - -import androidx.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.WifiScanAlwaysAvailableSettingsCompatibility}. - */ -@SmallTest -public class WifiScanAlwaysAvailableSettingsCompatibilityTest extends WifiBaseTest { - @Mock - private Context mContext; - @Mock - private Handler mHandler; - @Mock - private WifiSettingsStore mWifiSettingsStore; - @Mock - private ActiveModeWarden mActiveModeWarden; - @Mock - private FrameworkFacade mFrameworkFacade; - @Mock - private ContentResolver mContentResolver; - - private ArgumentCaptor<ContentObserver> mContentObserverArgumentCaptor = - ArgumentCaptor.forClass(ContentObserver.class); - - private WifiScanAlwaysAvailableSettingsCompatibility mScanAlwaysCompatibility; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mContext.getContentResolver()).thenReturn(mContentResolver); - mScanAlwaysCompatibility = - new WifiScanAlwaysAvailableSettingsCompatibility(mContext, mHandler, - mWifiSettingsStore, mActiveModeWarden, mFrameworkFacade); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - @Test - public void reactToContentObserverChanges() { - mScanAlwaysCompatibility.initialize(); - verify(mContentResolver).registerContentObserver( - any(), anyBoolean(), mContentObserverArgumentCaptor.capture()); - - ContentObserver contentObserver = mContentObserverArgumentCaptor.getValue(); - assertNotNull(contentObserver); - - when(mWifiSettingsStore.isScanAlwaysAvailable()).thenReturn(false); - when(mFrameworkFacade.getIntegerSetting( - any(ContentResolver.class), - eq(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE), - anyInt())) - .thenReturn(1); - contentObserver.onChange(false); - - verify(mWifiSettingsStore).handleWifiScanAlwaysAvailableToggled(true); - verify(mActiveModeWarden).scanAlwaysModeChanged(); - - when(mWifiSettingsStore.isScanAlwaysAvailable()).thenReturn(true); - when(mFrameworkFacade.getIntegerSetting( - any(ContentResolver.class), - eq(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE), - anyInt())) - .thenReturn(0); - contentObserver.onChange(false); - - verify(mWifiSettingsStore).handleWifiScanAlwaysAvailableToggled(false); - verify(mActiveModeWarden, times(2)).scanAlwaysModeChanged(); - } - - - @Test - public void changeSetting() { - mScanAlwaysCompatibility.initialize(); - - mScanAlwaysCompatibility.handleWifiScanAlwaysAvailableToggled(true); - verify(mFrameworkFacade).setIntegerSetting( - any(ContentResolver.class), - eq(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE), - eq(1)); - - mScanAlwaysCompatibility.handleWifiScanAlwaysAvailableToggled(false); - verify(mFrameworkFacade).setIntegerSetting( - any(ContentResolver.class), - eq(SETTINGS_GLOBAL_WIFI_SCAN_ALWAYS_AVAILABLE), - eq(0)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardProtoTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreCardProtoTest.java deleted file mode 100644 index 15a6f598e..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardProtoTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.junit.Assert.assertEquals; - -import android.net.wifi.WifiConfiguration; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.proto.WifiScoreCardProto; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.proto.WifiScoreCardProto}. - */ -@SmallTest -public class WifiScoreCardProtoTest extends WifiBaseTest { - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - - /** - * Test a builder - */ - @Test - public void testBuilder() throws Exception { - WifiScoreCardProto.Network network = WifiScoreCardProto.Network.newBuilder() - .setSsid("FloogleGuest") - .build(); - assertEquals("FloogleGuest", network.getSsid()); - } - - /** - * Make sure that the numeric values of SecurityType proto match - * the @IntDef versions. - */ - @Test - public void testSecurityTypeValues() throws Exception { - assertEquals(WifiConfiguration.SECURITY_TYPE_OPEN, - WifiScoreCardProto.SecurityType.OPEN.getNumber()); - assertEquals(WifiConfiguration.SECURITY_TYPE_WEP, - WifiScoreCardProto.SecurityType.WEP.getNumber()); - assertEquals(WifiConfiguration.SECURITY_TYPE_PSK, - WifiScoreCardProto.SecurityType.PSK.getNumber()); - assertEquals(WifiConfiguration.SECURITY_TYPE_EAP, - WifiScoreCardProto.SecurityType.EAP.getNumber()); - assertEquals(WifiConfiguration.SECURITY_TYPE_SAE, - WifiScoreCardProto.SecurityType.SAE.getNumber()); - assertEquals(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B, - WifiScoreCardProto.SecurityType.EAP_SUITE_B.getNumber()); - assertEquals(WifiConfiguration.SECURITY_TYPE_OWE, - WifiScoreCardProto.SecurityType.OWE.getNumber()); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java deleted file mode 100644 index e5739a1c8..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java +++ /dev/null @@ -1,1394 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static com.android.server.wifi.DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; -import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_REJECTION; -import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_TIMEOUT; -import static com.android.server.wifi.WifiHealthMonitor.REASON_AUTH_FAILURE; -import static com.android.server.wifi.WifiHealthMonitor.REASON_CONNECTION_FAILURE; -import static com.android.server.wifi.WifiHealthMonitor.REASON_DISCONNECTION_NONLOCAL; -import static com.android.server.wifi.WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL; -import static com.android.server.wifi.WifiScoreCard.CNT_ASSOCIATION_REJECTION; -import static com.android.server.wifi.WifiScoreCard.CNT_ASSOCIATION_TIMEOUT; -import static com.android.server.wifi.WifiScoreCard.CNT_AUTHENTICATION_FAILURE; -import static com.android.server.wifi.WifiScoreCard.CNT_CONNECTION_ATTEMPT; -import static com.android.server.wifi.WifiScoreCard.CNT_CONNECTION_DURATION_SEC; -import static com.android.server.wifi.WifiScoreCard.CNT_CONNECTION_FAILURE; -import static com.android.server.wifi.WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE; -import static com.android.server.wifi.WifiScoreCard.CNT_DISCONNECTION_NONLOCAL; -import static com.android.server.wifi.WifiScoreCard.CNT_SHORT_CONNECTION_NONLOCAL; -import static com.android.server.wifi.util.NativeUtil.hexStringFromByteArray; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.net.MacAddress; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiSsid; -import android.util.Base64; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiHealthMonitor.FailureStats; -import com.android.server.wifi.WifiScoreCard.NetworkConnectionStats; -import com.android.server.wifi.WifiScoreCard.PerNetwork; -import com.android.server.wifi.proto.WifiScoreCardProto.AccessPoint; -import com.android.server.wifi.proto.WifiScoreCardProto.ConnectionStats; -import com.android.server.wifi.proto.WifiScoreCardProto.Event; -import com.android.server.wifi.proto.WifiScoreCardProto.Network; -import com.android.server.wifi.proto.WifiScoreCardProto.NetworkList; -import com.android.server.wifi.proto.WifiScoreCardProto.NetworkStats; -import com.android.server.wifi.proto.WifiScoreCardProto.Signal; -import com.android.server.wifi.util.IntHistogram; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.WifiScoreCard}. - */ -@SmallTest -public class WifiScoreCardTest extends WifiBaseTest { - - static final WifiSsid TEST_SSID_1 = WifiSsid.createFromAsciiEncoded("Joe's Place"); - static final WifiSsid TEST_SSID_2 = WifiSsid.createFromAsciiEncoded("Poe's Ravn"); - - static final MacAddress TEST_BSSID_1 = MacAddress.fromString("aa:bb:cc:dd:ee:ff"); - static final MacAddress TEST_BSSID_2 = MacAddress.fromString("1:2:3:4:5:6"); - - static final int TEST_NETWORK_AGENT_ID = 123; - static final int TEST_NETWORK_CONFIG_ID = 1492; - - static final double TOL = 1e-6; // for assertEquals(double, double, tolerance) - - static final int TEST_BSSID_FAILURE_REASON = - BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION; - - WifiScoreCard mWifiScoreCard; - - @Mock Clock mClock; - @Mock WifiScoreCard.MemoryStore mMemoryStore; - @Mock DeviceConfigFacade mDeviceConfigFacade; - - final ArrayList<String> mKeys = new ArrayList<>(); - final ArrayList<WifiScoreCard.BlobListener> mBlobListeners = new ArrayList<>(); - final ArrayList<byte[]> mBlobs = new ArrayList<>(); - - long mMilliSecondsSinceBoot; - ExtendedWifiInfo mWifiInfo; - - void millisecondsPass(long ms) { - mMilliSecondsSinceBoot += ms; - when(mClock.getElapsedSinceBootMillis()).thenReturn(mMilliSecondsSinceBoot); - } - - void secondsPass(long s) { - millisecondsPass(s * 1000); - } - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mKeys.clear(); - mBlobListeners.clear(); - mBlobs.clear(); - mMilliSecondsSinceBoot = 0; - mWifiInfo = new ExtendedWifiInfo(mock(Context.class)); - mWifiInfo.setSSID(TEST_SSID_1); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - mWifiInfo.setNetworkId(TEST_NETWORK_CONFIG_ID); - millisecondsPass(0); - mWifiScoreCard = new WifiScoreCard(mClock, "some seed", mDeviceConfigFacade); - mWifiScoreCard.mPersistentHistograms = true; // TODO - remove when ready - when(mDeviceConfigFacade.getConnectionFailureHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getConnectionFailureCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_COUNT_MIN); - when(mDeviceConfigFacade.getAssocRejectionHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getAssocRejectionCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_ASSOC_REJECTION_COUNT_MIN); - when(mDeviceConfigFacade.getAssocTimeoutHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getAssocTimeoutCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_ASSOC_TIMEOUT_COUNT_MIN); - when(mDeviceConfigFacade.getAuthFailureHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getAuthFailureCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_AUTH_FAILURE_COUNT_MIN); - when(mDeviceConfigFacade.getShortConnectionNonlocalHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getShortConnectionNonlocalCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_SHORT_CONNECTION_NONLOCAL_COUNT_MIN); - when(mDeviceConfigFacade.getDisconnectionNonlocalHighThrPercent()).thenReturn( - DeviceConfigFacade.DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT); - when(mDeviceConfigFacade.getDisconnectionNonlocalCountMin()).thenReturn( - DeviceConfigFacade.DEFAULT_DISCONNECTION_NONLOCAL_COUNT_MIN); - when(mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM); - when(mDeviceConfigFacade.getHealthMonitorRatioThrNumerator()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR); - when(mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT); - when(mDeviceConfigFacade.getHealthMonitorShortConnectionDurationThrMs()).thenReturn( - DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_SHORT_CONNECTION_DURATION_THR_MS); - when(mDeviceConfigFacade.getAbnormalDisconnectionReasonCodeMask()).thenReturn( - DeviceConfigFacade.DEFAULT_ABNORMAL_DISCONNECTION_REASON_CODE_MASK); - when(mDeviceConfigFacade.getHealthMonitorRssiPollValidTimeMs()).thenReturn(3000); - // Disable FW alert time check by default - when(mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()).thenReturn(-1); - when(mDeviceConfigFacade.getBugReportThresholdExtraRatio()).thenReturn(1); - mWifiScoreCard.enableVerboseLogging(true); - } - - /** - * Test generic update - */ - @Test - public void testUpdate() throws Exception { - mWifiInfo.setSSID(TEST_SSID_1); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); - assertTrue(perBssid.id > 0); - assertNotNull(perBssid.getL2Key()); - assertTrue("L2Key length should be more than 16.", perBssid.getL2Key().length() > 16); - - mWifiInfo.setBSSID(TEST_BSSID_2.toString()); - - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - - assertEquals(perBssid, mWifiScoreCard.fetchByBssid(TEST_BSSID_1)); - assertNotEquals(perBssid.id, mWifiScoreCard.fetchByBssid(TEST_BSSID_2).id); - assertNotEquals(perBssid.getL2Key(), mWifiScoreCard.fetchByBssid(TEST_BSSID_2).getL2Key()); - } - - /** - * Test the get, increment, and removal of Bssid blocklist streak counts. - */ - @Test - public void testBssidBlocklistStreakOperations() { - mWifiInfo.setSSID(TEST_SSID_1); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - - String ssid = mWifiInfo.getSSID(); - String bssid = mWifiInfo.getBSSID(); - assertEquals(0, mWifiScoreCard.getBssidBlocklistStreak( - ssid, bssid, TEST_BSSID_FAILURE_REASON)); - for (int i = 1; i < 3; i++) { - assertEquals(i, mWifiScoreCard.incrementBssidBlocklistStreak( - ssid, bssid, TEST_BSSID_FAILURE_REASON)); - assertEquals(i, mWifiScoreCard.getBssidBlocklistStreak( - ssid, bssid, TEST_BSSID_FAILURE_REASON)); - } - mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, TEST_BSSID_FAILURE_REASON); - assertEquals(0, mWifiScoreCard.getBssidBlocklistStreak( - ssid, bssid, TEST_BSSID_FAILURE_REASON)); - } - - /** - * Test clearing the blocklist streak for all APs belonging to a SSID. - */ - @Test - public void testClearBssidBlocklistStreakForSsid() { - // Increment and verify the blocklist streak for SSID_1, BSSID_1 - mWifiInfo.setSSID(TEST_SSID_1); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - for (int i = 1; i < 3; i++) { - assertEquals(i, mWifiScoreCard.incrementBssidBlocklistStreak( - mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); - assertEquals(i, mWifiScoreCard.getBssidBlocklistStreak( - mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); - } - - // Increment and verify the blocklist streak for SSID_2, BSSID_2 - mWifiInfo.setSSID(TEST_SSID_2); - mWifiInfo.setBSSID(TEST_BSSID_2.toString()); - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - for (int i = 1; i < 3; i++) { - assertEquals(i, mWifiScoreCard.incrementBssidBlocklistStreak( - mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); - assertEquals(i, mWifiScoreCard.getBssidBlocklistStreak( - mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); - } - - // Clear the blocklist streak for SSID_2 - mWifiScoreCard.resetBssidBlocklistStreakForSsid(mWifiInfo.getSSID()); - // Verify that the blocklist streak for SSID_2 is cleared. - assertEquals(0, mWifiScoreCard.getBssidBlocklistStreak( - mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); - - // verify that the blocklist streak for SSID_1 is not cleared. - mWifiInfo.setSSID(TEST_SSID_1); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - assertEquals(2, mWifiScoreCard.getBssidBlocklistStreak( - mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); - } - - /** - * Test the update and retrieval of the last connection time to a BSSID. - */ - @Test - public void testSetBssidConnectionTimestampMs() { - mWifiInfo.setSSID(TEST_SSID_1); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - - String ssid = mWifiInfo.getSSID(); - String bssid = mWifiInfo.getBSSID(); - assertEquals(0L, mWifiScoreCard.getBssidConnectionTimestampMs(ssid, bssid)); - assertEquals(0L, mWifiScoreCard.setBssidConnectionTimestampMs(ssid, bssid, 100L)); - assertEquals(100L, mWifiScoreCard.getBssidConnectionTimestampMs(ssid, bssid)); - } - - /** - * Test identifiers. - */ - @Test - public void testIdentifiers() throws Exception { - mWifiInfo.setSSID(TEST_SSID_1); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - Pair<String, String> p1 = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); - assertNotNull(p1.first); - assertNotNull(p1.second); - mWifiInfo.setBSSID(TEST_BSSID_2.toString()); - Pair<String, String> p2 = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); - assertNotEquals(p1.first, p2.first); - assertEquals(p1.second, p2.second); - mWifiInfo.setBSSID(null); - Pair<String, String> p3 = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); - assertNull(p3.first); - assertNull(p3.second); - mWifiInfo.setBSSID("02:00:00:00:00:00"); - Pair<String, String> p4 = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); - assertNull(p4.first); - assertNull(p4.second); - } - - /** - * Test rssi poll updates - */ - @Test - public void testRssiPollUpdates() throws Exception { - // Start out on one frequency - mWifiInfo.setFrequency(5805); - mWifiInfo.setRssi(-77); - mWifiInfo.setLinkSpeed(12); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - // Switch channels for a bit - mWifiInfo.setFrequency(5290); - mWifiInfo.setRssi(-66); - mWifiInfo.setLinkSpeed(666); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - // Back to the first channel - mWifiInfo.setFrequency(5805); - mWifiInfo.setRssi(-55); - mWifiInfo.setLinkSpeed(86); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - - double expectSum = -77 + -55; - double expectSumSq = 77 * 77 + 55 * 55; - - // Now verify - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); - // Looking up the same thing twice should yield the same object. - assertTrue(perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) - == perBssid.lookupSignal(Event.SIGNAL_POLL, 5805)); - // Check the rssi statistics for the first channel - assertEquals(2, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805).rssi.count); - assertEquals(expectSum, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) - .rssi.sum, TOL); - assertEquals(expectSumSq, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) - .rssi.sumOfSquares, TOL); - assertEquals(-77.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) - .rssi.minValue, TOL); - assertEquals(-55.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) - .rssi.maxValue, TOL); - // Check the rssi statistics for the second channel - assertEquals(1, perBssid.lookupSignal(Event.SIGNAL_POLL, 5290).rssi.count); - // Check that the linkspeed was updated - assertEquals(666.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5290).linkspeed.sum, TOL); - } - - /** - * Statistics on time-to-connect, connection duration - */ - @Test - public void testDurationStatistics() throws Exception { - // Start out disconnected; start connecting - mWifiInfo.setBSSID(android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS); - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - // First poll has a bad RSSI - millisecondsPass(111); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - mWifiInfo.setFrequency(5805); - mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); - // A bit later, connection is complete (up through DHCP) - millisecondsPass(222); - mWifiInfo.setRssi(-55); - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - millisecondsPass(666); - // Rssi polls for 99 seconds - for (int i = 0; i < 99; i += 3) { - mWifiScoreCard.noteSignalPoll(mWifiInfo); - secondsPass(3); - } - // Make sure our simulated time adds up - assertEquals(mMilliSecondsSinceBoot, 99999); - // Validation success, rather late! - mWifiScoreCard.noteValidationSuccess(mWifiInfo); - // A long while later, wifi is toggled off - secondsPass(9900); - // Second validation success should not matter. - mWifiScoreCard.noteValidationSuccess(mWifiInfo); - mWifiInfo.setRssi(-88); - mWifiScoreCard.noteIpReachabilityLost(mWifiInfo); - mWifiScoreCard.noteWifiDisabled(mWifiInfo); - - // Now verify - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); - assertEquals(1, perBssid.lookupSignal(Event.IP_CONFIGURATION_SUCCESS, 5805) - .elapsedMs.count); - assertEquals(333.0, perBssid.lookupSignal(Event.IP_CONFIGURATION_SUCCESS, 5805) - .elapsedMs.sum, TOL); - assertEquals(9999999.0, perBssid.lookupSignal(Event.WIFI_DISABLED, 5805) - .elapsedMs.maxValue, TOL); - assertEquals(999.0, perBssid.lookupSignal(Event.FIRST_POLL_AFTER_CONNECTION, 5805) - .elapsedMs.minValue, TOL); - assertEquals(99999.0, perBssid.lookupSignal(Event.VALIDATION_SUCCESS, 5805) - .elapsedMs.sum, TOL); - assertEquals(-88.0, perBssid.lookupSignal(Event.IP_REACHABILITY_LOST, 5805) - .rssi.sum, TOL); - assertNull(perBssid.lookupSignal(Event.SIGNAL_POLL, 5805).elapsedMs); - } - - /** - * Firmware roam - */ - @Test - public void testFirmwareRoam() throws Exception { - // Start out disconnected; start connecting - mWifiInfo.setBSSID(android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS); - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - - // First poll has a bad RSSI - millisecondsPass(111); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - mWifiInfo.setSupplicantState(SupplicantState.COMPLETED); - mWifiInfo.setFrequency(5805); - mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); - - // A bit later, connection is complete (up through DHCP) - millisecondsPass(222); - mWifiInfo.setRssi(-55); - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - - millisecondsPass(666); - mWifiInfo.setRssi(-77); - // Rssi polls for 99 seconds - for (int i = 0; i < 99; i += 9) { - mWifiScoreCard.noteSignalPoll(mWifiInfo); - secondsPass(9); - } - - // Make sure our simulated time adds up - assertEquals(mMilliSecondsSinceBoot, 99999); - // Validation success, rather late! - mWifiScoreCard.noteValidationSuccess(mWifiInfo); - // Simulate a successful roam - mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, SupplicantState.COMPLETED); - millisecondsPass(1); - mWifiInfo.setBSSID(TEST_BSSID_2.toString()); - mWifiInfo.setRssi(-66); - mWifiInfo.setFrequency(2412); - mWifiInfo.setSupplicantState(SupplicantState.COMPLETED); - mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); - secondsPass(9); - assertEquals(mMilliSecondsSinceBoot, 109000); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - - // Simulate an unsuccessful roam - secondsPass(1); - mWifiInfo.setRssi(-74); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - secondsPass(1); - mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, SupplicantState.COMPLETED); - mWifiInfo.setBSSID(TEST_BSSID_1.toString()); - mWifiInfo.setFrequency(5805); - mWifiInfo.setSupplicantState(SupplicantState.COMPLETED); - mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); - secondsPass(3); - mWifiScoreCard.noteIpReachabilityLost(mWifiInfo); - - // Now verify - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); - assertEquals(1, perBssid.lookupSignal(Event.IP_CONFIGURATION_SUCCESS, 5805) - .elapsedMs.count); - assertEquals(-77, perBssid.lookupSignal(Event.LAST_POLL_BEFORE_ROAM, 5805) - .rssi.minValue, TOL); - assertEquals(1, perBssid.lookupSignal(Event.ROAM_FAILURE, 5805) - .rssi.count); - - assertEquals(67, perBssid.estimatePercentInternetAvailability()); - - perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_2); - assertEquals(-66.0, perBssid.lookupSignal(Event.ROAM_SUCCESS, 2412) - .rssi.sum, TOL); - assertEquals(50, perBssid.estimatePercentInternetAvailability()); - } - - /** - * Constructs a protobuf form of AccessPoint example. - */ - private byte[] makeSerializedAccessPointExample() { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); - millisecondsPass(10); - // Association completes, a NetworkAgent is created - mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo, TEST_NETWORK_AGENT_ID); - millisecondsPass(101); - mWifiInfo.setRssi(-55); - mWifiInfo.setFrequency(5805); - mWifiInfo.setLinkSpeed(384); - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - perNetwork.addFrequency(mWifiInfo.getFrequency()); - millisecondsPass(888); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - millisecondsPass(1000); - mWifiInfo.setRssi(-44); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - mWifiInfo.setFrequency(2432); - perNetwork.addFrequency(mWifiInfo.getFrequency()); - for (int round = 0; round < 4; round++) { - for (int i = 0; i < HISTOGRAM_COUNT.length; i++) { - if (HISTOGRAM_COUNT[i] > round) { - mWifiInfo.setRssi(HISTOGRAM_RSSI[i]); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - } - } - } - mWifiScoreCard.resetConnectionState(); - - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); - perBssid.lookupSignal(Event.SIGNAL_POLL, 2412).rssi.historicalMean = -42.0; - perBssid.lookupSignal(Event.SIGNAL_POLL, 2412).rssi.historicalVariance = 4.0; - checkSerializationBssidExample("before serialization", perBssid); - // Now convert to protobuf form - byte[] serialized = perBssid.toAccessPoint().toByteArray(); - return serialized; - } - private static final int[] HISTOGRAM_RSSI = {-80, -79, -78}; - private static final int[] HISTOGRAM_COUNT = {3, 1, 4}; - - private void checkHistogramExample(String diag, IntHistogram rssiHistogram) { - int i = 0; - for (IntHistogram.Bucket bucket : rssiHistogram) { - if (bucket.count != 0) { - assertTrue(diag, i < HISTOGRAM_COUNT.length); - assertEquals(diag, HISTOGRAM_RSSI[i], bucket.start); - assertEquals(diag, HISTOGRAM_COUNT[i], bucket.count); - i++; - } - } - assertEquals(diag, HISTOGRAM_COUNT.length, i); - } - - /** - * Checks that the fields of the bssid serialization example are as expected - */ - private void checkSerializationBssidExample(String diag, WifiScoreCard.PerBssid perBssid) { - assertEquals(diag, 2, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805).rssi.count); - assertEquals(diag, -55.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) - .rssi.minValue, TOL); - assertEquals(diag, -44.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) - .rssi.maxValue, TOL); - assertEquals(diag, 384.0, perBssid.lookupSignal(Event.FIRST_POLL_AFTER_CONNECTION, 5805) - .linkspeed.sum, TOL); - assertEquals(diag, 111.0, perBssid.lookupSignal(Event.IP_CONFIGURATION_SUCCESS, 5805) - .elapsedMs.minValue, TOL); - assertEquals(diag, 0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412).rssi.count); - assertEquals(diag, -42.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412) - .rssi.historicalMean, TOL); - assertEquals(diag, 4.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412) - .rssi.historicalVariance, TOL); - checkHistogramExample(diag, perBssid.lookupSignal(Event.SIGNAL_POLL, - 2432).rssi.intHistogram); - } - - /** - * Checks that the fields of the network are as expected with bssid serialization example - */ - private void checkSerializationBssidExample(String diag, PerNetwork perNetwork) { - NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); - assertEquals(diag, 1, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); - assertEquals(diag, 0, dailyStats.getCount(CNT_CONNECTION_FAILURE)); - assertEquals(diag, 1, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); - assertEquals(diag, 0, dailyStats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); - assertEquals(diag, 0, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL)); - assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); - assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); - assertEquals(diag, 0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); - List<Integer> frequencies = perNetwork.getFrequencies(Long.MAX_VALUE); - assertEquals(diag, 2, frequencies.size()); - List<Integer> expectedFrequencies = new ArrayList<>(Arrays.asList(2432, 5805)); - assertEquals(diag, expectedFrequencies, frequencies); - } - - /** - * AccessPoint serialization - */ - @Test - public void testAccessPointSerialization() throws Exception { - byte[] serialized = makeSerializedAccessPointExample(); - - // Verify by parsing it and checking that we see the expected results - AccessPoint ap = AccessPoint.parseFrom(serialized); - assertEquals(5, ap.getEventStatsCount()); - for (Signal signal: ap.getEventStatsList()) { - if (signal.getFrequency() == 2412) { - assertFalse(signal.getRssi().hasCount()); - assertEquals(-42.0, signal.getRssi().getHistoricalMean(), TOL); - assertEquals(4.0, signal.getRssi().getHistoricalVariance(), TOL); - continue; - } - if (signal.getFrequency() == 2432) { - assertEquals(Event.SIGNAL_POLL, signal.getEvent()); - assertEquals(HISTOGRAM_RSSI[2], signal.getRssi().getBuckets(2).getLow()); - assertEquals(HISTOGRAM_COUNT[2], signal.getRssi().getBuckets(2).getNumber()); - continue; - } - assertEquals(5805, signal.getFrequency()); - switch (signal.getEvent()) { - case IP_CONFIGURATION_SUCCESS: - assertEquals(384.0, signal.getLinkspeed().getMaxValue(), TOL); - assertEquals(111.0, signal.getElapsedMs().getMinValue(), TOL); - break; - case SIGNAL_POLL: - assertEquals(2, signal.getRssi().getCount()); - break; - case FIRST_POLL_AFTER_CONNECTION: - assertEquals(-55.0, signal.getRssi().getSum(), TOL); - break; - default: - fail(signal.getEvent().toString()); - } - } - } - - /** - * Serialization should be reproducible - */ - @Test - public void testReproducableSerialization() throws Exception { - byte[] serialized = makeSerializedAccessPointExample(); - setUp(); - assertArrayEquals(serialized, makeSerializedAccessPointExample()); - } - - /** - * AccessPoint Deserialization - */ - @Test - public void testAccessPointDeserialization() throws Exception { - byte[] serialized = makeSerializedAccessPointExample(); - setUp(); // Get back to the initial state - - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.perBssidFromAccessPoint( - mWifiInfo.getSSID(), - AccessPoint.parseFrom(serialized)); - - // Now verify - String diag = hexStringFromByteArray(serialized); - checkSerializationBssidExample(diag, perBssid); - } - - /** - * Serialization of all internally represented networks - */ - @Test - public void testNetworksSerialization() throws Exception { - makeSerializedAccessPointExample(); - - byte[] serialized = mWifiScoreCard.getNetworkListByteArray(false); - byte[] cleaned = mWifiScoreCard.getNetworkListByteArray(true); - String base64Encoded = mWifiScoreCard.getNetworkListBase64(true); - - setUp(); // Get back to the initial state - String diag = hexStringFromByteArray(serialized); - NetworkList networkList = NetworkList.parseFrom(serialized); - assertEquals(diag, 1, networkList.getNetworksCount()); - Network network = networkList.getNetworks(0); - assertEquals(diag, 1, network.getAccessPointsCount()); - AccessPoint accessPoint = network.getAccessPoints(0); - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.perBssidFromAccessPoint(network.getSsid(), - accessPoint); - NetworkStats networkStats = network.getNetworkStats(); - PerNetwork perNetwork = mWifiScoreCard.perNetworkFromNetworkStats(network.getSsid(), - networkStats); - - checkSerializationBssidExample(diag, perBssid); - checkSerializationBssidExample(diag, perNetwork); - // Leaving out the bssids should make the cleaned version shorter. - assertTrue(cleaned.length < serialized.length); - // Check the Base64 version - assertTrue(Arrays.equals(cleaned, Base64.decode(base64Encoded, Base64.DEFAULT))); - // Check that the network ids were carried over - assertEquals(TEST_NETWORK_AGENT_ID, network.getNetworkAgentId()); - assertEquals(TEST_NETWORK_CONFIG_ID, network.getNetworkConfigId()); - } - - /** - * Installation of memory store does not crash - */ - @Test - public void testInstallationOfMemoryStoreDoesNotCrash() throws Exception { - mWifiScoreCard.installMemoryStore(mMemoryStore); - makeSerializedAccessPointExample(); - mWifiScoreCard.installMemoryStore(mMemoryStore); - } - - /** - * Merge of lazy reads - */ - @Test - public void testLazyReads() { - // Install our own MemoryStore object, which records read requests - mWifiScoreCard.installMemoryStore(new WifiScoreCard.MemoryStore() { - @Override - public void read(String key, String name, WifiScoreCard.BlobListener listener) { - mKeys.add(key); - mBlobListeners.add(listener); - } - @Override - public void write(String key, String name, byte[] value) { - // ignore for now - } - @Override - public void setCluster(String key, String cluster) { - // ignore for now - } - @Override - public void removeCluster(String cluster) { - // ignore for now - } - }); - - // Now make some changes - byte[] serialized = makeSerializedAccessPointExample(); - // 1 for perfBssid and 1 for perNetwork - assertEquals(2, mKeys.size()); - - // Simulate the asynchronous completion of the read request - millisecondsPass(33); - mBlobListeners.get(0).onBlobRetrieved(serialized); - - // Check that the historical mean and variance were updated accordingly - WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); - assertEquals(-42.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412) - .rssi.historicalMean, TOL); - assertEquals(4.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412) - .rssi.historicalVariance, TOL); - } - - /** - * Write test - */ - @Test - public void testWrites() throws Exception { - // Install our own MemoryStore object, which records write requests - mWifiScoreCard.installMemoryStore(new WifiScoreCard.MemoryStore() { - @Override - public void read(String key, String name, WifiScoreCard.BlobListener listener) { - // Just record these, never answer - mBlobListeners.add(listener); - } - @Override - public void write(String key, String name, byte[] value) { - mKeys.add(key); - mBlobs.add(value); - } - @Override - public void setCluster(String key, String cluster) { - } - @Override - public void removeCluster(String cluster) { - // ignore for now - } - }); - - // Make some changes - byte[] serialized = makeSerializedAccessPointExample(); - // 1 for perfBssid and 1 for perNetwork - assertEquals(2, mBlobListeners.size()); - - secondsPass(33); - - // There should be one changed bssid now. We may have already done some writes. - mWifiScoreCard.doWrites(); - assertTrue(mKeys.size() > 0); - - // The written blob should not contain the BSSID, though the full serialized version does - String writtenHex = hexStringFromByteArray(mBlobs.get(mKeys.size() - 1)); - String fullHex = hexStringFromByteArray(serialized); - String bssidHex = hexStringFromByteArray(TEST_BSSID_1.toByteArray()); - assertFalse(writtenHex, writtenHex.contains(bssidHex)); - assertTrue(fullHex, fullHex.contains(bssidHex)); - - // A second write request should not find anything to write - final int beforeSize = mKeys.size(); - assertEquals(0, mWifiScoreCard.doWrites()); - assertEquals(beforeSize, mKeys.size()); - } - - /** - * Calling doWrites before installing a MemoryStore should do nothing. - */ - @Test - public void testNoWritesUntilReady() throws Exception { - makeSerializedAccessPointExample(); - assertEquals(0, mWifiScoreCard.doWrites()); - } - - /** - * Installing a MemoryStore after startup should issue reads. - */ - @Test - public void testReadAfterDelayedMemoryStoreInstallation() throws Exception { - makeSerializedAccessPointExample(); - mWifiScoreCard.installMemoryStore(mMemoryStore); - // 1 for requestReadBssid - verify(mMemoryStore, times(1)).read(any(), any(), any()); - } - - /** - * Calling clear should forget the state. - */ - @Test - public void testClearReallyDoesClearTheState() throws Exception { - byte[] serialized = makeSerializedAccessPointExample(); - assertNotEquals(0, serialized.length); - mWifiScoreCard.clear(); - byte[] leftovers = mWifiScoreCard.getNetworkListByteArray(false); - assertEquals(0, leftovers.length); - } - - /** - * Test that older items are evicted from memory. - */ - @Test - public void testOlderItemsShouldBeEvicted() throws Exception { - mWifiInfo.setRssi(-55); - mWifiInfo.setFrequency(5805); - mWifiInfo.setLinkSpeed(384); - mWifiScoreCard.installMemoryStore(mMemoryStore); - for (int i = 0; i < 256; i++) { - MacAddress bssid = MacAddress.fromBytes(new byte[]{2, 2, 2, 2, 2, (byte) i}); - mWifiInfo.setBSSID(bssid.toString()); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - } - // 256 for requestReadBssid() and 1 for requestReadNetwork() - verify(mMemoryStore, times(256 + 1)).read(any(), any(), any()); - verify(mMemoryStore, atLeastOnce()).write(any(), any(), any()); // Assumes target size < 256 - reset(mMemoryStore); - - for (int i = 256 - 3; i < 256; i++) { - MacAddress bssid = MacAddress.fromBytes(new byte[]{2, 2, 2, 2, 2, (byte) i}); - mWifiInfo.setBSSID(bssid.toString()); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - } - verify(mMemoryStore, never()).read(any(), any(), any()); // Assumes target size >= 3 - - for (int i = 0; i < 3; i++) { - MacAddress bssid = MacAddress.fromBytes(new byte[]{2, 2, 2, 2, 2, (byte) i}); - mWifiInfo.setBSSID(bssid.toString()); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - } - verify(mMemoryStore, times(3)).read(any(), any(), any()); // Assumes target size < 253 - } - - private void makeAssocTimeOutExample() { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(1000); - mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT); - } - - /** - * Check network stats after association timeout. - */ - @Test - public void testNetworkAssocTimeOut() throws Exception { - makeAssocTimeOutExample(); - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); - - assertEquals(1, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); - assertEquals(1, dailyStats.getCount(CNT_CONNECTION_FAILURE)); - assertEquals(0, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); - assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); - assertEquals(1, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); - assertEquals(0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); - assertEquals(1, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); - } - - private void makeAuthFailureAndWrongPassword() { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(500); - mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE); - millisecondsPass(1000); - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(1000); - mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_WRONG_PASSWORD); - } - - private void makeAuthFailureExample() { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(500); - mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE); - } - - /** - * Check network stats after authentication failure and wrong password. - */ - @Test - public void testNetworkAuthenticationFailureWrongPassword() throws Exception { - makeAuthFailureAndWrongPassword(); - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); - - assertEquals(2, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); - assertEquals(1, dailyStats.getCount(CNT_CONNECTION_FAILURE)); - assertEquals(0, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); - assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); - assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); - assertEquals(1, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); - assertEquals(1, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); - - makeNormalConnectionExample(); - assertEquals(0, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); - } - - /** - * Check network stats when a new connection attempt for SSID2 is issued - * before disconnection of SSID1 - */ - @Test - public void testNetworkSwitchWithOverlapping() throws Exception { - // Connect to SSID_1 - String ssid1 = mWifiInfo.getSSID(); - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, ssid1); - millisecondsPass(5000); - - // Attempt to connect to SSID_2 - mWifiInfo.setSSID(TEST_SSID_2); - mWifiInfo.setBSSID(TEST_BSSID_2.toString()); - String ssid2 = mWifiInfo.getSSID(); - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, ssid2); - - // Disconnect from SSID_1 - millisecondsPass(100); - int disconnectionReason = 4; - mWifiScoreCard.noteNonlocalDisconnect(disconnectionReason); - millisecondsPass(100); - mWifiScoreCard.resetConnectionState(); - - // SSID_2 is connected and then disconnected - millisecondsPass(2000); - mWifiScoreCard.noteIpConfiguration(mWifiInfo); - millisecondsPass(2000); - mWifiScoreCard.resetConnectionState(); - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(ssid1); - assertEquals(5, perNetwork.getRecentStats().getCount(CNT_CONNECTION_DURATION_SEC)); - - perNetwork = mWifiScoreCard.fetchByNetwork(ssid2); - assertEquals(4, perNetwork.getRecentStats().getCount(CNT_CONNECTION_DURATION_SEC)); - } - - /** - * Check network stats after 2 connection failures at low RSSI. - */ - @Test - public void testNetworkConnectionFailureLowRssi() throws Exception { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -83, mWifiInfo.getSSID()); - millisecondsPass(1000); - mWifiScoreCard.noteConnectionFailure(mWifiInfo, -83, mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION); - millisecondsPass(3000); - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -83, mWifiInfo.getSSID()); - millisecondsPass(1000); - mWifiScoreCard.noteConnectionFailure(mWifiInfo, -83, mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION); - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); - checkShortConnectionExample(dailyStats, 0); - } - - private void makeShortConnectionExample(boolean addFwAlert) { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(5000); - mWifiInfo.setTxLinkSpeedMbps(100); - mWifiInfo.setSuccessfulTxPacketsPerSecond(20.0); - mWifiInfo.setRetriedTxPacketsRate(1.0); - mWifiInfo.setRssi(-80); - millisecondsPass(1000); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - millisecondsPass(2000); - int disconnectionReason = 34; - mWifiScoreCard.noteNonlocalDisconnect(disconnectionReason); - if (addFwAlert) { - mWifiScoreCard.noteFirmwareAlert(6); - } - millisecondsPass(1000); - mWifiScoreCard.resetConnectionState(); - } - - private void checkShortConnectionExample(NetworkConnectionStats stats, int scale) { - assertEquals(1 * scale, stats.getCount(CNT_CONNECTION_ATTEMPT)); - assertEquals(0, stats.getCount(CNT_CONNECTION_FAILURE)); - assertEquals(9 * scale, stats.getCount(CNT_CONNECTION_DURATION_SEC)); - assertEquals(0, stats.getCount(CNT_ASSOCIATION_REJECTION)); - assertEquals(0, stats.getCount(CNT_ASSOCIATION_TIMEOUT)); - assertEquals(0, stats.getCount(CNT_AUTHENTICATION_FAILURE)); - assertEquals(1 * scale, stats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); - assertEquals(1 * scale, stats.getCount(CNT_DISCONNECTION_NONLOCAL)); - assertEquals(0, stats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); - } - - private void makeShortConnectionOldRssiPollingExample() { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(2000); - mWifiInfo.setRssi(-55); - millisecondsPass(1000); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - millisecondsPass(29000); - int disconnectionReason = 3; - mWifiScoreCard.noteNonlocalDisconnect(disconnectionReason); - millisecondsPass(1000); - mWifiScoreCard.resetConnectionState(); - } - - private void checkShortConnectionOldPollingExample(NetworkConnectionStats stats) { - assertEquals(1, stats.getCount(CNT_CONNECTION_ATTEMPT)); - assertEquals(0, stats.getCount(CNT_CONNECTION_FAILURE)); - assertEquals(33, stats.getCount(CNT_CONNECTION_DURATION_SEC)); - assertEquals(0, stats.getCount(CNT_ASSOCIATION_REJECTION)); - assertEquals(0, stats.getCount(CNT_ASSOCIATION_TIMEOUT)); - assertEquals(0, stats.getCount(CNT_AUTHENTICATION_FAILURE)); - assertEquals(0, stats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); - assertEquals(0, stats.getCount(CNT_DISCONNECTION_NONLOCAL)); - } - - /** - * Check network stats after RSSI poll and disconnection, pass FW alert check - */ - @Test - public void testNetworkRssiPollShortNonlocalDisconnectionPassFwAlertCheck() throws Exception { - when(mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()).thenReturn(2000); - // 1st connection session - makeShortConnectionExample(/*addFwAlert*/true); - // 2nd connection session - makeNormalConnectionExample(); - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); - assertEquals(2, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); - assertEquals(0, dailyStats.getCount(CNT_CONNECTION_FAILURE)); - assertEquals(20, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); - assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); - assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); - assertEquals(0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); - assertEquals(1, dailyStats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); - assertEquals(1, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL)); - } - - /** - * Check network stats after RSSI poll and disconnection, fail FW alert check - */ - @Test - public void testNetworkRssiPollShortNonlocalDisconnectionFailFwAlertCheck() throws Exception { - when(mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()).thenReturn(2000); - // 1st connection session - makeShortConnectionExample(/*addFwAlert*/false); - // 2nd connection session - makeNormalConnectionExample(); - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); - assertEquals(0, dailyStats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); - assertEquals(0, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL)); - } - - /** - * Check network stats after short connection with an old RSSI polling - */ - @Test - public void testShortNonlocalDisconnectionOldRssiPolling() throws Exception { - makeShortConnectionOldRssiPollingExample(); - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - checkShortConnectionOldPollingExample(perNetwork.getRecentStats()); - } - - private void makeNormalConnectionExample() { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(1000); - mWifiInfo.setRssi(-55); - millisecondsPass(7000); - mWifiScoreCard.noteSignalPoll(mWifiInfo); - millisecondsPass(3000); - mWifiScoreCard.resetConnectionState(); - } - - /** - * Constructs a protobuf form of Network example. - */ - private byte[] makeSerializedNetworkExample() { - makeNormalConnectionExample(); - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - checkSerializationNetworkExample("before serialization", perNetwork); - // Now convert to protobuf form - byte[] serialized = perNetwork.toNetworkStats().toByteArray(); - return serialized; - } - - /** - * Checks that the fields of the network serialization example are as expected. - */ - private void checkSerializationNetworkExample(String diag, PerNetwork perNetwork) { - NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); - assertEquals(diag, 1, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); - assertEquals(diag, 0, dailyStats.getCount(CNT_CONNECTION_FAILURE)); - assertEquals(diag, 11, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); - assertEquals(diag, 0, dailyStats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); - assertEquals(diag, 0, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL)); - assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); - assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); - assertEquals(diag, 0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); - } - - /** - * Test NetworkStats serialization. - */ - @Test - public void testNetworkStatsSerialization() throws Exception { - byte[] serialized = makeSerializedNetworkExample(); - - // Verify by parsing it and checking that we see the expected results - NetworkStats ns = NetworkStats.parseFrom(serialized); - ConnectionStats dailyStats = ns.getRecentStats(); - assertEquals(1, dailyStats.getNumConnectionAttempt()); - assertEquals(0, dailyStats.getNumConnectionFailure()); - assertEquals(11, dailyStats.getConnectionDurationSec()); - assertEquals(0, dailyStats.getNumDisconnectionNonlocal()); - assertEquals(0, dailyStats.getNumShortConnectionNonlocal()); - assertEquals(0, dailyStats.getNumAssociationRejection()); - assertEquals(0, dailyStats.getNumAssociationTimeout()); - assertEquals(0, dailyStats.getNumAuthenticationFailure()); - } - - /** - * Test NetworkStats Deserialization. - */ - @Test - public void testNetworkStatsDeserialization() throws Exception { - byte[] serialized = makeSerializedNetworkExample(); - setUp(); // Get back to the initial state - - PerNetwork perNetwork = mWifiScoreCard.perNetworkFromNetworkStats(mWifiInfo.getSSID(), - NetworkStats.parseFrom(serialized)); - - // Now verify - String diag = hexStringFromByteArray(serialized); - checkSerializationNetworkExample(diag, perNetwork); - } - - /** - * Check network stats after network connection and then removeNetWork(). - */ - @Test - public void testRemoveNetwork() throws Exception { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - millisecondsPass(1000); - mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), - BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION); - mWifiScoreCard.removeNetwork(mWifiInfo.getSSID()); - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - assertNull(perNetwork); - } - - @Test - public void testUpdateAfterDailyDetection() throws Exception { - for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { - makeShortConnectionExample(/*addFwAlert*/false); - } - - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - perNetwork.updateAfterDailyDetection(); - - checkShortConnectionExample(perNetwork.getRecentStats(), 0); - checkShortConnectionExample(perNetwork.getStatsCurrBuild(), - DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT); - checkShortConnectionExample(perNetwork.getStatsPrevBuild(), 0); - } - - @Test - public void testUpdateAfterSwBuildChange() throws Exception { - for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { - makeShortConnectionExample(/*addFwAlert*/false); - } - PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); - perNetwork.updateAfterDailyDetection(); - perNetwork.updateAfterSwBuildChange(); - - checkShortConnectionExample(perNetwork.getRecentStats(), 0); - checkShortConnectionExample(perNetwork.getStatsCurrBuild(), 0); - checkShortConnectionExample(perNetwork.getStatsPrevBuild(), - DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT); - } - - private void makeRecentStatsWithGoodConnection() { - for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { - makeNormalConnectionExample(); - } - } - - private void makeRecentStatsWithShortConnection() { - for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { - makeShortConnectionExample(/*addFwAlert*/false); - } - } - - private void makeRecentStatsWithAssocTimeOut() { - for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { - makeAssocTimeOutExample(); - } - } - - private void makeRecentStatsWithAuthFailure() { - for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { - makeAuthFailureExample(); - } - } - - private void checkStatsDeltaExample(FailureStats stats, int scale) { - assertEquals(0, stats.getCount(REASON_ASSOC_REJECTION)); - assertEquals(1 * scale, stats.getCount(REASON_ASSOC_TIMEOUT)); - assertEquals(1 * scale, stats.getCount(REASON_AUTH_FAILURE)); - assertEquals(1 * scale, stats.getCount(REASON_CONNECTION_FAILURE)); - assertEquals(1 * scale, stats.getCount(REASON_DISCONNECTION_NONLOCAL)); - assertEquals(1 * scale, stats.getCount(REASON_SHORT_CONNECTION_NONLOCAL)); - } - - /** - * Check if daily detection is skipped with insufficient daily stats. - */ - @Test - public void testDailyDetectionWithInsufficientRecentStats() throws Exception { - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); - makeShortConnectionExample(/*addFwAlert*/false); - - FailureStats statsDec = new FailureStats(); - FailureStats statsInc = new FailureStats(); - FailureStats statsHigh = new FailureStats(); - int detectionFlag = perNetwork.dailyDetection(statsDec, statsInc, statsHigh); - assertEquals(WifiScoreCard.INSUFFICIENT_RECENT_STATS, detectionFlag); - checkStatsDeltaExample(statsDec, 0); - checkStatsDeltaExample(statsInc, 0); - checkStatsDeltaExample(statsHigh, 0); - perNetwork.updateAfterDailyDetection(); - checkShortConnectionExample(perNetwork.getRecentStats(), 1); - checkShortConnectionExample(perNetwork.getStatsPrevBuild(), 0); - assertEquals(WifiHealthMonitor.REASON_NO_FAILURE, - mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); - } - - /** - * Run a few days with mostly good connection and some failures, - * followed by a SW build change which results - * in performance regression. Check if the regression is detected properly. - */ - @Test - public void testRegressionAfterSwBuildChange() throws Exception { - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); - int numGoodConnectionDays = 4; - for (int i = 0; i < numGoodConnectionDays; i++) { - makeRecentStatsWithGoodConnection(); - perNetwork.updateAfterDailyDetection(); - } - // Extra day with mixed failures - makeRecentStatsWithShortConnection(); - makeRecentStatsWithAssocTimeOut(); - makeRecentStatsWithAuthFailure(); - perNetwork.updateAfterDailyDetection(); - - perNetwork.updateAfterSwBuildChange(); - // Add >2x failures after the SW build change - int numBadConnectionDays = 4; - for (int i = 0; i < numBadConnectionDays; i++) { - makeRecentStatsWithAssocTimeOut(); - makeRecentStatsWithAuthFailure(); - makeRecentStatsWithShortConnection(); - } - - assertEquals(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL, - mWifiScoreCard.detectAbnormalDisconnection()); - FailureStats statsDec = new FailureStats(); - FailureStats statsInc = new FailureStats(); - FailureStats statsHigh = new FailureStats(); - int detectionFlag = perNetwork.dailyDetection(statsDec, statsInc, statsHigh); - assertEquals(WifiScoreCard.SUFFICIENT_RECENT_PREV_STATS, detectionFlag); - checkStatsDeltaExample(statsDec, 0); - checkStatsDeltaExample(statsInc, 1); - checkStatsDeltaExample(statsHigh, 0); - } - - /** - * Check regression detection is missed due to low failure count - */ - @Test - public void testMissRegressionDetectionDuetoLowFailureCnt() throws Exception { - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); - int numGoodConnectionDays = 1; - for (int i = 0; i < numGoodConnectionDays; i++) { - makeRecentStatsWithGoodConnection(); - perNetwork.updateAfterDailyDetection(); - } - - perNetwork.updateAfterSwBuildChange(); - makeRecentStatsWithGoodConnection(); - // Add a small number of failures for each failure type after the SW build change - for (int i = 0; i < mDeviceConfigFacade.getAuthFailureCountMin() - 1; i++) { - makeShortConnectionExample(/*addFwAlert*/false); - makeAssocTimeOutExample(); - makeAuthFailureExample(); - } - - FailureStats statsDec = new FailureStats(); - FailureStats statsInc = new FailureStats(); - FailureStats statsHigh = new FailureStats(); - int detectionFlag = perNetwork.dailyDetection(statsDec, statsInc, statsHigh); - assertEquals(WifiScoreCard.SUFFICIENT_RECENT_PREV_STATS, detectionFlag); - checkStatsDeltaExample(statsDec, 0); - checkStatsDeltaExample(statsInc, 0); - checkStatsDeltaExample(statsHigh, 0); - assertEquals(WifiHealthMonitor.REASON_NO_FAILURE, - mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); - } - - /** - * Run a few days with bad connections, followed by a SW build change which results - * in performance improvement. Check if the improvement is detected properly. - */ - @Test - public void testImprovementAfterSwBuildChange() throws Exception { - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); - for (int i = 0; i < 2; i++) { - makeRecentStatsWithShortConnection(); - makeRecentStatsWithAssocTimeOut(); - makeRecentStatsWithAuthFailure(); - perNetwork.updateAfterDailyDetection(); - } - - perNetwork.updateAfterSwBuildChange(); - // Add <50% failures after the SW build change - int numGoodConnectionDays = 4; - for (int i = 0; i < numGoodConnectionDays; i++) { - makeRecentStatsWithGoodConnection(); - } - makeRecentStatsWithAssocTimeOut(); - makeRecentStatsWithAuthFailure(); - makeRecentStatsWithShortConnection(); - - assertEquals(WifiHealthMonitor.REASON_NO_FAILURE, - mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); - FailureStats statsDec = new FailureStats(); - FailureStats statsInc = new FailureStats(); - FailureStats statsHigh = new FailureStats(); - perNetwork.dailyDetection(statsDec, statsInc, statsHigh); - checkStatsDeltaExample(statsDec, 1); - checkStatsDeltaExample(statsInc, 0); - checkStatsDeltaExample(statsHigh, 0); - } - - @Test - public void testPoorConnectionWithoutHistory() throws Exception { - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); - - makeRecentStatsWithShortConnection(); // Day 1 - makeRecentStatsWithAuthFailure(); - makeRecentStatsWithAssocTimeOut(); - - assertEquals(WifiHealthMonitor.REASON_ASSOC_TIMEOUT, - mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); - FailureStats statsDec = new FailureStats(); - FailureStats statsInc = new FailureStats(); - FailureStats statsHigh = new FailureStats(); - int detectionFlag = perNetwork.dailyDetection(statsDec, statsInc, statsHigh); - assertEquals(WifiScoreCard.SUFFICIENT_RECENT_STATS_ONLY, detectionFlag); - checkStatsDeltaExample(statsDec, 0); - checkStatsDeltaExample(statsInc, 0); - checkStatsDeltaExample(statsHigh, 1); - } - - @Test - public void testHighAuthFailureRate() throws Exception { - makeRecentStatsWithGoodConnection(); - makeRecentStatsWithAuthFailure(); - assertEquals(WifiHealthMonitor.REASON_AUTH_FAILURE, - mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); - } - - @Test - public void testAddGetFrequencies() { - mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); - PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); - millisecondsPass(100); - perNetwork.addFrequency(5805); - millisecondsPass(1000); - perNetwork.addFrequency(2432); - assertEquals(2, perNetwork.getFrequencies(Long.MAX_VALUE).size()); - assertEquals(2432, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(0)); - assertEquals(5805, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(1)); - // Check over aged channel will not return. - assertEquals(1, perNetwork.getFrequencies(900L).size()); - assertEquals(2432, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(0)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java deleted file mode 100644 index b85f223b7..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java +++ /dev/null @@ -1,1081 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.AdditionalAnswers.answerVoid; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.atMost; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.net.ConnectivityManager; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.wifi.IScoreUpdateObserver; -import android.net.wifi.IWifiConnectedNetworkScorer; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.RemoteException; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.PrintWriter; - -/** - * Unit tests for {@link com.android.server.wifi.WifiScoreReport}. - */ -@SmallTest -public class WifiScoreReportTest extends WifiBaseTest { - class FakeClock extends Clock { - long mWallClockMillis = 1500000000000L; - int mStepMillis = 1001; - - @Override - public long getWallClockMillis() { - mWallClockMillis += mStepMillis; - return mWallClockMillis; - } - } - - private static final int TEST_NETWORK_ID = 860370; - private static final int TEST_SESSION_ID = 8603703; // last digit is a check digit - - FakeClock mClock; - WifiConfiguration mWifiConfiguration; - WifiScoreReport mWifiScoreReport; - ScanDetailCache mScanDetailCache; - WifiInfo mWifiInfo; - ScoringParams mScoringParams; - NetworkAgent mNetworkAgent; - WifiThreadRunner mWifiThreadRunner; - @Mock Context mContext; - @Mock Resources mResources; - @Mock WifiMetrics mWifiMetrics; - @Mock PrintWriter mPrintWriter; - @Mock IBinder mAppBinder; - @Mock IWifiConnectedNetworkScorer mWifiConnectedNetworkScorer; - @Mock WifiNative mWifiNative; - @Mock BssidBlocklistMonitor mBssidBlocklistMonitor; - @Mock Network mNetwork; - @Mock DeviceConfigFacade mDeviceConfigFacade; - @Mock Looper mWifiLooper; - @Mock FrameworkFacade mFrameworkFacade; - private TestLooper mLooper; - - public class WifiConnectedNetworkScorerImpl extends IWifiConnectedNetworkScorer.Stub { - public IScoreUpdateObserver mScoreUpdateObserver; - public int mSessionId = -1; - - @Override - public void onStart(int sessionId) { - mSessionId = sessionId; - } - @Override - public void onStop(int sessionId) { - } - @Override - public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) { - mScoreUpdateObserver = observerImpl; - } - } - - // NetworkAgent is abstract, so a subclass is necessary - private static class TestNetworkAgent extends NetworkAgent { - TestNetworkAgent(Context context) { - super(new TestLooper().getLooper(), context, "TestNetworkAgent", - mock(NetworkInfo.class), new NetworkCapabilities(), new LinkProperties(), 0); - } - @Override protected void unwanted() { } - } - - /** - * Sets up resource values for testing - * - * See frameworks/base/core/res/res/values/config.xml - */ - private void setUpResources(Resources resources) { - when(resources.getInteger( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz)) - .thenReturn(-82); - when(resources.getInteger( - R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz)) - .thenReturn(-77); - when(resources.getInteger( - R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz)) - .thenReturn(-70); - when(resources.getInteger( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz)) - .thenReturn(-57); - when(resources.getInteger( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz)) - .thenReturn(-85); - when(resources.getInteger( - R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz)) - .thenReturn(-80); - when(resources.getInteger( - R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz)) - .thenReturn(-73); - when(resources.getInteger( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz)) - .thenReturn(-60); - when(resources.getInteger( - R.integer.config_wifiFrameworkScoreBadRssiThreshold6ghz)) - .thenReturn(-82); - when(resources.getInteger( - R.integer.config_wifiFrameworkScoreEntryRssiThreshold6ghz)) - .thenReturn(-77); - when(resources.getInteger( - R.integer.config_wifiFrameworkScoreLowRssiThreshold6ghz)) - .thenReturn(-70); - when(resources.getInteger( - R.integer.config_wifiFrameworkScoreGoodRssiThreshold6ghz)) - .thenReturn(-57); - when(resources.getInteger( - R.integer.config_wifiFrameworkMinPacketPerSecondHighTraffic)) - .thenReturn(100); - when(resources.getBoolean( - R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)) - .thenReturn(false); - } - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - setUpResources(mResources); - mWifiInfo = new WifiInfo(); - mWifiInfo.setFrequency(2412); - mLooper = new TestLooper(); - when(mContext.getResources()).thenReturn(mResources); - final ConnectivityManager cm = mock(ConnectivityManager.class); - when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(cm); - when(cm.registerNetworkAgent(any(), any(), any(), any(), anyInt(), any(), anyInt())) - .thenReturn(mNetwork); - when(mNetwork.getNetId()).thenReturn(0); - mNetworkAgent = spy(new TestNetworkAgent(mContext)); - mClock = new FakeClock(); - mScoringParams = new ScoringParams(); - mWifiThreadRunner = new WifiThreadRunner(new Handler(mLooper.getLooper())); - when(mFrameworkFacade.getIntegerSetting(any(Context.class), - eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) - .thenReturn(1); - mWifiScoreReport = new WifiScoreReport(mScoringParams, mClock, mWifiMetrics, mWifiInfo, - mWifiNative, mBssidBlocklistMonitor, mWifiThreadRunner, - mDeviceConfigFacade, mContext, mWifiLooper, mFrameworkFacade); - mWifiScoreReport.setNetworkAgent(mNetworkAgent); - mWifiScoreReport.initialize(); - when(mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()).thenReturn( - DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS); - when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn( - DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS); - when(mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm()).thenReturn( - DeviceConfigFacade.DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM); - } - - /** - * Cleans up after test - */ - @After - public void tearDown() throws Exception { - mResources = null; - mWifiScoreReport = null; - mWifiMetrics = null; - } - - /** - * Test for score reporting - * - * The score should be sent to both the NetworkAgent and the - * WifiMetrics - */ - @Test - public void calculateAndReportScoreSucceeds() throws Exception { - mWifiInfo.setRssi(-77); - mWifiScoreReport.calculateAndReportScore(); - verify(mNetworkAgent).sendNetworkScore(anyInt()); - verify(mWifiMetrics).incrementWifiScoreCount(anyInt()); - } - - /** - * Test for no score report if rssi is invalid - * - * The score should be sent to neither the NetworkAgent nor the - * WifiMetrics - */ - @Test - public void calculateAndReportScoreDoesNotReportWhenRssiIsNotValid() throws Exception { - mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); - mWifiScoreReport.calculateAndReportScore(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - verify(mWifiMetrics, never()).incrementWifiScoreCount(anyInt()); - } - - /** - * Test for operation with null NetworkAgent - * - * Expect to not die, and to calculate the score and report to metrics. - */ - @Test - public void networkAgentMayBeNull() throws Exception { - mWifiInfo.setRssi(-33); - mWifiScoreReport.enableVerboseLogging(true); - mWifiScoreReport.setNetworkAgent(null); - mWifiScoreReport.calculateAndReportScore(); - verify(mWifiMetrics).incrementWifiScoreCount(anyInt()); - } - - /** - * Exercise the rates with low RSSI - * - * The setup has a low (not bad) RSSI, and data movement (txSuccessRate) above - * the threshold. - * - * Expect a score above threshold. - */ - @Test - public void allowLowRssiIfDataIsMoving() throws Exception { - mWifiInfo.setRssi(-80); - mWifiInfo.setLinkSpeed(6); // Mbps - mWifiInfo.setSuccessfulTxPacketsPerSecond(5.1); // proportional to pps - mWifiInfo.setSuccessfulRxPacketsPerSecond(5.1); - for (int i = 0; i < 10; i++) { - mWifiScoreReport.calculateAndReportScore(); - } - int score = mWifiInfo.getScore(); - assertTrue(score > ConnectedScore.WIFI_TRANSITION_SCORE); - } - - /** - * Bad RSSI without data moving should allow handoff - * - * The setup has a bad RSSI, and the txSuccessRate is below threshold; several - * scoring iterations are performed. - * - * Expect the score to drop below the handoff threshold. - */ - @Test - public void giveUpOnBadRssiWhenDataIsNotMoving() throws Exception { - mWifiInfo.setRssi(-100); - mWifiInfo.setLinkSpeed(6); // Mbps - mWifiInfo.setFrequency(5220); - mWifiScoreReport.enableVerboseLogging(true); - mWifiInfo.setSuccessfulTxPacketsPerSecond(0.1); - mWifiInfo.setSuccessfulRxPacketsPerSecond(0.1); - for (int i = 0; i < 10; i++) { - mWifiScoreReport.calculateAndReportScore(); - } - int score = mWifiInfo.getScore(); - assertTrue(score < ConnectedScore.WIFI_TRANSITION_SCORE); - verify(mNetworkAgent, atLeast(1)).sendNetworkScore(score); - } - - /** - * When the score ramps down to the exit theshold, let go. - */ - @Test - public void giveUpOnBadRssiAggressively() throws Exception { - String oops = "giveUpOnBadRssiAggressively"; - mWifiInfo.setFrequency(5220); - for (int rssi = -60; rssi >= -83; rssi -= 1) { - mWifiInfo.setRssi(rssi); - oops += " " + mClock.mWallClockMillis + "," + rssi; - mWifiScoreReport.calculateAndReportScore(); - oops += ":" + mWifiInfo.getScore(); - } - int score = mWifiInfo.getScore(); - verify(mNetworkAgent, atLeast(1)).sendNetworkScore(score); - assertTrue(oops, score < ConnectedScore.WIFI_TRANSITION_SCORE); - } - - /** - * RSSI that falls rapidly but does not cross entry threshold should not cause handoff - * - * Expect the score to not drop below the handoff threshold. - */ - @Test - public void stayOnIfRssiDoesNotGetBelowEntryThreshold() throws Exception { - String oops = "didNotStickLanding"; - int minScore = 100; - mWifiInfo.setLinkSpeed(6); // Mbps - mWifiInfo.setFrequency(5220); - mWifiScoreReport.enableVerboseLogging(true); - mWifiInfo.setSuccessfulTxPacketsPerSecond(0.1); - mWifiInfo.setSuccessfulRxPacketsPerSecond(0.1); - assertTrue(mScoringParams.update("rssi5=-83:-80:-66:-55")); - for (int r = -30; r >= -100; r -= 1) { - int rssi = Math.max(r, -80); - mWifiInfo.setRssi(rssi); - oops += " " + mClock.mWallClockMillis + "," + rssi; - mWifiScoreReport.calculateAndReportScore(); - oops += ":" + mWifiInfo.getScore(); - if (mWifiInfo.getScore() < minScore) minScore = mWifiInfo.getScore(); - } - assertTrue(oops, minScore > ConnectedScore.WIFI_TRANSITION_SCORE); - } - - /** - * Don't breach if the success rates are great - * - * Ramp the RSSI down, but maintain a high packet throughput - * - * Expect score to stay above above threshold. - */ - @Test - public void allowTerribleRssiIfDataIsMovingWell() throws Exception { - mWifiInfo.setSuccessfulTxPacketsPerSecond( - mScoringParams.getYippeeSkippyPacketsPerSecond() + 0.1); - mWifiInfo.setSuccessfulRxPacketsPerSecond( - mScoringParams.getYippeeSkippyPacketsPerSecond() + 0.1); - assertTrue(mWifiInfo.getSuccessfulTxPacketsPerSecond() > 10); - mWifiInfo.setFrequency(5220); - for (int r = -30; r >= -120; r -= 2) { - mWifiInfo.setRssi(r); - mWifiScoreReport.calculateAndReportScore(); - assertTrue(mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE); - } - // If the throughput dips, we should let go - mWifiInfo.setSuccessfulRxPacketsPerSecond( - mScoringParams.getYippeeSkippyPacketsPerSecond() - 0.1); - mWifiScoreReport.calculateAndReportScore(); - assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); - // And even if throughput improves again, once we have decided to let go, disregard - // the good rates. - mWifiInfo.setSuccessfulRxPacketsPerSecond( - mScoringParams.getYippeeSkippyPacketsPerSecond() + 0.1); - mWifiScoreReport.calculateAndReportScore(); - assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); - } - - /** - * Never ask for nud check when nud=0 - */ - @Test - public void neverAskForNudCheckWhenNudKnobIsZero() throws Exception { - assertTrue(mScoringParams.update("nud=0")); - assertEquals(0, mScoringParams.getNudKnob()); - mWifiInfo.setFrequency(5220); - for (int rssi = -30; rssi >= -120; rssi -= 1) { - mWifiInfo.setRssi(rssi); - mWifiScoreReport.calculateAndReportScore(); - assertFalse(mWifiScoreReport.shouldCheckIpLayer()); - } - } - - /** - * Eventually ask for nud check when nud=1 - */ - @Test - public void eventuallyAskForNudCheckWhenNudKnobIsOne() throws Exception { - String oops = "nud=1"; - long lastAskedMillis = 0; // Check that we don't send too soon - int asks = 0; // Keep track of how many time we asked - assertTrue(mScoringParams.update("nud=1")); - assertEquals(1, mScoringParams.getNudKnob()); - mWifiInfo.setFrequency(5220); - for (int rssi = -40; rssi >= -120; rssi -= 1) { - mWifiInfo.setRssi(rssi); - mWifiScoreReport.calculateAndReportScore(); - boolean ask = mWifiScoreReport.shouldCheckIpLayer(); - if (ask) { - assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); - assertTrue(oops, mClock.mWallClockMillis >= lastAskedMillis + 5000); - lastAskedMillis = mClock.mWallClockMillis; - oops += " " + lastAskedMillis + ":" + mWifiInfo.getScore(); - mWifiScoreReport.noteIpCheck(); - asks++; - } - } - assertTrue(oops + " asks:" + asks, asks > 5 && asks < 15); - } - - - /** - * Ask for more nud checks when nud=10 - */ - @Test - public void askForMoreNudChecksWhenNudKnobIsBigger() throws Exception { - String oops = "nud=10"; - long lastAskedMillis = 0; // Check that we don't send too soon - int asks = 0; // Keep track of how many time we asked - assertTrue(mScoringParams.update("nud=10")); - assertEquals(10, mScoringParams.getNudKnob()); - mWifiInfo.setFrequency(5220); - for (int rssi = -40; rssi >= -120; rssi -= 1) { - mWifiInfo.setRssi(rssi); - mWifiScoreReport.calculateAndReportScore(); - boolean ask = mWifiScoreReport.shouldCheckIpLayer(); - if (ask) { - assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); - assertTrue(oops, mClock.mWallClockMillis >= lastAskedMillis + 5000); - lastAskedMillis = mClock.mWallClockMillis; - oops += " " + lastAskedMillis + ":" + mWifiInfo.getScore(); - mWifiScoreReport.noteIpCheck(); - asks++; - } - } - assertTrue(oops + " asks:" + asks, asks > 12 && asks < 80); - } - - /** - * Test initial conditions, and after reset() - */ - @Test - public void exerciseReset() throws Exception { - assertFalse(mWifiScoreReport.shouldCheckIpLayer()); - mWifiScoreReport.reset(); - assertFalse(mWifiScoreReport.shouldCheckIpLayer()); - } - - /** - * This setup causes some reports to be generated when println - * methods are called, to check for "concurrent" modification - * errors. - */ - private void setupToGenerateAReportWhenPrintlnIsCalled() { - int[] counter = new int[1]; - doAnswer(answerVoid((String line) -> { - if (counter[0]++ < 3) { - mWifiScoreReport.calculateAndReportScore(); - } - })).when(mPrintWriter).println(anyString()); - } - - /** - * Test data logging - */ - @Test - public void testDataLogging() throws Exception { - for (int i = 0; i < 10; i++) { - mWifiInfo.setRssi(-65 + i); - mWifiInfo.setLinkSpeed(300); - mWifiInfo.setFrequency(5220); - mWifiInfo.setSuccessfulTxPacketsPerSecond(0.1 + i); - mWifiInfo.setRetriedTxPacketsRate(0.2 + i); - mWifiInfo.setLostTxPacketsPerSecond(0.01 * i); - mWifiInfo.setSuccessfulRxPacketsPerSecond(0.3 + i); - mWifiScoreReport.calculateAndReportScore(); - } - setupToGenerateAReportWhenPrintlnIsCalled(); - mWifiScoreReport.dump(null, mPrintWriter, null); - verify(mPrintWriter, times(11)).println(anyString()); - } - - /** - * Test data logging limit - * <p> - * Check that only a bounded amount of data is collected for dumpsys report - */ - @Test - public void testDataLoggingLimit() throws Exception { - for (int i = 0; i < 3620; i++) { - mWifiInfo.setRssi(-65 + i % 20); - mWifiInfo.setLinkSpeed(300); - mWifiInfo.setFrequency(5220); - mWifiInfo.setSuccessfulTxPacketsPerSecond(0.1 + i % 100); - mWifiInfo.setRetriedTxPacketsRate(0.2 + i % 100); - mWifiInfo.setLostTxPacketsPerSecond(0.0001 * i); - mWifiInfo.setSuccessfulRxPacketsPerSecond(0.3 + i % 200); - mWifiScoreReport.calculateAndReportScore(); - } - mWifiScoreReport.dump(null, mPrintWriter, null); - verify(mPrintWriter, atMost(3601)).println(anyString()); - } - - /** - * Test for staying at below transition score for a certain period of time. - */ - @Test - public void stayAtBelowTransitionScoreForCertainPeriodOfTime() throws Exception { - mWifiScoreReport.enableVerboseLogging(true); - mWifiInfo.setFrequency(5220); - - // Reduce RSSI value to fall below the transition score - for (int rssi = -60; rssi >= -83; rssi -= 1) { - mWifiInfo.setRssi(rssi); - mWifiScoreReport.calculateAndReportScore(); - } - assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); - - // Then, set high RSSI value to exceed the transition score - mWifiInfo.setRssi(-50); - // 8 seconds elapse - for (int i = 0; i < 8; i++) { - mWifiScoreReport.calculateAndReportScore(); - } - assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); - - // 9 seconds elapse - mWifiScoreReport.calculateAndReportScore(); - assertTrue(mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE); - } - - /** - * Test for resetting the internal timer which is used to keep staying at - * below transition score for a certain period of time. - */ - @Test - public void stayAtBelowTransitionScoreWithReset() throws Exception { - mWifiScoreReport.enableVerboseLogging(true); - mWifiInfo.setFrequency(5220); - - // Reduce RSSI value to fall below the transition score - for (int rssi = -60; rssi >= -83; rssi -= 1) { - mWifiInfo.setRssi(rssi); - mWifiScoreReport.calculateAndReportScore(); - } - assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); - - // Then, set high RSSI value to exceed the transition score - mWifiInfo.setRssi(-50); - // Reset the internal timer so that no need to wait for 9 seconds - mWifiScoreReport.reset(); - mWifiScoreReport.calculateAndReportScore(); - assertTrue(mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE); - } - - /** - * Verify that client gets ScoreChangeCallback object when client sets its scorer. - */ - @Test - public void testClientNotification() throws RemoteException { - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - // Client should get ScoreChangeCallback. - verify(mWifiConnectedNetworkScorer).onSetScoreUpdateObserver(any()); - } - - /** - * Verify that clear client should be handled. - */ - @Test - public void testClearClient() throws RemoteException { - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - mWifiScoreReport.clearWifiConnectedNetworkScorer(); - verify(mAppBinder).unlinkToDeath(any(), anyInt()); - - mWifiScoreReport.startConnectedNetworkScorer(10); - verify(mWifiConnectedNetworkScorer, never()).onStart(anyInt()); - } - - /** - * Verify that WifiScoreReport adds for death notification on setting client. - */ - @Test - public void testAddsForBinderDeathOnSetClient() throws Exception { - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - } - - /** - * Verify that client fails to get message when scorer add failed. - */ - @Test - public void testAddsScorerFailureOnLinkToDeath() throws Exception { - doThrow(new RemoteException()) - .when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - - // Client should not get any message when scorer add failed. - verify(mWifiConnectedNetworkScorer, never()).onSetScoreUpdateObserver(any()); - } - - /** - * Verify netId to sessionId conversion. - */ - @Test - public void testSessionId() throws Exception { - assertEquals(-1, WifiScoreReport.sessionIdFromNetId(Integer.MIN_VALUE)); - assertEquals(-1, WifiScoreReport.sessionIdFromNetId(-42)); - assertEquals(-1, WifiScoreReport.sessionIdFromNetId(-1)); - assertEquals(-1, WifiScoreReport.sessionIdFromNetId(0)); - assertEquals(18, WifiScoreReport.sessionIdFromNetId(1)); - assertEquals(3339, WifiScoreReport.sessionIdFromNetId(333)); - assertEquals(TEST_SESSION_ID, WifiScoreReport.sessionIdFromNetId(TEST_NETWORK_ID)); - int dangerOfOverflow = Integer.MAX_VALUE / 10; - assertEquals(214748364, dangerOfOverflow); - assertEquals(2147483646, WifiScoreReport.sessionIdFromNetId(dangerOfOverflow)); - assertEquals(8, WifiScoreReport.sessionIdFromNetId(dangerOfOverflow + 1)); - assertEquals(8, WifiScoreReport.sessionIdFromNetId(Integer.MAX_VALUE)); - } - - /** - * Verify that client gets session ID when onStart() method is called. - */ - @Test - public void testClientGetSessionIdOnStart() throws Exception { - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - verify(mWifiConnectedNetworkScorer).onStart(TEST_SESSION_ID); - } - - /** - * Verify that onStart is called if there is already an active network when registered. - */ - @Test - public void testClientStartOnRegWhileActive() throws Exception { - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - verify(mWifiConnectedNetworkScorer).onStart(TEST_SESSION_ID); - } - - /** - * Verify that client gets session ID when onStop() method is called. - */ - @Test - public void testClientGetSessionIdOnStop() throws Exception { - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - verify(mWifiConnectedNetworkScorer).onStart(TEST_SESSION_ID); - mWifiScoreReport.stopConnectedNetworkScorer(); - verify(mWifiConnectedNetworkScorer).onStop(TEST_SESSION_ID); - // After the session stops, it should not start again (without a new NetworkAgent) - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - verify(mWifiConnectedNetworkScorer).onStart(anyInt()); - } - - /** - * Verify that only a single Wi-Fi connected network scorer can be registered successfully. - */ - @Test - public void verifyOnlyASingleScorerCanBeRegisteredSuccessively() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - assertEquals(true, mWifiScoreReport.setWifiConnectedNetworkScorer( - mAppBinder, scorerImpl)); - assertEquals(false, mWifiScoreReport.setWifiConnectedNetworkScorer( - mAppBinder, scorerImpl)); - } - - /** - * Verify that WifiScoreReport gets updated score when notifyScoreUpdate() is called by apps. - */ - @Test - public void testFrameworkGetsUpdatesScore() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - - assertEquals(TEST_SESSION_ID, scorerImpl.mSessionId); - - // Invalid session ID - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(-1, 49); - assertEquals(mWifiScoreReport.getScore(), ConnectedScore.WIFI_MAX_SCORE); - - // Incorrect session ID - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId + 10, 49); - assertEquals(mWifiScoreReport.getScore(), ConnectedScore.WIFI_MAX_SCORE); - - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(49); - assertEquals(mWifiScoreReport.getScore(), 49); - - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 59); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(59); - assertEquals(mWifiScoreReport.getScore(), 59); - } - - /** - * Verify that WifiScoreReport triggers an update of WifiUsabilityStatsEntry. - */ - @Test - public void testFrameworkTriggersUpdateOfWifiUsabilityStats() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - mWifiScoreReport.setInterfaceName("wlan0"); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - - scorerImpl.mScoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(scorerImpl.mSessionId); - mLooper.dispatchAll(); - verify(mWifiNative).getWifiLinkLayerStats("wlan0"); - verify(mWifiNative).signalPoll("wlan0"); - } - - /** - * Ask for nud when score from external scorer breaches - */ - @Test - public void askForNudCheckWhenExternalScoreBreaches() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - - mClock.mWallClockMillis = 5001; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - assertTrue(mWifiScoreReport.shouldCheckIpLayer()); - mWifiScoreReport.noteIpCheck(); - - mClock.mWallClockMillis = 10000; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - assertFalse(mWifiScoreReport.shouldCheckIpLayer()); - - mClock.mWallClockMillis = 10001; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - assertTrue(mWifiScoreReport.shouldCheckIpLayer()); - } - - /** - * Verify BSSID blocklist does not happen when score stays below threshold for less than the - * minimum duration - */ - @Test - public void bssidBlockListDoesnotHappenWhenExitingIsLessThanMinDuration() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - - mClock.mWallClockMillis = 10; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - mClock.mWallClockMillis = 29009; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - mWifiScoreReport.stopConnectedNetworkScorer(); - mLooper.dispatchAll(); - verify(mBssidBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(), - anyInt(), anyInt()); - } - - /** - * Verify BSSID blocklist happens when score stays below threshold for longer than the - * minimum duration - */ - @Test - public void bssidBlockListHappensWhenExitingIsLongerThanMinDuration() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - - mClock.mWallClockMillis = 10; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - mClock.mWallClockMillis = 29011; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - mWifiScoreReport.stopConnectedNetworkScorer(); - mLooper.dispatchAll(); - verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(any(), any(), - eq(BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE), anyInt()); - } - - /** - * Verify BSSID blocklist does not happen when there is score flip flop - */ - @Test - public void bssidBlockListDoesnotHappenWhenExitingIsReset() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - - mClock.mWallClockMillis = 10; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - mClock.mWallClockMillis = 15000; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 51); - mLooper.dispatchAll(); - mClock.mWallClockMillis = 29011; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - mWifiScoreReport.stopConnectedNetworkScorer(); - mLooper.dispatchAll(); - verify(mBssidBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(), - anyInt(), anyInt()); - } - - /** - * Verify that the initial score value in WifiInfo is the max when onStart is called. - */ - @Test - public void testOnStartInitialScoreInWifiInfoIsMaxScore() throws Exception { - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - assertEquals(ConnectedScore.WIFI_MAX_SCORE, mWifiInfo.getScore()); - } - - /** - * Verify confirmation duration is not added when it is not enabled in config overlay by default - */ - @Test - public void confirmationDurationIsNotAddedWhenItIsNotEnabledInConfigOverlay() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - - mClock.mWallClockMillis = 10; - mWifiInfo.setRssi(-65); - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(anyInt()); - } - - /** - * Verify confirmation duration is not added when there is no score breacht - */ - @Test - public void confirmationDurationIsNotAddedWhenThereIsNoScoreBreach() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - when(mContext.getResources().getBoolean( - R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); - - mClock.mWallClockMillis = 10; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 60); - mWifiInfo.setRssi(-70); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(60); - mClock.mWallClockMillis = 3010; - mWifiInfo.setRssi(-65); - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 59); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(59); - mClock.mWallClockMillis = 6010; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 58); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(58); - } - - /** - * Verify confirmation duration and RSSI check is added for reporting low score when it is - * enabled in config overlay - */ - @Test - public void confirmationDurationAndRssiCheckIsAddedForSendingLowScore() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - when(mContext.getResources().getBoolean( - R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); - - mClock.mWallClockMillis = 10; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - mClock.mWallClockMillis = 10 - + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS - 1; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 48); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - mClock.mWallClockMillis = 10 - + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS; - mWifiInfo.setRssi(-65); - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 47); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(47); - mClock.mWallClockMillis = 10 - + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS + 3000; - mWifiInfo.setRssi(-68); - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 46); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(46); - } - - /** - * Verify confirmation duration is not added for reporting high score with default zero value - */ - @Test - public void confirmationDurationIsNotAddedForSendingHighScore() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - when(mContext.getResources().getBoolean( - R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); - - mClock.mWallClockMillis = 10; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - mClock.mWallClockMillis = 3000; - mWifiInfo.setRssi(-70); - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 51); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(51); - mClock.mWallClockMillis = 6000; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 52); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(52); - } - - /** - * Verify confirmation duration is added for reporting high score with non-zero value - */ - @Test - public void confirmationDurationIsAddedForSendingHighScore() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - when(mContext.getResources().getBoolean( - R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); - when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(4000); - - mClock.mWallClockMillis = 10; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - mClock.mWallClockMillis = 3000; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 51); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - mClock.mWallClockMillis = 6999; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 52); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - mClock.mWallClockMillis = 7000; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 53); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(53); - } - - /** - * Verify NUD check is not recommended and the score of 51 is sent to connectivity service - * when adaptive connectivity is disabled for AOSP scorer. - */ - @Test - public void verifyNudCheckAndScoreIfToggleOffForAospScorer() throws Exception { - mWifiInfo.setFrequency(5220); - mWifiInfo.setRssi(-85); - ArgumentCaptor<ContentObserver> observer = ArgumentCaptor.forClass(ContentObserver.class); - verify(mFrameworkFacade).registerContentObserver( - any(), any(), eq(true), observer.capture()); - when(mFrameworkFacade.getIntegerSetting(any(Context.class), - eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) - .thenReturn(0); - observer.getValue().onChange(true); - mWifiScoreReport.calculateAndReportScore(); - assertFalse(mWifiScoreReport.shouldCheckIpLayer()); - verify(mNetworkAgent).sendNetworkScore(51); - } - - /** - * Verify NUD check is not recommended and the score of 51 is sent to connectivity service - * when adaptive connectivity is disabled for external Wi-Fi scorer. - */ - @Test - public void verifyNudCheckAndScoreIfToggleOffForExternalScorer() throws Exception { - WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); - // Register Client for verification. - mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); - when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); - mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); - mClock.mStepMillis = 0; - when(mContext.getResources().getBoolean( - R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); - when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(4000); - - ArgumentCaptor<ContentObserver> observer = ArgumentCaptor.forClass(ContentObserver.class); - verify(mFrameworkFacade).registerContentObserver( - any(), any(), eq(true), observer.capture()); - when(mFrameworkFacade.getIntegerSetting(any(Context.class), - eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) - .thenReturn(0); - observer.getValue().onChange(true); - - mClock.mWallClockMillis = 10; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - assertFalse(mWifiScoreReport.shouldCheckIpLayer()); - - mClock.mWallClockMillis = 10 - + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS - 1; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 48); - mLooper.dispatchAll(); - verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); - mClock.mWallClockMillis = 10 - + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS; - scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 47); - mLooper.dispatchAll(); - verify(mNetworkAgent).sendNetworkScore(51); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java deleted file mode 100644 index c1ddd6321..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ /dev/null @@ -1,5865 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static android.Manifest.permission.ACCESS_WIFI_STATE; -import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; -import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_STATIONARY; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY; -import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; -import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC; -import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; -import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL; -import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; -import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED; -import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL; -import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; -import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; -import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; -import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR; -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.AdditionalAnswers.returnsSecondArg; -import static org.mockito.ArgumentMatchers.notNull; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.argThat; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.ignoreStubs; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.isNull; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.validateMockitoUsage; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -import android.Manifest; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.app.test.MockAnswerUtil; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.ParceledListSlice; -import android.content.res.Resources; -import android.net.MacAddress; -import android.net.NetworkStack; -import android.net.Uri; -import android.net.wifi.IActionListener; -import android.net.wifi.IDppCallback; -import android.net.wifi.ILocalOnlyHotspotCallback; -import android.net.wifi.INetworkRequestMatchCallback; -import android.net.wifi.IOnWifiActivityEnergyInfoListener; -import android.net.wifi.IOnWifiUsabilityStatsListener; -import android.net.wifi.IScanResultsCallback; -import android.net.wifi.ISoftApCallback; -import android.net.wifi.ISuggestionConnectionStatusListener; -import android.net.wifi.ITrafficStateCallback; -import android.net.wifi.IWifiConnectedNetworkScorer; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApInfo; -import android.net.wifi.WifiClient; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.KeyMgmt; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; -import android.net.wifi.WifiManager.SoftApCallback; -import android.net.wifi.WifiNetworkSuggestion; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.os.Binder; -import android.os.Build; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.IPowerManager; -import android.os.IThermalService; -import android.os.Message; -import android.os.PowerManager; -import android.os.Process; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.connectivity.WifiActivityEnergyInfo; -import android.os.test.TestLooper; -import android.telephony.CarrierConfigManager; -import android.telephony.PhoneStateListener; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import com.android.internal.os.PowerProfile; -import com.android.internal.util.AsyncChannel; -import com.android.server.wifi.WifiServiceImpl.LocalOnlyRequestorCallback; -import com.android.server.wifi.hotspot2.PasspointManager; -import com.android.server.wifi.hotspot2.PasspointProvisioningTestUtil; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; -import com.android.server.wifi.util.ApConfigUtil; -import com.android.server.wifi.util.WifiAsyncChannel; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Unit tests for {@link WifiServiceImpl}. - * - * Note: this is intended to build up over time and will not immediately cover the entire file. - */ -@SmallTest -public class WifiServiceImplTest extends WifiBaseTest { - - private static final String TAG = "WifiServiceImplTest"; - private static final String SCAN_PACKAGE_NAME = "scanPackage"; - private static final int DEFAULT_VERBOSE_LOGGING = 0; - private static final String ANDROID_SYSTEM_PACKAGE = "android"; - private static final String TEST_PACKAGE_NAME = "TestPackage"; - private static final String TEST_FEATURE_ID = "TestFeature"; - private static final String SYSUI_PACKAGE_NAME = "com.android.systemui"; - private static final int TEST_PID = 6789; - private static final int TEST_PID2 = 9876; - private static final int TEST_UID = 1200000; - private static final int OTHER_TEST_UID = 1300000; - private static final int TEST_USER_HANDLE = 13; - private static final int TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER = 17; - private static final int TEST_NETWORK_REQUEST_MATCH_CALLBACK_IDENTIFIER = 234; - private static final int TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER = 2; - private static final int TEST_WIFI_CONNECTED_NETWORK_SCORER_IDENTIFIER = 1; - private static final String WIFI_IFACE_NAME = "wlan0"; - private static final String WIFI_IFACE_NAME2 = "wlan1"; - private static final String TEST_COUNTRY_CODE = "US"; - private static final String TEST_FACTORY_MAC = "10:22:34:56:78:92"; - private static final MacAddress TEST_FACTORY_MAC_ADDR = MacAddress.fromString(TEST_FACTORY_MAC); - private static final String TEST_FQDN = "testfqdn"; - private static final String TEST_FRIENDLY_NAME = "testfriendlyname"; - private static final List<WifiConfiguration> TEST_WIFI_CONFIGURATION_LIST = Arrays.asList( - WifiConfigurationTestUtil.generateWifiConfig( - 0, 1000000, "\"red\"", true, true, null, null), - WifiConfigurationTestUtil.generateWifiConfig( - 1, 1000001, "\"green\"", true, false, "example.com", "Green"), - WifiConfigurationTestUtil.generateWifiConfig( - 2, 1200000, "\"blue\"", false, true, null, null), - WifiConfigurationTestUtil.generateWifiConfig( - 3, 1100000, "\"cyan\"", true, true, null, null), - WifiConfigurationTestUtil.generateWifiConfig( - 4, 1100001, "\"yellow\"", true, true, "example.org", "Yellow"), - WifiConfigurationTestUtil.generateWifiConfig( - 5, 1100002, "\"magenta\"", false, false, null, null)); - private static final int TEST_AP_FREQUENCY = 2412; - private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; - private static final int NETWORK_CALLBACK_ID = 1100; - private static final String TEST_CAP = "[RSN-PSK-CCMP]"; - private static final String TEST_SSID = "Sid's Place"; - private static final String TEST_SSID_WITH_QUOTES = "\"" + TEST_SSID + "\""; - private static final String TEST_BSSID = "01:02:03:04:05:06"; - private static final String TEST_PACKAGE = "package"; - private static final int TEST_NETWORK_ID = 567; - - private SoftApInfo mTestSoftApInfo; - private AsyncChannel mAsyncChannel; - private WifiServiceImpl mWifiServiceImpl; - private TestLooper mLooper; - private PowerManager mPowerManager; - private PhoneStateListener mPhoneStateListener; - private int mPid; - private int mPid2 = Process.myPid(); - private OsuProvider mOsuProvider; - private SoftApCallback mStateMachineSoftApCallback; - private SoftApCallback mLohsApCallback; - private String mLohsInterfaceName; - private ApplicationInfo mApplicationInfo; - private static final String DPP_URI = "DPP:some_dpp_uri"; - - private final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - final ArgumentCaptor<IntentFilter> mIntentFilterCaptor = - ArgumentCaptor.forClass(IntentFilter.class); - - final ArgumentCaptor<Message> mMessageCaptor = ArgumentCaptor.forClass(Message.class); - final ArgumentCaptor<SoftApModeConfiguration> mSoftApModeConfigCaptor = - ArgumentCaptor.forClass(SoftApModeConfiguration.class); - final ArgumentCaptor<Handler> mHandlerCaptor = ArgumentCaptor.forClass(Handler.class); - - @Mock Context mContext; - @Mock WifiInjector mWifiInjector; - @Mock WifiCountryCode mWifiCountryCode; - @Mock Clock mClock; - @Mock WifiTrafficPoller mWifiTrafficPoller; - @Mock ClientModeImpl mClientModeImpl; - @Mock ActiveModeWarden mActiveModeWarden; - @Mock HandlerThread mHandlerThread; - @Mock Resources mResources; - @Mock FrameworkFacade mFrameworkFacade; - @Mock WifiLockManager mLockManager; - @Mock WifiMulticastLockManager mWifiMulticastLockManager; - @Mock WifiLastResortWatchdog mWifiLastResortWatchdog; - @Mock WifiBackupRestore mWifiBackupRestore; - @Mock SoftApBackupRestore mSoftApBackupRestore; - @Mock WifiMetrics mWifiMetrics; - @Mock WifiPermissionsUtil mWifiPermissionsUtil; - @Mock WifiPermissionsWrapper mWifiPermissionsWrapper; - @Mock WifiSettingsStore mSettingsStore; - @Mock ContentResolver mContentResolver; - @Mock PackageManager mPackageManager; - @Mock UserManager mUserManager; - @Mock WifiApConfigStore mWifiApConfigStore; - @Mock WifiConfiguration mApConfig; - @Mock ActivityManager mActivityManager; - @Mock AppOpsManager mAppOpsManager; - @Mock IBinder mAppBinder; - @Mock IBinder mAnotherAppBinder; - @Mock LocalOnlyHotspotRequestInfo mRequestInfo; - @Mock LocalOnlyHotspotRequestInfo mRequestInfo2; - @Mock IProvisioningCallback mProvisioningCallback; - @Mock ISoftApCallback mClientSoftApCallback; - @Mock ISoftApCallback mAnotherSoftApCallback; - @Mock PowerProfile mPowerProfile; - @Mock WifiTrafficPoller mWifiTrafficPolller; - @Mock ScanRequestProxy mScanRequestProxy; - @Mock WakeupController mWakeupController; - @Mock ITrafficStateCallback mTrafficStateCallback; - @Mock INetworkRequestMatchCallback mNetworkRequestMatchCallback; - @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - @Mock TelephonyManager mTelephonyManager; - @Mock IOnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener; - @Mock WifiConfigManager mWifiConfigManager; - @Mock WifiScoreReport mWifiScoreReport; - @Mock WifiScoreCard mWifiScoreCard; - @Mock WifiHealthMonitor mWifiHealthMonitor; - @Mock PasspointManager mPasspointManager; - @Mock IDppCallback mDppCallback; - @Mock SarManager mSarManager; - @Mock ILocalOnlyHotspotCallback mLohsCallback; - @Mock IScanResultsCallback mScanResultsCallback; - @Mock ISuggestionConnectionStatusListener mSuggestionConnectionStatusListener; - @Mock IOnWifiActivityEnergyInfoListener mOnWifiActivityEnergyInfoListener; - @Mock IWifiConnectedNetworkScorer mWifiConnectedNetworkScorer; - @Mock WifiSettingsConfigStore mWifiSettingsConfigStore; - @Mock WifiScanAlwaysAvailableSettingsCompatibility mScanAlwaysAvailableSettingsCompatibility; - @Mock PackageInfo mPackageInfo; - - WifiLog mLog = new LogcatLog(TAG); - - @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - mAsyncChannel = spy(new AsyncChannel()); - mApplicationInfo = new ApplicationInfo(); - mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; - when(mResources.getInteger( - eq(R.integer.config_wifiHardwareSoftapMaxClientCount))) - .thenReturn(10); - WifiInjector.sWifiInjector = mWifiInjector; - when(mRequestInfo.getPid()).thenReturn(mPid); - when(mRequestInfo2.getPid()).thenReturn(mPid2); - when(mWifiInjector.getUserManager()).thenReturn(mUserManager); - when(mWifiInjector.getWifiCountryCode()).thenReturn(mWifiCountryCode); - when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); - when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl); - when(mClientModeImpl.getHandler()).thenReturn(new Handler()); - when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); - when(mWifiInjector.getAsyncChannelHandlerThread()).thenReturn(mHandlerThread); - when(mWifiInjector.getWifiHandlerThread()).thenReturn(mHandlerThread); - when(mHandlerThread.getThreadHandler()).thenReturn(new Handler(mLooper.getLooper())); - when(mHandlerThread.getLooper()).thenReturn(mLooper.getLooper()); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getContentResolver()).thenReturn(mContentResolver); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mPackageManager.getApplicationInfoAsUser(any(), anyInt(), any())) - .thenReturn(mApplicationInfo); - when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(mPackageInfo); - when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore); - doNothing().when(mFrameworkFacade).registerContentObserver(eq(mContext), any(), - anyBoolean(), any()); - when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager); - when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager); - IPowerManager powerManagerService = mock(IPowerManager.class); - IThermalService thermalService = mock(IThermalService.class); - mPowerManager = - new PowerManager(mContext, powerManagerService, thermalService, new Handler()); - when(mContext.getSystemServiceName(PowerManager.class)).thenReturn(Context.POWER_SERVICE); - when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); - WifiAsyncChannel wifiAsyncChannel = new WifiAsyncChannel("WifiServiceImplTest"); - wifiAsyncChannel.setWifiLog(mLog); - when(mFrameworkFacade.makeWifiAsyncChannel(anyString())).thenReturn(wifiAsyncChannel); - when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade); - when(mWifiInjector.getWifiLockManager()).thenReturn(mLockManager); - when(mWifiInjector.getWifiMulticastLockManager()).thenReturn(mWifiMulticastLockManager); - when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); - when(mWifiInjector.getWifiBackupRestore()).thenReturn(mWifiBackupRestore); - when(mWifiInjector.getSoftApBackupRestore()).thenReturn(mSoftApBackupRestore); - when(mWifiInjector.makeLog(anyString())).thenReturn(mLog); - when(mWifiInjector.getWifiTrafficPoller()).thenReturn(mWifiTrafficPoller); - when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiInjector.getWifiSettingsStore()).thenReturn(mSettingsStore); - when(mWifiInjector.getClock()).thenReturn(mClock); - when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy); - when(mWifiInjector.getWakeupController()).thenReturn(mWakeupController); - when(mWifiInjector.getWifiNetworkSuggestionsManager()) - .thenReturn(mWifiNetworkSuggestionsManager); - when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager); - when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); - when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager); - when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager); - when(mClientModeImpl.getWifiScoreReport()).thenReturn(mWifiScoreReport); - when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard); - when(mWifiInjector.getWifiHealthMonitor()).thenReturn(mWifiHealthMonitor); - when(mWifiInjector.getSarManager()).thenReturn(mSarManager); - when(mWifiInjector.getWifiNetworkScoreCache()) - .thenReturn(mock(WifiNetworkScoreCache.class)); - when(mWifiInjector.getWifiThreadRunner()) - .thenReturn(new WifiThreadRunner(new Handler(mLooper.getLooper()))); - when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore); - when(mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility()) - .thenReturn(mScanAlwaysAvailableSettingsCompatibility); - when(mClientModeImpl.syncStartSubscriptionProvisioning(anyInt(), - any(OsuProvider.class), any(IProvisioningCallback.class), any())).thenReturn(true); - // Create an OSU provider that can be provisioned via an open OSU AP - mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true); - when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME); - when(mContext.getAttributionTag()).thenReturn(TEST_FEATURE_ID); - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_STACK), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); - when(mScanRequestProxy.startScan(anyInt(), anyString())).thenReturn(true); - when(mLohsCallback.asBinder()).thenReturn(mock(IBinder.class)); - when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true); - - mWifiServiceImpl = makeWifiServiceImpl(); - mDppCallback = new IDppCallback() { - @Override - public void onSuccessConfigReceived(int newNetworkId) throws RemoteException { - - } - - @Override - public void onSuccess(int status) throws RemoteException { - - } - - @Override - public void onFailure(int status, String ssid, String channelList, int[] bandList) - throws RemoteException { - - } - - @Override - public void onProgress(int status) throws RemoteException { - - } - - @Override - public IBinder asBinder() { - return null; - } - }; - - // permission not granted by default - doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( - eq(Manifest.permission.NETWORK_SETUP_WIZARD), any()); - mTestSoftApInfo = new SoftApInfo(); - mTestSoftApInfo.setFrequency(TEST_AP_FREQUENCY); - mTestSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - private WifiServiceImpl makeWifiServiceImpl() { - reset(mActiveModeWarden); - WifiServiceImpl wifiServiceImpl = - new WifiServiceImpl(mContext, mWifiInjector, mAsyncChannel); - ArgumentCaptor<SoftApCallback> softApCallbackCaptor = - ArgumentCaptor.forClass(SoftApCallback.class); - verify(mActiveModeWarden).registerSoftApCallback(softApCallbackCaptor.capture()); - mStateMachineSoftApCallback = softApCallbackCaptor.getValue(); - ArgumentCaptor<SoftApCallback> lohsCallbackCaptor = - ArgumentCaptor.forClass(SoftApCallback.class); - mLohsInterfaceName = WIFI_IFACE_NAME; - verify(mActiveModeWarden).registerLohsCallback(lohsCallbackCaptor.capture()); - mLohsApCallback = lohsCallbackCaptor.getValue(); - mLooper.dispatchAll(); - return wifiServiceImpl; - } - - private WifiServiceImpl makeWifiServiceImplWithMockRunnerWhichTimesOut() { - WifiThreadRunner mockRunner = mock(WifiThreadRunner.class); - when(mockRunner.call(any(), any())).then(returnsSecondArg()); - when(mockRunner.call(any(), any(int.class))).then(returnsSecondArg()); - when(mockRunner.call(any(), any(boolean.class))).then(returnsSecondArg()); - when(mockRunner.post(any())).thenReturn(false); - - when(mWifiInjector.getWifiThreadRunner()).thenReturn(mockRunner); - return makeWifiServiceImpl(); - } - - /** - * Test that REMOVE_NETWORK returns failure to public API when WifiConfigManager returns - * failure. - */ - @Test - public void testRemoveNetworkFailureAppBelowQSdk() { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME, - TEST_FEATURE_ID, null); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - when(mWifiConfigManager.removeNetwork(anyInt(), anyInt(), anyString())).thenReturn(false); - - mLooper.startAutoDispatch(); - boolean succeeded = mWifiServiceImpl.removeNetwork(0, TEST_PACKAGE_NAME); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - assertFalse(succeeded); - } - - /** - * Ensure WifiMetrics.dump() is the only dump called when 'dumpsys wifi WifiMetricsProto' is - * called. This is required to support simple metrics collection via dumpsys - */ - @Test - public void testWifiMetricsDump() { - mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), - new String[]{mWifiMetrics.PROTO_DUMP_ARG}); - verify(mWifiMetrics).setEnhancedMacRandomizationForceEnabled(anyBoolean()); - verify(mWifiMetrics).setIsScanningAlwaysEnabled(anyBoolean()); - verify(mWifiMetrics).setVerboseLoggingEnabled(anyBoolean()); - verify(mWifiMetrics) - .dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class)); - verify(mClientModeImpl, never()) - .dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class)); - } - - /** - * Ensure WifiServiceImpl.dump() doesn't throw an NPE when executed with null args - */ - @Test - public void testDumpNullArgs() { - mLooper.startAutoDispatch(); - mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - } - - /** - * Ensure that WifiServiceImpl.dump() calls - * {@link ClientModeImpl#updateLinkLayerStatsRssiAndScoreReport()}, then calls - * mWifiInjector.getClientModeImplHandler().runWithScissors() at least once before calling - * {@link WifiScoreReport#dump(FileDescriptor, PrintWriter, String[])}. - * - * runWithScissors() needs to be called at least once so that we know that the async call - * {@link ClientModeImpl#updateLinkLayerStatsRssiAndScoreReport()} has completed, since - * runWithScissors() blocks the current thread until the call completes, which includes all - * previous calls posted to that thread. - * - * This ensures that WifiScoreReport will always get updated RSSI and link layer stats before - * dumping during a bug report, no matter if the screen is on or not. - */ - @Test - public void testWifiScoreReportDump() { - mLooper.startAutoDispatch(); - mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - InOrder inOrder = inOrder(mClientModeImpl, mWifiScoreReport); - - inOrder.verify(mClientModeImpl).updateLinkLayerStatsRssiAndScoreReport(); - inOrder.verify(mWifiScoreReport).dump(any(), any(), any()); - } - - /** - * Verify that metrics is incremented correctly for Privileged Apps. - */ - @Test - public void testSetWifiEnabledMetricsPrivilegedApp() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mSettingsStore.handleWifiToggled(anyBoolean())).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - - InOrder inorder = inOrder(mWifiMetrics); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - inorder.verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON); - inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(true), eq(true)); - inorder.verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_TOGGLE_WIFI_OFF), - anyInt()); - inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(true), eq(false)); - } - - /** - * Verify that metrics is incremented correctly for normal Apps targeting pre-Q. - */ - @Test - public void testSetWifiEnabledMetricsNormalAppBelowQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - when(mSettingsStore.handleWifiToggled(anyBoolean())).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - - InOrder inorder = inOrder(mWifiMetrics); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(false), eq(true)); - inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(false), eq(false)); - } - - /** - * Verify that metrics is not incremented by apps targeting Q SDK. - */ - @Test - public void testSetWifiEnabledMetricsNormalAppTargetingQSdkNoIncrement() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false); - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - - assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - verify(mWifiMetrics, never()).incrementNumWifiToggles(anyBoolean(), anyBoolean()); - } - - /** - * Verify that wifi can be enabled by a caller with NETWORK_SETTINGS permission. - */ - @Test - public void testSetWifiEnabledSuccessWithNetworkSettingsPermission() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi can be enabled by a caller with NETWORK_MANAGED_PROVISIONING permission. - */ - @Test - public void testSetWifiEnabledSuccessWithNetworkManagedProvisioningPermission() - throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi can be enabled by the DO apps targeting Q SDK. - */ - @Test - public void testSetWifiEnabledSuccessForDOAppsTargetingQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME)) - .thenReturn(true); - - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi can be enabled by the system apps targeting Q SDK. - */ - @Test - public void testSetWifiEnabledSuccessForSystemAppsTargetingQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false); - mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; - - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi can be enabled by the apps targeting pre-Q SDK. - */ - @Test - public void testSetWifiEnabledSuccessForAppsTargetingBelowQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi cannot be enabled by the apps targeting Q SDK. - */ - @Test - public void testSetWifiEnabledFailureForAppsTargetingQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false); - - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - - verify(mActiveModeWarden, never()).wifiToggled(); - } - - /** - * Verify a SecurityException is thrown if OPSTR_CHANGE_WIFI_STATE is disabled for the app. - */ - @Test - public void testSetWifiEnableAppOpsRejected() throws Exception { - doThrow(new SecurityException()).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - try { - mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true); - fail(); - } catch (SecurityException e) { - - } - verify(mActiveModeWarden, never()).wifiToggled(); - } - - /** - * Verify a SecurityException is thrown if OP_CHANGE_WIFI_STATE is set to MODE_IGNORED - * for the app. - */ - @Test // No exception expected, but the operation should not be done - public void testSetWifiEnableAppOpsIgnored() throws Exception { - doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - - mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true); - verify(mActiveModeWarden, never()).wifiToggled(); - } - - /** - * Verify that a call from an app with the NETWORK_SETTINGS permission can enable wifi if we - * are in airplane mode. - */ - @Test - public void testSetWifiEnabledFromNetworkSettingsHolderWhenInAirplaneMode() throws Exception { - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - when(mContext.checkPermission( - eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - - assertTrue(mWifiServiceImpl.setWifiEnabled(SYSUI_PACKAGE_NAME, true)); - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that a caller without the NETWORK_SETTINGS permission can't enable wifi - * if we are in airplane mode. - */ - @Test - public void testSetWifiEnabledFromAppFailsWhenInAirplaneMode() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - when(mContext.checkPermission( - eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())) - .thenReturn(PackageManager.PERMISSION_DENIED); - - assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - verify(mActiveModeWarden, never()).wifiToggled(); - } - - /** - * Helper to verify registering for state changes. - */ - private void verifyApRegistration() { - assertNotNull(mLohsApCallback); - } - - /** - * Helper to emulate local-only hotspot state changes. - * - * Must call verifyApRegistration first. - */ - private void changeLohsState(int apState, int previousState, int error) { - // TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext, - // apState, previousState, error, WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY); - mLohsApCallback.onStateChanged(apState, error); - } - - /** - * Verify that a call from an app with the NETWORK_SETTINGS permission can enable wifi if we - * are in softap mode. - */ - @Test - public void testSetWifiEnabledFromNetworkSettingsHolderWhenApEnabled() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); - when(mContext.checkPermission( - eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(SYSUI_PACKAGE_NAME, true)); - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that a call from an app cannot enable wifi if we are in softap mode. - */ - @Test - public void testSetWifiEnabledFromAppFailsWhenApEnabled() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - - when(mContext.checkPermission( - eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())) - .thenReturn(PackageManager.PERMISSION_DENIED); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - verify(mSettingsStore, never()).handleWifiToggled(anyBoolean()); - verify(mActiveModeWarden, never()).wifiToggled(); - } - - - /** - * Verify that the CMD_TOGGLE_WIFI message won't be sent if wifi is already on. - */ - @Test - public void testSetWifiEnabledNoToggle() throws Exception { - when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(false); - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); - verify(mActiveModeWarden, never()).wifiToggled(); - } - - /** - * Verify a SecurityException is thrown if a caller does not have the CHANGE_WIFI_STATE - * permission to toggle wifi. - */ - @Test - public void testSetWifiEnableWithoutChangeWifiStatePermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE), - eq("WifiService")); - try { - mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true); - fail(); - } catch (SecurityException e) { - } - } - - /** - * Verify that wifi can be disabled by a caller with NETWORK_SETTINGS permission. - */ - @Test - public void testSetWifiDisabledSuccessWithNetworkSettingsPermission() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi can be disabled by a caller with NETWORK_MANAGED_PROVISIONING permission. - */ - @Test - public void testSetWifiDisabledSuccessWithNetworkManagedProvisioningPermission() - throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi can be disabled by the PO apps targeting Q SDK. - */ - @Test - public void testSetWifiDisabledSuccessForPOAppsTargetingQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME)) - .thenReturn(true); - - when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi can be disabled by the system apps targeting Q SDK. - */ - @Test - public void testSetWifiDisabledSuccessForSystemAppsTargetingQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false); - mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; - - when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - - verify(mActiveModeWarden).wifiToggled(); - } - - - /** - * Verify that wifi can be disabled by the apps targeting pre-Q SDK. - */ - @Test - public void testSetWifiDisabledSuccessForAppsTargetingBelowQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - - when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - - verify(mActiveModeWarden).wifiToggled(); - } - - /** - * Verify that wifi cannot be disabled by the apps targeting Q SDK. - */ - @Test - public void testSetWifiDisabledFailureForAppsTargetingQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(false); - - when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true); - when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); - assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - - verify(mActiveModeWarden, never()).wifiToggled(); - } - - /** - * Verify that CMD_TOGGLE_WIFI message won't be sent if wifi is already off. - */ - @Test - public void testSetWifiDisabledNoToggle() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(false); - assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); - verify(mActiveModeWarden, never()).wifiToggled(); - } - - /** - * Verify a SecurityException is thrown if a caller does not have the CHANGE_WIFI_STATE - * permission to toggle wifi. - */ - @Test - public void testSetWifiDisabledWithoutChangeWifiStatePermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE), - eq("WifiService")); - try { - mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false); - fail(); - } catch (SecurityException e) { } - } - - /** - * Ensure unpermitted callers cannot write the SoftApConfiguration. - */ - @Test - public void testSetWifiApConfigurationNotSavedWithoutPermission() throws Exception { - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false); - WifiConfiguration apConfig = new WifiConfiguration(); - try { - mWifiServiceImpl.setWifiApConfiguration(apConfig, TEST_PACKAGE_NAME); - fail("Expected SecurityException"); - } catch (SecurityException e) { } - } - - /** - * Ensure softap config is written when the caller has the correct permission. - */ - @Test - public void testSetWifiApConfigurationSuccess() throws Exception { - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); - WifiConfiguration wifiApConfig = createValidWifiApConfiguration(); - - assertTrue(mWifiServiceImpl.setWifiApConfiguration(wifiApConfig, TEST_PACKAGE_NAME)); - mLooper.dispatchAll(); - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mWifiApConfigStore).setApConfiguration(eq( - ApConfigUtil.fromWifiConfiguration(wifiApConfig))); - } - - /** - * Ensure that a null config does not overwrite the saved ap config. - */ - @Test - public void testSetWifiApConfigurationNullConfigNotSaved() throws Exception { - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); - assertFalse(mWifiServiceImpl.setWifiApConfiguration(null, TEST_PACKAGE_NAME)); - verify(mWifiApConfigStore, never()).setApConfiguration(isNull(SoftApConfiguration.class)); - } - - /** - * Ensure that an invalid config does not overwrite the saved ap config. - */ - @Test - public void testSetWifiApConfigurationWithInvalidConfigNotSaved() throws Exception { - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); - assertFalse(mWifiServiceImpl.setWifiApConfiguration(new WifiConfiguration(), - TEST_PACKAGE_NAME)); - verify(mWifiApConfigStore, never()).setApConfiguration(any()); - } - - /** - * Ensure unpermitted callers cannot write the SoftApConfiguration. - */ - @Test - public void testSetSoftApConfigurationNotSavedWithoutPermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - SoftApConfiguration apConfig = createValidSoftApConfiguration(); - try { - mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME); - fail("Expected SecurityException"); - } catch (SecurityException e) { } - } - - /** - * Ensure softap config is written when the caller has the correct permission. - */ - @Test - public void testSetSoftApConfigurationSuccess() throws Exception { - doNothing().when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - SoftApConfiguration apConfig = createValidSoftApConfiguration(); - - assertTrue(mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME)); - mLooper.dispatchAll(); - verify(mWifiApConfigStore).setApConfiguration(eq(apConfig)); - verify(mActiveModeWarden).updateSoftApConfiguration(apConfig); - verify(mContext).enforceCallingOrSelfPermission( - eq(android.Manifest.permission.NETWORK_SETTINGS), eq("WifiService")); - } - - /** - * Ensure that a null config does not overwrite the saved ap config. - */ - @Test - public void testSetSoftApConfigurationNullConfigNotSaved() throws Exception { - doNothing().when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - assertFalse(mWifiServiceImpl.setSoftApConfiguration(null, TEST_PACKAGE_NAME)); - verify(mWifiApConfigStore, never()).setApConfiguration(isNull(SoftApConfiguration.class)); - verify(mActiveModeWarden, never()).updateSoftApConfiguration(any()); - verify(mContext).enforceCallingOrSelfPermission( - eq(android.Manifest.permission.NETWORK_SETTINGS), eq("WifiService")); - } - - /** - * Ensure that an invalid config does not overwrite the saved ap config. - */ - @Test - public void testSetSoftApConfigurationWithInvalidConfigNotSaved() throws Exception { - doNothing().when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - assertFalse(mWifiServiceImpl.setSoftApConfiguration( - new SoftApConfiguration.Builder().build(), TEST_PACKAGE_NAME)); - verify(mWifiApConfigStore, never()).setApConfiguration(any()); - verify(mContext).enforceCallingOrSelfPermission( - eq(android.Manifest.permission.NETWORK_SETTINGS), eq("WifiService")); - } - - /** - * Ensure unpermitted callers are not able to retrieve the softap config. - */ - @Test - public void testGetSoftApConfigurationNotReturnedWithoutPermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.getSoftApConfiguration(); - fail("Expected a SecurityException"); - } catch (SecurityException e) { - } - } - - /** - * Ensure permitted callers are able to retrieve the softap config. - */ - @Test - public void testGetSoftApConfigurationSuccess() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - doNothing().when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - SoftApConfiguration apConfig = createValidSoftApConfiguration(); - when(mWifiApConfigStore.getApConfiguration()).thenReturn(apConfig); - - mLooper.startAutoDispatch(); - assertThat(apConfig).isEqualTo(mWifiServiceImpl.getSoftApConfiguration()); - - mLooper.stopAutoDispatchAndIgnoreExceptions(); - } - - /** - * Ensure unpermitted callers are not able to retrieve the softap config. - */ - @Test - public void testGetWifiApConfigurationNotReturnedWithoutPermission() throws Exception { - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false); - try { - mWifiServiceImpl.getWifiApConfiguration(); - fail("Expected a SecurityException"); - } catch (SecurityException e) { - } - } - - /** - * Ensure permitted callers are able to retrieve the softap config. - */ - @Test - public void testGetWifiApConfigurationSuccess() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); - SoftApConfiguration apConfig = new SoftApConfiguration.Builder().build(); - when(mWifiApConfigStore.getApConfiguration()).thenReturn(apConfig); - - mLooper.startAutoDispatch(); - WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp( - apConfig.toWifiConfiguration(), - mWifiServiceImpl.getWifiApConfiguration()); - - mLooper.stopAutoDispatchAndIgnoreExceptions(); - } - - /** - * Ensure we return the proper variable for the softap state after getting an AP state change - * broadcast. - */ - @Test - public void testGetWifiApEnabled() throws Exception { - // ap should be disabled when wifi hasn't been started - assertEquals(WifiManager.WIFI_AP_STATE_DISABLED, mWifiServiceImpl.getWifiApEnabledState()); - - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - // ap should be disabled initially - assertEquals(WifiManager.WIFI_AP_STATE_DISABLED, mWifiServiceImpl.getWifiApEnabledState()); - - // send an ap state change to verify WifiServiceImpl is updated - verifyApRegistration(); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); - mLooper.dispatchAll(); - - assertEquals(WifiManager.WIFI_AP_STATE_FAILED, mWifiServiceImpl.getWifiApEnabledState()); - } - - /** - * Ensure we do not allow unpermitted callers to get the wifi ap state. - */ - @Test - public void testGetWifiApEnabledPermissionDenied() { - // we should not be able to get the state - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE), - eq("WifiService")); - - try { - mWifiServiceImpl.getWifiApEnabledState(); - fail("expected SecurityException"); - } catch (SecurityException expected) { } - } - - /** - * Make sure we do start WifiController (wifi disabled) if the device is already decrypted. - */ - @Test - public void testWifiControllerStartsWhenDeviceBootsWithWifiDisabled() { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mWifiConfigManager).loadFromStore(); - verify(mActiveModeWarden).start(); - verify(mActiveModeWarden, never()).wifiToggled(); - } - - @Test - public void testWifiVerboseLoggingInitialization() { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mWifiConfigManager).loadFromStore(); - verify(mClientModeImpl).enableVerboseLogging(1); - verify(mActiveModeWarden).start(); - } - - /** - * Make sure we do start WifiController (wifi enabled) if the device is already decrypted. - */ - @Test - public void testWifiFullyStartsWhenDeviceBootsWithWifiEnabled() { - when(mSettingsStore.handleWifiToggled(true)).thenReturn(true); - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); - when(mClientModeImpl.syncGetWifiState()).thenReturn(WIFI_STATE_DISABLED); - when(mContext.getPackageName()).thenReturn(ANDROID_SYSTEM_PACKAGE); - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mWifiConfigManager).loadFromStore(); - verify(mActiveModeWarden).start(); - } - - /** - * Verify caller with proper permission can call startSoftAp. - */ - @Test - public void testStartSoftApWithPermissionsAndNullConfig() { - boolean result = mWifiServiceImpl.startSoftAp(null); - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertNull(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - } - - /** - * Verify caller with proper permissions but an invalid config does not start softap. - */ - @Test - public void testStartSoftApWithPermissionsAndInvalidConfig() { - boolean result = mWifiServiceImpl.startSoftAp(mApConfig); - assertFalse(result); - verify(mActiveModeWarden, never()).startSoftAp(any()); - } - - /** - * Verify caller with proper permission and valid config does start softap. - */ - @Test - public void testStartSoftApWithPermissionsAndValidConfig() { - WifiConfiguration config = createValidWifiApConfiguration(); - boolean result = mWifiServiceImpl.startSoftAp(config); - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp( - config, - mSoftApModeConfigCaptor.getValue().getSoftApConfiguration().toWifiConfiguration()); - } - - /** - * Verify a SecurityException is thrown when a caller without the correct permission attempts to - * start softap. - */ - @Test(expected = SecurityException.class) - public void testStartSoftApWithoutPermissionThrowsException() throws Exception { - when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK)) - .thenReturn(PackageManager.PERMISSION_DENIED); - doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any()); - mWifiServiceImpl.startSoftAp(null); - } - - /** - * Verify that startSoftAP() succeeds if the caller does not have the NETWORK_STACK permission - * but does have the MAINLINE_NETWORK_STACK permission. - */ - @Test - public void testStartSoftApWithoutNetworkStackWithMainlineNetworkStackSucceeds() { - when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK)) - .thenReturn(PackageManager.PERMISSION_DENIED); - WifiConfiguration config = createValidWifiApConfiguration(); - boolean result = mWifiServiceImpl.startSoftAp(config); - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp( - config, - mSoftApModeConfigCaptor.getValue().getSoftApConfiguration().toWifiConfiguration()); - verify(mContext).enforceCallingOrSelfPermission( - eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any()); - } - - /** - * Verify that startSoftAp() with valid config succeeds after a failed call - */ - @Test - public void testStartSoftApWithValidConfigSucceedsAfterFailure() { - // First initiate a failed call - assertFalse(mWifiServiceImpl.startSoftAp(mApConfig)); - verify(mActiveModeWarden, never()).startSoftAp(any()); - - // Next attempt a valid config - WifiConfiguration config = createValidWifiApConfiguration(); - assertTrue(mWifiServiceImpl.startSoftAp(config)); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp( - config, - mSoftApModeConfigCaptor.getValue().getSoftApConfiguration().toWifiConfiguration()); - } - - /** - * Verify caller with proper permission can call startTetheredHotspot. - */ - @Test - public void testStartTetheredHotspotWithPermissionsAndNullConfig() { - boolean result = mWifiServiceImpl.startTetheredHotspot(null); - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertNull(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - } - - /** - * Verify caller with proper permissions but an invalid config does not start softap. - */ - @Test - public void testStartTetheredHotspotWithPermissionsAndInvalidConfig() { - boolean result = mWifiServiceImpl.startTetheredHotspot( - new SoftApConfiguration.Builder().build()); - assertFalse(result); - verify(mActiveModeWarden, never()).startSoftAp(any()); - } - - /** - * Verify caller with proper permission and valid config does start softap. - */ - @Test - public void testStartTetheredHotspotWithPermissionsAndValidConfig() { - SoftApConfiguration config = createValidSoftApConfiguration(); - boolean result = mWifiServiceImpl.startTetheredHotspot(config); - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - } - - /** - * Verify attempt to start softAp with a supported 5GHz band succeeds. - */ - @Test - public void testStartTetheredHotspotWithSupported5gBand() { - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ)).thenReturn(true); - - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setSsid("TestAp") - .setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .setBand(SoftApConfiguration.BAND_5GHZ) - .build(); - - mLooper.startAutoDispatch(); - boolean result = mWifiServiceImpl.startTetheredHotspot(config); - - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - } - - /** - * Verify attempt to start softAp with a non-supported 5GHz band fails. - */ - @Test - public void testStartTetheredHotspotWithUnSupported5gBand() { - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ)).thenReturn(false); - - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setSsid("TestAp") - .setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .setBand(SoftApConfiguration.BAND_5GHZ) - .build(); - - mLooper.startAutoDispatch(); - boolean result = mWifiServiceImpl.startTetheredHotspot(config); - - assertFalse(result); - verify(mActiveModeWarden, never()).startSoftAp(any()); - } - - /** - * Verify attempt to start softAp with a supported 6GHz band succeeds. - */ - @Test - public void testStartTetheredHotspotWithSupported6gBand() { - when(mResources.getBoolean( - eq(R.bool.config_wifiSoftap6ghzSupported))) - .thenReturn(true); - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn(true); - - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setSsid("TestAp") - .setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .setBand(SoftApConfiguration.BAND_6GHZ) - .build(); - - mLooper.startAutoDispatch(); - boolean result = mWifiServiceImpl.startTetheredHotspot(config); - - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - } - - /** - * Verify attempt to start softAp with a non-supported 6GHz band fails. - */ - @Test - public void testStartTetheredHotspotWithUnSupported6gBand() { - when(mResources.getBoolean( - eq(R.bool.config_wifiSoftap6ghzSupported))) - .thenReturn(false); - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn(true); - - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setSsid("TestAp") - .setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .setBand(SoftApConfiguration.BAND_6GHZ) - .build(); - - mLooper.startAutoDispatch(); - boolean result = mWifiServiceImpl.startTetheredHotspot(config); - - assertFalse(result); - verify(mActiveModeWarden, never()).startSoftAp(any()); - } - - /** - * Verify attempt to start softAp with a supported band succeeds. - */ - @Test - public void testStartTetheredHotspotWithSupportedBand() { - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ)).thenReturn(true); - - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setSsid("TestAp") - .setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .setBand(SoftApConfiguration.BAND_5GHZ) - .build(); - - mLooper.startAutoDispatch(); - boolean result = mWifiServiceImpl.startTetheredHotspot(config); - - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - } - - /** - * Verify a SecurityException is thrown when a caller without the correct permission attempts to - * start softap. - */ - @Test(expected = SecurityException.class) - public void testStartTetheredHotspotWithoutPermissionThrowsException() throws Exception { - when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK)) - .thenReturn(PackageManager.PERMISSION_DENIED); - doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any()); - mWifiServiceImpl.startTetheredHotspot(null); - } - - /** - * Verify that startTetheredHotspot() succeeds if the caller does not have the - * NETWORK_STACK permission but does have the MAINLINE_NETWORK_STACK permission. - */ - @Test - public void testStartTetheredHotspotWithoutNetworkStackWithMainlineNetworkStackSucceeds() { - when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK)) - .thenReturn(PackageManager.PERMISSION_DENIED); - SoftApConfiguration config = createValidSoftApConfiguration(); - boolean result = mWifiServiceImpl.startTetheredHotspot(config); - assertTrue(result); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - verify(mContext).enforceCallingOrSelfPermission( - eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any()); - } - - /** - * Verify a valied call to startTetheredHotspot succeeds after a failed call. - */ - @Test - public void testStartTetheredHotspotWithValidConfigSucceedsAfterFailedCall() { - // First issue an invalid call - assertFalse(mWifiServiceImpl.startTetheredHotspot( - new SoftApConfiguration.Builder().build())); - verify(mActiveModeWarden, never()).startSoftAp(any()); - - // Now attempt a successful call - assertTrue(mWifiServiceImpl.startTetheredHotspot(null)); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertNull(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - } - - /** - * Verify caller with proper permission can call stopSoftAp. - */ - @Test - public void testStopSoftApWithPermissions() { - boolean result = mWifiServiceImpl.stopSoftAp(); - assertTrue(result); - verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_TETHERED); - } - - /** - * Verify SecurityException is thrown when a caller without the correct permission attempts to - * stop softap. - */ - @Test(expected = SecurityException.class) - public void testStopSoftApWithoutPermissionThrowsException() throws Exception { - when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK)) - .thenReturn(PackageManager.PERMISSION_DENIED); - doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK), any()); - mWifiServiceImpl.stopSoftAp(); - } - - /** - * Ensure that we handle app ops check failure when handling scan request. - */ - @Test - public void testStartScanFailureAppOpsIgnored() { - doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), SCAN_PACKAGE_NAME); - mLooper.startAutoDispatch(); - assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mScanRequestProxy, never()).startScan(Process.myUid(), SCAN_PACKAGE_NAME); - } - - /** - * Ensure that we handle scan access permission check failure when handling scan request. - */ - @Test - public void testStartScanFailureInCanAccessScanResultsPermission() { - doThrow(new SecurityException()).when(mWifiPermissionsUtil) - .enforceCanAccessScanResults(SCAN_PACKAGE_NAME, TEST_FEATURE_ID, Process.myUid(), - null); - mLooper.startAutoDispatch(); - assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mScanRequestProxy, never()).startScan(Process.myUid(), SCAN_PACKAGE_NAME); - } - - /** - * Ensure that we handle scan request failure when posting the runnable to handler fails. - */ - @Test - public void testStartScanFailureInRunWithScissors() { - mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut(); - - mLooper.startAutoDispatch(); - assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mScanRequestProxy, never()).startScan(anyInt(), eq(SCAN_PACKAGE_NAME)); - } - - /** - * Ensure that we handle scan request failure from ScanRequestProxy fails. - */ - @Test - public void testStartScanFailureFromScanRequestProxy() { - when(mScanRequestProxy.startScan(anyInt(), anyString())).thenReturn(false); - - mLooper.startAutoDispatch(); - assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mScanRequestProxy).startScan(Binder.getCallingUid(), SCAN_PACKAGE_NAME); - } - - private void setupForGetConnectionInfo() { - WifiInfo wifiInfo = new WifiInfo(); - wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID)); - wifiInfo.setBSSID(TEST_BSSID); - wifiInfo.setNetworkId(TEST_NETWORK_ID); - wifiInfo.setFQDN(TEST_FQDN); - wifiInfo.setProviderFriendlyName(TEST_FRIENDLY_NAME); - when(mClientModeImpl.syncRequestConnectionInfo()).thenReturn(wifiInfo); - } - - /** - * Test that connected SSID and BSSID are not exposed to an app that does not have the - * appropriate permissions. - */ - @Test - public void testConnectedIdsAreHiddenFromAppWithoutPermission() throws Exception { - setupForGetConnectionInfo(); - - doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( - anyString(), nullable(String.class), anyInt(), nullable(String.class)); - - WifiInfo connectionInfo = mWifiServiceImpl.getConnectionInfo(TEST_PACKAGE, TEST_FEATURE_ID); - - assertEquals(WifiManager.UNKNOWN_SSID, connectionInfo.getSSID()); - assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getBSSID()); - assertEquals(WifiConfiguration.INVALID_NETWORK_ID, connectionInfo.getNetworkId()); - assertNull(connectionInfo.getPasspointFqdn()); - assertNull(connectionInfo.getPasspointProviderFriendlyName()); - } - - /** - * Test that connected SSID and BSSID are not exposed to an app that does not have the - * appropriate permissions, when enforceCanAccessScanResults raises a SecurityException. - */ - @Test - public void testConnectedIdsAreHiddenOnSecurityException() throws Exception { - setupForGetConnectionInfo(); - - doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( - anyString(), nullable(String.class), anyInt(), nullable(String.class)); - - WifiInfo connectionInfo = mWifiServiceImpl.getConnectionInfo(TEST_PACKAGE, TEST_FEATURE_ID); - - assertEquals(WifiManager.UNKNOWN_SSID, connectionInfo.getSSID()); - assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getBSSID()); - assertEquals(WifiConfiguration.INVALID_NETWORK_ID, connectionInfo.getNetworkId()); - assertNull(connectionInfo.getPasspointFqdn()); - assertNull(connectionInfo.getPasspointProviderFriendlyName()); - } - - /** - * Test that connected SSID and BSSID are exposed to an app that does have the - * appropriate permissions. - */ - @Test - public void testConnectedIdsAreVisibleFromPermittedApp() throws Exception { - setupForGetConnectionInfo(); - - WifiInfo connectionInfo = mWifiServiceImpl.getConnectionInfo(TEST_PACKAGE, TEST_FEATURE_ID); - - assertEquals(TEST_SSID_WITH_QUOTES, connectionInfo.getSSID()); - assertEquals(TEST_BSSID, connectionInfo.getBSSID()); - assertEquals(TEST_NETWORK_ID, connectionInfo.getNetworkId()); - assertEquals(TEST_FQDN, connectionInfo.getPasspointFqdn()); - assertEquals(TEST_FRIENDLY_NAME, connectionInfo.getPasspointProviderFriendlyName()); - } - - /** - * Test that configured network list are exposed empty list to an app that does not have the - * appropriate permissions. - */ - @Test - public void testConfiguredNetworkListAreEmptyFromAppWithoutPermission() throws Exception { - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(TEST_WIFI_CONFIGURATION_LIST); - - // no permission = target SDK=Q && not a carrier app - when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(anyString())).thenReturn( - TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS); - - ParceledListSlice<WifiConfiguration> configs = - mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID); - - assertEquals(0, configs.getList().size()); - } - - /** - * Test that configured network list are exposed empty list to an app that does not have the - * appropriate permissions, when enforceCanAccessScanResults raises a SecurityException. - */ - @Test - public void testConfiguredNetworkListAreEmptyOnSecurityException() throws Exception { - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(TEST_WIFI_CONFIGURATION_LIST); - - doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( - anyString(), nullable(String.class), anyInt(), nullable(String.class)); - - ParceledListSlice<WifiConfiguration> configs = - mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID); - - assertEquals(0, configs.getList().size()); - - } - - /** - * Test that configured network list are exposed to an app that does have the - * appropriate permissions. - */ - @Test - public void testConfiguredNetworkListAreVisibleFromPermittedApp() throws Exception { - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(TEST_WIFI_CONFIGURATION_LIST); - - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - - mWifiServiceImpl.mClientModeImplChannel = mAsyncChannel; - - mLooper.startAutoDispatch(); - ParceledListSlice<WifiConfiguration> configs = - mWifiServiceImpl.getConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verify(mWifiConfigManager).getSavedNetworks(eq(Process.WIFI_UID)); - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - TEST_WIFI_CONFIGURATION_LIST, configs.getList()); - } - - - /** - * Test that privileged network list are exposed null to an app that does not have the - * appropriate permissions. - */ - @Test - public void testPrivilegedConfiguredNetworkListAreEmptyFromAppWithoutPermission() { - when(mWifiConfigManager.getConfiguredNetworksWithPasswords()) - .thenReturn(TEST_WIFI_CONFIGURATION_LIST); - - doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( - anyString(), nullable(String.class), anyInt(), nullable(String.class)); - - mLooper.startAutoDispatch(); - ParceledListSlice<WifiConfiguration> configs = - mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - assertNull(configs); - } - - /** - * Test that privileged network list are exposed null to an app that does not have the - * appropriate permissions, when enforceCanAccessScanResults raises a SecurityException. - */ - @Test - public void testPrivilegedConfiguredNetworkListAreEmptyOnSecurityException() { - when(mWifiConfigManager.getConfiguredNetworksWithPasswords()) - .thenReturn(TEST_WIFI_CONFIGURATION_LIST); - - doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( - anyString(), nullable(String.class), anyInt(), nullable(String.class)); - - mLooper.startAutoDispatch(); - ParceledListSlice<WifiConfiguration> configs = - mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - assertNull(configs); - } - - /** - * Test that privileged network list are exposed to an app that does have the - * appropriate permissions (simulated by not throwing an exception for READ_WIFI_CREDENTIAL). - */ - @Test - public void testPrivilegedConfiguredNetworkListAreVisibleFromPermittedApp() { - when(mWifiConfigManager.getConfiguredNetworksWithPasswords()) - .thenReturn(TEST_WIFI_CONFIGURATION_LIST); - - mLooper.startAutoDispatch(); - ParceledListSlice<WifiConfiguration> configs = - mWifiServiceImpl.getPrivilegedConfiguredNetworks(TEST_PACKAGE, TEST_FEATURE_ID); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( - TEST_WIFI_CONFIGURATION_LIST, configs.getList()); - } - - /** - * Test fetching of scan results. - */ - @Test - public void testGetScanResults() { - ScanResult[] scanResults = - ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0] - .getResults(); - List<ScanResult> scanResultList = - new ArrayList<>(Arrays.asList(scanResults)); - when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList); - - String packageName = "test.com"; - String featureId = "test.com.featureId"; - mLooper.startAutoDispatch(); - List<ScanResult> retrievedScanResultList = mWifiServiceImpl.getScanResults(packageName, - featureId); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mScanRequestProxy).getScanResults(); - - ScanTestUtil.assertScanResultsEquals(scanResults, - retrievedScanResultList.toArray(new ScanResult[retrievedScanResultList.size()])); - } - - /** - * Ensure that we handle scan results failure when posting the runnable to handler fails. - */ - @Test - public void testGetScanResultsFailureInRunWithScissors() { - mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut(); - - ScanResult[] scanResults = - ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0] - .getResults(); - List<ScanResult> scanResultList = - new ArrayList<>(Arrays.asList(scanResults)); - when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList); - - String packageName = "test.com"; - String featureId = "test.com.featureId"; - mLooper.startAutoDispatch(); - List<ScanResult> retrievedScanResultList = mWifiServiceImpl.getScanResults(packageName, - featureId); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mScanRequestProxy, never()).getScanResults(); - - assertTrue(retrievedScanResultList.isEmpty()); - } - - /** - * Test fetching of matching scan results with provided WifiNetworkSuggestion, but it doesn't - * specify the scan results to be filtered. - */ - @Test - public void testGetMatchingScanResultsWithoutSpecifiedScanResults() { - ScanResult[] scanResults = - ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0] - .getResults(); - List<ScanResult> scanResultList = - new ArrayList<>(Arrays.asList(scanResults)); - when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList); - WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class); - List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{ - add(mockSuggestion); - }}; - Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{ - put(mockSuggestion, scanResultList); - }}; - when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions), - eq(scanResultList))).thenReturn(result); - - String packageName = "test.com"; - String featureId = "test.com.featureId"; - mLooper.startAutoDispatch(); - Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults = - mWifiServiceImpl.getMatchingScanResults( - matchingSuggestions, null, packageName, featureId); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - ScanTestUtil.assertScanResultsEquals(scanResults, - retrievedScanResults.get(mockSuggestion) - .toArray(new ScanResult[retrievedScanResults.size()])); - } - - /** - * Test fetching of matching scan results with provided WifiNetworkSuggestion and ScanResults. - */ - @Test - public void testGetMatchingScanResultsWithSpecifiedScanResults() { - ScanResult[] scanResults = - ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0] - .getResults(); - List<ScanResult> scanResultList = - new ArrayList<>(Arrays.asList(scanResults)); - WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class); - List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{ - add(mockSuggestion); - }}; - Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{ - put(mockSuggestion, scanResultList); - }}; - when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions), - eq(scanResultList))).thenReturn(result); - - String packageName = "test.com"; - String featureId = "test.com.featureId"; - mLooper.startAutoDispatch(); - Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults = - mWifiServiceImpl.getMatchingScanResults( - matchingSuggestions, scanResultList, packageName, featureId); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - ScanTestUtil.assertScanResultsEquals(scanResults, - retrievedScanResults.get(mockSuggestion) - .toArray(new ScanResult[retrievedScanResults.size()])); - } - - /** - * Ensure that we handle failure when posting the runnable to handler fails. - */ - @Test - public void testGetMatchingScanResultsFailureInRunWithScissors() { - mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut(); - - ScanResult[] scanResults = - ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0] - .getResults(); - List<ScanResult> scanResultList = - new ArrayList<>(Arrays.asList(scanResults)); - when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList); - WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class); - List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{ - add(mockSuggestion); - }}; - Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{ - put(mockSuggestion, scanResultList); - }}; - when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions), - eq(scanResultList))).thenReturn(result); - - String packageName = "test.com"; - String featureId = "test.com.featureId"; - mLooper.startAutoDispatch(); - Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults = - mWifiServiceImpl.getMatchingScanResults( - matchingSuggestions, null, packageName, featureId); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - assertTrue(retrievedScanResults.isEmpty()); - } - - private void setupLohsPermissions() { - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mUserManager.hasUserRestrictionForUser( - eq(UserManager.DISALLOW_CONFIG_TETHERING), any())) - .thenReturn(false); - } - - private void registerLOHSRequestFull() { - setupLohsPermissions(); - int result = mWifiServiceImpl.startLocalOnlyHotspot(mLohsCallback, TEST_PACKAGE_NAME, - TEST_FEATURE_ID, null); - assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result); - verifyCheckChangePermission(TEST_PACKAGE_NAME); - } - - /** - * Verify that the call to startLocalOnlyHotspot returns REQUEST_REGISTERED when successfully - * called. - */ - @Test - public void testStartLocalOnlyHotspotSingleRegistrationReturnsRequestRegistered() { - registerLOHSRequestFull(); - } - - /** - * Verify that a call to startLocalOnlyHotspot throws a SecurityException if the caller does not - * have the CHANGE_WIFI_STATE permission. - */ - @Test(expected = SecurityException.class) - public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutCorrectPermission() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE), - eq("WifiService")); - mWifiServiceImpl.startLocalOnlyHotspot( - mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null); - } - - /** - * Verify that a call to startLocalOnlyHotspot throws a SecurityException if the caller does not - * have Location permission. - */ - @Test(expected = SecurityException.class) - public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationPermission() { - doThrow(new SecurityException()) - .when(mWifiPermissionsUtil).enforceLocationPermission(eq(TEST_PACKAGE_NAME), - eq(TEST_FEATURE_ID), - anyInt()); - mWifiServiceImpl.startLocalOnlyHotspot( - mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null); - } - - /** - * Verify that a call to startLocalOnlyHotspot throws a SecurityException if Location mode is - * disabled. - */ - @Test(expected = SecurityException.class) - public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationEnabled() { - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); - mWifiServiceImpl.startLocalOnlyHotspot( - mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null); - } - - /** - * Only start LocalOnlyHotspot if the caller is the foreground app at the time of the request. - */ - @Test - public void testStartLocalOnlyHotspotFailsIfRequestorNotForegroundApp() throws Exception { - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false); - int result = mWifiServiceImpl.startLocalOnlyHotspot( - mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null); - assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result); - } - - /** - * Only start tethering if we are not tethering. - */ - @Test - public void testTetheringDoesNotStartWhenAlreadyTetheringActive() throws Exception { - WifiConfiguration config = createValidWifiApConfiguration(); - assertTrue(mWifiServiceImpl.startSoftAp(config)); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - WifiConfigurationTestUtil.assertConfigurationEqualForSoftAp( - config, - mSoftApModeConfigCaptor.getValue().getSoftApConfiguration().toWifiConfiguration()); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - assertEquals(WIFI_AP_STATE_ENABLED, mWifiServiceImpl.getWifiApEnabledState()); - reset(mActiveModeWarden); - - // Start another session without a stop, that should fail. - assertFalse(mWifiServiceImpl.startSoftAp(createValidWifiApConfiguration())); - - verifyNoMoreInteractions(mActiveModeWarden); - } - - /** - * Only start tethering if we are not tethering in new API: startTetheredHotspot. - */ - @Test - public void testStartTetheredHotspotDoesNotStartWhenAlreadyTetheringActive() throws Exception { - SoftApConfiguration config = createValidSoftApConfiguration(); - assertTrue(mWifiServiceImpl.startTetheredHotspot(config)); - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - assertThat(config).isEqualTo(mSoftApModeConfigCaptor.getValue().getSoftApConfiguration()); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - assertEquals(WIFI_AP_STATE_ENABLED, mWifiServiceImpl.getWifiApEnabledState()); - reset(mActiveModeWarden); - - // Start another session without a stop, that should fail. - assertFalse(mWifiServiceImpl.startTetheredHotspot(config)); - - verifyNoMoreInteractions(mActiveModeWarden); - } - - /** - * Only start LocalOnlyHotspot if we are not tethering. - */ - @Test - public void testHotspotDoesNotStartWhenAlreadyTethering() throws Exception { - WifiConfiguration config = createValidWifiApConfiguration(); - assertTrue(mWifiServiceImpl.startSoftAp(config)); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); - - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - mLooper.dispatchAll(); - int returnCode = mWifiServiceImpl.startLocalOnlyHotspot( - mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null); - assertEquals(ERROR_INCOMPATIBLE_MODE, returnCode); - } - - /** - * Only start LocalOnlyHotspot if admin setting does not disallow tethering. - */ - @Test - public void testHotspotDoesNotStartWhenTetheringDisallowed() throws Exception { - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true); - when(mUserManager.hasUserRestrictionForUser( - eq(UserManager.DISALLOW_CONFIG_TETHERING), any())) - .thenReturn(true); - int returnCode = mWifiServiceImpl.startLocalOnlyHotspot( - mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null); - assertEquals(ERROR_TETHERING_DISALLOWED, returnCode); - } - - /** - * Verify that callers can only have one registered LOHS request. - */ - @Test(expected = IllegalStateException.class) - public void testStartLocalOnlyHotspotThrowsExceptionWhenCallerAlreadyRegistered() { - registerLOHSRequestFull(); - - // now do the second request that will fail - mWifiServiceImpl.startLocalOnlyHotspot( - mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null); - } - - /** - * Verify that the call to stopLocalOnlyHotspot does not do anything when there aren't any - * registered callers. - */ - @Test - public void testStopLocalOnlyHotspotDoesNothingWithoutRegisteredRequests() throws Exception { - // allow test to proceed without a permission check failure - mWifiServiceImpl.stopLocalOnlyHotspot(); - mLooper.dispatchAll(); - // there is nothing registered, so this shouldn't do anything - verify(mActiveModeWarden, never()).stopSoftAp(anyInt()); - } - - /** - * Verify that the call to stopLocalOnlyHotspot does not do anything when one caller unregisters - * but there is still an active request - */ - @Test - public void testStopLocalOnlyHotspotDoesNothingWithRemainingRequest() throws Exception { - // register a request that will remain after the stopLOHS call - mWifiServiceImpl.registerLOHSForTest(mPid, mRequestInfo); - - setupLocalOnlyHotspot(); - - // Since we are calling with the same pid, the second register call will be removed - mWifiServiceImpl.stopLocalOnlyHotspot(); - mLooper.dispatchAll(); - // there is still a valid registered request - do not tear down LOHS - verify(mActiveModeWarden, never()).stopSoftAp(anyInt()); - } - - /** - * Verify that the call to stopLocalOnlyHotspot sends a message to WifiController to stop - * the softAp when there is one registered caller when that caller is removed. - */ - @Test - public void testStopLocalOnlyHotspotTriggersStopWithOneRegisteredRequest() throws Exception { - setupLocalOnlyHotspot(); - - verify(mActiveModeWarden).startSoftAp(any()); - - mWifiServiceImpl.stopLocalOnlyHotspot(); - mLooper.dispatchAll(); - - // No permission check required for change_wifi_state. - verify(mContext, never()).enforceCallingOrSelfPermission( - eq("android.Manifest.permission.CHANGE_WIFI_STATE"), anyString()); - - // there is was only one request registered, we should tear down LOHS - verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - } - - /** - * Verify that by default startLocalOnlyHotspot starts access point at 2 GHz. - */ - @Test - public void testStartLocalOnlyHotspotAt2Ghz() { - registerLOHSRequestFull(); - verifyLohsBand(SoftApConfiguration.BAND_2GHZ); - } - - /** - * Verify that startLocalOnlyHotspot will start access point at 6 GHz if properly configured - * and if feasible, even if the 5GHz is enabled. - */ - @Test - public void testStartLocalOnlyHotspotAt6Ghz() { - when(mResources.getBoolean( - eq(R.bool.config_wifi_local_only_hotspot_5ghz))) - .thenReturn(true); - when(mResources.getBoolean( - eq(R.bool.config_wifiLocalOnlyHotspot6ghz))) - .thenReturn(true); - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ)).thenReturn(true); - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn(true); - when(mResources.getBoolean( - eq(R.bool.config_wifiSoftap6ghzSupported))) - .thenReturn(true); - when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(true); - - verify(mAsyncChannel).connect(any(), mHandlerCaptor.capture(), any(Handler.class)); - final Handler handler = mHandlerCaptor.getValue(); - handler.handleMessage(handler.obtainMessage( - AsyncChannel.CMD_CHANNEL_HALF_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL, 0)); - - mLooper.startAutoDispatch(); - registerLOHSRequestFull(); - verifyLohsBand(SoftApConfiguration.BAND_6GHZ); - } - - /** - * Verify that startLocalOnlyHotspot will start access point at 5 GHz if both 5GHz and 6GHz - * are enabled, but SoftAp is not supported for 6GHz. - */ - @Test - public void testStartLocalOnlyHotspotAt5Ghz() { - when(mResources.getBoolean( - eq(R.bool.config_wifi_local_only_hotspot_5ghz))) - .thenReturn(true); - when(mResources.getBoolean( - eq(R.bool.config_wifiLocalOnlyHotspot6ghz))) - .thenReturn(true); - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ)).thenReturn(true); - when(mClientModeImpl.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn(true); - when(mResources.getBoolean( - eq(R.bool.config_wifiSoftap6ghzSupported))) - .thenReturn(false); - when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(true); - - verify(mAsyncChannel).connect(any(), mHandlerCaptor.capture(), any(Handler.class)); - final Handler handler = mHandlerCaptor.getValue(); - handler.handleMessage(handler.obtainMessage( - AsyncChannel.CMD_CHANNEL_HALF_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL, 0)); - - mLooper.startAutoDispatch(); - registerLOHSRequestFull(); - verifyLohsBand(SoftApConfiguration.BAND_5GHZ); - } - - private void verifyLohsBand(int expectedBand) { - verify(mActiveModeWarden).startSoftAp(mSoftApModeConfigCaptor.capture()); - final SoftApConfiguration configuration = - mSoftApModeConfigCaptor.getValue().getSoftApConfiguration(); - assertNotNull(configuration); - assertEquals(expectedBand, configuration.getBand()); - } - - private static class FakeLohsCallback extends ILocalOnlyHotspotCallback.Stub { - boolean mIsStarted = false; - SoftApConfiguration mSoftApConfig = null; - - @Override - public void onHotspotStarted(SoftApConfiguration softApConfig) { - mIsStarted = true; - this.mSoftApConfig = softApConfig; - } - - @Override - public void onHotspotStopped() { - mIsStarted = false; - mSoftApConfig = null; - } - - @Override - public void onHotspotFailed(int i) { - mIsStarted = false; - mSoftApConfig = null; - } - } - - private void setupForCustomLohs() { - setupLohsPermissions(); - when(mContext.checkPermission(eq(Manifest.permission.NETWORK_SETUP_WIZARD), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - setupWardenForCustomLohs(); - } - - private void setupWardenForCustomLohs() { - doAnswer(invocation -> { - changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR); - mWifiServiceImpl.updateInterfaceIpState(mLohsInterfaceName, IFACE_IP_MODE_LOCAL_ONLY); - return null; - }).when(mActiveModeWarden).startSoftAp(any()); - } - - @Test(expected = SecurityException.class) - public void testCustomLohs_FailsWithoutPermission() { - SoftApConfiguration customConfig = new SoftApConfiguration.Builder() - .setSsid("customConfig") - .build(); - // set up basic permissions, but not NETWORK_SETUP_WIZARD - setupLohsPermissions(); - setupWardenForCustomLohs(); - mWifiServiceImpl.startLocalOnlyHotspot(mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, - customConfig); - } - - private static void nopDeathCallback(LocalOnlyHotspotRequestInfo requestor) { - } - - @Test - public void testCustomLohs_ExclusiveAfterShared() { - FakeLohsCallback sharedCallback = new FakeLohsCallback(); - FakeLohsCallback exclusiveCallback = new FakeLohsCallback(); - SoftApConfiguration exclusiveConfig = new SoftApConfiguration.Builder() - .setSsid("customSsid") - .build(); - - setupForCustomLohs(); - mWifiServiceImpl.registerLOHSForTest(mPid, new LocalOnlyHotspotRequestInfo( - sharedCallback, WifiServiceImplTest::nopDeathCallback, null)); - assertThat(mWifiServiceImpl.startLocalOnlyHotspot(exclusiveCallback, TEST_PACKAGE_NAME, - TEST_FEATURE_ID, exclusiveConfig)).isEqualTo(ERROR_GENERIC); - mLooper.dispatchAll(); - - assertThat(sharedCallback.mIsStarted).isTrue(); - assertThat(exclusiveCallback.mIsStarted).isFalse(); - } - - @Test - public void testCustomLohs_ExclusiveBeforeShared() { - FakeLohsCallback sharedCallback = new FakeLohsCallback(); - FakeLohsCallback exclusiveCallback = new FakeLohsCallback(); - SoftApConfiguration exclusiveConfig = new SoftApConfiguration.Builder() - .setSsid("customSsid") - .build(); - - setupForCustomLohs(); - mWifiServiceImpl.registerLOHSForTest(mPid, new LocalOnlyHotspotRequestInfo( - exclusiveCallback, WifiServiceImplTest::nopDeathCallback, exclusiveConfig)); - assertThat(mWifiServiceImpl.startLocalOnlyHotspot(sharedCallback, TEST_PACKAGE_NAME, - TEST_FEATURE_ID, null)).isEqualTo(ERROR_GENERIC); - mLooper.dispatchAll(); - - assertThat(exclusiveCallback.mIsStarted).isTrue(); - assertThat(sharedCallback.mIsStarted).isFalse(); - } - - @Test - public void testCustomLohs_Wpa2() { - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setSsid("customSsid") - .setPassphrase("passphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .build(); - FakeLohsCallback callback = new FakeLohsCallback(); - - setupForCustomLohs(); - assertThat( - mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, - config)).isEqualTo(REQUEST_REGISTERED); - mLooper.dispatchAll(); - - assertThat(callback.mIsStarted).isTrue(); - assertThat(callback.mSoftApConfig.getSsid()).isEqualTo("customSsid"); - assertThat(callback.mSoftApConfig.getSecurityType()) - .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertThat(callback.mSoftApConfig.getPassphrase()).isEqualTo("passphrase"); - } - - @Test - public void testCustomLohs_Open() { - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setSsid("customSsid") - .build(); - FakeLohsCallback callback = new FakeLohsCallback(); - - setupForCustomLohs(); - assertThat( - mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, - config)).isEqualTo(REQUEST_REGISTERED); - mLooper.dispatchAll(); - - assertThat(callback.mIsStarted).isTrue(); - assertThat(callback.mSoftApConfig.getSsid()).isEqualTo("customSsid"); - assertThat(callback.mSoftApConfig.getSecurityType()) - .isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN); - assertThat(callback.mSoftApConfig.getPassphrase()).isNull(); - } - - @Test - public void testCustomLohs_GeneratesSsidIfAbsent() { - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setPassphrase("passphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .build(); - FakeLohsCallback callback = new FakeLohsCallback(); - - setupForCustomLohs(); - assertThat( - mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, - config)).isEqualTo(REQUEST_REGISTERED); - mLooper.dispatchAll(); - - assertThat(callback.mIsStarted).isTrue(); - assertThat(callback.mSoftApConfig.getSsid()).isNotEmpty(); - } - - @Test - public void testCustomLohs_ForwardsBssid() { - SoftApConfiguration config = new SoftApConfiguration.Builder() - .setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")) - .build(); - FakeLohsCallback callback = new FakeLohsCallback(); - - setupForCustomLohs(); - assertThat( - mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, - config)).isEqualTo(REQUEST_REGISTERED); - mLooper.dispatchAll(); - - assertThat(callback.mIsStarted).isTrue(); - assertThat(callback.mSoftApConfig.getBssid().toString()) - .ignoringCase().isEqualTo("aa:bb:cc:dd:ee:ff"); - } - - /** - * Verify that WifiServiceImpl does not send the stop ap message if there were no - * pending LOHS requests upon a binder death callback. - */ - @Test - public void testServiceImplNotCalledWhenBinderDeathTriggeredNoRequests() { - LocalOnlyRequestorCallback binderDeathCallback = - mWifiServiceImpl.new LocalOnlyRequestorCallback(); - - binderDeathCallback.onLocalOnlyHotspotRequestorDeath(mRequestInfo); - verify(mActiveModeWarden, never()).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - } - - /** - * Verify that WifiServiceImpl does not send the stop ap message if there are remaining - * registered LOHS requests upon a binder death callback. Additionally verify that softap mode - * will be stopped if that remaining request is removed (to verify the binder death properly - * cleared the requestor that died). - */ - @Test - public void testServiceImplNotCalledWhenBinderDeathTriggeredWithRequests() throws Exception { - LocalOnlyRequestorCallback binderDeathCallback = - mWifiServiceImpl.new LocalOnlyRequestorCallback(); - - // registering a request directly from the test will not trigger a message to start - // softap mode - mWifiServiceImpl.registerLOHSForTest(mPid, mRequestInfo); - - setupLocalOnlyHotspot(); - - binderDeathCallback.onLocalOnlyHotspotRequestorDeath(mRequestInfo); - verify(mActiveModeWarden, never()).stopSoftAp(anyInt()); - - reset(mActiveModeWarden); - - // now stop as the second request and confirm CMD_SET_AP will be sent to make sure binder - // death requestor was removed - mWifiServiceImpl.stopLocalOnlyHotspot(); - mLooper.dispatchAll(); - verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - } - - /** - * Verify that a call to registerSoftApCallback throws a SecurityException if the caller does - * not have neither NETWORK_SETTINGS nor MAINLINE_NETWORK_STACK permission. - */ - @Test(expected = SecurityException.class) - public void registerSoftApCallbackThrowsSecurityExceptionOnMissingPermissions() { - when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS)) - .thenReturn(PackageManager.PERMISSION_DENIED); - when(mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)) - .thenReturn(PackageManager.PERMISSION_DENIED); - final int callbackIdentifier = 1; - mWifiServiceImpl.registerSoftApCallback( - mAppBinder, mClientSoftApCallback, callbackIdentifier); - } - - /** - * Verify that a call to registerSoftApCallback throws an IllegalArgumentException if the - * parameters are not provided. - */ - @Test - public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnInvalidArguments() { - try { - final int callbackIdentifier = 1; - mWifiServiceImpl.registerSoftApCallback(mAppBinder, null, callbackIdentifier); - fail("expected IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - } - } - - /** - * Verify that a call to unregisterSoftApCallback throws a SecurityException if the caller does - * not have neither NETWORK_SETTINGS nor MAINLINE_NETWORK_STACK permission. - */ - @Test(expected = SecurityException.class) - public void unregisterSoftApCallbackThrowsSecurityExceptionOnMissingPermissions() { - when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS)) - .thenReturn(PackageManager.PERMISSION_DENIED); - when(mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)) - .thenReturn(PackageManager.PERMISSION_DENIED); - final int callbackIdentifier = 1; - mWifiServiceImpl.unregisterSoftApCallback(callbackIdentifier); - } - - /** - * Verifies that we handle softap callback registration failure if we encounter an exception - * while linking to death. - */ - @Test - public void registerSoftApCallbackFailureOnLinkToDeath() throws Exception { - doThrow(new RemoteException()) - .when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - mWifiServiceImpl.registerSoftApCallback(mAppBinder, mClientSoftApCallback, 1); - mLooper.dispatchAll(); - verify(mClientSoftApCallback, never()).onStateChanged(WIFI_AP_STATE_DISABLED, 0); - verify(mClientSoftApCallback, never()).onConnectedClientsChanged(any()); - verify(mClientSoftApCallback, never()).onInfoChanged(any()); - verify(mClientSoftApCallback, never()).onCapabilityChanged(any()); - } - - - /** - * Registers a soft AP callback, then verifies that the current soft AP state and num clients - * are sent to caller immediately after callback is registered. - */ - private void registerSoftApCallbackAndVerify(ISoftApCallback callback, int callbackIdentifier) - throws Exception { - registerSoftApCallbackAndVerify(mAppBinder, callback, callbackIdentifier); - } - - /** - * Registers a soft AP callback, then verifies that the current soft AP state and num clients - * are sent to caller immediately after callback is registered. - */ - private void registerSoftApCallbackAndVerify(IBinder binder, ISoftApCallback callback, - int callbackIdentifier) throws Exception { - mWifiServiceImpl.registerSoftApCallback(binder, callback, callbackIdentifier); - mLooper.dispatchAll(); - verify(callback).onStateChanged(WIFI_AP_STATE_DISABLED, 0); - verify(callback).onConnectedClientsChanged(Mockito.<WifiClient>anyList()); - verify(callback).onInfoChanged(new SoftApInfo()); - verify(callback).onCapabilityChanged(ApConfigUtil.updateCapabilityFromResource(mContext)); - // Don't need to invoke callback when register. - verify(callback, never()).onBlockedClientConnecting(any(), anyInt()); - } - - /** - * Verify that registering twice with same callbackIdentifier will replace the first callback. - */ - @Test - public void replacesOldCallbackWithNewCallbackWhenRegisteringTwice() throws Exception { - final int callbackIdentifier = 1; - registerSoftApCallbackAndVerify(mAppBinder, mClientSoftApCallback, callbackIdentifier); - registerSoftApCallbackAndVerify( - mAnotherAppBinder, mAnotherSoftApCallback, callbackIdentifier); - - verify(mAppBinder).linkToDeath(any(), anyInt()); - verify(mAppBinder).unlinkToDeath(any(), anyInt()); - verify(mAnotherAppBinder).linkToDeath(any(), anyInt()); - verify(mAnotherAppBinder, never()).unlinkToDeath(any(), anyInt()); - - final WifiClient testClient = new WifiClient(TEST_FACTORY_MAC_ADDR); - final List<WifiClient> testClients = new ArrayList(); - testClients.add(testClient); - mStateMachineSoftApCallback.onConnectedClientsChanged(testClients); - mLooper.dispatchAll(); - // Verify only the second callback is being called - verify(mClientSoftApCallback, never()).onConnectedClientsChanged(testClients); - verify(mAnotherSoftApCallback).onConnectedClientsChanged(testClients); - } - - /** - * Verify that unregisterSoftApCallback removes callback from registered callbacks list - */ - @Test - public void unregisterSoftApCallbackRemovesCallback() throws Exception { - final int callbackIdentifier = 1; - registerSoftApCallbackAndVerify(mClientSoftApCallback, callbackIdentifier); - - mWifiServiceImpl.unregisterSoftApCallback(callbackIdentifier); - mLooper.dispatchAll(); - - final WifiClient testClient = new WifiClient(TEST_FACTORY_MAC_ADDR); - final List<WifiClient> testClients = new ArrayList(); - testClients.add(testClient); - mStateMachineSoftApCallback.onConnectedClientsChanged(testClients); - mLooper.dispatchAll(); - verify(mClientSoftApCallback, never()).onConnectedClientsChanged(testClients); - } - - /** - * Verify that unregisterSoftApCallback is no-op if callbackIdentifier not registered. - */ - @Test - public void unregisterSoftApCallbackDoesNotRemoveCallbackIfCallbackIdentifierNotMatching() - throws Exception { - final int callbackIdentifier = 1; - registerSoftApCallbackAndVerify(mClientSoftApCallback, callbackIdentifier); - - final int differentCallbackIdentifier = 2; - mWifiServiceImpl.unregisterSoftApCallback(differentCallbackIdentifier); - mLooper.dispatchAll(); - - final WifiClient testClient = new WifiClient(TEST_FACTORY_MAC_ADDR); - final List<WifiClient> testClients = new ArrayList(); - testClients.add(testClient); - mStateMachineSoftApCallback.onConnectedClientsChanged(testClients); - mLooper.dispatchAll(); - verify(mClientSoftApCallback).onConnectedClientsChanged(testClients); - } - - /** - * Registers two callbacks, remove one then verify the right callback is being called on events. - */ - @Test - public void correctCallbackIsCalledAfterAddingTwoCallbacksAndRemovingOne() throws Exception { - final int callbackIdentifier = 1; - WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77")); - mWifiServiceImpl.registerSoftApCallback(mAppBinder, mClientSoftApCallback, - callbackIdentifier); - mLooper.dispatchAll(); - - // Change state from default before registering the second callback - final List<WifiClient> testClients = new ArrayList(); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - mStateMachineSoftApCallback.onConnectedClientsChanged(testClients); - mStateMachineSoftApCallback.onInfoChanged(mTestSoftApInfo); - mStateMachineSoftApCallback.onBlockedClientConnecting(testWifiClient, 0); - - - // Register another callback and verify the new state is returned in the immediate callback - final int anotherUid = 2; - mWifiServiceImpl.registerSoftApCallback(mAppBinder, mAnotherSoftApCallback, anotherUid); - mLooper.dispatchAll(); - verify(mAnotherSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0); - verify(mAnotherSoftApCallback).onConnectedClientsChanged(testClients); - verify(mAnotherSoftApCallback).onInfoChanged(mTestSoftApInfo); - // Verify only first callback will receive onBlockedClientConnecting since it call after - // first callback register but before another callback register. - verify(mClientSoftApCallback).onBlockedClientConnecting(testWifiClient, 0); - verify(mAnotherSoftApCallback, never()).onBlockedClientConnecting(testWifiClient, 0); - - // unregister the fisrt callback - mWifiServiceImpl.unregisterSoftApCallback(callbackIdentifier); - mLooper.dispatchAll(); - - // Update soft AP state and verify the remaining callback receives the event - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_FAILED, - SAP_START_FAILURE_NO_CHANNEL); - mLooper.dispatchAll(); - verify(mClientSoftApCallback, never()).onStateChanged(WIFI_AP_STATE_FAILED, - SAP_START_FAILURE_NO_CHANNEL); - verify(mAnotherSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, - SAP_START_FAILURE_NO_CHANNEL); - } - - /** - * Verify that wifi service registers for callers BinderDeath event - */ - @Test - public void registersForBinderDeathOnRegisterSoftApCallback() throws Exception { - final int callbackIdentifier = 1; - registerSoftApCallbackAndVerify(mClientSoftApCallback, callbackIdentifier); - verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - } - - /** - * Verify that we un-register the soft AP callback on receiving BinderDied event. - */ - @Test - public void unregistersSoftApCallbackOnBinderDied() throws Exception { - ArgumentCaptor<IBinder.DeathRecipient> drCaptor = - ArgumentCaptor.forClass(IBinder.DeathRecipient.class); - final int callbackIdentifier = 1; - registerSoftApCallbackAndVerify(mClientSoftApCallback, callbackIdentifier); - verify(mAppBinder).linkToDeath(drCaptor.capture(), anyInt()); - - drCaptor.getValue().binderDied(); - mLooper.dispatchAll(); - verify(mAppBinder).unlinkToDeath(drCaptor.getValue(), 0); - - // Verify callback is removed from the list as well - final WifiClient testClient = new WifiClient(TEST_FACTORY_MAC_ADDR); - final List<WifiClient> testClients = new ArrayList(); - testClients.add(testClient); - mStateMachineSoftApCallback.onConnectedClientsChanged(testClients); - mLooper.dispatchAll(); - verify(mClientSoftApCallback, never()).onConnectedClientsChanged(testClients); - } - - /** - * Verify that soft AP callback is called on NumClientsChanged event - */ - @Test - public void callsRegisteredCallbacksOnConnectedClientsChangedEvent() throws Exception { - final int callbackIdentifier = 1; - registerSoftApCallbackAndVerify(mClientSoftApCallback, callbackIdentifier); - - final WifiClient testClient = new WifiClient(TEST_FACTORY_MAC_ADDR); - final List<WifiClient> testClients = new ArrayList(); - testClients.add(testClient); - mStateMachineSoftApCallback.onConnectedClientsChanged(testClients); - mLooper.dispatchAll(); - verify(mClientSoftApCallback).onConnectedClientsChanged(testClients); - } - - /** - * Verify that soft AP callback is called on SoftApStateChanged event - */ - @Test - public void callsRegisteredCallbacksOnSoftApStateChangedEvent() throws Exception { - final int callbackIdentifier = 1; - registerSoftApCallbackAndVerify(mClientSoftApCallback, callbackIdentifier); - - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - mLooper.dispatchAll(); - verify(mClientSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0); - } - - /** - * Verify that mSoftApState and mSoftApNumClients in WifiServiceImpl are being updated on soft - * Ap events, even when no callbacks are registered. - */ - @Test - public void updatesSoftApStateAndConnectedClientsOnSoftApEvents() throws Exception { - final List<WifiClient> testClients = new ArrayList(); - WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77")); - mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0); - mStateMachineSoftApCallback.onConnectedClientsChanged(testClients); - mStateMachineSoftApCallback.onInfoChanged(mTestSoftApInfo); - mStateMachineSoftApCallback.onBlockedClientConnecting(testWifiClient, 0); - - // Register callback after num clients and soft AP are changed. - final int callbackIdentifier = 1; - mWifiServiceImpl.registerSoftApCallback(mAppBinder, mClientSoftApCallback, - callbackIdentifier); - mLooper.dispatchAll(); - verify(mClientSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0); - verify(mClientSoftApCallback).onConnectedClientsChanged(testClients); - verify(mClientSoftApCallback).onInfoChanged(mTestSoftApInfo); - // Don't need to invoke callback when register. - verify(mClientSoftApCallback, never()).onBlockedClientConnecting(any(), anyInt()); - } - - private class IntentFilterMatcher implements ArgumentMatcher<IntentFilter> { - @Override - public boolean matches(IntentFilter filter) { - return filter.hasAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); - } - } - - /** - * Verify that onFailed is called for registered LOHS callers on SAP_START_FAILURE_GENERAL. - */ - @Test - public void testRegisteredCallbacksTriggeredOnSoftApFailureGeneric() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - - registerLOHSRequestFull(); - - changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_GENERAL); - mLooper.dispatchAll(); - - verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC); - } - - /** - * Verify that onFailed is called for registered LOHS callers on SAP_START_FAILURE_NO_CHANNEL. - */ - @Test - public void testRegisteredCallbacksTriggeredOnSoftApFailureNoChannel() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - - registerLOHSRequestFull(); - - changeLohsState(WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_NO_CHANNEL); - - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotFailed(ERROR_NO_CHANNEL); - } - - /** - * Common setup for starting a LOHS. - */ - private void setupLocalOnlyHotspot() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - - registerLOHSRequestFull(); - - changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR); - mWifiServiceImpl.updateInterfaceIpState(mLohsInterfaceName, IFACE_IP_MODE_LOCAL_ONLY); - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotStarted(any()); - } - - /** - * Verify that onStopped is called for registered LOHS callers when a callback is - * received with WIFI_AP_STATE_DISABLING and LOHS was active. - */ - @Test - public void testRegisteredCallbacksTriggeredOnSoftApDisabling() throws Exception { - setupLocalOnlyHotspot(); - - changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR); - - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotStopped(); - } - - - /** - * Verify that onStopped is called for registered LOHS callers when a callback is - * received with WIFI_AP_STATE_DISABLED and LOHS was enabled. - */ - @Test - public void testRegisteredCallbacksTriggeredOnSoftApDisabled() throws Exception { - setupLocalOnlyHotspot(); - - changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR); - - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotStopped(); - } - - /** - * Verify that no callbacks are called for registered LOHS callers when a callback is - * received and the softap started. - */ - @Test - public void testRegisteredCallbacksNotTriggeredOnSoftApStart() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - - registerLOHSRequestFull(); - - changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR); - - mLooper.dispatchAll(); - verifyZeroInteractions(ignoreStubs(mLohsCallback)); - } - - /** - * Verify that onStopped is called only once for registered LOHS callers when - * callbacks are received with WIFI_AP_STATE_DISABLING and - * WIFI_AP_STATE_DISABLED when LOHS was enabled. - */ - @Test - public void testRegisteredCallbacksTriggeredOnlyOnceWhenSoftApDisabling() throws Exception { - setupLocalOnlyHotspot(); - - changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR); - changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR); - - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotStopped(); - } - - /** - * Verify that onFailed is called only once for registered LOHS callers when - * callbacks are received with WIFI_AP_STATE_FAILED twice. - */ - @Test - public void testRegisteredCallbacksTriggeredOnlyOnceWhenSoftApFailsTwice() throws Exception { - setupLocalOnlyHotspot(); - - changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC); - changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC); - - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC); - } - - /** - * Verify that onFailed is called for all registered LOHS callers when - * callbacks are received with WIFI_AP_STATE_FAILED. - */ - @Test - public void testAllRegisteredCallbacksTriggeredWhenSoftApFails() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - - // make an additional request for this test - mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo); - - registerLOHSRequestFull(); - - changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC); - changeLohsState(WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC); - - verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC); - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC); - } - - /** - * Verify that onStopped is called for all registered LOHS callers when - * callbacks are received with WIFI_AP_STATE_DISABLED when LOHS was - * active. - */ - @Test - public void testAllRegisteredCallbacksTriggeredWhenSoftApStops() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - - mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo); - - registerLOHSRequestFull(); - - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY); - mLooper.dispatchAll(); - verify(mRequestInfo).sendHotspotStartedMessage(any()); - verify(mLohsCallback).onHotspotStarted(any()); - - reset(mRequestInfo); - clearInvocations(mLohsCallback); - - changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR); - changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR); - - verify(mRequestInfo).sendHotspotStoppedMessage(); - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotStopped(); - } - - /** - * Verify that onFailed is called for all registered LOHS callers when - * callbacks are received with WIFI_AP_STATE_DISABLED when LOHS was - * not active. - */ - @Test - public void testAllRegisteredCallbacksTriggeredWhenSoftApStopsLOHSNotActive() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - - verifyApRegistration(); - - mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo); - mWifiServiceImpl.registerLOHSForTest(TEST_PID2, mRequestInfo2); - - changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR); - changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR); - - verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC); - verify(mRequestInfo2).sendHotspotFailedMessage(ERROR_GENERIC); - } - - /** - * Verify that if we do not have registered LOHS requestors and we receive an update that LOHS - * is up and ready for use, we tell WifiController to tear it down. This can happen if softap - * mode fails to come up properly and we get an onFailed message for a tethering call and we - * had registered callers for LOHS. - */ - @Test - public void testLOHSReadyWithoutRegisteredRequestsStopsSoftApMode() { - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY); - mLooper.dispatchAll(); - - verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - } - - /** - * Verify that all registered LOHS requestors are notified via a HOTSPOT_STARTED message that - * the hotspot is up and ready to use. - */ - @Test - public void testRegisteredLocalOnlyHotspotRequestorsGetOnStartedCallbackWhenReady() - throws Exception { - registerLOHSRequestFull(); - - mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo); - - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY); - mLooper.dispatchAll(); - verify(mRequestInfo).sendHotspotStartedMessage(any(SoftApConfiguration.class)); - - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotStarted(notNull()); - } - - /** - * Verify that if a LOHS is already active, a new call to register a request will trigger the - * onStarted callback. - */ - @Test - public void testRegisterLocalOnlyHotspotRequestAfterAlreadyStartedGetsOnStartedCallback() - throws Exception { - mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo); - - changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR); - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY); - mLooper.dispatchAll(); - - registerLOHSRequestFull(); - - mLooper.dispatchAll(); - - verify(mLohsCallback).onHotspotStarted(any()); - } - - /** - * Verify that if a LOHS request is active and we receive an update with an ip mode - * configuration error, callers are notified via the onFailed callback with the generic - * error and are unregistered. - */ - @Test - public void testCallOnFailedLocalOnlyHotspotRequestWhenIpConfigFails() throws Exception { - setupLocalOnlyHotspot(); - reset(mActiveModeWarden); - - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_CONFIGURATION_ERROR); - mLooper.dispatchAll(); - - verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC); - verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - - clearInvocations(mLohsCallback); - - // send HOTSPOT_FAILED message should only happen once since the requestor should be - // unregistered - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_CONFIGURATION_ERROR); - mLooper.dispatchAll(); - verifyZeroInteractions(ignoreStubs(mLohsCallback)); - } - - /** - * Verify that softap mode is stopped for tethering if we receive an update with an ip mode - * configuration error. - */ - @Test - public void testStopSoftApWhenIpConfigFails() throws Exception { - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_CONFIGURATION_ERROR); - mLooper.dispatchAll(); - - verify(mActiveModeWarden).stopSoftAp(IFACE_IP_MODE_TETHERED); - } - - /** - * Verify that if a LOHS request is active and tethering starts, callers are notified on the - * incompatible mode and are unregistered. - */ - @Test - public void testCallOnFailedLocalOnlyHotspotRequestWhenTetheringStarts() throws Exception { - registerLOHSRequestFull(); - - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY); - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotStarted(any()); - clearInvocations(mLohsCallback); - - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - - verify(mLohsCallback).onHotspotFailed(ERROR_INCOMPATIBLE_MODE); - - // sendMessage should only happen once since the requestor should be unregistered - clearInvocations(mLohsCallback); - - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - verifyZeroInteractions(ignoreStubs(mLohsCallback)); - } - - /** - * Verify that if LOHS is disabled, a new call to register a request will not trigger the - * onStopped callback. - */ - @Test - public void testRegisterLocalOnlyHotspotRequestWhenStoppedDoesNotGetOnStoppedCallback() - throws Exception { - registerLOHSRequestFull(); - mLooper.dispatchAll(); - - verifyZeroInteractions(ignoreStubs(mLohsCallback)); - } - - /** - * Verify that if a LOHS was active and then stopped, a new call to register a request will - * not trigger the onStarted callback. - */ - @Test - public void testRegisterLocalOnlyHotspotRequestAfterStoppedNoOnStartedCallback() - throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verifyApRegistration(); - - // register a request so we don't drop the LOHS interface ip update - mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo); - changeLohsState(WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR); - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY); - mLooper.dispatchAll(); - - registerLOHSRequestFull(); - mLooper.dispatchAll(); - - verify(mLohsCallback).onHotspotStarted(any()); - - clearInvocations(mLohsCallback); - - // now stop the hotspot - changeLohsState(WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR); - changeLohsState(WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR); - mLooper.dispatchAll(); - verify(mLohsCallback).onHotspotStopped(); - - clearInvocations(mLohsCallback); - - // now register a new caller - they should not get the onStarted callback - ILocalOnlyHotspotCallback callback2 = mock(ILocalOnlyHotspotCallback.class); - when(callback2.asBinder()).thenReturn(mock(IBinder.class)); - - int result = mWifiServiceImpl.startLocalOnlyHotspot( - callback2, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null); - assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result); - mLooper.dispatchAll(); - - verify(mLohsCallback, never()).onHotspotStarted(any()); - } - - /** - * Verify that a call to startWatchLocalOnlyHotspot is only allowed from callers with the - * signature only NETWORK_SETTINGS permission. - * - * This test is expecting the permission check to enforce the permission and throw a - * SecurityException for callers without the permission. This exception should be bubbled up to - * the caller of startLocalOnlyHotspot. - */ - @Test(expected = SecurityException.class) - public void testStartWatchLocalOnlyHotspotNotApprovedCaller() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.startWatchLocalOnlyHotspot(mLohsCallback); - } - - /** - * Verify that the call to startWatchLocalOnlyHotspot throws the UnsupportedOperationException - * when called until the implementation is complete. - */ - @Test(expected = UnsupportedOperationException.class) - public void testStartWatchLocalOnlyHotspotNotSupported() { - mWifiServiceImpl.startWatchLocalOnlyHotspot(mLohsCallback); - } - - /** - * Verify that a call to stopWatchLocalOnlyHotspot is only allowed from callers with the - * signature only NETWORK_SETTINGS permission. - */ - @Test(expected = SecurityException.class) - public void testStopWatchLocalOnlyHotspotNotApprovedCaller() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.stopWatchLocalOnlyHotspot(); - } - - /** - * Verify that the call to stopWatchLocalOnlyHotspot throws the UnsupportedOperationException - * until the implementation is complete. - */ - @Test(expected = UnsupportedOperationException.class) - public void testStopWatchLocalOnlyHotspotNotSupported() { - mWifiServiceImpl.stopWatchLocalOnlyHotspot(); - } - - /** - * Verify that the call to addOrUpdateNetwork for installing Passpoint profile is redirected - * to the Passpoint specific API addOrUpdatePasspointConfiguration. - */ - @Test - public void testAddPasspointProfileViaAddNetwork() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork(); - config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - - PackageManager pm = mock(PackageManager.class); - when(mContext.getPackageManager()).thenReturn(pm); - when(pm.getApplicationInfoAsUser(any(), anyInt(), any())).thenReturn(mApplicationInfo); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.R), anyInt())).thenReturn(true); - - when(mPasspointManager.addOrUpdateProvider( - any(PasspointConfiguration.class), anyInt(), eq(TEST_PACKAGE_NAME), eq(false), - eq(true))).thenReturn(true); - mLooper.startAutoDispatch(); - assertEquals(0, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mPasspointManager).addOrUpdateProvider( - any(PasspointConfiguration.class), anyInt(), eq(TEST_PACKAGE_NAME), eq(false), - eq(true)); - reset(mPasspointManager); - - when(mPasspointManager.addOrUpdateProvider( - any(PasspointConfiguration.class), anyInt(), eq(TEST_PACKAGE_NAME), anyBoolean(), - anyBoolean())).thenReturn(false); - mLooper.startAutoDispatch(); - assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mPasspointManager).addOrUpdateProvider( - any(PasspointConfiguration.class), anyInt(), eq(TEST_PACKAGE_NAME), anyBoolean(), - anyBoolean()); - } - - /** - * Verify that the call to getAllMatchingPasspointProfilesForScanResults is not redirected to - * specific API getAllMatchingPasspointProfilesForScanResults when the caller doesn't have - * NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testGetAllMatchingPasspointProfilesForScanResultsWithoutPermissions() { - mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(new ArrayList<>()); - } - - /** - * Verify that the call to getAllMatchingPasspointProfilesForScanResults is redirected to - * specific API getAllMatchingPasspointProfilesForScanResults when the caller have - * NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD. - */ - @Test - public void testGetAllMatchingPasspointProfilesForScanResultsWithPermissions() { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(createScanResultList()); - mLooper.dispatchAll(); - verify(mPasspointManager).getAllMatchingPasspointProfilesForScanResults(any()); - } - - /** - * Verify that the call to getAllMatchingPasspointProfilesForScanResults is not redirected to - * specific API getAllMatchingPasspointProfilesForScanResults when the caller provider invalid - * ScanResult. - */ - @Test - public void testGetAllMatchingPasspointProfilesForScanResultsWithInvalidScanResult() { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(new ArrayList<>()); - mLooper.dispatchAll(); - verify(mPasspointManager, never()).getAllMatchingPasspointProfilesForScanResults(any()); - } - - /** - * Verify that the call to getWifiConfigsForPasspointProfiles is not redirected to specific API - * syncGetWifiConfigsForPasspointProfiles when the caller doesn't have NETWORK_SETTINGS - * permissions and NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testGetWifiConfigsForPasspointProfilesWithoutPermissions() { - mWifiServiceImpl.getWifiConfigsForPasspointProfiles(new ArrayList<>()); - } - - /** - * Verify that the call to getMatchingOsuProviders is not redirected to specific API - * syncGetMatchingOsuProviders when the caller doesn't have NETWORK_SETTINGS - * permissions and NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testGetMatchingOsuProvidersWithoutPermissions() { - mWifiServiceImpl.getMatchingOsuProviders(new ArrayList<>()); - } - - /** - * Verify that the call to getMatchingOsuProviders is redirected to specific API - * syncGetMatchingOsuProviders when the caller have NETWORK_SETTINGS - * permissions and NETWORK_SETUP_WIZARD. - */ - @Test - public void testGetMatchingOsuProvidersWithPermissions() { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl.getMatchingOsuProviders(createScanResultList()); - mLooper.dispatchAll(); - verify(mPasspointManager).getMatchingOsuProviders(any()); - } - - /** - * Verify that the call to getMatchingOsuProviders is not redirected to specific API - * syncGetMatchingOsuProviders when the caller provider invalid ScanResult - */ - @Test - public void testGetMatchingOsuProvidersWithInvalidScanResult() { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl.getMatchingOsuProviders(new ArrayList<>()); - mLooper.dispatchAll(); - verify(mPasspointManager, never()).getMatchingOsuProviders(any()); - } - - /** - * Verify that the call to getMatchingPasspointConfigsForOsuProviders is not redirected to - * specific API syncGetMatchingPasspointConfigsForOsuProviders when the caller doesn't have - * NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testGetMatchingPasspointConfigsForOsuProvidersWithoutPermissions() { - mWifiServiceImpl.getMatchingPasspointConfigsForOsuProviders(new ArrayList<>()); - } - - /** - * Verify that the call to startSubscriptionProvisioning is redirected to the Passpoint - * specific API startSubscriptionProvisioning when the caller has the right permissions. - */ - @Test - public void testStartSubscriptionProvisioningWithPermission() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - - mWifiServiceImpl.startSubscriptionProvisioning(mOsuProvider, mProvisioningCallback); - verify(mClientModeImpl).syncStartSubscriptionProvisioning(anyInt(), - eq(mOsuProvider), eq(mProvisioningCallback), any()); - } - - /** - * Verify that the call to startSubscriptionProvisioning is not redirected to the Passpoint - * specific API startSubscriptionProvisioning when the caller provides invalid arguments - */ - @Test(expected = IllegalArgumentException.class) - public void testStartSubscriptionProvisioningWithInvalidProvider() throws Exception { - mWifiServiceImpl.startSubscriptionProvisioning(null, mProvisioningCallback); - } - - - /** - * Verify that the call to startSubscriptionProvisioning is not redirected to the Passpoint - * specific API startSubscriptionProvisioning when the caller provides invalid callback - */ - @Test(expected = IllegalArgumentException.class) - public void testStartSubscriptionProvisioningWithInvalidCallback() throws Exception { - mWifiServiceImpl.startSubscriptionProvisioning(mOsuProvider, null); - } - - /** - * Verify that the call to startSubscriptionProvisioning is not redirected to the Passpoint - * specific API startSubscriptionProvisioning when the caller doesn't have NETWORK_SETTINGS - * permissions and NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testStartSubscriptionProvisioningWithoutPermissions() throws Exception { - when(mContext.checkCallingOrSelfPermission( - eq(android.Manifest.permission.NETWORK_SETTINGS))).thenReturn( - PackageManager.PERMISSION_DENIED); - when(mContext.checkSelfPermission( - eq(android.Manifest.permission.NETWORK_SETUP_WIZARD))).thenReturn( - PackageManager.PERMISSION_DENIED); - - mWifiServiceImpl.startSubscriptionProvisioning(mOsuProvider, mProvisioningCallback); - } - - /** - * Verify the call to getPasspointConfigurations when the caller doesn't have - * NETWORK_SETTINGS and NETWORK_SETUP_WIZARD permissions. - */ - @Test - public void testGetPasspointConfigurationsWithOutPrivilegedPermissions() { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false); - - mLooper.startAutoDispatch(); - mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE_NAME); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager).getProviderConfigs(Binder.getCallingUid(), false); - } - - /** - * Verify that the call to getPasspointConfigurations when the caller does have - * NETWORK_SETTINGS permission. - */ - @Test - public void testGetPasspointConfigurationsWithPrivilegedPermissions() { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - - mLooper.startAutoDispatch(); - mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE_NAME); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager).getProviderConfigs(Binder.getCallingUid(), true); - } - - /** - * Verify that GetPasspointConfigurations will redirect calls to {@link PasspointManager} - * and returning the result that's returned from {@link PasspointManager}. - */ - @Test - public void testGetPasspointConfigurations() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - - // Setup expected configs. - List<PasspointConfiguration> expectedConfigs = new ArrayList<>(); - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn("test.com"); - config.setHomeSp(homeSp); - expectedConfigs.add(config); - - when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) - .thenReturn(expectedConfigs); - mLooper.startAutoDispatch(); - assertEquals(expectedConfigs, mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - reset(mPasspointManager); - - when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) - .thenReturn(new ArrayList<PasspointConfiguration>()); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE).isEmpty()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - } - - /** - * Verify the call to removePasspointConfigurations when the caller doesn't have - * NETWORK_SETTINGS and NETWORK_CARRIER_PROVISIONING permissions. - */ - @Test - public void testRemovePasspointConfigurationWithOutPrivilegedPermissions() { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())).thenReturn( - false); - - mLooper.startAutoDispatch(); - mWifiServiceImpl.removePasspointConfiguration(TEST_FQDN, TEST_PACKAGE_NAME); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager).removeProvider(Binder.getCallingUid(), false, null, - TEST_FQDN); - } - - /** - * Verify the call to removePasspointConfigurations when the caller does have - * NETWORK_CARRIER_PROVISIONING permission. - */ - @Test - public void testRemovePasspointConfigurationWithPrivilegedPermissions() { - when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())).thenReturn( - true); - - mLooper.startAutoDispatch(); - mWifiServiceImpl.removePasspointConfiguration(TEST_FQDN, TEST_PACKAGE_NAME); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager).removeProvider(Binder.getCallingUid(), true, null, - TEST_FQDN); - } - - /** - * Verify that a call to {@link WifiServiceImpl#restoreBackupData(byte[])} is only allowed from - * callers with the signature only NETWORK_SETTINGS permission. - */ - @Test(expected = SecurityException.class) - public void testRestoreBackupDataNotApprovedCaller() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.restoreBackupData(null); - verify(mWifiBackupRestore, never()).retrieveConfigurationsFromBackupData(any(byte[].class)); - } - - /** - * Verify that a call to {@link WifiServiceImpl#restoreSupplicantBackupData(byte[], byte[])} is - * only allowed from callers with the signature only NETWORK_SETTINGS permission. - */ - @Test(expected = SecurityException.class) - public void testRestoreSupplicantBackupDataNotApprovedCaller() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.restoreSupplicantBackupData(null, null); - verify(mWifiBackupRestore, never()).retrieveConfigurationsFromSupplicantBackupData( - any(byte[].class), any(byte[].class)); - } - - /** - * Verify that a call to {@link WifiServiceImpl#retrieveBackupData()} is only allowed from - * callers with the signature only NETWORK_SETTINGS permission. - */ - @Test(expected = SecurityException.class) - public void testRetrieveBackupDataNotApprovedCaller() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.retrieveBackupData(); - verify(mWifiBackupRestore, never()).retrieveBackupDataFromConfigurations(any(List.class)); - } - - /** - * Verify that a call to {@link WifiServiceImpl#restoreSoftApBackupData(byte[])} - * is only allowed from callers with the signature only NETWORK_SETTINGS permission. - */ - @Test(expected = SecurityException.class) - public void testRestoreSoftApBackupDataNotApprovedCaller() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.restoreSoftApBackupData(null); - verify(mSoftApBackupRestore, never()) - .retrieveSoftApConfigurationFromBackupData(any(byte[].class)); - } - - /** - * Verify that a call to {@link WifiServiceImpl#retrieveSoftApBackupData()} is only allowed from - * callers with the signature only NETWORK_SETTINGS permission. - */ - @Test(expected = SecurityException.class) - public void testRetrieveSoftApBackupDataNotApprovedCaller() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.retrieveSoftApBackupData(); - verify(mSoftApBackupRestore, never()) - .retrieveBackupDataFromSoftApConfiguration(any(SoftApConfiguration.class)); - } - - /** - * Verify that a call to {@link WifiServiceImpl#enableVerboseLogging(int)} is allowed from - * callers with the signature only NETWORK_SETTINGS permission. - */ - @Test - public void testEnableVerboseLoggingWithNetworkSettingsPermission() { - doNothing().when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - // Vebose logging is enabled first in the constructor for WifiServiceImpl, so reset - // before invocation. - reset(mClientModeImpl); - mWifiServiceImpl.enableVerboseLogging(1); - verify(mWifiSettingsConfigStore).put(WIFI_VERBOSE_LOGGING_ENABLED, true); - verify(mClientModeImpl).enableVerboseLogging(anyInt()); - } - - /** - * Verify that a call to {@link WifiServiceImpl#enableVerboseLogging(int)} is not allowed from - * callers without the signature only NETWORK_SETTINGS permission. - */ - @Test(expected = SecurityException.class) - public void testEnableVerboseLoggingWithNoNetworkSettingsPermission() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - // Vebose logging is enabled first in the constructor for WifiServiceImpl, so reset - // before invocation. - reset(mClientModeImpl); - mWifiServiceImpl.enableVerboseLogging(1); - verify(mWifiSettingsConfigStore, never()).put( - WIFI_VERBOSE_LOGGING_ENABLED, anyBoolean()); - verify(mClientModeImpl, never()).enableVerboseLogging(anyInt()); - } - - /** - * Verify that the CONNECT_NETWORK message received from an app without - * one of the privileged permission is rejected with a security exception. - */ - @Test - public void testConnectNetworkWithoutPrivilegedPermission() throws Exception { - try { - mWifiServiceImpl.connect(mock(WifiConfiguration.class), TEST_NETWORK_ID, - mock(Binder.class), - mock(IActionListener.class), 0); - fail(); - } catch (SecurityException e) { - verify(mClientModeImpl, never()).connect(any(WifiConfiguration.class), anyInt(), - any(Binder.class), any(IActionListener.class), anyInt(), anyInt()); - } - } - - /** - * Verify that the FORGET_NETWORK message received from an app without - * one of the privileged permission is rejected with a security exception. - */ - @Test - public void testForgetNetworkWithoutPrivilegedPermission() throws Exception { - try { - mWifiServiceImpl.forget(TEST_NETWORK_ID, mock(Binder.class), - mock(IActionListener.class), 0); - fail(); - } catch (SecurityException e) { - verify(mClientModeImpl, never()).forget(anyInt(), any(Binder.class), - any(IActionListener.class), anyInt(), anyInt()); - } - } - - /** - * Verify that the SAVE_NETWORK message received from an app without - * one of the privileged permission is rejected with a security exception. - */ - @Test - public void testSaveNetworkWithoutPrivilegedPermission() throws Exception { - try { - mWifiServiceImpl.save(mock(WifiConfiguration.class), mock(Binder.class), - mock(IActionListener.class), 0); - fail(); - } catch (SecurityException e) { - verify(mClientModeImpl, never()).save(any(WifiConfiguration.class), - any(Binder.class), any(IActionListener.class), anyInt(), anyInt()); - } - } - - /** - * Verify that the CONNECT_NETWORK message received from an app with - * one of the privileged permission is forwarded to ClientModeImpl. - */ - @Test - public void testConnectNetworkWithPrivilegedPermission() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - mWifiServiceImpl.connect(mock(WifiConfiguration.class), TEST_NETWORK_ID, - mock(Binder.class), - mock(IActionListener.class), 0); - verify(mClientModeImpl).connect(any(WifiConfiguration.class), anyInt(), - any(Binder.class), any(IActionListener.class), anyInt(), anyInt()); - verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK), - anyInt()); - } - - /** - * Verify that the SAVE_NETWORK message received from an app with - * one of the privileged permission is forwarded to ClientModeImpl. - */ - @Test - public void testSaveNetworkWithPrivilegedPermission() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - mWifiServiceImpl.save(mock(WifiConfiguration.class), mock(Binder.class), - mock(IActionListener.class), 0); - verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK), - anyInt()); - verify(mClientModeImpl).save(any(WifiConfiguration.class), - any(Binder.class), any(IActionListener.class), anyInt(), anyInt()); - } - - /** - * Verify that the FORGET_NETWORK message received from an app with - * one of the privileged permission is forwarded to ClientModeImpl. - */ - @Test - public void testForgetNetworkWithPrivilegedPermission() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - mWifiServiceImpl.forget(TEST_NETWORK_ID, mock(Binder.class), mock(IActionListener.class), - 0); - - InOrder inOrder = inOrder(mClientModeImpl, mWifiMetrics); - inOrder.verify(mWifiMetrics).logUserActionEvent( - UserActionEvent.EVENT_FORGET_WIFI, TEST_NETWORK_ID); - inOrder.verify(mClientModeImpl).forget(anyInt(), any(Binder.class), - any(IActionListener.class), anyInt(), anyInt()); - } - - /** - * Tests the scenario when a scan request arrives while the device is idle. In this case - * the scan is done when idle mode ends. - */ - @Test - public void testHandleDelayedScanAfterIdleMode() throws Exception { - when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); - when(mWifiInjector.getPasspointProvisionerHandlerThread()) - .thenReturn(mock(HandlerThread.class)); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - mWifiServiceImpl.handleBootCompleted(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - (IntentFilter) argThat(new IdleModeIntentMatcher())); - - // Tell the wifi service that the device became idle. - when(mPowerManager.isDeviceIdleMode()).thenReturn(true); - TestUtil.sendIdleModeChanged(mBroadcastReceiverCaptor.getValue(), mContext); - mLooper.dispatchAll(); - - // Send a scan request while the device is idle. - mLooper.startAutoDispatch(); - assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - // No scans must be made yet as the device is idle. - verify(mScanRequestProxy, never()).startScan(Process.myUid(), SCAN_PACKAGE_NAME); - - // Tell the wifi service that idle mode ended. - when(mPowerManager.isDeviceIdleMode()).thenReturn(false); - TestUtil.sendIdleModeChanged(mBroadcastReceiverCaptor.getValue(), mContext); - mLooper.dispatchAll(); - - // Must scan now. - verify(mScanRequestProxy).startScan(Process.myUid(), TEST_PACKAGE_NAME); - // The app ops check is executed with this package's identity (not the identity of the - // original remote caller who requested the scan while idle). - verify(mAppOpsManager).noteOp( - AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - - // Send another scan request. The device is not idle anymore, so it must be executed - // immediately. - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mScanRequestProxy).startScan(Process.myUid(), SCAN_PACKAGE_NAME); - } - - /** - * Verify that if the caller has NETWORK_SETTINGS permission, then it doesn't need - * CHANGE_WIFI_STATE permission. - */ - @Test - public void testDisconnectWithNetworkSettingsPerm() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - android.Manifest.permission.CHANGE_WIFI_STATE, "WifiService"); - doThrow(new SecurityException()).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - assertTrue(mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME)); - verify(mClientModeImpl).disconnectCommand(); - } - - /** - * Verify that if the caller doesn't have NETWORK_SETTINGS permission, it could still - * get access with the CHANGE_WIFI_STATE permission. - */ - @Test - public void testDisconnectWithChangeWifiStatePerm() throws Exception { - assertFalse(mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME)); - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mClientModeImpl, never()).disconnectCommand(); - } - - /** - * Verify that the operation fails if the caller has neither NETWORK_SETTINGS or - * CHANGE_WIFI_STATE permissions. - */ - @Test - public void testDisconnectRejected() throws Exception { - doThrow(new SecurityException()).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - try { - mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME); - fail(); - } catch (SecurityException e) { - - } - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mClientModeImpl, never()).disconnectCommand(); - } - - @Test - public void testPackageFullyRemovedBroadcastHandling() throws Exception { - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED) - && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED) - && filter.hasAction(Intent.ACTION_PACKAGE_CHANGED))); - int uid = TEST_UID; - String packageName = TEST_PACKAGE_NAME; - doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager) - .getApplicationInfo(TEST_PACKAGE_NAME, 0); - // Send the broadcast - Intent intent = new Intent(Intent.ACTION_PACKAGE_FULLY_REMOVED); - intent.putExtra(Intent.EXTRA_UID, uid); - intent.setData(Uri.fromParts("package", packageName, "")); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - mLooper.dispatchAll(); - - ArgumentCaptor<ApplicationInfo> aiCaptor = ArgumentCaptor.forClass(ApplicationInfo.class); - verify(mWifiConfigManager).removeNetworksForApp(aiCaptor.capture()); - assertNotNull(aiCaptor.getValue()); - assertEquals(uid, aiCaptor.getValue().uid); - assertEquals(packageName, aiCaptor.getValue().packageName); - - verify(mScanRequestProxy).clearScanRequestTimestampsForApp(packageName, uid); - verify(mWifiNetworkSuggestionsManager).removeApp(packageName); - verify(mClientModeImpl).removeNetworkRequestUserApprovedAccessPointsForApp(packageName); - verify(mPasspointManager).removePasspointProviderWithPackage(packageName); - } - - @Test - public void testPackageRemovedBroadcastHandling() throws Exception { - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED) - && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED) - && filter.hasAction(Intent.ACTION_PACKAGE_CHANGED))); - int uid = TEST_UID; - String packageName = TEST_PACKAGE_NAME; - // Send the broadcast - Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED); - intent.putExtra(Intent.EXTRA_UID, uid); - intent.setData(Uri.fromParts("package", packageName, "")); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - mLooper.dispatchAll(); - - ArgumentCaptor<ApplicationInfo> aiCaptor = ArgumentCaptor.forClass(ApplicationInfo.class); - verify(mWifiConfigManager).removeNetworksForApp(aiCaptor.capture()); - assertNotNull(aiCaptor.getValue()); - assertEquals(uid, aiCaptor.getValue().uid); - assertEquals(packageName, aiCaptor.getValue().packageName); - - verify(mScanRequestProxy).clearScanRequestTimestampsForApp(packageName, uid); - verify(mWifiNetworkSuggestionsManager).removeApp(packageName); - verify(mClientModeImpl).removeNetworkRequestUserApprovedAccessPointsForApp(packageName); - verify(mPasspointManager).removePasspointProviderWithPackage(packageName); - } - - @Test - public void testPackageDisableBroadcastHandling() throws Exception { - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED) - && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED) - && filter.hasAction(Intent.ACTION_PACKAGE_CHANGED))); - int uid = TEST_UID; - String packageName = TEST_PACKAGE_NAME; - mPackageInfo.applicationInfo = mApplicationInfo; - mApplicationInfo.enabled = false; - // Send the broadcast - Intent intent = new Intent(Intent.ACTION_PACKAGE_CHANGED); - intent.putExtra(Intent.EXTRA_UID, uid); - intent.setData(Uri.fromParts("package", packageName, "")); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - mLooper.dispatchAll(); - - ArgumentCaptor<ApplicationInfo> aiCaptor = ArgumentCaptor.forClass(ApplicationInfo.class); - verify(mWifiConfigManager).removeNetworksForApp(aiCaptor.capture()); - assertNotNull(aiCaptor.getValue()); - assertEquals(uid, aiCaptor.getValue().uid); - assertEquals(packageName, aiCaptor.getValue().packageName); - - verify(mScanRequestProxy).clearScanRequestTimestampsForApp(packageName, uid); - verify(mWifiNetworkSuggestionsManager).removeApp(packageName); - verify(mClientModeImpl).removeNetworkRequestUserApprovedAccessPointsForApp(packageName); - verify(mPasspointManager).removePasspointProviderWithPackage(packageName); - } - - @Test - public void testPackageRemovedBroadcastHandlingWithNoUid() { - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED))); - - String packageName = TEST_PACKAGE_NAME; - // Send the broadcast - Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED); - intent.setData(Uri.fromParts("package", packageName, "")); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - - verify(mWifiConfigManager, never()).removeNetworksForApp(any()); - - mLooper.dispatchAll(); - verify(mScanRequestProxy, never()).clearScanRequestTimestampsForApp(anyString(), anyInt()); - verify(mWifiNetworkSuggestionsManager, never()).removeApp(anyString()); - verify(mClientModeImpl, never()).removeNetworkRequestUserApprovedAccessPointsForApp( - packageName); - verify(mPasspointManager, never()).removePasspointProviderWithPackage(anyString()); - } - - @Test - public void testPackageRemovedBroadcastHandlingWithNoPackageName() { - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED))); - - int uid = TEST_UID; - // Send the broadcast - Intent intent = new Intent(Intent.ACTION_PACKAGE_FULLY_REMOVED); - intent.putExtra(Intent.EXTRA_UID, uid); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - - verify(mWifiConfigManager, never()).removeNetworksForApp(any()); - - mLooper.dispatchAll(); - verify(mScanRequestProxy, never()).clearScanRequestTimestampsForApp(anyString(), anyInt()); - verify(mWifiNetworkSuggestionsManager, never()).removeApp(anyString()); - verify(mClientModeImpl, never()).removeNetworkRequestUserApprovedAccessPointsForApp( - anyString()); - verify(mPasspointManager, never()).removePasspointProviderWithPackage(anyString()); - } - - @Test - public void testUserRemovedBroadcastHandling() { - when(mWifiInjector.getPasspointProvisionerHandlerThread()) - .thenReturn(mock(HandlerThread.class)); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - mWifiServiceImpl.handleBootCompleted(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(Intent.ACTION_USER_REMOVED))); - - UserHandle userHandle = UserHandle.of(TEST_USER_HANDLE); - // Send the broadcast - Intent intent = new Intent(Intent.ACTION_USER_REMOVED); - intent.putExtra(Intent.EXTRA_USER, userHandle); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - mLooper.dispatchAll(); - - verify(mWifiConfigManager).removeNetworksForUser(userHandle.getIdentifier()); - } - - @Test - public void testUserRemovedBroadcastHandlingWithWrongIntentAction() { - when(mWifiInjector.getPasspointProvisionerHandlerThread()) - .thenReturn(mock(HandlerThread.class)); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - mWifiServiceImpl.handleBootCompleted(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(Intent.ACTION_USER_REMOVED))); - - UserHandle userHandle = UserHandle.of(TEST_USER_HANDLE); - // Send the broadcast with wrong action - Intent intent = new Intent(Intent.ACTION_USER_FOREGROUND); - intent.putExtra(Intent.EXTRA_USER, userHandle); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - - verify(mWifiConfigManager, never()).removeNetworksForUser(anyInt()); - } - - private class IdleModeIntentMatcher implements ArgumentMatcher<IntentFilter> { - @Override - public boolean matches(IntentFilter filter) { - return filter.hasAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - } - } - - /** - * Verifies that enforceChangePermission(String package) is called and the caller doesn't - * have NETWORK_SETTINGS permission - */ - private void verifyCheckChangePermission(String callingPackageName) { - verify(mContext, atLeastOnce()) - .checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt()); - verify(mContext, atLeastOnce()).enforceCallingOrSelfPermission( - android.Manifest.permission.CHANGE_WIFI_STATE, "WifiService"); - verify(mAppOpsManager, atLeastOnce()).noteOp( - AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), callingPackageName); - } - - private WifiConfiguration createValidWifiApConfiguration() { - WifiConfiguration apConfig = new WifiConfiguration(); - apConfig.SSID = "TestAp"; - apConfig.preSharedKey = "thisIsABadPassword"; - apConfig.allowedKeyManagement.set(KeyMgmt.WPA2_PSK); - apConfig.apBand = WifiConfiguration.AP_BAND_2GHZ; - - return apConfig; - } - - private SoftApConfiguration createValidSoftApConfiguration() { - return new SoftApConfiguration.Builder() - .setSsid("TestAp") - .setPassphrase("thisIsABadPassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .setBand(SoftApConfiguration.BAND_2GHZ) - .build(); - } - - /** - * Verifies that sim state change does not set or reset the country code - */ - @Test - public void testSimStateChangeDoesNotResetCountryCode() { - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - (IntentFilter) argThat((IntentFilter filter) -> - filter.hasAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED))); - - int userHandle = TEST_USER_HANDLE; - // Send the broadcast - Intent intent = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED); - intent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - verifyNoMoreInteractions(mWifiCountryCode); - } - - /** - * Verifies that sim state change does not set or reset the country code - */ - @Test - public void testSimStateChangeDoesNotResetCountryCodeForRebroadcastedIntent() { - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - (IntentFilter) argThat((IntentFilter filter) -> - filter.hasAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED))); - - int userHandle = TEST_USER_HANDLE; - // Send the broadcast - Intent intent = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED); - intent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle); - intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, Intent.SIM_STATE_ABSENT); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - verifyNoMoreInteractions(mWifiCountryCode); - } - - /** - * Verifies that entering airplane mode does not reset country code. - */ - @Test - public void testEnterAirplaneModeNotResetCountryCode() { - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - (IntentFilter) argThat((IntentFilter filter) -> - filter.hasAction(Intent.ACTION_AIRPLANE_MODE_CHANGED))); - - when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); - - // Send the broadcast - Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - - verifyNoMoreInteractions(mWifiCountryCode); - } - - /** - * Verify that a call to registerTrafficStateCallback throws a SecurityException if the caller - * does not have NETWORK_SETTINGS permission. - */ - @Test - public void registerTrafficStateCallbackThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.registerTrafficStateCallback(mAppBinder, mTrafficStateCallback, - TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that a call to registerTrafficStateCallback throws an IllegalArgumentException if the - * parameters are not provided. - */ - @Test - public void registerTrafficStateCallbackThrowsIllegalArgumentExceptionOnInvalidArguments() { - try { - mWifiServiceImpl.registerTrafficStateCallback( - mAppBinder, null, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - fail("expected IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - } - } - - /** - * Verify that a call to unregisterTrafficStateCallback throws a SecurityException if the caller - * does not have NETWORK_SETTINGS permission. - */ - @Test - public void unregisterTrafficStateCallbackThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.unregisterTrafficStateCallback(TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that registerTrafficStateCallback adds callback to {@link WifiTrafficPoller}. - */ - @Test - public void registerTrafficStateCallbackAndVerify() throws Exception { - mWifiServiceImpl.registerTrafficStateCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - mLooper.dispatchAll(); - verify(mWifiTrafficPoller).addCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - } - - /** - * Verify that unregisterTrafficStateCallback removes callback from {@link WifiTrafficPoller}. - */ - @Test - public void unregisterTrafficStateCallbackAndVerify() throws Exception { - mWifiServiceImpl.unregisterTrafficStateCallback(0); - mLooper.dispatchAll(); - verify(mWifiTrafficPoller).removeCallback(0); - } - - /** - * Verify that a call to registerNetworkRequestMatchCallback throws a SecurityException if the - * caller does not have NETWORK_SETTINGS permission. - */ - @Test - public void registerNetworkRequestMatchCallbackThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.registerNetworkRequestMatchCallback(mAppBinder, - mNetworkRequestMatchCallback, - TEST_NETWORK_REQUEST_MATCH_CALLBACK_IDENTIFIER); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that a call to registerNetworkRequestMatchCallback throws an IllegalArgumentException - * if the parameters are not provided. - */ - @Test - public void - registerNetworkRequestMatchCallbackThrowsIllegalArgumentExceptionOnInvalidArguments() { - try { - mWifiServiceImpl.registerNetworkRequestMatchCallback( - mAppBinder, null, TEST_NETWORK_REQUEST_MATCH_CALLBACK_IDENTIFIER); - fail("expected IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - } - } - - /** - * Verify that a call to unregisterNetworkRequestMatchCallback throws a SecurityException if the - * caller does not have NETWORK_SETTINGS permission. - */ - @Test - public void unregisterNetworkRequestMatchCallbackThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.unregisterNetworkRequestMatchCallback( - TEST_NETWORK_REQUEST_MATCH_CALLBACK_IDENTIFIER); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that registerNetworkRequestMatchCallback adds callback to - * {@link ClientModeImpl}. - */ - @Test - public void registerNetworkRequestMatchCallbackAndVerify() throws Exception { - mWifiServiceImpl.registerNetworkRequestMatchCallback( - mAppBinder, mNetworkRequestMatchCallback, - TEST_NETWORK_REQUEST_MATCH_CALLBACK_IDENTIFIER); - mLooper.dispatchAll(); - verify(mClientModeImpl).addNetworkRequestMatchCallback( - mAppBinder, mNetworkRequestMatchCallback, - TEST_NETWORK_REQUEST_MATCH_CALLBACK_IDENTIFIER); - } - - /** - * Verify that unregisterNetworkRequestMatchCallback removes callback from - * {@link ClientModeImpl}. - */ - @Test - public void unregisterNetworkRequestMatchCallbackAndVerify() throws Exception { - mWifiServiceImpl.unregisterNetworkRequestMatchCallback( - TEST_NETWORK_REQUEST_MATCH_CALLBACK_IDENTIFIER); - mLooper.dispatchAll(); - verify(mClientModeImpl).removeNetworkRequestMatchCallback( - TEST_NETWORK_REQUEST_MATCH_CALLBACK_IDENTIFIER); - } - - /** - * Verify that Wifi configuration and Passpoint configuration are removed in factoryReset. - */ - @Test - public void testFactoryReset() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - final String fqdn = "example.com"; - WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork(); - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - config.setHomeSp(homeSp); - Credential credential = new Credential(); - credential.setRealm("example.com"); - config.setCredential(credential); - - mWifiServiceImpl.mClientModeImplChannel = mAsyncChannel; - when(mWifiConfigManager.getSavedNetworks(anyInt())) - .thenReturn(Arrays.asList(network)); - when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) - .thenReturn(Arrays.asList(config)); - - mLooper.startAutoDispatch(); - mWifiServiceImpl.factoryReset(TEST_PACKAGE_NAME); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - // Let the final post inside the |factoryReset| method run to completion. - mLooper.dispatchAll(); - - verify(mWifiConfigManager).removeNetwork( - network.networkId, Binder.getCallingUid(), TEST_PACKAGE_NAME); - verify(mPasspointManager).removeProvider(anyInt(), anyBoolean(), eq(config.getUniqueId()), - isNull()); - verify(mPasspointManager).clearAnqpRequestsAndFlushCache(); - verify(mWifiConfigManager).clearUserTemporarilyDisabledList(); - verify(mWifiConfigManager).removeAllEphemeralOrPasspointConfiguredNetworks(); - verify(mClientModeImpl).clearNetworkRequestUserApprovedAccessPoints(); - verify(mWifiNetworkSuggestionsManager).clear(); - verify(mWifiScoreCard).clear(); - verify(mWifiHealthMonitor).clear(); - verify(mPasspointManager).getProviderConfigs(anyInt(), anyBoolean()); - } - - /** - * Verify that a call to factoryReset throws a SecurityException if the caller does not have - * the NETWORK_SETTINGS permission. - */ - @Test - public void testFactoryResetWithoutNetworkSettingsPermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.factoryReset(TEST_PACKAGE_NAME); - fail(); - } catch (SecurityException e) { - } - verify(mWifiConfigManager, never()).getSavedNetworks(anyInt()); - verify(mPasspointManager, never()).getProviderConfigs(anyInt(), anyBoolean()); - } - - /** - * Verify that add or update networks is not allowed for apps targeting Q SDK. - */ - @Test - public void testAddOrUpdateNetworkIsNotAllowedForAppsTargetingQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn( - new NetworkUpdateResult(0)); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - mLooper.startAutoDispatch(); - assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), any()); - verify(mWifiMetrics, never()).incrementNumAddOrUpdateNetworkCalls(); - } - - /** - * Verify that add or update networks is allowed for apps targeting below Q SDK. - */ - @Test - public void testAddOrUpdateNetworkIsAllowedForAppsTargetingBelowQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn( - new NetworkUpdateResult(0)); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - mLooper.startAutoDispatch(); - assertEquals(0, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any()); - verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls(); - } - - /** - * Verify that add or update networks is allowed for settings app. - */ - @Test - public void testAddOrUpdateNetworkIsAllowedForSettingsApp() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.P; - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn( - new NetworkUpdateResult(0)); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - mLooper.startAutoDispatch(); - assertEquals(0, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - // Ensure that we don't check for change permission. - verify(mContext, never()).enforceCallingOrSelfPermission( - android.Manifest.permission.CHANGE_WIFI_STATE, "WifiService"); - verify(mAppOpsManager, never()).noteOp( - AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any()); - verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls(); - } - - /** - * Verify that add or update networks is allowed for system apps. - */ - @Test - public void testAddOrUpdateNetworkIsAllowedForSystemApp() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn( - new NetworkUpdateResult(0)); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - mLooper.startAutoDispatch(); - assertEquals(0, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any()); - verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls(); - } - - /** - * Verify that add or update networks is allowed for apps holding system alert permission. - */ - @Test - public void testAddOrUpdateNetworkIsAllowedForAppsWithSystemAlertPermission() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn( - new NetworkUpdateResult(0)); - - when(mWifiPermissionsUtil.checkSystemAlertWindowPermission( - Process.myUid(), TEST_PACKAGE_NAME)).thenReturn(true); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - mLooper.startAutoDispatch(); - assertEquals(0, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mWifiPermissionsUtil).checkSystemAlertWindowPermission(anyInt(), anyString()); - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any()); - verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls(); - } - - /** - * Verify that add or update networks is allowed for DeviceOwner app. - */ - @Test - public void testAddOrUpdateNetworkIsAllowedForDOApp() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME)) - .thenReturn(true); - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn( - new NetworkUpdateResult(0)); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - mLooper.startAutoDispatch(); - assertEquals(0, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any()); - verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls(); - } - - /** - * Verify that add or update networks is allowed for ProfileOwner app. - */ - @Test - public void testAddOrUpdateNetworkIsAllowedForPOApp() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME)) - .thenReturn(true); - when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any())).thenReturn( - new NetworkUpdateResult(0)); - - WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); - mLooper.startAutoDispatch(); - assertEquals(0, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt(), any()); - verify(mWifiMetrics).incrementNumAddOrUpdateNetworkCalls(); - } - - /** - * Verify that enableNetwork is allowed for privileged Apps - */ - @Test - public void testEnableNetworkWithDisableOthersAllowedForPrivilegedApps() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public void answer(WifiConfiguration config, int netId, IBinder binder, - IActionListener callback, int callbackIdentifier, int callingUid) { - try { - callback.onSuccess(); // return success - } catch (RemoteException e) { } - } - }).when(mClientModeImpl).connect( - isNull(), eq(TEST_NETWORK_ID), any(), any(), anyInt(), anyInt()); - - assertTrue(mWifiServiceImpl.enableNetwork(TEST_NETWORK_ID, true, TEST_PACKAGE_NAME)); - - verify(mClientModeImpl).connect(isNull(), eq(TEST_NETWORK_ID), any(), any(), anyInt(), - anyInt()); - verify(mWifiMetrics).incrementNumEnableNetworkCalls(); - } - - /** - * Verify that enableNetwork (with disableOthers=true) is allowed for Apps targeting a SDK - * version less than Q - */ - @Test - public void testEnabledNetworkWithDisableOthersAllowedForAppsTargetingBelowQSdk() - throws Exception { - mLooper.dispatchAll(); - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public void answer(WifiConfiguration config, int netId, IBinder binder, - IActionListener callback, int callbackIdentifier, int callingUid) { - try { - callback.onSuccess(); // return success - } catch (RemoteException e) { } - } - }).when(mClientModeImpl).connect( - isNull(), eq(TEST_NETWORK_ID), any(), any(), anyInt(), anyInt()); - - assertTrue(mWifiServiceImpl.enableNetwork(TEST_NETWORK_ID, true, TEST_PACKAGE_NAME)); - - verify(mClientModeImpl).connect(isNull(), eq(TEST_NETWORK_ID), any(), any(), anyInt(), - anyInt()); - verify(mWifiMetrics).incrementNumEnableNetworkCalls(); - } - - /** - * Verify that enableNetwork (with disableOthers=false) is allowed for Apps targeting a SDK - * version less than Q - */ - @Test - public void testEnabledNetworkWithoutDisableOthersAllowedForAppsTargetingBelowQSdk() - throws Exception { - mLooper.dispatchAll(); - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - - when(mWifiConfigManager.enableNetwork(anyInt(), anyBoolean(), anyInt(), anyString())) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.enableNetwork(TEST_NETWORK_ID, false, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mWifiConfigManager).enableNetwork(eq(TEST_NETWORK_ID), eq(false), - eq(Binder.getCallingUid()), eq(TEST_PACKAGE_NAME)); - verify(mWifiMetrics).incrementNumEnableNetworkCalls(); - } - - /** - * Verify that enableNetwork is not allowed for Apps targeting Q SDK - */ - @Test - public void testEnableNetworkNotAllowedForAppsTargetingQ() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - - mWifiServiceImpl.enableNetwork(TEST_NETWORK_ID, true, TEST_PACKAGE_NAME); - - verify(mClientModeImpl, never()).connect(isNull(), anyInt(), any(), any(), anyInt(), - anyInt()); - verify(mWifiMetrics, never()).incrementNumEnableNetworkCalls(); - } - - /** - * Ensure that we invoke {@link WifiNetworkSuggestionsManager} to add network - * suggestions. - */ - @Test - public void testAddNetworkSuggestions() { - when(mWifiNetworkSuggestionsManager.add(any(), anyInt(), anyString(), - nullable(String.class))).thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - mLooper.startAutoDispatch(); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - when(mWifiNetworkSuggestionsManager.add(any(), anyInt(), anyString(), - nullable(String.class))).thenReturn( - WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE); - mLooper.startAutoDispatch(); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verify(mWifiNetworkSuggestionsManager, times(2)).add( - any(), eq(Binder.getCallingUid()), eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID)); - } - - /** - * Ensure that we don't invoke {@link WifiNetworkSuggestionsManager} to add network - * suggestions when the looper sync call times out. - */ - @Test - public void testAddNetworkSuggestionsFailureInRunWithScissors() { - mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut(); - - mLooper.startAutoDispatch(); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verify(mWifiNetworkSuggestionsManager, never()).add(any(), eq(Binder.getCallingUid()), - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID)); - } - - /** - * Ensure that we invoke {@link WifiNetworkSuggestionsManager} to remove network - * suggestions. - */ - @Test - public void testRemoveNetworkSuggestions() { - when(mWifiNetworkSuggestionsManager.remove(any(), anyInt(), anyString())) - .thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID); - mLooper.startAutoDispatch(); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, - mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - when(mWifiNetworkSuggestionsManager.remove(any(), anyInt(), anyString())) - .thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); - mLooper.startAutoDispatch(); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verify(mWifiNetworkSuggestionsManager, times(2)).remove(any(), anyInt(), - eq(TEST_PACKAGE_NAME)); - } - - /** - * Ensure that we don't invoke {@link WifiNetworkSuggestionsManager} to remove network - * suggestions when the looper sync call times out. - */ - @Test - public void testRemoveNetworkSuggestionsFailureInRunWithScissors() { - mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut(); - - mLooper.startAutoDispatch(); - assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, - mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verify(mWifiNetworkSuggestionsManager, never()).remove(any(), anyInt(), - eq(TEST_PACKAGE_NAME)); - } - - /** - * Ensure that we invoke {@link WifiNetworkSuggestionsManager} to get network - * suggestions. - */ - @Test - public void testGetNetworkSuggestions() { - List<WifiNetworkSuggestion> testList = new ArrayList<>(); - when(mWifiNetworkSuggestionsManager.get(anyString(), anyInt())).thenReturn(testList); - mLooper.startAutoDispatch(); - assertEquals(testList, mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verify(mWifiNetworkSuggestionsManager).get(eq(TEST_PACKAGE_NAME), anyInt()); - } - - /** - * Ensure that we don't invoke {@link WifiNetworkSuggestionsManager} to get network - * suggestions when the looper sync call times out. - */ - @Test - public void testGetNetworkSuggestionsFailureInRunWithScissors() { - mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut(); - - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME).isEmpty()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - verify(mWifiNetworkSuggestionsManager, never()).get(eq(TEST_PACKAGE_NAME), anyInt()); - } - - /** - * Verify that if the caller has NETWORK_SETTINGS permission, then it can invoke - * {@link WifiManager#disableEphemeralNetwork(String)}. - */ - @Test - public void testDisableEphemeralNetworkWithNetworkSettingsPerm() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl.disableEphemeralNetwork(new String(), TEST_PACKAGE_NAME); - mLooper.dispatchAll(); - verify(mWifiConfigManager).userTemporarilyDisabledNetwork(anyString(), anyInt()); - } - - /** - * Verify that if the caller does not have NETWORK_SETTINGS permission, then it cannot invoke - * {@link WifiManager#disableEphemeralNetwork(String)}. - */ - @Test - public void testDisableEphemeralNetworkWithoutNetworkSettingsPerm() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); - mWifiServiceImpl.disableEphemeralNetwork(new String(), TEST_PACKAGE_NAME); - mLooper.dispatchAll(); - verify(mWifiConfigManager, never()).userTemporarilyDisabledNetwork(anyString(), anyInt()); - } - - /** - * Verify getting the factory MAC address. - */ - @Test - public void testGetFactoryMacAddresses() throws Exception { - when(mClientModeImpl.getFactoryMacAddress()).thenReturn(TEST_FACTORY_MAC); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - mLooper.startAutoDispatch(); - final String[] factoryMacs = mWifiServiceImpl.getFactoryMacAddresses(); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - assertEquals(1, factoryMacs.length); - assertEquals(TEST_FACTORY_MAC, factoryMacs[0]); - verify(mClientModeImpl).getFactoryMacAddress(); - } - - /** - * Verify getting the factory MAC address returns null when posting the runnable to handler - * fails. - */ - @Test - public void testGetFactoryMacAddressesPostFail() throws Exception { - mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut(); - - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - mLooper.startAutoDispatch(); - assertArrayEquals(new String[0], mWifiServiceImpl.getFactoryMacAddresses()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mClientModeImpl, never()).getFactoryMacAddress(); - } - - /** - * Verify getting the factory MAC address returns null when the lower layers fail. - */ - @Test - public void testGetFactoryMacAddressesFail() throws Exception { - when(mClientModeImpl.getFactoryMacAddress()).thenReturn(null); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - mLooper.startAutoDispatch(); - assertArrayEquals(new String[0], mWifiServiceImpl.getFactoryMacAddresses()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mClientModeImpl).getFactoryMacAddress(); - } - - /** - * Verify getting the factory MAC address throws a SecurityException if the calling app - * doesn't have NETWORK_SETTINGS permission. - */ - @Test - public void testGetFactoryMacAddressesFailNoNetworkSettingsPermission() throws Exception { - when(mClientModeImpl.getFactoryMacAddress()).thenReturn(TEST_FACTORY_MAC); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - try { - mLooper.startAutoDispatch(); - mWifiServiceImpl.getFactoryMacAddresses(); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - fail(); - } catch (SecurityException e) { - assertTrue("Exception message should contain 'factory MAC'", - e.toString().contains("factory MAC")); - } - } - - /** - * Verify that a call to setDeviceMobilityState throws a SecurityException if the - * caller does not have WIFI_SET_DEVICE_MOBILITY_STATE permission. - */ - @Test - public void setDeviceMobilityStateThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission( - eq(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE), - eq("WifiService")); - try { - mWifiServiceImpl.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verifies that setDeviceMobilityState runs on a separate handler thread. - */ - @Test - public void setDeviceMobilityStateRunsOnHandler() { - mWifiServiceImpl.setDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY); - verify(mClientModeImpl, never()).setDeviceMobilityState(anyInt()); - mLooper.dispatchAll(); - verify(mClientModeImpl).setDeviceMobilityState(eq(DEVICE_MOBILITY_STATE_STATIONARY)); - } - - /** - * Verify that a call to addOnWifiUsabilityStatsListener throws a SecurityException if - * the caller does not have WIFI_UPDATE_USABILITY_STATS_SCORE permission. - */ - @Test - public void testAddStatsListenerThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission( - eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE), - eq("WifiService")); - try { - mWifiServiceImpl.addOnWifiUsabilityStatsListener(mAppBinder, - mOnWifiUsabilityStatsListener, TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that a call to addOnWifiUsabilityStatsListener throws an IllegalArgumentException - * if the parameters are not provided. - */ - @Test - public void testAddStatsListenerThrowsIllegalArgumentExceptionOnInvalidArguments() { - try { - mWifiServiceImpl.addOnWifiUsabilityStatsListener( - mAppBinder, null, TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - fail("expected IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - } - } - - /** - * Verify that a call to removeOnWifiUsabilityStatsListener throws a SecurityException if - * the caller does not have WIFI_UPDATE_USABILITY_STATS_SCORE permission. - */ - @Test - public void testRemoveStatsListenerThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission( - eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE), - eq("WifiService")); - try { - mWifiServiceImpl.removeOnWifiUsabilityStatsListener( - TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that addOnWifiUsabilityStatsListener adds listener to {@link WifiMetrics}. - */ - @Test - public void testAddOnWifiUsabilityStatsListenerAndVerify() throws Exception { - mWifiServiceImpl.addOnWifiUsabilityStatsListener(mAppBinder, mOnWifiUsabilityStatsListener, - TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - mLooper.dispatchAll(); - verify(mWifiMetrics).addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener, - TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER); - } - - /** - * Verify that removeOnWifiUsabilityStatsListener removes listener from - * {@link WifiMetrics}. - */ - @Test - public void testRemoveOnWifiUsabilityStatsListenerAndVerify() throws Exception { - mWifiServiceImpl.removeOnWifiUsabilityStatsListener(0); - mLooper.dispatchAll(); - verify(mWifiMetrics).removeOnWifiUsabilityListener(0); - } - - /** - * Verify that a call to updateWifiUsabilityScore throws a SecurityException if the - * caller does not have UPDATE_WIFI_USABILITY_SCORE permission. - */ - @Test - public void testUpdateWifiUsabilityScoreThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission( - eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE), - eq("WifiService")); - try { - mWifiServiceImpl.updateWifiUsabilityScore(anyInt(), anyInt(), 15); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that mClientModeImpl in WifiServiceImpl is being updated on Wifi usability score - * update event. - */ - @Test - public void testWifiUsabilityScoreUpdateAfterScoreEvent() { - mWifiServiceImpl.updateWifiUsabilityScore(anyInt(), anyInt(), 15); - mLooper.dispatchAll(); - verify(mClientModeImpl).updateWifiUsabilityScore(anyInt(), anyInt(), anyInt()); - } - - private void startLohsAndTethering(boolean isApConcurrencySupported) throws Exception { - // initialization - when(mActiveModeWarden.canRequestMoreSoftApManagers()).thenReturn(isApConcurrencySupported); - // For these tests, always use distinct interface names for LOHS and tethered. - mLohsInterfaceName = WIFI_IFACE_NAME2; - - mLooper.startAutoDispatch(); - setupLocalOnlyHotspot(); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - reset(mActiveModeWarden); - - when(mActiveModeWarden.canRequestMoreSoftApManagers()).thenReturn(isApConcurrencySupported); - - // start tethering - mLooper.startAutoDispatch(); - boolean tetheringResult = mWifiServiceImpl.startSoftAp(null); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - assertTrue(tetheringResult); - verify(mActiveModeWarden).startSoftAp(any()); - mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); - mLooper.dispatchAll(); - } - - /** - * Verify LOHS gets stopped when trying to start tethering concurrently on devices that - * doesn't support dual AP operation. - */ - @Test - public void testStartLohsAndTethering1AP() throws Exception { - startLohsAndTethering(false); - - // verify LOHS got stopped - verify(mLohsCallback).onHotspotFailed(anyInt()); - verify(mActiveModeWarden).stopSoftAp(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - } - - /** - * Verify LOHS doesn't get stopped when trying to start tethering concurrently on devices - * that does support dual AP operation. - */ - @Test - public void testStartLohsAndTethering2AP() throws Exception { - startLohsAndTethering(true); - - // verify LOHS didn't get stopped - verifyZeroInteractions(ignoreStubs(mLohsCallback)); - verify(mActiveModeWarden, never()).stopSoftAp(anyInt()); - } - - /** - * Verify that the call to startDppAsConfiguratorInitiator throws a security exception when the - * caller doesn't have NETWORK_SETTINGS permissions or NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testStartDppAsConfiguratorInitiatorWithoutPermissions() { - mWifiServiceImpl.startDppAsConfiguratorInitiator(mAppBinder, DPP_URI, - 1, 1, mDppCallback); - } - - /** - * Verify that the call to startDppAsEnrolleeInitiator throws a security exception when the - * caller doesn't have NETWORK_SETTINGS permissions or NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testStartDppAsEnrolleeInitiatorWithoutPermissions() { - mWifiServiceImpl.startDppAsEnrolleeInitiator(mAppBinder, DPP_URI, mDppCallback); - } - - /** - * Verify that the call to stopDppSession throws a security exception when the - * caller doesn't have NETWORK_SETTINGS permissions or NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testStopDppSessionWithoutPermissions() { - try { - mWifiServiceImpl.stopDppSession(); - } catch (RemoteException e) { - } - } - - /** - * Verifies that configs can be removed. - */ - @Test - public void testRemoveNetworkIsAllowedForAppsTargetingBelowQSdk() { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiConfigManager.removeNetwork(eq(0), anyInt(), anyString())).thenReturn(true); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - - mLooper.startAutoDispatch(); - boolean result = mWifiServiceImpl.removeNetwork(0, TEST_PACKAGE_NAME); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - assertTrue(result); - verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt(), anyString()); - } - - /** - * Verify that addOrUpdatePasspointConfiguration is allowed for apps targeting below R SDK. - */ - @Test - public void addOrUpdatePasspointConfigIsAllowedForAppsTargetingBelowRSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.R), anyInt())).thenReturn(true); - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn("test.com"); - config.setHomeSp(homeSp); - - when(mPasspointManager.addOrUpdateProvider( - config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true)) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - reset(mPasspointManager); - - when(mPasspointManager.addOrUpdateProvider( - config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true)) - .thenReturn(false); - mLooper.startAutoDispatch(); - assertFalse(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - } - - /** - * Verify that addOrUpdatePasspointConfiguration is not allowed for apps targeting R SDK. - */ - @Test - public void addOrUpdatePasspointConfigIsNotAllowedForAppsTargetingRSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn("test.com"); - config.setHomeSp(homeSp); - - when(mPasspointManager.addOrUpdateProvider( - config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true)) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertFalse(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager, never()) - .addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), anyBoolean()); - - } - - /** - * Verify that addOrUpdatePasspointConfiguration is allowed for Settings apps. - */ - @Test - public void addOrUpdatePasspointConfigIsAllowedSettingsApp() throws Exception { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.R), anyInt())).thenReturn(false); - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn("test.com"); - config.setHomeSp(homeSp); - - when(mPasspointManager.addOrUpdateProvider( - config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true)) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager).addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), - anyBoolean()); - } - - /** - * Verify that addOrUpdatePasspointConfiguration is allowed for System apps. - */ - @Test - public void addOrUpdatePasspointConfigIsAllowedSystemApp() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.R), anyInt())).thenReturn(false); - mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn("test.com"); - config.setHomeSp(homeSp); - - when(mPasspointManager.addOrUpdateProvider( - config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true)) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager).addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), - anyBoolean()); - } - - /** - * Verify that addOrUpdatePasspointConfiguration is allowed for DeviceOwner apps. - */ - @Test - public void addOrUpdatePasspointConfigIsAllowedSystemAlertDOApp() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.R), anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.isDeviceOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME)) - .thenReturn(true); - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn("test.com"); - config.setHomeSp(homeSp); - - when(mPasspointManager.addOrUpdateProvider( - config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true)) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager).addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), - anyBoolean()); - } - - /** - * Verify that addOrUpdatePasspointConfiguration is allowed for ProfileOwner apps. - */ - @Test - public void addOrUpdatePasspointConfigIsAllowedSystemAlertPOApp() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.R), anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.isProfileOwner(Binder.getCallingUid(), TEST_PACKAGE_NAME)) - .thenReturn(true); - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn("test.com"); - config.setHomeSp(homeSp); - - when(mPasspointManager.addOrUpdateProvider( - config, Binder.getCallingUid(), TEST_PACKAGE_NAME, false, true)) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.addOrUpdatePasspointConfiguration(config, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mPasspointManager).addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(), - anyBoolean()); - } - - /** - * Verify that removePasspointConfiguration will redirect calls to {@link PasspointManager} - * and returning the result that's returned from {@link PasspointManager}. - */ - @Test - public void removePasspointConfig() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - - String fqdn = "test.com"; - when(mPasspointManager.removeProvider(anyInt(), anyBoolean(), isNull(), eq(fqdn))) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.removePasspointConfiguration(fqdn, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - reset(mPasspointManager); - - when(mPasspointManager.removeProvider(anyInt(), anyBoolean(), isNull(), eq(fqdn))) - .thenReturn(false); - mLooper.startAutoDispatch(); - assertFalse(mWifiServiceImpl.removePasspointConfiguration(fqdn, TEST_PACKAGE_NAME)); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - } - - /** - * Test that DISABLE_NETWORK returns failure to public API when WifiConfigManager returns - * failure. - */ - @Test - public void testDisableNetworkFailureAppBelowQSdk() throws Exception { - doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) - .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - when(mWifiConfigManager.disableNetwork(anyInt(), anyInt(), anyString())).thenReturn(false); - - mLooper.startAutoDispatch(); - boolean succeeded = mWifiServiceImpl.disableNetwork(0, TEST_PACKAGE_NAME); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - assertFalse(succeeded); - } - - @Test - public void testAllowAutojoinGlobalFailureNoNetworkSettingsPermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.allowAutojoinGlobal(true); - fail("Expected SecurityException"); - } catch (SecurityException e) { - // Test succeeded - } - } - - @Test - public void testAllowAutojoinFailureNoNetworkSettingsPermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.allowAutojoin(0, true); - fail("Expected SecurityException"); - } catch (SecurityException e) { - // Test succeeded - } - } - - @Test - public void testAllowAutojoinOnSuggestionNetwork() { - WifiConfiguration config = new WifiConfiguration(); - config.allowAutojoin = false; - config.fromWifiNetworkSuggestion = true; - when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config); - when(mWifiNetworkSuggestionsManager.allowNetworkSuggestionAutojoin(any(), anyBoolean())) - .thenReturn(true); - mWifiServiceImpl.allowAutojoin(0, true); - mLooper.dispatchAll(); - verify(mWifiConfigManager).getConfiguredNetwork(0); - verify(mWifiNetworkSuggestionsManager).allowNetworkSuggestionAutojoin(any(), anyBoolean()); - verify(mWifiConfigManager).allowAutojoin(anyInt(), anyBoolean()); - verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON), - anyInt()); - } - - @Test - public void testAllowAutojoinOnSavedNetwork() { - WifiConfiguration config = new WifiConfiguration(); - config.allowAutojoin = false; - config.fromWifiNetworkSuggestion = false; - config.fromWifiNetworkSpecifier = false; - when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config); - mWifiServiceImpl.allowAutojoin(0, true); - mLooper.dispatchAll(); - verify(mWifiConfigManager).getConfiguredNetwork(0); - verify(mWifiNetworkSuggestionsManager, never()) - .allowNetworkSuggestionAutojoin(any(), anyBoolean()); - verify(mWifiConfigManager).allowAutojoin(anyInt(), anyBoolean()); - } - - @Test - public void testAllowAutojoinOnWifiNetworkSpecifier() { - WifiConfiguration config = new WifiConfiguration(); - config.fromWifiNetworkSpecifier = true; - when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config); - mWifiServiceImpl.allowAutojoin(0, true); - mLooper.dispatchAll(); - verify(mWifiConfigManager).getConfiguredNetwork(0); - verify(mWifiNetworkSuggestionsManager, never()) - .allowNetworkSuggestionAutojoin(config, true); - verify(mWifiConfigManager, never()).allowAutojoin(0, true); - } - - @Test - public void testAllowAutojoinOnSavedPasspointNetwork() { - WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork(); - when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config); - when(mWifiNetworkSuggestionsManager.allowNetworkSuggestionAutojoin(any(), anyBoolean())) - .thenReturn(true); - mWifiServiceImpl.allowAutojoin(0, true); - mLooper.dispatchAll(); - verify(mWifiConfigManager).getConfiguredNetwork(0); - verify(mWifiNetworkSuggestionsManager, never()) - .allowNetworkSuggestionAutojoin(config, true); - verify(mWifiConfigManager, never()).allowAutojoin(0, true); - } - - /** - * Test that setMacRandomizationSettingPasspointEnabled is protected by NETWORK_SETTINGS - * permission. - */ - @Test - public void testSetMacRandomizationSettingPasspointEnabledFailureNoNetworkSettingsPermission() - throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.setMacRandomizationSettingPasspointEnabled("TEST_FQDN", true); - fail("Expected SecurityException"); - } catch (SecurityException e) { - // Test succeeded - } - } - - /** - * Test that setMacRandomizationSettingPasspointEnabled makes the appropriate calls. - */ - @Test - public void testSetMacRandomizationSettingPasspointEnabled() throws Exception { - mWifiServiceImpl.setMacRandomizationSettingPasspointEnabled("TEST_FQDN", true); - mLooper.dispatchAll(); - verify(mPasspointManager).enableMacRandomization("TEST_FQDN", true); - } - - /** - * Test that setPasspointMeteredOverride is protected by NETWORK_SETTINGS permission. - */ - @Test - public void testSetPasspointMeteredOverrideFailureNoNetworkSettingsPermission() - throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - try { - mWifiServiceImpl.setPasspointMeteredOverride("TEST_FQDN", METERED_OVERRIDE_METERED); - fail("Expected SecurityException"); - } catch (SecurityException e) { - // Test succeeded - } - } - - /** - * Test that setPasspointMeteredOverride makes the appropriate calls. - */ - @Test - public void testSetPasspointMeteredOverride() throws Exception { - mWifiServiceImpl.setPasspointMeteredOverride("TEST_FQDN", METERED_OVERRIDE_METERED); - mLooper.dispatchAll(); - verify(mPasspointManager).setMeteredOverride("TEST_FQDN", METERED_OVERRIDE_METERED); - } - - /** - * Test handle boot completed sequence. - */ - @Test - public void testHandleBootCompleted() throws Exception { - when(mWifiInjector.getPasspointProvisionerHandlerThread()) - .thenReturn(mock(HandlerThread.class)); - mWifiServiceImpl.handleBootCompleted(); - mLooper.dispatchAll(); - - verify(mPasspointManager).initializeProvisioner(any()); - verify(mClientModeImpl).handleBootCompleted(); - } - - /** - * Test handle user switch sequence. - */ - @Test - public void testHandleUserSwitch() throws Exception { - mWifiServiceImpl.handleUserSwitch(5); - mLooper.dispatchAll(); - verify(mWifiConfigManager).handleUserSwitch(5); - } - - /** - * Test handle user unlock sequence. - */ - @Test - public void testHandleUserUnlock() throws Exception { - mWifiServiceImpl.handleUserUnlock(5); - mLooper.dispatchAll(); - verify(mWifiConfigManager).handleUserUnlock(5); - } - - /** - * Test handle user stop sequence. - */ - @Test - public void testHandleUserStop() throws Exception { - mWifiServiceImpl.handleUserStop(5); - mLooper.dispatchAll(); - verify(mWifiConfigManager).handleUserStop(5); - } - - /** - * Test register scan result callback without permission. - */ - @Test(expected = SecurityException.class) - public void testRegisterScanResultCallbackWithMissingPermission() throws Exception { - doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(ACCESS_WIFI_STATE), eq("WifiService")); - mWifiServiceImpl.registerScanResultsCallback(mScanResultsCallback); - } - - /** - * Test unregister scan result callback without permission. - */ - @Test(expected = SecurityException.class) - public void testUnregisterScanResultCallbackWithMissingPermission() throws Exception { - doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(ACCESS_WIFI_STATE), eq("WifiService")); - mWifiServiceImpl.unregisterScanResultsCallback(mScanResultsCallback); - } - - /** - * Test register scan result callback with illegal argument. - */ - @Test(expected = IllegalArgumentException.class) - public void testRegisterScanResultCallbackWithIllegalArgument() throws Exception { - mWifiServiceImpl.registerScanResultsCallback(null); - } - - /** - * Test register and unregister callback will go to ScanRequestProxy; - */ - @Test - public void testRegisterUnregisterScanResultCallback() throws Exception { - mWifiServiceImpl.registerScanResultsCallback(mScanResultsCallback); - mLooper.dispatchAll(); - verify(mScanRequestProxy).registerScanResultsCallback(mScanResultsCallback); - mWifiServiceImpl.unregisterScanResultsCallback(mScanResultsCallback); - mLooper.dispatchAll(); - verify(mScanRequestProxy).unregisterScanResultsCallback(mScanResultsCallback); - } - - /** - * Test register callback without permission. - */ - @Test(expected = SecurityException.class) - public void testRegisterSuggestionNetworkCallbackWithMissingPermission() { - doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(ACCESS_WIFI_STATE), eq("WifiService")); - mWifiServiceImpl.registerSuggestionConnectionStatusListener(mAppBinder, - mSuggestionConnectionStatusListener, NETWORK_CALLBACK_ID, TEST_PACKAGE_NAME, - TEST_FEATURE_ID); - } - - /** - * Test register callback without callback - */ - @Test(expected = IllegalArgumentException.class) - public void testRegisterSuggestionNetworkCallbackWithIllegalArgument() { - mWifiServiceImpl.registerSuggestionConnectionStatusListener(mAppBinder, null, - NETWORK_CALLBACK_ID, TEST_PACKAGE_NAME, TEST_FEATURE_ID); - } - - /** - * Test unregister callback without permission. - */ - @Test(expected = SecurityException.class) - public void testUnregisterSuggestionNetworkCallbackWithMissingPermission() { - doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(ACCESS_WIFI_STATE), eq("WifiService")); - mWifiServiceImpl.unregisterSuggestionConnectionStatusListener( - NETWORK_CALLBACK_ID, TEST_PACKAGE_NAME); - } - - /** - * Test register nad unregister callback will go to WifiNetworkSuggestionManager - */ - @Test - public void testRegisterUnregisterSuggestionNetworkCallback() throws Exception { - mWifiServiceImpl.registerSuggestionConnectionStatusListener(mAppBinder, - mSuggestionConnectionStatusListener, NETWORK_CALLBACK_ID, TEST_PACKAGE_NAME, - TEST_FEATURE_ID); - mLooper.dispatchAll(); - verify(mWifiNetworkSuggestionsManager).registerSuggestionConnectionStatusListener( - eq(mAppBinder), eq(mSuggestionConnectionStatusListener), eq(NETWORK_CALLBACK_ID), - eq(TEST_PACKAGE_NAME), anyInt()); - mWifiServiceImpl.unregisterSuggestionConnectionStatusListener(NETWORK_CALLBACK_ID, - TEST_PACKAGE_NAME); - mLooper.dispatchAll(); - verify(mWifiNetworkSuggestionsManager).unregisterSuggestionConnectionStatusListener( - eq(NETWORK_CALLBACK_ID), eq(TEST_PACKAGE_NAME), anyInt()); - } - - - /** - * Test to verify that the lock mode is verified before dispatching the operation - * - * Steps: call acquireWifiLock with an invalid lock mode. - * Expected: the call should throw an IllegalArgumentException. - */ - @Test(expected = IllegalArgumentException.class) - public void acquireWifiLockShouldThrowExceptionOnInvalidLockMode() throws Exception { - final int wifiLockModeInvalid = -1; - - mWifiServiceImpl.acquireWifiLock(mAppBinder, wifiLockModeInvalid, "", null); - } - - private void setupReportActivityInfo() { - WifiLinkLayerStats stats = new WifiLinkLayerStats(); - stats.on_time = 1000; - stats.tx_time = 1; - stats.rx_time = 2; - stats.tx_time_per_level = new int[] {3, 4, 5}; - stats.on_time_scan = 6; - when(mClientModeImpl.syncGetLinkLayerStats(any())).thenReturn(stats); - when(mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE)) - .thenReturn(7.0); - when(mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX)) - .thenReturn(8.0); - when(mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX)) - .thenReturn(9.0); - when(mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE)) - .thenReturn(10000.0); - when(mClock.getElapsedSinceBootMillis()).thenReturn(9999L); - } - - private void validateWifiActivityEnergyInfo(WifiActivityEnergyInfo info) { - assertNotNull(info); - assertEquals(9999L, info.getTimeSinceBootMillis()); - assertEquals(WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, info.getStackState()); - assertEquals(1, info.getControllerTxDurationMillis()); - assertEquals(2, info.getControllerRxDurationMillis()); - assertEquals(6, info.getControllerScanDurationMillis()); - assertEquals(997, info.getControllerIdleDurationMillis()); - } - - /** - * Tests that {@link WifiServiceImpl#getWifiActivityEnergyInfoAsync} throws - * {@link SecurityException} if the caller doesn't have the necessary permissions. - */ - @Test(expected = SecurityException.class) - public void getWifiActivityEnergyInfoAsyncNoPermission() throws Exception { - doThrow(SecurityException.class) - .when(mContext).enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE), any()); - mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener); - } - - /** - * Tests that {@link WifiServiceImpl#getWifiActivityEnergyInfoAsync} passes null to the listener - * if link layer stats is unsupported. - */ - @Test - public void getWifiActivityEnergyInfoAsyncFeatureUnsupported() throws Exception { - when(mClientModeImpl.syncGetSupportedFeatures(any())).thenReturn(0L); - mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener); - verify(mOnWifiActivityEnergyInfoListener).onWifiActivityEnergyInfo(null); - } - - /** - * Tests that {@link WifiServiceImpl#getWifiActivityEnergyInfoAsync} passes the expected values - * to the listener on success. - */ - @Test - public void getWifiActivityEnergyInfoAsyncSuccess() throws Exception { - when(mClientModeImpl.syncGetSupportedFeatures(any())).thenReturn(Long.MAX_VALUE); - setupReportActivityInfo(); - mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener); - ArgumentCaptor<WifiActivityEnergyInfo> infoCaptor = - ArgumentCaptor.forClass(WifiActivityEnergyInfo.class); - verify(mOnWifiActivityEnergyInfoListener).onWifiActivityEnergyInfo(infoCaptor.capture()); - validateWifiActivityEnergyInfo(infoCaptor.getValue()); - } - - @Test - public void testCarrierConfigChangeUpdateSoftApCapability() throws Exception { - MockitoSession staticMockSession = mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - lenient().when(SubscriptionManager.getActiveDataSubscriptionId()) - .thenReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED))); - - // Send the broadcast - Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); - mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); - mLooper.dispatchAll(); - verify(mActiveModeWarden).updateSoftApCapability(any()); - staticMockSession.finishMocking(); - } - - @Test - public void testPhoneActiveDataSubscriptionIdChangedUpdateSoftApCapability() throws Exception { - MockitoSession staticMockSession = mockitoSession() - .mockStatic(SubscriptionManager.class) - .startMocking(); - lenient().when(SubscriptionManager.getActiveDataSubscriptionId()) - .thenReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); - mWifiServiceImpl.checkAndStartWifi(); - mLooper.dispatchAll(); - verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), - argThat((IntentFilter filter) -> - filter.hasAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED))); - ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)); - mPhoneStateListener = phoneStateListenerCaptor.getValue(); - assertNotNull(mPhoneStateListener); - mPhoneStateListener.onActiveDataSubscriptionIdChanged(2); - mLooper.dispatchAll(); - verify(mActiveModeWarden).updateSoftApCapability(any()); - staticMockSession.finishMocking(); - } - - /** - * Verify that the call to getWifiConfigsForMatchedNetworkSuggestions is not redirected to - * specific API getWifiConfigForMatchedNetworkSuggestionsSharedWithUser when the caller doesn't - * have NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD. - */ - @Test(expected = SecurityException.class) - public void testGetWifiConfigsForMatchedNetworkSuggestionsWithoutPermissions() { - mWifiServiceImpl.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>()); - } - - /** - * Verify that the call to getWifiConfigsForMatchedNetworkSuggestions is redirected to - * specific API getWifiConfigForMatchedNetworkSuggestionsSharedWithUser when the caller - * have NETWORK_SETTINGS. - */ - @Test - public void testGetWifiConfigsForMatchedNetworkSuggestionsWithSettingPermissions() { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(createScanResultList()); - mLooper.dispatchAll(); - verify(mWifiNetworkSuggestionsManager) - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()); - } - - /** - * Verify that the call to getWifiConfigsForMatchedNetworkSuggestions is redirected to - * specific API getWifiConfigForMatchedNetworkSuggestionsSharedWithUser when the caller - * have NETWORK_SETUP_WIZARD. - */ - @Test - public void testGetWifiConfigsForMatchedNetworkSuggestionsWithSetupWizardPermissions() { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETUP_WIZARD), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(createScanResultList()); - mLooper.dispatchAll(); - verify(mWifiNetworkSuggestionsManager) - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()); - } - - @Test - public void testGetWifiConfigsForMatchedNetworkSuggestionsWithInvalidScanResults() { - when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>()); - mLooper.dispatchAll(); - verify(mWifiNetworkSuggestionsManager, never()) - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()); - } - - /** - * Verify that a call to setWifiConnectedNetworkScorer throws a SecurityException if - * the caller does not have WIFI_UPDATE_USABILITY_STATS_SCORE permission. - */ - @Test - public void testSetNetworkScorerThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission( - eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE), - eq("WifiService")); - try { - mWifiServiceImpl.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that a call to setWifiConnectedNetworkScorer throws an IllegalArgumentException - * if the parameters are not provided. - */ - @Test - public void testSetScorerThrowsIllegalArgumentExceptionOnInvalidArguments() { - try { - mWifiServiceImpl.setWifiConnectedNetworkScorer(mAppBinder, null); - fail("expected IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - } - } - - /** - * Verify that a call to clearWifiConnectedNetworkScorer throws a SecurityException if - * the caller does not have WIFI_UPDATE_USABILITY_STATS_SCORE permission. - */ - @Test - public void testClearNetworkScorerThrowsSecurityExceptionOnMissingPermissions() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission( - eq(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE), - eq("WifiService")); - try { - mWifiServiceImpl.clearWifiConnectedNetworkScorer(); - fail("expected SecurityException"); - } catch (SecurityException expected) { - } - } - - /** - * Verify that setWifiConnectedNetworkScorer sets scorer to {@link WifiScoreReport}. - */ - @Test - public void testSetWifiConnectedNetworkScorerAndVerify() throws Exception { - mWifiServiceImpl.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); - mLooper.dispatchAll(); - verify(mWifiScoreReport).setWifiConnectedNetworkScorer(mAppBinder, - mWifiConnectedNetworkScorer); - } - - /** - * Verify that clearWifiConnectedNetworkScorer clears scorer from {@link WifiScoreReport}. - */ - @Test - public void testClearWifiConnectedNetworkScorerAndVerify() throws Exception { - mWifiServiceImpl.clearWifiConnectedNetworkScorer(); - mLooper.dispatchAll(); - verify(mWifiScoreReport).clearWifiConnectedNetworkScorer(); - } - - private long testGetSupportedFeaturesCaseForRtt( - long supportedFeaturesFromClientModeImpl, boolean rttDisabled) { - when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn( - !rttDisabled); - when(mClientModeImpl.syncGetSupportedFeatures(any())) - .thenReturn(supportedFeaturesFromClientModeImpl); - mLooper.startAutoDispatch(); - long supportedFeatures = mWifiServiceImpl.getSupportedFeatures(); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - return supportedFeatures; - } - - /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ - @Test - public void syncGetSupportedFeaturesForRtt() { - final long featureAware = WifiManager.WIFI_FEATURE_AWARE; - final long featureInfra = WifiManager.WIFI_FEATURE_INFRA; - final long featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT; - final long featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT; - final long featureLongBits = 0x1000000000L; - - assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, false)); - assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, true)); - assertEquals(featureAware | featureInfra, - testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, false)); - assertEquals(featureAware | featureInfra, - testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, true)); - assertEquals(featureInfra | featureD2dRtt, - testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, false)); - assertEquals(featureInfra, - testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, true)); - assertEquals(featureInfra | featureD2apRtt, - testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, false)); - assertEquals(featureInfra, - testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, true)); - assertEquals(featureInfra | featureD2dRtt | featureD2apRtt, - testGetSupportedFeaturesCaseForRtt( - featureInfra | featureD2dRtt | featureD2apRtt, false)); - assertEquals(featureInfra, - testGetSupportedFeaturesCaseForRtt( - featureInfra | featureD2dRtt | featureD2apRtt, true)); - - assertEquals(featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, - testGetSupportedFeaturesCaseForRtt( - featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, false)); - assertEquals(featureLongBits | featureInfra, - testGetSupportedFeaturesCaseForRtt( - featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, true)); - } - - private long testGetSupportedFeaturesCaseForMacRandomization( - long supportedFeaturesFromClientModeImpl, boolean apMacRandomizationEnabled, - boolean staConnectedMacRandomizationEnabled, boolean p2pMacRandomizationEnabled) { - when(mResources.getBoolean( - R.bool.config_wifi_connected_mac_randomization_supported)) - .thenReturn(staConnectedMacRandomizationEnabled); - when(mResources.getBoolean( - R.bool.config_wifi_ap_mac_randomization_supported)) - .thenReturn(apMacRandomizationEnabled); - when(mResources.getBoolean( - R.bool.config_wifi_p2p_mac_randomization_supported)) - .thenReturn(p2pMacRandomizationEnabled); - when(mClientModeImpl.syncGetSupportedFeatures( - any())).thenReturn(supportedFeaturesFromClientModeImpl); - mLooper.startAutoDispatch(); - long supportedFeatures = mWifiServiceImpl.getSupportedFeatures(); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - return supportedFeatures; - } - - /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ - @Test - public void syncGetSupportedFeaturesForMacRandomization() { - final long featureStaConnectedMacRandomization = - WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; - final long featureApMacRandomization = - WifiManager.WIFI_FEATURE_AP_RAND_MAC; - final long featureP2pMacRandomization = - WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; - - assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization - | featureP2pMacRandomization, - testGetSupportedFeaturesCaseForMacRandomization( - featureP2pMacRandomization, true, true, true)); - // p2p supported by HAL, but disabled by overlay. - assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization, - testGetSupportedFeaturesCaseForMacRandomization( - featureP2pMacRandomization, true, true, false)); - assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization, - testGetSupportedFeaturesCaseForMacRandomization(0, true, true, false)); - } - - /** - * Verifies that syncGetSupportedFeatures() adds capabilities based on interface - * combination. - */ - @Test - public void syncGetSupportedFeaturesForStaApConcurrency() { - long supportedFeaturesFromClientModeImpl = WifiManager.WIFI_FEATURE_OWE; - when(mClientModeImpl.syncGetSupportedFeatures( - any())).thenReturn(supportedFeaturesFromClientModeImpl); - - when(mActiveModeWarden.isStaApConcurrencySupported()) - .thenReturn(false); - mLooper.startAutoDispatch(); - assertEquals(supportedFeaturesFromClientModeImpl, - mWifiServiceImpl.getSupportedFeatures()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - - when(mActiveModeWarden.isStaApConcurrencySupported()) - .thenReturn(true); - mLooper.startAutoDispatch(); - assertEquals(supportedFeaturesFromClientModeImpl | WifiManager.WIFI_FEATURE_AP_STA, - mWifiServiceImpl.getSupportedFeatures()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - } - - @Test - public void testSetScanThrottleEnabledWithNetworkSettingsPermission() { - doNothing().when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.setScanThrottleEnabled(true); - mLooper.dispatchAll(); - verify(mScanRequestProxy).setScanThrottleEnabled(true); - - mWifiServiceImpl.setScanThrottleEnabled(false); - mLooper.dispatchAll(); - verify(mScanRequestProxy).setScanThrottleEnabled(false); - } - - @Test(expected = SecurityException.class) - public void testSetScanThrottleEnabledWithNoNetworkSettingsPermission() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - - mWifiServiceImpl.setScanThrottleEnabled(true); - mLooper.dispatchAll(); - verify(mScanRequestProxy, never()).setScanThrottleEnabled(true); - } - - @Test - public void testIsScanThrottleEnabled() { - when(mScanRequestProxy.isScanThrottleEnabled()).thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.isScanThrottleEnabled()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mScanRequestProxy).isScanThrottleEnabled(); - } - - @Test - public void testSetAutoWakeupEnabledWithNetworkSettingsPermission() { - doNothing().when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.setAutoWakeupEnabled(true); - mLooper.dispatchAll(); - verify(mWakeupController).setEnabled(true); - - mWifiServiceImpl.setAutoWakeupEnabled(false); - mLooper.dispatchAll(); - verify(mWakeupController).setEnabled(false); - } - - @Test(expected = SecurityException.class) - public void testSetAutoWakeupEnabledWithNoNetworkSettingsPermission() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - - mWifiServiceImpl.setAutoWakeupEnabled(true); - mLooper.dispatchAll(); - verify(mWakeupController, never()).setEnabled(true); - } - - @Test - public void testIsAutoWakeupEnabled() { - when(mWakeupController.isEnabled()).thenReturn(true); - mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.isAutoWakeupEnabled()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mWakeupController).isEnabled(); - } - - @Test - public void testSetScanAlwaysAvailableWithNetworkSettingsPermission() { - doNothing().when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - mWifiServiceImpl.setScanAlwaysAvailable(true); - verify(mSettingsStore).handleWifiScanAlwaysAvailableToggled(true); - verify(mActiveModeWarden).scanAlwaysModeChanged(); - - mWifiServiceImpl.setScanAlwaysAvailable(false); - verify(mSettingsStore).handleWifiScanAlwaysAvailableToggled(false); - verify(mActiveModeWarden, times(2)).scanAlwaysModeChanged(); - } - - @Test(expected = SecurityException.class) - public void testSetScanAlwaysAvailableWithNoNetworkSettingsPermission() { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), - eq("WifiService")); - - mWifiServiceImpl.setScanAlwaysAvailable(true); - verify(mSettingsStore, never()).handleWifiScanAlwaysAvailableToggled(anyBoolean()); - verify(mActiveModeWarden, never()).scanAlwaysModeChanged(); - } - - private List<ScanResult> createScanResultList() { - return Collections.singletonList(new ScanResult(WifiSsid.createFromAsciiEncoded(TEST_SSID), - TEST_SSID, TEST_BSSID, 1245, 0, TEST_CAP, -78, 2450, 1025, 22, 33, 20, 0, 0, true)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiSettingsConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiSettingsConfigStoreTest.java deleted file mode 100644 index e2e2575d8..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiSettingsConfigStoreTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.validateMockitoUsage; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.wifi.WifiMigration; -import android.os.Handler; -import android.os.test.TestLooper; -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.WifiSettingsConfigStore.Key; -import com.android.server.wifi.util.SettingsMigrationDataHolder; -import com.android.server.wifi.util.XmlUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - - -/** - * Unit tests for {@link com.android.server.wifi.WifiSettingsConfigStore}. - */ -@SmallTest -public class WifiSettingsConfigStoreTest extends WifiBaseTest { - @Mock - private Context mContext; - @Mock - private SettingsMigrationDataHolder mSettingsMigrationDataHolder; - @Mock - private WifiConfigStore mWifiConfigStore; - @Mock - private WifiConfigManager mWifiConfigManager; - - private TestLooper mLooper; - private WifiSettingsConfigStore mWifiSettingsConfigStore; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mLooper = new TestLooper(); - mWifiSettingsConfigStore = - new WifiSettingsConfigStore(mContext, new Handler(mLooper.getLooper()), - mSettingsMigrationDataHolder, mWifiConfigManager, mWifiConfigStore); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - } - - @Test - public void testSetterGetter() { - assertFalse(mWifiSettingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED)); - mWifiSettingsConfigStore.put(WIFI_VERBOSE_LOGGING_ENABLED, true); - mLooper.dispatchAll(); - assertTrue(mWifiSettingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED)); - verify(mWifiConfigManager).saveToStore(true); - } - - @Test - public void testChangeListener() { - WifiSettingsConfigStore.OnSettingsChangedListener listener = mock( - WifiSettingsConfigStore.OnSettingsChangedListener.class); - mWifiSettingsConfigStore.registerChangeListener(WIFI_VERBOSE_LOGGING_ENABLED, listener, - new Handler(mLooper.getLooper())); - mWifiSettingsConfigStore.put(WIFI_VERBOSE_LOGGING_ENABLED, true); - mLooper.dispatchAll(); - verify(listener).onSettingsChanged(WIFI_VERBOSE_LOGGING_ENABLED, true); - - mWifiSettingsConfigStore.unregisterChangeListener(WIFI_VERBOSE_LOGGING_ENABLED, listener); - mWifiSettingsConfigStore.put(WIFI_VERBOSE_LOGGING_ENABLED, false); - mLooper.dispatchAll(); - verifyNoMoreInteractions(listener); - } - - @Test - public void testSaveAndLoadFromStore() throws Exception { - ArgumentCaptor<WifiConfigStore.StoreData> storeDataCaptor = ArgumentCaptor.forClass( - WifiConfigStore.StoreData.class); - verify(mWifiConfigStore).registerStoreData(storeDataCaptor.capture()); - assertNotNull(storeDataCaptor.getValue()); - - XmlPullParser in = createSettingsTestXmlForParsing(WIFI_VERBOSE_LOGGING_ENABLED, true); - - storeDataCaptor.getValue().resetData(); - storeDataCaptor.getValue().deserializeData(in, in.getDepth(), -1, null); - - assertTrue(mWifiSettingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED)); - // verify that we did not trigger migration. - verifyNoMoreInteractions(mSettingsMigrationDataHolder); - } - - @Test - public void testLoadFromMigration() throws Exception { - ArgumentCaptor<WifiConfigStore.StoreData> storeDataCaptor = ArgumentCaptor.forClass( - WifiConfigStore.StoreData.class); - verify(mWifiConfigStore).registerStoreData(storeDataCaptor.capture()); - assertNotNull(storeDataCaptor.getValue()); - - WifiMigration.SettingsMigrationData migrationData = mock( - WifiMigration.SettingsMigrationData.class); - when(mSettingsMigrationDataHolder.retrieveData()).thenReturn(migrationData); - when(migrationData.isVerboseLoggingEnabled()).thenReturn(true); - - // indicate that there is not data in the store file to trigger migration. - storeDataCaptor.getValue().resetData(); - storeDataCaptor.getValue().deserializeData(null, -1, -1, null); - mLooper.dispatchAll(); - - assertTrue(mWifiSettingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED)); - // Trigger store file write after migration. - verify(mWifiConfigManager).saveToStore(true); - } - - private XmlPullParser createSettingsTestXmlForParsing(Key key, Object value) - throws Exception { - Map<String, Object> settings = new HashMap<>(); - // Serialize - settings.put(key.key, value); - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - XmlUtil.writeDocumentStart(out, "Test"); - XmlUtil.writeNextValue(out, "Values", settings); - XmlUtil.writeDocumentEnd(out, "Test"); - - // Start Deserializing - final XmlPullParser in = Xml.newPullParser(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - XmlUtil.gotoDocumentStart(in, "Test"); - return in; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java b/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java deleted file mode 100644 index 1f4af5cc0..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.validateMockitoUsage; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.wifi.SoftApConfiguration; -import android.os.Binder; -import android.os.Process; - -import androidx.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.FileDescriptor; - -/** - * Unit tests for {@link com.android.server.wifi.WifiShellCommand}. - */ -@SmallTest -public class WifiShellCommandTest extends WifiBaseTest { - private static final String TEST_PACKAGE = "com.android.test"; - - @Mock WifiInjector mWifiInjector; - @Mock ClientModeImpl mClientModeImpl; - @Mock WifiLockManager mWifiLockManager; - @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - @Mock WifiConfigManager mWifiConfigManager; - @Mock WifiNative mWifiNative; - @Mock HostapdHal mHostapdHal; - @Mock WifiCountryCode mWifiCountryCode; - @Mock WifiLastResortWatchdog mWifiLastResortWatchdog; - @Mock WifiServiceImpl mWifiService; - @Mock Context mContext; - @Mock ConnectivityManager mConnectivityManager; - @Mock WifiCarrierInfoManager mWifiCarrierInfoManager; - - WifiShellCommand mWifiShellCommand; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl); - when(mWifiInjector.getWifiLockManager()).thenReturn(mWifiLockManager); - when(mWifiInjector.getWifiNetworkSuggestionsManager()) - .thenReturn(mWifiNetworkSuggestionsManager); - when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager); - when(mWifiInjector.getHostapdHal()).thenReturn(mHostapdHal); - when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); - when(mWifiInjector.getWifiCountryCode()).thenReturn(mWifiCountryCode); - when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); - when(mWifiInjector.getWifiCarrierInfoManager()).thenReturn(mWifiCarrierInfoManager); - - mWifiShellCommand = new WifiShellCommand(mWifiInjector, mWifiService, mContext); - - // by default emulate shell uid. - BinderUtil.setUid(Process.SHELL_UID); - } - - @After - public void tearDown() throws Exception { - validateMockitoUsage(); - } - - @Test - public void testSetIpReachDisconnect() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"set-ipreach-disconnect", "enabled"}); - verify(mClientModeImpl, never()).setIpReachabilityDisconnectEnabled(anyBoolean()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"set-ipreach-disconnect", "enabled"}); - verify(mClientModeImpl).setIpReachabilityDisconnectEnabled(true); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"set-ipreach-disconnect", "disabled"}); - verify(mClientModeImpl).setIpReachabilityDisconnectEnabled(false); - - // invalid arg - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"set-ipreach-disconnect", "yes"}); - verifyNoMoreInteractions(mClientModeImpl); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - } - - @Test - public void testGetIpReachDisconnect() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"get-ipreach-disconnect"}); - verify(mClientModeImpl, never()).getIpReachabilityDisconnectEnabled(); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - when(mClientModeImpl.getIpReachabilityDisconnectEnabled()).thenReturn(true); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"get-ipreach-disconnect"}); - verify(mClientModeImpl).getIpReachabilityDisconnectEnabled(); - mWifiShellCommand.getOutPrintWriter().toString().contains( - "IPREACH_DISCONNECT state is true"); - - when(mClientModeImpl.getIpReachabilityDisconnectEnabled()).thenReturn(false); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"get-ipreach-disconnect"}); - verify(mClientModeImpl, times(2)).getIpReachabilityDisconnectEnabled(); - mWifiShellCommand.getOutPrintWriter().toString().contains( - "IPREACH_DISCONNECT state is false"); - } - - @Test - public void testSetPollRssiIntervalMsecs() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"set-poll-rssi-interval-msecs", "5"}); - verify(mClientModeImpl, never()).setPollRssiIntervalMsecs(anyInt()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"set-poll-rssi-interval-msecs", "5"}); - verify(mClientModeImpl).setPollRssiIntervalMsecs(5); - - // invalid arg - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"set-poll-rssi-interval-msecs", "0"}); - verifyNoMoreInteractions(mClientModeImpl); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - } - - @Test - public void testGetPollRssiIntervalMsecs() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"get-poll-rssi-interval-msecs"}); - verify(mClientModeImpl, never()).getPollRssiIntervalMsecs(); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - when(mClientModeImpl.getPollRssiIntervalMsecs()).thenReturn(5); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"get-poll-rssi-interval-msecs"}); - verify(mClientModeImpl).getPollRssiIntervalMsecs(); - mWifiShellCommand.getOutPrintWriter().toString().contains( - "ClientModeImpl.mPollRssiIntervalMsecs = 5"); - } - - @Test - public void testForceHiPerfMode() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"force-hi-perf-mode", "enabled"}); - verify(mWifiLockManager, never()).forceHiPerfMode(anyBoolean()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"force-hi-perf-mode", "enabled"}); - verify(mWifiLockManager).forceHiPerfMode(true); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"force-hi-perf-mode", "disabled"}); - verify(mWifiLockManager).forceHiPerfMode(false); - } - - @Test - public void testForceLowLatencyMode() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"force-low-latency-mode", "enabled"}); - verify(mWifiLockManager, never()).forceLowLatencyMode(anyBoolean()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"force-low-latency-mode", "enabled"}); - verify(mWifiLockManager).forceLowLatencyMode(true); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"force-low-latency-mode", "disabled"}); - verify(mWifiLockManager).forceLowLatencyMode(false); - } - - @Test - public void testNetworkSuggestionsSetUserApproved() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-suggestions-set-user-approved", TEST_PACKAGE, "yes"}); - verify(mWifiNetworkSuggestionsManager, never()).setHasUserApprovedForApp( - anyBoolean(), anyString()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-suggestions-set-user-approved", TEST_PACKAGE, "yes"}); - verify(mWifiNetworkSuggestionsManager).setHasUserApprovedForApp( - true, TEST_PACKAGE); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-suggestions-set-user-approved", TEST_PACKAGE, "no"}); - verify(mWifiNetworkSuggestionsManager).setHasUserApprovedForApp( - false, TEST_PACKAGE); - } - - @Test - public void testNetworkSuggestionsHasUserApproved() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-suggestions-has-user-approved", TEST_PACKAGE}); - verify(mWifiNetworkSuggestionsManager, never()).hasUserApprovedForApp(anyString()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - when(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE)) - .thenReturn(true); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-suggestions-has-user-approved", TEST_PACKAGE}); - verify(mWifiNetworkSuggestionsManager).hasUserApprovedForApp(TEST_PACKAGE); - mWifiShellCommand.getOutPrintWriter().toString().contains("yes"); - - when(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE)) - .thenReturn(false); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-suggestions-has-user-approved", TEST_PACKAGE}); - verify(mWifiNetworkSuggestionsManager, times(2)).hasUserApprovedForApp(TEST_PACKAGE); - mWifiShellCommand.getOutPrintWriter().toString().contains("no"); - } - - @Test - public void testImsiProtectionExemptionsSetUserApproved() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"imsi-protection-exemption-set-user-approved-for-carrier", "5", - "yes"}); - verify(mWifiCarrierInfoManager, never()).setHasUserApprovedImsiPrivacyExemptionForCarrier( - anyBoolean(), anyInt()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"imsi-protection-exemption-set-user-approved-for-carrier", "5", - "yes"}); - verify(mWifiCarrierInfoManager).setHasUserApprovedImsiPrivacyExemptionForCarrier( - true, 5); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"imsi-protection-exemption-set-user-approved-for-carrier", "5", - "no"}); - verify(mWifiCarrierInfoManager).setHasUserApprovedImsiPrivacyExemptionForCarrier( - false, 5); - } - - @Test - public void testImsiProtectionExemptionsHasUserApproved() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"imsi-protection-exemption-has-user-approved-for-carrier", "5"}); - verify(mWifiCarrierInfoManager, never()).hasUserApprovedImsiPrivacyExemptionForCarrier( - anyInt()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(5)) - .thenReturn(true); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"imsi-protection-exemption-has-user-approved-for-carrier", "5"}); - verify(mWifiCarrierInfoManager).hasUserApprovedImsiPrivacyExemptionForCarrier(5); - mWifiShellCommand.getOutPrintWriter().toString().contains("yes"); - - when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(5)) - .thenReturn(false); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"imsi-protection-exemption-has-user-approved-for-carrier", "5"}); - verify(mWifiCarrierInfoManager, times(2)).hasUserApprovedImsiPrivacyExemptionForCarrier(5); - mWifiShellCommand.getOutPrintWriter().toString().contains("no"); - } - - @Test - public void testNetworkRequestsSetUserApproved() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-requests-set-user-approved", TEST_PACKAGE, "yes"}); - verify(mClientModeImpl, never()).setNetworkRequestUserApprovedApp( - anyString(), anyBoolean()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-requests-set-user-approved", TEST_PACKAGE, "yes"}); - verify(mClientModeImpl).setNetworkRequestUserApprovedApp(TEST_PACKAGE, true); - - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-requests-set-user-approved", TEST_PACKAGE, "no"}); - verify(mClientModeImpl).setNetworkRequestUserApprovedApp(TEST_PACKAGE, false); - } - - @Test - public void testNetworkRequestsHasUserApproved() { - // not allowed for unrooted shell. - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-requests-has-user-approved", TEST_PACKAGE}); - verify(mClientModeImpl, never()).hasNetworkRequestUserApprovedApp(anyString()); - assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); - - BinderUtil.setUid(Process.ROOT_UID); - - when(mClientModeImpl.hasNetworkRequestUserApprovedApp(TEST_PACKAGE)) - .thenReturn(true); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-requests-has-user-approved", TEST_PACKAGE}); - verify(mClientModeImpl).hasNetworkRequestUserApprovedApp(TEST_PACKAGE); - mWifiShellCommand.getOutPrintWriter().toString().contains("yes"); - - when(mClientModeImpl.hasNetworkRequestUserApprovedApp(TEST_PACKAGE)) - .thenReturn(false); - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"network-requests-has-user-approved", TEST_PACKAGE}); - verify(mClientModeImpl, times(2)).hasNetworkRequestUserApprovedApp(TEST_PACKAGE); - mWifiShellCommand.getOutPrintWriter().toString().contains("no"); - } - - @Test - public void testStartSoftAp() { - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"start-softap", "ap1", "wpa2", "xyzabc321", "-b", "5"}); - ArgumentCaptor<SoftApConfiguration> softApConfigurationCaptor = ArgumentCaptor.forClass( - SoftApConfiguration.class); - verify(mWifiService).startTetheredHotspot(softApConfigurationCaptor.capture()); - assertEquals(SoftApConfiguration.BAND_5GHZ, - softApConfigurationCaptor.getValue().getBand()); - assertEquals(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, - softApConfigurationCaptor.getValue().getSecurityType()); - assertEquals("\"ap1\"", softApConfigurationCaptor.getValue().getSsid()); - assertEquals("xyzabc321", softApConfigurationCaptor.getValue().getPassphrase()); - } - - @Test - public void testStopSoftAp() { - mWifiShellCommand.exec( - new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), - new String[]{"stop-softap"}); - verify(mWifiService).stopSoftAp(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateTrackerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateTrackerTest.java deleted file mode 100644 index 8531240bd..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiStateTrackerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.os.BatteryStatsManager; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/* - * Unit tests for {@link com.android.server.wifi.WifiStateTracker}. - */ -@SmallTest -public class WifiStateTrackerTest extends WifiBaseTest { - - private static final String TAG = "WifiStateTrackerTest"; - @Mock - BatteryStatsManager mBatteryStats; - private WifiStateTracker mWifiStateTracker; - - /** - * Setup test. - */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mWifiStateTracker = new WifiStateTracker(mBatteryStats); - } - - /** - * Ensure BatteryStats's reportWifiState() is called when the method - * updateState() is invoked on WifiStateTracker for relevant states. - */ - @Test - public void testBatteryStatsUpdated() throws Exception { - int[] relevantStates = new int[] { WifiStateTracker.SCAN_MODE, - WifiStateTracker.CONNECTED, WifiStateTracker.DISCONNECTED, - WifiStateTracker.SOFT_AP}; - for (int i = 0; i < relevantStates.length; i++) { - mWifiStateTracker.updateState(relevantStates[i]); - } - verify(mBatteryStats, times(relevantStates.length)).reportWifiState(anyInt(), any()); - } - - /** - * Ensure BatteryStats's reportWifiState() is not called when the method - * updateState() is invoked on WifiStateTracker for irrelevant states. - */ - @Test - public void testBatteryStatsNotUpdated() throws Exception { - int[] irrelevantStates = new int[] { WifiStateTracker.SCAN_MODE - 1, - WifiStateTracker.SOFT_AP + 1}; - for (int i = 0; i < irrelevantStates.length; i++) { - mWifiStateTracker.updateState(irrelevantStates[i]); - } - verify(mBatteryStats, times(0)).reportWifiState(anyInt(), any()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiTestUtil.java b/tests/wifitests/src/com/android/server/wifi/WifiTestUtil.java deleted file mode 100644 index acd6777f6..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiTestUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi; - -import androidx.test.filters.SmallTest; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -/** - * Generial Utilities for Wifi tests - */ -@SmallTest -public class WifiTestUtil { - - /** - * Walk up the stack and find the first method annotated with @Test - * Note: this will evaluate all overloads with the method name for the @Test annotation - */ - public static String getTestMethod() { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - for (StackTraceElement e : stack) { - if (e.isNativeMethod()) { - continue; - } - Class clazz; - try { - clazz = Class.forName(e.getClassName()); - } catch (ClassNotFoundException ex) { - throw new RuntimeException("Could not find class from stack", ex); - } - Method[] methods = clazz.getDeclaredMethods(); - for (Method method : methods) { - if (method.getName().equals(e.getMethodName())) { - Annotation[] annotations = method.getDeclaredAnnotations(); - for (Annotation annotation : annotations) { - if (annotation.annotationType().equals(org.junit.Test.class)) { - return e.getClassName() + "#" + e.getMethodName(); - } - } - } - } - } - throw new RuntimeException("Could not find a test method in the stack"); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiThreadRunnerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiThreadRunnerTest.java deleted file mode 100644 index 59f2ed817..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiThreadRunnerTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -import android.os.Handler; -import android.os.HandlerThread; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.util.function.Supplier; - -@SmallTest -public class WifiThreadRunnerTest { - - private static final int RESULT = 2; - private static final int VALUE_ON_TIMEOUT = -1; - - private WifiThreadRunner mWifiThreadRunner; - - @Mock private Runnable mRunnable; - - private Handler mHandler; - - @Spy private Supplier<Integer> mSupplier = () -> RESULT; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - HandlerThread mHandlerThread = new HandlerThread("WifiThreadRunnerTestHandlerThread"); - mHandlerThread.start(); - - // runWithScissors() is a final method that cannot be mocked, instead wrap it in a spy, - // then it can be mocked - mHandler = spy(mHandlerThread.getThreadHandler()); - - mWifiThreadRunner = new WifiThreadRunner(mHandler); - } - - @Test - public void callSuccess_returnExpectedValue() { - // doAnswer(<lambda>).when(<spy>).method(<args>) syntax is needed for spies instead of - // when(<mock>.method(<args>)).thenAnswer(<lambda>) for mocks - doAnswer(invocation -> { - Object[] args = invocation.getArguments(); - Runnable runnable = (Runnable) args[0]; - runnable.run(); - return true; - }).when(mHandler).runWithScissors(any(), anyLong()); - - Integer result = mWifiThreadRunner.call(mSupplier, VALUE_ON_TIMEOUT); - - assertThat(result).isEqualTo(RESULT); - verify(mSupplier).get(); - } - - @Test - public void callFailure_returnValueOnTimeout() { - doReturn(false).when(mHandler).post(any()); - - Integer result = mWifiThreadRunner.call(mSupplier, VALUE_ON_TIMEOUT); - - assertThat(result).isEqualTo(VALUE_ON_TIMEOUT); - verify(mSupplier, never()).get(); - } - - @Test - public void runSuccess() { - doAnswer(invocation -> { - Object[] args = invocation.getArguments(); - Runnable runnable = (Runnable) args[0]; - runnable.run(); - return true; - }).when(mHandler).runWithScissors(any(), anyLong()); - - boolean result = mWifiThreadRunner.run(mRunnable); - - assertThat(result).isTrue(); - verify(mRunnable).run(); - } - - @Test - public void runFailure() { - doReturn(false).when(mHandler).post(any()); - - boolean runSuccess = mWifiThreadRunner.run(mRunnable); - - assertThat(runSuccess).isFalse(); - verify(mRunnable, never()).run(); - } - - @Test - public void postSuccess() { - doReturn(true).when(mHandler).post(any()); - - boolean postSuccess = mWifiThreadRunner.post(mRunnable); - - assertThat(postSuccess).isTrue(); - verify(mHandler).post(mRunnable); - // assert that the runnable is not run on the calling thread - verify(mRunnable, never()).run(); - } - - @Test - public void postFailure() { - doReturn(false).when(mHandler).post(any()); - - boolean postSuccess = mWifiThreadRunner.post(mRunnable); - - assertThat(postSuccess).isFalse(); - verify(mHandler).post(mRunnable); - verify(mRunnable, never()).run(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiTrafficPollerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiTrafficPollerTest.java deleted file mode 100644 index ecdf490c4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiTrafficPollerTest.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.net.wifi.ITrafficStateCallback; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.WifiTrafficPoller}. - */ -@SmallTest -public class WifiTrafficPollerTest extends WifiBaseTest { - public static final String TAG = "WifiTrafficPollerTest"; - - private TestLooper mLooper; - private WifiTrafficPoller mWifiTrafficPoller; - private final static long DEFAULT_PACKET_COUNT = 10; - private final static long TX_PACKET_COUNT = 40; - private final static long RX_PACKET_COUNT = 50; - private static final int TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER = 14; - private static final int TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER2 = 42; - - @Mock IBinder mAppBinder; - @Mock ITrafficStateCallback mTrafficStateCallback; - - @Mock IBinder mAppBinder2; - @Mock ITrafficStateCallback mTrafficStateCallback2; - - /** - * Called before each test - */ - @Before - public void setUp() throws Exception { - // Ensure looper exists - mLooper = new TestLooper(); - MockitoAnnotations.initMocks(this); - - mWifiTrafficPoller = new WifiTrafficPoller(new Handler(mLooper.getLooper())); - - // Set the current mTxPkts and mRxPkts to DEFAULT_PACKET_COUNT - mWifiTrafficPoller.notifyOnDataActivity(DEFAULT_PACKET_COUNT, DEFAULT_PACKET_COUNT); - } - - /** - * Verify that clients should be notified of activity in case Tx/Rx packet count changes. - */ - @Test - public void testClientNotification() throws RemoteException { - // Register Client to verify that Tx/RX packet message is properly received. - mWifiTrafficPoller.addCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT, RX_PACKET_COUNT); - - // Client should get the DATA_ACTIVITY_NOTIFICATION - verify(mTrafficStateCallback).onStateChanged( - WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT); - } - - /** - * Verify that remove client should be handled - */ - @Test - public void testRemoveClient() throws RemoteException { - // Register Client to verify that Tx/RX packet message is properly received. - mWifiTrafficPoller.addCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - mWifiTrafficPoller.removeCallback(TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - verify(mAppBinder).unlinkToDeath(any(), anyInt()); - - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT, RX_PACKET_COUNT); - - // Client should not get any message after the client is removed. - verify(mTrafficStateCallback, never()).onStateChanged(anyInt()); - } - - /** - * Verify that remove client ignores when callback identifier is wrong. - */ - @Test - public void testRemoveClientWithWrongIdentifier() throws RemoteException { - // Register Client to verify that Tx/RX packet message is properly received. - mWifiTrafficPoller.addCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - mWifiTrafficPoller.removeCallback(TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER + 5); - mLooper.dispatchAll(); - - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT, RX_PACKET_COUNT); - - // Client should get the DATA_ACTIVITY_NOTIFICATION - verify(mTrafficStateCallback).onStateChanged( - WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT); - } - - /** - * - * Verify that traffic poller registers for death notification on adding client. - */ - @Test - public void registersForBinderDeathOnAddClient() throws Exception { - mWifiTrafficPoller.addCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - } - - /** - * - * Verify that traffic poller registers for death notification on adding client. - */ - @Test - public void addCallbackFailureOnLinkToDeath() throws Exception { - doThrow(new RemoteException()) - .when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - mWifiTrafficPoller.addCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT, RX_PACKET_COUNT); - - // Client should not get any message callback add failed. - verify(mTrafficStateCallback, never()).onStateChanged(anyInt()); - } - - /** Test that if the data activity didn't change, the client is not notified. */ - @Test - public void unchangedDataActivityNotNotified() throws Exception { - mWifiTrafficPoller.addCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT, RX_PACKET_COUNT); - - verify(mTrafficStateCallback).onStateChanged( - WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT); - - // since TX and RX both increased, should still be INOUT. But since it's the same data - // activity as before, the callback should not be triggered again. - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT + 1, RX_PACKET_COUNT + 1); - - // still only called once - verify(mTrafficStateCallback).onStateChanged(anyInt()); - } - - /** - * If there are 2 callbacks, but the data activity only changed for one of them, only that - * callback should be triggered. - */ - @Test - public void multipleCallbacksOnlyChangedNotified() throws Exception { - mWifiTrafficPoller.addCallback( - mAppBinder, mTrafficStateCallback, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER); - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT, RX_PACKET_COUNT); - - verify(mTrafficStateCallback).onStateChanged( - WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT); - verify(mTrafficStateCallback2, never()).onStateChanged(anyInt()); - - mWifiTrafficPoller.addCallback( - mAppBinder2, mTrafficStateCallback2, TEST_TRAFFIC_STATE_CALLBACK_IDENTIFIER2); - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT + 1, RX_PACKET_COUNT + 1); - - // still only called once - verify(mTrafficStateCallback).onStateChanged(anyInt()); - // called for the first time with INOUT - verify(mTrafficStateCallback2) - .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT); - // not called with anything else - verify(mTrafficStateCallback2).onStateChanged(anyInt()); - - // now only TX increased - mWifiTrafficPoller.notifyOnDataActivity(TX_PACKET_COUNT + 2, RX_PACKET_COUNT + 1); - - // called once with OUT - verify(mTrafficStateCallback) - .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT); - // called twice total - verify(mTrafficStateCallback, times(2)).onStateChanged(anyInt()); - - // called once with OUT - verify(mTrafficStateCallback2) - .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT); - // called twice total - verify(mTrafficStateCallback2, times(2)).onStateChanged(anyInt()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java deleted file mode 100644 index 9cf9ed4b1..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java +++ /dev/null @@ -1,3370 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyByte; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.anyShort; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.hardware.wifi.V1_0.IWifiApIface; -import android.hardware.wifi.V1_0.IWifiChip; -import android.hardware.wifi.V1_0.IWifiChipEventCallback; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiStaIface; -import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.StaApfPacketFilterCapabilities; -import android.hardware.wifi.V1_0.StaBackgroundScanCapabilities; -import android.hardware.wifi.V1_0.StaBackgroundScanParameters; -import android.hardware.wifi.V1_0.StaLinkLayerIfacePacketStats; -import android.hardware.wifi.V1_0.StaLinkLayerIfaceStats; -import android.hardware.wifi.V1_0.StaLinkLayerRadioStats; -import android.hardware.wifi.V1_0.StaLinkLayerStats; -import android.hardware.wifi.V1_0.StaRoamingCapabilities; -import android.hardware.wifi.V1_0.StaRoamingState; -import android.hardware.wifi.V1_0.StaScanData; -import android.hardware.wifi.V1_0.StaScanDataFlagMask; -import android.hardware.wifi.V1_0.StaScanResult; -import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; -import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; -import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags; -import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; -import android.hardware.wifi.V1_0.WifiDebugRingBufferVerboseLevel; -import android.hardware.wifi.V1_0.WifiDebugRxPacketFate; -import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport; -import android.hardware.wifi.V1_0.WifiDebugTxPacketFate; -import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport; -import android.hardware.wifi.V1_0.WifiInformationElement; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_2.IWifiChipEventCallback.IfaceInfo; -import android.hardware.wifi.V1_2.IWifiChipEventCallback.RadioModeInfo; -import android.hardware.wifi.V1_3.WifiChannelStats; -import android.net.KeepalivePacketData; -import android.net.MacAddress; -import android.net.NattKeepalivePacketData; -import android.net.apf.ApfCapabilities; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.RemoteException; -import android.os.test.TestLooper; -import android.system.OsConstants; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; -import com.android.server.wifi.WifiLinkLayerStats.ChannelStats; -import com.android.server.wifi.util.NativeUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.stubbing.Answer; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.WifiVendorHal}. - */ -@SmallTest -public class WifiVendorHalTest extends WifiBaseTest { - - private static final String TEST_IFACE_NAME = "wlan0"; - private static final String TEST_IFACE_NAME_1 = "wlan1"; - private static final MacAddress TEST_MAC_ADDRESS = MacAddress.fromString("ee:33:a2:94:10:92"); - private static final int[] TEST_FREQUENCIES = - {2412, 2417, 2422, 2427, 2432, 2437}; - - private WifiVendorHal mWifiVendorHal; - private WifiStatus mWifiStatusSuccess; - private WifiStatus mWifiStatusFailure; - private WifiStatus mWifiStatusBusy; - private WifiLog mWifiLog; - private TestLooper mLooper; - private Handler mHandler; - @Mock - private HalDeviceManager mHalDeviceManager; - @Mock - private WifiVendorHal.HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; - @Mock - private IWifiApIface mIWifiApIface; - @Mock - private android.hardware.wifi.V1_4.IWifiApIface mIWifiApIfaceV14; - @Mock - private IWifiChip mIWifiChip; - @Mock - private android.hardware.wifi.V1_1.IWifiChip mIWifiChipV11; - @Mock - private android.hardware.wifi.V1_2.IWifiChip mIWifiChipV12; - @Mock - private android.hardware.wifi.V1_3.IWifiChip mIWifiChipV13; - @Mock - private android.hardware.wifi.V1_4.IWifiChip mIWifiChipV14; - @Mock - private IWifiStaIface mIWifiStaIface; - @Mock - private android.hardware.wifi.V1_2.IWifiStaIface mIWifiStaIfaceV12; - @Mock - private android.hardware.wifi.V1_3.IWifiStaIface mIWifiStaIfaceV13; - private IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback; - private IWifiChipEventCallback mIWifiChipEventCallback; - private android.hardware.wifi.V1_2.IWifiChipEventCallback mIWifiChipEventCallbackV12; - private android.hardware.wifi.V1_4.IWifiChipEventCallback mIWifiChipEventCallbackV14; - @Mock - private WifiNative.VendorHalDeathEventHandler mVendorHalDeathHandler; - @Mock - private WifiNative.VendorHalRadioModeChangeEventHandler mVendorHalRadioModeChangeHandler; - - /** - * Spy used to return the V1_1 IWifiChip mock object to simulate the 1.1 HAL running on the - * device. - */ - private class WifiVendorHalSpyV1_1 extends WifiVendorHal { - WifiVendorHalSpyV1_1(HalDeviceManager halDeviceManager, Handler handler) { - super(halDeviceManager, handler); - } - - @Override - protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() { - return mIWifiChipV11; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiChip getWifiChipForV1_2Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiChip getWifiChipForV1_3Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_4.IWifiChip getWifiChipForV1_4Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceForV1_2Mockable( - String ifaceName) { - return null; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceForV1_3Mockable( - String ifaceName) { - return null; - } - } - - /** - * Spy used to return the V1_2 IWifiChip and IWifiStaIface mock objects to simulate - * the 1.2 HAL running on the device. - */ - private class WifiVendorHalSpyV1_2 extends WifiVendorHal { - WifiVendorHalSpyV1_2(HalDeviceManager halDeviceManager, Handler handler) { - super(halDeviceManager, handler); - } - - @Override - protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() { - return mIWifiChipV11; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiChip getWifiChipForV1_2Mockable() { - return mIWifiChipV12; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiChip getWifiChipForV1_3Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_4.IWifiChip getWifiChipForV1_4Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceForV1_2Mockable( - String ifaceName) { - return mIWifiStaIfaceV12; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceForV1_3Mockable( - String ifaceName) { - return null; - } - } - - /** - * Spy used to return the V1_3 IWifiChip and V1_3 IWifiStaIface mock objects to simulate - * the 1.3 HAL running on the device. - */ - private class WifiVendorHalSpyV1_3 extends WifiVendorHal { - WifiVendorHalSpyV1_3(HalDeviceManager halDeviceManager, Handler handler) { - super(halDeviceManager, handler); - } - - @Override - protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() { - return mIWifiChipV11; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiChip getWifiChipForV1_2Mockable() { - return mIWifiChipV12; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiChip getWifiChipForV1_3Mockable() { - return mIWifiChipV13; - } - - @Override - protected android.hardware.wifi.V1_4.IWifiChip getWifiChipForV1_4Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceForV1_2Mockable( - String ifaceName) { - return mIWifiStaIfaceV12; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceForV1_3Mockable( - String ifaceName) { - return mIWifiStaIfaceV13; - } - } - - /** - * Spy used to return the V1_4 IWifiChip and V1_4 IWifiStaIface mock objects to simulate - * the 1.4 HAL running on the device. - */ - private class WifiVendorHalSpyV1_4 extends WifiVendorHal { - WifiVendorHalSpyV1_4(HalDeviceManager halDeviceManager, Handler handler) { - super(halDeviceManager, handler); - } - - @Override - protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() { - return mIWifiChipV11; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiChip getWifiChipForV1_2Mockable() { - return mIWifiChipV12; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiChip getWifiChipForV1_3Mockable() { - return mIWifiChipV13; - } - - @Override - protected android.hardware.wifi.V1_4.IWifiChip getWifiChipForV1_4Mockable() { - return mIWifiChipV14; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceForV1_2Mockable( - String ifaceName) { - return mIWifiStaIfaceV12; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceForV1_3Mockable( - String ifaceName) { - return mIWifiStaIfaceV13; - } - } - - /** - * Identity function to supply a type to its argument, which is a lambda - */ - static Answer<WifiStatus> answerWifiStatus(Answer<WifiStatus> statusLambda) { - return (statusLambda); - } - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mWifiLog = new FakeWifiLog(); - mLooper = new TestLooper(); - mHandler = new Handler(mLooper.getLooper()); - mWifiStatusSuccess = new WifiStatus(); - mWifiStatusSuccess.code = WifiStatusCode.SUCCESS; - mWifiStatusFailure = new WifiStatus(); - mWifiStatusFailure.code = WifiStatusCode.ERROR_UNKNOWN; - mWifiStatusFailure.description = "I don't even know what a Mock Turtle is."; - mWifiStatusBusy = new WifiStatus(); - mWifiStatusBusy.code = WifiStatusCode.ERROR_BUSY; - mWifiStatusBusy.description = "Don't bother me, kid"; - when(mIWifiStaIface.enableLinkLayerStatsCollection(false)).thenReturn(mWifiStatusSuccess); - - // Setup the HalDeviceManager mock's start/stop behaviour. This can be overridden in - // individual tests, if needed. - doAnswer(new AnswerWithArguments() { - public boolean answer() { - when(mHalDeviceManager.isReady()).thenReturn(true); - when(mHalDeviceManager.isStarted()).thenReturn(true); - mHalDeviceManagerStatusCallbacks.onStatusChanged(); - mLooper.dispatchAll(); - return true; - } - }).when(mHalDeviceManager).start(); - - doAnswer(new AnswerWithArguments() { - public void answer() { - when(mHalDeviceManager.isReady()).thenReturn(true); - when(mHalDeviceManager.isStarted()).thenReturn(false); - mHalDeviceManagerStatusCallbacks.onStatusChanged(); - mLooper.dispatchAll(); - } - }).when(mHalDeviceManager).stop(); - when(mHalDeviceManager.createStaIface(any(), eq(null))) - .thenReturn(mIWifiStaIface); - when(mHalDeviceManager.createApIface(any(), eq(null))) - .thenReturn(mIWifiApIface); - when(mHalDeviceManager.removeIface(any())).thenReturn(true); - when(mHalDeviceManager.getChip(any(IWifiIface.class))) - .thenReturn(mIWifiChip); - when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class))) - .thenReturn(mWifiStatusSuccess); - mIWifiStaIfaceEventCallback = null; - when(mIWifiStaIface.registerEventCallback(any(IWifiStaIfaceEventCallback.class))) - .thenAnswer(answerWifiStatus((invocation) -> { - Object[] args = invocation.getArguments(); - mIWifiStaIfaceEventCallback = (IWifiStaIfaceEventCallback) args[0]; - return (mWifiStatusSuccess); - })); - when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class))) - .thenAnswer(answerWifiStatus((invocation) -> { - Object[] args = invocation.getArguments(); - mIWifiChipEventCallback = (IWifiChipEventCallback) args[0]; - return (mWifiStatusSuccess); - })); - when(mIWifiChipV12.registerEventCallback_1_2( - any(android.hardware.wifi.V1_2.IWifiChipEventCallback.class))) - .thenAnswer(answerWifiStatus((invocation) -> { - Object[] args = invocation.getArguments(); - mIWifiChipEventCallbackV12 = - (android.hardware.wifi.V1_2.IWifiChipEventCallback) args[0]; - return (mWifiStatusSuccess); - })); - - when(mIWifiChipV14.registerEventCallback_1_4( - any(android.hardware.wifi.V1_4.IWifiChipEventCallback.class))) - .thenAnswer(answerWifiStatus((invocation) -> { - Object[] args = invocation.getArguments(); - mIWifiChipEventCallbackV14 = - (android.hardware.wifi.V1_4.IWifiChipEventCallback) args[0]; - return (mWifiStatusSuccess); - })); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, TEST_IFACE_NAME); - } - }).when(mIWifiStaIface).getName(any(IWifiIface.getNameCallback.class)); - doAnswer(new AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, TEST_IFACE_NAME); - } - }).when(mIWifiApIface).getName(any(IWifiIface.getNameCallback.class)); - - // Create the vendor HAL object under test. - mWifiVendorHal = new WifiVendorHal(mHalDeviceManager, mHandler); - - // Initialize the vendor HAL to capture the registered callback. - mWifiVendorHal.initialize(mVendorHalDeathHandler); - ArgumentCaptor<WifiVendorHal.HalDeviceManagerStatusListener> hdmCallbackCaptor = - ArgumentCaptor.forClass(WifiVendorHal.HalDeviceManagerStatusListener.class); - verify(mHalDeviceManager).registerStatusListener( - hdmCallbackCaptor.capture(), any(Handler.class)); - mHalDeviceManagerStatusCallbacks = hdmCallbackCaptor.getValue(); - - } - - /** - * Tests the successful starting of HAL in STA mode using - * {@link WifiVendorHal#startVendorHalSta()}. - */ - @Test - public void testStartHalSuccessInStaMode() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createStaIface(any(), eq(null)); - verify(mHalDeviceManager).getChip(eq(mIWifiStaIface)); - verify(mHalDeviceManager).isReady(); - verify(mHalDeviceManager).isStarted(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class)); - - verify(mHalDeviceManager, never()).createApIface(any(), eq(null)); - } - - /** - * Tests the successful starting of HAL in AP mode using - * {@link WifiVendorHal#startVendorHalAp()}. - */ - @Test - public void testStartHalSuccessInApMode() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalAp()); - assertTrue(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createApIface(any(), eq(null)); - verify(mHalDeviceManager).getChip(eq(mIWifiApIface)); - verify(mHalDeviceManager).isReady(); - verify(mHalDeviceManager).isStarted(); - - verify(mHalDeviceManager, never()).createStaIface(any(), eq(null)); - } - - /** - * Tests the failure to start HAL in STA mode using - * {@link WifiVendorHal#startVendorHalSta()}. - */ - @Test - public void testStartHalFailureInStaMode() throws Exception { - // No callbacks are invoked in this case since the start itself failed. So, override - // default AnswerWithArguments that we setup. - doAnswer(new AnswerWithArguments() { - public boolean answer() throws Exception { - return false; - } - }).when(mHalDeviceManager).start(); - assertFalse(mWifiVendorHal.startVendorHalSta()); - assertFalse(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - - verify(mHalDeviceManager, never()).createStaIface(any(), eq(null)); - verify(mHalDeviceManager, never()).createApIface(any(), eq(null)); - verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class)); - verify(mIWifiStaIface, never()) - .registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - } - - /** - * Tests the failure to start HAL in STA mode using - * {@link WifiVendorHal#startVendorHalSta()}. - */ - @Test - public void testStartHalFailureInIfaceCreationInStaMode() throws Exception { - when(mHalDeviceManager.createStaIface(any(), eq(null))).thenReturn(null); - assertFalse(mWifiVendorHal.startVendorHalSta()); - assertFalse(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createStaIface(any(), eq(null)); - verify(mHalDeviceManager).stop(); - - verify(mHalDeviceManager, never()).createApIface(any(), eq(null)); - verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class)); - verify(mIWifiStaIface, never()) - .registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - } - - /** - * Tests the failure to start HAL in STA mode using - * {@link WifiVendorHal#startVendorHalSta()}. - */ - @Test - public void testStartHalFailureInChipGetInStaMode() throws Exception { - when(mHalDeviceManager.getChip(any(IWifiIface.class))).thenReturn(null); - assertFalse(mWifiVendorHal.startVendorHalSta()); - assertFalse(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createStaIface(any(), eq(null)); - verify(mHalDeviceManager).getChip(any(IWifiIface.class)); - verify(mHalDeviceManager).stop(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - - verify(mHalDeviceManager, never()).createApIface(any(), eq(null)); - } - - /** - * Tests the failure to start HAL in STA mode using - * {@link WifiVendorHal#startVendorHalSta()}. - */ - @Test - public void testStartHalFailureInStaIfaceCallbackRegistration() throws Exception { - when(mIWifiStaIface.registerEventCallback(any(IWifiStaIfaceEventCallback.class))) - .thenReturn(mWifiStatusFailure); - assertFalse(mWifiVendorHal.startVendorHalSta()); - assertFalse(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createStaIface(any(), eq(null)); - verify(mHalDeviceManager).stop(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - - verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class)); - verify(mHalDeviceManager, never()).createApIface(any(), eq(null)); - } - - /** - * Tests the failure to start HAL in STA mode using - * {@link WifiVendorHal#startVendorHalSta()}. - */ - @Test - public void testStartHalFailureInChipCallbackRegistration() throws Exception { - when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class))) - .thenReturn(mWifiStatusFailure); - assertFalse(mWifiVendorHal.startVendorHalSta()); - assertFalse(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createStaIface(any(), eq(null)); - verify(mHalDeviceManager).getChip(any(IWifiIface.class)); - verify(mHalDeviceManager).stop(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class)); - - verify(mHalDeviceManager, never()).createApIface(any(), eq(null)); - } - - /** - * Tests the failure to start HAL in AP mode using - * {@link WifiVendorHal#startVendorHalAp()}. - */ - @Test - public void testStartHalFailureInApMode() throws Exception { - when(mHalDeviceManager.createApIface(any(), eq(null))).thenReturn(null); - assertFalse(mWifiVendorHal.startVendorHalAp()); - assertFalse(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createApIface(any(), eq(null)); - verify(mHalDeviceManager).stop(); - - verify(mHalDeviceManager, never()).createStaIface(any(), eq(null)); - verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class)); - } - - /** - * Tests the stopping of HAL in STA mode using - * {@link WifiVendorHal#stopVendorHal()}. - */ - @Test - public void testStopHalInStaMode() { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.isHalStarted()); - - mWifiVendorHal.stopVendorHal(); - assertFalse(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).stop(); - verify(mHalDeviceManager).createStaIface(any(), eq(null)); - verify(mHalDeviceManager).getChip(eq(mIWifiStaIface)); - verify(mHalDeviceManager, times(2)).isReady(); - verify(mHalDeviceManager, times(2)).isStarted(); - - verify(mHalDeviceManager, never()).createApIface(any(), eq(null)); - } - - /** - * Tests the stopping of HAL in AP mode using - * {@link WifiVendorHal#stopVendorHal()}. - */ - @Test - public void testStopHalInApMode() { - assertTrue(mWifiVendorHal.startVendorHalAp()); - assertTrue(mWifiVendorHal.isHalStarted()); - - mWifiVendorHal.stopVendorHal(); - assertFalse(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).stop(); - verify(mHalDeviceManager).createApIface(any(), eq(null)); - verify(mHalDeviceManager).getChip(eq(mIWifiApIface)); - verify(mHalDeviceManager, times(2)).isReady(); - verify(mHalDeviceManager, times(2)).isStarted(); - - verify(mHalDeviceManager, never()).createStaIface(any(), eq(null)); - } - - /** - * Tests the handling of interface destroyed callback from HalDeviceManager. - */ - @Test - public void testStaInterfaceDestroyedHandling() throws Exception { - ArgumentCaptor<InterfaceDestroyedListener> internalListenerCaptor = - ArgumentCaptor.forClass(InterfaceDestroyedListener.class); - InterfaceDestroyedListener externalLister = mock(InterfaceDestroyedListener.class); - - assertTrue(mWifiVendorHal.startVendorHal()); - assertNotNull(mWifiVendorHal.createStaIface(externalLister)); - assertTrue(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createStaIface(internalListenerCaptor.capture(), - eq(null)); - verify(mHalDeviceManager).getChip(eq(mIWifiStaIface)); - verify(mHalDeviceManager).isReady(); - verify(mHalDeviceManager).isStarted(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class)); - - // Now trigger the interface destroyed callback from HalDeviceManager and ensure the - // external listener is invoked and iface removed from internal database. - internalListenerCaptor.getValue().onDestroyed(TEST_IFACE_NAME); - verify(externalLister).onDestroyed(TEST_IFACE_NAME); - - // This should fail now, since the interface was already destroyed. - assertFalse(mWifiVendorHal.removeStaIface(TEST_IFACE_NAME)); - verify(mHalDeviceManager, never()).removeIface(any()); - } - - /** - * Tests the handling of interface destroyed callback from HalDeviceManager. - */ - @Test - public void testApInterfaceDestroyedHandling() throws Exception { - ArgumentCaptor<InterfaceDestroyedListener> internalListenerCaptor = - ArgumentCaptor.forClass(InterfaceDestroyedListener.class); - InterfaceDestroyedListener externalLister = mock(InterfaceDestroyedListener.class); - - assertTrue(mWifiVendorHal.startVendorHal()); - assertNotNull(mWifiVendorHal.createApIface(externalLister)); - assertTrue(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createApIface(internalListenerCaptor.capture(), eq(null)); - verify(mHalDeviceManager).getChip(eq(mIWifiApIface)); - verify(mHalDeviceManager).isReady(); - verify(mHalDeviceManager).isStarted(); - verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class)); - - // Now trigger the interface destroyed callback from HalDeviceManager and ensure the - // external listener is invoked and iface removed from internal database. - internalListenerCaptor.getValue().onDestroyed(TEST_IFACE_NAME); - verify(externalLister).onDestroyed(TEST_IFACE_NAME); - - // This should fail now, since the interface was already destroyed. - assertFalse(mWifiVendorHal.removeApIface(TEST_IFACE_NAME)); - verify(mHalDeviceManager, never()).removeIface(any()); - } - - /** - * Test that enter logs when verbose logging is enabled - */ - @Test - public void testEnterLogging() { - mWifiVendorHal.mLog = spy(mWifiLog); - mWifiVendorHal.enableVerboseLogging(true); - mWifiVendorHal.installPacketFilter(TEST_IFACE_NAME, new byte[0]); - verify(mWifiVendorHal.mLog).trace(eq("filter length %"), eq(1)); - } - - /** - * Test that enter does not log when verbose logging is not enabled - */ - @Test - public void testEnterSilenceWhenNotEnabled() { - mWifiVendorHal.mLog = spy(mWifiLog); - mWifiVendorHal.installPacketFilter(TEST_IFACE_NAME, new byte[0]); - mWifiVendorHal.enableVerboseLogging(true); - mWifiVendorHal.enableVerboseLogging(false); - mWifiVendorHal.installPacketFilter(TEST_IFACE_NAME, new byte[0]); - verify(mWifiVendorHal.mLog, never()).trace(eq("filter length %"), anyInt()); - } - - /** - * Test that boolResult logs a false result - */ - @Test - public void testBoolResultFalse() { - mWifiLog = spy(mWifiLog); - mWifiVendorHal.mLog = mWifiLog; - mWifiVendorHal.mVerboseLog = mWifiLog; - assertFalse(mWifiVendorHal.getBgScanCapabilities( - TEST_IFACE_NAME, new WifiNative.ScanCapabilities())); - verify(mWifiLog).err("% returns %"); - } - - /** - * Test that getBgScanCapabilities is hooked up to the HAL correctly - * - * A call before the vendor HAL is started should return a non-null result with version 0 - * - * A call after the HAL is started should return the mocked values. - */ - @Test - public void testGetBgScanCapabilities() throws Exception { - StaBackgroundScanCapabilities capabilities = new StaBackgroundScanCapabilities(); - capabilities.maxCacheSize = 12; - capabilities.maxBuckets = 34; - capabilities.maxApCachePerScan = 56; - capabilities.maxReportingThreshold = 78; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getBackgroundScanCapabilitiesCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, capabilities); - } - }).when(mIWifiStaIface).getBackgroundScanCapabilities(any( - IWifiStaIface.getBackgroundScanCapabilitiesCallback.class)); - - WifiNative.ScanCapabilities result = new WifiNative.ScanCapabilities(); - - // should fail - not started - assertFalse(mWifiVendorHal.getBgScanCapabilities(TEST_IFACE_NAME, result)); - // Start the vendor hal - assertTrue(mWifiVendorHal.startVendorHalSta()); - // should succeed - assertTrue(mWifiVendorHal.getBgScanCapabilities(TEST_IFACE_NAME, result)); - - assertEquals(12, result.max_scan_cache_size); - assertEquals(34, result.max_scan_buckets); - assertEquals(56, result.max_ap_cache_per_scan); - assertEquals(78, result.max_scan_reporting_threshold); - } - - /** - * Test translation to WifiManager.WIFI_FEATURE_* - * - * Just do a spot-check with a few feature bits here; since the code is table- - * driven we don't have to work hard to exercise all of it. - */ - @Test - public void testStaIfaceFeatureMaskTranslation() { - int caps = ( - IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN - | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS - ); - long expected = ( - WifiManager.WIFI_FEATURE_SCANNER - | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); - assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromStaCapabilities(caps)); - } - - /** - * Test translation to WifiManager.WIFI_FEATURE_* - * - * Just do a spot-check with a few feature bits here; since the code is table- - * driven we don't have to work hard to exercise all of it. - */ - @Test - public void testChipFeatureMaskTranslation() { - int caps = ( - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT - | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT - | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT - ); - long expected = ( - WifiManager.WIFI_FEATURE_TX_POWER_LIMIT - | WifiManager.WIFI_FEATURE_D2D_RTT - | WifiManager.WIFI_FEATURE_D2AP_RTT - ); - assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromChipCapabilities(caps)); - } - - /** - * Test translation to WifiManager.WIFI_FEATURE_* for V1.3 - * - * Test the added features in V1.3 - */ - @Test - public void testChipFeatureMaskTranslation_1_3() { - int caps = ( - android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE - | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT - ); - long expected = ( - WifiManager.WIFI_FEATURE_LOW_LATENCY - | WifiManager.WIFI_FEATURE_D2D_RTT - ); - assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromChipCapabilities_1_3(caps)); - } - - /** - * Test get supported features. Tests whether we coalesce information from different sources - * (IWifiStaIface, IWifiChip and HalDeviceManager) into the bitmask of supported features - * correctly. - */ - @Test - public void testGetSupportedFeatures() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - - int staIfaceHidlCaps = ( - IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN - | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS - ); - int chipHidlCaps = - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT; - Set<Integer> halDeviceManagerSupportedIfaces = new HashSet<Integer>() {{ - add(IfaceType.STA); - add(IfaceType.P2P); - }}; - long expectedFeatureSet = ( - WifiManager.WIFI_FEATURE_SCANNER - | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS - | WifiManager.WIFI_FEATURE_TX_POWER_LIMIT - | WifiManager.WIFI_FEATURE_INFRA - | WifiManager.WIFI_FEATURE_P2P - ); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getCapabilitiesCallback cb) throws RemoteException { - cb.onValues(mWifiStatusSuccess, staIfaceHidlCaps); - } - }).when(mIWifiStaIface).getCapabilities(any(IWifiStaIface.getCapabilitiesCallback.class)); - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.getCapabilitiesCallback cb) throws RemoteException { - cb.onValues(mWifiStatusSuccess, chipHidlCaps); - } - }).when(mIWifiChip).getCapabilities(any(IWifiChip.getCapabilitiesCallback.class)); - when(mHalDeviceManager.getSupportedIfaceTypes()) - .thenReturn(halDeviceManagerSupportedIfaces); - - assertEquals(expectedFeatureSet, mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)); - } - - /** - * Test |getFactoryMacAddress| gets called when the hal version is V1_3 - * @throws Exception - */ - @Test - public void testGetFactoryMacWithHalV1_3() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.V1_3.IWifiStaIface.getFactoryMacAddressCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, MacAddress.BROADCAST_ADDRESS.toByteArray()); - } - }).when(mIWifiStaIfaceV13).getFactoryMacAddress(any( - android.hardware.wifi.V1_3.IWifiStaIface.getFactoryMacAddressCallback.class)); - mWifiVendorHal = new WifiVendorHalSpyV1_3(mHalDeviceManager, mHandler); - assertEquals(MacAddress.BROADCAST_ADDRESS.toString(), - mWifiVendorHal.getFactoryMacAddress(TEST_IFACE_NAME).toString()); - verify(mIWifiStaIfaceV13).getFactoryMacAddress(any()); - } - - /** - * Test enablement of link layer stats after startup - * - * Request link layer stats before HAL start - * - should not make it to the HAL layer - * Start the HAL in STA mode - * Request link layer stats twice more - * - enable request should make it to the HAL layer - * - HAL layer should have been called to make the requests (i.e., two calls total) - */ - @Test - public void testLinkLayerStatsEnableAfterStartup() throws Exception { - doNothing().when(mIWifiStaIface).getLinkLayerStats(any()); - - assertNull(mWifiVendorHal.getWifiLinkLayerStats(TEST_IFACE_NAME)); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.isHalStarted()); - - verify(mHalDeviceManager).start(); - mWifiVendorHal.getWifiLinkLayerStats(TEST_IFACE_NAME); - mWifiVendorHal.getWifiLinkLayerStats(TEST_IFACE_NAME); - verify(mIWifiStaIface).enableLinkLayerStatsCollection(false); // mLinkLayerStatsDebug - verify(mIWifiStaIface, times(2)).getLinkLayerStats(any()); - } - - /** - * Test getLinkLayerStats_1_3 gets called when the hal version is V1_3. - */ - @Test - public void testLinkLayerStatsCorrectVersionWithHalV1_3() throws Exception { - mWifiVendorHal = new WifiVendorHalSpyV1_3(mHalDeviceManager, mHandler); - mWifiVendorHal.getWifiLinkLayerStats(TEST_IFACE_NAME); - verify(mIWifiStaIfaceV13).getLinkLayerStats_1_3(any()); - } - - /** - * Test that link layer stats are not enabled and harmless in AP mode - * - * Start the HAL in AP mode - * - stats should not be enabled - * Request link layer stats - * - HAL layer should have been called to make the request - */ - @Test - public void testLinkLayerStatsNotEnabledAndHarmlessInApMode() throws Exception { - doNothing().when(mIWifiStaIface).getLinkLayerStats(any()); - - assertTrue(mWifiVendorHal.startVendorHalAp()); - assertTrue(mWifiVendorHal.isHalStarted()); - assertNull(mWifiVendorHal.getWifiLinkLayerStats(TEST_IFACE_NAME)); - - verify(mHalDeviceManager).start(); - - verify(mIWifiStaIface, never()).enableLinkLayerStatsCollection(false); - verify(mIWifiStaIface, never()).getLinkLayerStats(any()); - } - - /** - * Test that the link layer stats fields are populated correctly. - * - * This is done by filling Hal LinkLayerStats (V1_0) with random values, converting it to - * WifiLinkLayerStats and then asserting the values in the original structure are equal to the - * values in the converted structure. - */ - @Test - public void testLinkLayerStatsAssignment() throws Exception { - Random r = new Random(1775968256); - StaLinkLayerStats stats = new StaLinkLayerStats(); - randomizePacketStats(r, stats.iface.wmeBePktStats); - randomizePacketStats(r, stats.iface.wmeBkPktStats); - randomizePacketStats(r, stats.iface.wmeViPktStats); - randomizePacketStats(r, stats.iface.wmeVoPktStats); - randomizeRadioStats(r, stats.radios); - stats.timeStampInMs = r.nextLong() & 0xFFFFFFFFFFL; - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats(stats); - - verifyIFaceStats(stats.iface, converted); - verifyRadioStats(stats.radios, converted); - assertEquals(stats.timeStampInMs, converted.timeStampInMs); - assertEquals(WifiLinkLayerStats.V1_0, converted.version); - } - - /** - * Test that the link layer stats V1_3 fields are populated correctly. - * - * This is done by filling Hal LinkLayerStats (V1_3) with random values, converting it to - * WifiLinkLayerStats and then asserting the values in the original structure are equal to the - * values in the converted structure. - */ - @Test - public void testLinkLayerStatsAssignment_1_3() throws Exception { - Random r = new Random(1775968256); - android.hardware.wifi.V1_3.StaLinkLayerStats stats = - new android.hardware.wifi.V1_3.StaLinkLayerStats(); - randomizePacketStats(r, stats.iface.wmeBePktStats); - randomizePacketStats(r, stats.iface.wmeBkPktStats); - randomizePacketStats(r, stats.iface.wmeViPktStats); - randomizePacketStats(r, stats.iface.wmeVoPktStats); - randomizeRadioStats_1_3(r, stats.radios); - stats.timeStampInMs = r.nextLong() & 0xFFFFFFFFFFL; - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats_1_3(stats); - - verifyIFaceStats(stats.iface, converted); - verifyRadioStats_1_3(stats.radios, converted); - assertEquals(stats.timeStampInMs, converted.timeStampInMs); - assertEquals(WifiLinkLayerStats.V1_3, converted.version); - } - - private void verifyIFaceStats(StaLinkLayerIfaceStats iface, - WifiLinkLayerStats wifiLinkLayerStats) { - assertEquals(iface.beaconRx, wifiLinkLayerStats.beacon_rx); - assertEquals(iface.avgRssiMgmt, wifiLinkLayerStats.rssi_mgmt); - - assertEquals(iface.wmeBePktStats.rxMpdu, wifiLinkLayerStats.rxmpdu_be); - assertEquals(iface.wmeBePktStats.txMpdu, wifiLinkLayerStats.txmpdu_be); - assertEquals(iface.wmeBePktStats.lostMpdu, wifiLinkLayerStats.lostmpdu_be); - assertEquals(iface.wmeBePktStats.retries, wifiLinkLayerStats.retries_be); - - assertEquals(iface.wmeBkPktStats.rxMpdu, wifiLinkLayerStats.rxmpdu_bk); - assertEquals(iface.wmeBkPktStats.txMpdu, wifiLinkLayerStats.txmpdu_bk); - assertEquals(iface.wmeBkPktStats.lostMpdu, wifiLinkLayerStats.lostmpdu_bk); - assertEquals(iface.wmeBkPktStats.retries, wifiLinkLayerStats.retries_bk); - - assertEquals(iface.wmeViPktStats.rxMpdu, wifiLinkLayerStats.rxmpdu_vi); - assertEquals(iface.wmeViPktStats.txMpdu, wifiLinkLayerStats.txmpdu_vi); - assertEquals(iface.wmeViPktStats.lostMpdu, wifiLinkLayerStats.lostmpdu_vi); - assertEquals(iface.wmeViPktStats.retries, wifiLinkLayerStats.retries_vi); - - assertEquals(iface.wmeVoPktStats.rxMpdu, wifiLinkLayerStats.rxmpdu_vo); - assertEquals(iface.wmeVoPktStats.txMpdu, wifiLinkLayerStats.txmpdu_vo); - assertEquals(iface.wmeVoPktStats.lostMpdu, wifiLinkLayerStats.lostmpdu_vo); - assertEquals(iface.wmeVoPktStats.retries, wifiLinkLayerStats.retries_vo); - } - - private void verifyRadioStats(List<StaLinkLayerRadioStats> radios, - WifiLinkLayerStats wifiLinkLayerStats) { - StaLinkLayerRadioStats radio = radios.get(0); - assertEquals(radio.onTimeInMs, wifiLinkLayerStats.on_time); - assertEquals(radio.txTimeInMs, wifiLinkLayerStats.tx_time); - assertEquals(radio.rxTimeInMs, wifiLinkLayerStats.rx_time); - assertEquals(radio.onTimeInMsForScan, wifiLinkLayerStats.on_time_scan); - assertEquals(radio.txTimeInMsPerLevel.size(), - wifiLinkLayerStats.tx_time_per_level.length); - for (int i = 0; i < radio.txTimeInMsPerLevel.size(); i++) { - assertEquals((int) radio.txTimeInMsPerLevel.get(i), - wifiLinkLayerStats.tx_time_per_level[i]); - } - } - - private void verifyRadioStats_1_3( - List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios, - WifiLinkLayerStats wifiLinkLayerStats) { - android.hardware.wifi.V1_3.StaLinkLayerRadioStats radio = radios.get(0); - assertEquals(radio.V1_0.onTimeInMs, wifiLinkLayerStats.on_time); - assertEquals(radio.V1_0.txTimeInMs, wifiLinkLayerStats.tx_time); - assertEquals(radio.V1_0.rxTimeInMs, wifiLinkLayerStats.rx_time); - assertEquals(radio.V1_0.onTimeInMsForScan, wifiLinkLayerStats.on_time_scan); - assertEquals(radio.V1_0.txTimeInMsPerLevel.size(), - wifiLinkLayerStats.tx_time_per_level.length); - for (int i = 0; i < radio.V1_0.txTimeInMsPerLevel.size(); i++) { - assertEquals((int) radio.V1_0.txTimeInMsPerLevel.get(i), - wifiLinkLayerStats.tx_time_per_level[i]); - } - assertEquals(radio.onTimeInMsForNanScan, wifiLinkLayerStats.on_time_nan_scan); - assertEquals(radio.onTimeInMsForBgScan, wifiLinkLayerStats.on_time_background_scan); - assertEquals(radio.onTimeInMsForRoamScan, wifiLinkLayerStats.on_time_roam_scan); - assertEquals(radio.onTimeInMsForPnoScan, wifiLinkLayerStats.on_time_pno_scan); - assertEquals(radio.onTimeInMsForHs20Scan, wifiLinkLayerStats.on_time_hs20_scan); - assertEquals(radio.channelStats.size(), - wifiLinkLayerStats.channelStatsMap.size()); - for (int j = 0; j < radio.channelStats.size(); j++) { - WifiChannelStats channelStats = radio.channelStats.get(j); - ChannelStats retrievedChannelStats = - wifiLinkLayerStats.channelStatsMap.get(channelStats.channel.centerFreq); - assertNotNull(retrievedChannelStats); - assertEquals(channelStats.channel.centerFreq, retrievedChannelStats.frequency); - assertEquals(channelStats.onTimeInMs, retrievedChannelStats.radioOnTimeMs); - assertEquals(channelStats.ccaBusyTimeInMs, retrievedChannelStats.ccaBusyTimeMs); - } - } - - - /** - * Populate packet stats with non-negative random values - */ - private static void randomizePacketStats(Random r, StaLinkLayerIfacePacketStats pstats) { - pstats.rxMpdu = r.nextLong() & 0xFFFFFFFFFFL; // more than 32 bits - pstats.txMpdu = r.nextLong() & 0xFFFFFFFFFFL; - pstats.lostMpdu = r.nextLong() & 0xFFFFFFFFFFL; - pstats.retries = r.nextLong() & 0xFFFFFFFFFFL; - } - - /** - * Populate radio stats with non-negative random values - */ - private static void randomizeRadioStats(Random r, ArrayList<StaLinkLayerRadioStats> rstats) { - StaLinkLayerRadioStats rstat = new StaLinkLayerRadioStats(); - rstat.onTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.txTimeInMs = r.nextInt() & 0xFFFFFF; - for (int i = 0; i < 4; i++) { - Integer v = r.nextInt() & 0xFFFFFF; - rstat.txTimeInMsPerLevel.add(v); - } - rstat.rxTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForScan = r.nextInt() & 0xFFFFFF; - rstats.add(rstat); - } - - /** - * Populate radio stats with non-negative random values - */ - private static void randomizeRadioStats_1_3(Random r, - ArrayList<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> rstats) { - android.hardware.wifi.V1_3.StaLinkLayerRadioStats rstat = - new android.hardware.wifi.V1_3.StaLinkLayerRadioStats(); - rstat.V1_0.onTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.V1_0.txTimeInMs = r.nextInt() & 0xFFFFFF; - for (int i = 0; i < 4; i++) { - Integer v = r.nextInt() & 0xFFFFFF; - rstat.V1_0.txTimeInMsPerLevel.add(v); - } - rstat.V1_0.rxTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.V1_0.onTimeInMsForScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForNanScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForBgScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForRoamScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForPnoScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForHs20Scan = r.nextInt() & 0xFFFFFF; - for (int j = 0; j < TEST_FREQUENCIES.length; j++) { - WifiChannelStats channelStats = new WifiChannelStats(); - channelStats.channel.centerFreq = TEST_FREQUENCIES[j]; - channelStats.onTimeInMs = r.nextInt() & 0xFFFFFF; - channelStats.ccaBusyTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.channelStats.add(channelStats); - } - rstats.add(rstat); - } - - /** - * Test that getFirmwareVersion() and getDriverVersion() work - * - * Calls before the STA is started are expected to return null. - */ - @Test - public void testVersionGetters() throws Exception { - String firmwareVersion = "fuzzy"; - String driverVersion = "dizzy"; - IWifiChip.ChipDebugInfo chipDebugInfo = new IWifiChip.ChipDebugInfo(); - chipDebugInfo.firmwareDescription = firmwareVersion; - chipDebugInfo.driverDescription = driverVersion; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.requestChipDebugInfoCallback cb) throws RemoteException { - cb.onValues(mWifiStatusSuccess, chipDebugInfo); - } - }).when(mIWifiChip).requestChipDebugInfo(any(IWifiChip.requestChipDebugInfoCallback.class)); - - assertNull(mWifiVendorHal.getFirmwareVersion()); - assertNull(mWifiVendorHal.getDriverVersion()); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertEquals(firmwareVersion, mWifiVendorHal.getFirmwareVersion()); - assertEquals(driverVersion, mWifiVendorHal.getDriverVersion()); - } - - /** - * For checkRoundTripIntTranslation lambdas - */ - interface IntForInt { - int translate(int value); - } - - /** - * Checks that translation from x to y and back again is the identity function - * - * @param xFromY reverse translator - * @param yFromX forward translator - * @param xLimit non-inclusive upper bound on x (lower bound is zero) - */ - private void checkRoundTripIntTranslation( - IntForInt xFromY, IntForInt yFromX, int xFirst, int xLimit) throws Exception { - int ex = 0; - for (int i = xFirst; i < xLimit; i++) { - assertEquals(i, xFromY.translate(yFromX.translate(i))); - } - try { - yFromX.translate(xLimit); - assertTrue("expected an exception here", false); - } catch (IllegalArgumentException e) { - ex++; - } - try { - xFromY.translate(yFromX.translate(xLimit - 1) + 1); - assertTrue("expected an exception here", false); - } catch (IllegalArgumentException e) { - ex++; - } - assertEquals(2, ex); - } - - @Test - public void testStartSendingOffloadedPacket() throws Exception { - byte[] srcMac = NativeUtil.macAddressToByteArray("4007b2088c81"); - byte[] dstMac = NativeUtil.macAddressToByteArray("4007b8675309"); - InetAddress src = InetAddress.parseNumericAddress("192.168.13.13"); - InetAddress dst = InetAddress.parseNumericAddress("93.184.216.34"); - int slot = 13; - int millis = 16000; - - KeepalivePacketData kap = - NattKeepalivePacketData.nattKeepalivePacket(src, 63000, dst, 4500); - - when(mIWifiStaIface.startSendingKeepAlivePackets( - anyInt(), any(), anyShort(), any(), any(), anyInt() - )).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(0 == mWifiVendorHal.startSendingOffloadedPacket( - TEST_IFACE_NAME, slot, srcMac, dstMac, kap.getPacket(), - OsConstants.ETH_P_IPV6, millis)); - - verify(mIWifiStaIface).startSendingKeepAlivePackets( - eq(slot), any(), anyShort(), any(), any(), eq(millis)); - } - - @Test - public void testStopSendingOffloadedPacket() throws Exception { - int slot = 13; - - when(mIWifiStaIface.stopSendingKeepAlivePackets(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(0 == mWifiVendorHal.stopSendingOffloadedPacket( - TEST_IFACE_NAME, slot)); - - verify(mIWifiStaIface).stopSendingKeepAlivePackets(eq(slot)); - } - - /** - * Test the setup, invocation, and removal of a RSSI event handler - * - */ - @Test - public void testRssiMonitoring() throws Exception { - when(mIWifiStaIface.startRssiMonitoring(anyInt(), anyInt(), anyInt())) - .thenReturn(mWifiStatusSuccess); - when(mIWifiStaIface.stopRssiMonitoring(anyInt())) - .thenReturn(mWifiStatusSuccess); - - ArrayList<Byte> breach = new ArrayList<>(10); - byte hi = -21; - byte med = -42; - byte lo = -84; - Byte lower = -88; - WifiNative.WifiRssiEventHandler handler; - handler = ((cur) -> { - breach.add(cur); - }); - // not started - assertEquals(-1, mWifiVendorHal.startRssiMonitoring(TEST_IFACE_NAME, hi, lo, handler)); - // not started - assertEquals(-1, mWifiVendorHal.stopRssiMonitoring(TEST_IFACE_NAME)); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertEquals(0, mWifiVendorHal.startRssiMonitoring(TEST_IFACE_NAME, hi, lo, handler)); - int theCmdId = mWifiVendorHal.sRssiMonCmdId; - breach.clear(); - mIWifiStaIfaceEventCallback.onRssiThresholdBreached(theCmdId, new byte[6], lower); - assertEquals(breach.get(0), lower); - assertEquals(0, mWifiVendorHal.stopRssiMonitoring(TEST_IFACE_NAME)); - assertEquals(0, mWifiVendorHal.startRssiMonitoring(TEST_IFACE_NAME, hi, lo, handler)); - // replacing works - assertEquals(0, mWifiVendorHal.startRssiMonitoring(TEST_IFACE_NAME, med, lo, handler)); - // null handler fails - assertEquals(-1, mWifiVendorHal.startRssiMonitoring( - TEST_IFACE_NAME, hi, lo, null)); - assertEquals(0, mWifiVendorHal.startRssiMonitoring(TEST_IFACE_NAME, hi, lo, handler)); - // empty range - assertEquals(-1, mWifiVendorHal.startRssiMonitoring(TEST_IFACE_NAME, lo, hi, handler)); - } - - /** - * Test that getApfCapabilities is hooked up to the HAL correctly - * - * A call before the vendor HAL is started should return a non-null result with version 0 - * - * A call after the HAL is started should return the mocked values. - */ - @Test - public void testApfCapabilities() throws Exception { - int myVersion = 33; - int myMaxSize = 1234; - - StaApfPacketFilterCapabilities capabilities = new StaApfPacketFilterCapabilities(); - capabilities.version = myVersion; - capabilities.maxLength = myMaxSize; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getApfPacketFilterCapabilitiesCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, capabilities); - } - }).when(mIWifiStaIface).getApfPacketFilterCapabilities(any( - IWifiStaIface.getApfPacketFilterCapabilitiesCallback.class)); - - - assertEquals(0, mWifiVendorHal.getApfCapabilities(TEST_IFACE_NAME) - .apfVersionSupported); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - ApfCapabilities actual = mWifiVendorHal.getApfCapabilities(TEST_IFACE_NAME); - - assertEquals(myVersion, actual.apfVersionSupported); - assertEquals(myMaxSize, actual.maximumApfProgramSize); - assertEquals(android.system.OsConstants.ARPHRD_ETHER, actual.apfPacketFormat); - assertNotEquals(0, actual.apfPacketFormat); - } - - /** - * Test that an APF program can be installed. - */ - @Test - public void testInstallApf() throws Exception { - byte[] filter = new byte[] {19, 53, 10}; - - ArrayList<Byte> expected = new ArrayList<>(3); - for (byte b : filter) expected.add(b); - - when(mIWifiStaIface.installApfPacketFilter(anyInt(), any(ArrayList.class))) - .thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.installPacketFilter(TEST_IFACE_NAME, filter)); - - verify(mIWifiStaIface).installApfPacketFilter(eq(0), eq(expected)); - } - - /** - * Test that an APF program and data buffer can be read back. - */ - @Test - public void testReadApf() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - - byte[] program = new byte[] {65, 66, 67}; - ArrayList<Byte> expected = new ArrayList<>(3); - for (byte b : program) expected.add(b); - - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.V1_2.IWifiStaIface.readApfPacketFilterDataCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, expected); - } - }).when(mIWifiStaIfaceV12).readApfPacketFilterData(any( - android.hardware.wifi.V1_2.IWifiStaIface.readApfPacketFilterDataCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertArrayEquals(program, mWifiVendorHal.readPacketFilter(TEST_IFACE_NAME)); - } - - /** - * Test that the country code is set in AP mode (when it should be). - */ - @Test - public void testSetCountryCodeHal() throws Exception { - byte[] expected = new byte[]{(byte) 'C', (byte) 'A'}; - - when(mIWifiApIface.setCountryCode(any())) - .thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalAp()); - - assertFalse(mWifiVendorHal.setCountryCodeHal(TEST_IFACE_NAME, null)); - assertFalse(mWifiVendorHal.setCountryCodeHal(TEST_IFACE_NAME, "")); - assertFalse(mWifiVendorHal.setCountryCodeHal(TEST_IFACE_NAME, "A")); - // Only one expected to succeed - assertTrue(mWifiVendorHal.setCountryCodeHal(TEST_IFACE_NAME, "CA")); - assertFalse(mWifiVendorHal.setCountryCodeHal(TEST_IFACE_NAME, "ZZZ")); - - verify(mIWifiApIface).setCountryCode(eq(expected)); - } - - /** - * Test that RemoteException is caught and logged. - */ - @Test - public void testRemoteExceptionIsHandled() throws Exception { - mWifiLog = spy(mWifiLog); - mWifiVendorHal.mVerboseLog = mWifiLog; - when(mIWifiApIface.setCountryCode(any())) - .thenThrow(new RemoteException("oops")); - assertTrue(mWifiVendorHal.startVendorHalAp()); - assertFalse(mWifiVendorHal.setCountryCodeHal(TEST_IFACE_NAME, "CA")); - assertFalse(mWifiVendorHal.isHalStarted()); - verify(mWifiLog).err("% RemoteException in HIDL call %"); - } - - /** - * Test that startLoggingToDebugRingBuffer is plumbed to chip - * - * A call before the vendor hal is started should just return false. - * After starting in STA mode, the call should succeed, and pass ther right things down. - */ - @Test - public void testStartLoggingRingBuffer() throws Exception { - when(mIWifiChip.startLoggingToDebugRingBuffer( - any(String.class), anyInt(), anyInt(), anyInt() - )).thenReturn(mWifiStatusSuccess); - - assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One")); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One")); - - verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000); - } - - /** - * Same test as testStartLoggingRingBuffer, but in AP mode rather than STA. - */ - @Test - public void testStartLoggingRingBufferOnAp() throws Exception { - when(mIWifiChip.startLoggingToDebugRingBuffer( - any(String.class), anyInt(), anyInt(), anyInt() - )).thenReturn(mWifiStatusSuccess); - - assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One")); - assertTrue(mWifiVendorHal.startVendorHalAp()); - assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One")); - - verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000); - } - - /** - * Test that getRingBufferStatus gets and translates its stuff correctly - */ - @Test - public void testRingBufferStatus() throws Exception { - WifiDebugRingBufferStatus one = new WifiDebugRingBufferStatus(); - one.ringName = "One"; - one.flags = WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES; - one.ringId = 5607371; - one.sizeInBytes = 54321; - one.freeSizeInBytes = 42; - one.verboseLevel = WifiDebugRingBufferVerboseLevel.VERBOSE; - String oneExpect = "name: One flag: 1 ringBufferId: 5607371 ringBufferByteSize: 54321" - + " verboseLevel: 2 writtenBytes: 0 readBytes: 0 writtenRecords: 0"; - - WifiDebugRingBufferStatus two = new WifiDebugRingBufferStatus(); - two.ringName = "Two"; - two.flags = WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES - | WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES; - two.ringId = 4512470; - two.sizeInBytes = 300; - two.freeSizeInBytes = 42; - two.verboseLevel = WifiDebugRingBufferVerboseLevel.DEFAULT; - - ArrayList<WifiDebugRingBufferStatus> halBufferStatus = new ArrayList<>(2); - halBufferStatus.add(one); - halBufferStatus.add(two); - - WifiNative.RingBufferStatus[] actual; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.getDebugRingBuffersStatusCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, halBufferStatus); - } - }).when(mIWifiChip).getDebugRingBuffersStatus(any( - IWifiChip.getDebugRingBuffersStatusCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - actual = mWifiVendorHal.getRingBufferStatus(); - - assertEquals(halBufferStatus.size(), actual.length); - assertEquals(oneExpect, actual[0].toString()); - assertEquals(two.ringId, actual[1].ringBufferId); - } - - /** - * Test that getRingBufferData calls forceDumpToDebugRingBuffer - * - * Try once before hal start, and twice after (one success, one failure). - */ - @Test - public void testForceRingBufferDump() throws Exception { - when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Gunk"))).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Glop"))).thenReturn(mWifiStatusFailure); - - assertFalse(mWifiVendorHal.getRingBufferData("Gunk")); // hal not started - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertTrue(mWifiVendorHal.getRingBufferData("Gunk")); // mocked call succeeds - assertFalse(mWifiVendorHal.getRingBufferData("Glop")); // mocked call fails - - verify(mIWifiChip).forceDumpToDebugRingBuffer("Gunk"); - verify(mIWifiChip).forceDumpToDebugRingBuffer("Glop"); - } - - /** - * Test flush ring buffer to files. - * - * Try once before hal start, and once after. - */ - @Test - public void testFlushRingBufferToFile() throws Exception { - mWifiVendorHal = new WifiVendorHalSpyV1_3(mHalDeviceManager, mHandler); - when(mIWifiChipV13.flushRingBufferToFile()).thenReturn(mWifiStatusSuccess); - - assertFalse(mWifiVendorHal.flushRingBufferData()); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.flushRingBufferData()); - verify(mIWifiChipV13).flushRingBufferToFile(); - } - - /** - * Tests the start of packet fate monitoring. - * - * Try once before hal start, and once after (one success, one failure). - */ - @Test - public void testStartPktFateMonitoring() throws Exception { - when(mIWifiStaIface.startDebugPacketFateMonitoring()).thenReturn(mWifiStatusSuccess); - - assertFalse(mWifiVendorHal.startPktFateMonitoring(TEST_IFACE_NAME)); - verify(mIWifiStaIface, never()).startDebugPacketFateMonitoring(); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.startPktFateMonitoring(TEST_IFACE_NAME)); - verify(mIWifiStaIface).startDebugPacketFateMonitoring(); - } - - /** - * Tests the retrieval of tx packet fates. - * - * Try once before hal start, and once after. - */ - @Test - public void testGetTxPktFates() throws Exception { - byte[] frameContentBytes = new byte[30]; - new Random().nextBytes(frameContentBytes); - WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport(); - fateReport.fate = WifiDebugTxPacketFate.DRV_QUEUED; - fateReport.frameInfo.driverTimestampUsec = new Random().nextLong(); - fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II; - fateReport.frameInfo.frameContent.addAll( - NativeUtil.byteArrayToArrayList(frameContentBytes)); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) { - cb.onValues(mWifiStatusSuccess, - new ArrayList<WifiDebugTxPacketFateReport>(Arrays.asList(fateReport))); - } - }).when(mIWifiStaIface) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - - WifiNative.TxFateReport[] retrievedFates = new WifiNative.TxFateReport[1]; - assertFalse(mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME, retrievedFates)); - verify(mIWifiStaIface, never()) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertTrue(mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME, retrievedFates)); - verify(mIWifiStaIface) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - assertEquals(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, retrievedFates[0].mFate); - assertEquals(fateReport.frameInfo.driverTimestampUsec, - retrievedFates[0].mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFates[0].mFrameType); - assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes); - } - - /** - * Tests the retrieval of tx packet fates when the number of fates retrieved exceeds the - * input array. - * - * Try once before hal start, and once after. - */ - @Test - public void testGetTxPktFatesExceedsInputArrayLength() throws Exception { - byte[] frameContentBytes = new byte[30]; - new Random().nextBytes(frameContentBytes); - WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport(); - fateReport.fate = WifiDebugTxPacketFate.FW_DROP_OTHER; - fateReport.frameInfo.driverTimestampUsec = new Random().nextLong(); - fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211; - fateReport.frameInfo.frameContent.addAll( - NativeUtil.byteArrayToArrayList(frameContentBytes)); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) { - cb.onValues(mWifiStatusSuccess, - new ArrayList<WifiDebugTxPacketFateReport>(Arrays.asList( - fateReport, fateReport))); - } - }).when(mIWifiStaIface) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - - WifiNative.TxFateReport[] retrievedFates = new WifiNative.TxFateReport[1]; - assertFalse(mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME, retrievedFates)); - verify(mIWifiStaIface, never()) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertTrue(mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME, retrievedFates)); - verify(mIWifiStaIface) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - assertEquals(WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, retrievedFates[0].mFate); - assertEquals(fateReport.frameInfo.driverTimestampUsec, - retrievedFates[0].mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFates[0].mFrameType); - assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes); - } - - /** - * Tests the retrieval of rx packet fates. - * - * Try once before hal start, and once after. - */ - @Test - public void testGetRxPktFates() throws Exception { - byte[] frameContentBytes = new byte[30]; - new Random().nextBytes(frameContentBytes); - WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport(); - fateReport.fate = WifiDebugRxPacketFate.SUCCESS; - fateReport.frameInfo.driverTimestampUsec = new Random().nextLong(); - fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II; - fateReport.frameInfo.frameContent.addAll( - NativeUtil.byteArrayToArrayList(frameContentBytes)); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) { - cb.onValues(mWifiStatusSuccess, - new ArrayList<WifiDebugRxPacketFateReport>(Arrays.asList(fateReport))); - } - }).when(mIWifiStaIface) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - - WifiNative.RxFateReport[] retrievedFates = new WifiNative.RxFateReport[1]; - assertFalse(mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME, retrievedFates)); - verify(mIWifiStaIface, never()) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertTrue(mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME, retrievedFates)); - verify(mIWifiStaIface) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - assertEquals(WifiLoggerHal.RX_PKT_FATE_SUCCESS, retrievedFates[0].mFate); - assertEquals(fateReport.frameInfo.driverTimestampUsec, - retrievedFates[0].mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFates[0].mFrameType); - assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes); - } - - /** - * Tests the retrieval of rx packet fates when the number of fates retrieved exceeds the - * input array. - * - * Try once before hal start, and once after. - */ - @Test - public void testGetRxPktFatesExceedsInputArrayLength() throws Exception { - byte[] frameContentBytes = new byte[30]; - new Random().nextBytes(frameContentBytes); - WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport(); - fateReport.fate = WifiDebugRxPacketFate.FW_DROP_FILTER; - fateReport.frameInfo.driverTimestampUsec = new Random().nextLong(); - fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211; - fateReport.frameInfo.frameContent.addAll( - NativeUtil.byteArrayToArrayList(frameContentBytes)); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) { - cb.onValues(mWifiStatusSuccess, - new ArrayList<WifiDebugRxPacketFateReport>(Arrays.asList( - fateReport, fateReport))); - } - }).when(mIWifiStaIface) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - - WifiNative.RxFateReport[] retrievedFates = new WifiNative.RxFateReport[1]; - assertFalse(mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME, retrievedFates)); - verify(mIWifiStaIface, never()) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertTrue(mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME, retrievedFates)); - verify(mIWifiStaIface) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, retrievedFates[0].mFate); - assertEquals(fateReport.frameInfo.driverTimestampUsec, - retrievedFates[0].mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFates[0].mFrameType); - assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes); - } - - /** - * Tests the failure to retrieve tx packet fates when the input array is empty. - */ - @Test - public void testGetTxPktFatesEmptyInputArray() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertFalse(mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME, new WifiNative.TxFateReport[0])); - verify(mIWifiStaIface, never()) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - } - - /** - * Tests the failure to retrieve rx packet fates when the input array is empty. - */ - @Test - public void testGetRxPktFatesEmptyInputArray() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertFalse(mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME, new WifiNative.RxFateReport[0])); - verify(mIWifiStaIface, never()) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - } - - /** - * Tests the nd offload enable/disable. - */ - @Test - public void testEnableDisableNdOffload() throws Exception { - when(mIWifiStaIface.enableNdOffload(anyBoolean())).thenReturn(mWifiStatusSuccess); - - assertFalse(mWifiVendorHal.configureNeighborDiscoveryOffload(TEST_IFACE_NAME, true)); - verify(mIWifiStaIface, never()).enableNdOffload(anyBoolean()); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertTrue(mWifiVendorHal.configureNeighborDiscoveryOffload(TEST_IFACE_NAME, true)); - verify(mIWifiStaIface).enableNdOffload(eq(true)); - assertTrue(mWifiVendorHal.configureNeighborDiscoveryOffload(TEST_IFACE_NAME, false)); - verify(mIWifiStaIface).enableNdOffload(eq(false)); - } - - /** - * Tests the nd offload enable failure. - */ - @Test - public void testEnableNdOffloadFailure() throws Exception { - when(mIWifiStaIface.enableNdOffload(eq(true))).thenReturn(mWifiStatusFailure); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertFalse(mWifiVendorHal.configureNeighborDiscoveryOffload(TEST_IFACE_NAME, true)); - verify(mIWifiStaIface).enableNdOffload(eq(true)); - } - - /** - * Helper class for mocking getRoamingCapabilities callback - */ - private class GetRoamingCapabilitiesAnswer extends AnswerWithArguments { - private final WifiStatus mStatus; - private final StaRoamingCapabilities mCaps; - - GetRoamingCapabilitiesAnswer(WifiStatus status, StaRoamingCapabilities caps) { - mStatus = status; - mCaps = caps; - } - - public void answer(IWifiStaIface.getRoamingCapabilitiesCallback cb) { - cb.onValues(mStatus, mCaps); - } - } - - /** - * Tests retrieval of firmware roaming capabilities - */ - @Test - public void testFirmwareRoamingCapabilityRetrieval() throws Exception { - WifiNative.RoamingCapabilities roamingCapabilities = new WifiNative.RoamingCapabilities(); - assertTrue(mWifiVendorHal.startVendorHalSta()); - for (int i = 0; i < 4; i++) { - int blacklistSize = i + 10; - int whitelistSize = i * 3; - StaRoamingCapabilities caps = new StaRoamingCapabilities(); - caps.maxBlacklistSize = blacklistSize; - caps.maxWhitelistSize = whitelistSize; - doAnswer(new GetRoamingCapabilitiesAnswer(mWifiStatusSuccess, caps)) - .when(mIWifiStaIface).getRoamingCapabilities( - any(IWifiStaIface.getRoamingCapabilitiesCallback.class)); - assertTrue(mWifiVendorHal.getRoamingCapabilities(TEST_IFACE_NAME, roamingCapabilities)); - assertEquals(blacklistSize, roamingCapabilities.maxBlacklistSize); - assertEquals(whitelistSize, roamingCapabilities.maxWhitelistSize); - } - } - - /** - * Tests unsuccessful retrieval of firmware roaming capabilities - */ - @Test - public void testUnsuccessfulFirmwareRoamingCapabilityRetrieval() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - int blacklistSize = 42; - int whitelistSize = 17; - WifiNative.RoamingCapabilities roamingCapabilities = new WifiNative.RoamingCapabilities(); - roamingCapabilities.maxBlacklistSize = blacklistSize; - roamingCapabilities.maxWhitelistSize = whitelistSize; - StaRoamingCapabilities caps = new StaRoamingCapabilities(); - caps.maxBlacklistSize = blacklistSize + 1; // different value here - caps.maxWhitelistSize = whitelistSize + 1; - - // hal returns a failure status - doAnswer(new GetRoamingCapabilitiesAnswer(mWifiStatusFailure, null)) - .when(mIWifiStaIface).getRoamingCapabilities( - any(IWifiStaIface.getRoamingCapabilitiesCallback.class)); - assertFalse(mWifiVendorHal.getRoamingCapabilities(TEST_IFACE_NAME, roamingCapabilities)); - // in failure cases, result container should not be changed - assertEquals(blacklistSize, roamingCapabilities.maxBlacklistSize); - assertEquals(whitelistSize, roamingCapabilities.maxWhitelistSize); - - // hal returns failure status, but supplies caps anyway - doAnswer(new GetRoamingCapabilitiesAnswer(mWifiStatusFailure, caps)) - .when(mIWifiStaIface).getRoamingCapabilities( - any(IWifiStaIface.getRoamingCapabilitiesCallback.class)); - assertFalse(mWifiVendorHal.getRoamingCapabilities(TEST_IFACE_NAME, roamingCapabilities)); - // in failure cases, result container should not be changed - assertEquals(blacklistSize, roamingCapabilities.maxBlacklistSize); - assertEquals(whitelistSize, roamingCapabilities.maxWhitelistSize); - - // lost connection - doThrow(new RemoteException()) - .when(mIWifiStaIface).getRoamingCapabilities( - any(IWifiStaIface.getRoamingCapabilitiesCallback.class)); - assertFalse(mWifiVendorHal.getRoamingCapabilities(TEST_IFACE_NAME, roamingCapabilities)); - // in failure cases, result container should not be changed - assertEquals(blacklistSize, roamingCapabilities.maxBlacklistSize); - assertEquals(whitelistSize, roamingCapabilities.maxWhitelistSize); - } - - /** - * Tests enableFirmwareRoaming successful enable - */ - @Test - public void testEnableFirmwareRoamingSuccess() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - when(mIWifiStaIface.setRoamingState(eq(StaRoamingState.ENABLED))) - .thenReturn(mWifiStatusSuccess); - assertEquals(WifiNative.SET_FIRMWARE_ROAMING_SUCCESS, - mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, - WifiNative.ENABLE_FIRMWARE_ROAMING)); - } - - /** - * Tests enableFirmwareRoaming successful disable - */ - @Test - public void testDisbleFirmwareRoamingSuccess() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - when(mIWifiStaIface.setRoamingState(eq(StaRoamingState.DISABLED))) - .thenReturn(mWifiStatusSuccess); - assertEquals(WifiNative.SET_FIRMWARE_ROAMING_SUCCESS, - mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, - WifiNative.DISABLE_FIRMWARE_ROAMING)); - } - - /** - * Tests enableFirmwareRoaming failure case - invalid argument - */ - @Test - public void testEnableFirmwareRoamingFailureInvalidArgument() throws Exception { - final int badState = WifiNative.DISABLE_FIRMWARE_ROAMING - + WifiNative.ENABLE_FIRMWARE_ROAMING + 1; - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertEquals(WifiNative.SET_FIRMWARE_ROAMING_FAILURE, - mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, badState)); - verify(mIWifiStaIface, never()).setRoamingState(anyByte()); - } - - /** - * Tests enableFirmwareRoaming failure case - busy - */ - @Test - public void testEnableFirmwareRoamingFailureBusy() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - when(mIWifiStaIface.setRoamingState(anyByte())) - .thenReturn(mWifiStatusBusy); - assertEquals(WifiNative.SET_FIRMWARE_ROAMING_BUSY, - mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, - WifiNative.ENABLE_FIRMWARE_ROAMING)); - } - - /** - * Tests enableFirmwareRoaming generic failure case - */ - @Test - public void testEnableFirmwareRoamingFailure() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - when(mIWifiStaIface.setRoamingState(anyByte())) - .thenReturn(mWifiStatusFailure); - assertEquals(WifiNative.SET_FIRMWARE_ROAMING_FAILURE, - mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, - WifiNative.ENABLE_FIRMWARE_ROAMING)); - } - - /** - * Tests enableFirmwareRoaming remote exception failure case - */ - @Test - public void testEnableFirmwareRoamingException() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - doThrow(new RemoteException()).when(mIWifiStaIface).setRoamingState(anyByte()); - assertEquals(WifiNative.SET_FIRMWARE_ROAMING_FAILURE, - mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, - WifiNative.ENABLE_FIRMWARE_ROAMING)); - } - - /** - * Tests configureRoaming success - */ - @Test - public void testConfigureRoamingSuccess() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - roamingConfig.blacklistBssids = new ArrayList(); - roamingConfig.blacklistBssids.add("12:34:56:78:ca:fe"); - roamingConfig.whitelistSsids = new ArrayList(); - roamingConfig.whitelistSsids.add("\"xyzzy\""); - roamingConfig.whitelistSsids.add("\"\u0F00 \u05D0\""); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface).configureRoaming(any()); - } - - /** - * Tests configureRoaming success with null lists - */ - @Test - public void testConfigureRoamingResetSuccess() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface).configureRoaming(any()); - } - - /** - * Tests configureRoaming failure when hal returns failure - */ - @Test - public void testConfigureRoamingFailure() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusFailure); - assertFalse(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface).configureRoaming(any()); - } - - /** - * Tests configureRoaming failure due to remote exception - */ - @Test - public void testConfigureRoamingRemoteException() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - doThrow(new RemoteException()).when(mIWifiStaIface).configureRoaming(any()); - assertFalse(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface).configureRoaming(any()); - } - - /** - * Tests configureRoaming failure due to invalid bssid - */ - @Test - public void testConfigureRoamingBadBssid() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - roamingConfig.blacklistBssids = new ArrayList(); - roamingConfig.blacklistBssids.add("12:34:56:78:zz:zz"); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); - assertFalse(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface, never()).configureRoaming(any()); - } - - /** - * Tests configureRoaming failure due to invalid ssid - */ - @Test - public void testConfigureRoamingBadSsid() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - roamingConfig.whitelistSsids = new ArrayList(); - // Add an SSID that is too long (> 32 bytes) due to the multi-byte utf-8 characters - roamingConfig.whitelistSsids.add("\"123456789012345678901234567890\u0F00\u05D0\""); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); - assertFalse(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface, never()).configureRoaming(any()); - } - - /** - * Tests the retrieval of wlan wake reason stats. - */ - @Test - public void testGetWlanWakeReasonCount() throws Exception { - WifiDebugHostWakeReasonStats stats = new WifiDebugHostWakeReasonStats(); - Random rand = new Random(); - stats.totalCmdEventWakeCnt = rand.nextInt(); - stats.totalDriverFwLocalWakeCnt = rand.nextInt(); - stats.totalRxPacketWakeCnt = rand.nextInt(); - stats.rxPktWakeDetails.rxUnicastCnt = rand.nextInt(); - stats.rxPktWakeDetails.rxMulticastCnt = rand.nextInt(); - stats.rxIcmpPkWakeDetails.icmpPkt = rand.nextInt(); - stats.rxIcmpPkWakeDetails.icmp6Pkt = rand.nextInt(); - stats.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt = rand.nextInt(); - stats.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt = rand.nextInt(); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.getDebugHostWakeReasonStatsCallback cb) { - cb.onValues(mWifiStatusSuccess, stats); - } - }).when(mIWifiChip).getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); - - assertNull(mWifiVendorHal.getWlanWakeReasonCount()); - verify(mIWifiChip, never()) - .getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - WlanWakeReasonAndCounts retrievedStats = mWifiVendorHal.getWlanWakeReasonCount(); - verify(mIWifiChip).getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); - assertNotNull(retrievedStats); - assertEquals(stats.totalCmdEventWakeCnt, retrievedStats.totalCmdEventWake); - assertEquals(stats.totalDriverFwLocalWakeCnt, retrievedStats.totalDriverFwLocalWake); - assertEquals(stats.totalRxPacketWakeCnt, retrievedStats.totalRxDataWake); - assertEquals(stats.rxPktWakeDetails.rxUnicastCnt, retrievedStats.rxUnicast); - assertEquals(stats.rxPktWakeDetails.rxMulticastCnt, retrievedStats.rxMulticast); - assertEquals(stats.rxIcmpPkWakeDetails.icmpPkt, retrievedStats.icmp); - assertEquals(stats.rxIcmpPkWakeDetails.icmp6Pkt, retrievedStats.icmp6); - assertEquals(stats.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt, - retrievedStats.ipv4RxMulticast); - assertEquals(stats.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt, - retrievedStats.ipv6Multicast); - } - - /** - * Tests the failure in retrieval of wlan wake reason stats. - */ - @Test - public void testGetWlanWakeReasonCountFailure() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.getDebugHostWakeReasonStatsCallback cb) { - cb.onValues(mWifiStatusFailure, new WifiDebugHostWakeReasonStats()); - } - }).when(mIWifiChip).getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); - - // This should work in both AP & STA mode. - assertTrue(mWifiVendorHal.startVendorHalAp()); - - assertNull(mWifiVendorHal.getWlanWakeReasonCount()); - verify(mIWifiChip).getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); - } - - /** - * Test that getFwMemoryDump is properly plumbed - */ - @Test - public void testGetFwMemoryDump() throws Exception { - byte [] sample = NativeUtil.hexStringToByteArray("268c7a3fbfa4661c0bdd6a36"); - ArrayList<Byte> halBlob = NativeUtil.byteArrayToArrayList(sample); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.requestFirmwareDebugDumpCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, halBlob); - } - }).when(mIWifiChip).requestFirmwareDebugDump(any( - IWifiChip.requestFirmwareDebugDumpCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertArrayEquals(sample, mWifiVendorHal.getFwMemoryDump()); - } - - /** - * Test that getDriverStateDump is properly plumbed - * - * Just for variety, use AP mode here. - */ - @Test - public void testGetDriverStateDump() throws Exception { - byte [] sample = NativeUtil.hexStringToByteArray("e83ff543cf80083e6459d20f"); - ArrayList<Byte> halBlob = NativeUtil.byteArrayToArrayList(sample); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.requestDriverDebugDumpCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, halBlob); - } - }).when(mIWifiChip).requestDriverDebugDump(any( - IWifiChip.requestDriverDebugDumpCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalAp()); - assertArrayEquals(sample, mWifiVendorHal.getDriverStateDump()); - } - - /** - * Test that background scan failure is handled correctly. - */ - @Test - public void testBgScanFailureCallback() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - startBgScan(eventHandler); - - mIWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId); - verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); - } - - /** - * Test that background scan failure with wrong id is not reported. - */ - @Test - public void testBgScanFailureCallbackWithInvalidCmdId() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - startBgScan(eventHandler); - - mIWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId + 1); - verify(eventHandler, never()).onScanStatus(WifiNative.WIFI_SCAN_FAILED); - } - - /** - * Test that background scan full results are handled correctly. - */ - @Test - public void testBgScanFullScanResults() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - startBgScan(eventHandler); - - Pair<StaScanResult, ScanResult> result = createHidlAndFrameworkBgScanResult(); - mIWifiStaIfaceEventCallback.onBackgroundFullScanResult( - mWifiVendorHal.mScan.cmdId, 5, result.first); - - ArgumentCaptor<ScanResult> scanResultCaptor = ArgumentCaptor.forClass(ScanResult.class); - verify(eventHandler).onFullScanResult(scanResultCaptor.capture(), eq(5)); - - assertScanResultEqual(result.second, scanResultCaptor.getValue()); - } - - /** - * Test that background scan results are handled correctly. - */ - @Test - public void testBgScanScanResults() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - startBgScan(eventHandler); - - Pair<ArrayList<StaScanData>, ArrayList<WifiScanner.ScanData>> data = - createHidlAndFrameworkBgScanDatas(); - mIWifiStaIfaceEventCallback.onBackgroundScanResults( - mWifiVendorHal.mScan.cmdId, data.first); - - verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - assertScanDatasEqual( - data.second, Arrays.asList(mWifiVendorHal.mScan.latestScanResults)); - } - - /** - * Test that starting a new background scan when one is active will stop the previous one. - */ - @Test - public void testBgScanReplacement() throws Exception { - when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - startBgScan(eventHandler); - int cmdId1 = mWifiVendorHal.mScan.cmdId; - startBgScan(eventHandler); - assertNotEquals(mWifiVendorHal.mScan.cmdId, cmdId1); - verify(mIWifiStaIface, times(2)).startBackgroundScan(anyInt(), any()); - verify(mIWifiStaIface).stopBackgroundScan(cmdId1); - } - - /** - * Test stopping a background scan. - */ - @Test - public void testBgScanStop() throws Exception { - when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - startBgScan(eventHandler); - - int cmdId = mWifiVendorHal.mScan.cmdId; - - mWifiVendorHal.stopBgScan(TEST_IFACE_NAME); - mWifiVendorHal.stopBgScan(TEST_IFACE_NAME); // second call should not do anything - verify(mIWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once - } - - /** - * Test pausing and restarting a background scan. - */ - @Test - public void testBgScanPauseAndRestart() throws Exception { - when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - startBgScan(eventHandler); - - int cmdId = mWifiVendorHal.mScan.cmdId; - - mWifiVendorHal.pauseBgScan(TEST_IFACE_NAME); - mWifiVendorHal.restartBgScan(TEST_IFACE_NAME); - verify(mIWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once - verify(mIWifiStaIface, times(2)).startBackgroundScan(eq(cmdId), any()); - } - - /** - * Test the handling of log handler set. - */ - @Test - public void testSetLogHandler() throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - - WifiNative.WifiLoggerEventHandler eventHandler = - mock(WifiNative.WifiLoggerEventHandler.class); - - assertFalse(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip).enableDebugErrorAlerts(eq(true)); - reset(mIWifiChip); - - // Second call should fail. - assertFalse(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); - } - - /** - * Test the handling of log handler reset. - */ - @Test - public void testResetLogHandler() throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess); - - assertFalse(mWifiVendorHal.resetLogHandler()); - verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); - verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer(); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - // Now set and then reset. - assertTrue(mWifiVendorHal.setLoggingEventHandler( - mock(WifiNative.WifiLoggerEventHandler.class))); - assertTrue(mWifiVendorHal.resetLogHandler()); - verify(mIWifiChip).enableDebugErrorAlerts(eq(false)); - verify(mIWifiChip).stopLoggingToDebugRingBuffer(); - reset(mIWifiChip); - } - - /** - * Test the handling of log handler reset. - */ - @Test - public void testResetLogHandlerAfterHalStop() throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess); - - // Start in STA mode. - assertTrue(mWifiVendorHal.startVendorHalSta()); - - // Now set the log handler, succeeds. - assertTrue(mWifiVendorHal.setLoggingEventHandler( - mock(WifiNative.WifiLoggerEventHandler.class))); - verify(mIWifiChip).enableDebugErrorAlerts(eq(true)); - - // Stop - mWifiVendorHal.stopVendorHal(); - - // Reset the log handler after stop, not HAL methods invoked. - assertFalse(mWifiVendorHal.resetLogHandler()); - verify(mIWifiChip, never()).enableDebugErrorAlerts(eq(false)); - verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer(); - - // Start in STA mode again. - assertTrue(mWifiVendorHal.startVendorHalSta()); - - // Now set the log handler again, should succeed. - assertTrue(mWifiVendorHal.setLoggingEventHandler( - mock(WifiNative.WifiLoggerEventHandler.class))); - verify(mIWifiChip, times(2)).enableDebugErrorAlerts(eq(true)); - } - - /** - * Test the handling of alert callback. - */ - @Test - public void testAlertCallback() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallback); - - testAlertCallbackUsingProvidedCallback(mIWifiChipEventCallback); - } - - /** - * Test the handling of ring buffer callback. - */ - @Test - public void testRingBufferDataCallback() throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallback); - - byte[] errorData = new byte[45]; - new Random().nextBytes(errorData); - - // Randomly raise the HIDL callback before we register for the log callback. - // This should be safely ignored. (Not trigger NPE.) - mIWifiChipEventCallback.onDebugRingBufferDataAvailable( - new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); - mLooper.dispatchAll(); - - WifiNative.WifiLoggerEventHandler eventHandler = - mock(WifiNative.WifiLoggerEventHandler.class); - assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip).enableDebugErrorAlerts(eq(true)); - - // Now raise the HIDL callback, this should be properly handled. - mIWifiChipEventCallback.onDebugRingBufferDataAvailable( - new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); - mLooper.dispatchAll(); - verify(eventHandler).onRingBufferData( - any(WifiNative.RingBufferStatus.class), eq(errorData)); - - // Now stop the logging and invoke the callback. This should be ignored. - reset(eventHandler); - assertTrue(mWifiVendorHal.resetLogHandler()); - mIWifiChipEventCallback.onDebugRingBufferDataAvailable( - new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); - mLooper.dispatchAll(); - verify(eventHandler, never()).onRingBufferData(anyObject(), anyObject()); - } - - /** - * Test the handling of Vendor HAL death. - */ - @Test - public void testVendorHalDeath() { - // Invoke the HAL device manager status callback with ready set to false to indicate the - // death of the HAL. - when(mHalDeviceManager.isReady()).thenReturn(false); - mHalDeviceManagerStatusCallbacks.onStatusChanged(); - mLooper.dispatchAll(); - - verify(mVendorHalDeathHandler).onDeath(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation for 1.0 interface. - * This should return failure since SAR is not supported for this interface version. - */ - @Test - public void testSelectTxPowerScenario_1_0() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - sarInfo.isVoiceCall = true; - - assertTrue(mWifiVendorHal.startVendorHalSta()); - // Should fail because we exposed the 1.0 IWifiChip. - assertFalse(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt()); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation for 1.1 interface. - * This should return success. - */ - @Test - public void testSelectTxPowerScenario_1_1() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - sarInfo.isVoiceCall = true; - - // Now expose the 1.1 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mHandler); - when(mIWifiChipV11.selectTxPowerScenario(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV11).selectTxPowerScenario( - eq(android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL)); - verify(mIWifiChipV11, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation for 1.2 interface. - * This should return success. - */ - @Test - public void testSelectTxPowerScenario_1_2() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - sarInfo.isVoiceCall = true; - - // Now expose the 1.2 IWifiChip - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.VOICE_CALL)); - verify(mIWifiChipV12, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the resetTxPowerScenario HIDL method invocation for 1.0 interface. - * This should return failure since it does not supprt SAR. - */ - @Test - public void testResetTxPowerScenario_1_0() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - // Should fail because we exposed the 1.0 IWifiChip. - assertFalse(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV11, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the resetTxPowerScenario HIDL method invocation for 1.1 interface. - * This should return success. - */ - @Test - public void testResetTxPowerScenario_1_1() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - // Now expose the 1.1 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mHandler); - when(mIWifiChipV11.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV11).resetTxPowerScenario(); - verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt()); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test resetting SAR scenario when not needed, should return true without invoking - * the HAL method. - * This is using HAL 1.1 interface. - */ - @Test - public void testResetTxPowerScenario_not_needed_1_1() throws RemoteException { - InOrder inOrder = inOrder(mIWifiChipV11); - - // Create a SAR info record (no SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - // Now expose the 1.1 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mHandler); - when(mIWifiChipV11.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - /* Calling reset once */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV11).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt()); - sarInfo.reportingSuccessful(); - - /* Calling reset second time */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV11, never()).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt()); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the new resetTxPowerScenario HIDL method invocation for 1.2 interface. - * This should return success. - */ - @Test - public void testResetTxPowerScenario_1_2() throws RemoteException { - // Create a SAR info record (no SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - // Now expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).resetTxPowerScenario(); - verify(mIWifiChipV12, never()).selectTxPowerScenario_1_2(anyInt()); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test resetting SAR scenario when not needed, should return true without invoking - * the HAL method. - * This is using HAL 1.2 interface. - */ - @Test - public void testResetTxPowerScenario_not_needed_1_2() throws RemoteException { - InOrder inOrder = inOrder(mIWifiChipV12); - - // Create a SAR info record (no SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - // Now expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - /* Calling reset once */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV12).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt()); - sarInfo.reportingSuccessful(); - - /* Calling reset second time */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV12, never()).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt()); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with SAP and voice call support. - * When SAP is enabled, should result in SAP with near body scenario - * Using IWifiChip 1.2 interface - */ - @Test - public void testSapScenarios_SelectTxPowerV1_2() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - sarInfo.isWifiSapEnabled = true; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - // ON_BODY_CELL_ON - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_BODY_CELL_ON)); - verify(mIWifiChipV12, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with SAP and voice call support. - * When a voice call is ongoing, should result in cell with near head scenario - * Using IWifiChip 1.2 interface - */ - @Test - public void testVoiceCallScenarios_SelectTxPowerV1_2() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - sarInfo.isVoiceCall = true; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - // ON_HEAD_CELL_ON - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON)); - verify(mIWifiChipV12, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with SAP and voice call support. - * When earpiece is active, should result in cell with near head scenario - * Using IWifiChip 1.2 interface - */ - @Test - public void testEarPieceScenarios_SelectTxPowerV1_2() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - sarInfo.isEarPieceActive = true; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - // ON_HEAD_CELL_ON - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON)); - verify(mIWifiChipV12, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test setting SAR scenario when not needed, should return true without invoking - * the HAL method. - * This is using HAL 1.2 interface. - */ - @Test - public void testSetTxPowerScenario_not_needed_1_2() throws RemoteException { - InOrder inOrder = inOrder(mIWifiChipV12); - - // Create a SAR info record (no SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - // Now expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - /* Calling set once */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV12).resetTxPowerScenario(); - sarInfo.reportingSuccessful(); - - /* Calling set second time */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV12, never()).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt()); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with IWifiChip 1.2 interface. - * The following inputs: - * - SAP is enabled - * - No voice call - */ - @Test - public void testSelectTxPowerScenario_1_2_sap() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - sarInfo.isWifiSapEnabled = true; - sarInfo.isVoiceCall = false; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_BODY_CELL_ON)); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with IWifiChip 1.2 interface. - * The following inputs: - * - SAP is enabled - * - voice call is enabled - */ - @Test - public void testSelectTxPowerScenario_1_2_head_sap_call() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - sarInfo.isWifiSapEnabled = true; - sarInfo.isVoiceCall = true; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON)); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the setLowLatencyMode HIDL method invocation with IWifiChip 1.2 interface. - * Function should return false - */ - @Test - public void testSetLowLatencyMode_1_2() throws RemoteException { - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - assertFalse(mWifiVendorHal.setLowLatencyMode(true)); - assertFalse(mWifiVendorHal.setLowLatencyMode(false)); - } - - /** - * Test the setLowLatencyMode HIDL method invocation with IWifiChip 1.3 interface - */ - @Test - public void testSetLowLatencyMode_1_3_enabled() throws RemoteException { - int mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.LOW; - - // Expose the 1.3 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_3(mHalDeviceManager, mHandler); - when(mIWifiChipV13.setLatencyMode(anyInt())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.setLowLatencyMode(true)); - verify(mIWifiChipV13).setLatencyMode(eq(mode)); - } - - /** - * Test the setLowLatencyMode HIDL method invocation with IWifiChip 1.3 interface - */ - @Test - public void testSetLowLatencyMode_1_3_disabled() throws RemoteException { - int mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.NORMAL; - - // Expose the 1.3 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_3(mHalDeviceManager, mHandler); - when(mIWifiChipV13.setLatencyMode(anyInt())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.setLowLatencyMode(false)); - verify(mIWifiChipV13).setLatencyMode(eq(mode)); - } - - /** - * Test the STA Iface creation failure due to iface name retrieval failure. - */ - @Test - public void testCreateStaIfaceFailureInIfaceName() throws RemoteException { - doAnswer(new AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusFailure, "wlan0"); - } - }).when(mIWifiStaIface).getName(any(IWifiIface.getNameCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHal()); - assertNull(mWifiVendorHal.createStaIface(null)); - verify(mHalDeviceManager).createStaIface(any(), eq(null)); - } - - /** - * Test the STA Iface creation failure due to iface name retrieval failure. - */ - @Test - public void testCreateApIfaceFailureInIfaceName() throws RemoteException { - doAnswer(new AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusFailure, "wlan0"); - } - }).when(mIWifiApIface).getName(any(IWifiIface.getNameCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHal()); - assertNull(mWifiVendorHal.createApIface(null)); - verify(mHalDeviceManager).createApIface(any(), eq(null)); - } - - /** - * Test the creation and removal of STA Iface. - */ - @Test - public void testCreateRemoveStaIface() throws RemoteException { - assertTrue(mWifiVendorHal.startVendorHal()); - String ifaceName = mWifiVendorHal.createStaIface(null); - verify(mHalDeviceManager).createStaIface(any(), eq(null)); - assertEquals(TEST_IFACE_NAME, ifaceName); - assertTrue(mWifiVendorHal.removeStaIface(ifaceName)); - verify(mHalDeviceManager).removeIface(eq(mIWifiStaIface)); - } - - /** - * Test the creation and removal of Ap Iface. - */ - @Test - public void testCreateRemoveApIface() throws RemoteException { - assertTrue(mWifiVendorHal.startVendorHal()); - String ifaceName = mWifiVendorHal.createApIface(null); - verify(mHalDeviceManager).createApIface(any(), eq(null)); - assertEquals(TEST_IFACE_NAME, ifaceName); - assertTrue(mWifiVendorHal.removeApIface(ifaceName)); - verify(mHalDeviceManager).removeIface(eq(mIWifiApIface)); - } - - /** - * Test the callback handling for the 1.2 HAL. - */ - @Test - public void testAlertCallbackUsing_1_2_EventCallback() throws Exception { - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallbackV12); - - testAlertCallbackUsingProvidedCallback(mIWifiChipEventCallbackV12); - } - - /** - * Verifies setMacAddress() success. - */ - @Test - public void testSetStaMacAddressSuccess() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - when(mIWifiStaIfaceV12.setMacAddress(macByteArray)).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.setMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - verify(mIWifiStaIfaceV12).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() can handle failure status. - */ - @Test - public void testSetStaMacAddressFailDueToStatusFailure() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - when(mIWifiStaIfaceV12.setMacAddress(macByteArray)).thenReturn(mWifiStatusFailure); - - assertFalse(mWifiVendorHal.setMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - verify(mIWifiStaIfaceV12).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() can handle RemoteException. - */ - @Test - public void testSetStaMacAddressFailDueToRemoteException() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - doThrow(new RemoteException()).when(mIWifiStaIfaceV12).setMacAddress(macByteArray); - - assertFalse(mWifiVendorHal.setMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - verify(mIWifiStaIfaceV12).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() success. - */ - @Test - public void testSetApMacAddressSuccess() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV14); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - when(mIWifiApIfaceV14.setMacAddress(macByteArray)).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.setMacAddress(TEST_IFACE_NAME_1, TEST_MAC_ADDRESS)); - verify(mIWifiApIfaceV14).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() can handle failure status. - */ - @Test - public void testSetApMacAddressFailDueToStatusFailure() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV14); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - when(mIWifiApIfaceV14.setMacAddress(macByteArray)).thenReturn(mWifiStatusFailure); - - assertFalse(mWifiVendorHal.setMacAddress(TEST_IFACE_NAME_1, TEST_MAC_ADDRESS)); - verify(mIWifiApIfaceV14).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() can handle RemoteException. - */ - @Test - public void testSetApMacAddressFailDueToRemoteException() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV14); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - doThrow(new RemoteException()).when(mIWifiApIfaceV14).setMacAddress(macByteArray); - - assertFalse(mWifiVendorHal.setMacAddress(TEST_IFACE_NAME_1, TEST_MAC_ADDRESS)); - verify(mIWifiApIfaceV14).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() does not crash with older HALs. - */ - @Test - public void testSetMacAddressDoesNotCrashOnOlderHal() throws Exception { - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - assertFalse(mWifiVendorHal.setMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - } - - /** - * Verifies isSetMacAddressSupported(). - */ - @Test - public void testIsSetMacAddressSupportedWhenV1_4Support() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV14); - - assertTrue(mWifiVendorHal.isSetMacAddressSupported(TEST_IFACE_NAME_1)); - } - - /** - * Verifies isSetMacAddressSupported(). - */ - @Test - public void testIsSetMacAddressSupportedWhenV1_2Support() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - assertTrue(mWifiVendorHal.isSetMacAddressSupported(TEST_IFACE_NAME)); - } - - /** - * Verifies isSetMacAddressSupported() does not crash with older HALs. - */ - @Test - public void testIsSetMacAddressSupportedOnOlderHal() throws Exception { - assertFalse(mWifiVendorHal.isSetMacAddressSupported(TEST_IFACE_NAME)); - } - - /** - * Verifies radio mode change callback to indicate DBS mode. - */ - @Test - public void testRadioModeChangeCallbackToDbsMode() throws Exception { - startHalInStaModeAndRegisterRadioModeChangeCallback(); - - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - RadioModeInfo radioModeInfo1 = new RadioModeInfo(); - radioModeInfo1.bandInfo = WifiScanner.WIFI_BAND_24_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 1; - - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo1.ifaceInfos.add(ifaceInfo1); - - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); - radioModeInfos.add(radioModeInfo0); - radioModeInfos.add(radioModeInfo1); - - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); - mLooper.dispatchAll(); - verify(mVendorHalRadioModeChangeHandler).onDbs(); - - verifyNoMoreInteractions(mVendorHalRadioModeChangeHandler); - } - - /** - * Verifies radio mode change callback to indicate DBS mode using V1.4 callback. - */ - @Test - public void testRadioModeChangeCallbackToDbsModeV14() throws Exception { - startHalInStaModeAndRegisterRadioModeChangeCallback14(); - - android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo radioModeInfo0 = - new android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_6_GHZ; - android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo radioModeInfo1 = - new android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo(); - radioModeInfo1.bandInfo = WifiScanner.WIFI_BAND_24_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 1; - - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo1.ifaceInfos.add(ifaceInfo1); - - ArrayList<android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo> radioModeInfos = - new ArrayList<>(); - radioModeInfos.add(radioModeInfo0); - radioModeInfos.add(radioModeInfo1); - - mIWifiChipEventCallbackV14.onRadioModeChange_1_4(radioModeInfos); - mLooper.dispatchAll(); - verify(mVendorHalRadioModeChangeHandler).onDbs(); - - verifyNoMoreInteractions(mVendorHalRadioModeChangeHandler); - } - - /** - * Verifies radio mode change callback to indicate SBS mode. - */ - @Test - public void testRadioModeChangeCallbackToSbsMode() throws Exception { - startHalInStaModeAndRegisterRadioModeChangeCallback(); - - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - RadioModeInfo radioModeInfo1 = new RadioModeInfo(); - radioModeInfo1.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 36; - - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo1.ifaceInfos.add(ifaceInfo1); - - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); - radioModeInfos.add(radioModeInfo0); - radioModeInfos.add(radioModeInfo1); - - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); - mLooper.dispatchAll(); - verify(mVendorHalRadioModeChangeHandler).onSbs(WifiScanner.WIFI_BAND_5_GHZ); - - verifyNoMoreInteractions(mVendorHalRadioModeChangeHandler); - } - - /** - * Verifies radio mode change callback to indicate SCC mode. - */ - @Test - public void testRadioModeChangeCallbackToSccMode() throws Exception { - startHalInStaModeAndRegisterRadioModeChangeCallback(); - - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 34; - - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo0.ifaceInfos.add(ifaceInfo1); - - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); - radioModeInfos.add(radioModeInfo0); - - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); - mLooper.dispatchAll(); - verify(mVendorHalRadioModeChangeHandler).onScc(WifiScanner.WIFI_BAND_5_GHZ); - - verifyNoMoreInteractions(mVendorHalRadioModeChangeHandler); - } - - /** - * Verifies radio mode change callback to indicate MCC mode. - */ - @Test - public void testRadioModeChangeCallbackToMccMode() throws Exception { - startHalInStaModeAndRegisterRadioModeChangeCallback(); - - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_BOTH; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 1; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 36; - - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo0.ifaceInfos.add(ifaceInfo1); - - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); - radioModeInfos.add(radioModeInfo0); - - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); - mLooper.dispatchAll(); - verify(mVendorHalRadioModeChangeHandler).onMcc(WifiScanner.WIFI_BAND_BOTH); - - verifyNoMoreInteractions(mVendorHalRadioModeChangeHandler); - } - - /** - * Verifies radio mode change callback error cases. - */ - @Test - public void testRadioModeChangeCallbackErrorSimultaneousWithSameIfaceOnBothRadios() - throws Exception { - startHalInStaModeAndRegisterRadioModeChangeCallback(); - - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_24_GHZ; - RadioModeInfo radioModeInfo1 = new RadioModeInfo(); - radioModeInfo1.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo1.ifaceInfos.add(ifaceInfo0); - - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); - radioModeInfos.add(radioModeInfo0); - radioModeInfos.add(radioModeInfo1); - - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); - mLooper.dispatchAll(); - // Ignored.... - - verifyNoMoreInteractions(mVendorHalRadioModeChangeHandler); - } - - @Test - public void testStaInterfaceAvailableForRequestListeners() throws Exception { - WifiNative.InterfaceAvailableForRequestListener staListener = - mock(WifiNative.InterfaceAvailableForRequestListener.class); - - when(mHalDeviceManager.isStarted()).thenReturn(false); - mWifiVendorHal.registerStaIfaceAvailabilityListener(staListener); - verify(mHalDeviceManager, never()).registerInterfaceAvailableForRequestListener( - eq(IfaceType.STA), any(), any()); - - when(mHalDeviceManager.isStarted()).thenReturn(true); - mHalDeviceManagerStatusCallbacks.onStatusChanged(); - verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( - eq(IfaceType.STA), any(), any()); - } - - @Test - public void testApInterfaceAvailableForRequestListeners() throws Exception { - WifiNative.InterfaceAvailableForRequestListener apListener = - mock(WifiNative.InterfaceAvailableForRequestListener.class); - - when(mHalDeviceManager.isStarted()).thenReturn(false); - mWifiVendorHal.registerApIfaceAvailabilityListener(apListener); - verify(mHalDeviceManager, never()).registerInterfaceAvailableForRequestListener( - eq(IfaceType.AP), any(), any()); - - when(mHalDeviceManager.isStarted()).thenReturn(true); - mHalDeviceManagerStatusCallbacks.onStatusChanged(); - verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( - eq(IfaceType.AP), any(), any()); - } - - private void startHalInStaModeAndRegisterRadioModeChangeCallback() { - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); - mWifiVendorHal.registerRadioModeChangeHandler(mVendorHalRadioModeChangeHandler); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallbackV12); - } - - private void startHalInStaModeAndRegisterRadioModeChangeCallback14() { - // Expose the 1.4 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_4(mHalDeviceManager, mHandler); - mWifiVendorHal.registerRadioModeChangeHandler(mVendorHalRadioModeChangeHandler); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallbackV14); - } - - private void testAlertCallbackUsingProvidedCallback(IWifiChipEventCallback chipCallback) - throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess); - - int errorCode = 5; - byte[] errorData = new byte[45]; - new Random().nextBytes(errorData); - - // Randomly raise the HIDL callback before we register for the log callback. - // This should be safely ignored. (Not trigger NPE.) - chipCallback.onDebugErrorAlert( - errorCode, NativeUtil.byteArrayToArrayList(errorData)); - mLooper.dispatchAll(); - - WifiNative.WifiLoggerEventHandler eventHandler = - mock(WifiNative.WifiLoggerEventHandler.class); - assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip).enableDebugErrorAlerts(eq(true)); - - // Now raise the HIDL callback, this should be properly handled. - chipCallback.onDebugErrorAlert( - errorCode, NativeUtil.byteArrayToArrayList(errorData)); - mLooper.dispatchAll(); - verify(eventHandler).onWifiAlert(eq(errorCode), eq(errorData)); - - // Now stop the logging and invoke the callback. This should be ignored. - reset(eventHandler); - assertTrue(mWifiVendorHal.resetLogHandler()); - chipCallback.onDebugErrorAlert( - errorCode, NativeUtil.byteArrayToArrayList(errorData)); - mLooper.dispatchAll(); - verify(eventHandler, never()).onWifiAlert(anyInt(), anyObject()); - } - - private void startBgScan(WifiNative.ScanEventHandler eventHandler) throws Exception { - when(mIWifiStaIface.startBackgroundScan( - anyInt(), any(StaBackgroundScanParameters.class))).thenReturn(mWifiStatusSuccess); - WifiNative.ScanSettings settings = new WifiNative.ScanSettings(); - settings.num_buckets = 1; - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - bucketSettings.bucket = 0; - bucketSettings.period_ms = 16000; - bucketSettings.report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - settings.buckets = new WifiNative.BucketSettings[] {bucketSettings}; - assertTrue(mWifiVendorHal.startBgScan(TEST_IFACE_NAME, settings, eventHandler)); - } - - // Create a pair of HIDL scan result and its corresponding framework scan result for - // comparison. - private Pair<StaScanResult, ScanResult> createHidlAndFrameworkBgScanResult() { - StaScanResult staScanResult = new StaScanResult(); - Random random = new Random(); - byte[] ssid = new byte[8]; - random.nextBytes(ssid); - staScanResult.ssid.addAll(NativeUtil.byteArrayToArrayList(ssid)); - random.nextBytes(staScanResult.bssid); - staScanResult.frequency = 2432; - staScanResult.rssi = -45; - staScanResult.timeStampInUs = 5; - WifiInformationElement ie1 = new WifiInformationElement(); - byte[] ie1_data = new byte[56]; - random.nextBytes(ie1_data); - ie1.id = 1; - ie1.data.addAll(NativeUtil.byteArrayToArrayList(ie1_data)); - staScanResult.informationElements.add(ie1); - - // Now create the corresponding Scan result structure. - ScanResult scanResult = new ScanResult(); - scanResult.SSID = NativeUtil.encodeSsid(staScanResult.ssid); - scanResult.BSSID = NativeUtil.macAddressFromByteArray(staScanResult.bssid); - scanResult.wifiSsid = WifiSsid.createFromByteArray(ssid); - scanResult.frequency = staScanResult.frequency; - scanResult.level = staScanResult.rssi; - scanResult.timestamp = staScanResult.timeStampInUs; - - return Pair.create(staScanResult, scanResult); - } - - // Create a pair of HIDL scan datas and its corresponding framework scan datas for - // comparison. - private Pair<ArrayList<StaScanData>, ArrayList<WifiScanner.ScanData>> - createHidlAndFrameworkBgScanDatas() { - ArrayList<StaScanData> staScanDatas = new ArrayList<>(); - StaScanData staScanData = new StaScanData(); - - Pair<StaScanResult, ScanResult> result = createHidlAndFrameworkBgScanResult(); - staScanData.results.add(result.first); - staScanData.bucketsScanned = 5; - staScanData.flags = StaScanDataFlagMask.INTERRUPTED; - staScanDatas.add(staScanData); - - ArrayList<WifiScanner.ScanData> scanDatas = new ArrayList<>(); - ScanResult[] scanResults = new ScanResult[1]; - scanResults[0] = result.second; - WifiScanner.ScanData scanData = - new WifiScanner.ScanData(mWifiVendorHal.mScan.cmdId, 1, - staScanData.bucketsScanned, WifiScanner.WIFI_BAND_UNSPECIFIED, scanResults); - scanDatas.add(scanData); - return Pair.create(staScanDatas, scanDatas); - } - - private void assertScanResultEqual(ScanResult expected, ScanResult actual) { - assertEquals(expected.SSID, actual.SSID); - assertEquals(expected.wifiSsid.getHexString(), actual.wifiSsid.getHexString()); - assertEquals(expected.BSSID, actual.BSSID); - assertEquals(expected.frequency, actual.frequency); - assertEquals(expected.level, actual.level); - assertEquals(expected.timestamp, actual.timestamp); - } - - private void assertScanResultsEqual(ScanResult[] expected, ScanResult[] actual) { - assertEquals(expected.length, actual.length); - for (int i = 0; i < expected.length; i++) { - assertScanResultEqual(expected[i], actual[i]); - } - } - - private void assertScanDataEqual(WifiScanner.ScanData expected, WifiScanner.ScanData actual) { - assertEquals(expected.getId(), actual.getId()); - assertEquals(expected.getFlags(), actual.getFlags()); - assertEquals(expected.getBucketsScanned(), actual.getBucketsScanned()); - assertScanResultsEqual(expected.getResults(), actual.getResults()); - } - - private void assertScanDatasEqual( - List<WifiScanner.ScanData> expected, List<WifiScanner.ScanData> actual) { - assertEquals(expected.size(), actual.size()); - for (int i = 0; i < expected.size(); i++) { - assertScanDataEqual(expected.get(i), actual.get(i)); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiWakeMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiWakeMetricsTest.java deleted file mode 100644 index 760a9a2d4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiWakeMetricsTest.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2018 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.server.wifi; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static junit.framework.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiWakeStats; - -import org.junit.Before; -import org.junit.Test; - -@SmallTest -public class WifiWakeMetricsTest extends WifiBaseTest { - - private WifiWakeMetrics mWifiWakeMetrics; - - @Before - public void setUp() { - mWifiWakeMetrics = new WifiWakeMetrics(); - } - - @Test - public void buildsEmptyProto() { - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 0); - assertEquals(wifiWakeStats.numWakeups, 0); - assertEquals(wifiWakeStats.numIgnoredStarts, 0); - assertEquals(wifiWakeStats.sessions.length, 0); - } - - @Test - public void buildsMultiSessionProto_fewerThanMax() { - mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(1 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(2 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 3); - assertEquals(wifiWakeStats.numWakeups, 0); - assertEquals(wifiWakeStats.sessions.length, 3); - } - - @Test - public void buildsMultiSessionProto_greaterThanMax() { - int numSessions = WifiWakeMetrics.MAX_RECORDED_SESSIONS + 1; - for (int i = 0; i < numSessions; i++) { - mWifiWakeMetrics.recordStartEvent(i); - mWifiWakeMetrics.recordInitializeEvent(i, i); - mWifiWakeMetrics.recordUnlockEvent(i); - mWifiWakeMetrics.recordWakeupEvent(i); - mWifiWakeMetrics.recordResetEvent(i); - } - - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, numSessions); - assertEquals(wifiWakeStats.numWakeups, numSessions); - assertEquals(wifiWakeStats.sessions.length, WifiWakeMetrics.MAX_RECORDED_SESSIONS); - - // ensure that the first (not last) MAX_RECORDED_SESSIONS are recorded - for (int i = 0; i < WifiWakeMetrics.MAX_RECORDED_SESSIONS; i++) { - WifiWakeStats.Session session = wifiWakeStats.sessions[i]; - assertNotNull(session); - assertEquals(session.lockedNetworksAtStart, i); - assertEquals(session.lockedNetworksAtInitialize, i); - } - } - - @Test - public void buildProtoCountsWakes() { - mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */); - mWifiWakeMetrics.recordWakeupEvent(3 /* numScans */); - mWifiWakeMetrics.recordResetEvent(3 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(1 /* numNetworks */); - mWifiWakeMetrics.recordWakeupEvent(3 /* numScans */); - mWifiWakeMetrics.recordResetEvent(3 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(2 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 3); - assertEquals(wifiWakeStats.numWakeups, 2); - assertEquals(wifiWakeStats.sessions.length, 3); - } - - @Test - public void buildProtoDoesNotCountWakeInCurrentSession() { - mWifiWakeMetrics.recordStartEvent(1 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(2 /* numNetworks */); - mWifiWakeMetrics.recordWakeupEvent(3 /* numScans */); - - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 1); - assertEquals(wifiWakeStats.numWakeups, 0); - assertEquals(wifiWakeStats.sessions.length, 1); - } - - @Test - public void buildProtoCountsIgnoredStarts() { - mWifiWakeMetrics.recordIgnoredStart(); - mWifiWakeMetrics.recordIgnoredStart(); - mWifiWakeMetrics.recordIgnoredStart(); - - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numIgnoredStarts, 3); - } - - @Test - public void buildProtoDoesNotIncludeCurrentSession() { - mWifiWakeMetrics.recordStartEvent(1 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(2 /* numNetworks */); - - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 1); - assertEquals(wifiWakeStats.sessions.length, 1); - assertEquals(wifiWakeStats.sessions[0].lockedNetworksAtStart, 1); - } - - @Test - public void ignoresEventsIfStartNotCalled() { - mWifiWakeMetrics.recordUnlockEvent(1 /* numScans */); - mWifiWakeMetrics.recordWakeupEvent(1 /* numScans */); - mWifiWakeMetrics.recordResetEvent(1 /* numScans */); - - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 0); - assertEquals(wifiWakeStats.sessions.length, 0); - } - - @Test - public void ignoresEventsAfterResetAndBeforeStartCalled() { - mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */); - mWifiWakeMetrics.recordWakeupEvent(1 /* numScans */); - mWifiWakeMetrics.recordResetEvent(1 /* numScans */); - - mWifiWakeMetrics.recordWakeupEvent(10 /* numScans */); - - // verify only 1 session - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 1); - assertEquals(wifiWakeStats.sessions.length, 1); - - // verify it didn't overwrite session - WifiWakeStats.Session session = wifiWakeStats.sessions[0]; - assertNotNull(session.wakeupEvent); - assertEquals(session.wakeupEvent.elapsedScans, 1); - } - - @Test - public void clearRemovesSessions() { - mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */); - mWifiWakeMetrics.recordWakeupEvent(3 /* numScans */); - mWifiWakeMetrics.recordResetEvent(3 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */); - mWifiWakeMetrics.recordIgnoredStart(); - mWifiWakeMetrics.recordIgnoredStart(); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - // verify sessions - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 3); - assertEquals(wifiWakeStats.numWakeups, 1); - assertEquals(wifiWakeStats.numIgnoredStarts, 2); - assertEquals(wifiWakeStats.sessions.length, 3); - - mWifiWakeMetrics.clear(); - wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 0); - assertEquals(wifiWakeStats.numWakeups, 0); - assertEquals(wifiWakeStats.numIgnoredStarts, 0); - assertEquals(wifiWakeStats.sessions.length, 0); - } - - @Test - public void clearDoesNotInterruptCurrentSession() { - mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - mWifiWakeMetrics.recordStartEvent(0 /* numNetworks */); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - mWifiWakeMetrics.recordStartEvent(1 /* numNetworks */); - mWifiWakeMetrics.clear(); - mWifiWakeMetrics.recordResetEvent(0 /* numScans */); - - // keeps the current session - WifiWakeStats wifiWakeStats = mWifiWakeMetrics.buildProto(); - assertNotNull(wifiWakeStats); - assertEquals(wifiWakeStats.numSessions, 1); - assertEquals(wifiWakeStats.sessions.length, 1); - } - - @Test - public void session_buildsEmptyProto() { - WifiWakeMetrics.Session session = - new WifiWakeMetrics.Session(1 /* numNetworks */, 1000 /* timestamp */); - - WifiWakeStats.Session sessionProto = session.buildProto(); - assertNotNull(sessionProto); - assertEquals(sessionProto.lockedNetworksAtStart, 1); - assertEquals(sessionProto.startTimeMillis, 1000); - assertNull(sessionProto.unlockEvent); - assertNull(sessionProto.wakeupEvent); - assertNull(sessionProto.resetEvent); - } - - @Test - public void session_recordsEvents() { - WifiWakeMetrics.Session session = - new WifiWakeMetrics.Session(1 /* numNetworks */, 1000 /* timestamp */); - - session.recordUnlockEvent(1 /* numScans */, 1100 /* timestamp */); - assertNotNull(session.mUnlockEvent); - assertEquals(session.mUnlockEvent.mNumScans, 1); - assertEquals(session.mUnlockEvent.mElapsedTime, 100); - - session.recordWakeupEvent(2 /* numScans */, 1200 /* timestamp */); - assertNotNull(session.mWakeupEvent); - assertEquals(session.mWakeupEvent.mNumScans, 2); - assertEquals(session.mWakeupEvent.mElapsedTime, 200); - - session.recordResetEvent(3 /* numScans */, 1300 /* timestamp */); - assertNotNull(session.mResetEvent); - assertEquals(session.mResetEvent.mNumScans, 3); - assertEquals(session.mResetEvent.mElapsedTime, 300); - } - - @Test - public void session_buildProto() { - WifiWakeMetrics.Session session = - new WifiWakeMetrics.Session(1 /* numNetworks */, 1000 /* timestamp */); - - session.recordInitializeEvent(1 /* numScans */, 2 /* numNetworks */, 1100 /* timestamp */); - session.recordUnlockEvent(2 /* numScans */, 1200 /* timestamp */); - session.recordWakeupEvent(3 /* numScans */, 1300 /* timestamp */); - session.recordResetEvent(4 /* numScans */, 1400 /* timestamp */); - - WifiWakeStats.Session sessionProto = session.buildProto(); - assertNotNull(sessionProto); - assertEquals(sessionProto.lockedNetworksAtStart, 1); - assertEquals(sessionProto.lockedNetworksAtInitialize, 2); - assertEquals(sessionProto.startTimeMillis, 1000); - - verifyEventProto(sessionProto.initializeEvent, 1, 100); - verifyEventProto(sessionProto.unlockEvent, 2, 200); - verifyEventProto(sessionProto.wakeupEvent, 3, 300); - verifyEventProto(sessionProto.resetEvent, 4, 400); - } - - @Test - public void session_ignoresRepeatedEvents() { - WifiWakeMetrics.Session session = - new WifiWakeMetrics.Session(1 /* numNetworks */, 1000 /* timestamp */); - - session.recordResetEvent(1 /* numScans */, 1100 /* timestamp */); - assertNotNull(session.mResetEvent); - assertEquals(session.mResetEvent.mNumScans, 1); - assertEquals(session.mResetEvent.mElapsedTime, 100); - - session.recordResetEvent(2 /* numScans */, 1200 /* timestamp */); - assertEquals(session.mResetEvent.mNumScans, 1); - assertEquals(session.mResetEvent.mElapsedTime, 100); - } - - @Test - public void session_hasWakeupTriggered() { - WifiWakeMetrics.Session session = - new WifiWakeMetrics.Session(0 /* numNetworks */, 1000 /* timestamp */); - assertFalse(session.hasWakeupTriggered()); - - session.recordInitializeEvent(3 /* numScans */, 0 /* numNetworks */, 1100 /* timestamp */); - assertFalse(session.hasWakeupTriggered()); - - session.recordWakeupEvent(3 /* numScans */, 1100 /* timestamp */); - assertTrue(session.hasWakeupTriggered()); - - session.recordResetEvent(3 /* numScans */, 1100 /* timestamp */); - assertTrue(session.hasWakeupTriggered()); - } - - @Test - public void event_buildsProto() { - WifiWakeMetrics.Event event = - new WifiWakeMetrics.Event(1 /* numScans */, 1000 /* elapsedTime */); - - verifyEventProto(event.buildProto(), 1, 1000); - } - - private void verifyEventProto(WifiWakeStats.Session.Event event, int scans, int elapsedTime) { - assertNotNull(event); - assertEquals(event.elapsedScans, scans); - assertEquals(event.elapsedTimeMillis, elapsedTime); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WrongPasswordNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/WrongPasswordNotifierTest.java deleted file mode 100644 index b4d58d045..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WrongPasswordNotifierTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.ActivityManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.os.UserHandle; -import android.provider.Settings; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Answers; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; - -import java.util.Arrays; - -/** - * Unit tests for {@link com.android.server.wifi.WrongPasswordNotifier}. - */ -@SmallTest -public class WrongPasswordNotifierTest extends WifiBaseTest { - private static final String TEST_SSID = "Test SSID"; - private static final String TEST_SETTINGS_PACKAGE = "android"; - - @Mock WifiContext mContext; - @Mock Resources mResources; - @Mock PackageManager mPackageManager; - @Mock NotificationManager mNotificationManager; - @Mock FrameworkFacade mFrameworkFacade; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Notification.Builder mNotificationBuilder; - WrongPasswordNotifier mWrongPassNotifier; - private MockitoSession mSession; - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - ResolveInfo settingsResolveInfo = new ResolveInfo(); - settingsResolveInfo.activityInfo = new ActivityInfo(); - settingsResolveInfo.activityInfo.packageName = TEST_SETTINGS_PACKAGE; - when(mPackageManager.queryIntentActivitiesAsUser( - argThat(((intent) -> intent.getAction().equals(Settings.ACTION_WIFI_SETTINGS))), - anyInt(), any())) - .thenReturn(Arrays.asList(settingsResolveInfo)); - when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) - .thenReturn(mNotificationManager); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources"); - mWrongPassNotifier = new WrongPasswordNotifier(mContext, mFrameworkFacade); - - // static mocking - mSession = ExtendedMockito.mockitoSession() - .mockStatic(ActivityManager.class, withSettings().lenient()) - .startMocking(); - when(ActivityManager.getCurrentUser()).thenReturn(UserHandle.USER_SYSTEM); - } - - /** - * Called after each test - */ - @After - public void cleanup() { - validateMockitoUsage(); - if (mSession != null) { - mSession.finishMocking(); - } - } - - /** - * Verify that a wrong password notification will be generated/pushed when a wrong password - * error is detected for the current connection. - * - * @throws Exception - */ - @Test - public void onWrongPasswordError() throws Exception { - when(mFrameworkFacade.makeNotificationBuilder(any(), - eq(WifiService.NOTIFICATION_NETWORK_ALERTS))).thenReturn(mNotificationBuilder); - mWrongPassNotifier.onWrongPasswordError(TEST_SSID); - verify(mNotificationManager).notify(eq(WrongPasswordNotifier.NOTIFICATION_ID), any()); - ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); - verify(mFrameworkFacade).getActivity( - any(Context.class), anyInt(), intent.capture(), anyInt()); - assertEquals(Settings.ACTION_WIFI_SETTINGS, intent.getValue().getAction()); - assertEquals(TEST_SETTINGS_PACKAGE, intent.getValue().getPackage()); - assertEquals(TEST_SSID, intent.getValue().getStringExtra("wifi_start_connect_ssid")); - } - - /** - * Verify that we will attempt to dismiss the wrong password notification when starting a new - * connection attempt with the previous connection resulting in a wrong password error. - * - * @throws Exception - */ - @Test - public void onNewConnectionAttemptWithPreviousWrongPasswordError() throws Exception { - onWrongPasswordError(); - reset(mNotificationManager); - - mWrongPassNotifier.onNewConnectionAttempt(); - verify(mNotificationManager).cancel(any(), eq(WrongPasswordNotifier.NOTIFICATION_ID)); - } - - /** - * Verify that we don't attempt to dismiss the wrong password notification when starting a new - * connection attempt with the previous connection not resulting in a wrong password error. - * - * @throws Exception - */ - @Test - public void onNewConnectionAttemptWithoutPreviousWrongPasswordError() throws Exception { - mWrongPassNotifier.onNewConnectionAttempt(); - verify(mNotificationManager, never()).cancel(any(), anyInt()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/aware/TestUtils.java b/tests/wifitests/src/com/android/server/wifi/aware/TestUtils.java deleted file mode 100644 index 351bb9895..000000000 --- a/tests/wifitests/src/com/android/server/wifi/aware/TestUtils.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.aware; - -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.util.SparseIntArray; - -/** - * Utility methods for Wi-Fi Aware unit tests. - */ -public class TestUtils { - public static class MonitoredWifiAwareNativeApi extends WifiAwareNativeApi { - private SparseIntArray mTransactionIds = new SparseIntArray(); - - MonitoredWifiAwareNativeApi() { - super(null); // doesn't matter - mocking parent - } - - private void addTransactionId(int transactionId) { - if (transactionId == 0) { - return; // transaction ID == 0 is used as a dummy ID in several command - acceptable - } - mTransactionIds.append(transactionId, mTransactionIds.get(transactionId) + 1); - } - - public void validateUniqueTransactionIds() { - for (int i = 0; i < mTransactionIds.size(); ++i) { - if (mTransactionIds.valueAt(i) != 1) { - throw new RuntimeException("Duplicate transaction IDs -- " + mTransactionIds); - } - } - } - - public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest, - boolean notifyIdentityChange, boolean initialConfiguration, boolean isInteractive, - boolean isIdle, boolean rangingEnabled) { - addTransactionId(transactionId); - return true; - } - - public boolean disable(short transactionId) { - addTransactionId(transactionId); - return true; - } - - public boolean publish(short transactionId, byte publishId, PublishConfig publishConfig) { - addTransactionId(transactionId); - return true; - } - - public boolean subscribe(short transactionId, byte subscribeId, - SubscribeConfig subscribeConfig) { - addTransactionId(transactionId); - return true; - } - - public boolean sendMessage(short transactionId, byte pubSubId, int requestorInstanceId, - byte[] dest, byte[] message, int messageId) { - addTransactionId(transactionId); - return true; - } - - public boolean stopPublish(short transactionId, byte pubSubId) { - addTransactionId(transactionId); - return true; - } - - public boolean stopSubscribe(short transactionId, byte pubSubId) { - addTransactionId(transactionId); - return true; - } - - public boolean getCapabilities(short transactionId) { - addTransactionId(transactionId); - return true; - } - - public boolean createAwareNetworkInterface(short transactionId, String interfaceName) { - addTransactionId(transactionId); - return true; - } - - public boolean deleteAwareNetworkInterface(short transactionId, String interfaceName) { - addTransactionId(transactionId); - return true; - } - - public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType, - int channel, byte[] peer, String interfaceName, byte[] pmk, String passphrase, - boolean isOutOfBand, byte[] appInfo, Capabilities capabilities) { - addTransactionId(transactionId); - return true; - } - - public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId, - String interfaceName, byte[] pmk, String passphrase, byte[] appInfo, - boolean isOutOfBand, Capabilities capabilities) { - addTransactionId(transactionId); - return true; - } - - public boolean endDataPath(short transactionId, int ndpId) { - addTransactionId(transactionId); - return true; - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java deleted file mode 100644 index a21442f6c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java +++ /dev/null @@ -1,1972 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import static android.hardware.wifi.V1_0.NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyShort; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.Manifest; -import android.app.test.TestAlarmManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.hardware.wifi.V1_0.NanStatusType; -import android.net.ConnectivityManager; -import android.net.MacAddress; -import android.net.NetworkCapabilities; -import android.net.NetworkFactory; -import android.net.NetworkProvider; -import android.net.NetworkRequest; -import android.net.NetworkSpecifier; -import android.net.wifi.WifiManager; -import android.net.wifi.aware.AttachCallback; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.DiscoverySession; -import android.net.wifi.aware.DiscoverySessionCallback; -import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; -import android.net.wifi.aware.IWifiAwareEventCallback; -import android.net.wifi.aware.IWifiAwareManager; -import android.net.wifi.aware.PeerHandle; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.PublishDiscoverySession; -import android.net.wifi.aware.SubscribeConfig; -import android.net.wifi.aware.SubscribeDiscoverySession; -import android.net.wifi.aware.TlvBufferUtils; -import android.net.wifi.aware.WifiAwareManager; -import android.net.wifi.aware.WifiAwareNetworkInfo; -import android.net.wifi.aware.WifiAwareNetworkSpecifier; -import android.net.wifi.aware.WifiAwareSession; -import android.net.wifi.util.HexEncoding; -import android.os.Build; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; -import android.os.PowerManager; -import android.os.Process; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.AsyncChannel; -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.nio.ByteOrder; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - - -/** - * Unit test harness for WifiAwareDataPathStateManager class. - */ -@SmallTest -public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { - private static final String sAwareInterfacePrefix = "aware_data"; - private static final String TEST_PACKAGE_NAME = "com.android.somePackage"; - private static final String TEST_FEATURE_ID = "com.android.someFeature"; - - private TestLooper mMockLooper; - private Handler mMockLooperHandler; - private WifiAwareStateManager mDut; - @Mock private Clock mClock; - @Mock private WifiAwareNativeManager mMockNativeManager; - @Spy private TestUtils.MonitoredWifiAwareNativeApi mMockNative = - new TestUtils.MonitoredWifiAwareNativeApi(); - @Mock private Context mMockContext; - @Mock private ConnectivityManager mMockCm; - @Mock private NetdWrapper mMockNetdWrapper; - @Mock private WifiAwareDataPathStateManager.NetworkInterfaceWrapper mMockNetworkInterface; - @Mock private IWifiAwareEventCallback mMockCallback; - @Mock IWifiAwareDiscoverySessionCallback mMockSessionCallback; - @Mock private WifiAwareMetrics mAwareMetricsMock; - @Mock private WifiPermissionsUtil mWifiPermissionsUtil; - @Mock private WifiPermissionsWrapper mPermissionsWrapperMock; - @Mock private WifiManager mMockWifiManager; - TestAlarmManager mAlarmManager; - @Mock private PowerManager mMockPowerManager; - - @Rule - public ErrorCollector collector = new ErrorCollector(); - - /** - * Initialize mocks. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mAlarmManager = new TestAlarmManager(); - when(mMockContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - - when(mMockContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager); - when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED); - - mMockLooper = new TestLooper(); - mMockLooperHandler = new Handler(mMockLooper.getLooper()); - - when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mMockCm); - when(mMockContext.getSystemServiceName(PowerManager.class)).thenReturn( - Context.POWER_SERVICE); - when(mMockContext.getSystemService(PowerManager.class)).thenReturn(mMockPowerManager); - - // by default pretend to be an old API: i.e. allow Responders configured as *ANY*. This - // allows older (more extrensive) tests to run. - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), anyInt(), anyInt())) - .thenReturn(true); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); - - mDut = new WifiAwareStateManager(); - mDut.setNative(mMockNativeManager, mMockNative); - mDut.start(mMockContext, mMockLooper.getLooper(), mAwareMetricsMock, - mWifiPermissionsUtil, mPermissionsWrapperMock, mClock, mMockNetdWrapper); - mDut.startLate(); - mMockLooper.dispatchAll(); - - when(mMockNetworkInterface.configureAgentProperties(any(), any(), anyInt(), any(), - any())).thenReturn(true); - when(mMockNetworkInterface.isAddressUsable(any())).thenReturn(true); - - when(mMockPowerManager.isDeviceIdleMode()).thenReturn(false); - when(mMockPowerManager.isInteractive()).thenReturn(true); - - mDut.mDataPathMgr.mNetdWrapper = mMockNetdWrapper; - mDut.mDataPathMgr.mNiWrapper = mMockNetworkInterface; - } - - /** - * Post-test validation. - */ - @After - public void tearDown() throws Exception { - mMockNative.validateUniqueTransactionIds(); - } - - /** - * Validates that creating and deleting all interfaces works based on capabilities. - */ - @Test - public void testCreateDeleteAllInterfaces() throws Exception { - final int numNdis = 3; - final int failCreateInterfaceIndex = 1; - - Capabilities capabilities = new Capabilities(); - capabilities.maxNdiInterfaces = numNdis; - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<String> interfaceName = ArgumentCaptor.forClass(String.class); - InOrder inOrder = inOrder(mMockNative); - - // (1) get capabilities - mDut.queryCapabilities(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), capabilities); - mMockLooper.dispatchAll(); - - // (2) create all interfaces - mDut.createAllDataPathInterfaces(); - mMockLooper.dispatchAll(); - for (int i = 0; i < numNdis; ++i) { - inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(), - interfaceName.capture()); - collector.checkThat("interface created -- " + i, sAwareInterfacePrefix + i, - equalTo(interfaceName.getValue())); - mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - } - - // (3) delete all interfaces [one unsuccessfully] - note that will not necessarily be - // done sequentially - boolean[] done = new boolean[numNdis]; - Arrays.fill(done, false); - mDut.deleteAllDataPathInterfaces(); - mMockLooper.dispatchAll(); - for (int i = 0; i < numNdis; ++i) { - inOrder.verify(mMockNative).deleteAwareNetworkInterface(transactionId.capture(), - interfaceName.capture()); - int interfaceIndex = Integer.valueOf( - interfaceName.getValue().substring(sAwareInterfacePrefix.length())); - done[interfaceIndex] = true; - if (interfaceIndex == failCreateInterfaceIndex) { - mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), false, 0); - } else { - mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), true, 0); - } - mMockLooper.dispatchAll(); - } - for (int i = 0; i < numNdis; ++i) { - collector.checkThat("interface deleted -- " + i, done[i], equalTo(true)); - } - - // (4) create all interfaces (should get a delete for the one which couldn't delete earlier) - mDut.createAllDataPathInterfaces(); - mMockLooper.dispatchAll(); - for (int i = 0; i < numNdis; ++i) { - if (i == failCreateInterfaceIndex) { - inOrder.verify(mMockNative).deleteAwareNetworkInterface(transactionId.capture(), - interfaceName.capture()); - collector.checkThat("interface delete pre-create -- " + i, - sAwareInterfacePrefix + i, equalTo(interfaceName.getValue())); - mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - } - inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(), - interfaceName.capture()); - collector.checkThat("interface created -- " + i, sAwareInterfacePrefix + i, - equalTo(interfaceName.getValue())); - mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - } - - verifyNoMoreInteractions(mMockNative, mMockNetdWrapper); - } - - /** - * Validate that trying to specify port info on subscriber results in failure. - */ - @Test - public void testDataPathWithPortInfoOnPublisher() throws Exception { - final int clientId = 123; - final byte pubSubId = 55; - final int requestorId = 1341234; - final String passphrase = "SomeSecurePassword"; - final int ndpId = 1; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, false); - - // (1) request network - NetworkRequest nr = getSessionNetworkRequestMore(clientId, res.mSessionId, res.mPeerHandle, - null, passphrase, true, 0, 5, 6); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // (2) provide a request - mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, null); - mMockLooper.dispatchAll(); - - // do not respond/create a data-path! - verify(mMockNative, never()).respondToDataPathRequest(anyShort(), anyBoolean(), anyInt(), - anyString(), any(), anyString(), any(), anyBoolean(), any()); - } - - /** - * Validate that trying to specify invalid port info results in failure. - */ - @Test - public void testDataPathWithPortInfoInvalidPort() throws Exception { - final int clientId = 123; - final byte pubSubId = 55; - final int requestorId = 1341234; - final String passphrase = "SomeSecurePassword"; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, false); - - // (1) request network - NetworkRequest nr = getSessionNetworkRequestMore(clientId, res.mSessionId, res.mPeerHandle, - null, passphrase, false, 0, -3, 6); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // do not create a data-path! - verify(mMockNative, never()).initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(), - any(), anyString(), any(), anyString(), anyBoolean(), any(), any()); - } - - /** - * Validate that trying to specify port info without security results in failure. - */ - @Test - public void testDataPathWithPortInfoButNoSecurityOnSubscriber() throws Exception { - final int clientId = 123; - final byte pubSubId = 55; - final int requestorId = 1341234; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, false); - - // (1) request network - NetworkRequest nr = getSessionNetworkRequestMore(clientId, res.mSessionId, res.mPeerHandle, - null, null, false, 0, 10, 6); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // do not create a data-path! - verify(mMockNative, never()).initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(), - any(), anyString(), any(), anyString(), anyBoolean(), any(), any()); - } - - /** - * Validate that if the data-interfaces are deleted while a data-path is being created, the - * process will terminate. - */ - @Test - public void testDestroyNdiDuringNdpSetupResponder() throws Exception { - final int clientId = 123; - final byte pubSubId = 55; - final int requestorId = 1341234; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - final int ndpId = 3; - - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, true); - - // (1) request network - NetworkRequest nr = getSessionNetworkRequest(clientId, res.mSessionId, res.mPeerHandle, - null, null, true, 0); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // (2) delete interface(s) - mDut.deleteAllDataPathInterfaces(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).deleteAwareNetworkInterface(transactionId.capture(), - anyString()); - mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - - // (3) have responder receive request - mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, null); - mMockLooper.dispatchAll(); - - // (4) verify that responder aborts (i.e. refuses request) - inOrder.verify(mMockNative).respondToDataPathRequest(transactionId.capture(), eq(false), - eq(ndpId), eq(""), eq(null), eq(null), eq(null), eq(false), any()); - mDut.onRespondToDataPathSetupRequestResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - - verifyRequestDeclaredUnfullfillable(nr); - - // failure if there's further activity - verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNetdWrapper); - } - - /** - * Validate multiple NDPs created on a single NDI. Most importantly that the interface is - * set up on first NDP and torn down on last NDP - and not when one or the other is created or - * deleted. - * - * Procedure: - * - create NDP 1, 2, and 3 (interface up only on first) - * - delete NDP 2, 1, and 3 (interface down only on last) - */ - @Test - public void testMultipleNdpsOnSingleNdi() throws Exception { - final int clientId = 123; - final byte pubSubId = 58; - final int requestorId = 1341234; - final int ndpId = 2; - final String interfaceName = sAwareInterfacePrefix + "0"; - final int port = 23; - final byte transportProtocol = 6; - - final int[] startOrder = {0, 1, 2}; - final int[] endOrder = {1, 0, 2}; - int networkRequestId = 0; - - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<NetworkCapabilities> netCapCaptor = ArgumentCaptor.forClass( - NetworkCapabilities.class); - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback, - mMockNetdWrapper); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - NetworkRequest[] nrs = new NetworkRequest[3]; - DataPathEndPointInfo[] ress = new DataPathEndPointInfo[3]; - Messenger[] agentMessengers = new Messenger[3]; - Messenger messenger = null; - boolean first = true; - for (int i : startOrder) { - networkRequestId += 1; - byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - peerDiscoveryMac[5] = (byte) (peerDiscoveryMac[5] + i); - peerDataPathMac[5] = (byte) (peerDataPathMac[5] + i); - - // (0) initialize - ress[i] = initDataPathEndPoint(first, clientId, (byte) (pubSubId + i), - requestorId + i, peerDiscoveryMac, inOrder, inOrderM, false); - if (first) { - messenger = ress[i].mMessenger; - } - - // (1) request network - nrs[i] = getSessionNetworkRequest(clientId, ress[i].mSessionId, ress[i].mPeerHandle, - null, null, false, networkRequestId); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nrs[i]; - reqNetworkMsg.arg1 = 0; - messenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), - eq(requestorId + i), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), - eq(interfaceName), eq(null), - eq(null), eq(false), any(), any()); - - mDut.onInitiateDataPathResponseSuccess(transactionId.getValue(), ndpId + i); - mMockLooper.dispatchAll(); - - // (2) get confirmation - mDut.onDataPathConfirmNotification(ndpId + i, peerDataPathMac, true, 0, - buildTlv(port, transportProtocol, true), null); - mMockLooper.dispatchAll(); - if (first) { - inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); - inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); - - first = false; - } - inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(), any(), any(), - netCapCaptor.capture(), anyInt(), any(), anyInt()); - agentMessengers[i] = messengerCaptor.getValue(); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), - eq(false), anyLong()); - inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); - WifiAwareNetworkInfo netInfo = - (WifiAwareNetworkInfo) netCapCaptor.getValue().getTransportInfo(); - assertArrayEquals(MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getAddress(), - netInfo.getPeerIpv6Addr().getAddress()); - assertEquals(port, netInfo.getPort()); - assertEquals(transportProtocol, netInfo.getTransportProtocol()); - } - - // (3) end data-path (unless didn't get confirmation) - int index = 0; - for (int i: endOrder) { - Message endNetworkReqMsg = Message.obtain(); - endNetworkReqMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; - endNetworkReqMsg.obj = nrs[i]; - messenger.send(endNetworkReqMsg); - - Message endNetworkUsageMsg = Message.obtain(); - endNetworkUsageMsg.what = AsyncChannel.CMD_CHANNEL_DISCONNECTED; - agentMessengers[i].send(endNetworkUsageMsg); - mMockLooper.dispatchAll(); - - inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId + i)); - - mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); - mDut.onDataPathEndNotification(ndpId + i); - mMockLooper.dispatchAll(); - - if (index++ == endOrder.length - 1) { - inOrder.verify(mMockNetdWrapper).setInterfaceDown(anyString()); - } - inOrderM.verify(mAwareMetricsMock).recordNdpSessionDuration(anyLong()); - } - - verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNetdWrapper); - } - - /** - * Validate that multiple NDP requests which resolve to the same canonical request are treated - * as one. - */ - @Test - public void testMultipleIdenticalRequests() throws Exception { - final int numRequestsPre = 6; - final int numRequestsPost = 5; - final int clientId = 123; - final int ndpId = 5; - final int port = 0; - final int transportProtocol = 6; // can't specify transport protocol without port - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - final byte[] allZeros = HexEncoding.decode("000000000000".toCharArray(), false); - NetworkRequest[] nrs = new NetworkRequest[numRequestsPre + numRequestsPost + 1]; - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Messenger> agentMessengerCaptor = ArgumentCaptor.forClass(Messenger.class); - ArgumentCaptor<NetworkCapabilities> netCapCaptor = ArgumentCaptor.forClass( - NetworkCapabilities.class); - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback, - mMockNetdWrapper); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (1) initialize all clients - Messenger messenger = initOobDataPathEndPoint(true, 2, clientId, inOrder, inOrderM); - for (int i = 1; i < numRequestsPre + numRequestsPost; ++i) { - initOobDataPathEndPoint(false, 1, clientId + i, inOrder, inOrderM); - } - DataPathEndPointInfo ddepi = initDataPathEndPoint(false, - clientId + numRequestsPre + numRequestsPost, (byte) 10, 11, peerDiscoveryMac, - inOrder, inOrderM, false); - - // (2) make initial network requests (all identical under the hood) - for (int i = 0; i < numRequestsPre; ++i) { - nrs[i] = getDirectNetworkRequest(clientId + i, - WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, peerDiscoveryMac, null, - null, i); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nrs[i]; - reqNetworkMsg.arg1 = 0; - messenger.send(reqNetworkMsg); - } - mMockLooper.dispatchAll(); - - // (3) verify the start NDP HAL request - inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(0), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), - eq(sAwareInterfacePrefix + "0"), eq(null), eq(null), eq(true), any(), any()); - - // (4) unregister request #0 (the primary) - Message endNetworkReqMsg = Message.obtain(); - endNetworkReqMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; - endNetworkReqMsg.obj = nrs[0]; - messenger.send(endNetworkReqMsg); - mMockLooper.dispatchAll(); - - // (5) respond to the registration request - mDut.onInitiateDataPathResponseSuccess(transactionId.getValue(), ndpId); - mMockLooper.dispatchAll(); - - // (6) unregister request #1 - endNetworkReqMsg = Message.obtain(); - endNetworkReqMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; - endNetworkReqMsg.obj = nrs[1]; - messenger.send(endNetworkReqMsg); - mMockLooper.dispatchAll(); - - // (6.5) provide a (semi) bogus NDP Requst Indication - mostly bogus on Initiator but - // may contain the peer's TLVs (in this case it does) - mDut.onDataPathRequestNotification(0, allZeros, ndpId, - buildTlv(port, transportProtocol, true)); - - // (7) confirm the NDP creation - mDut.onDataPathConfirmNotification(ndpId, peerDataPathMac, true, 0, null, null); - mMockLooper.dispatchAll(); - - inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); - inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); - inOrder.verify(mMockCm).registerNetworkAgent(agentMessengerCaptor.capture(), any(), any(), - netCapCaptor.capture(), anyInt(), any(), anyInt()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), - eq(true), anyLong()); - inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); - WifiAwareNetworkInfo netInfo = - (WifiAwareNetworkInfo) netCapCaptor.getValue().getTransportInfo(); - assertArrayEquals(MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getAddress(), - netInfo.getPeerIpv6Addr().getAddress()); - assertEquals(port, netInfo.getPort()); - assertEquals(transportProtocol, netInfo.getTransportProtocol()); - - // (8) execute 'post' requests - for (int i = numRequestsPre; i < numRequestsPre + numRequestsPost; ++i) { - nrs[i] = getDirectNetworkRequest(clientId + i, - WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, peerDiscoveryMac, null, - null, i); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nrs[i]; - reqNetworkMsg.arg1 = 0; - messenger.send(reqNetworkMsg); - } - nrs[numRequestsPre + numRequestsPost] = getSessionNetworkRequest( - clientId + numRequestsPre + numRequestsPost, ddepi.mSessionId, ddepi.mPeerHandle, - null, null, false, 11); - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nrs[numRequestsPre + numRequestsPost]; - reqNetworkMsg.arg1 = 0; - messenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // (9) unregister all requests - for (int i = 2; i < numRequestsPre + numRequestsPost + 1; ++i) { - endNetworkReqMsg = Message.obtain(); - endNetworkReqMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; - endNetworkReqMsg.obj = nrs[i]; - messenger.send(endNetworkReqMsg); - mMockLooper.dispatchAll(); - } - - Message endNetworkUsageMsg = Message.obtain(); - endNetworkUsageMsg.what = AsyncChannel.CMD_CHANNEL_DISCONNECTED; - agentMessengerCaptor.getValue().send(endNetworkUsageMsg); - mMockLooper.dispatchAll(); - - // (10) verify that NDP torn down - inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); - - mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); - mDut.onDataPathEndNotification(ndpId); - mMockLooper.dispatchAll(); - - inOrder.verify(mMockNetdWrapper).setInterfaceDown(anyString()); - inOrderM.verify(mAwareMetricsMock).recordNdpSessionDuration(anyLong()); - - verifyNoMoreInteractions(mMockNative, mMockCm, mMockCallback, mMockSessionCallback, - mAwareMetricsMock, mMockNetdWrapper); - } - - /** - * Validate that multiple NDP requests to the same peer target different NDIs. - */ - @Test - public void testMultipleNdi() throws Exception { - final int numNdis = 5; - final int clientId = 123; - final int ndpId = 5; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<String> ifNameCaptor = ArgumentCaptor.forClass(String.class); - ArgumentCaptor<NetworkCapabilities> netCapCaptor = ArgumentCaptor.forClass( - NetworkCapabilities.class); - - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback, - mMockNetdWrapper); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (1) initialize all clients - Messenger messenger = initOobDataPathEndPoint(true, numNdis, clientId, inOrder, inOrderM); - for (int i = 1; i < numNdis + 3; ++i) { - initOobDataPathEndPoint(false, numNdis, clientId + i, inOrder, inOrderM); - } - - // (2) make N network requests: each unique - Set<String> interfaces = new HashSet<>(); - for (int i = 0; i < numNdis + 1; ++i) { - byte[] pmk = new byte[32]; - pmk[0] = (byte) i; - - NetworkRequest nr = getDirectNetworkRequest(clientId + i, - WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, peerDiscoveryMac, pmk, - null, i); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - messenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - if (i < numNdis) { - inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(0), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), - ifNameCaptor.capture(), eq(pmk), eq(null), eq(true), any(), any()); - interfaces.add(ifNameCaptor.getValue()); - - mDut.onInitiateDataPathResponseSuccess(transactionId.getValue(), ndpId + i); - mDut.onDataPathConfirmNotification(ndpId + i, peerDataPathMac, true, 0, null, null); - mMockLooper.dispatchAll(); - - inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); - inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); - inOrder.verify(mMockCm).registerNetworkAgent(any(), any(), any(), - netCapCaptor.capture(), anyInt(), any(), anyInt()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), - eq(true), anyLong()); - inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); - WifiAwareNetworkInfo netInfo = - (WifiAwareNetworkInfo) netCapCaptor.getValue().getTransportInfo(); - assertArrayEquals(MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getAddress(), - netInfo.getPeerIpv6Addr().getAddress()); - assertEquals(0, netInfo.getPort()); // uninitialized -> 0 - assertEquals(-1, netInfo.getTransportProtocol()); // uninitialized -> -1 - } else { - verifyRequestDeclaredUnfullfillable(nr); - } - } - - // verify that each interface name is unique - assertEquals("Number of unique interface names", numNdis, interfaces.size()); - - verifyNoMoreInteractions(mMockNative, mMockCm, mMockCallback, mMockSessionCallback, - mAwareMetricsMock, mMockNetdWrapper); - } - - /* - * Initiator tests - */ - - /** - * Validate the success flow of the Initiator: using session network specifier with a non-null - * PMK. - */ - @Test - public void testDataPathInitiatorMacPmkSuccess() throws Exception { - testDataPathInitiatorUtility(false, true, true, false, true, false); - } - - /** - * Validate the success flow of the Initiator: using a direct network specifier with a non-null - * peer mac and non-null PMK. - */ - @Test - public void testDataPathInitiatorDirectMacPmkSuccess() throws Exception { - testDataPathInitiatorUtility(true, true, true, false, true, false); - } - - - /** - * Validate the fail flow of the Initiator: use a session network specifier with a non-null - * PMK, but don't get a confirmation. - */ - @Test - public void testDataPathInitiatorNoConfirmationTimeoutFail() throws Exception { - testDataPathInitiatorUtility(false, true, true, false, false, false); - } - - /** - * Validate the fail flow of the Initiator: use a session network specifier with a non-null - * Passphrase, but get an immediate failure - */ - @Test - public void testDataPathInitiatorNoConfirmationHalFail() throws Exception { - testDataPathInitiatorUtility(false, true, false, true, true, true); - } - - /** - * Verify that an TLV configuration with large port/transport-protocol work correctly. - */ - @Test - public void testDataPathInitiatorNetInfoLargeValuesExp1() throws Exception { - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - String linkLocalIpv6Address = MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress(); - - testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac, - buildTlv((1 << 16) - 1, (1 << 8) - 1, true), (1 << 16) - 1, (1 << 8) - 1, - linkLocalIpv6Address, 0); - } - - /** - * Verify that an TLV configuration with large port/transport-protocol work correctly. - */ - @Test - public void testDataPathInitiatorNetInfoLargeValuesExp2() throws Exception { - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - String linkLocalIpv6Address = MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress(); - - testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac, - buildTlv(1 << 15, 1 << 7, true), 1 << 15, 1 << 7, linkLocalIpv6Address, 0); - } - - /** - * Verify that an TLV configuration with large port/transport-protocol work correctly. - */ - @Test - public void testDataPathInitiatorNetInfoLargeValuesExp3() throws Exception { - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - String linkLocalIpv6Address = MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress(); - - testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac, - buildTlv((1 << 15) - 1, (1 << 7) - 1, true), (1 << 15) - 1, (1 << 7) - 1, - linkLocalIpv6Address, 0); - } - - /** - * Verify that an TLV configuration with an IPv6 override works correctly. - */ - @Test - public void testDataPathInitiatorNetInfoIpv6Override() throws Exception { - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - final byte[] testVector = - new byte[]{0x00, 0x08, 0x00, 0x00, (byte) 0xb3, (byte) 0xe1, (byte) 0xff, - (byte) 0xfe, 0x7a, 0x2f, (byte) 0xa2}; - - testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac, - testVector, 0, -1, "fe80::b3:e1ff:fe7a:2fa2", 0); - } - - /** - * Verify that retrying address validation a 'small' number of times results in successful - * NDP setup. - */ - @Test - public void testDataPathInitiatorAddressValidationRetrySuccess() throws Exception { - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - String linkLocalIpv6Address = MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress(); - - testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac, - null, 0, -1, linkLocalIpv6Address, - WifiAwareDataPathStateManager.ADDRESS_VALIDATION_TIMEOUT_MS - / WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS - 1); - } - - /** - * Verify that retrying address validation a 'large' number of times results in failure. - */ - @Test - public void testDataPathInitiatorAddressValidationRetryFail() throws Exception { - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - String linkLocalIpv6Address = MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress(); - - testDataPathInitiatorUtilityMore(false, true, true, false, true, false, peerDataPathMac, - null, 0, -1, linkLocalIpv6Address, - WifiAwareDataPathStateManager.ADDRESS_VALIDATION_TIMEOUT_MS - / WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS + 10); - } - - /** - * Validate the fail flow of a mis-configured request: Publisher as Initiator - */ - @Test - public void testDataPathInitiatorOnPublisherError() throws Exception { - testDataPathInitiatorResponderMismatchUtility(true); - } - - /** - * Validate the fail flow of an Initiator (subscriber) with its UID set as a malicious - * attacker (i.e. mismatched to its requested client's UID). - */ - @Test - public void testDataPathInitiatorUidSetIncorrectlyError() throws Exception { - testDataPathInitiatorResponderInvalidUidUtility(false); - } - - /** - * Validate the fail flow of an Initiator (subscriber) with its package namee set as a malicious - * attacker (i.e. mismatched to its requested client's package name). - */ - @Test - public void testDataPathInitiatorPackageNameSetIncorrectlyError() throws Exception { - testDataPathInitiatorResponderInvalidPackageNameUtility(false); - } - - /* - * Responder tests - */ - - /** - * Validate the success flow of the Responder: using session network specifier with a - * PMK. - */ - @Test - public void testDataPathResonderMacPmkSuccess() throws Exception { - testDataPathResponderUtility(false, true, true, false, true); - } - - /** - * Validate the success flow of the Responder: using session network specifier with a - * Passphrase. - */ - @Test - public void testDataPathResonderMacPassphraseSuccess() throws Exception { - testDataPathResponderUtility(false, true, false, false, true); - } - - /** - * Validate the success flow of the Responder: using session network specifier with a - * Passphrase and no peer ID (i.e. 0). - */ - @Test - public void testDataPathResonderMacPassphraseNoPeerIdSuccess() throws Exception { - testDataPathResponderUtility(false, false, false, true, true); - } - - /** - * Validate the success flow of the Responder: using session network specifier with a null - * PMK/Passphrase and no peer ID (i.e. 0). - */ - @Test - public void testDataPathResonderMacOpenNoPeerIdNoPmkPassphraseSuccess() throws Exception { - testDataPathResponderUtility(false, false, false, false, true); - } - - /** - * Validate the failure flow of the Responder: using session network specifier with a - * Passphrase and no peer ID (i.e. 0) on a NON-LEGACY device. - */ - @Test - public void testDataPathResonderMacPassphraseNoPeerIdSuccessNonLegacy() throws Exception { - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), anyInt(), anyInt())) - .thenReturn(false); - testDataPathResponderUtility(false, false, false, true, true); - } - - /** - * Validate the failure flow of the Responder: using session network specifier with a null - * PMK/Passphrase and no peer ID (i.e. 0) on a NON-LEGACY device. - */ - @Test - public void testDataPathResonderMacOpenNoPeerIdNoPmkPassphraseSuccessNonLegacy() - throws Exception { - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), anyInt(), anyInt())) - .thenReturn(false); - testDataPathResponderUtility(false, false, false, false, true); - } - - /** - * Validate the success flow of the Responder: using a direct network specifier with a non-null - * peer mac and non-null PMK. - */ - @Test - public void testDataPathResonderDirectMacPmkSuccess() throws Exception { - testDataPathResponderUtility(true, true, true, false, true); - } - - /** - * Validate the success flow of the Responder: using a direct network specifier with a non-null - * peer mac and null PMK/Passphrase. - */ - @Test - public void testDataPathResonderDirectMacNoPmkPassphraseSuccess() throws Exception { - testDataPathResponderUtility(true, true, false, false, true); - } - - /** - * Validate the success flow of the Responder: using a direct network specifier with a null peer - * mac and non-null Passphrase. - */ - @Test - public void testDataPathResonderDirectNoMacPassphraseSuccess() throws Exception { - testDataPathResponderUtility(true, false, false, true, true); - } - - /** - * Validate the success flow of the Responder: using a direct network specifier with a null peer - * mac and null Pmk/Passphrase. - */ - @Test - public void testDataPathResonderDirectNoMacNoPmkPassphraseSuccess() throws Exception { - testDataPathResponderUtility(true, false, false, false, true); - } - - /** - * Validate the failure flow of the Responder: using a direct network specifier with a null peer - * mac and non-null Passphrase on a NON-LEGACY device. - */ - @Test - public void testDataPathResonderDirectNoMacPassphraseSuccessNonLegacy() throws Exception { - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), anyInt(), anyInt())) - .thenReturn(false); - testDataPathResponderUtility(true, false, false, true, true); - } - - /** - * Validate the failure flow of the Responder: using a direct network specifier with a null peer - * mac and null Pmk/Passphrase on a NON-LEGACY device. - */ - @Test - public void testDataPathResonderDirectNoMacNoPmkPassphraseSuccessNonLegacy() throws Exception { - when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), anyInt(), anyInt())) - .thenReturn(false); - testDataPathResponderUtility(true, false, false, false, true); - } - - /** - * Validate the fail flow of the Responder: use a session network specifier with a non-null - * PMK, but don't get a confirmation. - */ - @Test - public void testDataPathResponderNoConfirmationTimeoutFail() throws Exception { - testDataPathResponderUtility(false, true, true, false, false); - } - - /** - * Validate the fail flow of a mis-configured request: Subscriber as Responder - */ - @Test - public void testDataPathResponderOnSubscriberError() throws Exception { - testDataPathInitiatorResponderMismatchUtility(false); - } - - /** - * Validate the fail flow of an Initiator (subscriber) with its UID set as a malicious - * attacker (i.e. mismatched to its requested client's UID). - */ - @Test - public void testDataPathResponderUidSetIncorrectlyError() throws Exception { - testDataPathInitiatorResponderInvalidUidUtility(true); - } - - - /** - * Validate the fail flow of an Initiator (subscriber) with its package name set as a malicious - * attacker (i.e. mismatched to its requested client's package name). - */ - @Test - public void testDataPathResponderPackageNameSetIncorrectlyError() throws Exception { - testDataPathInitiatorResponderInvalidPackageNameUtility(true); - } - - /** - * Validate the TLV generation based on a test vector manually generated from spec. - */ - @Test - public void testTlvGenerationTestVectorPortTransportProtocol() { - int port = 7000; - int transportProtocol = 6; - - byte[] tlvData = WifiAwareDataPathStateManager.NetworkInformationData.buildTlv(port, - transportProtocol); - byte[] testVector = - new byte[]{0x01, 0x0d, 0x00, 0x50, 0x6f, (byte) 0x9a, 0x02, 0x00, 0x02, 0x00, 0x58, - 0x1b, 0x01, 0x01, 0x00, 0x06}; - - assertArrayEquals(testVector, tlvData); - } - - /** - * Validate the TLV parsing based on a test vector of the port + transport protocol manually - * generated from spec. - */ - @Test - public void testTlvParsingTestVectorPortTransportProtocol() { - int port = 7000; - int transportProtocol = 6; - - byte[] testVector = - new byte[]{0x01, 0x0d, 0x00, 0x50, 0x6f, (byte) 0x9a, 0x02, 0x00, 0x02, 0x00, 0x58, - 0x1b, 0x01, 0x01, 0x00, 0x06}; - - WifiAwareDataPathStateManager.NetworkInformationData.ParsedResults parsed = - WifiAwareDataPathStateManager.NetworkInformationData.parseTlv(testVector); - assertEquals(port, (int) parsed.port); - assertEquals(transportProtocol, (int) parsed.transportProtocol); - } - - /* - * Utilities - */ - - private void testDataPathInitiatorResponderMismatchUtility(boolean doPublish) throws Exception { - final int clientId = 123; - final byte pubSubId = 55; - final int ndpId = 2; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - final int requestorId = 1341234; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, doPublish); - - // (1) request network - NetworkRequest nr = getSessionNetworkRequest(clientId, res.mSessionId, res.mPeerHandle, pmk, - null, doPublish, 0); - - // corrupt the network specifier: reverse the role (so it's mis-matched) - WifiAwareNetworkSpecifier ns = - (WifiAwareNetworkSpecifier) nr.networkCapabilities.getNetworkSpecifier(); - ns = new WifiAwareNetworkSpecifier( - ns.type, - 1 - ns.role, // corruption hack - ns.clientId, - ns.sessionId, - ns.peerId, - ns.peerMac, - ns.pmk, - ns.passphrase, - 0, - 0); - nr.networkCapabilities.setNetworkSpecifier(ns); - nr.networkCapabilities.setRequestorUid(Process.myUid()); - nr.networkCapabilities.setRequestorPackageName(TEST_PACKAGE_NAME); - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // consequences of failure: - // Responder (publisher): responds with a rejection to any data-path requests - // Initiator (subscribe): doesn't initiate (i.e. no HAL requests) - verifyRequestDeclaredUnfullfillable(nr); - if (doPublish) { - // (2) get request & respond - mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, null); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false), - eq(ndpId), eq(""), eq(null), eq(null), eq(null), anyBoolean(), any()); - } - - verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNetdWrapper); - } - - private void testDataPathInitiatorResponderInvalidUidUtility(boolean doPublish) - throws Exception { - final int clientId = 123; - final byte pubSubId = 56; - final int ndpId = 2; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - final int requestorId = 1341234; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, doPublish); - - // (1) create network request - NetworkRequest nr = getSessionNetworkRequest(clientId, res.mSessionId, res.mPeerHandle, pmk, - null, doPublish, 0); - - // (2) corrupt request's UID - WifiAwareNetworkSpecifier ns = - (WifiAwareNetworkSpecifier) nr.networkCapabilities.getNetworkSpecifier(); - ns = new WifiAwareNetworkSpecifier( - ns.type, - ns.role, - ns.clientId, - ns.sessionId, - ns.peerId, - ns.peerMac, - ns.pmk, - ns.passphrase, - 0, - 0); - nr.networkCapabilities.setNetworkSpecifier(ns); - nr.networkCapabilities.setRequestorUid(0 + 1); // corruption hack - nr.networkCapabilities.setRequestorPackageName(TEST_PACKAGE_NAME); - - // (3) request network - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // consequences of failure: - // Responder (publisher): responds with a rejection to any data-path requests - // Initiator (subscribe): doesn't initiate (i.e. no HAL requests) - verifyRequestDeclaredUnfullfillable(nr); - if (doPublish) { - // (2) get request & respond - mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, null); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false), - eq(ndpId), eq(""), eq(null), eq(null), eq(null), anyBoolean(), any()); - } - - verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNetdWrapper); - } - - private void testDataPathInitiatorResponderInvalidPackageNameUtility(boolean doPublish) - throws Exception { - final int clientId = 123; - final byte pubSubId = 56; - final int ndpId = 2; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - final int requestorId = 1341234; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, doPublish); - - // (1) create network request - NetworkRequest nr = getSessionNetworkRequest(clientId, res.mSessionId, res.mPeerHandle, pmk, - null, doPublish, 0); - - // (2) corrupt request's UID - WifiAwareNetworkSpecifier ns = - (WifiAwareNetworkSpecifier) nr.networkCapabilities.getNetworkSpecifier(); - ns = new WifiAwareNetworkSpecifier( - ns.type, - ns.role, - ns.clientId, - ns.sessionId, - ns.peerId, - ns.peerMac, - ns.pmk, - ns.passphrase, - 0, - 0); - nr.networkCapabilities.setNetworkSpecifier(ns); - nr.networkCapabilities.setRequestorUid(Process.myUid()); // corruption hack - nr.networkCapabilities.setRequestorPackageName(TEST_PACKAGE_NAME + "h"); // corruption hack - - // (3) request network - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // consequences of failure: - // Responder (publisher): responds with a rejection to any data-path requests - // Initiator (subscribe): doesn't initiate (i.e. no HAL requests) - verifyRequestDeclaredUnfullfillable(nr); - if (doPublish) { - // (2) get request & respond - mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, null); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false), - eq(ndpId), eq(""), eq(null), eq(null), eq(null), anyBoolean(), any()); - } - - verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNetdWrapper); - } - - private void testDataPathInitiatorUtility(boolean useDirect, boolean provideMac, - boolean providePmk, boolean providePassphrase, boolean getConfirmation, - boolean immediateHalFailure) throws Exception { - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - String linkLocalIpv6Address = MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getHostAddress(); - - testDataPathInitiatorUtilityMore(useDirect, provideMac, providePmk, providePassphrase, - getConfirmation, immediateHalFailure, peerDataPathMac, null, 0, -1, - linkLocalIpv6Address, 0); - } - - private void testDataPathInitiatorUtilityMore(boolean useDirect, boolean provideMac, - boolean providePmk, boolean providePassphrase, boolean getConfirmation, - boolean immediateHalFailure, byte[] peerDataPathMac, byte[] peerToken, int port, - int transportProtocol, String ipv6Address, int numAddrValidationRetries) - throws Exception { - final int clientId = 123; - final byte pubSubId = 58; - final int requestorId = 1341234; - final int ndpId = 2; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - final String passphrase = "some passphrase"; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<NetworkCapabilities> netCapCaptor = ArgumentCaptor.forClass( - NetworkCapabilities.class); - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback, - mMockNetdWrapper, mMockNetworkInterface); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - if (!providePmk) { - when(mPermissionsWrapperMock.getUidPermission( - eq(Manifest.permission.NETWORK_STACK), eq(Process.myUid()))).thenReturn( - PackageManager.PERMISSION_DENIED); - } - - if (immediateHalFailure) { - when(mMockNative.initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(), any(), - any(), any(), any(), anyBoolean(), any(), any())).thenReturn(false); - - } - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, false); - - // (1) request network - NetworkRequest nr; - if (useDirect) { - nr = getDirectNetworkRequest(clientId, - WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, - provideMac ? peerDiscoveryMac : null, providePmk ? pmk : null, - providePassphrase ? passphrase : null, 0); - } else { - nr = getSessionNetworkRequest(clientId, res.mSessionId, - provideMac ? res.mPeerHandle : null, providePmk ? pmk : null, - providePassphrase ? passphrase : null, false, 0); - } - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), - eq(useDirect ? 0 : requestorId), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), - eq(sAwareInterfacePrefix + "0"), eq(providePmk ? pmk : null), - eq(providePassphrase ? passphrase : null), eq(useDirect), any(), any()); - if (immediateHalFailure) { - // short-circuit the rest of this test - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.INTERNAL_FAILURE), - eq(useDirect), anyLong()); - verifyRequestDeclaredUnfullfillable(nr); - verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock); - return; - } - - mDut.onInitiateDataPathResponseSuccess(transactionId.getValue(), ndpId); - mMockLooper.dispatchAll(); - - // (2) get confirmation OR timeout - boolean timeout = false; - if (getConfirmation) { - int numConfigureAgentPropertiesFail = 0; - if (numAddrValidationRetries > 0) { - when(mMockNetworkInterface.isAddressUsable(any())).thenReturn(false); - when(mMockNetworkInterface.configureAgentProperties(any(), any(), anyInt(), - any(), any())).thenReturn(false); - // First retry will be ConfigureAgentProperties failure. - numConfigureAgentPropertiesFail = 1; - } - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - - mDut.onDataPathConfirmNotification(ndpId, peerDataPathMac, true, 0, peerToken, null); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); - inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); - inOrder.verify(mMockNetworkInterface).configureAgentProperties(any(), any(), anyInt(), - any(), any()); - if (numAddrValidationRetries <= 0) { - inOrder.verify(mMockNetworkInterface).isAddressUsable(any()); - } - for (int i = 0; i < numAddrValidationRetries; ++i) { - if (i == numConfigureAgentPropertiesFail) { - when(mMockNetworkInterface.configureAgentProperties(any(), any(), anyInt(), - any(), any())).thenReturn(true); - } - if (i == numAddrValidationRetries - 1) { - when(mMockNetworkInterface.isAddressUsable(any())).thenReturn(true); - } - long currentTime = (i + 1L) - * WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime); - mMockLooper.moveTimeForward( - WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS + 1); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNetworkInterface).configureAgentProperties(any(), any(), - anyInt(), any(), any()); - if (i < numConfigureAgentPropertiesFail) { - continue; - } - inOrder.verify(mMockNetworkInterface).isAddressUsable(any()); - if (currentTime > WifiAwareDataPathStateManager.ADDRESS_VALIDATION_TIMEOUT_MS) { - timeout = true; - break; - } - } - if (timeout) { - verifyRequestDeclaredUnfullfillable(nr); - inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); - mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); - } else { - inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(), any(), - any(), netCapCaptor.capture(), anyInt(), any(), anyInt()); - inOrder.verify(mMockNetworkInterface).setConnected(any()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), - eq(useDirect), anyLong()); - inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); - WifiAwareNetworkInfo netInfo = - (WifiAwareNetworkInfo) netCapCaptor.getValue().getTransportInfo(); - assertEquals(ipv6Address, netInfo.getPeerIpv6Addr().getHostAddress()); - assertEquals(port, netInfo.getPort()); - assertEquals(transportProtocol, netInfo.getTransportProtocol()); - } - } else { - assertTrue(mAlarmManager.dispatch( - WifiAwareStateManager.HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG)); - mMockLooper.dispatchAll(); - verifyRequestDeclaredUnfullfillable(nr); - inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); - mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.INTERNAL_FAILURE), - eq(useDirect), anyLong()); - } - - // (3) end data-path (unless didn't get confirmation) - if (getConfirmation && !timeout) { - Message endNetworkReqMsg = Message.obtain(); - endNetworkReqMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; - endNetworkReqMsg.obj = nr; - res.mMessenger.send(endNetworkReqMsg); - - Message endNetworkUsageMsg = Message.obtain(); - endNetworkUsageMsg.what = AsyncChannel.CMD_CHANNEL_DISCONNECTED; - messengerCaptor.getValue().send(endNetworkUsageMsg); - mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); - mDut.onDataPathEndNotification(ndpId); - mMockLooper.dispatchAll(); - - inOrder.verify(mMockNetdWrapper).setInterfaceDown(anyString()); - inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); - inOrderM.verify(mAwareMetricsMock).recordNdpSessionDuration(anyLong()); - } - - verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNetdWrapper, - mMockNetworkInterface); - } - - private void testDataPathResponderUtility(boolean useDirect, boolean provideMac, - boolean providePmk, boolean providePassphrase, boolean getConfirmation) - throws Exception { - final int clientId = 123; - final byte pubSubId = 60; - final int requestorId = 1341234; - final int ndpId = 2; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - final String passphrase = "some passphrase"; - final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); - final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); - - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<NetworkCapabilities> netCapCaptor = ArgumentCaptor.forClass( - NetworkCapabilities.class); - InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback, - mMockNetdWrapper); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - boolean isLegacy = mWifiPermissionsUtil.isTargetSdkLessThan("anything", - Build.VERSION_CODES.P, 0); - - if (providePmk) { - when(mPermissionsWrapperMock.getUidPermission( - eq(Manifest.permission.NETWORK_STACK), eq(Process.myUid()))).thenReturn( - PackageManager.PERMISSION_GRANTED); - } - - // (0) initialize - DataPathEndPointInfo res = initDataPathEndPoint(true, clientId, pubSubId, requestorId, - peerDiscoveryMac, inOrder, inOrderM, true); - - // (1) request network - NetworkRequest nr; - if (useDirect) { - nr = getDirectNetworkRequest(clientId, - WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, - provideMac ? peerDiscoveryMac : null, providePmk ? pmk : null, - providePassphrase ? passphrase : null, 0); - } else { - nr = getSessionNetworkRequest(clientId, res.mSessionId, - provideMac ? res.mPeerHandle : null, providePmk ? pmk : null, - providePassphrase ? passphrase : null, true, 0); - } - - Message reqNetworkMsg = Message.obtain(); - reqNetworkMsg.what = NetworkProvider.CMD_REQUEST_NETWORK; - reqNetworkMsg.obj = nr; - reqNetworkMsg.arg1 = 0; - res.mMessenger.send(reqNetworkMsg); - mMockLooper.dispatchAll(); - - // (2) get request & respond (if legacy) - mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, null); - mMockLooper.dispatchAll(); - if (isLegacy) { - inOrder.verify(mMockNative).respondToDataPathRequest(transactionId.capture(), eq(true), - eq(ndpId), eq(sAwareInterfacePrefix + "0"), eq(providePmk ? pmk : null), - eq(providePassphrase ? passphrase : null), eq(null), eq(useDirect), any()); - mDut.onRespondToDataPathSetupRequestResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - - // (3) get confirmation OR timeout - if (getConfirmation) { - mDut.onDataPathConfirmNotification(ndpId, peerDataPathMac, true, 0, null, null); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); - inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); - inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(), any(), - any(), netCapCaptor.capture(), anyInt(), any(), anyInt()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), - eq(useDirect), anyLong()); - inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); - WifiAwareNetworkInfo netInfo = - (WifiAwareNetworkInfo) netCapCaptor.getValue().getTransportInfo(); - assertArrayEquals(MacAddress.fromBytes( - peerDataPathMac).getLinkLocalIpv6FromEui48Mac().getAddress(), - netInfo.getPeerIpv6Addr().getAddress()); - assertEquals(0, netInfo.getPort()); - assertEquals(-1, netInfo.getTransportProtocol()); - } else { - assertTrue(mAlarmManager.dispatch( - WifiAwareStateManager.HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG)); - mMockLooper.dispatchAll(); - verifyRequestDeclaredUnfullfillable(nr); - inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); - mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus( - eq(NanStatusType.INTERNAL_FAILURE), eq(useDirect), anyLong()); - } - - // (4) end data-path (unless didn't get confirmation) - if (getConfirmation) { - Message endNetworkMsg = Message.obtain(); - endNetworkMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; - endNetworkMsg.obj = nr; - res.mMessenger.send(endNetworkMsg); - - Message endNetworkUsageMsg = Message.obtain(); - endNetworkUsageMsg.what = AsyncChannel.CMD_CHANNEL_DISCONNECTED; - messengerCaptor.getValue().send(endNetworkUsageMsg); - - mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); - mDut.onDataPathEndNotification(ndpId); - mMockLooper.dispatchAll(); - - inOrder.verify(mMockNetdWrapper).setInterfaceDown(anyString()); - inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); - inOrderM.verify(mAwareMetricsMock).recordNdpSessionDuration(anyLong()); - } - } else { - verifyRequestDeclaredUnfullfillable(nr); - inOrder.verify(mMockNative).respondToDataPathRequest(transactionId.capture(), eq(false), - eq(ndpId), eq(""), eq(null), eq(null), eq(null), eq(false), any()); - mDut.onRespondToDataPathSetupRequestResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - } - - verifyNoMoreInteractions(mMockNative, mMockCm, mAwareMetricsMock, mMockNetdWrapper); - } - - private NetworkRequest getSessionNetworkRequest(int clientId, int sessionId, - PeerHandle peerHandle, byte[] pmk, String passphrase, boolean doPublish, int requestId) - throws Exception { - return getSessionNetworkRequestMore(clientId, sessionId, peerHandle, pmk, passphrase, - doPublish, requestId, 0, -1); - } - - private NetworkRequest getSessionNetworkRequestMore(int clientId, int sessionId, - PeerHandle peerHandle, byte[] pmk, String passphrase, boolean doPublish, int requestId, - int port, int transportProtocol) - throws Exception { - final IWifiAwareManager mockAwareService = mock(IWifiAwareManager.class); - final WifiAwareManager mgr = new WifiAwareManager(mMockContext, mockAwareService); - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - final PublishConfig publishConfig = new PublishConfig.Builder().build(); - final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( - WifiAwareSession.class); - ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor - .forClass(IWifiAwareEventCallback.class); - ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor - .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<DiscoverySession> discoverySession = ArgumentCaptor - .forClass(DiscoverySession.class); - - AttachCallback mockCallback = mock(AttachCallback.class); - DiscoverySessionCallback mockSessionCallback = mock( - DiscoverySessionCallback.class); - - InOrder inOrderS = inOrder(mockAwareService, mockCallback, mockSessionCallback); - - mgr.attach(mMockLooperHandler, configRequest, mockCallback, null); - inOrderS.verify(mockAwareService).connect(any(), any(), any(), - clientProxyCallback.capture(), eq(configRequest), eq(false)); - IWifiAwareEventCallback iwaec = clientProxyCallback.getValue(); - iwaec.onConnectSuccess(clientId); - mMockLooper.dispatchAll(); - inOrderS.verify(mockCallback).onAttached(sessionCaptor.capture()); - if (doPublish) { - sessionCaptor.getValue().publish(publishConfig, mockSessionCallback, - mMockLooperHandler); - inOrderS.verify(mockAwareService).publish(any(), any(), eq(clientId), eq(publishConfig), - sessionProxyCallback.capture()); - } else { - sessionCaptor.getValue().subscribe(subscribeConfig, mockSessionCallback, - mMockLooperHandler); - inOrderS.verify(mockAwareService).subscribe(any(), any(), eq(clientId), - eq(subscribeConfig), sessionProxyCallback.capture()); - } - sessionProxyCallback.getValue().onSessionStarted(sessionId); - mMockLooper.dispatchAll(); - if (doPublish) { - inOrderS.verify(mockSessionCallback).onPublishStarted( - (PublishDiscoverySession) discoverySession.capture()); - } else { - inOrderS.verify(mockSessionCallback).onSubscribeStarted( - (SubscribeDiscoverySession) discoverySession.capture()); - } - - NetworkSpecifier ns; - if (pmk == null && passphrase == null) { - ns = createNetworkSpecifier(clientId, - doPublish ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER - : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, sessionId, - peerHandle, null, null, port, transportProtocol); - } else if (passphrase == null) { - ns = createNetworkSpecifier(clientId, - doPublish ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER - : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, sessionId, - peerHandle, pmk, null, port, transportProtocol); - } else { - ns = createNetworkSpecifier(clientId, - doPublish ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER - : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, sessionId, - peerHandle, null, passphrase, port, transportProtocol); - } - - NetworkCapabilities nc = new NetworkCapabilities(); - nc.clearAll(); - nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN).addCapability( - NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - nc.setNetworkSpecifier(ns); - nc.setLinkUpstreamBandwidthKbps(1); - nc.setLinkDownstreamBandwidthKbps(1); - nc.setSignalStrength(1); - nc.setRequestorUid(Process.myUid()); - nc.setRequestorPackageName(TEST_PACKAGE_NAME); - - return new NetworkRequest(nc, 0, requestId, NetworkRequest.Type.REQUEST); - } - - private NetworkRequest getDirectNetworkRequest(int clientId, int role, byte[] peer, - byte[] pmk, String passphrase, int requestId) throws Exception { - return getDirectNetworkRequestMore(clientId, role, peer, pmk, passphrase, requestId, 0, -1); - } - - private NetworkRequest getDirectNetworkRequestMore(int clientId, int role, byte[] peer, - byte[] pmk, String passphrase, int requestId, int port, int transportProtocol) - throws Exception { - final IWifiAwareManager mockAwareService = mock(IWifiAwareManager.class); - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - final WifiAwareManager mgr = new WifiAwareManager(mMockContext, mockAwareService); - - ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( - WifiAwareSession.class); - ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor - .forClass(IWifiAwareEventCallback.class); - - AttachCallback mockCallback = mock(AttachCallback.class); - - mgr.attach(mMockLooperHandler, configRequest, mockCallback, null); - verify(mockAwareService).connect(any(), any(), any(), - clientProxyCallback.capture(), eq(configRequest), eq(false)); - clientProxyCallback.getValue().onConnectSuccess(clientId); - mMockLooper.dispatchAll(); - verify(mockCallback).onAttached(sessionCaptor.capture()); - - NetworkSpecifier ns; - if (pmk == null && passphrase == null) { - ns = createNetworkSpecifier(clientId, role, peer, null, null, port, transportProtocol); - } else if (passphrase == null) { - ns = createNetworkSpecifier(clientId, role, peer, pmk, null, port, transportProtocol); - } else { - ns = createNetworkSpecifier(clientId, role, peer, null, passphrase, port, - transportProtocol); - } - NetworkCapabilities nc = new NetworkCapabilities(); - nc.clearAll(); - nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); - nc.setNetworkSpecifier(ns); - nc.setLinkUpstreamBandwidthKbps(1); - nc.setLinkDownstreamBandwidthKbps(1); - nc.setSignalStrength(1); - nc.setRequestorUid(Process.myUid()); - nc.setRequestorPackageName(TEST_PACKAGE_NAME); - - return new NetworkRequest(nc, 0, requestId, NetworkRequest.Type.REQUEST); - } - - private DataPathEndPointInfo initDataPathEndPoint(boolean isFirstIteration, int clientId, - byte pubSubId, int requestorId, byte[] peerDiscoveryMac, InOrder inOrder, - InOrder inOrderM, boolean doPublish) - throws Exception { - final String someMsg = "some arbitrary message from peer"; - final PublishConfig publishConfig = new PublishConfig.Builder().build(); - final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - - Messenger messenger = initOobDataPathEndPoint(isFirstIteration, 1, clientId, inOrder, - inOrderM); - - if (doPublish) { - mDut.publish(clientId, publishConfig, mMockSessionCallback); - } else { - mDut.subscribe(clientId, subscribeConfig, mMockSessionCallback); - } - mMockLooper.dispatchAll(); - if (doPublish) { - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - } else { - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - } - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), doPublish, pubSubId); - mMockLooper.dispatchAll(); - inOrder.verify(mMockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(Process.myUid()), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(Process.myUid(), - NanStatusType.SUCCESS, doPublish); - - mDut.onMessageReceivedNotification(pubSubId, requestorId, peerDiscoveryMac, - someMsg.getBytes()); - mMockLooper.dispatchAll(); - inOrder.verify(mMockSessionCallback).onMessageReceived(peerIdCaptor.capture(), - eq(someMsg.getBytes())); - - return new DataPathEndPointInfo(sessionId.getValue(), peerIdCaptor.getValue(), - isFirstIteration ? messenger : null); - } - - private Messenger initOobDataPathEndPoint(boolean startUpSequence, - int maxNdiInterfaces, int clientId, InOrder inOrder, InOrder inOrderM) - throws Exception { - final int pid = 2000; - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); - ArgumentCaptor<NetworkProvider> networkProviderCaptor = - ArgumentCaptor.forClass(NetworkProvider.class); - ArgumentCaptor<String> strCaptor = ArgumentCaptor.forClass(String.class); - - Capabilities capabilities = new Capabilities(); - capabilities.maxNdiInterfaces = maxNdiInterfaces; - - if (startUpSequence) { - // (0) start/registrations - inOrder.verify(mMockCm).registerNetworkProvider(networkProviderCaptor.capture()); - collector.checkThat("factory name", "WIFI_AWARE_FACTORY", - equalTo(networkProviderCaptor.getValue().getName())); - - // (1) get capabilities - mDut.queryCapabilities(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), capabilities); - mMockLooper.dispatchAll(); - - // (2) enable usage - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - } - - // (3) create client - mDut.connect(clientId, Process.myUid(), pid, TEST_PACKAGE_NAME, TEST_FEATURE_ID, - mMockCallback, configRequest, false); - mMockLooper.dispatchAll(); - - if (startUpSequence) { - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - } - - inOrder.verify(mMockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(Process.myUid()), eq(false), - any()); - - if (startUpSequence) { - for (int i = 0; i < maxNdiInterfaces; ++i) { - inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(), - strCaptor.capture()); - collector.checkThat("interface created -- " + i, sAwareInterfacePrefix + i, - equalTo(strCaptor.getValue())); - mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0); - mMockLooper.dispatchAll(); - } - Messenger messenger = networkProviderCaptor.getValue().getMessenger(); - return messenger; - } - - return null; - } - - /** - * Copy of DiscoverySession.createNetworkSpecifier - but without any checks! Allows creating - * network requests which may not be valid (e.g. for the API level). - */ - public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId, - PeerHandle peerHandle, byte[] pmk, String passphrase, int port, int transportProtocol) { - return new WifiAwareNetworkSpecifier( - (peerHandle == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER - : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB, - role, - clientId, - sessionId, - peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID - null, // peerMac (not used in this method) - pmk, - passphrase, - port, - transportProtocol); - } - - /** - * Copy of WifiAwareSession.createNetworkSpecifier - but without any checks! Allows creating - * network requests which may not be valid (e.g. for the API level). - */ - private NetworkSpecifier createNetworkSpecifier(int clientId, int role, byte[] peer, byte[] pmk, - String passphrase, int port, int transportProtocol) { - return new WifiAwareNetworkSpecifier( - (peer == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER - : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB, - role, - clientId, - 0, // 0 is an invalid session ID - 0, // 0 is an invalid peer ID - peer, - pmk, - passphrase, - port, - transportProtocol); - } - - private static class DataPathEndPointInfo { - int mSessionId; - PeerHandle mPeerHandle; - Messenger mMessenger; - - DataPathEndPointInfo(int sessionId, int peerId, Messenger messenger) { - mSessionId = sessionId; - mPeerHandle = new PeerHandle(peerId); - mMessenger = messenger; - } - } - - /** - * Verify that declareNetworkRequestUnfulfillable was called. - */ - private void verifyRequestDeclaredUnfullfillable(NetworkRequest request) throws Exception { - mMockLooper.dispatchAll(); - verify(mMockCm, atLeastOnce()).declareNetworkRequestUnfulfillable(any()); - } - - // copy of the method in WifiAwareDataPathStateManager - but without error checking (so we can - // construct invalid TLVs for testing). - private static byte[] buildTlv(int port, int transportProtocol, boolean includeGarbageTlv) { - if (port == 0 && transportProtocol == -1) { - return null; - } - - TlvBufferUtils.TlvConstructor tlvc = new TlvBufferUtils.TlvConstructor(1, 2); - tlvc.setByteOrder(ByteOrder.LITTLE_ENDIAN); - tlvc.allocate(30); // safe size for now - - tlvc.putRawByteArray(WifiAwareDataPathStateManager.NetworkInformationData.WFA_OUI); - tlvc.putRawByte((byte) WifiAwareDataPathStateManager.NetworkInformationData - .GENERIC_SERVICE_PROTOCOL_TYPE); - - if (port != 0) { - tlvc.putShort(WifiAwareDataPathStateManager.NetworkInformationData.SUB_TYPE_PORT, - (short) port); - } - if (transportProtocol != -1) { - tlvc.putByte(WifiAwareDataPathStateManager.NetworkInformationData - .SUB_TYPE_TRANSPORT_PROTOCOL, (byte) transportProtocol); - } - if (includeGarbageTlv) { - tlvc.putShort(55, (short) -1298); - } - - byte[] subTypes = tlvc.getArray(); - - tlvc.allocate(30); - tlvc.putByteArray(WifiAwareDataPathStateManager.NetworkInformationData.SERVICE_INFO_TYPE, - subTypes); - if (includeGarbageTlv) { - tlvc.putInt(78, 44); - } - - return tlvc.getArray(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java deleted file mode 100644 index 824a3e54c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.aware; - -import static com.android.server.wifi.aware.WifiAwareMetrics.addNanHalStatusToHistogram; -import static com.android.server.wifi.aware.WifiAwareMetrics.histogramToProtoArray; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.Mockito.when; - -import android.app.AppOpsManager; -import android.content.Context; -import android.hardware.wifi.V1_0.NanStatusType; -import android.net.wifi.aware.WifiAwareNetworkSpecifier; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.MetricsUtils; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.HashMap; -import java.util.Map; - -/** - * Unit test harness for WifiAwareMetrics - */ -@SmallTest -public class WifiAwareMetricsTest extends WifiBaseTest { - @Mock Clock mClock; - @Mock private Context mMockContext; - @Mock private AppOpsManager mMockAppOpsManager; - @Mock private WifiPermissionsUtil mWifiPermissionsUtil; - @Rule public ErrorCollector collector = new ErrorCollector(); - - private WifiAwareMetrics mDut; - - // Histogram definition: start[i] = b + p * m^i with s sub-buckets, i=0,...,n-1 - - /** - * Histogram of following buckets, start[i] = 0 + 1 * 10^i with 9 sub-buckets, i=0,...,5 - * 1 - 10: 9 sub-buckets each of width 1 - * 10 - 100: 10 - * 100 - 10e3: 10^2 - * 10e3 - 10e4: 10^3 - * 10e4 - 10e5: 10^4 - * 10e5 - 10e6: 10^5 - */ - private static final MetricsUtils.LogHistParms HIST1 = new MetricsUtils.LogHistParms(0, 1, - 10, 9, 6); - - /** - * Histogram of following buckets, start[i] = -20 + 2 * 5^i with 40 sub-buckets, i=0,...,2 - * -18 - -10: 40 sub-bucket each of width 0.2 - * -10 - 30: 1 - * 30 - 230: 5 - */ - private static final MetricsUtils.LogHistParms HIST2 = new MetricsUtils.LogHistParms(-20, 2, - 5, 40, 3); - - // Linear histogram of following buckets: - // <10 - // [10, 30) - // [30, 60) - // [60, 100) - // >100 - private static final int[] HIST_LINEAR = { 10, 30, 60, 100 }; - - /** - * Pre-test configuration. Initialize and install mocks. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOpsManager); - setTime(0); - - mDut = new WifiAwareMetrics(mClock); - } - - /** - * Validates that recordEnableUsage() and recordDisableUsage() record valid metrics. - */ - @Test - public void testEnableDisableUsageMetrics() { - WifiMetricsProto.WifiAwareLog log; - - // create 2 records - setTime(5); - mDut.recordEnableUsage(); - setTime(10); - mDut.recordDisableUsage(); - setTime(11); - mDut.recordEnableUsage(); - setTime(12); - mDut.recordDisableUsage(); - - setTime(14); - log = mDut.consolidateProto(); - collector.checkThat(countAllHistogramSamples(log.histogramAwareAvailableDurationMs), - equalTo(2)); - validateProtoHistBucket("Duration[0] #1", log.histogramAwareAvailableDurationMs[0], 1, 2, - 1); - validateProtoHistBucket("Duration[1] #1", log.histogramAwareAvailableDurationMs[1], 5, 6, - 1); - collector.checkThat(log.availableTimeMs, equalTo(6L)); - - // create another partial record - setTime(15); - mDut.recordEnableUsage(); - - setTime(17); - log = mDut.consolidateProto(); - collector.checkThat(countAllHistogramSamples(log.histogramAwareAvailableDurationMs), - equalTo(2)); - validateProtoHistBucket("Duration[0] #2", log.histogramAwareAvailableDurationMs[0], 1, 2, - 1); - validateProtoHistBucket("Duration[1] #2", log.histogramAwareAvailableDurationMs[1], 5, 6, - 1); - collector.checkThat(log.availableTimeMs, equalTo(8L)); // the partial record of 2ms - - - // clear and continue that partial record (verify completed) - mDut.clear(); - setTime(23); - mDut.recordDisableUsage(); - - log = mDut.consolidateProto(); - collector.checkThat(countAllHistogramSamples(log.histogramAwareAvailableDurationMs), - equalTo(1)); - validateProtoHistBucket("Duration[0] #3", log.histogramAwareAvailableDurationMs[0], 8, 9, - 1); - collector.checkThat(log.availableTimeMs, equalTo(6L)); // the remnant record of 6ms - - // clear and verify empty records - mDut.clear(); - log = mDut.consolidateProto(); - collector.checkThat(countAllHistogramSamples(log.histogramAwareAvailableDurationMs), - equalTo(0)); - } - - /** - * Validates that recordEnableAware() and recordDisableAware() record valid metrics. - */ - @Test - public void testEnableDisableAwareMetrics() { - WifiMetricsProto.WifiAwareLog log; - - // create 2 records - setTime(5); - mDut.recordEnableAware(); - setTime(10); - mDut.recordDisableAware(); - setTime(11); - mDut.recordEnableAware(); - setTime(12); - mDut.recordDisableAware(); - - setTime(14); - log = mDut.consolidateProto(); - collector.checkThat(countAllHistogramSamples(log.histogramAwareEnabledDurationMs), - equalTo(2)); - validateProtoHistBucket("Duration[0] #1", log.histogramAwareEnabledDurationMs[0], 1, 2, - 1); - validateProtoHistBucket("Duration[1] #1", log.histogramAwareEnabledDurationMs[1], 5, 6, - 1); - collector.checkThat(log.enabledTimeMs, equalTo(6L)); - - // create another partial record - setTime(15); - mDut.recordEnableAware(); - - setTime(17); - log = mDut.consolidateProto(); - collector.checkThat(countAllHistogramSamples(log.histogramAwareEnabledDurationMs), - equalTo(2)); - validateProtoHistBucket("Duration[0] #2", log.histogramAwareEnabledDurationMs[0], 1, 2, - 1); - validateProtoHistBucket("Duration[1] #2", log.histogramAwareEnabledDurationMs[1], 5, 6, - 1); - collector.checkThat(log.enabledTimeMs, equalTo(8L)); // the partial record of 2ms - - - // clear and continue that partial record (verify completed) - mDut.clear(); - setTime(23); - mDut.recordDisableAware(); - - log = mDut.consolidateProto(); - collector.checkThat(countAllHistogramSamples(log.histogramAwareEnabledDurationMs), - equalTo(1)); - validateProtoHistBucket("Duration[0] #3", log.histogramAwareEnabledDurationMs[0], 8, 9, - 1); - collector.checkThat(log.enabledTimeMs, equalTo(6L)); // the remnant record of 6ms - - // clear and verify empty records - mDut.clear(); - log = mDut.consolidateProto(); - collector.checkThat(countAllHistogramSamples(log.histogramAwareEnabledDurationMs), - equalTo(0)); - } - - @Test - public void testAttachSessionMetrics() { - final int uid1 = 1005; - final int uid2 = 1006; - final SparseArray<WifiAwareClientState> clients = new SparseArray<>(); - WifiMetricsProto.WifiAwareLog log; - - setTime(5); - - // uid1: session 1 - clients.put(10, - new WifiAwareClientState(mMockContext, 10, uid1, 0, null, null, null, null, false, - mClock.getElapsedSinceBootMillis(), mWifiPermissionsUtil)); - mDut.recordAttachSession(uid1, false, clients); - - // uid1: session 2 - clients.put(11, - new WifiAwareClientState(mMockContext, 11, uid1, 0, null, null, null, null, false, - mClock.getElapsedSinceBootMillis(), mWifiPermissionsUtil)); - mDut.recordAttachSession(uid1, false, clients); - - // uid2: session 1 - clients.put(12, - new WifiAwareClientState(mMockContext, 12, uid2, 0, null, null, null, null, false, - mClock.getElapsedSinceBootMillis(), mWifiPermissionsUtil)); - mDut.recordAttachSession(uid2, false, clients); - - // uid2: session 2 - clients.put(13, - new WifiAwareClientState(mMockContext, 13, uid2, 0, null, null, null, null, true, - mClock.getElapsedSinceBootMillis(), mWifiPermissionsUtil)); - mDut.recordAttachSession(uid2, true, clients); - - // uid2: delete session 1 - setTime(10); - mDut.recordAttachSessionDuration(clients.get(12).getCreationTime()); - clients.delete(12); - - // uid2: delete session 2 - setTime(15); - mDut.recordAttachSessionDuration(clients.get(13).getCreationTime()); - clients.delete(13); - - // uid2: session 3 - clients.put(14, - new WifiAwareClientState(mMockContext, 14, uid2, 0, null, null, null, null, false, - mClock.getElapsedSinceBootMillis(), mWifiPermissionsUtil)); - mDut.recordAttachSession(uid2, false, clients); - - // a few failures - mDut.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); - mDut.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); - mDut.recordAttachStatus(-5); // invalid - - // verify - log = mDut.consolidateProto(); - - collector.checkThat("numApps", log.numApps, equalTo(2)); - collector.checkThat("numAppsUsingIdentityCallback", log.numAppsUsingIdentityCallback, - equalTo(1)); - collector.checkThat("maxConcurrentAttachSessionsInApp", - log.maxConcurrentAttachSessionsInApp, equalTo(2)); - collector.checkThat("histogramAttachSessionStatus.length", - log.histogramAttachSessionStatus.length, equalTo(3)); // 3 buckets - validateNanStatusProtoHistBucket("Bucket[SUCCESS]", - log.histogramAttachSessionStatus[0], - WifiMetricsProto.WifiAwareLog.SUCCESS, 5); - validateNanStatusProtoHistBucket("Bucket[INTERNAL_FAILURE]", - log.histogramAttachSessionStatus[1], - WifiMetricsProto.WifiAwareLog.INTERNAL_FAILURE, 2); - validateNanStatusProtoHistBucket("Bucket[UNKNOWN_HAL_STATUS]", - log.histogramAttachSessionStatus[2], - WifiMetricsProto.WifiAwareLog.UNKNOWN_HAL_STATUS, 1); - collector.checkThat("histogramAttachDurationMs.length", - log.histogramAttachDurationMs.length, equalTo(2)); - validateProtoHistBucket("Duration[0]", log.histogramAttachDurationMs[0], 5, 6, 1); - validateProtoHistBucket("Duration[1]", log.histogramAttachDurationMs[1], 10, 20, 1); - } - - @Test - public void testDiscoverySessionMetrics() { - final int uid1 = 1005; - final int uid2 = 1006; - final int uid3 = 1007; - final SparseArray<WifiAwareClientState> clients = new SparseArray<>(); - WifiMetricsProto.WifiAwareLog log; - - setTime(5); - WifiAwareClientState client1 = new WifiAwareClientState(mMockContext, 10, uid1, 0, null, - null, null, null, false, 0, mWifiPermissionsUtil); - WifiAwareClientState client2 = new WifiAwareClientState(mMockContext, 11, uid2, 0, null, - null, null, null, false, 0, mWifiPermissionsUtil); - WifiAwareClientState client3 = new WifiAwareClientState(mMockContext, 12, uid3, 0, null, - null, null, null, false, 0, mWifiPermissionsUtil); - clients.put(10, client1); - clients.put(11, client2); - clients.put(12, client3); - - // uid1: publish session 1 - client1.addSession(new WifiAwareDiscoverySessionState(null, 100, (byte) 0, null, true, - false, mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySession(uid1, clients); - mDut.recordDiscoveryStatus(uid1, NanStatusType.SUCCESS, true); - - // uid1: publish session 2 - client1.addSession(new WifiAwareDiscoverySessionState(null, 101, (byte) 0, null, true, - false, mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySession(uid1, clients); - mDut.recordDiscoveryStatus(uid1, NanStatusType.SUCCESS, true); - - // uid3: publish session 3 with ranging - client3.addSession(new WifiAwareDiscoverySessionState(null, 111, (byte) 0, null, true, - true, mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySessionWithRanging(uid3, false, -1, -1, clients); - mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, true); - - // uid2: subscribe session 1 - client2.addSession(new WifiAwareDiscoverySessionState(null, 102, (byte) 0, null, false, - false, mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySession(uid2, clients); - mDut.recordDiscoveryStatus(uid2, NanStatusType.SUCCESS, false); - - // uid2: publish session 2 - client2.addSession(new WifiAwareDiscoverySessionState(null, 103, (byte) 0, null, true, - false, mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySession(uid2, clients); - mDut.recordDiscoveryStatus(uid2, NanStatusType.SUCCESS, false); - - // uid3: subscribe session 3 with ranging: min - client3.addSession(new WifiAwareDiscoverySessionState(null, 112, (byte) 0, null, false, - true, mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySessionWithRanging(uid3, true, 10, -1, clients); - mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); - - // uid3: subscribe session 3 with ranging: max - client3.addSession(new WifiAwareDiscoverySessionState(null, 113, (byte) 0, null, false, - true, mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySessionWithRanging(uid3, true, -1, 50, clients); - mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); - - // uid3: subscribe session 3 with ranging: minmax - client3.addSession(new WifiAwareDiscoverySessionState(null, 114, (byte) 0, null, false, - true, mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySessionWithRanging(uid3, true, 0, 110, clients); - mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); - - // uid1: delete session 1 - setTime(10); - mDut.recordDiscoverySessionDuration(client1.getSession(100).getCreationTime(), - client1.getSession(100).isPublishSession()); - client1.removeSession(100); - - // uid2: delete session 1 - setTime(15); - mDut.recordDiscoverySessionDuration(client2.getSession(102).getCreationTime(), - client2.getSession(102).isPublishSession()); - client2.removeSession(102); - - // uid2: subscribe session 3 - mDut.recordDiscoverySession(uid2, clients); - client2.addSession(new WifiAwareDiscoverySessionState(null, 104, (byte) 0, null, false, - false, mClock.getElapsedSinceBootMillis())); - - // a few failures - mDut.recordDiscoveryStatus(uid1, NanStatusType.INTERNAL_FAILURE, true); - mDut.recordDiscoveryStatus(uid2, NanStatusType.INTERNAL_FAILURE, false); - mDut.recordDiscoveryStatus(uid2, NanStatusType.NO_RESOURCES_AVAILABLE, false); - mDut.recordAttachStatus(-5); // invalid - - // verify - log = mDut.consolidateProto(); - - collector.checkThat("maxConcurrentPublishInApp", log.maxConcurrentPublishInApp, equalTo(2)); - collector.checkThat("maxConcurrentSubscribeInApp", log.maxConcurrentSubscribeInApp, - equalTo(3)); - collector.checkThat("maxConcurrentDiscoverySessionsInApp", - log.maxConcurrentDiscoverySessionsInApp, equalTo(4)); - collector.checkThat("maxConcurrentPublishInSystem", log.maxConcurrentPublishInSystem, - equalTo(4)); - collector.checkThat("maxConcurrentSubscribeInSystem", log.maxConcurrentSubscribeInSystem, - equalTo(4)); - collector.checkThat("maxConcurrentDiscoverySessionsInSystem", - log.maxConcurrentDiscoverySessionsInSystem, equalTo(8)); - collector.checkThat("histogramPublishStatus.length", - log.histogramPublishStatus.length, equalTo(2)); // 2 buckets - validateNanStatusProtoHistBucket("Bucket[SUCCESS]", - log.histogramPublishStatus[0], - WifiMetricsProto.WifiAwareLog.SUCCESS, 3); - validateNanStatusProtoHistBucket("Bucket[INTERNAL_FAILURE]", - log.histogramPublishStatus[1], - WifiMetricsProto.WifiAwareLog.INTERNAL_FAILURE, 1); - collector.checkThat("histogramSubscribeStatus.length", - log.histogramSubscribeStatus.length, equalTo(3)); // 3 buckets - validateNanStatusProtoHistBucket("Bucket[SUCCESS]", - log.histogramSubscribeStatus[0], - WifiMetricsProto.WifiAwareLog.SUCCESS, 5); - validateNanStatusProtoHistBucket("Bucket[INTERNAL_FAILURE]", - log.histogramSubscribeStatus[1], - WifiMetricsProto.WifiAwareLog.INTERNAL_FAILURE, 1); - validateNanStatusProtoHistBucket("Bucket[NO_RESOURCES_AVAILABLE]", - log.histogramSubscribeStatus[2], - WifiMetricsProto.WifiAwareLog.NO_RESOURCES_AVAILABLE, 1); - collector.checkThat("numAppsWithDiscoverySessionFailureOutOfResources", - log.numAppsWithDiscoverySessionFailureOutOfResources, equalTo(1)); - validateProtoHistBucket("Publish Duration[0]", log.histogramPublishSessionDurationMs[0], 5, - 6, 1); - validateProtoHistBucket("Subscribe Duration[0]", log.histogramSubscribeSessionDurationMs[0], - 10, 20, 1); - - collector.checkThat("maxConcurrentPublishWithRangingInApp", - log.maxConcurrentPublishWithRangingInApp, equalTo(1)); - collector.checkThat("maxConcurrentSubscribeWithRangingInApp", - log.maxConcurrentSubscribeWithRangingInApp, equalTo(3)); - collector.checkThat("maxConcurrentPublishWithRangingInSystem", - log.maxConcurrentPublishWithRangingInSystem, equalTo(1)); - collector.checkThat("maxConcurrentSubscribeWithRangingInSystem", - log.maxConcurrentSubscribeWithRangingInSystem, equalTo(3)); - collector.checkThat("numSubscribesWithRanging", log.numSubscribesWithRanging, equalTo(3)); - collector.checkThat("histogramSubscribeGeofenceMin.length", - log.histogramSubscribeGeofenceMin.length, equalTo(2)); - collector.checkThat("histogramSubscribeGeofenceMax.length", - log.histogramSubscribeGeofenceMax.length, equalTo(2)); - validateProtoHistBucket("histogramSubscribeGeofenceMin[0]", - log.histogramSubscribeGeofenceMin[0], Integer.MIN_VALUE, 10, 1); - validateProtoHistBucket("histogramSubscribeGeofenceMin[1]", - log.histogramSubscribeGeofenceMin[1], 10, 30, 1); - validateProtoHistBucket("histogramSubscribeGeofenceMax[0]", - log.histogramSubscribeGeofenceMax[0], 30, 60, 1); - validateProtoHistBucket("histogramSubscribeGeofenceMax[1]", - log.histogramSubscribeGeofenceMax[1], 100, Integer.MAX_VALUE, 1); - } - - /** - * Validate the data-path (NDP & NDI) metrics. - */ - @Test - public void testDataPathMetrics() { - final int uid1 = 1005; - final String package1 = "com.test1"; - final int uid2 = 1006; - final String package2 = "com.test2"; - final String ndi0 = "aware_data0"; - final String ndi1 = "aware_data1"; - Map<WifiAwareNetworkSpecifier, WifiAwareDataPathStateManager.AwareNetworkRequestInformation> - networkRequestCache = new HashMap<>(); - WifiMetricsProto.WifiAwareLog log; - - setTime(5); - - // uid1: ndp (non-secure) on ndi0 - addNetworkInfoToCache(networkRequestCache, 10, uid1, package1, ndi0, null); - mDut.recordNdpCreation(uid1, package1, networkRequestCache); - setTime(7); // 2ms creation time - mDut.recordNdpStatus(NanStatusType.SUCCESS, false, 5); - - // uid2: ndp (non-secure) on ndi0 - WifiAwareNetworkSpecifier ns = addNetworkInfoToCache(networkRequestCache, 11, uid2, - package2, ndi0, null); - mDut.recordNdpCreation(uid2, package2, networkRequestCache); - setTime(10); // 3 ms creation time - mDut.recordNdpStatus(NanStatusType.SUCCESS, false, 7); - - // uid2: ndp (secure) on ndi1 (OOB) - addNetworkInfoToCache(networkRequestCache, 12, uid2, package2, ndi1, - "passphrase of some kind"); - mDut.recordNdpCreation(uid2, package2, networkRequestCache); - setTime(25); // 15 ms creation time - mDut.recordNdpStatus(NanStatusType.SUCCESS, true, 10); - - // uid2: ndp (secure) on ndi0 (OOB) - addNetworkInfoToCache(networkRequestCache, 13, uid2, package2, ndi0, - "super secret password"); - mDut.recordNdpCreation(uid2, package2, networkRequestCache); - setTime(36); // 11 ms creation time - mDut.recordNdpStatus(NanStatusType.SUCCESS, true, 25); - - // uid2: delete the first NDP - networkRequestCache.remove(ns); - - // uid2: ndp (non-secure) on ndi0 - addNetworkInfoToCache(networkRequestCache, 14, uid2, package2, ndi0, null); - mDut.recordNdpCreation(uid2, package2, networkRequestCache); - setTime(37); // 1 ms creation time! - mDut.recordNdpStatus(NanStatusType.SUCCESS, false, 36); - - // a few error codes - mDut.recordNdpStatus(NanStatusType.INTERNAL_FAILURE, false, 0); - mDut.recordNdpStatus(NanStatusType.INTERNAL_FAILURE, false, 0); - mDut.recordNdpStatus(NanStatusType.NO_RESOURCES_AVAILABLE, false, 0); - - // and some durations - setTime(150); - mDut.recordNdpSessionDuration(7); // 143ms - mDut.recordNdpSessionDuration(10); // 140ms - mDut.recordNdpSessionDuration(25); // 125ms - mDut.recordNdpSessionDuration(140); // 10ms - - //verify - log = mDut.consolidateProto(); - - collector.checkThat("maxConcurrentNdiInApp", log.maxConcurrentNdiInApp, equalTo(2)); - collector.checkThat("maxConcurrentNdiInSystem", log.maxConcurrentNdiInSystem, equalTo(2)); - collector.checkThat("maxConcurrentNdpInApp", log.maxConcurrentNdpInApp, equalTo(3)); - collector.checkThat("maxConcurrentNdpInSystem", log.maxConcurrentNdpInSystem, equalTo(4)); - collector.checkThat("maxConcurrentSecureNdpInApp", log.maxConcurrentSecureNdpInApp, - equalTo(2)); - collector.checkThat("maxConcurrentSecureNdpInSystem", log.maxConcurrentSecureNdpInSystem, - equalTo(2)); - collector.checkThat("maxConcurrentNdpPerNdi", log.maxConcurrentNdpPerNdi, equalTo(3)); - collector.checkThat("histogramRequestNdpStatus.length", - log.histogramRequestNdpStatus.length, equalTo(3)); - validateNanStatusProtoHistBucket("Bucket[SUCCESS]", - log.histogramRequestNdpStatus[0], - WifiMetricsProto.WifiAwareLog.SUCCESS, 3); - validateNanStatusProtoHistBucket("Bucket[INTERNAL_FAILURE]", - log.histogramRequestNdpStatus[1], - WifiMetricsProto.WifiAwareLog.INTERNAL_FAILURE, 2); - validateNanStatusProtoHistBucket("Bucket[UNKNOWN_HAL_STATUS]", - log.histogramRequestNdpStatus[2], - WifiMetricsProto.WifiAwareLog.NO_RESOURCES_AVAILABLE, 1); - collector.checkThat("histogramRequestNdpOobStatus.length", - log.histogramRequestNdpOobStatus.length, equalTo(1)); - validateNanStatusProtoHistBucket("Bucket[SUCCESS]", - log.histogramRequestNdpOobStatus[0], - WifiMetricsProto.WifiAwareLog.SUCCESS, 2); - - collector.checkThat("ndpCreationTimeMsMin", log.ndpCreationTimeMsMin, equalTo(1L)); - collector.checkThat("ndpCreationTimeMsMax", log.ndpCreationTimeMsMax, equalTo(15L)); - collector.checkThat("ndpCreationTimeMsSum", log.ndpCreationTimeMsSum, equalTo(32L)); - collector.checkThat("ndpCreationTimeMsSumOfSq", log.ndpCreationTimeMsSumOfSq, - equalTo(360L)); - collector.checkThat("ndpCreationTimeMsNumSamples", log.ndpCreationTimeMsNumSamples, - equalTo(5L)); - validateProtoHistBucket("Creation[0]", log.histogramNdpCreationTimeMs[0], 1, 2, 1); - validateProtoHistBucket("Creation[1]", log.histogramNdpCreationTimeMs[1], 2, 3, 1); - validateProtoHistBucket("Creation[2]", log.histogramNdpCreationTimeMs[2], 3, 4, 1); - validateProtoHistBucket("Creation[3]", log.histogramNdpCreationTimeMs[3], 10, 20, 2); - - validateProtoHistBucket("Duration[0]", log.histogramNdpSessionDurationMs[0], 10, 20, 1); - validateProtoHistBucket("Duration[1]", log.histogramNdpSessionDurationMs[1], 100, 200, 3); - } - - /** - * Validate that the histogram configuration is initialized correctly: bucket starting points - * and sub-bucket widths. - */ - @Test - public void testHistParamInit() { - collector.checkThat("HIST1.mLog", HIST1.mLog, equalTo(Math.log(10))); - collector.checkThat("HIST1.bb[0]", HIST1.bb[0], equalTo(1.0)); - collector.checkThat("HIST1.bb[1]", HIST1.bb[1], equalTo(10.0)); - collector.checkThat("HIST1.bb[2]", HIST1.bb[2], equalTo(100.0)); - collector.checkThat("HIST1.bb[3]", HIST1.bb[3], equalTo(1000.0)); - collector.checkThat("HIST1.bb[4]", HIST1.bb[4], equalTo(10000.0)); - collector.checkThat("HIST1.bb[5]", HIST1.bb[5], equalTo(100000.0)); - collector.checkThat("HIST1.sbw[0]", HIST1.sbw[0], equalTo(1.0)); - collector.checkThat("HIST1.sbw[1]", HIST1.sbw[1], equalTo(10.0)); - collector.checkThat("HIST1.sbw[2]", HIST1.sbw[2], equalTo(100.0)); - collector.checkThat("HIST1.sbw[3]", HIST1.sbw[3], equalTo(1000.0)); - collector.checkThat("HIST1.sbw[4]", HIST1.sbw[4], equalTo(10000.0)); - collector.checkThat("HIST1.sbw[5]", HIST1.sbw[5], equalTo(100000.0)); - - collector.checkThat("HIST2.mLog", HIST1.mLog, equalTo(Math.log(10))); - collector.checkThat("HIST2.bb[0]", HIST2.bb[0], equalTo(-18.0)); - collector.checkThat("HIST2.bb[1]", HIST2.bb[1], equalTo(-10.0)); - collector.checkThat("HIST2.bb[2]", HIST2.bb[2], equalTo(30.0)); - collector.checkThat("HIST2.sbw[0]", HIST2.sbw[0], equalTo(0.2)); - collector.checkThat("HIST2.sbw[1]", HIST2.sbw[1], equalTo(1.0)); - collector.checkThat("HIST2.sbw[2]", HIST2.sbw[2], equalTo(5.0)); - } - - /** - * Validate the conversion to a NanStatusType proto raw histogram. - */ - @Test - public void testNanStatusTypeHistogram() { - SparseIntArray statusHistogram = new SparseIntArray(); - - addNanHalStatusToHistogram(NanStatusType.SUCCESS, statusHistogram); - addNanHalStatusToHistogram(-1, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.ALREADY_ENABLED, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.SUCCESS, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.INTERNAL_FAILURE, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.SUCCESS, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.INTERNAL_FAILURE, statusHistogram); - addNanHalStatusToHistogram(55, statusHistogram); - addNanHalStatusToHistogram(65, statusHistogram); - - WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket[] sh = histogramToProtoArray( - statusHistogram); - collector.checkThat("Number of buckets", sh.length, equalTo(4)); - validateNanStatusProtoHistBucket("Bucket[SUCCESS]", sh[0], - WifiMetricsProto.WifiAwareLog.SUCCESS, 3); - validateNanStatusProtoHistBucket("Bucket[INTERNAL_FAILURE]", sh[1], - WifiMetricsProto.WifiAwareLog.INTERNAL_FAILURE, 2); - validateNanStatusProtoHistBucket("Bucket[ALREADY_ENABLED]", sh[2], - WifiMetricsProto.WifiAwareLog.ALREADY_ENABLED, 1); - validateNanStatusProtoHistBucket("Bucket[UNKNOWN_HAL_STATUS]", sh[3], - WifiMetricsProto.WifiAwareLog.UNKNOWN_HAL_STATUS, 3); - } - - // utilities - - /** - * Mock the elapsed time since boot to the input argument. - */ - private void setTime(long timeMs) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - } - - /** - * Sum all the 'count' entries in the histogram array. - */ - private int countAllHistogramSamples(WifiMetricsProto.WifiAwareLog.HistogramBucket[] hba) { - int sum = 0; - for (WifiMetricsProto.WifiAwareLog.HistogramBucket hb: hba) { - sum += hb.count; - } - return sum; - } - - private int countAllHistogramSamples( - WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket[] nshba) { - int sum = 0; - for (WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket nshb: nshba) { - sum += nshb.count; - } - return sum; - } - - private void validateProtoHistBucket(String logPrefix, - WifiMetricsProto.WifiAwareLog.HistogramBucket bucket, long start, long end, int count) { - collector.checkThat(logPrefix + ": start", bucket.start, equalTo(start)); - collector.checkThat(logPrefix + ": end", bucket.end, equalTo(end)); - collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count)); - } - - private void validateNanStatusProtoHistBucket(String logPrefix, - WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket bucket, int type, int count) { - collector.checkThat(logPrefix + ": type", bucket.nanStatusType, equalTo(type)); - collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count)); - } - - private WifiAwareNetworkSpecifier addNetworkInfoToCache( - Map<WifiAwareNetworkSpecifier, WifiAwareDataPathStateManager - .AwareNetworkRequestInformation> networkRequestCache, - int index, int uid, String packageName, String interfaceName, String passphrase) { - WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier(0, 0, 0, index, 0, null, null, - passphrase, 0, 0); - WifiAwareDataPathStateManager.AwareNetworkRequestInformation anri = - new WifiAwareDataPathStateManager.AwareNetworkRequestInformation(); - anri.networkSpecifier = ns; - anri.state = WifiAwareDataPathStateManager.AwareNetworkRequestInformation.STATE_CONFIRMED; - anri.uid = uid; - anri.packageName = packageName; - anri.interfaceName = interfaceName; - - networkRequestCache.put(ns, anri); - return ns; - } - - private void dumpDut(String prefix) { - StringWriter sw = new StringWriter(); - mDut.dump(null, new PrintWriter(sw), null); - Log.e("WifiAwareMetrics", prefix + sw.toString()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java deleted file mode 100644 index 08eae1d36..000000000 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java +++ /dev/null @@ -1,785 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.aware; - -import static android.hardware.wifi.V1_0.NanCipherSuiteType.SHARED_KEY_128_MASK; -import static android.hardware.wifi.V1_0.NanCipherSuiteType.SHARED_KEY_256_MASK; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyShort; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.NanBandIndex; -import android.hardware.wifi.V1_0.NanConfigRequest; -import android.hardware.wifi.V1_0.NanDataPathSecurityType; -import android.hardware.wifi.V1_0.NanEnableRequest; -import android.hardware.wifi.V1_0.NanPublishRequest; -import android.hardware.wifi.V1_0.NanRangingIndication; -import android.hardware.wifi.V1_0.NanSubscribeRequest; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_2.NanConfigRequestSupplemental; -import android.net.MacAddress; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.os.RemoteException; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.PrintWriter; -import java.util.ArrayList; - - -/** - * Unit test harness for WifiAwareNativeApi - */ -@SmallTest -public class WifiAwareNativeApiTest extends WifiBaseTest { - @Mock WifiAwareNativeManager mWifiAwareNativeManagerMock; - @Mock IWifiNanIface mIWifiNanIfaceMock; - @Mock android.hardware.wifi.V1_2.IWifiNanIface mIWifiNanIface12Mock; - - @Rule public ErrorCollector collector = new ErrorCollector(); - - private class MockableWifiAwareNativeApi extends WifiAwareNativeApi { - MockableWifiAwareNativeApi(WifiAwareNativeManager wifiAwareNativeManager) { - super(wifiAwareNativeManager); - } - - @Override - public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { - return mIsInterface12 ? mIWifiNanIface12Mock : null; - } - } - - private MockableWifiAwareNativeApi mDut; - private boolean mIsInterface12; - - /** - * Initializes mocks. - */ - @Before - public void setup() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mWifiAwareNativeManagerMock.getWifiNanIface()).thenReturn(mIWifiNanIfaceMock); - - WifiStatus status = new WifiStatus(); - status.code = WifiStatusCode.SUCCESS; - when(mIWifiNanIfaceMock.enableRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.configRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.startPublishRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.startSubscribeRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.initiateDataPathRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.respondToDataPathIndicationRequest(anyShort(), any())).thenReturn( - status); - when(mIWifiNanIface12Mock.enableRequest_1_2(anyShort(), any(), any())).thenReturn(status); - when(mIWifiNanIface12Mock.configRequest_1_2(anyShort(), any(), any())).thenReturn(status); - when(mIWifiNanIface12Mock.startPublishRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIface12Mock.startSubscribeRequest(anyShort(), any())).thenReturn(status); - - mIsInterface12 = false; - - mDut = new MockableWifiAwareNativeApi(mWifiAwareNativeManagerMock); - } - - /** - * Test that the set parameter shell command executor works when parameters are valid. - */ - @Test - public void testSetParameterShellCommandSuccess() { - setSettableParam(WifiAwareNativeApi.PARAM_MAC_RANDOM_INTERVAL_SEC, Integer.toString(1), - true); - } - - /** - * Test that the set parameter shell command executor fails on incorrect name. - */ - @Test - public void testSetParameterShellCommandInvalidParameterName() { - setSettableParam("XXX", Integer.toString(1), false); - } - - /** - * Test that the set parameter shell command executor fails on invalid value (not convertible - * to an int). - */ - @Test - public void testSetParameterShellCommandInvalidValue() { - setSettableParam(WifiAwareNativeApi.PARAM_MAC_RANDOM_INTERVAL_SEC, "garbage", false); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using default values at the default power state. - */ - @Test - public void testEnableAndConfigPowerSettingsDefaults() throws RemoteException { - byte default5 = 1; - byte default24 = 1; - - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), true, - true, true, false, false); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", default5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-24", default24, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .discoveryWindowIntervalVal)); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using the specified non-interactive values when in that power state. - */ - @Test - public void testEnableAndConfigPowerSettingsNoneInteractive() throws RemoteException { - byte interactive5 = 2; - byte interactive24 = 3; - - setPowerConfigurationParams(interactive5, interactive24, (byte) -1, (byte) -1); - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, - false, false, false, false); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", interactive5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-24", interactive24, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .discoveryWindowIntervalVal)); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using the specified idle (doze) values when in that power state. - */ - @Test - public void testEnableAndConfigPowerSettingsIdle() throws RemoteException { - byte idle5 = 2; - byte idle24 = -1; - - setPowerConfigurationParams((byte) -1, (byte) -1, idle5, idle24); - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, - true, false, true, false); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", idle5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", false, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using default values at the default power state. - * - * Using HAL 1.2: additional power configurations. - */ - @Test - public void testEnableAndConfigPowerSettingsDefaults_1_2() throws RemoteException { - byte default5 = 1; - byte default24 = 1; - - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), true, - true, true, false, true); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", default5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-24", default24, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .discoveryWindowIntervalVal)); - - collector.checkThat("discoveryBeaconIntervalMs", 0, - equalTo(configs.second.discoveryBeaconIntervalMs)); - collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, - equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); - collector.checkThat("enableDiscoveryWindowEarlyTermination", false, - equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using the specified non-interactive values when in that power state. - * - * Using HAL 1.2: additional power configurations. - */ - @Test - public void testEnableAndConfigPowerSettingsNoneInteractive_1_2() throws RemoteException { - byte interactive5 = 2; - byte interactive24 = 3; - - setPowerConfigurationParams(interactive5, interactive24, (byte) -1, (byte) -1); - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, - false, false, false, true); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", interactive5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-24", interactive24, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .discoveryWindowIntervalVal)); - - // Note: still defaults (i.e. disabled) - will be tweaked for low power - collector.checkThat("discoveryBeaconIntervalMs", 0, - equalTo(configs.second.discoveryBeaconIntervalMs)); - collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, - equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); - collector.checkThat("enableDiscoveryWindowEarlyTermination", false, - equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using the specified idle (doze) values when in that power state. - * - * Using HAL 1.2: additional power configurations. - */ - @Test - public void testEnableAndConfigPowerSettingsIdle_1_2() throws RemoteException { - byte idle5 = 2; - byte idle24 = -1; - - setPowerConfigurationParams((byte) -1, (byte) -1, idle5, idle24); - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, - true, false, true, true); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", idle5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", false, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - - // Note: still defaults (i.e. disabled) - will be tweaked for low power - collector.checkThat("discoveryBeaconIntervalMs", 0, - equalTo(configs.second.discoveryBeaconIntervalMs)); - collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, - equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); - collector.checkThat("enableDiscoveryWindowEarlyTermination", false, - equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); - } - - @Test - public void testDiscoveryRangingSettings() throws RemoteException { - short tid = 666; - byte pid = 34; - int minDistanceMm = 100; - int maxDistanceMm = 555; - // TODO: b/69428593 remove once HAL is converted from CM to MM - short minDistanceCm = (short) (minDistanceMm / 10); - short maxDistanceCm = (short) (maxDistanceMm / 10); - - ArgumentCaptor<NanPublishRequest> pubCaptor = ArgumentCaptor.forClass( - NanPublishRequest.class); - ArgumentCaptor<NanSubscribeRequest> subCaptor = ArgumentCaptor.forClass( - NanSubscribeRequest.class); - - PublishConfig pubDefault = new PublishConfig.Builder().setServiceName("XXX").build(); - PublishConfig pubWithRanging = new PublishConfig.Builder().setServiceName( - "XXX").setRangingEnabled(true).build(); - SubscribeConfig subDefault = new SubscribeConfig.Builder().setServiceName("XXX").build(); - SubscribeConfig subWithMin = new SubscribeConfig.Builder().setServiceName( - "XXX").setMinDistanceMm(minDistanceMm).build(); - SubscribeConfig subWithMax = new SubscribeConfig.Builder().setServiceName( - "XXX").setMaxDistanceMm(maxDistanceMm).build(); - SubscribeConfig subWithMinMax = new SubscribeConfig.Builder().setServiceName( - "XXX").setMinDistanceMm(minDistanceMm).setMaxDistanceMm(maxDistanceMm).build(); - - mDut.publish(tid, pid, pubDefault); - mDut.publish(tid, pid, pubWithRanging); - mDut.subscribe(tid, pid, subDefault); - mDut.subscribe(tid, pid, subWithMin); - mDut.subscribe(tid, pid, subWithMax); - mDut.subscribe(tid, pid, subWithMinMax); - - verify(mIWifiNanIfaceMock, times(2)).startPublishRequest(eq(tid), pubCaptor.capture()); - verify(mIWifiNanIfaceMock, times(4)).startSubscribeRequest(eq(tid), subCaptor.capture()); - - NanPublishRequest halPubReq; - NanSubscribeRequest halSubReq; - - // pubDefault - halPubReq = pubCaptor.getAllValues().get(0); - collector.checkThat("pubDefault.baseConfigs.sessionId", pid, - equalTo(halPubReq.baseConfigs.sessionId)); - collector.checkThat("pubDefault.baseConfigs.rangingRequired", false, - equalTo(halPubReq.baseConfigs.rangingRequired)); - - // pubWithRanging - halPubReq = pubCaptor.getAllValues().get(1); - collector.checkThat("pubWithRanging.baseConfigs.sessionId", pid, - equalTo(halPubReq.baseConfigs.sessionId)); - collector.checkThat("pubWithRanging.baseConfigs.rangingRequired", true, - equalTo(halPubReq.baseConfigs.rangingRequired)); - - // subDefault - halSubReq = subCaptor.getAllValues().get(0); - collector.checkThat("subDefault.baseConfigs.sessionId", pid, - equalTo(halSubReq.baseConfigs.sessionId)); - collector.checkThat("subDefault.baseConfigs.rangingRequired", false, - equalTo(halSubReq.baseConfigs.rangingRequired)); - - // subWithMin - halSubReq = subCaptor.getAllValues().get(1); - collector.checkThat("subWithMin.baseConfigs.sessionId", pid, - equalTo(halSubReq.baseConfigs.sessionId)); - collector.checkThat("subWithMin.baseConfigs.rangingRequired", true, - equalTo(halSubReq.baseConfigs.rangingRequired)); - collector.checkThat("subWithMin.baseConfigs.configRangingIndications", - NanRangingIndication.EGRESS_MET_MASK, - equalTo(halSubReq.baseConfigs.configRangingIndications)); - collector.checkThat("subWithMin.baseConfigs.distanceEgressCm", minDistanceCm, - equalTo(halSubReq.baseConfigs.distanceEgressCm)); - - // subWithMax - halSubReq = subCaptor.getAllValues().get(2); - collector.checkThat("subWithMax.baseConfigs.sessionId", pid, - equalTo(halSubReq.baseConfigs.sessionId)); - collector.checkThat("subWithMax.baseConfigs.rangingRequired", true, - equalTo(halSubReq.baseConfigs.rangingRequired)); - collector.checkThat("subWithMax.baseConfigs.configRangingIndications", - NanRangingIndication.INGRESS_MET_MASK, - equalTo(halSubReq.baseConfigs.configRangingIndications)); - collector.checkThat("subWithMin.baseConfigs.distanceIngressCm", maxDistanceCm, - equalTo(halSubReq.baseConfigs.distanceIngressCm)); - - // subWithMinMax - halSubReq = subCaptor.getAllValues().get(3); - collector.checkThat("subWithMinMax.baseConfigs.sessionId", pid, - equalTo(halSubReq.baseConfigs.sessionId)); - collector.checkThat("subWithMinMax.baseConfigs.rangingRequired", true, - equalTo(halSubReq.baseConfigs.rangingRequired)); - collector.checkThat("subWithMinMax.baseConfigs.configRangingIndications", - NanRangingIndication.INGRESS_MET_MASK | NanRangingIndication.EGRESS_MET_MASK, - equalTo(halSubReq.baseConfigs.configRangingIndications)); - collector.checkThat("subWithMin.baseConfigs.distanceEgressCm", minDistanceCm, - equalTo(halSubReq.baseConfigs.distanceEgressCm)); - collector.checkThat("subWithMin.baseConfigs.distanceIngressCm", maxDistanceCm, - equalTo(halSubReq.baseConfigs.distanceIngressCm)); - } - - /** - * Validate the initiation of NDP for an open link. - */ - @Test - public void testInitiateDataPathOpen() throws Exception { - validateInitiateDataPath( - /* usePmk */ false, - /* usePassphrase */ false, - /* isOutOfBand */ false, - /* supportedCipherSuites */ SHARED_KEY_256_MASK, - /* expectedCipherSuite */ SHARED_KEY_256_MASK); - } - - /** - * Validate the initiation of NDP for an PMK protected link with in-band discovery. - */ - @Test - public void testInitiateDataPathPmkInBand() throws Exception { - validateInitiateDataPath( - /* usePmk */ true, - /* usePassphrase */ false, - /* isOutOfBand */ false, - /* supportedCipherSuites */ SHARED_KEY_128_MASK, - /* expectedCipherSuite */ SHARED_KEY_128_MASK); - - } - - /** - * Validate the initiation of NDP for an Passphrase protected link with in-band discovery. - */ - @Test - public void testInitiateDataPathPassphraseInBand() throws Exception { - validateInitiateDataPath( - /* usePmk */ false, - /* usePassphrase */ true, - /* isOutOfBand */ false, - /* supportedCipherSuites */ SHARED_KEY_256_MASK | SHARED_KEY_128_MASK, - /* expectedCipherSuite */ SHARED_KEY_256_MASK); - } - - /** - * Validate the initiation of NDP for an PMK protected link with out-of-band discovery. - */ - @Test - public void testInitiateDataPathPmkOutOfBand() throws Exception { - validateInitiateDataPath( - /* usePmk */ true, - /* usePassphrase */ false, - /* isOutOfBand */ true, - /* supportedCipherSuites */ 0, - /* expectedCipherSuite */ 0); - } - - /** - * Validate the response to an NDP request for an open link. - */ - @Test - public void testRespondToDataPathRequestOpenInBand() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ false, - /* usePassphrase */ false, - /* accept */ true, - /* isOutOfBand */ false, - /* supportedCipherSuites */ SHARED_KEY_128_MASK, - /* expectedCipherSuite */ SHARED_KEY_128_MASK); - } - - /** - * Validate the response to an NDP request for a PMK-protected link with in-band discovery. - */ - @Test - public void testRespondToDataPathRequestPmkInBand() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ true, - /* usePassphrase */ false, - /* accept */ true, - /* isOutOfBand */ false, - /* supportedCipherSuites */ SHARED_KEY_256_MASK | SHARED_KEY_128_MASK, - /* expectedCipherSuite */ SHARED_KEY_256_MASK); - } - - /** - * Validate the response to an NDP request for a Passphrase-protected link with in-band - * discovery. - */ - @Test - public void testRespondToDataPathRequestPassphraseInBand() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ false, - /* usePassphrase */ true, - /* accept */ true, - /* isOutOfBand */ false, - /* supportedCipherSuites */ SHARED_KEY_256_MASK, - /* expectedCipherSuite */ SHARED_KEY_256_MASK); - } - - /** - * Validate the response to an NDP request for a PMK-protected link with out-of-band discovery. - */ - @Test - public void testRespondToDataPathRequestPmkOutOfBand() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ true, - /* usePassphrase */ false, - /* accept */ true, - /* isOutOfBand */ true, - /* supportedCipherSuites */ 0, - /* expectedCipherSuite */ 0); - } - - /** - * Validate the response to an NDP request - when request is rejected. - */ - @Test - public void testRespondToDataPathRequestReject() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ true, - /* usePassphrase */ false, - /* accept */ false, - /* isOutOfBand */ true, - /* supportedCipherSuites */ 0, - /* expectedCipherSuite */ 0); - } - - // utilities - - private void setPowerConfigurationParams(byte interactive5, byte interactive24, byte idle5, - byte idle24) { - setSettablePowerParam(WifiAwareNativeApi.POWER_PARAM_INACTIVE_KEY, - WifiAwareNativeApi.PARAM_DW_5GHZ, Integer.toString(interactive5), true); - setSettablePowerParam(WifiAwareNativeApi.POWER_PARAM_INACTIVE_KEY, - WifiAwareNativeApi.PARAM_DW_24GHZ, Integer.toString(interactive24), true); - setSettablePowerParam(WifiAwareNativeApi.POWER_PARAM_IDLE_KEY, - WifiAwareNativeApi.PARAM_DW_5GHZ, Integer.toString(idle5), true); - setSettablePowerParam(WifiAwareNativeApi.POWER_PARAM_IDLE_KEY, - WifiAwareNativeApi.PARAM_DW_24GHZ, Integer.toString(idle24), true); - } - - private void setSettablePowerParam(String mode, String name, String value, - boolean expectSuccess) { - PrintWriter pwMock = mock(PrintWriter.class); - WifiAwareShellCommand parentShellMock = mock(WifiAwareShellCommand.class); - when(parentShellMock.getNextArgRequired()).thenReturn("set-power").thenReturn( - mode).thenReturn(name).thenReturn(value); - when(parentShellMock.getErrPrintWriter()).thenReturn(pwMock); - - collector.checkThat(mDut.onCommand(parentShellMock), equalTo(expectSuccess ? 0 : -1)); - } - - private void setSettableParam(String name, String value, boolean expectSuccess) { - PrintWriter pwMock = mock(PrintWriter.class); - WifiAwareShellCommand parentShellMock = mock(WifiAwareShellCommand.class); - when(parentShellMock.getNextArgRequired()).thenReturn("set").thenReturn(name).thenReturn( - value); - when(parentShellMock.getErrPrintWriter()).thenReturn(pwMock); - - collector.checkThat(mDut.onCommand(parentShellMock), equalTo(expectSuccess ? 0 : -1)); - } - - private Pair<NanConfigRequest, NanConfigRequestSupplemental> validateEnableAndConfigure( - short transactionId, ConfigRequest configRequest, boolean notifyIdentityChange, - boolean initialConfiguration, boolean isInteractive, boolean isIdle, boolean isHal12) - throws RemoteException { - mIsInterface12 = isHal12; - - mDut.enableAndConfigure(transactionId, configRequest, notifyIdentityChange, - initialConfiguration, isInteractive, isIdle, false); - - ArgumentCaptor<NanEnableRequest> enableReqCaptor = ArgumentCaptor.forClass( - NanEnableRequest.class); - ArgumentCaptor<NanConfigRequest> configReqCaptor = ArgumentCaptor.forClass( - NanConfigRequest.class); - ArgumentCaptor<NanConfigRequestSupplemental> configSuppCaptor = ArgumentCaptor.forClass( - NanConfigRequestSupplemental.class); - NanConfigRequest config; - NanConfigRequestSupplemental configSupp = null; - - if (initialConfiguration) { - if (isHal12) { - verify(mIWifiNanIface12Mock).enableRequest_1_2(eq(transactionId), - enableReqCaptor.capture(), configSuppCaptor.capture()); - configSupp = configSuppCaptor.getValue(); - } else { - verify(mIWifiNanIfaceMock).enableRequest(eq(transactionId), - enableReqCaptor.capture()); - } - config = enableReqCaptor.getValue().configParams; - } else { - if (isHal12) { - verify(mIWifiNanIface12Mock).configRequest_1_2(eq(transactionId), - configReqCaptor.capture(), configSuppCaptor.capture()); - configSupp = configSuppCaptor.getValue(); - } else { - verify(mIWifiNanIfaceMock).configRequest(eq(transactionId), - configReqCaptor.capture()); - } - config = configReqCaptor.getValue(); - } - - collector.checkThat("disableDiscoveryAddressChangeIndication", !notifyIdentityChange, - equalTo(config.disableDiscoveryAddressChangeIndication)); - collector.checkThat("disableStartedClusterIndication", !notifyIdentityChange, - equalTo(config.disableStartedClusterIndication)); - collector.checkThat("disableJoinedClusterIndication", !notifyIdentityChange, - equalTo(config.disableJoinedClusterIndication)); - - return new Pair<>(config, configSupp); - } - - private void validateInitiateDataPath(boolean usePmk, boolean usePassphrase, - boolean isOutOfBand, int supportedCipherSuites, int expectedCipherSuite) - throws Exception { - short tid = 44; - int peerId = 555; - int channelRequestType = - android.hardware.wifi.V1_0.NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED; - int channel = 2146; - byte[] peer = MacAddress.fromString("00:01:02:03:04:05").toByteArray(); - String interfaceName = "aware_data5"; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - String passphrase = "blahblah"; - final byte[] appInfo = "Out-of-band info".getBytes(); - - Capabilities cap = new Capabilities(); - cap.supportedCipherSuites = supportedCipherSuites; - - ArgumentCaptor<android.hardware.wifi.V1_0.NanInitiateDataPathRequest> captor = - ArgumentCaptor.forClass( - android.hardware.wifi.V1_0.NanInitiateDataPathRequest.class); - - mDut.initiateDataPath(tid, peerId, channelRequestType, channel, peer, interfaceName, - usePmk ? pmk : null, usePassphrase ? passphrase : null, isOutOfBand, appInfo, cap); - - verify(mIWifiNanIfaceMock).initiateDataPathRequest(eq(tid), captor.capture()); - - android.hardware.wifi.V1_0.NanInitiateDataPathRequest nidpr = captor.getValue(); - collector.checkThat("peerId", peerId, equalTo(nidpr.peerId)); - collector.checkThat("peerDiscMacAddr", peer, equalTo(nidpr.peerDiscMacAddr)); - collector.checkThat("channelRequestType", channelRequestType, - equalTo(nidpr.channelRequestType)); - collector.checkThat("channel", channel, equalTo(nidpr.channel)); - collector.checkThat("ifaceName", interfaceName, equalTo(nidpr.ifaceName)); - - if (usePmk) { - collector.checkThat("securityConfig.securityType", - NanDataPathSecurityType.PMK, - equalTo(nidpr.securityConfig.securityType)); - collector.checkThat("securityConfig.cipherType", expectedCipherSuite, - equalTo(nidpr.securityConfig.cipherType)); - collector.checkThat("securityConfig.pmk", pmk, equalTo(nidpr.securityConfig.pmk)); - collector.checkThat("securityConfig.passphrase.length", 0, - equalTo(nidpr.securityConfig.passphrase.size())); - } - - if (usePassphrase) { - collector.checkThat("securityConfig.securityType", - NanDataPathSecurityType.PASSPHRASE, - equalTo(nidpr.securityConfig.securityType)); - collector.checkThat("securityConfig.cipherType", expectedCipherSuite, - equalTo(nidpr.securityConfig.cipherType)); - collector.checkThat("securityConfig.passphrase", passphrase.getBytes(), - equalTo(convertArrayListToNativeByteArray(nidpr.securityConfig.passphrase))); - } - - collector.checkThat("appInfo", appInfo, - equalTo(convertArrayListToNativeByteArray(nidpr.appInfo))); - - if ((usePmk || usePassphrase) && isOutOfBand) { - collector.checkThat("serviceNameOutOfBand", - WifiAwareNativeApi.SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(), - equalTo(convertArrayListToNativeByteArray(nidpr.serviceNameOutOfBand))); - } else { - collector.checkThat("serviceNameOutOfBand.length", 0, - equalTo(nidpr.serviceNameOutOfBand.size())); - } - } - - private void validateRespondToDataPathRequest(boolean usePmk, boolean usePassphrase, - boolean accept, boolean isOutOfBand, int supportedCipherSuites, int expectedCipherSuite) - throws Exception { - short tid = 33; - int ndpId = 44; - String interfaceName = "aware_whatever22"; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - String passphrase = "blahblah"; - final byte[] appInfo = "Out-of-band info".getBytes(); - - Capabilities cap = new Capabilities(); - cap.supportedCipherSuites = supportedCipherSuites; - - ArgumentCaptor<android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest> captor = - ArgumentCaptor.forClass( - android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest.class); - - mDut.respondToDataPathRequest(tid, accept, ndpId, interfaceName, usePmk ? pmk : null, - usePassphrase ? passphrase : null, appInfo, isOutOfBand, cap); - - verify(mIWifiNanIfaceMock).respondToDataPathIndicationRequest(eq(tid), captor.capture()); - - android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest nrtdpir = - captor.getValue(); - collector.checkThat("acceptRequest", accept, equalTo(nrtdpir.acceptRequest)); - collector.checkThat("ndpInstanceId", ndpId, equalTo(nrtdpir.ndpInstanceId)); - collector.checkThat("ifaceName", interfaceName, equalTo(nrtdpir.ifaceName)); - - if (accept) { - if (usePmk) { - collector.checkThat("securityConfig.securityType", - NanDataPathSecurityType.PMK, - equalTo(nrtdpir.securityConfig.securityType)); - collector.checkThat("securityConfig.cipherType", expectedCipherSuite, - equalTo(nrtdpir.securityConfig.cipherType)); - collector.checkThat("securityConfig.pmk", pmk, equalTo(nrtdpir.securityConfig.pmk)); - collector.checkThat("securityConfig.passphrase.length", 0, - equalTo(nrtdpir.securityConfig.passphrase.size())); - } - - if (usePassphrase) { - collector.checkThat("securityConfig.securityType", - NanDataPathSecurityType.PASSPHRASE, - equalTo(nrtdpir.securityConfig.securityType)); - collector.checkThat("securityConfig.cipherType", expectedCipherSuite, - equalTo(nrtdpir.securityConfig.cipherType)); - collector.checkThat("securityConfig.passphrase", passphrase.getBytes(), - equalTo(convertArrayListToNativeByteArray( - nrtdpir.securityConfig.passphrase))); - } - - collector.checkThat("appInfo", appInfo, - equalTo(convertArrayListToNativeByteArray(nrtdpir.appInfo))); - - if ((usePmk || usePassphrase) && isOutOfBand) { - collector.checkThat("serviceNameOutOfBand", - WifiAwareNativeApi.SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(), - equalTo(convertArrayListToNativeByteArray(nrtdpir.serviceNameOutOfBand))); - } else { - collector.checkThat("serviceNameOutOfBand.length", 0, - equalTo(nrtdpir.serviceNameOutOfBand.size())); - } - } - } - - private byte[] convertArrayListToNativeByteArray(ArrayList<Byte> from) { - if (from == null) { - return null; - } - - byte[] to = new byte[from.size()]; - for (int i = 0; i < from.size(); ++i) { - to[i] = from.get(i); - } - return to; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java deleted file mode 100644 index d97ae0604..000000000 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.aware; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.os.Handler; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit test harness for WifiAwareNativeManager. - */ -@SmallTest -public class WifiAwareNativeManagerTest extends WifiBaseTest { - private WifiAwareNativeManager mDut; - @Mock private WifiAwareStateManager mWifiAwareStateManagerMock; - @Mock private HalDeviceManager mHalDeviceManager; - @Mock private WifiAwareNativeCallback mWifiAwareNativeCallback; - @Mock private IWifiNanIface mWifiNanIfaceMock; - @Mock android.hardware.wifi.V1_2.IWifiNanIface mIWifiNanIface12Mock; - @Mock private Handler mHandlerMock; - private ArgumentCaptor<HalDeviceManager.ManagerStatusListener> mManagerStatusListenerCaptor = - ArgumentCaptor.forClass(HalDeviceManager.ManagerStatusListener.class); - private ArgumentCaptor<HalDeviceManager.InterfaceDestroyedListener> - mDestroyedListenerCaptor = ArgumentCaptor.forClass( - HalDeviceManager.InterfaceDestroyedListener.class); - private ArgumentCaptor<HalDeviceManager.InterfaceAvailableForRequestListener> - mAvailListenerCaptor = ArgumentCaptor.forClass( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - private InOrder mInOrder; - @Rule public ErrorCollector collector = new ErrorCollector(); - - private WifiStatus mStatusOk; - - private class MockableWifiAwareNativeManager extends WifiAwareNativeManager { - MockableWifiAwareNativeManager(WifiAwareStateManager awareStateManager, - HalDeviceManager halDeviceManager, - WifiAwareNativeCallback wifiAwareNativeCallback) { - super(awareStateManager, halDeviceManager, wifiAwareNativeCallback); - } - - @Override - public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { - return (iface == mIWifiNanIface12Mock) ? mIWifiNanIface12Mock : null; - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mStatusOk = new WifiStatus(); - mStatusOk.code = WifiStatusCode.SUCCESS; - - when(mWifiNanIfaceMock.registerEventCallback(any())).thenReturn(mStatusOk); - when(mIWifiNanIface12Mock.registerEventCallback_1_2(any())).thenReturn(mStatusOk); - - mDut = new MockableWifiAwareNativeManager(mWifiAwareStateManagerMock, - mHalDeviceManager, mWifiAwareNativeCallback); - mDut.start(mHandlerMock); - - mInOrder = inOrder(mWifiAwareStateManagerMock, mHalDeviceManager, mWifiNanIfaceMock, - mIWifiNanIface12Mock); - - // validate (and capture) that register manage status callback - mInOrder.verify(mHalDeviceManager).initialize(); - mInOrder.verify(mHalDeviceManager).registerStatusListener( - mManagerStatusListenerCaptor.capture(), any()); - } - - /** - * Test the control flow of the manager when Aware isn't being actively used: - * - * 1. onStatusChange (ready/started) - * 2. on available -> enableUsage - * 3. onStatusChange (!started) -> disableUsage - * 4. onStatusChange (ready/started) + available -> enableUsage - * 5. on not available -> disableUsage - * - * --> no interface creation at any point! - */ - @Test - public void testControlFlowWithoutInterface() { - // configure HalDeviceManager as ready/wifi started (and to return an interface if - // requested) - when(mHalDeviceManager.isStarted()).thenReturn(true); - when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock); - - // 1. onStatusChange (ready/started) - mManagerStatusListenerCaptor.getValue().onStatusChanged(); - mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( - eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); - - // 2. NAN is available -> enableUsage - mAvailListenerCaptor.getValue().onAvailabilityChanged(true); - mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); - - // 3. onStatusChange (not ready) -> disableUsage - when(mHalDeviceManager.isStarted()).thenReturn(false); - mManagerStatusListenerCaptor.getValue().onStatusChanged(); - - mInOrder.verify(mWifiAwareStateManagerMock).disableUsage(); - - // 4. onStatusChange (ready/started) + available -> enableUsage - when(mHalDeviceManager.isStarted()).thenReturn(true); - mManagerStatusListenerCaptor.getValue().onStatusChanged(); - - mManagerStatusListenerCaptor.getValue().onStatusChanged(); - mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( - eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); - mAvailListenerCaptor.getValue().onAvailabilityChanged(true); - - mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); - - // 5. not available -> disableUsage - mAvailListenerCaptor.getValue().onAvailabilityChanged(false); - - mInOrder.verify(mWifiAwareStateManagerMock).disableUsage(); - - mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any()); - verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, - mIWifiNanIface12Mock); - assertNull("Interface non-null!", mDut.getWifiNanIface()); - } - - /** - * Test the control flow (and reference counting) of the manager when Aware is actively used and - * reference counted (i.e. irregular requests/releases). - */ - @Test - public void testReferenceCounting() throws Exception { - // configure HalDeviceManager as ready/wifi started (and to return an interface if - // requested) - when(mHalDeviceManager.isStarted()).thenReturn(true); - when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock); - - // 1. onStatusChange (ready/started) - mManagerStatusListenerCaptor.getValue().onStatusChanged(); - mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( - eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); - assertNull("Interface non-null!", mDut.getWifiNanIface()); - - mAvailListenerCaptor.getValue().onAvailabilityChanged(true); - mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); - - // 2. request (interface obtained) - mDut.tryToGetAware(); - mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), - any()); - mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); - assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); - - // 3. release (interface released) - mDut.releaseAware(); - mInOrder.verify(mHalDeviceManager).removeIface(mWifiNanIfaceMock); - assertNull("Interface non-null!", mDut.getWifiNanIface()); - - mDestroyedListenerCaptor.getValue().onDestroyed("nan0"); - - // 4. request (interface obtained) - mDut.tryToGetAware(); - mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), - any()); - mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); - assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); - - // 5. request (nop - already have interface) - mDut.tryToGetAware(); - assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); - - // 6. release (nop - reference counting requests) - mDut.releaseAware(); - assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); - - // 7. release (interface released) - mDut.releaseAware(); - mInOrder.verify(mHalDeviceManager).removeIface(mWifiNanIfaceMock); - assertNull("Interface non-null!", mDut.getWifiNanIface()); - - mDestroyedListenerCaptor.getValue().onDestroyed("nan0"); - - mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any()); - mInOrder.verify(mHalDeviceManager, never()).removeIface(any()); - verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, - mIWifiNanIface12Mock); - } - - /** - * Test the control flow when the interface gets deleted due to external - */ - @Test - public void testRequestFlowWithAsyncDeletes() throws Exception { - // configure HalDeviceManager as ready/wifi started (and to return an interface if - // requested) - when(mHalDeviceManager.isStarted()).thenReturn(true); - when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock); - - // 1. onStatusChange (ready/started) - mManagerStatusListenerCaptor.getValue().onStatusChanged(); - mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( - eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); - assertNull("Interface non-null!", mDut.getWifiNanIface()); - - mAvailListenerCaptor.getValue().onAvailabilityChanged(true); - mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); - - // 2. request (interface obtained) - mDut.tryToGetAware(); - mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), - any()); - mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); - assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); - - // 3. interface gets destroyed - mDestroyedListenerCaptor.getValue().onDestroyed("nan0"); - - mInOrder.verify(mWifiAwareStateManagerMock).disableUsage(); - assertNull("Interface non-null!", mDut.getWifiNanIface()); - - // 4. a release doesn't do much - mDut.releaseAware(); - - mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any()); - mInOrder.verify(mHalDeviceManager, never()).removeIface(any()); - verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, - mIWifiNanIface12Mock); - } - - /** - * Test the basic control flow for HAL 1.2 - validate that the correct event registration - * occurs. - */ - @Test - public void testBasicFlowHal12() throws Exception { - // configure HalDeviceManager as ready/wifi started (and to return an interface if - // requested) - when(mHalDeviceManager.isStarted()).thenReturn(true); - when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mIWifiNanIface12Mock); - - // 1. onStatusChange (ready/started) - mManagerStatusListenerCaptor.getValue().onStatusChanged(); - mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( - eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); - assertNull("Interface non-null!", mDut.getWifiNanIface()); - - mAvailListenerCaptor.getValue().onAvailabilityChanged(true); - mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); - - // 2. request (interface obtained) - mDut.tryToGetAware(); - mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), - any()); - mInOrder.verify(mIWifiNanIface12Mock).registerEventCallback_1_2(any()); - assertEquals("Interface mismatch", mIWifiNanIface12Mock, mDut.getWifiNanIface()); - - // 3. receive Availability Change, has interface, should ignore - mAvailListenerCaptor.getValue().onAvailabilityChanged(false); - assertTrue("AwareNativeAvailable mismatch ", mDut.isAwareNativeAvailable()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java deleted file mode 100644 index c6c83ba53..000000000 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java +++ /dev/null @@ -1,750 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.Manifest; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.hardware.wifi.V1_0.NanCipherSuiteType; -import android.net.wifi.aware.Characteristics; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; -import android.net.wifi.aware.IWifiAwareEventCallback; -import android.net.wifi.aware.IWifiAwareMacAddressProvider; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.test.TestLooper; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiSettingsConfigStore; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - - -/** - * Unit test harness for WifiAwareStateManager. - */ -@SmallTest -public class WifiAwareServiceImplTest extends WifiBaseTest { - private static final int MAX_LENGTH = 255; - - private WifiAwareServiceImplSpy mDut; - private int mDefaultUid = 1500; - private String mPackageName = "some.package"; - private String mFeatureId = "some.feature"; - private TestLooper mMockLooper; - - @Mock - private Context mContextMock; - @Mock - private HandlerThread mHandlerThreadMock; - @Mock - private PackageManager mPackageManagerMock; - @Mock - private WifiAwareStateManager mAwareStateManagerMock; - @Mock - private WifiAwareShellCommand mWifiAwareShellCommandMock; - @Mock - private IBinder mBinderMock; - @Mock - private IWifiAwareEventCallback mCallbackMock; - @Mock - private IWifiAwareDiscoverySessionCallback mSessionCallbackMock; - @Mock private WifiAwareMetrics mAwareMetricsMock; - @Mock private WifiPermissionsUtil mWifiPermissionsUtil; - @Mock private WifiPermissionsWrapper mPermissionsWrapperMock; - @Mock - WifiSettingsConfigStore mWifiSettingsConfigStore; - - /** - * Using instead of spy to avoid native crash failures - possibly due to - * spy's copying of state. - */ - private class WifiAwareServiceImplSpy extends WifiAwareServiceImpl { - public int fakeUid; - - WifiAwareServiceImplSpy(Context context) { - super(context); - } - - /** - * Return the fake UID instead of the real one: pseudo-spy - * implementation. - */ - @Override - public int getMockableCallingUid() { - return fakeUid; - } - } - - /** - * Initializes mocks. - */ - @Before - public void setup() throws Exception { - MockitoAnnotations.initMocks(this); - mMockLooper = new TestLooper(); - - when(mHandlerThreadMock.getLooper()).thenReturn(mMockLooper.getLooper()); - - AppOpsManager appOpsMock = mock(AppOpsManager.class); - when(mContextMock.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(appOpsMock); - - when(mContextMock.getApplicationContext()).thenReturn(mContextMock); - when(mContextMock.getPackageManager()).thenReturn(mPackageManagerMock); - when(mPackageManagerMock.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)) - .thenReturn(true); - when(mPackageManagerMock.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)) - .thenReturn(true); - when(mAwareStateManagerMock.getCharacteristics()).thenReturn(getCharacteristics()); - when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true); - - mDut = new WifiAwareServiceImplSpy(mContextMock); - mDut.fakeUid = mDefaultUid; - mDut.start(mHandlerThreadMock, mAwareStateManagerMock, mWifiAwareShellCommandMock, - mAwareMetricsMock, mWifiPermissionsUtil, mPermissionsWrapperMock, - mWifiSettingsConfigStore, - mock(WifiAwareNativeManager.class), mock(WifiAwareNativeApi.class), - mock(WifiAwareNativeCallback.class), mock(NetdWrapper.class)); - mMockLooper.dispatchAll(); - verify(mAwareStateManagerMock).start(eq(mContextMock), any(), eq(mAwareMetricsMock), - eq(mWifiPermissionsUtil), eq(mPermissionsWrapperMock), any(), any()); - } - - /** - * Validate isUsageEnabled() function - */ - @Test - public void testIsUsageEnabled() { - mDut.isUsageEnabled(); - - verify(mAwareStateManagerMock).isUsageEnabled(); - } - - - /** - * Validate connect() - returns and uses a client ID. - */ - @Test - public void testConnect() { - doConnect(); - } - - /** - * Validate connect() when a non-null config is passed. - */ - @Test - public void testConnectWithConfig() { - ConfigRequest configRequest = new ConfigRequest.Builder().setMasterPreference(55).build(); - String callingPackage = "com.google.somePackage"; - String callingFeatureId = "com.google.someFeature"; - - mDut.connect(mBinderMock, callingPackage, callingFeatureId, mCallbackMock, - configRequest, false); - - verify(mAwareStateManagerMock).connect(anyInt(), anyInt(), anyInt(), eq(callingPackage), - eq(callingFeatureId), eq(mCallbackMock), eq(configRequest), eq(false)); - } - - /** - * Validate disconnect() - correct pass-through args. - * - * @throws Exception - */ - @Test - public void testDisconnect() throws Exception { - int clientId = doConnect(); - - mDut.disconnect(clientId, mBinderMock); - - verify(mAwareStateManagerMock).disconnect(clientId); - validateInternalStateCleanedUp(clientId); - } - - /** - * Validate that security exception thrown when attempting operation using - * an invalid client ID. - */ - @Test(expected = SecurityException.class) - public void testFailOnInvalidClientId() { - mDut.disconnect(-1, mBinderMock); - } - - /** - * Validate that security exception thrown when attempting operation using a - * client ID which was already cleared-up. - */ - @Test(expected = SecurityException.class) - public void testFailOnClearedUpClientId() throws Exception { - int clientId = doConnect(); - - mDut.disconnect(clientId, mBinderMock); - - verify(mAwareStateManagerMock).disconnect(clientId); - validateInternalStateCleanedUp(clientId); - - mDut.disconnect(clientId, mBinderMock); - } - - /** - * Validate that trying to use a client ID from a UID which is different - * from the one that created it fails - and that the internal state is not - * modified so that a valid call (from the correct UID) will subsequently - * succeed. - */ - @Test - public void testFailOnAccessClientIdFromWrongUid() throws Exception { - int clientId = doConnect(); - - mDut.fakeUid = mDefaultUid + 1; - - /* - * Not using thrown.expect(...) since want to test that subsequent - * access works. - */ - boolean failsAsExpected = false; - try { - mDut.disconnect(clientId, mBinderMock); - } catch (SecurityException e) { - failsAsExpected = true; - } - - mDut.fakeUid = mDefaultUid; - - PublishConfig publishConfig = new PublishConfig.Builder().setServiceName("valid.value") - .build(); - mDut.publish(mPackageName, mFeatureId, clientId, publishConfig, mSessionCallbackMock); - - verify(mAwareStateManagerMock).publish(clientId, publishConfig, mSessionCallbackMock); - assertTrue("SecurityException for invalid access from wrong UID thrown", failsAsExpected); - } - - /** - * Validate that the RTT feature support is checked when attempting a Publish with ranging. - */ - @Test(expected = IllegalArgumentException.class) - public void testFailOnPublishRangingWithoutRttFeature() throws Exception { - when(mPackageManagerMock.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn( - false); - - PublishConfig publishConfig = new PublishConfig.Builder().setServiceName("something.valid") - .setRangingEnabled(true).build(); - int clientId = doConnect(); - IWifiAwareDiscoverySessionCallback mockCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - - mDut.publish(mPackageName, mFeatureId, clientId, publishConfig, mockCallback); - } - - /** - * Validate that the RTT feature support is checked when attempting a Subscribe with ranging. - */ - @Test(expected = IllegalArgumentException.class) - public void testFailOnSubscribeRangingWithoutRttFeature() throws Exception { - when(mPackageManagerMock.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn( - false); - - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName( - "something.valid").setMaxDistanceMm(100).build(); - int clientId = doConnect(); - IWifiAwareDiscoverySessionCallback mockCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - - mDut.subscribe(mPackageName, mFeatureId, clientId, subscribeConfig, mockCallback); - } - - - /** - * Validates that on binder death we get a disconnect(). - */ - @Test - public void testBinderDeath() throws Exception { - ArgumentCaptor<IBinder.DeathRecipient> deathRecipient = ArgumentCaptor - .forClass(IBinder.DeathRecipient.class); - - int clientId = doConnect(); - - verify(mBinderMock).linkToDeath(deathRecipient.capture(), eq(0)); - deathRecipient.getValue().binderDied(); - verify(mAwareStateManagerMock).disconnect(clientId); - validateInternalStateCleanedUp(clientId); - } - - /** - * Validates that sequential connect() calls return increasing client IDs. - */ - @Test - public void testClientIdIncrementing() { - int loopCount = 100; - - InOrder inOrder = inOrder(mAwareStateManagerMock); - ArgumentCaptor<Integer> clientIdCaptor = ArgumentCaptor.forClass(Integer.class); - - int prevId = 0; - for (int i = 0; i < loopCount; ++i) { - mDut.connect(mBinderMock, "", "", mCallbackMock, null, false); - inOrder.verify(mAwareStateManagerMock).connect(clientIdCaptor.capture(), anyInt(), - anyInt(), any(), any(), eq(mCallbackMock), any(), eq(false)); - int id = clientIdCaptor.getValue(); - if (i != 0) { - assertTrue("Client ID incrementing", id > prevId); - } - prevId = id; - } - } - - /** - * Validate terminateSession() - correct pass-through args. - */ - @Test - public void testTerminateSession() { - int sessionId = 1024; - int clientId = doConnect(); - - mDut.terminateSession(clientId, sessionId); - - verify(mAwareStateManagerMock).terminateSession(clientId, sessionId); - } - - /** - * Validate publish() - correct pass-through args. - */ - @Test - public void testPublish() { - PublishConfig publishConfig = new PublishConfig.Builder().setServiceName("something.valid") - .setRangingEnabled(true).build(); - int clientId = doConnect(); - IWifiAwareDiscoverySessionCallback mockCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - - mDut.publish(mPackageName, mFeatureId, clientId, publishConfig, mockCallback); - - verify(mAwareStateManagerMock).publish(clientId, publishConfig, mockCallback); - } - - /** - * Validate that publish() verifies the input PublishConfig and fails on an invalid service - * name. - */ - @Test(expected = IllegalArgumentException.class) - public void testPublishInvalidServiceName() { - doBadPublishConfiguration("Including invalid characters - spaces", null, null); - } - - /** - * Validate that publish() verifies the input PublishConfig and fails on a "very long" - * service name. - */ - @Test(expected = IllegalArgumentException.class) - public void testPublishServiceNameTooLong() { - byte[] byteArray = new byte[MAX_LENGTH + 1]; - for (int i = 0; i < MAX_LENGTH + 1; ++i) { - byteArray[i] = 'a'; - } - doBadPublishConfiguration(new String(byteArray), null, null); - } - - /** - * Validate that publish() verifies the input PublishConfig and fails on a "very long" ssi. - */ - @Test(expected = IllegalArgumentException.class) - public void testPublishSsiTooLong() { - doBadPublishConfiguration("correctservicename", new byte[MAX_LENGTH + 1], null); - } - - /** - * Validate that publish() verifies the input PublishConfig and fails on a "very long" match - * filter. - */ - @Test(expected = IllegalArgumentException.class) - public void testPublishMatchFilterTooLong() { - doBadPublishConfiguration("correctservicename", null, new byte[MAX_LENGTH + 1]); - } - - /** - * Validate that publish() verifies the input PublishConfig and fails on a bad match filter - - * invalid LV. - */ - @Test(expected = IllegalArgumentException.class) - public void testPublishMatchFilterBadLv() { - byte[] badLv = { 0, 1, 127, 2, 126, 125, 3 }; - doBadPublishConfiguration("correctservicename", null, badLv); - } - - /** - * Validate updatePublish() - correct pass-through args. - */ - @Test - public void testUpdatePublish() { - int sessionId = 1232; - PublishConfig publishConfig = new PublishConfig.Builder().setServiceName("something.valid") - .build(); - int clientId = doConnect(); - - mDut.updatePublish(clientId, sessionId, publishConfig); - - verify(mAwareStateManagerMock).updatePublish(clientId, sessionId, publishConfig); - } - - /** - * Validate updatePublish() error checking. - */ - @Test(expected = IllegalArgumentException.class) - public void testUpdatePublishInvalid() { - int sessionId = 1232; - PublishConfig publishConfig = new PublishConfig.Builder() - .setServiceName("something with spaces").build(); - int clientId = doConnect(); - - mDut.updatePublish(clientId, sessionId, publishConfig); - - verify(mAwareStateManagerMock).updatePublish(clientId, sessionId, publishConfig); - } - - /** - * Validate subscribe() - correct pass-through args. - */ - @Test - public void testSubscribe() { - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder() - .setServiceName("something.valid").setMaxDistanceMm(100).build(); - int clientId = doConnect(); - IWifiAwareDiscoverySessionCallback mockCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - - mDut.subscribe(mPackageName, mFeatureId, clientId, subscribeConfig, mockCallback); - - verify(mAwareStateManagerMock).subscribe(clientId, subscribeConfig, mockCallback); - } - - /** - * Validate that subscribe() verifies the input SubscribeConfig and fails on an invalid service - * name. - */ - @Test(expected = IllegalArgumentException.class) - public void testSubscribeInvalidServiceName() { - doBadSubscribeConfiguration("Including invalid characters - spaces", null, null); - } - - /** - * Validate that subscribe() verifies the input SubscribeConfig and fails on a "very long" - * service name. - */ - @Test(expected = IllegalArgumentException.class) - public void testSubscribeServiceNameTooLong() { - byte[] byteArray = new byte[MAX_LENGTH + 1]; - for (int i = 0; i < MAX_LENGTH + 1; ++i) { - byteArray[i] = 'a'; - } - doBadSubscribeConfiguration(new String(byteArray), null, null); - } - - /** - * Validate that subscribe() verifies the input SubscribeConfig and fails on a "very long" ssi. - */ - @Test(expected = IllegalArgumentException.class) - public void testSubscribeSsiTooLong() { - doBadSubscribeConfiguration("correctservicename", new byte[MAX_LENGTH + 1], null); - } - - /** - * Validate that subscribe() verifies the input SubscribeConfig and fails on a "very long" match - * filter. - */ - @Test(expected = IllegalArgumentException.class) - public void testSubscribeMatchFilterTooLong() { - doBadSubscribeConfiguration("correctservicename", null, new byte[MAX_LENGTH + 1]); - } - - /** - * Validate that subscribe() verifies the input SubscribeConfig and fails on a bad match filter - * - invalid LV. - */ - @Test(expected = IllegalArgumentException.class) - public void testSubscribeMatchFilterBadLv() { - byte[] badLv = { 0, 1, 127, 2, 126, 125, 3 }; - doBadSubscribeConfiguration("correctservicename", null, badLv); - } - - /** - * Validate updateSubscribe() error checking. - */ - @Test(expected = IllegalArgumentException.class) - public void testUpdateSubscribeInvalid() { - int sessionId = 1232; - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder() - .setServiceName("something.valid") - .setServiceSpecificInfo(new byte[MAX_LENGTH + 1]).build(); - int clientId = doConnect(); - - mDut.updateSubscribe(clientId, sessionId, subscribeConfig); - - verify(mAwareStateManagerMock).updateSubscribe(clientId, sessionId, subscribeConfig); - } - - /** - * Validate updateSubscribe() validates configuration. - */ - @Test - public void testUpdateSubscribe() { - int sessionId = 1232; - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder() - .setServiceName("something.valid").build(); - int clientId = doConnect(); - - mDut.updateSubscribe(clientId, sessionId, subscribeConfig); - - verify(mAwareStateManagerMock).updateSubscribe(clientId, sessionId, subscribeConfig); - } - - /** - * Validate sendMessage() - correct pass-through args. - */ - @Test - public void testSendMessage() { - int sessionId = 2394; - int peerId = 2032; - byte[] message = new byte[MAX_LENGTH]; - int messageId = 2043; - int clientId = doConnect(); - - mDut.sendMessage(clientId, sessionId, peerId, message, messageId, 0); - - verify(mAwareStateManagerMock).sendMessage(anyInt(), eq(clientId), eq(sessionId), - eq(peerId), eq(message), eq(messageId), eq(0)); - } - - /** - * Validate sendMessage() validates that message length is correct. - */ - @Test(expected = IllegalArgumentException.class) - public void testSendMessageTooLong() { - int sessionId = 2394; - int peerId = 2032; - byte[] message = new byte[MAX_LENGTH + 1]; - int messageId = 2043; - int clientId = doConnect(); - - mDut.sendMessage(clientId, sessionId, peerId, message, messageId, 0); - - verify(mAwareStateManagerMock).sendMessage(anyInt(), eq(clientId), eq(sessionId), - eq(peerId), eq(message), eq(messageId), eq(0)); - } - - @Test - public void testRequestMacAddress() { - int uid = 1005; - List<Integer> list = new ArrayList<>(); - IWifiAwareMacAddressProvider callback = new IWifiAwareMacAddressProvider() { // dummy - @Override - public void macAddress(Map peerIdToMacMap) throws RemoteException { - // empty - } - - @Override - public IBinder asBinder() { - return null; - } - }; - - mDut.requestMacAddresses(uid, list, callback); - - verify(mAwareStateManagerMock).requestMacAddresses(uid, list, callback); - } - - @Test(expected = SecurityException.class) - public void testRequestMacAddressWithoutPermission() { - doThrow(new SecurityException()).when(mContextMock).enforceCallingOrSelfPermission( - eq(Manifest.permission.NETWORK_STACK), anyString()); - - mDut.requestMacAddresses(1005, new ArrayList<>(), new IWifiAwareMacAddressProvider() { - @Override - public void macAddress(Map peerIdToMacMap) throws RemoteException { - } - - @Override - public IBinder asBinder() { - return null; - } - }); - } - - @Test - public void testCapabilityTranslation() { - final int maxServiceName = 66; - final int maxServiceSpecificInfo = 69; - final int maxMatchFilter = 55; - - Capabilities cap = new Capabilities(); - cap.maxConcurrentAwareClusters = 1; - cap.maxPublishes = 2; - cap.maxSubscribes = 2; - cap.maxServiceNameLen = maxServiceName; - cap.maxMatchFilterLen = maxMatchFilter; - cap.maxTotalMatchFilterLen = 255; - cap.maxServiceSpecificInfoLen = maxServiceSpecificInfo; - cap.maxExtendedServiceSpecificInfoLen = MAX_LENGTH; - cap.maxNdiInterfaces = 1; - cap.maxNdpSessions = 1; - cap.maxAppInfoLen = 255; - cap.maxQueuedTransmitMessages = 6; - cap.supportedCipherSuites = NanCipherSuiteType.SHARED_KEY_256_MASK; - - Characteristics characteristics = cap.toPublicCharacteristics(); - assertEquals(characteristics.getMaxServiceNameLength(), maxServiceName); - assertEquals(characteristics.getMaxServiceSpecificInfoLength(), maxServiceSpecificInfo); - assertEquals(characteristics.getMaxMatchFilterLength(), maxMatchFilter); - assertEquals(characteristics.getSupportedCipherSuites(), - Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256); - } - - /* - * Utilities - */ - - /* - * Tests of internal state of WifiAwareServiceImpl: very limited (not usually - * a good idea). However, these test that the internal state is cleaned-up - * appropriately. Alternatively would cause issues with memory leaks or - * information leak between sessions. - */ - private void validateInternalStateCleanedUp(int clientId) throws Exception { - int uidEntry = getInternalStateUid(clientId); - assertEquals(-1, uidEntry); - - IBinder.DeathRecipient dr = getInternalStateDeathRecipient(clientId); - assertEquals(null, dr); - } - - private void doBadPublishConfiguration(String serviceName, byte[] ssi, byte[] matchFilter) - throws IllegalArgumentException { - // using the hidden constructor since may be passing invalid parameters which would be - // caught by the Builder. Want to test whether service side will catch invalidly - // constructed configs. - PublishConfig publishConfig = new PublishConfig(serviceName.getBytes(), ssi, matchFilter, - PublishConfig.PUBLISH_TYPE_UNSOLICITED, 0, true, false); - int clientId = doConnect(); - IWifiAwareDiscoverySessionCallback mockCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - - mDut.publish(mPackageName, mFeatureId, clientId, publishConfig, mockCallback); - - verify(mAwareStateManagerMock).publish(clientId, publishConfig, mockCallback); - } - - private void doBadSubscribeConfiguration(String serviceName, byte[] ssi, byte[] matchFilter) - throws IllegalArgumentException { - // using the hidden constructor since may be passing invalid parameters which would be - // caught by the Builder. Want to test whether service side will catch invalidly - // constructed configs. - SubscribeConfig subscribeConfig = new SubscribeConfig(serviceName.getBytes(), ssi, - matchFilter, SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE, 0, true, false, 0, false, 0); - int clientId = doConnect(); - IWifiAwareDiscoverySessionCallback mockCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - - mDut.subscribe(mPackageName, mFeatureId, clientId, subscribeConfig, mockCallback); - - verify(mAwareStateManagerMock).subscribe(clientId, subscribeConfig, mockCallback); - } - - private int doConnect() { - String callingPackage = "com.google.somePackage"; - String callingFeatureId = "com.google.someFeature"; - - mDut.connect(mBinderMock, callingPackage, callingFeatureId, mCallbackMock, null, false); - - ArgumentCaptor<Integer> clientId = ArgumentCaptor.forClass(Integer.class); - verify(mAwareStateManagerMock).connect(clientId.capture(), anyInt(), anyInt(), - eq(callingPackage), eq(callingFeatureId), eq(mCallbackMock), - eq(new ConfigRequest.Builder().build()), eq(false)); - - return clientId.getValue(); - } - - private static Characteristics getCharacteristics() { - Capabilities cap = new Capabilities(); - cap.maxConcurrentAwareClusters = 1; - cap.maxPublishes = 2; - cap.maxSubscribes = 2; - cap.maxServiceNameLen = MAX_LENGTH; - cap.maxMatchFilterLen = MAX_LENGTH; - cap.maxTotalMatchFilterLen = 255; - cap.maxServiceSpecificInfoLen = MAX_LENGTH; - cap.maxExtendedServiceSpecificInfoLen = MAX_LENGTH; - cap.maxNdiInterfaces = 1; - cap.maxNdpSessions = 1; - cap.maxAppInfoLen = 255; - cap.maxQueuedTransmitMessages = 6; - cap.supportedCipherSuites = NanCipherSuiteType.SHARED_KEY_256_MASK; - return cap.toPublicCharacteristics(); - } - - private int getInternalStateUid(int clientId) throws Exception { - Field field = WifiAwareServiceImpl.class.getDeclaredField("mUidByClientId"); - field.setAccessible(true); - @SuppressWarnings("unchecked") - SparseIntArray uidByClientId = (SparseIntArray) field.get(mDut); - - return uidByClientId.get(clientId, -1); - } - - private IBinder.DeathRecipient getInternalStateDeathRecipient(int clientId) throws Exception { - Field field = WifiAwareServiceImpl.class.getDeclaredField("mDeathRecipientsByClientId"); - field.setAccessible(true); - @SuppressWarnings("unchecked") - SparseArray<IBinder.DeathRecipient> deathRecipientsByClientId = - (SparseArray<IBinder.DeathRecipient>) field.get(mDut); - - return deathRecipientsByClientId.get(clientId); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java deleted file mode 100644 index 7292fca36..000000000 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java +++ /dev/null @@ -1,3872 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.aware; - -import static android.hardware.wifi.V1_0.NanRangingIndication.EGRESS_MET_MASK; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.hamcrest.core.IsNull.notNullValue; -import static org.hamcrest.core.IsNull.nullValue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyByte; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyShort; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.AppOpsManager; -import android.app.test.MockAnswerUtil; -import android.app.test.TestAlarmManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.hardware.wifi.V1_0.NanRangingIndication; -import android.hardware.wifi.V1_0.NanStatusType; -import android.location.LocationManager; -import android.net.ConnectivityManager; -import android.net.wifi.WifiManager; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; -import android.net.wifi.aware.IWifiAwareEventCallback; -import android.net.wifi.aware.IWifiAwareMacAddressProvider; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.net.wifi.aware.WifiAwareManager; -import android.net.wifi.util.HexEncoding; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.test.TestLooper; -import android.util.Log; -import android.util.SparseArray; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; - - -/** - * Unit test harness for WifiAwareStateManager. - */ -@SmallTest -public class WifiAwareStateManagerTest extends WifiBaseTest { - private TestLooper mMockLooper; - private Random mRandomNg = new Random(15687); - private WifiAwareStateManager mDut; - @Mock private WifiAwareNativeManager mMockNativeManager; - @Spy private TestUtils.MonitoredWifiAwareNativeApi mMockNative = - new TestUtils.MonitoredWifiAwareNativeApi(); - @Mock private Context mMockContext; - @Mock private AppOpsManager mMockAppOpsManager; - @Mock private WifiAwareMetrics mAwareMetricsMock; - @Mock private WifiPermissionsUtil mWifiPermissionsUtil; - @Mock private WifiPermissionsWrapper mPermissionsWrapperMock; - TestAlarmManager mAlarmManager; - @Mock private PowerManager mMockPowerManager; - @Mock private WifiManager mMockWifiManager; - private BroadcastReceiver mPowerBcastReceiver; - private BroadcastReceiver mLocationModeReceiver; - private BroadcastReceiver mWifiStateChangedReceiver; - @Mock private WifiAwareDataPathStateManager mMockAwareDataPathStatemanager; - - @Rule - public ErrorCollector collector = new ErrorCollector(); - - private static final byte[] ALL_ZERO_MAC = new byte[] {0, 0, 0, 0, 0, 0}; - - /** - * Pre-test configuration. Initialize and install mocks. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mAlarmManager = new TestAlarmManager(); - when(mMockContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - - when(mMockContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager); - when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED); - - mMockLooper = new TestLooper(); - - when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn( - mock(ConnectivityManager.class)); - when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOpsManager); - when(mMockContext.getSystemServiceName(PowerManager.class)).thenReturn( - Context.POWER_SERVICE); - when(mMockContext.getSystemService(PowerManager.class)).thenReturn(mMockPowerManager); - when(mMockContext.checkPermission(eq(android.Manifest.permission.ACCESS_FINE_LOCATION), - anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); - when(mMockAppOpsManager.noteOp(eq(AppOpsManager.OP_FINE_LOCATION), anyInt(), - any())).thenReturn(AppOpsManager.MODE_ERRORED); - when(mMockPowerManager.isDeviceIdleMode()).thenReturn(false); - when(mMockPowerManager.isInteractive()).thenReturn(true); - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); - when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); - - ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass( - BroadcastReceiver.class); - mDut = new WifiAwareStateManager(); - mDut.setNative(mMockNativeManager, mMockNative); - mDut.start(mMockContext, mMockLooper.getLooper(), mAwareMetricsMock, - mWifiPermissionsUtil, mPermissionsWrapperMock, new Clock(), - mock(NetdWrapper.class)); - mDut.startLate(); - mMockLooper.dispatchAll(); - verify(mMockContext, times(3)).registerReceiver(bcastRxCaptor.capture(), - any(IntentFilter.class)); - mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(0); - mLocationModeReceiver = bcastRxCaptor.getAllValues().get(1); - mWifiStateChangedReceiver = bcastRxCaptor.getAllValues().get(2); - installMocksInStateManager(mDut, mMockAwareDataPathStatemanager); - } - - /** - * Post-test validation. - */ - @After - public void tearDown() throws Exception { - mMockNative.validateUniqueTransactionIds(); - } - - /** - * Test that the set parameter shell command executor works when parameters are valid. - */ - @Test - public void testSetParameterShellCommandSuccess() { - setSettableParam(WifiAwareStateManager.PARAM_ON_IDLE_DISABLE_AWARE, Integer.toString(1), - true); - } - - /** - * Test that the set parameter shell command executor fails on incorrect name. - */ - @Test - public void testSetParameterShellCommandInvalidParameterName() { - setSettableParam("XXX", Integer.toString(1), false); - } - - /** - * Test that the set parameter shell command executor fails on invalid value (not convertible - * to an int). - */ - @Test - public void testSetParameterShellCommandInvalidValue() { - setSettableParam(WifiAwareStateManager.PARAM_ON_IDLE_DISABLE_AWARE, "garbage", false); - } - - /** - * Test the PeerHandle -> MAC address API: - * - Start up discovery of 2 sessions - * - Get multiple matches (PeerHandles) - * - Request translation as UID of sesssion #1 for PeerHandles of the same UID + of the other - * discovery session (to which we shouldn't have access) + invalid PeerHandle. - * -> validate results - */ - @Test - public void testRequestMacAddresses() throws Exception { - final int clientId1 = 1005; - final int clientId2 = 1006; - final int uid1 = 1000; - final int uid2 = 1001; - final int pid1 = 2000; - final int pid2 = 2001; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String serviceName = "some-service-name"; - final byte subscribeId1 = 15; - final byte subscribeId2 = 16; - final int requestorIdBase = 22; - final byte[] peerMac1 = HexEncoding.decode("060708090A0B".toCharArray(), false); - final byte[] peerMac2 = HexEncoding.decode("010203040506".toCharArray(), false); - final byte[] peerMac3 = HexEncoding.decode("AABBCCDDEEFF".toCharArray(), false); - final int distance = 10; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) - .build(); - - IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); - IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback1 = mock( - IWifiAwareDiscoverySessionCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback2 = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback1, mockCallback2, mockSessionCallback1, - mockSessionCallback2, mMockNative); - - // (0) enable - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect 2 clients - mDut.connect(clientId1, uid1, pid1, callingPackage, callingFeature, mockCallback1, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback1).onConnectSuccess(clientId1); - - mDut.connect(clientId2, uid2, pid2, callingPackage, callingFeature, mockCallback2, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback2).onConnectSuccess(clientId2); - - // (2) subscribe both clients - mDut.subscribe(clientId1, subscribeConfig, mockSessionCallback1); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId1); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback1).onSessionStarted(sessionId.capture()); - - mDut.subscribe(clientId2, subscribeConfig, mockSessionCallback2); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId2); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback2).onSessionStarted(sessionId.capture()); - - // (3) 2 matches on session 1 (second one with distance), 1 match on session 2 - mDut.onMatchNotification(subscribeId1, requestorIdBase, peerMac1, null, null, 0, 0); - mDut.onMatchNotification(subscribeId1, requestorIdBase + 1, peerMac2, null, null, - NanRangingIndication.INGRESS_MET_MASK, distance); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback1).onMatch(peerIdCaptor.capture(), isNull(), - isNull()); - inOrder.verify(mockSessionCallback1).onMatchWithDistance(peerIdCaptor.capture(), isNull(), - isNull(), eq(distance)); - int peerId1 = peerIdCaptor.getAllValues().get(0); - int peerId2 = peerIdCaptor.getAllValues().get(1); - - mDut.onMatchNotification(subscribeId2, requestorIdBase + 2, peerMac3, null, null, 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback2).onMatch(peerIdCaptor.capture(), isNull(), isNull()); - int peerId3 = peerIdCaptor.getAllValues().get(0); - - // request MAC addresses - List<Integer> request = new ArrayList<>(); - request.add(peerId1); - request.add(peerId2); - request.add(peerId3); // for uid2: so should not be in results - request.add(peerId1 * 20 + peerId2 + peerId3); // garbage values != to any - Mutable<Map> response = new Mutable<>(); - mDut.requestMacAddresses(uid1, request, new IWifiAwareMacAddressProvider() { - @Override - public void macAddress(Map peerIdToMacMap) throws RemoteException { - response.value = peerIdToMacMap; - } - - @Override - public IBinder asBinder() { - return null; - } - }); - mMockLooper.dispatchAll(); - - assertNotEquals("Non-null result", null, response.value); - assertEquals("Number of results", 2, response.value.size()); - assertEquals("Results[peerId1]", peerMac1, response.value.get(peerId1)); - assertEquals("Results[peerId2]", peerMac2, response.value.get(peerId2)); - } - - /** - * Validate that Aware data-path interfaces are brought up and down correctly. - */ - @Test - public void testAwareDataPathInterfaceUpDown() throws Exception { - final int clientId = 12341; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mMockContext, mMockNative, mMockAwareDataPathStatemanager, - mockCallback); - - // (1) enable usage - mDut.enableUsage(); - mMockLooper.dispatchAll(); - validateCorrectAwareStatusChangeBroadcast(inOrder); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - - // (2) connect (enable Aware) - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrder.verify(mMockAwareDataPathStatemanager).createAllInterfaces(); - - // (3) disconnect (disable Aware) - mDut.disconnect(clientId); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); - mMockLooper.dispatchAll(); - inOrder.verify(mMockAwareDataPathStatemanager).deleteAllInterfaces(); - - verifyNoMoreInteractions(mMockNative, mMockAwareDataPathStatemanager); - } - - /** - * Validate that APIs aren't functional when usage is disabled. - */ - @Test - public void testDisableUsageDisablesApis() throws Exception { - final int clientId = 12314; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - InOrder inOrder = inOrder(mMockContext, mMockNative, mockCallback); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - - // (1) check initial state - mDut.enableUsage(); - mMockLooper.dispatchAll(); - validateCorrectAwareStatusChangeBroadcast(inOrder); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - - // (2) disable usage and validate state - mDut.disableUsage(); - mMockLooper.dispatchAll(); - collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); - inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - // (3) try connecting and validate that get failure callback (though app should be aware of - // non-availability through state change broadcast and/or query API) - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectFail(anyInt()); - - verifyNoMoreInteractions(mMockNative, mockCallback); - } - - /** - * Validate that when API usage is disabled while in the middle of a connection that internal - * state is cleaned-up, and that all subsequent operations are NOP. Then enable usage again and - * validate that operates correctly. - */ - @Test - public void testDisableUsageFlow() throws Exception { - final int clientId = 12341; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<SparseArray> sparseArrayCaptor = ArgumentCaptor.forClass(SparseArray.class); - InOrder inOrder = inOrder(mMockContext, mMockNative, mockCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - // (1) check initial state - mDut.enableUsage(); - mMockLooper.dispatchAll(); - validateCorrectAwareStatusChangeBroadcast(inOrder); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - - // (2) connect (successfully) - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), - sparseArrayCaptor.capture()); - collector.checkThat("num of clients", sparseArrayCaptor.getValue().size(), equalTo(1)); - - // (3) disable usage & verify callbacks - mDut.disableUsage(); - mMockLooper.dispatchAll(); - collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); - inOrder.verify(mMockNative).disable(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordAttachSessionDuration(anyLong()); - inOrderM.verify(mAwareMetricsMock).recordDisableAware(); - inOrderM.verify(mAwareMetricsMock).recordDisableUsage(); - validateCorrectAwareStatusChangeBroadcast(inOrder); - validateInternalClientInfoCleanedUp(clientId); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); - mMockLooper.dispatchAll(); - inOrderM.verify(mAwareMetricsMock).recordDisableAware(); - - // (4) try connecting again and validate that get a failure - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectFail(anyInt()); - inOrderM.verify(mAwareMetricsMock).recordAttachStatus(NanStatusType.INTERNAL_FAILURE); - - // (5) disable usage again and validate that not much happens - mDut.disableUsage(); - mMockLooper.dispatchAll(); - collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); - - // (6) enable usage - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - // (7) connect (should be successful) - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), - sparseArrayCaptor.capture()); - collector.checkThat("num of clients", sparseArrayCaptor.getValue().size(), equalTo(1)); - - verifyNoMoreInteractions(mMockNative, mockCallback, mAwareMetricsMock); - } - - /** - * Validates that a HAL failure on enable and configure results in failed callback. - */ - @Test - public void testHalFailureEnableAndConfigure() throws Exception { - final int clientId = 12341; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mMockContext, mMockNative, mockCallback); - - when(mMockNative.enableAndConfigure(anyShort(), any(), anyBoolean(), - anyBoolean(), eq(true), eq(false), eq(false))).thenReturn(false); - - // (1) check initial state - mDut.enableUsage(); - mMockLooper.dispatchAll(); - validateCorrectAwareStatusChangeBroadcast(inOrder); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (2) connect with HAL failure - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - inOrder.verify(mockCallback).onConnectFail(NanStatusType.INTERNAL_FAILURE); - - validateInternalClientInfoCleanedUp(clientId); - verifyNoMoreInteractions(mMockNative, mockCallback); - } - - /** - * Validates that all events are delivered with correct arguments. Validates - * that IdentityChanged not delivered if configuration disables delivery. - */ - @Test - public void testAwareEventsDelivery() throws Exception { - final int clientId1 = 1005; - final int clientId2 = 1007; - final int clusterLow = 5; - final int clusterHigh = 100; - final int masterPref = 111; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int reason = NanStatusType.INTERNAL_FAILURE; - final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false); - final byte[] someMac2 = HexEncoding.decode("060708090A0B".toCharArray(), false); - - ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) - .setClusterHigh(clusterHigh).setMasterPreference(masterPref) - .build(); - - IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); - IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); - ArgumentCaptor<Short> transactionIdCapture = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mockCallback1, mockCallback2, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionIdCapture.capture()); - mDut.onCapabilitiesUpdateResponse(transactionIdCapture.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect 1st and 2nd clients - mDut.connect(clientId1, uid, pid, callingPackage, callingFeature, mockCallback1, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionIdCapture.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - short transactionId = transactionIdCapture.getValue(); - mDut.onConfigSuccessResponse(transactionId); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback1).onConnectSuccess(clientId1); - - mDut.connect(clientId2, uid, pid, callingPackage, callingFeature, mockCallback2, - configRequest, true); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionIdCapture.capture(), - eq(configRequest), eq(true), eq(false), eq(true), eq(false), eq(false)); - transactionId = transactionIdCapture.getValue(); - mDut.onConfigSuccessResponse(transactionId); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback2).onConnectSuccess(clientId2); - - // (2) deliver Aware events - without LOCATIONING permission - mDut.onClusterChangeNotification(WifiAwareClientState.CLUSTER_CHANGE_EVENT_STARTED, - someMac); - mDut.onInterfaceAddressChangeNotification(someMac); - mMockLooper.dispatchAll(); - - inOrder.verify(mockCallback2).onIdentityChanged(ALL_ZERO_MAC); - - // (3) deliver new identity - still without LOCATIONING permission (should get an event) - mDut.onInterfaceAddressChangeNotification(someMac2); - mMockLooper.dispatchAll(); - - inOrder.verify(mockCallback2).onIdentityChanged(ALL_ZERO_MAC); - - // (4) deliver same identity - still without LOCATIONING permission (should - // not get an event) - mDut.onInterfaceAddressChangeNotification(someMac2); - mMockLooper.dispatchAll(); - - // (5) deliver new identity - with LOCATIONING permission - when(mWifiPermissionsUtil.checkCallersLocationPermission(eq(callingPackage), - eq(callingFeature), eq(uid), anyBoolean(), any())).thenReturn(true); - mDut.onInterfaceAddressChangeNotification(someMac); - mMockLooper.dispatchAll(); - - inOrder.verify(mockCallback2).onIdentityChanged(someMac); - - // (6) Aware down (no feedback) - mDut.onAwareDownNotification(reason); - mMockLooper.dispatchAll(); - - validateInternalClientInfoCleanedUp(clientId1); - validateInternalClientInfoCleanedUp(clientId2); - - verifyNoMoreInteractions(mockCallback1, mockCallback2, mMockNative); - } - - /** - * Validate that when the HAL doesn't respond we get a TIMEOUT (which - * results in a failure response) at which point we can process additional - * commands. Steps: (1) connect, (2) publish - timeout, (3) publish + - * success. - */ - @Test - public void testHalNoResponseTimeout() throws Exception { - final int clientId = 12341; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - final PublishConfig publishConfig = new PublishConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect (successfully) - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (2) publish + timeout - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(anyShort(), eq((byte) 0), eq(publishConfig)); - assertTrue(mAlarmManager.dispatch(WifiAwareStateManager.HAL_COMMAND_TIMEOUT_TAG)); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, - NanStatusType.INTERNAL_FAILURE, true); - validateInternalNoSessions(clientId); - - // (3) publish + success - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, (byte) 99); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); - - verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback, mAwareMetricsMock); - } - - /** - * Validates publish flow: (1) initial publish (2) fail informed by notification, (3) fail due - * to immediate HAL failure. Expected: get a failure callback. - */ - @Test - public void testPublishFail() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - PublishConfig publishConfig = new PublishConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (1) initial publish - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - - // (2) publish failure callback (i.e. firmware tried and failed) - mDut.onSessionConfigFailResponse(transactionId.getValue(), true, reasonFail); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, true); - validateInternalNoSessions(clientId); - - // (3) publish and get immediate failure (i.e. HAL failed) - when(mMockNative.publish(anyShort(), anyByte(), any())).thenReturn(false); - - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - - inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, true); - validateInternalNoSessions(clientId); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); - } - - /** - * Validates the publish flow: (1) initial publish (2) success (3) - * termination (e.g. DONE) (4) update session attempt (5) terminateSession - * (6) update session attempt. Expected: session ID callback + session - * cleaned-up. - */ - @Test - public void testPublishSuccessTerminated() throws Exception { - final int clientId = 2005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int reasonTerminate = NanStatusType.SUCCESS; - final byte publishId = 15; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - PublishConfig publishConfig = new PublishConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (1) initial publish - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - - // (2) publish success - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); - - // (3) publish termination (from firmware - not app!) - mDut.onSessionTerminatedNotification(publishId, reasonTerminate, true); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionTerminated(reasonTerminate); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionDuration(anyLong(), eq(true)); - - // (4) app update session (race condition: app didn't get termination - // yet) - mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); - mMockLooper.dispatchAll(); - - // (5) app terminates session - mDut.terminateSession(clientId, sessionId.getValue()); - mMockLooper.dispatchAll(); - - // (6) app updates session (app already knows that terminated - will get - // a local FAIL). - mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); - mMockLooper.dispatchAll(); - - validateInternalSessionInfoCleanedUp(clientId, sessionId.getValue()); - - verifyNoMoreInteractions(mockSessionCallback, mMockNative, mAwareMetricsMock); - } - - /** - * Validate the publish flow: (1) initial publish + (2) success + (3) update + (4) update - * fails (callback from firmware) + (5) update + (6). Expected: session is still alive after - * update failure so second update succeeds (no callbacks) + (7) update + immediate failure from - * HAL + (8) update + failure for invalid ID (which should clean-up state) + (9) another update - * - should get no response. - */ - @Test - public void testPublishUpdateFail() throws Exception { - final int clientId = 2005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final byte publishId = 15; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - PublishConfig publishConfig = new PublishConfig.Builder().setRangingEnabled(true).build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (1) initial publish - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - - // (2) publish success - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(false), - eq(-1), eq(-1), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); - mMockLooper.dispatchAll(); - // Verify reconfigure aware to enable ranging. - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(false), eq(true), eq(false), eq(true)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - // (3) update publish - mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId), - eq(publishConfig)); - - // (4) update fails - mDut.onSessionConfigFailResponse(transactionId.getValue(), true, reasonFail); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, true); - - // (5) another update publish - mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId), - eq(publishConfig)); - - // (6) update succeeds - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigSuccess(); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); - - // (7) another update + immediate failure - when(mMockNative.publish(anyShort(), anyByte(), any())).thenReturn(false); - - mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId), - eq(publishConfig)); - inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, true); - - // (8) an update with bad ID failure - when(mMockNative.publish(anyShort(), anyByte(), any())).thenReturn(true); - - mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId), - eq(publishConfig)); - mDut.onSessionConfigFailResponse(transactionId.getValue(), true, - NanStatusType.INVALID_SESSION_ID); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INVALID_SESSION_ID); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, - NanStatusType.INVALID_SESSION_ID, true); - // Verify reconfigure aware to disable ranging. - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(false), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - // (9) try updating again - do nothing/get nothing - mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); - mMockLooper.dispatchAll(); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); - } - - /** - * Validate race condition: publish pending but session terminated (due to - * disconnect - can't terminate such a session directly from app). Need to - * make sure that once publish succeeds (failure isn't a problem) the - * session is immediately terminated since no-one is listening for it. - */ - @Test - public void testDisconnectWhilePublishPending() throws Exception { - final int clientId = 2005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final byte publishId = 15; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - PublishConfig publishConfig = new PublishConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (1) initial publish - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - - // (2) disconnect (but doesn't get executed until get response for - // publish command) - mDut.disconnect(clientId); - mMockLooper.dispatchAll(); - - // (3) publish success - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); - inOrder.verify(mMockNative).stopPublish(transactionId.capture(), eq(publishId)); - inOrder.verify(mMockNative).disable(anyShort()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); - inOrderM.verify(mAwareMetricsMock).recordAttachSessionDuration(anyLong()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionDuration(anyLong(), eq(true)); - - validateInternalClientInfoCleanedUp(clientId); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); - } - - /** - * Validates subscribe flow: (1) initial subscribe (2) fail (callback from firmware), (3) fail - * due to immeidate HAL failure. Expected: get a failure callback. - */ - @Test - public void testSubscribeFail() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (1) initial subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - - // (2) subscribe failure - mDut.onSessionConfigFailResponse(transactionId.getValue(), false, reasonFail); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, false); - validateInternalNoSessions(clientId); - - // (3) subscribe and get immediate failure (i.e. HAL failed) - when(mMockNative.subscribe(anyShort(), anyByte(), any())) - .thenReturn(false); - - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - - inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, false); - validateInternalNoSessions(clientId); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); - } - - /** - * Validates the subscribe flow: (1) initial subscribe (2) success (3) - * termination (e.g. DONE) (4) update session attempt (5) terminateSession - * (6) update session attempt. Expected: session ID callback + session - * cleaned-up - */ - @Test - public void testSubscribeSuccessTerminated() throws Exception { - final int clientId = 2005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int reasonTerminate = NanStatusType.SUCCESS; - final byte subscribeId = 15; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (1) initial subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - - // (2) subscribe success - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); - - // (3) subscribe termination (from firmware - not app!) - mDut.onSessionTerminatedNotification(subscribeId, reasonTerminate, false); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionTerminated(reasonTerminate); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionDuration(anyLong(), eq(false)); - - // (4) app update session (race condition: app didn't get termination - // yet) - mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); - mMockLooper.dispatchAll(); - - // (5) app terminates session - mDut.terminateSession(clientId, sessionId.getValue()); - mMockLooper.dispatchAll(); - - // (6) app updates session - mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); - mMockLooper.dispatchAll(); - - validateInternalSessionInfoCleanedUp(clientId, sessionId.getValue()); - - verifyNoMoreInteractions(mockSessionCallback, mMockNative, mAwareMetricsMock); - } - - /** - * Validate the subscribe flow: (1) initial subscribe + (2) success + (3) update + (4) update - * fails (callback from firmware) + (5) update + (6). Expected: session is still alive after - * update failure so second update succeeds (no callbacks). + (7) update + immediate failure - * from HAL. - */ - @Test - public void testSubscribeUpdateFail() throws Exception { - final int clientId = 2005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final byte subscribeId = 15; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; - final int rangeMax = 10; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setMaxDistanceMm( - rangeMax).build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (1) initial subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - - // (2) subscribe success - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true), - eq(-1), eq(rangeMax), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); - // Verify reconfigure aware to enable ranging. - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(false), eq(true), eq(false), eq(true)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - // (3) update subscribe - mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(subscribeId), - eq(subscribeConfig)); - - // (4) update fails - mDut.onSessionConfigFailResponse(transactionId.getValue(), false, reasonFail); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, false); - - // (5) another update subscribe - mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(subscribeId), - eq(subscribeConfig)); - - // (6) update succeeds - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigSuccess(); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); - - // (7) another update + immediate failure - when(mMockNative.subscribe(anyShort(), anyByte(), any())) - .thenReturn(false); - - mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(subscribeId), - eq(subscribeConfig)); - inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, false); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); - } - - /** - * Validate race condition: subscribe pending but session terminated (due to - * disconnect - can't terminate such a session directly from app). Need to - * make sure that once subscribe succeeds (failure isn't a problem) the - * session is immediately terminated since no-one is listening for it. - */ - @Test - public void testDisconnectWhileSubscribePending() throws Exception { - final int clientId = 2005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final byte subscribeId = 15; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (1) initial subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - - // (2) disconnect (but doesn't get executed until get response for - // subscribe command) - mDut.disconnect(clientId); - mMockLooper.dispatchAll(); - - // (3) subscribe success - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); - inOrder.verify(mMockNative).stopSubscribe((short) 0, subscribeId); - inOrder.verify(mMockNative).disable(anyShort()); - - validateInternalClientInfoCleanedUp(clientId); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); - } - - /** - * Validate (1) subscribe (success), (2) match (i.e. discovery), (3) message reception, - * (4) message transmission failed (after ok queuing), (5) message transmission success. - */ - @Test - public void testMatchAndMessages() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String serviceName = "some-service-name"; - final String ssi = "some much longer and more arbitrary data"; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; - final byte subscribeId = 15; - final int requestorId = 22; - final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); - final String peerSsi = "some peer ssi data"; - final String peerMatchFilter = "filter binary array represented as string"; - final String peerMsg = "some message from peer"; - final int messageId = 6948; - final int messageId2 = 6949; - final int rangeMin = 0; - final int rangeMax = 55; - final int rangedDistance = 30; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) - .setServiceSpecificInfo(ssi.getBytes()) - .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE) - .setMinDistanceMm(rangeMin) - .setMaxDistanceMm(rangeMax) - .build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - InOrder inOrderM = inOrder(mAwareMetricsMock); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); - - // (1) subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true), - eq(rangeMin), eq(rangeMax), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); - // Verify reconfigure aware to enable ranging. - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(false), eq(true), eq(false), eq(true)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - - // (2) 2 matches : with and w/o range - mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), - peerMatchFilter.getBytes(), 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), eq(peerSsi.getBytes()), - eq(peerMatchFilter.getBytes())); - inOrderM.verify(mAwareMetricsMock).recordMatchIndicationForRangeEnabledSubscribe(false); - int peerId1 = peerIdCaptor.getValue(); - - mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), - peerMatchFilter.getBytes(), EGRESS_MET_MASK, rangedDistance); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMatchWithDistance(peerIdCaptor.capture(), - eq(peerSsi.getBytes()), eq(peerMatchFilter.getBytes()), eq(rangedDistance)); - inOrderM.verify(mAwareMetricsMock).recordMatchIndicationForRangeEnabledSubscribe(true); - int peerId2 = peerIdCaptor.getValue(); - - assertEquals(peerId1, peerId2); - - // (3) message Rx - mDut.onMessageReceivedNotification(subscribeId, requestorId, peerMac, peerMsg.getBytes()); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.getValue(), - peerMsg.getBytes()); - - // (4) message Tx successful queuing - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - ssi.getBytes(), messageId, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); - short tid1 = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(tid1); - mMockLooper.dispatchAll(); - - // (5) message Tx successful queuing - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - ssi.getBytes(), messageId2, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId2)); - short tid2 = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(tid2); - mMockLooper.dispatchAll(); - - // (4) and (5) final Tx results (on-air results) - mDut.onMessageSendFailNotification(tid1, reasonFail); - mDut.onMessageSendSuccessNotification(tid2); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, reasonFail); - inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId2); - validateInternalSendMessageQueuesCleanedUp(messageId); - validateInternalSendMessageQueuesCleanedUp(messageId2); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); - } - - /** - * Summary: in a single publish session interact with multiple peers - * (different MAC addresses). - */ - @Test - public void testMultipleMessageSources() throws Exception { - final int clientId = 300; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int clusterLow = 7; - final int clusterHigh = 7; - final int masterPref = 0; - final String serviceName = "some-service-name"; - final byte publishId = 88; - final int requestorId1 = 568; - final int requestorId2 = 873; - final byte[] peerMac1 = HexEncoding.decode("000102030405".toCharArray(), false); - final byte[] peerMac2 = HexEncoding.decode("060708090A0B".toCharArray(), false); - final String msgFromPeer1 = "hey from 000102..."; - final String msgFromPeer2 = "hey from 0607..."; - final String msgToPeer1 = "hey there 000102..."; - final String msgToPeer2 = "hey there 0506..."; - final int msgToPeerId1 = 546; - final int msgToPeerId2 = 9654; - final int reason = NanStatusType.INTERNAL_FAILURE; - - ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) - .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); - - PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName) - .setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) publish - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - - // (3) message received from peers 1 & 2 - mDut.onMessageReceivedNotification(publishId, requestorId1, peerMac1, - msgFromPeer1.getBytes()); - mDut.onMessageReceivedNotification(publishId, requestorId2, peerMac2, - msgFromPeer2.getBytes()); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.capture(), - eq(msgFromPeer1.getBytes())); - int peerId1 = peerIdCaptor.getValue(); - inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.capture(), - eq(msgFromPeer2.getBytes())); - int peerId2 = peerIdCaptor.getValue(); - - // (4) sending messages back to same peers: one Tx fails, other succeeds - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerId2, msgToPeer2.getBytes(), - msgToPeerId2, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), - eq(requestorId2), eq(peerMac2), eq(msgToPeer2.getBytes()), eq(msgToPeerId2)); - short transactionIdVal = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(transactionIdVal); - mDut.onMessageSendSuccessNotification(transactionIdVal); - - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerId1, msgToPeer1.getBytes(), - msgToPeerId1, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId2); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), - eq(requestorId1), eq(peerMac1), eq(msgToPeer1.getBytes()), eq(msgToPeerId1)); - transactionIdVal = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(transactionIdVal); - mDut.onMessageSendFailNotification(transactionIdVal, reason); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendFail(msgToPeerId1, reason); - validateInternalSendMessageQueuesCleanedUp(msgToPeerId1); - validateInternalSendMessageQueuesCleanedUp(msgToPeerId2); - - verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); - } - - /** - * Summary: interact with a peer which changed its identity (MAC address) - * but which keeps its requestor instance ID. Should be transparent. - */ - @Test - public void testMessageWhilePeerChangesIdentity() throws Exception { - final int clientId = 300; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int clusterLow = 7; - final int clusterHigh = 7; - final int masterPref = 0; - final String serviceName = "some-service-name"; - final byte publishId = 88; - final int requestorId = 568; - final byte[] peerMacOrig = HexEncoding.decode("000102030405".toCharArray(), false); - final byte[] peerMacLater = HexEncoding.decode("060708090A0B".toCharArray(), false); - final String msgFromPeer1 = "hey from 000102..."; - final String msgFromPeer2 = "hey from 0607..."; - final String msgToPeer1 = "hey there 000102..."; - final String msgToPeer2 = "hey there 0506..."; - final int msgToPeerId1 = 546; - final int msgToPeerId2 = 9654; - ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) - .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); - - PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName) - .setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerId = ArgumentCaptor.forClass(Integer.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) publish - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - - // (3) message received & responded to - mDut.onMessageReceivedNotification(publishId, requestorId, peerMacOrig, - msgFromPeer1.getBytes()); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageReceived(peerId.capture(), - eq(msgFromPeer1.getBytes())); - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerId.getValue(), - msgToPeer1.getBytes(), msgToPeerId1, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), - eq(requestorId), eq(peerMacOrig), eq(msgToPeer1.getBytes()), - eq(msgToPeerId1)); - mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); - mDut.onMessageSendSuccessNotification(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId1); - validateInternalSendMessageQueuesCleanedUp(msgToPeerId1); - - // (4) message received with same peer ID but different MAC - mDut.onMessageReceivedNotification(publishId, requestorId, peerMacLater, - msgFromPeer2.getBytes()); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageReceived(peerId.capture(), - eq(msgFromPeer2.getBytes())); - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerId.getValue(), - msgToPeer2.getBytes(), msgToPeerId2, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), - eq(requestorId), eq(peerMacLater), eq(msgToPeer2.getBytes()), - eq(msgToPeerId2)); - mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); - mDut.onMessageSendSuccessNotification(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId2); - validateInternalSendMessageQueuesCleanedUp(msgToPeerId2); - - verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); - } - - /** - * Validate that get failure (with correct code) when trying to send a - * message to an invalid peer ID. - */ - @Test - public void testSendMessageToInvalidPeerId() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String ssi = "some much longer and more arbitrary data"; - final byte subscribeId = 15; - final int requestorId = 22; - final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); - final String peerSsi = "some peer ssi data"; - final String peerMatchFilter = "filter binary array represented as string"; - final int messageId = 6948; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) subscribe & match - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), - peerMatchFilter.getBytes(), 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), eq(peerSsi.getBytes()), - eq(peerMatchFilter.getBytes())); - - // (3) send message to invalid peer ID - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue() + 5, - ssi.getBytes(), messageId, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, - NanStatusType.INTERNAL_FAILURE); - validateInternalSendMessageQueuesCleanedUp(messageId); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); - } - - /** - * Validate that on send message errors are handled correctly: immediate send error, queue fail - * error (not queue full), and timeout. Behavior: correct callback is dispatched and a later - * firmware notification is ignored. Intersperse with one successfull transmission. - */ - @Test - public void testSendMessageErrorsImmediateQueueTimeout() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String ssi = "some much longer and more arbitrary data"; - final byte subscribeId = 15; - final int requestorId = 22; - final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); - final String peerSsi = "some peer ssi data"; - final String peerMatchFilter = "filter binary array represented as string"; - final int messageId = 6948; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) subscribe & match - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), - peerMatchFilter.getBytes(), 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), eq(peerSsi.getBytes()), - eq(peerMatchFilter.getBytes())); - - // (3) send 2 messages and enqueue successfully - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - ssi.getBytes(), messageId, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); - short transactionId1 = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(transactionId1); - mMockLooper.dispatchAll(); - - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - ssi.getBytes(), messageId + 1, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 1)); - short transactionId2 = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(transactionId2); - mMockLooper.dispatchAll(); - - // (4) send a message and get a queueing failure (not queue full) - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - ssi.getBytes(), messageId + 2, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 2)); - short transactionId3 = transactionId.getValue(); - mDut.onMessageSendQueuedFailResponse(transactionId3, NanStatusType.INTERNAL_FAILURE); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 2, - NanStatusType.INTERNAL_FAILURE); - validateInternalSendMessageQueuesCleanedUp(messageId + 2); - - // (5) send a message and get an immediate failure (configure first) - when(mMockNative.sendMessage(anyShort(), anyByte(), anyInt(), any(), - any(), anyInt())).thenReturn(false); - - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - ssi.getBytes(), messageId + 3, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 3)); - short transactionId4 = transactionId.getValue(); - inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 3, - NanStatusType.INTERNAL_FAILURE); - validateInternalSendMessageQueuesCleanedUp(messageId + 3); - - // (6) message send timeout - assertTrue(mAlarmManager.dispatch(WifiAwareStateManager.HAL_SEND_MESSAGE_TIMEOUT_TAG)); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, - NanStatusType.INTERNAL_FAILURE); - validateInternalSendMessageQueuesCleanedUp(messageId); - - // (7) firmware response (unlikely - but good to check) - mDut.onMessageSendSuccessNotification(transactionId1); - mDut.onMessageSendSuccessNotification(transactionId2); - - // bogus: these didn't even go to firmware or weren't queued - mDut.onMessageSendSuccessNotification(transactionId3); - mDut.onMessageSendFailNotification(transactionId4, NanStatusType.INTERNAL_FAILURE); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId + 1); - - validateInternalSendMessageQueuesCleanedUp(messageId + 1); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); - } - - /** - * Validate that when sending a message with a retry count the message is retried the specified - * number of times. Scenario ending with success. - */ - @Test - public void testSendMessageRetransmitSuccess() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String ssi = "some much longer and more arbitrary data"; - final byte subscribeId = 15; - final int requestorId = 22; - final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); - final String peerSsi = "some peer ssi data"; - final String peerMatchFilter = "filter binary array represented as string"; - final int messageId = 6948; - final int retryCount = 3; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) subscribe & match - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), - peerMatchFilter.getBytes(), 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), eq(peerSsi.getBytes()), - eq(peerMatchFilter.getBytes())); - - // (3) send message and enqueue successfully - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - ssi.getBytes(), messageId, retryCount); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); - mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - // (4) loop and fail until reach retryCount - for (int i = 0; i < retryCount; ++i) { - mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusType.NO_OTA_ACK); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); - mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - } - - // (5) succeed on last retry - mDut.onMessageSendSuccessNotification(transactionId.getValue()); - mMockLooper.dispatchAll(); - - inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); - validateInternalSendMessageQueuesCleanedUp(messageId); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); - } - - /** - * Validate that when sending a message with a retry count the message is retried the specified - * number of times. Scenario ending with failure. - */ - @Test - public void testSendMessageRetransmitFail() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String ssi = "some much longer and more arbitrary data"; - final byte subscribeId = 15; - final int requestorId = 22; - final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); - final String peerSsi = "some peer ssi data"; - final String peerMatchFilter = "filter binary array represented as string"; - final int messageId = 6948; - final int retryCount = 3; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) subscribe & match - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), - peerMatchFilter.getBytes(), 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), eq(peerSsi.getBytes()), - eq(peerMatchFilter.getBytes())); - - // (3) send message and enqueue successfully - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - ssi.getBytes(), messageId, retryCount); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); - mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - // (4) loop and fail until reach retryCount+1 - for (int i = 0; i < retryCount + 1; ++i) { - mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusType.NO_OTA_ACK); - mMockLooper.dispatchAll(); - - if (i != retryCount) { - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); - mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - } - } - - inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, - NanStatusType.NO_OTA_ACK); - validateInternalSendMessageQueuesCleanedUp(messageId); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); - } - - /** - * Validate that the host-side message queue functions. Tests the perfect case of queue always - * succeeds and all messages are received on first attempt. - */ - @Test - public void testSendMessageQueueSequence() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String serviceName = "some-service-name"; - final byte subscribeId = 15; - final int requestorId = 22; - final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); - final int messageIdBase = 6948; - final int numberOfMessages = 30; - final int queueDepth = 6; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) - .build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> messageIdCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (1) subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - - // (2) match - mDut.onMatchNotification(subscribeId, requestorId, peerMac, null, null, 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), isNull(), isNull()); - - // (3) transmit messages - SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth, - null, null, null); - when(mMockNative.sendMessage(anyShort(), anyByte(), anyInt(), any(), - any(), anyInt())).thenAnswer(answerObj); - - int remainingMessages = numberOfMessages; - for (int i = 0; i < numberOfMessages; ++i) { - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), null, - messageIdBase + i, 0); - mMockLooper.dispatchAll(); - // at 1/2 interval have the system simulate transmitting a queued message over-the-air - if (i % 2 == 1) { - assertTrue(answerObj.process()); - remainingMessages--; - mMockLooper.dispatchAll(); - } - } - for (int i = 0; i < remainingMessages; ++i) { - assertTrue(answerObj.process()); - mMockLooper.dispatchAll(); - } - assertEquals("queue empty", 0, answerObj.queueSize()); - - inOrder.verify(mockSessionCallback, times(numberOfMessages)).onMessageSendSuccess( - messageIdCaptor.capture()); - for (int i = 0; i < numberOfMessages; ++i) { - assertEquals("message ID: " + i, (long) messageIdBase + i, - (long) messageIdCaptor.getAllValues().get(i)); - } - - verifyNoMoreInteractions(mockCallback, mockSessionCallback); - } - - /** - * Validate that the message queue depth per process function. Tests the case - * with two processes both have message num larger than queue depth. And all messages get - * into the firmware queue are sent out and are received on first attempt. - */ - @Test - public void testSendMessageQueueLimitBlock() throws Exception { - final int clientId1 = 1005; - final int clientId2 = 1006; - final int uid1 = 1000; - final int uid2 = 1500; - final int pid1 = 2000; - final int pid2 = 3000; - final String callingPackage1 = "com.google.somePackage1"; - final String callingPackage2 = "com.google.somePackage2"; - final String callingFeature = "com.google.someFeature"; - final String serviceName1 = "some-service-name1"; - final String serviceName2 = "some-service-name2"; - final byte subscribeId1 = 15; - final byte subscribeId2 = 16; - final int requestorId1 = 22; - final int requestorId2 = 23; - final byte[] peerMac1 = HexEncoding.decode("060708090A0B".toCharArray(), false); - final byte[] peerMac2 = HexEncoding.decode("060708090A0C".toCharArray(), false); - final int messageIdBase1 = 6948; - final int messageIdBase2 = 7948; - final int numberOfMessages = 70; - final int queueDepth = 6; - final int messageQueueDepthPerUid = 50; - final int numOfReject = numberOfMessages - messageQueueDepthPerUid; - - ConfigRequest configRequest1 = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig1 = new SubscribeConfig.Builder() - .setServiceName(serviceName1).build(); - ConfigRequest configRequest2 = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig2 = new SubscribeConfig.Builder() - .setServiceName(serviceName2).build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId1 = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> sessionId2 = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> messageIdCaptorFail = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> messageIdCaptorSuccess = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor1 = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor2 = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId1, uid1, pid1, callingPackage1, callingFeature, mockCallback, - configRequest1, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest1), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId1); - - mDut.connect(clientId2, uid2, pid2, callingPackage2, callingFeature, mockCallback, - configRequest2, false); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId2); - - // (1) subscribe - mDut.subscribe(clientId1, subscribeConfig1, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig1)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId1); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId1.capture()); - - mDut.subscribe(clientId2, subscribeConfig2, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig2)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId2); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId2.capture()); - - // (2) match - mDut.onMatchNotification(subscribeId1, requestorId1, peerMac1, null, null, 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor1.capture(), isNull(), isNull()); - - mDut.onMatchNotification(subscribeId2, requestorId2, peerMac2, null, null, 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor2.capture(), isNull(), isNull()); - - // (3) Enqueue messages - SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth, - null, null, null); - when(mMockNative.sendMessage(anyShort(), anyByte(), anyInt(), any(), - any(), anyInt())).thenAnswer(answerObj); - - for (int i = 0; i < numberOfMessages; ++i) { - mDut.sendMessage(uid1, clientId1, sessionId1.getValue(), peerIdCaptor1.getValue(), null, - messageIdBase1 + i, 0); - } - for (int i = 0; i < numberOfMessages; ++i) { - mDut.sendMessage(uid2, clientId2, sessionId2.getValue(), peerIdCaptor2.getValue(), null, - messageIdBase2 + i, 0); - } - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback, times(numOfReject * 2)) - .onMessageSendFail(messageIdCaptorFail.capture(), - eq(NanStatusType.INTERNAL_FAILURE)); - - // (4) Transmit messages - int successNum = 0; - for (int i = 0; i < numberOfMessages * 2; ++i) { - if (answerObj.process()) { - successNum++; - } else { - break; - } - mMockLooper.dispatchAll(); - } - assertEquals("queue empty", 0, answerObj.queueSize()); - assertEquals("success message num", messageQueueDepthPerUid * 2, successNum); - inOrder.verify(mockSessionCallback, times(messageQueueDepthPerUid * 2)) - .onMessageSendSuccess(messageIdCaptorSuccess.capture()); - - for (int i = 0; i < numOfReject; ++i) { - assertEquals("message ID: " + i + messageQueueDepthPerUid, - messageIdBase1 + i + messageQueueDepthPerUid, - (int) messageIdCaptorFail.getAllValues().get(i)); - assertEquals("message ID: " + i + messageQueueDepthPerUid, - messageIdBase2 + i + messageQueueDepthPerUid, - (int) messageIdCaptorFail.getAllValues().get(i + numOfReject)); - } - - for (int i = 0; i < messageQueueDepthPerUid; ++i) { - assertEquals("message ID: " + i, messageIdBase1 + i, - (int) messageIdCaptorSuccess.getAllValues().get(i)); - assertEquals("message ID: " + i, messageIdBase2 + i, - (int) messageIdCaptorSuccess.getAllValues().get(i + messageQueueDepthPerUid)); - } - - verifyNoMoreInteractions(mockCallback, mockSessionCallback); - } - - /** - * Validate that the host-side message queue functions. A combination of imperfect conditions: - * - Failure to queue: synchronous firmware error - * - Failure to queue: asyncronous firmware error - * - Failure to transmit: OTA (which will be retried) - * - Failure to transmit: other - */ - @Test - public void testSendMessageQueueSequenceImperfect() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String serviceName = "some-service-name"; - final byte subscribeId = 15; - final int requestorId = 22; - final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); - final int messageIdBase = 6948; - final int numberOfMessages = 300; - final int queueDepth = 6; - final int retransmitCount = 3; // not the maximum - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) - .build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (1) subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - - // (2) match - mDut.onMatchNotification(subscribeId, requestorId, peerMac, null, null, 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), isNull(), isNull()); - - // (3) transmit messages: configure a mix of failures/success - Set<Integer> failQueueCommandImmediately = new HashSet<>(); - Set<Integer> failQueueCommandLater = new HashSet<>(); - Map<Integer, Integer> numberOfRetries = new HashMap<>(); - - int numOfSuccesses = 0; - int numOfFailuresInternalFailure = 0; - int numOfFailuresNoOta = 0; - for (int i = 0; i < numberOfMessages; ++i) { - // random results: - // - 0-50: success - // - 51-60: retransmit value (which will fail for >5) - // - 61-70: fail queue later - // - 71-80: fail queue immediately - // - 81-90: fail retransmit with non-OTA failure - int random = mRandomNg.nextInt(90); - if (random <= 50) { - numberOfRetries.put(messageIdBase + i, 0); - numOfSuccesses++; - } else if (random <= 60) { - numberOfRetries.put(messageIdBase + i, random - 51); - if (random - 51 > retransmitCount) { - numOfFailuresNoOta++; - } else { - numOfSuccesses++; - } - } else if (random <= 70) { - failQueueCommandLater.add(messageIdBase + i); - numOfFailuresInternalFailure++; - } else if (random <= 80) { - failQueueCommandImmediately.add(messageIdBase + i); - numOfFailuresInternalFailure++; - } else { - numberOfRetries.put(messageIdBase + i, -1); - numOfFailuresInternalFailure++; - } - } - - Log.v("WifiAwareStateManagerTest", - "failQueueCommandImmediately=" + failQueueCommandImmediately - + ", failQueueCommandLater=" + failQueueCommandLater + ", numberOfRetries=" - + numberOfRetries + ", numOfSuccesses=" + numOfSuccesses - + ", numOfFailuresInternalFailure=" + numOfFailuresInternalFailure - + ", numOfFailuresNoOta=" + numOfFailuresNoOta); - - SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth, - failQueueCommandImmediately, failQueueCommandLater, numberOfRetries); - when(mMockNative.sendMessage(anyShort(), anyByte(), anyInt(), any(), - any(), anyInt())).thenAnswer(answerObj); - - for (int i = 0; i < numberOfMessages; ++i) { - mDut.sendMessage(uid + i, clientId, sessionId.getValue(), peerIdCaptor.getValue(), null, - messageIdBase + i, retransmitCount); - mMockLooper.dispatchAll(); - } - - while (answerObj.queueSize() != 0) { - assertTrue(answerObj.process()); - mMockLooper.dispatchAll(); - } - - verify(mockSessionCallback, times(numOfSuccesses)).onMessageSendSuccess(anyInt()); - verify(mockSessionCallback, times(numOfFailuresInternalFailure)).onMessageSendFail(anyInt(), - eq(NanStatusType.INTERNAL_FAILURE)); - verify(mockSessionCallback, times(numOfFailuresNoOta)).onMessageSendFail(anyInt(), - eq(NanStatusType.NO_OTA_ACK)); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback); - } - - /** - * Validate that can send empty message successfully: null, byte[0], "" - */ - @Test - public void testSendEmptyMessages() throws Exception { - final int clientId = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final String serviceName = "some-service-name"; - final String ssi = "some much longer and more arbitrary data"; - final byte subscribeId = 15; - final int requestorId = 22; - final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); - final String peerSsi = "some peer ssi data"; - final String peerMatchFilter = "filter binary array represented as string"; - final int messageId = 6948; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) - .setServiceSpecificInfo(ssi.getBytes()) - .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE) - .build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); - ArgumentCaptor<byte[]> byteArrayCaptor = ArgumentCaptor.forClass(byte[].class); - InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (0) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (1) subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - - // (2) match - mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), - peerMatchFilter.getBytes(), 0, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), eq(peerSsi.getBytes()), - eq(peerMatchFilter.getBytes())); - - // (3) message null Tx successful queuing - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - null, messageId, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), isNull(byte[].class), eq(messageId)); - short tid = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(tid); - mMockLooper.dispatchAll(); - - // (4) final Tx results (on-air results) - mDut.onMessageSendSuccessNotification(tid); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); - validateInternalSendMessageQueuesCleanedUp(messageId); - - // (5) message byte[0] Tx successful queuing - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), new byte[0], - messageId, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), eq(new byte[0]), eq(messageId)); - tid = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(tid); - mMockLooper.dispatchAll(); - - // (6) final Tx results (on-air results) - mDut.onMessageSendSuccessNotification(tid); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); - validateInternalSendMessageQueuesCleanedUp(messageId); - - // (7) message "" Tx successful queuing - mDut.sendMessage(uid, clientId, sessionId.getValue(), peerIdCaptor.getValue(), - "".getBytes(), messageId, 0); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), - eq(requestorId), eq(peerMac), byteArrayCaptor.capture(), eq(messageId)); - collector.checkThat("Empty message contents", "", - equalTo(new String(byteArrayCaptor.getValue()))); - tid = transactionId.getValue(); - mDut.onMessageSendQueuedSuccessResponse(tid); - mMockLooper.dispatchAll(); - - // (8) final Tx results (on-air results) - mDut.onMessageSendSuccessNotification(tid); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); - validateInternalSendMessageQueuesCleanedUp(messageId); - - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); - } - - private class SendMessageQueueModelAnswer extends MockAnswerUtil.AnswerWithArguments { - private final int mMaxQueueDepth; - - // keyed by message ID - private final Set<Integer> mFailQueueCommandImmediately; // return a false - private final Set<Integer> mFailQueueCommandLater; // return an error != TX_QUEUE_FULL - - // # of times to return NO_OTA_ACK before returning SUCCESS. So a 0 means success on first - // try, a very large number means - never succeed (since max retry is 5). - // a -1 impiles a non-OTA failure: on first attempt - private final Map<Integer, Integer> mRetryLimit; - - private final LinkedList<Short> mQueue = new LinkedList<>(); // transaction ID (tid) - private final Map<Short, Integer> mMessageIdsByTid = new HashMap<>(); // tid -> message ID - private final Map<Integer, Integer> mTriesUsedByMid = new HashMap<>(); // mid -> # of retx - - SendMessageQueueModelAnswer(int maxQueueDepth, Set<Integer> failQueueCommandImmediately, - Set<Integer> failQueueCommandLater, Map<Integer, Integer> numberOfRetries) { - mMaxQueueDepth = maxQueueDepth; - mFailQueueCommandImmediately = failQueueCommandImmediately; - mFailQueueCommandLater = failQueueCommandLater; - mRetryLimit = numberOfRetries; - - if (mRetryLimit != null) { - for (int mid : mRetryLimit.keySet()) { - mTriesUsedByMid.put(mid, 0); - } - } - } - - public boolean answer(short transactionId, byte pubSubId, int requestorInstanceId, - byte[] dest, byte[] message, int messageId) throws Exception { - if (mFailQueueCommandImmediately != null && mFailQueueCommandImmediately.contains( - messageId)) { - return false; - } - - if (mFailQueueCommandLater != null && mFailQueueCommandLater.contains(messageId)) { - mDut.onMessageSendQueuedFailResponse(transactionId, NanStatusType.INTERNAL_FAILURE); - } else { - if (mQueue.size() <= mMaxQueueDepth) { - mQueue.addLast(transactionId); - mMessageIdsByTid.put(transactionId, messageId); - mDut.onMessageSendQueuedSuccessResponse(transactionId); - } else { - mDut.onMessageSendQueuedFailResponse(transactionId, - NanStatusType.FOLLOWUP_TX_QUEUE_FULL); - } - } - - return true; - } - - /** - * Processes the first message in the queue: i.e. responds as if sent over-the-air - * (successfully or failed) - */ - boolean process() { - if (mQueue.size() == 0) { - return false; - } - short tid = mQueue.poll(); - int mid = mMessageIdsByTid.get(tid); - - if (mRetryLimit != null && mRetryLimit.containsKey(mid)) { - int numRetries = mRetryLimit.get(mid); - if (numRetries == -1) { - mDut.onMessageSendFailNotification(tid, NanStatusType.INTERNAL_FAILURE); - } else { - int currentRetries = mTriesUsedByMid.get(mid); - if (currentRetries > numRetries) { - return false; // shouldn't be retrying!? - } else if (currentRetries == numRetries) { - mDut.onMessageSendSuccessNotification(tid); - } else { - mDut.onMessageSendFailNotification(tid, NanStatusType.NO_OTA_ACK); - } - mTriesUsedByMid.put(mid, currentRetries + 1); - } - } else { - mDut.onMessageSendSuccessNotification(tid); - } - - return true; - } - - /** - * Returns the number of elements in the queue. - */ - int queueSize() { - return mQueue.size(); - } - } - - /** - * Test sequence of configuration: (1) config1, (2) config2 - incompatible, - * (3) config3 - compatible with config1 (requiring upgrade), (4) disconnect - * config3 (should get a downgrade), (5) disconnect config1 (should get a - * disable). - */ - @Test - public void testConfigs() throws Exception { - final int clientId1 = 9999; - final int clientId2 = 1001; - final int clientId3 = 1005; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int masterPref1 = 111; - final int masterPref3 = 115; - final int dwInterval1Band24 = 2; - final int dwInterval3Band24 = 1; - final int dwInterval3Band5 = 0; - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<ConfigRequest> crCapture = ArgumentCaptor.forClass(ConfigRequest.class); - - ConfigRequest configRequest1 = new ConfigRequest.Builder() - .setClusterLow(5).setClusterHigh(100) - .setMasterPreference(masterPref1) - .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_24GHZ, dwInterval1Band24) - .build(); - - ConfigRequest configRequest2 = new ConfigRequest.Builder() - .setSupport5gBand(true) // compatible - .setSupport6gBand(false) - .setClusterLow(7).setClusterHigh(155) // incompatible! - .setMasterPreference(0) // compatible - .build(); - - ConfigRequest configRequest3 = new ConfigRequest.Builder() - .setSupport5gBand(true) // compatible (will use true) - .setSupport6gBand(false) - .setClusterLow(5).setClusterHigh(100) // identical (hence compatible) - .setMasterPreference(masterPref3) // compatible (will use max) - // compatible: will use min - .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_24GHZ, dwInterval3Band24) - // compatible: will use interval3 since interval1 not init - .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_5GHZ, dwInterval3Band5) - .build(); - - IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); - IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); - IWifiAwareEventCallback mockCallback3 = mock(IWifiAwareEventCallback.class); - - InOrder inOrder = inOrder(mMockNative, mockCallback1, mockCallback2, mockCallback3); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) config1 (valid) - mDut.connect(clientId1, uid, pid, callingPackage, callingFeature, mockCallback1, - configRequest1, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - crCapture.capture(), eq(false), eq(true), eq(true), eq(false), eq(false)); - collector.checkThat("merge: stage 1", crCapture.getValue(), equalTo(configRequest1)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback1).onConnectSuccess(clientId1); - - // (2) config2 (incompatible with config1) - mDut.connect(clientId2, uid, pid, callingPackage, callingFeature, mockCallback2, - configRequest2, false); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback2).onConnectFail(NanStatusType.INTERNAL_FAILURE); - validateInternalClientInfoCleanedUp(clientId2); - - // (3) config3 (compatible with config1) - mDut.connect(clientId3, uid, pid, callingPackage, callingFeature, mockCallback3, - configRequest3, true); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - crCapture.capture(), eq(true), eq(false), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback3).onConnectSuccess(clientId3); - - collector.checkThat("support 5g: or", true, equalTo(crCapture.getValue().mSupport5gBand)); - collector.checkThat("support 6g: or", false, equalTo(crCapture.getValue().mSupport6gBand)); - collector.checkThat("master preference: max", Math.max(masterPref1, masterPref3), - equalTo(crCapture.getValue().mMasterPreference)); - collector.checkThat("dw interval on 2.4: ~min", - Math.min(dwInterval1Band24, dwInterval3Band24), - equalTo(crCapture.getValue().mDiscoveryWindowInterval[ConfigRequest - .NAN_BAND_24GHZ])); - collector.checkThat("dw interval on 5: ~min", dwInterval3Band5, - equalTo(crCapture.getValue().mDiscoveryWindowInterval[ConfigRequest - .NAN_BAND_5GHZ])); - - // (4) disconnect config3: downgrade to config1 - mDut.disconnect(clientId3); - mMockLooper.dispatchAll(); - validateInternalClientInfoCleanedUp(clientId3); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - crCapture.capture(), eq(false), eq(false), eq(true), eq(false), eq(false)); - - collector.checkThat("configRequest1", configRequest1, equalTo(crCapture.getValue())); - - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - // (5) disconnect config1: disable - mDut.disconnect(clientId1); - mMockLooper.dispatchAll(); - validateInternalClientInfoCleanedUp(clientId1); - inOrder.verify(mMockNative).disable(anyShort()); - - verifyNoMoreInteractions(mMockNative, mockCallback1, mockCallback2, mockCallback3); - } - - /** - * Validate that identical configuration but with different identity callback requirements - * trigger the correct HAL sequence. - * 1. Attach w/o identity -> enable - * 2. Attach w/o identity -> nop - * 3. Attach w/ identity -> re-configure - * 4. Attach w/o identity -> nop - * 5. Attach w/ identity -> nop - */ - @Test - public void testConfigsIdentityCallback() throws Exception { - int clientId = 9999; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - InOrder inOrder = inOrder(mMockNative, mockCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) attach w/o identity - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - any(ConfigRequest.class), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) attach w/o identity - ++clientId; - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (3) attach w/ identity - ++clientId; - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, true); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - any(ConfigRequest.class), eq(true), eq(false), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (4) attach w/o identity - ++clientId; - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (5) attach w/ identity - ++clientId; - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, true); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - verifyNoMoreInteractions(mMockNative, mockCallback); - } - - /** - * Summary: disconnect a client while there are pending transactions. - */ - @Test - public void testDisconnectWithPendingTransactions() throws Exception { - final int clientId = 125; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int clusterLow = 5; - final int clusterHigh = 100; - final int masterPref = 111; - final String serviceName = "some-service-name"; - final String ssi = "some much longer and more arbitrary data"; - final byte publishId = 22; - - ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) - .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); - - PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( - serviceName).setServiceSpecificInfo(ssi.getBytes()).setPublishType( - PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) publish (no response yet) - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - - // (3) disconnect (but doesn't get executed until get a RESPONSE to the - // previous publish) - mDut.disconnect(clientId); - mMockLooper.dispatchAll(); - - // (4) get successful response to the publish - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); - inOrder.verify(mMockNative).stopPublish((short) 0, publishId); - inOrder.verify(mMockNative).disable(anyShort()); - - validateInternalClientInfoCleanedUp(clientId); - - // (5) trying to publish on the same client: NOP - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - - // (6) got some callback on original publishId - should be ignored - mDut.onSessionTerminatedNotification(publishId, 0, true); - mMockLooper.dispatchAll(); - - verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); - } - - /** - * Validate that an unknown transaction (i.e. a callback from HAL with an - * unknown type) is simply ignored - but also cleans up its state. - */ - @Test - public void testUnknownTransactionType() throws Exception { - final int clientId = 129; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final int clusterLow = 15; - final int clusterHigh = 192; - final int masterPref = 234; - final String serviceName = "some-service-name"; - final String ssi = "some much longer and more arbitrary data"; - - ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) - .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); - - PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( - serviceName).setServiceSpecificInfo(ssi.getBytes()).setPublishType( - PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockPublishSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockPublishSessionCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) publish - no response - mDut.publish(clientId, publishConfig, mockPublishSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - - verifyNoMoreInteractions(mMockNative, mockCallback, mockPublishSessionCallback); - } - - /** - * Validate that a NoOp transaction (i.e. a callback from HAL which doesn't - * require any action except clearing up state) actually cleans up its state - * (and does nothing else). - */ - @Test - public void testNoOpTransaction() throws Exception { - final int clientId = 1294; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect (no response) - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - - verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); - } - - /** - * Validate that getting callbacks from HAL with unknown (expired) - * transaction ID or invalid publish/subscribe ID session doesn't have any - * impact. - */ - @Test - public void testInvalidCallbackIdParameters() throws Exception { - final byte pubSubId = 125; - final int clientId = 132; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect and succeed - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - short transactionIdConfig = transactionId.getValue(); - mDut.onConfigSuccessResponse(transactionIdConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) use the same transaction ID to send a bunch of other responses - mDut.onConfigSuccessResponse(transactionIdConfig); - mDut.onConfigFailedResponse(transactionIdConfig, -1); - mDut.onSessionConfigFailResponse(transactionIdConfig, true, -1); - mDut.onMessageSendQueuedSuccessResponse(transactionIdConfig); - mDut.onMessageSendQueuedFailResponse(transactionIdConfig, -1); - mDut.onSessionConfigFailResponse(transactionIdConfig, false, -1); - mDut.onMatchNotification(-1, -1, new byte[0], new byte[0], new byte[0], 0, 0); - mDut.onSessionTerminatedNotification(-1, -1, true); - mDut.onSessionTerminatedNotification(-1, -1, false); - mDut.onMessageReceivedNotification(-1, -1, new byte[0], new byte[0]); - mDut.onSessionConfigSuccessResponse(transactionIdConfig, true, pubSubId); - mDut.onSessionConfigSuccessResponse(transactionIdConfig, false, pubSubId); - mMockLooper.dispatchAll(); - - verifyNoMoreInteractions(mMockNative, mockCallback); - } - - /** - * Validate that trying to update-subscribe on a publish session fails. - */ - @Test - public void testSubscribeOnPublishSessionType() throws Exception { - final int clientId = 188; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final byte publishId = 25; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - PublishConfig publishConfig = new PublishConfig.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), - eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) publish - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - - // (3) update-subscribe -> failure - mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - - verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); - } - - /** - * Validate that trying to (re)subscribe on a publish session or (re)publish - * on a subscribe session fails. - */ - @Test - public void testPublishOnSubscribeSessionType() throws Exception { - final int clientId = 188; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final byte subscribeId = 25; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - PublishConfig publishConfig = new PublishConfig.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) subscribe - mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq((byte) 0), - eq(subscribeConfig)); - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - - // (3) update-publish -> error - mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); - - verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); - } - - /** - * Validate that the session ID increments monotonically - */ - @Test - public void testSessionIdIncrement() throws Exception { - final int clientId = 188; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - int loopCount = 100; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - PublishConfig publishConfig = new PublishConfig.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( - IWifiAwareDiscoverySessionCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - int prevId = 0; - for (int i = 0; i < loopCount; ++i) { - // (2) publish - mDut.publish(clientId, publishConfig, mockSessionCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).publish(transactionId.capture(), eq((byte) 0), - eq(publishConfig)); - - // (3) publish-success - mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, (byte) (i + 1)); - mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - - if (i != 0) { - assertTrue("Session ID incrementing", sessionId.getValue() > prevId); - } - prevId = sessionId.getValue(); - } - } - - /** - * Validate configuration changes on power state changes when Aware is not disabled on doze. - */ - @Test - public void testConfigOnPowerStateChanges() throws Exception { - final int clientId = 188; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - setSettableParam(WifiAwareStateManager.PARAM_ON_IDLE_DISABLE_AWARE, Integer.toString(0), - true); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - InOrder inOrder = inOrder(mMockNative, mockCallback); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) power state change: SCREEN OFF - simulatePowerStateChangeInteractive(false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(false), eq(false), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - // (3) power state change: DOZE - simulatePowerStateChangeDoze(true); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(false), eq(false), eq(true), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - // (4) restore power state to default - simulatePowerStateChangeInteractive(true); // effectively treated as no-doze - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(false), eq(true), eq(true), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - - verifyNoMoreInteractions(mMockNative, mockCallback); - } - - /** - * Validate aware enable/disable during doze transitions. - */ - @Test - public void testEnableDisableOnDoze() throws Exception { - final int clientId = 188; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - - setSettableParam(WifiAwareStateManager.PARAM_ON_IDLE_DISABLE_AWARE, Integer.toString(1), - true); - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - InOrder inOrder = inOrder(mMockContext, mMockNativeManager, mMockNative, mockCallback); - inOrder.verify(mMockNativeManager).start(any(Handler.class)); - - mDut.enableUsage(); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).tryToGetAware(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).releaseAware(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).tryToGetAware(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (3) power state change: DOZE - simulatePowerStateChangeDoze(true); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); - collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - // (4) power state change: SCREEN ON (but DOZE still on - fakish but expect no changes) - simulatePowerStateChangeInteractive(false); - mMockLooper.dispatchAll(); - - // and same for other gating changes -> no changes - simulateLocationModeChange(false); - simulateWifiStateChange(false); - mMockLooper.dispatchAll(); - - // and same for other gating changes -> no changes - simulateLocationModeChange(true); - simulateWifiStateChange(true); - mMockLooper.dispatchAll(); - - // when WifiAware Native is not available, DOZE OFF -> no change - when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(false); - simulatePowerStateChangeDoze(false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); - - // (5) power state change: DOZE OFF - simulatePowerStateChangeDoze(false); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - mMockLooper.dispatchAll(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - verifyNoMoreInteractions(mMockNativeManager, mMockNative, mockCallback); - } - - /** - * Validate aware enable/disable during LOCATION MODE transitions. - */ - @Test - public void testEnableDisableOnLocationModeChanges() throws Exception { - final int clientId = 188; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - InOrder inOrder = inOrder(mMockContext, mMockNativeManager, mMockNative, mockCallback); - inOrder.verify(mMockNativeManager).start(any(Handler.class)); - - mDut.enableUsage(); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).tryToGetAware(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).releaseAware(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).tryToGetAware(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (3) location mode change: disable - simulateLocationModeChange(false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); - collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - // disable other gating feature -> no change - simulatePowerStateChangeDoze(true); - simulateWifiStateChange(false); - mMockLooper.dispatchAll(); - - // enable other gating feature -> no change - simulatePowerStateChangeDoze(false); - simulateWifiStateChange(true); - mMockLooper.dispatchAll(); - - // when WifiAware Native is not available, enable location -> no change - when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(false); - simulateLocationModeChange(true); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - mMockLooper.dispatchAll(); - when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); - - // (4) location mode change: enable - simulateLocationModeChange(true); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - mMockLooper.dispatchAll(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - verifyNoMoreInteractions(mMockNativeManager, mMockNative, mockCallback); - } - - /** - * Validate aware enable/disable during Wi-Fi State transitions. - */ - @Test - public void testEnableDisableOnWifiStateChanges() throws Exception { - final int clientId = 188; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - InOrder inOrder = inOrder(mMockContext, mMockNativeManager, mMockNative, mockCallback); - inOrder.verify(mMockNativeManager).start(any(Handler.class)); - - mDut.enableUsage(); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).tryToGetAware(); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).releaseAware(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).tryToGetAware(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (3) wifi state change: disable - simulateWifiStateChange(false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); - collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - // disable other gating feature -> no change - simulatePowerStateChangeDoze(true); - simulateLocationModeChange(false); - mMockLooper.dispatchAll(); - - // enable other gating feature -> no change - simulatePowerStateChangeDoze(false); - simulateLocationModeChange(true); - mMockLooper.dispatchAll(); - - // when WifiAware Native is not available, enable Wifi -> no change - when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(false); - simulateWifiStateChange(true); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - mMockLooper.dispatchAll(); - when(mMockNativeManager.isAwareNativeAvailable()).thenReturn(true); - - // (4) wifi state change: enable - simulateWifiStateChange(true); - inOrder.verify(mMockNativeManager).isAwareNativeAvailable(); - mMockLooper.dispatchAll(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - verifyNoMoreInteractions(mMockNativeManager, mMockNative, mockCallback); - } - - /** - * Validate aware state change when get aware down from native - */ - @Test - public void testWifiAwareStateChangeFromNative() throws Exception { - final int clientId = 12314; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - final ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - InOrder inOrder = inOrder(mMockContext, mMockNative, mockCallback); - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - - // (0) check initial state - mDut.enableUsage(); - mMockLooper.dispatchAll(); - validateCorrectAwareStatusChangeBroadcast(inOrder); - inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); - mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); - mMockLooper.dispatchAll(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - - // (1) connect client - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) Aware down notification from native - mDut.onAwareDownNotification(NanStatusType.UNSUPPORTED_CONCURRENCY_NAN_DISABLED); - mMockLooper.dispatchAll(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - // (3) try reconnect client - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false)); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - verifyNoMoreInteractions(mMockNative, mockCallback); - } - - /* - * Tests of internal state of WifiAwareStateManager: very limited (not usually - * a good idea). However, these test that the internal state is cleaned-up - * appropriately. Alternatively would cause issues with memory leaks or - * information leak between sessions. - */ - - /** - * Utility routine used to validate that the internal state is cleaned-up - * after a client is disconnected. To be used in every test which terminates - * a client. - * - * @param clientId The ID of the client which should be deleted. - */ - private void validateInternalClientInfoCleanedUp(int clientId) throws Exception { - WifiAwareClientState client = getInternalClientState(mDut, clientId); - collector.checkThat("Client record not cleared up for clientId=" + clientId, client, - nullValue()); - } - - /** - * Utility routine used to validate that the internal state is cleaned-up - * (deleted) after a session is terminated through API (not callback!). To - * be used in every test which terminates a session. - * - * @param clientId The ID of the client containing the session. - * @param sessionId The ID of the terminated session. - */ - private void validateInternalSessionInfoCleanedUp(int clientId, int sessionId) - throws Exception { - WifiAwareClientState client = getInternalClientState(mDut, clientId); - collector.checkThat("Client record exists clientId=" + clientId, client, notNullValue()); - WifiAwareDiscoverySessionState session = getInternalSessionState(client, sessionId); - collector.checkThat("Client record not cleaned-up for sessionId=" + sessionId, session, - nullValue()); - } - - /** - * Utility routine used to validate that the internal state is cleaned-up - * (deleted) correctly. Checks that a specific client has no sessions - * attached to it. - * - * @param clientId The ID of the client which we want to check. - */ - private void validateInternalNoSessions(int clientId) throws Exception { - WifiAwareClientState client = getInternalClientState(mDut, clientId); - collector.checkThat("Client record exists clientId=" + clientId, client, notNullValue()); - - Field field = WifiAwareClientState.class.getDeclaredField("mSessions"); - field.setAccessible(true); - @SuppressWarnings("unchecked") - SparseArray<WifiAwareDiscoverySessionState> sessions = - (SparseArray<WifiAwareDiscoverySessionState>) field.get(client); - - collector.checkThat("No sessions exist for clientId=" + clientId, sessions.size(), - equalTo(0)); - } - - /** - * Validates that the broadcast sent on Aware status change is correct. - */ - private void validateCorrectAwareStatusChangeBroadcast(InOrder inOrder) { - ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); - - inOrder.verify(mMockContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL)); - - collector.checkThat("intent action", intent.getValue().getAction(), - equalTo(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED)); - } - - /* - * Utilities - */ - private void setSettableParam(String name, String value, boolean expectSuccess) { - PrintWriter pwMock = mock(PrintWriter.class); - WifiAwareShellCommand parentShellMock = mock(WifiAwareShellCommand.class); - when(parentShellMock.getNextArgRequired()).thenReturn("set").thenReturn(name).thenReturn( - value); - when(parentShellMock.getErrPrintWriter()).thenReturn(pwMock); - - collector.checkThat(mDut.onCommand(parentShellMock), equalTo(expectSuccess ? 0 : -1)); - } - - private void dumpDut(String prefix) { - StringWriter sw = new StringWriter(); - mDut.dump(null, new PrintWriter(sw), null); - Log.e("WifiAwareStateManagerTest", prefix + sw.toString()); - } - - private static void installMocksInStateManager(WifiAwareStateManager awareStateManager, - WifiAwareDataPathStateManager mockDpMgr) - throws Exception { - Field field = WifiAwareStateManager.class.getDeclaredField("mDataPathMgr"); - field.setAccessible(true); - field.set(awareStateManager, mockDpMgr); - } - - private static WifiAwareClientState getInternalClientState(WifiAwareStateManager dut, - int clientId) throws Exception { - Field field = WifiAwareStateManager.class.getDeclaredField("mClients"); - field.setAccessible(true); - @SuppressWarnings("unchecked") - SparseArray<WifiAwareClientState> clients = (SparseArray<WifiAwareClientState>) field.get( - dut); - - return clients.get(clientId); - } - - private static WifiAwareDiscoverySessionState getInternalSessionState( - WifiAwareClientState client, int sessionId) throws Exception { - Field field = WifiAwareClientState.class.getDeclaredField("mSessions"); - field.setAccessible(true); - @SuppressWarnings("unchecked") - SparseArray<WifiAwareDiscoverySessionState> sessions = - (SparseArray<WifiAwareDiscoverySessionState>) field.get(client); - - return sessions.get(sessionId); - } - - private void validateInternalSendMessageQueuesCleanedUp(int messageId) throws Exception { - Field field = WifiAwareStateManager.class.getDeclaredField("mSm"); - field.setAccessible(true); - WifiAwareStateManager.WifiAwareStateMachine sm = - (WifiAwareStateManager.WifiAwareStateMachine) field.get(mDut); - - field = WifiAwareStateManager.WifiAwareStateMachine.class.getDeclaredField( - "mHostQueuedSendMessages"); - field.setAccessible(true); - SparseArray<Message> hostQueuedSendMessages = (SparseArray<Message>) field.get(sm); - - field = WifiAwareStateManager.WifiAwareStateMachine.class.getDeclaredField( - "mFwQueuedSendMessages"); - field.setAccessible(true); - Map<Short, Message> fwQueuedSendMessages = (Map<Short, Message>) field.get(sm); - - for (int i = 0; i < hostQueuedSendMessages.size(); ++i) { - Message msg = hostQueuedSendMessages.valueAt(i); - if (msg.getData().getInt("message_id") == messageId) { - collector.checkThat( - "Message not cleared-up from host queue. Message ID=" + messageId, msg, - nullValue()); - } - } - - for (Message msg: fwQueuedSendMessages.values()) { - if (msg.getData().getInt("message_id") == messageId) { - collector.checkThat( - "Message not cleared-up from firmware queue. Message ID=" + messageId, msg, - nullValue()); - } - } - } - - /** - * Simulate power state change due to doze. Changes the power manager return values and - * dispatches a broadcast. - */ - private void simulatePowerStateChangeDoze(boolean isDozeOn) { - when(mMockPowerManager.isDeviceIdleMode()).thenReturn(isDozeOn); - - Intent intent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - mPowerBcastReceiver.onReceive(mMockContext, intent); - } - - /** - * Simulate power state change due to interactive mode change (screen on/off). Changes the power - * manager return values and dispatches a broadcast. - */ - private void simulatePowerStateChangeInteractive(boolean isInteractive) { - when(mMockPowerManager.isInteractive()).thenReturn(isInteractive); - - Intent intent = new Intent( - isInteractive ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF); - mPowerBcastReceiver.onReceive(mMockContext, intent); - } - - /** - * Simulate Location Mode change. Changes the location manager return values and dispatches a - * broadcast. - */ - private void simulateLocationModeChange(boolean isLocationModeEnabled) { - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(isLocationModeEnabled); - - Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); - mLocationModeReceiver.onReceive(mMockContext, intent); - } - - /** - * Simulate Wi-Fi state change: broadcast state change and modify the API return value. - */ - private void simulateWifiStateChange(boolean isWifiOn) { - when(mMockWifiManager.getWifiState()).thenReturn( - isWifiOn ? WifiManager.WIFI_STATE_ENABLED : WifiManager.WIFI_STATE_DISABLED); - - Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); - intent.putExtra(WifiManager.EXTRA_WIFI_STATE, - isWifiOn ? WifiManager.WIFI_STATE_ENABLED : WifiManager.WIFI_STATE_DISABLED); - mWifiStateChangedReceiver.onReceive(mMockContext, intent); - } - - private static Capabilities getCapabilities() { - Capabilities cap = new Capabilities(); - cap.maxConcurrentAwareClusters = 1; - cap.maxPublishes = 2; - cap.maxSubscribes = 2; - cap.maxServiceNameLen = 255; - cap.maxMatchFilterLen = 255; - cap.maxTotalMatchFilterLen = 255; - cap.maxServiceSpecificInfoLen = 255; - cap.maxExtendedServiceSpecificInfoLen = 255; - cap.maxNdiInterfaces = 1; - cap.maxNdpSessions = 1; - cap.maxAppInfoLen = 255; - cap.maxQueuedTransmitMessages = 6; - return cap; - } - - private static class Mutable<E> { - public E value; - - Mutable() { - value = null; - } - - Mutable(E value) { - this.value = value; - } - } -} - diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPDataTest.java deleted file mode 100644 index a467f822f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPDataTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import java.util.Map; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.ANQPData}. - * - * TODO(b/33000864): add more test once the ANQP elements cleanup are completed, which will - * allow easy construction of ANQP elements for testing. - */ -@SmallTest -public class ANQPDataTest extends WifiBaseTest { - @Mock Clock mClock; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - // Returning the initial timestamp. - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - } - - /** - * Verify creation of ANQPData with null elements. - * - * @throws Exception - */ - @Test - public void createWithNullElements() throws Exception { - ANQPData data = new ANQPData(mClock, null); - Map<Constants.ANQPElementType, ANQPElement> elements = data.getElements(); - assertTrue(elements.isEmpty()); - } - - /** - * Verify the data expiration behavior. - * - * @throws Exception - */ - @Test - public void verifyExpiration() throws Exception { - ANQPData data = new ANQPData(mClock, null); - assertFalse(data.expired(ANQPData.DATA_LIFETIME_MILLISECONDS - 1)); - assertTrue(data.expired(ANQPData.DATA_LIFETIME_MILLISECONDS)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java deleted file mode 100644 index b7bb8afc1..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.net.wifi.EAPConstants; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.IMSIParameter; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.anqp.CellularNetwork; -import com.android.server.wifi.hotspot2.anqp.DomainNameElement; -import com.android.server.wifi.hotspot2.anqp.NAIRealmData; -import com.android.server.wifi.hotspot2.anqp.NAIRealmElement; -import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement; -import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement; -import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; -import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; -import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.ANQPMatcher}. - */ -@SmallTest -public class ANQPMatcherTest extends WifiBaseTest { - /** - * Verify that domain name match will fail when a null Domain Name ANQP element is provided. - * - * @throws Exception - */ - @Test - public void matchDomainNameWithNullElement() throws Exception { - assertFalse(ANQPMatcher.matchDomainName(null, "test.com", null, null)); - } - - /** - * Verify that domain name match will succeed when the specified FQDN matches a domain name - * in the Domain Name ANQP element. - * - * @throws Exception - */ - @Test - public void matchDomainNameUsingFQDN() throws Exception { - String fqdn = "test.com"; - String[] domains = new String[] {fqdn}; - DomainNameElement element = new DomainNameElement(Arrays.asList(domains)); - assertTrue(ANQPMatcher.matchDomainName(element, fqdn, null, null)); - } - - /** - * Verify that domain name match will succeed when the specified IMSI parameter and IMSI list - * matches a 3GPP network domain in the Domain Name ANQP element. - * - * @throws Exception - */ - @Test - public void matchDomainNameUsingIMSI() throws Exception { - IMSIParameter imsiParam = new IMSIParameter("123456", true); - String simImsi = "123456789012345"; - // 3GPP network domain with MCC=123 and MNC=456. - String[] domains = new String[] {"wlan.mnc456.mcc123.3gppnetwork.org"}; - DomainNameElement element = new DomainNameElement(Arrays.asList(domains)); - assertTrue(ANQPMatcher.matchDomainName(element, null, imsiParam, simImsi)); - } - - /** - * Verify that roaming consortium match will fail when a null Roaming Consortium ANQP - * element is provided. - * - * @throws Exception - */ - @Test - public void matchRoamingConsortiumWithNullElement() throws Exception { - assertFalse(ANQPMatcher.matchRoamingConsortium(null, new long[0], false)); - } - - /** - * Verify that a roaming consortium match will succeed when the specified OI matches - * an OI in the Roaming Consortium ANQP element. - * - * @throws Exception - */ - @Test - public void matchRoamingConsortium() throws Exception { - long oi = 0x1234L; - RoamingConsortiumElement element = - new RoamingConsortiumElement(Arrays.asList(new Long[] {oi})); - assertTrue(ANQPMatcher.matchRoamingConsortium(element, new long[] {oi}, false)); - } - - /** - * Verify that no match will be returned when matching a null NAI Realm - * ANQP element. - * - * @throws Exception - */ - @Test - public void matchNAIRealmWithNullElement() throws Exception { - assertFalse(ANQPMatcher.matchNAIRealm(null, "test.com")); - } - - /** - * Verify that no match will be returned when matching a NAI Realm - * ANQP element contained no NAI realm data. - * - * @throws Exception - */ - @Test - public void matchNAIRealmWithEmtpyRealmData() throws Exception { - NAIRealmElement element = new NAIRealmElement(new ArrayList<NAIRealmData>()); - assertFalse(ANQPMatcher.matchNAIRealm(element, "test.com")); - } - - /** - * Verify that a realm match will be returned when the specified realm matches a realm - * in the NAI Realm ANQP element with no EAP methods. - * - * @throws Exception - */ - @Test - public void matchNAIRealmWithRealmMatch() throws Exception { - String realm = "test.com"; - NAIRealmData realmData = new NAIRealmData( - Arrays.asList(new String[] {realm}), new ArrayList<EAPMethod>()); - NAIRealmElement element = new NAIRealmElement( - Arrays.asList(new NAIRealmData[] {realmData})); - assertTrue(ANQPMatcher.matchNAIRealm(element, realm)); - } - - /** - * Verify that a realm match will be returned when the specified realm and EAP - * method matches a realm in the NAI Realm ANQP element. - * - * @throws Exception - */ - @Test - public void matchNAIRealmWithRealmMethodMatch() throws Exception { - // Test data. - String realm = "test.com"; - int eapMethodID = EAPConstants.EAP_TLS; - - // Setup NAI Realm element. - EAPMethod method = new EAPMethod(eapMethodID, new HashMap<Integer, Set<AuthParam>>()); - NAIRealmData realmData = new NAIRealmData( - Arrays.asList(new String[] {realm}), Arrays.asList(new EAPMethod[] {method})); - NAIRealmElement element = new NAIRealmElement( - Arrays.asList(new NAIRealmData[] {realmData})); - - assertTrue(ANQPMatcher.matchNAIRealm(element, realm)); - } - - /** - * Verify that a realm match will be returned when the specified realm, EAP - * method, and the authentication parameter matches a realm with the associated EAP method and - * authentication parameter in the NAI Realm ANQP element. - * - * @throws Exception - */ - @Test - public void matchNAIRealmWithExactMatch() throws Exception { - // Test data. - String realm = "test.com"; - int eapMethodID = EAPConstants.EAP_TTLS; - NonEAPInnerAuth authParam = new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAP); - Set<AuthParam> authSet = new HashSet<>(); - authSet.add(authParam); - Map<Integer, Set<AuthParam>> authMap = new HashMap<>(); - authMap.put(authParam.getAuthTypeID(), authSet); - - // Setup NAI Realm element. - EAPMethod method = new EAPMethod(eapMethodID, authMap); - NAIRealmData realmData = new NAIRealmData( - Arrays.asList(new String[] {realm}), Arrays.asList(new EAPMethod[] {method})); - NAIRealmElement element = new NAIRealmElement( - Arrays.asList(new NAIRealmData[] {realmData})); - - assertTrue(ANQPMatcher.matchNAIRealm(element, realm)); - } - - /** - * Verify that a realm match will be returned when the specified EAP method - * doesn't match with the corresponding EAP method in the NAI Realm ANQP element. - * - * @throws Exception - */ - @Test - public void matchNAIRealmWithEAPMethodMismatch() throws Exception { - // Test data. - String realm = "test.com"; - int eapMethodID = EAPConstants.EAP_TTLS; - NonEAPInnerAuth authParam = new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAP); - Set<AuthParam> authSet = new HashSet<>(); - authSet.add(authParam); - Map<Integer, Set<AuthParam>> authMap = new HashMap<>(); - authMap.put(authParam.getAuthTypeID(), authSet); - - // Setup NAI Realm element. - EAPMethod method = new EAPMethod(eapMethodID, authMap); - NAIRealmData realmData = new NAIRealmData( - Arrays.asList(new String[] {realm}), Arrays.asList(new EAPMethod[] {method})); - NAIRealmElement element = new NAIRealmElement( - Arrays.asList(new NAIRealmData[] {realmData})); - - assertTrue(ANQPMatcher.matchNAIRealm(element, realm)); - } - - /** - * Verify that a realm match will be returned when the specified authentication - * parameter doesn't match with the corresponding authentication parameter in the NAI Realm - * ANQP element. - * - * @throws Exception - */ - @Test - public void matchNAIRealmWithAuthTypeMismatch() throws Exception { - // Test data. - String realm = "test.com"; - int eapMethodID = EAPConstants.EAP_TTLS; - NonEAPInnerAuth authParam = new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAP); - Set<AuthParam> authSet = new HashSet<>(); - authSet.add(authParam); - Map<Integer, Set<AuthParam>> authMap = new HashMap<>(); - authMap.put(authParam.getAuthTypeID(), authSet); - - // Setup NAI Realm element. - EAPMethod method = new EAPMethod(eapMethodID, authMap); - NAIRealmData realmData = new NAIRealmData( - Arrays.asList(new String[] {realm}), Arrays.asList(new EAPMethod[] {method})); - NAIRealmElement element = new NAIRealmElement( - Arrays.asList(new NAIRealmData[] {realmData})); - - // Mismatch in authentication type which we ignore. - assertTrue(ANQPMatcher.matchNAIRealm(element, realm)); - } - - /** - * Verify that 3GPP Network match will fail when a null element is provided. - * - * @throws Exception - */ - @Test - public void matchThreeGPPNetworkWithNullElement() throws Exception { - IMSIParameter imsiParam = new IMSIParameter("12345", true); - String simImsi = "123456789012345"; - assertFalse(ANQPMatcher.matchThreeGPPNetwork(null, imsiParam, simImsi)); - } - - /** - * Verify that 3GPP network will succeed when the given 3GPP Network ANQP element contained - * a MCC-MNC that matches the both IMSI parameter and a SIM IMSI. - * - * @throws Exception - */ - @Test - public void matchThreeGPPNetwork() throws Exception { - IMSIParameter imsiParam = new IMSIParameter("123456", true); - String simImsi = "123456789012345"; - - CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123456"})); - ThreeGPPNetworkElement element = - new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); - // The MCC-MNC provided in 3GPP Network ANQP element matches both IMSI parameter - // and an IMSI from the installed SIM card. - assertTrue(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsi)); - } - - /** - * Verify that 3GPP network will succeed when the given 3GPP Network ANQP element contained - * a MCC-MNC that matches the both IMSI parameter and a SIM IMSI contains 5 digits mccmnc. - * - * @throws Exception - */ - @Test - public void matchThreeGPPNetworkWith5DigitsMccMnc() throws Exception { - IMSIParameter imsiParam = new IMSIParameter("12345", true); - String simImsi = "123456789012345"; - - CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"12345"})); - ThreeGPPNetworkElement element = - new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); - // The MCC-MNC provided in 3GPP Network ANQP element matches both IMSI parameter - // and an IMSI from the installed SIM card. - assertTrue(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsi)); - } - - /** - * Verify that 3GPP network will failed when the given 3GPP Network ANQP element contained - * a MCC-MNC that match the IMSI parameter but not the SIM IMSI. - * - * @throws Exception - */ - @Test - public void matchThreeGPPNetworkWithoutSimImsiMatch() throws Exception { - IMSIParameter imsiParam = new IMSIParameter("123457", true); - String simImsi = "123456789012345"; - - CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123457"})); - ThreeGPPNetworkElement element = - new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); - // The MCC-MNC provided in 3GPP Network ANQP element doesn't match any of the IMSIs - // from the installed SIM card. - assertFalse(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsi)); - } - - /** - * Verify that 3GPP network will failed when the given 3GPP Network ANQP element contained - * a MCC-MNC that doesn't match with the IMSI parameter. - * - * @throws Exception - */ - @Test - public void matchThreeGPPNetworkWithImsiParamMismatch() throws Exception { - IMSIParameter imsiParam = new IMSIParameter("12345", true); - String simImsi = "123456789012345"; - - CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123356"})); - ThreeGPPNetworkElement element = - new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); - // The MCC-MNC provided in 3GPP Network ANQP element doesn't match the IMSI parameter. - assertFalse(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsi)); - } - - /** - * Verify that domain name match will fail when domain contains invalid values. - * - * @throws Exception - */ - @Test - public void verifyInvalidDomain() throws Exception { - IMSIParameter imsiParam = new IMSIParameter("123456", true); - String simImsi = "123456789012345"; - // 3GPP network domain with MCC=123 and MNC=456. - String[] domains = new String[] {"wlan.mnc456.mccI23.3gppnetwork.org"}; - DomainNameElement element = new DomainNameElement(Arrays.asList(domains)); - assertFalse(ANQPMatcher.matchDomainName(element, null, imsiParam, simImsi)); - } - - /** - * Verify that match is found when HomeOI contains some of the RCOIs advertised by an AP marked - * as not required. - * - * @throws Exception - */ - @Test - public void matchAnyHomeOi() throws Exception { - long[] providerOis = new long[] {0x1234L, 0x5678L, 0xabcdL}; - Long[] anqpOis = new Long[] {0x1234L, 0x5678L, 0xdeadL, 0xf0cdL}; - RoamingConsortiumElement element = - new RoamingConsortiumElement(Arrays.asList(anqpOis)); - assertTrue(ANQPMatcher.matchRoamingConsortium(element, providerOis, false)); - } - - /** - * Verify that no match is found when HomeOI does not contain any of the RCOIs advertised by an - * AP marked as not required. - * - * @throws Exception - */ - @Test - public void matchAnyHomeOiNegative() throws Exception { - long[] providerOis = new long[] {0x1234L, 0x5678L, 0xabcdL}; - Long[] anqpOis = new Long[] {0xabc2L, 0x1232L}; - RoamingConsortiumElement element = - new RoamingConsortiumElement(Arrays.asList(anqpOis)); - assertFalse(ANQPMatcher.matchRoamingConsortium(element, providerOis, false)); - } - - /** - * Verify that match is found when HomeOI contains all of the RCOIs advertised by an AP marked - * as required. - * - * @throws Exception - */ - @Test - public void matchAllHomeOi() throws Exception { - long[] providerOis = new long[] {0x1234L, 0x5678L, 0xabcdL}; - Long[] anqpOis = new Long[] {0x1234L, 0x5678L, 0xabcdL, 0xdeadL, 0xf0cdL}; - RoamingConsortiumElement element = - new RoamingConsortiumElement(Arrays.asList(anqpOis)); - assertTrue(ANQPMatcher.matchRoamingConsortium(element, providerOis, true)); - } - - /** - * Verify that match is not found when HomeOI does not contain all of the RCOIs advertised by an - * AP marked as required. - * - * @throws Exception - */ - @Test - public void matchAllHomeOiNegative() throws Exception { - long[] providerOis = new long[] {0x1234L, 0x5678L, 0xabcdL}; - Long[] anqpOis = new Long[] {0x1234L, 0x5678L, 0xdeadL, 0xf0cdL}; - RoamingConsortiumElement element = - new RoamingConsortiumElement(Arrays.asList(anqpOis)); - assertFalse(ANQPMatcher.matchRoamingConsortium(element, providerOis, true)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPNetworkKeyTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPNetworkKeyTest.java deleted file mode 100644 index fb7494045..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPNetworkKeyTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.ANQPNetworkKey}. - */ -@SmallTest -public class ANQPNetworkKeyTest extends WifiBaseTest { - private static final String SSID = "TestSSID"; - private static final long BSSID = 0x123456L; - private static final long HESSID = 0x789012L; - private static final int ANQP_DOMAIN_ID = 1; - - /** - * Verify that building a SSID based key works as expected. - * - * @throws Exception - */ - @Test - public void buildStandardESSKey() throws Exception { - ANQPNetworkKey expectedKey = new ANQPNetworkKey(SSID, 0, 0, ANQP_DOMAIN_ID); - ANQPNetworkKey actualKey = ANQPNetworkKey.buildKey(SSID, BSSID, 0, ANQP_DOMAIN_ID); - assertEquals(expectedKey, actualKey); - } - - /** - * Verify that building a HESSID based key works as expected. - * - * @throws Exception - */ - @Test - public void buildHessidKey() throws Exception { - ANQPNetworkKey expectedKey = new ANQPNetworkKey(null, 0, HESSID, ANQP_DOMAIN_ID); - ANQPNetworkKey actualKey = ANQPNetworkKey.buildKey(SSID, BSSID, HESSID, ANQP_DOMAIN_ID); - assertEquals(expectedKey, actualKey); - } - - /** - * Verify that building a key based on an AP (SSID + BSSID) works as expected. - * - * @throws Exception - */ - @Test - public void buildAPKey() throws Exception { - ANQPNetworkKey expectedKey = new ANQPNetworkKey(SSID, BSSID, 0, 0); - ANQPNetworkKey actualKey = ANQPNetworkKey.buildKey(SSID, BSSID, HESSID, 0); - assertEquals(expectedKey, actualKey); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPRequestManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPRequestManagerTest.java deleted file mode 100644 index 2f84c0d3c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPRequestManagerTest.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.ANQPRequestManager}. - */ -@SmallTest -public class ANQPRequestManagerTest extends WifiBaseTest { - private static final long TEST_BSSID = 0x123456L; - private static final ANQPNetworkKey TEST_ANQP_KEY = - new ANQPNetworkKey("TestSSID", TEST_BSSID, 0, 0); - - private static final List<Constants.ANQPElementType> R1_ANQP_WITHOUT_RC = Arrays.asList( - Constants.ANQPElementType.ANQPVenueName, - Constants.ANQPElementType.ANQPIPAddrAvailability, - Constants.ANQPElementType.ANQPNAIRealm, - Constants.ANQPElementType.ANQP3GPPNetwork, - Constants.ANQPElementType.ANQPDomName, - Constants.ANQPElementType.HSFriendlyName, - Constants.ANQPElementType.HSWANMetrics, - Constants.ANQPElementType.HSConnCapability); - - private static final List<Constants.ANQPElementType> R1_ANQP_WITH_RC = Arrays.asList( - Constants.ANQPElementType.ANQPVenueName, - Constants.ANQPElementType.ANQPIPAddrAvailability, - Constants.ANQPElementType.ANQPNAIRealm, - Constants.ANQPElementType.ANQP3GPPNetwork, - Constants.ANQPElementType.ANQPDomName, - Constants.ANQPElementType.HSFriendlyName, - Constants.ANQPElementType.HSWANMetrics, - Constants.ANQPElementType.HSConnCapability, - Constants.ANQPElementType.ANQPRoamingConsortium); - - private static final List<Constants.ANQPElementType> R1R2_ANQP_WITHOUT_RC = Arrays.asList( - Constants.ANQPElementType.ANQPVenueName, - Constants.ANQPElementType.ANQPIPAddrAvailability, - Constants.ANQPElementType.ANQPNAIRealm, - Constants.ANQPElementType.ANQP3GPPNetwork, - Constants.ANQPElementType.ANQPDomName, - Constants.ANQPElementType.HSFriendlyName, - Constants.ANQPElementType.HSWANMetrics, - Constants.ANQPElementType.HSConnCapability, - Constants.ANQPElementType.HSOSUProviders); - - private static final List<Constants.ANQPElementType> R1R2_ANQP_WITH_RC = Arrays.asList( - Constants.ANQPElementType.ANQPVenueName, - Constants.ANQPElementType.ANQPIPAddrAvailability, - Constants.ANQPElementType.ANQPNAIRealm, - Constants.ANQPElementType.ANQP3GPPNetwork, - Constants.ANQPElementType.ANQPDomName, - Constants.ANQPElementType.HSFriendlyName, - Constants.ANQPElementType.HSWANMetrics, - Constants.ANQPElementType.HSConnCapability, - Constants.ANQPElementType.ANQPRoamingConsortium, - Constants.ANQPElementType.HSOSUProviders); - - @Mock - PasspointEventHandler mHandler; - @Mock - Clock mClock; - ANQPRequestManager mManager; - - /** - * Test setup. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - mManager = new ANQPRequestManager(mHandler, mClock); - } - - /** - * Verify that the expected set of ANQP elements are being requested when the targeted AP - * doesn't provide roaming consortium OIs and doesn't support Hotspot 2.0 Release 2 ANQP - * elements, based on the IEs in the scan result . - * - * @throws Exception - */ - @Test - public void requestR1ANQPElementsWithoutRC() throws Exception { - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - } - - /** - * Verify that the expected set of ANQP elements are being requested when the targeted AP does - * provide roaming consortium OIs and doesn't support Hotspot 2.0 Release ANQP elements, based - * on the IEs in the scan result. - * - * @throws Exception - */ - @Test - public void requestR1ANQPElementsWithRC() throws Exception { - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITH_RC)).thenReturn(true); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, true, - NetworkDetail.HSRelease.R1)); - } - - /** - * Verify that the expected set of ANQP elements are being requested when the targeted AP - * doesn't provide roaming consortium OIs and does support Hotspot 2.0 Release ANQP elements, - * based on the IEs in the scan result. - * - * @throws Exception - */ - @Test - public void requestR1R2ANQPElementsWithoutRC() throws Exception { - when(mHandler.requestANQP(TEST_BSSID, R1R2_ANQP_WITHOUT_RC)).thenReturn(true); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R2)); - } - - /** - * Verify that the expected set of ANQP elements are being requested when the targeted AP does - * provide roaming consortium OIs and support Hotspot 2.0 Release ANQP elements, based on the - * IEs in the scan result. - * - * @throws Exception - */ - @Test - public void requestR1R2ANQPElementsWithRC() throws Exception { - when(mHandler.requestANQP(TEST_BSSID, R1R2_ANQP_WITH_RC)).thenReturn(true); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, true, - NetworkDetail.HSRelease.R2)); - } - - /** - * Verify that attempt to request ANQP elements from an AP will fail when there is a request - * already pending. The request will succeed when the hold off time is up. - * - * @throws Exception - */ - @Test - public void requestANQPElementsWithPendingRequest() throws Exception { - // Send the initial request. - long startTime = 0; - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - reset(mHandler); - - // Attempt another request will fail while one is still pending and hold off time is not up - // yet. - when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime + 1); - assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - verify(mHandler, never()).requestANQP(anyLong(), anyObject()); - reset(mHandler); - - // Attempt other request will succeed after the hold off time is up. - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(startTime + ANQPRequestManager.BASE_HOLDOFF_TIME_MILLISECONDS); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - } - - /** - * Verify that an immediate attempt to request ANQP elements from an AP will succeed when the - * previous request is failed on sending. - * - * @throws Exception - */ - @Test - public void requestANQPElementsAfterRequestSendFailure() throws Exception { - // Initial request failed to send. - long startTime = 0; - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(false); - when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime); - assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - reset(mHandler); - - // Verify that new request is not being held off after previous send failure. - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - } - - /** - * Verify that an immediate attempt to request ANQP elements from an AP will succeed when the - * previous request is completed with success. - * - * @throws Exception - */ - @Test - public void requestANQPElementsAfterRequestSucceeded() throws Exception { - // Send the initial request. - long startTime = 0; - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - reset(mHandler); - - // Request completed with success. Verify that the key associated with the request - // is returned. - assertEquals(TEST_ANQP_KEY, mManager.onRequestCompleted(TEST_BSSID, true)); - - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime + 1); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - } - - /** - * Verify that an immediate attempt to request ANQP elements from an AP will fail when the - * previous request is completed with failure. The request will succeed after the hold off time - * is up. - * - * @throws Exception - */ - @Test - public void requestANQPElementsAfterRequestFailed() throws Exception { - // Send the initial request. - long startTime = 0; - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - reset(mHandler); - - // Request completed with failure. Verify that the key associated with the request - // is returned - assertEquals(TEST_ANQP_KEY, mManager.onRequestCompleted(TEST_BSSID, false)); - - // Attempt another request will fail since the hold off time is not up yet. - when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime + 1); - assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - verify(mHandler, never()).requestANQP(anyLong(), anyObject()); - - // Attempt another request will succeed after the hold off time is up. - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(startTime + ANQPRequestManager.BASE_HOLDOFF_TIME_MILLISECONDS); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - } - - /** - * Verify the hold off time for each unanswered query, and that it will stay the same after - * reaching the max hold off count {@link ANQPRequestManager#MAX_HOLDOFF_COUNT}. - * - * @throws Exception - */ - @Test - public void requestANQPElementsWithMaxRetries() throws Exception { - long currentTime = 0; - - // Initial request. - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - reset(mHandler); - - // Sending the request with the hold off time based on the current hold off count. - for (int i = 0; i <= ANQPRequestManager.MAX_HOLDOFF_COUNT; i++) { - long currentHoldOffTime = ANQPRequestManager.BASE_HOLDOFF_TIME_MILLISECONDS * (1 << i); - currentTime += (currentHoldOffTime - 1); - - // Request will fail before the hold off time is up. - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime); - assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - verify(mHandler, never()).requestANQP(anyLong(), anyObject()); - - // Request will succeed when the hold off time is up. - currentTime += 1; - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - reset(mHandler); - } - - // Verify that the hold off time is max out at the maximum hold off count. - currentTime += (ANQPRequestManager.BASE_HOLDOFF_TIME_MILLISECONDS - * (1 << ANQPRequestManager.MAX_HOLDOFF_COUNT) - 1); - - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime); - assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - verify(mHandler, never()).requestANQP(anyLong(), anyObject()); - - currentTime += 1; - when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true); - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R1)); - reset(mHandler); - } - - /** - * Verify that the expected set of ANQP elements are being requested when the targeted AP - * doesn't provide roaming consortium OIs and does support Hotspot 2.0 Release 3 ANQP elements, - * based on the IEs in the scan result. - * - * @throws Exception - */ - @Test - public void requestR1R2ANQPElementsWithoutRCForR3() throws Exception { - when(mHandler.requestANQP(TEST_BSSID, R1R2_ANQP_WITHOUT_RC)).thenReturn(true); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, - NetworkDetail.HSRelease.R3)); - } - - /** - * Verify that the expected set of ANQP elements are being requested when the targeted AP does - * provide roaming consortium OIs and support Hotspot 2.0 Release 3 ANQP elements, based on the - * IEs in the scan result. - * - * @throws Exception - */ - @Test - public void requestR1R2ANQPElementsWithRCForR3() throws Exception { - when(mHandler.requestANQP(TEST_BSSID, R1R2_ANQP_WITH_RC)).thenReturn(true); - assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, true, - NetworkDetail.HSRelease.R3)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/AnqpCacheTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/AnqpCacheTest.java deleted file mode 100644 index c3c96cde5..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/AnqpCacheTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.ANQPData; -import com.android.server.wifi.hotspot2.AnqpCache; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.AnqpCache}. - * - * TODO(b/33000864): add more test once the ANQP elements cleanup are completed, which will - * allow easy construction of ANQP elements for testing. - */ -@SmallTest -public class AnqpCacheTest extends WifiBaseTest { - private static final ANQPNetworkKey ENTRY_KEY = new ANQPNetworkKey("test", 0L, 0L, 1); - - @Mock Clock mClock; - AnqpCache mCache; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - // Returning the initial timestamp. - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - mCache = new AnqpCache(mClock); - } - - /** - * Verify expectation for addEntry and getEntry. - * - * @throws Exception - */ - @Test - public void addAndGetEntry() throws Exception { - mCache.addEntry(ENTRY_KEY, null); - ANQPData data = mCache.getEntry(ENTRY_KEY); - assertNotNull(data); - assertTrue(data.getElements().isEmpty()); - } - - /** - * Verify that getting a non-existing entry will return a null. - * - * @throws Exception - */ - @Test - public void getNonExistEntry() throws Exception { - assertNull(mCache.getEntry(ENTRY_KEY)); - } - - /** - * Verify the expectation for the sweep function (expired entries will be removed). - * - * @throws Exception - */ - @Test - public void sweepRemoveExpiredEntry() throws Exception { - mCache.addEntry(ENTRY_KEY, null); - - // Sweep the cache when the entry is not expired. - when(mClock.getElapsedSinceBootMillis()) - .thenReturn(AnqpCache.CACHE_SWEEP_INTERVAL_MILLISECONDS); - mCache.sweep(); - assertNotNull(mCache.getEntry(ENTRY_KEY)); - - // Sweep the cache when the entry is expired. - when(mClock.getElapsedSinceBootMillis()).thenReturn(ANQPData.DATA_LIFETIME_MILLISECONDS); - mCache.sweep(); - assertNull(mCache.getEntry(ENTRY_KEY)); - } - - /** - * Verify the expectation for the flush function (all entries will be removed). - * - * @throws Exception - */ - @Test - public void testCacheFlush() throws Exception { - mCache.addEntry(ENTRY_KEY, null); - mCache.flush(); - assertNull(mCache.getEntry(ENTRY_KEY)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/DomainMatcherTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/DomainMatcherTest.java deleted file mode 100644 index d0e41d250..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/DomainMatcherTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.DomainMatcher}. - */ -@SmallTest -public class DomainMatcherTest extends WifiBaseTest { - private static final String PRIMARY_DOMAIN = "google.com"; - private static final String SECONDARY_DOMAIN1 = "android.com"; - private static final String SECONDARY_DOMAIN2 = "testing.test.com"; - - /** - * Test data for isSubDomain function. - */ - private static final Map<String, Integer> TEST_DOMAIN_MAP = new HashMap<>(); - static { - TEST_DOMAIN_MAP.put("", DomainMatcher.MATCH_NONE); - TEST_DOMAIN_MAP.put("com", DomainMatcher.MATCH_NONE); - TEST_DOMAIN_MAP.put("test.com", DomainMatcher.MATCH_NONE); - TEST_DOMAIN_MAP.put("google.com", DomainMatcher.MATCH_PRIMARY); - TEST_DOMAIN_MAP.put("test.google.com", DomainMatcher.MATCH_PRIMARY); - TEST_DOMAIN_MAP.put("android.com", DomainMatcher.MATCH_SECONDARY); - TEST_DOMAIN_MAP.put("test.android.com", DomainMatcher.MATCH_SECONDARY); - TEST_DOMAIN_MAP.put("testing.test.com", DomainMatcher.MATCH_SECONDARY); - TEST_DOMAIN_MAP.put("adbcd.testing.test.com", DomainMatcher.MATCH_SECONDARY); - } - - /** - * Test data for arg2SubdomainOfArg1 function. - */ - private static final Map<Pair<String, String>, Boolean> TEST_ARG_DOMAIN_MAP = new HashMap<>(); - static { - TEST_ARG_DOMAIN_MAP.put(new Pair<String, String>("test.com", "abc.test.com"), true); - TEST_ARG_DOMAIN_MAP.put(new Pair<String, String>("test.com", "ad.abc.test.com"), true); - TEST_ARG_DOMAIN_MAP.put(new Pair<String, String>("com", "test.com"), true); - TEST_ARG_DOMAIN_MAP.put(new Pair<String, String>("abc.test.com", "test.com"), false); - TEST_ARG_DOMAIN_MAP.put(new Pair<String, String>("test1.com", "test.com"), false); - TEST_ARG_DOMAIN_MAP.put(new Pair<String, String>("test.com", "com"), false); - } - - /** - * Verify that creating a matcher with empty domains doesn't cause any exceptions. - * - * @throws Exception - */ - @Test - public void createMatcherWithEmptyDomains() throws Exception { - DomainMatcher domainMatcher = new DomainMatcher(null, null); - assertEquals(DomainMatcher.MATCH_NONE, domainMatcher.isSubDomain("google.com")); - } - - /** - * Verify that matching a null domain doesn't cause any exceptions. - * - * @throws Exception - */ - @Test - public void matchNullDomain() throws Exception { - DomainMatcher domainMatcher = new DomainMatcher(PRIMARY_DOMAIN, - Arrays.asList(SECONDARY_DOMAIN1, SECONDARY_DOMAIN2)); - assertEquals(DomainMatcher.MATCH_NONE, domainMatcher.isSubDomain(null)); - } - - /** - * Verify the domain matching expectations based on the predefined {@link #TEST_DOMAIN_MAP}. - * - * @throws Exception - */ - @Test - public void matchTestDomains() throws Exception { - DomainMatcher domainMatcher = new DomainMatcher(PRIMARY_DOMAIN, - Arrays.asList(SECONDARY_DOMAIN1, SECONDARY_DOMAIN2)); - for (Map.Entry<String, Integer> entry : TEST_DOMAIN_MAP.entrySet()) { - assertEquals(entry.getValue().intValue(), domainMatcher.isSubDomain(entry.getKey())); - } - } - - /** - * Verify that the correct match status is returned when a domain matches both primary - * and secondary domain (primary domain have precedence over secondary). - * - * @throws Exception - */ - @Test - public void matchDomainWithBothPrimaryAndSecondary() throws Exception { - DomainMatcher domainMatcher = new DomainMatcher(PRIMARY_DOMAIN, - Arrays.asList(PRIMARY_DOMAIN)); - assertEquals(DomainMatcher.MATCH_PRIMARY, domainMatcher.isSubDomain(PRIMARY_DOMAIN)); - } - - /** - * Verify domain matching expectation when the secondary domain is a sub-domain of the - * primary domain. - * - * @throws Exception - */ - @Test - public void matchDomainWhenSecondaryIsSubdomainOfPrimary() throws Exception { - DomainMatcher domainMatcher = new DomainMatcher("google.com", - Arrays.asList("test.google.com")); - assertEquals(DomainMatcher.MATCH_PRIMARY, domainMatcher.isSubDomain("google.com")); - assertEquals(DomainMatcher.MATCH_PRIMARY, domainMatcher.isSubDomain("test.google.com")); - assertEquals(DomainMatcher.MATCH_PRIMARY, - domainMatcher.isSubDomain("abcd.test.google.com")); - } - - /** - * Verify domain matching expectations when the secondary domain is a sub-domain of the - * primary domain. - * - * @throws Exception - */ - @Test - public void matchDomainWhenPrimaryIsSubdomainOfSecondary() throws Exception { - DomainMatcher domainMatcher = new DomainMatcher("test.google.com", - Arrays.asList("google.com")); - assertEquals(DomainMatcher.MATCH_SECONDARY, domainMatcher.isSubDomain("google.com")); - assertEquals(DomainMatcher.MATCH_SECONDARY, domainMatcher.isSubDomain("test2.google.com")); - assertEquals(DomainMatcher.MATCH_PRIMARY, domainMatcher.isSubDomain("test.google.com")); - assertEquals(DomainMatcher.MATCH_PRIMARY, - domainMatcher.isSubDomain("adcd.test.google.com")); - } - - /** - * Verify domain matching expectations when the domain names contained empty label (domain - * name that contained ".."). - * - * @throws Exception - */ - @Test - public void matchDomainWithEmptyLabel() throws Exception { - DomainMatcher domainMatcher = new DomainMatcher("test.google..com", - Arrays.asList("google..com")); - assertEquals(DomainMatcher.MATCH_PRIMARY, domainMatcher.isSubDomain("test.google..com")); - assertEquals(DomainMatcher.MATCH_SECONDARY, domainMatcher.isSubDomain("google..com")); - } - - /** - * Verify domain matching expectation for arg2SubdomainOfArg1 based on predefined - * {@link #TEST_ARG_DOMAIN_MAP}. - * - * @throws Exception - */ - @Test - public void verifyArg2SubdomainOfArg1() throws Exception { - for (Map.Entry<Pair<String, String>, Boolean> entry : TEST_ARG_DOMAIN_MAP.entrySet()) { - assertEquals(entry.getValue().booleanValue(), - DomainMatcher.arg2SubdomainOfArg1(entry.getKey().first, entry.getKey().second)); - } - } - - /** - * Verify that arg2SubdomainOfArg1 works as expected when pass in null domains. - * - * @throws Exception - */ - @Test - public void arg2SubdomainOfArg1WithNullDomain() throws Exception { - assertFalse(DomainMatcher.arg2SubdomainOfArg1(null, "test.com")); - assertFalse(DomainMatcher.arg2SubdomainOfArg1("test.com", null)); - assertFalse(DomainMatcher.arg2SubdomainOfArg1(null, null)); - } - - /** - * Verify that arg2SubdomainOfArg1 works as expected when domain contains empty label. - * - * @throws Exception - */ - @Test - public void arg2SubdomainOfArg1WithEmptyLabel() throws Exception { - assertTrue(DomainMatcher.arg2SubdomainOfArg1("test..com", "adsf.test..com")); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/OsuNetworkConnectionTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/OsuNetworkConnectionTest.java deleted file mode 100644 index 8ada4b54e..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/OsuNetworkConnectionTest.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2017 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.server.wifi.hotspot2; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.eq; -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.BroadcastReceiver; -import android.content.Context; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.InetAddresses; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkRequest; -import android.net.RouteInfo; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.os.Handler; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.TestUtil; -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.net.InetAddress; - -/** - * Unit tests for {@link OsuNetworkConnection}. - */ -@SmallTest -public class OsuNetworkConnectionTest extends WifiBaseTest { - private static final String TAG = "OsuNetworkConnectionTest"; - private static final int ENABLE_LOGGING = 1; - private static final int DISABLE_LOGGING = 0; - - private static final int TEST_NETWORK_ID = 6; - private static final String TEST_NAI = null; - private static final String TEST_NAI_OSEN = "access.test.com"; - private static final String TEST_PROVIDER_NAME = "testService"; - private static final WifiSsid TEST_SSID = WifiSsid.createFromAsciiEncoded("Test SSID"); - - private OsuNetworkConnection mNetworkConnection; - private TestLooper mLooper; - private Handler mHandler; - - @Mock Context mContext; - @Mock WifiManager mWifiManager; - @Mock ConnectivityManager mConnectivityManager; - @Mock OsuNetworkConnection.Callbacks mNetworkCallbacks; - @Mock WifiInfo mWifiInfo; - @Mock Network mCurrentNetwork; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - doReturn(mWifiManager).when(mContext) - .getSystemService(eq(Context.WIFI_SERVICE)); - doReturn(mConnectivityManager).when(mContext) - .getSystemService(eq(Context.CONNECTIVITY_SERVICE)); - when(mWifiManager.isWifiEnabled()).thenReturn(true); - when(mWifiManager.enableNetwork(TEST_NETWORK_ID, true)).thenReturn(true); - when(mWifiManager.addNetwork(any(WifiConfiguration.class))).thenReturn(TEST_NETWORK_ID); - when(mWifiManager.getConnectionInfo()).thenReturn(mWifiInfo); - when(mWifiInfo.getNetworkId()).thenReturn(TEST_NETWORK_ID); - mLooper = new TestLooper(); - mHandler = new Handler(mLooper.getLooper()); - mNetworkConnection = new OsuNetworkConnection(mContext); - mNetworkConnection.enableVerboseLogging(ENABLE_LOGGING); - } - - private LinkProperties createProvisionedLinkProperties() { - InetAddress addrV4 = InetAddresses.parseNumericAddress("75.208.6.1"); - InetAddress dns1 = InetAddresses.parseNumericAddress("75.208.7.1"); - LinkAddress linkAddrV4 = new LinkAddress(addrV4, 32); - InetAddress gateway1 = InetAddresses.parseNumericAddress("75.208.8.1"); - LinkProperties lp4 = new LinkProperties(); - lp4.addLinkAddress(linkAddrV4); - lp4.addDnsServer(dns1); - lp4.addRoute(new RouteInfo(gateway1)); - return lp4; - } - - /** - * Verify that the class registers for receiving the necessary broadcast intents upon init. - * Verify that the initialization only occurs once even if init() is called multiple times. - */ - @Test - public void verifyBroadcastIntentRegistration() { - mNetworkConnection.init(mHandler); - - ArgumentCaptor<IntentFilter> intentFilterCaptor = - ArgumentCaptor.forClass(IntentFilter.class); - verify(mContext).registerReceiver(any(BroadcastReceiver.class), - intentFilterCaptor.capture(), any(), eq(mHandler)); - verify(mWifiManager).isWifiEnabled(); - IntentFilter intentFilter = intentFilterCaptor.getValue(); - assertEquals(intentFilter.countActions(), 1); - } - - /** - * Verifies that onWifiEnabled() callback is invoked when the relevant intent is - * received and the caller is subscribed to receive the callback. - */ - @Test - public void verifyWifiStateCallbacks() { - when(mWifiManager.isWifiEnabled()).thenReturn(false); - mNetworkConnection.init(mHandler); - ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), - any(IntentFilter.class), any(), eq(mHandler)); - BroadcastReceiver broadcastReceiver = broadcastReceiverCaptor.getValue(); - mLooper.dispatchAll(); - mNetworkConnection.setEventCallback(mNetworkCallbacks); - TestUtil.sendWifiStateChanged(broadcastReceiver, mContext, - WifiManager.WIFI_STATE_ENABLED); - TestUtil.sendWifiStateChanged(broadcastReceiver, mContext, - WifiManager.WIFI_STATE_DISABLED); - mNetworkConnection.setEventCallback(null); - TestUtil.sendWifiStateChanged(broadcastReceiver, mContext, - WifiManager.WIFI_STATE_ENABLED); - TestUtil.sendWifiStateChanged(broadcastReceiver, mContext, - WifiManager.WIFI_STATE_DISABLED); - verify(mNetworkCallbacks, times(1)).onWifiEnabled(); - verify(mNetworkCallbacks, times(1)).onWifiDisabled(); - } - - /** - * Verifies that connect() API returns false when Wifi is not enabled - */ - @Test - public void verifyNetworkConnectionWhenWifiIsDisabled() { - when(mWifiManager.isWifiEnabled()).thenReturn(false); - mNetworkConnection.init(mHandler); - assertEquals(false, mNetworkConnection.connect(TEST_SSID, TEST_NAI, TEST_PROVIDER_NAME)); - } - - /** - * Verifies that connect() API returns false when WifiManager's addNetwork() - * returns an invalid network ID - */ - @Test - public void verifyNetworkConnectionWhenAddNetworkFails() { - when(mWifiManager.addNetwork(any(WifiConfiguration.class))).thenReturn(-1); - mNetworkConnection.init(mHandler); - assertEquals(false, mNetworkConnection.connect(TEST_SSID, TEST_NAI, TEST_PROVIDER_NAME)); - verify(mWifiManager, never()).removeNetwork(TEST_NETWORK_ID); - } - - /** - * Verifies that connect() API returns false when WifiManager's enableNetwork() - * fails for the given network ID corresponding to the OSU AP - */ - @Test - public void verifyNetworkConnectionWhenEnableNetworkFails() { - when(mWifiManager.enableNetwork(TEST_NETWORK_ID, true)).thenReturn(false); - mNetworkConnection.init(mHandler); - assertEquals(false, mNetworkConnection.connect(TEST_SSID, TEST_NAI, TEST_PROVIDER_NAME)); - verify(mWifiManager).removeNetwork(TEST_NETWORK_ID); - } - - /** - * Verifies that network state callbacks are invoked when network callbacks - * are received and when WifiManager has successfully requested connection to the OSU AP. - * Ensure IP connectivity is available before invoking onConnected callback. - */ - @Test - public void verifyNetworkCallbackInvokedWhenConnected() { - mNetworkConnection.init(mHandler); - - mNetworkConnection.setEventCallback(mNetworkCallbacks); - assertEquals(true, mNetworkConnection.connect(TEST_SSID, TEST_NAI, TEST_PROVIDER_NAME)); - - ArgumentCaptor<ConnectivityManager.NetworkCallback> networkCallbackCaptor = - ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); - verify(mConnectivityManager).requestNetwork(any(NetworkRequest.class), - networkCallbackCaptor.capture(), any(Handler.class), anyInt()); - ConnectivityManager.NetworkCallback callback = networkCallbackCaptor.getValue(); - callback.onAvailable(mCurrentNetwork); - callback.onLinkPropertiesChanged(mCurrentNetwork, createProvisionedLinkProperties()); - verify(mNetworkCallbacks).onConnected(mCurrentNetwork); - - callback.onLost(mCurrentNetwork); - verify(mNetworkCallbacks).onDisconnected(); - - mNetworkConnection.disconnectIfNeeded(); - - verify(mConnectivityManager).unregisterNetworkCallback(any(ConnectivityManager - .NetworkCallback.class)); - verify(mWifiManager).removeNetwork(TEST_NETWORK_ID); - } - - /** - * Verifies that onConnected callback are never invoked when onLinkPropertiesChanged is invoked - * without onAvailable of NetworkCallback. - */ - @Test - public void verifyNetworkCallbackWithoutOnAvailable() { - mNetworkConnection.init(mHandler); - - mNetworkConnection.setEventCallback(mNetworkCallbacks); - assertEquals(true, mNetworkConnection.connect(TEST_SSID, TEST_NAI, TEST_PROVIDER_NAME)); - - ArgumentCaptor<ConnectivityManager.NetworkCallback> networkCallbackCaptor = - ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); - verify(mConnectivityManager).requestNetwork(any(NetworkRequest.class), - networkCallbackCaptor.capture(), any(Handler.class), anyInt()); - ConnectivityManager.NetworkCallback callback = networkCallbackCaptor.getValue(); - - callback.onLinkPropertiesChanged(mCurrentNetwork, createProvisionedLinkProperties()); - - verify(mNetworkCallbacks, never()).onConnected(mCurrentNetwork); - } - - /** - * Verifies that network state callbacks are invoked when the network callbacks - * are received and when WifiManager has successfully requested connection to the OSU AP. - * If IP connectivity is not provisioned, do not invoke onConnected callback. - */ - @Test - public void verifyNetworkConnectionTimeout() { - mNetworkConnection.init(mHandler); - - mNetworkConnection.setEventCallback(mNetworkCallbacks); - assertEquals(true, mNetworkConnection.connect(TEST_SSID, TEST_NAI, TEST_PROVIDER_NAME)); - - ArgumentCaptor<ConnectivityManager.NetworkCallback> networkCallbackCaptor = - ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); - verify(mConnectivityManager).requestNetwork(any(NetworkRequest.class), - networkCallbackCaptor.capture(), any(Handler.class), anyInt()); - ConnectivityManager.NetworkCallback callback = networkCallbackCaptor.getValue(); - callback.onLinkPropertiesChanged(mCurrentNetwork, new LinkProperties()); - verify(mNetworkCallbacks, never()).onConnected(mCurrentNetwork); - - callback.onUnavailable(); - verify(mNetworkCallbacks).onTimeOut(); - - mNetworkConnection.disconnectIfNeeded(); - - verify(mConnectivityManager).unregisterNetworkCallback(any(ConnectivityManager - .NetworkCallback.class)); - verify(mWifiManager).removeNetwork(TEST_NETWORK_ID); - } - - /** - * Verifies that WifiManager's removeNetwork() is called when disconnectIfNeeded() is called - * on the OSU AP's network ID. - */ - @Test - public void verifyNetworkDisconnect() { - mNetworkConnection.init(mHandler); - assertEquals(true, mNetworkConnection.connect(TEST_SSID, TEST_NAI, TEST_PROVIDER_NAME)); - - mNetworkConnection.disconnectIfNeeded(); - - verify(mConnectivityManager).unregisterNetworkCallback(any(ConnectivityManager - .NetworkCallback.class)); - verify(mWifiManager).removeNetwork(TEST_NETWORK_ID); - } - - /** - * Verifies that {@link WifiConfiguration} has been created properly for OSU network. - * It is supposed to create a network as ephemeral network and suppress no internet access - * notification. - */ - @Test - public void verifyWifiConfigurationForOsuNetwork() { - mNetworkConnection.init(mHandler); - - assertEquals(true, mNetworkConnection.connect(TEST_SSID, TEST_NAI, TEST_PROVIDER_NAME)); - - ArgumentCaptor<WifiConfiguration> wifiConfigurationCaptor = ArgumentCaptor.forClass( - WifiConfiguration.class); - verify(mWifiManager, times(1)).addNetwork(wifiConfigurationCaptor.capture()); - WifiConfiguration wifiConfiguration = wifiConfigurationCaptor.getValue(); - assertTrue(wifiConfiguration.isNoInternetAccessExpected()); - assertTrue(wifiConfiguration.isEphemeral()); - assertTrue(wifiConfiguration.osu); - - ArgumentCaptor<NetworkRequest> networkRequestCaptor = ArgumentCaptor.forClass( - NetworkRequest.class); - verify(mConnectivityManager, times(1)).requestNetwork(networkRequestCaptor.capture(), - any(ConnectivityManager.NetworkCallback.class), any(Handler.class), anyInt()); - assertFalse(networkRequestCaptor.getValue().hasCapability(NET_CAPABILITY_TRUSTED)); - - } - - /** - * Verifies that {@link WifiConfiguration} has been created properly for OSEN OSU network. - * It is supposed to create a network as ephemeral network with OSEN protocol and key management - * and suppress no internet access notification. - */ - @Test - public void verifyWifiConfigurationForOsenOsuNetwork() { - mNetworkConnection.init(mHandler); - - assertEquals(true, mNetworkConnection.connect(TEST_SSID, TEST_NAI_OSEN, - TEST_PROVIDER_NAME)); - - ArgumentCaptor<WifiConfiguration> wifiConfigurationCaptor = ArgumentCaptor.forClass( - WifiConfiguration.class); - verify(mWifiManager, times(1)).addNetwork(wifiConfigurationCaptor.capture()); - WifiConfiguration wifiConfiguration = wifiConfigurationCaptor.getValue(); - assertTrue(wifiConfiguration.isNoInternetAccessExpected()); - assertTrue(wifiConfiguration.isEphemeral()); - assertTrue(wifiConfiguration.osu); - assertTrue(wifiConfiguration.allowedProtocols.get(WifiConfiguration.Protocol.OSEN)); - assertTrue(wifiConfiguration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OSEN)); - assertEquals(wifiConfiguration.enterpriseConfig.getEapMethod(), - WifiEnterpriseConfig.Eap.UNAUTH_TLS); - assertEquals(wifiConfiguration.enterpriseConfig.getCaPath(), - WfaKeyStore.DEFAULT_WFA_CERT_DIR); - ArgumentCaptor<NetworkRequest> networkRequestCaptor = ArgumentCaptor.forClass( - NetworkRequest.class); - verify(mConnectivityManager, times(1)).requestNetwork(networkRequestCaptor.capture(), - any(ConnectivityManager.NetworkCallback.class), any(Handler.class), anyInt()); - assertFalse(networkRequestCaptor.getValue().hasCapability(NET_CAPABILITY_TRUSTED)); - - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/OsuServerConnectionTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/OsuServerConnectionTest.java deleted file mode 100644 index 4d75b3e8a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/OsuServerConnectionTest.java +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Copyright 2018 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.net.Network; -import android.os.test.TestLooper; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.soap.HttpsServiceConnection; -import com.android.server.wifi.hotspot2.soap.HttpsTransport; -import com.android.server.wifi.hotspot2.soap.SoapParser; -import com.android.server.wifi.hotspot2.soap.SppResponseMessage; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.HeaderProperty; -import org.ksoap2.SoapEnvelope; -import org.ksoap2.serialization.SoapObject; -import org.ksoap2.serialization.SoapSerializationEnvelope; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -/** - * Unit tests for {@link OsuServerConnection}. - */ -@SmallTest -public class OsuServerConnectionTest extends WifiBaseTest { - private static final String TEST_VALID_URL = "https://www.google.com"; - private static final String TEST_INVALID_URL = "http://www.google.com"; - private static final String AUTH_TYPE = "ECDHE_RSA"; - private static final String PROVIDER_NAME_VALID = "Boingo"; - private static final String PROVIDER_NAME_INVALID = "Boingo1"; - private static final String TEST_PROVIDER_CHINESE_NAME = "宝音阁"; - private static final int ENABLE_VERBOSE_LOGGING = 1; - private static final int TEST_SESSION_ID = 1; - - private TestLooper mLooper = new TestLooper(); - private OsuServerConnection mOsuServerConnection; - private URL mServerUrl; - private List<Pair<Locale, String>> mProviderIdentities = new ArrayList<>(); - private ArgumentCaptor<TrustManager[]> mTrustManagerCaptor = - ArgumentCaptor.forClass(TrustManager[].class); - private Map<Integer, Map<String, byte[]>> mTrustCertsInfo = new HashMap<>(); - private ArgumentCaptor<X509Certificate[]> mX509CertificateCaptor = - ArgumentCaptor.forClass(X509Certificate[].class); - private X509Certificate[] mCertificateArray; - - @Mock PasspointProvisioner.OsuServerCallbacks mOsuServerCallbacks; - @Mock Network mNetwork; - @Mock HttpsURLConnection mUrlConnection; - @Mock WfaKeyStore mWfaKeyStore; - @Mock SSLContext mTlsContext; - @Mock KeyStore mKeyStore; - @Mock X509TrustManager mX509TrustManager; - @Mock HttpsTransport mHttpsTransport; - @Mock HttpsServiceConnection mHttpsServiceConnection; - @Mock SppResponseMessage mSppResponseMessage; - @Mock TrustManagerFactory mTrustManagerFactory; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mOsuServerConnection = new OsuServerConnection(mLooper.getLooper()); - mOsuServerConnection.enableVerboseLogging(ENABLE_VERBOSE_LOGGING); - mProviderIdentities.add(Pair.create(Locale.US, PROVIDER_NAME_VALID)); - mServerUrl = new URL(TEST_VALID_URL); - when(mWfaKeyStore.get()).thenReturn(mKeyStore); - when(mOsuServerCallbacks.getSessionId()).thenReturn(TEST_SESSION_ID); - when(mNetwork.openConnection(any(URL.class))).thenReturn(mUrlConnection); - when(mHttpsTransport.getServiceConnection()).thenReturn(mHttpsServiceConnection); - when(mTrustManagerFactory.getTrustManagers()) - .thenReturn(new X509TrustManager[]{mX509TrustManager}); - mCertificateArray = new X509Certificate[]{ - PasspointProvisioningTestUtil.getOsuCertsForTest().get(0), - PasspointProvisioningTestUtil.getOsuCertsForTest().get(1) - }; - } - - /** - * Verifies initialization and connecting to the OSU server - */ - @Test - public void verifyInitAndConnect() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - ServiceProviderVerifier.class).startMocking(); - try { - when(ServiceProviderVerifier.getProviderNames(any(X509Certificate.class))).thenReturn( - mProviderIdentities); - - establishServerConnection(); - - TrustManager[] trustManagers = mTrustManagerCaptor.getValue(); - X509TrustManager trustManager = (X509TrustManager) trustManagers[0]; - - trustManager.checkServerTrusted(mCertificateArray, AUTH_TYPE); - - verify(mOsuServerCallbacks).onServerValidationStatus(anyInt(), eq(true)); - Map<String, String> providerNames = new HashMap<>(); - providerNames.put(Locale.US.getISO3Language(), PROVIDER_NAME_VALID); - assertTrue(mOsuServerConnection.validateProvider(providerNames)); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies multiple languages of OsuProvider names are matched with cert - */ - @Test - public void verifyValidateProviderWithMultipleProviderLangs() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - ServiceProviderVerifier.class).startMocking(); - try { - when(ServiceProviderVerifier.getProviderNames(any(X509Certificate.class))).thenReturn( - mProviderIdentities); - establishServerConnection(); - TrustManager[] trustManagers = mTrustManagerCaptor.getValue(); - X509TrustManager trustManager = (X509TrustManager) trustManagers[0]; - trustManager.checkServerTrusted(mCertificateArray, AUTH_TYPE); - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put( - Locale.SIMPLIFIED_CHINESE.getISO3Language(), TEST_PROVIDER_CHINESE_NAME); - friendlyNames.put(Locale.US.getISO3Language(), PROVIDER_NAME_VALID); - - assertTrue(mOsuServerConnection.validateProvider(friendlyNames)); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies wrong language of OsuProvider name is mismatched with cert - */ - @Test - public void verifyValidateProviderWithMismatchedProviderLang() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - ServiceProviderVerifier.class).startMocking(); - try { - when(ServiceProviderVerifier.getProviderNames(any(X509Certificate.class))).thenReturn( - mProviderIdentities); - establishServerConnection(); - TrustManager[] trustManagers = mTrustManagerCaptor.getValue(); - X509TrustManager trustManager = (X509TrustManager) trustManagers[0]; - trustManager.checkServerTrusted(mCertificateArray, AUTH_TYPE); - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put( - Locale.SIMPLIFIED_CHINESE.getISO3Language(), TEST_PROVIDER_CHINESE_NAME); - - assertFalse(mOsuServerConnection.validateProvider(friendlyNames)); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies same language from different regions. - */ - @Test - public void verifyValidateProviderWithSameLangButDifferentRegion() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - ServiceProviderVerifier.class).startMocking(); - try { - when(ServiceProviderVerifier.getProviderNames(any(X509Certificate.class))).thenReturn( - mProviderIdentities); - establishServerConnection(); - TrustManager[] trustManagers = mTrustManagerCaptor.getValue(); - X509TrustManager trustManager = (X509TrustManager) trustManagers[0]; - trustManager.checkServerTrusted(mCertificateArray, AUTH_TYPE); - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put( - Locale.CANADA.getISO3Language(), PROVIDER_NAME_VALID); - - assertTrue(mOsuServerConnection.validateProvider(friendlyNames)); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies initialization of the HTTPS connection with invalid TLSContext - */ - @Test - public void verifyInvalidTlsContext() { - mOsuServerConnection.init(null, mTrustManagerFactory); - mOsuServerConnection.setEventCallback(mOsuServerCallbacks); - - assertFalse(mOsuServerConnection.canValidateServer()); - } - - /** - * Verifies initialization of the HTTPS connection when TlsContext init fails - */ - @Test - public void verifyTlsContextInitFailure() throws Exception { - doThrow(new KeyManagementException()).when(mTlsContext).init(any(), any(), any()); - - mOsuServerConnection.init(mTlsContext, mTrustManagerFactory); - mOsuServerConnection.setEventCallback(mOsuServerCallbacks); - - assertFalse(mOsuServerConnection.canValidateServer()); - } - - /** - * Verifies initialization and opening URL connection failed on the network - */ - @Test - public void verifyInitAndNetworkOpenURLConnectionFailed() throws Exception { - doThrow(new IOException()).when(mNetwork).openConnection(any(URL.class)); - - mOsuServerConnection.init(mTlsContext, mTrustManagerFactory); - mOsuServerConnection.setEventCallback(mOsuServerCallbacks); - - assertTrue(mOsuServerConnection.canValidateServer()); - assertTrue(mOsuServerConnection.connect(mServerUrl, mNetwork)); - - mLooper.dispatchAll(); - - verify(mOsuServerCallbacks).onServerConnectionStatus(anyInt(), eq(false)); - } - - /** - * Verifies initialization and connection failure to OSU server - */ - @Test - public void verifyInitAndServerConnectFailure() throws Exception { - doThrow(new IOException()).when(mUrlConnection).connect(); - - mOsuServerConnection.init(mTlsContext, mTrustManagerFactory); - mOsuServerConnection.setEventCallback(mOsuServerCallbacks); - - assertTrue(mOsuServerConnection.canValidateServer()); - assertTrue(mOsuServerConnection.connect(mServerUrl, mNetwork)); - - mLooper.dispatchAll(); - - verify(mOsuServerCallbacks).onServerConnectionStatus(anyInt(), eq(false)); - } - - /** - * Verifies initialization and connecting to the OSU server, cert validation failure - */ - @Test - public void verifyInitAndConnectCertValidationFailure() throws Exception { - establishServerConnection(); - List<X509Certificate> certificateList = PasspointProvisioningTestUtil.getOsuCertsForTest(); - X509Certificate[] certificates = new X509Certificate[1]; - certificates[0] = certificateList.get(0); - TrustManager[] trustManagers = mTrustManagerCaptor.getValue(); - X509TrustManager trustManager = (X509TrustManager) trustManagers[0]; - doThrow(new CertificateException()).when(mX509TrustManager) - .checkServerTrusted(any(X509Certificate[].class), anyString()); - - trustManager.checkServerTrusted(certificates, AUTH_TYPE); - - verify(mOsuServerCallbacks).onServerValidationStatus(anyInt(), eq(false)); - } - - /** - * Verifies initialization and connecting to the OSU server, friendly name mismatch - */ - @Test - public void verifyInitAndConnectInvalidProviderIdentity()throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - ServiceProviderVerifier.class).startMocking(); - try { - when(ServiceProviderVerifier.getProviderNames(any(X509Certificate.class))).thenReturn( - mProviderIdentities); - - establishServerConnection(); - - TrustManager[] trustManagers = mTrustManagerCaptor.getValue(); - X509TrustManager trustManager = (X509TrustManager) trustManagers[0]; - - trustManager.checkServerTrusted(mCertificateArray, AUTH_TYPE); - - verify(mOsuServerCallbacks).onServerValidationStatus(anyInt(), eq(true)); - Map<String, String> providerNames = new HashMap<>(); - providerNames.put(Locale.US.getISO3Language(), PROVIDER_NAME_INVALID); - assertFalse(mOsuServerConnection.validateProvider(providerNames)); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies {@code ExchangeSoapMessage} should return {@code false} if there is no connection. - */ - @Test - public void verifyExchangeSoapMessageWithoutConnection() { - assertFalse(mOsuServerConnection.exchangeSoapMessage( - new SoapSerializationEnvelope(SoapEnvelope.VER12))); - } - - /** - * Verifies {@code ExchangeSoapMessage} should return {@code false} if {@code soapEnvelope} is - * {@code null} - */ - @Test - public void verifyExchangeSoapMessageWithInvalidArgument() throws Exception { - establishServerConnection(); - assertFalse(mOsuServerConnection.exchangeSoapMessage(null)); - } - - /** - * Verifies {@code ExchangeSoapMessage} should get {@code null} message if exception occurs - * during soap exchange. - */ - @Test - public void verifyExchangeSoapMessageWithException() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - HttpsTransport.class).startMocking(); - try { - establishServerConnection(); - when(HttpsTransport.createInstance(any(Network.class), any(URL.class))).thenReturn( - mHttpsTransport); - doThrow(new IOException()).when(mHttpsTransport).call(any(String.class), - any(SoapSerializationEnvelope.class)); - - assertTrue(mOsuServerConnection.exchangeSoapMessage( - new SoapSerializationEnvelope(SoapEnvelope.VER12))); - - mLooper.dispatchAll(); - - verify(mOsuServerCallbacks).onReceivedSoapMessage(anyInt(), isNull()); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies {@code ExchangeSoapMessage} should return an instance of {@link SppResponseMessage}. - */ - @Test - public void verifyExchangeSoapMessage() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - HttpsTransport.class).mockStatic(SoapParser.class).startMocking(); - try { - establishServerConnection(); - - SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12); - envelope.bodyIn = new SoapObject(); - when(HttpsTransport.createInstance(any(Network.class), any(URL.class))).thenReturn( - mHttpsTransport); - when(SoapParser.getResponse(any(SoapObject.class))).thenReturn(mSppResponseMessage); - - assertTrue(mOsuServerConnection.exchangeSoapMessage(envelope)); - - mLooper.dispatchAll(); - - verify(mOsuServerCallbacks).onReceivedSoapMessage(anyInt(), eq(mSppResponseMessage)); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies {@code retrieveTrustRootCerts} should return {@code false} if there is no - * connection. - */ - @Test - public void verifyRetrieveTrustRootCertsWithoutConnection() { - assertFalse(mOsuServerConnection.retrieveTrustRootCerts(mTrustCertsInfo)); - } - - /** - * Verifies {@code retrieveTrustRootCerts} should return {@code false} if {@code - * mTrustCertsInfo} is empty. - */ - @Test - public void verifyRetrieveTrustRootCertsWithEmptyOfTrustCertsInfo() { - mOsuServerConnection.init(mTlsContext, mTrustManagerFactory); - mOsuServerConnection.setEventCallback(mOsuServerCallbacks); - assertFalse(mOsuServerConnection.retrieveTrustRootCerts(mTrustCertsInfo)); - } - - /** - * Verifies it should return an empty collection of CA certificates if HTTPS response from - * server to get root CA certificate is not HTTP OK. - */ - @Test - public void verifyRetrieveTrustRootCertsWithErrorInHTTPSResponse() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - HttpsTransport.class).startMocking(); - try { - when(HttpsTransport.createInstance(any(Network.class), any(URL.class))).thenReturn( - mHttpsTransport); - when(mHttpsServiceConnection.getResponseCode()).thenReturn( - HttpURLConnection.HTTP_NO_CONTENT); - ArgumentCaptor<Map<Integer, List<X509Certificate>>> argumentCaptor = - ArgumentCaptor.forClass(Map.class); - - // Test Data - Map<String, byte[]> certInfo = new HashMap<>(); - certInfo.put("https://test.com/trustroot", "testData".getBytes()); - certInfo.put("https://test2.com/trustroot", "testData2".getBytes()); - mTrustCertsInfo.put(OsuServerConnection.TRUST_CERT_TYPE_AAA, certInfo); - - establishServerConnection(); - - assertTrue(mOsuServerConnection.retrieveTrustRootCerts(mTrustCertsInfo)); - - mLooper.dispatchAll(); - - verify(mOsuServerCallbacks).onReceivedTrustRootCertificates(anyInt(), - argumentCaptor.capture()); - assertTrue(argumentCaptor.getValue().isEmpty()); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies it should return a collection of CA certificates if there is no error while - * downloading root CA certificate from each {@code URL} provided - */ - @Test - public void verifyRetrieveTrustRootCertsWithoutError() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - HttpsTransport.class).mockStatic(CertificateFactory.class).mockStatic( - ServiceProviderVerifier.class).startMocking(); - try { - X509Certificate certificate = Mockito.mock(X509Certificate.class); - InputStream inputStream = Mockito.mock(InputStream.class); - - // To avoid infinite loop in OsuServerConnection.getCert. - when(inputStream.read(any(byte[].class), anyInt(), anyInt())).thenReturn(-1); - - CertificateFactory certificateFactory = Mockito.mock(CertificateFactory.class); - when(certificateFactory.generateCertificate(any(InputStream.class))).thenReturn( - certificate); - when(CertificateFactory.getInstance(anyString())).thenReturn(certificateFactory); - when(HttpsTransport.createInstance(any(Network.class), any(URL.class))).thenReturn( - mHttpsTransport); - when(mHttpsServiceConnection.getResponseCode()).thenReturn( - HttpURLConnection.HTTP_OK); - when(mHttpsServiceConnection.openInputStream()).thenReturn(inputStream); - ArgumentCaptor<Map<Integer, List<X509Certificate>>> argumentCaptor = - ArgumentCaptor.forClass(Map.class); - when(ServiceProviderVerifier.verifyCertFingerprint(any(X509Certificate.class), - any(byte[].class))).thenReturn(true); - - // Test Data - Map<String, byte[]> certInfo = new HashMap<>(); - certInfo.put("https://test.com/trustroot", "testData".getBytes()); - mTrustCertsInfo.put(OsuServerConnection.TRUST_CERT_TYPE_AAA, certInfo); - - List<HeaderProperty> properties = new ArrayList<>(); - - // Indicates that X.509 CA certificate is included. - properties.add(new HeaderProperty("Content-Type", "application/x-x509-ca-cert")); - when(mHttpsServiceConnection.getResponseProperties()).thenReturn(properties); - - establishServerConnection(); - - assertTrue(mOsuServerConnection.retrieveTrustRootCerts(mTrustCertsInfo)); - - mLooper.dispatchAll(); - - verify(mOsuServerCallbacks).onReceivedTrustRootCertificates(anyInt(), - argumentCaptor.capture()); - Assert.assertEquals(1, argumentCaptor.getValue().size()); - Assert.assertEquals(certificate, - argumentCaptor.getValue().get(OsuServerConnection.TRUST_CERT_TYPE_AAA).get(0)); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies that cleanup is properly called on the OsuServerHandlerThread. - */ - @Test - public void verifyCleanup() throws Exception { - // static mocking - MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( - HttpsTransport.class).mockStatic(SoapParser.class).startMocking(); - try { - establishServerConnection(); - - SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12); - envelope.bodyIn = new SoapObject(); - when(HttpsTransport.createInstance(any(Network.class), any(URL.class))).thenReturn( - mHttpsTransport); - when(SoapParser.getResponse(any(SoapObject.class))).thenReturn(mSppResponseMessage); - - assertTrue(mOsuServerConnection.exchangeSoapMessage(envelope)); - - mLooper.dispatchAll(); - - verify(mHttpsServiceConnection).disconnect(); - reset(mHttpsServiceConnection); - - mOsuServerConnection.cleanup(); - mLooper.dispatchAll(); - - verify(mUrlConnection).disconnect(); - verify(mHttpsServiceConnection, never()).disconnect(); - } finally { - session.finishMocking(); - } - } - - /** - * Verifies initialization and opening URL connection failure for an HTTP URL (not HTTPS) - */ - @Test - public void verifyInitAndNetworkOpenURLConnectionFailedWithHttpUrl() throws Exception { - mServerUrl = new URL(TEST_INVALID_URL); - mOsuServerConnection.init(mTlsContext, mTrustManagerFactory); - mOsuServerConnection.setEventCallback(mOsuServerCallbacks); - - assertTrue(mOsuServerConnection.canValidateServer()); - assertFalse(mOsuServerConnection.connect(mServerUrl, mNetwork)); - } - - private void establishServerConnection() throws Exception { - mOsuServerConnection.init(mTlsContext, mTrustManagerFactory); - mOsuServerConnection.setEventCallback(mOsuServerCallbacks); - verify(mTlsContext).init(isNull(), mTrustManagerCaptor.capture(), isNull()); - verify(mTrustManagerFactory).getTrustManagers(); - - assertTrue(mOsuServerConnection.canValidateServer()); - assertTrue(mOsuServerConnection.connect(mServerUrl, mNetwork)); - mLooper.dispatchAll(); - - verify(mOsuServerCallbacks).onServerConnectionStatus(anyInt(), eq(true)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java deleted file mode 100644 index 3ee3c15f6..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiConfigStore; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointConfigSharedStoreData}. - */ -@SmallTest -public class PasspointConfigSharedStoreDataTest extends WifiBaseTest { - @Mock PasspointConfigSharedStoreData.DataSource mDataSource; - PasspointConfigSharedStoreData mConfigStoreData; - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mConfigStoreData = new PasspointConfigSharedStoreData(mDataSource); - } - - /** - * Helper function for serializing store data to a XML block. - * - * @return byte[] - * @throws Exception - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for deserializing store data from a XML block. - * - * @param data The XML block data bytes - * @throws Exception - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - } - - /** - * Verify that the serialization and deserialization of share store data works as expected. - * The data used for serialization matches the result of the deserialization. - * - * @throws Exception - */ - @Test - public void serializeAndDeserializeShareStoreData() throws Exception { - // Setup expected data. - long providerIndex = 412; - - // Serialize data for share store. - when(mDataSource.getProviderIndex()).thenReturn(providerIndex); - byte[] data = serializeData(); - - // Deserialize data for share store and verify the content. - deserializeData(data); - verify(mDataSource).setProviderIndex(providerIndex); - } - - /** - * Verify that deserialization of an empty share store data doesn't cause any exception - * and the corresponding data source should not be updated. - * - * @throws Exception - */ - @Test - public void deserializeEmptyShareStoreData() throws Exception { - deserializeData(new byte[0]); - verify(mDataSource, never()).setProviderIndex(anyLong()); - } - - /** - * Verify that PasspointConfigUserStoreData is written to - * {@link WifiConfigStore#STORE_FILE_NAME_SHARED_GENERAL}. - * - * @throws Exception - */ - @Test - public void getUserStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_SHARED_GENERAL, - mConfigStoreData.getStoreFileId()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java deleted file mode 100644 index 697f83125..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2; - -import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.net.wifi.hotspot2.pps.Policy; -import android.net.wifi.hotspot2.pps.UpdateParameter; -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiCarrierInfoManager; -import com.android.server.wifi.WifiConfigStore; -import com.android.server.wifi.WifiKeyStore; -import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointConfigUserStoreData}. - */ -@SmallTest -public class PasspointConfigUserStoreDataTest extends WifiBaseTest { - private static final String TEST_CA_CERTIFICATE_ALIAS = "CaCert"; - private static final String TEST_CA_CERTIFICATE_ALIAS_2 = "CaCert_2"; - private static final String TEST_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS = "ClientPrivateKeyAndCert"; - private static final String TEST_REMEDIATION_CA_CERTIFICATE_ALIAS = "CaCert_3"; - private static final String TEST_CREATOR_PACKAGE = "com.android.test"; - private static final long TEST_PROVIDER_ID = 1; - private static final long TEST_PROVIDER_ID_2 = 2; - private static final int TEST_CREATOR_UID = 1234; - private static final boolean TEST_HAS_EVER_CONNECTED = true; - private static final boolean TEST_SHARED = false; - - @Mock WifiKeyStore mKeyStore; - @Mock WifiCarrierInfoManager mWifiCarrierInfoManager; - @Mock PasspointConfigUserStoreData.DataSource mDataSource; - PasspointConfigUserStoreData mConfigStoreData; - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mConfigStoreData = new PasspointConfigUserStoreData(mKeyStore, mWifiCarrierInfoManager, - mDataSource); - } - - /** - * Helper function for generating a {@link PasspointConfiguration} for testing the XML - * serialization/deserialization logic. - * - * @return {@link PasspointConfiguration} - * @throws Exception - */ - private PasspointConfiguration createFullPasspointConfiguration() throws Exception { - DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - byte[] certFingerprint = new byte[32]; - Arrays.fill(certFingerprint, (byte) 0x1f); - - PasspointConfiguration config = new PasspointConfiguration(); - config.setUpdateIdentifier(12); - config.setCredentialPriority(99); - - // AAA Server trust root. - Map<String, byte[]> trustRootCertList = new HashMap<>(); - trustRootCertList.put("server1.trust.root.com", certFingerprint); - config.setTrustRootCertList(trustRootCertList); - - // Subscription update. - UpdateParameter subscriptionUpdate = new UpdateParameter(); - subscriptionUpdate.setUpdateIntervalInMinutes(120); - subscriptionUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP); - subscriptionUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER); - subscriptionUpdate.setServerUri("subscription.update.com"); - subscriptionUpdate.setUsername("subscriptionUser"); - subscriptionUpdate.setBase64EncodedPassword("subscriptionPass"); - subscriptionUpdate.setTrustRootCertUrl("subscription.update.cert.com"); - subscriptionUpdate.setTrustRootCertSha256Fingerprint(certFingerprint); - config.setSubscriptionUpdate(subscriptionUpdate); - - // Subscription parameters. - config.setSubscriptionCreationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime()); - config.setSubscriptionExpirationTimeInMillis( - format.parse("2016-03-01T10:00:00Z").getTime()); - config.setSubscriptionType("Gold"); - config.setUsageLimitDataLimit(921890); - config.setUsageLimitStartTimeInMillis(format.parse("2016-12-01T10:00:00Z").getTime()); - config.setUsageLimitTimeLimitInMinutes(120); - config.setUsageLimitUsageTimePeriodInMinutes(99910); - - // HomeSP configuration. - HomeSp homeSp = new HomeSp(); - homeSp.setFriendlyName("Century House"); - homeSp.setFqdn("mi6.co.uk"); - homeSp.setRoamingConsortiumOis(new long[] {0x112233L, 0x445566L}); - homeSp.setIconUrl("icon.test.com"); - Map<String, Long> homeNetworkIds = new HashMap<>(); - homeNetworkIds.put("TestSSID", 0x12345678L); - homeNetworkIds.put("NullHESSID", null); - homeSp.setHomeNetworkIds(homeNetworkIds); - homeSp.setMatchAllOis(new long[] {0x11223344}); - homeSp.setMatchAnyOis(new long[] {0x55667788}); - homeSp.setOtherHomePartners(new String[] {"other.fqdn.com"}); - config.setHomeSp(homeSp); - - // Credential configuration. - Credential credential = new Credential(); - credential.setCreationTimeInMillis(format.parse("2016-01-01T10:00:00Z").getTime()); - credential.setExpirationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime()); - credential.setRealm("shaken.stirred.com"); - credential.setCheckAaaServerCertStatus(true); - Credential.UserCredential userCredential = new Credential.UserCredential(); - userCredential.setUsername("james"); - userCredential.setPassword("Ym9uZDAwNw=="); - userCredential.setMachineManaged(true); - userCredential.setSoftTokenApp("TestApp"); - userCredential.setAbleToShare(true); - userCredential.setEapType(21); - userCredential.setNonEapInnerMethod("MS-CHAP-V2"); - credential.setUserCredential(userCredential); - Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); - certCredential.setCertType("x509v3"); - certCredential.setCertSha256Fingerprint(certFingerprint); - credential.setCertCredential(certCredential); - Credential.SimCredential simCredential = new Credential.SimCredential(); - simCredential.setImsi("imsi"); - simCredential.setEapType(24); - credential.setSimCredential(simCredential); - config.setCredential(credential); - - // Policy configuration. - Policy policy = new Policy(); - List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>(); - Policy.RoamingPartner partner1 = new Policy.RoamingPartner(); - partner1.setFqdn("test1.fqdn.com"); - partner1.setFqdnExactMatch(true); - partner1.setPriority(127); - partner1.setCountries("us,fr"); - Policy.RoamingPartner partner2 = new Policy.RoamingPartner(); - partner2.setFqdn("test2.fqdn.com"); - partner2.setFqdnExactMatch(false); - partner2.setPriority(200); - partner2.setCountries("*"); - preferredRoamingPartnerList.add(partner1); - preferredRoamingPartnerList.add(partner2); - policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList); - policy.setMinHomeDownlinkBandwidth(23412); - policy.setMinHomeUplinkBandwidth(9823); - policy.setMinRoamingDownlinkBandwidth(9271); - policy.setMinRoamingUplinkBandwidth(2315); - policy.setExcludedSsidList(new String[] {"excludeSSID"}); - Map<Integer, String> requiredProtoPortMap = new HashMap<>(); - requiredProtoPortMap.put(12, "34,92,234"); - policy.setRequiredProtoPortMap(requiredProtoPortMap); - policy.setMaximumBssLoadValue(23); - UpdateParameter policyUpdate = new UpdateParameter(); - policyUpdate.setUpdateIntervalInMinutes(120); - policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM); - policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP); - policyUpdate.setServerUri("policy.update.com"); - policyUpdate.setUsername("updateUser"); - policyUpdate.setBase64EncodedPassword("updatePass"); - policyUpdate.setTrustRootCertUrl("update.cert.com"); - policyUpdate.setTrustRootCertSha256Fingerprint(certFingerprint); - policy.setPolicyUpdate(policyUpdate); - config.setPolicy(policy); - return config; - } - - /** - * Helper function for serializing store data to a XML block. - * - * @return byte[] - * @throws Exception - */ - private byte[] serializeData() throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); - out.flush(); - return outputStream.toByteArray(); - } - - /** - * Helper function for deserializing store data from a XML block. - * - * @param data The XML block data bytes - * @throws Exception - */ - private void deserializeData(byte[] data) throws Exception { - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.deserializeData(in, in.getDepth(), - WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, - mock(WifiConfigStoreEncryptionUtil.class)); - } - - /** - * Verify that the serialization and deserialization of user store data works as expected. - * The data used for serialization matches the result of the deserialization. - * - * @throws Exception - */ - @Test - public void serializeAndDeserializeUserStoreData() throws Exception { - // Setup expected data. - List<PasspointProvider> providerList = new ArrayList<>(); - PasspointProvider provider1 = new PasspointProvider(createFullPasspointConfiguration(), - mKeyStore, mWifiCarrierInfoManager, TEST_PROVIDER_ID, TEST_CREATOR_UID, - TEST_CREATOR_PACKAGE, false, Arrays.asList(TEST_CA_CERTIFICATE_ALIAS), - TEST_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, null, - TEST_HAS_EVER_CONNECTED, TEST_SHARED); - PasspointProvider provider2 = new PasspointProvider(createFullPasspointConfiguration(), - mKeyStore, mWifiCarrierInfoManager, TEST_PROVIDER_ID_2, TEST_CREATOR_UID, - TEST_CREATOR_PACKAGE, true, - Arrays.asList(TEST_CA_CERTIFICATE_ALIAS, TEST_CA_CERTIFICATE_ALIAS_2), - TEST_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, TEST_REMEDIATION_CA_CERTIFICATE_ALIAS, - TEST_HAS_EVER_CONNECTED, TEST_SHARED); - provider2.setAutojoinEnabled(false); - provider2.setMacRandomizationEnabled(false); - provider2.setMeteredOverride(METERED_OVERRIDE_METERED); - provider2.setTrusted(false); - providerList.add(provider1); - providerList.add(provider2); - - // Serialize data for user store. - when(mDataSource.getProviders()).thenReturn(providerList); - byte[] data = serializeData(); - - // Deserialize data for user store and verify the content. - ArgumentCaptor<ArrayList> providersCaptor = ArgumentCaptor.forClass(ArrayList.class); - deserializeData(data); - verify(mDataSource).setProviders(providersCaptor.capture()); - assertEquals(providerList, providersCaptor.getValue()); - } - - /** - * Verify that deserialization of an empty user store data doesn't cause any exception and - * the corresponding data source should not be updated. - * - * @throws Exception - */ - @Test - public void deserializeEmptyUserStoreData() throws Exception { - deserializeData(new byte[0]); - verify(mDataSource, never()).setProviders(any(ArrayList.class)); - } - - /** - * Verify that PasspointConfigUserStoreData is written to - * {@link WifiConfigStore#STORE_FILE_USER_GENERAL}. - * - * @throws Exception - */ - @Test - public void getUserStoreFileId() throws Exception { - assertEquals(WifiConfigStore.STORE_FILE_USER_GENERAL, - mConfigStoreData.getStoreFileId()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointEventHandlerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointEventHandlerTest.java deleted file mode 100644 index c21697e69..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointEventHandlerTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.hotspot2.anqp.Constants; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointEventHandler}. - * TODO(zqiu): add more test when switch over to use wificond. - */ -@SmallTest -public class PasspointEventHandlerTest extends WifiBaseTest { - - private static final String TAG = "PasspointEventHandlerTest"; - - private static final long BSSID = 0x112233445566L; - private static final String BSSID_STR = "11:22:33:44:55:66"; - private static final String ICON_FILENAME = "icon.test"; - - @Mock WifiNative mWifiNative; - @Mock PasspointEventHandler.Callbacks mCallbacks; - PasspointEventHandler mHandler; - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - initMocks(this); - mHandler = new PasspointEventHandler(mWifiNative, mCallbacks); - } - - /** - * Test for requesting Hotspot 2.0 R1 ANQP element. - */ - @Test - public void requestR1AnqpElement() { - List<Constants.ANQPElementType> elementToRequest = - Arrays.asList(Constants.ANQPElementType.ANQPRoamingConsortium); - HashSet<Integer> expAnqpIds = - new HashSet<>(Arrays.asList(Constants.getANQPElementID( - Constants.ANQPElementType.ANQPRoamingConsortium))); - HashSet<Integer> expHs20Subtypes = new HashSet<>(); - - // wpa_supplicant succeeded the request. - when(mWifiNative.requestAnqp(any(), eq(BSSID_STR), eq(expAnqpIds), eq(expHs20Subtypes))) - .thenReturn(true); - assertTrue(mHandler.requestANQP(BSSID, elementToRequest)); - - // wpa_supplicant failed the request. - when(mWifiNative.requestAnqp(any(), eq(BSSID_STR), eq(expAnqpIds), eq(expHs20Subtypes))) - .thenReturn(false); - assertFalse(mHandler.requestANQP(BSSID, elementToRequest)); - } - - /** - * Test for requesting Hotspot 2.0 R2 ANQP element. - */ - @Test - public void requestR2AnqpElement() { - List<Constants.ANQPElementType> elementToRequest = - Arrays.asList(Constants.ANQPElementType.HSFriendlyName); - HashSet<Integer> expAnqpIds = new HashSet<>(); - HashSet<Integer> expHs20Subtypes = - new HashSet<>(Arrays.asList(Constants.getHS20ElementID( - Constants.ANQPElementType.HSFriendlyName))); - - // wpa_supplicant succeeded the request. - when(mWifiNative.requestAnqp(any(), eq(BSSID_STR), eq(expAnqpIds), eq(expHs20Subtypes))) - .thenReturn(true); - assertTrue(mHandler.requestANQP(BSSID, elementToRequest)); - - // wpa_supplicant failed the request. - when(mWifiNative.requestAnqp(any(), eq(BSSID_STR), eq(expAnqpIds), eq(expHs20Subtypes))) - .thenReturn(false); - assertFalse(mHandler.requestANQP(BSSID, elementToRequest)); - } - - /** - * Test for requesting both Hotspot 2.0 R1 and R2 ANQP elements. - */ - @Test - public void requestMixAnqpElements() { - List<Constants.ANQPElementType> elementToRequest = - Arrays.asList(Constants.ANQPElementType.ANQPRoamingConsortium, - Constants.ANQPElementType.HSFriendlyName); - HashSet<Integer> expAnqpIds = - new HashSet<>(Arrays.asList(Constants.getANQPElementID( - Constants.ANQPElementType.ANQPRoamingConsortium))); - HashSet<Integer> expHs20Subtypes = - new HashSet<>(Arrays.asList(Constants.getHS20ElementID( - Constants.ANQPElementType.HSFriendlyName))); - - // wpa_supplicant succeeded the request. - when(mWifiNative.requestAnqp(any(), eq(BSSID_STR), eq(expAnqpIds), eq(expHs20Subtypes))) - .thenReturn(true); - assertTrue(mHandler.requestANQP(BSSID, elementToRequest)); - - // wpa_supplicant failed the request. - when(mWifiNative.requestAnqp(any(), eq(BSSID_STR), eq(expAnqpIds), eq(expHs20Subtypes))) - .thenReturn(false); - assertFalse(mHandler.requestANQP(BSSID, elementToRequest)); - } - - /** - * Test for requesting both Hotspot 2.0 R2 icon file. - */ - @Test - public void requestIconFile() { - // wpa_supplicant succeeded the request. - when(mWifiNative.requestIcon(any(), eq(BSSID_STR), eq(ICON_FILENAME))).thenReturn(true); - assertTrue(mHandler.requestIcon(BSSID, ICON_FILENAME)); - - // wpa_supplicant failed the request. - when(mWifiNative.requestIcon(any(), eq(BSSID_STR), eq(ICON_FILENAME))).thenReturn(false); - assertFalse(mHandler.requestIcon(BSSID, ICON_FILENAME)); - } - - /** - * Test for ANQP request completed with error. - */ - @Test - public void anqpRequestCompletedWithError() { - mHandler.notifyANQPDone(new AnqpEvent(BSSID, null)); - verify(mCallbacks).onANQPResponse(BSSID, null); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java deleted file mode 100644 index cb459728a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java +++ /dev/null @@ -1,2627 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static android.app.AppOpsManager.MODE_IGNORED; -import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE; -import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; -import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NOT_METERED; -import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS; - -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP; - -import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.anyMap; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.app.AppOpsManager; -import android.content.Context; -import android.content.Intent; -import android.net.MacAddress; -import android.net.Uri; -import android.net.wifi.EAPConstants; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.os.Handler; -import android.os.Looper; -import android.os.UserHandle; -import android.os.test.TestLooper; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.util.Base64; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.ClientModeImpl; -import com.android.server.wifi.Clock; -import com.android.server.wifi.FakeKeys; -import com.android.server.wifi.FrameworkFacade; -import com.android.server.wifi.MacAddressUtil; -import com.android.server.wifi.NetworkUpdateResult; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiCarrierInfoManager; -import com.android.server.wifi.WifiConfigManager; -import com.android.server.wifi.WifiConfigStore; -import com.android.server.wifi.WifiConfigurationTestUtil; -import com.android.server.wifi.WifiContext; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiKeyStore; -import com.android.server.wifi.WifiMetrics; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.WifiNetworkSuggestionsManager; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; -import com.android.server.wifi.hotspot2.anqp.DomainNameElement; -import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement; -import com.android.server.wifi.hotspot2.anqp.I18Name; -import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; -import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; -import com.android.server.wifi.util.InformationElementUtil; -import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoSession; - -import java.nio.charset.StandardCharsets; -import java.security.KeyStore; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -/** - * Unit tests for {@link PasspointManager}. - */ -@SmallTest -public class PasspointManagerTest extends WifiBaseTest { - private static final long BSSID = 0x112233445566L; - private static final String TEST_PACKAGE = "com.android.test"; - private static final String TEST_PACKAGE1 = "com.android.test1"; - private static final String TEST_FQDN = "test1.test.com"; - private static final String TEST_FQDN2 = "test2.test.com"; - private static final String TEST_FRIENDLY_NAME = "friendly name"; - private static final String TEST_FRIENDLY_NAME2 = "second friendly name"; - private static final String TEST_REALM = "realm.test.com"; - private static final String TEST_REALM2 = "realm.test2.com"; - private static final String TEST_REALM3 = "realm.test3.com"; - private static final String TEST_IMSI = "123456*"; - private static final String FULL_IMSI = "123456789123456"; - private static final int TEST_CARRIER_ID = 10; - private static final int TEST_SUBID = 1; - - private static final long TEST_BSSID = 0x112233445566L; - private static final String TEST_SSID = "TestSSID"; - private static final String TEST_BSSID_STRING = "11:22:33:44:55:66"; - private static final String TEST_SSID2 = "TestSSID2"; - private static final String TEST_BSSID_STRING2 = "11:22:33:44:55:77"; - private static final String TEST_SSID3 = "TestSSID3"; - private static final String TEST_BSSID_STRING3 = "11:22:33:44:55:88"; - private static final String TEST_MCC_MNC = "123456"; - private static final String TEST_3GPP_FQDN = String.format("wlan.mnc%s.mcc%s.3gppnetwork.org", - TEST_MCC_MNC.substring(3), TEST_MCC_MNC.substring(0, 3)); - - private static final long TEST_HESSID = 0x5678L; - private static final int TEST_ANQP_DOMAIN_ID = 0; - private static final int TEST_ANQP_DOMAIN_ID2 = 1; - private static final ANQPNetworkKey TEST_ANQP_KEY = ANQPNetworkKey.buildKey( - TEST_SSID, TEST_BSSID, TEST_HESSID, TEST_ANQP_DOMAIN_ID); - private static final ANQPNetworkKey TEST_ANQP_KEY2 = ANQPNetworkKey.buildKey( - TEST_SSID, TEST_BSSID, TEST_HESSID, TEST_ANQP_DOMAIN_ID2); - private static final int TEST_CREATOR_UID = 1234; - private static final int TEST_CREATOR_UID1 = 1235; - private static final int TEST_UID = 1500; - private static final int TEST_NETWORK_ID = 2; - - @Mock Context mContext; - @Mock WifiNative mWifiNative; - @Mock WifiKeyStore mWifiKeyStore; - @Mock Clock mClock; - @Mock PasspointObjectFactory mObjectFactory; - @Mock PasspointEventHandler.Callbacks mCallbacks; - @Mock AnqpCache mAnqpCache; - @Mock ANQPRequestManager mAnqpRequestManager; - @Mock WifiConfigManager mWifiConfigManager; - @Mock WifiConfigStore mWifiConfigStore; - PasspointConfigSharedStoreData.DataSource mSharedDataSource; - PasspointConfigUserStoreData.DataSource mUserDataSource; - @Mock WifiMetrics mWifiMetrics; - @Mock OsuNetworkConnection mOsuNetworkConnection; - @Mock OsuServerConnection mOsuServerConnection; - @Mock PasspointProvisioner mPasspointProvisioner; - @Mock IProvisioningCallback mCallback; - @Mock WfaKeyStore mWfaKeyStore; - @Mock KeyStore mKeyStore; - @Mock AppOpsManager mAppOpsManager; - @Mock WifiInjector mWifiInjector; - @Mock ClientModeImpl mClientModeImpl; - @Mock TelephonyManager mTelephonyManager; - @Mock SubscriptionManager mSubscriptionManager; - @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; - @Mock MacAddressUtil mMacAddressUtil; - @Mock WifiPermissionsUtil mWifiPermissionsUtil; - - Handler mHandler; - TestLooper mLooper; - PasspointManager mManager; - ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor = - ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class); - WifiCarrierInfoManager mWifiCarrierInfoManager; - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - initMocks(this); - when(mObjectFactory.makeAnqpCache(mClock)).thenReturn(mAnqpCache); - when(mObjectFactory.makeANQPRequestManager(any(), eq(mClock))) - .thenReturn(mAnqpRequestManager); - when(mObjectFactory.makeOsuNetworkConnection(any(Context.class))) - .thenReturn(mOsuNetworkConnection); - when(mObjectFactory.makeOsuServerConnection()) - .thenReturn(mOsuServerConnection); - when(mObjectFactory.makeWfaKeyStore()).thenReturn(mWfaKeyStore); - when(mWfaKeyStore.get()).thenReturn(mKeyStore); - when(mObjectFactory.makePasspointProvisioner(any(Context.class), any(WifiNative.class), - any(PasspointManager.class), any(WifiMetrics.class))) - .thenReturn(mPasspointProvisioner); - when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager); - when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl); - when(mWifiInjector.getWifiNetworkSuggestionsManager()) - .thenReturn(mWifiNetworkSuggestionsManager); - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(true); - mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager, - mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class), - mock(WifiContext.class), mWifiConfigStore, mock(Handler.class), mWifiMetrics); - mLooper = new TestLooper(); - mHandler = new Handler(mLooper.getLooper()); - mManager = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative, - mWifiKeyStore, mClock, mObjectFactory, mWifiConfigManager, - mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil, - mWifiPermissionsUtil); - ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks = - ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class); - verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class), - callbacks.capture()); - ArgumentCaptor<PasspointConfigSharedStoreData.DataSource> sharedDataSource = - ArgumentCaptor.forClass(PasspointConfigSharedStoreData.DataSource.class); - verify(mObjectFactory).makePasspointConfigSharedStoreData(sharedDataSource.capture()); - ArgumentCaptor<PasspointConfigUserStoreData.DataSource> userDataSource = - ArgumentCaptor.forClass(PasspointConfigUserStoreData.DataSource.class); - verify(mObjectFactory).makePasspointConfigUserStoreData(any(WifiKeyStore.class), - any(WifiCarrierInfoManager.class), userDataSource.capture()); - mCallbacks = callbacks.getValue(); - mSharedDataSource = sharedDataSource.getValue(); - mUserDataSource = userDataSource.getValue(); - // SIM is absent - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Collections.emptyList()); - } - - /** - * Verify that the given Passpoint configuration matches the one that's added to - * the PasspointManager. - * - * @param expectedConfig The expected installed Passpoint configuration - */ - private void verifyInstalledConfig(PasspointConfiguration expectedConfig) { - List<PasspointConfiguration> installedConfigs = - mManager.getProviderConfigs(TEST_CREATOR_UID, true); - assertEquals(1, installedConfigs.size()); - assertEquals(expectedConfig, installedConfigs.get(0)); - } - - private PasspointProvider createMockProvider(PasspointConfiguration config) { - WifiConfiguration wifiConfig = WifiConfigurationTestUtil.generateWifiConfig(-1, - TEST_UID, "\"PasspointTestSSID\"", true, true, - config.getHomeSp().getFqdn(), TEST_FRIENDLY_NAME, SECURITY_EAP); - return createMockProvider(config, wifiConfig, false); - } - - /** - * Create a mock PasspointProvider with default expectations. - * - * @param config The configuration associated with the provider - * @return {@link com.android.server.wifi.hotspot2.PasspointProvider} - */ - private PasspointProvider createMockProvider( - PasspointConfiguration config, WifiConfiguration wifiConfig, boolean isSuggestion) { - PasspointProvider provider = mock(PasspointProvider.class); - when(provider.installCertsAndKeys()).thenReturn(true); - lenient().when(provider.getConfig()).thenReturn(config); - lenient().when(provider.getWifiConfig()).thenReturn(wifiConfig); - lenient().when(provider.getCreatorUid()).thenReturn(TEST_CREATOR_UID); - lenient().when(provider.isFromSuggestion()).thenReturn(isSuggestion); - lenient().when(provider.isAutojoinEnabled()).thenReturn(true); - return provider; - } - - /** - * Helper function for creating a test configuration with user credential. - * - * @return {@link PasspointConfiguration} - */ - private PasspointConfiguration createTestConfigWithUserCredential(String fqdn, - String friendlyName) { - return createTestConfigWithUserCredentialAndRealm(fqdn, friendlyName, TEST_REALM); - } - - /** - * Helper function for creating a test configuration with user credential - * and a unique realm. - * - * @return {@link PasspointConfiguration} - */ - private PasspointConfiguration createTestConfigWithUserCredentialAndRealm(String fqdn, - String friendlyName, String realm) { - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - homeSp.setFriendlyName(friendlyName); - config.setHomeSp(homeSp); - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put("en", friendlyName); - friendlyNames.put("kr", friendlyName + 1); - friendlyNames.put("jp", friendlyName + 2); - config.setServiceFriendlyNames(friendlyNames); - Credential credential = new Credential(); - credential.setRealm(realm != null ? realm : TEST_REALM); - credential.setCaCertificate(FakeKeys.CA_CERT0); - Credential.UserCredential userCredential = new Credential.UserCredential(); - userCredential.setUsername("username"); - userCredential.setPassword("password"); - userCredential.setEapType(EAPConstants.EAP_TTLS); - userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP); - credential.setUserCredential(userCredential); - config.setCredential(credential); - return config; - } - - /** - * Helper function for creating a test configuration with SIM credential. - * - * @return {@link PasspointConfiguration} - */ - private PasspointConfiguration createTestConfigWithSimCredential(String fqdn, String imsi, - String realm) { - PasspointConfiguration config = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - homeSp.setFriendlyName(TEST_FRIENDLY_NAME); - config.setHomeSp(homeSp); - Credential credential = new Credential(); - credential.setRealm(TEST_REALM); - Credential.SimCredential simCredential = new Credential.SimCredential(); - simCredential.setImsi(imsi); - simCredential.setEapType(EAPConstants.EAP_SIM); - credential.setSimCredential(simCredential); - config.setCredential(credential); - return config; - } - - private PasspointProvider addTestProvider(String fqdn, String friendlyName, - String packageName, boolean isSuggestion, String realm) { - WifiConfiguration wifiConfig = WifiConfigurationTestUtil.generateWifiConfig(-1, TEST_UID, - "\"PasspointTestSSID\"", true, true, - fqdn, friendlyName, SECURITY_EAP); - - return addTestProvider(fqdn, friendlyName, packageName, wifiConfig, isSuggestion, realm); - } - - /** - * Helper function for adding a test provider to the manager. Return the mock - * provider that's added to the manager. - * - * @return {@link PasspointProvider} - */ - private PasspointProvider addTestProvider(String fqdn, String friendlyName, - String packageName, WifiConfiguration wifiConfig, boolean isSuggestion, String realm) { - PasspointConfiguration config = - createTestConfigWithUserCredentialAndRealm(fqdn, friendlyName, realm); - wifiConfig.setPasspointUniqueId(config.getUniqueId()); - PasspointProvider provider = createMockProvider(config, wifiConfig, isSuggestion); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(isSuggestion))).thenReturn(provider); - when(provider.getPackageName()).thenReturn(packageName); - assertTrue(mManager.addOrUpdateProvider( - config, TEST_CREATOR_UID, TEST_PACKAGE, isSuggestion, true)); - return provider; - } - - /** - * Helper function for creating a ScanResult for testing. - * - * @return {@link ScanResult} - */ - private ScanResult createTestScanResult() { - ScanResult scanResult = new ScanResult(); - scanResult.SSID = TEST_SSID; - scanResult.BSSID = TEST_BSSID_STRING; - scanResult.hessid = TEST_HESSID; - scanResult.anqpDomainId = TEST_ANQP_DOMAIN_ID; - scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK; - return scanResult; - } - - /** - * Helper function for creating a ScanResult for testing. - * - * @return {@link ScanResult} - */ - private List<ScanResult> createTestScanResults() { - List<ScanResult> scanResults = new ArrayList<>(); - - // Passpoint AP - ScanResult scanResult = new ScanResult(); - scanResult.SSID = TEST_SSID; - scanResult.BSSID = TEST_BSSID_STRING; - scanResult.hessid = TEST_HESSID; - scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK; - scanResult.anqpDomainId = TEST_ANQP_DOMAIN_ID2; - scanResults.add(scanResult); - - // Non-Passpoint AP - ScanResult scanResult2 = new ScanResult(); - scanResult2.SSID = TEST_SSID2; - scanResult2.BSSID = TEST_BSSID_STRING2; - scanResult2.hessid = TEST_HESSID; - scanResult2.flags = 0; - scanResults.add(scanResult2); - - // Passpoint AP - ScanResult scanResult3 = new ScanResult(); - scanResult3.SSID = TEST_SSID3; - scanResult3.BSSID = TEST_BSSID_STRING3; - scanResult3.hessid = TEST_HESSID; - scanResult3.flags = ScanResult.FLAG_PASSPOINT_NETWORK; - scanResult3.anqpDomainId = TEST_ANQP_DOMAIN_ID2; - scanResults.add(scanResult3); - - return scanResults; - } - - /** - * Verify that the ANQP elements will be added to the ANQP cache on receiving a successful - * response. - * - * @throws Exception - */ - @Test - public void anqpResponseSuccess() throws Exception { - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); - - when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(TEST_ANQP_KEY); - mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap); - verify(mAnqpCache).addEntry(TEST_ANQP_KEY, anqpElementMap); - verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class), - any(String.class)); - } - - /** - * Verify that no ANQP elements will be added to the ANQP cache on receiving a successful - * response for a request that's not sent by us. - * - * @throws Exception - */ - @Test - public void anqpResponseSuccessWithUnknownRequest() throws Exception { - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); - - when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(null); - mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap); - verify(mAnqpCache, never()).addEntry(any(ANQPNetworkKey.class), anyMap()); - } - - /** - * Verify that no ANQP elements will be added to the ANQP cache on receiving a failure response. - * - * @throws Exception - */ - @Test - public void anqpResponseFailure() throws Exception { - when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, false)).thenReturn(TEST_ANQP_KEY); - mCallbacks.onANQPResponse(TEST_BSSID, null); - verify(mAnqpCache, never()).addEntry(any(ANQPNetworkKey.class), anyMap()); - - } - - /** - * Verify that adding a provider with a null configuration will fail. - * - * @throws Exception - */ - @Test - public void addProviderWithNullConfig() throws Exception { - assertFalse(mManager.addOrUpdateProvider(null, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify that adding a provider with a empty configuration will fail. - * - * @throws Exception - */ - @Test - public void addProviderWithEmptyConfig() throws Exception { - assertFalse(mManager.addOrUpdateProvider(new PasspointConfiguration(), TEST_CREATOR_UID, - TEST_PACKAGE, false, true)); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify taht adding a provider with an invalid credential will fail (using EAP-TLS - * for user credential). - * - * @throws Exception - */ - @Test - public void addProviderWithInvalidCredential() throws Exception { - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - // EAP-TLS not allowed for user credential. - config.getCredential().getUserCredential().setEapType(EAPConstants.EAP_TLS); - assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify that adding a provider from a background user will fail. - * - * @throws Exception - */ - @Test - public void addProviderWithBackgroundUser() throws Exception { - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(false); - - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config); - when(provider.getPackageName()).thenReturn(TEST_PACKAGE); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(provider); - assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, - TEST_PACKAGE, false, true)); - - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify that adding a user saved provider with a valid configuration and user credential will - * succeed. - * - * @throws Exception - */ - private void addRemoveSavedProviderWithValidUserCredential(boolean useFqdn) throws Exception { - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config); - when(provider.getPackageName()).thenReturn(TEST_PACKAGE); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(provider); - assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verifyInstalledConfig(config); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE), - any(AppOpsManager.OnOpChangedListener.class)); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Verify content in the data source. - List<PasspointProvider> providers = mUserDataSource.getProviders(); - assertEquals(1, providers.size()); - assertEquals(config, providers.get(0).getConfig()); - - // Verify calling |enableAutoJoin|, |enableMacRandomization|, and |setMeteredOverride| - verifyEnableAutojoin(providers.get(0), useFqdn); - verifyEnableMacRandomization(providers.get(0)); - verifySetMeteredOverride(providers.get(0)); - - // Provider index start with 0, should be 1 after adding a provider. - assertEquals(1, mSharedDataSource.getProviderIndex()); - - // Remove the provider as the creator app. - if (useFqdn) { - assertTrue(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN)); - } else { - assertTrue( - mManager.removeProvider(TEST_CREATOR_UID, false, config.getUniqueId(), null)); - } - - verify(provider).uninstallCertsAndKeys(); - verify(mWifiConfigManager, times(3)).removePasspointConfiguredNetwork( - provider.getWifiConfig().getKey()); - /** - * 1 from |removeProvider| + 2 from |setAutojoinEnabled| + 2 from - * |enableMacRandomization| + 2 from |setMeteredOverride| = 7 calls to |saveToStore| - */ - verify(mWifiConfigManager, times(7)).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess(); - verify(mAppOpsManager).stopWatchingMode(any(AppOpsManager.OnOpChangedListener.class)); - assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty()); - - // Verify content in the data source. - assertTrue(mUserDataSource.getProviders().isEmpty()); - // Removing a provider should not change the provider index. - assertEquals(1, mSharedDataSource.getProviderIndex()); - } - - /** - * Verify that adding a user saved provider with a valid configuration and user credential will - * succeed. Remove provider using FQDN as key. - * - * @throws Exception - */ - @Test - public void addRemoveByFqdnSavedProviderWithValidUserCredential() throws Exception { - addRemoveSavedProviderWithValidUserCredential(true); - } - - /** - * Verify that adding a user saved provider with a valid configuration and user credential will - * succeed. Remove provider using unique identifier as key. - * - * @throws Exception - */ - @Test - public void addRemoveByUniqueIdSavedProviderWithValidUserCredential() throws Exception { - addRemoveSavedProviderWithValidUserCredential(false); - } - - /** - * Verify enable/disable autojoin on a provider. - * @param provider a mock provider that is already added into the PasspointManager - */ - private void verifyEnableAutojoin(PasspointProvider provider, boolean useFqdn) { - when(provider.setAutojoinEnabled(anyBoolean())).thenReturn(true); - if (useFqdn) { - assertTrue(mManager.enableAutojoin(null, provider.getConfig().getHomeSp().getFqdn(), - false)); - verify(provider).setAutojoinEnabled(false); - assertTrue(mManager.enableAutojoin(null, provider.getConfig().getHomeSp().getFqdn(), - true)); - verify(provider).setAutojoinEnabled(true); - assertFalse(mManager.enableAutojoin(null, provider.getConfig().getHomeSp() - .getFqdn() + "-XXXX", true)); - } else { - assertTrue(mManager.enableAutojoin(provider.getConfig().getUniqueId(), null, - false)); - verify(provider).setAutojoinEnabled(false); - assertTrue(mManager.enableAutojoin(provider.getConfig().getUniqueId(), null, - true)); - verify(provider).setAutojoinEnabled(true); - assertFalse( - mManager.enableAutojoin(provider.getConfig().getHomeSp().getFqdn() + "-XXXX", - null, true)); - } - verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF, - false, true); - verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON, - false, true); - } - - /** - * Verify enable/disable mac randomization on a provider. - * @param provider a mock provider that is already added into the PasspointManager - */ - private void verifyEnableMacRandomization(PasspointProvider provider) { - when(provider.setMacRandomizationEnabled(anyBoolean())).thenReturn(true); - assertTrue(mManager.enableMacRandomization(provider.getConfig().getHomeSp().getFqdn(), - false)); - verify(provider).setMacRandomizationEnabled(false); - verify(mWifiMetrics).logUserActionEvent( - UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF, false, true); - assertTrue(mManager.enableMacRandomization(provider.getConfig().getHomeSp().getFqdn(), - true)); - verify(mWifiConfigManager, times(2)).removePasspointConfiguredNetwork( - provider.getWifiConfig().getKey()); - verify(mWifiMetrics).logUserActionEvent( - UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_ON, false, true); - verify(provider).setMacRandomizationEnabled(true); - assertFalse(mManager.enableMacRandomization(provider.getConfig().getHomeSp().getFqdn() - + "-XXXX", false)); - } - - private void verifySetMeteredOverride(PasspointProvider provider) { - when(provider.setMeteredOverride(anyInt())).thenReturn(true); - assertTrue(mManager.setMeteredOverride(provider.getConfig().getHomeSp().getFqdn(), - METERED_OVERRIDE_METERED)); - verify(provider).setMeteredOverride(METERED_OVERRIDE_METERED); - verify(mWifiMetrics).logUserActionEvent( - UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_METERED, false, true); - assertTrue(mManager.setMeteredOverride(provider.getConfig().getHomeSp().getFqdn(), - METERED_OVERRIDE_NOT_METERED)); - verify(provider).setMeteredOverride(METERED_OVERRIDE_NOT_METERED); - verify(mWifiMetrics).logUserActionEvent( - UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_UNMETERED, false, true); - assertFalse(mManager.setMeteredOverride(provider.getConfig().getHomeSp().getFqdn() - + "-XXXX", METERED_OVERRIDE_METERED)); - } - - /** - * Verify that adding a user saved provider with a valid configuration and SIM credential will - * succeed. - * - * @throws Exception - */ - @Test - public void addRemoveSavedProviderWithValidSimCredential() throws Exception { - PasspointConfiguration config = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, - TEST_REALM); - PasspointProvider provider = createMockProvider(config); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(provider); - assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verifyInstalledConfig(config); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Verify content in the data source. - List<PasspointProvider> providers = mUserDataSource.getProviders(); - assertEquals(1, providers.size()); - assertEquals(config, providers.get(0).getConfig()); - // Provider index start with 0, should be 1 after adding a provider. - assertEquals(1, mSharedDataSource.getProviderIndex()); - - // Remove the provider as a privileged non-creator app. - assertTrue(mManager.removeProvider(TEST_UID, true, null, TEST_FQDN)); - verify(provider).uninstallCertsAndKeys(); - verify(mWifiConfigManager).removePasspointConfiguredNetwork( - provider.getWifiConfig().getKey()); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess(); - assertTrue(mManager.getProviderConfigs(TEST_UID, true).isEmpty()); - - // Verify content in the data source. - assertTrue(mUserDataSource.getProviders().isEmpty()); - // Removing a provider should not change the provider index. - assertEquals(1, mSharedDataSource.getProviderIndex()); - } - - /** - * Verify that if the passpoint profile has full IMSI, the carrier ID should be updated when - * the matched SIM card is present. - * @throws Exception - */ - @Test - public void addProviderWithValidFullImsiOfSimCredential() throws Exception { - PasspointConfiguration config = - createTestConfigWithSimCredential(TEST_FQDN, FULL_IMSI, TEST_REALM); - X509Certificate[] certArr = new X509Certificate[] {FakeKeys.CA_CERT0}; - config.getCredential().setCaCertificates(certArr); - SubscriptionInfo subInfo = mock(SubscriptionInfo.class); - when(subInfo.getSubscriptionId()).thenReturn(TEST_SUBID); - when(subInfo.getCarrierId()).thenReturn(TEST_CARRIER_ID); - TelephonyManager specifiedTm = mock(TelephonyManager.class); - when(mTelephonyManager.createForSubscriptionId(eq(TEST_SUBID))).thenReturn(specifiedTm); - when(specifiedTm.getSubscriberId()).thenReturn(FULL_IMSI); - List<SubscriptionInfo> subInfoList = new ArrayList<SubscriptionInfo>() {{ - add(subInfo); - }}; - when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subInfoList); - when(mWifiKeyStore.putCaCertInKeyStore(any(String.class), any(Certificate.class))) - .thenReturn(true); - PasspointObjectFactory spyFactory = spy(new PasspointObjectFactory()); - when(mWifiNetworkSuggestionsManager.isPasspointSuggestionSharedWithUser(any())) - .thenReturn(true); - PasspointManager ut = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative, - mWifiKeyStore, mClock, spyFactory, mWifiConfigManager, - mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil, - mWifiPermissionsUtil); - - assertTrue(ut.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - true, true)); - - assertEquals(TEST_CARRIER_ID, config.getCarrierId()); - List<String> passpointProfilesList = new ArrayList<String>(){{ - add(config.getUniqueId()); - }}; - assertEquals(TEST_CARRIER_ID, - ut.getWifiConfigsForPasspointProfiles(passpointProfilesList).get(0).carrierId); - - } - - /** - * Verify that adding a user saved provider with the same base domain as the existing provider - * will succeed, and verify that the new provider with the new configuration is added. - * - * @throws Exception - */ - @Test - public void addSavedProviderWithExistingConfig() throws Exception { - // Add a provider with the original configuration. - PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, - TEST_REALM); - PasspointProvider origProvider = createMockProvider(origConfig); - when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(origProvider); - assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verifyInstalledConfig(origConfig); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Verify data source content. - List<PasspointProvider> origProviders = mUserDataSource.getProviders(); - assertEquals(1, origProviders.size()); - assertEquals(origConfig, origProviders.get(0).getConfig()); - assertEquals(1, mSharedDataSource.getProviderIndex()); - - // Add same provider as existing suggestion provider - // This should be no WifiConfig deletion - WifiConfiguration origWifiConfig = origProvider.getWifiConfig(); - when(mWifiConfigManager.getConfiguredNetwork(origWifiConfig.getKey())) - .thenReturn(origWifiConfig); - when(mWifiConfigManager.addOrUpdateNetwork( - origWifiConfig, TEST_CREATOR_UID, TEST_PACKAGE)) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verify(mWifiConfigManager, never()).removePasspointConfiguredNetwork( - origWifiConfig.getKey()); - verify(mWifiConfigManager).addOrUpdateNetwork( - argThat((c) -> c.FQDN.equals(TEST_FQDN)), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE)); - verify(mWifiConfigManager).allowAutojoin(TEST_NETWORK_ID, origWifiConfig.allowAutojoin); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - assertEquals(2, mSharedDataSource.getProviderIndex()); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Add another provider with the same base domain as the existing provider. - // This should replace the existing provider with the new configuration. - PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider newProvider = createMockProvider(newConfig); - when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(newProvider); - when(mWifiConfigManager.getConfiguredNetwork(origProvider.getWifiConfig().getKey())) - .thenReturn(origWifiConfig); - assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - - List<PasspointConfiguration> installedConfigs = - mManager.getProviderConfigs(TEST_CREATOR_UID, true); - assertEquals(2, installedConfigs.size()); - assertTrue(installedConfigs.contains(origConfig)); - assertTrue(installedConfigs.contains(newConfig)); - - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - - // Verify data source content. - List<PasspointProvider> newProviders = mUserDataSource.getProviders(); - assertEquals(2, newProviders.size()); - assertTrue(newConfig.equals(newProviders.get(0).getConfig()) - || newConfig.equals(newProviders.get(1).getConfig())); - assertEquals(3, mSharedDataSource.getProviderIndex()); - } - - /** - * Verify that adding a provider will fail when failing to install certificates and - * key to the keystore. - * - * @throws Exception - */ - @Test - public void addProviderOnKeyInstallationFailiure() throws Exception { - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider provider = mock(PasspointProvider.class); - when(provider.installCertsAndKeys()).thenReturn(false); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), eq( - mWifiCarrierInfoManager), - anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false))).thenReturn(provider); - assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify that adding a provider with R1 configuration and a private self-signed CA certificate - * is installed correctly. - * - * @throws Exception - */ - @Test - public void addProviderWithR1ConfigPrivateCaCert() throws Exception { - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(provider); - assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verifyInstalledConfig(config); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify that adding a provider with R2 configuration will not perform CA certificate - * verification. - * - * @throws Exception - */ - @Test - public void addProviderWithR2Config() throws Exception { - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - config.setUpdateIdentifier(1); - PasspointProvider provider = createMockProvider(config); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(provider); - assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verifyInstalledConfig(config); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify that removing a non-existing provider will fail. - * - * @throws Exception - */ - @Test - public void removeNonExistingProvider() throws Exception { - assertFalse(mManager.removeProvider(TEST_CREATOR_UID, true, null, TEST_FQDN)); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess(); - } - - /** - * Verify that a empty list will be returned when no providers are installed. - * - * @throws Exception - */ - @Test - public void matchProviderWithNoProvidersInstalled() throws Exception { - assertTrue(mManager.matchProvider(createTestScanResult()).isEmpty()); - } - - /** - * Verify that a {code null} be returned when ANQP entry doesn't exist in the cache. - * - * @throws Exception - */ - @Test - public void matchProviderWithAnqpCacheMissed() throws Exception { - // static mocking - MockitoSession session = - com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic( - InformationElementUtil.class).startMocking(); - try { - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null); - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.hsRelease = NetworkDetail.HSRelease.R1; - when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); - InformationElementUtil.RoamingConsortium roamingConsortium = - new InformationElementUtil.RoamingConsortium(); - roamingConsortium.anqpOICount = 0; - when(InformationElementUtil.getRoamingConsortiumIE(isNull())) - .thenReturn(roamingConsortium); - assertTrue(mManager.matchProvider(createTestScanResult()).isEmpty()); - // Verify that a request for ANQP elements is initiated. - verify(mAnqpRequestManager).requestANQPElements(eq(TEST_BSSID), - any(ANQPNetworkKey.class), - anyBoolean(), any(NetworkDetail.HSRelease.class)); - } finally { - session.finishMocking(); - } - } - - /** - * Verify that the expected provider will be returned when a HomeProvider is matched. - * - * @throws Exception - */ - @Test - public void matchProviderAsHomeProvider() throws Exception { - PasspointProvider provider = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - ANQPData entry = new ANQPData(mClock, null); - - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.HomeProvider); - List<Pair<PasspointProvider, PasspointMatch>> results = - mManager.matchProvider(createTestScanResult()); - Pair<PasspointProvider, PasspointMatch> result = results.get(0); - assertEquals(PasspointMatch.HomeProvider, result.second); - assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn()); - } - - /** - * Verify that the expected provider will be returned when a RoamingProvider is matched. - * - * @throws Exception - */ - @Test - public void matchProviderAsRoamingProvider() throws Exception { - PasspointProvider provider = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - ANQPData entry = new ANQPData(mClock, null); - - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.RoamingProvider); - List<Pair<PasspointProvider, PasspointMatch>> results = - mManager.matchProvider(createTestScanResult()); - Pair<PasspointProvider, PasspointMatch> result = results.get(0); - assertEquals(PasspointMatch.RoamingProvider, result.second); - assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn()); - } - - /** - * When multiple providers matched for a single scanResult, when there is any home provider - * available, return all matched home provider. Otherwise return all roaming provider. - */ - @Test - public void matchScanResultWithMultipleProviderAsHomeAndRoaming() { - // Only add roaming providers. - PasspointProvider roamingProvider1 = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - PasspointProvider roamingProvider2 = - addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2, TEST_PACKAGE1, false, null); - ANQPData entry = new ANQPData(mClock, null); - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(roamingProvider1.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.RoamingProvider); - when(roamingProvider2.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.RoamingProvider); - List<Pair<PasspointProvider, PasspointMatch>> results = - mManager.matchProvider(createTestScanResult()); - // Return all matched roaming providers. - assertEquals(2, results.size()); - for (Pair<PasspointProvider, PasspointMatch> result : results) { - assertEquals(PasspointMatch.RoamingProvider, result.second); - } - // Add home providers. - PasspointProvider homeProvider1 = - addTestProvider(TEST_FQDN + "home", TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - PasspointProvider homeProvider2 = addTestProvider(TEST_FQDN2 + "home", TEST_FRIENDLY_NAME2, - TEST_PACKAGE1, false, null); - when(homeProvider1.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.HomeProvider); - when(homeProvider2.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.HomeProvider); - results = mManager.matchProvider(createTestScanResult()); - // When home providers are available, should return all home providers. - assertEquals(2, results.size()); - for (Pair<PasspointProvider, PasspointMatch> result : results) { - assertEquals(PasspointMatch.HomeProvider, result.second); - } - } - - /** - * Verify that a {code null} will be returned when there is no matching provider. - * - * @throws Exception - */ - @Test - public void matchProviderWithNoMatch() throws Exception { - PasspointProvider provider = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - ANQPData entry = new ANQPData(mClock, null); - - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.None); - assertTrue(mManager.matchProvider(createTestScanResult()).isEmpty()); - } - - /** - * Verify the expectations for sweepCache. - * - * @throws Exception - */ - @Test - public void sweepCache() throws Exception { - mManager.sweepCache(); - verify(mAnqpCache).sweep(); - } - - /** - * Verify that an empty map will be returned if ANQP elements are not cached for the given AP. - * - * @throws Exception - */ - @Test - public void getANQPElementsWithNoMatchFound() throws Exception { - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null); - assertTrue(mManager.getANQPElements(createTestScanResult()).isEmpty()); - } - - /** - * Verify that an expected ANQP elements will be returned if ANQP elements are cached for the - * given AP. - * - * @throws Exception - */ - @Test - public void getANQPElementsWithMatchFound() throws Exception { - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); - ANQPData entry = new ANQPData(mClock, anqpElementMap); - - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - assertEquals(anqpElementMap, mManager.getANQPElements(createTestScanResult())); - } - - /** - * Verify that if the Carrier ID is updated during match, the config should be persisted. - */ - @Test - public void getAllMatchingProvidersUpdatedConfigWithFullImsiSimCredential() { - // static mocking - MockitoSession session = - com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic( - InformationElementUtil.class).startMocking(); - try { - PasspointProvider provider = addTestProvider(TEST_FQDN + 0, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - when(provider.tryUpdateCarrierId()).thenReturn(true); - reset(mWifiConfigManager); - - ANQPData entry = new ANQPData(mClock, null); - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2; - - when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(entry); - when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); - when(provider.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.HomeProvider); - - List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = - mManager.getAllMatchedProviders(createTestScanResult()); - - verify(mWifiConfigManager).saveToStore(eq(true)); - - } finally { - session.finishMocking(); - } - } - /** - * Verify that an expected map of FQDN and a list of ScanResult will be returned when provided - * scanResults are matched to installed Passpoint profiles. - */ - @Test - public void getAllMatchingFqdnsForScanResults() { - // static mocking - MockitoSession session = - com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic( - InformationElementUtil.class).startMocking(); - try { - PasspointProvider providerHome = addTestProvider(TEST_FQDN + 0, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - providerHome.getWifiConfig().isHomeProviderNetwork = true; - PasspointProvider providerRoaming = addTestProvider(TEST_FQDN + 1, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1, - TEST_UID, "\"PasspointTestSSID\"", true, true, - TEST_FQDN + 2, TEST_FRIENDLY_NAME, SECURITY_EAP); - PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME, - TEST_PACKAGE, wifiConfiguration, false, null); - ANQPData entry = new ANQPData(mClock, null); - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2; - - when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(entry); - when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); - when(providerHome.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.HomeProvider); - when(providerRoaming.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.RoamingProvider); - when(providerNone.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.None); - - Map<String, Map<Integer, List<ScanResult>>> configs = - mManager.getAllMatchingPasspointProfilesForScanResults( - createTestScanResults()); - - // Expects to be matched with home Provider for each AP (two APs). - assertEquals(2, configs.get(providerHome.getConfig().getUniqueId()).get( - WifiManager.PASSPOINT_HOME_NETWORK).size()); - assertFalse(configs.get(providerHome.getConfig().getUniqueId()) - .containsKey(WifiManager.PASSPOINT_ROAMING_NETWORK)); - - // Expects to be matched with roaming Provider for each AP (two APs). - assertEquals(2, configs.get(providerRoaming.getConfig().getUniqueId()).get( - WifiManager.PASSPOINT_ROAMING_NETWORK).size()); - assertFalse(configs.get(providerRoaming.getConfig().getUniqueId()) - .containsKey(WifiManager.PASSPOINT_HOME_NETWORK)); - - } finally { - session.finishMocking(); - } - } - - /** - * Verify that an expected list of {@link WifiConfiguration} will be returned when provided - * a list of FQDN is matched to installed Passpoint profiles. For suggestion passpoint network, - * will check if that suggestion share credential with user to choose from wifi picker. - */ - @Test - public void getWifiConfigsForPasspointProfiles() { - PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - PasspointProvider provider2 = addTestProvider(TEST_FQDN + 1, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - PasspointProvider provider3 = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - - assertEquals(3, mManager.getWifiConfigsForPasspointProfiles( - Arrays.asList(provider1.getConfig().getUniqueId(), - provider2.getConfig().getUniqueId(), provider3.getConfig().getUniqueId(), - TEST_FQDN + "_353ab8c93", TEST_FQDN + "_83765319aca")).size()); - PasspointProvider provider4 = addTestProvider(TEST_FQDN + 3, TEST_FRIENDLY_NAME, - TEST_PACKAGE, true, null); - when(mWifiNetworkSuggestionsManager - .isPasspointSuggestionSharedWithUser(provider4.getWifiConfig())).thenReturn(false); - assertEquals(3, mManager.getWifiConfigsForPasspointProfiles( - Arrays.asList(provider1.getConfig().getUniqueId(), - provider2.getConfig().getUniqueId(), provider3.getConfig().getUniqueId(), - provider4.getConfig().getUniqueId(), TEST_FQDN + "_83765319aca")).size()); - PasspointProvider provider5 = addTestProvider(TEST_FQDN + 4, TEST_FRIENDLY_NAME, - TEST_PACKAGE, true, null); - when(mWifiNetworkSuggestionsManager - .isPasspointSuggestionSharedWithUser(provider5.getWifiConfig())).thenReturn(true); - assertEquals(4, mManager.getWifiConfigsForPasspointProfiles( - Arrays.asList(provider1.getConfig().getUniqueId(), - provider2.getConfig().getUniqueId(), provider3.getConfig().getUniqueId(), - provider4.getConfig().getUniqueId(), provider5.getConfig().getUniqueId())) - .size()); - } - - /** - * Verify that a {@link WifiConfiguration} will be returned with the correct value for the - * randomized MAC address. - */ - @Test - public void getWifiConfigsForPasspointProfilesWithoutEnhancedMacRandomization() { - MacAddress randomizedMacAddress = MacAddress.fromString("01:23:45:67:89:ab"); - when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(randomizedMacAddress); - when(mWifiConfigManager.shouldUseAggressiveRandomization(any())).thenReturn(false); - PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - WifiConfiguration config = mManager.getWifiConfigsForPasspointProfiles( - Collections.singletonList(provider.getConfig().getUniqueId())).get(0); - assertEquals(config.getRandomizedMacAddress(), randomizedMacAddress); - } - - /** - * Verify that a {@link WifiConfiguration} will be returned with DEFAULT_MAC_ADDRESS for the - * randomized MAC address if enhanced mac randomization is enabled. This value will display in - * the wifi picker's network details page as "Not available" if the network is disconnected. - */ - @Test - public void getWifiConfigsForPasspointProfilesWithEnhancedMacRandomization() { - MacAddress randomizedMacAddress = MacAddress.fromString("01:23:45:67:89:ab"); - when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(randomizedMacAddress); - when(mWifiConfigManager.shouldUseAggressiveRandomization(any())).thenReturn(true); - PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - WifiConfiguration config = mManager.getWifiConfigsForPasspointProfiles( - Collections.singletonList(provider.getConfig().getUniqueId())).get(0); - assertEquals(config.getRandomizedMacAddress(), MacAddress.fromString(DEFAULT_MAC_ADDRESS)); - } - - /** - * Verify that an empty map will be returned when trying to get all matching FQDN for a {@code - * null} {@link ScanResult}. - */ - @Test - public void getAllMatchingFqdnsForScanResultsWithNullScanResult() throws Exception { - assertEquals(0, - mManager.getAllMatchingPasspointProfilesForScanResults(null).size()); - } - - /** - * Verify that an empty map will be returned when trying to get a all matching FQDN for a {@link - * ScanResult} with a {@code null} BSSID. - */ - @Test - public void getAllMatchingFqdnsForScanResultsWithNullBSSID() throws Exception { - ScanResult scanResult = createTestScanResult(); - scanResult.BSSID = null; - - assertEquals(0, - mManager.getAllMatchingPasspointProfilesForScanResults( - Arrays.asList(scanResult)).size()); - } - - /** - * Verify that an empty map will be returned when trying to get all matching FQDN for a {@link - * ScanResult} with an invalid BSSID. - */ - @Test - public void ggetAllMatchingFqdnsForScanResultsWithInvalidBSSID() throws Exception { - ScanResult scanResult = createTestScanResult(); - scanResult.BSSID = "asdfdasfas"; - - assertEquals(0, - mManager.getAllMatchingPasspointProfilesForScanResults( - Arrays.asList(scanResult)).size()); - } - - /** - * Verify that an empty map will be returned when trying to get all matching FQDN for a - * non-Passpoint AP. - */ - @Test - public void getAllMatchingFqdnsForScanResultsForNonPasspointAP() throws Exception { - ScanResult scanResult = createTestScanResult(); - scanResult.flags = 0; - assertEquals(0, - mManager.getAllMatchingPasspointProfilesForScanResults( - Arrays.asList(scanResult)).size()); - } - - /** - * Verify that an empty list will be returned when retrieving OSU providers for an AP with - * null scan result. - * - * @throws Exception - */ - @Test - public void getMatchingOsuProvidersForNullScanResult() throws Exception { - assertTrue(mManager.getMatchingOsuProviders(null).isEmpty()); - } - - /** - * Verify that an empty list will be returned when retrieving OSU providers for an AP with - * invalid BSSID. - * - * @throws Exception - */ - @Test - public void getMatchingOsuProvidersForInvalidBSSID() throws Exception { - ScanResult scanResult = createTestScanResult(); - scanResult.BSSID = "asdfdasfas"; - assertTrue(mManager.getMatchingOsuProviders(Arrays.asList(scanResult)).isEmpty()); - } - - /** - * Verify that an empty list will be returned when retrieving OSU providers for a - * non-Passpoint AP. - * - * @throws Exception - */ - @Test - public void getMatchingOsuProvidersForNonPasspointAP() throws Exception { - ScanResult scanResult = createTestScanResult(); - scanResult.flags = 0; - assertTrue(mManager.getMatchingOsuProviders(Arrays.asList(scanResult)).isEmpty()); - } - - /** - * Verify that an empty list will be returned when no match is found from the ANQP cache. - * - * @throws Exception - */ - @Test - public void getMatchingOsuProviderWithNoMatch() throws Exception { - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null); - assertTrue( - mManager.getMatchingOsuProviders(Arrays.asList(createTestScanResult())).isEmpty()); - } - - /** - * Verify that an expected provider list will be returned when a match is found from - * the ANQP cache with a given list of scanResult. - * - * @throws Exception - */ - @Test - public void getMatchingOsuProvidersWithMatch() throws Exception { - // Setup OSU providers ANQP element for AP1. - List<OsuProviderInfo> providerInfoListOfAp1 = new ArrayList<>(); - Map<ANQPElementType, ANQPElement> anqpElementMapOfAp1 = new HashMap<>(); - Set<OsuProvider> expectedOsuProvidersForDomainId = new HashSet<>(); - - // Setup OSU providers ANQP element for AP2. - List<OsuProviderInfo> providerInfoListOfAp2 = new ArrayList<>(); - Map<ANQPElementType, ANQPElement> anqpElementMapOfAp2 = new HashMap<>(); - Set<OsuProvider> expectedOsuProvidersForDomainId2 = new HashSet<>(); - int osuProviderCount = 4; - - // static mocking - MockitoSession session = - com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic( - InformationElementUtil.class).startMocking(); - try { - for (int i = 0; i < osuProviderCount; i++) { - // Test data. - String friendlyName = "Test Provider" + i; - String serviceDescription = "Dummy Service" + i; - Uri serverUri = Uri.parse("https://" + "test" + i + ".com"); - String nai = "access.test.com"; - List<Integer> methodList = Arrays.asList(1); - List<I18Name> friendlyNames = Arrays.asList( - new I18Name(Locale.ENGLISH.getLanguage(), Locale.ENGLISH, friendlyName)); - List<I18Name> serviceDescriptions = Arrays.asList( - new I18Name(Locale.ENGLISH.getLanguage(), Locale.ENGLISH, - serviceDescription)); - Map<String, String> friendlyNameMap = new HashMap<>(); - friendlyNames.forEach(e -> friendlyNameMap.put(e.getLanguage(), e.getText())); - - expectedOsuProvidersForDomainId.add(new OsuProvider( - (WifiSsid) null, friendlyNameMap, serviceDescription, - serverUri, nai, methodList)); - - // add All OSU Providers for AP1. - providerInfoListOfAp1.add(new OsuProviderInfo( - friendlyNames, serverUri, methodList, null, nai, serviceDescriptions)); - - // add only half of All OSU Providers for AP2. - if (i >= osuProviderCount / 2) { - providerInfoListOfAp2.add(new OsuProviderInfo( - friendlyNames, serverUri, methodList, null, nai, serviceDescriptions)); - expectedOsuProvidersForDomainId2.add(new OsuProvider( - (WifiSsid) null, friendlyNameMap, serviceDescription, - serverUri, nai, methodList)); - } - } - anqpElementMapOfAp1.put(ANQPElementType.HSOSUProviders, - new HSOsuProvidersElement(WifiSsid.createFromAsciiEncoded("Test SSID"), - providerInfoListOfAp1)); - ANQPData anqpData = new ANQPData(mClock, anqpElementMapOfAp1); - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(anqpData); - - anqpElementMapOfAp2.put(ANQPElementType.HSOSUProviders, - new HSOsuProvidersElement(WifiSsid.createFromAsciiEncoded("Test SSID2"), - providerInfoListOfAp2)); - ANQPData anqpData2 = new ANQPData(mClock, anqpElementMapOfAp2); - when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(anqpData2); - - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - - // ANQP_DOMAIN_ID(TEST_ANQP_KEY) - vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID; - when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); - assertEquals(mManager.getMatchingOsuProviders( - Arrays.asList(createTestScanResult())).keySet(), - expectedOsuProvidersForDomainId); - - // ANQP_DOMAIN_ID2(TEST_ANQP_KEY2) - vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2; - when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); - assertEquals(mManager.getMatchingOsuProviders( - createTestScanResults()).keySet(), expectedOsuProvidersForDomainId2); - } finally { - session.finishMocking(); - } - } - - /** - * Verify that matching Passpoint configurations will be returned as map with corresponding - * OSU providers. - */ - @Test - public void getMatchingPasspointConfigsForOsuProvidersWithMatch() { - PasspointProvider provider1 = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - PasspointProvider provider2 = - addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2, TEST_PACKAGE, false, null); - - List<OsuProvider> osuProviders = new ArrayList<>(); - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put("en", "NO-MATCH-NAME"); - friendlyNames.put("kr", TEST_FRIENDLY_NAME + 1); - - osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true, - friendlyNames)); - friendlyNames = new HashMap<>(); - friendlyNames.put("en", TEST_FRIENDLY_NAME2); - osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true, - friendlyNames)); - - Map<OsuProvider, PasspointConfiguration> results = - mManager.getMatchingPasspointConfigsForOsuProviders(osuProviders); - - assertEquals(2, results.size()); - assertThat(Arrays.asList(provider1.getConfig(), provider2.getConfig()), - containsInAnyOrder(results.values().toArray())); - } - - /** - * Verify that empty map will be returned when there is no matching Passpoint configuration. - */ - @Test - public void getMatchingPasspointConfigsForOsuProvidersWitNoMatch() { - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2, TEST_PACKAGE, false, null); - - List<OsuProvider> osuProviders = new ArrayList<>(); - - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put("en", "NO-MATCH-NAME"); - osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true, - friendlyNames)); - friendlyNames = new HashMap<>(); - friendlyNames.put("en", "NO-MATCH-NAME-2"); - osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true, - friendlyNames)); - - assertEquals(0, mManager.getMatchingPasspointConfigsForOsuProviders(osuProviders).size()); - } - - /** - * Verify that the provider list maintained by the PasspointManager after the list is updated - * in the data source. - * - * @throws Exception - */ - @Test - public void verifyProvidersAfterDataSourceUpdate() throws Exception { - // Update the provider list in the data source. - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config); - List<PasspointProvider> providers = new ArrayList<>(); - providers.add(provider); - mUserDataSource.setProviders(providers); - - // Verify the providers maintained by PasspointManager. - assertEquals(1, mManager.getProviderConfigs(TEST_CREATOR_UID, true).size()); - assertEquals(config, mManager.getProviderConfigs(TEST_CREATOR_UID, true).get(0)); - } - - /** - * Verify that the provider index used by PasspointManager is updated after it is updated in - * the data source. - * - * @throws Exception - */ - @Test - public void verifyProviderIndexAfterDataSourceUpdate() throws Exception { - long providerIndex = 9; - mSharedDataSource.setProviderIndex(providerIndex); - assertEquals(providerIndex, mSharedDataSource.getProviderIndex()); - - // Add a provider. - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config); - // Verify the provider ID used to create the new provider. - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), eq(providerIndex), eq(TEST_CREATOR_UID), - eq(TEST_PACKAGE), eq(false))).thenReturn(provider); - - assertTrue( - mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false, true)); - verifyInstalledConfig(config); - reset(mWifiConfigManager); - } - - /** - * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when - * adding a legacy Passpoint configuration containing a valid user credential. - * - * @throws Exception - */ - @Test - public void addLegacyPasspointConfigWithUserCredential() throws Exception { - // Test data. - String fqdn = "test.com"; - String friendlyName = "Friendly Name"; - long[] rcOIs = new long[] {0x1234L, 0x2345L}; - String realm = "realm.com"; - String username = "username"; - String password = "password"; - byte[] base64EncodedPw = - Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); - String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); - String caCertificateAlias = "CaCert"; - - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = fqdn; - wifiConfig.providerFriendlyName = friendlyName; - wifiConfig.roamingConsortiumIds = rcOIs; - wifiConfig.enterpriseConfig.setIdentity(username); - wifiConfig.enterpriseConfig.setPassword(password); - wifiConfig.enterpriseConfig.setRealm(realm); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); - wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP); - wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); - - // Setup expected {@link PasspointConfiguration} - PasspointConfiguration passpointConfig = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - homeSp.setFriendlyName(friendlyName); - homeSp.setRoamingConsortiumOis(rcOIs); - passpointConfig.setHomeSp(homeSp); - Credential credential = new Credential(); - Credential.UserCredential userCredential = new Credential.UserCredential(); - userCredential.setUsername(username); - userCredential.setPassword(encodedPasswordStr); - userCredential.setEapType(EAPConstants.EAP_TTLS); - userCredential.setNonEapInnerMethod("PAP"); - credential.setUserCredential(userCredential); - credential.setRealm(realm); - passpointConfig.setCredential(credential); - - assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); - verifyInstalledConfig(passpointConfig); - } - - /** - * Verify that adding a legacy Passpoint configuration containing user credential will - * fail when client certificate is not provided. - * - * @throws Exception - */ - @Test - public void addLegacyPasspointConfigWithUserCredentialWithoutCaCert() throws Exception { - // Test data. - String fqdn = "test.com"; - String friendlyName = "Friendly Name"; - long[] rcOIs = new long[] {0x1234L, 0x2345L}; - String realm = "realm.com"; - String username = "username"; - String password = "password"; - byte[] base64EncodedPw = - Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); - String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); - - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = fqdn; - wifiConfig.providerFriendlyName = friendlyName; - wifiConfig.roamingConsortiumIds = rcOIs; - wifiConfig.enterpriseConfig.setIdentity(username); - wifiConfig.enterpriseConfig.setPassword(password); - wifiConfig.enterpriseConfig.setRealm(realm); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); - wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP); - - assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); - } - - /** - * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when - * adding a legacy Passpoint configuration containing a valid SIM credential. - * - * @throws Exception - */ - @Test - public void addLegacyPasspointConfigWithSimCredential() throws Exception { - // Test data. - String fqdn = "test.com"; - String friendlyName = "Friendly Name"; - long[] rcOIs = new long[] {0x1234L, 0x2345L}; - String realm = "realm.com"; - String imsi = "1234"; - - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = fqdn; - wifiConfig.providerFriendlyName = friendlyName; - wifiConfig.roamingConsortiumIds = rcOIs; - wifiConfig.enterpriseConfig.setRealm(realm); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); - wifiConfig.enterpriseConfig.setPlmn(imsi); - - // Setup expected {@link PasspointConfiguration} - PasspointConfiguration passpointConfig = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - homeSp.setFriendlyName(friendlyName); - homeSp.setRoamingConsortiumOis(rcOIs); - passpointConfig.setHomeSp(homeSp); - Credential credential = new Credential(); - Credential.SimCredential simCredential = new Credential.SimCredential(); - simCredential.setEapType(EAPConstants.EAP_SIM); - simCredential.setImsi(imsi); - credential.setSimCredential(simCredential); - credential.setRealm(realm); - passpointConfig.setCredential(credential); - - assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); - verifyInstalledConfig(passpointConfig); - } - - /** - * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when - * adding a legacy Passpoint configuration containing a valid certificate credential. - * - * @throws Exception - */ - @Test - public void addLegacyPasspointConfigWithCertCredential() throws Exception { - // Test data. - String fqdn = "test.com"; - String friendlyName = "Friendly Name"; - long[] rcOIs = new long[] {0x1234L, 0x2345L}; - String realm = "realm.com"; - String caCertificateAlias = "CaCert"; - String clientCertificateAlias = "ClientCert"; - - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = fqdn; - wifiConfig.providerFriendlyName = friendlyName; - wifiConfig.roamingConsortiumIds = rcOIs; - wifiConfig.enterpriseConfig.setRealm(realm); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); - wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias); - - // Setup expected {@link PasspointConfiguration} - PasspointConfiguration passpointConfig = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(fqdn); - homeSp.setFriendlyName(friendlyName); - homeSp.setRoamingConsortiumOis(rcOIs); - passpointConfig.setHomeSp(homeSp); - Credential credential = new Credential(); - Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); - certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3); - credential.setCertCredential(certCredential); - credential.setRealm(realm); - passpointConfig.setCredential(credential); - - assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); - verifyInstalledConfig(passpointConfig); - } - - /** - * Verify that adding a legacy Passpoint configuration containing certificate credential will - * fail when CA certificate is not provided. - * - * @throws Exception - */ - @Test - public void addLegacyPasspointConfigWithCertCredentialWithoutCaCert() throws Exception { - // Test data. - String fqdn = "test.com"; - String friendlyName = "Friendly Name"; - long[] rcOIs = new long[] {0x1234L, 0x2345L}; - String realm = "realm.com"; - String clientCertificateAlias = "ClientCert"; - - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = fqdn; - wifiConfig.providerFriendlyName = friendlyName; - wifiConfig.roamingConsortiumIds = rcOIs; - wifiConfig.enterpriseConfig.setRealm(realm); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias); - - assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); - } - - /** - * Verify that adding a legacy Passpoint configuration containing certificate credential will - * fail when client certificate is not provided. - * - * @throws Exception - */ - @Test - public void addLegacyPasspointConfigWithCertCredentialWithoutClientCert() throws Exception { - // Test data. - String fqdn = "test.com"; - String friendlyName = "Friendly Name"; - long[] rcOIs = new long[] {0x1234L, 0x2345L}; - String realm = "realm.com"; - String caCertificateAlias = "CaCert"; - - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = fqdn; - wifiConfig.providerFriendlyName = friendlyName; - wifiConfig.roamingConsortiumIds = rcOIs; - wifiConfig.enterpriseConfig.setRealm(realm); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); - - assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); - } - - /** - * Verify that the provider's "hasEverConnected" flag will be set to true and the associated - * metric is updated after the provider was used to successfully connect to a Passpoint - * network for the first time. - * - * @throws Exception - */ - @Test - public void providerNetworkConnectedFirstTime() throws Exception { - PasspointProvider provider = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - when(provider.getHasEverConnected()).thenReturn(false); - mManager.onPasspointNetworkConnected(provider.getConfig().getUniqueId()); - verify(provider).setHasEverConnected(eq(true)); - } - - /** - * Verify that the provider's "hasEverConnected" flag the associated metric is not updated - * after the provider was used to successfully connect to a Passpoint network for non-first - * time. - * - * @throws Exception - */ - @Test - public void providerNetworkConnectedNotFirstTime() throws Exception { - PasspointProvider provider = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - when(provider.getHasEverConnected()).thenReturn(true); - mManager.onPasspointNetworkConnected(TEST_FQDN); - verify(provider, never()).setHasEverConnected(anyBoolean()); - } - - /** - * Verify that the expected Passpoint metrics are updated when - * {@link PasspointManager#updateMetrics} is invoked. - * - * @throws Exception - */ - @Test - public void updateMetrics() { - PasspointProvider provider = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - ArgumentCaptor<Map<String, PasspointProvider>> argCaptor = ArgumentCaptor.forClass( - Map.class); - // Provider have not provided a successful network connection. - int expectedInstalledProviders = 1; - int expectedConnectedProviders = 0; - when(provider.getHasEverConnected()).thenReturn(false); - mManager.updateMetrics(); - verify(mWifiMetrics).updateSavedPasspointProfiles( - eq(expectedInstalledProviders), eq(expectedConnectedProviders)); - - verify(mWifiMetrics).updateSavedPasspointProfilesInfo(argCaptor.capture()); - assertEquals(expectedInstalledProviders, argCaptor.getValue().size()); - assertEquals(provider, argCaptor.getValue().get(provider.getConfig().getUniqueId())); - reset(mWifiMetrics); - - // Provider have provided a successful network connection. - expectedConnectedProviders = 1; - when(provider.getHasEverConnected()).thenReturn(true); - mManager.updateMetrics(); - verify(mWifiMetrics).updateSavedPasspointProfiles( - eq(expectedInstalledProviders), eq(expectedConnectedProviders)); - } - - /** - * Verify Passpoint Manager's provisioning APIs by invoking methods in PasspointProvisioner for - * initiailization and provisioning a provider. - */ - @Test - public void verifyPasspointProvisioner() { - mManager.initializeProvisioner(mLooper.getLooper()); - verify(mPasspointProvisioner).init(any(Looper.class)); - when(mPasspointProvisioner.startSubscriptionProvisioning(anyInt(), any(OsuProvider.class), - any(IProvisioningCallback.class))).thenReturn(true); - OsuProvider osuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true); - assertEquals(true, - mManager.startSubscriptionProvisioning(TEST_UID, osuProvider, mCallback)); - } - - /** - * Verify that the corresponding Passpoint provider is removed when the app is disabled. - */ - @Test - public void verifyRemovingPasspointProfilesWhenAppIsDisabled() { - WifiConfiguration currentConfiguration = WifiConfigurationTestUtil.createPasspointNetwork(); - currentConfiguration.FQDN = TEST_FQDN; - when(mClientModeImpl.getCurrentWifiConfiguration()).thenReturn(currentConfiguration); - PasspointProvider passpointProvider = - addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null); - currentConfiguration.setPasspointUniqueId(passpointProvider.getConfig().getUniqueId()); - verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE), - mAppOpChangedListenerCaptor.capture()); - assertEquals(1, mManager.getProviderConfigs(TEST_CREATOR_UID, true).size()); - AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); - assertNotNull(listener); - - // Disallow change wifi state & ensure we remove the profiles from database. - when(mAppOpsManager.unsafeCheckOpNoThrow( - OPSTR_CHANGE_WIFI_STATE, TEST_CREATOR_UID, - TEST_PACKAGE)) - .thenReturn(MODE_IGNORED); - listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE); - mLooper.dispatchAll(); - - verify(mAppOpsManager).stopWatchingMode(mAppOpChangedListenerCaptor.getValue()); - verify(mClientModeImpl).disconnectCommand(); - assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, true).isEmpty()); - } - - /** - * Verify that removing a provider with a different UID will not succeed. - * - * @throws Exception - */ - @Test - public void removeGetProviderWithDifferentUid() throws Exception { - PasspointConfiguration config = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, - TEST_REALM); - PasspointProvider provider = createMockProvider(config); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(provider); - assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verifyInstalledConfig(config); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // no profiles available for TEST_UID - assertTrue(mManager.getProviderConfigs(TEST_UID, false).isEmpty()); - // 1 profile available for TEST_CREATOR_UID - assertFalse(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty()); - - // Remove the provider as a non-privileged non-creator app. - assertFalse(mManager.removeProvider(TEST_UID, false, null, TEST_FQDN)); - verify(provider, never()).uninstallCertsAndKeys(); - verify(mWifiConfigManager, never()).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess(); - - // no profiles available for TEST_UID - assertTrue(mManager.getProviderConfigs(TEST_UID, false).isEmpty()); - // 1 profile available for TEST_CREATOR_UID - assertFalse(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty()); - } - - /** - * Verify that removing a provider from a background user will fail. - * - * @throws Exception - */ - @Test - public void removeProviderWithBackgroundUser() throws Exception { - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(provider); - assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verifyInstalledConfig(config); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - - when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(false); - assertFalse(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN)); - } - - /** - * Verify that adding a suggestion provider with a valid configuration and user credential will - * succeed. - * - * @throws Exception - */ - @Test - public void addRemoveSuggestionProvider() throws Exception { - PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config); - when(provider.getPackageName()).thenReturn(TEST_PACKAGE); - when(provider.isFromSuggestion()).thenReturn(true); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(provider); - assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, - true, true)); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - verify(mAppOpsManager, never()).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), - eq(TEST_PACKAGE), any(AppOpsManager.OnOpChangedListener.class)); - assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty()); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Verify content in the data source. - List<PasspointProvider> providers = mUserDataSource.getProviders(); - assertEquals(1, providers.size()); - assertEquals(config, providers.get(0).getConfig()); - // Provider index start with 0, should be 1 after adding a provider. - assertEquals(1, mSharedDataSource.getProviderIndex()); - - // Remove from another Suggestor app, should fail. - assertFalse(mManager.removeProvider(TEST_UID, false, null, TEST_FQDN)); - verify(provider, never()).uninstallCertsAndKeys(); - verify(mWifiConfigManager, never()).removePasspointConfiguredNetwork( - provider.getWifiConfig().getKey()); - verify(mWifiConfigManager, never()).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess(); - verify(mAppOpsManager, never()).stopWatchingMode( - any(AppOpsManager.OnOpChangedListener.class)); - // Verify content in the data source. - providers = mUserDataSource.getProviders(); - assertEquals(1, providers.size()); - assertEquals(config, providers.get(0).getConfig()); - // Provider index start with 0, should be 1 after adding a provider. - assertEquals(1, mSharedDataSource.getProviderIndex()); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Remove the provider from same app. - assertTrue(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN)); - verify(provider).uninstallCertsAndKeys(); - verify(mWifiConfigManager).removePasspointConfiguredNetwork( - provider.getWifiConfig().getKey()); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess(); - verify(mAppOpsManager, never()).stopWatchingMode( - any(AppOpsManager.OnOpChangedListener.class)); - - // Verify content in the data source. - assertTrue(mUserDataSource.getProviders().isEmpty()); - // Removing a provider should not change the provider index. - assertEquals(1, mSharedDataSource.getProviderIndex()); - } - - /** - * Verify that adding a suggestion provider with the same base domain as the existing - * suggestion provider from same app will succeed, and verify that the new provider is - * added along with the existing provider. - * - * @throws Exception - */ - @Test - public void addSuggestionProviderWithExistingConfig() throws Exception { - // Add a provider with the original configuration. - PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, - TEST_REALM); - PasspointProvider origProvider = createMockProvider(origConfig); - when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE); - when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(origProvider); - assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, - true, true)); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Verify data source content. - List<PasspointProvider> origProviders = mUserDataSource.getProviders(); - assertEquals(1, origProviders.size()); - assertEquals(origConfig, origProviders.get(0).getConfig()); - assertEquals(1, mSharedDataSource.getProviderIndex()); - - // Add same provider as existing suggestion provider - // This should be no WifiConfig deletion - WifiConfiguration origWifiConfig = origProvider.getWifiConfig(); - origWifiConfig.fromWifiNetworkSuggestion = true; - origWifiConfig.creatorUid = TEST_CREATOR_UID; - origWifiConfig.creatorName = TEST_PACKAGE; - when(mWifiConfigManager.getConfiguredNetwork(origWifiConfig.getKey())) - .thenReturn(origWifiConfig); - when(mWifiConfigManager.addOrUpdateNetwork( - origWifiConfig, TEST_CREATOR_UID, TEST_PACKAGE)) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, - true, true)); - verify(mWifiConfigManager, never()).removePasspointConfiguredNetwork( - origWifiConfig.getKey()); - verify(mWifiConfigManager).addOrUpdateNetwork( - argThat((c) -> c.FQDN.equals(TEST_FQDN)), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE)); - verify(mWifiConfigManager).allowAutojoin(TEST_NETWORK_ID, origWifiConfig.allowAutojoin); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - assertEquals(2, mSharedDataSource.getProviderIndex()); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Add another provider with the same base domain as the existing saved provider. - // This should replace the existing provider with the new configuration. - PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider newProvider = createMockProvider(newConfig); - when(newProvider.isFromSuggestion()).thenReturn(true); - when(newProvider.getPackageName()).thenReturn(TEST_PACKAGE); - when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(newProvider); - assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE, - true, true)); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - - // Verify data source content. - List<PasspointProvider> newProviders = mUserDataSource.getProviders(); - assertEquals(2, newProviders.size()); - assertTrue(newConfig.equals(newProviders.get(0).getConfig()) - || newConfig.equals(newProviders.get(1).getConfig())); - assertTrue(origConfig.equals(newProviders.get(0).getConfig()) - || origConfig.equals(newProviders.get(1).getConfig())); - assertEquals(3, mSharedDataSource.getProviderIndex()); - } - - /** - * Verify that adding a saved provider with the same base domain as the existing - * suggestion provider will succeed, and verify that the new provider with the new configuration - * is added along with the existing provider. - * - * @throws Exception - */ - @Test - public void addSavedProviderWithExistingSuggestionConfig() throws Exception { - // Add a provider with the original configuration. - PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, - TEST_REALM); - PasspointProvider origProvider = createMockProvider(origConfig); - when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE); - when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(origProvider); - assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, - true, true)); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Verify data source content. - List<PasspointProvider> origProviders = mUserDataSource.getProviders(); - assertEquals(1, origProviders.size()); - assertEquals(origConfig, origProviders.get(0).getConfig()); - assertEquals(1, mSharedDataSource.getProviderIndex()); - - // Add another provider with the same base domain as the existing saved provider. - // This should replace the existing provider with the new configuration. - PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider newProvider = createMockProvider(newConfig); - when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(newProvider); - assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE, - false, true)); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - - // Verify data source content. - List<PasspointProvider> newProviders = mUserDataSource.getProviders(); - assertEquals(2, newProviders.size()); - assertTrue(newConfig.equals(newProviders.get(0).getConfig()) - || newConfig.equals(newProviders.get(1).getConfig())); - assertTrue(origConfig.equals(newProviders.get(0).getConfig()) - || origConfig.equals(newProviders.get(1).getConfig())); - assertEquals(2, mSharedDataSource.getProviderIndex()); - } - - /** - * Verify that adding a suggestion provider with the same base domain as the existing provider - * from different apps will add a new provider. - * - * @throws Exception - */ - @Test - public void addSuggestionProviderWithExistingConfigFromDifferentSource() throws Exception { - // Add a provider with the original configuration. - PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, - TEST_REALM); - PasspointProvider origProvider = createMockProvider(origConfig); - when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE); - when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(false))).thenReturn(origProvider); - assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, false, - true)); - verifyInstalledConfig(origConfig); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - reset(mWifiMetrics); - reset(mWifiConfigManager); - - // Verify data source content. - List<PasspointProvider> origProviders = mUserDataSource.getProviders(); - assertEquals(1, origProviders.size()); - assertEquals(origConfig, origProviders.get(0).getConfig()); - assertEquals(1, mSharedDataSource.getProviderIndex()); - - // Add another provider with the same base domain as the existing saved provider but from - // different app. This should not replace the existing provider with the new configuration - // but add another one. - PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN, - TEST_FRIENDLY_NAME); - PasspointProvider newProvider = createMockProvider(newConfig); - when(newProvider.isFromSuggestion()).thenReturn(true); - when(newProvider.getPackageName()).thenReturn(TEST_PACKAGE1); - when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE1), - eq(true))).thenReturn(newProvider); - assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE1, true, - true)); - verify(mWifiConfigManager).saveToStore(true); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - - // Verify data source content. - List<PasspointProvider> newProviders = mUserDataSource.getProviders(); - assertEquals(2, newProviders.size()); - assertTrue(origConfig.equals(newProviders.get(0).getConfig()) - || origConfig.equals(newProviders.get(1).getConfig())); - - assertEquals(2, mSharedDataSource.getProviderIndex()); - } - - /** - * Verify that the HomeProvider provider will be returned when a HomeProvider profile has - * not expired and RoamingProvider expiration is unset (still valid). - * - * @throws Exception - */ - @Test - public void matchHomeProviderWhenHomeProviderNotExpired() throws Exception { - // static mocking - MockitoSession session = - com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic( - InformationElementUtil.class).startMocking(); - try { - PasspointProvider providerHome = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - providerHome.getConfig().setSubscriptionExpirationTimeInMillis( - System.currentTimeMillis() + 100000); - providerHome.getWifiConfig().isHomeProviderNetwork = true; - PasspointProvider providerRoaming = addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1, - TEST_UID, "\"PasspointTestSSID\"", true, true, - TEST_FQDN + 2, TEST_FRIENDLY_NAME, SECURITY_EAP); - PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME, - TEST_PACKAGE, wifiConfiguration, false, null); - ANQPData entry = new ANQPData(mClock, null); - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID; - - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); - when(providerHome.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.HomeProvider); - when(providerRoaming.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.RoamingProvider); - when(providerNone.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.None); - - List<Pair<PasspointProvider, PasspointMatch>> results = - mManager.matchProvider(createTestScanResult()); - Pair<PasspointProvider, PasspointMatch> result = results.get(0); - - assertEquals(PasspointMatch.HomeProvider, result.second); - assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn()); - - } finally { - session.finishMocking(); - } - } - - /** - * Verify that the RoamingProvider provider will be returned when a HomeProvider profile has - * expired and RoamingProvider expiration is unset (still valid). - * - * @throws Exception - */ - @Test - public void matchRoamingProviderUnsetWhenHomeProviderExpired() throws Exception { - // static mocking - MockitoSession session = - com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic( - InformationElementUtil.class).startMocking(); - try { - PasspointProvider providerHome = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - providerHome.getConfig().setSubscriptionExpirationTimeInMillis( - System.currentTimeMillis() - 10000); - providerHome.getWifiConfig().isHomeProviderNetwork = true; - PasspointProvider providerRoaming = addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1, - TEST_UID, "\"PasspointTestSSID\"", true, true, - TEST_FQDN + 2, TEST_FRIENDLY_NAME, SECURITY_EAP); - PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME, - TEST_PACKAGE, wifiConfiguration, false, null); - ANQPData entry = new ANQPData(mClock, null); - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID; - - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); - when(providerHome.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.HomeProvider); - when(providerRoaming.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.RoamingProvider); - when(providerNone.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.None); - - List<Pair<PasspointProvider, PasspointMatch>> results = - mManager.matchProvider(createTestScanResult()); - Pair<PasspointProvider, PasspointMatch> result = results.get(0); - - assertEquals(PasspointMatch.RoamingProvider, result.second); - assertEquals(TEST_FQDN2, result.first.getConfig().getHomeSp().getFqdn()); - - } finally { - session.finishMocking(); - } - } - - /** - * Verify that the RoamingProvider provider will be returned when a HomeProvider profile has - * expired and RoamingProvider expiration is still valid. - * - * @throws Exception - */ - @Test - public void matchRoamingProviderNonExpiredWhenHomeProviderExpired() throws Exception { - // static mocking - MockitoSession session = - com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic( - InformationElementUtil.class).startMocking(); - try { - PasspointProvider providerHome = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - providerHome.getConfig().setSubscriptionExpirationTimeInMillis( - System.currentTimeMillis() - 10000); - providerHome.getWifiConfig().isHomeProviderNetwork = true; - PasspointProvider providerRoaming = addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, null); - providerRoaming.getConfig().setSubscriptionExpirationTimeInMillis( - System.currentTimeMillis() + 100000); - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1, - TEST_UID, "\"PasspointTestSSID\"", true, true, - TEST_FQDN + 2, TEST_FRIENDLY_NAME, SECURITY_EAP); - PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME, - TEST_PACKAGE, wifiConfiguration, false, null); - ANQPData entry = new ANQPData(mClock, null); - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID; - - when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa); - when(providerHome.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.HomeProvider); - when(providerRoaming.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.RoamingProvider); - when(providerNone.match(anyMap(), isNull())) - .thenReturn(PasspointMatch.None); - - List<Pair<PasspointProvider, PasspointMatch>> results = - mManager.matchProvider(createTestScanResult()); - Pair<PasspointProvider, PasspointMatch> result = results.get(0); - - assertEquals(PasspointMatch.RoamingProvider, result.second); - assertEquals(TEST_FQDN2, result.first.getConfig().getHomeSp().getFqdn()); - - } finally { - session.finishMocking(); - } - } - - /** - * Verify add untrusted passpoint network from suggestion success. - */ - @Test - public void testAddUntrustedPasspointNetworkFromSuggestion() { - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = TEST_FQDN; - PasspointConfiguration config = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config, wifiConfig, true); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(provider); - when(provider.getPackageName()).thenReturn(TEST_PACKAGE); - assertTrue(mManager.addOrUpdateProvider( - config, TEST_CREATOR_UID, TEST_PACKAGE, true, false)); - verify(provider).setTrusted(false); - } - - /** - * Verify add untrusted passpoint network not from suggestion fail. - */ - @Test - public void testAddUntrustedPasspointNetworkNotFromSuggestion() { - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = TEST_FQDN; - PasspointConfiguration config = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config, wifiConfig, false); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(provider); - when(provider.getPackageName()).thenReturn(TEST_PACKAGE); - assertFalse(mManager.addOrUpdateProvider( - config, TEST_CREATOR_UID, TEST_PACKAGE, false, false)); - verify(provider, never()).setTrusted(false); - } - - /** - * Verify that the ScanResults(Access Points) are returned when it may be - * authenticated with the provided passpoint configuration as roaming match. - */ - @Test - public void getMatchingScanResultsTestWithRoamingMatch() { - PasspointConfiguration config = mock(PasspointConfiguration.class); - PasspointProvider mockProvider = mock(PasspointProvider.class); - when(mObjectFactory.makePasspointProvider(config, null, - mWifiCarrierInfoManager, 0, 0, null, false)) - .thenReturn(mockProvider); - List<ScanResult> scanResults = new ArrayList<>() {{ - add(mock(ScanResult.class)); - }}; - when(mockProvider.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.RoamingProvider); - - List<ScanResult> testResults = mManager.getMatchingScanResults(config, scanResults); - - assertEquals(1, testResults.size()); - } - - /** - * Verify that the ScanResults(Access Points) are returned when it may be - * authenticated with the provided passpoint configuration as home match. - */ - @Test - public void getMatchingScanResultsTestWithHomeMatch() { - PasspointConfiguration config = mock(PasspointConfiguration.class); - PasspointProvider mockProvider = mock(PasspointProvider.class); - when(mObjectFactory.makePasspointProvider(config, null, - mWifiCarrierInfoManager, 0, 0, null, false)) - .thenReturn(mockProvider); - List<ScanResult> scanResults = new ArrayList<>() {{ - add(mock(ScanResult.class)); - }}; - when(mockProvider.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.HomeProvider); - - List<ScanResult> testResults = mManager.getMatchingScanResults(config, scanResults); - - assertEquals(1, testResults.size()); - } - - /** - * Verify that the ScanResults(Access Points) are not returned when it cannot be - * authenticated with the provided passpoint configuration as none match. - */ - @Test - public void getMatchingScanResultsTestWithNonMatch() { - PasspointConfiguration config = mock(PasspointConfiguration.class); - - PasspointProvider mockProvider = mock(PasspointProvider.class); - - when(mObjectFactory.makePasspointProvider(config, null, - mWifiCarrierInfoManager, 0, 0, null, false)) - .thenReturn(mockProvider); - - List<ScanResult> scanResults = new ArrayList<>() {{ - add(mock(ScanResult.class)); - }}; - when(mockProvider.match(anyMap(), any(RoamingConsortium.class))) - .thenReturn(PasspointMatch.None); - - List<ScanResult> testResults = mManager.getMatchingScanResults(config, scanResults); - - assertEquals(0, testResults.size()); - } - - /** - * Verify that no ANQP queries are requested when not allowed (i.e. by WifiMetrics) when - * there is a cache miss. - */ - @Test - public void testAnqpRequestNotAllowed() { - reset(mWifiConfigManager); - when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(null); - verify(mAnqpRequestManager, never()).requestANQPElements(any(long.class), - any(ANQPNetworkKey.class), any(boolean.class), any(NetworkDetail.HSRelease.class)); - } - - /** - * Verify that removing of multiple providers with the same FQDN is done correctly. - */ - @Test - public void removeAllProvidersWithSameFqdn() { - PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, TEST_REALM); - PasspointProvider provider2 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, TEST_REALM2); - PasspointProvider provider3 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, - TEST_PACKAGE, false, TEST_REALM3); - - List<PasspointProvider> providers = mUserDataSource.getProviders(); - assertEquals(3, providers.size()); - verify(mWifiMetrics, times(3)).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics, times(3)).incrementNumPasspointProviderInstallSuccess(); - - // Remove the provider as the creator app. - assertTrue(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN)); - - verify(provider1).uninstallCertsAndKeys(); - verify(mWifiConfigManager, times(1)).removePasspointConfiguredNetwork( - provider1.getWifiConfig().getKey()); - verify(provider2).uninstallCertsAndKeys(); - verify(mWifiConfigManager, times(1)).removePasspointConfiguredNetwork( - provider2.getWifiConfig().getKey()); - verify(provider3).uninstallCertsAndKeys(); - verify(mWifiConfigManager, times(1)).removePasspointConfiguredNetwork( - provider3.getWifiConfig().getKey()); - - verify(mWifiMetrics, times(3)).incrementNumPasspointProviderUninstallation(); - verify(mWifiMetrics, times(3)).incrementNumPasspointProviderUninstallSuccess(); - verify(mAppOpsManager).stopWatchingMode(any(AppOpsManager.OnOpChangedListener.class)); - assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty()); - - // Verify content in the data source. - assertTrue(mUserDataSource.getProviders().isEmpty()); - } - - /** - * Verify that adding a provider with a self signed root CA increments the metrics correctly. - * - * @throws Exception - */ - @Test - public void verifySelfSignRootCaMetrics() throws Exception { - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = TEST_FQDN; - PasspointConfiguration config = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - PasspointProvider provider = createMockProvider(config, wifiConfig, true); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(provider); - when(provider.getPackageName()).thenReturn(TEST_PACKAGE); - assertTrue(mManager.addOrUpdateProvider( - config, TEST_CREATOR_UID, TEST_PACKAGE, true, false)); - verify(mWifiMetrics).incrementNumPasspointProviderWithSelfSignedRootCa(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderWithNoRootCa(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify that adding a provider with no root CA increments the metrics correctly. - * - * @throws Exception - */ - @Test - public void verifyNoRootCaMetrics() throws Exception { - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = TEST_FQDN; - PasspointConfiguration config = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - config.getCredential().setCaCertificate(null); - PasspointProvider provider = createMockProvider(config, wifiConfig, true); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(provider); - when(provider.getPackageName()).thenReturn(TEST_PACKAGE); - assertTrue(mManager.addOrUpdateProvider( - config, TEST_CREATOR_UID, TEST_PACKAGE, true, false)); - verify(mWifiMetrics).incrementNumPasspointProviderWithNoRootCa(); - verify(mWifiMetrics, never()).incrementNumPasspointProviderWithSelfSignedRootCa(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - } - - /** - * Verify that adding a provider with subscription expiration increments the metrics correctly. - * - * @throws Exception - */ - @Test - public void verifySubscriptionExpirationMetrics() throws Exception { - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = TEST_FQDN; - PasspointConfiguration config = - createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME); - config.setSubscriptionExpirationTimeInMillis(1586228641000L); - PasspointProvider provider = createMockProvider(config, wifiConfig, true); - when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), - eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), - eq(true))).thenReturn(provider); - when(provider.getPackageName()).thenReturn(TEST_PACKAGE); - assertTrue(mManager.addOrUpdateProvider( - config, TEST_CREATOR_UID, TEST_PACKAGE, true, false)); - verify(mWifiMetrics).incrementNumPasspointProviderWithSubscriptionExpiration(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); - verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelperTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelperTest.java deleted file mode 100644 index a361a19bc..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelperTest.java +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -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 static org.mockito.MockitoAnnotations.initMocks; - -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; -import android.util.LocalLog; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.NetworkUpdateResult; -import com.android.server.wifi.ScanDetail; -import com.android.server.wifi.WifiConfigManager; -import com.android.server.wifi.WifiConfigurationTestUtil; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; -import com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement; -import com.android.server.wifi.util.ScanResultUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Unit tests for {@link PasspointNetworkNominateHelper}. - */ -@SmallTest -public class PasspointNetworkNominateHelperTest { - // TODO(b/140763176): should extend WifiBaseTest, but if it does then it fails with NPE - private static final int TEST_NETWORK_ID = 1; - private static final int TEST_NETWORK_ID2 = 2; - private static final String TEST_SSID1 = "ssid1"; - private static final String TEST_SSID2 = "ssid2"; - private static final String TEST_BSSID1 = "01:23:45:56:78:9a"; - private static final String TEST_BSSID2 = "23:12:34:90:81:12"; - private static final String TEST_FQDN1 = "test1.com"; - private static final String TEST_FQDN2 = "test2.com"; - private static final int TEST_UID = 5555; - private static final String TEST_PACKAGE = "test.package.com"; - private static final WifiConfiguration TEST_CONFIG1 = generateWifiConfig(TEST_FQDN1); - private static final WifiConfiguration TEST_CONFIG2 = generateWifiConfig(TEST_FQDN2); - private static PasspointProvider sTestProvider1; - private static PasspointProvider sTestProvider2; - - @Mock PasspointManager mPasspointManager; - @Mock WifiConfigManager mWifiConfigManager; - @Mock SubscriptionManager mSubscriptionManager; - LocalLog mLocalLog; - PasspointNetworkNominateHelper mNominateHelper; - - /** - * Helper function for generating {@link WifiConfiguration} for testing. - * - * @param fqdn The FQDN associated with the configuration - * @return {@link WifiConfiguration} - */ - private static WifiConfiguration generateWifiConfig(String fqdn) { - WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1, - TEST_UID, "\"PasspointTestSSID\"", true, true, - fqdn, fqdn, SECURITY_EAP); - - return wifiConfiguration; - } - - /** - * Helper function for generating {@link PasspointProvider} for testing. - * - * @param config The WifiConfiguration associated with the provider - * @return {@link PasspointProvider} - */ - private static PasspointProvider generateProvider(WifiConfiguration config) { - PasspointProvider provider = mock(PasspointProvider.class); - PasspointConfiguration passpointConfig = new PasspointConfiguration(); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(config.FQDN); - passpointConfig.setHomeSp(homeSp); - when(provider.getConfig()).thenReturn(passpointConfig); - when(provider.getWifiConfig()).thenReturn(config); - when(provider.isFromSuggestion()).thenReturn(false); - when(provider.isAutojoinEnabled()).thenReturn(true); - return provider; - } - - /** - * Helper function for generating {@link ScanDetail} for testing. - * - * @param ssid The SSID associated with the scan - * @param bssid The BSSID associated with the scan - * @return {@link ScanDetail} - */ - private static ScanDetail generateScanDetail(String ssid, String bssid) { - NetworkDetail networkDetail = mock(NetworkDetail.class); - when(networkDetail.isInterworking()).thenReturn(true); - when(networkDetail.getHSRelease()).thenReturn(NetworkDetail.HSRelease.R1); - when(networkDetail.getAnt()).thenReturn(NetworkDetail.Ant.FreePublic); - when(networkDetail.isInternet()).thenReturn(true); - - ScanDetail scanDetail = mock(ScanDetail.class); - ScanResult scanResult = new ScanResult(); - scanResult.SSID = ssid; - scanResult.BSSID = bssid; - when(scanDetail.getSSID()).thenReturn(ssid); - when(scanDetail.getBSSIDString()).thenReturn(bssid); - when(scanDetail.getScanResult()).thenReturn(scanResult); - when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); - return scanDetail; - } - - /** - * Test setup. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - sTestProvider1 = generateProvider(TEST_CONFIG1); - sTestProvider2 = generateProvider(TEST_CONFIG2); - - mLocalLog = new LocalLog(512); - mNominateHelper = new PasspointNetworkNominateHelper(mPasspointManager, mWifiConfigManager, - mLocalLog); - } - - /** - * Verify that no candidate will be nominated when evaluating scans without any matching - * providers. - */ - @Test - public void evaluateScansWithNoMatch() { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), - generateScanDetail(TEST_SSID2, TEST_BSSID2)); - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(null); - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertTrue(candidates.isEmpty()); - } - - /** - * Verify that provider matching will not be performed when evaluating scans with no - * interworking support, verify that no candidate will be nominated. - * - * @throws Exception - */ - @Test - public void evaluateScansWithNoInterworkingAP() throws Exception { - NetworkDetail networkDetail = mock(NetworkDetail.class); - when(networkDetail.isInterworking()).thenReturn(false); - ScanDetail scanDetail = mock(ScanDetail.class); - when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); - - List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {scanDetail}); - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertTrue(candidates.isEmpty()); - // Verify that no provider matching is performed. - verify(mPasspointManager, never()).matchProvider(any(ScanResult.class)); - } - - /** - * Verify that when a network matches a home provider is found, the correct network - * information (WifiConfiguration) is setup and nominated. - * - * @throws Exception - */ - @Test - public void evaluateScansWithNetworkMatchingHomeProvider() throws Exception { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), - generateScanDetail(TEST_SSID2, TEST_BSSID2)); - - // Setup matching providers for ScanDetail with TEST_SSID1. - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - - // Return homeProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for - // for the second (TEST_SSID2); - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider) - .thenReturn(null); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertEquals(1, candidates.size()); - - // Verify the content of the WifiConfiguration that was added to WifiConfigManager. - ArgumentCaptor<WifiConfiguration> addedConfig = - ArgumentCaptor.forClass(WifiConfiguration.class); - verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt(), any()); - assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID1), addedConfig.getValue().SSID); - assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN); - assertNotNull(addedConfig.getValue().enterpriseConfig); - assertEquals("", addedConfig.getValue().enterpriseConfig.getAnonymousIdentity()); - assertTrue(addedConfig.getValue().isHomeProviderNetwork); - verify(mWifiConfigManager).enableNetwork( - eq(TEST_NETWORK_ID), eq(false), anyInt(), any()); - verify(mWifiConfigManager).setNetworkCandidateScanResult( - eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt()); - verify(mWifiConfigManager).updateScanDetailForNetwork( - eq(TEST_NETWORK_ID), any(ScanDetail.class)); - } - - /** - * Verify that when a network matches a roaming provider is found, the correct network - * information (WifiConfiguration) is setup and nominated. - */ - @Test - public void evaluateScansWithNetworkMatchingRoamingProvider() { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), - generateScanDetail(TEST_SSID2, TEST_BSSID2)); - - // Setup matching providers for ScanDetail with TEST_SSID1. - List<Pair<PasspointProvider, PasspointMatch>> roamingProvider = new ArrayList<>(); - roamingProvider.add(Pair.create(sTestProvider1, PasspointMatch.RoamingProvider)); - - // Return roamingProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for - // for the second (TEST_SSID2); - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(roamingProvider) - .thenReturn(null); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), any())) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertEquals(1, candidates.size()); - - // Verify the content of the WifiConfiguration that was added to WifiConfigManager. - ArgumentCaptor<WifiConfiguration> addedConfig = - ArgumentCaptor.forClass(WifiConfiguration.class); - verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt(), any()); - assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID1), addedConfig.getValue().SSID); - assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN); - assertNotNull(addedConfig.getValue().enterpriseConfig); - assertEquals("", addedConfig.getValue().enterpriseConfig.getAnonymousIdentity()); - assertFalse(addedConfig.getValue().isHomeProviderNetwork); - verify(mWifiConfigManager).enableNetwork( - eq(TEST_NETWORK_ID), eq(false), anyInt(), any()); - verify(mWifiConfigManager).setNetworkCandidateScanResult( - eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt()); - verify(mWifiConfigManager).updateScanDetailForNetwork( - eq(TEST_NETWORK_ID), any(ScanDetail.class)); - } - - /** - * Verify that when a network matches a roaming provider is found for different scanDetails, - * will nominate both as the candidates. - * - * @throws Exception - */ - @Test - public void evaluateScansWithHomeProviderNetworkAndRoamingProviderNetwork() throws Exception { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), - generateScanDetail(TEST_SSID2, TEST_BSSID2)); - - // Setup matching providers for ScanDetail with TEST_SSID1. - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - List<Pair<PasspointProvider, PasspointMatch>> roamingProvider = new ArrayList<>(); - roamingProvider.add(Pair.create(sTestProvider2, PasspointMatch.RoamingProvider)); - - // Return homeProvider for the first ScanDetail (TEST_SSID1) and - // roamingProvider for the second (TEST_SSID2); - when(mPasspointManager.matchProvider(any(ScanResult.class))) - .thenReturn(homeProvider).thenReturn(roamingProvider); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID + 1)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID + 1)) - .thenReturn(TEST_CONFIG2); - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertEquals(2, candidates.size()); - - verify(mWifiConfigManager, times(2)) - .addOrUpdateNetwork(any(), anyInt(), any()); - } - - /** - * Verify that anonymous identity is empty when matching a SIM credential provider with a - * network that supports encrypted IMSI and anonymous identity. The anonymous identity will be - * populated with {@code anonymous@<realm>} by ClientModeImpl's handling of the - * CMD_START_CONNECT event. - */ - @Test - public void evaluateSIMProviderWithNetworkSupportingEncryptedIMSI() { - // Setup ScanDetail and match providers. - List<ScanDetail> scanDetails = Collections.singletonList( - generateScanDetail(TEST_SSID1, TEST_BSSID1)); - WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( - WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - config.networkId = TEST_NETWORK_ID; - PasspointProvider testProvider = generateProvider(config); - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(testProvider, PasspointMatch.HomeProvider)); - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); - when(testProvider.isSimCredential()).thenReturn(true); - // SIM is present - when(mSubscriptionManager.getActiveSubscriptionInfoList()) - .thenReturn(Arrays.asList(mock(SubscriptionInfo.class))); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config); - - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertEquals(1, candidates.size()); - - assertEquals("", candidates.get(0).second.enterpriseConfig.getAnonymousIdentity()); - assertTrue(candidates.get(0).second.enterpriseConfig.isAuthenticationSimBased()); - } - - /** - * Verify that when the current active network is matched, the scan info associated with - * the network is updated. - */ - @Test - public void evaluateScansMatchingActiveNetworkWithDifferentBSS() { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID2)); - // Setup matching provider. - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - - // Setup currently connected network. - WifiConfiguration currentNetwork = new WifiConfiguration(); - currentNetwork.networkId = TEST_NETWORK_ID; - currentNetwork.SSID = ScanResultUtil.createQuotedSSID(TEST_SSID1); - String currentBssid = TEST_BSSID1; - - // Match the current connected network to a home provider. - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(currentNetwork); - - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - - assertEquals(1, candidates.size()); - - // Verify network candidate information is updated. - ArgumentCaptor<ScanResult> updatedCandidateScanResult = - ArgumentCaptor.forClass(ScanResult.class); - verify(mWifiConfigManager).setNetworkCandidateScanResult(eq(TEST_NETWORK_ID), - updatedCandidateScanResult.capture(), anyInt()); - assertEquals(TEST_BSSID2, updatedCandidateScanResult.getValue().BSSID); - ArgumentCaptor<ScanDetail> updatedCandidateScanDetail = - ArgumentCaptor.forClass(ScanDetail.class); - verify(mWifiConfigManager).updateScanDetailForNetwork(eq(TEST_NETWORK_ID), - updatedCandidateScanDetail.capture()); - assertEquals(TEST_BSSID2, updatedCandidateScanDetail.getValue().getBSSIDString()); - } - - /** - * Verify that the current configuration for the passpoint network is disabled, it will not - * nominated that network. - */ - @Test - public void evaluateNetworkWithDisabledWifiConfig() { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), - generateScanDetail(TEST_SSID2, TEST_BSSID2)); - - WifiConfiguration disableConfig = new WifiConfiguration(); - WifiConfiguration.NetworkSelectionStatus selectionStatus = - new WifiConfiguration.NetworkSelectionStatus(); - selectionStatus.setNetworkSelectionDisableReason( - WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); - selectionStatus.setNetworkSelectionStatus( - WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - disableConfig.setNetworkSelectionStatus(selectionStatus); - disableConfig.networkId = TEST_NETWORK_ID; - TEST_CONFIG1.networkId = TEST_NETWORK_ID; - - // Setup matching providers for ScanDetail with TEST_SSID1. - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - - // Return homeProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for - // for the second (TEST_SSID2); - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider) - .thenReturn(null); - when(mWifiConfigManager.getConfiguredNetwork(anyString())).thenReturn(disableConfig); - - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(WifiConfiguration.class), - anyInt(), any()); - assertTrue(candidates.isEmpty()); - } - - /** - * Verify that when a network matching a home provider is found, but the network was - * disconnected previously by user, it will not nominated that network. - */ - @Test - public void evaluateScanResultWithHomeMatchButPreviouslyUserDisconnected() { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); - - // Setup matching providers for ScanDetail with TEST_SSID1. - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - - // Return homeProvider for the first ScanDetail (TEST_SSID1). - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - when(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(TEST_FQDN1)) - .thenReturn(true); - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertTrue(candidates.isEmpty()); - } - - /** - * Verify that when the WAN metrics status is 'LINK_STATUS_DOWN', it should be ignored. - * @throws Exception - */ - @Test - public void evaluateScansWithNetworkMatchingHomeProviderWithAnqpLinkDown() throws Exception { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); - // Setup matching providers for ScanDetail with TEST_SSID1. - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - // Setup WAN metrics status is 'LINK_STATUS_DOWN' - HSWanMetricsElement wm = mock(HSWanMetricsElement.class); - Map<ANQPElementType, ANQPElement> anqpElements = new HashMap<>(); - anqpElements.put(ANQPElementType.HSWANMetrics, wm); - when(mPasspointManager.getANQPElements(any(ScanResult.class))) - .thenReturn(anqpElements); - when(wm.getStatus()).thenReturn(HSWanMetricsElement.LINK_STATUS_DOWN); - - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertTrue(candidates.isEmpty()); - } - - /** - * Verify that when same provider is match home and roaming for different scanDetail, - * the home provider matched scanDetail will be chosen. - */ - - @Test - public void evaluateScansWithNetworkMatchingBothHomeAndRoamingForSameProvider() { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), - generateScanDetail(TEST_SSID2, TEST_BSSID2)); - - // Setup matching providers for ScanDetail. - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - List<Pair<PasspointProvider, PasspointMatch>> roamingProvider = new ArrayList<>(); - roamingProvider.add(Pair.create(sTestProvider1, PasspointMatch.RoamingProvider)); - // Return homeProvider for the first ScanDetail (TEST_SSID1) and - // roamingProvider for the second (TEST_SSID2); - when(mPasspointManager.matchProvider(any(ScanResult.class))) - .thenReturn(roamingProvider).thenReturn(homeProvider); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - // verify Only home provider matched candidate will by chosen - assertEquals(1, candidates.size()); - assertTrue(candidates.get(0).second.isHomeProviderNetwork); - assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID2), candidates.get(0).second.SSID); - } - - /** - * For multiple scanDetails with matched providers, for each scanDetail nominate the best - * providers: if home available, return all home providers; otherwise return all roaming - * providers. - * ScanDetail1 matches home providerA, scanDetail2 matches roaming providerB, will nominate both - * matched pairs. - */ - @Test - public void evaluateScansWithNetworkMatchingBothHomeAndRoamingForDifferentProvider() { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), - generateScanDetail(TEST_SSID2, TEST_BSSID2)); - // Setup matching providers for ScanDetail. - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - List<Pair<PasspointProvider, PasspointMatch>> roamingProvider = new ArrayList<>(); - roamingProvider.add(Pair.create(sTestProvider2, PasspointMatch.RoamingProvider)); - // Return homeProvider for the first ScanDetail (TEST_SSID1) and - // roamingProvider for the second (TEST_SSID2); - when(mPasspointManager.matchProvider(any(ScanResult.class))) - .thenReturn(homeProvider).thenReturn(roamingProvider); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) - .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID2)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID2)).thenReturn(TEST_CONFIG2); - - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - // Nominate matched home provider for first ScanDetail (TEST_SSID1) and roaming provider for - // the second (TEST_SSID2). - assertEquals(2, candidates.size()); - assertTrue(candidates.stream().anyMatch(c -> c.second.isHomeProviderNetwork - && c.second.SSID.equals(ScanResultUtil.createQuotedSSID(TEST_SSID1)))); - assertTrue(candidates.stream().anyMatch(c -> !c.second.isHomeProviderNetwork - && c.second.SSID.equals(ScanResultUtil.createQuotedSSID(TEST_SSID2)))); - } - - /** - * For multiple matched providers from suggestion and user saved, return right ones according to - * the request. - */ - @Test - public void evaluateScansWithNetworkMatchingProviderBothFromSavedAndSuggestion() { - List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); - // Setup matching providers for ScanDetail. One provider is saved, the other is suggestion. - WifiConfiguration suggestionConfig = generateWifiConfig(TEST_FQDN2); - suggestionConfig.creatorUid = TEST_UID; - suggestionConfig.creatorName = TEST_PACKAGE; - suggestionConfig.fromWifiNetworkSuggestion = true; - PasspointProvider suggestionProvider = generateProvider(suggestionConfig); - when(suggestionProvider.isFromSuggestion()).thenReturn(true); - - List<Pair<PasspointProvider, PasspointMatch>> homeProviders = new ArrayList<>(); - homeProviders.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - homeProviders.add(Pair.create(suggestionProvider, PasspointMatch.HomeProvider)); - when(mPasspointManager.matchProvider(any(ScanResult.class))) - .thenReturn(homeProviders); - when(mWifiConfigManager.addOrUpdateNetwork(eq(TEST_CONFIG1), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.addOrUpdateNetwork(eq(suggestionConfig), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID2)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID2)) - .thenReturn(suggestionConfig); - //Get saved passpoint network candidate - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertEquals(1, candidates.size()); - assertEquals(TEST_FQDN1, candidates.get(0).second.FQDN); - //Get suggestion passpoint network candidate - candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, true); - assertEquals(1, candidates.size()); - assertEquals(TEST_FQDN2, candidates.get(0).second.FQDN); - } - - /** - * Verify that provider matching will not be performed when evaluating scans with interworking - * support, but no HS2.0 VSA element with release version, verify that no candidate will be - * nominated. - * - * @throws Exception - */ - @Test - public void evaluateScansWithInterworkingAndNoHs20VsaAP() throws Exception { - NetworkDetail networkDetail = mock(NetworkDetail.class); - when(networkDetail.isInterworking()).thenReturn(true); - when(networkDetail.getHSRelease()).thenReturn(null); - when(networkDetail.getAnt()).thenReturn(NetworkDetail.Ant.FreePublic); - when(networkDetail.isInternet()).thenReturn(true); - ScanDetail scanDetail = mock(ScanDetail.class); - when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); - - List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {scanDetail}); - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertTrue(candidates.isEmpty()); - // Verify that no provider matching is performed. - verify(mPasspointManager, never()).matchProvider(any(ScanResult.class)); - } - - /** - * Verify matching passpoint provider with ChargeablePublic AP will nominate a metered - * candidate. - */ - @Test - public void evaluateScansWithAntIsChargeablePublic() { - ScanDetail scanDetail = generateScanDetail(TEST_SSID1, TEST_BSSID1); - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - when(networkDetail.getAnt()).thenReturn(NetworkDetail.Ant.ChargeablePublic); - List<ScanDetail> scanDetails = Arrays.asList(scanDetail); - - List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); - homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); - - // Return homeProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for - // for the second (TEST_SSID2); - when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider) - .thenReturn(null); - when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), - any())).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); - when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); - List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper - .getPasspointNetworkCandidates(scanDetails, false); - assertEquals(1, candidates.size()); - assertTrue(WifiConfiguration.isMetered(candidates.get(0).second, null)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java deleted file mode 100644 index 936a8c4c9..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java +++ /dev/null @@ -1,1591 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.net.wifi.EAPConstants; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.net.wifi.hotspot2.pps.UpdateParameter; -import android.text.TextUtils; -import android.util.Base64; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.FakeKeys; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiCarrierInfoManager; -import com.android.server.wifi.WifiKeyStore; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.CellularNetwork; -import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; -import com.android.server.wifi.hotspot2.anqp.DomainNameElement; -import com.android.server.wifi.hotspot2.anqp.NAIRealmData; -import com.android.server.wifi.hotspot2.anqp.NAIRealmElement; -import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement; -import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement; -import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; -import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; -import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; -import com.android.server.wifi.util.ArrayUtils; -import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.mockito.Mock; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointProvider}. - */ -@SmallTest -@RunWith(Parameterized.class) -public class PasspointProviderTest extends WifiBaseTest { - private static final long PROVIDER_ID = 12L; - private static final int CREATOR_UID = 1234; - private static final String CREATOR_PACKAGE = "com.android.test"; - private static final String CA_CERTIFICATE_ALIAS = "HS2_12_0"; - private static final String CA_CERTIFICATE_ALIAS_2 = "HS2_12_1"; - private static final String CLIENT_CERTIFICATE_ALIAS = "HS2_12"; - private static final String CLIENT_PRIVATE_KEY_AND_CERT_ALIAS = "HS2_12"; - private static final String REMEDIATION_CA_CERTIFICATE_ALIAS = "HS2_REMEDIATION_12"; - private static final String SYSTEM_CA_STORE_PATH = "/system/etc/security/cacerts"; - - private static final int TEST_UPDATE_IDENTIFIER = 1234; - private static final int TEST_USAGE_LIMIT_DATA_LIMIT = 100; - private static final String TEST_FQDN = "test.com"; - private static final String TEST_FQDN2 = "test2.com"; - private static final String TEST_FQDN3 = "test3.com"; - private static final String TEST_FRIENDLY_NAME = "Friendly Name"; - private static final long[] TEST_RC_OIS = new long[] {0x1234L, 0x2345L}; - private static final long[] TEST_IE_RC_OIS = new long[] {0x1234L, 0x2133L}; - private static final long[] TEST_IE_NO_MATCHED_RC_OIS = new long[] {0x2255L, 0x2133L}; - private static final Long[] TEST_ANQP_RC_OIS = new Long[] {0x1234L, 0x2133L}; - private static final String TEST_REALM = "realm.com"; - private static final String[] TEST_TRUSTED_NAME = - new String[] {"trusted.fqdn.com", "another.fqdn.com"}; - // User credential data - private static final String TEST_USERNAME = "username"; - private static final String TEST_PASSWORD = "password3"; - // SIM credential data - private static final int TEST_EAP_TYPE = WifiEnterpriseConfig.Eap.SIM; - private static final int TEST_SIM_CREDENTIAL_TYPE = EAPConstants.EAP_SIM; - private static final String TEST_IMSI = "1234567890"; - private static final int VALID_CARRIER_ID = 1; - - private enum CredentialType { - USER, - CERT, - SIM - } - - @Mock WifiKeyStore mKeyStore; - @Mock - WifiCarrierInfoManager mWifiCarrierInfoManager; - @Mock RoamingConsortium mRoamingConsortium; - PasspointProvider mProvider; - X509Certificate mRemediationCaCertificate; - String mExpectedResult; - - @Parameterized.Parameters - public static Collection rootCAConfigsForRemediation() { - return Arrays.asList( - new Object[][]{ - {FakeKeys.CA_CERT0, REMEDIATION_CA_CERTIFICATE_ALIAS}, // For R2 config - {null, null}, // For R1 config - }); - } - - public PasspointProviderTest(X509Certificate remediationCaCertificate, String expectedResult) { - mRemediationCaCertificate = remediationCaCertificate; - mExpectedResult = expectedResult; - } - - /** Sets up test. */ - @Before - public void setUp() throws Exception { - initMocks(this); - when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(null); - } - - /** - * Helper function for creating a provider instance for testing. - * - * @param config The configuration associated with the provider - * @return {@link com.android.server.wifi.hotspot2.PasspointProvider} - */ - private PasspointProvider createProvider(PasspointConfiguration config) { - return new PasspointProvider(config, mKeyStore, mWifiCarrierInfoManager, PROVIDER_ID, - CREATOR_UID, CREATOR_PACKAGE, false); - } - - /** - * Verify that the configuration associated with the provider is the same or not the same - * as the expected configuration. - * - * @param expectedConfig The expected configuration - * @param equals Flag indicating equality or inequality check - */ - private void verifyInstalledConfig(PasspointConfiguration expectedConfig, boolean equals) { - PasspointConfiguration actualConfig = mProvider.getConfig(); - if (equals) { - assertTrue(actualConfig.equals(expectedConfig)); - } else { - assertFalse(actualConfig.equals(expectedConfig)); - } - } - - /** - * Helper function for creating a Domain Name ANQP element. - * - * @param domains List of domain names - * @return {@link DomainNameElement} - */ - private DomainNameElement createDomainNameElement(String[] domains) { - return new DomainNameElement(Arrays.asList(domains)); - } - - /** - * Helper function for creating a NAI Realm ANQP element. - * - * @param realm The realm of the network - * @param eapMethodID EAP Method ID - * @param authParam Authentication parameter - * @return {@link NAIRealmElement} - */ - private NAIRealmElement createNAIRealmElement(String realm, int eapMethodID, - AuthParam authParam) { - Map<Integer, Set<AuthParam>> authParamMap = new HashMap<>(); - if (authParam != null) { - Set<AuthParam> authSet = new HashSet<>(); - authSet.add(authParam); - authParamMap.put(authParam.getAuthTypeID(), authSet); - } - EAPMethod eapMethod = new EAPMethod(eapMethodID, authParamMap); - NAIRealmData realmData = new NAIRealmData(Arrays.asList(new String[] {realm}), - Arrays.asList(new EAPMethod[] {eapMethod})); - return new NAIRealmElement(Arrays.asList(new NAIRealmData[] {realmData})); - } - - /** - * Helper function for creating a Roaming Consortium ANQP element. - * - * @param rcOIs Roaming consortium OIs - * @return {@link RoamingConsortiumElement} - */ - private RoamingConsortiumElement createRoamingConsortiumElement(Long[] rcOIs) { - return new RoamingConsortiumElement(Arrays.asList(rcOIs)); - } - - /** - * Helper function for creating a 3GPP Network ANQP element. - * - * @param imsiList List of IMSI to be included in a 3GPP Network - * @return {@link ThreeGPPNetworkElement} - */ - private ThreeGPPNetworkElement createThreeGPPNetworkElement(String[] imsiList) { - CellularNetwork network = new CellularNetwork(Arrays.asList(imsiList)); - return new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); - } - - /** - * Helper function for generating test passpoint configuration for test cases - * - * @param credentialType which type credential is generated. - * @param isLegacy if true, omit some passpoint fields to avoid breaking comparison - * between passpoint configuration converted from wifi configuration - * and generated passpoint configuration. - * @return a valid passpoint configuration - * @throws Exception - */ - private PasspointConfiguration generateTestPasspointConfiguration( - CredentialType credentialType, boolean isLegacy) throws Exception { - PasspointConfiguration config = new PasspointConfiguration(); - if (!isLegacy) { - config.setUpdateIdentifier(TEST_UPDATE_IDENTIFIER); - config.setUsageLimitDataLimit(TEST_USAGE_LIMIT_DATA_LIMIT); - } - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn(TEST_FQDN); - homeSp.setFriendlyName(TEST_FRIENDLY_NAME); - homeSp.setRoamingConsortiumOis(TEST_RC_OIS); - config.setHomeSp(homeSp); - Credential credential = new Credential(); - credential.setRealm(TEST_REALM); - - if (credentialType == CredentialType.USER) { - byte[] base64EncodedPw = - Base64.encode(TEST_PASSWORD.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); - String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); - Credential.UserCredential userCredential = new Credential.UserCredential(); - userCredential.setEapType(EAPConstants.EAP_TTLS); - userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); - userCredential.setUsername(TEST_USERNAME); - userCredential.setPassword(encodedPasswordStr); - if (!isLegacy) { - credential.setCaCertificates(new X509Certificate[] {FakeKeys.CA_CERT0}); - } - credential.setUserCredential(userCredential); - } else if (credentialType == CredentialType.CERT) { - Credential.CertificateCredential certCredential = - new Credential.CertificateCredential(); - if (!isLegacy) { - certCredential.setCertSha256Fingerprint( - MessageDigest.getInstance("SHA-256") - .digest(FakeKeys.CLIENT_CERT.getEncoded())); - credential.setCaCertificates(new X509Certificate[] {FakeKeys.CA_CERT0}); - credential.setClientPrivateKey(FakeKeys.RSA_KEY1); - credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT}); - } else { - certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3); - } - credential.setCertCredential(certCredential); - } else if (credentialType == CredentialType.SIM) { - Credential.SimCredential simCredential = new Credential.SimCredential(); - simCredential.setImsi(TEST_IMSI); - simCredential.setEapType(EAPConstants.EAP_SIM); - credential.setSimCredential(simCredential); - } - config.setCredential(credential); - - return config; - } - - /** - * Helper function for verifying wifi configuration based on Passpoint configuration - * - * @param passpointConfig the source of wifi configuration. - * @param wifiConfig wifi configuration be verified. - * - * @throws Exception - */ - private void verifyWifiConfigWithTestData( - PasspointConfiguration passpointConfig, WifiConfiguration wifiConfig) { - BitSet allowedProtocols = new BitSet(); - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - - HomeSp homeSp = passpointConfig.getHomeSp(); - Credential credential = passpointConfig.getCredential(); - - // Need to verify field by field since WifiConfiguration doesn't - // override equals() function. - WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig; - assertEquals(homeSp.getFqdn(), wifiConfig.FQDN); - assertEquals(homeSp.getFriendlyName(), wifiConfig.providerFriendlyName); - assertTrue(Arrays.equals(homeSp.getRoamingConsortiumOis(), - wifiConfig.roamingConsortiumIds)); - - assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)); - assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)); - assertEquals(wifiConfig.updateIdentifier, - Integer.toString(passpointConfig.getUpdateIdentifier())); - assertEquals(allowedProtocols, wifiConfig.allowedProtocols); - assertEquals(Integer.toString(passpointConfig.getUpdateIdentifier()), - wifiConfig.updateIdentifier); - assertFalse(wifiConfig.shared); - assertEquals(credential.getRealm(), wifiEnterpriseConfig.getRealm()); - if (passpointConfig.isMacRandomizationEnabled()) { - assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT, - wifiConfig.macRandomizationSetting); - } else { - assertEquals(WifiConfiguration.RANDOMIZATION_NONE, wifiConfig.macRandomizationSetting); - } - - if (credential.getUserCredential() != null) { - String decodedPassword; - Credential.UserCredential userCredential = credential.getUserCredential(); - try { - byte[] pwOctets = Base64.decode(userCredential.getPassword(), Base64.DEFAULT); - decodedPassword = new String(pwOctets, StandardCharsets.UTF_8); - } catch (IllegalArgumentException e) { - decodedPassword = userCredential.getPassword(); - } - - assertEquals("anonymous@" + credential.getRealm(), - wifiEnterpriseConfig.getAnonymousIdentity()); - assertEquals(WifiEnterpriseConfig.Eap.TTLS, wifiEnterpriseConfig.getEapMethod()); - switch (userCredential.getNonEapInnerMethod()) { - case Credential.UserCredential.AUTH_METHOD_PAP: - assertEquals(WifiEnterpriseConfig.Phase2.PAP, - wifiEnterpriseConfig.getPhase2Method()); - break; - case Credential.UserCredential.AUTH_METHOD_MSCHAP: - assertEquals(WifiEnterpriseConfig.Phase2.MSCHAP, - wifiEnterpriseConfig.getPhase2Method()); - break; - case Credential.UserCredential.AUTH_METHOD_MSCHAPV2: - assertEquals(WifiEnterpriseConfig.Phase2.MSCHAPV2, - wifiEnterpriseConfig.getPhase2Method()); - break; - } - assertEquals(userCredential.getUsername(), wifiEnterpriseConfig.getIdentity()); - assertEquals(decodedPassword, wifiEnterpriseConfig.getPassword()); - assertEquals(decodedPassword, TEST_PASSWORD); - assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE, - wifiConfig.meteredOverride); - - if (!ArrayUtils.isEmpty(passpointConfig.getAaaServerTrustedNames())) { - assertEquals(String.join(";", passpointConfig.getAaaServerTrustedNames()), - wifiEnterpriseConfig.getDomainSuffixMatch()); - } else { - assertEquals(homeSp.getFqdn(), wifiEnterpriseConfig.getDomainSuffixMatch()); - } - - if (!ArrayUtils.isEmpty(passpointConfig.getAaaServerTrustedNames())) { - assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath()); - } else if (ArrayUtils.isEmpty(credential.getCaCertificates())) { - assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath()); - } else { - assertEquals(CA_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getCaCertificateAlias()); - } - if (passpointConfig.getCredential().getCheckAaaServerCertStatus()) { - assertEquals(wifiEnterpriseConfig.getOcsp(), - WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); - } else { - assertEquals(wifiEnterpriseConfig.getOcsp(), - WifiEnterpriseConfig.OCSP_NONE); - } - } else if (credential.getCertCredential() != null) { - Credential.CertificateCredential certCredential = credential.getCertCredential(); - assertEquals("anonymous@" + credential.getRealm(), - wifiEnterpriseConfig.getAnonymousIdentity()); - assertEquals(WifiEnterpriseConfig.Eap.TLS, wifiEnterpriseConfig.getEapMethod()); - assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE, wifiConfig.meteredOverride); - // Domain suffix match - if (ArrayUtils.isEmpty(passpointConfig.getAaaServerTrustedNames())) { - assertEquals(homeSp.getFqdn(), wifiEnterpriseConfig.getDomainSuffixMatch()); - } else { - assertEquals(String.join(";", passpointConfig.getAaaServerTrustedNames()), - wifiEnterpriseConfig.getDomainSuffixMatch()); - assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath()); - } - // CA certificate - if (!ArrayUtils.isEmpty(passpointConfig.getAaaServerTrustedNames())) { - assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath()); - } else if (!ArrayUtils.isEmpty(credential.getCaCertificates())) { - assertEquals(CA_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getCaCertificateAlias()); - } else { - assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath()); - } - if (passpointConfig.getCredential().getCheckAaaServerCertStatus()) { - assertEquals(wifiEnterpriseConfig.getOcsp(), - WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); - } else { - assertEquals(wifiEnterpriseConfig.getOcsp(), - WifiEnterpriseConfig.OCSP_NONE); - } - } else if (credential.getSimCredential() != null) { - Credential.SimCredential simCredential = credential.getSimCredential(); - switch (simCredential.getEapType()) { - case EAPConstants.EAP_SIM: - assertEquals(WifiEnterpriseConfig.Eap.SIM, - wifiEnterpriseConfig.getEapMethod()); - break; - case EAPConstants.EAP_AKA: - assertEquals(WifiEnterpriseConfig.Eap.AKA, - wifiEnterpriseConfig.getEapMethod()); - break; - case EAPConstants.EAP_AKA_PRIME: - assertEquals(WifiEnterpriseConfig.Eap.AKA_PRIME, - wifiEnterpriseConfig.getEapMethod()); - break; - } - assertEquals(simCredential.getImsi(), wifiEnterpriseConfig.getPlmn()); - } - } - - /** - * Verify that modification to the configuration used for creating PasspointProvider - * will not change the configuration stored inside the PasspointProvider. - * - * @throws Exception - */ - @Test - public void verifyModifyOriginalConfig() throws Exception { - // Create a dummy PasspointConfiguration. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - verifyInstalledConfig(config, true); - - // Modify the original configuration, the configuration maintained by the provider - // should be unchanged. - config.getHomeSp().setFqdn(TEST_FQDN2); - verifyInstalledConfig(config, false); - } - - /** - * Verify that modification to the configuration retrieved from the PasspointProvider - * will not change the configuration stored inside the PasspointProvider. - * - * @throws Exception - */ - @Test - public void verifyModifyRetrievedConfig() throws Exception { - // Create a dummy PasspointConfiguration. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - verifyInstalledConfig(config, true); - - // Modify the retrieved configuration, verify the configuration maintained by the - // provider should be unchanged. - PasspointConfiguration retrievedConfig = mProvider.getConfig(); - retrievedConfig.getHomeSp().setFqdn(TEST_FQDN2); - verifyInstalledConfig(retrievedConfig, false); - } - - /** - * Verify a successful installation of certificates and key. - * - * @throws Exception - */ - @Test - public void installCertsAndKeysSuccess() throws Exception { - // Create a dummy configuration with certificate credential. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.CERT, false); - Credential credential = config.getCredential(); - Credential.CertificateCredential certCredential = credential.getCertCredential(); - credential.setCaCertificates(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); - if (mRemediationCaCertificate != null) { - UpdateParameter updateParameter = new UpdateParameter(); - updateParameter.setCaCertificate(mRemediationCaCertificate); - config.setSubscriptionUpdate(updateParameter); - } - mProvider = createProvider(config); - - // Install client certificate and key to the keystore successfully. - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS_2, FakeKeys.CA_CERT1)) - .thenReturn(true); - when(mKeyStore.putUserPrivKeyAndCertsInKeyStore( - CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1, - new Certificate[] {FakeKeys.CLIENT_CERT})) - .thenReturn(true); - when(mKeyStore.putCaCertInKeyStore(REMEDIATION_CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - assertTrue(mProvider.installCertsAndKeys()); - - // Verify client certificate and key in the configuration gets cleared and aliases - // are set correctly. - PasspointConfiguration curConfig = mProvider.getConfig(); - assertTrue(curConfig.getCredential().getCaCertificates() == null); - assertTrue(curConfig.getCredential().getClientPrivateKey() == null); - assertTrue(curConfig.getCredential().getClientCertificateChain() == null); - if (mRemediationCaCertificate != null) { - assertTrue(curConfig.getSubscriptionUpdate().getCaCertificate() == null); - } - assertTrue(mProvider.getCaCertificateAliases().equals( - Arrays.asList(CA_CERTIFICATE_ALIAS, CA_CERTIFICATE_ALIAS_2))); - assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias() - .equals(CLIENT_PRIVATE_KEY_AND_CERT_ALIAS)); - assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias() - .equals(CLIENT_PRIVATE_KEY_AND_CERT_ALIAS)); - assertTrue(TextUtils.equals(mProvider.getRemediationCaCertificateAlias(), mExpectedResult)); - } - - /** - * Verify a failure installation of certificates and key. - */ - @Test - public void installCertsAndKeysFailure() throws Exception { - // Create a dummy configuration with certificate credential. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.CERT, false); - Credential credential = config.getCredential(); - Credential.CertificateCredential certCredential = credential.getCertCredential(); - credential.setCaCertificates(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); - config.setCredential(credential); - - UpdateParameter updateParameter = new UpdateParameter(); - updateParameter.setCaCertificate(mRemediationCaCertificate); - config.setSubscriptionUpdate(updateParameter); - mProvider = createProvider(config); - - // Failed to install client certificate to the keystore. - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS_2, FakeKeys.CA_CERT1)) - .thenReturn(false); - when(mKeyStore.putUserPrivKeyAndCertsInKeyStore( - CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1, - new Certificate[] {FakeKeys.CLIENT_CERT})) - .thenReturn(true); - when(mKeyStore.putCaCertInKeyStore(REMEDIATION_CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - assertFalse(mProvider.installCertsAndKeys()); - - // Verify certificates and key in the configuration are not cleared and aliases - // are not set. - PasspointConfiguration curConfig = mProvider.getConfig(); - assertTrue(curConfig.getCredential().getCaCertificates() != null); - assertTrue(curConfig.getCredential().getClientCertificateChain() != null); - assertTrue(curConfig.getCredential().getClientPrivateKey() != null); - if (mRemediationCaCertificate != null) { - assertTrue(curConfig.getSubscriptionUpdate().getCaCertificate() != null); - } - assertTrue(mProvider.getCaCertificateAliases() == null); - assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias() == null); - assertTrue(mProvider.getRemediationCaCertificateAlias() == null); - } - - /** - * Verify a successful uninstallation of certificates and key. - */ - @Test - public void uninstallCertsAndKeys() throws Exception { - // Create a dummy configuration with certificate credential. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.CERT, false); - Credential credential = config.getCredential(); - Credential.CertificateCredential certCredential = credential.getCertCredential(); - credential.setCaCertificates(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); - config.setCredential(credential); - if (mRemediationCaCertificate != null) { - UpdateParameter updateParameter = new UpdateParameter(); - updateParameter.setCaCertificate(FakeKeys.CA_CERT0); - config.setSubscriptionUpdate(updateParameter); - } - mProvider = createProvider(config); - - // Install client certificate and key to the keystore successfully. - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS_2, FakeKeys.CA_CERT1)) - .thenReturn(true); - when(mKeyStore.putUserPrivKeyAndCertsInKeyStore( - CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1, - new Certificate[] {FakeKeys.CLIENT_CERT})) - .thenReturn(true); - when(mKeyStore.putCaCertInKeyStore(REMEDIATION_CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - assertTrue(mProvider.installCertsAndKeys()); - assertTrue(mProvider.getCaCertificateAliases().equals( - Arrays.asList(CA_CERTIFICATE_ALIAS, CA_CERTIFICATE_ALIAS_2))); - assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias() - .equals(CLIENT_PRIVATE_KEY_AND_CERT_ALIAS)); - assertTrue(TextUtils.equals(mProvider.getRemediationCaCertificateAlias(), mExpectedResult)); - - // Uninstall certificates and key from the keystore. - mProvider.uninstallCertsAndKeys(); - verify(mKeyStore).removeEntryFromKeyStore(CA_CERTIFICATE_ALIAS); - verify(mKeyStore).removeEntryFromKeyStore(CA_CERTIFICATE_ALIAS_2); - verify(mKeyStore).removeEntryFromKeyStore(CLIENT_CERTIFICATE_ALIAS); - verify(mKeyStore).removeEntryFromKeyStore(CLIENT_PRIVATE_KEY_AND_CERT_ALIAS); - if (mRemediationCaCertificate != null) { - verify(mKeyStore).removeEntryFromKeyStore(REMEDIATION_CA_CERTIFICATE_ALIAS); - } - - assertTrue(mProvider.getCaCertificateAliases() == null); - assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias() == null); - assertTrue(mProvider.getRemediationCaCertificateAlias() == null); - } - - /** - * Verify that a provider is a home provider when its FQDN matches a domain name in the - * Domain Name ANQP element and no NAI realm is provided. - * - * @throws Exception - */ - @Test - public void matchFQDNWithoutNAIRealm() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup ANQP elements. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN})); - - assertEquals(PasspointMatch.HomeProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a home provider when its FQDN matches a domain name in the - * Domain Name ANQP element and the provider's credential matches the NAI realm provided. - * - * @throws Exception - */ - @Test - public void matchFQDNWithNAIRealmMatch() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup Domain Name ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN})); - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS, - new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); - - assertEquals(PasspointMatch.HomeProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that Home provider is matched even when the provider's FQDN matches a domain name in - * the Domain Name ANQP element but the provider's credential doesn't match the authentication - * method provided in the NAI realm. This can happen when the infrastructure provider is not - * the identity provider, and authentication method matching is not required in the spec. - * - * @throws Exception - */ - @Test - public void matchFQDNWithNAIRealmMismatch() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup Domain Name ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN})); - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TLS, null)); - - assertEquals(PasspointMatch.HomeProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a home provider when its SIM credential matches an 3GPP network - * domain name in the Domain Name ANQP element. - * - * @throws Exception - */ - @Test - public void matchFQDNWith3GPPNetworkDomainName() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI)) - .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); - mProvider = createProvider(config); - - // Setup Domain Name ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {"wlan.mnc456.mcc123.3gppnetwork.org"})); - - assertEquals(PasspointMatch.HomeProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a home provider when its FQDN, roaming consortium OI, and - * IMSI all matched against the ANQP elements, since we prefer matching home provider over - * roaming provider. - * - * @throws Exception - */ - @Test - public void matchFQDNOverRoamingProvider() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI)) - .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); - mProvider = createProvider(config); - - // Setup ANQP elements. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN})); - anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, - createRoamingConsortiumElement(TEST_ANQP_RC_OIS)); - anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, - createThreeGPPNetworkElement(new String[] {"123456"})); - - assertEquals(PasspointMatch.HomeProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI - * in the roaming consortium ANQP element and no NAI realm is provided. - * - * @throws Exception - */ - @Test - public void matchRoamingConsortiumWithoutNAIRealm() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - mProvider = createProvider(config); - when(mWifiCarrierInfoManager.getMatchingImsiCarrierId( - eq(config.getCredential().getSimCredential().getImsi()))) - .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); - - // Setup Roaming Consortium ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, - createRoamingConsortiumElement(TEST_ANQP_RC_OIS)); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI - * in the roaming consortium ANQP element and the provider's credential matches the - * NAI realm provided. - * - * @throws Exception - */ - @Test - public void matchRoamingConsortiumWithNAIRealmMatch() throws Exception { - - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup Roaming Consortium ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, - createRoamingConsortiumElement(TEST_ANQP_RC_OIS)); - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS, - new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that there is Roaming provider match when a roaming consortium OI matches an OI - * in the roaming consortium ANQP element and regardless of NAI realm mismatch. - * - * @throws Exception - */ - @Test - public void matchRoamingConsortiumWithNAIRealmMisMatch() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup Roaming Consortium ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, - createRoamingConsortiumElement(TEST_ANQP_RC_OIS)); - // Set up NAI with different EAP method - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TLS, null)); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI - * in the roaming consortium information element and no NAI realm is provided. - * - * @throws Exception - */ - @Test - public void matchRoamingConsortiumIeWithoutNAIRealm() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup Roaming Consortium ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - - // Setup Roaming Consortium Information element. - when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(TEST_IE_RC_OIS); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI - * in the roaming consortium information element and the provider's credential matches the - * NAI realm provided. - * - * @throws Exception - */ - @Test - public void matchRoamingConsortiumIeWithNAIRealmMatch() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup Roaming Consortium ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - - // Setup Roaming Consortium Information element. - when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(TEST_IE_RC_OIS); - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS, - new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that there is Roaming provider match when a roaming consortium OI matches an OI - * in the roaming consortium information element, but NAI realm is not matched. - * This can happen in roaming federation where the infrastructure provider is not the - * identity provider. - * Page 133 in the Hotspot2.0 specification states: - * Per subclause 11.25.8 of [2], if the value of HomeOI matches an OI in the Roaming - * Consortium advertised by a hotspot operator, successful authentication with that hotspot - * is possible. - * - * @throws Exception - */ - @Test - public void matchRoamingConsortiumIeWithNAIRealmMismatch() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup Roaming Consortium ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - - // Setup Roaming Consortium Information element. - when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(TEST_IE_RC_OIS); - // Set up NAI with different EAP method - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TLS, null)); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that none of matched providers are found when a roaming consortium OI doesn't - * matches an OI in the roaming consortium information element and - * none of NAI realms match each other. - * - * @throws Exception - */ - @Test - public void misMatchForRoamingConsortiumIeAndNAIRealm() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup Roaming Consortium ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - - // Setup Roaming Consortium Information element. - when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(TEST_IE_NO_MATCHED_RC_OIS); - - assertEquals(PasspointMatch.None, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a roaming provider when the provider's IMSI parameter and an IMSI - * from the SIM card matches a MCC-MNC in the 3GPP Network ANQP element regardless of NAI realm - * mismatch. - * - * @throws Exception - */ - @Test - public void matchThreeGPPNetworkWithNAIRealmMismatch() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI)) - .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); - mProvider = createProvider(config); - - // Setup 3GPP Network ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, - createThreeGPPNetworkElement(new String[] {"123456"})); - - // Setup NAI Realm ANQP element with different realm. - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS, - new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a roaming provider when the provider's IMSI parameter and an IMSI - * from the SIM card matches a MCC-MNC in the 3GPP Network ANQP element regardless of NAI realm - * match. - * - * @throws Exception - */ - @Test - public void matchThreeGPPNetworkWithNAIRealmMatch() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI)) - .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID)); - mProvider = createProvider(config); - - // Setup 3GPP Network ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, - createThreeGPPNetworkElement(new String[] {"123456"})); - - // Setup NAI Realm ANQP element with same realm. - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_AKA, null)); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - assertEquals(VALID_CARRIER_ID, mProvider.getWifiConfig().carrierId); - } - - /** - * Verify that when the SIM card matched by carrier ID of profile is absent, it shouldn't - * be matched even the profile and ANQP elements are matched. - * - * @throws Exception - */ - @Test - public void matchNothingIfSimMatchedByCarrierIdIsAbsent() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - config.setCarrierId(VALID_CARRIER_ID); - when(mWifiCarrierInfoManager.getMatchingImsi(eq(VALID_CARRIER_ID))) - .thenReturn(null); - mProvider = createProvider(config); - - // Setup 3GPP Network ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, - createThreeGPPNetworkElement(new String[] {"123456"})); - - // Setup NAI Realm ANQP element with same realm. - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_AKA, null)); - - assertEquals(PasspointMatch.None, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that when the SIM card matched by IMSI of profile is absent, it shouldn't be - * matched even the profile and ANQP elements are matched. - * - * @throws Exception - */ - @Test - public void matchNothingIfSimMatchedByImsiIsAbsent() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(eq(TEST_IMSI))) - .thenReturn(null); - mProvider = createProvider(config); - - // Setup 3GPP Network ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, - createThreeGPPNetworkElement(new String[] {"123456"})); - - // Setup NAI Realm ANQP element with same realm. - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_AKA, null)); - - assertEquals(PasspointMatch.None, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that a provider is a roaming provider when its credential only matches a NAI realm in - * the NAI Realm ANQP element and not match for Domain Name, RoamingConsortium and 3GPP. - * - * @throws Exception - */ - @Test - public void matchOnlyNAIRealmWithOtherInformationMismatch() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Setup NAI Realm ANQP element. - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPNAIRealm, - createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS, - new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); - - assertEquals(PasspointMatch.RoamingProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that an expected WifiConfiguration will be returned for a Passpoint provider - * with a user credential. - * - * @throws Exception - */ - @Test - public void getWifiConfigWithUserCredential() throws Exception { - // Create provider for R2. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - // Install certificate. - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - assertTrue(mProvider.installCertsAndKeys()); - - // Retrieve the WifiConfiguration associated with the provider, and verify the content of - // the configuration. - verifyWifiConfigWithTestData(config, mProvider.getWifiConfig()); - - // Verify that AAA server trusted names are provisioned. - config.setAaaServerTrustedNames(TEST_TRUSTED_NAME); - mProvider = createProvider(config); - verifyWifiConfigWithTestData(config, - createProvider(config).getWifiConfig()); - } - - /** - * Verify that an expected WifiConfiguration will be returned for a Passpoint provider - * with a user credential which has AAA server trusted names provisioned. - * - * @throws Exception - */ - @Test - public void getWifiConfigWithUserCredentialHasAaaServerTrustedNames() throws Exception { - // Create provider for R2. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - config.setAaaServerTrustedNames(TEST_TRUSTED_NAME); - Credential credential = config.getCredential(); - // OCSP (Online Certificate Status Protocol) is required. - credential.setCheckAaaServerCertStatus(true); - mProvider = createProvider(config); - - // Install certificate. - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - assertTrue(mProvider.installCertsAndKeys()); - - // Retrieve the WifiConfiguration associated with the provider, and verify the content of - // the configuration. - verifyWifiConfigWithTestData(config, mProvider.getWifiConfig()); - - // Verify that AAA server trusted names are provisioned. - config.setAaaServerTrustedNames(TEST_TRUSTED_NAME); - mProvider = createProvider(config); - verifyWifiConfigWithTestData(config, - createProvider(config).getWifiConfig()); - } - - /** - * Verify that an expected WifiConfiguration will be returned for a Passpoint provider - * with a user credential which has no CA cert. - * - * @throws Exception - */ - @Test - public void getWifiConfigWithUserCredentialNoCaCert() throws Exception { - // Create provider for R2. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - config.getCredential().setCaCertificates(null); - mProvider = createProvider(config); - - // Retrieve the WifiConfiguration associated with the provider, and verify the content of - // the configuration. - verifyWifiConfigWithTestData(config, mProvider.getWifiConfig()); - } - - /** - * Verify that an expected WifiConfiguration will be returned for a Passpoint provider - * with a certificate credential. - * - * @throws Exception - */ - @Test - public void getWifiConfigWithCertCredential() throws Exception { - // Create provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.CERT, false); - mProvider = createProvider(config); - - // Install certificate. - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - when(mKeyStore.putUserPrivKeyAndCertsInKeyStore( - CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1, - new Certificate[] {FakeKeys.CLIENT_CERT})) - .thenReturn(true); - assertTrue(mProvider.installCertsAndKeys()); - - // Retrieve the WifiConfiguration associated with the provider, and verify the content of - // the configuration. - verifyWifiConfigWithTestData(config, mProvider.getWifiConfig()); - } - - /** - * Verify that an expected WifiConfiguration will be returned for a Passpoint provider - * with a certificate credential which has AAA server trusted names provisioned. - * - * @throws Exception - */ - @Test - public void getWifiConfigWithCertCredentialHasAaaServerTrustedNames() throws Exception { - // Create provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.CERT, false); - config.setAaaServerTrustedNames(TEST_TRUSTED_NAME); - mProvider = createProvider(config); - - // Install certificate. - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - when(mKeyStore.putUserPrivKeyAndCertsInKeyStore( - CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1, - new Certificate[] {FakeKeys.CLIENT_CERT})) - .thenReturn(true); - assertTrue(mProvider.installCertsAndKeys()); - - // Retrieve the WifiConfiguration associated with the provider, and verify the content of - // the configuration. - verifyWifiConfigWithTestData(config, mProvider.getWifiConfig()); - } - - /** - * Verify that an expected WifiConfiguration will be returned for a Passpoint provider - * with a certificate credential which has no CA cert. - * - * @throws Exception - */ - @Test - public void getWifiConfigWithCertCredentialNoCaCert() throws Exception { - // Create provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.CERT, false); - config.getCredential().setCaCertificates(null); - mProvider = createProvider(config); - - // Install certificate. - when(mKeyStore.putUserPrivKeyAndCertsInKeyStore( - CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1, - new Certificate[] {FakeKeys.CLIENT_CERT})) - .thenReturn(true); - assertTrue(mProvider.installCertsAndKeys()); - - // Retrieve the WifiConfiguration associated with the provider, and verify the content of - // the configuration. - verifyWifiConfigWithTestData(config, mProvider.getWifiConfig()); - } - - /** - * Verify that an expected WifiConfiguration will be returned for a Passpoint provider - * with a SIM credential. - * - * @throws Exception - */ - @Test - public void getWifiConfigWithSimCredential() throws Exception { - // Create provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - mProvider = createProvider(config); - - // Retrieve the WifiConfiguration associated with the provider, and verify the content of - // the configuration. - verifyWifiConfigWithTestData(config, mProvider.getWifiConfig()); - } - - @Test - public void getWifiConfigWithWithAutojoinDisable() throws Exception { - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - - assertTrue(mProvider.getWifiConfig().allowAutojoin); - mProvider.setAutojoinEnabled(false); - assertFalse(mProvider.getWifiConfig().allowAutojoin); - } - - /** - * Verify that the mac randomization setting will be included in the generated - * WifiConfiguration. - */ - @Test - public void testSetMacRandomizationEnabledToFalse() throws Exception { - // Create provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - mProvider = createProvider(config); - mProvider.setMacRandomizationEnabled(false); - verifyWifiConfigWithTestData(mProvider.getConfig(), mProvider.getWifiConfig()); - } - - /** - * Verify that an expected {@link PasspointConfiguration} will be returned when converting - * from a {@link WifiConfiguration} containing a user credential. - * - * @throws Exception - */ - @Test - public void convertFromWifiConfigWithUserCredential() throws Exception { - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = TEST_FQDN; - wifiConfig.providerFriendlyName = TEST_FRIENDLY_NAME; - wifiConfig.roamingConsortiumIds = TEST_RC_OIS; - wifiConfig.enterpriseConfig.setIdentity(TEST_USERNAME); - wifiConfig.enterpriseConfig.setPassword(TEST_PASSWORD); - wifiConfig.enterpriseConfig.setRealm(TEST_REALM); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); - wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP); - - // Setup expected {@link PasspointConfiguration} - PasspointConfiguration passpointConfig = generateTestPasspointConfiguration( - CredentialType.USER, true); - Credential.UserCredential userCredential = - passpointConfig.getCredential().getUserCredential(); - userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_PAP); - - assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig)); - } - - /** - * Verify that an expected {@link PasspointConfiguration} will be returned when converting - * from a {@link WifiConfiguration} containing a SIM credential. - * - * @throws Exception - */ - @Test - public void convertFromWifiConfigWithSimCredential() throws Exception { - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = TEST_FQDN; - wifiConfig.providerFriendlyName = TEST_FRIENDLY_NAME; - wifiConfig.roamingConsortiumIds = TEST_RC_OIS; - wifiConfig.enterpriseConfig.setRealm(TEST_REALM); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); - wifiConfig.enterpriseConfig.setPlmn(TEST_IMSI); - - // Setup expected {@link PasspointConfiguration} - PasspointConfiguration passpointConfig = generateTestPasspointConfiguration( - CredentialType.SIM, true); - - assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig)); - } - - /** - * Verify that an expected {@link PasspointConfiguration} will be returned when converting - * from a {@link WifiConfiguration} containing a certificate credential. - * - * @throws Exception - */ - @Test - public void convertFromWifiConfigWithCertCredential() throws Exception { - // Setup WifiConfiguration for legacy Passpoint configuraiton. - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.FQDN = TEST_FQDN; - wifiConfig.providerFriendlyName = TEST_FRIENDLY_NAME; - wifiConfig.roamingConsortiumIds = TEST_RC_OIS; - wifiConfig.enterpriseConfig.setRealm(TEST_REALM); - wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - - // Setup expected {@link PasspointConfiguration} - PasspointConfiguration passpointConfig = generateTestPasspointConfiguration( - CredentialType.CERT, true); - - assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig)); - } - - /** - * Verify that {@link PasspointProvider#isSimCredential} will return true for provider that's - * backed by a SIM credential. - * - * @throws Exception - */ - @Test - public void providerBackedBySimCredential() throws Exception { - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.SIM, false); - mProvider = createProvider(config); - - assertTrue(mProvider.isSimCredential()); - } - - /** - * Verify that {@link PasspointProvider#isSimCredential} will return false for provider that's - * not backed by a SIM credential. - * - * @throws Exception - */ - @Test - public void providerNotBackedBySimCredential() throws Exception { - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.CERT, false); - mProvider = createProvider(config); - - assertFalse(mProvider.isSimCredential()); - } - - /** - * Verify that hasEverConnected flag is set correctly using - * {@link PasspointProvider#setHasEverConnected}. - * - * @throws Exception - */ - @Test - public void setHasEverConnected() throws Exception { - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - mProvider = createProvider(config); - verifyInstalledConfig(config, true); - - assertFalse(mProvider.getHasEverConnected()); - mProvider.setHasEverConnected(true); - assertTrue(mProvider.getHasEverConnected()); - } - - /** - * Verify that a provider is a home provider when there is a match between Other Home Partners - * in the profile and the Domain Name ANQP element. - * - * @throws Exception - */ - @Test - public void getWifiConfigWithUserCredentialAndNonBase64Password() throws Exception { - // Create provider for R2. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - - // Update the password to non-Base64 - Credential credential = config.getCredential(); - Credential.UserCredential userCredential = credential.getUserCredential(); - userCredential.setPassword(TEST_PASSWORD); - credential.setUserCredential(userCredential); - config.setCredential(credential); - - mProvider = createProvider(config); - - // Install certificate. - when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0)) - .thenReturn(true); - assertTrue(mProvider.installCertsAndKeys()); - - // Retrieve the WifiConfiguration associated with the provider, and verify the content of - // the configuration. - verifyWifiConfigWithTestData(config, mProvider.getWifiConfig()); - - // Verify that AAA server trusted names are provisioned. - config.setAaaServerTrustedNames(TEST_TRUSTED_NAME); - mProvider = createProvider(config); - verifyWifiConfigWithTestData(config, - createProvider(config).getWifiConfig()); - } - - /** - * Verify that an expected WifiConfiguration will be returned for a Passpoint provider - * with a user credential. - * - * @throws Exception - */ - @Test - public void matchOtherPartnersDomainName() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - - // Configuration was created with TEST_FQDN as the FQDN, add TEST_FQDN3 as other home - // partner. - HomeSp homeSp = config.getHomeSp(); - homeSp.setOtherHomePartners(new String [] {TEST_FQDN3}); - config.setHomeSp(homeSp); - mProvider = createProvider(config); - - // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3 - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN2, TEST_FQDN3})); - - assertEquals(PasspointMatch.HomeProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that matching Any HomeOI results in a Home Provider match - * - * @throws Exception - */ - @Test - public void matchAnyHomeOi() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - Long[] anqpOis = new Long[] {0x1234L, 0xdeadL, 0xf0cdL}; - - // Configuration was created with TEST_FQDN as the FQDN - HomeSp homeSp = config.getHomeSp(); - homeSp.setMatchAnyOis(TEST_RC_OIS); - homeSp.setRoamingConsortiumOis(null); - config.setHomeSp(homeSp); - mProvider = createProvider(config); - - // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3 - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN2, TEST_FQDN3})); - // Setup RCOIs advertised by the AP - anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, - createRoamingConsortiumElement(anqpOis)); - - assertEquals(PasspointMatch.HomeProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that non-matching Any HomeOI results in a None Provider match - * - * @throws Exception - */ - @Test - public void matchAnyHomeOiNegative() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - Long[] anqpOis = new Long[] {0x12a4L, 0xceadL, 0xf0cdL}; - - // Configuration was created with TEST_FQDN as the FQDN - HomeSp homeSp = config.getHomeSp(); - homeSp.setMatchAnyOis(TEST_RC_OIS); - homeSp.setRoamingConsortiumOis(null); - config.setHomeSp(homeSp); - mProvider = createProvider(config); - - // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3 - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN2, TEST_FQDN3})); - // Setup RCOIs advertised by the AP - anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, - createRoamingConsortiumElement(anqpOis)); - - assertEquals(PasspointMatch.None, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that matching All HomeOI results in a Home Provider match - * - * @throws Exception - */ - @Test - public void matchAllHomeOi() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - Long[] anqpOis = new Long[] {0x1234L, 0x2345L, 0xabcdL, 0xdeadL, 0xf0cdL}; - - // Configuration was created with TEST_FQDN as the FQDN - HomeSp homeSp = config.getHomeSp(); - homeSp.setMatchAllOis(TEST_RC_OIS); - homeSp.setRoamingConsortiumOis(null); - config.setHomeSp(homeSp); - mProvider = createProvider(config); - - // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3 - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN2, TEST_FQDN3})); - // Setup RCOIs advertised by the AP - anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, - createRoamingConsortiumElement(anqpOis)); - - assertEquals(PasspointMatch.HomeProvider, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } - - /** - * Verify that non-matching All HomeOI results in a None Provider match - * - * @throws Exception - */ - @Test - public void matchAllHomeOiNegative() throws Exception { - // Setup test provider. - PasspointConfiguration config = generateTestPasspointConfiguration( - CredentialType.USER, false); - // 0x1234 matches, but 0x2345 does not - Long[] anqpOis = new Long[] {0x1234L, 0x5678L, 0xdeadL, 0xf0cdL}; - - // Configuration was created with TEST_FQDN as the FQDN - HomeSp homeSp = config.getHomeSp(); - homeSp.setMatchAllOis(TEST_RC_OIS); - homeSp.setRoamingConsortiumOis(null); - config.setHomeSp(homeSp); - mProvider = createProvider(config); - - // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3 - Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - anqpElementMap.put(ANQPElementType.ANQPDomName, - createDomainNameElement(new String[] {TEST_FQDN2, TEST_FQDN3})); - // Setup RCOIs advertised by the AP - anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, - createRoamingConsortiumElement(anqpOis)); - - assertEquals(PasspointMatch.None, - mProvider.match(anqpElementMap, mRoamingConsortium)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java deleted file mode 100644 index 6423f950f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java +++ /dev/null @@ -1,992 +0,0 @@ -/* - * Copyright 2017 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.net.Network; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.ProvisioningCallback; -import android.net.wifi.hotspot2.omadm.PpsMoParser; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.net.wifi.hotspot2.pps.UpdateParameter; -import android.os.Build; -import android.os.Handler; -import android.os.RemoteException; -import android.os.test.TestLooper; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import com.android.dx.mockito.inline.extended.ExtendedMockito; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiMetrics; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.hotspot2.anqp.ANQPElement; -import com.android.server.wifi.hotspot2.anqp.Constants; -import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement; -import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; -import com.android.server.wifi.hotspot2.anqp.OsuProviderInfoTestUtil; -import com.android.server.wifi.hotspot2.soap.ExchangeCompleteMessage; -import com.android.server.wifi.hotspot2.soap.PostDevDataResponse; -import com.android.server.wifi.hotspot2.soap.RedirectListener; -import com.android.server.wifi.hotspot2.soap.SppConstants; -import com.android.server.wifi.hotspot2.soap.SppResponseMessage; -import com.android.server.wifi.hotspot2.soap.UpdateResponseMessage; -import com.android.server.wifi.hotspot2.soap.command.BrowserUri; -import com.android.server.wifi.hotspot2.soap.command.PpsMoData; -import com.android.server.wifi.hotspot2.soap.command.SppCommand; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.serialization.SoapSerializationEnvelope; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; - -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.security.KeyStore; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; - -/** - * Unit tests for {@link PasspointProvisioner}. - */ -@SmallTest -public class PasspointProvisionerTest extends WifiBaseTest { - private static final int TEST_UID = 1500; - private static final int STEP_INIT = 0; - private static final int STEP_AP_CONNECT = 1; - private static final int STEP_SERVER_CONNECT = 2; - private static final int STEP_WAIT_FOR_REDIRECT_RESPONSE = 3; - private static final int STEP_WAIT_FOR_SECOND_SOAP_RESPONSE = 4; - private static final int STEP_WAIT_FOR_THIRD_SOAP_RESPONSE = 5; - private static final int STEP_WAIT_FOR_TRUST_ROOT_CERTS = 6; - - private static final String TEST_DEV_ID = "12312341"; - private static final String TEST_MANUFACTURER = Build.MANUFACTURER; - private static final String TEST_MODEL = Build.MODEL; - private static final String TEST_LANGUAGE = "en"; - private static final String TEST_SESSION_ID = "123456"; - private static final String TEST_URL = "https://127.0.0.1/session_id=" + TEST_SESSION_ID; - private static final String TEST_MAC_ADDR = "11:22:33:44:55:66"; - private static final String TEST_IMSI = "310150123456789"; - private static final String TEST_SW_VERSION = "Android Test 1.0"; - private static final String TEST_REDIRECT_URL = "http://127.0.0.1:12345/index.htm"; - private static final String TEST_SSID = "TestSSID"; - private static final String TEST_BSSID_STRING = "11:22:33:44:55:66"; - private static final String TEST_SSID2 = "TestSSID2"; - private static final String TEST_BSSID_STRING2 = "11:22:33:44:55:77"; - private static final String TEST_SSID3 = "TestSSID3"; - private static final String TEST_BSSID_STRING3 = "11:22:33:44:55:88"; - private static final String OSU_APP_PACKAGE = "com.android.hotspot2.osulogin"; - private static final String OSU_APP_NAME = "OsuLogin"; - - private static final byte[] TEST_OSU_SSID_BYTES = "OSU_SSID".getBytes(StandardCharsets.UTF_8); - private static final byte[] TEST_OSU_SSID3_BYTES = "OSU_SSID3".getBytes(StandardCharsets.UTF_8); - private static final WifiSsid TEST_OSU_SSID = - WifiSsid.createFromByteArray(TEST_OSU_SSID_BYTES); - private static final WifiSsid TEST_OSU_SSID3 = - WifiSsid.createFromByteArray(TEST_OSU_SSID3_BYTES); - private static final List<OsuProviderInfo> TEST_PROVIDER_LIST = - Arrays.asList(OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO); - private static final HSOsuProvidersElement TEST_OSU_PROVIDERS_ELEMENT = - new HSOsuProvidersElement(TEST_OSU_SSID, TEST_PROVIDER_LIST); - private static final HSOsuProvidersElement TEST_OSU_PROVIDERS3_ELEMENT = - new HSOsuProvidersElement(TEST_OSU_SSID3, TEST_PROVIDER_LIST); - - private PasspointProvisioner mPasspointProvisioner; - private TestLooper mLooper = new TestLooper(); - private Handler mHandler; - private OsuNetworkConnection.Callbacks mOsuNetworkCallbacks; - private PasspointProvisioner.OsuServerCallbacks mOsuServerCallbacks; - private RedirectListener.RedirectCallback mRedirectReceivedListener; - private ArgumentCaptor<OsuNetworkConnection.Callbacks> mOsuNetworkCallbacksCaptor = - ArgumentCaptor.forClass(OsuNetworkConnection.Callbacks.class); - private ArgumentCaptor<PasspointProvisioner.OsuServerCallbacks> mOsuServerCallbacksCaptor = - ArgumentCaptor.forClass(PasspointProvisioner.OsuServerCallbacks.class); - private ArgumentCaptor<RedirectListener.RedirectCallback> - mOnRedirectReceivedArgumentCaptor = - ArgumentCaptor.forClass(RedirectListener.RedirectCallback.class); - private ArgumentCaptor<Handler> mHandlerCaptor = ArgumentCaptor.forClass(Handler.class); - private OsuProvider mOsuProvider; - private TrustManagerFactory mDelegate; - private URL mTestUrl; - private MockitoSession mSession; - - @Mock PasspointObjectFactory mObjectFactory; - @Mock PasspointManager mPasspointManager; - @Mock Context mContext; - @Mock WifiManager mWifiManager; - @Mock IProvisioningCallback mCallback; - @Mock OsuNetworkConnection mOsuNetworkConnection; - @Mock OsuServerConnection mOsuServerConnection; - @Mock Network mNetwork; - @Mock WfaKeyStore mWfaKeyStore; - @Mock KeyStore mKeyStore; - @Mock SSLContext mTlsContext; - @Mock WifiNative mWifiNative; - @Mock PostDevDataResponse mSppResponseMessage; - @Mock ExchangeCompleteMessage mExchangeCompleteMessage; - @Mock SystemInfo mSystemInfo; - @Mock TelephonyManager mTelephonyManager; - @Mock TelephonyManager mDataTelephonyManager; - @Mock SppCommand mSppCommand; - @Mock BrowserUri mBrowserUri; - @Mock PpsMoData mPpsMoData; - @Mock RedirectListener mRedirectListener; - @Mock PackageManager mPackageManager; - @Mock PasspointConfiguration mPasspointConfiguration; - @Mock X509Certificate mX509Certificate; - @Mock SoapSerializationEnvelope mSoapSerializationEnvelope; - @Mock WifiMetrics mWifiMetrics; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mTestUrl = new URL(TEST_REDIRECT_URL); - mSession = ExtendedMockito.mockitoSession().mockStatic( - RedirectListener.class).mockStatic(PpsMoParser.class).mockStatic( - UpdateResponseMessage.class).startMocking(); - when(RedirectListener.createInstance(mLooper.getLooper())).thenReturn(mRedirectListener); - when(mRedirectListener.getServerUrl()).thenReturn(new URL(TEST_REDIRECT_URL)); - when(mRedirectListener.startServer( - any(RedirectListener.RedirectCallback.class), any(Handler.class))).thenReturn(true); - when(mRedirectListener.isAlive()).thenReturn(true); - when(mWifiManager.isWifiEnabled()).thenReturn(true); - when(mObjectFactory.makeOsuNetworkConnection(any(Context.class))) - .thenReturn(mOsuNetworkConnection); - when(mObjectFactory.makeOsuServerConnection()).thenReturn(mOsuServerConnection); - when(mWfaKeyStore.get()).thenReturn(mKeyStore); - when(mObjectFactory.makeWfaKeyStore()).thenReturn(mWfaKeyStore); - when(mObjectFactory.getSSLContext(any(String.class))).thenReturn(mTlsContext); - when(mObjectFactory.getSystemInfo(any(Context.class), any(WifiNative.class))).thenReturn( - mSystemInfo); - doReturn(mWifiManager).when(mContext) - .getSystemService(eq(Context.WIFI_SERVICE)); - mPasspointProvisioner = new PasspointProvisioner(mContext, mWifiNative, mObjectFactory, - mPasspointManager, mWifiMetrics); - when(mOsuNetworkConnection.connect(any(WifiSsid.class), any(), any())).thenReturn(true); - when(mOsuServerConnection.connect(any(URL.class), any(Network.class))).thenReturn(true); - when(mOsuServerConnection.validateProvider( - anyMap())).thenReturn(true); - when(mOsuServerConnection.canValidateServer()).thenReturn(true); - mPasspointProvisioner.enableVerboseLogging(1); - mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true); - mDelegate = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - mDelegate.init(PasspointProvisioningTestUtil.createFakeKeyStore()); - when(mObjectFactory.getTrustManagerFactory(any(KeyStore.class))).thenReturn(mDelegate); - when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager); - when(mSystemInfo.getDeviceModel()).thenReturn(TEST_MODEL); - when(mSystemInfo.getLanguage()).thenReturn(TEST_LANGUAGE); - when(mSystemInfo.getDeviceId()).thenReturn(TEST_DEV_ID); - when(mSystemInfo.getDeviceManufacturer()).thenReturn(TEST_MANUFACTURER); - when(mSystemInfo.getMacAddress(any(String.class))).thenReturn(TEST_MAC_ADDR); - when(mSystemInfo.getSoftwareVersion()).thenReturn(TEST_SW_VERSION); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(TEST_IMSI); - - when(mExchangeCompleteMessage.getMessageType()).thenReturn( - SppResponseMessage.MessageType.EXCHANGE_COMPLETE); - when(mExchangeCompleteMessage.getStatus()).thenReturn( - SppConstants.SppStatus.EXCHANGE_COMPLETE); - when(mExchangeCompleteMessage.getSessionID()).thenReturn(TEST_SESSION_ID); - when(mExchangeCompleteMessage.getError()).thenReturn(SppConstants.INVALID_SPP_CONSTANT); - when(mSppResponseMessage.getMessageType()).thenReturn( - SppResponseMessage.MessageType.POST_DEV_DATA_RESPONSE); - when(mSppResponseMessage.getSppCommand()).thenReturn(mSppCommand); - when(mSppResponseMessage.getSessionID()).thenReturn(TEST_SESSION_ID); - when(mSppCommand.getSppCommandId()).thenReturn(SppCommand.CommandId.EXEC); - when(mSppCommand.getExecCommandId()).thenReturn(SppCommand.ExecCommandId.BROWSER); - when(mSppCommand.getCommandData()).thenReturn(mBrowserUri); - when(mBrowserUri.getUri()).thenReturn(TEST_URL); - when(mOsuServerConnection.exchangeSoapMessage( - any(SoapSerializationEnvelope.class))).thenReturn(true); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - ResolveInfo resolveInfo = new ResolveInfo(); - resolveInfo.activityInfo = new ActivityInfo(); - resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); - resolveInfo.activityInfo.name = OSU_APP_NAME; - resolveInfo.activityInfo.applicationInfo.packageName = OSU_APP_PACKAGE; - when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())) - .thenReturn(Arrays.asList(resolveInfo)); - - Map<String, byte[]> trustCertInfo = new HashMap<>(); - trustCertInfo.put("https://testurl.com", "testData".getBytes()); - when(mPasspointConfiguration.getTrustRootCertList()).thenReturn(trustCertInfo); - when(mPasspointConfiguration.getCredential()).thenReturn(new Credential()); - HomeSp homeSp = new HomeSp(); - homeSp.setFqdn("test.com"); - when(mPasspointConfiguration.getHomeSp()).thenReturn(homeSp); - - UpdateParameter updateParameter = new UpdateParameter(); - updateParameter.setTrustRootCertUrl("https://testurl.com"); - updateParameter.setTrustRootCertSha256Fingerprint("testData".getBytes()); - when(mPasspointConfiguration.getSubscriptionUpdate()).thenReturn(updateParameter); - when(mOsuServerConnection.retrieveTrustRootCerts(anyMap())).thenReturn(true); - lenient().when(PpsMoParser.parseMoText(isNull())).thenReturn(mPasspointConfiguration); - - when(mPasspointConfiguration.validateForR2()).thenReturn(true); - lenient().when(UpdateResponseMessage.serializeToSoapEnvelope(any(String.class), - any(Boolean.class))).thenReturn(mSoapSerializationEnvelope); - } - - @After - public void cleanUp() { - mSession.finishMocking(); - } - - private void initAndStartProvisioning() { - mPasspointProvisioner.init(mLooper.getLooper()); - verify(mOsuNetworkConnection).init(mHandlerCaptor.capture()); - - mHandler = mHandlerCaptor.getValue(); - assertEquals(mHandler.getLooper(), mLooper.getLooper()); - - mLooper.dispatchAll(); - - assertTrue(mPasspointProvisioner.startSubscriptionProvisioning( - TEST_UID, mOsuProvider, mCallback)); - // Runnable posted by the provisioning start request - assertEquals(mHandler.hasMessagesOrCallbacks(), true); - mLooper.dispatchAll(); - assertEquals(mHandler.hasMessagesOrCallbacks(), false); - - verify(mOsuNetworkConnection, atLeastOnce()) - .setEventCallback(mOsuNetworkCallbacksCaptor.capture()); - mOsuNetworkCallbacks = mOsuNetworkCallbacksCaptor.getAllValues().get(0); - verify(mOsuServerConnection, atLeastOnce()) - .setEventCallback(mOsuServerCallbacksCaptor.capture()); - mOsuServerCallbacks = mOsuServerCallbacksCaptor.getAllValues().get(0); - } - - private void stopAfterStep(int finalStep) throws RemoteException { - for (int step = STEP_INIT; step <= finalStep; step++) { - if (step == STEP_INIT) { - initAndStartProvisioning(); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_AP_CONNECTING); - } else if (step == STEP_AP_CONNECT) { - // Connection to OSU AP successful - mOsuNetworkCallbacks.onConnected(mNetwork); - - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_AP_CONNECTED); - } else if (step == STEP_SERVER_CONNECT) { - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_SERVER_CONNECTING); - } else if (step == STEP_WAIT_FOR_REDIRECT_RESPONSE) { - // Server validation passed - mOsuServerCallbacks.onServerValidationStatus(mOsuServerCallbacks.getSessionId(), - true); - mLooper.dispatchAll(); - - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_SERVER_VALIDATED); - - // Server connection succeeded - mOsuServerCallbacks.onServerConnectionStatus(mOsuServerCallbacks.getSessionId(), - true); - mLooper.dispatchAll(); - - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_SERVER_CONNECTED); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_INIT_SOAP_EXCHANGE); - - // Received a first soapMessageResponse - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - mSppResponseMessage); - mLooper.dispatchAll(); - - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE); - verify(mRedirectListener, atLeastOnce()) - .startServer(mOnRedirectReceivedArgumentCaptor.capture(), - any(Handler.class)); - mRedirectReceivedListener = mOnRedirectReceivedArgumentCaptor.getValue(); - verifyNoMoreInteractions(mCallback); - } else if (step == STEP_WAIT_FOR_SECOND_SOAP_RESPONSE) { - when(mSppCommand.getSppCommandId()).thenReturn(SppCommand.CommandId.ADD_MO); - when(mSppCommand.getExecCommandId()).thenReturn(-1); - when(mSppCommand.getCommandData()).thenReturn(mPpsMoData); - - // Received HTTP redirect response. - mRedirectReceivedListener.onRedirectReceived(); - mLooper.dispatchAll(); - - verify(mRedirectListener, atLeastOnce()).stopServer(any(Handler.class)); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_REDIRECT_RESPONSE_RECEIVED); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_SECOND_SOAP_EXCHANGE); - - // Received a second soapMessageResponse - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - mSppResponseMessage); - mLooper.dispatchAll(); - } else if (step == STEP_WAIT_FOR_THIRD_SOAP_RESPONSE) { - ExtendedMockito.verify( - () -> UpdateResponseMessage.serializeToSoapEnvelope(eq(TEST_SESSION_ID), - eq(false))); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_THIRD_SOAP_EXCHANGE); - - // Received a third soapMessageResponse - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - mExchangeCompleteMessage); - mLooper.dispatchAll(); - } else if (step == STEP_WAIT_FOR_TRUST_ROOT_CERTS) { - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS); - - Map<Integer, List<X509Certificate>> trustRootCertificates = new HashMap<>(); - List<X509Certificate> certificates = new ArrayList<>(); - certificates.add(mX509Certificate); - trustRootCertificates.put(OsuServerConnection.TRUST_CERT_TYPE_AAA, certificates); - trustRootCertificates.put(OsuServerConnection.TRUST_CERT_TYPE_REMEDIATION, - certificates); - - // Received trust root CA certificates - mOsuServerCallbacks.onReceivedTrustRootCertificates( - mOsuServerCallbacks.getSessionId(), trustRootCertificates); - mLooper.dispatchAll(); - verify(mCallback).onProvisioningComplete(); - // Verify WifiMetrics for provisioning success. - verify(mWifiMetrics).incrementPasspointProvisionSuccess(); - } - } - } - - /** - * Verifies provisioning failure state. - */ - private void verifyProvisioningFailure(int failureCode) throws RemoteException { - verify(mCallback).onProvisioningFailure(failureCode); - // Verify WifiMetrics for provisioning failure. - // incrementPasspointProvisionFailure() has to be called only once - // and with correct failureCode - verify(mWifiMetrics).incrementPasspointProvisionFailure(failureCode); - verify(mWifiMetrics).incrementPasspointProvisionFailure(anyInt()); - } - - /** - * Verifies initialization and starting subscription provisioning flow. - */ - @Test - public void verifyInitAndStartProvisioning() { - initAndStartProvisioning(); - } - - /** - * Verifies Provisioning flow is aborted when OSU server is not possible for the flow. - */ - @Test - public void verifyProvisioningUnavailable() throws RemoteException { - when(mOsuServerConnection.canValidateServer()).thenReturn(false); - - initAndStartProvisioning(); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE); - } - - /** - * Verifies Provisioning flow is aborted when an {@link OsuProvider} is not found for the flow. - */ - @Test - public void verifyOsuProviderNotFoundForProvisioning() throws RemoteException { - mOsuProvider.setOsuSsid(null); - when(mWifiManager.getScanResults()).thenReturn(null); - - initAndStartProvisioning(); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_OSU_PROVIDER_NOT_FOUND); - } - - /** - * Verifies Provisioning flow is started with the OSU SSID of AP that has strongest signal - * strength. - */ - @Test - public void verifySelectBestOsuProviderForProvisioning() throws RemoteException { - List<ScanResult> scanResults = new ArrayList<>(); - - // Passpoint AP - ScanResult scanResult = new ScanResult(); - scanResult.SSID = TEST_SSID; - scanResult.BSSID = TEST_BSSID_STRING; - scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK; - scanResult.level = -70; - scanResults.add(scanResult); - - // Non-Passpoint AP - ScanResult scanResult2 = new ScanResult(); - scanResult2.SSID = TEST_SSID2; - scanResult2.BSSID = TEST_BSSID_STRING2; - scanResult2.flags = 0; - scanResult2.level = -50; - scanResults.add(scanResult2); - - // Passpoint AP - ScanResult scanResult3 = new ScanResult(); - scanResult3.SSID = TEST_SSID3; - scanResult3.BSSID = TEST_BSSID_STRING3; - scanResult3.flags = ScanResult.FLAG_PASSPOINT_NETWORK; - scanResult3.level = -60; - scanResults.add(scanResult3); - - when(mWifiManager.getScanResults()).thenReturn(scanResults); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public Map<Constants.ANQPElementType, ANQPElement> answer(ScanResult scanResult) { - Map<Constants.ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); - if (scanResult.SSID.equals(TEST_SSID)) { - anqpElementMap.put(Constants.ANQPElementType.HSOSUProviders, - TEST_OSU_PROVIDERS_ELEMENT); - } else if (scanResult.SSID.equals(TEST_SSID3)) { - anqpElementMap.put(Constants.ANQPElementType.HSOSUProviders, - TEST_OSU_PROVIDERS3_ELEMENT); - } - return anqpElementMap; - } - }).when(mPasspointManager).getANQPElements(any(ScanResult.class)); - OsuProviderInfo info = OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO; - mOsuProvider = new OsuProvider((WifiSsid) null, info.getFriendlyNames(), - info.getServiceDescription(), - info.getServerUri(), - info.getNetworkAccessIdentifier(), info.getMethodList()); - - stopAfterStep(STEP_INIT); - ArgumentCaptor<WifiSsid> wifiSsidArgumentCaptor = ArgumentCaptor.forClass(WifiSsid.class); - - verify(mOsuNetworkConnection, atLeastOnce()).connect(wifiSsidArgumentCaptor.capture(), - any(String.class), any(String.class)); - assertEquals(TEST_OSU_SSID3, wifiSsidArgumentCaptor.getValue()); - } - - /** - * Verifies existing provisioning flow is aborted before starting another one. - */ - @Test - public void verifyProvisioningAbort() throws RemoteException { - initAndStartProvisioning(); - - IProvisioningCallback mCallback2 = mock(IProvisioningCallback.class); - assertTrue(mPasspointProvisioner.startSubscriptionProvisioning( - TEST_UID, mOsuProvider, mCallback2)); - mLooper.dispatchAll(); - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - } - - /** - * Verifies existing provisioning flow is aborted when failing to create an instance of {@link - * RedirectListener}. - */ - @Test - public void verifyRedirectStartFailure() throws RemoteException { - when(RedirectListener.createInstance(mLooper.getLooper())).thenReturn(null); - mPasspointProvisioner.init(mLooper.getLooper()); - verify(mOsuNetworkConnection).init(mHandlerCaptor.capture()); - - mHandler = mHandlerCaptor.getValue(); - assertEquals(mHandler.getLooper(), mLooper.getLooper()); - - mLooper.dispatchAll(); - - assertTrue(mPasspointProvisioner.startSubscriptionProvisioning( - TEST_UID, mOsuProvider, mCallback)); - - mLooper.dispatchAll(); - - // Since creating an instance of RedirectListener, directly move to FAILED_STATE - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER); - - // Failure case, no more runnable posted - verifyNoMoreInteractions(mCallback); - - } - - /** - * Verifies that if connection attempt to OSU AP fails, corresponding error callback is invoked. - */ - @Test - public void verifyConnectAttemptFailure() throws RemoteException { - when(mOsuNetworkConnection.connect(any(WifiSsid.class), any(), any())).thenReturn(false); - initAndStartProvisioning(); - - // Since connection attempt fails, directly move to FAILED_STATE - verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION); - // Failure case, no more runnables posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that after connection attempt succeeds and a network disconnection occurs, the - * corresponding failure callback is invoked. - */ - @Test - public void verifyConnectAttemptedAndConnectionFailed() throws RemoteException { - stopAfterStep(STEP_INIT); - - // state expected is WAITING_TO_CONNECT - verify(mCallback).onProvisioningStatus(ProvisioningCallback.OSU_STATUS_AP_CONNECTING); - // Connection to OSU AP fails - mOsuNetworkCallbacks.onDisconnected(); - - // Move to failed state - verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION); - // Failure case, no more runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that a connection drop is reported via callback. - */ - @Test - public void verifyConnectionDrop() throws RemoteException { - stopAfterStep(STEP_SERVER_CONNECT); - - // Disconnect received - mOsuNetworkCallbacks.onDisconnected(); - - // Move to failed state - verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION); - // No more callbacks, Osu server validation not initiated - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that Wifi Disable while provisioning is communicated as provisioning failure - */ - @Test - public void verifyFailureDueToWifiDisable() throws RemoteException { - stopAfterStep(STEP_SERVER_CONNECT); - - // Wifi disabled notification - mOsuNetworkCallbacks.onWifiDisabled(); - - // Wifi Disable is processed first and move to failed state - verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION); - // OSU server connection event is not handled - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the right provisioning callbacks are invoked as the provisioner connects - * to OSU AP and OSU server and that invalid server URL generates the right error callback. - */ - @Test - public void verifyInvalidOsuServerURL() throws RemoteException { - mOsuProvider = PasspointProvisioningTestUtil.generateInvalidServerUrlOsuProvider(); - initAndStartProvisioning(); - - // Attempting to connect to OSU server fails due to invalid server URL, move to failed state - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_SERVER_URL_INVALID); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the right provisioning callbacks are invoked as the provisioner progresses - * to associating with the OSU AP and connection to OSU server fails. - */ - @Test - public void verifyServerConnectionFailure() throws RemoteException { - when(mOsuServerConnection.connect(any(URL.class), any(Network.class))).thenReturn(false); - stopAfterStep(STEP_AP_CONNECT); - - // Connection to OSU Server fails, move to failed state - verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the right provisioning callbacks are invoked as the provisioner is unable - * to validate the OSU Server - */ - @Test - public void verifyServerValidationFailure() throws RemoteException { - stopAfterStep(STEP_SERVER_CONNECT); - - // OSU Server validation of certs fails - mOsuServerCallbacks.onServerValidationStatus(mOsuServerCallbacks.getSessionId(), false); - mLooper.dispatchAll(); - - // Server validation failure, move to failed state - verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the status for server validation from a previous session is ignored - * by the provisioning state machine - */ - @Test - public void verifyServerValidationFailurePreviousSession() throws RemoteException { - stopAfterStep(STEP_SERVER_CONNECT); - - // OSU Server validation of certs failure but from a previous session - mOsuServerCallbacks.onServerValidationStatus(mOsuServerCallbacks.getSessionId() - 1, false); - // Runnable posted by server callback - assertTrue(mHandler.hasMessagesOrCallbacks()); - mLooper.dispatchAll(); - - // Server validation failure, move to failed state - verify(mCallback, never()).onProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the status for server validation from a previous session is ignored - * by the provisioning state machine - */ - @Test - public void verifyServerValidationSuccessPreviousSession() throws RemoteException { - stopAfterStep(STEP_SERVER_CONNECT); - - // OSU Server validation success but from a previous session - mOsuServerCallbacks.onServerValidationStatus(mOsuServerCallbacks.getSessionId() - 1, true); - // Runnable posted by server callback - assertTrue(mHandler.hasMessagesOrCallbacks()); - mLooper.dispatchAll(); - - // Ignore the validation complete event because of different session id. - verify(mCallback, never()).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_SERVER_VALIDATED); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the right provisioning callbacks are invoked when provisioner is unable - * to validate the OSU provider - */ - @Test - public void verifyProviderVerificationFailure() throws RemoteException { - when(mOsuServerConnection.validateProvider( - anyMap())).thenReturn(false); - stopAfterStep(STEP_SERVER_CONNECT); - - // Wait for OSU server validation callback - mOsuServerCallbacks.onServerValidationStatus(mOsuServerCallbacks.getSessionId(), true); - // Runnable posted by server callback - assertTrue(mHandler.hasMessagesOrCallbacks()); - // OSU server validation success posts another runnable to validate the provider - mLooper.dispatchAll(); - - // Provider validation failure is processed next, move to failed state - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the right provisioning callbacks are invoked when SOAP message exchange fails. - */ - @Test - public void verifyExchangingSoapMessageFailure() throws RemoteException { - // Fail to exchange the SOAP message - when(mOsuServerConnection.exchangeSoapMessage( - any(SoapSerializationEnvelope.class))).thenReturn(false); - stopAfterStep(STEP_SERVER_CONNECT); - - // Server validation passed - mOsuServerCallbacks.onServerValidationStatus(mOsuServerCallbacks.getSessionId(), true); - mLooper.dispatchAll(); - - verify(mCallback).onProvisioningStatus(ProvisioningCallback.OSU_STATUS_SERVER_VALIDATED); - - // Server connection passed - mOsuServerCallbacks.onServerConnectionStatus(mOsuServerCallbacks.getSessionId(), true); - mLooper.dispatchAll(); - - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_SERVER_CONNECTED); - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the right provisioning callbacks are invoked when there is no OSU activity for - * the intent - */ - @Test - public void verifyNoOsuActivityFoundFailure() throws RemoteException { - // There is no activity found for the intent - when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(null); - stopAfterStep(STEP_SERVER_CONNECT); - - // Server validation passed - mOsuServerCallbacks.onServerValidationStatus(mOsuServerCallbacks.getSessionId(), true); - mLooper.dispatchAll(); - - verify(mCallback).onProvisioningStatus(ProvisioningCallback.OSU_STATUS_SERVER_VALIDATED); - - // Server connection passed - mOsuServerCallbacks.onServerConnectionStatus(mOsuServerCallbacks.getSessionId(), true); - mLooper.dispatchAll(); - - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_SERVER_CONNECTED); - verify(mCallback).onProvisioningStatus(ProvisioningCallback.OSU_STATUS_INIT_SOAP_EXCHANGE); - - // Received soapMessageResponse - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - mSppResponseMessage); - mLooper.dispatchAll(); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_NO_OSU_ACTIVITY_FOUND); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the right provisioning callbacks are invoked when timeout occurs for HTTP - * redirect response. - */ - @Test - public void verifyRedirectResponseTimeout() throws RemoteException { - stopAfterStep(STEP_WAIT_FOR_REDIRECT_RESPONSE); - - // Timed out for HTTP redirect response. - mRedirectReceivedListener.onRedirectTimedOut(); - mLooper.dispatchAll(); - - verify(mRedirectListener, atLeastOnce()).stopServer(any(Handler.class)); - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER); - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } - - /** - * Verifies that the right provisioning callbacks are invoked when a command of a second soap - * response {@link PostDevDataResponse} is not for ADD MO command. - */ - @Test - public void verifyNotAddMoCommandFailureForSecondSoapResponse() throws RemoteException { - stopAfterStep(STEP_WAIT_FOR_REDIRECT_RESPONSE); - - // Received HTTP redirect response. - mRedirectReceivedListener.onRedirectReceived(); - mLooper.dispatchAll(); - - verify(mRedirectListener, atLeastOnce()).stopServer(any(Handler.class)); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_REDIRECT_RESPONSE_RECEIVED); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_SECOND_SOAP_EXCHANGE); - - // Received a second soapMessageResponse - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - mSppResponseMessage); - mLooper.dispatchAll(); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_UNEXPECTED_COMMAND_TYPE); - } - - /** - * Verifies that the right provisioning callbacks are invoked when a message of a third soap - * response {@link ExchangeCompleteMessage} has an error property. - */ - @Test - public void verifyHandlingErrorPropertyInThirdSoapResponse() throws RemoteException { - when(mExchangeCompleteMessage.getError()).thenReturn( - SppConstants.SppError.PROVISIONING_FAILED); - stopAfterStep(STEP_WAIT_FOR_SECOND_SOAP_RESPONSE); - - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_THIRD_SOAP_EXCHANGE); - - // Received a third soapMessageResponse - mOsuServerCallbacks.onReceivedSoapMessage(mOsuServerCallbacks.getSessionId(), - mExchangeCompleteMessage); - mLooper.dispatchAll(); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED); - } - - /** - * Verifies that the {@link UpdateResponseMessage#serializeToSoapEnvelope(String, boolean)} is - * invoked with right arguments when a PPS-MO xml received from server is not valid in terms of - * schema of PPS MO. - */ - @Test - public void verifyHandlingInvalidPpsMoForSoapResponse() throws RemoteException { - when(mPasspointConfiguration.validateForR2()).thenReturn(false); - stopAfterStep(STEP_WAIT_FOR_SECOND_SOAP_RESPONSE); - - ExtendedMockito.verify( - () -> UpdateResponseMessage.serializeToSoapEnvelope(eq(TEST_SESSION_ID), eq(true))); - } - - /** - * Verifies that the right provisioning callbacks are invoked when failing to call {@link - * OsuServerConnection#retrieveTrustRootCerts(Map)}. - */ - @Test - public void verifyHandlingErrorForCallingRetrieveTrustRootCerts() - throws RemoteException { - when(mOsuServerConnection.retrieveTrustRootCerts(anyMap())).thenReturn(false); - stopAfterStep(STEP_WAIT_FOR_THIRD_SOAP_RESPONSE); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION); - } - - /** - * Verifies that the right provisioning callbacks are invoked when a new {@link - * PasspointConfiguration} is failed to add. - */ - @Test - public void verifyHandlingErrorForAddingPasspointConfiguration() throws RemoteException { - doThrow(IllegalArgumentException.class).when( - mWifiManager).addOrUpdatePasspointConfiguration(any(PasspointConfiguration.class)); - stopAfterStep(STEP_WAIT_FOR_THIRD_SOAP_RESPONSE); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS); - - Map<Integer, List<X509Certificate>> trustRootCertificates = new HashMap<>(); - List<X509Certificate> certificates = new ArrayList<>(); - certificates.add(mX509Certificate); - trustRootCertificates.put(OsuServerConnection.TRUST_CERT_TYPE_AAA, certificates); - trustRootCertificates.put(OsuServerConnection.TRUST_CERT_TYPE_REMEDIATION, certificates); - - // Received trust root CA certificates - mOsuServerCallbacks.onReceivedTrustRootCertificates( - mOsuServerCallbacks.getSessionId(), trustRootCertificates); - mLooper.dispatchAll(); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION); - } - - /** - * Verifies that the right provisioning callbacks are invoked when it is failed to retrieve - * trust root certificates from the URLs provided. - */ - @Test - public void verifyHandlingEmptyTrustRootCertificateRetrieved() throws RemoteException { - stopAfterStep(STEP_WAIT_FOR_THIRD_SOAP_RESPONSE); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS); - - // Empty trust root certificates. - Map<Integer, List<X509Certificate>> trustRootCertificates = new HashMap<>(); - - // Received trust root CA certificates - mOsuServerCallbacks.onReceivedTrustRootCertificates( - mOsuServerCallbacks.getSessionId(), trustRootCertificates); - mLooper.dispatchAll(); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES); - } - - /** - * Verifies that the right provisioning callbacks are invoked when it is failed to retrieve - * trust root certificate for remediation server from the URLs provided. - */ - @Test - public void verifyHandlingEmptyRemediationTrustRootCertificateRetrieved() - throws RemoteException { - stopAfterStep(STEP_WAIT_FOR_THIRD_SOAP_RESPONSE); - verify(mCallback).onProvisioningStatus( - ProvisioningCallback.OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS); - - // trust root certificates. - Map<Integer, List<X509Certificate>> trustRootCertificates = new HashMap<>(); - List<X509Certificate> certificates = new ArrayList<>(); - certificates.add(mX509Certificate); - - // Add trust root certificate for AAA server - trustRootCertificates.put(OsuServerConnection.TRUST_CERT_TYPE_AAA, certificates); - - // Received trust root CA certificates - mOsuServerCallbacks.onReceivedTrustRootCertificates( - mOsuServerCallbacks.getSessionId(), trustRootCertificates); - mLooper.dispatchAll(); - - verifyProvisioningFailure( - ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES); - } - - /** - * Verifies that the right provisioning callbacks are invoked as the provisioner progresses - * to the end as successful case. - */ - @Test - public void verifyProvisioningFlowForSuccessfulCase() throws RemoteException { - stopAfterStep(STEP_WAIT_FOR_TRUST_ROOT_CERTS); - - // No further runnable posted - verifyNoMoreInteractions(mCallback); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisioningTestUtil.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisioningTestUtil.java deleted file mode 100644 index 10fcd7be6..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisioningTestUtil.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2017 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.server.wifi.hotspot2; - -import android.net.Uri; -import android.net.wifi.WifiSsid; -import android.net.wifi.hotspot2.OsuProvider; -import android.util.Base64; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Helper for creating and populating WifiConfigurations in unit tests. - */ -public class PasspointProvisioningTestUtil { - /** - * These are constants used to generate predefined OsuProvider. - */ - public static final WifiSsid TEST_SSID = - WifiSsid.createFromByteArray("TEST SSID".getBytes(StandardCharsets.UTF_8)); - public static final String TEST_FRIENDLY_NAME = "Friendly Name"; - public static final String TEST_SERVICE_DESCRIPTION = "Dummy Service"; - public static final Uri TEST_SERVER_URI = Uri.parse("https://test.com"); - public static final Uri INVALID_SERVER_URI = Uri.parse("abcd"); - public static final String TEST_NAI = "test.access.com"; - public static final List<Integer> TEST_METHOD_LIST = - Arrays.asList(OsuProvider.METHOD_SOAP_XML_SPP); - - /** - * Construct a {@link android.net.wifi.hotspot2.OsuProvider}. - * - * @param openOsuAP indicates if the OSU AP belongs to an open or OSEN network - * @return the constructed {@link android.net.wifi.hotspot2.OsuProvider} - */ - public static OsuProvider generateOsuProvider(boolean openOsuAP) { - Map<String, String> friendlyNames = new HashMap<>(); - friendlyNames.put("en", TEST_FRIENDLY_NAME); - return generateOsuProviderWithFriendlyName(openOsuAP, friendlyNames); - } - - /** - * Construct a {@link android.net.wifi.hotspot2.OsuProvider} with given friendlyName. - * - * @param openOsuAP indicates if the OSU AP belongs to an open or OSEN network - * @param friendlyNames map of friendly names with language and friendly name in the language - * @return the constructed {@link android.net.wifi.hotspot2.OsuProvider} - */ - public static OsuProvider generateOsuProviderWithFriendlyName(boolean openOsuAP, - Map<String, String> friendlyNames) { - if (openOsuAP) { - return new OsuProvider(TEST_SSID, friendlyNames, - TEST_SERVICE_DESCRIPTION, - TEST_SERVER_URI, null, TEST_METHOD_LIST); - } else { - return new OsuProvider(TEST_SSID, friendlyNames, - TEST_SERVICE_DESCRIPTION, - TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST); - } - } - - /** - * Construct a {@link android.net.wifi.hotspot2.OsuProvider} with invalid server URL - * @return the constructed {@link android.net.wifi.hotspot2.OsuProvider} - */ - public static OsuProvider generateInvalidServerUrlOsuProvider() { - HashMap<String, String> friendlyNameMap = new HashMap<>(); - friendlyNameMap.put("en", TEST_FRIENDLY_NAME); - return new OsuProvider(TEST_SSID, friendlyNameMap, - TEST_SERVICE_DESCRIPTION, INVALID_SERVER_URI, null, TEST_METHOD_LIST); - } - - /** - * Create the fake keyStore for the test. - * - * @return KeyStore that has the TEST_CERTs, null if not processed - */ - public static KeyStore createFakeKeyStore() { - KeyStore keyStore = null; - int index = 0; - try { - keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null, null); - List<X509Certificate> certs = getOsuCertsForTest(); - for (X509Certificate cert : certs) { - keyStore.setCertificateEntry(String.format("%d", index), cert); - index++; - } - } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException - | IOException e) { - e.printStackTrace(); - } - return keyStore; - } - - /** - * Return a set of OSU server certs to test with - * @return List<X509Certificate> an array of OSU certs - */ - /* package */ static List<X509Certificate> getOsuCertsForTest() { - List<X509Certificate> osuCerts = new ArrayList<X509Certificate>(); - try { - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - for (String certString : TEST_CERTS) { - ByteArrayInputStream bis = new ByteArrayInputStream( - Base64.decode(certString, Base64.DEFAULT)); - Certificate cert = certFactory.generateCertificate(bis); - osuCerts.add((X509Certificate) cert); - } - } catch (CertificateException e) { - e.printStackTrace(); - } - return osuCerts; - } - - private static final String[] TEST_CERTS = { - "MIID8zCCAtugAwIBAgIJAIY3yjv1B5eWMA0GCSqGSIb3DQEBCwUAMIGPMQswCQYD" - + "VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxDzAN" - + "BgNVBAoMBkdvb2dsZTEQMA4GA1UECwwHQW5kcm9pZDETMBEGA1UEAwwKZ29vZ2xl" - + "LmNvbTEjMCEGCSqGSIb3DQEJARYUc29oYW5pcmFvQGdvb2dsZS5jb20wHhcNMTgw" - + "MTEyMDM0NjI3WhcNMTkwMTEyMDM0NjI3WjCBjzELMAkGA1UEBhMCVVMxCzAJBgNV" - + "BAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MQ8wDQYDVQQKDAZHb29nbGUx" - + "EDAOBgNVBAsMB0FuZHJvaWQxEzARBgNVBAMMCmdvb2dsZS5jb20xIzAhBgkqhkiG" - + "9w0BCQEWFHNvaGFuaXJhb0Bnb29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC" - + "AQ8AMIIBCgKCAQEA41IIl6NpaN60XbS/fb0bW8+nWGh8OrHjFTyEOSXAE9W+sxFi" - + "x2ygJxJvOpN0Nj+UFXMDnwIkvq7l0L0kUTAljQh1C1Gm4a2rDYKkMhTNab5uSp1/" - + "X3VDUztIJVn4EKIt5jT9vGTqwvI4Xxd3fmM1/eRHpzR8gRLLs89itulpoHrXiN29" - + "dlD72J2877vo3QktFMo/MiHyWPne5WiU5+qiAw70MflnptzaOCeisCVSYHyvhDtK" - + "xWPgQ9eqG1jHgxOgdOEB6nzJvWY26GzjpEVZlUOBeEvcznmTqrFoM4Q4ANX//F1+" - + "zdNfQPes5fPShMgLp65MAdVJFQKq7o8jVcX+2wIDAQABo1AwTjAdBgNVHQ4EFgQU" - + "467KG5Zzpr4nnURUbOwdr5hoQVkwHwYDVR0jBBgwFoAU467KG5Zzpr4nnURUbOwd" - + "r5hoQVkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAvI9DKIXTrJQi" - + "Gaobr0wnQ1JfpP3oezWHmhFDSwdq3xhFLlxlZOLi3Ay/GwaW3cQfQ8c6xzpbjVNm" - + "uMyNzfVHZjzRoX7Ae9S0uzsYmXuAm3LbD4EDflDDHlYKz97J4nlzPvi/EUxoOmk0" - + "CF2LS9CAsI/AVCOqXne89EK4TwsZ8fSzNv0I2YdA2VFHUqqW2h1uZCG9Mb4gmwGj" - + "bjxrdFAKFlSKxUfrus+BGwjOKwfvvkWLmU4TPqBAPgVLHUBrcdDoIoYW6XAA4Dnd" - + "4eMFTUDmMaUew8K5aGuuj+2fNcOuz+/wy2xL8TkGF/m1Xi1JUbk0Ny/pG3qaznzB" - + "FeODMMYDCg==", - - "MIIC7jCCAdagAwIBAgIJAI0gOVoxJv+kMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV" - + "BAMTC2RvbWFpbjEuY29tMB4XDTE4MDExMzAwMzczOFoXDTE4MDIxMjAwMzczOFow" - + "FjEUMBIGA1UEAxMLZG9tYWluMS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw" - + "ggEKAoIBAQDsIvx1z9iLMuXXjP2/9YEBAMCQ6qC75t5YmqZeCfl2SIjt3Ho2qCRA" - + "Wq5y5ZTSqTTBTMMiDHGAYe+qcP7+4UuyCx60CbhJVn1Maxcrhs3tUEKJlQNqEk4t" - + "I4DONvZjsOX1UxYNvbjMlWf3KZ0rXLusvMjk4VEOxZVvyO4EyJ+K4tMse7OkHBGt" - + "eBATgOqFvOZxy3SaicH36bN5eL6KWHOe0IIGoQ4VLcMrW9hBwSBaO9m95I0ZNAqt" - + "0+84hgJNna6KtPRGfPaHdJfYZ6yqWMtpUr9yz8GRlSY67vieFkB+Qx2WO/En2K25" - + "PM/zVGqmNFpDeATbUmCUDWegNb4XPkJBAgMBAAGjPzA9MAsGA1UdDwQEAwIEMDAT" - + "BgNVHSUEDDAKBggrBgEFBQcDATAZBgNVHREEEjAQgg53d3cuZ29vZ2xlLmNvbTAN" - + "BgkqhkiG9w0BAQsFAAOCAQEAQX+HT2JlCnZ/Zb9hCe8139poDxqkj4ZhYu94OpLH" - + "Y+eRsMY8SA/rHp0fbCiqA4H/IL9GI79HGdcjNChqVH304fvdic97dwXZLOFC/JcO" - + "XXIZs/j1ir6WfezhTdrLHXB+ZYahST2L8fEHeyS+goZFK0XNgdvTe1h2W7qfdn3Z" - + "G4DkdYhFlzXnvSq+YI2SvSArrbw02wg4xZzHwXHsV8sIXuve8KvZzKw0+zP2oj5b" - + "XgkNgi75VBf+dEvA9D6GSJ9uNaUmhlglpiwyeMBhDGYibje1/e4aQYclaarWMkf2" - + "IYatpc/KqB9TWGIAVGLsCcfDbdbIil2AlaoA006SXa1fHA==" - }; -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointXmlUtilsTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointXmlUtilsTest.java deleted file mode 100644 index 233a740f9..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointXmlUtilsTest.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.pps.Credential; -import android.net.wifi.hotspot2.pps.HomeSp; -import android.net.wifi.hotspot2.pps.Policy; -import android.net.wifi.hotspot2.pps.UpdateParameter; -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointXmlUtilsTest}. - */ -@SmallTest -public class PasspointXmlUtilsTest extends WifiBaseTest { - - /** - * Helper function for generating a {@link PasspointConfiguration} for testing the XML - * serialization/deserialization logic. - * - * @return {@link PasspointConfiguration} - * @throws Exception - */ - private PasspointConfiguration createFullPasspointConfiguration() throws Exception { - DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - byte[] certFingerprint = new byte[32]; - Arrays.fill(certFingerprint, (byte) 0x1f); - - PasspointConfiguration config = new PasspointConfiguration(); - config.setUpdateIdentifier(12); - config.setCredentialPriority(99); - - // AAA Server trust root. - Map<String, byte[]> trustRootCertList = new HashMap<>(); - trustRootCertList.put("server1.trust.root.com", certFingerprint); - config.setTrustRootCertList(trustRootCertList); - - // Subscription update. - UpdateParameter subscriptionUpdate = new UpdateParameter(); - subscriptionUpdate.setUpdateIntervalInMinutes(120); - subscriptionUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP); - subscriptionUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER); - subscriptionUpdate.setServerUri("subscription.update.com"); - subscriptionUpdate.setUsername("subscriptionUser"); - subscriptionUpdate.setBase64EncodedPassword("subscriptionPass"); - subscriptionUpdate.setTrustRootCertUrl("subscription.update.cert.com"); - subscriptionUpdate.setTrustRootCertSha256Fingerprint(certFingerprint); - config.setSubscriptionUpdate(subscriptionUpdate); - - // Subscription parameters. - config.setSubscriptionCreationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime()); - config.setSubscriptionExpirationTimeInMillis( - format.parse("2016-03-01T10:00:00Z").getTime()); - config.setSubscriptionType("Gold"); - config.setUsageLimitDataLimit(921890); - config.setUsageLimitStartTimeInMillis(format.parse("2016-12-01T10:00:00Z").getTime()); - config.setUsageLimitTimeLimitInMinutes(120); - config.setUsageLimitUsageTimePeriodInMinutes(99910); - - // HomeSP configuration. - HomeSp homeSp = new HomeSp(); - homeSp.setFriendlyName("Century House"); - homeSp.setFqdn("mi6.co.uk"); - homeSp.setRoamingConsortiumOis(new long[] {0x112233L, 0x445566L}); - homeSp.setIconUrl("icon.test.com"); - Map<String, Long> homeNetworkIds = new HashMap<>(); - homeNetworkIds.put("TestSSID", 0x12345678L); - homeNetworkIds.put("NullHESSID", null); - homeSp.setHomeNetworkIds(homeNetworkIds); - homeSp.setMatchAllOis(new long[] {0x11223344}); - homeSp.setMatchAnyOis(new long[] {0x55667788}); - homeSp.setOtherHomePartners(new String[] {"other.fqdn.com"}); - config.setHomeSp(homeSp); - - // Credential configuration. - Credential credential = new Credential(); - credential.setCreationTimeInMillis(format.parse("2016-01-01T10:00:00Z").getTime()); - credential.setExpirationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime()); - credential.setRealm("shaken.stirred.com"); - credential.setCheckAaaServerCertStatus(true); - Credential.UserCredential userCredential = new Credential.UserCredential(); - userCredential.setUsername("james"); - userCredential.setPassword("Ym9uZDAwNw=="); - userCredential.setMachineManaged(true); - userCredential.setSoftTokenApp("TestApp"); - userCredential.setAbleToShare(true); - userCredential.setEapType(21); - userCredential.setNonEapInnerMethod("MS-CHAP-V2"); - credential.setUserCredential(userCredential); - Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); - certCredential.setCertType("x509v3"); - certCredential.setCertSha256Fingerprint(certFingerprint); - credential.setCertCredential(certCredential); - Credential.SimCredential simCredential = new Credential.SimCredential(); - simCredential.setImsi("imsi"); - simCredential.setEapType(24); - credential.setSimCredential(simCredential); - config.setCredential(credential); - - // Policy configuration. - Policy policy = new Policy(); - List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>(); - Policy.RoamingPartner partner1 = new Policy.RoamingPartner(); - partner1.setFqdn("test1.fqdn.com"); - partner1.setFqdnExactMatch(true); - partner1.setPriority(127); - partner1.setCountries("us,fr"); - Policy.RoamingPartner partner2 = new Policy.RoamingPartner(); - partner2.setFqdn("test2.fqdn.com"); - partner2.setFqdnExactMatch(false); - partner2.setPriority(200); - partner2.setCountries("*"); - preferredRoamingPartnerList.add(partner1); - preferredRoamingPartnerList.add(partner2); - policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList); - policy.setMinHomeDownlinkBandwidth(23412); - policy.setMinHomeUplinkBandwidth(9823); - policy.setMinRoamingDownlinkBandwidth(9271); - policy.setMinRoamingUplinkBandwidth(2315); - policy.setExcludedSsidList(new String[] {"excludeSSID"}); - Map<Integer, String> requiredProtoPortMap = new HashMap<>(); - requiredProtoPortMap.put(12, "34,92,234"); - policy.setRequiredProtoPortMap(requiredProtoPortMap); - policy.setMaximumBssLoadValue(23); - UpdateParameter policyUpdate = new UpdateParameter(); - policyUpdate.setUpdateIntervalInMinutes(120); - policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM); - policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP); - policyUpdate.setServerUri("policy.update.com"); - policyUpdate.setUsername("updateUser"); - policyUpdate.setBase64EncodedPassword("updatePass"); - policyUpdate.setTrustRootCertUrl("update.cert.com"); - policyUpdate.setTrustRootCertSha256Fingerprint(certFingerprint); - policy.setPolicyUpdate(policyUpdate); - config.setPolicy(policy); - return config; - } - - /** - * Verify the serialization and deserialization logic of a {@link PasspointConfiguration}. - * - * 1. Serialize the test config to a XML block - * 2. Deserialize the XML block to a {@link PasspointConfiguration} - * 3. Verify that the deserialized config is the same as the test config - * - * @param testConfig The configuration to used for testing - * @throws Exception - */ - private void serializeAndDeserializePasspointConfiguration(PasspointConfiguration testConfig) - throws Exception { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - PasspointXmlUtils.serializePasspointConfiguration(out, testConfig); - out.flush(); - - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = - new ByteArrayInputStream(outputStream.toByteArray()); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - - PasspointConfiguration deserializedConfig = - PasspointXmlUtils.deserializePasspointConfiguration(in, in.getDepth()); - assertEquals(testConfig, deserializedConfig); - } - - /** - * Verify that the serialization and deserialization logic for a full - * {@link PasspointConfiguration} (all fields are set) works as expected. - * - * @throws Exception - */ - @Test - public void serializeAndDeserializeFullPasspointConfiguration() throws Exception { - serializeAndDeserializePasspointConfiguration(createFullPasspointConfiguration()); - } - - /** - * Verify that the serialization and deserialization logic for an empty - * {@link PasspointConfiguration} works as expected. - * - * @throws Exception - */ - @Test - public void serializeAndDeserializeEmptyPasspointConfiguration() throws Exception { - serializeAndDeserializePasspointConfiguration(new PasspointConfiguration()); - } - - /** - * Verify that a XmlPullParserException will be thrown when deserialize a XML block - * for a PasspointConfiguraiton containing an unknown tag. - * - * @throws Exception - */ - @Test(expected = XmlPullParserException.class) - public void deserializePasspointConfigurationWithUnknownTag() throws Exception { - String xmlStr = "<UnknownTag>\n" - + "</UnknownTag>\n"; - final XmlPullParser in = Xml.newPullParser(); - final ByteArrayInputStream inputStream = - new ByteArrayInputStream(xmlStr.getBytes(StandardCharsets.UTF_8)); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - PasspointXmlUtils.deserializePasspointConfiguration(in, in.getDepth()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/ServiceProviderVerifierTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/ServiceProviderVerifierTest.java deleted file mode 100644 index fc4611af3..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/ServiceProviderVerifierTest.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2018 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.server.wifi.hotspot2; - -import static com.android.server.wifi.hotspot2.ServiceProviderVerifier - .ID_WFA_OID_HOTSPOT_FRIENDLYNAME; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.DERTaggedObject; -import org.bouncycastle.asn1.DERUTF8String; -import org.bouncycastle.asn1.x509.GeneralName; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import java.security.cert.CertificateParsingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -/** - * Unit tests for {@link ServiceProviderVerifier}. - */ -@SmallTest -public class ServiceProviderVerifierTest extends WifiBaseTest { - private List<List<?>> mNewNames; - private static final String LOCAL_HOST_NAME = "localhost"; - private static final byte[] LOCAL_HOST_ADDRESS = {127, 0, 0, 1}; - private static final String TEST_FRIENDLY_NAME = "Boingo"; - private static final String TEST_LANGUAGE = "eng"; - private static final Locale TEST_LOCALE = new Locale.Builder().setLanguage( - TEST_LANGUAGE).build(); - private static final Pair<Locale, String> EXPECTED_RESULT = Pair.create(TEST_LOCALE, - TEST_FRIENDLY_NAME); - private static final ASN1ObjectIdentifier WFA_OID_HOTSPOT_FRIENDLYNAME = - (new ASN1ObjectIdentifier(ID_WFA_OID_HOTSPOT_FRIENDLYNAME)); - @Mock - private X509Certificate mX509Certificate; - - /**Sets up test. */ - @Before - public void setUp() throws Exception { - initMocks(this); - mNewNames = new ArrayList<>(); - } - - /** - * Verify that getProviderNames should return empty List in case providerCert is null. - */ - @Test - public void testNullForProviderCertShouldReturnEmptyList() { - assertTrue(ServiceProviderVerifier.getProviderNames(null).isEmpty()); - } - - /** - * Verify that getProviderNames should return empty List in case providerCert doesn't have - * SubjectAltName entry - */ - @Test - public void testNullFromgetSubjectAlternativeNamesShouldReturnEmptyList() throws Exception { - when(mX509Certificate.getSubjectAlternativeNames()).thenReturn(null); - assertTrue(ServiceProviderVerifier.getProviderNames(mX509Certificate).isEmpty()); - } - - /** - * Verify that getProviderNames should return empty List in case providerCert return empty list - * for SubjectAltName entry - */ - @Test - public void testEmptyListFromGetSubjectAlternativeNamesShouldReturnEmptyList() - throws Exception { - when(mX509Certificate.getSubjectAlternativeNames()).thenReturn(Collections.emptySet()); - assertTrue(ServiceProviderVerifier.getProviderNames(mX509Certificate).isEmpty()); - } - - /** - * Verify that getProviderNames should return empty List in case calling - * getSubjectAlternativeNames() throws the CertificateParsingException. - */ - @Test - public void testExceptionFromGetSubjectAlternativeNamesShouldReturnEmptyList() - throws Exception { - doThrow(new CertificateParsingException()).when( - mX509Certificate).getSubjectAlternativeNames(); - - assertTrue(ServiceProviderVerifier.getProviderNames(mX509Certificate).isEmpty()); - } - - /** - * Verify that getProviderNames should return empty List in case the subjectAlternativeNames - * doesn't comply with the otherName sequence - */ - @Test - public void testNonOtherNameFromGetSubjectAlternativeNamesShouldReturnEmptyList() - throws Exception { - mNewNames.add(makeAltNames(new GeneralName(GeneralName.dNSName, LOCAL_HOST_NAME), "DER")); - mNewNames.add( - makeAltNames(new GeneralName(GeneralName.iPAddress, - new DEROctetString(LOCAL_HOST_ADDRESS)), "DER")); - when(mX509Certificate.getSubjectAlternativeNames()).thenReturn( - Collections.unmodifiableCollection(mNewNames)); - - assertTrue(ServiceProviderVerifier.getProviderNames(mX509Certificate).isEmpty()); - } - - /** - * Verify that getProviderNames should return empty List in case the subjectAlternativeNames - * returns the result that has only one element in the list. - */ - @Test - public void testInvalidFormatFromGetSubjectAlternativeNamesShouldReturnEmptyList() - throws Exception { - // Create a list that has one element as result for getSubjectAlternativeNames() - // to violate the expected format that has two elements in a list. - List<Object> nameEntry = new ArrayList<>(1); - nameEntry.add(Integer.valueOf(4)); - mNewNames.add(nameEntry); - when(mX509Certificate.getSubjectAlternativeNames()).thenReturn( - Collections.unmodifiableCollection(mNewNames)); - - assertTrue(ServiceProviderVerifier.getProviderNames(mX509Certificate).isEmpty()); - } - - /** - * Verify that getProviderNames should return a List that has a result in case the - * subjectAlternativeNames has valid friendly name for service provider. - */ - @Test - public void testValidEntryFromGetSubjectAlternativeNamesShouldReturnList() - throws Exception { - // Create the valid entry for FriendlyName - ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(WFA_OID_HOTSPOT_FRIENDLYNAME); - v.add(new DERTaggedObject(12, new DERUTF8String(TEST_LANGUAGE + TEST_FRIENDLY_NAME))); - mNewNames.add( - makeAltNames(new GeneralName(GeneralName.otherName, new DERSequence(v)), "DER")); - - when(mX509Certificate.getSubjectAlternativeNames()).thenReturn( - Collections.unmodifiableCollection(mNewNames)); - - List<Pair<Locale, String>> result = ServiceProviderVerifier.getProviderNames( - mX509Certificate); - - assertThat(result.size(), is(1)); - assertEquals(EXPECTED_RESULT, result.get(0)); - } - - /** - * Verify that verifyCertFingerPrint should return {@code true} when a fingerprint of {@link - * X509Certificate} is same with a value of hash provided. - */ - @Test - public void testVerifyFingerPrintOfCertificateWithSameFingerPrintValueReturnTrue() - throws Exception { - String testData = "testData"; - String testHash = "ba477a0ac57e10dd90bb5bf0289c5990fe839c619b26fde7c2aac62f526d4113"; - when(mX509Certificate.getEncoded()).thenReturn(testData.getBytes()); - - assertTrue(ServiceProviderVerifier.verifyCertFingerprint(mX509Certificate, - hexToBytes(testHash))); - } - - /** - * Verify that verifyCertFingerPrint should return {@code false} when a fingerprint of {@link - * X509Certificate} is different with a value of hash provided. - */ - @Test - public void testVerifyFingerPrintOfCertificateWithDifferentFingerPrintValueReturnFalse() - throws Exception { - String testData = "differentData"; - String testHash = "ba477a0ac57e10dd90bb5bf0289c5990fe839c619b26fde7c2aac62f526d4113"; - when(mX509Certificate.getEncoded()).thenReturn(testData.getBytes()); - - assertFalse(ServiceProviderVerifier.verifyCertFingerprint(mX509Certificate, - hexToBytes(testHash))); - } - - /** - * Helper function to create an entry complying with the format returned - * {@link X509Certificate#getSubjectAlternativeNames()} - */ - private List<Object> makeAltNames(GeneralName name, String encoding) throws Exception { - List<Object> nameEntry = new ArrayList<>(2); - nameEntry.add(Integer.valueOf(name.getTagNo())); - nameEntry.add(name.getEncoded(encoding)); - - return nameEntry; - } - - /** - * Converts a hex string to an array of bytes. The {@code hex} should have an even length. If - * not, the last character will be ignored. - */ - private byte[] hexToBytes(String hex) { - byte[] output = new byte[hex.length() / 2]; - for (int i = 0, j = 0; i + 1 < hex.length(); i += 2, j++) { - output[j] = (byte) (charToByte(hex.charAt(i)) << 4 | charToByte(hex.charAt(i + 1))); - } - return output; - } - - /** - * Converts a character of [0-9a-aA-F] to its hex value in a byte. If the character is not a - * hex number, 0 will be returned. - */ - private byte charToByte(char c) { - if (c >= 0x30 && c <= 0x39) { - return (byte) (c - 0x30); - } else if (c >= 0x41 && c <= 0x46) { - return (byte) (c - 0x37); - } else if (c >= 0x61 && c <= 0x66) { - return (byte) (c - 0x57); - } - return 0; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/SystemInfoTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/SystemInfoTest.java deleted file mode 100644 index 6acc8872c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/SystemInfoTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.content.Context; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiNative; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -/** - * Unit tests for {@link SystemInfo}. - */ -@SmallTest -public class SystemInfoTest extends WifiBaseTest { - @Mock Context mContext; - @Mock TelephonyManager mTelephonyManager; - @Mock TelephonyManager mDataTelephonyManager; - @Mock WifiNative mWifiNative; - - SystemInfo mSystemInfo; - private static final String TEST_MAC = "11:22:33:44:55:66"; - private static final String TEST_IFACE = "wlan0"; - - @Before - public void setUp() throws Exception { - initMocks(this); - when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager); - mSystemInfo = new SystemInfo(mContext, mWifiNative); - } - - /** - * Verify that IMEI is returned as device ID when it is provided by {@link TelephonyManager}. - */ - @Test - public void getDeviceIdWithImei() { - String imei = "123456"; - when(mDataTelephonyManager.getImei()).thenReturn(imei); - assertEquals(imei, mSystemInfo.getDeviceId()); - } - - /** - * Verify that MEID is returned as device ID when it is provided by {@link TelephonyManager}. - */ - @Test - public void getDeviceIdWithMeid() { - String meid = "098763"; - when(mDataTelephonyManager.getImei()).thenReturn(null); - when(mDataTelephonyManager.getMeid()).thenReturn(meid); - assertEquals(meid, mSystemInfo.getDeviceId()); - } - - /** - * Verify that {@link SystemInfo#UNKNOWN_INFO} is returned as device ID when both IMEI and - * MEID are not provided by {@link TelephonyManager}. - */ - @Test - public void getDeviceIdWithoutSim() { - when(mDataTelephonyManager.getImei()).thenReturn(null); - when(mDataTelephonyManager.getMeid()).thenReturn(null); - assertEquals(SystemInfo.UNKNOWN_INFO, mSystemInfo.getDeviceId()); - } - - /** - * Verify that mac address is returned successfully. - */ - @Test - public void getWifiMacAddress() { - when(mWifiNative.getMacAddress(any(String.class))).thenReturn(TEST_MAC); - assertEquals(TEST_MAC, mSystemInfo.getMacAddress(TEST_IFACE)); - } -} - diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/UtilsTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/UtilsTest.java deleted file mode 100644 index b3e17c617..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/UtilsTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.hotspot2; - -import static org.junit.Assert.*; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.util.ArrayList; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.Utils}. - */ -public class UtilsTest extends WifiBaseTest { - @Test - public void testRoamingConsortiumsToStringLong() { - assertEquals("null", Utils.roamingConsortiumsToString((long[]) null)); - - long[] ois = new long[]{1L, 2L, 1L << (63 - 40)}; - String expected = "000001, 000002, 0000800000"; - String result = Utils.roamingConsortiumsToString(ois); - assertEquals(expected, result); - } - - @Test - public void testRoamingConsortiumsToStringCollection() { - ArrayList<Long> ois = new ArrayList<>(); - assertEquals("", Utils.roamingConsortiumsToString(ois)); - - ois.add(1L); - ois.add(2L); - ois.add((1L << (63 - 40))); - String expected = "000001, 000002, 0000800000"; - String result = Utils.roamingConsortiumsToString(ois); - assertEquals(expected, result); - } - - @Test - public void testToUnicodeEscapedString() { - assertEquals("", Utils.toUnicodeEscapedString("")); - - StringBuilder unescapedStringBuilder = new StringBuilder(); - StringBuilder escapedStringBuilder = new StringBuilder(); - for (int c = 0; c < 128; c++) { - unescapedStringBuilder.append((char) c); - if (c >= ' ' && c < 127) { - escapedStringBuilder.append((char) c); - } else { - escapedStringBuilder.append("\\u").append(String.format("%04x", c)); - } - } - assertEquals(escapedStringBuilder.toString(), - Utils.toUnicodeEscapedString(unescapedStringBuilder.toString())); - } - - @Test - public void testToHexString() { - assertEquals("null", Utils.toHexString(null)); - - byte[] bytes = {(byte) 0xab, (byte) 0xcd, (byte) 0xef}; - String expected = "ab cd ef"; - String result = Utils.toHexString(bytes); - assertEquals(expected, result.toLowerCase()); - } - - @Test - public void testToHex() { - assertEquals("", Utils.toHex(new byte[0])); - - byte[] bytes = {(byte) 0xab, (byte) 0xcd, (byte) 0xef}; - String expected = "abcdef"; - String result = Utils.toHex(bytes); - assertEquals(expected, result.toLowerCase()); - - } - - @Test - public void testHexToBytes() { - assertArrayEquals(new byte[0], Utils.hexToBytes("")); - - String hexString = "abcd"; - byte[] expected = {(byte) 0xab, (byte) 0xcd}; - byte[] result = Utils.hexToBytes(hexString); - assertArrayEquals(expected, result); - } - - @Test - public void testFromHex() { - int i = 0; - for (char c : "0123456789abcdef".toCharArray()) { - assertEquals(i, Utils.fromHex(c, true)); - assertEquals(i, Utils.fromHex(c, false)); - assertEquals(i, Utils.fromHex(Character.toUpperCase(c), true)); - assertEquals(i, Utils.fromHex(Character.toUpperCase(c), false)); - i++; - } - - assertEquals(-1, Utils.fromHex('q', true)); - - try { - Utils.fromHex('q', false); - fail("Exception should be thrown!"); - } catch (NumberFormatException e) { - // expected - } - } - - @Test - public void testCompare() { - assertEquals(-1, Utils.compare(-1, 1)); - assertEquals(0, Utils.compare(0, 0)); - assertEquals(1, Utils.compare(1, -1)); - - assertEquals(-1, Utils.compare(null, 0)); - assertEquals(0, Utils.compare(null, null)); - assertEquals(1, Utils.compare(0, null)); - } - - @Test - public void testToHMS() { - long hours = 12; - long minutes = 34; - long millis = 56789; - - long time = (((hours * 60) + minutes) * 60) * 1000 + millis; - - String expected = "12:34:56.789"; - String result = Utils.toHMS(time); - assertEquals(expected, result); - - expected = "-12:34:56.789"; - result = Utils.toHMS(-time); - assertEquals(expected, result); - } - - @Test - public void testToUTCString() { - long millis = 832077296000L; - - String expected = "1996/05/14 12:34:56Z"; - String result = Utils.toUTCString(millis); - assertEquals(expected, result); - } - - @Test - public void testUnquote() { - assertEquals(null, Utils.unquote(null)); - - String unquoted = "This is a wug."; - String quoted = "\"This is a wug.\""; - String twiceQuoted = "\"\"This is a wug.\"\""; - String unclosedQuoted = "\"This is a wug."; - String quotedUnclosedQuoted = "\"\"This is a wug.\""; - - assertEquals(unquoted, Utils.unquote(quoted)); - assertEquals(quoted, Utils.unquote(twiceQuoted)); - assertEquals(unclosedQuoted, Utils.unquote(unclosedQuoted)); - assertEquals(unclosedQuoted, Utils.unquote(quotedUnclosedQuoted)); - } -} - - diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ANQPParserTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ANQPParserTest.java deleted file mode 100644 index 2aabcaa7a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ANQPParserTest.java +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import android.net.wifi.WifiSsid; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.ProtocolException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.ANQPParser}. - */ -@SmallTest -public class ANQPParserTest extends WifiBaseTest { - /** - * Helper function for generating payload for a Venue Name ANQP element. - * - * @param language Array of languages - * @param text Array of text - * @return byte[] - * @throws IOException - */ - private static byte[] getVenueNamePayload(String[] language, String[] text) - throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - stream.write(new byte[VenueNameElement.VENUE_INFO_LENGTH]); - stream.write(getI18NameListPayload(language, text)); - return stream.toByteArray(); - } - - /** - * Helper function for generating payload for a Domain Name ANQP element. - * - * @param names Array of domain names - * @return byte[] - * @throws IOException - */ - private static byte[] getDomainNamePayload(String[] names) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - for (String name : names) { - byte[] nameBytes = name.getBytes(StandardCharsets.ISO_8859_1); - stream.write((byte) nameBytes.length); - stream.write(nameBytes); - } - return stream.toByteArray(); - } - - /** - * Helper function for generating payload for a Roaming Consortium ANQP element. - * - * @param ois Array of OIs - * @param oisLength Array of length of each corresponding OI - * @return byte[] - * @throws IOException - */ - private static byte[] getRoamingConsortiumPayload(Long[] ois, int[] oisLength) - throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - for (int i = 0; i < ois.length; i++) { - stream.write((byte) oisLength[i]); - // Write the OI data in big-endian. - for (int l = oisLength[i] - 1; l >= 0; l--) { - stream.write((byte) ((ois[i].longValue() >> l * Byte.SIZE) & 0xFF)); - } - } - return stream.toByteArray(); - } - - /** - * Helper function for generating payload for a NAI Realm ANQP element. - * - * @param realmDataList Array of realm data. - * @return byte[] - * @throws IOException - */ - private static byte[] getNAIRealmPayload(byte[][] realmDataList) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - // Data count in little-endian - stream.write((byte) (realmDataList.length & 0xFF)); - stream.write((byte) ((realmDataList.length >> 8) & 0xFF)); - for (byte[] realmData : realmDataList) { - stream.write(realmData); - } - return stream.toByteArray(); - } - - /** - * Helper function for generating payload for 3GPP Network ANQP element. - * - * @param ieiList Array of IEI data - * @return byte[] - * @throws IOException - */ - private static byte[] getThreeGPPNetworkPayload(byte[][] ieiList) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - int totalIeiSize = CellularNetworkTestUtil.getDataSize(ieiList); - stream.write((byte) ThreeGPPNetworkElement.GUD_VERSION_1); - stream.write((byte) totalIeiSize); - for (byte[] iei : ieiList) { - stream.write(iei); - } - return stream.toByteArray(); - } - - /** - * Helper function for generating payload for Vendor Specific ANQP element. - * - * @param oi The OI of the vendor - * @param type The type of the element - * @param subtype The subtype of the element - * @param payload The vendor specific data - * @return byte[] - * @throws IOException - */ - private static byte[] getVendorSpecificPayload(int oi, int type, int subtype, byte[] payload) - throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - stream.write((byte) ((oi >> 16) & 0xFF)); - stream.write((byte) ((oi >> 8) & 0xFF)); - stream.write((byte) (oi & 0xFF)); - stream.write((byte) type); - stream.write((byte) subtype); - stream.write((byte) 0); // Reserved - stream.write(payload); - return stream.toByteArray(); - } - - /** - * Helper function for generating payload for a Hotspot 2.0 Operator Friendly Name ANQP element. - * - * @param language Array of language - * @param text Array of text - * @return byte[] - * @throws IOException - */ - private static byte[] getHSFriendlyNamePayload(String[] language, String[] text) - throws IOException { - return getI18NameListPayload(language, text); - } - - /** - * Helper function for generating payload for a Hotspot 2.0 WAN Metrics ANQP element. - * - * @param status Link status - * @param symmetric Flag indicating symmetric link speed - * @param capped Flag indicating link operating at max capacity - * @param downlinkSpeed Downlink speed - * @param uplinkSpeed Uplink speed - * @param downlinkLoad Downlink load - * @param uplinkLoad Uplink load - * @param lmd Load measurement duration - * @return byte[] - */ - private static byte[] getHSWanMetricsPayload(int status, boolean symmetric, boolean capped, - long downlinkSpeed, long uplinkSpeed, int downlinkLoad, int uplinkLoad, int lmd) { - ByteBuffer buffer = ByteBuffer.allocate(HSWanMetricsElement.EXPECTED_BUFFER_SIZE) - .order(ByteOrder.LITTLE_ENDIAN); - int wanInfo = status & HSWanMetricsElement.LINK_STATUS_MASK; - if (symmetric) wanInfo |= HSWanMetricsElement.SYMMETRIC_LINK_MASK; - if (capped) wanInfo |= HSWanMetricsElement.AT_CAPACITY_MASK; - buffer.put((byte) wanInfo); - buffer.putInt((int) (downlinkSpeed & 0xFFFFFFFFL)); - buffer.putInt((int) (uplinkSpeed & 0xFFFFFFFFL)); - buffer.put((byte) (downlinkLoad & 0xFF)); - buffer.put((byte) (uplinkLoad & 0xFF)); - buffer.putShort((short) (lmd & 0xFFFF)); - buffer.position(0); - byte[] data = new byte[HSWanMetricsElement.EXPECTED_BUFFER_SIZE]; - buffer.get(data); - return data; - } - - /** - * Helper function for generating payload for a Hotspot 2.0 Connection Capability ANQP - * element. - * - * @param protocol Network protocol - * @param port Network port - * @param status Status of the port - * @return byte[] - */ - private static byte[] getHSConnectionCapabilityPayload(int protocol, int port, int status) { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - stream.write((byte) protocol); - // Write 2-byte port in little-endian. - stream.write((byte) (port & 0xFF)); - stream.write((byte) ((port >> 8) & 0xFF)); - stream.write((byte) status); - return stream.toByteArray(); - } - - /** - * Helper function for generating payload for a Hotspot 2.0 OSU Providers List ANQP - * element. - * - * @param osuSsidBytes Bytes of OSU SSID - * @return byte[] - */ - private static byte[] getHSOsuProvidersPayload(byte[] osuSsidBytes) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write((byte) osuSsidBytes.length); - out.write(osuSsidBytes); - out.write((byte) 1); - out.write(OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO_RAW_BYTES); - return out.toByteArray(); - } - - /** - * Helper function for generating payload for a list of I18Name. - * - * @param language Array of language - * @param text Array of text - * @return byte[] - * @throws IOException - */ - private static byte[] getI18NameListPayload(String[] language, String[] text) - throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - for (int i = 0; i < language.length; i++) { - byte[] textBytes = text[i].getBytes(StandardCharsets.UTF_8); - int length = I18Name.LANGUAGE_CODE_LENGTH + text[i].length(); - stream.write((byte) length); - stream.write(language[i].getBytes(StandardCharsets.US_ASCII)); - // Add padding for two-character language code. - if (language[i].getBytes(StandardCharsets.US_ASCII).length - < I18Name.LANGUAGE_CODE_LENGTH) { - stream.write(new byte[]{(byte) 0x0}); - } - stream.write(textBytes); - } - return stream.toByteArray(); - } - - /** - * Verify that an expected VenueNameElement will be returned when parsing a buffer that - * contained a Venue Name ANQP element. - * - * @throws Exception - */ - @Test - public void parseVenueNameElement() throws Exception { - // Test data. - String[] language = new String[] {"en"}; - String[] text = new String[] {"test"}; - - // Setup expectation. - List<I18Name> nameList = new ArrayList<>(); - nameList.add(new I18Name(language[0], Locale.forLanguageTag(language[0]), text[0])); - VenueNameElement expected = new VenueNameElement(nameList); - - ByteBuffer buffer = ByteBuffer.wrap(getVenueNamePayload(language, text)); - assertEquals(expected, - ANQPParser.parseElement(Constants.ANQPElementType.ANQPVenueName, buffer)); - } - - /** - * Verify that an expected IPAddressTypeAvailabilityElement will be returned when parsing a - * buffer that contained an IP Address Type Availability ANQP element. - * - * @throws Exception - */ - @Test - public void parseIPAddressTypeAvailabilityElement() throws Exception { - // Test data. - int ipAddressAvailability = IPAddressTypeAvailabilityElement.IPV4_PUBLIC << 2 - | IPAddressTypeAvailabilityElement.IPV6_AVAILABLE; - - // Setup expectation. - IPAddressTypeAvailabilityElement expected = new IPAddressTypeAvailabilityElement( - IPAddressTypeAvailabilityElement.IPV4_PUBLIC, - IPAddressTypeAvailabilityElement.IPV6_AVAILABLE); - - ByteBuffer buffer = ByteBuffer.wrap(new byte[] {(byte) ipAddressAvailability}); - assertEquals(expected, - ANQPParser.parseElement(Constants.ANQPElementType.ANQPIPAddrAvailability, buffer)); - } - - /** - * Verify that an expected DomainNameElement will be returned when parsing a buffer that - * contained a Domain Name ANQP element. - * - * @throws Exception - */ - @Test - public void parseDomainNameElement() throws Exception { - String[] testNames = new String[] {"test.com", "abc.com"}; - DomainNameElement expected = new DomainNameElement(Arrays.asList(testNames)); - - ByteBuffer buffer = ByteBuffer.wrap(getDomainNamePayload(testNames)); - assertEquals(expected, - ANQPParser.parseElement(Constants.ANQPElementType.ANQPDomName, buffer)); - } - - /** - * Verify that an expected RoamingConsortiumElement will be returned when parsing a buffer that - * contained a Roaming Consortium ANQP element. - * - * @throws Exception - */ - @Test - public void parseRoamingConsortium() throws Exception { - Long[] ois = new Long[] {0x12345678L, 0x5678L}; - int[] oisLength = new int[] {4, 2}; - RoamingConsortiumElement expected = new RoamingConsortiumElement(Arrays.asList(ois)); - - ByteBuffer buffer = ByteBuffer.wrap(getRoamingConsortiumPayload(ois, oisLength)); - assertEquals(expected, - ANQPParser.parseElement(Constants.ANQPElementType.ANQPRoamingConsortium, buffer)); - } - - /** - * Verify that an expected NAIRealmElement will be returned when parsing a buffer that - * contained a NAI Realm ANQP element. - * - * @throws Exception - */ - @Test - public void parseNAIRealmElement() throws Exception { - byte[][] testBytes = new byte[][] {NAIRealmDataTestUtil.TEST_REAML_WITH_UTF8_DATA_BYTES}; - NAIRealmData[] realmDataList = new NAIRealmData[] {NAIRealmDataTestUtil.TEST_REALM_DATA}; - NAIRealmElement expected = new NAIRealmElement(Arrays.asList(realmDataList)); - - ByteBuffer buffer = ByteBuffer.wrap(getNAIRealmPayload(testBytes)); - assertEquals(expected, - ANQPParser.parseElement(Constants.ANQPElementType.ANQPNAIRealm, buffer)); - } - - /** - * Verify that an expected ThreeGPPNetworkElement will be returned when parsing a buffer that - * contained a 3GPP Network ANQP element. - * - * @throws Exception - */ - @Test - public void parseThreeGPPNetworkElement() throws Exception { - byte[][] plmnBytes = new byte[][] {new byte[] {(byte) 0x87, 0x29, 0x10}}; - String[] plmnList = new String[] {"789012"}; - - List<CellularNetwork> networkList = new ArrayList<>(); - networkList.add(new CellularNetwork(Arrays.asList(plmnList))); - ThreeGPPNetworkElement expected = new ThreeGPPNetworkElement(networkList); - - ByteBuffer buffer = ByteBuffer.wrap(getThreeGPPNetworkPayload( - new byte[][] {CellularNetworkTestUtil.formatPLMNListIEI(plmnBytes)})); - assertEquals(expected, - ANQPParser.parseElement(Constants.ANQPElementType.ANQP3GPPNetwork, buffer)); - } - - /** - * Verify that ProtocolException will be thrown when parsing a buffer that contained a - * vendor specific element that contained a non-Hotspot 2.0 ANQP-element. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseNonHS20VendorSpecificElement() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap( - getVendorSpecificPayload(0x123456, 0x12, 1, new byte[0])); - ANQPParser.parseElement(Constants.ANQPElementType.ANQPVendorSpec, buffer); - } - - /** - * Verify that an expected HSFriendlyNameElement will be returned when parsing a buffer that - * contained a vendor specific element that contained a Hotspot 2.0 friendly name - * ANQP element. - * - * @throws Exception - */ - @Test - public void parseVendorSpecificElementWithHSFriendlyName() throws Exception { - String[] language = new String[] {"en"}; - String[] text = new String[] {"test"}; - - // Setup expectation. - List<I18Name> nameList = new ArrayList<>(); - nameList.add(new I18Name(language[0], Locale.forLanguageTag(language[0]), text[0])); - HSFriendlyNameElement expected = new HSFriendlyNameElement(nameList); - - byte[] hsFriendlyNameBytes = getHSFriendlyNamePayload(language, text); - byte[] data = getVendorSpecificPayload( - ANQPParser.VENDOR_SPECIFIC_HS20_OI, ANQPParser.VENDOR_SPECIFIC_HS20_TYPE, - Constants.HS_FRIENDLY_NAME, hsFriendlyNameBytes); - assertEquals(expected, ANQPParser.parseElement( - Constants.ANQPElementType.ANQPVendorSpec, ByteBuffer.wrap(data))); - } - - /** - * Verify that an expected HSFriendlyNameElement will be returned when parsing a buffer that - * contained a Hotspot 2.0 Friendly Name ANQP element. - * - * @throws Exception - */ - @Test - public void parseHSFrendlyNameElement() throws Exception { - // Test data. - String[] language = new String[] {"en"}; - String[] text = new String[] {"test"}; - - // Setup expectation. - List<I18Name> nameList = new ArrayList<>(); - nameList.add(new I18Name(language[0], Locale.forLanguageTag(language[0]), text[0])); - HSFriendlyNameElement expected = new HSFriendlyNameElement(nameList); - - ByteBuffer buffer = ByteBuffer.wrap(getHSFriendlyNamePayload(language, text)); - assertEquals(expected, - ANQPParser.parseHS20Element(Constants.ANQPElementType.HSFriendlyName, buffer)); - } - - /** - * Verify that an expected HSWanMetricsElement will be returned when parsing a buffer that - * contained a Hotspot 2.0 WAN Metrics ANQP element. - * - * @throws Exception - */ - @Test - public void parseHSWANMetricsElement() throws Exception { - int status = HSWanMetricsElement.LINK_STATUS_UP; - boolean symmetric = false; - boolean capped = true; - long downlinkSpeed = 0x12453L; - long uplinkSpeed = 0x12423L; - int downlinkLoad = 0x12; - int uplinkLoad = 0x23; - int lmd = 0x2321; - - HSWanMetricsElement expected = new HSWanMetricsElement(status, symmetric, capped, - downlinkSpeed, uplinkSpeed, downlinkLoad, uplinkLoad, lmd); - - byte[] data = getHSWanMetricsPayload(status, symmetric, capped, downlinkSpeed, - uplinkSpeed, downlinkLoad, uplinkLoad, lmd); - ByteBuffer buffer = ByteBuffer.wrap(data); - assertEquals(expected, - ANQPParser.parseHS20Element(Constants.ANQPElementType.HSWANMetrics, buffer)); - } - - /** - * Verify that an expected HSConnectionCapabilityElement will be returned when parsing a - * buffer that contained a Hotspot 2.0 Connection Capability ANQP element. - * - * @throws Exception - */ - @Test - public void parseHSConnectionCapabilityElement() throws Exception { - int protocol = 12; - int port = 23; - int status = ProtocolPortTuple.PROTO_STATUS_OPEN; - - List<ProtocolPortTuple> statusList = new ArrayList<>(); - statusList.add(new ProtocolPortTuple(protocol, port, status)); - HSConnectionCapabilityElement expected = new HSConnectionCapabilityElement(statusList); - - ByteBuffer buffer = ByteBuffer.wrap( - getHSConnectionCapabilityPayload(protocol, port, status)); - assertEquals(expected, - ANQPParser.parseHS20Element(Constants.ANQPElementType.HSConnCapability, buffer)); - } - - /** - * Verify that an expected RawByteElement will be returned when parsing a buffer that - * contained a Hotspot 2.0 OSU Providers element. - * - * @throws Exception - */ - @Test - public void parseHSOUSProvidersElement() throws Exception { - byte[] osuSsidBytes = "Test SSID".getBytes(StandardCharsets.UTF_8); - byte[] data = getHSOsuProvidersPayload(osuSsidBytes); - - HSOsuProvidersElement expected = new HSOsuProvidersElement( - WifiSsid.createFromByteArray(osuSsidBytes), - Arrays.asList(OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO)); - - ByteBuffer buffer = ByteBuffer.wrap(data); - assertEquals(expected, - ANQPParser.parseHS20Element(Constants.ANQPElementType.HSOSUProviders, buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTest.java deleted file mode 100644 index 1cfc85db1..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.CellularNetwork}. - */ -@SmallTest -public class CellularNetworkTest extends WifiBaseTest { - private static final byte[] TEST_PLMN_BYTES_1 = new byte[] {0x12, 0x34, 0x56}; - private static final String TEST_PLMN_STRING_1 = "214653"; - private static final byte[] TEST_PLMN_BYTES_2 = new byte[] {0x13, (byte) 0xF9, 0x32}; - private static final String TEST_PLMN_STRING_2 = "31923"; - - /** - * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseBufferWithEmptyBuffer() throws Exception { - CellularNetwork.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that a null will be returned when parsing a buffer contained an unsupported IEI type. - * - * @throws Exception - */ - @Test - public void parseBufferWithInvalidIEIType() throws Exception { - byte[][] plmnsData = new byte[][] {TEST_PLMN_BYTES_1, TEST_PLMN_BYTES_2}; - byte[] testData = CellularNetworkTestUtil.formatPLMNListIEI(1, plmnsData); - assertNull(CellularNetwork.parse(ByteBuffer.wrap(testData))); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseBufferWithIncompleteData() throws Exception { - byte[][] plmnsData = new byte[][] {TEST_PLMN_BYTES_1, TEST_PLMN_BYTES_2}; - byte[] testData = CellularNetworkTestUtil.formatPLMNListIEI(plmnsData); - CellularNetwork.parse(ByteBuffer.wrap(testData, 0, testData.length - 1)); - } - - /** - * Verify that ProtocolException will be thrown when IEI size and the PLMN count doesn't - * match. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithMismatchIEISizeAndPLMNCount() throws Exception { - byte[][] plmnsData = new byte[][] {TEST_PLMN_BYTES_1, TEST_PLMN_BYTES_2}; - // Get test data with IEI size set to incorrect value. - byte[] testData = CellularNetworkTestUtil.formatPLMNListIEI( - CellularNetwork.IEI_TYPE_PLMN_LIST, plmnsData, true); - CellularNetwork.parse(ByteBuffer.wrap(testData)); - } - - /** - * Verify that the expected ProtocolPortTuple is returned when parsing a buffer contained - * the test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - byte[][] plmnsData = new byte[][] {TEST_PLMN_BYTES_1, TEST_PLMN_BYTES_2}; - byte[] testData = CellularNetworkTestUtil.formatPLMNListIEI(plmnsData); - - // Setup the expected CellularNetwork. - List<String> plmnList = new ArrayList<>(); - plmnList.add(TEST_PLMN_STRING_1); - plmnList.add(TEST_PLMN_STRING_2); - CellularNetwork expected = new CellularNetwork(plmnList); - - assertEquals(expected, CellularNetwork.parse(ByteBuffer.wrap(testData))); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTestUtil.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTestUtil.java deleted file mode 100644 index dad2919f0..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTestUtil.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * Utility class for formatting IEI (Information Element Identity) data for testing. - */ -public class CellularNetworkTestUtil { - /** - * Format and return PLMN List IEI with the given PLMN list data. - * - * @param plmnList The array of PLMN data - * @return byte[] - * @throws IOException - */ - public static byte[] formatPLMNListIEI(byte[][] plmnList) throws IOException { - return formatPLMNListIEI(CellularNetwork.IEI_TYPE_PLMN_LIST, plmnList); - } - - /** - * Format and return PLMN List IEI with the given IEI type and PLMN list data. This - * allows the test to use an invalid IEI type for testing purpose. - * - * @param ieiType The IEI type - * @param plmnList The array of PLMN data - * @return byte[] - * @throws IOException - */ - public static byte[] formatPLMNListIEI(int ieiType, byte[][] plmnList) throws IOException { - return formatPLMNListIEI(ieiType, plmnList, false); - } - - /** - * Format and return PLMN List IEI with the given IEI type and PLMN list data. This also - * allows the test to intentionally setting an incorrect size value. - * - * @param ieiType The IEI type - * @param plmnList The array of PLMN data - * @param setWrongSize Flag for setting incorrect IEI size - * @return byte[] - * @throws IOException - */ - public static byte[] formatPLMNListIEI(int ieiType, byte[][] plmnList, boolean setWrongSize) - throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - - // Calculate the total bytes for all the PLMNs. - int plmnsSize = getDataSize(plmnList); - - // Use incorrect size intentionally. - if (setWrongSize) plmnsSize -= 1; - - stream.write((byte) ieiType); - // One extra byte for the PLMN count field. - stream.write((byte) ((plmnsSize + 1) & CellularNetwork.IEI_CONTENT_LENGTH_MASK)); - stream.write((byte) plmnList.length); - for (byte[] plmn : plmnList) { - stream.write(plmn); - } - - return stream.toByteArray(); - } - - /** - * Return the number of bytes in a 2D array. - * - * @param dataArray The 2D array - * @return The number of bytes in the 2D array - */ - public static int getDataSize(byte[][] dataArray) { - int size = 0; - for (byte[] data : dataArray) { - size += data.length; - } - return size; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/DomainNameElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/DomainNameElementTest.java deleted file mode 100644 index 1b81749d8..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/DomainNameElementTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.DomainNameElement}. - */ -@SmallTest -public class DomainNameElementTest extends WifiBaseTest { - private static final String TEST_DOMAIN_NAME1 = "test1.com"; - private static final String TEST_DOMAIN_NAME2 = "test2.com"; - - /** - * Helper function for appending a Domain Name to an output stream. - * - * @param stream Stream to write to - * @param domain The domain name string - * @throws IOException - */ - private void appendDomain(ByteArrayOutputStream stream, String domain) throws IOException { - byte[] domainBytes = domain.getBytes(StandardCharsets.ISO_8859_1); - stream.write((byte) domainBytes.length); - stream.write(domainBytes); - } - - /** - * Helper function for generating test data. - * - * @return byte[] of data - * @throws IOException - */ - private byte[] getTestData(String[] domains) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - for (String domain : domains) { - appendDomain(stream, domain); - } - return stream.toByteArray(); - } - - /** - * Verify that a DomainNameElement with empty domain list will be returned when parsing an - * empty buffer. - * - * @throws Exception - */ - @Test - public void parseEmptyBuffer() throws Exception { - assertTrue(DomainNameElement.parse(ByteBuffer.allocate(0)).getDomains().isEmpty()); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[] {TEST_DOMAIN_NAME1})); - buffer.limit(buffer.remaining() - 1); - DomainNameElement.parse(buffer); - } - - /** - * Verify that a DomainNameElement with expected domain list will be returned when parsing a - * buffer contained valid domain name list. - * - * @throws Exception - */ - @Test - public void parseBufferWithValidDomainNames() throws Exception { - byte[] testData = getTestData(new String[] {TEST_DOMAIN_NAME1, TEST_DOMAIN_NAME2}); - ByteBuffer buffer = ByteBuffer.wrap(testData); - - // Setup expected element. - List<String> domainList = new ArrayList<>(); - domainList.add(TEST_DOMAIN_NAME1); - domainList.add(TEST_DOMAIN_NAME2); - DomainNameElement expectedElement = new DomainNameElement(domainList); - - assertEquals(expectedElement, DomainNameElement.parse(buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElementTest.java deleted file mode 100644 index 8c68c13f3..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElementTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.HSConnectionCapabilityElement}. - */ -@SmallTest -public class HSConnectionCapabilityElementTest extends WifiBaseTest { - private static final ProtocolPortTuple TEST_TUPLE1 = - new ProtocolPortTuple(1, 2, ProtocolPortTuple.PROTO_STATUS_CLOSED); - private static final ProtocolPortTuple TEST_TUPLE2 = - new ProtocolPortTuple(3, 4, ProtocolPortTuple.PROTO_STATUS_OPEN); - - /** - * Helper function for writing a ProtocolPortTuple into a buffer. - * - * @param buffer The buffer to write to - * @param tuple The tuple to write - */ - private void appendProtocolPortTuple(ByteBuffer buffer, ProtocolPortTuple tuple) { - buffer.put((byte) tuple.getProtocol()); - buffer.putShort((short) tuple.getPort()); - buffer.put((byte) tuple.getStatus()); - } - - /** - * Helper function for generating a buffer with test data. - * - * @param tuples Tuples to put in the buffer - * @return {@link ByteBuffer} - */ - private ByteBuffer getTestBuffer(ProtocolPortTuple[] tuples) { - ByteBuffer buffer = ByteBuffer.allocate(tuples.length * ProtocolPortTuple.RAW_BYTE_SIZE) - .order(ByteOrder.LITTLE_ENDIAN); - for (ProtocolPortTuple tuple : tuples) { - appendProtocolPortTuple(buffer, tuple); - } - buffer.position(0); - return buffer; - } - - /** - * Verify that a HSConnectionCapabilityElement with an empty status list will be returned - * when parsing an empty buffer. - * - * @throws Exception - */ - @Test - public void parseEmptyBuffer() throws Exception { - HSConnectionCapabilityElement element = - HSConnectionCapabilityElement.parse(ByteBuffer.allocate(0)); - assertTrue(element.getStatusList().isEmpty()); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a buffer without - * the complete tuple data (missing status field). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseBufferWithLessThanMinimumSize() throws Exception { - ByteBuffer buffer = ByteBuffer.allocate(ProtocolPortTuple.RAW_BYTE_SIZE - 1); - buffer.put(new byte[ProtocolPortTuple.RAW_BYTE_SIZE - 1]); - buffer.position(0); - HSConnectionCapabilityElement.parse(buffer); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a buffer that contained - * incomplete bytes for a tuple. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseBufferWithIncompleteTupleBytes() throws Exception { - // Construct a buffer which will contained a tuple and an extra byte at the end. - ByteBuffer buffer = ByteBuffer.allocate(ProtocolPortTuple.RAW_BYTE_SIZE + 1); - appendProtocolPortTuple(buffer, TEST_TUPLE1); - buffer.put((byte) 0); - buffer.position(0); - HSConnectionCapabilityElement.parse(buffer); - } - - /** - * Verify that the expected HSConnectionCapabilityElement is returned when parsing - * a buffer containing the test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - ByteBuffer buffer = getTestBuffer(new ProtocolPortTuple[] {TEST_TUPLE1, TEST_TUPLE2}); - - // Setup expected element. - List<ProtocolPortTuple> tupleList = new ArrayList<>(); - tupleList.add(TEST_TUPLE1); - tupleList.add(TEST_TUPLE2); - HSConnectionCapabilityElement expected = new HSConnectionCapabilityElement(tupleList); - - assertEquals(expected, HSConnectionCapabilityElement.parse(buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSFriendlyNameElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSFriendlyNameElementTest.java deleted file mode 100644 index 256df8273..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSFriendlyNameElementTest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement}. - */ -@SmallTest -public class HSFriendlyNameElementTest extends WifiBaseTest { - private static final String TEST_LANGUAGE = "en"; - private static final Locale TEST_LOCALE = Locale.forLanguageTag(TEST_LANGUAGE); - private static final String TEST_OPERATOR_NAME1 = "Operator1"; - private static final String TEST_OPERATOR_NAME2 = "Operator2"; - - /** - * Helper function for appending a Operator Name to an output stream. - * - * @param stream Stream to write to - * @param operator The name of the operator - * @throws IOException - */ - private void appendOperatorName(ByteArrayOutputStream stream, String operator) - throws IOException { - byte[] nameBytes = operator.getBytes(StandardCharsets.UTF_8); - int length = I18Name.LANGUAGE_CODE_LENGTH + operator.length(); - stream.write((byte) length); - stream.write(TEST_LANGUAGE.getBytes(StandardCharsets.US_ASCII)); - stream.write(new byte[]{(byte) 0x0}); // Padding for language code. - stream.write(nameBytes); - } - - /** - * Helper function for generating test data. - * - * @return byte[] of data - * @throws IOException - */ - private byte[] getTestData(String[] names) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - for (String name : names) { - appendOperatorName(stream, name); - } - return stream.toByteArray(); - } - - /** - * Verify that HSFriendlyNameElement with a empty operator name list will be returned when - * parsing an empty buffer. - * - * @throws Exception - */ - @Test - public void parseBufferWithEmptyBuffer() throws Exception { - assertTrue(HSFriendlyNameElement.parse(ByteBuffer.allocate(0)).getNames().isEmpty()); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseBufferWithTruncatedByte() throws Exception { - byte[] testData = getTestData(new String[] {TEST_OPERATOR_NAME1}); - // Truncate a byte at the end. - ByteBuffer buffer = ByteBuffer.allocate(testData.length - 1); - buffer.put(testData, 0, testData.length - 1); - buffer.position(0); - HSFriendlyNameElement.parse(buffer); - } - - /** - * Verify that an expected HSFriendlyNameElement will be returned when parsing a buffer - * containing the default test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithDefaultTestData() throws Exception { - byte[] testData = getTestData(new String[] {TEST_OPERATOR_NAME1, TEST_OPERATOR_NAME2}); - ByteBuffer buffer = ByteBuffer.allocate(testData.length); - buffer.put(testData); - buffer.position(0); - - // Setup expected element. - List<I18Name> nameList = new ArrayList<>(); - nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_OPERATOR_NAME1)); - nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_OPERATOR_NAME2)); - HSFriendlyNameElement expectedElement = new HSFriendlyNameElement(nameList); - - assertEquals(expectedElement, HSFriendlyNameElement.parse(buffer)); - } - - /** - * Verify that an expected HSFriendlyNameElement will be returned when parsing a buffer - * containing a operator name with the maximum length. - * - * @throws Exception - */ - @Test - public void parseBufferWithMaxLengthOperatoreName() throws Exception { - // Operator name with the maximum length. - byte[] textData = new byte[HSFriendlyNameElement.MAXIMUM_OPERATOR_NAME_LENGTH]; - Arrays.fill(textData, (byte) 'a'); - String text = new String(textData); - byte[] testData = getTestData(new String[] {text}); - ByteBuffer buffer = ByteBuffer.allocate(testData.length); - buffer.put(testData); - buffer.position(0); - - // Setup expected element. - List<I18Name> nameList = new ArrayList<>(); - nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, text)); - HSFriendlyNameElement expectedElement = new HSFriendlyNameElement(nameList); - - assertEquals(expectedElement, HSFriendlyNameElement.parse(buffer)); - } - - /** - * Verify that ProtocolException will be thrown when parsing a buffer containing a - * operator name that exceeds the maximum length. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithOperatorNameLengthExceedMax() throws Exception { - byte[] textData = new byte[HSFriendlyNameElement.MAXIMUM_OPERATOR_NAME_LENGTH + 1]; - Arrays.fill(textData, (byte) 'a'); - String text = new String(textData); - byte[] testData = getTestData(new String[] {text}); - ByteBuffer buffer = ByteBuffer.allocate(testData.length); - buffer.put(testData); - buffer.position(0); - HSFriendlyNameElement.parse(buffer); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSIconFileElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSIconFileElementTest.java deleted file mode 100644 index 2b77613ae..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSIconFileElementTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.HSIconFileElement}. - */ -@SmallTest -public class HSIconFileElementTest extends WifiBaseTest { - private static final String TEST_ICON_TYPE = "png"; - private static final byte[] TEST_ICON_DATA = new byte[8]; - - /** - * Utility function for generating test data. - * - * @param statusCode Status code of the icon file download - * @return byte[] - */ - private static byte[] getTestData(int statusCode) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write((byte) statusCode); - if (statusCode != HSIconFileElement.STATUS_CODE_SUCCESS) { - // No need to write other data if status code is not success. - return out.toByteArray(); - } - - byte[] iconTypeBytes = TEST_ICON_TYPE.getBytes(StandardCharsets.US_ASCII); - out.write(iconTypeBytes.length); - out.write(iconTypeBytes); - out.write(TEST_ICON_DATA.length & 0xFF); - out.write((TEST_ICON_DATA.length >> 8) & 0xFF); - out.write(TEST_ICON_DATA); - return out.toByteArray(); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - HSIconFileElement.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(getTestData(HSIconFileElement.STATUS_CODE_SUCCESS)); - buffer.limit(buffer.remaining() - 1); - HSIconFileElement.parse(buffer); - } - - /** - * Verify that an expected {@link HSIconFileElement} is returned when parsing a buffer - * containing icon data. - * - * @throws Exception - */ - @Test - public void parseBufferWithIconData() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(getTestData(HSIconFileElement.STATUS_CODE_SUCCESS)); - HSIconFileElement expected = new HSIconFileElement( - HSIconFileElement.STATUS_CODE_SUCCESS, TEST_ICON_TYPE, TEST_ICON_DATA); - assertEquals(expected, HSIconFileElement.parse(buffer)); - } - - /** - * Verify that an expected {@link HSIconFileElement} is returned when parsing a buffer - * without icon data (icon file not found). - * - * @throws Exception - */ - @Test - public void parseBufferWithoutIconData() throws Exception { - ByteBuffer buffer = - ByteBuffer.wrap(getTestData(HSIconFileElement.STATUS_CODE_FILE_NOT_FOUND)); - HSIconFileElement expected = - new HSIconFileElement(HSIconFileElement.STATUS_CODE_FILE_NOT_FOUND, null, null); - assertEquals(expected, HSIconFileElement.parse(buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSOsuProvidersElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSOsuProvidersElementTest.java deleted file mode 100644 index dfb5abec2..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSOsuProvidersElementTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import android.net.wifi.WifiSsid; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement}. - */ -@SmallTest -public class HSOsuProvidersElementTest extends WifiBaseTest { - private static final byte[] TEST_OSU_SSID_BYTES = "Test SSID".getBytes(StandardCharsets.UTF_8); - private static final WifiSsid TEST_OSU_SSID = - WifiSsid.createFromByteArray(TEST_OSU_SSID_BYTES); - private static final List<OsuProviderInfo> TEST_PROVIDER_LIST = - Arrays.asList(OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO); - - private static final HSOsuProvidersElement TEST_OSU_PROVIDERS_ELEMENT = - new HSOsuProvidersElement(TEST_OSU_SSID, TEST_PROVIDER_LIST); - - /** - * Utility function for generating test data. - * - * @param osuSsidBytes The OSU SSID bytes - * @return byte[] - */ - private static byte[] getTestData(byte[] osuSsidBytes) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write((byte) osuSsidBytes.length); - out.write(osuSsidBytes); - out.write((byte) TEST_PROVIDER_LIST.size()); - out.write(OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO_RAW_BYTES); - return out.toByteArray(); - } catch (IOException e) { - return null; - } - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - HSOsuProvidersElement.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(getTestData(TEST_OSU_SSID_BYTES)); - buffer.limit(buffer.remaining() - 1); - HSOsuProvidersElement.parse(buffer); - } - - /** - * Verify that ProtocolException will be thrown when parsing a buffer containing an - * invalid OSU SSID. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithInvalidLength() throws Exception { - byte[] invalidSsidBytes = new byte[HSOsuProvidersElement.MAXIMUM_OSU_SSID_LENGTH + 1]; - ByteBuffer buffer = ByteBuffer.wrap(getTestData(invalidSsidBytes)); - HSOsuProvidersElement.parse(buffer); - } - - /** - * Verify that an expected {@link HSOsuProvidersElement} will be returned when parsing a buffer - * containing pre-defined test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(getTestData(TEST_OSU_SSID_BYTES)); - assertEquals(TEST_OSU_PROVIDERS_ELEMENT, HSOsuProvidersElement.parse(buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElementTest.java deleted file mode 100644 index e4b65f359..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElementTest.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement}. - */ -@SmallTest -public class HSWanMetricsElementTest extends WifiBaseTest { - private static final int TEST_LINK_STATUS = HSWanMetricsElement.LINK_STATUS_UP; - private static final boolean TEST_SYMMETRIC_LINK = true; - private static final boolean TEST_AT_CAPACITY = true; - private static final long TEST_DOWNLINK_SPEED = 0x1234556L; - private static final long TEST_UPLINK_SPEED = 0x342343L; - private static final int TEST_DOWNLINK_LOAD = 0x23; - private static final int TEST_UPLINK_LOAD = 0x45; - private static final int TEST_LMD = 0x2132; - - private static final HSWanMetricsElement TEST_ELEMENT = new HSWanMetricsElement( - TEST_LINK_STATUS, TEST_SYMMETRIC_LINK, TEST_AT_CAPACITY, - TEST_DOWNLINK_SPEED, TEST_UPLINK_SPEED, TEST_DOWNLINK_LOAD, - TEST_UPLINK_LOAD, TEST_LMD); - - /** - * Helper function for generating a ByteBuffer with the test data. - * - * @return {@link ByteBuffer} - */ - private ByteBuffer getTestBuffer() { - ByteBuffer buffer = ByteBuffer.allocate(HSWanMetricsElement.EXPECTED_BUFFER_SIZE) - .order(ByteOrder.LITTLE_ENDIAN); - int wanInfo = TEST_LINK_STATUS & HSWanMetricsElement.LINK_STATUS_MASK; - if (TEST_SYMMETRIC_LINK) wanInfo |= HSWanMetricsElement.SYMMETRIC_LINK_MASK; - if (TEST_AT_CAPACITY) wanInfo |= HSWanMetricsElement.AT_CAPACITY_MASK; - buffer.put((byte) wanInfo); - buffer.putInt((int) (TEST_DOWNLINK_SPEED & 0xFFFFFFFFL)); - buffer.putInt((int) (TEST_UPLINK_SPEED & 0xFFFFFFFFL)); - buffer.put((byte) (TEST_DOWNLINK_LOAD & 0xFF)); - buffer.put((byte) (TEST_UPLINK_LOAD & 0xFF)); - buffer.putShort((short) (TEST_LMD & 0xFFFF)); - buffer.position(0); - return buffer; - } - - @Test - public void testGetStatus() { - assertEquals(TEST_LINK_STATUS, TEST_ELEMENT.getStatus()); - } - - @Test - public void testIsSymmetric() { - assertEquals(TEST_SYMMETRIC_LINK, TEST_ELEMENT.isSymmetric()); - } - - @Test - public void testIsCapped() { - assertEquals(TEST_AT_CAPACITY, TEST_ELEMENT.isCapped()); - } - - @Test - public void testGetDownlinkSpeed() { - assertEquals(TEST_DOWNLINK_SPEED, TEST_ELEMENT.getDownlinkSpeed()); - } - - @Test - public void testGetUplinkSpeed() { - assertEquals(TEST_UPLINK_SPEED, TEST_ELEMENT.getUplinkSpeed()); - } - - @Test - public void testGetDownlinkLoad() { - assertEquals(TEST_DOWNLINK_LOAD, TEST_ELEMENT.getDownlinkLoad()); - } - - @Test - public void testGetUplinkLoad() { - assertEquals(TEST_UPLINK_LOAD, TEST_ELEMENT.getUplinkLoad()); - } - - @Test - public void testGetLMD() { - assertEquals(TEST_LMD, TEST_ELEMENT.getLMD()); - } - - /** - * Verify that ProtocolException will be thrown when parsing an empty buffer. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseEmptyBuffer() throws Exception { - HSWanMetricsElement.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that ProtocolException will be thrown when a buffer with size less than the - * expected. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithLessThanExpectedSize() throws Exception { - ByteBuffer buffer = ByteBuffer.allocate(HSWanMetricsElement.EXPECTED_BUFFER_SIZE - 1); - buffer.put(new byte[HSWanMetricsElement.EXPECTED_BUFFER_SIZE - 1]); - buffer.position(0); - HSWanMetricsElement.parse(buffer); - } - - /** - * Verify that ProtocolException will be thrown when a buffer with size more than the - * expected. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithMoreThanExpectedSize() throws Exception { - ByteBuffer buffer = ByteBuffer.allocate(HSWanMetricsElement.EXPECTED_BUFFER_SIZE + 1); - buffer.put(new byte[HSWanMetricsElement.EXPECTED_BUFFER_SIZE + 1]); - buffer.position(0); - HSWanMetricsElement.parse(buffer); - } - - /** - * Verify that the expected HSWanMetricsElement is returned when parsing - * a buffer containing the test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - ByteBuffer buffer = getTestBuffer(); - HSWanMetricsElement expectedElement = new HSWanMetricsElement( - TEST_LINK_STATUS, TEST_SYMMETRIC_LINK, TEST_AT_CAPACITY, - TEST_DOWNLINK_SPEED, TEST_UPLINK_SPEED, TEST_DOWNLINK_LOAD, - TEST_UPLINK_LOAD, TEST_LMD); - assertEquals(expectedElement, HSWanMetricsElement.parse(buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/I18NameTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/I18NameTest.java deleted file mode 100644 index bf9e23045..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/I18NameTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Locale; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.I18Name}. - */ -@SmallTest -public class I18NameTest extends WifiBaseTest { - private static final String TEST_LANGUAGE = "en"; - private static final Locale TEST_LOCALE = Locale.forLanguageTag(TEST_LANGUAGE); - private static final String TEST_TEXT = "Hello World"; - - /** - * Helper function for returning byte array containing test data. - * - * @param language The language code string - * @param text The text string - * @return byte[] - * @throws IOException - */ - private byte[] getTestData(String language, String text) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - stream.write(language.getBytes(StandardCharsets.US_ASCII)); - stream.write(new byte[]{(byte) 0x0}); // Padding for language code. - stream.write(text.getBytes(StandardCharsets.UTF_8)); - return stream.toByteArray(); - } - - /** - * Helper function for generating default test data. The test data include the language code - * and text field. - * - * @return byte[] of data - * @throws IOException - */ - private byte[] getDefaultTestData() throws IOException { - return getTestData(TEST_LANGUAGE, TEST_TEXT); - } - - /** - * Helper function for returning a buffer containing a I18Name test data. - * - * @Param data The byte array of I18Name data - * @param length The length value to set in the I18Name header - * @return {@link ByteBuffer} - * @throws IOException - */ - private ByteBuffer getTestBuffer(byte[] data, int length) throws IOException { - // Allocate extra byte for storing the length field. - ByteBuffer buffer = ByteBuffer.allocate(data.length + 1); - buffer.put((byte) length); - buffer.put(data); - buffer.position(0); - return buffer; - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing from an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - I18Name.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that BufferUnderflowException will be thrown when the length field is set to more - * than the actual buffer size. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - byte[] data = getDefaultTestData(); - ByteBuffer buffer = getTestBuffer(data, data.length); - buffer.limit(buffer.remaining() - 1); - I18Name.parse(buffer); - } - - /** - * Verify that ProtocolException will be thrown when the length field is set to less than - * the minimum. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithLengthLessThanMinimum() throws Exception { - byte[] data = getDefaultTestData(); - I18Name.parse(getTestBuffer(data, I18Name.MINIMUM_LENGTH - 1)); - } - - /** - * Verify that the expected I18Name will be returned when parsing a buffer contained the - * predefined test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithDefaultTestData() throws Exception { - byte[] data = getDefaultTestData(); - I18Name actualName = I18Name.parse(getTestBuffer(data, data.length)); - I18Name expectedName = new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_TEXT); - assertEquals(expectedName, actualName); - } - - /** - * Verify that the expected I18Name will be returned when parsing a buffer contained - * a non-English (French) language. - * - * @throws Exception - */ - @Test - public void parseBufferWithFrenchData() throws Exception { - // Test data for French. - String language = "fr"; - String text = "Hello World"; - byte[] data = getTestData(language, text); - I18Name actualName = I18Name.parse(getTestBuffer(data, data.length)); - I18Name expectedName = new I18Name(language, Locale.forLanguageTag(language), text); - assertEquals(expectedName, actualName); - } - - /** - * Verify that an I18Name with an empty text will be returned when parsing a buffer contained - * an empty text field. - * - * @throws Exception - */ - @Test - public void parseBufferWithEmptyText() throws Exception { - byte[] data = getTestData(TEST_LANGUAGE, ""); - I18Name actualName = I18Name.parse(getTestBuffer(data, data.length)); - I18Name expectedName = new I18Name(TEST_LANGUAGE, TEST_LOCALE, ""); - assertEquals(expectedName, actualName); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IPAddressTypeAvailabilityElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IPAddressTypeAvailabilityElementTest.java deleted file mode 100644 index 2250871be..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IPAddressTypeAvailabilityElementTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.IPAddressTypeAvailabilityElement}. - */ -@SmallTest -public class IPAddressTypeAvailabilityElementTest extends WifiBaseTest { - private static final int TEST_IPV4_AVAILABILITY = - IPAddressTypeAvailabilityElement.IPV4_PUBLIC; - private static final int TEST_IPV6_AVAILABILITY = - IPAddressTypeAvailabilityElement.IPV6_AVAILABLE; - - private static int getIPAvailability() { - return (TEST_IPV4_AVAILABILITY << 2) | TEST_IPV6_AVAILABILITY; - } - - /** - * Verify that ProtocolException will be thrown when parsing an empty buffer. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferEmptyBuffer() throws Exception { - IPAddressTypeAvailabilityElement.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that ProtocolException will be thrown when parsing an buffer containing excess - * data. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithExcessData() throws Exception { - ByteBuffer buffer = ByteBuffer.allocate( - IPAddressTypeAvailabilityElement.EXPECTED_BUFFER_LENGTH + 1); - buffer.put((byte) getIPAvailability()); - buffer.put((byte) 0); // Excess data. - buffer.position(0); - IPAddressTypeAvailabilityElement.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that the expected IPAddressTypeAvailabilityElement is returned when parsing - * a buffer containing the test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - ByteBuffer buffer = ByteBuffer.allocate( - IPAddressTypeAvailabilityElement.EXPECTED_BUFFER_LENGTH); - buffer.put((byte) getIPAvailability()); - buffer.position(0); - - IPAddressTypeAvailabilityElement expectedElement = new IPAddressTypeAvailabilityElement( - TEST_IPV4_AVAILABILITY, TEST_IPV6_AVAILABILITY); - assertEquals(expectedElement, IPAddressTypeAvailabilityElement.parse(buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IconInfoTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IconInfoTest.java deleted file mode 100644 index 3580a745c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IconInfoTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.IconInfo}. - */ -@SmallTest -public class IconInfoTest extends WifiBaseTest { - private static final int TEST_WIDTH = 1111; - private static final int TEST_HEIGHT = 2222; - private static final String TEST_LANGUAGE = "language"; - private static final String TEST_ICON_TYPE = "iconType"; - private static final String TEST_FILE_NAME = "filename"; - - private static final IconInfo TEST_ICON_INFO = - new IconInfo(TEST_WIDTH, TEST_HEIGHT, TEST_LANGUAGE, TEST_ICON_TYPE, TEST_FILE_NAME); - - @Test - public void testGetWidth() { - assertEquals(TEST_WIDTH, TEST_ICON_INFO.getWidth()); - } - - @Test - public void testGetHeight() { - assertEquals(TEST_HEIGHT, TEST_ICON_INFO.getHeight()); - } - - @Test - public void testGetLanguage() { - assertEquals(TEST_LANGUAGE, TEST_ICON_INFO.getLanguage()); - } - - @Test - public void testGetIconType() { - assertEquals(TEST_ICON_TYPE, TEST_ICON_INFO.getIconType()); - } - - @Test - public void testGetFileName() { - assertEquals(TEST_FILE_NAME, TEST_ICON_INFO.getFileName()); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - IconInfo.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(IconInfoTestUtil.TEST_ICON_INFO_RAW_BYTES); - buffer.limit(buffer.remaining() - 1); - IconInfo.parse(buffer); - } - - /** - * Verify that an expected {@link IconInfo} will be returned when parsing a buffer containing - * pre-defined test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(IconInfoTestUtil.TEST_ICON_INFO_RAW_BYTES); - assertEquals(IconInfoTestUtil.TEST_ICON_INFO, IconInfo.parse(buffer)); - } - - /** - * Tests the hash function. - */ - @Test - public void testHashCode() { - int width1 = 1; - int height1 = 1; - String language1 = "language1"; - String iconType1 = "iconType1"; - String fileName1 = "filename1"; - - int width2 = 2; - int height2 = 2; - String language2 = "language2"; - String iconType2 = "iconType2"; - String fileName2 = "filename2"; - - IconInfo info1 = new IconInfo(width1, height1, language1, iconType1, fileName1); - IconInfo info2 = new IconInfo(width2, height2, language2, iconType2, fileName2); - IconInfo info1Dup = new IconInfo(width1, height1, language1, iconType1, fileName1); - - assertNotEquals(info1.hashCode(), info2.hashCode()); - assertEquals(info1.hashCode(), info1Dup.hashCode()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IconInfoTestUtil.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IconInfoTestUtil.java deleted file mode 100644 index fa0e9f8aa..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/IconInfoTestUtil.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -/** - * Utility class containing test data and object for {@link IconInfo}. - */ -public class IconInfoTestUtil { - // Test data - private static final int TEST_WIDTH = 9811; - private static final int TEST_HEIGHT = 4523; - private static final String TEST_LANGUAGE = "en"; - private static final String TEST_TYPE = "png"; - private static final String TEST_FILENAME = "testicon.png"; - - /** - * {@link IconInfo} object with pre-defined test data. - */ - public static final IconInfo TEST_ICON_INFO = - new IconInfo(TEST_WIDTH, TEST_HEIGHT, TEST_LANGUAGE, TEST_TYPE, TEST_FILENAME); - - /** - * Raw bytes of icon info with pre-defined test data. - */ - public static final byte[] TEST_ICON_INFO_RAW_BYTES = getTestData(); - - /** - * Generate raw bytes based on the pre-defined test data. - * - * @return array of bytes - */ - private static byte[] getTestData() { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - writeShortLE(out, TEST_WIDTH); - writeShortLE(out, TEST_HEIGHT); - out.write(TEST_LANGUAGE.getBytes(StandardCharsets.US_ASCII)); - out.write((byte) 0); // Padding for language code. - writeByteArrayWithLength(out, TEST_TYPE.getBytes(StandardCharsets.US_ASCII)); - writeByteArrayWithLength(out, TEST_FILENAME.getBytes(StandardCharsets.UTF_8)); - return out.toByteArray(); - } catch (IOException e) { - return null; - } - } - - /** - * Write the lower 2-bytes of an integer to the given output stream in Little-Endian. - * - * @param out The output stream to write to - * @param value The integer value to write - */ - private static void writeShortLE(ByteArrayOutputStream out, int value) { - out.write(value & 0xFF); - out.write((value >> 8) & 0xFF); - } - - /** - * Write the given byte array to the given output stream, the array data is prefixed with a - * byte specifying the length of the byte array. - * - * @param out The output stream to write to - * @param data The byte array to write - * @throws IOException - */ - private static void writeByteArrayWithLength(ByteArrayOutputStream out, byte[] data) - throws IOException { - out.write((byte) data.length); - out.write(data); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmDataTest.java deleted file mode 100644 index 4839b3d63..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmDataTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.NAIRealmData}. - */ -@SmallTest -public class NAIRealmDataTest extends WifiBaseTest { - /** - * Verify that BufferUnderflowException will be thrown when parsing from an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - NAIRealmData.parse(ByteBuffer.wrap(new byte[0])); - } - - /** - * Verify that ProtocolException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(NAIRealmDataTestUtil.TEST_REAML_WITH_UTF8_DATA_BYTES); - buffer.limit(buffer.remaining() - 1); - NAIRealmData.parse(buffer); - } - - /** - * Verify that an expected NAIRealmData will be returned when parsing a buffer contained - * the test data with realm string encoded using UTF8. - * - * @throws Exception - */ - @Test - public void parseBufferWithUTF8EncodedNAIRealmData() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(NAIRealmDataTestUtil.TEST_REAML_WITH_UTF8_DATA_BYTES); - assertEquals(NAIRealmDataTestUtil.TEST_REALM_DATA, NAIRealmData.parse(buffer)); - } - - /** - * Verify that the expected NAIRealmData will be returned when parsing a buffer contained - * the test data with realm string encoded using non-UTF8. - * - * @throws Exception - */ - @Test - public void parseBufferWithNonUTF8EncodedNAIRealmData() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap( - NAIRealmDataTestUtil.TEST_REAML_WITH_NON_UTF8_DATA_BYTES); - assertEquals(NAIRealmDataTestUtil.TEST_REALM_DATA, NAIRealmData.parse(buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmDataTestUtil.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmDataTestUtil.java deleted file mode 100644 index 1ce304498..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmDataTestUtil.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import android.net.wifi.EAPConstants; - -import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; -import com.android.server.wifi.hotspot2.anqp.eap.CredentialType; -import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Utility class containing test data for NAI Realm Data. - */ -public class NAIRealmDataTestUtil { - /** - * Raw bytes for EAP Method. - */ - private static final byte[] TEST_EAP_METHOD_BYTES = - new byte[] {0x05 /* length */, 0x0D /* EAP_TLS */, 0x01 /* Auth Param Count */, - 0x05 /* CredentialType */, 0x01, 0x02 /* USIM */}; - - /** - * NAI Realm strings. - */ - private static final String[] TEST_REALMS = new String[] {"test1", "test2"}; - - /** - * Setup expected EAPMethod list. - */ - private static final Map<Integer, Set<AuthParam>> TEST_EAP_METHOD_AUTH_PARAMS = - new HashMap<>(); - private static final Set<AuthParam> TEST_EAP_METHOD_CREDENTIAL_TYPE_PARAMS = new HashSet<>(); - private static final List<EAPMethod> TEST_EAP_METHOD_LIST = new ArrayList<>(); - static { - TEST_EAP_METHOD_CREDENTIAL_TYPE_PARAMS.add(new CredentialType( - AuthParam.PARAM_TYPE_CREDENTIAL_TYPE, CredentialType.CREDENTIAL_TYPE_USIM)); - TEST_EAP_METHOD_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_CREDENTIAL_TYPE, - TEST_EAP_METHOD_CREDENTIAL_TYPE_PARAMS); - - TEST_EAP_METHOD_LIST.add(new EAPMethod(EAPConstants.EAP_TLS, TEST_EAP_METHOD_AUTH_PARAMS)); - } - - /** - * Setup expected NAIRealmData. - */ - public static final NAIRealmData TEST_REALM_DATA = - new NAIRealmData(Arrays.asList(TEST_REALMS), TEST_EAP_METHOD_LIST); - - public static byte[] TEST_REAML_WITH_UTF8_DATA_BYTES = formatNAIRealmData(true); - public static byte[] TEST_REAML_WITH_NON_UTF8_DATA_BYTES = formatNAIRealmData(false); - - /** - * Helper function for returning raw bytes of NAI Realm Data (including the length field) for - * testing. - * - * @param utfEncoding Flag indicating the UTF encoding of the realm string - * @return byte[] - */ - private static byte[] formatNAIRealmData(boolean utfEncoding) { - try { - byte[] realmData = getNAIRealmData(utfEncoding); - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - // Realm Data length in Little-Endian. - stream.write((byte) realmData.length); - stream.write((byte) realmData.length >> 8); - stream.write(realmData); - return stream.toByteArray(); - } catch (IOException e) { - return null; - } - } - - /** - * Helper function for returning raw bytes of NAI Realm Data payload. - * - * @param utfEncoding Flag indicating the encoding of NAI Realm string - * @return byte[] - * @throws IOException - */ - private static byte[] getNAIRealmData(boolean utfEncoding) throws IOException { - String realmsStr = String.join(NAIRealmData.NAI_REALM_STRING_SEPARATOR, TEST_REALMS); - byte[] realmStrData = realmsStr.getBytes( - utfEncoding ? StandardCharsets.UTF_8 : StandardCharsets.US_ASCII); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - // NAI Realm Encoding byte. - stream.write((byte) (utfEncoding ? NAIRealmData.NAI_ENCODING_UTF8_MASK : 0)); - stream.write((byte) realmStrData.length); - stream.write(realmStrData); - stream.write((byte) 1); // EAP Method count - stream.write(TEST_EAP_METHOD_BYTES); - return stream.toByteArray(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmElementTest.java deleted file mode 100644 index 6e0c87a3c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/NAIRealmElementTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.NAIRealmElement}. - */ -@SmallTest -public class NAIRealmElementTest extends WifiBaseTest { - /** - * Helper function for returning a ByteBuffer containing raw bytes for NAI Realm Element - * with specified number of NAI Realm Data. - * - * @param dataCount The number of NAI Realm Data to be added to the buffer - * @return {@link ByteBuffer} - */ - private static ByteBuffer getTestBufferWithNAIRealmData(int dataCount) { - int dataLength = NAIRealmDataTestUtil.TEST_REAML_WITH_UTF8_DATA_BYTES.length * dataCount; - // 2-bytes for the NAI Realm Data count header. - ByteBuffer buffer = ByteBuffer.allocate(dataLength + 2).order(ByteOrder.LITTLE_ENDIAN); - buffer.putShort((short) dataCount); - for (int i = 0; i < dataCount; i++) { - buffer.put(NAIRealmDataTestUtil.TEST_REAML_WITH_UTF8_DATA_BYTES); - } - buffer.position(0); - return buffer; - } - - /** - * Verify that a NAIRealmElement with an empty NAIRealmData list will be returned when parsing - * from an empty buffer. - * - * @throws Exception - */ - @Test - public void parseEmptyBuffer() throws Exception { - assertTrue(NAIRealmElement.parse( - ByteBuffer.wrap(new byte[0])).getRealmDataList().isEmpty()); - } - - /** - * Verify that an expected NAIRealmElement will be returned when parsing a buffer containing - * a NAI Realm Element with single NAI Realm Data. - * - * @throws Exception - */ - @Test - public void parseBufferWithSingleNAIRealmData() throws Exception { - // Setup expected NAIRealmElement. - List<NAIRealmData> realmDataList = new ArrayList<>(); - realmDataList.add(NAIRealmDataTestUtil.TEST_REALM_DATA); - NAIRealmElement expected = new NAIRealmElement(realmDataList); - - assertEquals(expected, NAIRealmElement.parse(getTestBufferWithNAIRealmData(1))); - } - - /** - * Verify that an expected NAIRealmElement will be returned when parsing a buffer containing - * a NAI Realm Element with multiple NAI Realm Data. - * - * @throws Exception - */ - @Test - public void parseBufferWithMultipleNAIRealmData() throws Exception { - // Setup expected NAIRealmElement. - List<NAIRealmData> realmDataList = new ArrayList<>(); - realmDataList.add(NAIRealmDataTestUtil.TEST_REALM_DATA); - realmDataList.add(NAIRealmDataTestUtil.TEST_REALM_DATA); - NAIRealmElement expected = new NAIRealmElement(realmDataList); - - assertEquals(expected, NAIRealmElement.parse(getTestBufferWithNAIRealmData(2))); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/OsuProviderInfoTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/OsuProviderInfoTest.java deleted file mode 100644 index 7dea30be0..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/OsuProviderInfoTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.OsuProviderInfo}. - */ -@SmallTest -public class OsuProviderInfoTest extends WifiBaseTest { - /** - * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - OsuProviderInfo.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap( - OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO_RAW_BYTES); - buffer.limit(buffer.remaining() - 1); - OsuProviderInfo.parse(buffer); - } - - /** - * Verify that ProtocolException will be thrown when parsing a buffer containing an - * invalid length value. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithInvalidLength() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap( - OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO_RAW_BYTES_WITH_INVALID_LENGTH); - OsuProviderInfo.parse(buffer); - } - - /** - * Verify that an expected {@link OsuProviderInfo} will be returned when parsing a buffer - * containing pre-defined test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap( - OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO_RAW_BYTES); - assertEquals(OsuProviderInfoTestUtil.TEST_OSU_PROVIDER_INFO, - OsuProviderInfo.parse(buffer)); - } - - /** - * Verify that when a provider contained multiple friendly names in different languages, the - * friendly name that's in default language is returned. - * - * @throws Exception - */ - @Test - public void getFriendlyNameMatchingDefaultLocale() throws Exception { - List<I18Name> friendlyNames = new ArrayList<>(); - Locale defaultLocale = Locale.getDefault(); - Locale nonDefaultLocale = Locale.FRENCH; - if (defaultLocale.equals(nonDefaultLocale)) { - nonDefaultLocale = Locale.ENGLISH; - } - String nonDefaultString = "Non-default"; - String defaultString = "Default"; - friendlyNames.add( - new I18Name(nonDefaultLocale.getLanguage(), nonDefaultLocale, nonDefaultString)); - friendlyNames.add(new I18Name(defaultLocale.getLanguage(), defaultLocale, defaultString)); - OsuProviderInfo providerInfo = - new OsuProviderInfo(friendlyNames, null, null, null, null, null); - assertEquals(defaultString, providerInfo.getFriendlyName()); - } - - /** - * Verify that when a provider contained multiple friendly names where no friendly name - * is in default language, the first name in the list is returned. - * - * @throws Exception - */ - @Test - public void getFriendlyNameNotMatchingDefaultLocale() throws Exception { - List<I18Name> friendlyNames = new ArrayList<>(); - Locale nonDefaultLocale = Locale.FRENCH; - if (nonDefaultLocale.equals(Locale.getDefault())) { - nonDefaultLocale = Locale.ENGLISH; - } - String firstString = "First name"; - String secondString = "Second name"; - friendlyNames.add( - new I18Name(nonDefaultLocale.getLanguage(), nonDefaultLocale, firstString)); - friendlyNames.add( - new I18Name(nonDefaultLocale.getLanguage(), nonDefaultLocale, secondString)); - OsuProviderInfo providerInfo = - new OsuProviderInfo(friendlyNames, null, null, null, null, null); - assertNotNull(providerInfo.getFriendlyName()); - } - - /** - * Verify that null will be returned for a provider containing empty friendly name list. - * - * @throws Exception - */ - @Test - public void getFriendlyNameWithEmptyList() throws Exception { - OsuProviderInfo providerInfo = - new OsuProviderInfo(new ArrayList<I18Name>(), null, null, null, null, null); - assertEquals(null, providerInfo.getFriendlyName()); - } - - /** - * Verify that when a provider contained multiple service descriptions in different languages, - * the service description that's in default language is returned. - * - * @throws Exception - */ - @Test - public void getServiceDescriptionMatchingDefaultLocale() throws Exception { - List<I18Name> serviceDescriptions = new ArrayList<>(); - Locale defaultLocale = Locale.getDefault(); - Locale nonDefaultLocale = Locale.FRENCH; - if (defaultLocale.equals(nonDefaultLocale)) { - nonDefaultLocale = Locale.ENGLISH; - } - String nonDefaultString = "Non-default"; - String defaultString = "Default"; - serviceDescriptions.add( - new I18Name(nonDefaultLocale.getLanguage(), nonDefaultLocale, nonDefaultString)); - serviceDescriptions.add( - new I18Name(defaultLocale.getLanguage(), defaultLocale, defaultString)); - OsuProviderInfo providerInfo = - new OsuProviderInfo(null, null, null, null, null, serviceDescriptions); - assertEquals(defaultString, providerInfo.getServiceDescription()); - } - - /** - * Verify that when a provider contained multiple service descriptions where none of them - * is in default language, the first element in the list is returned. - * - * @throws Exception - */ - @Test - public void getServiceDescriptionNotMatchingDefaultLocale() throws Exception { - List<I18Name> serviceDescriptions = new ArrayList<>(); - Locale nonDefaultLocale = Locale.FRENCH; - if (nonDefaultLocale.equals(Locale.getDefault())) { - nonDefaultLocale = Locale.ENGLISH; - } - String firstString = "First name"; - String secondString = "Second name"; - serviceDescriptions.add( - new I18Name(nonDefaultLocale.getLanguage(), nonDefaultLocale, firstString)); - serviceDescriptions.add( - new I18Name(nonDefaultLocale.getLanguage(), nonDefaultLocale, secondString)); - OsuProviderInfo providerInfo = - new OsuProviderInfo(null, null, null, null, null, serviceDescriptions); - assertEquals(firstString, providerInfo.getServiceDescription()); - } - - /** - * Verify that null will be returned for a provider containing empty friendly name list. - * - * @throws Exception - */ - @Test - public void getServiceDescriptionWithEmptyList() throws Exception { - OsuProviderInfo providerInfo = - new OsuProviderInfo(null, null, null, null, null, new ArrayList<I18Name>()); - assertEquals(null, providerInfo.getServiceDescription()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/OsuProviderInfoTestUtil.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/OsuProviderInfoTestUtil.java deleted file mode 100644 index e1bbe6345..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/OsuProviderInfoTestUtil.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.hotspot2.anqp; - -import android.net.Uri; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -/** - * Utility class containing test data and object for {@link OsuProviderInfo}. - */ -public class OsuProviderInfoTestUtil { - // Test data - private static final List<I18Name> TEST_FRIENDLY_NAMES = - Arrays.asList(new I18Name("en", Locale.forLanguageTag("en"), "FriendlyName")); - private static final String TEST_SERVER_URI = "https://test.server.com"; - private static final List<Integer> TEST_METHOD_LIST = Arrays.asList(0, 1); - private static final List<IconInfo> TEST_ICON_INFO_LIST = - Arrays.asList(IconInfoTestUtil.TEST_ICON_INFO); - private static final String TEST_NAI = "network_access@test.com"; - private static final List<I18Name> TEST_SERVICE_DESCRIPTIONS = - Arrays.asList(new I18Name("en", Locale.forLanguageTag("en"), "Test Service")); - - /** - * {@link IconInfo} object with pre-defined test data. - */ - public static final OsuProviderInfo TEST_OSU_PROVIDER_INFO = - new OsuProviderInfo(TEST_FRIENDLY_NAMES, Uri.parse(TEST_SERVER_URI), TEST_METHOD_LIST, - TEST_ICON_INFO_LIST, TEST_NAI, TEST_SERVICE_DESCRIPTIONS); - - /** - * Raw bytes of icon info with pre-defined test data. - */ - public static final byte[] TEST_OSU_PROVIDER_INFO_RAW_BYTES = getTestData(); - - public static final byte[] TEST_OSU_PROVIDER_INFO_RAW_BYTES_WITH_INVALID_LENGTH = - getTestDataWithInvalidLength(); - - /** - * Generate and return the raw data based on pre-defined test data. - * - * @return byte[] - */ - private static byte[] getTestData() { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] payload = getTestPayload(); - writeShortLE(out, payload.length); - out.write(payload); - return out.toByteArray(); - } catch (Exception e) { - return null; - } - } - - /** - * Generate and return the raw data based on pre-defined test data. - * - * @return byte[] - */ - private static byte[] getTestDataWithInvalidLength() { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] payload = getTestPayload(); - // Set length to less than the minimum required. - writeShortLE(out, OsuProviderInfo.MINIMUM_LENGTH - 1); - out.write(payload); - return out.toByteArray(); - } catch (Exception e) { - return null; - } - } - - /** - * Generate and return the payload containing OSU provider test data, excluding the length - * field. - * - * @return byte[] - * @throws IOException - */ - private static byte[] getTestPayload() throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - // Write friendly name list. - byte[] friendlyNamesData = getI18NameListData(TEST_FRIENDLY_NAMES); - writeShortLE(out, friendlyNamesData.length); - out.write(friendlyNamesData); - - // Write server URI. - writeByteArrayWithLength(out, TEST_SERVER_URI.getBytes(StandardCharsets.UTF_8)); - - // Write method list. - out.write((byte) TEST_METHOD_LIST.size()); - for (Integer method : TEST_METHOD_LIST) { - out.write((byte) method.intValue()); - } - - // Write icon info list. - writeShortLE(out, IconInfoTestUtil.TEST_ICON_INFO_RAW_BYTES.length); - out.write(IconInfoTestUtil.TEST_ICON_INFO_RAW_BYTES); - - // Write NAI. - writeByteArrayWithLength(out, TEST_NAI.getBytes(StandardCharsets.UTF_8)); - - // Write service descriptions. - byte[] serviceDescriptionsData = getI18NameListData(TEST_SERVICE_DESCRIPTIONS); - writeShortLE(out, serviceDescriptionsData.length); - out.write(serviceDescriptionsData); - - return out.toByteArray(); - } - - private static byte[] getI18NameListData(List<I18Name> nameList) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - for (I18Name name : nameList) { - byte[] data = getI18NameData(name); - out.write((byte) data.length); - out.write(data); - } - return out.toByteArray(); - } - - /** - * Format the raw bytes for the given {@link I18Name}. - * - * @param value The {@link I18Name} to serialize - * @return byte[] - * @throws IOException - */ - private static byte[] getI18NameData(I18Name value) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write(value.getLanguage().getBytes(StandardCharsets.US_ASCII)); - out.write((byte) 0); // Padding for language code. - out.write(value.getText().getBytes(StandardCharsets.UTF_8)); - return out.toByteArray(); - } - - /** - * Write the lower 2-bytes of an integer to the given output stream in Little-Endian. - * - * @param out The output stream to write to - * @param value The integer value to write - */ - private static void writeShortLE(ByteArrayOutputStream out, int value) { - out.write(value & 0xFF); - out.write((value >> 8) & 0xFF); - } - - /** - * Write the given byte array to the given output stream, the array data is prefixed with a - * byte specifying the length of the byte array. - * - * @param out The output stream to write to - * @param data The byte array to write - * @throws IOException - */ - private static void writeByteArrayWithLength(ByteArrayOutputStream out, byte[] data) - throws IOException { - out.write((byte) data.length); - out.write(data); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ProtocolPortTupleTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ProtocolPortTupleTest.java deleted file mode 100644 index ba6a79f7e..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ProtocolPortTupleTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.ProtocolPortTuple}. - */ -@SmallTest -public class ProtocolPortTupleTest extends WifiBaseTest { - private static final int TEST_PROTOCOL = 1; - private static final int TEST_PORT = 2; - private static final int TEST_STATUS = ProtocolPortTuple.PROTO_STATUS_CLOSED; - - /** - * Helper function for generating a buffer with test data. - * - * @param protocol Protocol value - * @param port Port value - * @param status Status value - * @return {@link ByteBuffer} - */ - private ByteBuffer getTestBuffer(int protocol, int port, int status) { - ByteBuffer buffer = ByteBuffer.allocate(ProtocolPortTuple.RAW_BYTE_SIZE) - .order(ByteOrder.LITTLE_ENDIAN); - buffer.put((byte) protocol); - buffer.putShort((short) port); - buffer.put((byte) status); - buffer.position(0); - return buffer; - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - ProtocolPortTuple.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a buffer without - * the complete tuple data (missing status field). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseBufferWithIncompleteData() throws Exception { - ByteBuffer buffer = ByteBuffer.allocate(ProtocolPortTuple.RAW_BYTE_SIZE - 1); - buffer.put(new byte[ProtocolPortTuple.RAW_BYTE_SIZE - 1]); - buffer.position(0); - ProtocolPortTuple.parse(buffer); - } - - /** - * Verify that the expected ProtocolPortTuple is returned when parsing a buffer contained - * the test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - ByteBuffer buffer = getTestBuffer(TEST_PROTOCOL, TEST_PORT, TEST_STATUS); - ProtocolPortTuple expected = new ProtocolPortTuple(TEST_PROTOCOL, TEST_PORT, TEST_STATUS); - assertEquals(expected, ProtocolPortTuple.parse(buffer)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RawByteElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RawByteElementTest.java deleted file mode 100644 index dd78f3333..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RawByteElementTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.RawByteElement}. - */ -@SmallTest -public class RawByteElementTest extends WifiBaseTest { - private static final Constants.ANQPElementType TEST_ELEMENT_ID = - Constants.ANQPElementType.HSOSUProviders; - - /** - * Verify that a RawByteElement with an empty payload will be returned when parsing - * an empty buffer. - * - * @throws Exception - */ - @Test - public void parseEmptyBuffer() throws Exception { - byte[] data = new byte[0]; - RawByteElement actual = RawByteElement.parse(TEST_ELEMENT_ID, ByteBuffer.wrap(data)); - RawByteElement expected = new RawByteElement(TEST_ELEMENT_ID, data); - assertEquals(expected, actual); - } - - /** - * Verify that the expected RawByteElement will be returned when parsing a non-empty - * buffer. - * - * @throws Exception - */ - @Test - public void parseNonEmptyBuffer() throws Exception { - byte[] data = new byte[10]; - RawByteElement actual = RawByteElement.parse(TEST_ELEMENT_ID, ByteBuffer.wrap(data)); - RawByteElement expected = new RawByteElement(TEST_ELEMENT_ID, data); - assertEquals(expected, actual); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElementTest.java deleted file mode 100644 index 2df578a40..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElementTest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement}. - */ -@SmallTest -public class RoamingConsortiumElementTest extends WifiBaseTest { - // Default test data. Each test data contained a pair indicating the number of bytes for the - // OI and the value of the OI. - private static final Pair<Integer, Long> TEST_OI1 = new Pair<Integer, Long>(1, 0x12L); - private static final Pair<Integer, Long> TEST_OI2 = new Pair<Integer, Long>(2, 0x1234L); - private static final Pair<Integer, Long> TEST_OI3 = new Pair<Integer, Long>(4, 0x12345678L); - private static final Pair<Integer, Long> TEST_OI4 = new Pair<Integer, Long>(8, 0x1234567890L); - - /** - * Helper function for appending an OI field to the given output stream. - * - * @param stream The output stream to write to - * @param OI The OI to write to the output stream - */ - private void appendOI(ByteArrayOutputStream stream, Pair<Integer, Long> oi) { - stream.write(oi.first.byteValue()); - // Write the OI data in big-endian. - for (int i = oi.first.intValue() - 1; i >= 0; i--) { - stream.write((byte) ((oi.second.longValue() >> i * Byte.SIZE) & 0xFF)); - } - } - /** - * Helper function for generating test data with the provided OIs. - * - * @param OIs The OIs to generate the data with - * @return byte[] of data - * @throws IOException - */ - private byte[] getTestData(List<Pair<Integer, Long>> ois) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - for (Pair<Integer, Long> oi : ois) { - appendOI(stream, oi); - } - return stream.toByteArray(); - } - - /** - * Helper function for generating test data using the predefined OIs. - * - * @return byte[] of data - * @throws IOException - */ - private byte[] getDefaultTestData() throws IOException { - List<Pair<Integer, Long>> oiList = new ArrayList<>(); - oiList.add(TEST_OI1); - oiList.add(TEST_OI2); - oiList.add(TEST_OI3); - oiList.add(TEST_OI4); - return getTestData(oiList); - } - - /** - * Helper function for creating a RoamingConsortiumElement using the predefined OIs. - * - * @return {@link RoamingConsortiumElement} - */ - private RoamingConsortiumElement getDefaultElement() { - List<Long> oiList = new ArrayList<>(); - oiList.add(TEST_OI1.second); - oiList.add(TEST_OI2.second); - oiList.add(TEST_OI3.second); - oiList.add(TEST_OI4.second); - return new RoamingConsortiumElement(oiList); - } - - /** - * Verify that no exception will be thrown when parsing an empty buffer and the returned - * RoamingConsortiumElement will contained an empty list of OIs. - * - * @throws Exception - */ - @Test - public void parseEmptyBuffer() throws Exception { - RoamingConsortiumElement element = RoamingConsortiumElement.parse(ByteBuffer.allocate(0)); - assertTrue(element.getOIs().isEmpty()); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(getDefaultTestData()); - buffer.limit(buffer.remaining() - 1); - RoamingConsortiumElement.parse(buffer); - } - - /** - * Verify that an expected RoamingConsortiumElement will be returned when parsing a buffer - * containing valid data. - * - * @throws Exception - */ - @Test - public void parseBufferWithDefaultTestData() throws Exception { - // Setup expected element. - RoamingConsortiumElement expectedElement = getDefaultElement(); - - ByteBuffer buffer = ByteBuffer.wrap(getDefaultTestData()); - assertEquals(expectedElement, RoamingConsortiumElement.parse(buffer)); - } - - /** - * Verify that ProtocolException will be thrown when parsing a buffer contained an OI length - * that's less than minimum allowed. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithOILengthLessThanMinimum() throws Exception { - ByteBuffer buffer = ByteBuffer.allocate(1); - buffer.put((byte) (RoamingConsortiumElement.MINIMUM_OI_LENGTH - 1)); - buffer.position(0); - RoamingConsortiumElement.parse(buffer); - } - - /** - * Verify that ProtocolException will be thrown when parsing a buffer contained an OI length - * that's more than maximum allowed. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithOILengthMoreThanMaximum() throws Exception { - ByteBuffer buffer = ByteBuffer.allocate(1); - buffer.put((byte) (RoamingConsortiumElement.MAXIMUM_OI_LENGTH + 1)); - buffer.position(0); - RoamingConsortiumElement.parse(buffer); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElementTest.java deleted file mode 100644 index 8a036e068..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElementTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement}. - */ -@SmallTest -public class ThreeGPPNetworkElementTest extends WifiBaseTest { - private static final byte[][] TEST_NETWORK1_PLMN_BYTES = - new byte[][] { new byte[] {0x21, 0x63, 0x54}, - new byte[] {0x43, (byte) 0x85, 0x76} }; - private static final List<String> TEST_NETWORK1_PLMN_LIST = new ArrayList<>(); - static { - TEST_NETWORK1_PLMN_LIST.add("123456"); - TEST_NETWORK1_PLMN_LIST.add("345678"); - } - private static final CellularNetwork TEST_NETWORK1 = - new CellularNetwork(TEST_NETWORK1_PLMN_LIST); - - private static final byte[][] TEST_NETWORK2_PLMN_BYTES = - new byte[][] { new byte[] {(byte) 0x87, 0x29, 0x10}, - new byte[] {0x62, (byte) 0xF5, 0x73} }; - private static final List<String> TEST_NETWORK2_PLMN_LIST = new ArrayList<>(); - static { - TEST_NETWORK2_PLMN_LIST.add("789012"); - TEST_NETWORK2_PLMN_LIST.add("26537"); - } - private static final CellularNetwork TEST_NETWORK2 = - new CellularNetwork(TEST_NETWORK2_PLMN_LIST); - - /** - * Helper function for generating test data. - * - * @param version The GUD version number - * @param ieiList The array containing IEI data - * @return byte[] - * @throws IOException - */ - private static byte[] getTestData(int version, byte[][] ieiList) - throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - int totalIeiSize = CellularNetworkTestUtil.getDataSize(ieiList); - stream.write((byte) version); - stream.write((byte) totalIeiSize); - for (byte[] iei : ieiList) { - stream.write(iei); - } - return stream.toByteArray(); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseBufferWithEmptyBuffer() throws Exception { - ThreeGPPNetworkElement.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that ProtocolException will be thrown when parsing an buffer contained - * an unsupported version number. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithUnsupportedVersionNumber() throws Exception { - byte[][] testIeiList = new byte[][] { - CellularNetworkTestUtil.formatPLMNListIEI(TEST_NETWORK1_PLMN_BYTES) }; - byte[] testData = getTestData(1, testIeiList); - ThreeGPPNetworkElement.parse(ByteBuffer.wrap(testData)); - } - - /** - * Verify that Protocol will be thrown when parsing a truncated buffer (missing a - * byte at the end), which will cause a inconsistency between the length value and - * the buffer size. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithIncompleteData() throws Exception { - byte[][] testIeiList = new byte[][] { - CellularNetworkTestUtil.formatPLMNListIEI(TEST_NETWORK1_PLMN_BYTES) }; - byte[] testData = getTestData(ThreeGPPNetworkElement.GUD_VERSION_1, testIeiList); - ThreeGPPNetworkElement.parse(ByteBuffer.wrap(testData, 0, testData.length - 1)); - } - - /** - * Verify that the expected ThreeGPPNetworkElement is returned when parsing a buffer contained - * the test data. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData() throws Exception { - byte[][] testIeiList = new byte[][] { - CellularNetworkTestUtil.formatPLMNListIEI(TEST_NETWORK1_PLMN_BYTES), - CellularNetworkTestUtil.formatPLMNListIEI(TEST_NETWORK2_PLMN_BYTES) }; - byte[] testData = getTestData(ThreeGPPNetworkElement.GUD_VERSION_1, testIeiList); - - // Setup the expected ThreeGPPNetworkElement. - List<CellularNetwork> networkList = new ArrayList<>(); - networkList.add(TEST_NETWORK1); - networkList.add(TEST_NETWORK2); - ThreeGPPNetworkElement expected = new ThreeGPPNetworkElement(networkList); - - assertEquals(expected, ThreeGPPNetworkElement.parse(ByteBuffer.wrap(testData))); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/VenueNameElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/VenueNameElementTest.java deleted file mode 100644 index 3bfcd69ff..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/VenueNameElementTest.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.VenueNameElement}. - */ -@SmallTest -public class VenueNameElementTest extends WifiBaseTest { - private static final String TEST_LANGUAGE = "en"; - private static final Locale TEST_LOCALE = Locale.forLanguageTag(TEST_LANGUAGE); - private static final String TEST_VENUE_NAME1 = "Venue1"; - private static final String TEST_VENUE_NAME2 = "Venue2"; - - /** - * Helper function for appending a Venue Name to an output stream. - * - * @param stream Stream to write to - * @param venue The venue name string - * @throws IOException - */ - private void appendVenue(ByteArrayOutputStream stream, String venue) throws IOException { - byte[] venueBytes = venue.getBytes(StandardCharsets.UTF_8); - int length = I18Name.LANGUAGE_CODE_LENGTH + venue.length(); - stream.write((byte) length); - stream.write(TEST_LANGUAGE.getBytes(StandardCharsets.US_ASCII)); - stream.write(new byte[]{(byte) 0x0}); // Padding for language code. - stream.write(venueBytes); - } - - /** - * Helper function for generating test data. - * - * @return byte[] of data - * @throws IOException - */ - private byte[] getTestData(String[] names) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - // Venue info data not currently used. - stream.write(new byte[VenueNameElement.VENUE_INFO_LENGTH]); - for (String name : names) { - appendVenue(stream, name); - } - return stream.toByteArray(); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - VenueNameElement.parse(ByteBuffer.allocate(0)); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[] {TEST_VENUE_NAME1})); - // Truncate a byte at the end. - buffer.limit(buffer.remaining() - 1); - VenueNameElement.parse(buffer); - } - - /** - * Verify that a VenueNameElement with empty name list will be returned when parsing a buffer - * contained no venue name (only contained the venue info data). - * - * @throws Exception - */ - @Test - public void parseBufferWithEmptyVenueName() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[0])); - assertTrue(VenueNameElement.parse(buffer).getNames().isEmpty()); - } - /** - * Verify that an expected VenueNameElement will be returned when parsing a buffer contained - * valid Venue Name data. - * - * @throws Exception - */ - @Test - public void parseBufferWithValidVenueNames() throws Exception { - // Setup expected element. - List<I18Name> nameList = new ArrayList<>(); - nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_VENUE_NAME1)); - nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_VENUE_NAME2)); - VenueNameElement expectedElement = new VenueNameElement(nameList); - - ByteBuffer buffer = ByteBuffer.wrap( - getTestData(new String[] {TEST_VENUE_NAME1, TEST_VENUE_NAME2})); - assertEquals(expectedElement, VenueNameElement.parse(buffer)); - } - - /** - * Verify that an expected VenueNameElement will be returned when parsing a buffer - * contained a venue name with the maximum length. - * - * @throws Exception - */ - @Test - public void parseBufferWithMaxLengthVenueName() throws Exception { - // Venue name with maximum length. - byte[] textData = new byte[VenueNameElement.MAXIMUM_VENUE_NAME_LENGTH]; - Arrays.fill(textData, (byte) 'a'); - String text = new String(textData); - ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[] {text})); - - // Setup expected element. - List<I18Name> nameList = new ArrayList<>(); - nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, text)); - VenueNameElement expectedElement = new VenueNameElement(nameList); - - assertEquals(expectedElement, VenueNameElement.parse(buffer)); - } - - /** - * Verify that ProtocolException will be thrown when parsing a buffer contained a - * venue name that exceeds the maximum length. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithVenueNameLengthExceedMax() throws Exception { - byte[] textData = new byte[VenueNameElement.MAXIMUM_VENUE_NAME_LENGTH + 1]; - Arrays.fill(textData, (byte) 'a'); - String text = new String(textData); - ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[] {text})); - VenueNameElement.parse(buffer); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/CredentialTypeTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/CredentialTypeTest.java deleted file mode 100644 index d130571b7..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/CredentialTypeTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.eap.CredentialType}. - */ -@SmallTest -public class CredentialTypeTest extends WifiBaseTest { - private static final int TEST_TYPE = CredentialType.CREDENTIAL_TYPE_USIM; - - /** - * Helper function for generating the test buffer. - * - * @return {@link ByteBuffer} - */ - private ByteBuffer getTestBuffer() { - return ByteBuffer.wrap(new byte[] {(byte) TEST_TYPE}); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing from an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - CredentialType.parse( - ByteBuffer.wrap(new byte[0]), CredentialType.EXPECTED_LENGTH_VALUE, false); - } - - /** - * Verify that ProtocolException will be thrown when the data length value is not the same - * as the expected - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithInvalidLength() throws Exception { - CredentialType.parse(getTestBuffer(), CredentialType.EXPECTED_LENGTH_VALUE - 1, false); - } - - /** - * Verify that an expected CredentialType is returned when parsing the buffer for a - * non-tunneled EAP method. - * - * @throws Exception - */ - @Test - public void parseBufferForNonTunneledEAPMethod() throws Exception { - CredentialType expected = - new CredentialType(AuthParam.PARAM_TYPE_CREDENTIAL_TYPE, TEST_TYPE); - CredentialType actual = CredentialType.parse( - getTestBuffer(), CredentialType.EXPECTED_LENGTH_VALUE, false); - assertEquals(expected, actual); - } - - /** - * Verify that an expected CredentialType is returned when parsing the buffer for a - * tunneled EAP method. - * - * @throws Exception - */ - @Test - public void parseBufferForTunneledEAPMethod() throws Exception { - CredentialType expected = new CredentialType( - AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE, TEST_TYPE); - CredentialType actual = CredentialType.parse( - getTestBuffer(), CredentialType.EXPECTED_LENGTH_VALUE, true); - assertEquals(expected, actual); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/EAPMethodTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/EAPMethodTest.java deleted file mode 100644 index 69c20d5d5..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/EAPMethodTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import static org.junit.Assert.assertEquals; - -import android.net.wifi.EAPConstants; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.eap.EAPMethod}. - */ -@SmallTest -public class EAPMethodTest extends WifiBaseTest { - /** - * Setup basic test data - contained multiple parameters of the same type. - */ - private static final byte[] TEST_DATA1_BYTES = - new byte[] {0x0B /* length */, 0x0D /* EAP_TLS */, 0x03 /* Auth Param Count */, - 0x05 /* CredentialType */, 0x01, 0x02 /* USIM */, - 0x05 /* CredentialType */, 0x01, 0x06 /* Certificate */, - 0x06 /* Tunneled CredentialType */, 0x01, 0x03 /* NFC */}; - private static final Map<Integer, Set<AuthParam>> TEST_DATA1_AUTH_PARAMS = - new HashMap<>(); - private static final Set<AuthParam> TEST_DATA1_CREDENTIAL_TYPE_PARAMS = new HashSet<>(); - private static final Set<AuthParam> TEST_DATA1_TUNNELED_CREDENTIAL_TYPE_PARAMS = - new HashSet<>(); - static { - TEST_DATA1_CREDENTIAL_TYPE_PARAMS.add(new CredentialType( - AuthParam.PARAM_TYPE_CREDENTIAL_TYPE, CredentialType.CREDENTIAL_TYPE_USIM)); - TEST_DATA1_CREDENTIAL_TYPE_PARAMS.add(new CredentialType( - AuthParam.PARAM_TYPE_CREDENTIAL_TYPE, CredentialType.CREDENTIAL_TYPE_CERTIFICATE)); - - TEST_DATA1_TUNNELED_CREDENTIAL_TYPE_PARAMS.add(new CredentialType( - AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE, - CredentialType.CREDENTIAL_TYPE_NFC)); - - TEST_DATA1_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_CREDENTIAL_TYPE, - TEST_DATA1_CREDENTIAL_TYPE_PARAMS); - TEST_DATA1_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE, - TEST_DATA1_TUNNELED_CREDENTIAL_TYPE_PARAMS); - } - private static final EAPMethod TEST_DATA1_EAP_METHOD = new EAPMethod( - EAPConstants.EAP_TLS, TEST_DATA1_AUTH_PARAMS); - - /** - * Setup test data for testing an EAP Method containing all types of authentication parameters. - */ - private static final byte[] TEST_DATA2_BYTES = - new byte[] {0x26 /* length */, 0x0D /* EAP_TLS */, 0x07, - // Expanded EAP Method - 0x01, 0x07, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, - // Non-EAP Inner Auth Type - 0x02, 0x01, 0x03 /* AUTH_TYPE_MSCHAP */, - // Inner Auth EAP Method - 0x03, 0x01, 0x1D /* EAP_PEAP */, - // Expanded Inner EAP Method - 0x04, 0x07, 0x01, 0x23, 0x45, 0x56, 0x78, 0x56, 0x12, - // Credential Type - 0x05, 0x01, 0x02 /* USIM */, - // Tunneled Credential Type - 0x06, 0x01, 0x03 /* NFC */, - // Vendor Specific - (byte) 0xDD, 0x04, 0x12, 0x23, 0x45, 0x56}; - private static final Map<Integer, Set<AuthParam>> TEST_DATA2_AUTH_PARAMS = - new HashMap<>(); - private static final Set<AuthParam> TEST_DATA2_EXPANDED_EAP_METHOD_PARAMS = new HashSet<>(); - private static final Set<AuthParam> TEST_DATA2_NON_EAP_INNER_AUTH_PARAMS = new HashSet<>(); - private static final Set<AuthParam> TEST_DATA2_INNER_AUTH_EAP_PARAMS = new HashSet<>(); - private static final Set<AuthParam> TEST_DATA2_EXPANDED_INNER_EAP_PARAMS = new HashSet<>(); - private static final Set<AuthParam> TEST_DATA2_CREDENTIAL_TYPE_PARAMS = new HashSet<>(); - private static final Set<AuthParam> TEST_DATA2_TUNNELED_CREDENTIAL_TYPE_PARAMS = - new HashSet<>(); - private static final Set<AuthParam> TEST_DATA2_VENDOR_SPECIFIC_PARAMS = new HashSet<>(); - static { - TEST_DATA2_EXPANDED_EAP_METHOD_PARAMS.add(new ExpandedEAPMethod( - AuthParam.PARAM_TYPE_EXPANDED_EAP_METHOD, 0x122334, 0x45566778L)); - TEST_DATA2_NON_EAP_INNER_AUTH_PARAMS.add(new NonEAPInnerAuth( - NonEAPInnerAuth.AUTH_TYPE_MSCHAP)); - TEST_DATA2_INNER_AUTH_EAP_PARAMS.add(new InnerAuthEAP(EAPConstants.EAP_PEAP)); - TEST_DATA2_EXPANDED_INNER_EAP_PARAMS.add(new ExpandedEAPMethod( - AuthParam.PARAM_TYPE_EXPANDED_INNER_EAP_METHOD, 0x012345, 0x56785612L)); - TEST_DATA2_CREDENTIAL_TYPE_PARAMS.add(new CredentialType( - AuthParam.PARAM_TYPE_CREDENTIAL_TYPE, CredentialType.CREDENTIAL_TYPE_USIM)); - TEST_DATA2_TUNNELED_CREDENTIAL_TYPE_PARAMS.add(new CredentialType( - AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE, - CredentialType.CREDENTIAL_TYPE_NFC)); - TEST_DATA2_VENDOR_SPECIFIC_PARAMS.add(new VendorSpecificAuth( - new byte[] {0x12, 0x23, 0x45, 0x56})); - - TEST_DATA2_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_EXPANDED_EAP_METHOD, - TEST_DATA2_EXPANDED_EAP_METHOD_PARAMS); - TEST_DATA2_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_NON_EAP_INNER_AUTH_TYPE, - TEST_DATA2_NON_EAP_INNER_AUTH_PARAMS); - TEST_DATA2_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_INNER_AUTH_EAP_METHOD_TYPE, - TEST_DATA2_INNER_AUTH_EAP_PARAMS); - TEST_DATA2_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_EXPANDED_INNER_EAP_METHOD, - TEST_DATA2_EXPANDED_INNER_EAP_PARAMS); - TEST_DATA2_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_CREDENTIAL_TYPE, - TEST_DATA2_CREDENTIAL_TYPE_PARAMS); - TEST_DATA2_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE, - TEST_DATA2_TUNNELED_CREDENTIAL_TYPE_PARAMS); - TEST_DATA2_AUTH_PARAMS.put(AuthParam.PARAM_TYPE_VENDOR_SPECIFIC, - TEST_DATA2_VENDOR_SPECIFIC_PARAMS); - } - private static final EAPMethod TEST_DATA2_EAP_METHOD = new EAPMethod( - EAPConstants.EAP_TLS, TEST_DATA2_AUTH_PARAMS); - - /** - * Verify that BufferUnderflowException will be thrown when parsing from an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - EAPMethod.parse(ByteBuffer.wrap(new byte[0])); - } - - /** - * Verify that ProtocolException will be thrown when parsing a truncated buffer - * (missing a byte at the end). - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseTruncatedBuffer() throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(TEST_DATA1_BYTES, 0, TEST_DATA1_BYTES.length - 1); - EAPMethod.parse(buffer); - } - - /** - * Verify that the expected EAPMethod is return when parsing a buffer contained - * {@link #TEST_DATA1_BYTES}. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData1() throws Exception { - assertEquals(TEST_DATA1_EAP_METHOD, EAPMethod.parse(ByteBuffer.wrap(TEST_DATA1_BYTES))); - } - - /** - * Verify that the expected EAPMethod is return when parsing a buffer contained - * {@link #TEST_DATA2_BYTES}. - * - * @throws Exception - */ - @Test - public void parseBufferWithTestData2() throws Exception { - assertEquals(TEST_DATA2_EAP_METHOD, EAPMethod.parse(ByteBuffer.wrap(TEST_DATA2_BYTES))); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethodTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethodTest.java deleted file mode 100644 index a2c92fd9a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethodTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.eap.ExpandedEAPMethod}. - */ -@SmallTest -public class ExpandedEAPMethodTest extends WifiBaseTest { - private static final int TEST_VENDOR_ID = 0x123456; - private static final long TEST_VENDOR_TYPE = 0x23456523; - private static final byte[] TEST_DATA_BYTES = - new byte[] {0x12, 0x34, 0x56, 0x23, 0x45, 0x65, 0x23}; - - /** - * Verify that BufferUnderflowException will be thrown when parsing from an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - ExpandedEAPMethod.parse( - ByteBuffer.wrap(new byte[0]), ExpandedEAPMethod.EXPECTED_LENGTH_VALUE, false); - } - - /** - * Verify that ProtocolException will be thrown when the data length is not the expected - * length. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithInvalidLength() throws Exception { - ExpandedEAPMethod.parse(ByteBuffer.wrap(TEST_DATA_BYTES), - ExpandedEAPMethod.EXPECTED_LENGTH_VALUE - 1, false); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseBufferWithTruncatedBuffer() throws Exception { - ExpandedEAPMethod.parse(ByteBuffer.wrap(TEST_DATA_BYTES, 0, TEST_DATA_BYTES.length - 1), - ExpandedEAPMethod.EXPECTED_LENGTH_VALUE, false); - } - - /** - * Verify that an expected ExpandedEAPMethod is returned when parsing the buffer for a - * non-inner EAP method. - * - * @throws Exception - */ - @Test - public void parseBufferForNonInnerEAPMethod() throws Exception { - ExpandedEAPMethod expected = new ExpandedEAPMethod( - AuthParam.PARAM_TYPE_EXPANDED_EAP_METHOD, TEST_VENDOR_ID, TEST_VENDOR_TYPE); - ExpandedEAPMethod actual = ExpandedEAPMethod.parse( - ByteBuffer.wrap(TEST_DATA_BYTES), ExpandedEAPMethod.EXPECTED_LENGTH_VALUE, false); - assertEquals(expected, actual); - } - - /** - * Verify that an expected CredentialType is returned when parsing the buffer for a - * inner EAP method. - * - * @throws Exception - */ - @Test - public void parseBufferForTunneledEAPMethod() throws Exception { - ExpandedEAPMethod expected = new ExpandedEAPMethod( - AuthParam.PARAM_TYPE_EXPANDED_INNER_EAP_METHOD, TEST_VENDOR_ID, TEST_VENDOR_TYPE); - ExpandedEAPMethod actual = ExpandedEAPMethod.parse( - ByteBuffer.wrap(TEST_DATA_BYTES), ExpandedEAPMethod.EXPECTED_LENGTH_VALUE, true); - assertEquals(expected, actual); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAPTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAPTest.java deleted file mode 100644 index 6a2bc79a3..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAPTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import static org.junit.Assert.assertEquals; - -import android.net.wifi.EAPConstants; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.eap.InnerAuthEAP}. - */ -@SmallTest -public class InnerAuthEAPTest extends WifiBaseTest { - private static final int TEST_EAP_METHOD_ID = EAPConstants.EAP_TTLS; - - /** - * Helper function for generating the test buffer. - * - * @return {@link ByteBuffer} - */ - private ByteBuffer getTestBuffer() { - return ByteBuffer.wrap(new byte[] {(byte) TEST_EAP_METHOD_ID}); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing from an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - InnerAuthEAP.parse(ByteBuffer.wrap(new byte[0]), InnerAuthEAP.EXPECTED_LENGTH_VALUE); - } - - /** - * Verify that ProtocolException will be thrown when the data length is not the expected - * length. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithInvalidLength() throws Exception { - InnerAuthEAP.parse(getTestBuffer(), InnerAuthEAP.EXPECTED_LENGTH_VALUE - 1); - } - - /** - * Verify that an expected InnerAuthEAP is returned when parsing a buffer contained - * the expected EAP method ID. - * - * @throws Exception - */ - @Test - public void parseBuffer() throws Exception { - InnerAuthEAP expected = new InnerAuthEAP(TEST_EAP_METHOD_ID); - InnerAuthEAP actual = - InnerAuthEAP.parse(getTestBuffer(), InnerAuthEAP.EXPECTED_LENGTH_VALUE); - assertEquals(expected, actual); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuthTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuthTest.java deleted file mode 100644 index c3101f7e4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuthTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.net.ProtocolException; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth}. - */ -@SmallTest -public class NonEAPInnerAuthTest extends WifiBaseTest { - private static final int TEST_AUTH_TYPE = NonEAPInnerAuth.AUTH_TYPE_MSCHAP; - - /** - * Helper function for generating the test buffer. - * - * @return {@link ByteBuffer} - */ - private ByteBuffer getTestBuffer() { - return ByteBuffer.wrap(new byte[] {(byte) TEST_AUTH_TYPE}); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing from an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - NonEAPInnerAuth.parse(ByteBuffer.wrap(new byte[0]), NonEAPInnerAuth.EXPECTED_LENGTH_VALUE); - } - - /** - * Verify that ProtocolException will be thrown when the data length is not the expected - * length. - * - * @throws Exception - */ - @Test(expected = ProtocolException.class) - public void parseBufferWithInvalidLength() throws Exception { - NonEAPInnerAuth.parse(getTestBuffer(), NonEAPInnerAuth.EXPECTED_LENGTH_VALUE - 1); - } - - /** - * Verify that an expected NonEAPInnerAuth is returned when parsing a buffer contained - * the expected auth type. - * - * @throws Exception - */ - @Test - public void parseBuffer() throws Exception { - NonEAPInnerAuth expected = new NonEAPInnerAuth(TEST_AUTH_TYPE); - NonEAPInnerAuth actual = - NonEAPInnerAuth.parse(getTestBuffer(), NonEAPInnerAuth.EXPECTED_LENGTH_VALUE); - assertEquals(expected, actual); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuthTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuthTest.java deleted file mode 100644 index 3e167f847..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuthTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.hotspot2.anqp.eap; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -/** - * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.eap.VendorSpecificAuth}. - */ -@SmallTest -public class VendorSpecificAuthTest extends WifiBaseTest { - private static final byte[] TEST_DATA = new byte[] {0x12, 0x34, 0x45, 0x56}; - - /** - * Verify that BufferUnderflowException will be thrown when parsing from an empty buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseEmptyBuffer() throws Exception { - VendorSpecificAuth.parse(ByteBuffer.wrap(new byte[0]), 1); - } - - /** - * Verify that BufferUnderflowException will be thrown when parsing from a truncated buffer. - * - * @throws Exception - */ - @Test(expected = BufferUnderflowException.class) - public void parseTruncatedBuffer() throws Exception { - VendorSpecificAuth.parse( - ByteBuffer.wrap(TEST_DATA, 0, TEST_DATA.length - 1), TEST_DATA.length); - } - - /** - * Verify that a VendorSpecificAuth with a empty data array is returned when parsing - * a zero byte from a buffer. - * - * @throws Exception - */ - @Test - public void parseBufferWithZeroLength() throws Exception { - VendorSpecificAuth expected = new VendorSpecificAuth(new byte[0]); - assertEquals(expected, VendorSpecificAuth.parse(ByteBuffer.wrap(TEST_DATA), 0)); - } - - /** - * Verify that an expected VendorSpecificAuth is returned when parsing a buffer contained - * the expected data. - * - * @throws Exception - */ - @Test - public void parseBuffer() throws Exception { - VendorSpecificAuth expected = new VendorSpecificAuth(TEST_DATA); - VendorSpecificAuth actual = - VendorSpecificAuth.parse(ByteBuffer.wrap(TEST_DATA), TEST_DATA.length); - assertEquals(expected, actual); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/DevDetailMoTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/DevDetailMoTest.java deleted file mode 100644 index b1fbd37b4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/DevDetailMoTest.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.omadm; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNull; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.content.Context; -import android.os.Build; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.SystemInfo; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -/** - * Unit tests for {@link DevDetailMo}. - * TODO(b/80300806): change the test to verify the XML in terms of the structure of XML. - */ -@SmallTest -public class DevDetailMoTest extends WifiBaseTest { - private static final String TEST_DEV_ID = "12312341"; - private static final String TEST_MANUFACTURER = Build.MANUFACTURER; - private static final String TEST_MAC_ADDR = "11:22:33:44:55:66"; - private static final String TEST_IMSI = "310150123456789"; - private static final String TEST_SW_VERSION = "Android Test 1.0"; - private static final String TEST_REDIRECT_URL = "http://127.0.0.1:12345/index.htm"; - - @Mock - private SystemInfo mSystemInfo; - @Mock - private Context mContext; - @Mock - private TelephonyManager mTelephonyManager; - @Mock - private TelephonyManager mDataTelephonyManager; - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager); - when(mSystemInfo.getDeviceId()).thenReturn(TEST_DEV_ID); - when(mSystemInfo.getDeviceManufacturer()).thenReturn(TEST_MANUFACTURER); - when(mSystemInfo.getMacAddress(any(String.class))).thenReturn(TEST_MAC_ADDR); - when(mSystemInfo.getSoftwareVersion()).thenReturn(TEST_SW_VERSION); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(TEST_IMSI); - DevDetailMo.setAllowToSendImsiImeiInfo(false); - } - - /** - * Verify the serialization will return null if wifi mac address was missed. - */ - @Test - public void serializeDevDetailMoWithoutMacaddress() { - when(mSystemInfo.getMacAddress(any(String.class))).thenReturn(null); - assertNull(DevDetailMo.serializeToXml(mContext, mSystemInfo, TEST_REDIRECT_URL)); - } - - /** - * Verify the serialization will include IMSI and IMEI if it is allowed to send the information. - */ - @Test - public void serializeDevDetailMoForHomeNetworkCarrier() { - DevDetailMo.setAllowToSendImsiImeiInfo(true); - String expected = String.format("<MgmtTree>" - + "<VerDTD>%s</VerDTD>" - + "<Node><NodeName>DevDetail</NodeName>" - + "<RTProperties>" - + "<Type><DDFName>%s</DDFName></Type>" - + "</RTProperties>" - + "<Node><NodeName>ext</NodeName>" - + "<Node><NodeName>org.wi-fi</NodeName>" - + "<RTProperties>" - + "<Type><DDFName>%s</DDFName></Type>" - + "</RTProperties>" - + "<Node><NodeName>Wi-Fi</NodeName>" - + "<Node><NodeName>EAPMethodList</NodeName>" - + "<Node><NodeName>EAPMethod01</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>MS-CHAP-V2</Value></Node>" - + "</Node>" - + "<Node><NodeName>EAPMethod02</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>MS-CHAP</Value></Node>" - + "</Node>" - + "<Node><NodeName>EAPMethod03</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>PAP</Value></Node></Node>" - + "<Node><NodeName>EAPMethod04</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>13</Value></Node></Node>" - + "<Node><NodeName>EAPMethod05</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>18</Value></Node></Node>" - + "<Node><NodeName>EAPMethod06</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>23</Value></Node></Node>" - + "<Node><NodeName>EAPMethod07</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>50</Value></Node></Node>" - + "</Node>" - + "<Node><NodeName>ManufacturingCertificate</NodeName><Value>FALSE</Value>" - + "</Node>" - + "<Node><NodeName>ClientTriggerRedirectURI</NodeName>" - + "<Value>%s</Value></Node>" - + "<Node><NodeName>Wi-FiMACAddress</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>IMSI</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>IMEI_MEID</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>Ops</NodeName>" - + "<Node><NodeName>launchBrowserToURI</NodeName><Value/></Node>" - + "</Node>" - + "</Node>" - + "</Node>" - + "</Node>" - + "<Node><NodeName>URI</NodeName>" - + "<Node><NodeName>MaxDepth</NodeName><Value>32</Value></Node>" - + "<Node><NodeName>MaxTotLen</NodeName><Value>2048</Value></Node>" - + "<Node><NodeName>MaxSegLen</NodeName><Value>64</Value></Node>" - + "</Node>" - + "<Node><NodeName>OEM</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>SwV</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>LrgOrj</NodeName><Value>TRUE</Value></Node>" - + "</Node>" - + "</MgmtTree>", - MoSerializer.DM_VERSION, DevDetailMo.URN, DevDetailMo.HS20_URN, - TEST_REDIRECT_URL, TEST_MAC_ADDR.replace(":", ""), TEST_IMSI, TEST_DEV_ID, - TEST_MANUFACTURER, TEST_SW_VERSION); - assertEquals(expected, - DevDetailMo.serializeToXml(mContext, mSystemInfo, TEST_REDIRECT_URL)); - } - - /** - * Verify the serialization will not include IMSI and IMEI if the HS2.0 network is not a home - * carrier network. - */ - @Test - public void serializeDevDetailMoForOtherCarrier() { - String expected = String.format("<MgmtTree>" - + "<VerDTD>%s</VerDTD>" - + "<Node><NodeName>DevDetail</NodeName>" - + "<RTProperties>" - + "<Type><DDFName>%s</DDFName></Type>" - + "</RTProperties>" - + "<Node><NodeName>ext</NodeName>" - + "<Node><NodeName>org.wi-fi</NodeName>" - + "<RTProperties>" - + "<Type><DDFName>%s</DDFName></Type>" - + "</RTProperties>" - + "<Node><NodeName>Wi-Fi</NodeName>" - + "<Node><NodeName>EAPMethodList</NodeName>" - + "<Node><NodeName>EAPMethod01</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>MS-CHAP-V2</Value></Node>" - + "</Node>" - + "<Node><NodeName>EAPMethod02</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>MS-CHAP</Value>" - + "</Node></Node>" - + "<Node><NodeName>EAPMethod03</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>PAP</Value></Node></Node>" - + "<Node><NodeName>EAPMethod04</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>13</Value></Node></Node>" - + "<Node><NodeName>EAPMethod05</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>18</Value></Node></Node>" - + "<Node><NodeName>EAPMethod06</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>23</Value></Node></Node>" - + "<Node><NodeName>EAPMethod07</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>50</Value></Node></Node>" - + "</Node>" - + "<Node><NodeName>ManufacturingCertificate</NodeName><Value>FALSE</Value>" - + "</Node>" - + "<Node><NodeName>ClientTriggerRedirectURI</NodeName>" - + "<Value>%s</Value></Node>" - + "<Node><NodeName>Wi-FiMACAddress</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>Ops</NodeName>" - + "<Node><NodeName>launchBrowserToURI</NodeName><Value/></Node>" - + "</Node>" - + "</Node>" - + "</Node>" - + "</Node>" - + "<Node><NodeName>URI</NodeName>" - + "<Node><NodeName>MaxDepth</NodeName><Value>32</Value></Node>" - + "<Node><NodeName>MaxTotLen</NodeName><Value>2048</Value></Node>" - + "<Node><NodeName>MaxSegLen</NodeName><Value>64</Value></Node>" - + "</Node>" - + "<Node><NodeName>OEM</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>SwV</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>LrgOrj</NodeName><Value>TRUE</Value></Node>" - + "</Node>" - + "</MgmtTree>", - MoSerializer.DM_VERSION, DevDetailMo.URN, DevDetailMo.HS20_URN, TEST_REDIRECT_URL, - TEST_MAC_ADDR.replace(":", ""), TEST_MANUFACTURER, - TEST_SW_VERSION); - assertEquals(expected, - DevDetailMo.serializeToXml(mContext, mSystemInfo, TEST_REDIRECT_URL)); - } - - /** - * Verify the serialization will not include IMSI and IMEI if the device has no SIM. - */ - @Test - public void serializeDevDetailMoWithoutSim() { - DevDetailMo.setAllowToSendImsiImeiInfo(true); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(null); - String expected = String.format("<MgmtTree>" - + "<VerDTD>%s</VerDTD>" - + "<Node><NodeName>DevDetail</NodeName>" - + "<RTProperties>" - + "<Type><DDFName>%s</DDFName></Type>" - + "</RTProperties>" - + "<Node><NodeName>ext</NodeName>" - + "<Node><NodeName>org.wi-fi</NodeName>" - + "<RTProperties>" - + "<Type><DDFName>%s</DDFName></Type>" - + "</RTProperties>" - + "<Node><NodeName>Wi-Fi</NodeName>" - + "<Node><NodeName>EAPMethodList</NodeName>" - + "<Node><NodeName>EAPMethod01</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>MS-CHAP-V2</Value></Node>" - + "</Node>" - + "<Node><NodeName>EAPMethod02</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>MS-CHAP</Value>" - + "</Node></Node>" - + "<Node><NodeName>EAPMethod03</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>21</Value></Node>" - + "<Node><NodeName>InnerMethod</NodeName><Value>PAP</Value></Node></Node>" - + "<Node><NodeName>EAPMethod04</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>13</Value></Node></Node>" - + "<Node><NodeName>EAPMethod05</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>18</Value></Node></Node>" - + "<Node><NodeName>EAPMethod06</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>23</Value></Node></Node>" - + "<Node><NodeName>EAPMethod07</NodeName>" - + "<Node><NodeName>EAPType</NodeName><Value>50</Value></Node></Node>" - + "</Node>" - + "<Node><NodeName>ManufacturingCertificate</NodeName><Value>FALSE</Value>" - + "</Node>" - + "<Node><NodeName>ClientTriggerRedirectURI</NodeName>" - + "<Value>%s</Value></Node>" - + "<Node><NodeName>Wi-FiMACAddress</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>Ops</NodeName>" - + "<Node><NodeName>launchBrowserToURI</NodeName><Value/></Node>" - + "</Node>" - + "</Node>" - + "</Node>" - + "</Node>" - + "<Node><NodeName>URI</NodeName>" - + "<Node><NodeName>MaxDepth</NodeName><Value>32</Value></Node>" - + "<Node><NodeName>MaxTotLen</NodeName><Value>2048</Value></Node>" - + "<Node><NodeName>MaxSegLen</NodeName><Value>64</Value></Node>" - + "</Node>" - + "<Node><NodeName>OEM</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>SwV</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>LrgOrj</NodeName><Value>TRUE</Value></Node>" - + "</Node>" - + "</MgmtTree>", - MoSerializer.DM_VERSION, DevDetailMo.URN, DevDetailMo.HS20_URN, TEST_REDIRECT_URL, - TEST_MAC_ADDR.replace(":", ""), TEST_MANUFACTURER, - TEST_SW_VERSION); - assertEquals(expected, - DevDetailMo.serializeToXml(mContext, mSystemInfo, TEST_REDIRECT_URL)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/DevInfoMoTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/DevInfoMoTest.java deleted file mode 100644 index aaa4e39d4..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/DevInfoMoTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.omadm; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.os.Build; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.SystemInfo; - -import org.junit.Test; - -/** - * Unit tests for {@link DevInfoMo}. - * TODO(b/80300806): change the test to verify the XML in terms of the structure of XML. - */ -@SmallTest -public class DevInfoMoTest extends WifiBaseTest { - private static final String TEST_DEV_ID = "12312341"; - private static final String TEST_MANUFACTURER = Build.MANUFACTURER; - private static final String TEST_MODEL = Build.MODEL; - private static final String TEST_LANGUAGE = "en"; - - @Test - public void serializeDevInfo() { - SystemInfo systemInfo = mock(SystemInfo.class); - when(systemInfo.getDeviceId()).thenReturn(TEST_DEV_ID); - when(systemInfo.getDeviceManufacturer()).thenReturn(TEST_MANUFACTURER); - when(systemInfo.getDeviceModel()).thenReturn(TEST_MODEL); - when(systemInfo.getLanguage()).thenReturn(TEST_LANGUAGE); - String expected = String.format( - "<MgmtTree>" - + "<VerDTD>%s</VerDTD>" - + "<Node><NodeName>DevInfo</NodeName>" - + "<RTProperties><Type><DDFName>%s</DDFName></Type></RTProperties></Node>" - + "<Node><NodeName>DevID</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>Man</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>Mod</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>DmV</NodeName><Value>%s</Value></Node>" - + "<Node><NodeName>Lang</NodeName><Value>%s</Value></Node>" - + "</MgmtTree>", - MoSerializer.DM_VERSION, DevInfoMo.URN, TEST_DEV_ID, TEST_MANUFACTURER, - TEST_MODEL, MoSerializer.DM_VERSION, TEST_LANGUAGE); - assertEquals(expected, DevInfoMo.serializeToXml(systemInfo)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/MoSerializerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/MoSerializerTest.java deleted file mode 100644 index 213dd74c7..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/omadm/MoSerializerTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.omadm; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for {@link MoSerializer}. - */ -@SmallTest -public class MoSerializerTest extends WifiBaseTest { - MoSerializer mMoSerializer; - Document mDocument; - static final String TEST_NODE = "test_node"; - static final String TEST_VALUE = "test_value"; - static final String TEST_URN = "urn:oma:mo:oma-dm-devinfo:1.0"; - - @Before - public void setUp() throws Exception { - mMoSerializer = new MoSerializer(); - mDocument = mMoSerializer.createNewDocument(); - } - - /** - * Verify that the returned element should be valid element. - * - * Expected output: <MgmtTree></MgmtTree> - */ - @Test - public void testShouldReturnValidElementForCreateMgmtTree() { - Element element = mMoSerializer.createMgmtTree(mDocument); - - assertEquals(element.getTagName(), MoSerializer.TAG_MGMT_TREE); - assertTrue(mDocument.hasChildNodes()); - } - - /** - * Verify that the returned element should be valid element. - * - * Expected output: <VerDTD>[value]</VerDTD> - */ - @Test - public void testShouldReturnValidElementForWriteVersion() { - Element element = mMoSerializer.writeVersion(mDocument); - - assertEquals(element.getTagName(), MoSerializer.TAG_VERSION); - Node childNode = element.getFirstChild(); - assertNotNull(childNode); - assertEquals(childNode.getNodeValue(), MoSerializer.DM_VERSION); - } - - /** - * Verify that the returned element should be valid element. - * - * Expected output: <RTProperties><Type><DDFName>[urn]</DDFName></Type></RTProperites> - */ - @Test - public void testShouldReturnValidElementForCreateNodeForUrn() { - Element element = mMoSerializer.createNodeForUrn(mDocument, TEST_URN); - - assertEquals(element.getTagName(), MoSerializer.TAG_RTPROPERTIES); - assertEquals(element.getChildNodes().getLength(), 1); - Node childNode = element.getFirstChild(); - assertTrue(childNode instanceof Element); - assertEquals(((Element)childNode).getTagName(), MoSerializer.TAG_TYPE); - - Node childNode2 = childNode.getFirstChild(); - assertTrue(childNode2 instanceof Element); - assertEquals(((Element)childNode2).getTagName(), MoSerializer.TAG_DDF_NAME); - Node textNode = childNode2.getFirstChild(); - assertNotNull(textNode); - assertEquals(textNode.getNodeValue(), TEST_URN); - } - - /** - * Verify that the returned element should be valid element. - * - * Expected output: <Node><NodeName>[nodeName]</NodeName></Node> - */ - @Test - public void testShouldReturnValidElementForCreateNode() { - Element element = mMoSerializer.createNode(mDocument, TEST_NODE); - - assertEquals(element.getTagName(), MoSerializer.TAG_NODE); - assertEquals(element.getChildNodes().getLength(), 1); - Node childNode = element.getFirstChild(); - assertTrue(childNode instanceof Element); - Node textNode = childNode.getFirstChild(); - assertNotNull(textNode); - assertEquals(textNode.getNodeValue(), TEST_NODE); - } - - /** - * Verify that the returned element should be valid element. - * - * Expected output: - * <Node><NodeName>[name]</NodeName><Value>[value]</Value></Node> - */ - @Test - public void testShouldReturnValidElementForCreateNodeForValue() { - Element element = mMoSerializer.createNodeForValue(mDocument, TEST_NODE, TEST_VALUE); - - assertEquals(element.getTagName(), MoSerializer.TAG_NODE); - assertEquals(element.getChildNodes().getLength(), 2); - List<String> values = Arrays.asList(TEST_NODE, TEST_VALUE); - Node childNode; - Node textNode; - for (String value : values) { - childNode = element.getFirstChild(); - assertTrue(childNode instanceof Element); - textNode = childNode.getFirstChild(); - assertNotNull(textNode); - assertEquals(textNode.getNodeValue(), value); - element.removeChild(childNode); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/ExchangeCompleteMessageTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/ExchangeCompleteMessageTest.java deleted file mode 100644 index 4b2739be8..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/ExchangeCompleteMessageTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; -import org.ksoap2.serialization.SoapObject; - -/** - * Unit tests for {@link ExchangeCompleteMessage}. - */ -@SmallTest -public class ExchangeCompleteMessageTest extends WifiBaseTest { - private static final String TEST_STATUS = "OK"; - private static final String TEST_SESSION_ID = "D215D696517BA138F1D28442DF0F4E07"; - private static final String TEST_VERSION = "1.0"; - - private ExchangeCompleteMessage mExchangeCompleteMessage; - - /** - * Verify if the ExchangeCompleteMessage message is properly parsed. - */ - @Test - public void verifyValidExchangeComplete() { - SoapObject response = new SoapObject(); - response.addAttribute(SppResponseMessage.SPPStatusAttribute, TEST_STATUS); - response.addAttribute(SppResponseMessage.SPPSessionIDAttribute, TEST_SESSION_ID); - response.addAttribute(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - - mExchangeCompleteMessage = ExchangeCompleteMessage.createInstance(response); - - assertNotNull(mExchangeCompleteMessage); - } - - /** - * Verify if the exchangeComplete message missing session id will return {@code null} - */ - @Test - public void verifyInvalidExchangeCompleteReturnNull() { - SoapObject response = new SoapObject(); - response.addAttribute(SppResponseMessage.SPPStatusAttribute, TEST_STATUS); - response.addAttribute(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - mExchangeCompleteMessage = ExchangeCompleteMessage.createInstance(response); - - assertNull(mExchangeCompleteMessage); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/HttpsServiceConnectionTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/HttpsServiceConnectionTest.java deleted file mode 100644 index ee813a6b6..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/HttpsServiceConnectionTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.net.Network; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.HeaderProperty; -import org.mockito.Mock; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.net.ssl.HttpsURLConnection; - -/** - * Unit tests for {@link HttpsServiceConnection}. - */ -@SmallTest -public class HttpsServiceConnectionTest extends WifiBaseTest { - private static final String TEST_URL = "https://127.0.0.1:12345/index.htm"; - - private HttpsServiceConnection mHttpsServiceConnection; - private URL mUrl; - - @Mock Network mNetwork; - @Mock HttpsURLConnection mHttpsURLConnection; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - - mUrl = new URL(TEST_URL); - - when(mHttpsURLConnection.getURL()).thenReturn(mUrl); - when(mNetwork.openConnection(any(URL.class))).thenReturn(mHttpsURLConnection); - mHttpsServiceConnection = new HttpsServiceConnection(mNetwork, mUrl); - } - - /** - * Verify if the connect function actually calls {@link HttpsURLConnection#connect()} - */ - @Test - public void verifyConnect() throws IOException { - mHttpsServiceConnection.connect(); - verify(mHttpsURLConnection).connect(); - } - - /** - * Verify if the disconnect function actually calls {@link HttpsURLConnection#disconnect()} - */ - @Test - public void verifyDisconnect() { - mHttpsServiceConnection.disconnect(); - verify(mHttpsURLConnection).disconnect(); - } - - /** - * Verify if the response code returned is same with response code from - * {@link HttpsURLConnection#getResponseCode()}. - */ - @Test - public void verifyGetResponseProperties() { - Map<String, List<String>> testProperties = new HashMap<>(); - testProperties.put("test1", Arrays.asList("value1", "value2")); - testProperties.put("test2", Arrays.asList("value3")); - when(mHttpsURLConnection.getHeaderFields()).thenReturn(testProperties); - - Map<String, List<String>> actualResultsProperties = new HashMap<>(); - List<HeaderProperty> actualResults = mHttpsServiceConnection.getResponseProperties(); - actualResults.forEach(h -> { - if (actualResultsProperties.containsKey(h.getKey())) { - actualResultsProperties.get(h.getKey()).add(h.getValue()); - } else { - actualResultsProperties.put(h.getKey(), - new ArrayList<>(Arrays.asList(h.getValue()))); - } - }); - assertEquals(testProperties, actualResultsProperties); - } - - /** - * Verify if the response code returned is same with response code from - * {@link HttpsURLConnection#getResponseCode()}. - */ - @Test - public void verifyGetResponseCode() throws IOException { - int testResponseCode = 400; - when(mHttpsURLConnection.getResponseCode()).thenReturn(testResponseCode); - - assertEquals(testResponseCode, mHttpsServiceConnection.getResponseCode()); - } - - /** - * Verify if the InputStream returned is same with InputStream from - * {@link HttpsURLConnection#getInputStream()}. - */ - @Test - public void verifyOpenInputStream() throws IOException { - InputStream testInputStream = new InputStream() { - @Override - public int read() { - return 0; - } - }; - - when(mHttpsURLConnection.getInputStream()).thenReturn(testInputStream); - - assertEquals(testInputStream, mHttpsServiceConnection.openInputStream()); - } - - /** - * Verify if the OutputStream returned is same with OutputStream from - * {@link HttpsURLConnection#getOutputStream()}. - */ - @Test - public void verifyOpenOutputStream() throws IOException { - OutputStream testOutputStream = new OutputStream() { - @Override - public void write(int b) { - - } - }; - - when(mHttpsURLConnection.getOutputStream()).thenReturn(testOutputStream); - - assertEquals(testOutputStream, mHttpsServiceConnection.openOutputStream()); - } - - /** - * Verify if the InputStream returned is same with InputStream from - * {@link HttpsURLConnection#getErrorStream()}. - */ - @Test - public void verifyGetErrorStream() { - InputStream testInputStream = new InputStream() { - @Override - public int read() { - return 0; - } - }; - - when(mHttpsURLConnection.getErrorStream()).thenReturn(testInputStream); - - assertEquals(testInputStream, mHttpsServiceConnection.getErrorStream()); - } - - /** - * Verify if the host returned is same with host from test URL. - */ - @Test - public void verifyGetHost() { - assertEquals(mUrl.getHost(), mHttpsServiceConnection.getHost()); - } - - /** - * Verify if the port returned is same with port from test URL. - */ - @Test - public void verifyGetPort() { - assertEquals(mUrl.getPort(), mHttpsServiceConnection.getPort()); - } - - /** - * Verify if the path returned is same with path from test URL. - */ - @Test - public void verifyGetPath() { - assertEquals(mUrl.getPath(), mHttpsServiceConnection.getPath()); - } - - /** - * Verify if the setRequestProperty never get called for Connection:close property. - */ - @Test - public void verifyNotUpdatingRequestPropertyForIgnorableProperty() { - String testName = "Connection"; - String testValue = "close"; - mHttpsServiceConnection.setRequestProperty(testName, testValue); - - verify(mHttpsURLConnection, never()).setRequestProperty(any(String.class), - any(String.class)); - } - - /** - * Verify if the setRequestProperty get called for other properties but "Connection:close" - * property. - */ - @Test - public void verifyCallingSetRequestPropertyForProperty() { - String testName = "Content-Type"; - String testValue = "application/x-www-form-urlencoded"; - mHttpsServiceConnection.setRequestProperty(testName, testValue); - - verify(mHttpsURLConnection).setRequestProperty(any(String.class), - any(String.class)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/HttpsTransportTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/HttpsTransportTest.java deleted file mode 100644 index d0aff449b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/HttpsTransportTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.net.Network; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import java.io.IOException; -import java.net.URL; - -import javax.net.ssl.HttpsURLConnection; - -/** - * Unit tests for {@link HttpsTransport}. - */ -@SmallTest -public class HttpsTransportTest extends WifiBaseTest { - private static final String TEST_URL = "https://127.0.0.1:12345/index.htm"; - private URL mUrl; - private HttpsTransport mHttpsTransport; - - @Mock Network mNetwork; - @Mock HttpsURLConnection mHttpsURLConnection; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - mUrl = new URL(TEST_URL); - when(mNetwork.openConnection(any(URL.class))).thenReturn(mHttpsURLConnection); - mHttpsTransport = HttpsTransport.createInstance(mNetwork, mUrl); - } - - /** - * Verify if the getServiceConnection never returns {@code null}. - */ - @Test - public void verifyGetServiceConnection() throws IOException { - assertNotNull(mHttpsTransport.getServiceConnection()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/PostDevDataMessageTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/PostDevDataMessageTest.java deleted file mode 100644 index 38d477b72..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/PostDevDataMessageTest.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.content.Context; -import android.os.Build; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.SystemInfo; -import com.android.server.wifi.hotspot2.omadm.DevDetailMo; -import com.android.server.wifi.hotspot2.omadm.DevInfoMo; - -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.SoapEnvelope; -import org.ksoap2.serialization.AttributeInfo; -import org.ksoap2.serialization.PropertyInfo; -import org.ksoap2.serialization.SoapObject; -import org.ksoap2.serialization.SoapPrimitive; -import org.ksoap2.serialization.SoapSerializationEnvelope; -import org.mockito.Mock; - -/** - * Unit tests for {@link PostDevDataMessage}. - */ -@SmallTest -public class PostDevDataMessageTest extends WifiBaseTest { - private static final String TEST_DEV_ID = "12312341"; - private static final String TEST_MANUFACTURER = Build.MANUFACTURER; - private static final String TEST_MODEL = Build.MODEL; - private static final String TEST_LANGUAGE = "en"; - private static final String TEST_SESSION_ID = "123456"; - private static final String TEST_REQUEST_REASON = "test Reason"; - private static final String TEST_MAC_ADDR = "11:22:33:44:55:66"; - private static final String TEST_IMSI = "310150123456789"; - private static final String TEST_SW_VERSION = "Android Test 1.0"; - private static final String TEST_REDIRECT_URL = "http://127.0.0.1:12345/index.htm"; - - @Mock - private SystemInfo mSystemInfo; - @Mock - private Context mContext; - @Mock - private TelephonyManager mTelephonyManager; - @Mock - private TelephonyManager mDataTelephonyManager; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager); - when(mSystemInfo.getDeviceModel()).thenReturn(TEST_MODEL); - when(mSystemInfo.getLanguage()).thenReturn(TEST_LANGUAGE); - - when(mSystemInfo.getDeviceId()).thenReturn(TEST_DEV_ID); - when(mSystemInfo.getDeviceManufacturer()).thenReturn(TEST_MANUFACTURER); - when(mSystemInfo.getMacAddress(any(String.class))).thenReturn(TEST_MAC_ADDR); - when(mSystemInfo.getSoftwareVersion()).thenReturn(TEST_SW_VERSION); - when(mDataTelephonyManager.getSubscriberId()).thenReturn(TEST_IMSI); - } - - /** - * Verify the request is organized correctly with no session id. - */ - @Test - public void serializePostDevDataRequestWithoutSessionId() { - SoapSerializationEnvelope request = PostDevDataMessage.serializeToSoapEnvelope(mContext, - mSystemInfo, TEST_REDIRECT_URL, - TEST_REQUEST_REASON, null); - assertNotNull(request); - assertEquals(SoapEnvelope.VER12, request.version); - SoapObject soapRequest = (SoapObject) request.bodyOut; - verifyCommonFields(soapRequest); - // Should not have the session id attribute - assertFalse(soapRequest.hasAttribute(SoapEnvelope.NS20, SppConstants.ATTRIBUTE_SESSION_ID)); - } - - /** - * Verify the request is organized correctly with a session id. - */ - @Test - public void serializePostDevDataRequestWithSessionId() { - SoapSerializationEnvelope request = PostDevDataMessage.serializeToSoapEnvelope(mContext, - mSystemInfo, TEST_REDIRECT_URL, - TEST_REQUEST_REASON, TEST_SESSION_ID); - assertNotNull(request); - assertEquals(SoapEnvelope.VER12, request.version); - SoapObject soapRequest = (SoapObject) request.bodyOut; - verifyCommonFields(soapRequest); - // Should have session id attribute - assertEquals(TEST_SESSION_ID, soapRequest.getAttributeAsString(SoapEnvelope.NS20, - SppConstants.ATTRIBUTE_SESSION_ID)); - - } - - private void verifyCommonFields(SoapObject request) { - assertEquals(request.getNamespace(), SoapEnvelope.NS20); - assertEquals(request.getName(), SppConstants.METHOD_POST_DEV_DATA); - assertEquals(SppConstants.SUPPORTED_SPP_VERSION, - request.getAttributeAsString(SoapEnvelope.NS20, - SppConstants.ATTRIBUTE_SPP_VERSION)); - - int moCounter = 0; - PropertyInfo propertyInfo = new AttributeInfo(); - for (int i = 0; i < request.getPropertyCount(); i++) { - request.getPropertyInfo(i, propertyInfo); - if (propertyInfo.name.equals(SppConstants.PROPERTY_MO_CONTAINER)) { - SoapPrimitive soapPrimitive = (SoapPrimitive) propertyInfo.getValue(); - String moUrn = soapPrimitive.getAttributeAsString(SppConstants.ATTRIBUTE_MO_URN); - assertEquals(soapPrimitive.getNamespace(), SoapEnvelope.NS20); - if (moUrn.equals(DevDetailMo.URN) || moUrn.equals(DevInfoMo.URN)) { - moCounter++; - } - } - } - // DevInfoMo + DevDetailMo - assertEquals(2, moCounter); - - assertTrue( - request.hasProperty(SoapEnvelope.NS20, SppConstants.PROPERTY_MO_CONTAINER)); - - assertEquals(TEST_REQUEST_REASON, - request.getAttribute(SppConstants.ATTRIBUTE_REQUEST_REASON)); - assertEquals(TEST_REDIRECT_URL, request.getAttribute(SppConstants.ATTRIBUTE_REDIRECT_URI)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/PostDevDataResponseTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/PostDevDataResponseTest.java deleted file mode 100644 index 9e1fb2983..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/PostDevDataResponseTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.soap.command.SppCommand; - -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.serialization.PropertyInfo; -import org.ksoap2.serialization.SoapObject; - -/** - * Unit tests for {@link PostDevDataResponse}. - */ -@SmallTest -public class PostDevDataResponseTest extends WifiBaseTest { - private static final String EXEC = "exec"; - private static final String BROWSER_COMMAND = "launchBrowserToURI"; - private static final String TEST_URL = "https://127.0.0.1:12345/index.htm"; - private static final String TEST_STATUS = "OK"; - private static final String TEST_SESSION_ID = "D215D696517BA138F1D28442DF0F4E07"; - private static final String TEST_VERSION = "1.0"; - - private PostDevDataResponse mPostDevDataResponse; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - } - - /** - * Verify if the PostDevDataResponse message is properly parsed. - */ - @Test - public void verifyValidPostDevDataResponse() { - PropertyInfo propertyInfo = new PropertyInfo(); - SoapObject subCommand = new SoapObject(); - propertyInfo.setName(EXEC); - propertyInfo.setValue(subCommand); - subCommand.addProperty(BROWSER_COMMAND, TEST_URL); - SppCommand expectedResult = SppCommand.createInstance(propertyInfo); - - SoapObject response = new SoapObject(); - response.addAttribute(SppResponseMessage.SPPStatusAttribute, TEST_STATUS); - response.addAttribute(SppResponseMessage.SPPSessionIDAttribute, TEST_SESSION_ID); - response.addAttribute(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - - response.addProperty(propertyInfo); - - mPostDevDataResponse = PostDevDataResponse.createInstance(response); - - assertEquals(expectedResult, mPostDevDataResponse.getSppCommand()); - } - - /** - * Verify if the PostDevDataResponse message which has properties over MAX_PROPERTY_COUNT will - * return {@code null} - */ - @Test - public void verifyInvalidPostDevDataResponseReturnNull() { - // MAX_PROPERTY_COUNT is 1 - SoapObject response = new SoapObject(); - response.addProperty(new PropertyInfo()); - response.addProperty(new PropertyInfo()); - mPostDevDataResponse = PostDevDataResponse.createInstance(response); - - assertNull(mPostDevDataResponse); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/RedirectListenerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/RedirectListenerTest.java deleted file mode 100644 index aa4e18873..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/RedirectListenerTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import android.os.Handler; -import android.os.Looper; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import java.io.IOException; -import java.net.URL; - -import fi.iki.elonen.NanoHTTPD; - -/** - * Unit tests for {@link RedirectListener}. - */ -@SmallTest -public class RedirectListenerTest extends WifiBaseTest { - private static final int TEST_PORT = 1010; - - private RedirectListenerSpy mRedirectListener; - private URL mServerUrl; - private TestLooper mLooper = new TestLooper(); - private Handler mHandler = new Handler(mLooper.getLooper()); - - @Mock RedirectListener.RedirectCallback mListener; - @Mock NanoHTTPD.IHTTPSession mIHTTPSession; - - /** Spy class to avoid start/stop {@link NanoHTTPD} server */ - private class RedirectListenerSpy extends RedirectListener { - boolean mIsStart = false; - RedirectListenerSpy(Looper looper, int port) throws IOException { - super(looper, port); - } - - @Override - public void start() { - mIsStart = true; - } - - @Override - public void stop() { - mIsStart = false; - } - - @Override - public boolean isServerAlive() { - return mIsStart; - } - } - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - mRedirectListener = new RedirectListenerSpy(mLooper.getLooper(), TEST_PORT); - mServerUrl = mRedirectListener.getServerUrl(); - } - - private void verifyStartServer() { - mRedirectListener.startServer(mListener, mHandler); - mLooper.dispatchAll(); - - assertTrue(mRedirectListener.mIsStart); - } - - private void verifyStopServer() { - mRedirectListener.stopServer(mHandler); - mLooper.dispatchAll(); - - assertFalse(mRedirectListener.mIsStart); - - // true if there are pending messages in the message queue - assertFalse(mLooper.isIdle()); - } - - /** - * Verifies that Timeout handler will be invoked when There is no a known GET request received - * in a {@link RedirectListener#USER_TIMEOUT_MILLIS}. - */ - @Test - public void timeOutForKnownGetRequest() { - when(mIHTTPSession.getMethod()).thenReturn(NanoHTTPD.Method.PUT); - verifyStartServer(); - mRedirectListener.serve(mIHTTPSession); - - verify(mListener, never()).onRedirectReceived(); - - // Timeout has expired. - mLooper.moveTimeForward(RedirectListener.USER_TIMEOUT_MILLIS); - mLooper.dispatchAll(); - - verify(mListener).onRedirectTimedOut(); - verifyStopServer(); - } - - /** - * Verifies that {@link RedirectListener.RedirectCallback#onRedirectReceived()} will not be - * invoked when receiving a GET request with an unexpected path. - */ - @Test - public void receiveUnknownGetRequest() { - when(mIHTTPSession.getMethod()).thenReturn(NanoHTTPD.Method.GET); - when(mIHTTPSession.getUri()).thenReturn("/test"); - verifyStartServer(); - - mRedirectListener.serve(mIHTTPSession); - - verify(mListener, never()).onRedirectReceived(); - - // Timeout has expired. - mLooper.moveTimeForward(RedirectListener.USER_TIMEOUT_MILLIS); - mLooper.dispatchAll(); - - verify(mListener).onRedirectTimedOut(); - verifyStopServer(); - } - - /** - * Verifies that a {@link RedirectListener.RedirectCallback#onRedirectReceived()} callback will - * be invoked when receiving a GET request with an expected path. - */ - @Test - public void receiveKnownGetRequest() { - when(mIHTTPSession.getMethod()).thenReturn(NanoHTTPD.Method.GET); - when(mIHTTPSession.getUri()).thenReturn(mServerUrl.getPath()); - verifyStartServer(); - - mRedirectListener.serve(mIHTTPSession); - - verify(mListener).onRedirectReceived(); - - mLooper.moveTimeForward(RedirectListener.USER_TIMEOUT_MILLIS); - mLooper.dispatchAll(); - - // TimeoutTask is cancelled once receiving HTTP redirect response. - verify(mListener, never()).onRedirectTimedOut(); - verifyStopServer(); - } -} - - - - - - - - diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/SoapParserTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/SoapParserTest.java deleted file mode 100644 index c52a84abd..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/SoapParserTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.serialization.PropertyInfo; -import org.ksoap2.serialization.SoapObject; - -/** - * Unit tests for {@link SoapParser}. - */ -@SmallTest -public class SoapParserTest extends WifiBaseTest { - private static final String EXEC = "exec"; - private static final String BROWSER_COMMAND = "launchBrowserToURI"; - private static final String TEST_URL = "https://127.0.0.1:12345/index.htm"; - private static final String TEST_STATUS = "OK"; - private static final String TEST_SESSION_ID = "D215D696517BA138F1D28442DF0F4E07"; - private static final String TEST_VERSION = "1.0"; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - } - - /** - * Verify if the invalid message type SppSoapResponse message will return {@code null} - */ - @Test - public void verifyInvalidMessageType() { - SoapObject response = new SoapObject("Spp", "InvalidMessageType"); - assertNull(SoapParser.getResponse(response)); - } - - /** - * Verify if the valid sppPostDevDataResponse message will return {@link PostDevDataResponse} - */ - @Test - public void verifyValidSppPostDevDataResponse() { - PropertyInfo propertyInfo = new PropertyInfo(); - SoapObject subCommand = new SoapObject(); - propertyInfo.setName(EXEC); - propertyInfo.setValue(subCommand); - subCommand.addProperty(BROWSER_COMMAND, TEST_URL); - - SoapObject response = new SoapObject("Spp", "sppPostDevDataResponse"); - response.addAttribute(SppResponseMessage.SPPStatusAttribute, TEST_STATUS); - response.addAttribute(SppResponseMessage.SPPSessionIDAttribute, TEST_SESSION_ID); - response.addAttribute(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - response.addProperty(propertyInfo); - - SppResponseMessage result = SoapParser.getResponse(response); - - assertTrue(result instanceof PostDevDataResponse); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/SppResponseMessageTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/SppResponseMessageTest.java deleted file mode 100644 index 823cc9d60..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/SppResponseMessageTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.serialization.SoapObject; - -import java.util.HashMap; -import java.util.Map; - -/** - * Unit tests for {@link SppResponseMessage}. - */ -@SmallTest -public class SppResponseMessageTest extends WifiBaseTest { - private static final String TEST_STATUS = "OK"; - private static final String TEST_ERROR_STATUS = "Error occurred"; - private static final String TEST_SESSION_ID = "D215D696517BA138F1D28442DF0F4E07"; - private static final String TEST_VERSION = "1.0"; - private static final String TEST_ERROR = "SPP version not supported"; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - } - - /** - * Verify if the SppSoapResponse message without error attribute is properly parsed. - */ - @Test - public void verifySppSoapResponseWithoutErrorAttribute() { - SoapObject soapObject = new SoapObject(); - soapObject.addAttribute(SppResponseMessage.SPPStatusAttribute, TEST_STATUS); - soapObject.addAttribute(SppResponseMessage.SPPSessionIDAttribute, TEST_SESSION_ID); - soapObject.addAttribute(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - Map<String, String> expectedAttributes = new HashMap<>(); - expectedAttributes.put(SppResponseMessage.SPPStatusAttribute, TEST_STATUS); - expectedAttributes.put(SppResponseMessage.SPPSessionIDAttribute, TEST_SESSION_ID); - expectedAttributes.put(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - - SppResponseMessage sppResponseMessage = new SppResponseMessage(soapObject, - SppResponseMessage.MessageType.POST_DEV_DATA_RESPONSE); - - assertEquals(SppConstants.mapStatusStringToInt(TEST_STATUS), - sppResponseMessage.getStatus()); - assertEquals(SppResponseMessage.MessageType.POST_DEV_DATA_RESPONSE, - sppResponseMessage.getMessageType()); - assertEquals(TEST_SESSION_ID, sppResponseMessage.getSessionID()); - assertEquals(TEST_VERSION, sppResponseMessage.getVersion()); - assertEquals(expectedAttributes, sppResponseMessage.getAttributes()); - assertEquals(SppConstants.INVALID_SPP_CONSTANT, sppResponseMessage.getError()); - } - - /** - * Verify if the SppSoapResponse message with error attribute is properly parsed. - */ - @Test - public void verifySppSoapResponseWithErrorAttribute() { - SoapObject soapObject = new SoapObject(); - soapObject.addAttribute(SppResponseMessage.SPPStatusAttribute, TEST_ERROR_STATUS); - soapObject.addAttribute(SppResponseMessage.SPPSessionIDAttribute, TEST_SESSION_ID); - soapObject.addAttribute(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - SoapObject errorInfo = new SoapObject(); - errorInfo.addAttribute(SppResponseMessage.SPPErrorCodeAttribute, TEST_ERROR); - soapObject.addProperty(SppResponseMessage.SPPErrorProperty, errorInfo); - - Map<String, String> expectedAttributes = new HashMap<>(); - expectedAttributes.put(SppResponseMessage.SPPStatusAttribute, TEST_ERROR_STATUS); - expectedAttributes.put(SppResponseMessage.SPPSessionIDAttribute, TEST_SESSION_ID); - expectedAttributes.put(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - - SppResponseMessage sppResponseMessage = new SppResponseMessage(soapObject, - SppResponseMessage.MessageType.POST_DEV_DATA_RESPONSE); - - assertEquals(SppConstants.mapStatusStringToInt(TEST_ERROR_STATUS), - sppResponseMessage.getStatus()); - assertEquals(SppResponseMessage.MessageType.POST_DEV_DATA_RESPONSE, - sppResponseMessage.getMessageType()); - assertEquals(TEST_SESSION_ID, sppResponseMessage.getSessionID()); - assertEquals(TEST_VERSION, sppResponseMessage.getVersion()); - assertEquals(expectedAttributes, sppResponseMessage.getAttributes()); - assertEquals(SppConstants.mapErrorStringToInt(TEST_ERROR), sppResponseMessage.getError()); - } - - /** - * Verify if the incomplete SppSoapResponse message will raise - * {@code IllegalArgumentException}. - */ - @Test - public void verifyInCompleteSppSoapResponseRaiseException() { - SoapObject soapObject = new SoapObject(); - soapObject.addAttribute(SppResponseMessage.SPPStatusAttribute, TEST_STATUS); - soapObject.addAttribute(SppResponseMessage.SPPVersionAttribute, TEST_VERSION); - try { - new SppResponseMessage(soapObject, - SppResponseMessage.MessageType.POST_DEV_DATA_RESPONSE); - fail("expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // do nothing - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/UpdateResponseMessageTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/UpdateResponseMessageTest.java deleted file mode 100644 index 881ed9c94..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/UpdateResponseMessageTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; -import org.ksoap2.SoapEnvelope; -import org.ksoap2.serialization.SoapObject; -import org.ksoap2.serialization.SoapSerializationEnvelope; - -/** - * Unit tests for {@link UpdateResponseMessage}. - */ -@SmallTest -public class UpdateResponseMessageTest extends WifiBaseTest { - private static final String TEST_SESSION_ID = "123456"; - - /** - * Verify the request is organized correctly with a session id. - */ - @Test - public void serializeUpdateResponseMessageWithSessionIdWithoutError() { - SoapSerializationEnvelope request = UpdateResponseMessage.serializeToSoapEnvelope( - TEST_SESSION_ID, false); - assertNotNull(request); - assertEquals(SoapEnvelope.VER12, request.version); - SoapObject soapRequest = (SoapObject) request.bodyOut; - verifyCommonFields(soapRequest); - - // Should have an OK status attribute - assertEquals(SppConstants.mapStatusIntToString(SppConstants.SppStatus.OK), - soapRequest.getAttributeAsString(SoapEnvelope.NS20, - SppConstants.ATTRIBUTE_SPP_STATUS)); - } - - /** - * Verify the request is organized correctly with a session id and an error. - */ - @Test - public void serializeUpdateResponseMessageWithError() { - SoapSerializationEnvelope request = UpdateResponseMessage.serializeToSoapEnvelope( - TEST_SESSION_ID, true); - assertNotNull(request); - assertEquals(SoapEnvelope.VER12, request.version); - SoapObject soapRequest = (SoapObject) request.bodyOut; - verifyCommonFields(soapRequest); - - // Should have an error status attribute - assertEquals(SppConstants.mapStatusIntToString(SppConstants.SppStatus.ERROR), - soapRequest.getAttributeAsString(SoapEnvelope.NS20, - SppConstants.ATTRIBUTE_SPP_STATUS)); - assertEquals(1, soapRequest.getPropertyCount()); - - SoapObject sppError = (SoapObject) soapRequest.getProperty(0); - assertNotNull(sppError); - assertEquals(sppError.getNamespace(), SoapEnvelope.NS20); - assertEquals( - SppConstants.mapErrorIntToString(SppConstants.SppError.MO_ADD_OR_UPDATE_FAILED), - sppError.getAttributeAsString(SppConstants.ATTRIBUTE_ERROR_CODE)); - } - - private void verifyCommonFields(SoapObject request) { - assertEquals(request.getNamespace(), SoapEnvelope.NS20); - assertEquals(request.getName(), SppConstants.METHOD_UPDATE_RESPONSE); - assertEquals(SppConstants.SUPPORTED_SPP_VERSION, - request.getAttributeAsString(SoapEnvelope.NS20, - SppConstants.ATTRIBUTE_SPP_VERSION)); - - // Should have a session id attribute - assertEquals(TEST_SESSION_ID, request.getAttributeAsString(SoapEnvelope.NS20, - SppConstants.ATTRIBUTE_SESSION_ID)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/BrowserUriTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/BrowserUriTest.java deleted file mode 100644 index e5691e7d8..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/BrowserUriTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap.command; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.serialization.PropertyInfo; - -/** - * Unit tests for {@link BrowserUri}. - */ -@SmallTest -public class BrowserUriTest extends WifiBaseTest { - private static final String BROWSER_COMMAND = "launchBrowserToURI"; - private static final String TEST_URL = "https://127.0.0.1:12345/index.htm"; - private BrowserUri mBrowserUri; - private PropertyInfo mPropertyInfo; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - mPropertyInfo = new PropertyInfo(); - mPropertyInfo.setName(BROWSER_COMMAND); - mPropertyInfo.setValue(TEST_URL); - } - - /** - * Verify if the returned Uri is same with the TEST_URL - */ - @Test - public void verifyGetUri() { - mBrowserUri = BrowserUri.createInstance(mPropertyInfo); - assertEquals(TEST_URL, mBrowserUri.getUri()); - } - - /** - * Verify if the invalid message will return {@code null} - */ - @Test - public void verifyInvalidMessageReturnNull() { - mPropertyInfo.setName("UnknownCommand"); - mBrowserUri = BrowserUri.createInstance(mPropertyInfo); - - assertNull(mBrowserUri); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/PpsMoDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/PpsMoDataTest.java deleted file mode 100644 index 28642661e..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/PpsMoDataTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap.command; - -import static com.android.server.wifi.hotspot2.soap.command.PpsMoData.ADD_MO_COMMAND; -import static com.android.server.wifi.hotspot2.soap.command.PpsMoData.ATTRIBUTE_MANAGEMENT_TREE_URI; -import static com.android.server.wifi.hotspot2.soap.command.PpsMoData.ATTRIBUTE_MO_URN; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.serialization.PropertyInfo; -import org.ksoap2.serialization.SoapPrimitive; - -/** - * Unit tests for {@link PpsMoData}. - */ -@SmallTest -public class PpsMoDataTest extends WifiBaseTest { - private static final String TEST_PPS_MO_XML = "<MgmtTree>test</MgmtTree>"; - private static final String TEST_TREE_URI = "testTreeURI"; - private static final String TEST_MO_URN = "testMoURN"; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - } - - /** - * Verify if a message is valid format, it will return a PPS MO XML. - */ - @Test - public void verifyGetPpsMo() { - PropertyInfo propertyInfo = new PropertyInfo(); - propertyInfo.setName(ADD_MO_COMMAND); - SoapPrimitive soapPrimitive = new SoapPrimitive("namespace", "name", TEST_PPS_MO_XML); - soapPrimitive.addAttribute(ATTRIBUTE_MANAGEMENT_TREE_URI, TEST_TREE_URI); - soapPrimitive.addAttribute(ATTRIBUTE_MO_URN, TEST_MO_URN); - propertyInfo.setValue(soapPrimitive); - - assertEquals(TEST_PPS_MO_XML, PpsMoData.createInstance(propertyInfo).getPpsMoTree()); - } - - /** - * Verify if a message does not have PPS MO XML, it will return {@code null}. - */ - @Test - public void verifyMissingPpsMoReturnNull() { - PropertyInfo propertyInfo = new PropertyInfo(); - propertyInfo.setName(ADD_MO_COMMAND); - SoapPrimitive soapPrimitive = new SoapPrimitive("namespace", "name", TEST_PPS_MO_XML); - soapPrimitive.addAttribute(ATTRIBUTE_MANAGEMENT_TREE_URI, TEST_TREE_URI); - soapPrimitive.addAttribute(ATTRIBUTE_MO_URN, TEST_MO_URN); - propertyInfo.setValue(null); - - assertNull(PpsMoData.createInstance(propertyInfo)); - } - - /** - * Verify if a message is missing {@link PpsMoData#ATTRIBUTE_MANAGEMENT_TREE_URI}, it will - * return {@code null}. - */ - @Test - public void verifyMissingTreeURIAttributeReturnNull() { - PropertyInfo propertyInfo = new PropertyInfo(); - propertyInfo.setName(ADD_MO_COMMAND); - SoapPrimitive soapPrimitive = new SoapPrimitive("namespace", "name", TEST_PPS_MO_XML); - soapPrimitive.addAttribute(ATTRIBUTE_MO_URN, TEST_MO_URN); - propertyInfo.setValue(soapPrimitive); - - assertNull(PpsMoData.createInstance(propertyInfo)); - } - - /** - * Verify if a message is missing {@link PpsMoData#ATTRIBUTE_MO_URN}, it will return - * {@code null}. - */ - @Test - public void verifyMissingMoUrnAttributeReturnNull() { - PropertyInfo propertyInfo = new PropertyInfo(); - propertyInfo.setName(ADD_MO_COMMAND); - SoapPrimitive soapPrimitive = new SoapPrimitive("namespace", "name", TEST_PPS_MO_XML); - soapPrimitive.addAttribute(ATTRIBUTE_MANAGEMENT_TREE_URI, TEST_TREE_URI); - propertyInfo.setValue(soapPrimitive); - - assertNull(PpsMoData.createInstance(propertyInfo)); - } - - /** - * Verify if a message that is not for addMO command, it will return {@code null}. - */ - @Test - public void verifyNonAddMoCommandMessageReturnNull() { - PropertyInfo propertyInfo = new PropertyInfo(); - propertyInfo.setName("InvalidCommand"); - - assertNull(PpsMoData.createInstance(propertyInfo)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/SppCommandTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/SppCommandTest.java deleted file mode 100644 index 1f00e2c52..000000000 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/soap/command/SppCommandTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.hotspot2.soap.command; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.MockitoAnnotations.initMocks; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.ksoap2.serialization.PropertyInfo; -import org.ksoap2.serialization.SoapObject; - -/** - * Unit tests for {@link SppCommand}. - */ -@SmallTest -public class SppCommandTest extends WifiBaseTest { - private static final String EXEC = "exec"; - private static final String BROWSER_COMMAND = "launchBrowserToURI"; - private static final String GET_CERT_COMMAND = "getCertificate"; - private static final String TEST_URL = "https://127.0.0.1:12345/index.htm"; - - /** - * Sets up test. - */ - @Before - public void setUp() throws Exception { - initMocks(this); - } - - /** - * Verify if the LaunchBrowserCommand message is properly parsed. - */ - @Test - public void verifyLaunchBrowserCommand() { - PropertyInfo propertyInfo = new PropertyInfo(); - propertyInfo.setName(EXEC); - propertyInfo.setValue(new SoapObject().addProperty(BROWSER_COMMAND, TEST_URL)); - - SppCommand result = SppCommand.createInstance(propertyInfo); - - assertEquals(SppCommand.CommandId.EXEC, result.getSppCommandId()); - assertEquals(SppCommand.ExecCommandId.BROWSER, result.getExecCommandId()); - assertEquals(BrowserUri.class, result.getCommandData().getClass()); - assertEquals(TEST_URL, ((BrowserUri) result.getCommandData()).getUri()); - } - - /** - * Verify if the other command types, but LaunchBrowserCommand will return {@code null} - */ - @Test - public void verifyOtherCommandTypesReturnNull() { - PropertyInfo propertyInfo = new PropertyInfo(); - SoapObject subCommand = new SoapObject(); - propertyInfo.setName(EXEC); - propertyInfo.setValue(subCommand); - subCommand.addProperty(GET_CERT_COMMAND, ""); - - SppCommand result = SppCommand.createInstance(propertyInfo); - - assertNull(result.getCommandData()); - } - - /** - * Verify if the incomplete command message will return {@code null}. - */ - @Test - public void verifyIncompleteCommandReturnNull() { - PropertyInfo propertyInfo = new PropertyInfo(); - SoapObject subCommand = new SoapObject(); - propertyInfo.setName(EXEC); - propertyInfo.setValue(subCommand); - - assertNull(SppCommand.createInstance(propertyInfo)); - } - - /** - * Verify if the invalid command message will return {@code null}. - */ - @Test - public void verifyInvalidCommandReturnNull() { - PropertyInfo propertyInfo = new PropertyInfo(); - propertyInfo.setName("invalidCommand"); - - SppCommand result = SppCommand.createInstance(propertyInfo); - assertNull(result); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/MockWifiP2pMonitor.java b/tests/wifitests/src/com/android/server/wifi/p2p/MockWifiP2pMonitor.java deleted file mode 100644 index d36db2d82..000000000 --- a/tests/wifitests/src/com/android/server/wifi/p2p/MockWifiP2pMonitor.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.p2p; - -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; - -import android.os.Handler; -import android.os.Message; -import android.util.SparseArray; - -import com.android.server.wifi.WifiInjector; - -import java.util.HashMap; -import java.util.Map; - -/** - * Creates a mock WifiP2pMonitor. - * WARNING: This does not perfectly mock the behavior of WifiP2pMonitor at the moment - * ex. startMonitoring does nothing and will not send a connection/disconnection event - */ -public class MockWifiP2pMonitor extends WifiP2pMonitor { - private final Map<String, SparseArray<Handler>> mHandlerMap = new HashMap<>(); - - public MockWifiP2pMonitor() { - super(mock(WifiInjector.class)); - } - - @Override - public void registerHandler(String iface, int what, Handler handler) { - SparseArray<Handler> ifaceHandlers = mHandlerMap.get(iface); - if (ifaceHandlers == null) { - ifaceHandlers = new SparseArray<>(); - mHandlerMap.put(iface, ifaceHandlers); - } - ifaceHandlers.put(what, handler); - } - - @Override - public synchronized void startMonitoring(String iface) { - return; - } - - /** - * Send a message and assert that it was dispatched to a handler - */ - public void sendMessage(String iface, int what) { - sendMessage(iface, Message.obtain(null, what)); - } - - public void sendMessage(String iface, Message message) { - SparseArray<Handler> ifaceHandlers = mHandlerMap.get(iface); - if (ifaceHandlers != null) { - assertTrue("No handler for iface=" + iface + ",what=" + message.what, - sendMessage(ifaceHandlers, message)); - } else { - boolean sent = false; - for (Map.Entry<String, SparseArray<Handler>> entry : mHandlerMap.entrySet()) { - if (sendMessage(entry.getValue(), Message.obtain(message))) { - sent = true; - } - } - assertTrue("No handler for message with nonexistant iface, iface=" + iface - + ",what=" + message.what, sent); - } - } - - private boolean sendMessage(SparseArray<Handler> ifaceHandlers, Message message) { - Handler handler = ifaceHandlers.get(message.what); - if (handler != null) { - message.setTarget(handler); - message.sendToTarget(); - return true; - } - return false; - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackTest.java deleted file mode 100644 index cd20f475c..000000000 --- a/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackTest.java +++ /dev/null @@ -1,667 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.p2p; - -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.doAnswer; -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 android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback; -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback.P2pStatusCode; -import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; -import android.net.wifi.WpsInfo; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pProvDiscEvent; -import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus; -import com.android.server.wifi.util.NativeUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -/** - * Unit tests for SupplicantP2pIfaceCallback - */ -@SmallTest -public class SupplicantP2pIfaceCallbackTest extends WifiBaseTest { - private static final String TAG = "SupplicantP2pIfaceCallbackTest"; - - private String mIface = "test_p2p0"; - private String mGroupIface = "test_p2p-p2p0-3"; - private WifiP2pMonitor mMonitor; - private SupplicantP2pIfaceCallback mDut; - - private byte[] mDeviceAddressInvalid1 = { 0x00 }; - private byte[] mDeviceAddressInvalid2 = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; - private byte[] mDeviceAddress1Bytes = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; - private String mDeviceAddress1String = "00:11:22:33:44:55"; - private byte[] mDeviceAddress2Bytes = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56 }; - private String mDeviceAddress2String = "01:12:23:34:45:56"; - private byte[] mDeviceInfoBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; - private static final byte[] DEVICE_ADDRESS = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; - private static final int TEST_NETWORK_ID = 9; - private static final int TEST_GROUP_FREQUENCY = 5400; - - private class SupplicantP2pIfaceCallbackSpy extends SupplicantP2pIfaceCallback { - SupplicantP2pIfaceCallbackSpy(String iface, WifiP2pMonitor monitor) { - super(iface, monitor); - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mMonitor = mock(WifiP2pMonitor.class); - mDut = new SupplicantP2pIfaceCallbackSpy(mIface, mMonitor); - } - - /** - * Sunny day scenario for onDeviceFound call. - */ - @Test - public void testOnDeviceFound_success() throws Exception { - byte[] fakePrimaryDeviceTypeBytes = { 0x00, 0x01, 0x02, -1, 0x04, 0x05, 0x06, 0x07 }; - String fakePrimaryDeviceTypeString = "1-02FF0405-1543"; - String fakeDeviceName = "test device name"; - short fakeConfigMethods = 0x1234; - byte fakeCapabilities = 123; - int fakeGroupCapabilities = 456; - - doAnswer(new AnswerWithArguments() { - public void answer(String iface, WifiP2pDevice device) { - // NOTE: mDeviceAddress1Bytes seems to be ignored by - // legacy implementation of WifiP2pDevice. - assertEquals(iface, mIface); - assertEquals(device.deviceName, fakeDeviceName); - assertEquals(device.primaryDeviceType, fakePrimaryDeviceTypeString); - assertEquals(device.deviceCapability, fakeCapabilities); - assertEquals(device.groupCapability, fakeGroupCapabilities); - assertEquals(device.wpsConfigMethodsSupported, fakeConfigMethods); - assertEquals(device.deviceAddress, mDeviceAddress2String); - assertEquals(device.status, WifiP2pDevice.AVAILABLE); - } - }) - .when(mMonitor).broadcastP2pDeviceFound( - anyString(), any(WifiP2pDevice.class)); - - mDut.onDeviceFound( - mDeviceAddress1Bytes, mDeviceAddress2Bytes, - fakePrimaryDeviceTypeBytes, - fakeDeviceName, fakeConfigMethods, - fakeCapabilities, fakeGroupCapabilities, - mDeviceInfoBytes); - - mDut.onDeviceFound( - mDeviceAddress1Bytes, mDeviceAddress2Bytes, - fakePrimaryDeviceTypeBytes, - fakeDeviceName, fakeConfigMethods, - fakeCapabilities, fakeGroupCapabilities, - null); - - // Make sure we issued a broadcast each time. - verify(mMonitor, times(2)).broadcastP2pDeviceFound( - anyString(), any(WifiP2pDevice.class)); - } - - /** - * Sunny day scenario for onDeviceFound call with sign bit set in bytes. - */ - @Test - public void testOnDeviceFoundWithSignBitInDeviceInfoBytesSuccess() throws Exception { - byte[] fakePrimaryDeviceTypeBytes = { 0x00, 0x01, 0x02, -1, 0x04, 0x05, 0x06, 0x07 }; - String fakePrimaryDeviceTypeString = "1-02FF0405-1543"; - String fakeDeviceName = "test device name"; - short fakeConfigMethods = 0x1234; - byte fakeCapabilities = 123; - int fakeGroupCapabilities = 456; - byte[] fakeDevInfoBytes = { (byte) 0x80, 0x01, (byte) 0xC0, 0x03, (byte) 0xFF, 0x05 }; - - mDut.onDeviceFound( - mDeviceAddress1Bytes, mDeviceAddress2Bytes, - fakePrimaryDeviceTypeBytes, - fakeDeviceName, fakeConfigMethods, - fakeCapabilities, fakeGroupCapabilities, - fakeDevInfoBytes); - - ArgumentCaptor<WifiP2pDevice> deviceCaptor = ArgumentCaptor.forClass(WifiP2pDevice.class); - verify(mMonitor).broadcastP2pDeviceFound(eq(mIface), deviceCaptor.capture()); - - WifiP2pDevice device = deviceCaptor.getValue(); - assertEquals(fakeDeviceName, device.deviceName); - assertEquals(fakePrimaryDeviceTypeString, device.primaryDeviceType); - assertEquals(fakeCapabilities, device.deviceCapability); - assertEquals(fakeGroupCapabilities, device.groupCapability); - assertEquals(fakeConfigMethods, device.wpsConfigMethodsSupported); - assertEquals(mDeviceAddress2String, device.deviceAddress); - assertEquals(WifiP2pDevice.AVAILABLE, device.status); - - assertNotNull(device.wfdInfo); - // WifiP2pWfdInfo.mDeviceInfo won't be returned as the raw value, skip it. - assertEquals(((fakeDevInfoBytes[2] & 0xFF) << 8) + fakeDevInfoBytes[3], - device.wfdInfo.getControlPort()); - assertEquals(((fakeDevInfoBytes[4] & 0xFF) << 8) + fakeDevInfoBytes[5], - device.wfdInfo.getMaxThroughput()); - - // Make sure we issued a broadcast each time. - verify(mMonitor).broadcastP2pDeviceFound( - anyString(), any(WifiP2pDevice.class)); - } - - /** - * Failing scenarios for onDeviceFound call. - */ - @Test - public void testOnDeviceFound_invalidArguments() throws Exception { - byte[] fakePrimaryDeviceTypeBytes = { 0x0, 0x01, 0x02, -1, 0x04, 0x05, 0x06, 0x07 }; - String fakePrimaryDeviceTypeString = "1-02FF0405-1543"; - String fakeDeviceName = "test device name"; - short fakeConfigMethods = 0x1234; - byte fakeCapabilities = 123; - int fakeGroupCapabilities = 456; - - mDut.onDeviceFound( - mDeviceAddress2Bytes, null, - fakePrimaryDeviceTypeBytes, - fakeDeviceName, fakeConfigMethods, - fakeCapabilities, fakeGroupCapabilities, - mDeviceInfoBytes); - verify(mMonitor, never()).broadcastP2pDeviceFound( - anyString(), any(WifiP2pDevice.class)); - - - mDut.onDeviceFound( - mDeviceAddress1Bytes, mDeviceAddress2Bytes, - null, - fakeDeviceName, fakeConfigMethods, - fakeCapabilities, fakeGroupCapabilities, - mDeviceInfoBytes); - verify(mMonitor, never()).broadcastP2pDeviceFound( - anyString(), any(WifiP2pDevice.class)); - - - mDut.onDeviceFound( - mDeviceAddress1Bytes, mDeviceAddress2Bytes, - fakePrimaryDeviceTypeBytes, - null, fakeConfigMethods, - fakeCapabilities, fakeGroupCapabilities, - mDeviceInfoBytes); - verify(mMonitor, never()).broadcastP2pDeviceFound( - anyString(), any(WifiP2pDevice.class)); - - - mDut.onDeviceFound( - mDeviceAddress1Bytes, mDeviceAddressInvalid1, - fakePrimaryDeviceTypeBytes, - null, fakeConfigMethods, - fakeCapabilities, fakeGroupCapabilities, - mDeviceInfoBytes); - verify(mMonitor, never()).broadcastP2pDeviceFound( - anyString(), any(WifiP2pDevice.class)); - - - mDut.onDeviceFound( - mDeviceAddress1Bytes, mDeviceAddressInvalid2, - fakePrimaryDeviceTypeBytes, - null, fakeConfigMethods, - fakeCapabilities, fakeGroupCapabilities, - mDeviceInfoBytes); - verify(mMonitor, never()).broadcastP2pDeviceFound( - anyString(), any(WifiP2pDevice.class)); - } - - /** - * Sunny day scenario for onDeviceLost call. - */ - @Test - public void testOnDeviceLost_success() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer(String iface, WifiP2pDevice device) { - assertEquals(iface, mIface); - assertEquals(device.deviceAddress, mDeviceAddress1String); - assertEquals(device.status, WifiP2pDevice.UNAVAILABLE); - } - }) - .when(mMonitor).broadcastP2pDeviceLost( - anyString(), any(WifiP2pDevice.class)); - - mDut.onDeviceLost(mDeviceAddress1Bytes); - - // Make sure we issued a broadcast each time. - verify(mMonitor, times(1)).broadcastP2pDeviceLost( - anyString(), any(WifiP2pDevice.class)); - } - - /** - * Failing scenarios for onDeviceLost call. - */ - @Test - public void testOnDeviceLost_invalidArguments() throws Exception { - mDut.onDeviceLost(null); - verify(mMonitor, never()).broadcastP2pDeviceLost( - anyString(), any(WifiP2pDevice.class)); - - mDut.onDeviceLost(mDeviceAddressInvalid1); - verify(mMonitor, never()).broadcastP2pDeviceLost( - anyString(), any(WifiP2pDevice.class)); - - mDut.onDeviceLost(mDeviceAddressInvalid2); - verify(mMonitor, never()).broadcastP2pDeviceLost( - anyString(), any(WifiP2pDevice.class)); - } - - /** - * Sunny day scenario for onGoNegotiationRequest call. - */ - @Test - public void testOnGoNegotiationRequest_success() throws Exception { - HashSet<Integer> setups = new HashSet<Integer>(); - - doAnswer(new AnswerWithArguments() { - public void answer(String iface, WifiP2pConfig config) { - assertEquals(iface, mIface); - assertNotNull(config.wps); - setups.add(config.wps.setup); - assertEquals(config.deviceAddress, mDeviceAddress1String); - } - }) - .when(mMonitor).broadcastP2pGoNegotiationRequest( - anyString(), any(WifiP2pConfig.class)); - - mDut.onGoNegotiationRequest(mDeviceAddress1Bytes, - (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.USER_SPECIFIED); - assertTrue(setups.contains(WpsInfo.DISPLAY)); - - mDut.onGoNegotiationRequest(mDeviceAddress1Bytes, - (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.PUSHBUTTON); - assertTrue(setups.contains(WpsInfo.PBC)); - - mDut.onGoNegotiationRequest(mDeviceAddress1Bytes, - (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.REGISTRAR_SPECIFIED); - assertTrue(setups.contains(WpsInfo.KEYPAD)); - - // Invalid should default to PBC - setups.clear(); - mDut.onGoNegotiationRequest(mDeviceAddress1Bytes, (short)0xffff); - assertTrue(setups.contains(WpsInfo.PBC)); - } - - /** - * Failing scenarios for onGoNegotiationRequest call. - */ - @Test - public void testOnGoNegotiationRequest_invalidArguments() throws Exception { - mDut.onGoNegotiationRequest(null, (short)0); - verify(mMonitor, never()).broadcastP2pDeviceLost( - anyString(), any(WifiP2pDevice.class)); - - mDut.onGoNegotiationRequest(mDeviceAddressInvalid1, (short)0); - verify(mMonitor, never()).broadcastP2pDeviceLost( - anyString(), any(WifiP2pDevice.class)); - - mDut.onGoNegotiationRequest(mDeviceAddressInvalid2, (short)0); - verify(mMonitor, never()).broadcastP2pDeviceLost( - anyString(), any(WifiP2pDevice.class)); - } - - /** - * Sunny day scenario for onGroupStarted call. - */ - @Test - public void testOnGroupStarted_success() throws Exception { - String fakeName = "group name"; - String fakePassphrase = "secret"; - ArrayList<Byte> fakeSsidBytesList = new ArrayList<Byte>() {{ - add((byte)0x30); - add((byte)0x31); - add((byte)0x32); - add((byte)0x33); - }}; - String fakeSsidString = "0123"; - HashSet<String> passwords = new HashSet<String>(); - - doAnswer(new AnswerWithArguments() { - public void answer(String iface, WifiP2pGroup group) { - assertEquals(iface, mIface); - assertNotNull(group.getOwner()); - assertEquals(group.getOwner().deviceAddress, mDeviceAddress1String); - assertEquals(group.getNetworkId(), WifiP2pGroup.NETWORK_ID_PERSISTENT); - passwords.add(group.getPassphrase()); - assertEquals(group.getInterface(), fakeName); - assertEquals(group.getNetworkName(), fakeSsidString); - } - }) - .when(mMonitor).broadcastP2pGroupStarted( - anyString(), any(WifiP2pGroup.class)); - - mDut.onGroupStarted( - fakeName, true, fakeSsidBytesList, 1, null, fakePassphrase, - mDeviceAddress1Bytes, true); - assertTrue(passwords.contains(fakePassphrase)); - - mDut.onGroupStarted( - fakeName, true, fakeSsidBytesList, 1, null, null, - mDeviceAddress1Bytes, true); - assertTrue(passwords.contains(null)); - - verify(mMonitor, times(2)).broadcastP2pGroupStarted( - anyString(), any(WifiP2pGroup.class)); - } - - /** - * Failing scenarios for onGroupStarted call. - */ - @Test - public void testOnGroupStarted_invalidArguments() throws Exception { - String fakeName = "group name"; - String fakePassphrase = "secret"; - ArrayList<Byte> fakeSsidBytesList = new ArrayList<Byte>() {{ - add((byte)0x30); - add((byte)0x31); - add((byte)0x32); - add((byte)0x33); - }}; - String fakeSsidString = "0123"; - - mDut.onGroupStarted( - null, true, fakeSsidBytesList, 1, null, fakePassphrase, - mDeviceAddress1Bytes, true); - verify(mMonitor, never()).broadcastP2pGroupStarted( - anyString(), any(WifiP2pGroup.class)); - - mDut.onGroupStarted( - fakeName, true, null, 1, null, fakePassphrase, - mDeviceAddress1Bytes, true); - verify(mMonitor, never()).broadcastP2pGroupStarted( - anyString(), any(WifiP2pGroup.class)); - - mDut.onGroupStarted( - fakeName, true, fakeSsidBytesList, 1, null, fakePassphrase, - null, true); - verify(mMonitor, never()).broadcastP2pGroupStarted( - anyString(), any(WifiP2pGroup.class)); - } - - /** - * Test provision discovery callback. - */ - @Test - public void testOnProvisionDiscoveryCompleted() throws Exception { - byte[] p2pDeviceAddr = DEVICE_ADDRESS; - boolean isRequest = false; - byte status = ISupplicantP2pIfaceCallback.P2pProvDiscStatusCode.SUCCESS; - short configMethods = WpsConfigMethods.DISPLAY; - String generatedPin = "12345678"; - - ArgumentCaptor<WifiP2pProvDiscEvent> discEventCaptor = - ArgumentCaptor.forClass(WifiP2pProvDiscEvent.class); - mDut.onProvisionDiscoveryCompleted( - p2pDeviceAddr, isRequest, status, configMethods, generatedPin); - verify(mMonitor).broadcastP2pProvisionDiscoveryEnterPin( - anyString(), discEventCaptor.capture()); - assertEquals(WifiP2pProvDiscEvent.ENTER_PIN, discEventCaptor.getValue().event); - - configMethods = WpsConfigMethods.KEYPAD; - mDut.onProvisionDiscoveryCompleted( - p2pDeviceAddr, isRequest, status, configMethods, generatedPin); - verify(mMonitor).broadcastP2pProvisionDiscoveryShowPin( - anyString(), discEventCaptor.capture()); - assertEquals(WifiP2pProvDiscEvent.SHOW_PIN, discEventCaptor.getValue().event); - assertEquals(generatedPin, discEventCaptor.getValue().pin); - - isRequest = true; - configMethods = WpsConfigMethods.KEYPAD; - mDut.onProvisionDiscoveryCompleted( - p2pDeviceAddr, isRequest, status, configMethods, generatedPin); - verify(mMonitor, times(2)).broadcastP2pProvisionDiscoveryEnterPin( - anyString(), discEventCaptor.capture()); - assertEquals(WifiP2pProvDiscEvent.ENTER_PIN, discEventCaptor.getValue().event); - - configMethods = WpsConfigMethods.DISPLAY; - mDut.onProvisionDiscoveryCompleted( - p2pDeviceAddr, isRequest, status, configMethods, generatedPin); - verify(mMonitor, times(2)).broadcastP2pProvisionDiscoveryShowPin( - anyString(), discEventCaptor.capture()); - assertEquals(WifiP2pProvDiscEvent.SHOW_PIN, discEventCaptor.getValue().event); - assertEquals(generatedPin, discEventCaptor.getValue().pin); - - isRequest = false; - configMethods = WpsConfigMethods.PUSHBUTTON; - mDut.onProvisionDiscoveryCompleted( - p2pDeviceAddr, isRequest, status, configMethods, generatedPin); - verify(mMonitor).broadcastP2pProvisionDiscoveryPbcResponse( - anyString(), discEventCaptor.capture()); - assertEquals(WifiP2pProvDiscEvent.PBC_RSP, discEventCaptor.getValue().event); - - isRequest = true; - mDut.onProvisionDiscoveryCompleted( - p2pDeviceAddr, isRequest, status, configMethods, generatedPin); - verify(mMonitor).broadcastP2pProvisionDiscoveryPbcRequest( - anyString(), discEventCaptor.capture()); - assertEquals(WifiP2pProvDiscEvent.PBC_REQ, discEventCaptor.getValue().event); - } - - /** - * Test staAuth with device address, should trigger ApStaConnected broadcast - */ - @Test - public void testStaAuth_success() { - // Trigger onStaAuthorized callback, ensure wifimonitor broadcast is sent with WifiP2pDevice - // using the p2pDeviceAddress - ArgumentCaptor<WifiP2pDevice> p2pDeviceCaptor = - ArgumentCaptor.forClass(WifiP2pDevice.class); - mDut.onStaAuthorized(mDeviceAddress1Bytes, mDeviceAddress2Bytes); - verify(mMonitor).broadcastP2pApStaConnected(any(String.class), p2pDeviceCaptor.capture()); - assertEquals(mDeviceAddress2String, p2pDeviceCaptor.getValue().deviceAddress); - } - - /** - * Test staAuth without device address, should trigger ApStaConnected broadcast using srcAddress - */ - @Test - public void testStaAuth_noDeviceAddress_success() { - // Trigger onStaAuthorized callback, using a zero'd p2pDeviceAddress, ensure wifimonitor - // broadcast is sent with WifiP2pDevice using the srcAddress - ArgumentCaptor<WifiP2pDevice> p2pDeviceCaptor = - ArgumentCaptor.forClass(WifiP2pDevice.class); - mDut.onStaAuthorized(mDeviceAddress1Bytes, NativeUtil.ANY_MAC_BYTES); - verify(mMonitor).broadcastP2pApStaConnected(any(String.class), p2pDeviceCaptor.capture()); - assertEquals(mDeviceAddress1String, p2pDeviceCaptor.getValue().deviceAddress); - } - - // TLVS hex data encoded as a hex string. - // Taken directly from an observed supplicant service response event - private static final String SERV_DISC_RESP_TLVS = "1d00010100076578616d706c650b5f6166706f766572" - + "746370c00c001001001e000101000b5f6166706f766572746370c00c000c01074578616d706c65c0273c" - + "00010100096d797072696e746572045f697070c00c00100109747874766572733d311a70646c3d617070" - + "6c69636174696f6e2f706f73747363726970741900010100045f697070c00c000c01094d795072696e74" - + "6572c0275f000201000a757569643a36383539646564652d383537342d353961622d393333322d313233" - + "3435363738393031313a3a75726e3a736368656d61732d75706e702d6f72673a736572766963653a436f" - + "6e6e656374696f6e4d616e616765723a3159000201000a757569643a36383539646564652d383537342d" - + "353961622d393333322d3132333435363738393031313a3a75726e3a736368656d61732d75706e702d6f" - + "72673a736572766963653a41565472616e73706f72743a315a000201000a757569643a36383539646564" - + "652d383537342d353961622d393333322d3132333435363738393031313a3a75726e3a736368656d6173" - + "2d75706e702d6f72673a6465766963653a4d6564696152656e64657265723a313e000201000a75756964" - + "3a36383539646564652d383537342d353961622d393333322d3132333435363738393031313a3a75706e" - + "703a726f6f746465766963652d000201000a757569643a36383539646564652d383537342d353961622d" - + "393333322d313233343536373839303131"; - - /** - * Pretty basic onServiceDiscoveryResponse callback test. - * Mocks the callback event, passing some observed real data to it, and ensures that it returns - * a non-null WifiP2pServiceResponse list. - */ - @Test - public void testOnServiceDiscoveryResponseCompleted_success() throws Exception { - ArrayList<Byte> tlvs = NativeUtil.byteArrayToArrayList(hexStr2Bin(SERV_DISC_RESP_TLVS)); - ArgumentCaptor<List<WifiP2pServiceResponse>> respListCaptor = - ArgumentCaptor.forClass(List.class); - mDut.onServiceDiscoveryResponse( - mDeviceAddress1Bytes, - (short) 10 /* unused updateIndicator value */, - tlvs); - verify(mMonitor).broadcastP2pServiceDiscoveryResponse(anyString(), - respListCaptor.capture()); - assertNotNull(respListCaptor.getValue()); - } - - /** - * Test onFindStopped event should trigger P2pFindStopped broadcast. - */ - @Test - public void testOnFindStopped() { - mDut.onFindStopped(); - verify(mMonitor).broadcastP2pFindStopped(eq(mIface)); - } - - /** - * Test onGoNegotiationCompleted sunny case. - */ - @Test - public void testOnGoNegotiationCompletedSuccess() { - mDut.onGoNegotiationCompleted(P2pStatusCode.SUCCESS); - verify(mMonitor).broadcastP2pGoNegotiationSuccess(eq(mIface)); - } - - /** - * Test onGoNegotiationCompleted failure cases. - */ - @Test - public void testOnGoNegotiationCompletedFailureUnavailable() { - mDut.onGoNegotiationCompleted(P2pStatusCode.FAIL_INFO_CURRENTLY_UNAVAILABLE); - verify(mMonitor).broadcastP2pGoNegotiationFailure( - eq(mIface), eq(P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE)); - } - - /** - * Test onGroupFormationSuccess should trigger P2pGroupFormationSuccess broadcast. - */ - @Test - public void testOnGroupFormationSuccess() { - mDut.onGroupFormationSuccess(); - verify(mMonitor).broadcastP2pGroupFormationSuccess(eq(mIface)); - } - - /** - * Test onGroupFormationFailure should trigger P2pGroupFormationFailure broadcast. - */ - @Test - public void testOnGroupFormationFailure() { - mDut.onGroupFormationFailure("failure-reason"); - verify(mMonitor).broadcastP2pGroupFormationFailure(eq(mIface), eq("failure-reason")); - } - - /** - * Test onGroupRemoved should trigger P2pGroupRemoved broadcast for Group Owner. - */ - @Test - public void testOnGroupRemovedForGroupOwner() { - mDut.onGroupRemoved(mGroupIface, true); - ArgumentCaptor<WifiP2pGroup> groupCaptor = ArgumentCaptor.forClass(WifiP2pGroup.class); - verify(mMonitor).broadcastP2pGroupRemoved(eq(mIface), groupCaptor.capture()); - assertEquals(mGroupIface, groupCaptor.getValue().getInterface()); - assertEquals(true, groupCaptor.getValue().isGroupOwner()); - } - - /** - * Test onGroupRemoved should trigger P2pGroupRemoved broadcast for Group Client. - */ - @Test - public void testOnGroupRemovedForGroupClient() { - mDut.onGroupRemoved(mGroupIface, false); - - ArgumentCaptor<WifiP2pGroup> groupCaptor = ArgumentCaptor.forClass(WifiP2pGroup.class); - verify(mMonitor).broadcastP2pGroupRemoved(eq(mIface), groupCaptor.capture()); - assertEquals(mGroupIface, groupCaptor.getValue().getInterface()); - assertEquals(false, groupCaptor.getValue().isGroupOwner()); - } - - /** - * Test onInvitationReceived should trigger P2pInvitationReceived broadcast. - */ - @Test - public void testOnInvitationReceived() { - mDut.onInvitationReceived( - mDeviceAddress1Bytes, - mDeviceAddress2Bytes, - DEVICE_ADDRESS, - TEST_NETWORK_ID, - TEST_GROUP_FREQUENCY); - - ArgumentCaptor<WifiP2pGroup> groupCaptor = ArgumentCaptor.forClass(WifiP2pGroup.class); - verify(mMonitor).broadcastP2pInvitationReceived(eq(mIface), groupCaptor.capture()); - - WifiP2pGroup group = groupCaptor.getValue(); - assertEquals(TEST_NETWORK_ID, group.getNetworkId()); - assertEquals(mDeviceAddress2String, group.getOwner().deviceAddress); - } - - /** - * Test onInvitationResult should trigger P2pInvitationResult broadcast. - */ - @Test - public void testOnInvitationResult() { - mDut.onInvitationResult(mDeviceAddress1Bytes, P2pStatusCode.SUCCESS); - verify(mMonitor).broadcastP2pInvitationResult(eq(mIface), eq(P2pStatus.SUCCESS)); - } - - /** - * Test onStaDeauthorized should trigger P2pApStaDisconnected broadcast. - */ - @Test - public void testOnStaDeauthorized() { - mDut.onStaDeauthorized(mDeviceAddress1Bytes, mDeviceAddress2Bytes); - - ArgumentCaptor<WifiP2pDevice> p2pDeviceCaptor = - ArgumentCaptor.forClass(WifiP2pDevice.class); - verify(mMonitor).broadcastP2pApStaDisconnected(eq(mIface), p2pDeviceCaptor.capture()); - assertEquals(mDeviceAddress2String, p2pDeviceCaptor.getValue().deviceAddress); - } - /** - * Converts hex string to byte array. - * - * @param hex hex string. if invalid, return null. - * @return binary data. - */ - private static byte[] hexStr2Bin(String hex) { - int sz = hex.length() / 2; - byte[] b = new byte[hex.length() / 2]; - for (int i = 0; i < sz; i++) { - try { - b[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16); - } catch (Exception e) { - return null; - } - } - return b; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java deleted file mode 100644 index b4943d776..000000000 --- a/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java +++ /dev/null @@ -1,2949 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.p2p; - -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.hardware.wifi.supplicant.V1_0.ISupplicant; -import android.hardware.wifi.supplicant.V1_0.ISupplicantIface; -import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork; -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIface; -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback; -import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pNetwork; -import android.hardware.wifi.supplicant.V1_0.IfaceType; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; -import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; -import android.hidl.manager.V1_0.IServiceManager; -import android.hidl.manager.V1_0.IServiceNotification; -import android.net.wifi.WpsInfo; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pGroupList; -import android.net.wifi.p2p.WifiP2pManager; -import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; -import android.os.IHwBinder; -import android.os.RemoteException; -import android.text.TextUtils; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.util.NativeUtil; - -import org.junit.Assert.*; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -/** - * Unit tests for SupplicantP2pIfaceHal - */ -@SmallTest -public class SupplicantP2pIfaceHalTest extends WifiBaseTest { - private static final String TAG = "SupplicantP2pIfaceHalTest"; - private SupplicantP2pIfaceHal mDut; - private @Mock IServiceManager mServiceManagerMock; - private @Mock ISupplicant mISupplicantMock; - private android.hardware.wifi.supplicant.V1_1.ISupplicant mISupplicantMockV1_1; - private @Mock ISupplicantIface mISupplicantIfaceMock; - private @Mock ISupplicantP2pIface mISupplicantP2pIfaceMock; - private @Mock android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface - mISupplicantP2pIfaceMockV12; - private boolean mISupplicantV12Enabled; - private @Mock ISupplicantP2pNetwork mISupplicantP2pNetworkMock; - private @Mock WifiP2pMonitor mWifiMonitor; - - SupplicantStatus mStatusSuccess; - SupplicantStatus mStatusFailure; - RemoteException mRemoteException; - ISupplicant.IfaceInfo mStaIface; - ISupplicant.IfaceInfo mP2pIface; - ArrayList<ISupplicant.IfaceInfo> mIfaceInfoList; - private IHwBinder.DeathRecipient mDeathRecipient = null; - - final String mIfaceName = "virtual_interface_name"; - final String mSsid = "\"SSID\""; - final ArrayList<Byte> mSsidBytes = new ArrayList<Byte>() {{ - add((byte)'S'); add((byte)'S'); add((byte)'I'); add((byte)'D'); - }}; - final String mPeerMacAddress = "00:11:22:33:44:55"; - final byte mPeerMacAddressBytes[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; - final String mGroupOwnerMacAddress = "01:12:23:34:45:56"; - final byte mGroupOwnerMacAddressBytes[] = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56 }; - final String mInvalidMacAddress1 = "00:11:22:33:44"; - final String mInvalidMacAddress2 = ":::::"; - final String mInvalidMacAddress3 = "invalid"; - final byte mInvalidMacAddressBytes1[] = null; - final byte mInvalidMacAddressBytes2[] = {}; - final byte mInvalidMacAddressBytes3[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; - final byte mInvalidMacAddressBytes4[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; - HashSet<String> mInvalidMacAddresses = new HashSet<String>(Arrays.asList( - mInvalidMacAddress1, mInvalidMacAddress2, - mInvalidMacAddress3)); - HashSet<byte[]> mInvalidMacAddressesBytes = new HashSet<byte[]>(Arrays.asList( - mInvalidMacAddressBytes1, mInvalidMacAddressBytes2, - mInvalidMacAddressBytes3, mInvalidMacAddressBytes4)); - - final String mInvalidService1 = null; - final String mInvalidService2 = "service"; - final String mValidServiceRequestString = "30313233"; - final byte[] mValidServiceRequestBytes = { 0x30, 0x31, 0x32, 0x33 }; - final String mInvalidServiceRequestString = "not a hex string"; - final String mInvalidUpnpService1 = "upnp"; - final String mInvalidUpnpService2 = "upnp 1"; - final String mInvalidUpnpService3 = "upnp invalid_number name"; - final String mInvalidBonjourService1 = "bonjour"; - final String mInvalidBonjourService2 = "bonjour 123456"; - final String mInvalidBonjourService3 = "bonjour invalid_hex 123456"; - final String mInvalidBonjourService4 = "bonjour 123456 invalid_hex"; - final String mValidUpnpService = "upnp 10 serviceName"; - final int mValidUpnpServiceVersion = 16; - final String mValidUpnpServiceName = "serviceName"; - final String mValidBonjourService = "bonjour 30313233 34353637"; - final ArrayList<Byte> mValidBonjourServiceRequest = new ArrayList<Byte>() {{ - add((byte)'0'); add((byte)'1'); add((byte)'2'); add((byte)'3'); - }}; - final ArrayList<Byte> mValidBonjourServiceResponse = new ArrayList<Byte>() {{ - add((byte)'4'); add((byte)'5'); add((byte)'6'); add((byte)'7'); - }}; - - // variables for groupAdd with config - final String mNetworkName = "DIRECT-xy-Hello"; - final String mPassphrase = "12345678"; - final int mGroupOwnerBand = WifiP2pConfig.GROUP_OWNER_BAND_5GHZ; - final boolean mIsPersistent = false; - - private ArgumentCaptor<IHwBinder.DeathRecipient> mDeathRecipientCaptor = - ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); - private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor = - ArgumentCaptor.forClass(IServiceNotification.Stub.class); - private InOrder mInOrder; - - private class SupplicantP2pIfaceHalSpy extends SupplicantP2pIfaceHal { - SupplicantP2pIfaceHalSpy() { - super(mWifiMonitor); - } - - @Override - protected IServiceManager getServiceManagerMockable() throws RemoteException { - return mServiceManagerMock; - } - - @Override - protected ISupplicant getSupplicantMockable() throws RemoteException { - return mISupplicantMock; - } - - @Override - protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1() { - return mISupplicantMockV1_1; - } - - @Override - protected ISupplicantP2pIface getP2pIfaceMockable(ISupplicantIface iface) { - return mISupplicantP2pIfaceMock; - } - - @Override - protected android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface - getP2pIfaceMockableV1_2() { - return mISupplicantV12Enabled ? mISupplicantP2pIfaceMockV12 : null; - } - - @Override - protected ISupplicantP2pNetwork getP2pNetworkMockable(ISupplicantNetwork network) { - return mISupplicantP2pNetworkMock; - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mStatusSuccess = createSupplicantStatus(SupplicantStatusCode.SUCCESS); - mStatusFailure = createSupplicantStatus(SupplicantStatusCode.FAILURE_UNKNOWN); - mRemoteException = new RemoteException("Test Remote Exception"); - mStaIface = createIfaceInfo(IfaceType.STA, "wlan0"); - mP2pIface = createIfaceInfo(IfaceType.P2P, mIfaceName); - - mIfaceInfoList = new ArrayList<ISupplicant.IfaceInfo>(); - mIfaceInfoList.add(mStaIface); - mIfaceInfoList.add(mP2pIface); - - mISupplicantV12Enabled = false; - - when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), - any(IServiceNotification.Stub.class))).thenReturn(true); - when(mISupplicantMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mISupplicantP2pIfaceMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mISupplicantP2pIfaceMock.registerCallback(any(ISupplicantP2pIfaceCallback.class))) - .thenReturn(mStatusSuccess); - mDut = new SupplicantP2pIfaceHalSpy(); - } - - /** - * Sunny day scenario for SupplicantP2pIfaceHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_success() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - } - - /** - * Tests the initialization flow, with a RemoteException occurring when 'getInterface' is called - * Ensures initialization fails. - */ - @Test - public void testInitialize_remoteExceptionFailure() throws Exception { - executeAndValidateInitializationSequence(true, false, false); - } - - /** - * Tests the initialization flow, with listInterfaces returning 0 interfaces. - * Ensures failure - */ - @Test - public void testInitialize_zeroInterfacesFailure() throws Exception { - executeAndValidateInitializationSequence(false, true, false); - } - - /** - * Tests the initialization flow, with a null interface being returned by getInterface. - * Ensures initialization fails. - */ - @Test - public void testInitialize_nullInterfaceFailure() throws Exception { - executeAndValidateInitializationSequence(false, false, true); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal initialization - * Asserts successful initialization - */ - @Test - public void testInitialize_successV1_1() throws Exception { - mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class); - executeAndValidateInitializationSequenceV1_1(false, false); - } - - /** - * Tests the initialization flow, with a RemoteException occurring when 'getInterface' is called - * Ensures initialization fails. - */ - @Test - public void testInitialize_remoteExceptionFailureV1_1() throws Exception { - mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class); - executeAndValidateInitializationSequenceV1_1(true, false); - } - - /** - * Tests the initialization flow, with a null interface being returned by getInterface. - * Ensures initialization fails. - */ - @Test - public void testInitialize_nullInterfaceFailureV1_1() throws Exception { - mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class); - executeAndValidateInitializationSequenceV1_1(false, true); - } - - /** - * Ensures that reject addition of an existing iface. - */ - @Test - public void testDuplicateSetupIfaceV1_1_Fails() throws Exception { - mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class); - executeAndValidateInitializationSequenceV1_1(false, false); - - // Trying setting up the p2p0 interface again & ensure it fails. - assertFalse(mDut.setupIface(mIfaceName)); - verifyNoMoreInteractions(mISupplicantMockV1_1); - } - - /** - * Sunny day scenario for SupplicantStaIfaceHal teardown. - * Asserts successful teardown. - * Note: Only applicable for 1.1 supplicant HAL. - */ - @Test - public void testTeardown_successV1_1() throws Exception { - mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class); - executeAndValidateInitializationSequenceV1_1(false, false); - - when(mISupplicantMockV1_1.removeInterface(any(ISupplicant.IfaceInfo.class))) - .thenReturn(mStatusSuccess); - assertTrue(mDut.teardownIface(mIfaceName)); - verify(mISupplicantMockV1_1).removeInterface(any()); - } - - /** - * Ensures that we reject removal of an invalid iface. - */ - @Test - public void testInvalidTeardownInterfaceV1_1_Fails() throws Exception { - assertFalse(mDut.teardownIface(mIfaceName)); - verifyNoMoreInteractions(mISupplicantMock); - } - - /** - * Verify misorder supplicant death case. - */ - @Test - public void testMisorderSupplicantDeathHandlingV1_1() throws Exception { - mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class); - doAnswer(new AnswerWithArguments() { - public boolean answer(IHwBinder.DeathRecipient cb, long cookie) throws RemoteException { - mDeathRecipient = cb; - return true; - } - }).when(mISupplicantMock).linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong()); - - executeAndValidateInitializationSequenceV1_1(false, false); - mDeathRecipient.serviceDied(0L); - assertFalse(mDut.teardownIface(mIfaceName)); - } - - /** - * Sunny day scenario for getName() - */ - @Test - public void testGetName_success() throws Exception { - - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantIface.getNameCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, mIfaceName); - } - }) - .when(mISupplicantP2pIfaceMock).getName(any(ISupplicantIface.getNameCallback.class)); - - // Default value when service is not initialized. - assertNull(mDut.getName()); - executeAndValidateInitializationSequence(false, false, false); - assertEquals(mIfaceName, mDut.getName()); - } - - /** - * Verify that getName returns null, if status is not SUCCESS. - */ - @Test - public void testGetName_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantIface.getNameCallback cb) throws RemoteException { - cb.onValues(mStatusFailure, "none"); - } - }) - .when(mISupplicantP2pIfaceMock).getName(any(ISupplicantIface.getNameCallback.class)); - assertNull(mDut.getName()); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that getName disconnects and returns null, if HAL throws exception. - */ - @Test - public void testGetName_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantIface.getNameCallback cb) throws RemoteException { - throw new RemoteException("Test"); - } - }) - .when(mISupplicantP2pIfaceMock).getName(any(ISupplicantIface.getNameCallback.class)); - assertNull(mDut.getName()); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for find() - */ - @Test - public void testFind_success() throws Exception { - when(mISupplicantP2pIfaceMock.find(anyInt())).thenReturn(mStatusSuccess); - // Default value when service is not yet initialized. - assertFalse(mDut.find(1)); - - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.find(1)); - assertFalse(mDut.find(-1)); - } - - /** - * Verify that find returns false, if status is not SUCCESS. - */ - @Test - public void testFind_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.find(anyInt())).thenReturn(mStatusFailure); - assertFalse(mDut.find(1)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that find disconnects and returns false, if HAL throws exception. - */ - @Test - public void testFind_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.find(anyInt())).thenThrow(mRemoteException); - assertFalse(mDut.find(0)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for stopFind() - */ - @Test - public void testStopFind_success() throws Exception { - when(mISupplicantP2pIfaceMock.stopFind()).thenReturn(mStatusSuccess); - // Default value when service is not yet initialized. - assertFalse(mDut.stopFind()); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.stopFind()); - } - - /** - * Verify that stopFind returns false, if status is not SUCCESS. - */ - @Test - public void testStopFind_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.stopFind()).thenReturn(mStatusFailure); - assertFalse(mDut.stopFind()); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that stopFind disconnects and returns false, if HAL throws exception. - */ - @Test - public void testStopFind_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.stopFind()).thenThrow(mRemoteException); - assertFalse(mDut.stopFind()); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for flush() - */ - @Test - public void testFlush_success() throws Exception { - when(mISupplicantP2pIfaceMock.flush()).thenReturn(mStatusSuccess); - // Default value when service is not yet initialized. - assertFalse(mDut.flush()); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.flush()); - } - - /** - * Verify that flush returns false, if status is not SUCCESS. - */ - @Test - public void testFlush_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.flush()).thenReturn(mStatusFailure); - assertFalse(mDut.flush()); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that flush disconnects and returns false, if HAL throws exception. - */ - @Test - public void testFlush_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.flush()).thenThrow(mRemoteException); - assertFalse(mDut.flush()); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for serviceFlush() - */ - @Test - public void testServiceFlush_success() throws Exception { - when(mISupplicantP2pIfaceMock.flushServices()).thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.serviceFlush()); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.serviceFlush()); - } - - /** - * Verify that serviceFlush returns false, if status is not SUCCESS. - */ - @Test - public void testServiceFlush_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.flushServices()).thenReturn(mStatusFailure); - assertFalse(mDut.serviceFlush()); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that serviceFlush disconnects and returns false, if HAL throws exception. - */ - @Test - public void testServiceFlush_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.flushServices()).thenThrow(mRemoteException); - assertFalse(mDut.serviceFlush()); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for setPowerSave() - */ - @Test - public void testSetPowerSave_success() throws Exception { - when(mISupplicantP2pIfaceMock.setPowerSave(eq(mIfaceName), anyBoolean())) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.setPowerSave(mIfaceName, true)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.setPowerSave(mIfaceName, true)); - } - - /** - * Verify that setPowerSave returns false, if status is not SUCCESS. - */ - @Test - public void testSetPowerSave_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setPowerSave(eq(mIfaceName), anyBoolean())) - .thenReturn(mStatusFailure); - assertFalse(mDut.setPowerSave(mIfaceName, true)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that setPowerSave disconnects and returns false, if HAL throws exception. - */ - @Test - public void testSetPowerSave_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setPowerSave(eq(mIfaceName), anyBoolean())) - .thenThrow(mRemoteException); - assertFalse(mDut.setPowerSave(mIfaceName, true)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for setGroupIdle() - */ - @Test - public void testSetGroupIdle_success() throws Exception { - when(mISupplicantP2pIfaceMock.setGroupIdle(eq(mIfaceName), anyInt())) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.setGroupIdle(mIfaceName, 1)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.setGroupIdle(mIfaceName, 1)); - assertFalse(mDut.setGroupIdle(mIfaceName, -1)); - } - - /** - * Verify that setGroupIdle returns false, if status is not SUCCESS. - */ - @Test - public void testSetGroupIdle_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setGroupIdle(eq(mIfaceName), anyInt())) - .thenReturn(mStatusFailure); - assertFalse(mDut.setGroupIdle(mIfaceName, 1)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that setGroupIdle disconnects and returns false, if HAL throws exception. - */ - @Test - public void testSetGroupIdle_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setGroupIdle(eq(mIfaceName), anyInt())) - .thenThrow(mRemoteException); - assertFalse(mDut.setGroupIdle(mIfaceName, 1)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for setSsidPostfix() - */ - @Test - public void testSetSsidPostfix_success() throws Exception { - String ssid = "SSID POSTFIX"; - when(mISupplicantP2pIfaceMock.setSsidPostfix(eq(NativeUtil.decodeSsid("\"" + ssid + "\"")))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.setSsidPostfix(ssid)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.setSsidPostfix(ssid)); - assertFalse(mDut.setSsidPostfix(null)); - } - - /** - * Verify that setSsidPostfix returns false, if status is not SUCCESS. - */ - @Test - public void testSetSsidPostfix_failure() throws Exception { - String ssid = "SSID POSTFIX"; - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setSsidPostfix(eq(NativeUtil.decodeSsid("\"" + ssid + "\"")))) - .thenReturn(mStatusFailure); - assertFalse(mDut.setSsidPostfix(ssid)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that setSsidPostfix disconnects and returns false, if HAL throws exception. - */ - @Test - public void testSetSsidPostfix_exception() throws Exception { - String ssid = "SSID POSTFIX"; - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setSsidPostfix(eq(NativeUtil.decodeSsid("\"" + ssid + "\"")))) - .thenThrow(mRemoteException); - assertFalse(mDut.setSsidPostfix(ssid)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for connect() - */ - @Test - public void testConnect_success() throws Exception { - final String configPin = "12345"; - final HashSet<Integer> methods = new HashSet<>(); - - doAnswer(new AnswerWithArguments() { - public void answer(byte[] peer, int method, String pin, boolean joinExisting, - boolean persistent, int goIntent, - ISupplicantP2pIface.connectCallback cb) throws RemoteException { - methods.add(method); - - if (method == ISupplicantP2pIface.WpsProvisionMethod.DISPLAY - && TextUtils.isEmpty(pin)) { - // Return the configPin for DISPLAY method if the pin was not provided. - cb.onValues(mStatusSuccess, configPin); - } else { - if (method != ISupplicantP2pIface.WpsProvisionMethod.PBC) { - // PIN is only required for PIN methods. - assertEquals(pin, configPin); - } - // For all the other cases, there is no generated pin. - cb.onValues(mStatusSuccess, ""); - } - } - }) - .when(mISupplicantP2pIfaceMock).connect( - eq(mPeerMacAddressBytes), anyInt(), anyString(), anyBoolean(), anyBoolean(), - anyInt(), any(ISupplicantP2pIface.connectCallback.class)); - - WifiP2pConfig config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.DISPLAY, ""); - - // Default value when service is not initialized. - assertNull(mDut.connect(config, false)); - - executeAndValidateInitializationSequence(false, false, false); - - assertEquals(configPin, mDut.connect(config, false)); - assertTrue(methods.contains(ISupplicantP2pIface.WpsProvisionMethod.DISPLAY)); - methods.clear(); - - config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.DISPLAY, configPin); - assertTrue(mDut.connect(config, false).isEmpty()); - assertTrue(methods.contains(ISupplicantP2pIface.WpsProvisionMethod.DISPLAY)); - methods.clear(); - - config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.PBC, ""); - assertTrue(mDut.connect(config, false).isEmpty()); - assertTrue(methods.contains(ISupplicantP2pIface.WpsProvisionMethod.PBC)); - methods.clear(); - - config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.KEYPAD, configPin); - assertTrue(mDut.connect(config, false).isEmpty()); - assertTrue(methods.contains(ISupplicantP2pIface.WpsProvisionMethod.KEYPAD)); - } - - /** - * Test connect with invalid arguments. - */ - @Test - public void testConnect_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(byte[] peer, int method, String pin, boolean joinExisting, - boolean persistent, int goIntent, - ISupplicantP2pIface.connectCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, pin); - } - }) - .when(mISupplicantP2pIfaceMock).connect( - any(byte[].class), anyInt(), anyString(), anyBoolean(), anyBoolean(), - anyInt(), any(ISupplicantP2pIface.connectCallback.class)); - - WifiP2pConfig config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.DISPLAY, ""); - - // unsupported. - config.wps.setup = -1; - assertNull(mDut.connect(config, false)); - - // Invalid peer address. - config.wps.setup = WpsInfo.DISPLAY; - for (String address : mInvalidMacAddresses) { - config.deviceAddress = address; - assertNull(mDut.connect(config, false)); - } - - // null pin not valid. - config.wps.setup = WpsInfo.DISPLAY; - config.wps.pin = null; - assertNull(mDut.connect(config, false)); - - // Pin should be empty for PBC. - config.wps.setup = WpsInfo.PBC; - config.wps.pin = "03455323"; - assertNull(mDut.connect(config, false)); - } - - /** - * Verify that connect returns null, if status is not SUCCESS. - */ - @Test - public void testConnect_failure() throws Exception { - final String configPin = "12345"; - WifiP2pConfig config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.DISPLAY, configPin); - - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(byte[] peer, int method, String pin, boolean joinExisting, - boolean persistent, int goIntent, - ISupplicantP2pIface.connectCallback cb) throws RemoteException { - cb.onValues(mStatusFailure, null); - } - }) - .when(mISupplicantP2pIfaceMock).connect( - eq(mPeerMacAddressBytes), anyInt(), anyString(), anyBoolean(), anyBoolean(), - anyInt(), any(ISupplicantP2pIface.connectCallback.class)); - - assertNull(mDut.connect(config, false)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that connect disconnects and returns null, if HAL throws exception. - */ - @Test - public void testConnect_exception() throws Exception { - final String configPin = "12345"; - WifiP2pConfig config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.DISPLAY, configPin); - - doThrow(mRemoteException) - .when(mISupplicantP2pIfaceMock).connect( - eq(mPeerMacAddressBytes), anyInt(), anyString(), anyBoolean(), anyBoolean(), - anyInt(), any(ISupplicantP2pIface.connectCallback.class)); - - assertNull(mDut.connect(config, false)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for cancelConnect() - */ - @Test - public void testCancelConnect_success() throws Exception { - when(mISupplicantP2pIfaceMock.cancelConnect()) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.cancelConnect()); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.cancelConnect()); - } - - /** - * Verify that cancelConnect returns false, if status is not SUCCESS. - */ - @Test - public void testCancelConnect_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.cancelConnect()) - .thenReturn(mStatusFailure); - assertFalse(mDut.cancelConnect()); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that cancelConnect disconnects and returns false, if HAL throws exception. - */ - @Test - public void testCancelConnect_exception() throws Exception { - String ssid = "\"SSID POSTFIX\""; - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.cancelConnect()) - .thenThrow(mRemoteException); - assertFalse(mDut.cancelConnect()); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for provisionDiscovery() - */ - @Test - public void testProvisionDiscovery_success() throws Exception { - WifiP2pConfig config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.PBC, ""); - - when(mISupplicantP2pIfaceMock.provisionDiscovery( - eq(mPeerMacAddressBytes), anyInt())) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.provisionDiscovery(config)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.provisionDiscovery(config)); - } - - /** - * Test provisionDiscovery with invalid arguments. - */ - @Test - public void testProvisionDiscovery_invalidArguments() throws Exception { - when(mISupplicantP2pIfaceMock.provisionDiscovery( - eq(mPeerMacAddressBytes), anyInt())) - .thenReturn(mStatusSuccess); - executeAndValidateInitializationSequence(false, false, false); - - WifiP2pConfig config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.PBC, ""); - - // Unsupported method. - config.wps.setup = -1; - assertFalse(mDut.provisionDiscovery(config)); - - config.wps.setup = WpsInfo.PBC; - for (String address : mInvalidMacAddresses) { - config.deviceAddress = address; - assertFalse(mDut.provisionDiscovery(config)); - } - } - - /** - * Verify that provisionDiscovery returns false, if status is not SUCCESS. - */ - @Test - public void testProvisionDiscovery_failure() throws Exception { - WifiP2pConfig config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.PBC, ""); - - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.provisionDiscovery( - eq(mPeerMacAddressBytes), anyInt())) - .thenReturn(mStatusFailure); - assertFalse(mDut.provisionDiscovery(config)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that provisionDiscovery disconnects and returns false, if HAL throws exception. - */ - @Test - public void testProvisionDiscovery_exception() throws Exception { - WifiP2pConfig config = createDummyP2pConfig(mPeerMacAddress, WpsInfo.PBC, ""); - - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.provisionDiscovery( - eq(mPeerMacAddressBytes), anyInt())) - .thenThrow(mRemoteException); - assertFalse(mDut.provisionDiscovery(config)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for invite() - */ - @Test - public void testInvite_success() throws Exception { - WifiP2pGroup group = createDummyP2pGroup(); - - when(mISupplicantP2pIfaceMock.invite( - eq(mIfaceName), eq(mGroupOwnerMacAddressBytes), eq(mPeerMacAddressBytes))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.invite(group, mPeerMacAddress)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.invite(group, mPeerMacAddress)); - } - - /** - * Invite with invalid arguments. - */ - @Test - public void testInvite_invalidArguments() throws Exception { - WifiP2pGroup group = createDummyP2pGroup(); - - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.invite( - anyString(), any(byte[].class), any(byte[].class))) - .thenReturn(mStatusSuccess); - - for (String address : mInvalidMacAddresses) { - assertFalse(mDut.invite(group, address)); - } - - for (String address : mInvalidMacAddresses) { - group.getOwner().deviceAddress = address; - assertFalse(mDut.invite(group, mPeerMacAddress)); - } - - group.setOwner(null); - assertFalse(mDut.invite(group, mPeerMacAddress)); - assertFalse(mDut.invite(null, mPeerMacAddress)); - } - - /** - * Verify that invite returns false, if status is not SUCCESS. - */ - @Test - public void testInvite_failure() throws Exception { - WifiP2pGroup group = createDummyP2pGroup(); - - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.invite( - anyString(), any(byte[].class), any(byte[].class))) - .thenReturn(mStatusFailure); - assertFalse(mDut.invite(group, mPeerMacAddress)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that invite disconnects and returns false, if HAL throws exception. - */ - @Test - public void testInvite_exception() throws Exception { - WifiP2pGroup group = createDummyP2pGroup(); - - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.invite( - anyString(), any(byte[].class), any(byte[].class))) - .thenThrow(mRemoteException); - assertFalse(mDut.invite(group, mPeerMacAddress)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for reject() - */ - @Test - public void testReject_success() throws Exception { - when(mISupplicantP2pIfaceMock.reject(eq(mPeerMacAddressBytes))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.reject(mPeerMacAddress)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.reject(mPeerMacAddress)); - } - - /** - * Reject with invalid arguments. - */ - @Test - public void testReject_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.reject(any(byte[].class))) - .thenReturn(mStatusSuccess); - - for (String address : mInvalidMacAddresses) { - assertFalse(mDut.reject(address)); - } - } - - /** - * Verify that reject returns false, if status is not SUCCESS. - */ - @Test - public void testReject_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.reject(any(byte[].class))) - .thenReturn(mStatusFailure); - assertFalse(mDut.reject(mPeerMacAddress)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that reject disconnects and returns false, if HAL throws exception. - */ - @Test - public void testReject_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.reject(any(byte[].class))) - .thenThrow(mRemoteException); - assertFalse(mDut.reject(mPeerMacAddress)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for getDeviceAddress() - */ - @Test - public void testGetDeviceAddress_success() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pIface.getDeviceAddressCallback cb) { - cb.onValues(mStatusSuccess, mPeerMacAddressBytes); - } - }) - .when(mISupplicantP2pIfaceMock).getDeviceAddress( - any(ISupplicantP2pIface.getDeviceAddressCallback.class)); - - // Default value when service is not initialized. - assertNull(mDut.getDeviceAddress()); - executeAndValidateInitializationSequence(false, false, false); - assertEquals(mPeerMacAddress, mDut.getDeviceAddress()); - } - - /** - * Test getDeviceAddress() when invalid mac address is being reported. - */ - @Test - public void testGetDeviceAddress_invalidResult() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - HashSet<byte[]> addresses = new HashSet<byte[]>(Arrays.asList( - mInvalidMacAddressBytes1, mInvalidMacAddressBytes2, - mInvalidMacAddressBytes3, mInvalidMacAddressBytes4)); - - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pIface.getDeviceAddressCallback cb) { - byte[] address = addresses.iterator().next(); - cb.onValues(mStatusSuccess, address); - addresses.remove(address); - } - }) - .when(mISupplicantP2pIfaceMock).getDeviceAddress( - any(ISupplicantP2pIface.getDeviceAddressCallback.class)); - - // Default value when service is not initialized. - while (!addresses.isEmpty()) { - assertNull(mDut.getDeviceAddress()); - } - } - - /** - * Verify that getDeviceAddress returns false, if status is not SUCCESS. - */ - @Test - public void testGetDeviceAddress_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pIface.getDeviceAddressCallback cb) { - cb.onValues(mStatusFailure, null); - } - }) - .when(mISupplicantP2pIfaceMock).getDeviceAddress( - any(ISupplicantP2pIface.getDeviceAddressCallback.class)); - - assertNull(mDut.getDeviceAddress()); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that getDeviceAddress disconnects and returns false, if HAL throws exception. - */ - @Test - public void testGetDeviceAddress_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doThrow(mRemoteException).when(mISupplicantP2pIfaceMock).getDeviceAddress( - any(ISupplicantP2pIface.getDeviceAddressCallback.class)); - - assertNull(mDut.getDeviceAddress()); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for getSsid() - */ - @Test - public void testGetSsid_success() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ISupplicantP2pIface.getSsidCallback cb) { - cb.onValues(mStatusSuccess, mSsidBytes); - } - }) - .when(mISupplicantP2pIfaceMock).getSsid( - eq(mPeerMacAddressBytes), - any(ISupplicantP2pIface.getSsidCallback.class)); - - // Default value when service is not initialized. - assertNull(mDut.getSsid(mPeerMacAddress)); - executeAndValidateInitializationSequence(false, false, false); - assertEquals(NativeUtil.removeEnclosingQuotes(mSsid), mDut.getSsid(mPeerMacAddress)); - } - - /** - * Test getSsid() with invalid argument and response. - */ - @Test - public void testGetSsid_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ISupplicantP2pIface.getSsidCallback cb) { - cb.onValues(mStatusSuccess, mSsidBytes); - } - }) - .when(mISupplicantP2pIfaceMock).getSsid( - any(byte[].class), any(ISupplicantP2pIface.getSsidCallback.class)); - - for (String address : mInvalidMacAddresses) { - assertNull(mDut.getSsid(address)); - } - - // Simulate null response from HAL. - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ISupplicantP2pIface.getSsidCallback cb) { - cb.onValues(mStatusSuccess, null); - } - }) - .when(mISupplicantP2pIfaceMock).getSsid( - any(byte[].class), any(ISupplicantP2pIface.getSsidCallback.class)); - - assertNull(mDut.getSsid(mPeerMacAddress)); - } - - /** - * Verify that getSsid returns false, if status is not SUCCESS. - */ - @Test - public void testGetSsid_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ISupplicantP2pIface.getSsidCallback cb) { - cb.onValues(mStatusFailure, null); - } - }) - .when(mISupplicantP2pIfaceMock).getSsid( - any(byte[].class), any(ISupplicantP2pIface.getSsidCallback.class)); - - assertNull(mDut.getSsid(mPeerMacAddress)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that getSsid disconnects and returns false, if HAL throws exception. - */ - @Test - public void testGetSsid_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doThrow(mRemoteException) - .when(mISupplicantP2pIfaceMock).getSsid( - any(byte[].class), any(ISupplicantP2pIface.getSsidCallback.class)); - - assertNull(mDut.getSsid(mPeerMacAddress)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for reinvoke() - */ - @Test - public void testReinvoke_success() throws Exception { - when(mISupplicantP2pIfaceMock.reinvoke(anyInt(), eq(mPeerMacAddressBytes))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.reinvoke(0, mPeerMacAddress)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.reinvoke(0, mPeerMacAddress)); - } - - /** - * Reinvoke with invalid arguments. - */ - @Test - public void testReinvoke_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.reinvoke(anyInt(), any(byte[].class))) - .thenReturn(mStatusSuccess); - - for (String address : mInvalidMacAddresses) { - assertFalse(mDut.reinvoke(0, address)); - } - } - - /** - * Verify that reinvoke returns false, if status is not SUCCESS. - */ - @Test - public void testReinvoke_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.reinvoke(anyInt(), any(byte[].class))) - .thenReturn(mStatusFailure); - assertFalse(mDut.reinvoke(0, mPeerMacAddress)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that reinvoke disconnects and returns false, if HAL throws exception. - */ - @Test - public void testReinvoke_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.reinvoke(anyInt(), any(byte[].class))) - .thenThrow(mRemoteException); - assertFalse(mDut.reinvoke(0, mPeerMacAddress)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for groupAdd() - */ - @Test - public void testGroupAdd_success() throws Exception { - when(mISupplicantP2pIfaceMock.addGroup(eq(true), eq(3))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.groupAdd(3, true)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.groupAdd(3, true)); - } - - /** - * Verify that groupAdd returns false, if status is not SUCCESS. - */ - @Test - public void testGroupAdd_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.addGroup(anyBoolean(), anyInt())) - .thenReturn(mStatusFailure); - assertFalse(mDut.groupAdd(0, true)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that groupAdd disconnects and returns false, if HAL throws exception. - */ - @Test - public void testGroupAdd_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.addGroup(anyBoolean(), anyInt())) - .thenThrow(mRemoteException); - assertFalse(mDut.groupAdd(0, true)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for groupAdd() with config - */ - @Test - public void testGroupAddWithConfigSuccess() throws Exception { - when(mISupplicantP2pIfaceMockV12.addGroup_1_2( - eq(NativeUtil.decodeSsid("\"" + mNetworkName + "\"")), - eq(mPassphrase), - eq(mIsPersistent), - eq(mGroupOwnerBand), - eq(mPeerMacAddressBytes), - anyBoolean())) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent, - mGroupOwnerBand, mPeerMacAddress, true)); - verify(mISupplicantP2pIfaceMockV12, never()).addGroup_1_2( - any(ArrayList.class), anyString(), - anyBoolean(), anyInt(), - any(byte[].class), anyBoolean()); - - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent, - mGroupOwnerBand, mPeerMacAddress, true)); - verify(mISupplicantP2pIfaceMockV12).addGroup_1_2( - eq(NativeUtil.decodeSsid("\"" + mNetworkName + "\"")), - eq(mPassphrase), - eq(mIsPersistent), - eq(mGroupOwnerBand), - eq(mPeerMacAddressBytes), - eq(true)); - } - - /** - * Verify that groupAdd with config returns false, if status is not SUCCESS. - */ - @Test - public void testGroupAddWithConfigFailure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMockV12.addGroup_1_2( - any(ArrayList.class), anyString(), - anyBoolean(), anyInt(), - any(byte[].class), anyBoolean())) - .thenReturn(mStatusFailure); - assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent, - mGroupOwnerBand, mPeerMacAddress, true)); - verify(mISupplicantP2pIfaceMockV12).addGroup_1_2( - eq(NativeUtil.decodeSsid("\"" + mNetworkName + "\"")), - eq(mPassphrase), - eq(mIsPersistent), - eq(mGroupOwnerBand), - eq(mPeerMacAddressBytes), - eq(true)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that groupAdd with config returns false, if HIDL revision older than v1.2. - */ - @Test - public void testGroupAddWithConfigFailureV1_0() throws Exception { - when(mISupplicantP2pIfaceMockV12.addGroup_1_2( - any(ArrayList.class), anyString(), - anyBoolean(), anyInt(), - any(byte[].class), anyBoolean())) - .thenReturn(mStatusSuccess); - executeAndValidateInitializationSequence(false, false, false); - // disable 1.2 interface to simulator since older revision cannot be casted to v1.2 - mISupplicantV12Enabled = false; - - assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent, - mGroupOwnerBand, mPeerMacAddress, true)); - verify(mISupplicantP2pIfaceMockV12, never()).addGroup_1_2( - any(ArrayList.class), anyString(), - anyBoolean(), anyInt(), - any(byte[].class), anyBoolean()); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - - /** - * Verify that groupAdd with config disconnects and returns false, if HAL throws exception. - */ - @Test - public void testGroupAddWithConfigException() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMockV12.addGroup_1_2( - any(ArrayList.class), anyString(), - anyBoolean(), anyInt(), - any(byte[].class), anyBoolean())) - .thenThrow(mRemoteException); - assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent, - mGroupOwnerBand, mPeerMacAddress, true)); - verify(mISupplicantP2pIfaceMockV12).addGroup_1_2( - eq(NativeUtil.decodeSsid("\"" + mNetworkName + "\"")), - eq(mPassphrase), - eq(mIsPersistent), - eq(mGroupOwnerBand), - eq(mPeerMacAddressBytes), - eq(true)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - /** - * Sunny day scenario for groupRemove() - */ - @Test - public void testGroupRemove_success() throws Exception { - when(mISupplicantP2pIfaceMock.removeGroup(eq(mIfaceName))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.groupRemove(mIfaceName)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.groupRemove(mIfaceName)); - } - - /** - * Verify that groupRemove returns false, if status is not SUCCESS. - */ - @Test - public void testGroupRemove_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.removeGroup(anyString())) - .thenReturn(mStatusFailure); - assertFalse(mDut.groupRemove(mIfaceName)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that groupRemove disconnects and returns false, if HAL throws exception. - */ - @Test - public void testGroupRemove_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.removeGroup(anyString())) - .thenThrow(mRemoteException); - assertFalse(mDut.groupRemove(mIfaceName)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for getGroupCapability() - */ - @Test - public void testGetGroupCapability_success() throws Exception { - final int caps = 123; - - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ISupplicantP2pIface.getGroupCapabilityCallback cb) { - cb.onValues(mStatusSuccess, caps); - } - }) - .when(mISupplicantP2pIfaceMock) - .getGroupCapability( - eq(mPeerMacAddressBytes), - any(ISupplicantP2pIface.getGroupCapabilityCallback.class)); - - // Default value when service is not initialized. - assertEquals(-1, mDut.getGroupCapability(mPeerMacAddress)); - executeAndValidateInitializationSequence(false, false, false); - assertEquals(caps, mDut.getGroupCapability(mPeerMacAddress)); - } - - /** - * GetGroupCapability with invalid arguments. - */ - @Test - public void testGetGroupCapability_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ISupplicantP2pIface.getGroupCapabilityCallback cb) { - cb.onValues(mStatusSuccess, 0); - } - }) - .when(mISupplicantP2pIfaceMock) - .getGroupCapability( - eq(mPeerMacAddressBytes), - any(ISupplicantP2pIface.getGroupCapabilityCallback.class)); - - for (String address : mInvalidMacAddresses) { - assertEquals(-1, mDut.getGroupCapability(address)); - } - } - - /** - * Verify that getGroupCapability returns false, if status is not SUCCESS. - */ - @Test - public void testGetGroupCapability_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ISupplicantP2pIface.getGroupCapabilityCallback cb) { - cb.onValues(mStatusFailure, 0); - } - }) - .when(mISupplicantP2pIfaceMock) - .getGroupCapability( - eq(mPeerMacAddressBytes), - any(ISupplicantP2pIface.getGroupCapabilityCallback.class)); - - assertEquals(-1, mDut.getGroupCapability(mPeerMacAddress)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that getGroupCapability disconnects and returns false, if HAL throws exception. - */ - @Test - public void testGetGroupCapability_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doThrow(mRemoteException) - .when(mISupplicantP2pIfaceMock) - .getGroupCapability( - eq(mPeerMacAddressBytes), - any(ISupplicantP2pIface.getGroupCapabilityCallback.class)); - assertEquals(-1, mDut.getGroupCapability(mPeerMacAddress)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for configureExtListen() - */ - @Test - public void testConfigureExtListen_success() throws Exception { - when(mISupplicantP2pIfaceMock.configureExtListen(eq(123), eq(456))) - .thenReturn(mStatusSuccess); - when(mISupplicantP2pIfaceMock.configureExtListen(eq(0), eq(0))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.configureExtListen(true, 123, 456)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.configureExtListen(true, 123, 456)); - // Turning listening off should reset intervals to 0s. - assertTrue(mDut.configureExtListen(false, 999, 999)); - // Disable listening. - assertTrue(mDut.configureExtListen(false, -1, -1)); - } - - /** - * Test configureExtListen with invalid parameters. - */ - @Test - public void testConfigureExtListen_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.configureExtListen(anyInt(), anyInt())) - .thenReturn(mStatusFailure); - assertFalse(mDut.configureExtListen(true, -1, 1)); - assertFalse(mDut.configureExtListen(true, 1, -1)); - } - - /** - * Verify that configureExtListen returns false, if status is not SUCCESS. - */ - @Test - public void testConfigureExtListen_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.configureExtListen(anyInt(), anyInt())) - .thenReturn(mStatusFailure); - assertFalse(mDut.configureExtListen(true, 1, 1)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that configureExtListen disconnects and returns false, if HAL throws exception. - */ - @Test - public void testConfigureExtListen_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.configureExtListen(anyInt(), anyInt())) - .thenThrow(mRemoteException); - assertFalse(mDut.configureExtListen(true, 1, 1)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for setListenChannel() - */ - @Test - public void testSetListenChannel_success() throws Exception { - int lc = 4; - int oc = 163; - ISupplicantP2pIface.FreqRange range1 = new ISupplicantP2pIface.FreqRange(); - range1.min = 1000; - range1.max = 5810; - ISupplicantP2pIface.FreqRange range2 = new ISupplicantP2pIface.FreqRange(); - range2.min = 5820; - range2.max = 6000; - ArrayList<ISupplicantP2pIface.FreqRange> ranges = new ArrayList<>(); - ranges.add(range1); - ranges.add(range2); - - when(mISupplicantP2pIfaceMock.setListenChannel(eq(lc), anyInt())) - .thenReturn(mStatusSuccess); - when(mISupplicantP2pIfaceMock.setDisallowedFrequencies(eq(ranges))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.setListenChannel(lc, oc)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.setListenChannel(lc, oc)); - } - - /** - * Sunny day scenario for setListenChannel() - */ - @Test - public void testSetListenChannel_successResetDisallowedFreq() throws Exception { - int lc = 2; - int oc = 0; - ArrayList<ISupplicantP2pIface.FreqRange> ranges = new ArrayList<>(); - - when(mISupplicantP2pIfaceMock.setListenChannel(eq(lc), anyInt())) - .thenReturn(mStatusSuccess); - when(mISupplicantP2pIfaceMock.setDisallowedFrequencies(eq(ranges))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.setListenChannel(lc, oc)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.setListenChannel(lc, oc)); - } - - /** - * Test setListenChannel with invalid parameters. - */ - @Test - public void testSetListenChannel_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setListenChannel(anyInt(), anyInt())) - .thenReturn(mStatusSuccess); - when(mISupplicantP2pIfaceMock.setDisallowedFrequencies(any(ArrayList.class))) - .thenReturn(mStatusSuccess); - assertFalse(mDut.setListenChannel(-1, 1)); - assertFalse(mDut.setListenChannel(1, -1)); - } - - /** - * Verify that setListenChannel returns false, if status is not SUCCESS. - */ - @Test - public void testSetListenChannel_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setListenChannel(anyInt(), anyInt())) - .thenReturn(mStatusFailure); - when(mISupplicantP2pIfaceMock.setDisallowedFrequencies(any(ArrayList.class))) - .thenReturn(mStatusSuccess); - assertFalse(mDut.setListenChannel(1, 1)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that setListenChannel disconnects and returns false, if HAL throws exception. - */ - @Test - public void testSetListenChannel_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setListenChannel(anyInt(), anyInt())) - .thenThrow(mRemoteException); - assertFalse(mDut.setListenChannel(1, 1)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for serviceAdd() - */ - @Test - public void testServiceAdd_success() throws Exception { - WifiP2pServiceInfo info = createDummyP2pServiceInfo( - mValidUpnpService, mValidBonjourService); - final HashSet<String> services = new HashSet<String>(); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int version, String name) { - services.add("upnp"); - assertEquals(mValidUpnpServiceVersion, version); - assertEquals(mValidUpnpServiceName, name); - return mStatusSuccess; - } - }) - .when(mISupplicantP2pIfaceMock).addUpnpService(anyInt(), anyString()); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> request, ArrayList<Byte> response) { - services.add("bonjour"); - assertEquals(mValidBonjourServiceRequest, request); - assertEquals(mValidBonjourServiceResponse, response); - return mStatusSuccess; - } - }) - .when(mISupplicantP2pIfaceMock).addBonjourService( - any(ArrayList.class), any(ArrayList.class)); - - // Default value when service is not initialized. - assertFalse(mDut.serviceAdd(info)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.serviceAdd(info)); - // Confirm that both services have been added. - assertTrue(services.contains("upnp")); - assertTrue(services.contains("bonjour")); - - // Empty services should cause no trouble. - assertTrue(mDut.serviceAdd(createDummyP2pServiceInfo())); - } - - /** - * Test serviceAdd with invalid parameters. - */ - @Test - public void testServiceAdd_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - when(mISupplicantP2pIfaceMock.addUpnpService(anyInt(), anyString())) - .thenReturn(mStatusSuccess); - when(mISupplicantP2pIfaceMock.addBonjourService( - any(ArrayList.class), any(ArrayList.class))) - .thenReturn(mStatusSuccess); - - assertFalse(mDut.serviceAdd(null)); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidService1))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidService2))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidUpnpService1))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidUpnpService2))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidUpnpService3))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidBonjourService1))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidBonjourService2))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidBonjourService3))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mInvalidBonjourService4))); - } - - /** - * Verify that serviceAdd returns false, if status is not SUCCESS. - */ - @Test - public void testServiceAdd_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - when(mISupplicantP2pIfaceMock.addUpnpService(anyInt(), anyString())) - .thenReturn(mStatusFailure); - when(mISupplicantP2pIfaceMock.addBonjourService( - any(ArrayList.class), any(ArrayList.class))) - .thenReturn(mStatusFailure); - - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mValidUpnpService))); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mValidBonjourService))); - - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that serviceAdd disconnects and returns false, if HAL throws exception. - */ - @Test - public void testServiceAdd_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - when(mISupplicantP2pIfaceMock.addUpnpService(anyInt(), anyString())) - .thenThrow(mRemoteException); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mValidUpnpService))); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.addBonjourService( - any(ArrayList.class), any(ArrayList.class))) - .thenThrow(mRemoteException); - assertFalse(mDut.serviceAdd(createDummyP2pServiceInfo(mValidBonjourService))); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for serviceRemove() - */ - @Test - public void testServiceRemove_success() throws Exception { - WifiP2pServiceInfo info = createDummyP2pServiceInfo( - mValidUpnpService, mValidBonjourService); - final HashSet<String> services = new HashSet<String>(); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(int version, String name) { - services.add("upnp"); - assertEquals(mValidUpnpServiceVersion, version); - assertEquals(mValidUpnpServiceName, name); - return mStatusSuccess; - } - }) - .when(mISupplicantP2pIfaceMock).removeUpnpService(anyInt(), anyString()); - - doAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(ArrayList<Byte> request) { - services.add("bonjour"); - assertEquals(mValidBonjourServiceRequest, request); - return mStatusSuccess; - } - }) - .when(mISupplicantP2pIfaceMock).removeBonjourService(any(ArrayList.class)); - - // Default value when service is not initialized. - assertFalse(mDut.serviceRemove(info)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.serviceRemove(info)); - // Confirm that both services have been removed. - assertTrue(services.contains("upnp")); - assertTrue(services.contains("bonjour")); - - // Empty services should cause no trouble. - assertTrue(mDut.serviceRemove(createDummyP2pServiceInfo())); - } - - /** - * Test serviceRemove with invalid parameters. - */ - @Test - public void testServiceRemove_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - when(mISupplicantP2pIfaceMock.removeUpnpService(anyInt(), anyString())) - .thenReturn(mStatusSuccess); - when(mISupplicantP2pIfaceMock.removeBonjourService(any(ArrayList.class))) - .thenReturn(mStatusSuccess); - - assertFalse(mDut.serviceRemove(null)); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidService1))); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidService2))); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidUpnpService1))); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidUpnpService2))); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidUpnpService3))); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidBonjourService1))); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidBonjourService2))); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidBonjourService3))); - // Response parameter is ignored by serviceRemove call, hence the following would pass. - // The production code would need to parse otherwise redundant parameter to fail on this - // one. - // - // assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mInvalidBonjourService4))); - } - - /** - * Verify that serviceRemove returns false, if status is not SUCCESS. - */ - @Test - public void testServiceRemove_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - when(mISupplicantP2pIfaceMock.removeUpnpService(anyInt(), anyString())) - .thenReturn(mStatusFailure); - when(mISupplicantP2pIfaceMock.removeBonjourService(any(ArrayList.class))) - .thenReturn(mStatusFailure); - - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mValidUpnpService))); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mValidBonjourService))); - - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that serviceRemove disconnects and returns false, if HAL throws exception. - */ - @Test - public void testServiceRemove_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - when(mISupplicantP2pIfaceMock.removeUpnpService(anyInt(), anyString())) - .thenThrow(mRemoteException); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mValidUpnpService))); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.removeBonjourService(any(ArrayList.class))) - .thenThrow(mRemoteException); - assertFalse(mDut.serviceRemove(createDummyP2pServiceInfo(mValidBonjourService))); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for requestServiceDiscovery() - */ - @Test - public void testRequestServiceDiscovery_success() throws Exception { - final int caps = 123; - - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ArrayList<Byte> query, - ISupplicantP2pIface.requestServiceDiscoveryCallback cb) { - cb.onValues(mStatusSuccess, 1234); - } - }) - .when(mISupplicantP2pIfaceMock) - .requestServiceDiscovery( - eq(mPeerMacAddressBytes), - eq(mValidBonjourServiceRequest), - any(ISupplicantP2pIface.requestServiceDiscoveryCallback.class)); - - // Default value when service is not initialized. - assertNull(mDut.requestServiceDiscovery(mPeerMacAddress, mValidServiceRequestString)); - - executeAndValidateInitializationSequence(false, false, false); - assertEquals("1234", mDut.requestServiceDiscovery( - mPeerMacAddress, mValidServiceRequestString)); - } - - /** - * RequestServiceDiscovery with invalid arguments. - */ - @Test - public void testRequestServiceDiscovery_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - doAnswer(new AnswerWithArguments() { - public void answer(byte[] address, ArrayList<Byte> query, - ISupplicantP2pIface.requestServiceDiscoveryCallback cb) { - cb.onValues(mStatusSuccess, 0); - } - }) - .when(mISupplicantP2pIfaceMock) - .requestServiceDiscovery( - any(byte[].class), any(ArrayList.class), - any(ISupplicantP2pIface.requestServiceDiscoveryCallback.class)); - - for (String address : mInvalidMacAddresses) { - assertNull(mDut.requestServiceDiscovery( - address, mValidServiceRequestString)); - } - assertNull(mDut.requestServiceDiscovery(mPeerMacAddress, null)); - assertNull(mDut.requestServiceDiscovery(mPeerMacAddress, mInvalidServiceRequestString)); - } - - /** - * Verify that requestServiceDiscovery returns false, if status is not SUCCESS. - */ - @Test - public void testRequestServiceDiscovery_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - doAnswer(new AnswerWithArguments() { - public void answer( - byte[] address, ArrayList<Byte> query, - ISupplicantP2pIface.requestServiceDiscoveryCallback cb) { - cb.onValues(mStatusFailure, 0); - } - }) - .when(mISupplicantP2pIfaceMock) - .requestServiceDiscovery( - any(byte[].class), any(ArrayList.class), - any(ISupplicantP2pIface.requestServiceDiscoveryCallback.class)); - - assertNull(mDut.requestServiceDiscovery(mPeerMacAddress, mValidServiceRequestString)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that requestServiceDiscovery disconnects and returns false, if HAL throws exception. - */ - @Test - public void testRequestServiceDiscovery_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doThrow(mRemoteException) - .when(mISupplicantP2pIfaceMock) - .requestServiceDiscovery( - any(byte[].class), any(ArrayList.class), - any(ISupplicantP2pIface.requestServiceDiscoveryCallback.class)); - assertNull(mDut.requestServiceDiscovery(mPeerMacAddress, mValidServiceRequestString)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - // Test constant used in cancelServiceDiscovery tests - static final String SERVICE_IDENTIFIER_STR = "521918410304"; - static final long SERVICE_IDENTIFIER_LONG = 521918410304L; - - /** - * Sunny day scenario for cancelServiceDiscovery() - */ - @Test - public void testCancelServiceDiscovery_success() throws Exception { - when(mISupplicantP2pIfaceMock.cancelServiceDiscovery(SERVICE_IDENTIFIER_LONG)) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.cancelServiceDiscovery(SERVICE_IDENTIFIER_STR)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.cancelServiceDiscovery(SERVICE_IDENTIFIER_STR)); - } - - /** - * Test cancelServiceDiscovery with invalid parameters. - */ - @Test - public void testCancelServiceDiscovery_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.cancelServiceDiscovery(anyLong())) - .thenReturn(mStatusFailure); - assertFalse(mDut.cancelServiceDiscovery(null)); - assertFalse(mDut.cancelServiceDiscovery("not a number")); - } - - /** - * Verify that cancelServiceDiscovery returns false, if status is not SUCCESS. - */ - @Test - public void testCancelServiceDiscovery_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.cancelServiceDiscovery(anyLong())) - .thenReturn(mStatusFailure); - assertFalse(mDut.cancelServiceDiscovery(SERVICE_IDENTIFIER_STR)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that cancelServiceDiscovery disconnects and returns false, if HAL throws exception. - */ - @Test - public void testCancelServiceDiscovery_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.cancelServiceDiscovery(anyLong())) - .thenThrow(mRemoteException); - assertFalse(mDut.cancelServiceDiscovery(SERVICE_IDENTIFIER_STR)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for setMiracastMode() - */ - @Test - public void testSetMiracastMode_success() throws Exception { - HashSet<Byte> modes = new HashSet<Byte>(); - - when(mISupplicantP2pIfaceMock.setMiracastMode(anyByte())) - .thenAnswer(new AnswerWithArguments() { - public SupplicantStatus answer(byte mode) { - modes.add(mode); - return mStatusSuccess; - } - }); - // Default value when service is not initialized. - assertFalse(mDut.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE)); - assertTrue(modes.contains(ISupplicantP2pIface.MiracastMode.SOURCE)); - - assertTrue(mDut.setMiracastMode(WifiP2pManager.MIRACAST_SINK)); - assertTrue(modes.contains(ISupplicantP2pIface.MiracastMode.SINK)); - - // Any invalid number yields disabled miracast mode. - assertTrue(mDut.setMiracastMode(-1)); - assertTrue(modes.contains(ISupplicantP2pIface.MiracastMode.DISABLED)); - } - - /** - * Verify that setMiracastMode returns false, if status is not SUCCESS. - */ - @Test - public void testSetMiracastMode_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setMiracastMode(anyByte())) - .thenReturn(mStatusFailure); - assertFalse(mDut.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that setMiracastMode disconnects and returns false, if HAL throws exception. - */ - @Test - public void testSetMiracastMode_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setMiracastMode(anyByte())) - .thenThrow(mRemoteException); - assertFalse(mDut.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for startWpsPbc() - */ - @Test - public void testStartWpsPbc_success() throws Exception { - when(mISupplicantP2pIfaceMock.startWpsPbc(eq(mIfaceName), eq(mPeerMacAddressBytes))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.startWpsPbc(mIfaceName, mPeerMacAddress)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.startWpsPbc(mIfaceName, mPeerMacAddress)); - } - - /** - * StartWpsPbc with invalid arguments. - */ - @Test - public void testStartWpsPbc_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.startWpsPbc(anyString(), any(byte[].class))) - .thenReturn(mStatusSuccess); - - for (String address : mInvalidMacAddresses) { - assertFalse(mDut.startWpsPbc(mIfaceName, address)); - } - - assertFalse(mDut.startWpsPbc(null, mPeerMacAddress)); - } - - /** - * Verify that startWpsPbc returns false, if status is not SUCCESS. - */ - @Test - public void testStartWpsPbc_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.startWpsPbc(anyString(), any(byte[].class))) - .thenReturn(mStatusFailure); - assertFalse(mDut.startWpsPbc(mIfaceName, mPeerMacAddress)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that startWpsPbc disconnects and returns false, if HAL throws exception. - */ - @Test - public void testStartWpsPbc_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.startWpsPbc(anyString(), any(byte[].class))) - .thenThrow(mRemoteException); - assertFalse(mDut.startWpsPbc(mIfaceName, mPeerMacAddress)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for startWpsPinKeypad() - */ - @Test - public void testStartWpsPinKeypad_success() throws Exception { - when(mISupplicantP2pIfaceMock.startWpsPinKeypad(eq(mIfaceName), eq("1234"))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.startWpsPinKeypad(mIfaceName, "1234")); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.startWpsPinKeypad(mIfaceName, "1234")); - } - - /** - * StartWpsPinKeypad with invalid arguments. - */ - @Test - public void testStartWpsPinKeypad_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.startWpsPinKeypad(anyString(), anyString())) - .thenReturn(mStatusSuccess); - - assertFalse(mDut.startWpsPinKeypad(null, "1234")); - assertFalse(mDut.startWpsPinKeypad(mIfaceName, null)); - // StartWpsPinPinKeypad does not validate, that PIN indeed holds an integer encoded in a - // string. This code would be redundant, as HAL requires string to be passed. - } - - /** - * Verify that startWpsPinKeypad returns false, if status is not SUCCESS. - */ - @Test - public void testStartWpsPinKeypad_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.startWpsPinKeypad(anyString(), anyString())) - .thenReturn(mStatusFailure); - assertFalse(mDut.startWpsPinKeypad(mIfaceName, "1234")); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that startWpsPinKeypad disconnects and returns false, if HAL throws exception. - */ - @Test - public void testStartWpsPinKeypad_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.startWpsPinKeypad(anyString(), anyString())) - .thenThrow(mRemoteException); - assertFalse(mDut.startWpsPinKeypad(mIfaceName, "1234")); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for startWpsPinDisplay() - */ - @Test - public void testStartWpsPinDisplay_success() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer(String ifName, byte[] bssid, - ISupplicantP2pIface.startWpsPinDisplayCallback cb) { - cb.onValues(mStatusSuccess, "1234"); - } - }) - .when(mISupplicantP2pIfaceMock).startWpsPinDisplay( - eq(mIfaceName), eq(mPeerMacAddressBytes), - any(ISupplicantP2pIface.startWpsPinDisplayCallback.class)); - - // Default value when service is not initialized. - assertNull(mDut.startWpsPinDisplay(mIfaceName, mPeerMacAddress)); - executeAndValidateInitializationSequence(false, false, false); - assertEquals("1234", mDut.startWpsPinDisplay(mIfaceName, mPeerMacAddress)); - } - - /** - * StartWpsPinDisplay with invalid arguments. - */ - @Test - public void testStartWpsPinDisplay_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(String ifName, byte[] bssid, - ISupplicantP2pIface.startWpsPinDisplayCallback cb) { - cb.onValues(mStatusSuccess, "1234"); - } - }) - .when(mISupplicantP2pIfaceMock).startWpsPinDisplay( - anyString(), any(byte[].class), - any(ISupplicantP2pIface.startWpsPinDisplayCallback.class)); - - for (String address : mInvalidMacAddresses) { - assertNull(mDut.startWpsPinDisplay(mIfaceName, address)); - } - - assertNull(mDut.startWpsPinDisplay(null, mPeerMacAddress)); - } - - /** - * Verify that startWpsPinDisplay returns false, if status is not SUCCESS. - */ - @Test - public void testStartWpsPinDisplay_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(String ifName, byte[] bssid, - ISupplicantP2pIface.startWpsPinDisplayCallback cb) { - cb.onValues(mStatusFailure, "1234"); - } - }) - .when(mISupplicantP2pIfaceMock).startWpsPinDisplay( - anyString(), any(byte[].class), - any(ISupplicantP2pIface.startWpsPinDisplayCallback.class)); - - assertNull(mDut.startWpsPinDisplay(mIfaceName, mPeerMacAddress)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that startWpsPinDisplay disconnects and returns false, if HAL throws exception. - */ - @Test - public void testStartWpsPinDisplay_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - doThrow(mRemoteException) - .when(mISupplicantP2pIfaceMock).startWpsPinDisplay( - anyString(), any(byte[].class), - any(ISupplicantP2pIface.startWpsPinDisplayCallback.class)); - assertNull(mDut.startWpsPinDisplay(mIfaceName, mPeerMacAddress)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for cancelWps() - */ - @Test - public void testCancelWps_success() throws Exception { - when(mISupplicantP2pIfaceMock.cancelWps(eq(mIfaceName))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.cancelWps(mIfaceName)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.cancelWps(mIfaceName)); - } - - /** - * CancelWps with invalid arguments. - */ - @Test - public void testCancelWps_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.cancelWps(anyString())) - .thenReturn(mStatusSuccess); - - assertFalse(mDut.cancelWps(null)); - } - - /** - * Verify that cancelWps returns false, if status is not SUCCESS. - */ - @Test - public void testCancelWps_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.cancelWps(anyString())) - .thenReturn(mStatusFailure); - assertFalse(mDut.cancelWps(mIfaceName)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that cancelWps disconnects and returns false, if HAL throws exception. - */ - @Test - public void testCancelWps_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.cancelWps(anyString())) - .thenThrow(mRemoteException); - assertFalse(mDut.cancelWps(mIfaceName)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for enableWfd() - */ - @Test - public void testEnableWfd_success() throws Exception { - when(mISupplicantP2pIfaceMock.enableWfd(eq(true))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.enableWfd(true)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.enableWfd(true)); - } - - /** - * Verify that enableWfd returns false, if status is not SUCCESS. - */ - @Test - public void testEnableWfd_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.enableWfd(anyBoolean())) - .thenReturn(mStatusFailure); - assertFalse(mDut.enableWfd(true)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that enableWfd disconnects and returns false, if HAL throws exception. - */ - @Test - public void testEnableWfd_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.enableWfd(anyBoolean())) - .thenThrow(mRemoteException); - assertFalse(mDut.enableWfd(false)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - - /** - * Sunny day scenario for setWfdDeviceInfo() - */ - @Test - public void testSetWfdDeviceInfo_success() throws Exception { - when(mISupplicantP2pIfaceMock.setWfdDeviceInfo(eq(mValidServiceRequestBytes))) - .thenReturn(mStatusSuccess); - // Default value when service is not initialized. - assertFalse(mDut.setWfdDeviceInfo(mValidServiceRequestString)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.setWfdDeviceInfo(mValidServiceRequestString)); - } - - /** - * SetWfdDeviceInfo with invalid arguments. - */ - @Test - public void testSetWfdDeviceInfo_invalidArguments() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setWfdDeviceInfo(any(byte[].class))) - .thenReturn(mStatusSuccess); - - assertFalse(mDut.setWfdDeviceInfo(null)); - assertFalse(mDut.setWfdDeviceInfo(mInvalidServiceRequestString)); - } - - /** - * Verify that setWfdDeviceInfo returns false, if status is not SUCCESS. - */ - @Test - public void testSetWfdDeviceInfo_failure() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setWfdDeviceInfo(any(byte[].class))) - .thenReturn(mStatusFailure); - assertFalse(mDut.setWfdDeviceInfo(mValidServiceRequestString)); - // Check that service is still alive. - assertTrue(mDut.isInitializationComplete()); - } - - /** - * Verify that setWfdDeviceInfo disconnects and returns false, if HAL throws exception. - */ - @Test - public void testSetWfdDeviceInfo_exception() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - when(mISupplicantP2pIfaceMock.setWfdDeviceInfo(any(byte[].class))) - .thenThrow(mRemoteException); - assertFalse(mDut.setWfdDeviceInfo(mValidServiceRequestString)); - // Check service is dead. - assertFalse(mDut.isInitializationComplete()); - } - - /** - * Verify the loading of group info. - * Specifically, all groups returned by listNetworks are added as a persistent group, so long as - * they are NOT current. - */ - @Test - public void testLoadGroups() throws Exception { - executeAndValidateInitializationSequence(false, false, false); - - // Class to hold the P2p group info returned from the HIDL interface. - class P2pGroupInfo { - public String ssid; - public byte[] bssid; - public boolean isGo; - public boolean isCurrent; - P2pGroupInfo(String ssid, byte[] bssid, boolean isGo, boolean isCurrent) { - this.ssid = ssid; - this.bssid = bssid; - this.isGo = isGo; - this.isCurrent = isCurrent; - } - } - - Map<Integer, P2pGroupInfo> groups = new HashMap<>(); - groups.put(0, new P2pGroupInfo( - "test_34", - NativeUtil.macAddressToByteArray("56:34:ab:12:12:34"), - false, false)); - groups.put(1, new P2pGroupInfo( - "test_1234", - NativeUtil.macAddressToByteArray("16:ed:ab:12:45:34"), - true, false)); - groups.put(2, new P2pGroupInfo( - "test_4545", - NativeUtil.macAddressToByteArray("32:89:23:56:45:34"), - true, false)); - groups.put(3, new P2pGroupInfo( - "iShouldntBeHere", - NativeUtil.macAddressToByteArray("aa:bb:cc:56:45:34"), - true, true)); - - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pIface.listNetworksCallback cb) { - cb.onValues(mStatusSuccess, new ArrayList<Integer>(groups.keySet())); - } - }).when(mISupplicantP2pIfaceMock) - .listNetworks(any(ISupplicantP2pIface.listNetworksCallback.class)); - - doAnswer(new AnswerWithArguments() { - public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) { - try { - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pNetwork.getSsidCallback cb) { - cb.onValues(mStatusSuccess, - NativeUtil.stringToByteArrayList(groups.get(networkId).ssid)); - return; - } - }).when(mISupplicantP2pNetworkMock) - .getSsid(any(ISupplicantP2pNetwork.getSsidCallback.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pNetwork.getBssidCallback cb) { - cb.onValues(mStatusSuccess, groups.get(networkId).bssid); - return; - } - }).when(mISupplicantP2pNetworkMock) - .getBssid(any(ISupplicantP2pNetwork.getBssidCallback.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pNetwork.isCurrentCallback cb) { - cb.onValues(mStatusSuccess, groups.get(networkId).isCurrent); - return; - } - }).when(mISupplicantP2pNetworkMock) - .isCurrent(any(ISupplicantP2pNetwork.isCurrentCallback.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pNetwork.isGoCallback cb) { - cb.onValues(mStatusSuccess, groups.get(networkId).isGo); - return; - } - }).when(mISupplicantP2pNetworkMock) - .isGo(any(ISupplicantP2pNetwork.isGoCallback.class)); - } catch (RemoteException e) { - } - cb.onValues(mStatusSuccess, mISupplicantP2pNetworkMock); - return; - } - }).when(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - - WifiP2pGroupList p2pGroups = new WifiP2pGroupList(); - assertTrue(mDut.loadGroups(p2pGroups)); - - assertEquals(3, p2pGroups.getGroupList().size()); - for (WifiP2pGroup group : p2pGroups.getGroupList()) { - int networkId = group.getNetworkId(); - assertEquals(groups.get(networkId).ssid, group.getNetworkName()); - assertEquals( - NativeUtil.macAddressFromByteArray(groups.get(networkId).bssid), - group.getOwner().deviceAddress); - assertEquals(groups.get(networkId).isGo, group.isGroupOwner()); - } - } - - /** - * Sunny day scenario for setClientList() - */ - @Test - public void testSetClientList() throws Exception { - int testNetworkId = 5; - final String client1 = mGroupOwnerMacAddress; - final String client2 = mPeerMacAddress; - - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) { - if (networkId == testNetworkId) { - cb.onValues(mStatusSuccess, mISupplicantP2pNetworkMock); - } else { - cb.onValues(mStatusFailure, null); - } - return; - } - }).when(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - when(mISupplicantP2pNetworkMock.setClientList(any(ArrayList.class))) - .thenReturn(mStatusSuccess); - - String clientList = client1 + " " + client2; - assertTrue(mDut.setClientList(testNetworkId, clientList)); - verify(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - ArgumentCaptor<ArrayList> capturedClients = ArgumentCaptor.forClass(ArrayList.class); - verify(mISupplicantP2pNetworkMock).setClientList(capturedClients.capture()); - - // Convert these to long to help with comparisons. - ArrayList<byte[]> clients = capturedClients.getValue(); - ArrayList<Long> expectedClients = new ArrayList<Long>() {{ - add(NativeUtil.macAddressToLong(mGroupOwnerMacAddressBytes)); - add(NativeUtil.macAddressToLong(mPeerMacAddressBytes)); - }}; - ArrayList<Long> receivedClients = new ArrayList<Long>(); - for (byte[] client : clients) { - receivedClients.add(NativeUtil.macAddressToLong(client)); - } - assertEquals(expectedClients, receivedClients); - } - - /** - * Failure scenario for setClientList() when getNetwork returns null. - */ - @Test - public void testSetClientListFailureDueToGetNetwork() throws Exception { - int testNetworkId = 5; - final String client1 = mGroupOwnerMacAddress; - final String client2 = mPeerMacAddress; - - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) { - cb.onValues(mStatusFailure, null); - return; - } - }).when(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - when(mISupplicantP2pNetworkMock.setClientList(any(ArrayList.class))) - .thenReturn(mStatusSuccess); - - String clientList = client1 + " " + client2; - assertFalse(mDut.setClientList(testNetworkId, clientList)); - verify(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - verify(mISupplicantP2pNetworkMock, never()).setClientList(any(ArrayList.class)); - } - - /** - * Sunny day scenario for getClientList() - */ - @Test - public void testGetClientList() throws Exception { - int testNetworkId = 5; - final String client1 = mGroupOwnerMacAddress; - final String client2 = mPeerMacAddress; - - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) { - if (networkId == testNetworkId) { - cb.onValues(mStatusSuccess, mISupplicantP2pNetworkMock); - } else { - cb.onValues(mStatusFailure, null); - } - return; - } - }).when(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pNetwork.getClientListCallback cb) { - ArrayList<byte[]> clients = new ArrayList<byte[]>() {{ - add(mGroupOwnerMacAddressBytes); - add(mPeerMacAddressBytes); - }}; - cb.onValues(mStatusSuccess, clients); - return; - } - }).when(mISupplicantP2pNetworkMock) - .getClientList(any(ISupplicantP2pNetwork.getClientListCallback.class)); - - String clientList = client1 + " " + client2; - assertEquals(clientList, mDut.getClientList(testNetworkId)); - verify(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - verify(mISupplicantP2pNetworkMock) - .getClientList(any(ISupplicantP2pNetwork.getClientListCallback.class)); - } - - /** - * Failure scenario for getClientList() when getNetwork returns null. - */ - @Test - public void testGetClientListFailureDueToGetNetwork() throws Exception { - int testNetworkId = 5; - final String client1 = mGroupOwnerMacAddress; - final String client2 = mPeerMacAddress; - - executeAndValidateInitializationSequence(false, false, false); - doAnswer(new AnswerWithArguments() { - public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) { - cb.onValues(mStatusFailure, null); - return; - } - }).when(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicantP2pNetwork.getClientListCallback cb) { - ArrayList<byte[]> clients = new ArrayList<byte[]>() {{ - add(mGroupOwnerMacAddressBytes); - add(mPeerMacAddressBytes); - }}; - cb.onValues(mStatusSuccess, clients); - return; - } - }).when(mISupplicantP2pNetworkMock) - .getClientList(any(ISupplicantP2pNetwork.getClientListCallback.class)); - - assertEquals(null, mDut.getClientList(testNetworkId)); - verify(mISupplicantP2pIfaceMock) - .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); - verify(mISupplicantP2pNetworkMock, never()) - .getClientList(any(ISupplicantP2pNetwork.getClientListCallback.class)); - } - - /** - * Sunny day scenario for saveConfig() - */ - @Test - public void testSaveConfig() throws Exception { - when(mISupplicantP2pIfaceMock.saveConfig()).thenReturn(mStatusSuccess); - - // Should fail before initialization. - assertFalse(mDut.saveConfig()); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.saveConfig()); - verify(mISupplicantP2pIfaceMock).saveConfig(); - } - - /** - * Sunny day scenario for setMacRandomization() - */ - @Test - public void testEnableMacRandomization() throws Exception { - when(mISupplicantP2pIfaceMockV12.setMacRandomization(anyBoolean())) - .thenReturn(mStatusSuccess); - - // Should fail before initialization. - assertFalse(mDut.setMacRandomization(true)); - executeAndValidateInitializationSequence(false, false, false); - assertTrue(mDut.setMacRandomization(true)); - verify(mISupplicantP2pIfaceMockV12).setMacRandomization(eq(true)); - } - - /** - * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the - * expected result. Verifies if ISupplicantP2pIface manager is initialized or reset. - * Each of the arguments will cause a different failure mode when set true. - */ - private void executeAndValidateInitializationSequence(boolean causeRemoteException, - boolean getZeroInterfaces, boolean getNullInterface) throws Exception { - boolean shouldSucceed = !causeRemoteException && !getZeroInterfaces && !getNullInterface; - // Setup callback mock answers - ArrayList<ISupplicant.IfaceInfo> interfaces; - if (getZeroInterfaces) { - interfaces = new ArrayList<ISupplicant.IfaceInfo>(); - } else { - interfaces = mIfaceInfoList; - } - - doAnswer(new AnswerWithArguments() { - public void answer(ISupplicant.listInterfacesCallback cb) throws RemoteException { - cb.onValues(mStatusSuccess, interfaces); - } - }) - .when(mISupplicantMock).listInterfaces(any(ISupplicant.listInterfacesCallback.class)); - - if (causeRemoteException) { - doThrow(new RemoteException("Some error!!!")) - .when(mISupplicantMock).getInterface(any(ISupplicant.IfaceInfo.class), - any(ISupplicant.getInterfaceCallback.class)); - } else { - doAnswer(new GetGetInterfaceAnswer(getNullInterface)) - .when(mISupplicantMock).getInterface(any(ISupplicant.IfaceInfo.class), - any(ISupplicant.getInterfaceCallback.class)); - } - - mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantP2pIfaceMock); - // Initialize SupplicantP2pIfaceHal, should call serviceManager.registerForNotifications - assertTrue(mDut.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath( - any(IHwBinder.DeathRecipient.class), anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true); - mInOrder.verify(mISupplicantMock).linkToDeath( - any(IHwBinder.DeathRecipient.class), anyLong()); - assertEquals(true, mDut.isInitializationComplete()); - - // Now setup the iface. - assertTrue(mDut.setupIface(mIfaceName) == shouldSucceed); - - // verify: listInterfaces is called - mInOrder.verify(mISupplicantMock).listInterfaces( - any(ISupplicant.listInterfacesCallback.class)); - if (!causeRemoteException && !getNullInterface && !getZeroInterfaces) { - mInOrder.verify(mISupplicantMock) - .getInterface(any(ISupplicant.IfaceInfo.class), - any(ISupplicant.getInterfaceCallback.class)); - mInOrder.verify(mISupplicantP2pIfaceMock).linkToDeath( - any(IHwBinder.DeathRecipient.class), anyLong()); - mInOrder.verify(mISupplicantP2pIfaceMock).registerCallback( - any(ISupplicantP2pIfaceCallback.class)); - } - - // if no errors, V1_2 interface is on as well - mISupplicantV12Enabled = true; - } - - /** - * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the - * expected result. Verifies if ISupplicantP2pIface manager is initialized or reset. - * Each of the arguments will cause a different failure mode when set true. - */ - private void executeAndValidateInitializationSequenceV1_1(boolean causeRemoteException, - boolean getNullInterface) - throws Exception { - boolean shouldSucceed = !causeRemoteException && !getNullInterface; - // Setup callback mock answers - if (causeRemoteException) { - doThrow(new RemoteException("Some error!!!")) - .when(mISupplicantMockV1_1).addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback.class)); - } else { - doAnswer(new GetAddInterfaceAnswer(getNullInterface)) - .when(mISupplicantMockV1_1).addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback.class)); - } - - mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantMockV1_1, - mISupplicantP2pIfaceMock); - // Initialize SupplicantStaIfaceHal, should call serviceManager.registerForNotifications - assertTrue(mDut.initialize()); - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath( - any(IHwBinder.DeathRecipient.class), anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications( - eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); - // act: cause the onRegistration(...) callback to execute - mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true); - mInOrder.verify(mISupplicantMock).linkToDeath( - any(IHwBinder.DeathRecipient.class), anyLong()); - assertEquals(true, mDut.isInitializationComplete()); - - // Now setup the iface. - assertTrue(mDut.setupIface(mIfaceName) == shouldSucceed); - - // verify: addInterface is called - mInOrder.verify(mISupplicantMockV1_1) - .addInterface(any(ISupplicant.IfaceInfo.class), - any(android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback.class)); - if (!causeRemoteException && !getNullInterface) { - mInOrder.verify(mISupplicantP2pIfaceMock).linkToDeath( - any(IHwBinder.DeathRecipient.class), anyLong()); - mInOrder.verify(mISupplicantP2pIfaceMock).registerCallback( - any(ISupplicantP2pIfaceCallback.class)); - } - - // Ensure we don't try to use the listInterfaces method from 1.0 version. - verify(mISupplicantMock, never()).listInterfaces( - any(ISupplicant.listInterfacesCallback.class)); - verify(mISupplicantMock, never()).getInterface(any(ISupplicant.IfaceInfo.class), - any(ISupplicant.getInterfaceCallback.class)); - } - - private SupplicantStatus createSupplicantStatus(int code) { - SupplicantStatus status = new SupplicantStatus(); - status.code = code; - return status; - } - - /** - * Create an IfaceInfo with given type and name - */ - private ISupplicant.IfaceInfo createIfaceInfo(int type, String name) { - ISupplicant.IfaceInfo info = new ISupplicant.IfaceInfo(); - info.type = type; - info.name = name; - return info; - } - - /** - * Create new dummy WifiP2pConfig instance. - */ - private WifiP2pConfig createDummyP2pConfig(String peerAddress, int wpsProvMethod, String pin) { - WifiP2pConfig config = new WifiP2pConfig(); - config.wps = new WpsInfo(); - config.deviceAddress = peerAddress; - - config.wps.setup = wpsProvMethod; - config.wps.pin = pin; - - config.groupOwnerIntent = WifiP2pServiceImpl.DEFAULT_GROUP_OWNER_INTENT; - - return config; - } - - /** - * Create new dummy WifiP2pGroup instance. - */ - private WifiP2pGroup createDummyP2pGroup() { - WifiP2pGroup group = new WifiP2pGroup(); - group.setInterface(mIfaceName); - - WifiP2pDevice owner = new WifiP2pDevice(); - owner.deviceAddress = mGroupOwnerMacAddress; - group.setOwner(owner); - - return group; - } - - /** - * Create new dummy WifiP2pServiceInfo instance. - */ - private WifiP2pServiceInfo createDummyP2pServiceInfo(String... services) { - class TestP2pServiceInfo extends WifiP2pServiceInfo { - TestP2pServiceInfo(String[] services) { - super(Arrays.asList(services)); - } - } - return new TestP2pServiceInfo(services); - } - - private class GetGetInterfaceAnswer extends AnswerWithArguments { - boolean mGetNullInterface; - - GetGetInterfaceAnswer(boolean getNullInterface) { - mGetNullInterface = getNullInterface; - } - - public void answer(ISupplicant.IfaceInfo iface, ISupplicant.getInterfaceCallback cb) { - if (mGetNullInterface) { - cb.onValues(mStatusSuccess, null); - } else { - cb.onValues(mStatusSuccess, mISupplicantIfaceMock); - } - } - } - - private class GetAddInterfaceAnswer extends AnswerWithArguments { - boolean mGetNullInterface; - - GetAddInterfaceAnswer(boolean getNullInterface) { - mGetNullInterface = getNullInterface; - } - - public void answer(ISupplicant.IfaceInfo iface, - android.hardware.wifi.supplicant.V1_1.ISupplicant - .addInterfaceCallback cb) { - if (mGetNullInterface) { - cb.onValues(mStatusSuccess, null); - } else { - cb.onValues(mStatusSuccess, mISupplicantIfaceMock); - } - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pMetricsTest.java deleted file mode 100644 index bbfbd37b1..000000000 --- a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pMetricsTest.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.p2p; - -import static org.junit.Assert.assertEquals; - -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pGroupList; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.proto.nano.WifiMetricsProto.GroupEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiP2pStats; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.WifiP2pMetrics}. - */ -@SmallTest -public class WifiP2pMetricsTest extends WifiBaseTest { - @Mock Clock mClock; - WifiP2pMetrics mWifiP2pMetrics; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mWifiP2pMetrics = new WifiP2pMetrics(mClock); - } - - /** - * Test that startConnectionEvent and endConnectionEvent can be called repeatedly and out of - * order. Only tests no exception occurs and the count is correct. - * @throws Exception - */ - @Test - public void startAndEndConnectionEventSucceeds() throws Exception { - WifiP2pConfig config = new WifiP2pConfig(); - WifiP2pStats stats; - - // Start and end Connection event. - mWifiP2pMetrics.startConnectionEvent(P2pConnectionEvent.CONNECTION_FRESH, null); - mWifiP2pMetrics.endConnectionEvent(P2pConnectionEvent.CLF_NONE); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(1, stats.connectionEvent.length); - - // Start and end Connection event. - mWifiP2pMetrics.startConnectionEvent(P2pConnectionEvent.CONNECTION_FRESH, config); - mWifiP2pMetrics.endConnectionEvent(P2pConnectionEvent.CLF_NONE); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(2, stats.connectionEvent.length); - - // End Connection event without starting one. - // this would create a new connection event immediately. - mWifiP2pMetrics.endConnectionEvent(P2pConnectionEvent.CLF_TIMEOUT); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(3, stats.connectionEvent.length); - - // Start two ConnectionEvents in a row. - // The current active un-ended connection event is excluded. - mWifiP2pMetrics.startConnectionEvent(P2pConnectionEvent.CONNECTION_REINVOKE, config); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(3, stats.connectionEvent.length); - - // The last un-ended connection is ended. - // The current active un-ended connection event is excluded. - mWifiP2pMetrics.startConnectionEvent(P2pConnectionEvent.CONNECTION_REINVOKE, config); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(4, stats.connectionEvent.length); - } - - /** - * Test that startGroupEvent and endGroupEvent can be called repeastedly and out of order. - * Only tests no exception occurs and the count is correct. - * @throws Exception - */ - @Test - public void startAndEndGroupEventSucceeds() throws Exception { - WifiP2pGroup group = new WifiP2pGroup(); - WifiP2pStats stats; - - // Start and end Group event with null group. - // this won't generate valid group event. - mWifiP2pMetrics.startGroupEvent(null); - mWifiP2pMetrics.endGroupEvent(); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(0, stats.groupEvent.length); - - // Start and end Group event. - mWifiP2pMetrics.startGroupEvent(group); - mWifiP2pMetrics.endGroupEvent(); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(1, stats.groupEvent.length); - - // End Group event without starting one. - // just ignore this event. - mWifiP2pMetrics.endGroupEvent(); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(1, stats.groupEvent.length); - - // Start two GroupEvents in a row. - // The current active un-ended group event is excluded. - mWifiP2pMetrics.startGroupEvent(group); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(1, stats.groupEvent.length); - - // The last un-ended group is ended. - // The current active un-ended group event is excluded. - mWifiP2pMetrics.startGroupEvent(group); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(2, stats.groupEvent.length); - } - - /** - * Test that peer scan counter works normally. - * @throws Exception - */ - @Test - public void increasePeerScans() throws Exception { - WifiP2pStats stats; - mWifiP2pMetrics.incrementPeerScans(); - mWifiP2pMetrics.incrementPeerScans(); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(2, stats.numTotalPeerScans); - - mWifiP2pMetrics.clear(); - - mWifiP2pMetrics.incrementPeerScans(); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(1, stats.numTotalPeerScans); - } - - /** - * Test that service scan counter works normally. - * @throws Exception - */ - @Test - public void increaseServiceScans() throws Exception { - WifiP2pStats stats; - - mWifiP2pMetrics.incrementServiceScans(); - mWifiP2pMetrics.incrementServiceScans(); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(2, stats.numTotalServiceScans); - - mWifiP2pMetrics.clear(); - - mWifiP2pMetrics.incrementServiceScans(); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(1, stats.numTotalServiceScans); - } - - /** - * Test that updating persistent group number works normally. - * @throws Exception - */ - @Test - public void updatePersistentGroup() throws Exception { - WifiP2pStats stats; - WifiP2pGroupList mGroups = new WifiP2pGroupList(); - - mWifiP2pMetrics.updatePersistentGroup(mGroups); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(0, stats.numPersistentGroup); - - WifiP2pGroup group1 = new WifiP2pGroup(); - group1.setNetworkId(1); - WifiP2pGroup group2 = new WifiP2pGroup(); - group2.setNetworkId(2); - WifiP2pGroup group3 = new WifiP2pGroup(); - group3.setNetworkId(4); - mGroups.add(group1); - mGroups.add(group2); - mGroups.add(group3); - mWifiP2pMetrics.updatePersistentGroup(mGroups); - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(3, mGroups.getGroupList().size()); - assertEquals(3, stats.numPersistentGroup); - } - - /** - * Test that updateGroupEvent work normally. - * @throws Exception - */ - @Test - public void updateGroupEvent() throws Exception { - WifiP2pStats stats; - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(1); - - mWifiP2pMetrics.startGroupEvent(group); - - // total 4 new clients, and only one stays. - group.addClient("11:22:33:44:55:01"); - mWifiP2pMetrics.updateGroupEvent(group); - group.addClient("11:22:33:44:55:02"); - mWifiP2pMetrics.updateGroupEvent(group); - group.removeClient("11:22:33:44:55:01"); - mWifiP2pMetrics.updateGroupEvent(group); - group.addClient("11:22:33:44:55:03"); - mWifiP2pMetrics.updateGroupEvent(group); - group.addClient("11:22:33:44:55:04"); - mWifiP2pMetrics.updateGroupEvent(group); - group.removeClient("11:22:33:44:55:03"); - mWifiP2pMetrics.updateGroupEvent(group); - group.removeClient("11:22:33:44:55:02"); - mWifiP2pMetrics.updateGroupEvent(group); - - mWifiP2pMetrics.endGroupEvent(); - - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(1, stats.groupEvent.length); - GroupEvent event = stats.groupEvent[0]; - assertEquals(1, event.numConnectedClients); - assertEquals(4, event.numCumulativeClients); - } - - /** - * Test that updateGroupEvent is called before calling startGroupEvent. - * @throws Exception - */ - @Test - public void updateGroupEventWithNoCurrentGroup() throws Exception { - WifiP2pStats stats; - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(1); - - // total 4 new clients, and only one stays. - group.addClient("11:22:33:44:55:01"); - mWifiP2pMetrics.updateGroupEvent(group); - group.addClient("11:22:33:44:55:02"); - mWifiP2pMetrics.updateGroupEvent(group); - group.removeClient("11:22:33:44:55:01"); - mWifiP2pMetrics.updateGroupEvent(group); - group.addClient("11:22:33:44:55:03"); - mWifiP2pMetrics.updateGroupEvent(group); - group.addClient("11:22:33:44:55:04"); - mWifiP2pMetrics.updateGroupEvent(group); - group.removeClient("11:22:33:44:55:03"); - mWifiP2pMetrics.updateGroupEvent(group); - group.removeClient("11:22:33:44:55:02"); - mWifiP2pMetrics.updateGroupEvent(group); - - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(0, stats.groupEvent.length); - } - - /** - * Test that updateGroupEvent is called with different group from current group. - * @throws Exception - */ - @Test - public void updateGroupEventWithDifferentGroup() throws Exception { - WifiP2pStats stats; - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(1); - WifiP2pGroup differentGroup = new WifiP2pGroup(); - group.setNetworkId(2); - - mWifiP2pMetrics.startGroupEvent(group); - - // total 4 new clients, and only one stays. - differentGroup.addClient("11:22:33:44:55:01"); - mWifiP2pMetrics.updateGroupEvent(differentGroup); - differentGroup.addClient("11:22:33:44:55:02"); - mWifiP2pMetrics.updateGroupEvent(differentGroup); - differentGroup.removeClient("11:22:33:44:55:01"); - mWifiP2pMetrics.updateGroupEvent(differentGroup); - differentGroup.addClient("11:22:33:44:55:03"); - mWifiP2pMetrics.updateGroupEvent(differentGroup); - differentGroup.addClient("11:22:33:44:55:04"); - mWifiP2pMetrics.updateGroupEvent(differentGroup); - differentGroup.removeClient("11:22:33:44:55:03"); - mWifiP2pMetrics.updateGroupEvent(differentGroup); - differentGroup.removeClient("11:22:33:44:55:02"); - mWifiP2pMetrics.updateGroupEvent(differentGroup); - - mWifiP2pMetrics.endGroupEvent(); - - // since it is different group, the is still 0 client in current group. - stats = mWifiP2pMetrics.consolidateProto(); - assertEquals(1, stats.groupEvent.length); - GroupEvent event = stats.groupEvent[0]; - assertEquals(0, event.numConnectedClients); - assertEquals(0, event.numCumulativeClients); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pMonitorTest.java deleted file mode 100644 index bced05d00..000000000 --- a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pMonitorTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.p2p; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -import android.os.Handler; -import android.os.Message; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiInjector; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -/** - * Unit tests for {@link com.android.server.wifi.WifiP2pMonitor}. - */ -@SmallTest -public class WifiP2pMonitorTest extends WifiBaseTest { - private static final String P2P_IFACE_NAME = "p2p0"; - private static final String SECOND_P2P_IFACE_NAME = "p2p1"; - private WifiP2pMonitor mWifiP2pMonitor; - private TestLooper mLooper; - private Handler mHandlerSpy; - private Handler mSecondHandlerSpy; - - @Before - public void setUp() throws Exception { - mWifiP2pMonitor = new WifiP2pMonitor(mock(WifiInjector.class)); - mLooper = new TestLooper(); - mHandlerSpy = spy(new Handler(mLooper.getLooper())); - mSecondHandlerSpy = spy(new Handler(mLooper.getLooper())); - mWifiP2pMonitor.setMonitoring(P2P_IFACE_NAME, true); - } - - /** - * Broadcast message test. - */ - @Test - public void testBroadcastSupplicantDisconnectionEvent() { - mWifiP2pMonitor.registerHandler( - P2P_IFACE_NAME, WifiP2pMonitor.SUP_DISCONNECTION_EVENT, mHandlerSpy); - mWifiP2pMonitor.broadcastSupplicantDisconnectionEvent(P2P_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiP2pMonitor.SUP_DISCONNECTION_EVENT, messageCaptor.getValue().what); - } - /** - * Broadcast message to two handlers test. - */ - @Test - public void testBroadcastEventToTwoHandlers() { - mWifiP2pMonitor.registerHandler( - P2P_IFACE_NAME, WifiP2pMonitor.SUP_CONNECTION_EVENT, mHandlerSpy); - mWifiP2pMonitor.registerHandler( - P2P_IFACE_NAME, WifiP2pMonitor.SUP_CONNECTION_EVENT, mSecondHandlerSpy); - mWifiP2pMonitor.broadcastSupplicantConnectionEvent(P2P_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiP2pMonitor.SUP_CONNECTION_EVENT, messageCaptor.getValue().what); - verify(mSecondHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiP2pMonitor.SUP_CONNECTION_EVENT, messageCaptor.getValue().what); - } - /** - * Broadcast message when iface is null. - */ - @Test - public void testBroadcastEventWhenIfaceIsNull() { - mWifiP2pMonitor.registerHandler( - P2P_IFACE_NAME, WifiP2pMonitor.SUP_DISCONNECTION_EVENT, mHandlerSpy); - mWifiP2pMonitor.broadcastSupplicantDisconnectionEvent(null); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiP2pMonitor.SUP_DISCONNECTION_EVENT, messageCaptor.getValue().what); - } - /** - * Broadcast message when iface handler is null. - */ - @Test - public void testBroadcastEventWhenIfaceHandlerIsNull() { - mWifiP2pMonitor.registerHandler( - P2P_IFACE_NAME, WifiP2pMonitor.SUP_DISCONNECTION_EVENT, mHandlerSpy); - mWifiP2pMonitor.broadcastSupplicantDisconnectionEvent(SECOND_P2P_IFACE_NAME); - mLooper.dispatchAll(); - - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(mHandlerSpy).handleMessage(messageCaptor.capture()); - assertEquals(WifiP2pMonitor.SUP_DISCONNECTION_EVENT, messageCaptor.getValue().what); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java deleted file mode 100644 index 48a4334cb..000000000 --- a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.p2p; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiP2pIface; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.os.Handler; -import android.os.RemoteException; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.HalDeviceManager.InterfaceAvailableForRequestListener; -import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; -import com.android.server.wifi.HalDeviceManager.ManagerStatusListener; -import com.android.server.wifi.PropertyService; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiVendorHal; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for the interface management operations in - * {@link com.android.server.wifi.WifiP2pNative}. - */ -@SmallTest -public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { - private static final String P2P_IFACE_NAME = "p2p0"; - private static final String P2P_INTERFACE_PROPERTY = "wifi.direct.interface"; - - @Mock private SupplicantP2pIfaceHal mSupplicantP2pIfaceHal; - @Mock private HalDeviceManager mHalDeviceManager; - @Mock private PropertyService mPropertyService; - @Mock private Handler mHandler; - @Mock private InterfaceAvailableForRequestListener mInterfaceRequestListener; - @Mock private InterfaceDestroyedListener mHalDeviceInterfaceDestroyedListener; - @Mock private IWifiP2pIface mIWifiP2pIface; - @Mock private IWifiIface mIWifiIface; - @Mock private WifiVendorHal mWifiVendorHal; - @Mock private WifiInjector mWifiInjector; - private WifiP2pNative mWifiP2pNative; - private WifiStatus mWifiStatusSuccess; - private ManagerStatusListener mManagerStatusListener; - - /** - * Sets up for unit test - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mWifiStatusSuccess = new WifiStatus(); - mWifiStatusSuccess.code = WifiStatusCode.SUCCESS; - - when(mHalDeviceManager.isSupported()).thenReturn(true); - when(mHalDeviceManager.createP2pIface(any(InterfaceDestroyedListener.class), - any(Handler.class))).thenReturn(mIWifiP2pIface); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, P2P_IFACE_NAME); - } - }).when(mIWifiP2pIface).getName(any(IWifiIface.getNameCallback.class)); - - when(mSupplicantP2pIfaceHal.isInitializationStarted()).thenReturn(true); - when(mSupplicantP2pIfaceHal.initialize()).thenReturn(true); - when(mSupplicantP2pIfaceHal.isInitializationComplete()).thenReturn(true); - when(mSupplicantP2pIfaceHal.setupIface(P2P_IFACE_NAME)).thenReturn(true); - when(mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME)) - .thenReturn(P2P_IFACE_NAME); - - mWifiP2pNative = new WifiP2pNative(mWifiInjector, - mWifiVendorHal, mSupplicantP2pIfaceHal, mHalDeviceManager, - mPropertyService); - } - - /** - * Verifies the HAL (HIDL) interface listener. - */ - @Test - public void testRegisterInterfaceAvailableListener() throws Exception { - when(mHalDeviceManager.isStarted()).thenReturn(false); - - mWifiP2pNative.registerInterfaceAvailableListener(mInterfaceRequestListener, mHandler); - when(mHalDeviceManager.isStarted()).thenReturn(true); - - ArgumentCaptor<ManagerStatusListener> hdmCallbackCaptor = - ArgumentCaptor.forClass(ManagerStatusListener.class); - verify(mHalDeviceManager).registerStatusListener(hdmCallbackCaptor.capture(), eq(mHandler)); - // Simulate to call status callback from device hal manager - hdmCallbackCaptor.getValue().onStatusChanged(); - - verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener(eq(IfaceType.P2P), - any(InterfaceAvailableForRequestListener.class), eq(mHandler)); - } - - /** - * Verifies the setup of a p2p interface. - */ - @Test - public void testSetUpInterface() throws Exception { - assertEquals(P2P_IFACE_NAME, - mWifiP2pNative.setupInterface(mHalDeviceInterfaceDestroyedListener, mHandler)); - - verify(mHalDeviceManager).createP2pIface(any(InterfaceDestroyedListener.class), - eq(mHandler)); - verify(mSupplicantP2pIfaceHal).setupIface(eq(P2P_IFACE_NAME)); - } - - /** - * Verifies the setup of a p2p interface with no HAL (HIDL) support. - */ - @Test - public void testSetUpInterfaceWithNoVendorHal() throws Exception { - when(mHalDeviceManager.isSupported()).thenReturn(false); - - assertEquals(P2P_IFACE_NAME, mWifiP2pNative.setupInterface( - mHalDeviceInterfaceDestroyedListener, mHandler)); - - verify(mHalDeviceManager, never()) - .createP2pIface(any(InterfaceDestroyedListener.class), any(Handler.class)); - verify(mSupplicantP2pIfaceHal).setupIface(eq(P2P_IFACE_NAME)); - } - - /** - * Verifies the teardown of a p2p interface. - */ - @Test - public void testTeardownInterface() throws Exception { - assertEquals(P2P_IFACE_NAME, - mWifiP2pNative.setupInterface(mHalDeviceInterfaceDestroyedListener, - mHandler)); - - mWifiP2pNative.teardownInterface(); - - verify(mHalDeviceManager).removeIface(any(IWifiIface.class)); - verify(mSupplicantP2pIfaceHal).teardownIface(eq(P2P_IFACE_NAME)); - } - - /** - * Verifies the teardown of a p2p interface with no HAL (HIDL) support. - */ - @Test - public void testTeardownInterfaceWithNoVendorHal() throws Exception { - when(mHalDeviceManager.isSupported()).thenReturn(false); - - assertEquals(P2P_IFACE_NAME, mWifiP2pNative.setupInterface( - mHalDeviceInterfaceDestroyedListener, mHandler)); - - mWifiP2pNative.teardownInterface(); - - verify(mHalDeviceManager, never()).removeIface(any(IWifiIface.class)); - verify(mSupplicantP2pIfaceHal).teardownIface(eq(P2P_IFACE_NAME)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java deleted file mode 100644 index eca30bd90..000000000 --- a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.p2p; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.net.wifi.WifiManager; -import android.net.wifi.nl80211.WifiNl80211Manager; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pGroupList; -import android.net.wifi.p2p.WifiP2pManager; -import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo; -import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; -import android.os.Handler; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.PropertyService; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.WifiVendorHal; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.HashSet; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.WifiP2pMonitor}. - */ -@SmallTest -public class WifiP2pNativeTest extends WifiBaseTest { - - private static final String TEST_DEVICE_NAME = "Android_HelloWorld"; - private static final String TEST_IFACE = "p2p-p2p0-1"; - private static final String TEST_BSSID = "de:ad:be:ef:01:02"; - private static final String TEST_PIN = "12345678"; - private static final String TEST_DEVICE_TYPE = "12-1234abcd-08"; - private static final String TEST_WPS_CONFIG = "usba label display push_button keypad"; - private static final String TEST_SSID_POSTFIX = "NiceBoat"; - private static final int TEST_IDLE_TIME = 10; - private static final String TEST_NETWORK_NAME = "DIRECT-xy-NiceBoat"; - private static final String TEST_PASSPHRASE = "DeadEnd!"; - private static final int TEST_GROUP_FREQ = 5400; - private static final String TEST_WFD_DEVICE_INFO = "deadbeef"; - private static final int TEST_P2P_FIND_TIMEOUT = 120; - private static final String TEST_SERVICE_DISCOVERY_IDENTIFIER = "identifier"; - private static final String TEST_SERVICE_DISCOVERY_QUERY = "query"; - private static final String TEST_NFC_REQUEST_MSG = "request"; - private static final String TEST_NFC_SELECT_MSG = "select"; - private static final String TEST_CLIENT_LIST = "aa:bb:cc:dd:ee:ff 11:22:33:44:55:66"; - - @Mock private WifiInjector mWifiInjector; - @Mock private WifiNl80211Manager mWifiCondManager; - @Mock private WifiNative mWifiNative; - @Mock private WifiVendorHal mWifiVendorHalMock; - @Mock private SupplicantP2pIfaceHal mSupplicantP2pIfaceHalMock; - @Mock private HalDeviceManager mHalDeviceManagerMock; - @Mock private PropertyService mPropertyServiceMock; - @Mock private Handler mHandler; - - private WifiP2pNative mWifiP2pNative; - private WifiP2pGroupList mWifiP2pGroupList = new WifiP2pGroupList(); - private Set<String> mWifiClientInterfaceNames = new HashSet<String>(); - - private WifiP2pGroup createP2pGroup( - int networkId, String networkName, String passphrase, boolean isGo, String goAddr) { - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(networkId); - group.setNetworkName(networkName); - group.setPassphrase(passphrase); - group.setIsGroupOwner(isGo); - group.setOwner(new WifiP2pDevice(goAddr)); - return group; - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mWifiClientInterfaceNames.add("wlan0"); - mWifiClientInterfaceNames.add("wlan1"); - - mWifiP2pNative = new WifiP2pNative( - mWifiInjector, - mWifiVendorHalMock, - mSupplicantP2pIfaceHalMock, - mHalDeviceManagerMock, - mPropertyServiceMock); - - when(mWifiInjector.getWifiCondManager()).thenReturn(mWifiCondManager); - when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); - - when(mWifiNative.getClientInterfaceNames()).thenReturn(mWifiClientInterfaceNames); - - mWifiP2pGroupList.add( - createP2pGroup(1, "testGroup1", "passphrase", true, "aa:bb:cc:dd:ee:f0")); - mWifiP2pGroupList.add( - createP2pGroup(2, "testGroup2", "passphrase", false, "aa:bb:cc:dd:ee:f0")); - mWifiP2pGroupList.add( - createP2pGroup(3, "testGroup3", "passphrase", true, "aa:bb:cc:dd:ee:aa")); - mWifiP2pGroupList.add( - createP2pGroup(4, "testGroup4", "passphrase", true, "aa:bb:cc:dd:ee:bb")); - - // setup default mock behaviors - when(mHalDeviceManagerMock.isSupported()).thenReturn(true); - - doAnswer(new AnswerWithArguments() { - public boolean answer(WifiP2pGroupList groupList) { - for (WifiP2pGroup g : mWifiP2pGroupList.getGroupList()) { - groupList.add(g); - } - return true; - } - }).when(mSupplicantP2pIfaceHalMock).loadGroups(any()); - - } - - /** - * Verifies that isHalInterfaceSupported returns correct values. - */ - @Test - public void testIsHalInterfaceSupported() { - assertTrue(mWifiP2pNative.isHalInterfaceSupported()); - - when(mHalDeviceManagerMock.isSupported()).thenReturn(false); - assertFalse(mWifiP2pNative.isHalInterfaceSupported()); - } - - /** - * Verifies that the device name can be set. - */ - @Test - public void testSetDeviceName() { - when(mSupplicantP2pIfaceHalMock.setWpsDeviceName(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.setDeviceName(TEST_DEVICE_NAME)); - verify(mSupplicantP2pIfaceHalMock).setWpsDeviceName(eq(TEST_DEVICE_NAME)); - } - - /** - * Verifies that the device name can be set. - */ - @Test - public void testSetP2pDeviceName() { - when(mSupplicantP2pIfaceHalMock.setWpsDeviceName(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.setP2pDeviceName(TEST_DEVICE_NAME)); - verify(mSupplicantP2pIfaceHalMock).setWpsDeviceName(eq(TEST_DEVICE_NAME)); - } - - /** - * Verifies that networks could be listed. - */ - @Test - public void testP2pListNetworks() { - WifiP2pGroupList groupList = new WifiP2pGroupList(); - assertTrue(mWifiP2pNative.p2pListNetworks(groupList)); - - verify(mSupplicantP2pIfaceHalMock).loadGroups(any(WifiP2pGroupList.class)); - assertEquals(mWifiP2pGroupList.toString(), groupList.toString()); - } - - /** - * Verifies that WPS PBC starts without errors. - */ - @Test - public void testStartWpsPbc() { - when(mSupplicantP2pIfaceHalMock.startWpsPbc(anyString(), anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.startWpsPbc(TEST_IFACE, TEST_BSSID)); - verify(mSupplicantP2pIfaceHalMock).startWpsPbc(eq(TEST_IFACE), eq(TEST_BSSID)); - } - - /** - * Verifies that WPS Pin/Keypad starts without errors. - */ - @Test - public void testStartWpsPinKeypad() { - when(mSupplicantP2pIfaceHalMock.startWpsPinKeypad(anyString(), anyString())) - .thenReturn(true); - assertTrue(mWifiP2pNative.startWpsPinKeypad(TEST_IFACE, TEST_PIN)); - verify(mSupplicantP2pIfaceHalMock).startWpsPinKeypad(eq(TEST_IFACE), eq(TEST_PIN)); - } - - /** - * Verifies that WPS Pin/Display starts without errors. - */ - @Test - public void testStartWpsPinDisplay() { - when(mSupplicantP2pIfaceHalMock.startWpsPinDisplay(anyString(), anyString())) - .thenReturn(TEST_PIN); - assertEquals(TEST_PIN, mWifiP2pNative.startWpsPinDisplay(TEST_IFACE, TEST_BSSID)); - verify(mSupplicantP2pIfaceHalMock).startWpsPinDisplay(eq(TEST_IFACE), eq(TEST_BSSID)); - } - - /** - * Verifies removing a network. - */ - @Test - public void testP2pRemoveNetwork() { - when(mSupplicantP2pIfaceHalMock.removeNetwork(anyInt())).thenReturn(true); - assertTrue(mWifiP2pNative.removeP2pNetwork(1)); - verify(mSupplicantP2pIfaceHalMock).removeNetwork(eq(1)); - } - - /** - * Verifies setting the device type. - */ - @Test - public void testSetP2pDeviceType() { - when(mSupplicantP2pIfaceHalMock.setWpsDeviceType(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.setP2pDeviceType(TEST_DEVICE_TYPE)); - verify(mSupplicantP2pIfaceHalMock).setWpsDeviceType(eq(TEST_DEVICE_TYPE)); - } - - /** - * Verifies setting WPS config method. - */ - @Test - public void testSetConfigMethods() { - when(mSupplicantP2pIfaceHalMock.setWpsConfigMethods(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.setConfigMethods(TEST_WPS_CONFIG)); - verify(mSupplicantP2pIfaceHalMock).setWpsConfigMethods(eq(TEST_WPS_CONFIG)); - } - - /** - * Verifies setting SSID postfix. - */ - @Test - public void testSetP2pSsidPostfix() { - when(mSupplicantP2pIfaceHalMock.setSsidPostfix(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.setP2pSsidPostfix(TEST_SSID_POSTFIX)); - verify(mSupplicantP2pIfaceHalMock).setSsidPostfix(eq(TEST_SSID_POSTFIX)); - } - - /** - * Verifies setting group idle time. - */ - @Test - public void testSetP2pGroupIdle() { - when(mSupplicantP2pIfaceHalMock.setGroupIdle(anyString(), anyInt())).thenReturn(true); - assertTrue(mWifiP2pNative.setP2pGroupIdle(TEST_IFACE, TEST_IDLE_TIME)); - verify(mSupplicantP2pIfaceHalMock).setGroupIdle(eq(TEST_IFACE), eq(TEST_IDLE_TIME)); - } - - /** - * Verifies setting power save mode. - */ - @Test - public void testSetP2pPowerSave() { - when(mSupplicantP2pIfaceHalMock.setPowerSave(anyString(), anyBoolean())).thenReturn(true); - assertTrue(mWifiP2pNative.setP2pPowerSave(TEST_IFACE, true)); - verify(mSupplicantP2pIfaceHalMock).setPowerSave(eq(TEST_IFACE), eq(true)); - } - - /** - * Verifies enabling Wifi Display. - */ - @Test - public void testSetWfdEnable() { - when(mSupplicantP2pIfaceHalMock.enableWfd(anyBoolean())).thenReturn(true); - assertTrue(mWifiP2pNative.setWfdEnable(true)); - verify(mSupplicantP2pIfaceHalMock).enableWfd(eq(true)); - } - - /** - * Verifies setting WFD info. - */ - @Test - public void testSetWfdDeviceInfo() { - when(mSupplicantP2pIfaceHalMock.setWfdDeviceInfo(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.setWfdDeviceInfo(TEST_WFD_DEVICE_INFO)); - verify(mSupplicantP2pIfaceHalMock).setWfdDeviceInfo(eq(TEST_WFD_DEVICE_INFO)); - } - - /** - * Verifies initiating a P2P service discovery indefinitely. - */ - @Test - public void testP2pFindIndefinitely() { - when(mSupplicantP2pIfaceHalMock.find(anyInt())).thenReturn(true); - assertTrue(mWifiP2pNative.p2pFind()); - verify(mSupplicantP2pIfaceHalMock).find(eq(0)); - } - - /** - * Verifies initiating a P2P service discovery with timeout. - */ - @Test - public void testP2pFindWithTimeout() { - when(mSupplicantP2pIfaceHalMock.find(anyInt())).thenReturn(true); - assertTrue(mWifiP2pNative.p2pFind(TEST_P2P_FIND_TIMEOUT)); - verify(mSupplicantP2pIfaceHalMock).find(eq(TEST_P2P_FIND_TIMEOUT)); - } - - /** - * Verifies stopping a P2P service discovery. - */ - @Test - public void testP2pStopFind() { - when(mSupplicantP2pIfaceHalMock.stopFind()).thenReturn(true); - assertTrue(mWifiP2pNative.p2pStopFind()); - verify(mSupplicantP2pIfaceHalMock).stopFind(); - } - - /** - * Verifies configuring extended listen timing. - */ - @Test - public void testP2pExtListen() { - when(mSupplicantP2pIfaceHalMock.configureExtListen(anyBoolean(), anyInt(), anyInt())) - .thenReturn(true); - assertTrue(mWifiP2pNative.p2pExtListen(true, 10000, 20000)); - verify(mSupplicantP2pIfaceHalMock).configureExtListen(eq(true), eq(10000), eq(20000)); - } - - /** - * Verifies setting p2p listen channel. - */ - @Test - public void testP2pSetChannel() { - when(mSupplicantP2pIfaceHalMock.setListenChannel(anyInt(), anyInt())) - .thenReturn(true); - assertTrue(mWifiP2pNative.p2pSetChannel(1, 81)); - verify(mSupplicantP2pIfaceHalMock).setListenChannel(eq(1), eq(81)); - } - - /** - * Verifies flushing P2P peer table and state. - */ - @Test - public void testP2pFlush() { - when(mSupplicantP2pIfaceHalMock.flush()).thenReturn(true); - assertTrue(mWifiP2pNative.p2pFlush()); - verify(mSupplicantP2pIfaceHalMock).flush(); - } - - /** - * Verifies starting p2p group formation. - */ - @Test - public void testP2pConnect() { - WifiP2pConfig config = new WifiP2pConfig(); - config.deviceAddress = TEST_BSSID; - mWifiP2pNative.p2pConnect(config, true); - ArgumentCaptor<WifiP2pConfig> configCaptor = ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mSupplicantP2pIfaceHalMock).connect(configCaptor.capture(), eq(true)); - // there is no equals operator for WifiP2pConfig. - assertEquals(config.toString(), configCaptor.getValue().toString()); - } - - /** - * Verifies cancelling an ongoing P2P group formation and joining-a-group related operation. - */ - @Test - public void testP2pCancelConnect() { - when(mSupplicantP2pIfaceHalMock.cancelConnect()).thenReturn(true); - assertTrue(mWifiP2pNative.p2pCancelConnect()); - verify(mSupplicantP2pIfaceHalMock).cancelConnect(); - } - - /** - * Verifies sending P2P provision discovery request to the specified peer. - */ - @Test - public void testP2pProvisionDiscovery() { - when(mSupplicantP2pIfaceHalMock.provisionDiscovery(any(WifiP2pConfig.class))) - .thenReturn(true); - WifiP2pConfig config = new WifiP2pConfig(); - config.deviceAddress = TEST_BSSID; - assertTrue(mWifiP2pNative.p2pProvisionDiscovery(config)); - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mSupplicantP2pIfaceHalMock).provisionDiscovery(configCaptor.capture()); - // there is no equals operator for WifiP2pConfig. - assertEquals(config.toString(), configCaptor.getValue().toString()); - } - - /** - * Verifies joining p2p group. - */ - @Test - public void testJoinGroup() { - when(mSupplicantP2pIfaceHalMock.groupAdd(anyBoolean())).thenReturn(true); - assertTrue(mWifiP2pNative.p2pGroupAdd(true)); - verify(mSupplicantP2pIfaceHalMock).groupAdd(eq(true)); - } - - /** - * Verifies joining p2p group with network id. - */ - @Test - public void testJoinGroupWithNetworkId() { - when(mSupplicantP2pIfaceHalMock.groupAdd(anyInt(), anyBoolean())).thenReturn(true); - assertTrue(mWifiP2pNative.p2pGroupAdd(5)); - verify(mSupplicantP2pIfaceHalMock).groupAdd(eq(5), eq(true)); - } - - /** - * Verifies joining p2p group with config. - */ - @Test - public void testJoinGroupWithConfig() { - when(mSupplicantP2pIfaceHalMock.groupAdd( - anyString(), anyString(), anyBoolean(), - anyInt(), anyString(), anyBoolean())).thenReturn(true); - WifiP2pConfig config = new WifiP2pConfig.Builder() - .setNetworkName(TEST_NETWORK_NAME) - .setPassphrase(TEST_PASSPHRASE) - .enablePersistentMode(true) - .setGroupOperatingFrequency(TEST_GROUP_FREQ) - .build(); - assertTrue(mWifiP2pNative.p2pGroupAdd(config, true)); - - for (String intf: mWifiClientInterfaceNames) { - verify(mWifiCondManager).abortScan(eq(intf)); - } - - verify(mSupplicantP2pIfaceHalMock).groupAdd( - eq(TEST_NETWORK_NAME), - eq(TEST_PASSPHRASE), - eq(true), - eq(TEST_GROUP_FREQ), - eq(config.deviceAddress), - eq(true)); - } - - /** - * Verifies removing p2p group. - */ - @Test - public void testP2pGroupRemove() { - when(mSupplicantP2pIfaceHalMock.groupRemove(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.p2pGroupRemove(TEST_IFACE)); - verify(mSupplicantP2pIfaceHalMock).groupRemove(eq(TEST_IFACE)); - } - - /** - * Verifies rejecting a connection attemp. - */ - @Test - public void testP2pReject() { - when(mSupplicantP2pIfaceHalMock.reject(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.p2pReject(TEST_BSSID)); - verify(mSupplicantP2pIfaceHalMock).reject(eq(TEST_BSSID)); - } - - /** - * Verifies inviting a peer to a group. - */ - @Test - public void testP2pInvite() { - when(mSupplicantP2pIfaceHalMock.invite(any(WifiP2pGroup.class), anyString())) - .thenReturn(true); - WifiP2pGroup group = new WifiP2pGroup(); - assertTrue(mWifiP2pNative.p2pInvite(group, TEST_BSSID)); - ArgumentCaptor<WifiP2pGroup> groupCaptor = ArgumentCaptor.forClass(WifiP2pGroup.class); - verify(mSupplicantP2pIfaceHalMock).invite(groupCaptor.capture(), eq(TEST_BSSID)); - // no equals operator for WifiP2pGroup. - assertEquals(group.toString(), groupCaptor.getValue().toString()); - } - - /** - * Verifies reinvoking a device from a persiste group.. - */ - @Test - public void testP2pReinvoke() { - when(mSupplicantP2pIfaceHalMock.reinvoke(anyInt(), anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.p2pReinvoke(5, TEST_BSSID)); - verify(mSupplicantP2pIfaceHalMock).reinvoke(eq(5), eq(TEST_BSSID)); - } - - /** - * Verifies getting the operational SSID of the device. - */ - @Test - public void testP2pGetSsid() { - when(mSupplicantP2pIfaceHalMock.getSsid(anyString())).thenReturn(TEST_NETWORK_NAME); - assertEquals(TEST_NETWORK_NAME, mWifiP2pNative.p2pGetSsid(TEST_BSSID)); - verify(mSupplicantP2pIfaceHalMock).getSsid(eq(TEST_BSSID)); - } - - /** - * Verifies getting the MAC address of the device. - */ - @Test - public void testP2pGetDeviceAddress() { - when(mSupplicantP2pIfaceHalMock.getDeviceAddress()).thenReturn(TEST_BSSID); - assertEquals(TEST_BSSID, mWifiP2pNative.p2pGetDeviceAddress()); - verify(mSupplicantP2pIfaceHalMock).getDeviceAddress(); - } - - /** - * Verifies getting the group capabilities. - */ - @Test - public void testGetGroupCapability() { - when(mSupplicantP2pIfaceHalMock.getGroupCapability(anyString())).thenReturn(0x156); - assertEquals(0x156, mWifiP2pNative.getGroupCapability(TEST_BSSID)); - verify(mSupplicantP2pIfaceHalMock).getGroupCapability(eq(TEST_BSSID)); - } - - /** - * Verifies adding a service.. - */ - @Test - public void testP2pServiceAdd() { - when(mSupplicantP2pIfaceHalMock.serviceAdd(any(WifiP2pServiceInfo.class))) - .thenReturn(true); - WifiP2pServiceInfo info = - WifiP2pDnsSdServiceInfo.newInstance("MyPrinter", "_ipp._tcp", null); - assertTrue(mWifiP2pNative.p2pServiceAdd(info)); - verify(mSupplicantP2pIfaceHalMock).serviceAdd(eq(info)); - } - - /** - * Verifies deleting a service.. - */ - @Test - public void testP2pServiceDel() { - when(mSupplicantP2pIfaceHalMock.serviceRemove(any(WifiP2pServiceInfo.class))) - .thenReturn(true); - WifiP2pServiceInfo info = - WifiP2pDnsSdServiceInfo.newInstance("MyPrinter", "_ipp._tcp", null); - assertTrue(mWifiP2pNative.p2pServiceDel(info)); - verify(mSupplicantP2pIfaceHalMock).serviceRemove(eq(info)); - } - - /** - * Verifies flushing p2p services in this device. - */ - @Test - public void testP2pServiceFlush() { - when(mSupplicantP2pIfaceHalMock.serviceFlush()).thenReturn(true); - assertTrue(mWifiP2pNative.p2pServiceFlush()); - verify(mSupplicantP2pIfaceHalMock).serviceFlush(); - } - - /** - * Verifies scheduling a P2P service discovery request. - */ - @Test - public void testP2pServDiscReq() { - when(mSupplicantP2pIfaceHalMock.requestServiceDiscovery(anyString(), anyString())) - .thenReturn(TEST_SERVICE_DISCOVERY_IDENTIFIER); - assertEquals(TEST_SERVICE_DISCOVERY_IDENTIFIER, - mWifiP2pNative.p2pServDiscReq(TEST_BSSID, TEST_SERVICE_DISCOVERY_QUERY)); - verify(mSupplicantP2pIfaceHalMock) - .requestServiceDiscovery(eq(TEST_BSSID), eq(TEST_SERVICE_DISCOVERY_QUERY)); - } - - /** - * Verifies canceling a p2p service discovery request. - */ - @Test - public void testP2pServDiscCancelReq() { - when(mSupplicantP2pIfaceHalMock.cancelServiceDiscovery(anyString())).thenReturn(true); - assertTrue(mWifiP2pNative.p2pServDiscCancelReq( - TEST_SERVICE_DISCOVERY_IDENTIFIER)); - verify(mSupplicantP2pIfaceHalMock).cancelServiceDiscovery( - TEST_SERVICE_DISCOVERY_IDENTIFIER); - } - - /** - * Verifies setting miracast mode. - */ - @Test - public void testSetMiracastMode() { - mWifiP2pNative.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE); - verify(mSupplicantP2pIfaceHalMock).setMiracastMode(eq(WifiP2pManager.MIRACAST_SOURCE)); - } - - /** - * Verifies getting NFC handover request message. - */ - @Test - public void testGetNfcHandoverRequest() { - when(mSupplicantP2pIfaceHalMock.getNfcHandoverRequest()) - .thenReturn(TEST_NFC_REQUEST_MSG); - assertEquals(TEST_NFC_REQUEST_MSG, mWifiP2pNative.getNfcHandoverRequest()); - verify(mSupplicantP2pIfaceHalMock).getNfcHandoverRequest(); - } - - /** - * Verifies getting NFC handover select message. - */ - @Test - public void testGetNfcHandoverSelect() { - when(mSupplicantP2pIfaceHalMock.getNfcHandoverSelect()) - .thenReturn(TEST_NFC_SELECT_MSG); - assertEquals(TEST_NFC_SELECT_MSG, mWifiP2pNative.getNfcHandoverSelect()); - verify(mSupplicantP2pIfaceHalMock).getNfcHandoverSelect(); - } - - /** - * Verifies reporting NFC handover select message. - */ - @Test - public void testInitiatorReportNfcHandover() { - when(mSupplicantP2pIfaceHalMock.initiatorReportNfcHandover(anyString())) - .thenReturn(true); - assertTrue(mWifiP2pNative.initiatorReportNfcHandover(TEST_NFC_SELECT_MSG)); - verify(mSupplicantP2pIfaceHalMock).initiatorReportNfcHandover(eq(TEST_NFC_SELECT_MSG)); - } - - /** - * Verifies reporting NFC handover request message. - */ - @Test - public void testResponderReportNfcHandover() { - when(mSupplicantP2pIfaceHalMock.responderReportNfcHandover(anyString())) - .thenReturn(true); - assertTrue(mWifiP2pNative.responderReportNfcHandover(TEST_NFC_REQUEST_MSG)); - verify(mSupplicantP2pIfaceHalMock).responderReportNfcHandover(eq(TEST_NFC_REQUEST_MSG)); - } - - /** - * Verifies getting client list. - */ - @Test - public void testGetP2pClientList() { - when(mSupplicantP2pIfaceHalMock.getClientList(anyInt())) - .thenReturn(TEST_CLIENT_LIST); - assertEquals(TEST_CLIENT_LIST, mWifiP2pNative.getP2pClientList(5)); - verify(mSupplicantP2pIfaceHalMock).getClientList(eq(5)); - } - - /** - * Verifies setting client list. - */ - @Test - public void testSetP2pClientList() { - when(mSupplicantP2pIfaceHalMock.setClientList(anyInt(), anyString())) - .thenReturn(true); - assertTrue(mWifiP2pNative.setP2pClientList(5, TEST_CLIENT_LIST)); - verify(mSupplicantP2pIfaceHalMock).setClientList(eq(5), eq(TEST_CLIENT_LIST)); - } - - /** - * Verifies saving p2p config. - */ - @Test - public void testSaveConfig() { - when(mSupplicantP2pIfaceHalMock.saveConfig()) - .thenReturn(true); - assertTrue(mWifiP2pNative.saveConfig()); - verify(mSupplicantP2pIfaceHalMock).saveConfig(); - } - - /** - * Verifies enabling MAC randomization. - */ - @Test - public void testSetMacRandomization() { - when(mSupplicantP2pIfaceHalMock.setMacRandomization(anyBoolean())) - .thenReturn(true); - assertTrue(mWifiP2pNative.setMacRandomization(true)); - verify(mSupplicantP2pIfaceHalMock).setMacRandomization(eq(true)); - } - - /** - * Verifies getting supported feature set. - */ - @Test - public void testGetSupportedFeatureSet() { - when(mWifiVendorHalMock.getSupportedFeatureSet(anyString())) - .thenReturn(WifiManager.WIFI_FEATURE_P2P_RAND_MAC); - assertEquals(WifiManager.WIFI_FEATURE_P2P_RAND_MAC, - mWifiP2pNative.getSupportedFeatureSet(TEST_IFACE)); - verify(mWifiVendorHalMock).getSupportedFeatureSet(eq(TEST_IFACE)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java deleted file mode 100644 index 171dc9b24..000000000 --- a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java +++ /dev/null @@ -1,4077 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.p2p; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_DEVICE_NAME; -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_PENDING_FACTORY_RESET; -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.annotation.Nullable; -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.location.LocationManager; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.TetheringManager; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.net.wifi.WpsInfo; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pDeviceList; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pGroupList; -import android.net.wifi.p2p.WifiP2pInfo; -import android.net.wifi.p2p.WifiP2pManager; -import android.net.wifi.p2p.WifiP2pProvDiscEvent; -import android.net.wifi.p2p.WifiP2pWfdInfo; -import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; -import android.net.wifi.p2p.nsd.WifiP2pServiceRequest; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Message; -import android.os.Messenger; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.FakeWifiLog; -import com.android.server.wifi.FrameworkFacade; -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiSettingsConfigStore; -import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent; -import com.android.server.wifi.util.NetdWrapper; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.server.wifi.util.WifiPermissionsWrapper; -import com.android.wifi.resources.R; - -import libcore.net.InetAddressUtils; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.MockitoSession; -import org.mockito.Spy; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Unit test harness for WifiP2pServiceImpl. - */ -@SmallTest -public class WifiP2pServiceImplTest extends WifiBaseTest { - private static final String TAG = "WifiP2pServiceImplTest"; - private static final String IFACE_NAME_P2P = "mockP2p0"; - private static final String P2P_GO_IP = "192.168.49.1"; - private static final long STATE_CHANGE_WAITING_TIME = 1000; - private static final String thisDeviceMac = "11:22:33:44:55:66"; - private static final String thisDeviceName = "thisDeviceName"; - private static final String ANONYMIZED_DEVICE_ADDRESS = "02:00:00:00:00:00"; - - private ArgumentCaptor<HalDeviceManager.InterfaceAvailableForRequestListener> - mAvailListenerCaptor = ArgumentCaptor.forClass( - HalDeviceManager.InterfaceAvailableForRequestListener.class); - private ArgumentCaptor<BroadcastReceiver> mBcastRxCaptor = ArgumentCaptor.forClass( - BroadcastReceiver.class); - private Binder mClient1; - private Binder mClient2; - - private BroadcastReceiver mLocationModeReceiver; - private BroadcastReceiver mWifiStateChangedReceiver; - private BroadcastReceiver mTetherStateReceiver; - private Handler mClientHandler; - private Messenger mP2pStateMachineMessenger; - private Messenger mClientMessenger; - private WifiP2pServiceImpl mWifiP2pServiceImpl; - private TestLooper mClientHanderLooper; - private TestLooper mLooper; - private WifiP2pConfig mTestWifiP2pPeerConfig; - private WifiP2pConfig mTestWifiP2pFastConnectionConfig; - private WifiP2pGroup mTestWifiP2pNewPersistentGoGroup; - private WifiP2pGroup mTestWifiP2pGroup; - private WifiP2pDevice mTestWifiP2pDevice; - private WifiP2pGroupList mGroups = new WifiP2pGroupList(null, null); - private WifiP2pDevice mTestThisDevice; - private ArgumentCaptor<Message> mMessageCaptor = ArgumentCaptor.forClass(Message.class); - private MockitoSession mStaticMockSession = null; - - @Mock Context mContext; - @Mock FrameworkFacade mFrameworkFacade; - @Mock HandlerThread mHandlerThread; - @Mock NetdWrapper mNetdWrapper; - @Mock PackageManager mPackageManager; - @Mock Resources mResources; - @Mock NetworkInterface mP2pNetworkInterface; - @Mock WifiInjector mWifiInjector; - @Mock WifiManager mMockWifiManager; - @Mock WifiPermissionsUtil mWifiPermissionsUtil; - @Mock WifiSettingsConfigStore mWifiSettingsConfigStore; - @Mock WifiPermissionsWrapper mWifiPermissionsWrapper; - @Mock WifiP2pNative mWifiNative; - @Mock WifiP2pServiceInfo mTestWifiP2pServiceInfo; - @Mock WifiP2pServiceRequest mTestWifiP2pServiceRequest; - @Mock UserManager mUserManager; - @Mock WifiP2pMetrics mWifiP2pMetrics; - @Mock WifiManager mWifiManager; - @Mock WifiInfo mWifiInfo; - @Spy FakeWifiLog mLog; - @Spy MockWifiP2pMonitor mWifiMonitor; - - private void generatorTestData() { - mTestWifiP2pGroup = new WifiP2pGroup(); - mTestWifiP2pGroup.setNetworkName("TestGroupName"); - mTestWifiP2pDevice = spy(new WifiP2pDevice()); - mTestWifiP2pDevice.deviceName = "TestDeviceName"; - mTestWifiP2pDevice.deviceAddress = "aa:bb:cc:dd:ee:ff"; - - // for general connect command - mTestWifiP2pPeerConfig = new WifiP2pConfig(); - mTestWifiP2pPeerConfig.deviceAddress = mTestWifiP2pDevice.deviceAddress; - - // for fast-connection connect command - mTestWifiP2pFastConnectionConfig = new WifiP2pConfig.Builder() - .setNetworkName("DIRECT-XY-HELLO") - .setPassphrase("DEADBEEF") - .build(); - - // for general group started event - mTestWifiP2pNewPersistentGoGroup = new WifiP2pGroup(); - mTestWifiP2pNewPersistentGoGroup.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - mTestWifiP2pNewPersistentGoGroup.setNetworkName("DIRECT-xy-NEW"); - mTestWifiP2pNewPersistentGoGroup.setOwner(new WifiP2pDevice(thisDeviceMac)); - mTestWifiP2pNewPersistentGoGroup.setIsGroupOwner(true); - mTestWifiP2pNewPersistentGoGroup.setInterface(IFACE_NAME_P2P); - - mGroups.clear(); - WifiP2pGroup group1 = new WifiP2pGroup(); - group1.setNetworkId(0); - group1.setNetworkName(mTestWifiP2pGroup.getNetworkName()); - group1.setOwner(mTestWifiP2pDevice); - group1.setIsGroupOwner(false); - mGroups.add(group1); - - WifiP2pGroup group2 = new WifiP2pGroup(); - group2.setNetworkId(1); - group2.setNetworkName("DIRECT-ab-Hello"); - group2.setOwner(new WifiP2pDevice("12:34:56:78:90:ab")); - group2.setIsGroupOwner(false); - mGroups.add(group2); - - WifiP2pGroup group3 = new WifiP2pGroup(); - group3.setNetworkId(2); - group3.setNetworkName("DIRECT-cd-OWNER"); - group3.setOwner(new WifiP2pDevice(thisDeviceMac)); - group3.setIsGroupOwner(true); - mGroups.add(group3); - - mTestThisDevice = new WifiP2pDevice(); - mTestThisDevice.deviceName = thisDeviceName; - mTestThisDevice.deviceAddress = thisDeviceMac; - mTestThisDevice.primaryDeviceType = "10-0050F204-5"; - } - - /** - * Simulate Location Mode change: Changes the location manager return values and dispatches a - * broadcast. - * - * @param isLocationModeEnabled whether the location mode is enabled., - */ - private void simulateLocationModeChange(boolean isLocationModeEnabled) { - when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(isLocationModeEnabled); - - Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); - mLocationModeReceiver.onReceive(mContext, intent); - } - - /** - * Simulate Wi-Fi state change: broadcast state change and modify the API return value. - * - * @param isWifiOn whether the wifi mode is enabled. - */ - private void simulateWifiStateChange(boolean isWifiOn) { - when(mMockWifiManager.getWifiState()).thenReturn( - isWifiOn ? WifiManager.WIFI_STATE_ENABLED : WifiManager.WIFI_STATE_DISABLED); - - Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); - intent.putExtra(WifiManager.EXTRA_WIFI_STATE, - isWifiOn ? WifiManager.WIFI_STATE_ENABLED : WifiManager.WIFI_STATE_DISABLED); - mWifiStateChangedReceiver.onReceive(mContext, intent); - } - - /** - * Simulate tethering flow is completed - */ - private void simulateTetherReady() { - ArrayList<String> availableList = new ArrayList<>(); - ArrayList<String> localOnlyList = new ArrayList<>(); - localOnlyList.add(IFACE_NAME_P2P); - ArrayList<String> tetherList = new ArrayList<>(); - ArrayList<String> erroredList = new ArrayList<>(); - - Intent intent = new Intent(TetheringManager.ACTION_TETHER_STATE_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putStringArrayListExtra(TetheringManager.EXTRA_AVAILABLE_TETHER, availableList); - intent.putStringArrayListExtra(TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList); - intent.putStringArrayListExtra(TetheringManager.EXTRA_ACTIVE_TETHER, tetherList); - intent.putStringArrayListExtra(TetheringManager.EXTRA_ERRORED_TETHER, erroredList); - mTetherStateReceiver.onReceive(mContext, intent); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.UPDATE_CHANNEL_INFO - * - * @param pkgName package name used for p2p channel init - * @param featureId The feature in the package - * @param binder client binder used for p2p channel init - * @param replyMessenger for checking replied message. - */ - private void sendChannelInfoUpdateMsg(String pkgName, @Nullable String featureId, - Binder binder, Messenger replyMessenger) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.UPDATE_CHANNEL_INFO; - Bundle bundle = new Bundle(); - bundle.putString(WifiP2pManager.CALLING_PACKAGE, pkgName); - bundle.putString(WifiP2pManager.CALLING_FEATURE_ID, featureId); - bundle.putBinder(WifiP2pManager.CALLING_BINDER, binder); - msg.obj = bundle; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.ADD_LOCAL_SERVICE with mTestWifiP2pServiceInfo - * - * @param replyMessenger for checking replied message. - */ - private void sendAddLocalServiceMsg(Messenger replyMessenger) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.ADD_LOCAL_SERVICE; - msg.obj = mTestWifiP2pServiceInfo; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.CONNECT with ConfigValidAsGroup - * - * @param replyMessenger for checking replied message. - */ - private void sendConnectMsgWithConfigValidAsGroup(Messenger replyMessenger) throws Exception { - sendConnectMsg(replyMessenger, mTestWifiP2pFastConnectionConfig); - } - - /** - * Mock send WifiP2pManager.CREATE_GROUP with ConfigValidAsGroup - * - * @param replyMessenger for checking replied message. - */ - private void sendCreateGroupMsgWithConfigValidAsGroup(Messenger replyMessenger) - throws Exception { - sendCreateGroupMsg(replyMessenger, 0, mTestWifiP2pFastConnectionConfig); - } - - /** - * Mock send WifiP2pManager.DISCOVER_PEERS - * - * @param replyMessenger for checking replied message. - */ - private void sendDiscoverPeersMsg(Messenger replyMessenger) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.DISCOVER_PEERS; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.ADD_SERVICE_REQUEST with mocked mTestWifiP2pServiceRequest - * - * @param replyMessenger for checking replied message. - */ - private void sendAddServiceRequestMsg(Messenger replyMessenger) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.ADD_SERVICE_REQUEST; - msg.replyTo = replyMessenger; - msg.obj = mTestWifiP2pServiceRequest; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.DISCOVER_SERVICES - * - * @param replyMessenger for checking replied message. - */ - private void sendDiscoverServiceMsg(Messenger replyMessenger) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.DISCOVER_SERVICES; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.REQUEST_PEERS - * - * @param replyMessenger for checking replied message. - */ - private void sendRequestPeersMsg(Messenger replyMessenger) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.REQUEST_PEERS; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.REQUEST_GROUP_INFO - * - * @param replyMessenger for checking replied message. - */ - private void sendRequestGroupInfoMsg(Messenger replyMessenger) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.REQUEST_GROUP_INFO; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.DELETE_PERSISTENT_GROUP. - * - * @param replyMessenger for checking replied message. - * @param netId is the network id of the p2p group. - */ - private void sendDeletePersistentGroupMsg(Messenger replyMessenger, - int netId) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.DELETE_PERSISTENT_GROUP; - msg.arg1 = netId; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Send WifiP2pMonitor.P2P_GROUP_STARTED_EVENT. - * - * @param group the started group. - */ - private void sendGroupStartedMsg(WifiP2pGroup group) throws Exception { - if (group.getNetworkId() == WifiP2pGroup.NETWORK_ID_PERSISTENT) { - mGroups.add(group); - } - - Message msg = Message.obtain(); - msg.what = WifiP2pMonitor.P2P_GROUP_STARTED_EVENT; - msg.obj = group; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Send WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT. - */ - private void sendGroupRemovedMsg() throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Send WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT. - * - * @param device the found device. - */ - private void sendDeviceFoundEventMsg(WifiP2pDevice device) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT; - msg.obj = device; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Send WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT. - * - * @param status invitation result. - */ - private void sendInvitationResultMsg( - WifiP2pServiceImpl.P2pStatus status) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT; - msg.obj = status; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.SET_CHANNEL - * - * @param replyMessenger for checking replied message. - * @param p2pChannels stores the listen and operating channels. - */ - private void sendSetChannelMsg(Messenger replyMessenger, - Bundle p2pChannels) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.SET_CHANNEL; - msg.replyTo = replyMessenger; - msg.obj = p2pChannels; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.START_WPS - * - * @param replyMessenger for checking replied message. - * @param wps is the WPS configuration. - */ - private void sendStartWpsMsg(Messenger replyMessenger, WpsInfo wps) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.START_WPS; - msg.replyTo = replyMessenger; - msg.obj = wps; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.SET_DEVICE_NAME - * - * @param replyMessenger for checking replied message. - * @param dev is the P2p device configuration. - */ - private void sendSetDeviceNameMsg( - Messenger replyMessenger, WifiP2pDevice dev) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.SET_DEVICE_NAME; - msg.replyTo = replyMessenger; - msg.obj = dev; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.SET_WFD_INFO - * - * @param replyMessenger for checking replied message. - * @param wfdInfo is the P2p device's wfd information. - */ - private void sendSetWfdInfoMsg( - Messenger replyMessenger, WifiP2pWfdInfo wfdInfo) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.SET_WFD_INFO; - msg.replyTo = replyMessenger; - msg.obj = wfdInfo; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.SET_ONGOING_PEER_CONFIG - * - * @param replyMessenger for checking replied message. - * @param config used for change an ongoing peer connection. - */ - private void sendSetOngoingPeerConfigMsg( - Messenger replyMessenger, WifiP2pConfig config) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.SET_ONGOING_PEER_CONFIG; - msg.replyTo = replyMessenger; - msg.obj = config; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.REMOVE_LOCAL_SERVICE. - * - * @param replyMessenger for checking replied message. - * @param servInfo is the local service information. - */ - private void sendRemoveLocalServiceMsg(Messenger replyMessenger, - WifiP2pServiceInfo servInfo) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.REMOVE_LOCAL_SERVICE; - msg.obj = servInfo; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock send WifiP2pManager.REMOVE_SERVICE_REQUEST. - * - * @param replyMessenger for checking replied message. - * @param req is the service discovery request. - */ - private void sendRemoveServiceRequestMsg(Messenger replyMessenger, - WifiP2pServiceRequest req) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.REMOVE_SERVICE_REQUEST; - msg.obj = req; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Send Connect API msg. - * - * @param replyMessenger for checking replied message. - * @param config options as described in {@link WifiP2pConfig} class. - */ - private void sendConnectMsg(Messenger replyMessenger, - WifiP2pConfig config) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.CONNECT; - msg.obj = config; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Send CreateGroup API msg. - * - * @param replyMessenger for checking replied message. - * @param config options as described in {@link WifiP2pConfig} class. - */ - private void sendCreateGroupMsg(Messenger replyMessenger, - int netId, - WifiP2pConfig config) throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pManager.CREATE_GROUP; - msg.arg1 = netId; - msg.obj = config; - msg.replyTo = replyMessenger; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Send simple API msg. - * - * Mock the API msg without arguments. - * - * @param replyMessenger for checking replied message. - */ - private void sendSimpleMsg(Messenger replyMessenger, - int what) throws Exception { - Message msg = Message.obtain(); - msg.what = what; - if (replyMessenger != null) { - msg.replyTo = replyMessenger; - } - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Send simple API msg. - * - * Mock the API msg with objects. - * - * @param replyMessenger for checking replied message. - */ - private void sendSimpleMsg(Messenger replyMessenger, - int what, Object obj) throws Exception { - Message msg = Message.obtain(); - msg.what = what; - msg.obj = obj; - if (replyMessenger != null) { - msg.replyTo = replyMessenger; - } - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * force P2p State enter InactiveState to start others unit test - * - * @param clientBinder client binder to use for p2p channel init - */ - private void forceP2pEnabled(Binder clientBinder) throws Exception { - simulateWifiStateChange(true); - simulateLocationModeChange(true); - checkIsP2pInitWhenClientConnected(true, clientBinder); - } - - /** - * Check is P2p init as expected when client connected - * - * @param expectInit set true if p2p init should succeed as expected, set false when - * expected init should not happen - * @param clientBinder client binder to use for p2p channel init - */ - private void checkIsP2pInitWhenClientConnected(boolean expectInit, Binder clientBinder) - throws Exception { - mWifiP2pServiceImpl.getMessenger(clientBinder); - mLooper.dispatchAll(); - if (expectInit) { - verify(mWifiNative).setupInterface(any(), any()); - verify(mNetdWrapper).setInterfaceUp(anyString()); - verify(mWifiMonitor, atLeastOnce()).registerHandler(anyString(), anyInt(), any()); - } else { - verify(mWifiNative, never()).setupInterface(any(), any()); - verify(mNetdWrapper, never()).setInterfaceUp(anyString()); - verify(mWifiMonitor, never()).registerHandler(anyString(), anyInt(), any()); - } - } - - /** - * Check is P2p teardown as expected when client disconnected - * - * @param expectTearDown set true if p2p teardown should succeed as expected, - * set false when expected teardown should not happen - * @param clientBinder client binder to use for p2p channel init - */ - private void checkIsP2pTearDownWhenClientDisconnected( - boolean expectTearDown, Binder clientBinder) throws Exception { - mWifiP2pServiceImpl.close(clientBinder); - mLooper.dispatchAll(); - if (expectTearDown) { - verify(mWifiNative).teardownInterface(); - verify(mWifiMonitor).stopMonitoring(anyString()); - } else { - verify(mWifiNative, never()).teardownInterface(); - verify(mWifiMonitor, never()).stopMonitoring(anyString()); - } - } - - /** - * Check the broadcast of WIFI_P2P_THIS_DEVICE_CHANGED_ACTION is sent as expected. - */ - private void checkSendThisDeviceChangedBroadcast() { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - String[] permission_gold = new String[] {android.Manifest.permission.ACCESS_FINE_LOCATION, - android.Manifest.permission.ACCESS_WIFI_STATE}; - ArgumentCaptor<String []> permissionCaptor = ArgumentCaptor.forClass(String[].class); - verify(mContext, atLeastOnce()).sendBroadcastWithMultiplePermissions( - intentCaptor.capture(), permissionCaptor.capture()); - String [] permission = permissionCaptor.getValue(); - Arrays.sort(permission); - Arrays.sort(permission_gold); - assertEquals(permission_gold, permission); - Intent intent = intentCaptor.getValue(); - WifiP2pDevice device = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE); - assertEquals(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION, intent.getAction()); - assertEquals(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, intent.getFlags()); - assertEquals(mTestThisDevice.deviceName, device.deviceName); - assertEquals(ANONYMIZED_DEVICE_ADDRESS, device.deviceAddress); - assertEquals(mTestThisDevice.primaryDeviceType, device.primaryDeviceType); - assertEquals(mTestThisDevice.secondaryDeviceType, device.secondaryDeviceType); - assertEquals(mTestThisDevice.wpsConfigMethodsSupported, device.wpsConfigMethodsSupported); - assertEquals(mTestThisDevice.deviceCapability, device.deviceCapability); - assertEquals(mTestThisDevice.groupCapability, device.groupCapability); - assertEquals(mTestThisDevice.status, device.status); - if (mTestThisDevice.wfdInfo != null) { - assertEquals(mTestThisDevice.wfdInfo.isEnabled(), - device.wfdInfo.isEnabled()); - assertEquals(mTestThisDevice.wfdInfo.getDeviceInfoHex(), - device.wfdInfo.getDeviceInfoHex()); - assertEquals(mTestThisDevice.wfdInfo.getControlPort(), - device.wfdInfo.getControlPort()); - assertEquals(mTestThisDevice.wfdInfo.getMaxThroughput(), - device.wfdInfo.getMaxThroughput()); - } else { - assertEquals(mTestThisDevice.wfdInfo, device.wfdInfo); - } - } - - /** - * Check the broadcast of ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED is sent as expected. - */ - private void checkSendP2pPersistentGroupsChangedBroadcast() { - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser( - intentCaptor.capture(), eq(UserHandle.ALL)); - Intent intent = intentCaptor.getValue(); - assertEquals(WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED, intent.getAction()); - assertEquals(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, intent.getFlags()); - } - - /** - * Set up the instance of WifiP2pServiceImpl for testing. - * - * @param supported defines the p2p is supported or not in this instance. - */ - private void setUpWifiP2pServiceImpl(boolean supported) throws Exception { - reset(mContext, mFrameworkFacade, mHandlerThread, mPackageManager, mResources, - mWifiInjector, mWifiNative); - - generatorTestData(); - mClientHanderLooper = new TestLooper(); - mClientHandler = spy(new Handler(mClientHanderLooper.getLooper())); - mClientMessenger = new Messenger(mClientHandler); - mLooper = new TestLooper(); - - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager); - when(mWifiManager.getConnectionInfo()).thenReturn(mWifiInfo); - when(mWifiSettingsConfigStore.get(eq(WIFI_P2P_DEVICE_NAME))).thenReturn(thisDeviceName); - when(mWifiSettingsConfigStore.get(eq(WIFI_P2P_PENDING_FACTORY_RESET))).thenReturn(false); - when(mHandlerThread.getLooper()).thenReturn(mLooper.getLooper()); - if (supported) { - when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_WIFI_DIRECT))) - .thenReturn(true); - } else { - when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_WIFI_DIRECT))) - .thenReturn(false); - } - when(mResources.getString(R.string.config_wifi_p2p_device_type)) - .thenReturn("10-0050F204-5"); - when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade); - when(mWifiInjector.getUserManager()).thenReturn(mUserManager); - when(mWifiInjector.getWifiP2pMetrics()).thenReturn(mWifiP2pMetrics); - when(mWifiInjector.getWifiP2pMonitor()).thenReturn(mWifiMonitor); - when(mWifiInjector.getWifiP2pNative()).thenReturn(mWifiNative); - when(mWifiInjector.getWifiP2pServiceHandlerThread()).thenReturn(mHandlerThread); - when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil); - when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore); - // enable all permissions, disable specific permissions in tests - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.checkReadWifiCredentialPermission(anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - anyBoolean())).thenReturn(true); - when(mWifiNative.setupInterface(any(), any())).thenReturn(IFACE_NAME_P2P); - when(mWifiNative.p2pGetDeviceAddress()).thenReturn(thisDeviceMac); - doAnswer(new AnswerWithArguments() { - public boolean answer(WifiP2pGroupList groups) { - groups.clear(); - for (WifiP2pGroup group : mGroups.getGroupList()) { - groups.add(group); - } - return true; - } - }).when(mWifiNative).p2pListNetworks(any(WifiP2pGroupList.class)); - doAnswer(new AnswerWithArguments() { - public boolean answer(int netId) { - mGroups.remove(netId); - return true; - } - }).when(mWifiNative).removeP2pNetwork(anyInt()); - when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true); - - mWifiP2pServiceImpl = new WifiP2pServiceImpl(mContext, mWifiInjector); - if (supported) { - // register these event: - // * WifiManager.WIFI_STATE_CHANGED_ACTION - // * LocationManager.MODE_CHANGED_ACTION - // * TetheringManager.ACTION_TETHER_STATE_CHANGED - verify(mContext, times(3)).registerReceiver(mBcastRxCaptor.capture(), - any(IntentFilter.class)); - mWifiStateChangedReceiver = mBcastRxCaptor.getAllValues().get(0); - mLocationModeReceiver = mBcastRxCaptor.getAllValues().get(1); - mTetherStateReceiver = mBcastRxCaptor.getAllValues().get(2); - verify(mWifiNative).registerInterfaceAvailableListener( - mAvailListenerCaptor.capture(), any(Handler.class)); - mAvailListenerCaptor.getValue().onAvailabilityChanged(true); - } - - mWifiP2pServiceImpl.mNetdWrapper = mNetdWrapper; - mP2pStateMachineMessenger = mWifiP2pServiceImpl.getP2pStateMachineMessenger(); - mWifiP2pServiceImpl.setWifiHandlerLogForTest(mLog); - mWifiP2pServiceImpl.setWifiLogForReplyChannel(mLog); - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mStaticMockSession = mockitoSession() - .mockStatic(NetworkInterface.class) - .startMocking(); - lenient().when(NetworkInterface.getByName(eq(IFACE_NAME_P2P))) - .thenReturn(mP2pNetworkInterface); - ArrayList<InetAddress> p2pInetAddresses = new ArrayList<>(); - p2pInetAddresses.add(InetAddressUtils.parseNumericAddress(P2P_GO_IP)); - when(mP2pNetworkInterface.getInetAddresses()) - .thenReturn(Collections.enumeration(p2pInetAddresses)); - - setUpWifiP2pServiceImpl(true); - mClient1 = new Binder(); - mClient2 = new Binder(); - - when(mContext.createContextAsUser(any(), anyInt())).thenReturn(mContext); - } - - @After - public void cleanUp() throws Exception { - mStaticMockSession.finishMocking(); - } - - /** - * Mock enter Disabled state. - */ - private void mockEnterDisabledState() throws Exception { - Message msg = Message.obtain(); - msg.what = WifiP2pMonitor.SUP_DISCONNECTION_EVENT; - mP2pStateMachineMessenger.send(Message.obtain(msg)); - mLooper.dispatchAll(); - } - - /** - * Mock enter GroupNegotiation state. - */ - private void mockEnterGroupNegotiationState() throws Exception { - sendCreateGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_TEMPORARY, null); - } - - - /** - * Mock enter ProvisionDiscovery state. - */ - private void mockEnterProvisionDiscoveryState() throws Exception { - mockPeersList(); - sendConnectMsg(mClientMessenger, mTestWifiP2pPeerConfig); - } - - /** - * Mock WifiP2pServiceImpl.mPeers. - */ - private void mockPeersList() throws Exception { - sendDeviceFoundEventMsg(mTestWifiP2pDevice); - } - - /** - * Verify that p2p init / teardown whn a client connects / disconnects - * with wifi enabled - */ - @Test - public void testP2pInitWhenClientConnectWithWifiEnabled() throws Exception { - simulateWifiStateChange(true); - checkIsP2pInitWhenClientConnected(true, mClient1); - checkIsP2pTearDownWhenClientDisconnected(true, mClient1); - } - - /** - * Verify that p2p doesn't init when a client connects / disconnects - * with wifi disabled - */ - @Test - public void testP2pDoesntInitWhenClientConnectWithWifiDisabledEnabled() - throws Exception { - simulateWifiStateChange(false); - checkIsP2pInitWhenClientConnected(false, mClient1); - checkIsP2pTearDownWhenClientDisconnected(false, mClient1); - } - - /** - * Verify that p2p init / teardown when wifi off / on - * with a client connected - */ - @Test - public void checkIsP2pInitForWifiChanges() throws Exception { - forceP2pEnabled(mClient1); - - simulateWifiStateChange(false); - mLooper.dispatchAll(); - verify(mWifiNative).teardownInterface(); - verify(mWifiMonitor).stopMonitoring(anyString()); - // Force to back disable state for next test - mockEnterDisabledState(); - - simulateWifiStateChange(true); - mLooper.dispatchAll(); - verify(mWifiNative, times(2)).setupInterface(any(), any()); - verify(mNetdWrapper, times(2)).setInterfaceUp(anyString()); - verify(mWifiMonitor, atLeastOnce()).registerHandler(anyString(), anyInt(), any()); - } - - /** - * Verify p2p init / teardown when two clients connect / disconnect - */ - @Test - public void checkIsP2pInitForTwoClientsConnection() throws Exception { - forceP2pEnabled(mClient1); - // P2pInit check count should keep in once, same as one client connected case. - checkIsP2pInitWhenClientConnected(true, mClient2); - checkIsP2pTearDownWhenClientDisconnected(false, mClient2); - checkIsP2pTearDownWhenClientDisconnected(true, mClient1); - } - - /** - * Verify WifiP2pManager.ADD_LOCAL_SERVICE_FAILED is returned when a caller - * uses abnormal way to send WifiP2pManager.ADD_LOCAL_SERVICE (i.e no channel info updated). - */ - @Test - public void testAddLocalServiceFailureWhenNoChannelUpdated() throws Exception { - forceP2pEnabled(mClient1); - sendAddLocalServiceMsg(mClientMessenger); - verify(mWifiNative, never()).p2pServiceAdd(any()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_LOCAL_SERVICE_FAILED)); - } - - /** - * Verify WifiP2pManager.ADD_LOCAL_SERVICE_FAILED is returned when a caller - * uses wrong package name to initialize a channel. - */ - @Test - public void testAddLocalServiceFailureWhenChannelUpdateWrongPkgName() throws Exception { - forceP2pEnabled(mClient1); - doThrow(new SecurityException("P2p unit test")) - .when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddLocalServiceMsg(mClientMessenger); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_LOCAL_SERVICE_FAILED)); - verify(mWifiNative, never()).p2pServiceAdd(any()); - } - - /** - * Verify WifiP2pManager.ADD_LOCAL_SERVICE_FAILED is returned when a caller - * without proper permission attmepts to send WifiP2pManager.ADD_LOCAL_SERVICE. - */ - @Test - public void testAddLocalServiceFailureWhenCallerPermissionDenied() throws Exception { - forceP2pEnabled(mClient1); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect( - anyString(), anyString(), anyInt(), anyBoolean())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddLocalServiceMsg(mClientMessenger); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_LOCAL_SERVICE_FAILED)); - verify(mWifiNative, never()).p2pServiceAdd(any()); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - } - - /** - * Verify the caller with proper permission sends WifiP2pManager.ADD_LOCAL_SERVICE. - */ - @Test - public void testAddLocalServiceSuccess() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiNative.p2pServiceAdd(any())).thenReturn(true); - sendAddLocalServiceMsg(mClientMessenger); - verify(mWifiNative).p2pServiceAdd(any()); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED)); - } - - /** - * Verify WifiP2pManager.ADD_LOCAL_SERVICE_FAILED is returned when native call failure. - */ - @Test - public void testAddLocalServiceFailureWhenNativeCallFailure() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiNative.p2pServiceAdd(any())).thenReturn(false); - sendAddLocalServiceMsg(mClientMessenger); - verify(mWifiNative).p2pServiceAdd(any()); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_LOCAL_SERVICE_FAILED)); - } - - /** - * Verify WifiP2pManager.CONNECT_FAILED is returned when a caller - * uses abnormal way to send WifiP2pManager.CONNECT (i.e no channel info updated). - */ - @Test - public void testConnectWithConfigValidAsGroupFailureWhenNoChannelUpdated() throws Exception { - forceP2pEnabled(mClient1); - sendConnectMsgWithConfigValidAsGroup(mClientMessenger); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CONNECT_FAILED)); - verify(mWifiNative, never()).p2pGroupAdd(any(), anyBoolean()); - } - - /** - * Verify WifiP2pManager.CONNECT_FAILED is returned when a caller - * uses wrong package name to initialize a channel. - */ - @Test - public void testConnectWithConfigValidAsGroupFailureWhenChannelUpdateWrongPkgName() - throws Exception { - forceP2pEnabled(mClient1); - doThrow(new SecurityException("P2p unit test")) - .when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendConnectMsgWithConfigValidAsGroup(mClientMessenger); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CONNECT_FAILED)); - verify(mWifiNative, never()).p2pGroupAdd(any(), anyBoolean()); - } - - /** - * Verify WifiP2pManager.CONNECT_FAILED is returned when a caller - * without proper permission attmepts to send WifiP2pManager.CONNECT. - */ - @Test - public void testConnectWithConfigValidAsGroupFailureWhenPermissionDenied() throws Exception { - forceP2pEnabled(mClient1); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - anyBoolean())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendConnectMsgWithConfigValidAsGroup(mClientMessenger); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CONNECT_FAILED)); - verify(mWifiNative, never()).p2pGroupAdd(any(), anyBoolean()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - } - - /** - * Verify the caller with proper permission sends WifiP2pManager.CONNECT. - */ - @Test - public void testConnectWithConfigValidAsGroupSuccess() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - when(mWifiNative.p2pGroupAdd(any(), eq(true))).thenReturn(true); - sendConnectMsgWithConfigValidAsGroup(mClientMessenger); - verify(mWifiNative).p2pGroupAdd(any(), eq(true)); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CONNECT_SUCCEEDED)); - } - - /** - * Verify WifiP2pManager.CONNECT_FAILED is returned when native call failure. - */ - @Test - public void testConnectWithConfigValidAsGroupFailureWhenNativeCallFailure() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - when(mWifiNative.p2pGroupAdd(any(), eq(true))).thenReturn(false); - sendConnectMsgWithConfigValidAsGroup(mClientMessenger); - verify(mWifiNative).p2pGroupAdd(any(), eq(true)); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CONNECT_FAILED)); - } - - /** - * Verify WifiP2pManager.CREATE_GROUP_FAILED is returned when a caller - * uses abnormal way to send WifiP2pManager.CREATE_GROUP (i.e no channel info updated). - */ - @Test - public void testCreateGroupWithConfigValidAsGroupFailureWhenNoChannelUpdated() - throws Exception { - forceP2pEnabled(mClient1); - sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CREATE_GROUP_FAILED)); - verify(mWifiNative, never()).p2pGroupAdd(anyBoolean()); - verify(mWifiNative, never()).p2pGroupAdd(any(), anyBoolean()); - } - - /** - * Verify WifiP2pManager.CREATE_GROUP_FAILED is returned with null object when a caller - * uses wrong package name to initialize a channel. - */ - @Test - public void testCreateGroupWithConfigValidAsGroupFailureWhenChannelUpdateWrongPkgName() - throws Exception { - forceP2pEnabled(mClient1); - doThrow(new SecurityException("P2p unit test")) - .when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CREATE_GROUP_FAILED)); - verify(mWifiNative, never()).p2pGroupAdd(anyBoolean()); - verify(mWifiNative, never()).p2pGroupAdd(any(), anyBoolean()); - } - - /** - * Verify WifiP2pManager.CREATE_GROUP_FAILED is returned when a caller - * without proper permission attmepts to send WifiP2pManager.CREATE_GROUP. - */ - @Test - public void testCreateGroupWithConfigValidAsGroupFailureWhenPermissionDenied() - throws Exception { - forceP2pEnabled(mClient1); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - anyBoolean())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CREATE_GROUP_FAILED)); - verify(mWifiNative, never()).p2pGroupAdd(anyBoolean()); - verify(mWifiNative, never()).p2pGroupAdd(any(), anyBoolean()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - } - - /** - * Verify the caller with proper permission sends WifiP2pManager.CREATE_GROUP. - */ - @Test - public void testCreateGroupWithConfigValidAsGroupSuccess() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - when(mWifiNative.p2pGroupAdd(any(), eq(false))).thenReturn(true); - sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger); - verify(mWifiNative).p2pGroupAdd(any(), eq(false)); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CREATE_GROUP_SUCCEEDED)); - } - - /** - * Verify WifiP2pManager.CREATE_GROUP_FAILED is returned when native call failure. - */ - @Test - public void testCreateGroupWithConfigValidAsGroupFailureWhenNativeCallFailure() - throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - when(mWifiNative.p2pGroupAdd(any(), eq(false))).thenReturn(false); - sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger); - verify(mWifiNative).p2pGroupAdd(any(), eq(false)); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CREATE_GROUP_FAILED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_PEERS_FAILED is returned when a caller - * uses abnormal way to send WifiP2pManager.REQUEST_PEERS (i.e no channel info updated). - */ - @Test - public void testDiscoverPeersFailureWhenNoChannelUpdated() throws Exception { - forceP2pEnabled(mClient1); - sendDiscoverPeersMsg(mClientMessenger); - verify(mWifiNative, never()).p2pFind(anyInt()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_PEERS_FAILED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_PEERS_FAILED is returned when a caller - * uses wrong package name to initialize a channel. - */ - @Test - public void testDiscoverPeersFailureWhenChannelUpdateWrongPkgName() throws Exception { - forceP2pEnabled(mClient1); - doThrow(new SecurityException("P2p unit test")) - .when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendDiscoverPeersMsg(mClientMessenger); - verify(mWifiNative, never()).p2pFind(anyInt()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_PEERS_FAILED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_PEERS_FAILED is returned with null object when a caller - * without proper permission attmepts to send WifiP2pManager.DISCOVER_PEERS. - */ - @Test - public void testDiscoverPeersFailureWhenPermissionDenied() throws Exception { - forceP2pEnabled(mClient1); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - anyBoolean())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendDiscoverPeersMsg(mClientMessenger); - verify(mWifiNative, never()).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_PEERS_FAILED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_PEERS_FAILED is returned with null object when a caller - * attmepts to send WifiP2pManager.DISCOVER_PEERS and location mode is disabled. - */ - @Test - public void testDiscoverPeersFailureWhenLocationModeDisabled() throws Exception { - forceP2pEnabled(mClient1); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - eq(false))).thenReturn(true); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - eq(true))).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendDiscoverPeersMsg(mClientMessenger); - verify(mWifiNative, never()).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_PEERS_FAILED)); - } - - /** - * Verify the caller with proper permission sends WifiP2pManager.DISCOVER_PEERS. - */ - @Test - public void testDiscoverPeersSuccess() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pFind(anyInt())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendDiscoverPeersMsg(mClientMessenger); - verify(mWifiNative).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_PEERS_SUCCEEDED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_PEERS_FAILED is returned when native call failure. - */ - @Test - public void testDiscoverPeersFailureWhenNativeCallFailure() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pFind(anyInt())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendDiscoverPeersMsg(mClientMessenger); - verify(mWifiNative).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_PEERS_FAILED)); - } - - - /** - * Verify WifiP2pManager.DISCOVER_SERVICES_FAILED is returned when a caller - * uses abnormal way to send WifiP2pManager.DISCOVER_SERVICES (i.e no channel info updated). - */ - @Test - public void testDiscoverServicesFailureWhenNoChannelUpdated() throws Exception { - when(mWifiNative.p2pServDiscReq(anyString(), anyString())).thenReturn("mServiceDiscReqId"); - forceP2pEnabled(mClient1); - sendAddServiceRequestMsg(mClientMessenger); - sendDiscoverServiceMsg(mClientMessenger); - verify(mWifiNative, never()).p2pServDiscReq(anyString(), anyString()); - verify(mWifiNative, never()).p2pFind(anyInt()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_SERVICES_FAILED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_SERVICES_FAILED is returned when a caller - * uses wrong package name to initialize a channel. - */ - @Test - public void testDiscoverServicesFailureWhenChannelUpdateWrongPkgName() throws Exception { - when(mWifiNative.p2pServDiscReq(anyString(), anyString())).thenReturn("mServiceDiscReqId"); - forceP2pEnabled(mClient1); - doThrow(new SecurityException("P2p unit test")) - .when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddServiceRequestMsg(mClientMessenger); - sendDiscoverServiceMsg(mClientMessenger); - verify(mWifiNative, never()).p2pServDiscReq(anyString(), anyString()); - verify(mWifiNative, never()).p2pFind(anyInt()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_SERVICES_FAILED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_SERVICES_FAILED is returned when a caller - * without proper permission attmepts to send WifiP2pManager.DISCOVER_SERVICES. - */ - @Test - public void testDiscoverServicesFailureWhenPermissionDenied() throws Exception { - when(mWifiNative.p2pServDiscReq(anyString(), anyString())) - .thenReturn("mServiceDiscReqId"); - forceP2pEnabled(mClient1); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - anyBoolean())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddServiceRequestMsg(mClientMessenger); - sendDiscoverServiceMsg(mClientMessenger); - verify(mWifiNative, never()).p2pServDiscReq(anyString(), anyString()); - verify(mWifiNative, never()).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_SERVICES_FAILED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_SERVICES_FAILED is returned when a caller - * attmepts to send WifiP2pManager.DISCOVER_SERVICES and location mode is disabled. - */ - @Test - public void testDiscoverServicesFailureWhenLocationModeDisabled() throws Exception { - when(mWifiNative.p2pServDiscReq(anyString(), anyString())) - .thenReturn("mServiceDiscReqId"); - forceP2pEnabled(mClient1); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - eq(false))).thenReturn(true); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - eq(true))).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddServiceRequestMsg(mClientMessenger); - sendDiscoverServiceMsg(mClientMessenger); - verify(mWifiNative, never()).p2pServDiscReq(anyString(), anyString()); - verify(mWifiNative, never()).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_SERVICES_FAILED)); - } - - /** - * Verify the caller with proper permission sends WifiP2pManager.DISCOVER_SERVICES. - */ - @Test - public void testDiscoverServicesSuccess() throws Exception { - when(mWifiNative.p2pServDiscReq(anyString(), anyString())) - .thenReturn("mServiceDiscReqId"); - when(mWifiNative.p2pFind(anyInt())).thenReturn(true); - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddServiceRequestMsg(mClientMessenger); - sendDiscoverServiceMsg(mClientMessenger); - verify(mWifiNative).p2pServDiscReq(anyString(), anyString()); - verify(mWifiNative).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_SERVICES_SUCCEEDED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_SERVICES_FAILED is returned when add service failure. - */ - @Test - public void testDiscoverServicesFailureWhenAddServiceRequestFailure() throws Exception { - when(mWifiNative.p2pServDiscReq(anyString(), anyString())).thenReturn(null); - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddServiceRequestMsg(mClientMessenger); - sendDiscoverServiceMsg(mClientMessenger); - verify(mWifiNative).p2pServDiscReq(anyString(), anyString()); - verify(mWifiNative, never()).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_SERVICES_FAILED)); - } - - /** - * Verify WifiP2pManager.DISCOVER_SERVICES_FAILED is returned when native call failure. - */ - @Test - public void testDiscoverServicesFailureWhenNativeCallFailure() throws Exception { - when(mWifiNative.p2pServDiscReq(anyString(), anyString())) - .thenReturn("mServiceDiscReqId"); - when(mWifiNative.p2pFind(anyInt())).thenReturn(false); - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddServiceRequestMsg(mClientMessenger); - sendDiscoverServiceMsg(mClientMessenger); - verify(mWifiNative).p2pServDiscReq(anyString(), anyString()); - verify(mWifiNative).p2pFind(anyInt()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_SERVICES_FAILED)); - } - - /** - * Verify WifiP2pManager.RESPONSE_PEERS is returned with null object when a caller - * uses abnormal way to send WifiP2pManager.REQUEST_PEERS (i.e no channel info updated). - */ - @Test - public void testRequestPeersFailureWhenNoChannelUpdated() throws Exception { - forceP2pEnabled(mClient1); - mockPeersList(); - sendRequestPeersMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - WifiP2pDeviceList peers = (WifiP2pDeviceList) mMessageCaptor.getValue().obj; - assertEquals(WifiP2pManager.RESPONSE_PEERS, mMessageCaptor.getValue().what); - assertNull(peers.get(mTestWifiP2pDevice.deviceAddress)); - - } - - /** - * Verify WifiP2pManager.RESPONSE_PEERS is returned with null object when a caller - * uses wrong package name to initialize a channel. - */ - @Test - public void testRequestPeersFailureWhenChannelUpdateWrongPkgName() throws Exception { - forceP2pEnabled(mClient1); - mockPeersList(); - doThrow(new SecurityException("P2p unit test")) - .when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendRequestPeersMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - WifiP2pDeviceList peers = (WifiP2pDeviceList) mMessageCaptor.getValue().obj; - assertEquals(WifiP2pManager.RESPONSE_PEERS, mMessageCaptor.getValue().what); - assertNull(peers.get(mTestWifiP2pDevice.deviceAddress)); - } - - /** - * Verify WifiP2pManager.RESPONSE_PEERS is returned with null object when a caller - * without proper permission attmepts to send WifiP2pManager.REQUEST_PEERS. - */ - @Test - public void testRequestPeersFailureWhenPermissionDenied() throws Exception { - forceP2pEnabled(mClient1); - mockPeersList(); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - anyBoolean())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendRequestPeersMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - WifiP2pDeviceList peers = (WifiP2pDeviceList) mMessageCaptor.getValue().obj; - assertEquals(WifiP2pManager.RESPONSE_PEERS, mMessageCaptor.getValue().what); - assertNull(peers.get(mTestWifiP2pDevice.deviceAddress)); - - } - - /** - * Verify WifiP2pManager.RESPONSE_PEERS is returned with null object when a caller - * attmepts to send WifiP2pManager.REQUEST_PEERS and location mode is disabled. - */ - @Test - public void testRequestPeersFailureWhenLocationModeDisabled() throws Exception { - forceP2pEnabled(mClient1); - mockPeersList(); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - eq(false))).thenReturn(true); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - eq(true))).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendRequestPeersMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - WifiP2pDeviceList peers = (WifiP2pDeviceList) mMessageCaptor.getValue().obj; - assertEquals(WifiP2pManager.RESPONSE_PEERS, mMessageCaptor.getValue().what); - assertNull(peers.get(mTestWifiP2pDevice.deviceAddress)); - - } - - /** - * Verify WifiP2pManager.RESPONSE_PEERS is returned with expect object when a caller - * with proper permission to send WifiP2pManager.REQUEST_PEERS. - */ - @Test - public void testRequestPeersSuccess() throws Exception { - forceP2pEnabled(mClient1); - mockPeersList(); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendRequestPeersMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - WifiP2pDeviceList peers = (WifiP2pDeviceList) mMessageCaptor.getValue().obj; - assertEquals(WifiP2pManager.RESPONSE_PEERS, mMessageCaptor.getValue().what); - assertNotEquals(null, peers.get(mTestWifiP2pDevice.deviceAddress)); - } - - /** - * Verify WifiP2pManager.RESPONSE_GROUP_INFO is returned with null object when a caller - * uses abnormal way to send WifiP2pManager.REQUEST_GROUP_INFO (i.e no channel info updated). - */ - @Test - public void testRequestGroupInfoFailureWhenNoChannelUpdated() throws Exception { - forceP2pEnabled(mClient1); - sendGroupStartedMsg(mTestWifiP2pGroup); - simulateTetherReady(); - sendRequestGroupInfoMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); - assertNull(mMessageCaptor.getValue().obj); - } - - /** - * Verify WifiP2pManager.RESPONSE_GROUP_INFO is returned with null object when a caller - * uses wrong package name to initialize a channel. - */ - @Test - public void testRequestGroupInfoFailureWhenChannelUpdateWrongPkgName() throws Exception { - forceP2pEnabled(mClient1); - sendGroupStartedMsg(mTestWifiP2pGroup); - simulateTetherReady(); - doThrow(new SecurityException("P2p unit test")) - .when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendRequestGroupInfoMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); - assertNull(mMessageCaptor.getValue().obj); - } - - /** - * Verify WifiP2pManager.RESPONSE_GROUP_INFO is returned with null object when a caller - * without proper permission attempts to send WifiP2pManager.REQUEST_GROUP_INFO. - */ - @Test - public void testRequestGroupInfoFailureWhenPermissionDenied() throws Exception { - forceP2pEnabled(mClient1); - sendGroupStartedMsg(mTestWifiP2pGroup); - simulateTetherReady(); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - anyBoolean())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendRequestGroupInfoMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); - assertNull(mMessageCaptor.getValue().obj); - } - - /** - * Verify WifiP2pManager.RESPONSE_GROUP_INFO is returned with expect object when a caller - * with proper permission. - */ - @Test - public void testRequestGroupInfoSuccess() throws Exception { - mTestWifiP2pGroup.setOwner(mTestThisDevice); - forceP2pEnabled(mClient1); - sendGroupStartedMsg(mTestWifiP2pGroup); - simulateTetherReady(); - when(mWifiPermissionsUtil.checkLocalMacAddressPermission(anyInt())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendRequestGroupInfoMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); - WifiP2pGroup wifiP2pGroup = (WifiP2pGroup) mMessageCaptor.getValue().obj; - assertEquals(mTestWifiP2pGroup.getNetworkName(), wifiP2pGroup.getNetworkName()); - // Ensure that our own MAC address is anonymized if we're the group owner. - assertEquals(ANONYMIZED_DEVICE_ADDRESS, wifiP2pGroup.getOwner().deviceAddress); - } - - /** - * Verify WifiP2pManager.RESPONSE_GROUP_INFO does not anonymize this device's MAC address when - * requested by an app with the LOCAL_MAC_ADDRESS permission. - */ - @Test - public void testRequestGroupInfoIncludesMacForNetworkSettingsApp() throws Exception { - mTestWifiP2pGroup.setOwner(mTestThisDevice); - forceP2pEnabled(mClient1); - sendGroupStartedMsg(mTestWifiP2pGroup); - simulateTetherReady(); - when(mWifiPermissionsUtil.checkLocalMacAddressPermission(anyInt())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendRequestGroupInfoMsg(mClientMessenger); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); - WifiP2pGroup wifiP2pGroup = (WifiP2pGroup) mMessageCaptor.getValue().obj; - assertEquals(thisDeviceMac, wifiP2pGroup.getOwner().deviceAddress); - } - - /** - * Verify WifiP2pManager.START_LISTEN_FAILED is returned when a caller - * without proper permission attempts to send WifiP2pManager.START_LISTEN. - */ - @Test - public void testStartListenFailureWhenPermissionDenied() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - forceP2pEnabled(mClient1); - sendSimpleMsg(mClientMessenger, WifiP2pManager.START_LISTEN); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.START_LISTEN_FAILED)); - // p2pFlush should be invoked once in forceP2pEnabled. - verify(mWifiNative).p2pFlush(); - verify(mWifiNative, never()).p2pExtListen(anyBoolean(), anyInt(), anyInt()); - } - - /** - * Verify WifiP2pManager.START_LISTEN_FAILED is returned when native call failure. - */ - @Test - public void testStartListenFailureWhenNativeCallFailure() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mWifiNative.p2pExtListen(eq(true), anyInt(), anyInt())).thenReturn(false); - forceP2pEnabled(mClient1); - sendSimpleMsg(mClientMessenger, WifiP2pManager.START_LISTEN); - // p2pFlush would be invoked in forceP2pEnabled and startListen both. - verify(mWifiNative, times(2)).p2pFlush(); - verify(mWifiNative).p2pExtListen(eq(true), anyInt(), anyInt()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.START_LISTEN_FAILED)); - } - - /** - * Verify the caller with proper permission sends WifiP2pManager.START_LISTEN. - */ - @Test - public void testStartListenSuccess() throws Exception { - when(mWifiNative.p2pExtListen(eq(true), anyInt(), anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - forceP2pEnabled(mClient1); - sendSimpleMsg(mClientMessenger, WifiP2pManager.START_LISTEN); - // p2pFlush would be invoked in forceP2pEnabled and startListen both. - verify(mWifiNative, times(2)).p2pFlush(); - verify(mWifiNative).p2pExtListen(eq(true), anyInt(), anyInt()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.START_LISTEN_SUCCEEDED)); - } - - /** - * Verify WifiP2pManager.STOP_LISTEN_FAILED is returned when a caller - * without proper permission attempts to sends WifiP2pManager.STOP_LISTEN. - */ - @Test - public void testStopListenFailureWhenPermissionDenied() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - forceP2pEnabled(mClient1); - sendSimpleMsg(mClientMessenger, WifiP2pManager.STOP_LISTEN); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.STOP_LISTEN_FAILED)); - verify(mWifiNative, never()).p2pExtListen(anyBoolean(), anyInt(), anyInt()); - } - - /** - * Verify WifiP2pManager.STOP_LISTEN_FAILED is returned when native call failure. - */ - @Test - public void testStopListenFailureWhenNativeCallFailure() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mWifiNative.p2pExtListen(eq(false), anyInt(), anyInt())).thenReturn(false); - forceP2pEnabled(mClient1); - sendSimpleMsg(mClientMessenger, WifiP2pManager.STOP_LISTEN); - verify(mWifiNative).p2pExtListen(eq(false), anyInt(), anyInt()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.STOP_LISTEN_FAILED)); - } - - /** - * Verify the caller with proper permission sends WifiP2pManager.STOP_LISTEN. - */ - @Test - public void testStopListenSuccess() throws Exception { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mWifiNative.p2pExtListen(eq(false), anyInt(), anyInt())).thenReturn(true); - forceP2pEnabled(mClient1); - sendSimpleMsg(mClientMessenger, WifiP2pManager.STOP_LISTEN); - verify(mWifiNative).p2pExtListen(eq(false), anyInt(), anyInt()); - assertTrue(mClientHandler.hasMessages(WifiP2pManager.STOP_LISTEN_SUCCEEDED)); - } - - /** Verify the p2p randomized MAC feature is enabled if OEM supports it. */ - @Test - public void testP2pRandomMacWithOemSupport() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi_p2p_mac_randomization_supported)) - .thenReturn(true); - forceP2pEnabled(mClient1); - verify(mWifiNative, never()).setMacRandomization(eq(false)); - verify(mWifiNative).setMacRandomization(eq(true)); - } - - /** Verify the p2p randomized MAC feature is disabled if OEM does not support it. */ - @Test - public void testP2pRandomMacWithoutOemSupport() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi_p2p_mac_randomization_supported)) - .thenReturn(false); - forceP2pEnabled(mClient1); - verify(mWifiNative, never()).setMacRandomization(eq(true)); - verify(mWifiNative).setMacRandomization(eq(false)); - } - - /** - * Verify the caller sends WifiP2pManager.DELETE_PERSISTENT_GROUP. - */ - @Test - public void testDeletePersistentGroupSuccess() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - sendDeletePersistentGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_PERSISTENT); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED, message.what); - } - - /** - * Verify that respond with DELETE_PERSISTENT_GROUP_FAILED - * when caller sends DELETE_PERSISTENT_GROUP and p2p is disabled. - */ - @Test - public void testDeletePersistentGroupFailureWhenP2pDisabled() throws Exception { - sendDeletePersistentGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_PERSISTENT); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify that respond with DELETE_PERSISTENT_GROUP_FAILED - * when caller sends DELETE_PERSISTENT_GROUP and p2p is unsupported. - */ - @Test - public void testDeletePersistentGroupFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - sendDeletePersistentGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_PERSISTENT); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify that respond with DELETE_PERSISTENT_GROUP_FAILED - * when caller sends DELETE_PERSISTENT_GROUP and doesn't have the necessary permissions. - */ - @Test - public void testDeletePersistentGroupFailureWhenNoPermissions() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - // no permissions held - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false); - - sendDeletePersistentGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_PERSISTENT); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify the peer scan counter is increased while receiving WifiP2pManager.DISCOVER_PEERS at - * P2pEnabledState. - */ - @Test - public void testPeerScanMetricWhenSendDiscoverPeers() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pFind(anyInt())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendDiscoverPeersMsg(mClientMessenger); - verify(mWifiP2pMetrics).incrementPeerScans(); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - } - - /** - * Verify the service scan counter is increased while receiving - * WifiP2pManager.DISCOVER_SERVICES at P2pEnabledState. - */ - @Test - public void testServiceScanMetricWhenSendDiscoverServices() throws Exception { - when(mWifiNative.p2pServDiscReq(anyString(), anyString())) - .thenReturn("mServiceDiscReqId"); - when(mWifiNative.p2pFind(anyInt())).thenReturn(true); - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendAddServiceRequestMsg(mClientMessenger); - sendDiscoverServiceMsg(mClientMessenger); - verify(mWifiP2pMetrics).incrementServiceScans(); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(true)); - } - - /** - * Verify the persistent group counter is updated while receiving - * WifiP2pManager.FACTORY_RESET. - */ - @Test - public void testPersistentGroupMetricWhenSendFactoryReset() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - // permissions for factory reset - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())) - .thenReturn(true); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_NETWORK_RESET), any())) - .thenReturn(false); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_CONFIG_WIFI), any())) - .thenReturn(false); - - ArgumentCaptor<WifiP2pGroupList> groupsCaptor = - ArgumentCaptor.forClass(WifiP2pGroupList.class); - verify(mWifiP2pMetrics).updatePersistentGroup(groupsCaptor.capture()); - assertEquals(3, groupsCaptor.getValue().getGroupList().size()); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET); - - verify(mWifiP2pMetrics, times(2)).updatePersistentGroup(groupsCaptor.capture()); - // the captured object is the same object, just get the latest one is ok. - assertEquals(0, groupsCaptor.getValue().getGroupList().size()); - } - - /** - * Verify the persistent group counter is updated while receiving - * WifiP2pMonitor.P2P_GROUP_STARTED_EVENT. - */ - @Test - public void testPersistentGroupMetricWhenSendP2pGroupStartedEvent() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - ArgumentCaptor<WifiP2pGroupList> groupsCaptor = - ArgumentCaptor.forClass(WifiP2pGroupList.class); - verify(mWifiP2pMetrics).updatePersistentGroup(groupsCaptor.capture()); - assertEquals(3, groupsCaptor.getValue().getGroupList().size()); - - sendGroupStartedMsg(mTestWifiP2pNewPersistentGoGroup); - simulateTetherReady(); - - verify(mWifiP2pMetrics, times(2)).updatePersistentGroup(groupsCaptor.capture()); - // the captured object is the same object, just get the latest one is ok. - assertEquals(4, groupsCaptor.getValue().getGroupList().size()); - } - - /** - * Verify the persistent group counter is updated while receiving - * WifiP2pManager.DELETE_PERSISTENT_GROUP. - */ - @Test - public void testPersistentGroupMetricWhenSendDeletePersistentGroup() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - ArgumentCaptor<WifiP2pGroupList> groupsCaptor = - ArgumentCaptor.forClass(WifiP2pGroupList.class); - verify(mWifiP2pMetrics).updatePersistentGroup(groupsCaptor.capture()); - assertEquals(3, groupsCaptor.getValue().getGroupList().size()); - - sendDeletePersistentGroupMsg(mClientMessenger, 0); - - verify(mWifiP2pMetrics, times(2)).updatePersistentGroup(groupsCaptor.capture()); - // the captured object is the same object, just get the latest one is ok. - assertEquals(2, groupsCaptor.getValue().getGroupList().size()); - } - - /** - * Verify the group event. - */ - @Test - public void testGroupEventMetric() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - sendGroupStartedMsg(mTestWifiP2pNewPersistentGoGroup); - simulateTetherReady(); - - ArgumentCaptor<WifiP2pGroup> groupCaptor = - ArgumentCaptor.forClass(WifiP2pGroup.class); - verify(mWifiP2pMetrics).startGroupEvent(groupCaptor.capture()); - WifiP2pGroup groupCaptured = groupCaptor.getValue(); - assertEquals(mTestWifiP2pNewPersistentGoGroup.toString(), groupCaptured.toString()); - - sendGroupRemovedMsg(); - verify(mWifiP2pMetrics).endGroupEvent(); - } - - /** - * Verify the connection event for a fresh connection. - */ - @Test - public void testStartFreshConnectionEventWhenSendConnect() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockPeersList(); - sendConnectMsg(mClientMessenger, mTestWifiP2pPeerConfig); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mWifiP2pMetrics).startConnectionEvent( - eq(P2pConnectionEvent.CONNECTION_FRESH), - configCaptor.capture()); - assertEquals(mTestWifiP2pPeerConfig.toString(), configCaptor.getValue().toString()); - } - - /** - * Verify the connection event for a reinvoked connection. - */ - @Test - public void testStartReinvokeConnectionEventWhenSendConnect() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pGroupAdd(anyInt())) - .thenReturn(true); - when(mTestWifiP2pDevice.isGroupOwner()).thenReturn(true); - when(mWifiNative.p2pGetSsid(eq(mTestWifiP2pDevice.deviceAddress))) - .thenReturn(mTestWifiP2pGroup.getNetworkName()); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockPeersList(); - sendConnectMsg(mClientMessenger, mTestWifiP2pPeerConfig); - verify(mWifiPermissionsUtil) - .checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), anyInt(), eq(false)); - - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mWifiP2pMetrics).startConnectionEvent( - eq(P2pConnectionEvent.CONNECTION_REINVOKE), - configCaptor.capture()); - assertEquals(mTestWifiP2pPeerConfig.toString(), configCaptor.getValue().toString()); - } - - /** - * Verify the connection event for a reinvoked connection via - * createGroup API. - * - * If there is a persistent group whose owner is this deivce, this would be - * a reinvoked group. - */ - @Test - public void testStartReinvokeConnectionEventWhenCreateGroup() - throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - sendCreateGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_PERSISTENT, null); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - verify(mWifiP2pMetrics).startConnectionEvent( - eq(P2pConnectionEvent.CONNECTION_REINVOKE), - eq(null)); - } - - /** - * Verify the connection event for a local connection while setting - * netId to {@link WifiP2pGroup#NETWORK_ID_PERSISTENT}. - */ - @Test - public void testStartLocalConnectionWhenCreateGroup() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - // permissions for factory reset - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())) - .thenReturn(true); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_NETWORK_RESET), any())) - .thenReturn(false); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_CONFIG_WIFI), any())) - .thenReturn(false); - - // There is one group hosted by this device in mGroups. - // clear all groups to avoid re-invoking a group. - sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET); - - sendCreateGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_PERSISTENT, null); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - verify(mWifiP2pMetrics).startConnectionEvent( - eq(P2pConnectionEvent.CONNECTION_LOCAL), - eq(null)); - } - - /** - * Verify the connection event for a local connection while setting the - * netId to {@link WifiP2pGroup#NETWORK_ID_TEMPORARY}. - */ - @Test - public void testStartLocalConnectionEventWhenCreateTemporaryGroup() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - sendCreateGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_TEMPORARY, null); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - verify(mWifiP2pMetrics).startConnectionEvent( - eq(P2pConnectionEvent.CONNECTION_LOCAL), - eq(null)); - } - - /** - * Verify the connection event for a fast connection via - * connect with config. - */ - @Test - public void testStartFastConnectionEventWhenSendConnectWithConfig() - throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pGroupAdd(any(), eq(true))).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - sendConnectMsg(mClientMessenger, mTestWifiP2pFastConnectionConfig); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mWifiP2pMetrics).startConnectionEvent( - eq(P2pConnectionEvent.CONNECTION_FAST), - configCaptor.capture()); - assertEquals(mTestWifiP2pFastConnectionConfig.toString(), - configCaptor.getValue().toString()); - } - - /** - * Verify the connection event for a fast connection via - * createGroup API with config. - */ - @Test - public void testStartFastConnectionEventWhenCreateGroupWithConfig() - throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - sendCreateGroupMsg(mClientMessenger, 0, mTestWifiP2pFastConnectionConfig); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mWifiP2pMetrics).startConnectionEvent( - eq(P2pConnectionEvent.CONNECTION_FAST), - configCaptor.capture()); - assertEquals(mTestWifiP2pFastConnectionConfig.toString(), - configCaptor.getValue().toString()); - } - - /** - * Verify the connection event ends while the group is formed. - */ - @Test - public void testEndConnectionEventWhenGroupFormed() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - verify(mWifiP2pMetrics).endConnectionEvent( - eq(P2pConnectionEvent.CLF_NONE)); - } - - /** - * Verify the connection event ends due to timeout. - */ - @Test - public void testEndConnectionEventWhenTimeout() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterGroupNegotiationState(); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - mLooper.moveTimeForward(120 * 1000 * 2); - mLooper.dispatchAll(); - - verify(mWifiP2pMetrics).endConnectionEvent( - eq(P2pConnectionEvent.CLF_TIMEOUT)); - } - - /** - * Verify the connection event ends due to the cancellation. - */ - @Test - public void testEndConnectionEventWhenCancel() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterGroupNegotiationState(); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); - - verify(mWifiP2pMetrics).endConnectionEvent( - eq(P2pConnectionEvent.CLF_CANCEL)); - } - - /** - * Verify the connection event ends due to the provision discovery failure. - */ - @Test - public void testEndConnectionEventWhenProvDiscFailure() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterProvisionDiscoveryState(); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - sendSimpleMsg(null, WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT); - - verify(mWifiP2pMetrics).endConnectionEvent( - eq(P2pConnectionEvent.CLF_PROV_DISC_FAIL)); - } - - /** - * Verify the connection event ends due to the group removal. - */ - @Test - public void testEndConnectionEventWhenGroupRemoval() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterGroupNegotiationState(); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - sendSimpleMsg(null, WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT); - - verify(mWifiP2pMetrics).endConnectionEvent( - eq(P2pConnectionEvent.CLF_UNKNOWN)); - } - - /** - * Verify the connection event ends due to the invitation failure. - */ - @Test - public void testEndConnectionEventWhenInvitationFailure() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterGroupNegotiationState(); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - - sendInvitationResultMsg(WifiP2pServiceImpl.P2pStatus.UNKNOWN); - - verify(mWifiP2pMetrics).endConnectionEvent( - eq(P2pConnectionEvent.CLF_INVITATION_FAIL)); - } - - /** - * Verify WifiP2pManager.RESPONSE_DEVICE_INFO is returned with null object when a caller - * without proper permission attempts. - */ - @Test - public void testRequestDeviceInfoFailureWhenPermissionDenied() throws Exception { - forceP2pEnabled(mClient1); - doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString()); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(), - anyBoolean())).thenReturn(false); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DEVICE_INFO); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - assertEquals(WifiP2pManager.RESPONSE_DEVICE_INFO, mMessageCaptor.getValue().what); - assertNull(mMessageCaptor.getValue().obj); - } - - /** - * Verify WifiP2pManager.RESPONSE_DEVICE_INFO is returned with expect object when a caller - * with proper permission attempts in p2p enabled state. - */ - @Test - public void testRequestDeviceInfoSuccessWhenP2pEnabled() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DEVICE_INFO); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - assertEquals(WifiP2pManager.RESPONSE_DEVICE_INFO, mMessageCaptor.getValue().what); - WifiP2pDevice wifiP2pDevice = (WifiP2pDevice) mMessageCaptor.getValue().obj; - assertEquals(ANONYMIZED_DEVICE_ADDRESS, wifiP2pDevice.deviceAddress); - assertEquals(thisDeviceName, wifiP2pDevice.deviceName); - } - - /** - * Verify WifiP2pManager.RESPONSE_DEVICE_INFO is returned with empty object when a caller - * with proper permission attempts in p2p disabled state. - */ - @Test - public void testRequestDeviceInfoReturnEmptyWifiP2pDeviceWhenP2pDisabled() throws Exception { - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DEVICE_INFO); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - assertEquals(WifiP2pManager.RESPONSE_DEVICE_INFO, mMessageCaptor.getValue().what); - WifiP2pDevice wifiP2pDevice = (WifiP2pDevice) mMessageCaptor.getValue().obj; - assertEquals("", wifiP2pDevice.deviceAddress); - assertEquals("", wifiP2pDevice.deviceName); - } - - /** - * Verify WifiP2pManager.RESPONSE_DEVICE_INFO returns an object with the actual device MAC when - * the caller holds the LOCAL_MAC_ADDRESS permission. - */ - @Test - public void testRequestDeviceInfoReturnsActualMacForNetworkSettingsApp() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiPermissionsUtil.checkLocalMacAddressPermission(anyInt())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DEVICE_INFO); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(false)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - assertEquals(WifiP2pManager.RESPONSE_DEVICE_INFO, mMessageCaptor.getValue().what); - WifiP2pDevice wifiP2pDevice = (WifiP2pDevice) mMessageCaptor.getValue().obj; - assertEquals(thisDeviceMac, wifiP2pDevice.deviceAddress); - assertEquals(thisDeviceName, wifiP2pDevice.deviceName); - } - - /** - * Verify the caller sends WifiP2pManager.STOP_DISCOVERY. - */ - @Test - public void testStopDiscoverySuccess() throws Exception { - when(mWifiNative.p2pStopFind()).thenReturn(true); - forceP2pEnabled(mClient1); - sendSimpleMsg(mClientMessenger, WifiP2pManager.STOP_DISCOVERY); - verify(mWifiNative).p2pStopFind(); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.STOP_DISCOVERY_SUCCEEDED, message.what); - } - - /** - * Verify WifiP2pManager.STOP_DISCOVERY_FAILED is returned when native call failure. - */ - @Test - public void testStopDiscoveryFailureWhenNativeCallFailure() throws Exception { - when(mWifiNative.p2pStopFind()).thenReturn(false); - forceP2pEnabled(mClient1); - sendSimpleMsg(mClientMessenger, WifiP2pManager.STOP_DISCOVERY); - verify(mWifiNative).p2pStopFind(); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.STOP_DISCOVERY_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.STOP_DISCOVERY_FAILED is returned when p2p is disabled. - */ - @Test - public void testStopDiscoveryFailureWhenP2pDisabled() throws Exception { - sendSimpleMsg(mClientMessenger, WifiP2pManager.STOP_DISCOVERY); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.STOP_DISCOVERY_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.STOP_DISCOVERY_FAILED is returned when p2p is unsupported. - */ - @Test - public void testStopDiscoveryFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - sendSimpleMsg(mClientMessenger, WifiP2pManager.STOP_DISCOVERY); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.STOP_DISCOVERY_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.CANCEL_CONNECT. - */ - @Test - public void testCancelConnectSuccess() throws Exception { - // Move to group creating state - testConnectWithConfigValidAsGroupSuccess(); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); - verify(mClientHandler, atLeastOnce()).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CANCEL_CONNECT_SUCCEEDED, message.what); - } - - /** - * Verify WifiP2pManager.CANCEL_CONNECT_FAILED is returned when p2p is inactive. - */ - @Test - public void testCancelConnectFailureWhenP2pInactive() throws Exception { - // Move to inactive state - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CANCEL_CONNECT_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.CANCEL_CONNECT_FAILED is returned when p2p is disabled. - */ - @Test - public void testCancelConnectFailureWhenP2pDisabled() throws Exception { - sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CANCEL_CONNECT_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.CANCEL_CONNECT_FAILED is returned when p2p is unsupported. - */ - @Test - public void testCancelConnectFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CANCEL_CONNECT_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.REMOVE_GROUP. - */ - @Test - public void testRemoveGroupSuccess() throws Exception { - // Move to group created state - forceP2pEnabled(mClient1); - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - - when(mWifiNative.p2pGroupRemove(eq(IFACE_NAME_P2P))).thenReturn(true); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REMOVE_GROUP); - verify(mWifiNative).p2pGroupRemove(eq(IFACE_NAME_P2P)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_GROUP_SUCCEEDED, message.what); - } - - /** - * Verify WifiP2pManager.REMOVE_GROUP_FAILED is returned when native call failure. - */ - @Test - public void testRemoveGroupFailureWhenNativeCallFailure() throws Exception { - // Move to group created state - forceP2pEnabled(mClient1); - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - - when(mWifiNative.p2pGroupRemove(eq(IFACE_NAME_P2P))).thenReturn(false); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REMOVE_GROUP); - verify(mWifiNative).p2pGroupRemove(eq(IFACE_NAME_P2P)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_GROUP_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.REMOVE_GROUP_FAILED is returned when p2p is creating group. - */ - @Test - public void testRemoveGroupFailureWhenP2pCreatingGroup() throws Exception { - // Move to group creating state - testConnectWithConfigValidAsGroupSuccess(); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REMOVE_GROUP); - verify(mClientHandler, atLeastOnce()).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_GROUP_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.REMOVE_GROUP_FAILED is returned when p2p is inactive. - */ - @Test - public void testRemoveGroupFailureWhenP2pInactive() throws Exception { - // Move to inactive state - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REMOVE_GROUP); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_GROUP_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.REMOVE_GROUP_FAILED is returned when p2p is disabled. - */ - @Test - public void testRemoveGroupFailureWhenP2pDisabled() throws Exception { - sendSimpleMsg(mClientMessenger, WifiP2pManager.REMOVE_GROUP); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_GROUP_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.REMOVE_GROUP_FAILED is returned when p2p is unsupported. - */ - @Test - public void testRemoveGroupFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REMOVE_GROUP); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_GROUP_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.SET_CHANNEL. - */ - @Test - public void testSetChannelSuccess() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - Bundle p2pChannels = new Bundle(); - p2pChannels.putInt("lc", 1); - p2pChannels.putInt("oc", 2); - when(mWifiNative.p2pSetChannel(anyInt(), anyInt())).thenReturn(true); - sendSetChannelMsg(mClientMessenger, p2pChannels); - verify(mWifiNative).p2pSetChannel(eq(1), eq(2)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_CHANNEL_SUCCEEDED, message.what); - } - - /** - * Verify WifiP2pManager.SET_CHANNEL_FAILED is returned when native call failure. - */ - @Test - public void testSetChannelFailureWhenNativeCallFailure() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - Bundle p2pChannels = new Bundle(); - p2pChannels.putInt("lc", 1); - p2pChannels.putInt("oc", 2); - when(mWifiNative.p2pSetChannel(anyInt(), anyInt())).thenReturn(false); - sendSetChannelMsg(mClientMessenger, p2pChannels); - verify(mWifiNative).p2pSetChannel(eq(1), eq(2)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_CHANNEL_FAILED, message.what); - } - - /** - * Verify WifiP2pManager.SET_CHANNEL_FAILED is returned when no permissions are held. - */ - @Test - public void testSetChannelFailureWhenNoPermissions() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - // no permissions held - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false); - - Bundle p2pChannels = new Bundle(); - p2pChannels.putInt("lc", 1); - p2pChannels.putInt("oc", 2); - sendSetChannelMsg(mClientMessenger, p2pChannels); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_CHANNEL_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify p2pSetChannel doesn't been called when message contain null object. - */ - @Test - public void testSetChannelFailureWhenObjectIsNull() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - when(mWifiNative.p2pSetChannel(anyInt(), anyInt())).thenReturn(false); - sendSetChannelMsg(mClientMessenger, null); - verify(mWifiNative, never()).p2pSetChannel(anyInt(), anyInt()); - } - - /** - * Verify the caller sends WifiP2pManager.START_WPS with push button configuration. - */ - @Test - public void testStartWpsWithPbcSuccess() throws Exception { - // Move to group created state - forceP2pEnabled(mClient1); - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - - when(mWifiNative.startWpsPbc(anyString(), any())).thenReturn(true); - WpsInfo wps = new WpsInfo(); - wps.setup = WpsInfo.PBC; - sendStartWpsMsg(mClientMessenger, wps); - verify(mWifiNative).startWpsPbc(eq(IFACE_NAME_P2P), isNull()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_SUCCEEDED, message.what); - } - - /** - * Verify the caller sends WifiP2pManager.START_WPS with pin display. - */ - @Test - public void testStartWpsWithPinDisplaySuccess() throws Exception { - // TODO(hsiuchangchen): This test item is related to UI. - } - - /** - * Verify the caller sends WifiP2pManager.START_WPS with pin keypad. - */ - @Test - public void testStartWpsWithPinKeypadSuccess() throws Exception { - // Move to group created state - forceP2pEnabled(mClient1); - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - - when(mWifiNative.startWpsPinKeypad(anyString(), anyString())).thenReturn(true); - WpsInfo wps = new WpsInfo(); - wps.setup = WpsInfo.KEYPAD; - wps.pin = "1234"; - sendStartWpsMsg(mClientMessenger, wps); - verify(mWifiNative).startWpsPinKeypad(eq(IFACE_NAME_P2P), eq("1234")); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_SUCCEEDED, message.what); - } - - /** - * Verify WifiP2pManager.START_WPS_FAILED is returned when message contain null object. - */ - @Test - public void testStartWpsFailureWhenObjectIsNull() throws Exception { - // Move to group created state - forceP2pEnabled(mClient1); - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - - WpsInfo wps = null; - sendStartWpsMsg(mClientMessenger, wps); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_FAILED, message.what); - } - - /** - * Verify WifiP2pManager.START_WPS_FAILED is returned when native call failure with - * push button configuration. - */ - @Test - public void testStartWpsWithPbcFailureWhenNativeCallFailure() throws Exception { - // Move to group created state - forceP2pEnabled(mClient1); - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - when(mWifiNative.startWpsPbc(anyString(), any())).thenReturn(false); - WpsInfo wps = new WpsInfo(); - wps.setup = WpsInfo.PBC; - sendStartWpsMsg(mClientMessenger, wps); - verify(mWifiNative).startWpsPbc(eq(IFACE_NAME_P2P), isNull()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_FAILED, message.what); - } - - /** - * Verify WifiP2pManager.START_WPS_FAILED is returned when native call failure with - * pin display. - */ - @Test - public void testStartWpsWithPinDisplayFailureWhenNativeCallFailure() throws Exception { - // Move to group created state - forceP2pEnabled(mClient1); - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - - when(mWifiNative.startWpsPinDisplay(anyString(), any())).thenReturn("abcd"); - WpsInfo wps = new WpsInfo(); - wps.setup = WpsInfo.DISPLAY; - sendStartWpsMsg(mClientMessenger, wps); - verify(mWifiNative).startWpsPinDisplay(eq(IFACE_NAME_P2P), isNull()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_FAILED, message.what); - } - - /** - * Verify WifiP2pManager.START_WPS_FAILED is returned when native call failure with - * pin keypad. - */ - @Test - public void testStartWpsWithPinKeypadFailureWhenNativeCallFailure() throws Exception { - // Move to group created state - forceP2pEnabled(mClient1); - WifiP2pGroup group = new WifiP2pGroup(); - group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); - group.setNetworkName("DIRECT-xy-NEW"); - group.setOwner(new WifiP2pDevice("thisDeviceMac")); - group.setIsGroupOwner(true); - group.setInterface(IFACE_NAME_P2P); - sendGroupStartedMsg(group); - simulateTetherReady(); - - when(mWifiNative.startWpsPinKeypad(anyString(), anyString())).thenReturn(false); - WpsInfo wps = new WpsInfo(); - wps.setup = WpsInfo.KEYPAD; - wps.pin = "1234"; - sendStartWpsMsg(mClientMessenger, wps); - verify(mWifiNative).startWpsPinKeypad(eq(IFACE_NAME_P2P), eq("1234")); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_FAILED, message.what); - } - - /** - * Verify WifiP2pManager.START_WPS_FAILED is returned when p2p is inactive. - */ - @Test - public void testStartWpsFailureWhenP2pInactive() throws Exception { - // Move to inactive state - forceP2pEnabled(mClient1); - - WpsInfo wps = new WpsInfo(); - sendStartWpsMsg(mClientMessenger, wps); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.START_WPS_FAILED is returned when p2p is disabled. - */ - @Test - public void testStartWpsFailureWhenP2pDisabled() throws Exception { - WpsInfo wps = new WpsInfo(); - sendStartWpsMsg(mClientMessenger, wps); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.START_WPS_FAILED is returned when p2p is unsupported. - */ - @Test - public void testStartWpsFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - WpsInfo wps = new WpsInfo(); - sendStartWpsMsg(mClientMessenger, wps); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.START_WPS_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.SET_DEVICE_NAME. - */ - @Test - public void testSetDeviceNameSuccess() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - mTestThisDevice.status = mTestThisDevice.AVAILABLE; - - mTestThisDevice.deviceName = "another-name"; - when(mWifiNative.setDeviceName(anyString())).thenReturn(true); - sendSetDeviceNameMsg(mClientMessenger, mTestThisDevice); - verify(mWifiNative).setDeviceName(eq(mTestThisDevice.deviceName)); - verify(mWifiNative).setP2pSsidPostfix(eq("-" + mTestThisDevice.deviceName)); - verify(mWifiSettingsConfigStore).put( - eq(WIFI_P2P_DEVICE_NAME), eq(mTestThisDevice.deviceName)); - checkSendThisDeviceChangedBroadcast(); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED, message.what); - } - - /** - * Verify WifiP2pManager.SET_DEVICE_NAME_FAILED is returned when native call failed. - */ - @Test - public void testSetDeviceNameFailureWhenNativeCallFailure() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - when(mWifiNative.setDeviceName(anyString())).thenReturn(false); - sendSetDeviceNameMsg(mClientMessenger, mTestThisDevice); - verify(mWifiNative).setDeviceName(eq(mTestThisDevice.deviceName)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_DEVICE_NAME_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_DEVICE_NAME_FAILED is returned when p2p device is null. - */ - @Test - public void testSetDeviceNameFailureWhenDeviceIsNull() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - sendSetDeviceNameMsg(mClientMessenger, null); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_DEVICE_NAME_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_DEVICE_NAME_FAILED is returned when p2p device's name is null. - */ - @Test - public void testSetDeviceNameFailureWhenDeviceNameIsNull() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - mTestThisDevice.deviceName = null; - sendSetDeviceNameMsg(mClientMessenger, mTestThisDevice); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_DEVICE_NAME_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_DEVICE_NAME_FAILED is returned when p2p is disabled. - */ - @Test - public void testSetDeviceNameFailureWhenP2pDisabled() throws Exception { - sendSetDeviceNameMsg(mClientMessenger, mTestThisDevice); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_DEVICE_NAME_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_DEVICE_NAME_FAILED is returned when p2p is unsupported. - */ - @Test - public void testSetDeviceNameFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - sendSetDeviceNameMsg(mClientMessenger, mTestThisDevice); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_DEVICE_NAME_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_DEVICE_NAME_FAILED is returned when no permissions are held. - */ - @Test - public void testSetDeviceNameFailureWhenNoPermissions() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - // no permissions held - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false); - - sendSetDeviceNameMsg(mClientMessenger, null); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_DEVICE_NAME_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.SET_WFD_INFO with wfd enabled. - */ - @Test - public void testSetWfdInfoSuccessWithWfdEnabled() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - mTestThisDevice.status = mTestThisDevice.AVAILABLE; - - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - mTestThisDevice.wfdInfo.setEnabled(true); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiNative.setWfdEnable(anyBoolean())).thenReturn(true); - when(mWifiNative.setWfdDeviceInfo(anyString())).thenReturn(true); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mWifiNative).setWfdEnable(eq(true)); - verify(mWifiNative).setWfdDeviceInfo(eq(mTestThisDevice.wfdInfo.getDeviceInfoHex())); - checkSendThisDeviceChangedBroadcast(); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_SUCCEEDED, message.what); - } - - /** - * Verify the caller sends WifiP2pManager.SET_WFD_INFO with wfd is disabled. - */ - @Test - public void testSetWfdInfoSuccessWithWfdDisabled() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - mTestThisDevice.status = mTestThisDevice.AVAILABLE; - - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - mTestThisDevice.wfdInfo.setEnabled(false); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiNative.setWfdEnable(anyBoolean())).thenReturn(true); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mWifiNative).setWfdEnable(eq(false)); - checkSendThisDeviceChangedBroadcast(); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_SUCCEEDED, message.what); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when wfd permission denied. - */ - @Test - public void testSetWfdInfoFailureWhenWfdPermissionDenied() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - mTestThisDevice.status = mTestThisDevice.AVAILABLE; - - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_DENIED); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when wfdInfo is null. - */ - @Test - public void testSetWfdInfoFailureWhenWfdInfoIsNull() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - mTestThisDevice.status = mTestThisDevice.AVAILABLE; - - mTestThisDevice.wfdInfo = null; - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when wfd is enabled - * and native call "setWfdEnable" failure. - */ - @Test - public void testSetWfdInfoFailureWithWfdEnabledWhenNativeCallFailure1() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - mTestThisDevice.status = mTestThisDevice.AVAILABLE; - - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - mTestThisDevice.wfdInfo.setEnabled(true); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiNative.setWfdEnable(anyBoolean())).thenReturn(false); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mWifiNative).setWfdEnable(eq(true)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when wfd is enabled - * and native call "setWfdDeviceInfo" failure. - */ - @Test - public void testSetWfdInfoFailureWithWfdEnabledWhenNativeCallFailure2() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - mTestThisDevice.status = mTestThisDevice.AVAILABLE; - - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - mTestThisDevice.wfdInfo.setEnabled(true); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiNative.setWfdEnable(anyBoolean())).thenReturn(true); - when(mWifiNative.setWfdDeviceInfo(anyString())).thenReturn(false); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mWifiNative).setWfdEnable(eq(true)); - verify(mWifiNative).setWfdDeviceInfo(eq(mTestThisDevice.wfdInfo.getDeviceInfoHex())); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when wfd is disabled - * and native call failure. - */ - @Test - public void testSetWfdInfoFailureWithWfdDisabledWhenNativeCallFailure() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - mTestThisDevice.status = mTestThisDevice.AVAILABLE; - - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - mTestThisDevice.wfdInfo.setEnabled(false); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - when(mWifiNative.setWfdEnable(anyBoolean())).thenReturn(false); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mWifiNative).setWfdEnable(eq(false)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when p2p is disabled. - */ - @Test - public void testSetWfdInfoFailureWhenP2pDisabled() throws Exception { - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when wfd permission denied - * and p2p is disabled. - */ - @Test - public void testSetWfdInfoFailureWhenWfdPermissionDeniedAndP2pDisabled() throws Exception { - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_DENIED); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when p2p is unsupported. - */ - @Test - public void testSetWfdInfoFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify WifiP2pManager.SET_WFD_INFO_FAILED is returned when wfd permission denied - * and p2p is unsupported. - */ - @Test - public void testSetWfdInfoFailureWhenWfdPermissionDeniedAndP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - mTestThisDevice.wfdInfo = new WifiP2pWfdInfo(); - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_DENIED); - sendSetWfdInfoMsg(mClientMessenger, mTestThisDevice.wfdInfo); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_WFD_INFO_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify the call setMiracastMode when p2p is enabled. - */ - @Test - public void testSetMiracastModeWhenP2pEnabled() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiP2pServiceImpl.setMiracastMode(0); - mLooper.dispatchAll(); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mWifiNative).setMiracastMode(eq(0)); - } - - /** - * Verify the call setMiracastMode when p2p is disable. - */ - @Test - public void testSetMiracastModeWhenP2pDisabled() throws Exception { - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiP2pServiceImpl.setMiracastMode(0); - mLooper.dispatchAll(); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mWifiNative, never()).setMiracastMode(anyInt()); - } - - /** - * Verify the call setMiracastMode when CONFIGURE_WIFI_DISPLAY permission denied. - */ - @Test(expected = SecurityException.class) - public void testSetMiracastModeWhenPermissionDeined() throws Exception { - when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper); - when(mWifiPermissionsWrapper.getUidPermission(anyString(), anyInt())) - .thenReturn(PackageManager.PERMISSION_DENIED); - mWifiP2pServiceImpl.setMiracastMode(0); - verify(mWifiInjector).getWifiPermissionsWrapper(); - verify(mWifiPermissionsWrapper).getUidPermission( - eq(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY), anyInt()); - verify(mWifiNative, never()).setMiracastMode(anyInt()); - } - - /** - * Verify the caller sends WifiP2pManager.FACTORY_RESET when p2p is enabled. - */ - @Test - public void testFactoryResetSuccessWhenP2pEnabled() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - when(mWifiInjector.getUserManager()).thenReturn(mUserManager); - when(mPackageManager.getNameForUid(anyInt())).thenReturn("testPkg"); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_NETWORK_RESET), any())) - .thenReturn(false); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_CONFIG_WIFI), any())) - .thenReturn(false); - when(mWifiNative.p2pListNetworks(any())).thenReturn(true); - sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET); - checkSendP2pPersistentGroupsChangedBroadcast(); - verify(mWifiInjector).getUserManager(); - verify(mPackageManager).getNameForUid(anyInt()); - verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt()); - verify(mUserManager).hasUserRestrictionForUser( - eq(UserManager.DISALLOW_NETWORK_RESET), any()); - verify(mUserManager).hasUserRestrictionForUser(eq(UserManager.DISALLOW_CONFIG_WIFI), any()); - verify(mWifiNative, atLeastOnce()).p2pListNetworks(any()); - verify(mWifiSettingsConfigStore).put(eq(WIFI_P2P_PENDING_FACTORY_RESET), eq(false)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.FACTORY_RESET_SUCCEEDED, message.what); - } - - /** - * Verify the caller sends WifiP2pManager.FACTORY_RESET when p2p is disabled at first - * and changes to enabled. - */ - @Test - public void testFactoryResetSuccessWhenP2pFromDisabledToEnabled() throws Exception { - when(mWifiInjector.getUserManager()).thenReturn(mUserManager); - when(mPackageManager.getNameForUid(anyInt())).thenReturn("testPkg"); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_NETWORK_RESET), any())) - .thenReturn(false); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_CONFIG_WIFI), any())) - .thenReturn(false); - when(mWifiNative.p2pListNetworks(any())).thenReturn(true); - sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET); - verify(mWifiInjector).getUserManager(); - verify(mPackageManager).getNameForUid(anyInt()); - verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt()); - verify(mUserManager).hasUserRestrictionForUser( - eq(UserManager.DISALLOW_NETWORK_RESET), any()); - verify(mUserManager).hasUserRestrictionForUser(eq(UserManager.DISALLOW_CONFIG_WIFI), any()); - verify(mWifiNative, never()).p2pListNetworks(any()); - verify(mWifiSettingsConfigStore).put(eq(WIFI_P2P_PENDING_FACTORY_RESET), eq(true)); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.FACTORY_RESET_SUCCEEDED, message.what); - - // Move to enabled state - when(mWifiSettingsConfigStore.get(eq(WIFI_P2P_PENDING_FACTORY_RESET))).thenReturn(true); - forceP2pEnabled(mClient1); - verify(mWifiInjector, times(2)).getUserManager(); - verify(mPackageManager, times(2)).getNameForUid(anyInt()); - verify(mWifiPermissionsUtil, times(2)).checkNetworkSettingsPermission(anyInt()); - verify(mUserManager, times(2)).hasUserRestrictionForUser( - eq(UserManager.DISALLOW_NETWORK_RESET), any()); - verify(mUserManager, times(2)).hasUserRestrictionForUser( - eq(UserManager.DISALLOW_CONFIG_WIFI), any()); - verify(mWifiNative, atLeastOnce()).p2pListNetworks(any()); - verify(mWifiSettingsConfigStore).get(eq(WIFI_P2P_PENDING_FACTORY_RESET)); - verify(mWifiSettingsConfigStore).put(eq(WIFI_P2P_PENDING_FACTORY_RESET), eq(false)); - checkSendP2pPersistentGroupsChangedBroadcast(); - } - - /** - * Verify WifiP2pManager.FACTORY_RESET_FAILED is returned without network setting permission. - */ - @Test - public void testFactoryResetFailureWithoutNetworkSettingPermission() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - when(mWifiInjector.getUserManager()).thenReturn(mUserManager); - when(mPackageManager.getNameForUid(anyInt())).thenReturn("testPkg"); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET); - verify(mWifiInjector).getUserManager(); - verify(mPackageManager).getNameForUid(anyInt()); - verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.FACTORY_RESET_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.FACTORY_RESET_FAILED is returned when network reset disallow. - */ - @Test - public void testFactoryResetFailureWhenNetworkResetDisallow() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - when(mWifiInjector.getUserManager()).thenReturn(mUserManager); - when(mPackageManager.getNameForUid(anyInt())).thenReturn("testPkg"); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_NETWORK_RESET), any())) - .thenReturn(true); - sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET); - verify(mWifiInjector).getUserManager(); - verify(mPackageManager).getNameForUid(anyInt()); - verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt()); - verify(mUserManager).hasUserRestrictionForUser( - eq(UserManager.DISALLOW_NETWORK_RESET), any()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.FACTORY_RESET_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.FACTORY_RESET_FAILED is returned when config wifi disallow. - */ - @Test - public void testFactoryResetFailureWhenConfigWifiDisallow() throws Exception { - // Move to enabled state - forceP2pEnabled(mClient1); - - when(mWifiInjector.getUserManager()).thenReturn(mUserManager); - when(mPackageManager.getNameForUid(anyInt())).thenReturn("testPkg"); - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_NETWORK_RESET), any())) - .thenReturn(false); - when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_CONFIG_WIFI), any())) - .thenReturn(true); - sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET); - verify(mWifiInjector).getUserManager(); - verify(mPackageManager).getNameForUid(anyInt()); - verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt()); - verify(mUserManager).hasUserRestrictionForUser( - eq(UserManager.DISALLOW_NETWORK_RESET), any()); - verify(mUserManager).hasUserRestrictionForUser(eq(UserManager.DISALLOW_CONFIG_WIFI), any()); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.FACTORY_RESET_FAILED, message.what); - assertEquals(WifiP2pManager.ERROR, message.arg1); - } - - /** - * Verify WifiP2pManager.FACTORY_RESET_FAILED is returned when p2p is unsupported. - */ - @Test - public void testFactoryResetFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.FACTORY_RESET_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.SET_ONGOING_PEER_CONFIG. - */ - @Test - public void testSetOngingPeerConfigSuccess() throws Exception { - forceP2pEnabled(mClient1); - mockPeersList(); - WifiP2pConfig config = new WifiP2pConfig(); - config.deviceAddress = mTestWifiP2pDevice.deviceAddress; - - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(true); - sendSetOngoingPeerConfigMsg(mClientMessenger, config); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_ONGOING_PEER_CONFIG_SUCCEEDED, message.what); - } - - /** - * Verify WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED is returned without NETWORK_STACK - * permission. - */ - @Test - public void testSetOngingPeerConfigFailureWithoutPermission() throws Exception { - forceP2pEnabled(mClient1); - mockPeersList(); - WifiP2pConfig config = new WifiP2pConfig(); - - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(false); - sendSetOngoingPeerConfigMsg(mClientMessenger, config); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED, message.what); - } - - /** - * Verify WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED is returned with invalid peer config. - */ - @Test - public void testSetOngoingPeerConfigFailureWithInvalidPeerConfig() throws Exception { - forceP2pEnabled(mClient1); - mockPeersList(); - WifiP2pConfig config = new WifiP2pConfig(); - - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(true); - sendSetOngoingPeerConfigMsg(mClientMessenger, config); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED, message.what); - } - - /** - * Verify that respond with RESPONSE_ONGOING_PEER_CONFIG - * when caller sends REQUEST_ONGOING_PEER_CONFIG and permission is granted. - */ - @Test - public void testRequestOngoingPeerConfigSuccess() throws Exception { - forceP2pEnabled(mClient1); - - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(true); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - WifiP2pConfig config = (WifiP2pConfig) message.obj; - assertEquals(WifiP2pManager.RESPONSE_ONGOING_PEER_CONFIG, message.what); - assertNotNull(config); - } - - /** - * Verify that respond with RESPONSE_ONGOING_PEER_CONFIG - * when caller sends REQUEST_ONGOING_PEER_CONFIG and has no NETWORK_STACK permission. - */ - @Test - public void testRequestOngoingPeerConfigFailureWithoutPermission() throws Exception { - forceP2pEnabled(mClient1); - - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(false); - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - WifiP2pConfig config = (WifiP2pConfig) message.obj; - assertEquals(WifiP2pManager.RESPONSE_ONGOING_PEER_CONFIG, message.what); - assertNull(config); - } - - /** - * Verify that respond with RESPONSE_PERSISTENT_GROUP_INFO - * when caller sends REQUEST_PERSISTENT_GROUP_INFO. - */ - @Test - public void testRequestPersistentGroupInfoSuccess() throws Exception { - // Ensure our own MAC address is not anonymized in the result - when(mWifiPermissionsUtil.checkLocalMacAddressPermission(anyInt())).thenReturn(true); - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - WifiP2pGroupList groups = (WifiP2pGroupList) message.obj; - assertEquals(WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, message.what); - // WifiP2pGroupList does not implement equals operator, - // use toString to compare two lists. - assertEquals(mGroups.toString(), groups.toString()); - } - - /** - * Verify that when no permissions are held, an empty {@link WifiP2pGroupList} is returned. - */ - @Test - public void testRequestPersistentGroupInfoNoPermissionFailure() throws Exception { - // Ensure our own MAC address is not anonymized in the result - when(mWifiPermissionsUtil.checkLocalMacAddressPermission(anyInt())).thenReturn(true); - forceP2pEnabled(mClient1); - - // no permissions held - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkReadWifiCredentialPermission(anyInt())).thenReturn(false); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - WifiP2pGroupList groups = (WifiP2pGroupList) message.obj; - assertEquals(WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, message.what); - // WifiP2pGroupList does not implement equals operator, - // use toString to compare two lists. - // Expect empty WifiP2pGroupList() - assertEquals(new WifiP2pGroupList().toString(), groups.toString()); - } - - /** - * Verify that respond with RESPONSE_CONNECTION_INFO - * when caller sends REQUEST_CONNECTION_INFO. - */ - @Test - public void testRequestConnectionInfoSuccess() throws Exception { - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_CONNECTION_INFO); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - WifiP2pInfo info = (WifiP2pInfo) message.obj; - assertEquals(WifiP2pManager.RESPONSE_CONNECTION_INFO, message.what); - // WifiP2pInfo does not implement equals operator, - // use toString to compare two objects. - assertEquals((new WifiP2pInfo()).toString(), info.toString()); - } - - /** - * Verify that respond with RESPONSE_P2P_STATE - * when caller sends REQUEST_P2P_STATE and p2p is enabled. - */ - @Test - public void testRequestP2pStateEnabled() throws Exception { - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_P2P_STATE); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.RESPONSE_P2P_STATE, message.what); - assertEquals(WifiP2pManager.WIFI_P2P_STATE_ENABLED, message.arg1); - } - - /** - * Verify that respond with RESPONSE_P2P_STATE - * when caller sends REQUEST_P2P_STATE and p2p is disabled. - */ - @Test - public void testRequestP2pStateDisabled() throws Exception { - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_P2P_STATE); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.RESPONSE_P2P_STATE, message.what); - assertEquals(WifiP2pManager.WIFI_P2P_STATE_DISABLED, message.arg1); - } - - /** - * Verify that respond with RESPONSE_DISCOVERY_STATE - * when caller sends REQUEST_DISCOVERY_STATE and discovery is started. - */ - @Test - public void testRequestDiscoveryStateWhenStarted() throws Exception { - forceP2pEnabled(mClient1); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(any(), any(), - anyInt(), anyBoolean())).thenReturn(false); - when(mWifiPermissionsUtil.checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), anyBoolean())).thenReturn(true); - when(mWifiNative.p2pFind(anyInt())).thenReturn(true); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - sendDiscoverPeersMsg(mClientMessenger); - verify(mWifiNative).p2pFind(anyInt()); - verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"), - anyInt(), eq(true)); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DISCOVERY_STATE); - - // there are 2 responses: - // * WifiP2pManager.DISCOVER_PEERS_SUCCEEDED - // * WifiP2pManager.RESPONSE_DISCOVERY_STATE - verify(mClientHandler, times(2)).sendMessage(mMessageCaptor.capture()); - List<Message> messages = mMessageCaptor.getAllValues(); - assertEquals(WifiP2pManager.DISCOVER_PEERS_SUCCEEDED, messages.get(0).what); - assertEquals(WifiP2pManager.RESPONSE_DISCOVERY_STATE, messages.get(1).what); - assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED, messages.get(1).arg1); - } - - /** - * Verify that respond with RESPONSE_DISCOVERY_STATE - * when caller sends REQUEST_DISCOVERY_STATE and discovery is stopped. - */ - @Test - public void testRequestDiscoveryStateWhenStopped() throws Exception { - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DISCOVERY_STATE); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.RESPONSE_DISCOVERY_STATE, message.what); - assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED, message.arg1); - } - - /** - * Verify that respond with RESPONSE_NETWORK_INFO - * when caller sends REQUEST_NETWORK_INFO. - */ - @Test - public void testRequestNetworkInfoSuccess() throws Exception { - NetworkInfo info_gold = - new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, "WIFI_P2P", ""); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_NETWORK_INFO); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - NetworkInfo info = (NetworkInfo) message.obj; - assertEquals(WifiP2pManager.RESPONSE_NETWORK_INFO, message.what); - assertEquals(info_gold.toString(), info.toString()); - } - - /** - * Verify the caller sends WifiP2pManager.REMOVE_LOCAL_SERVICE. - */ - @Test - public void testRemoveLocalServiceSuccess() throws Exception { - forceP2pEnabled(mClient1); - testAddLocalServiceSuccess(); - - sendRemoveLocalServiceMsg(mClientMessenger, mTestWifiP2pServiceInfo); - verify(mWifiNative).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED)); - } - - /** - * Verify the caller sends WifiP2pManager.REMOVE_LOCAL_SERVICE without client info. - */ - @Test - public void testRemoveLocalServiceSuccessWithoutClientInfo() throws Exception { - forceP2pEnabled(mClient1); - - sendRemoveLocalServiceMsg(mClientMessenger, mTestWifiP2pServiceInfo); - verify(mWifiNative, never()).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED)); - } - - /** - * Verify the caller sends WifiP2pManager.REMOVE_LOCAL_SERVICE when service info is null. - */ - @Test - public void testRemoveLocalServiceSuccessWithNullServiceInfo() throws Exception { - forceP2pEnabled(mClient1); - testAddLocalServiceSuccess(); - - sendRemoveLocalServiceMsg(mClientMessenger, null); - verify(mWifiNative, never()).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED)); - } - - /** - * Verify that respond with REMOVE_LOCAL_SERVICE_FAILED - * when caller sends REMOVE_LOCAL_SERVICE and p2p is disabled. - */ - @Test - public void testRemoveLocalServiceFailureWhenP2pDisabled() throws Exception { - sendRemoveLocalServiceMsg(mClientMessenger, null); - verify(mWifiNative, never()).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify that respond with REMOVE_LOCAL_SERVICE_FAILED - * when caller sends REMOVE_LOCAL_SERVICE and p2p is unsupported. - */ - @Test - public void testRemoveLocalServiceFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - - sendRemoveLocalServiceMsg(mClientMessenger, null); - verify(mWifiNative, never()).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.CLEAR_LOCAL_SERVICES. - */ - @Test - public void testClearLocalServiceSuccess() throws Exception { - forceP2pEnabled(mClient1); - testAddLocalServiceSuccess(); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CLEAR_LOCAL_SERVICES); - verify(mWifiNative, atLeastOnce()).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED)); - } - - /** - * Verify the caller sends WifiP2pManager.CLEAR_LOCAL_SERVICES without client info. - */ - @Test - public void testClearLocalServiceSuccessWithoutClientInfo() throws Exception { - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CLEAR_LOCAL_SERVICES); - verify(mWifiNative, never()).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED)); - } - - /** - * Verify that respond with CLEAR_LOCAL_SERVICES_FAILED - * when caller sends CLEAR_LOCAL_SERVICES and p2p is disabled. - */ - @Test - public void testClearLocalServiceFailureWhenP2pDisabled() throws Exception { - sendSimpleMsg(mClientMessenger, WifiP2pManager.CLEAR_LOCAL_SERVICES); - verify(mWifiNative, never()).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify that respond with CLEAR_LOCAL_SERVICES_FAILED - * when caller sends CLEAR_LOCAL_SERVICES and p2p is unsupported. - */ - @Test - public void testClearLocalServiceFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CLEAR_LOCAL_SERVICES); - verify(mWifiNative, never()).p2pServiceDel(any(WifiP2pServiceInfo.class)); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.ADD_SERVICE_REQUEST without services discover. - */ - @Test - public void testAddServiceRequestSuccessWithoutServiceDiscover() throws Exception { - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - sendAddServiceRequestMsg(mClientMessenger); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED)); - } - - /** - * Verify the caller sends WifiP2pManager.ADD_SERVICE_REQUEST with services discover. - */ - @Test - public void testAddServiceRequestSuccessWithServiceDiscover() throws Exception { - testDiscoverServicesSuccess(); - - sendAddServiceRequestMsg(mClientMessenger); - verify(mWifiNative, atLeastOnce()).p2pServDiscReq(eq("00:00:00:00:00:00"), anyString()); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED)); - } - - /** - * Verify WifiP2pManager.ADD_SERVICE_REQUEST_FAILED is returned with null request. - */ - @Test - public void testAddServiceRequestFailureWithNullRequest() throws Exception { - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.ADD_SERVICE_REQUEST); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_SERVICE_REQUEST_FAILED)); - } - - /** - * Verify WifiP2pManager.ADD_SERVICE_REQUEST_FAILED is returned without client info. - */ - @Test - public void testAddServiceRequestFailureWithoutClientInfo() throws Exception { - forceP2pEnabled(mClient1); - - sendAddServiceRequestMsg(mClientMessenger); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.ADD_SERVICE_REQUEST_FAILED)); - } - - /** - * Verify that respond with ADD_SERVICE_REQUEST_FAILED - * when caller sends ADD_SERVICE_REQUEST and p2p is disabled. - */ - @Test - public void testAddServiceRequestFailureWhenP2pDisabled() throws Exception { - sendAddServiceRequestMsg(mClientMessenger); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.ADD_SERVICE_REQUEST_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify that respond with ADD_SERVICE_REQUEST_FAILED - * when caller sends ADD_SERVICE_REQUEST and p2p is unsupported. - */ - @Test - public void testAddServiceRequestFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - - sendAddServiceRequestMsg(mClientMessenger); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.ADD_SERVICE_REQUEST_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.REMOVE_SERVICE_REQUEST. - */ - @Test - public void testRemoveServiceRequestSuccess() throws Exception { - forceP2pEnabled(mClient1); - testAddServiceRequestSuccessWithoutServiceDiscover(); - - sendRemoveServiceRequestMsg(mClientMessenger, mTestWifiP2pServiceRequest); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED)); - } - - /** - * Verify the caller sends WifiP2pManager.REMOVE_SERVICE_REQUEST without client info. - */ - @Test - public void testRemoveServiceRequestSuccessWithoutClientInfo() throws Exception { - forceP2pEnabled(mClient1); - - sendRemoveServiceRequestMsg(mClientMessenger, mTestWifiP2pServiceRequest); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED)); - } - - /** - * Verify the caller sends WifiP2pManager.REMOVE_SERVICE_REQUEST when service info is null. - */ - @Test - public void testRemoveServiceRequestSuccessWithNullServiceInfo() throws Exception { - forceP2pEnabled(mClient1); - testAddLocalServiceSuccess(); - - sendRemoveServiceRequestMsg(mClientMessenger, null); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED)); - } - - /** - * Verify that respond with REMOVE_SERVICE_REQUEST_FAILED - * when caller sends REMOVE_SERVICE_REQUEST and p2p is disabled. - */ - @Test - public void testRemoveServiceRequestFailureWhenP2pDisabled() throws Exception { - sendRemoveServiceRequestMsg(mClientMessenger, null); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify that respond with REMOVE_SERVICE_REQUEST_FAILED - * when caller sends REMOVE_SERVICE_REQUEST and p2p is unsupported. - */ - @Test - public void testRemoveServiceRequestFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - - sendRemoveServiceRequestMsg(mClientMessenger, null); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify the caller sends WifiP2pManager.CLEAR_SERVICE_REQUESTS. - */ - @Test - public void testClearServiceRequestsSuccess() throws Exception { - forceP2pEnabled(mClient1); - testAddServiceRequestSuccessWithoutServiceDiscover(); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CLEAR_SERVICE_REQUESTS); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED)); - } - - /** - * Verify the caller sends WifiP2pManager.CLEAR_SERVICE_REQUESTS without client info. - */ - @Test - public void testClearServiceRequestsSuccessWithoutClientInfo() throws Exception { - forceP2pEnabled(mClient1); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CLEAR_SERVICE_REQUESTS); - - assertTrue(mClientHandler.hasMessages(WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED)); - } - - /** - * Verify that respond with CLEAR_SERVICE_REQUESTS_FAILED - * when caller sends CLEAR_SERVICE_REQUEST and p2p is disabled. - */ - @Test - public void testClearServiceRequestsFailureWhenP2pDisabled() throws Exception { - sendSimpleMsg(mClientMessenger, WifiP2pManager.CLEAR_SERVICE_REQUESTS); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED, message.what); - assertEquals(WifiP2pManager.BUSY, message.arg1); - } - - /** - * Verify that respond with CLEAR_SERVICE_REQUESTS_FAILED - * when caller sends CLEAR_SERVICE_REQUEST and p2p is unsupported. - */ - @Test - public void testClearServiceRequestsFailureWhenP2pUnsupported() throws Exception { - setUpWifiP2pServiceImpl(false); - - sendSimpleMsg(mClientMessenger, WifiP2pManager.CLEAR_SERVICE_REQUESTS); - - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED, message.what); - assertEquals(WifiP2pManager.P2P_UNSUPPORTED, message.arg1); - } - - /** - * Verify stopping discovery is executed when location mode is turned off. - */ - @Test - public void testStopDiscoveryWhenLocationModeIsDisabled() throws Exception { - forceP2pEnabled(mClient1); - simulateLocationModeChange(false); - mLooper.dispatchAll(); - verify(mWifiNative).p2pStopFind(); - } - - /** - * Verify a network name which is too long is rejected. - */ - @Test - public void testSendConnectMsgWithTooLongNetworkName() throws Exception { - mTestWifiP2pFastConnectionConfig.networkName = "DIRECT-xy-abcdefghijklmnopqrstuvw"; - sendConnectMsg(mClientMessenger, mTestWifiP2pFastConnectionConfig); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CONNECT_FAILED, message.what); - } - - /** - * Verify a network name which is too short is rejected. - */ - @Test - public void testSendConnectMsgWithTooShortNetworkName() throws Exception { - mTestWifiP2pFastConnectionConfig.networkName = "DIRECT-x"; - sendConnectMsg(mClientMessenger, mTestWifiP2pFastConnectionConfig); - verify(mClientHandler).sendMessage(mMessageCaptor.capture()); - Message message = mMessageCaptor.getValue(); - assertEquals(WifiP2pManager.CONNECT_FAILED, message.what); - } - - /** - * Verify the group owner intent value is selected correctly when no STA connection. - */ - @Test - public void testGroupOwnerIntentSelectionWithoutStaConnection() throws Exception { - when(mWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID); - when(mWifiInfo.getFrequency()).thenReturn(2412); - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterProvisionDiscoveryState(); - - WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent(); - pdEvent.device = mTestWifiP2pDevice; - sendSimpleMsg(null, - WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT, - pdEvent); - - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mWifiNative).p2pConnect(configCaptor.capture(), anyBoolean()); - WifiP2pConfig config = configCaptor.getValue(); - assertEquals(WifiP2pServiceImpl.DEFAULT_GROUP_OWNER_INTENT + 1, - config.groupOwnerIntent); - } - - /** - * Verify the group owner intent value is selected correctly when 2.4GHz STA connection. - */ - @Test - public void testGroupOwnerIntentSelectionWith24GStaConnection() throws Exception { - when(mWifiInfo.getNetworkId()).thenReturn(1); - when(mWifiInfo.getFrequency()).thenReturn(2412); - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterProvisionDiscoveryState(); - - WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent(); - pdEvent.device = mTestWifiP2pDevice; - sendSimpleMsg(null, - WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT, - pdEvent); - - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mWifiNative).p2pConnect(configCaptor.capture(), anyBoolean()); - WifiP2pConfig config = configCaptor.getValue(); - assertEquals(WifiP2pConfig.GROUP_OWNER_INTENT_MIN, - config.groupOwnerIntent); - } - - /** - * Verify the group owner intent value is selected correctly when 5GHz STA connection. - */ - @Test - public void testGroupOwnerIntentSelectionWith5GHzStaConnection() throws Exception { - when(mWifiInfo.getNetworkId()).thenReturn(1); - when(mWifiInfo.getFrequency()).thenReturn(5200); - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterProvisionDiscoveryState(); - - WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent(); - pdEvent.device = mTestWifiP2pDevice; - sendSimpleMsg(null, - WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT, - pdEvent); - - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mWifiNative).p2pConnect(configCaptor.capture(), anyBoolean()); - WifiP2pConfig config = configCaptor.getValue(); - assertEquals(WifiP2pConfig.GROUP_OWNER_INTENT_MAX - 1, - config.groupOwnerIntent); - } - - /** - * Verify the group owner intent value is selected correctly when 6GHz STA connection. - */ - @Test - public void testGroupOwnerIntentSelectionWith6GHzStaConnection() throws Exception { - when(mWifiInfo.getNetworkId()).thenReturn(1); - when(mWifiInfo.getFrequency()).thenReturn(6000); - forceP2pEnabled(mClient1); - sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger); - - mockEnterProvisionDiscoveryState(); - - WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent(); - pdEvent.device = mTestWifiP2pDevice; - sendSimpleMsg(null, - WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT, - pdEvent); - - ArgumentCaptor<WifiP2pConfig> configCaptor = - ArgumentCaptor.forClass(WifiP2pConfig.class); - verify(mWifiNative).p2pConnect(configCaptor.capture(), anyBoolean()); - WifiP2pConfig config = configCaptor.getValue(); - assertEquals(WifiP2pServiceImpl.DEFAULT_GROUP_OWNER_INTENT, - config.groupOwnerIntent); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/rtt/RttMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/rtt/RttMetricsTest.java deleted file mode 100644 index 937585610..000000000 --- a/tests/wifitests/src/com/android/server/wifi/rtt/RttMetricsTest.java +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.rtt; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.Mockito.when; - -import android.net.MacAddress; -import android.net.wifi.rtt.RangingRequest; -import android.net.wifi.rtt.RangingResult; -import android.net.wifi.rtt.ResponderConfig; -import android.os.WorkSource; -import android.util.Log; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.proto.nano.WifiMetricsProto; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; - -/** - * Unit test harness for RttMetrics - */ -@SmallTest -public class RttMetricsTest extends WifiBaseTest { - private RttMetrics mDut; - - @Mock - Clock mClock; - - @Rule - public ErrorCollector collector = new ErrorCollector(); - - /** - * Pre-test configuration. Initialize and install mocks. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - setTime(1); - mDut = new RttMetrics(mClock); - } - - /** - * Verify that recordRequest() records valid metrics. - */ - @Test - public void testRecordRequest() { - WifiMetricsProto.WifiRttLog log; - - // no requests - log = mDut.consolidateProto(); - checkMainStats("No requests", log, 0, 0, 0, 0); - checkPeerStats("No requests: AP", log.rttToAp, 0, 0, 0, 0, 0, 0, 0, 0); - checkPeerStats("No requests: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0); - - // multiple AP requests from multiple sources - WorkSource ws1 = new WorkSource(10); - WorkSource ws2 = new WorkSource(20); - ws2.add(10); - - RangingRequest requestAp1 = getDummyRangingRequest(1, 0); - RangingRequest requestAp2 = getDummyRangingRequest(2, 0); - RangingRequest requestAp5 = getDummyRangingRequest(5, 0); - RangingRequest requestAp6 = getDummyRangingRequest(6, 0); - - mDut.clear(); - mDut.recordRequest(ws1, requestAp1); - setTime(10); // delta = 9 - mDut.recordRequest(ws1, requestAp2); - setTime(20); // delta = 10 - mDut.recordRequest(ws1, requestAp5); - setTime(21); // delta = 1 - mDut.recordRequest(ws1, requestAp6); - setTime(1000); // delta = 979 - mDut.recordRequest(ws1, requestAp5); - setTime(5000); // delta = 4,000 - mDut.recordRequest(ws1, requestAp5); - setTime(1000000); // delta = 995,000 - mDut.recordRequest(ws1, requestAp2); - mDut.recordRequest(ws2, requestAp5); - mDut.recordRequest(ws2, requestAp5); - mDut.recordRequest(ws2, requestAp5); - - log = mDut.consolidateProto(); - checkMainStats("Sequence AP-only", log, 10, 0, 0, 0); - - checkPeerStats("Sequence AP-only: AP", log.rttToAp, 10, 41, 2, 2, 4, 0, 0, 5); - - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumRequestsPerApp[0]", - log.rttToAp.histogramNumRequestsPerApp[0], 1, 10, 1); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumRequestsPerApp[1]", - log.rttToAp.histogramNumRequestsPerApp[1], 10, 100, 1); - - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[0]", - log.rttToAp.histogramNumPeersPerRequest[0], 1, 1, 1); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[1]", - log.rttToAp.histogramNumPeersPerRequest[1], 2, 2, 2); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[2]", - log.rttToAp.histogramNumPeersPerRequest[2], 5, 5, 6); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[3]", - log.rttToAp.histogramNumPeersPerRequest[3], 6, 6, 1); - - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[0]", - log.rttToAp.histogramRequestIntervalMs[0], 1, 10, 5); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[1]", - log.rttToAp.histogramRequestIntervalMs[1], 10, 100, 1); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[2]", - log.rttToAp.histogramRequestIntervalMs[2], 100, 1000, 1); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[3]", - log.rttToAp.histogramRequestIntervalMs[3], 1000, 10000, 1); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[4]", - log.rttToAp.histogramRequestIntervalMs[4], 100000, 1000000, 1); - - checkPeerStats("Sequence AP-only: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0); - - // mix of AP and Aware requests - WorkSource ws3 = new WorkSource(30); - ws3.add(20); - ws3.add(40); - - RangingRequest requestMixed03 = getDummyRangingRequest(0, 3); - RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); - RangingRequest requestMixed50 = getDummyRangingRequest(5, 0); - RangingRequest requestMixed08 = getDummyRangingRequest(0, 8); - - mDut.clear(); - setTime(100); - mDut.recordRequest(ws3, requestMixed03); - setTime(101); - mDut.recordRequest(ws3, requestMixed25); - setTime(102); - mDut.recordRequest(ws3, requestMixed50); - setTime(103); - mDut.recordRequest(ws3, requestMixed08); - - log = mDut.consolidateProto(); - checkMainStats("Sequence Mixed AP/Aware", log, 4, 0, 0, 0); - - checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 2, 7, 3, 1, 2, 0, 0, 1); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumRequestsPerApp[0]", - log.rttToAp.histogramNumRequestsPerApp[0], 1, 10, 3); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumPeersPerRequest[0]", - log.rttToAp.histogramNumPeersPerRequest[0], 2, 2, 1); - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumPeersPerRequest[1]", - log.rttToAp.histogramNumPeersPerRequest[1], 5, 5, 1); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramRequestIntervalMs[0]", - log.rttToAp.histogramRequestIntervalMs[0], 1, 10, 1); - - checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 3, 16, 3, 1, 3, 0, 0, 1); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramNumRequestsPerApp[0]", - log.rttToAware.histogramNumRequestsPerApp[0], 1, 10, 3); - - validateProtoHistBucket( - "Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[0]", - log.rttToAware.histogramNumPeersPerRequest[0], 3, 3, 1); - validateProtoHistBucket( - "Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[1]", - log.rttToAware.histogramNumPeersPerRequest[1], 5, 5, 1); - validateProtoHistBucket( - "Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[2]", - log.rttToAware.histogramNumPeersPerRequest[2], 8, 8, 1); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramRequestIntervalMs[0]", - log.rttToAware.histogramRequestIntervalMs[0], 1, 10, 2); - } - - /** - * Verify that recordResult() records valid metrics. - */ - @Test - public void testRecordResult() { - WifiMetricsProto.WifiRttLog log; - - // no requests - log = mDut.consolidateProto(); - checkMainStats("No requests", log, 0, 0, 0, 0); - checkPeerStats("No requests: AP", log.rttToAp, 0, 0, 0, 0, 0, 0, 0, 0); - checkPeerStats("No requests: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0); - - // multiple AP results - RangingRequest requestAp1 = getDummyRangingRequest(1, 0); - RangingRequest requestAp2 = getDummyRangingRequest(2, 0); - RangingRequest requestAp5 = getDummyRangingRequest(5, 0); - RangingRequest requestAp6 = getDummyRangingRequest(6, 0); - - mDut.clear(); - mDut.recordResult(requestAp1, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, - requestAp1, 5, 0), 500); - mDut.recordResult(requestAp2, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, - requestAp2, 10, 30), 1500); - mDut.recordResult(requestAp5, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, - requestAp5, 0.3, -0.2), 700); - mDut.recordResult(requestAp6, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, - requestAp6, 40, 30), 1800); - log = mDut.consolidateProto(); - - checkMainStats("Sequence AP-only", log, 0, 0, 2, 0); - checkPeerStats("Sequence AP-only: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 6, 0); - - validateProtoHistBucket("Sequence AP-only: histogramMeasurementDurationApOnly[0]", - log.histogramMeasurementDurationApOnly[0], Integer.MIN_VALUE, 1 * 1000, 2); - validateProtoHistBucket("Sequence AP-only: histogramMeasurementDurationApOnly[1]", - log.histogramMeasurementDurationApOnly[1], 1 * 1000, 2 * 1000, 2); - - validateProtoIndividualStatusHistBucket( - "Sequence AP-only: rttToAp.histogramIndividualStatus[0]", - log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 14); - - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[0]", - log.rttToAp.histogramDistance[0], Integer.MIN_VALUE, 0, 3); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[1]", - log.rttToAp.histogramDistance[1], 0, 5 * 1000, 2); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[2]", - log.rttToAp.histogramDistance[2], 5 * 1000, 15 * 1000, 2); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[3]", - log.rttToAp.histogramDistance[3], 30 * 1000, 60 * 1000, 2); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[4]", - log.rttToAp.histogramDistance[4], 60 * 1000, 100 * 1000, 1); - validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[5]", - log.rttToAp.histogramDistance[5], 100 * 1000, Integer.MAX_VALUE, 4); - - checkPeerStats("Sequence AP-only: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0); - - // mix of AP and Aware requests - RangingRequest requestMixed03 = getDummyRangingRequest(0, 3); - RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); - RangingRequest requestMixed50 = getDummyRangingRequest(5, 0); - RangingRequest requestMixed08 = getDummyRangingRequest(0, 8); - - mDut.clear(); - mDut.recordResult(requestMixed03, getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed03, 5, 0), 6400); - mDut.recordResult(requestMixed25, getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30), 7800); - mDut.recordResult(requestMixed50, getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed50, 0.3, -0.2), 3100); - mDut.recordResult(requestMixed08, getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed08, 40, 30), 9500); - log = mDut.consolidateProto(); - - checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 1, 2); - - checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 4, 0); - - validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationApOnly[0]", - log.histogramMeasurementDurationApOnly[0], 3 * 1000, 4 * 1000, 1); - validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationWithAware[0]", - log.histogramMeasurementDurationWithAware[0], 6 * 1000, 8 * 1000, 2); - validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationWithAware[1]", - log.histogramMeasurementDurationWithAware[1], 8 * 1000, Integer.MAX_VALUE, 1); - - validateProtoIndividualStatusHistBucket( - "Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[0]", - log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 7); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[0]", - log.rttToAp.histogramDistance[0], Integer.MIN_VALUE, 0, 3); - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[1]", - log.rttToAp.histogramDistance[1], 0, 5 * 1000, 2); - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[2]", - log.rttToAp.histogramDistance[2], 5 * 1000, 15 * 1000, 1); - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[3]", - log.rttToAp.histogramDistance[3], 30 * 1000, 60 * 1000, 1); - - checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 1, 4, 0); - - validateProtoIndividualStatusHistBucket( - "Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]", - log.rttToAware.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, - 16); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[0]", - log.rttToAware.histogramDistance[0], 5 * 1000, 15 * 1000, 3); - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[1]", - log.rttToAware.histogramDistance[1], 30 * 1000, 60 * 1000, 1); - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[2]", - log.rttToAware.histogramDistance[2], 60 * 1000, 100 * 1000, 2); - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[3]", - log.rttToAware.histogramDistance[3], 100 * 1000, Integer.MAX_VALUE, 10); - } - - /** - * Verify the behavior when the HAL returns with missing results or some results set to null. - */ - @Test - public void testRecordMissingResults() { - WifiMetricsProto.WifiRttLog log; - - mDut.clear(); - RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); - List<RangingResult> resultMixed25 = getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30); - // remove some results - resultMixed25.remove(3); // Second Aware result: distance = 100 - resultMixed25.remove(0); // First AP result: distance = 10 - resultMixed25.add(null); - mDut.recordResult(requestMixed25, resultMixed25, 0); - - log = mDut.consolidateProto(); - - checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 0, 1); - - checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 2, 1, 0); - - validateProtoIndividualStatusHistBucket( - "Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[0]", - log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 1); - validateProtoIndividualStatusHistBucket( - "Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[1]", - log.rttToAp.histogramIndividualStatus[1], - WifiMetricsProto.WifiRttLog.MISSING_RESULT, 1); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[0]", - log.rttToAp.histogramDistance[0], 30 * 1000, 60 * 1000, 1); - - checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 2, 2, 0); - - validateProtoIndividualStatusHistBucket( - "Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]", - log.rttToAware.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, - 4); - validateProtoIndividualStatusHistBucket( - "Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[1]", - log.rttToAware.histogramIndividualStatus[1], - WifiMetricsProto.WifiRttLog.MISSING_RESULT, 1); - - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[0]", - log.rttToAware.histogramDistance[0], 60 * 1000, 100 * 1000, 1); - validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[1]", - log.rttToAware.histogramDistance[1], 100 * 1000, Integer.MAX_VALUE, 3); - } - - /** - * Verify the behavior when the HAL returns with NULL array. - */ - @Test - public void testRecordNullArrayResults() { - WifiMetricsProto.WifiRttLog log; - - mDut.clear(); - RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); - mDut.recordResult(requestMixed25, null, 0); - - log = mDut.consolidateProto(); - - checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 0, 0); - - checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 0, 0); - - validateProtoIndividualStatusHistBucket( - "Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[1]", - log.rttToAp.histogramIndividualStatus[0], - WifiMetricsProto.WifiRttLog.MISSING_RESULT, 2); - - checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 1, 0, 0); - - validateProtoIndividualStatusHistBucket( - "Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]", - log.rttToAware.histogramIndividualStatus[0], - WifiMetricsProto.WifiRttLog.MISSING_RESULT, 5); - } - - /** - * Verify that all individual status codes are translated correctly. - */ - @Test - public void testRecordResultsStatuses() { - WifiMetricsProto.WifiRttLog log; - - mDut.clear(); - - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, 5); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAILURE, 6); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, 7); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_REJECTED, 8); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, 9); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, 10); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, 11); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, 12); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_ABORTED, 13); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, 14); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, 15); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, 16); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, 17); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_INVALID_REQ, 18); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_NO_WIFI, 19); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE, 20); - - log = mDut.consolidateProto(); - - collector.checkThat("AP histogramIndividualStatus.length", - log.rttToAp.histogramIndividualStatus.length, equalTo(16)); - - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[0]", - log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 5); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[1]", - log.rttToAp.histogramIndividualStatus[1], WifiMetricsProto.WifiRttLog.FAILURE, 6); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[2]", - log.rttToAp.histogramIndividualStatus[2], WifiMetricsProto.WifiRttLog.FAIL_NO_RSP, - 7); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[3]", - log.rttToAp.histogramIndividualStatus[3], WifiMetricsProto.WifiRttLog.FAIL_REJECTED, - 8); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[4]", - log.rttToAp.histogramIndividualStatus[4], - WifiMetricsProto.WifiRttLog.FAIL_NOT_SCHEDULED_YET, 9); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[5]", - log.rttToAp.histogramIndividualStatus[5], - WifiMetricsProto.WifiRttLog.FAIL_TM_TIMEOUT, 10); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[6]", - log.rttToAp.histogramIndividualStatus[6], - WifiMetricsProto.WifiRttLog.FAIL_AP_ON_DIFF_CHANNEL, 11); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[7]", - log.rttToAp.histogramIndividualStatus[7], - WifiMetricsProto.WifiRttLog.FAIL_NO_CAPABILITY, 12); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[8]", - log.rttToAp.histogramIndividualStatus[8], WifiMetricsProto.WifiRttLog.ABORTED, 13); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[9]", - log.rttToAp.histogramIndividualStatus[9], - WifiMetricsProto.WifiRttLog.FAIL_INVALID_TS, 14); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[10]", - log.rttToAp.histogramIndividualStatus[10], - WifiMetricsProto.WifiRttLog.FAIL_PROTOCOL, 15); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[11]", - log.rttToAp.histogramIndividualStatus[11], - WifiMetricsProto.WifiRttLog.FAIL_SCHEDULE, 16); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[12]", - log.rttToAp.histogramIndividualStatus[12], - WifiMetricsProto.WifiRttLog.FAIL_BUSY_TRY_LATER, 17); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[13]", - log.rttToAp.histogramIndividualStatus[13], WifiMetricsProto.WifiRttLog.INVALID_REQ, - 18); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[14]", - log.rttToAp.histogramIndividualStatus[14], WifiMetricsProto.WifiRttLog.NO_WIFI, 19); - validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[15]", - log.rttToAp.histogramIndividualStatus[15], - WifiMetricsProto.WifiRttLog.FAIL_FTM_PARAM_OVERRIDE, 20); - - collector.checkThat("Aware histogramIndividualStatus.length", - log.rttToAware.histogramIndividualStatus.length, equalTo(0)); - } - - /** - * Verify that all overall status codes are recorded correctly. - */ - @Test - public void testRecordOverallStatus() { - WifiMetricsProto.WifiRttLog log; - - mDut.clear(); - - recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS, 5); - recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_FAIL, 6); - recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE, 7); - recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT, 8); - recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE, 9); - recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE, 10); - recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_AWARE_TRANSLATION_FAILURE, - 11); - recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING, - 12); - - log = mDut.consolidateProto(); - - collector.checkThat("histogramOverallStatus.length", log.histogramOverallStatus.length, - equalTo(8)); - - validateProtoOverallStatusHistBucket("histogramOverallStatus[0]", - log.histogramOverallStatus[0], WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS, 5); - validateProtoOverallStatusHistBucket("histogramOverallStatus[1]", - log.histogramOverallStatus[1], WifiMetricsProto.WifiRttLog.OVERALL_FAIL, 6); - validateProtoOverallStatusHistBucket("histogramOverallStatus[2]", - log.histogramOverallStatus[2], - WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE, 7); - validateProtoOverallStatusHistBucket("histogramOverallStatus[3]", - log.histogramOverallStatus[3], WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT, 8); - validateProtoOverallStatusHistBucket("histogramOverallStatus[4]", - log.histogramOverallStatus[4], WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE, 9); - validateProtoOverallStatusHistBucket("histogramOverallStatus[5]", - log.histogramOverallStatus[5], WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE, 10); - validateProtoOverallStatusHistBucket("histogramOverallStatus[6]", - log.histogramOverallStatus[6], - WifiMetricsProto.WifiRttLog.OVERALL_AWARE_TRANSLATION_FAILURE, 11); - validateProtoOverallStatusHistBucket("histogramOverallStatus[7]", - log.histogramOverallStatus[7], - WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING, 12); - } - - // Utilities - - /** - * Mock the elapsed time since boot to the input argument. - */ - private void setTime(long timeMs) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); - } - - private void validateProtoHistBucket(String logPrefix, - WifiMetricsProto.WifiRttLog.HistogramBucket bucket, long start, long end, int count) { - collector.checkThat(logPrefix + ": start", bucket.start, equalTo(start)); - collector.checkThat(logPrefix + ": end", bucket.end, equalTo(end)); - collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count)); - } - - private void validateProtoOverallStatusHistBucket(String logPrefix, - WifiMetricsProto.WifiRttLog.RttOverallStatusHistogramBucket bucket, int status, - int count) { - collector.checkThat(logPrefix + ": statusType", bucket.statusType, equalTo(status)); - collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count)); - } - - private void validateProtoIndividualStatusHistBucket(String logPrefix, - WifiMetricsProto.WifiRttLog.RttIndividualStatusHistogramBucket bucket, int status, - int count) { - collector.checkThat(logPrefix + ": statusType", bucket.statusType, equalTo(status)); - collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count)); - } - - private void checkMainStats(String msgPrefix, WifiMetricsProto.WifiRttLog log, int numRequests, - int histogramOverallStatusLength, int histogramMeasurementDurationApOnlyLength, - int histogramMeasurementDurationWithAwareLength) { - collector.checkThat(msgPrefix + ": numRequests", log.numRequests, equalTo(numRequests)); - collector.checkThat(msgPrefix + ": histogramOverallStatus.length", - log.histogramOverallStatus.length, - equalTo(histogramOverallStatusLength)); - collector.checkThat(msgPrefix + ": histogramMeasurementDurationApOnly.length", - log.histogramMeasurementDurationApOnly.length, - equalTo(histogramMeasurementDurationApOnlyLength)); - collector.checkThat(msgPrefix + ": histogramMeasurementDurationWithAware.length", - log.histogramMeasurementDurationWithAware.length, - equalTo(histogramMeasurementDurationWithAwareLength)); - } - - private void checkPeerStats(String msgPrefix, WifiMetricsProto.WifiRttLog.RttToPeerLog log, - int numRequests, int numIndividualRequests, - int numApps, int histogramNumRequestsPerAppLength, - int histogramNumPeersPerRequestLength, int histogramIndividualStatusLength, - int histogramDistanceLength, int histogramRequestIntervalMsLength) { - collector.checkThat(msgPrefix + ": numRequests", log.numRequests, equalTo(numRequests)); - collector.checkThat(msgPrefix + ": numIndividualRequests", log.numIndividualRequests, - equalTo(numIndividualRequests)); - collector.checkThat(msgPrefix + ": numApps", log.numApps, equalTo(numApps)); - collector.checkThat(msgPrefix + ": histogramNumRequestsPerApp.length", - log.histogramNumRequestsPerApp.length, equalTo(histogramNumRequestsPerAppLength)); - collector.checkThat(msgPrefix + ": histogramNumPeersPerRequest.length", - log.histogramNumPeersPerRequest.length, equalTo(histogramNumPeersPerRequestLength)); - collector.checkThat(msgPrefix + ": histogramIndividualStatus.length", - log.histogramIndividualStatus.length, equalTo(histogramIndividualStatusLength)); - collector.checkThat(msgPrefix + ": histogramDistance.length", - log.histogramDistance.length, equalTo(histogramDistanceLength)); - collector.checkThat(msgPrefix + ": histogramRequestIntervalMs.length", - log.histogramRequestIntervalMs.length, equalTo(histogramRequestIntervalMsLength)); - } - - private RangingRequest getDummyRangingRequest(int countAp, int countAware) { - RangingRequest.Builder builder = new RangingRequest.Builder(); - byte[] dummyMacBase = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5}; - - for (int i = 0; i < countAp; ++i) { - dummyMacBase[0]++; - builder.addResponder(new ResponderConfig(MacAddress.fromBytes(dummyMacBase), - ResponderConfig.RESPONDER_AP, true, 0, 0, 0, 0, 0)); - } - for (int i = 0; i < countAware; ++i) { - dummyMacBase[0]++; - builder.addResponder(new ResponderConfig(MacAddress.fromBytes(dummyMacBase), - ResponderConfig.RESPONDER_AWARE, true, 0, 0, 0, 0, 0)); - } - - return builder.build(); - } - - private List<RangingResult> getDummyRangingResults(int status, RangingRequest request, - double baseDistanceM, double incrDistanceM) { - List<RangingResult> rangingResults = new ArrayList<>(); - double distance = baseDistanceM; - - for (ResponderConfig peer : request.mRttPeers) { - - RangingResult rttResult = new RangingResult(status, peer.macAddress, - (int) (distance * 1000), 0, 0, 8, 8, null, null, null, 0); - distance += incrDistanceM; - rangingResults.add(rttResult); - } - - return rangingResults; - } - - private void recordResultNTimes(int status, int n) { - RangingRequest request = getDummyRangingRequest(1, 0); - List<RangingResult> results = getDummyRangingResults(status, request, 0, 0); - - for (int i = 0; i < n; ++i) { - mDut.recordResult(request, results, 0); - } - } - - private void recordOverallStatusNTimes(int status, int n) { - for (int i = 0; i < n; ++i) { - mDut.recordOverallStatus(status); - } - } - - private void dumpDut(String prefix) { - StringWriter sw = new StringWriter(); - mDut.dump(null, new PrintWriter(sw), null); - Log.e("RttMetrics", prefix + sw.toString()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java b/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java deleted file mode 100644 index d57857d64..000000000 --- a/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.rtt; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.hardware.wifi.V1_0.IWifiRttController; -import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback; -import android.hardware.wifi.V1_0.RttBw; -import android.hardware.wifi.V1_0.RttCapabilities; -import android.hardware.wifi.V1_0.RttConfig; -import android.hardware.wifi.V1_0.RttPeerType; -import android.hardware.wifi.V1_0.RttPreamble; -import android.hardware.wifi.V1_0.RttResult; -import android.hardware.wifi.V1_0.RttStatus; -import android.hardware.wifi.V1_0.RttType; -import android.hardware.wifi.V1_0.WifiChannelWidthInMhz; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.net.MacAddress; -import android.net.wifi.rtt.RangingRequest; -import android.net.wifi.rtt.RangingResult; -import android.net.wifi.rtt.ResponderConfig; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.WifiBaseTest; - -import org.hamcrest.core.IsNull; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; - -/** - * Unit test harness for the RttNative class. - */ -@SmallTest -public class RttNativeTest extends WifiBaseTest { - private RttNative mDut; - private WifiStatus mStatusSuccess; - - private ArgumentCaptor<ArrayList> mRttConfigCaptor = ArgumentCaptor.forClass(ArrayList.class); - private ArgumentCaptor<List> mRttResultCaptor = ArgumentCaptor.forClass(List.class); - private ArgumentCaptor<HalDeviceManager.ManagerStatusListener> mHdmStatusListener = - ArgumentCaptor.forClass(HalDeviceManager.ManagerStatusListener.class); - private ArgumentCaptor<HalDeviceManager.InterfaceRttControllerLifecycleCallback> - mRttLifecycleCbCaptor = ArgumentCaptor.forClass( - HalDeviceManager.InterfaceRttControllerLifecycleCallback.class); - private ArgumentCaptor<IWifiRttController.getCapabilitiesCallback> mGetCapCbCatpr = - ArgumentCaptor.forClass(IWifiRttController.getCapabilitiesCallback.class); - private ArgumentCaptor<IWifiRttControllerEventCallback.Stub> mEventCallbackArgumentCaptor = - ArgumentCaptor.forClass(IWifiRttControllerEventCallback.Stub.class); - - @Rule - public ErrorCollector collector = new ErrorCollector(); - - @Mock - public RttServiceImpl mockRttServiceImpl; - - @Mock - public HalDeviceManager mockHalDeviceManager; - - @Mock - public IWifiRttController mockRttController; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - when(mockHalDeviceManager.isStarted()).thenReturn(true); - - mStatusSuccess = new WifiStatus(); - mStatusSuccess.code = WifiStatusCode.SUCCESS; - when(mockRttController.registerEventCallback(mEventCallbackArgumentCaptor.capture())) - .thenReturn(mStatusSuccess); - when(mockRttController.rangeRequest(anyInt(), any(ArrayList.class))).thenReturn( - mStatusSuccess); - when(mockRttController.rangeCancel(anyInt(), any(ArrayList.class))).thenReturn( - mStatusSuccess); - - mDut = new RttNative(mockRttServiceImpl, mockHalDeviceManager); - mDut.start(null); - verify(mockHalDeviceManager).initialize(); - verify(mockHalDeviceManager).registerRttControllerLifecycleCallback( - mRttLifecycleCbCaptor.capture(), any()); - mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttController); - verify(mockRttController).registerEventCallback(any()); - verify(mockRttServiceImpl).enableIfPossible(); - verify(mockRttController).getCapabilities(mGetCapCbCatpr.capture()); - // will override capabilities (just call cb again) for specific tests - mGetCapCbCatpr.getValue().onValues(mStatusSuccess, getFullRttCapabilities()); - // This is for the castFrom() call - verify(mockRttController).asBinder(); - assertTrue(mDut.isReady()); - } - - /** - * Validate successful ranging flow. - */ - @Test - public void testRangeRequest() throws Exception { - int cmdId = 55; - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - - // (1) issue range request - mDut.rangeRequest(cmdId, request, true); - - // (2) verify HAL call and parameters - verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); - - // verify contents of HAL request (hard codes knowledge from getDummyRangingRequest()). - ArrayList<RttConfig> halRequest = mRttConfigCaptor.getValue(); - - collector.checkThat("number of entries", halRequest.size(), - equalTo(request.mRttPeers.size())); - - RttConfig rttConfig = halRequest.get(0); - collector.checkThat("entry 0: MAC", rttConfig.addr, - equalTo(MacAddress.fromString("00:01:02:03:04:00").toByteArray())); - collector.checkThat("entry 0: rtt type", rttConfig.type, equalTo(RttType.TWO_SIDED)); - collector.checkThat("entry 0: peer type", rttConfig.peer, equalTo(RttPeerType.AP)); - collector.checkThat("entry 0: lci", rttConfig.mustRequestLci, equalTo(true)); - collector.checkThat("entry 0: lcr", rttConfig.mustRequestLcr, equalTo(true)); - - rttConfig = halRequest.get(1); - collector.checkThat("entry 1: MAC", rttConfig.addr, - equalTo(MacAddress.fromString("0A:0B:0C:0D:0E:00").toByteArray())); - collector.checkThat("entry 1: rtt type", rttConfig.type, equalTo(RttType.ONE_SIDED)); - collector.checkThat("entry 1: peer type", rttConfig.peer, equalTo(RttPeerType.AP)); - collector.checkThat("entry 1: lci", rttConfig.mustRequestLci, equalTo(true)); - collector.checkThat("entry 1: lcr", rttConfig.mustRequestLcr, equalTo(true)); - - rttConfig = halRequest.get(2); - collector.checkThat("entry 2: MAC", rttConfig.addr, - equalTo(MacAddress.fromString("08:09:08:07:06:05").toByteArray())); - collector.checkThat("entry 2: rtt type", rttConfig.type, equalTo(RttType.TWO_SIDED)); - collector.checkThat("entry 2: peer type", rttConfig.peer, equalTo(RttPeerType.NAN)); - collector.checkThat("entry 2: lci", rttConfig.mustRequestLci, equalTo(false)); - collector.checkThat("entry 2: lcr", rttConfig.mustRequestLcr, equalTo(false)); - - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); - } - - /** - * Validate ranging request with a mix of Repsonders with and without IEEE 802.11mc support, - * from a non- privileged context. - */ - @Test - public void testRangeRequestNotPrivilegedNo80211mcSupportMixed() throws Exception { - int cmdId = 66; - - // the request has 3 responders: first AP support 802.11mc, second AP does not, third is - // Aware (which supports 802.11mc by default) - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - - // (1) issue range request - mDut.rangeRequest(cmdId, request, false); - - // (2) verify HAL call and parameters - verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); - - // verify contents of HAL request (hard codes knowledge from getDummyRangingRequest()). - ArrayList<RttConfig> halRequest = mRttConfigCaptor.getValue(); - - collector.checkThat("number of entries", halRequest.size(), equalTo(2)); - - RttConfig rttConfig = halRequest.get(0); - collector.checkThat("entry 0: MAC", rttConfig.addr, - equalTo(MacAddress.fromString("00:01:02:03:04:00").toByteArray())); - collector.checkThat("entry 0: rtt type", rttConfig.type, equalTo(RttType.TWO_SIDED)); - collector.checkThat("entry 0: peer type", rttConfig.peer, equalTo(RttPeerType.AP)); - collector.checkThat("entry 0: lci", rttConfig.mustRequestLci, equalTo(true)); - collector.checkThat("entry 0: lcr", rttConfig.mustRequestLcr, equalTo(true)); - - rttConfig = halRequest.get(1); - collector.checkThat("entry 1: MAC", rttConfig.addr, - equalTo(MacAddress.fromString("08:09:08:07:06:05").toByteArray())); - collector.checkThat("entry 1: rtt type", rttConfig.type, equalTo(RttType.TWO_SIDED)); - collector.checkThat("entry 1: peer type", rttConfig.peer, equalTo(RttPeerType.NAN)); - collector.checkThat("entry 1: lci", rttConfig.mustRequestLci, equalTo(false)); - collector.checkThat("entry 1: lcr", rttConfig.mustRequestLcr, equalTo(false)); - - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); - } - - /** - * Validate successful ranging flow - with privileges access but with limited capabilities: - * - No single-sided RTT - * - No LCI/LCR - * - Limited BW - * - Limited Preamble - */ - @Test - public void testRangeRequestWithLimitedCapabilities() throws Exception { - int cmdId = 55; - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - - // update capabilities to a limited set - RttCapabilities cap = getFullRttCapabilities(); - cap.rttOneSidedSupported = false; - cap.lciSupported = false; - cap.lcrSupported = false; - cap.bwSupport = RttBw.BW_10MHZ | RttBw.BW_160MHZ; - cap.preambleSupport = RttPreamble.LEGACY; - mGetCapCbCatpr.getValue().onValues(mStatusSuccess, cap); - - // Note: request 1: BW = 40MHz --> 10MHz, Preamble = HT (since 40MHz) -> Legacy - - // (1) issue range request - mDut.rangeRequest(cmdId, request, true); - - // (2) verify HAL call and parameters - verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); - - // verify contents of HAL request (hard codes knowledge from getDummyRangingRequest()). - ArrayList<RttConfig> halRequest = mRttConfigCaptor.getValue(); - - assertEquals("number of entries", halRequest.size(), 2); - - RttConfig rttConfig = halRequest.get(0); - collector.checkThat("entry 0: MAC", rttConfig.addr, - equalTo(MacAddress.fromString("00:01:02:03:04:00").toByteArray())); - collector.checkThat("entry 0: rtt type", rttConfig.type, equalTo(RttType.TWO_SIDED)); - collector.checkThat("entry 0: peer type", rttConfig.peer, equalTo(RttPeerType.AP)); - collector.checkThat("entry 0: lci", rttConfig.mustRequestLci, equalTo(false)); - collector.checkThat("entry 0: lcr", rttConfig.mustRequestLcr, equalTo(false)); - collector.checkThat("entry 0: channel.width", rttConfig.channel.width, equalTo( - WifiChannelWidthInMhz.WIDTH_40)); - collector.checkThat("entry 0: bw", rttConfig.bw, equalTo(RttBw.BW_10MHZ)); - collector.checkThat("entry 0: preamble", rttConfig.preamble, equalTo(RttPreamble.LEGACY)); - - rttConfig = halRequest.get(1); - collector.checkThat("entry 1: MAC", rttConfig.addr, - equalTo(MacAddress.fromString("08:09:08:07:06:05").toByteArray())); - collector.checkThat("entry 1: rtt type", rttConfig.type, equalTo(RttType.TWO_SIDED)); - collector.checkThat("entry 1: peer type", rttConfig.peer, equalTo(RttPeerType.NAN)); - collector.checkThat("entry 1: lci", rttConfig.mustRequestLci, equalTo(false)); - collector.checkThat("entry 1: lcr", rttConfig.mustRequestLcr, equalTo(false)); - - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); - } - - /** - * Validate successful ranging flow - with privileges access but with limited capabilities: - * - Very limited BW - * - Very limited Preamble - */ - @Test - public void testRangeRequestWithLimitedCapabilitiesNoOverlap() throws Exception { - int cmdId = 55; - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - - // update capabilities to a limited set - RttCapabilities cap = getFullRttCapabilities(); - cap.bwSupport = RttBw.BW_80MHZ; - cap.preambleSupport = RttPreamble.VHT; - mGetCapCbCatpr.getValue().onValues(mStatusSuccess, cap); - - // Note: request 1: BW = 40MHz --> no overlap -> dropped - // Note: request 2: BW = 160MHz --> 160MHz, preamble = VHT (since 160MHz) -> no overlap, - // dropped - - // (1) issue range request - mDut.rangeRequest(cmdId, request, true); - - // (2) verify HAL call and parameters - verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); - - // verify contents of HAL request (hard codes knowledge from getDummyRangingRequest()). - ArrayList<RttConfig> halRequest = mRttConfigCaptor.getValue(); - - collector.checkThat("number of entries", halRequest.size(), equalTo(1)); - - RttConfig rttConfig = halRequest.get(0); - collector.checkThat("entry 0: MAC", rttConfig.addr, - equalTo(MacAddress.fromString("08:09:08:07:06:05").toByteArray())); - collector.checkThat("entry 0: rtt type", rttConfig.type, equalTo(RttType.TWO_SIDED)); - collector.checkThat("entry 0: peer type", rttConfig.peer, equalTo(RttPeerType.NAN)); - collector.checkThat("entry 0: lci", rttConfig.mustRequestLci, equalTo(false)); - collector.checkThat("entry 0: lcr", rttConfig.mustRequestLcr, equalTo(false)); - - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); - } - - /** - * Validate ranging request with all Repsonders without IEEE 802.11mc support, from a non- - * privileged context. - */ - @Test - public void testRangeRequestNotPrivilegedNo80211mcSupportForAny() throws Exception { - int cmdId = 77; - RangingRequest request = RttTestUtils.getDummyRangingRequestNo80211mcSupport((byte) 0); - - // (1) issue range request - mDut.rangeRequest(cmdId, request, false); - - // (2) verify immediate result callback (empty result set) - verify(mockRttServiceImpl).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); - - collector.checkThat("Result set", mRttResultCaptor.getValue().size(), equalTo(0)); - - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); - } - - /** - * Validate no range request when Wi-Fi is down - */ - @Test - public void testWifiDown() throws Exception { - int cmdId = 55; - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - - // (1) simulate Wi-Fi down and send a status change indication - mRttLifecycleCbCaptor.getValue().onRttControllerDestroyed(); - verify(mockRttServiceImpl).disable(); - assertFalse(mDut.isReady()); - - // (2) issue range request - mDut.rangeRequest(cmdId, request, true); - - verifyNoMoreInteractions(mockRttServiceImpl, mockRttController); - } - - /** - * Validate that we react correctly (i.e. enable/disable global RTT availability) when - * notified that the RTT controller has disappear and appeared. - */ - @Test - public void testRttControllerLifecycle() throws Exception { - // RTT controller disappears - mRttLifecycleCbCaptor.getValue().onRttControllerDestroyed(); - verify(mockRttServiceImpl).disable(); - assertFalse(mDut.isReady()); - - // RTT controller re-appears (verification is x2 since 1st time is in setup()) - mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttController); - verify(mockRttController, times(2)).registerEventCallback(any()); - verify(mockRttServiceImpl, times(2)).enableIfPossible(); - verify(mockRttController, times(2)).getCapabilities(mGetCapCbCatpr.capture()); - // This is for the castFrom() calls - verify(mockRttController, times(2)).asBinder(); - assertTrue(mDut.isReady()); - - verifyNoMoreInteractions(mockRttServiceImpl, mockRttController); - } - - /** - * Validate ranging cancel flow. - */ - @Test - public void testRangeCancel() throws Exception { - int cmdId = 66; - ArrayList<byte[]> macAddresses = new ArrayList<>(); - byte[] mac1 = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - byte[] mac2 = {0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; - macAddresses.add(mac1); - macAddresses.add(mac2); - - // (1) issue cancel request - mDut.rangeCancel(cmdId, macAddresses); - - // (2) verify HAL call and parameters - verify(mockRttController).rangeCancel(cmdId, macAddresses); - - verifyNoMoreInteractions(mockRttController); - } - - /** - * Validate correct result conversion from HAL to framework. - */ - @Test - public void testRangeResults() throws Exception { - int cmdId = 55; - ArrayList<RttResult> results = new ArrayList<>(); - RttResult res = new RttResult(); - res.addr[0] = 5; - res.addr[1] = 6; - res.addr[2] = 7; - res.addr[3] = 8; - res.addr[4] = 9; - res.addr[5] = 10; - res.status = RttStatus.SUCCESS; - res.distanceInMm = 1500; - res.timeStampInUs = 6000; - results.add(res); - - // (1) have HAL call native with results - mEventCallbackArgumentCaptor.getValue().onResults(cmdId, results); - - // (2) verify call to framework - verify(mockRttServiceImpl).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); - - // verify contents of the framework results - List<RangingResult> rttR = mRttResultCaptor.getValue(); - - collector.checkThat("number of entries", rttR.size(), equalTo(1)); - - RangingResult rttResult = rttR.get(0); - collector.checkThat("status", rttResult.getStatus(), - equalTo(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS)); - collector.checkThat("mac", rttResult.getMacAddress().toByteArray(), - equalTo(MacAddress.fromString("05:06:07:08:09:0A").toByteArray())); - collector.checkThat("distanceCm", rttResult.getDistanceMm(), equalTo(1500)); - collector.checkThat("timestamp", rttResult.getRangingTimestampMillis(), equalTo(6L)); - - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); - } - - /** - * Validate correct cleanup when a null array of results is provided by HAL. - */ - @Test - public void testRangeResultsNullArray() throws Exception { - int cmdId = 66; - - mEventCallbackArgumentCaptor.getValue().onResults(cmdId, null); - verify(mockRttServiceImpl).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); - - collector.checkThat("number of entries", mRttResultCaptor.getValue().size(), equalTo(0)); - } - - /** - * Validate correct cleanup when an array of results containing null entries is provided by HAL. - */ - @Test - public void testRangeResultsSomeNulls() throws Exception { - int cmdId = 77; - - ArrayList<RttResult> results = new ArrayList<>(); - results.add(null); - results.add(new RttResult()); - results.add(null); - results.add(null); - results.add(new RttResult()); - results.add(null); - - mEventCallbackArgumentCaptor.getValue().onResults(cmdId, results); - verify(mockRttServiceImpl).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); - - List<RttResult> rttR = mRttResultCaptor.getValue(); - collector.checkThat("number of entries", rttR.size(), equalTo(2)); - for (int i = 0; i < rttR.size(); ++i) { - collector.checkThat("entry", rttR.get(i), IsNull.notNullValue()); - } - } - - /** - * Validation ranging with invalid bw and preamble combination will be ignored. - */ - @Test - public void testRangingWithInvalidParameterCombination() throws Exception { - int cmdId = 88; - RangingRequest request = new RangingRequest.Builder().build(); - ResponderConfig invalidConfig = new ResponderConfig( - MacAddress.fromString("08:09:08:07:06:88"), ResponderConfig.RESPONDER_AP, true, - ResponderConfig.CHANNEL_WIDTH_80MHZ, 0, 0, 0, ResponderConfig.PREAMBLE_HT); - ResponderConfig config = new ResponderConfig(MacAddress.fromString("08:09:08:07:06:89"), - ResponderConfig.RESPONDER_AP, true, - ResponderConfig.CHANNEL_WIDTH_80MHZ, 0, 0, 0, ResponderConfig.PREAMBLE_VHT); - - // Add a ResponderConfig with invalid parameter, should be ignored. - request.mRttPeers.add(invalidConfig); - request.mRttPeers.add(config); - mDut.rangeRequest(cmdId, request, true); - verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); - assertEquals(request.mRttPeers.size() - 1, mRttConfigCaptor.getValue().size()); - } - - // Utilities - - /** - * Return an RttCapabilities structure with all features enabled and support for all - * preambles and bandwidths. The purpose is to enable any request. The returned structure can - * then be modified to disable specific features. - */ - RttCapabilities getFullRttCapabilities() { - RttCapabilities cap = new RttCapabilities(); - - cap.rttOneSidedSupported = true; - cap.rttFtmSupported = true; - cap.lciSupported = true; - cap.lcrSupported = true; - cap.responderSupported = true; // unused - cap.preambleSupport = RttPreamble.LEGACY | RttPreamble.HT | RttPreamble.VHT - | android.hardware.wifi.V1_4.RttPreamble.HE; - cap.bwSupport = - RttBw.BW_5MHZ | RttBw.BW_10MHZ | RttBw.BW_20MHZ | RttBw.BW_40MHZ | RttBw.BW_80MHZ - | RttBw.BW_160MHZ; - cap.mcVersion = 1; // unused - - return cap; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java deleted file mode 100644 index 687c24f52..000000000 --- a/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java +++ /dev/null @@ -1,1534 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.rtt; - -import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; -import static com.android.server.wifi.rtt.RttTestUtils.compareListContentsNoOrdering; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.app.ActivityManager; -import android.app.AlarmManager; -import android.app.test.MockAnswerUtil; -import android.app.test.TestAlarmManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.net.MacAddress; -import android.net.wifi.aware.IWifiAwareMacAddressProvider; -import android.net.wifi.aware.PeerHandle; -import android.net.wifi.aware.WifiAwareManager; -import android.net.wifi.rtt.IRttCallback; -import android.net.wifi.rtt.RangingRequest; -import android.net.wifi.rtt.RangingResult; -import android.net.wifi.rtt.RangingResultCallback; -import android.net.wifi.rtt.ResponderConfig; -import android.net.wifi.rtt.WifiRttManager; -import android.os.Handler; -import android.os.IBinder; -import android.os.IPowerManager; -import android.os.IThermalService; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.UserHandle; -import android.os.WorkSource; -import android.os.test.TestLooper; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.MockResources; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiSettingsConfigStore; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.util.WifiPermissionsUtil; -import com.android.wifi.resources.R; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - - -/** - * Unit test harness for the RttServiceImpl class. - */ -@SmallTest -public class RttServiceImplTest extends WifiBaseTest { - - private static final int BACKGROUND_PROCESS_EXEC_GAP_MS = 10 * 60 * 1000; // 10 minutes. - private static final int MEASUREMENT_DURATION = 1000; - - private RttServiceImplSpy mDut; - private TestLooper mMockLooper; - private TestAlarmManager mAlarmManager; - private PowerManager mMockPowerManager; - private BroadcastReceiver mPowerBcastReceiver; - private BroadcastReceiver mLocationModeReceiver; - private MockResources mMockResources = new MockResources(); - - private final String mPackageName = "some.package.name.for.rtt.app"; - private final String mFeatureId = "some.feature.name.for.rtt.app"; - private int mDefaultUid = 1500; - private WorkSource mDefaultWs = new WorkSource(mDefaultUid); - - private ArgumentCaptor<Integer> mIntCaptor = ArgumentCaptor.forClass(Integer.class); - private ArgumentCaptor<IBinder.DeathRecipient> mDeathRecipientCaptor = ArgumentCaptor - .forClass(IBinder.DeathRecipient.class); - private ArgumentCaptor<RangingRequest> mRequestCaptor = ArgumentCaptor.forClass( - RangingRequest.class); - private ArgumentCaptor<List> mListCaptor = ArgumentCaptor.forClass(List.class); - - private BinderLinkToDeathAnswer mBinderLinkToDeathCounter = new BinderLinkToDeathAnswer(); - private BinderUnlinkToDeathAnswer mBinderUnlinkToDeathCounter = new BinderUnlinkToDeathAnswer(); - - private InOrder mInOrder; - - @Mock - public Context mockContext; - - @Mock - public ActivityManager mockActivityManager; - - @Mock - public Clock mockClock; - - @Mock - public RttNative mockNative; - - @Mock - public RttMetrics mockMetrics; - - @Mock - public WifiAwareManager mockAwareManager; - - @Mock - public WifiPermissionsUtil mockPermissionUtil; - - @Mock - public IBinder mockIbinder; - - @Mock - public IRttCallback mockCallback; - - @Mock - WifiSettingsConfigStore mWifiSettingsConfigStore; - - /** - * Using instead of spy to avoid native crash failures - possibly due to - * spy's copying of state. - */ - private class RttServiceImplSpy extends RttServiceImpl { - public int fakeUid; - - RttServiceImplSpy(Context context) { - super(context); - } - - /** - * Return the fake UID instead of the real one: pseudo-spy - * implementation. - */ - @Override - public int getMockableCallingUid() { - return fakeUid; - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mDut = new RttServiceImplSpy(mockContext); - mDut.fakeUid = mDefaultUid; - mMockLooper = new TestLooper(); - - when(mockContext.checkCallingOrSelfPermission( - android.Manifest.permission.LOCATION_HARDWARE)).thenReturn( - PackageManager.PERMISSION_GRANTED); - - when(mockContext.getResources()).thenReturn(mMockResources); - mMockResources.setInteger( - R.integer.config_wifiRttBackgroundExecGapMs, BACKGROUND_PROCESS_EXEC_GAP_MS); - - mAlarmManager = new TestAlarmManager(); - when(mockContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - mInOrder = inOrder(mAlarmManager.getAlarmManager(), mockContext); - - when(mockContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn( - mockActivityManager); - when(mockActivityManager.getUidImportance(anyInt())).thenReturn( - ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE); - - when(mockPermissionUtil.checkCallersLocationPermission(eq(mPackageName), eq(mFeatureId), - anyInt(), anyBoolean(), nullable(String.class))).thenReturn(true); - when(mockPermissionUtil.isLocationModeEnabled()).thenReturn(true); - when(mockNative.isReady()).thenReturn(true); - when(mockNative.rangeRequest(anyInt(), any(RangingRequest.class), anyBoolean())).thenReturn( - true); - when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true); - - mMockPowerManager = new PowerManager(mockContext, mock(IPowerManager.class), - mock(IThermalService.class), new Handler(mMockLooper.getLooper())); - when(mMockPowerManager.isDeviceIdleMode()).thenReturn(false); - when(mockContext.getSystemServiceName(PowerManager.class)).thenReturn( - Context.POWER_SERVICE); - when(mockContext.getSystemService(PowerManager.class)).thenReturn(mMockPowerManager); - - doAnswer(mBinderLinkToDeathCounter).when(mockIbinder).linkToDeath(any(), anyInt()); - doAnswer(mBinderUnlinkToDeathCounter).when(mockIbinder).unlinkToDeath(any(), anyInt()); - - mDut.start(mMockLooper.getLooper(), mockClock, mockAwareManager, mockNative, - mockMetrics, mockPermissionUtil, mWifiSettingsConfigStore); - mMockLooper.dispatchAll(); - ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass( - BroadcastReceiver.class); - verify(mockContext, times(2)).registerReceiver(bcastRxCaptor.capture(), - any(IntentFilter.class)); - verify(mockNative).start(any()); - mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(0); - mLocationModeReceiver = bcastRxCaptor.getAllValues().get(1); - - assertTrue(mDut.isAvailable()); - } - - @After - public void tearDown() throws Exception { - assertEquals("Binder links != unlinks to death (size)", - mBinderLinkToDeathCounter.mUniqueExecs.size(), - mBinderUnlinkToDeathCounter.mUniqueExecs.size()); - assertEquals("Binder links != unlinks to death", mBinderLinkToDeathCounter.mUniqueExecs, - mBinderUnlinkToDeathCounter.mUniqueExecs); - } - - /** - * Validate successful ranging flow. - */ - @Test - public void testRangingFlow() throws Exception { - int numIter = 10; - RangingRequest[] requests = new RangingRequest[numIter]; - List<Pair<List<RangingResult>, List<RangingResult>>> results = new ArrayList<>(); - - for (int i = 0; i < numIter; ++i) { // even: MC, non-MC, Aware, odd: MC only - if (i % 2 == 0) { - requests[i] = RttTestUtils.getDummyRangingRequestMcOnly((byte) i); - } else { - requests[i] = RttTestUtils.getDummyRangingRequest((byte) i); - } - results.add(RttTestUtils.getDummyRangingResults(requests[i])); - } - - ClockAnswer clock = new ClockAnswer(); - doAnswer(clock).when(mockClock).getWallClockMillis(); - clock.time = 100; - // (1) request 10 ranging operations - for (int i = 0; i < numIter; ++i) { - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, requests[i], - mockCallback); - } - mMockLooper.dispatchAll(); - - for (int i = 0; i < numIter; ++i) { - clock.time += MEASUREMENT_DURATION; - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(requests[i]), eq(true)); - verifyWakeupSet(i % 2 != 0, 0); - - // (3) native calls back with result - mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).second); - mMockLooper.dispatchAll(); - - // (4) verify that results dispatched - verify(mockCallback).onRangingResults(results.get(i).second); - verifyWakeupCancelled(); - - // (5) replicate results - shouldn't dispatch another callback - mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).second); - mMockLooper.dispatchAll(); - } - - // verify metrics - for (int i = 0; i < numIter; ++i) { - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(requests[i])); - verify(mockMetrics).recordResult(eq(requests[i]), eq(results.get(i).second), - eq(MEASUREMENT_DURATION)); - } - verify(mockMetrics, times(numIter)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate a successful ranging flow with PeerHandles (i.e. verify translations) - */ - @Test - public void testRangingFlowUsingAwarePeerHandles() throws Exception { - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0xA); - PeerHandle peerHandle1 = new PeerHandle(1022); - PeerHandle peerHandle2 = new PeerHandle(1023); - PeerHandle peerHandle3 = new PeerHandle(1024); - request.mRttPeers.add(ResponderConfig.fromWifiAwarePeerHandleWithDefaults(peerHandle1)); - request.mRttPeers.add(ResponderConfig.fromWifiAwarePeerHandleWithDefaults(peerHandle2)); - request.mRttPeers.add(ResponderConfig.fromWifiAwarePeerHandleWithDefaults(peerHandle3)); - Map<Integer, MacAddress> peerHandleToMacMap = new HashMap<>(); - MacAddress macAwarePeer1 = MacAddress.fromString("AA:BB:CC:DD:EE:FF"); - MacAddress macAwarePeer2 = MacAddress.fromString("BB:BB:BB:EE:EE:EE"); - peerHandleToMacMap.put(peerHandle1.peerId, macAwarePeer1); - peerHandleToMacMap.put(peerHandle2.peerId, macAwarePeer2); - peerHandleToMacMap.put(peerHandle3.peerId, null); // bad answer from Aware (expired?) - - AwareTranslatePeerHandlesToMac answer = new AwareTranslatePeerHandlesToMac(mDefaultUid, - peerHandleToMacMap); - doAnswer(answer).when(mockAwareManager).requestMacAddresses(anyInt(), any(), any()); - - // issue request - ClockAnswer clock = new ClockAnswer(); - doAnswer(clock).when(mockClock).getWallClockMillis(); - clock.time = 100; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request, mockCallback); - mMockLooper.dispatchAll(); - - // verify that requested with MAC address translated from the PeerHandle issued to Native - verify(mockNative).rangeRequest(mIntCaptor.capture(), mRequestCaptor.capture(), eq(true)); - verifyWakeupSet(true, 0); - - RangingRequest finalRequest = mRequestCaptor.getValue(); - assertNotEquals("Request to native is not null", null, finalRequest); - assertEquals("Size of request", request.mRttPeers.size() - 1, - finalRequest.mRttPeers.size()); - assertEquals("Aware peer 1 MAC", macAwarePeer1, - finalRequest.mRttPeers.get(finalRequest.mRttPeers.size() - 2).macAddress); - assertEquals("Aware peer 2 MAC", macAwarePeer2, - finalRequest.mRttPeers.get(finalRequest.mRttPeers.size() - 1).macAddress); - - // issue results - but remove the one for peer #2 - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(mRequestCaptor.getValue()); - results.first.remove(results.first.size() - 1); - RangingResult removed = results.second.remove(results.second.size() - 1); - results.second.add( - new RangingResult(RangingResult.STATUS_FAIL, removed.getPeerHandle(), 0, 0, 0, 0, 0, - null, null, null, 0)); - clock.time += MEASUREMENT_DURATION; - mDut.onRangingResults(mIntCaptor.getValue(), results.first); - mMockLooper.dispatchAll(); - - // verify that results with MAC addresses filtered out and replaced by PeerHandles issued - // to callback - verify(mockCallback).onRangingResults(mListCaptor.capture()); - verifyWakeupCancelled(); - - assertEquals(results.second, mListCaptor.getValue()); - assertTrue(compareListContentsNoOrdering(results.second, mListCaptor.getValue())); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); - verify(mockMetrics).recordResult(eq(finalRequest), eq(results.first), - eq(MEASUREMENT_DURATION)); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate failed ranging flow (native failure). - */ - @Test - public void testRangingFlowNativeFailure() throws Exception { - int numIter = 10; - RangingRequest[] requests = new RangingRequest[numIter]; - List<Pair<List<RangingResult>, List<RangingResult>>> results = new ArrayList<>(); - - for (int i = 0; i < numIter; ++i) { - requests[i] = RttTestUtils.getDummyRangingRequest((byte) i); - results.add(RttTestUtils.getDummyRangingResults(requests[i])); - } - - // (1) request 10 ranging operations: fail the first one - when(mockNative.rangeRequest(anyInt(), any(RangingRequest.class), anyBoolean())).thenReturn( - false); - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, requests[0], mockCallback); - mMockLooper.dispatchAll(); - - when(mockNative.rangeRequest(anyInt(), any(RangingRequest.class), anyBoolean())).thenReturn( - true); - for (int i = 1; i < numIter; ++i) { - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, requests[i], - mockCallback); - } - mMockLooper.dispatchAll(); - - for (int i = 0; i < numIter; ++i) { - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(requests[i]), eq(true)); - - // (3) verify that failure callback dispatched (for the HAL failure) - if (i == 0) { - verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - } else { - verifyWakeupSet(true, 0); - } - - // (4) on failed HAL: even if native calls back with result we shouldn't dispatch - // callback, otherwise expect result - mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).second); - mMockLooper.dispatchAll(); - - if (i != 0) { - verify(mockCallback).onRangingResults(results.get(i).second); - verifyWakeupCancelled(); - } - } - - // verify metrics - for (int i = 0; i < numIter; ++i) { - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(requests[i])); - if (i != 0) { - verify(mockMetrics).recordResult(eq(requests[i]), eq(results.get(i).second), - anyInt()); - } - } - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE); - verify(mockMetrics, times(numIter - 1)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate a ranging flow for an app whose LOCATION runtime permission is revoked. - */ - @Test - public void testRangingRequestWithoutRuntimePermission() throws Exception { - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(request); - - // (1) request ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request, mockCallback); - mMockLooper.dispatchAll(); - - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // (3) native calls back with result - should get a FAILED callback - when(mockPermissionUtil.checkCallersLocationPermission(eq(mPackageName), eq(mFeatureId), - anyInt(), anyBoolean(), nullable(String.class))).thenReturn(false); - - mDut.onRangingResults(mIntCaptor.getValue(), results.second); - mMockLooper.dispatchAll(); - - verify(mockCallback).onRangingFailure(eq(RangingResultCallback.STATUS_CODE_FAIL)); - verifyWakeupCancelled(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); - verify(mockMetrics).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that the ranging app's binder death clears record of request - no callbacks are - * attempted. - */ - @Test - public void testBinderDeathOfRangingApp() throws Exception { - int numIter = 10; - RangingRequest[] requests = new RangingRequest[numIter]; - List<Pair<List<RangingResult>, List<RangingResult>>> results = new ArrayList<>(); - - for (int i = 0; i < numIter; ++i) { - requests[i] = RttTestUtils.getDummyRangingRequest((byte) i); - results.add(RttTestUtils.getDummyRangingResults(requests[i])); - } - - // (1) request 10 ranging operations: even/odd with different UIDs - for (int i = 0; i < numIter; ++i) { - mDut.fakeUid = mDefaultUid + i % 2; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, requests[i], - mockCallback); - } - mMockLooper.dispatchAll(); - - // (2) capture death listeners - verify(mockIbinder, times(numIter)).linkToDeath(mDeathRecipientCaptor.capture(), anyInt()); - - for (int i = 0; i < numIter; ++i) { - // (3) verify first request and all odd requests issued to HAL - if (i == 0 || i % 2 == 1) { - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(requests[i]), eq(true)); - verifyWakeupSet(true, 0); - } - - // (4) trigger first death recipient (which will map to the even UID) - if (i == 0) { - mDeathRecipientCaptor.getAllValues().get(0).binderDied(); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), - (ArrayList) mListCaptor.capture()); - RangingRequest request0 = requests[0]; - assertEquals(request0.mRttPeers.size(), mListCaptor.getValue().size()); - assertArrayEquals(MacAddress.fromString("00:01:02:03:04:00").toByteArray(), - (byte[]) mListCaptor.getValue().get(0)); - assertArrayEquals(MacAddress.fromString("0A:0B:0C:0D:0E:00").toByteArray(), - (byte[]) mListCaptor.getValue().get(1)); - assertArrayEquals(MacAddress.fromString("08:09:08:07:06:05").toByteArray(), - (byte[]) mListCaptor.getValue().get(2)); - } - - // (5) native calls back with all results - should get requests for the odd attempts and - // should only get callbacks for the odd attempts (the non-dead UID), but this simulates - // invalid results (or possibly the firmware not cancelling some requests) - mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).second); - mMockLooper.dispatchAll(); - if (i == 0) { - verifyWakeupCancelled(); // as the first (dispatched) request is aborted - } - if (i % 2 == 1) { - verify(mockCallback).onRangingResults(results.get(i).second); - verifyWakeupCancelled(); - } - } - - // verify metrics - WorkSource oddWs = new WorkSource(mDefaultUid + 1); - for (int i = 0; i < numIter; ++i) { - verify(mockMetrics).recordRequest(eq((i % 2) == 0 ? mDefaultWs : oddWs), - eq(requests[i])); - if (i % 2 == 1) { - verify(mockMetrics).recordResult(eq(requests[i]), eq(results.get(i).second), - anyInt()); - } - } - verify(mockMetrics, times(numIter / 2)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that a ranging app which uses WorkSource and dies (binder death) results in the - * request cleanup. - */ - @Test - public void testBinderDeathWithWorkSource() throws Exception { - WorkSource ws = new WorkSource(100); - - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(request); - - // (1) request ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, ws, request, mockCallback); - mMockLooper.dispatchAll(); - - verify(mockIbinder).linkToDeath(mDeathRecipientCaptor.capture(), anyInt()); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // (2) execute binder death - mDeathRecipientCaptor.getValue().binderDied(); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); - verifyWakeupCancelled(); - - // (3) provide results back - should be ignored - mDut.onRangingResults(mIntCaptor.getValue(), results.second); - mMockLooper.dispatchAll(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(ws), eq(request)); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that when a cancelRanging is called, using the same work source specification as the - * request, that the request is cancelled. - */ - @Test - public void testCancelRangingFullMatch() throws Exception { - int uid1 = 10; - int uid2 = 20; - int uid3 = 30; - int uid4 = 40; - WorkSource worksourceRequest = new WorkSource(uid1); - worksourceRequest.add(uid2); - worksourceRequest.add(uid3); - worksourceRequest.createWorkChain().addNode(uid4, "foo"); - WorkSource worksourceCancel = new WorkSource(uid2); - worksourceCancel.add(uid3); - worksourceCancel.add(uid1); - worksourceCancel.createWorkChain().addNode(uid4, "foo"); - - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(request); - - // (1) request ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, worksourceRequest, request, - mockCallback); - mMockLooper.dispatchAll(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(worksourceRequest), eq(request)); - - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // (3) cancel the request - mDut.cancelRanging(worksourceCancel); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); - verifyWakeupCancelled(); - - // (4) send results back from native - mDut.onRangingResults(mIntCaptor.getValue(), results.second); - mMockLooper.dispatchAll(); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that when a cancelRanging is called - but specifies a subset of the WorkSource - * uids then the ranging proceeds. - */ - @Test - public void testCancelRangingPartialMatch() throws Exception { - int uid1 = 10; - int uid2 = 20; - int uid3 = 30; - WorkSource worksourceRequest = new WorkSource(uid1); - worksourceRequest.add(uid2); - worksourceRequest.createWorkChain().addNode(uid3, null); - WorkSource worksourceCancel = new WorkSource(uid1); - worksourceCancel.add(uid2); - - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(request); - - // (1) request ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, worksourceRequest, request, - mockCallback); - mMockLooper.dispatchAll(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(worksourceRequest), eq(request)); - - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // (3) cancel the request - mDut.cancelRanging(worksourceCancel); - - // (4) send results back from native - mDut.onRangingResults(mIntCaptor.getValue(), results.second); - mMockLooper.dispatchAll(); - - verify(mockCallback).onRangingResults(results.second); - verifyWakeupCancelled(); - - // verify metrics - verify(mockMetrics).recordResult(eq(request), eq(results.second), anyInt()); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that when an unexpected result is provided by the Native it is not propagated to - * caller (unexpected = different command ID). - */ - @Test - public void testUnexpectedResult() throws Exception { - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(request); - - // (1) request ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request, mockCallback); - mMockLooper.dispatchAll(); - - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // (3) native calls back with result - but wrong ID - mDut.onRangingResults(mIntCaptor.getValue() + 1, - RttTestUtils.getDummyRangingResults(null).second); - mMockLooper.dispatchAll(); - - // (4) now send results with correct ID (different set of results to differentiate) - mDut.onRangingResults(mIntCaptor.getValue(), results.second); - mMockLooper.dispatchAll(); - - // (5) verify that results dispatched - verify(mockCallback).onRangingResults(results.second); - verifyWakeupCancelled(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); - verify(mockMetrics).recordResult(eq(request), eq(results.second), anyInt()); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that the HAL returns results with "missing" entries (i.e. some requests don't get - * results) they are filled-in with FAILED results. - */ - @Test - public void testMissingResults() throws Exception { - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(request); - results.first.remove(1); // remove a direct AWARE request - RangingResult removed = results.second.remove(1); - results.second.add( - new RangingResult(RangingResult.STATUS_FAIL, removed.getMacAddress(), 0, 0, 0, 0, 0, - null, null, null, 0)); - results.first.remove(0); // remove an AP request - removed = results.second.remove(0); - results.second.add( - new RangingResult(RangingResult.STATUS_FAIL, removed.getMacAddress(), 0, 0, 0, 0, 0, - null, null, null, 0)); - - // (1) request ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request, mockCallback); - mMockLooper.dispatchAll(); - - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // (3) return results with missing entries - mDut.onRangingResults(mIntCaptor.getValue(), results.second); - mMockLooper.dispatchAll(); - - // (5) verify that (full) results dispatched - verify(mockCallback).onRangingResults(mListCaptor.capture()); - assertTrue(compareListContentsNoOrdering(results.second, mListCaptor.getValue())); - verifyWakeupCancelled(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); - verify(mockMetrics).recordResult(eq(request), eq(results.second), anyInt()); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that when HAL returns an empty result set (completely empty) - they are filled-in - * with FAILED results. - */ - @Test - public void testMissingAllResults() throws Exception { - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(request); - List<RangingResult> allFailResults = new ArrayList<>(); - for (RangingResult result : results.second) { - allFailResults.add( - new RangingResult(RangingResult.STATUS_FAIL, result.getMacAddress(), 0, 0, 0, 0, - 0, null, null, null, 0)); - } - - // (1) request ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request, mockCallback); - mMockLooper.dispatchAll(); - - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // (3) return results with ALL results missing - mDut.onRangingResults(mIntCaptor.getValue(), new ArrayList<>()); - mMockLooper.dispatchAll(); - - // (5) verify that (full) results dispatched - verify(mockCallback).onRangingResults(mListCaptor.capture()); - assertTrue(compareListContentsNoOrdering(allFailResults, mListCaptor.getValue())); - verifyWakeupCancelled(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); - verify(mockMetrics).recordResult(eq(request), eq(new ArrayList<>()), anyInt()); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that when the HAL returns results with "missing" entries (i.e. some requests - * don't get results) AND these correspond to peers which do not support 802.11mc AND the - * request is from a non-privileged context: they are filled-in with FAILED results. - */ - @Test - public void testMissingResultsForNonSupportOf80211mc() throws Exception { - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - Pair<List<RangingResult>, List<RangingResult>> results = - RttTestUtils.getDummyRangingResults(request); - results.first.remove(1); // remove the entry which doesn't support 802.11mc - RangingResult removed = results.second.remove(1); - results.second.add( - new RangingResult(RangingResult.STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC, - removed.getMacAddress(), 0, 0, 0, 0, 0, null, null, null, 0)); - results.first.remove( - 0); // remove an AP request (i.e. test combo of missing for different reasons) - removed = results.second.remove(0); - results.second.add( - new RangingResult(RangingResult.STATUS_FAIL, removed.getMacAddress(), 0, 0, 0, 0, 0, - null, null, null, 0)); - - when(mockContext.checkCallingOrSelfPermission( - android.Manifest.permission.LOCATION_HARDWARE)).thenReturn( - PackageManager.PERMISSION_DENIED); - - // (1) request ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request, mockCallback); - mMockLooper.dispatchAll(); - - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(false)); - verifyWakeupSet(true, 0); - - // (3) return results with missing entries - mDut.onRangingResults(mIntCaptor.getValue(), results.second); - mMockLooper.dispatchAll(); - - // (5) verify that (full) results dispatched - verify(mockCallback).onRangingResults(mListCaptor.capture()); - assertTrue(compareListContentsNoOrdering(results.second, mListCaptor.getValue())); - verifyWakeupCancelled(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); - verify(mockMetrics).recordResult(eq(request), eq(results.second), anyInt()); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that when the HAL times out we fail, clean-up the queue and move to the next - * request. - */ - @Test - public void testRangingTimeout() throws Exception { - RangingRequest request1 = RttTestUtils.getDummyRangingRequest((byte) 1); - RangingRequest request2 = RttTestUtils.getDummyRangingRequest((byte) 2); - Pair<List<RangingResult>, List<RangingResult>> result1 = - RttTestUtils.getDummyRangingResults(request1); - Pair<List<RangingResult>, List<RangingResult>> result2 = - RttTestUtils.getDummyRangingResults(request2); - - // (1) request 2 ranging operation - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request1, mockCallback); - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request2, mockCallback); - mMockLooper.dispatchAll(); - - // verify that request 1 issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true)); - int cmdId1 = mIntCaptor.getValue(); - verifyWakeupSet(true, 0); - - // (2) time-out - mAlarmManager.dispatch(RttServiceImpl.HAL_RANGING_TIMEOUT_TAG); - mMockLooper.dispatchAll(); - - // verify that: failure callback + request 2 issued to native - verify(mockNative).rangeCancel(eq(cmdId1), any()); - verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request2), eq(true)); - verifyWakeupSet(true, 0); - - // (3) send both result 1 and result 2 - mDut.onRangingResults(cmdId1, result1.second); - mDut.onRangingResults(mIntCaptor.getValue(), result2.second); - mMockLooper.dispatchAll(); - - // verify that only result 2 is forwarded to client - verify(mockCallback).onRangingResults(result2.second); - verifyWakeupCancelled(); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request1)); - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request2)); - verify(mockMetrics).recordResult(eq(request2), eq(result2.second), anyInt()); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that ranging requests from background apps are throttled. The sequence is: - * - Time 1: Background request -> ok - * - Time 2 = t1 + 0.5gap: Background request -> fail (throttled) - * - Time 3 = t1 + 1.1gap: Background request -> ok - * - Time 4 = t3 + small: Foreground request -> ok - * - Time 5 = t4 + small: Background request -> fail (throttled) - */ - @Test - public void testRangingThrottleBackground() throws Exception { - RangingRequest request1 = RttTestUtils.getDummyRangingRequest((byte) 1); - RangingRequest request2 = RttTestUtils.getDummyRangingRequest((byte) 2); - RangingRequest request3 = RttTestUtils.getDummyRangingRequest((byte) 3); - RangingRequest request4 = RttTestUtils.getDummyRangingRequest((byte) 4); - RangingRequest request5 = RttTestUtils.getDummyRangingRequest((byte) 5); - - Pair<List<RangingResult>, List<RangingResult>> result1 = - RttTestUtils.getDummyRangingResults(request1); - Pair<List<RangingResult>, List<RangingResult>> result3 = - RttTestUtils.getDummyRangingResults(request3); - Pair<List<RangingResult>, List<RangingResult>> result4 = - RttTestUtils.getDummyRangingResults(request4); - - InOrder cbInorder = inOrder(mockCallback); - - ClockAnswer clock = new ClockAnswer(); - doAnswer(clock).when(mockClock).getElapsedSinceBootMillis(); - when(mockActivityManager.getUidImportance(anyInt())).thenReturn( - ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); // far background - - // (1) issue a request at time t1: should be dispatched since first one! - clock.time = 100; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request1, mockCallback); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true)); - verifyWakeupSet(true, clock.time); - - // (1.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result1.second); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingResults(result1.second); - verifyWakeupCancelled(); - - // (2) issue a request at time t2 = t1 + 0.5 gap: should be rejected (throttled) - clock.time = 100 + BACKGROUND_PROCESS_EXEC_GAP_MS / 2; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request2, mockCallback); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - - // (3) issue a request at time t3 = t1 + 1.1 gap: should be dispatched since enough time - clock.time = 100 + BACKGROUND_PROCESS_EXEC_GAP_MS * 11 / 10; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request3, mockCallback); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request3), eq(true)); - verifyWakeupSet(true, clock.time); - - // (3.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result3.second); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingResults(result3.second); - verifyWakeupCancelled(); - - // (4) issue a foreground request at t4 = t3 + small: should be dispatched (foreground!) - when(mockActivityManager.getUidImportance(anyInt())).thenReturn( - ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); - - clock.time = clock.time + 5; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request4, mockCallback); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request4), eq(true)); - verifyWakeupSet(true, clock.time); - - // (4.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result4.second); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingResults(result4.second); - verifyWakeupCancelled(); - - // (5) issue a background request at t5 = t4 + small: should be rejected (throttled) - when(mockActivityManager.getUidImportance(anyInt())).thenReturn( - ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); - - clock.time = clock.time + 5; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request5, mockCallback); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request1)); - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request2)); - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request3)); - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request4)); - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request5)); - verify(mockMetrics).recordResult(eq(request1), eq(result1.second), anyInt()); - verify(mockMetrics).recordResult(eq(request3), eq(result3.second), anyInt()); - verify(mockMetrics).recordResult(eq(request4), eq(result4.second), anyInt()); - verify(mockMetrics, times(2)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE); - verify(mockMetrics, times(3)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that throttling of background request handles multiple work source correctly: - * - Time t1: background request uid=10: ok - * - Time t2 = t1+small: background request ws={10,20}: ok - * - Time t3 = t1+gap: background request uid=10: fail (throttled) - */ - @Test - public void testRangingThrottleBackgroundWorkSources() throws Exception { - runTestRangingThrottleBackgroundWorkSources(false); - } - - @Test - public void testRangingThrottleBackgroundChainedWorkSources() throws Exception { - runTestRangingThrottleBackgroundWorkSources(true); - } - - private void runTestRangingThrottleBackgroundWorkSources(boolean isChained) throws Exception { - final WorkSource wsReq1 = new WorkSource(); - final WorkSource wsReq2 = new WorkSource(); - if (isChained) { - wsReq1.createWorkChain().addNode(10, "foo"); - - wsReq2.createWorkChain().addNode(10, "foo"); - wsReq2.createWorkChain().addNode(20, "bar"); - } else { - wsReq1.add(10); - - wsReq2.add(10); - wsReq2.add(20); - } - - RangingRequest request1 = RttTestUtils.getDummyRangingRequest((byte) 1); - RangingRequest request2 = RttTestUtils.getDummyRangingRequest((byte) 2); - RangingRequest request3 = RttTestUtils.getDummyRangingRequest((byte) 3); - - Pair<List<RangingResult>, List<RangingResult>> result1 = - RttTestUtils.getDummyRangingResults(request1); - Pair<List<RangingResult>, List<RangingResult>> result2 = - RttTestUtils.getDummyRangingResults(request2); - - InOrder cbInorder = inOrder(mockCallback); - - ClockAnswer clock = new ClockAnswer(); - doAnswer(clock).when(mockClock).getElapsedSinceBootMillis(); - when(mockActivityManager.getUidImportance(anyInt())).thenReturn( - ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE); // far background - - // (1) issue a request at time t1 for {10}: should be dispatched since first one! - clock.time = 100; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, wsReq1, request1, mockCallback); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true)); - verifyWakeupSet(true, clock.time); - - // (1.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result1.second); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingResults(result1.second); - verifyWakeupCancelled(); - - // (2) issue a request at time t2 = t1 + 0.5 gap for {10,20}: should be dispatched since - // uid=20 should not be throttled - clock.time = 100 + BACKGROUND_PROCESS_EXEC_GAP_MS / 2; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, wsReq2, request2, mockCallback); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request2), eq(true)); - verifyWakeupSet(true, clock.time); - - // (2.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result2.second); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingResults(result2.second); - verifyWakeupCancelled(); - - // (3) issue a request at t3 = t1 + 1.1 * gap for {10}: should be rejected (throttled) - clock.time = 100 + BACKGROUND_PROCESS_EXEC_GAP_MS * 11 / 10; - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, wsReq1, request3, mockCallback); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - - // verify metrics - verify(mockMetrics).recordRequest(eq(wsReq1), eq(request1)); - verify(mockMetrics).recordRequest(eq(wsReq2), eq(request2)); - verify(mockMetrics).recordRequest(eq(wsReq1), eq(request3)); - verify(mockMetrics).recordResult(eq(request1), eq(result1.second), anyInt()); - verify(mockMetrics).recordResult(eq(request2), eq(result2.second), anyInt()); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE); - verify(mockMetrics, times(2)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that flooding the service with ranging requests will cause it to start rejecting - * rejects from the flooding uid. Single UID. - */ - @Test - public void testRejectFloodingRequestsSingleUid() throws Exception { - runFloodRequestsTest(true, false); - } - - /** - * Validate that flooding the service with ranging requests will cause it to start rejecting - * rejects from the flooding uid. WorkSource (all identical). - */ - @Test - public void testRejectFloodingRequestsIdenticalWorksources() throws Exception { - runFloodRequestsTest(false, false); - } - - @Test - public void testRejectFloodingRequestsIdenticalChainedWorksources() throws Exception { - runFloodRequestsTest(false, true); - } - - /** - * Validate that flooding the service with ranging requests will cause it to start rejecting - * rejects from the flooding uid. WorkSource (with one constant UID but other varying UIDs - - * the varying UIDs should prevent the flood throttle) - */ - @Test - public void testDontRejectFloodingRequestsVariousUids() throws Exception { - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 1); - WorkSource ws = new WorkSource(10); - - // 1. issue a request - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, ws, request, mockCallback); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // 2. issue FLOOD LEVEL requests + 10 at various UIDs - no failure expected - for (int i = 0; i < RttServiceImpl.MAX_QUEUED_PER_UID + 10; ++i) { - WorkSource wsExtra = new WorkSource(ws); - wsExtra.add(11 + i); - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, wsExtra, request, - mockCallback); - } - mMockLooper.dispatchAll(); - - // 3. clear queue - mDut.disable(); - mMockLooper.dispatchAll(); - - verifyWakeupCancelled(); - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); - verify(mockCallback, times(RttServiceImpl.MAX_QUEUED_PER_UID + 11)) - .onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); - - // verify metrics - for (int i = 0; i < RttServiceImpl.MAX_QUEUED_PER_UID + 11; ++i) { - WorkSource wsExtra = new WorkSource(10); - if (i != 0) { - wsExtra.add(10 + i); - } - verify(mockMetrics).recordRequest(eq(wsExtra), eq(request)); - } - verify(mockMetrics, times(RttServiceImpl.MAX_QUEUED_PER_UID + 11)) - .recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Utility to run configurable tests for flooding range requests. - * - Execute a single request - * - Flood service with requests: using same ID or same WorkSource - * - Provide results (to clear queue) and execute another test: validate succeeds - */ - private void runFloodRequestsTest(boolean useUids, boolean useChainedWorkSources) - throws Exception { - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 1); - Pair<List<RangingResult>, List<RangingResult>> result = - RttTestUtils.getDummyRangingResults(request); - - WorkSource ws = new WorkSource(); - if (useChainedWorkSources) { - ws.createWorkChain().addNode(10, "foo"); - ws.createWorkChain().addNode(20, "bar"); - ws.createWorkChain().addNode(30, "baz"); - } else { - ws.add(10); - ws.add(20); - ws.add(30); - } - - InOrder cbInorder = inOrder(mockCallback); - InOrder nativeInorder = inOrder(mockNative); - - // 1. issue a request - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, useUids ? null : ws, request, - mockCallback); - mMockLooper.dispatchAll(); - - nativeInorder.verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // 2. issue FLOOD LEVEL requests + 10: should get 11 failures (10 extra + 1 original) - for (int i = 0; i < RttServiceImpl.MAX_QUEUED_PER_UID + 10; ++i) { - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, useUids ? null : ws, request, - mockCallback); - } - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback, times(11)).onRangingFailure( - RangingResultCallback.STATUS_CODE_FAIL); - - // 3. provide results - mDut.onRangingResults(mIntCaptor.getValue(), result.second); - mMockLooper.dispatchAll(); - - cbInorder.verify(mockCallback).onRangingResults(result.second); - verifyWakeupCancelled(); - - nativeInorder.verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); - verifyWakeupSet(true, 0); - - // 4. issue a request: don't expect a failure - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, useUids ? null : ws, request, - mockCallback); - mMockLooper.dispatchAll(); - - // 5. clear queue - mDut.disable(); - mMockLooper.dispatchAll(); - - verifyWakeupCancelled(); - nativeInorder.verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); - cbInorder.verify(mockCallback, times(RttServiceImpl.MAX_QUEUED_PER_UID)).onRangingFailure( - RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); - - // verify metrics - verify(mockMetrics, times(RttServiceImpl.MAX_QUEUED_PER_UID + 12)).recordRequest( - eq(useUids ? mDefaultWs : ws), eq(request)); - verify(mockMetrics).recordResult(eq(request), eq(result.second), anyInt()); - verify(mockMetrics, times(11)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE); - verify(mockMetrics, times(RttServiceImpl.MAX_QUEUED_PER_UID)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); - verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, - mAlarmManager.getAlarmManager()); - } - - /** - * Validate that when Wi-Fi gets disabled (HAL level) the ranging queue gets cleared. - */ - @Test - public void testDisableWifiFlow() throws Exception { - runDisableRttFlow(FAILURE_MODE_DISABLE_WIFI); - } - - /** - * Validate that when Doze mode starts, RTT gets disabled and the ranging queue gets cleared. - */ - @Test - public void testDozeModeFlow() throws Exception { - runDisableRttFlow(FAILURE_MODE_ENABLE_DOZE); - } - - /** - * Validate that when locationing is disabled, RTT gets disabled and the ranging queue gets - * cleared. - */ - @Test - public void testLocationingOffFlow() throws Exception { - runDisableRttFlow(FAILURE_MODE_DISABLE_LOCATIONING); - } - - - private static final int FAILURE_MODE_DISABLE_WIFI = 0; - private static final int FAILURE_MODE_ENABLE_DOZE = 1; - private static final int FAILURE_MODE_DISABLE_LOCATIONING = 2; - - /** - * Actually execute the disable RTT flow: either by disabling Wi-Fi or enabling doze. - * - * @param failureMode The mechanism by which RTT is to be disabled. One of the FAILURE_MODE_* - * constants above. - */ - private void runDisableRttFlow(int failureMode) throws Exception { - RangingRequest request1 = RttTestUtils.getDummyRangingRequest((byte) 1); - RangingRequest request2 = RttTestUtils.getDummyRangingRequest((byte) 2); - RangingRequest request3 = RttTestUtils.getDummyRangingRequest((byte) 3); - - IRttCallback mockCallback2 = mock(IRttCallback.class); - IRttCallback mockCallback3 = mock(IRttCallback.class); - - // (1) request 2 ranging operations: request 1 should be sent to HAL - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request1, mockCallback); - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request2, mockCallback2); - mMockLooper.dispatchAll(); - - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true)); - verifyWakeupSet(true, 0); - - // (2) disable RTT: all requests should "fail" - if (failureMode == FAILURE_MODE_DISABLE_WIFI) { - when(mockNative.isReady()).thenReturn(false); - mDut.disable(); - } else if (failureMode == FAILURE_MODE_ENABLE_DOZE) { - simulatePowerStateChangeDoze(true); - } else if (failureMode == FAILURE_MODE_DISABLE_LOCATIONING) { - when(mockPermissionUtil.isLocationModeEnabled()).thenReturn(false); - simulateLocationModeChange(); - } - mMockLooper.dispatchAll(); - - assertFalse(mDut.isAvailable()); - validateCorrectRttStatusChangeBroadcast(false); - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); - verify(mockCallback).onRangingFailure( - RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); - verify(mockCallback2).onRangingFailure( - RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); - verifyWakeupCancelled(); - - // (3) issue another request: it should fail - mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request3, mockCallback3); - mMockLooper.dispatchAll(); - - verify(mockCallback3).onRangingFailure( - RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); - - // (4) enable RTT: nothing should happen (no requests in queue!) - if (failureMode == FAILURE_MODE_DISABLE_WIFI) { - when(mockNative.isReady()).thenReturn(true); - mDut.enableIfPossible(); - } else if (failureMode == FAILURE_MODE_ENABLE_DOZE) { - simulatePowerStateChangeDoze(false); - } else if (failureMode == FAILURE_MODE_DISABLE_LOCATIONING) { - when(mockPermissionUtil.isLocationModeEnabled()).thenReturn(true); - simulateLocationModeChange(); - } - mMockLooper.dispatchAll(); - - assertTrue(mDut.isAvailable()); - validateCorrectRttStatusChangeBroadcast(true); - - // verify metrics - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request1)); - verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request2)); - verify(mockMetrics, times(3)).recordOverallStatus( - WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); - - verify(mockNative, atLeastOnce()).isReady(); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, mockCallback2, - mockCallback3, mAlarmManager.getAlarmManager()); - } - - /* - * Utilities - */ - - /** - * Simulate power state change due to doze. Changes the power manager return values and - * dispatches a broadcast. - */ - private void simulatePowerStateChangeDoze(boolean isDozeOn) { - when(mMockPowerManager.isDeviceIdleMode()).thenReturn(isDozeOn); - - Intent intent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - mPowerBcastReceiver.onReceive(mockContext, intent); - } - - /** - * Simulate the broadcast which is dispatched when a LOCATION_MODE is modified. - */ - private void simulateLocationModeChange() { - Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); - mLocationModeReceiver.onReceive(mockContext, intent); - } - - private void verifyWakeupSet(boolean useAwareTimeout, long baseTime) { - ArgumentCaptor<Long> longCaptor = ArgumentCaptor.forClass(Long.class); - - mInOrder.verify(mAlarmManager.getAlarmManager()).setExact(anyInt(), longCaptor.capture(), - eq(RttServiceImpl.HAL_RANGING_TIMEOUT_TAG), any(AlarmManager.OnAlarmListener.class), - any(Handler.class)); - - assertEquals(baseTime + (useAwareTimeout ? RttServiceImpl.HAL_AWARE_RANGING_TIMEOUT_MS - : RttServiceImpl.HAL_RANGING_TIMEOUT_MS), longCaptor.getValue().longValue()); - } - - private void verifyWakeupCancelled() { - mInOrder.verify(mAlarmManager.getAlarmManager()).cancel( - any(AlarmManager.OnAlarmListener.class)); - } - - /** - * Validates that the broadcast sent on RTT status change is correct. - * - * @param expectedEnabled The expected change status - i.e. are we expected to announce that - * RTT is enabled (true) or disabled (false). - */ - private void validateCorrectRttStatusChangeBroadcast(boolean expectedEnabled) { - ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); - - mInOrder.verify(mockContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL)); - assertEquals(intent.getValue().getAction(), WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED); - } - - private class AwareTranslatePeerHandlesToMac extends MockAnswerUtil.AnswerWithArguments { - private int mExpectedUid; - private Map<Integer, MacAddress> mPeerIdToMacMap; - - AwareTranslatePeerHandlesToMac(int expectedUid, Map<Integer, MacAddress> peerIdToMacMap) { - mExpectedUid = expectedUid; - mPeerIdToMacMap = peerIdToMacMap; - } - - public void answer(int uid, List<Integer> peerIds, IWifiAwareMacAddressProvider callback) { - assertEquals("Invalid UID", mExpectedUid, uid); - - Map<Integer, byte[]> result = new HashMap<>(); - for (Integer peerId: peerIds) { - byte[] macBytes = null; - MacAddress macAddr = mPeerIdToMacMap.get(peerId); - if (macAddr != null) { - macBytes = macAddr.toByteArray(); - } - - result.put(peerId, macBytes); - } - - try { - callback.macAddress(result); - } catch (RemoteException e) { - e.printStackTrace(); - } - } - } - - private class BinderDeathAnswerBase extends MockAnswerUtil.AnswerWithArguments { - protected Set<IBinder.DeathRecipient> mUniqueExecs = new HashSet<>(); - } - - private class BinderLinkToDeathAnswer extends BinderDeathAnswerBase { - public void answer(IBinder.DeathRecipient recipient, int flags) { - mUniqueExecs.add(recipient); - } - } - - private class BinderUnlinkToDeathAnswer extends BinderDeathAnswerBase { - public boolean answer(IBinder.DeathRecipient recipient, int flags) { - mUniqueExecs.add(recipient); - return true; - } - } - - private class ClockAnswer extends MockAnswerUtil.AnswerWithArguments { - public long time; - - public long answer() { - return time; - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java b/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java deleted file mode 100644 index a112a7c17..000000000 --- a/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.rtt; - -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.rtt.RangingRequest; -import android.net.wifi.rtt.RangingResult; -import android.net.wifi.rtt.ResponderConfig; -import android.util.Pair; - -import java.util.ArrayList; -import java.util.List; - -/** - * Utilities for the Rtt unit test suite. - */ -public class RttTestUtils { - /** - * Compare the two lists and return true for equality, false otherwise. The two lists are - * considered identical if they have the same number of elements and contain equal elements - * (equality of elements using the equal() operator of the component objects). - * - * Note: null != empty list - */ - public static boolean compareListContentsNoOrdering(List a, List b) { - if (a == b) { - return true; - } - if (a == null || b == null) { - return false; // at this point they're not both null - } - if (a.size() != b.size()) { // at this point neither is null - return false; - } - return a.containsAll(b) && b.containsAll(a); - } - - /** - * Returns a dummy ranging request with 3 requests: - * - First: 802.11mc capable - * - Second: 802.11mc not capable - * - Third: Aware peer - */ - public static RangingRequest getDummyRangingRequest(byte lastMacByte) { - RangingRequest.Builder builder = new RangingRequest.Builder(); - - ScanResult scan1 = new ScanResult(); - scan1.BSSID = "00:01:02:03:04:" + String.format("%02d", lastMacByte); - scan1.setFlag(ScanResult.FLAG_80211mc_RESPONDER); - scan1.channelWidth = ScanResult.CHANNEL_WIDTH_40MHZ; - ScanResult scan2 = new ScanResult(); - scan2.BSSID = "0A:0B:0C:0D:0E:" + String.format("%02d", lastMacByte); - scan2.channelWidth = ScanResult.CHANNEL_WIDTH_20MHZ; - MacAddress mac1 = MacAddress.fromString("08:09:08:07:06:05"); - - builder.addAccessPoint(scan1); - builder.addAccessPoint(scan2); - builder.addWifiAwarePeer(mac1); - - return builder.build(); - } - - /** - * Returns a dummy ranging request with 2 requests: - * - First: 802.11mc capable - */ - public static RangingRequest getDummyRangingRequestMcOnly(byte lastMacByte) { - RangingRequest.Builder builder = new RangingRequest.Builder(); - - ScanResult scan1 = new ScanResult(); - scan1.BSSID = "00:01:02:03:04:" + String.format("%02d", lastMacByte); - scan1.setFlag(ScanResult.FLAG_80211mc_RESPONDER); - scan1.channelWidth = ScanResult.CHANNEL_WIDTH_40MHZ; - - builder.addAccessPoint(scan1); - - return builder.build(); - } - - /** - * Returns a dummy ranging request with 2 requests - neither of which support 802.11mc. - */ - public static RangingRequest getDummyRangingRequestNo80211mcSupport(byte lastMacByte) { - RangingRequest.Builder builder = new RangingRequest.Builder(); - - ScanResult scan1 = new ScanResult(); - scan1.BSSID = "00:01:02:03:04:" + String.format("%02d", lastMacByte); - ScanResult scan2 = new ScanResult(); - scan2.BSSID = "0A:0B:0C:0D:0E:" + String.format("%02d", lastMacByte); - - builder.addAccessPoint(scan1); - builder.addAccessPoint(scan2); - - return builder.build(); - } - - /** - * Returns a matched set of dummy ranging results: HAL RttResult and the public API - * RangingResult. - * - * @param request If non-null will be used as a template (BSSID) for the range results. - */ - public static Pair<List<RangingResult>, List<RangingResult>> getDummyRangingResults( - RangingRequest request) { - int rangeCmBase = 15; - int rangeStdDevCmBase = 3; - int rssiBase = -20; - long rangeTimestampBase = 666; - List<RangingResult> halResults = new ArrayList<>(); - List<RangingResult> results = new ArrayList<>(); - - if (request != null) { - for (ResponderConfig peer: request.mRttPeers) { - RangingResult rangingResult; - halResults.add(new RangingResult(RangingResult.STATUS_SUCCESS, - peer.macAddress, rangeCmBase, rangeStdDevCmBase, rssiBase, - 8, 5, null, null, null, rangeTimestampBase)); - if (peer.peerHandle == null) { - rangingResult = new RangingResult(RangingResult.STATUS_SUCCESS, - peer.macAddress, rangeCmBase++, rangeStdDevCmBase++, rssiBase++, - 8, 5, null, null, null, rangeTimestampBase++); - } else { - rangingResult = new RangingResult(RangingResult.STATUS_SUCCESS, - peer.peerHandle, rangeCmBase++, rangeStdDevCmBase++, rssiBase++, - 8, 5, null, null, null, rangeTimestampBase++); - } - results.add(rangingResult); - - } - } else { - results.add(new RangingResult(RangingResult.STATUS_SUCCESS, - MacAddress.fromString("10:01:02:03:04:05"), rangeCmBase++, - rangeStdDevCmBase++, rssiBase++, 8, 4, null, null, - null, rangeTimestampBase++)); - results.add(new RangingResult(RangingResult.STATUS_SUCCESS, - MacAddress.fromString("1A:0B:0C:0D:0E:0F"), rangeCmBase++, - rangeStdDevCmBase++, rssiBase++, 9, 3, null, null, - null, rangeTimestampBase++)); - results.add(new RangingResult(RangingResult.STATUS_SUCCESS, - MacAddress.fromString("08:09:08:07:06:05"), rangeCmBase++, - rangeStdDevCmBase++, rssiBase++, 10, 2, null, null, - null, rangeTimestampBase++)); - halResults.addAll(results); - } - - return new Pair<>(halResults, results); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/BackgroundScanSchedulerTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/BackgroundScanSchedulerTest.java deleted file mode 100644 index 54e0c6907..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/BackgroundScanSchedulerTest.java +++ /dev/null @@ -1,869 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder; -import static com.android.server.wifi.ScanTestUtil.assertNativeScanSettingsEquals; -import static com.android.server.wifi.ScanTestUtil.channelsToSpec; -import static com.android.server.wifi.ScanTestUtil.createRequest; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.validateMockitoUsage; - -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ScanSettings; -import android.util.ArraySet; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.WifiNative.BucketSettings; -import com.android.server.wifi.scanner.KnownBandsChannelHelper.KnownBandsChannelCollection; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.scanner.BackgroundScanScheduler}. - */ -@SmallTest -public class BackgroundScanSchedulerTest extends WifiBaseTest { - - private static final int DEFAULT_MAX_BUCKETS = 9; - private static final int DEFAULT_MAX_CHANNELS_PER_BUCKET = 23; - private static final int DEFAULT_MAX_BATCH = 11; - private static final int DEFAULT_MAX_AP_PER_SCAN = 33; - - private KnownBandsChannelHelper mChannelHelper; - private BackgroundScanScheduler mScheduler; - - @Before - public void setUp() throws Exception { - mChannelHelper = new PresetKnownBandsChannelHelper( - new int[]{2400, 2450}, - new int[]{5150, 5175}, - new int[]{5600, 5650, 5660}, - new int[]{5945, 5985}); - mScheduler = new BackgroundScanScheduler(mChannelHelper); - mScheduler.setMaxBuckets(DEFAULT_MAX_BUCKETS); - mScheduler.setMaxChannelsPerBucket(DEFAULT_MAX_CHANNELS_PER_BUCKET); - mScheduler.setMaxBatch(DEFAULT_MAX_BATCH); - mScheduler.setMaxApPerScan(DEFAULT_MAX_AP_PER_SCAN); - } - - @After - public void cleanup() { - validateMockitoUsage(); - } - - @Test - public void noRequest() { - Collection<ScanSettings> requests = Collections.emptyList(); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals(30000, schedule.base_period_ms); - assertBuckets(schedule, 0); - } - - @Test - public void singleRequest() { - Collection<ScanSettings> requests = Collections.singleton(createRequest( - WifiScanner.WIFI_BAND_BOTH, 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - )); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals(30000, schedule.base_period_ms); - assertBuckets(schedule, 1); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - } - - @Test - public void singleRequestWithoutPredefinedBucket() { - Collection<ScanSettings> requests = Collections.singleton(createRequest( - WifiScanner.WIFI_BAND_BOTH, 7500, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - )); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 1); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - } - - @Test - public void fewRequests() { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - requests.add(createRequest(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY, 14000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - } - - @Test - public void manyRequests() { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - requests.add(createRequest(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY, 15000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - requests.add(createRequest(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY, 10000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, false); - } - } - - @Test - public void requestsWithNoPeriodCommonDenominator() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(WifiScanner.WIFI_BAND_BOTH, 299999, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - requests.add(createRequest(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY, 10500, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - } - - @Test - public void manyRequestsDifferentReportScans() { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(5175), 60000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL)); - requests.add(createRequest(channelsToSpec(2400), 60000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(2450), 60000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - requests.add(createRequest(channelsToSpec(5150), 60000, 0, 20, - WifiScanner.REPORT_EVENT_NO_BATCH)); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 60000, schedule.base_period_ms); - assertBuckets(schedule, 1); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - } - - @Test - public void exceedMaxBatch() { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(5175), 30000, 10, 20, - WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL)); - - mScheduler.setMaxBatch(5); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 30000, schedule.base_period_ms); - assertBuckets(schedule, 1); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - assertEquals("maxScansToCache", 5, schedule.report_threshold_num_scans); - } - - @Test - public void defaultMaxBatch() { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(5175), 60000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL)); - - mScheduler.setMaxBatch(6); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 60000, schedule.base_period_ms); - assertBuckets(schedule, 1); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - assertEquals("maxScansToCache", 6, schedule.report_threshold_num_scans); - } - - @Test - public void exceedMaxAps() { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(5175), 30000, 10, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxApPerScan(5); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("maxScansToCache", 5, schedule.max_ap_per_scan); - } - - @Test - public void defaultMaxAps() { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(5175), 30000, 10, 0, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxApPerScan(8); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("maxApsPerScan", 8, schedule.max_ap_per_scan); - } - - @Test - public void optimalScheduleExceedsNumberOfAvailableBuckets() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(2450), 10000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(5150), 120000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(2); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 30000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, true, true); - } - } - - @Test - public void optimalScheduleExceedsNumberOfAvailableBuckets2() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(2450), 60000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(5150), 3840000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(2); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 30000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, true, true); - } - } - - /** - * Ensure that a channel request is placed in the bucket closest to the original - * period and not the bucket it is initially placed in. Here the 5 min period is - * initially placed in the 240s bucket, but that bucket is eliminated because it - * would be a 7th bucket. This test ensures that the request is placed in the 480s - * bucket and not the 120s bucket. - */ - @Test - public void optimalScheduleExceedsNumberOfAvailableBucketsClosestToOriginal() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400), 30 * 1000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(2450), 120 * 1000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(5150), 480 * 1000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(5175), 10 * 1000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(5600), 60 * 1000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(5650), 1920 * 1000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - requests.add(createRequest(channelsToSpec(5660), 300 * 1000, 0, 20, // 5 min - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(6); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 6); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, true, true); - } - } - - @Test - public void optimalScheduleExceedsMaxChannelsOnSingleBand() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400, 2450), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(2); - mScheduler.setMaxChannelsPerBucket(1); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 30000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, true, true); - } - } - - @Test - public void optimalScheduleExceedsMaxChannelsOnMultipleBands() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400, 2450, 5150), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(2); - mScheduler.setMaxChannelsPerBucket(2); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 30000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, true, true); - } - } - - @Test - public void optimalScheduleExceedsMaxChannelsOnMultipleBandsFromMultipleRequests() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400, 2450), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(WifiScanner.WIFI_BAND_5_GHZ, 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(2); - mScheduler.setMaxChannelsPerBucket(2); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 30000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, true, true); - } - } - - @Test - public void exactRequests() { - scheduleAndTestExactRequest(createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, 0, - 20, WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL)); - scheduleAndTestExactRequest(createRequest(WifiScanner.WIFI_BAND_5_GHZ, 60000, 3, - 13, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - scheduleAndTestExactRequest(createRequest(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY, 10000, 2, - 10, WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)); - scheduleAndTestExactRequest(createRequest(WifiScanner.WIFI_BAND_BOTH, 25000, 0, - 10, WifiScanner.REPORT_EVENT_NO_BATCH)); - scheduleAndTestExactRequest(createRequest(WifiScanner.WIFI_BAND_BOTH, 25000, 3, - 0, WifiScanner.REPORT_EVENT_NO_BATCH)); - scheduleAndTestExactRequest(createRequest(channelsToSpec(2400, 5175, 5650) , 25000, 3, - 0, WifiScanner.REPORT_EVENT_NO_BATCH)); - } - - @Test - public void singleExponentialBackOffRequest() { - Collection<ScanSettings> requests = Collections.singleton(createRequest( - WifiScanner.SCAN_TYPE_LOW_LATENCY, WifiScanner.WIFI_BAND_BOTH, - 30000, 160000, 2, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN - )); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals(30000, schedule.base_period_ms); - assertBuckets(schedule, 1); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - } - - @Test - public void exponentialBackOffAndRegularRequests() { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(WifiScanner.SCAN_TYPE_LOW_LATENCY, WifiScanner.WIFI_BAND_BOTH, - 30000, 200000, 1, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(5175), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL)); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 30000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, true); - } - } - - /** - * Add 2 background scan requests with different time intervals, but one of the setting channels - * is totally contained in the other setting. Ensure that the requests are collapsed into a - * common bucket with the lower time period setting. - */ - @Test - public void optimalScheduleFullyCollapsesDuplicateChannelsInBand() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400, 2450), 240000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(WifiScanner.WIFI_BAND_24_GHZ, 10000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(2); - mScheduler.setMaxChannelsPerBucket(2); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 1); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, false); - } - - assertEquals("scheduled bucket", 0, mScheduler.getScheduledBucket(requests.get(0))); - assertEquals("scheduled bucket", 0, mScheduler.getScheduledBucket(requests.get(1))); - - KnownBandsChannelCollection collection = mChannelHelper.createChannelCollection(); - collection.addBand(WifiScanner.WIFI_BAND_24_GHZ); - Set<Integer> expectedBucketChannelSet = collection.getAllChannels(); - assertBucketChannels(schedule.buckets[0], expectedBucketChannelSet); - } - - /** - * Add 2 background scan requests with different time intervals, but one of the setting channels - * is totally contained in the other setting. Ensure that the requests are collapsed into a - * common bucket with the lower time period setting. - */ - @Test - public void optimalScheduleFullyCollapsesDuplicateChannels() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400, 2450), 240000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(2400, 2450), 10000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(2); - mScheduler.setMaxChannelsPerBucket(2); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 1); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, false); - } - - assertEquals("scheduled bucket", 0, mScheduler.getScheduledBucket(requests.get(0))); - assertEquals("scheduled bucket", 0, mScheduler.getScheduledBucket(requests.get(1))); - - Set<Integer> expectedBucketChannelSet = new ArraySet<>(); - expectedBucketChannelSet.add(2400); - expectedBucketChannelSet.add(2450); - assertBucketChannels(schedule.buckets[0], expectedBucketChannelSet); - } - - /** - * Add 2 background scan requests with different time intervals, but one of the setting channels - * is partially contained in the other setting. Ensure that the requests are partially split - * across the lower time period bucket. - */ - @Test - public void optimalSchedulePartiallyCollapsesDuplicateChannels() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400, 2450), 10000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(2400, 2450, 5175), 240000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(2); - mScheduler.setMaxChannelsPerBucket(2); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 2); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, false); - } - - assertEquals("scheduled bucket", 0, mScheduler.getScheduledBucket(requests.get(0))); - assertEquals("scheduled bucket", 1, mScheduler.getScheduledBucket(requests.get(1))); - - Set<Integer> expectedBucketChannelSet = new ArraySet<>(); - expectedBucketChannelSet.add(2400); - expectedBucketChannelSet.add(2450); - assertBucketChannels(schedule.buckets[0], expectedBucketChannelSet); - - expectedBucketChannelSet.clear(); - expectedBucketChannelSet.add(5175); - assertBucketChannels(schedule.buckets[1], expectedBucketChannelSet); - } - - /** - * Add 2 background scan requests with different time intervals, but one of the setting channels - * is partially contained in the 2 other settings. Ensure that the requests are partially split - * across the lower time period buckets. - */ - @Test - public void optimalSchedulePartiallyCollapsesDuplicateChannelsAcrossMultipleBuckets() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400, 2450), 10000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(2400, 2450, 5175), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 240000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(3); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 3); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, false); - } - - assertEquals("scheduled bucket", 0, mScheduler.getScheduledBucket(requests.get(0))); - assertEquals("scheduled bucket", 1, mScheduler.getScheduledBucket(requests.get(1))); - assertEquals("scheduled bucket", 2, mScheduler.getScheduledBucket(requests.get(2))); - - Set<Integer> expectedBucketChannelSet = new ArraySet<>(); - expectedBucketChannelSet.add(2400); - expectedBucketChannelSet.add(2450); - assertBucketChannels(schedule.buckets[0], expectedBucketChannelSet); - - expectedBucketChannelSet.clear(); - expectedBucketChannelSet.add(5175); - assertBucketChannels(schedule.buckets[1], expectedBucketChannelSet); - - KnownBandsChannelCollection collection = mChannelHelper.createChannelCollection(); - collection.addBand(WifiScanner.WIFI_BAND_BOTH_WITH_DFS); - expectedBucketChannelSet = collection.getAllChannels(); - expectedBucketChannelSet.remove(5175); - expectedBucketChannelSet.remove(2400); - expectedBucketChannelSet.remove(2450); - assertBucketChannels(schedule.buckets[2], expectedBucketChannelSet); - } - - /** - * Add 2 background scan requests with different time intervals, but one of the setting channels - * is partially contained in the 2 other settings. Ensure that the requests are partially split - * across the lower time period buckets and the last bucket is split into 2 because the - * channel list does not fit into a single bucket. - */ - @Test - public void optimalSchedulePartiallyCollapsesDuplicateChannelsWithSplitBuckets() { - ArrayList<ScanSettings> requests = new ArrayList<>(); - requests.add(createRequest(channelsToSpec(2400, 2450), 10000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(channelsToSpec(2400, 2450, 5175), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - requests.add(createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 240000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)); - - mScheduler.setMaxBuckets(5); - mScheduler.setMaxChannelsPerBucket(2); - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - assertEquals("base_period_ms", 10000, schedule.base_period_ms); - assertBuckets(schedule, 4); - for (ScanSettings request : requests) { - assertSettingsSatisfied(schedule, request, false, false); - } - - assertEquals("scheduled bucket", 0, mScheduler.getScheduledBucket(requests.get(0))); - assertEquals("scheduled bucket", 1, mScheduler.getScheduledBucket(requests.get(1))); - assertEquals("scheduled bucket", 2, mScheduler.getScheduledBucket(requests.get(2))); - - Set<Integer> expectedBucketChannelSet = new ArraySet<>(); - expectedBucketChannelSet.add(2400); - expectedBucketChannelSet.add(2450); - assertBucketChannels(schedule.buckets[0], expectedBucketChannelSet); - - expectedBucketChannelSet.clear(); - expectedBucketChannelSet.add(5175); - assertBucketChannels(schedule.buckets[1], expectedBucketChannelSet); - - KnownBandsChannelCollection collection = mChannelHelper.createChannelCollection(); - collection.addBand(WifiScanner.WIFI_BAND_BOTH_WITH_DFS); - expectedBucketChannelSet = collection.getAllChannels(); - expectedBucketChannelSet.remove(5175); - expectedBucketChannelSet.remove(2400); - expectedBucketChannelSet.remove(2450); - // Check if the combined channel set matches what we expect - Set<Integer> combinedBucketChannelSet = getAllChannels(schedule.buckets[2]); - combinedBucketChannelSet.addAll(getAllChannels(schedule.buckets[3])); - assertChannels(combinedBucketChannelSet, expectedBucketChannelSet); - } - - protected Set<Integer> getAllChannels(BucketSettings bucket) { - KnownBandsChannelCollection collection = mChannelHelper.createChannelCollection(); - collection.addChannels(bucket); - return collection.getAllChannels(); - } - - protected Set<Integer> getAllChannels(WifiScanner.ScanSettings settings) { - KnownBandsChannelCollection collection = mChannelHelper.createChannelCollection(); - collection.addChannels(settings); - return collection.getAllChannels(); - } - - public void scheduleAndTestExactRequest(ScanSettings settings) { - Collection<ScanSettings> requests = new ArrayList<>(); - requests.add(settings); - - mScheduler.updateSchedule(requests); - WifiNative.ScanSettings schedule = mScheduler.getSchedule(); - - int expectedPeriod = computeExpectedPeriod(settings.periodInMs); - NativeScanSettingsBuilder expectedBuilder = new NativeScanSettingsBuilder() - .withBasePeriod(expectedPeriod) - .withMaxApPerScan(settings.numBssidsPerScan == 0 - ? DEFAULT_MAX_AP_PER_SCAN - : settings.numBssidsPerScan) - .withMaxScansToCache(settings.maxScansToCache == 0 - ? DEFAULT_MAX_BATCH - : settings.maxScansToCache); - - if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - expectedBuilder.addBucketWithChannels(expectedPeriod, settings.reportEvents, - settings.channels); - } else { - expectedBuilder.addBucketWithBand(expectedPeriod, settings.reportEvents, settings.band); - } - assertNativeScanSettingsEquals(expectedBuilder.build(), schedule); - } - - private void assertBuckets(WifiNative.ScanSettings schedule, int numBuckets) { - assertEquals("num_buckets", numBuckets, schedule.num_buckets); - assertNotNull("buckets was null", schedule.buckets); - assertEquals("num_buckets and actual buckets", schedule.num_buckets, - schedule.buckets.length); - for (int i = 0; i < numBuckets; i++) { - assertNotNull("bucket[" + i + "] was null", schedule.buckets[i]); - if (schedule.buckets[i].band == WifiScanner.WIFI_BAND_UNSPECIFIED) { - assertTrue("num channels <= 0", schedule.buckets[i].num_channels > 0); - assertTrue("bucket channels > max channels", - schedule.buckets[i].num_channels <= mScheduler.getMaxChannelsPerBucket()); - assertNotNull("Channels was null", schedule.buckets[i].channels); - for (int c = 0; c < schedule.buckets[i].num_channels; c++) { - assertNotNull("Channel was null", schedule.buckets[i].channels[c]); - } - } else { - assertTrue("Invalid band: " + schedule.buckets[i].band, - schedule.buckets[i].band > WifiScanner.WIFI_BAND_UNSPECIFIED - && schedule.buckets[i].band <= WifiScanner.WIFI_BAND_BOTH_WITH_DFS); - } - } - } - - private void assertSettingsSatisfied(WifiNative.ScanSettings schedule, - ScanSettings settings, boolean bucketsLimited, boolean exactPeriod) { - assertTrue("bssids per scan: " + schedule.max_ap_per_scan + " /<= " - + settings.numBssidsPerScan, - schedule.max_ap_per_scan <= settings.numBssidsPerScan); - - if (settings.maxScansToCache > 0) { - assertTrue("scans to cache: " + schedule.report_threshold_num_scans + " /<= " - + settings.maxScansToCache, - schedule.report_threshold_num_scans <= settings.maxScansToCache); - } - - Set<Integer> channelSet = getAllChannels(settings); - - StringBuilder ignoreString = new StringBuilder(); - - KnownBandsChannelCollection scheduleChannels = mChannelHelper.createChannelCollection(); - for (int b = 0; b < schedule.num_buckets; b++) { - BucketSettings bucket = schedule.buckets[b]; - if ((settings.reportEvents & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) != 0) { - if ((bucket.report_events & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) == 0) { - ignoreString - .append(" ") - .append(getAllChannels(bucket)) - .append("=after_each_scan:") - .append(bucket.report_events & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) - .append("!=") - .append(settings.reportEvents - & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - continue; - } - } - if ((settings.reportEvents & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { - if ((bucket.report_events & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) == 0) { - ignoreString - .append(" ") - .append(getAllChannels(bucket)) - .append("=full_result:") - .append(bucket.report_events - & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) - .append("!=") - .append(settings.reportEvents - & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT); - continue; - } - } - if ((settings.reportEvents & WifiScanner.REPORT_EVENT_NO_BATCH) == 0) { - if ((bucket.report_events & WifiScanner.REPORT_EVENT_NO_BATCH) != 0) { - ignoreString - .append(" ") - .append(getAllChannels(bucket)) - .append("=no_batch:") - .append(bucket.report_events & WifiScanner.REPORT_EVENT_NO_BATCH) - .append("!=") - .append(settings.reportEvents & WifiScanner.REPORT_EVENT_NO_BATCH); - continue; - } - } - int expectedPeriod; - - if (settings.maxPeriodInMs != 0 && settings.periodInMs != settings.maxPeriodInMs) { - // exponential back off scan - expectedPeriod = settings.periodInMs; - } else { - if (bucketsLimited) { - expectedPeriod = computeExpectedPeriod(settings.periodInMs, schedule); - } else { - expectedPeriod = computeExpectedPeriod(settings.periodInMs); - } - } - - if (exactPeriod) { - if (bucket.period_ms != expectedPeriod) { - ignoreString - .append(" ") - .append(getAllChannels(bucket)) - .append("=period:") - .append(bucket.period_ms) - .append("!=") - .append(settings.periodInMs); - continue; - } - } else { - if (bucket.period_ms > expectedPeriod) { - ignoreString - .append(" ") - .append(getAllChannels(bucket)) - .append("=period:") - .append(bucket.period_ms) - .append(">") - .append(settings.periodInMs); - continue; - } - } - scheduleChannels.addChannels(bucket); - } - - assertTrue("expected that " + scheduleChannels.getAllChannels() + " contained " - + channelSet + ", Channel ignore reasons:" + ignoreString.toString(), - scheduleChannels.getAllChannels().containsAll(channelSet)); - } - - private void assertBucketChannels(BucketSettings bucket, Set<Integer> expectedChannelSet) { - Set<Integer> bucketChannelSet = getAllChannels(bucket); - assertChannels(bucketChannelSet, expectedChannelSet); - } - - private void assertChannels(Set<Integer> channelSet, Set<Integer> expectedChannelSet) { - assertTrue("expected that " + channelSet + " contained " - + expectedChannelSet, channelSet.containsAll(expectedChannelSet)); - } - - private static int[] getPredefinedBuckets() { - try { - Field f = BackgroundScanScheduler.class.getDeclaredField("PREDEFINED_BUCKET_PERIODS"); - f.setAccessible(true); - return (int[]) f.get(null); - } catch (Exception e) { - throw new RuntimeException("Could not get predefined buckets", e); - } - } - private static final int[] PREDEFINED_BUCKET_PERIODS = getPredefinedBuckets(); - - // find closest bucket period to the requested period - private static int computeExpectedPeriod(int requestedPeriod) { - int period = 0; - int minDiff = Integer.MAX_VALUE; - for (int bucketPeriod : PREDEFINED_BUCKET_PERIODS) { - int diff = Math.abs(bucketPeriod - requestedPeriod); - if (diff < minDiff) { - minDiff = diff; - period = bucketPeriod; - } - } - return period; - } - - // find closest bucket period to the requested period that exists in the schedule - private static int computeExpectedPeriod(int requestedPeriod, - WifiNative.ScanSettings schedule) { - int period = 0; - int minDiff = Integer.MAX_VALUE; - for (int i = 0; i < schedule.num_buckets; ++i) { - int bucketPeriod = schedule.buckets[i].period_ms; - int diff = Math.abs(bucketPeriod - requestedPeriod); - if (diff < minDiff) { - minDiff = diff; - period = bucketPeriod; - } - } - return period; - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java deleted file mode 100644 index 10f475c96..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder; -import static com.android.server.wifi.ScanTestUtil.assertScanDataEquals; -import static com.android.server.wifi.ScanTestUtil.createFreqSet; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.test.TestAlarmManager; -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiSsid; -import android.os.SystemClock; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.MockResources; -import com.android.server.wifi.MockWifiMonitor; -import com.android.server.wifi.ScanDetail; -import com.android.server.wifi.ScanResults; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiMonitor; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -/** - * Base unit tests that should pass for all implementations of - * {@link com.android.server.wifi.scanner.WifiScannerImpl}. - */ -@SmallTest -public abstract class BaseWifiScannerImplTest extends WifiBaseTest { - protected static final String IFACE_NAME = "a_test_interface_name"; - @Mock Context mContext; - TestAlarmManager mAlarmManager; - MockWifiMonitor mWifiMonitor; - TestLooper mLooper; - @Mock WifiNative mWifiNative; - MockResources mResources; - @Mock Clock mClock; - - /** - * mScanner implementation should be filled in by derived test class - */ - WifiScannerImpl mScanner; - - @Before - public void setUpBase() throws Exception { - MockitoAnnotations.initMocks(this); - - mLooper = new TestLooper(); - mAlarmManager = new TestAlarmManager(); - mWifiMonitor = new MockWifiMonitor(); - mResources = new MockResources(); - - when(mWifiNative.getClientInterfaceName()).thenReturn(IFACE_NAME); - - when(mContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - - when(mContext.getResources()).thenReturn(mResources); - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); - } - - protected Set<Integer> expectedBandScanFreqs(int band) { - ChannelCollection collection = mScanner.getChannelHelper().createChannelCollection(); - collection.addBand(band); - return collection.getScanFreqs(); - } - - protected Set<Integer> expectedBandAndChannelScanFreqs(int band, int... channels) { - ChannelCollection collection = mScanner.getChannelHelper().createChannelCollection(); - collection.addBand(band); - for (int channel : channels) { - collection.addChannel(channel); - } - return collection.getScanFreqs(); - } - - @Test - public void singleScanSuccess() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) // ms - .withMaxApPerScan(10) - .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - - doSuccessfulSingleScanTest(settings, - expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), - new ArrayList<String>(), - ScanResults.create(0, WifiScanner.WIFI_BAND_24_GHZ, - 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), false); - } - - @Test - public void singleScanSuccessWithChannels() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5650) - .build(); - - doSuccessfulSingleScanTest(settings, createFreqSet(5650), - new ArrayList<String>(), - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, - 5650, 5650, 5650, 5650, 5650, 5650, 5650, 5650), false); - } - - @Test - public void singleScanSuccessWithChannelsAndHighAccuracyType() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withType(WifiScanner.SCAN_TYPE_HIGH_ACCURACY) - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5650) - .build(); - - doSuccessfulSingleScanTest(settings, createFreqSet(5650), - new ArrayList<String>(), - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, - 5650, 5650, 5650, 5650, 5650, 5650, 5650, 5650), false); - } - - @Test - public void singleScanSuccessWithFullResults() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand(10000, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN - | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - - doSuccessfulSingleScanTest(settings, expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), - new ArrayList<String>(), - ScanResults.create(0, WifiScanner.WIFI_BAND_24_GHZ, - 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), true); - } - - /** - * Tests whether the provided hidden networkId's in scan settings is correctly passed along - * when invoking native scan. - */ - @Test - public void singleScanSuccessWithHiddenNetworkIds() { - String[] hiddenNetworkSSIDs = {"test_ssid_1", "test_ssid_2"}; - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .withHiddenNetworkSSIDs(hiddenNetworkSSIDs) - .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5650) - .build(); - - List<String> hiddenNetworkSSIDSet = new ArrayList<>(); - for (int i = 0; i < hiddenNetworkSSIDs.length; i++) { - hiddenNetworkSSIDSet.add(hiddenNetworkSSIDs[i]); - } - doSuccessfulSingleScanTest(settings, createFreqSet(5650), - hiddenNetworkSSIDSet, - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, - 5650, 5650, 5650, 5650, 5650, 5650, 5650, 5650), false); - } - - /** - * Tests whether the provided hidden networkId's in scan settings is truncated to max size - * supported by wificond when invoking native scan. - */ - @Test - public void singleScanSuccessWithTruncatedHiddenNetworkIds() { - String[] hiddenNetworkSSIDs = { - "test_ssid_0", "test_ssid_1", "test_ssid_2", "test_ssid_3", "test_ssid_4", - "test_ssid_5", "test_ssid_6", "test_ssid_7", "test_ssid_8", "test_ssid_9", - "test_ssid_10", "test_ssid_11", "test_ssid_12", "test_ssid_13", "test_ssid_14", - "test_ssid_15", "test_ssid_16", "test_ssid_17", "test_ssid_18", "test_ssid_19" - }; - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .withHiddenNetworkSSIDs(hiddenNetworkSSIDs) - .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5650) - .build(); - - List<String> hiddenNetworkSSIDSet = new ArrayList<>(); - for (int i = 0; i < WificondScannerImpl.MAX_HIDDEN_NETWORK_IDS_PER_SCAN; i++) { - hiddenNetworkSSIDSet.add(hiddenNetworkSSIDs[i]); - } - doSuccessfulSingleScanTest(settings, createFreqSet(5650), - hiddenNetworkSSIDSet, - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, - 5650, 5650, 5650, 5650, 5650, 5650, 5650), false); - } - - @Test - public void overlappingSingleScanFails() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) // ms - .withMaxApPerScan(10) - .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - - WifiNative.ScanSettings settings2 = new NativeScanSettingsBuilder() - .withBasePeriod(10000) // ms - .withMaxApPerScan(10) - .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_5_GHZ) - .build(); - WifiNative.ScanEventHandler eventHandler2 = mock(WifiNative.ScanEventHandler.class); - - // scan start succeeds - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - assertFalse("second scan while first scan running should fail immediately", - mScanner.startSingleScan(settings2, eventHandler2)); - } - - @Test - public void singleScanFailOnExecute() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - - InOrder order = inOrder(eventHandler, mWifiNative); - - // scan fails - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(false); - - // start scan - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - - mLooper.dispatchAll(); - order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); - - verifyNoMoreInteractions(eventHandler); - } - - /** - * Test that a scan failure is reported if a scan times out - */ - @Test - public void singleScanFailOnTimeout() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - - InOrder order = inOrder(eventHandler, mWifiNative); - - // scan succeeds - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - - // start scan - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - mLooper.dispatchAll(); - - // Fire timeout - mAlarmManager.dispatch(WificondScannerImpl.TIMEOUT_ALARM_TAG); - mLooper.dispatchAll(); - - order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); - - verifyNoMoreInteractions(eventHandler); - } - - /** - * Test that a scan failure is reported if wificond sends a scan failed event - */ - @Test - public void singleScanFailOnFailedEvent() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - - InOrder order = inOrder(eventHandler, mWifiNative); - - // scan succeeds - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - - // start scan - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - mLooper.dispatchAll(); - - // Fire failed event - mWifiMonitor.sendMessage(eq(IFACE_NAME), WifiMonitor.SCAN_FAILED_EVENT); - mLooper.dispatchAll(); - - order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); - - verifyNoMoreInteractions(eventHandler); - } - - @Test - public void singleScanNullEventHandler() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - assertFalse(mScanner.startSingleScan(settings, null)); - } - - @Test - public void singleScanNullSettings() { - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - - assertFalse(mScanner.startSingleScan(null, eventHandler)); - - verifyNoMoreInteractions(eventHandler); - } - - @Test - public void multipleSingleScanSuccess() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - WifiNative.ScanSettings settings2 = new NativeScanSettingsBuilder() - .withType(WifiScanner.SCAN_TYPE_LOW_POWER) - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_BOTH_WITH_DFS) - .build(); - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - InOrder order = inOrder(eventHandler, mWifiNative); - - // scans succeed - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - - // start first scan - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - - expectSuccessfulSingleScan(order, WifiScanner.SCAN_TYPE_LOW_LATENCY, eventHandler, - expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), - new ArrayList<String>(), - ScanResults.create(0, WifiScanner.WIFI_BAND_24_GHZ, - 2400, 2450, 2450), false); - - // start second scan - assertTrue(mScanner.startSingleScan(settings2, eventHandler)); - - expectSuccessfulSingleScan(order, WifiScanner.SCAN_TYPE_LOW_POWER, eventHandler, - expectedBandScanFreqs(WifiScanner.WIFI_BAND_BOTH_WITH_DFS), - new ArrayList<String>(), - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH_WITH_DFS, - 5150, 5175), false); - - verifyNoMoreInteractions(eventHandler); - } - - /** - * Validate that scan results that are returned from wificond, which are timestamped prior to - * the start of the scan, are ignored. - */ - @Test - public void singleScanWhereSupplicantReturnsSomeOldResults() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(2) - .addBucketWithBand(10000, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN - | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - - long approxScanStartUs = mClock.getElapsedSinceBootMillis() * 1000; - ArrayList<ScanDetail> rawResults = new ArrayList<>(Arrays.asList( - new ScanDetail(WifiSsid.createFromAsciiEncoded("TEST AP 1"), - "00:00:00:00:00:00", "", -70, 2450, - approxScanStartUs + 2000 * 1000, 0), - new ScanDetail(WifiSsid.createFromAsciiEncoded("TEST AP 2"), - "AA:BB:CC:DD:EE:FF", "", -66, 2400, - approxScanStartUs + 2500 * 1000, 0), - new ScanDetail(WifiSsid.createFromAsciiEncoded("TEST AP 3"), - "00:00:00:00:00:00", "", -80, 2450, - approxScanStartUs - 2000 * 1000, 0), // old result will be filtered - new ScanDetail(WifiSsid.createFromAsciiEncoded("TEST AP 4"), - "AA:BB:CC:11:22:33", "", -65, 2450, - approxScanStartUs + 4000 * 1000, 0))); - - ArrayList<ScanResult> fullResults = new ArrayList<>(); - for (ScanDetail detail : rawResults) { - if (detail.getScanResult().timestamp > approxScanStartUs) { - fullResults.add(detail.getScanResult()); - } - } - ArrayList<ScanResult> scanDataResults = new ArrayList<>(fullResults); - Collections.sort(scanDataResults, ScanResults.SCAN_RESULT_RSSI_COMPARATOR); - ScanData scanData = new ScanData(0, 0, 0, - WifiScanner.WIFI_BAND_24_GHZ, - scanDataResults.toArray(new ScanResult[scanDataResults.size()])); - Set<Integer> expectedScan = expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ); - - // Actual test - - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - - InOrder order = inOrder(eventHandler, mWifiNative); - - // scan succeeds - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - - // start scan - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - - order.verify(mWifiNative).scan(eq(IFACE_NAME), anyInt(), eq(expectedScan), any(List.class)); - - when(mWifiNative.getScanResults(eq(IFACE_NAME))).thenReturn(rawResults); - - // Notify scan has finished - mWifiMonitor.sendMessage(eq(IFACE_NAME), WifiMonitor.SCAN_RESULTS_EVENT); - - mLooper.dispatchAll(); - - for (ScanResult result : fullResults) { - order.verify(eventHandler).onFullScanResult(eq(result), eq(0)); - } - - order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - assertScanDataEquals(scanData, mScanner.getLatestSingleScanResults()); - - verifyNoMoreInteractions(eventHandler); - } - - @Test - public void backgroundScanNullEventHandler() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - assertFalse(mScanner.startBatchedScan(settings, null)); - } - - @Test - public void backgroundScanNullSettings() { - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - - assertFalse(mScanner.startBatchedScan(null, eventHandler)); - - verifyNoMoreInteractions(eventHandler); - } - - protected void doSuccessfulSingleScanTest(WifiNative.ScanSettings settings, - Set<Integer> expectedScan, List<String> expectedHiddenNetSSIDs, ScanResults results, - boolean expectFullResults) { - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - - InOrder order = inOrder(eventHandler, mWifiNative); - - // scan succeeds - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - - // start scan - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - - expectSuccessfulSingleScan(order, settings.scanType, eventHandler, expectedScan, - expectedHiddenNetSSIDs, results, expectFullResults); - - verifyNoMoreInteractions(eventHandler); - } - - protected void expectSuccessfulSingleScan(InOrder order, - int scanType, WifiNative.ScanEventHandler eventHandler, Set<Integer> expectedScan, - List<String> expectedHiddenNetSSIDs, ScanResults results, boolean expectFullResults) { - order.verify(mWifiNative).scan( - eq(IFACE_NAME), eq(scanType), eq(expectedScan), eq(expectedHiddenNetSSIDs)); - - when(mWifiNative.getScanResults( - eq(IFACE_NAME))).thenReturn(results.getScanDetailArrayList()); - - // Notify scan has finished - mWifiMonitor.sendMessage(eq(IFACE_NAME), WifiMonitor.SCAN_RESULTS_EVENT); - - mLooper.dispatchAll(); - - if (expectFullResults) { - for (ScanResult result : results.getRawScanResults()) { - order.verify(eventHandler).onFullScanResult(eq(result), eq(0)); - } - } - - order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - assertScanDataEquals(results.getScanData(), mScanner.getLatestSingleScanResults()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/ChannelHelperTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/ChannelHelperTest.java deleted file mode 100644 index 28cfd83e8..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/ChannelHelperTest.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.scanner; - -import static com.android.server.wifi.ScanTestUtil.channelsToNativeSettings; -import static com.android.server.wifi.ScanTestUtil.channelsToSpec; -import static com.android.server.wifi.ScanTestUtil.createRequest; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import android.net.wifi.WifiScanner; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiNative; - -import org.junit.Before; -import org.junit.Test; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; - -/** - * Unit tests for {@link com.android.server.wifi.scanner.ChannelHelper}. - */ -@RunWith(Enclosed.class) // WARNING: tests cannot be declared in the outer class -public class ChannelHelperTest extends WifiBaseTest { - - /** - * Unit tests for - * {@link com.android.server.wifi.scanner.ChannelHelper#toString}. - */ - @SmallTest - public static class ToStringTest extends WifiBaseTest { - /** - * Compute a string representing the channels in a ScanSettings with a band set. - */ - @Test - public void scanSettings_band() { - WifiScanner.ScanSettings scanSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - assertEquals("24Ghz & 5Ghz (no DFS)", ChannelHelper.toString(scanSettings)); - } - - /** - * Compute a string representing the channels in a ScanSettings with a list of channels set. - */ - @Test - public void scanSettings_channels() { - WifiScanner.ScanSettings scanSettings = createRequest(channelsToSpec(5150, 2400), - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - assertEquals("[5150,2400]", ChannelHelper.toString(scanSettings)); - } - - /** - * Compute a string representing the channels in a BucketSettings with a band set. - */ - @Test - public void bucketSettings_band() { - WifiScanner.ScanSettings scanSettings = createRequest(WifiScanner.WIFI_BAND_5_GHZ, - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - assertEquals("5Ghz (no DFS)", ChannelHelper.toString(scanSettings)); - } - - /** - * Compute a string representing the channels in a BucketSettings with a list of channels - * set. - */ - @Test - public void bucketSettings_channels() { - WifiScanner.ScanSettings scanSettings = createRequest(channelsToSpec(2400, 5100), - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - assertEquals("[2400,5100]", ChannelHelper.toString(scanSettings)); - } - } - - /** - * Unit tests for - * {@link com.android.server.wifi.scanner.ChannelHelper#bandToString}. - */ - @Test - public void bandToString_ShouldReturnApproapriateString() { - assertEquals("unspecified", ChannelHelper.bandToString( - WifiScanner.WIFI_BAND_UNSPECIFIED)); - assertEquals("24Ghz", ChannelHelper.bandToString(WifiScanner.WIFI_BAND_24_GHZ)); - assertEquals("5Ghz (no DFS)", ChannelHelper.bandToString(WifiScanner.WIFI_BAND_5_GHZ)); - assertEquals("5Ghz (DFS only)", ChannelHelper.bandToString( - WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY)); - assertEquals("5Ghz (DFS incl)", ChannelHelper.bandToString( - WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS)); - assertEquals("24Ghz & 5Ghz (no DFS)", ChannelHelper.bandToString( - WifiScanner.WIFI_BAND_BOTH)); - assertEquals("24Ghz & 5Ghz (DFS incl)", ChannelHelper.bandToString( - WifiScanner.WIFI_BAND_BOTH_WITH_DFS)); - assertEquals("24Ghz & 5Ghz (DFS incl) & 6Ghz", ChannelHelper.bandToString( - WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ)); - assertEquals("invalid band", ChannelHelper.bandToString(-235342)); - } - - /** - * Unit tests for - * {@link com.android.server.wifi.scanner.ChannelHelper.ChannelCollection}. - */ - @SmallTest - public static class ChannelCollectionTest extends WifiBaseTest { - ChannelHelper.ChannelCollection mChannelCollection; - - /** - * Called before each test - * Create an instance of ChannelCollection that calls all real methods, but allows mocking - * of abstract methods. - */ - @Before - public void setUp() throws Exception { - mChannelCollection = mock(ChannelHelper.ChannelCollection.class); - doCallRealMethod().when(mChannelCollection) - .addChannels(any(WifiScanner.ScanSettings.class)); - doCallRealMethod().when(mChannelCollection) - .addChannels(any(WifiNative.BucketSettings.class)); - } - - /** - * Verify adding channels from a WifiScanner.ScanSettings with channels - */ - @Test - public void addChannelsWifiScanner_channels() { - WifiScanner.ScanSettings testSettings = createRequest(channelsToSpec(5150, 2400), - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - - mChannelCollection.addChannels(testSettings); - - verify(mChannelCollection).addChannel(2400); - verify(mChannelCollection).addChannel(5150); - } - - /** - * Verify adding channels from a WifiScanner.ScanSettings with bands - */ - @Test - public void addChannelsWifiScanner_band() { - WifiScanner.ScanSettings testSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - - mChannelCollection.addChannels(testSettings); - - verify(mChannelCollection).addBand(WifiScanner.WIFI_BAND_BOTH); - } - - /** - * Verify adding channels from a WifiNative.BucketSetting with channels - */ - @Test - public void addChannelsWifiNativeBucket_channels() { - WifiNative.BucketSettings testBucket = new WifiNative.BucketSettings(); - testBucket.band = WifiScanner.WIFI_BAND_UNSPECIFIED; - testBucket.num_channels = 2; - testBucket.channels = channelsToNativeSettings(2450, 5100); - - mChannelCollection.addChannels(testBucket); - - verify(mChannelCollection).addChannel(2450); - verify(mChannelCollection).addChannel(5100); - } - - /** - * Verify adding channels from a WifiNative.BucketSetting with bands - */ - @Test - public void addChannelsWifiNativeBucket_band() { - WifiNative.BucketSettings testBucket = new WifiNative.BucketSettings(); - testBucket.band = WifiScanner.WIFI_BAND_5_GHZ; - - mChannelCollection.addChannels(testBucket); - - verify(mChannelCollection).addBand(WifiScanner.WIFI_BAND_5_GHZ); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/HalWifiScannerTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/HalWifiScannerTest.java deleted file mode 100644 index 7cc0367b9..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/HalWifiScannerTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import static com.android.server.wifi.ScanTestUtil.setupMockChannels; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; - -/** - * Unit tests for {@link com.android.server.wifi.scanner.HalWifiScannerImpl}. - */ -@SmallTest -public class HalWifiScannerTest extends BaseWifiScannerImplTest { - - @Before - public void setUp() throws Exception { - setupMockChannels(mWifiNative, - new int[]{2400, 2450}, - new int[]{5150, 5175}, - new int[]{5600, 5650}, - new int[]{5945, 5985}); - mScanner = new HalWifiScannerImpl(mContext, BaseWifiScannerImplTest.IFACE_NAME, - mWifiNative, mWifiMonitor, mLooper.getLooper(), mClock); - } - - // Subtle: tests are inherited from base class. -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/KnownBandsChannelHelperTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/KnownBandsChannelHelperTest.java deleted file mode 100644 index 3e7ad7166..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/KnownBandsChannelHelperTest.java +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.scanner; - -import static com.android.server.wifi.ScanTestUtil.bandIs; -import static com.android.server.wifi.ScanTestUtil.channelsAre; -import static com.android.server.wifi.ScanTestUtil.channelsToSpec; -import static com.android.server.wifi.ScanTestUtil.createRequest; - -import static org.hamcrest.MatcherAssert.assertThat; -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 android.net.wifi.WifiScanner; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiNative; - -import org.junit.Before; -import org.junit.Test; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; - -/** - * Unit tests for {@link com.android.server.wifi.scanner.KnownBandsChannelHelper}. - */ -@RunWith(Enclosed.class) // WARNING: tests cannot be declared in the outer class -public class KnownBandsChannelHelperTest { - - private static final int[] CHANNELS_24_GHZ = new int[]{2412, 2450}; - private static final int[] CHANNELS_5_GHZ = new int[]{5160, 5175}; - private static final int[] CHANNELS_DFS = new int[]{5600, 5650, 5660}; - private static final int[] CHANNELS_DFS_OTHER = new int[]{5600, 5650, 5660, 5680}; - private static final int[] CHANNELS_6_GHZ = new int[]{5945, 5985}; - - /** - * Unit tests for - * {@link com.android.server.wifi.scanner.KnownBandsChannelHelper.estimateScanDuration}. - */ - @SmallTest - public static class EstimateScanDurationTest extends WifiBaseTest { - KnownBandsChannelHelper mChannelHelper; - - /** - * Called before each test - * Create a channel helper - */ - @Before - public void setUp() throws Exception { - mChannelHelper = new PresetKnownBandsChannelHelper( - CHANNELS_24_GHZ, - CHANNELS_5_GHZ, - CHANNELS_DFS, - CHANNELS_6_GHZ); - } - - /** - * check a settings object with a few channels - */ - @Test - public void fewChannels() { - WifiScanner.ScanSettings testSettings = createRequest(channelsToSpec(2412, 2450, 5200), - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - - assertEquals(ChannelHelper.SCAN_PERIOD_PER_CHANNEL_MS * 3, - mChannelHelper.estimateScanDuration(testSettings)); - } - - /** - * check a settings object with a band - */ - @Test - public void band() { - WifiScanner.ScanSettings testSettings = createRequest(WifiScanner.WIFI_BAND_24_GHZ, - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - - assertEquals(ChannelHelper.SCAN_PERIOD_PER_CHANNEL_MS * CHANNELS_24_GHZ.length, - mChannelHelper.estimateScanDuration(testSettings)); - } - } - - /** - * Unit tests for - * {@link com.android.server.wifi.scanner.KnownBandsChannelHelper.getAvailableScanChannels}. - */ - @SmallTest - public static class GetAvailableScanChannelsTest extends WifiBaseTest { - KnownBandsChannelHelper mChannelHelper; - - /** - * Called before each test - * Create a channel helper - */ - @Before - public void setUp() throws Exception { - mChannelHelper = new PresetKnownBandsChannelHelper( - CHANNELS_24_GHZ, - CHANNELS_5_GHZ, - CHANNELS_DFS, - CHANNELS_6_GHZ); - } - - private void testBand(int[] expectedChannels, int band) { - WifiScanner.ChannelSpec[][] channels = - mChannelHelper.getAvailableScanChannels(band); - int len = 0; - for (int i = 0; i < channels.length; ++i) { - len += channels[i].length; - } - assertEquals("num channels", expectedChannels.length, len); - int index = 0; - for (int i = 0; i < channels.length; ++i) { - for (int j = 0; j < channels[i].length; ++j) { - assertEquals("channels[" + index + "].frequency", - expectedChannels[index++], channels[i][j].frequency); - } - } - } - - /** - * test the 2.4GHz band - */ - @Test - public void channels24Ghz() { - testBand(CHANNELS_24_GHZ, WifiScanner.WIFI_BAND_24_GHZ); - } - - /** - * test the 5GHz band - */ - @Test - public void channels5Ghz() { - testBand(CHANNELS_5_GHZ, WifiScanner.WIFI_BAND_5_GHZ); - } - - /** - * test the 5GHz DFS band - */ - @Test - public void channelsDfs() { - testBand(CHANNELS_DFS, WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY); - } - - /** - * test the 2.4GHz and 5GHz band - */ - @Test - public void channels24GhzAnd5Ghz() { - int[] expectedChannels = new int[CHANNELS_24_GHZ.length + CHANNELS_5_GHZ.length]; - System.arraycopy(CHANNELS_24_GHZ, 0, expectedChannels, 0, CHANNELS_24_GHZ.length); - System.arraycopy(CHANNELS_5_GHZ, 0, expectedChannels, CHANNELS_24_GHZ.length, - CHANNELS_5_GHZ.length); - testBand(expectedChannels, WifiScanner.WIFI_BAND_BOTH); - } - - /** - * test all bands - */ - @Test - public void channelsAll() { - int[] expectedChannels = - new int[CHANNELS_24_GHZ.length + CHANNELS_5_GHZ.length + CHANNELS_DFS.length]; - System.arraycopy(CHANNELS_24_GHZ, 0, expectedChannels, 0, CHANNELS_24_GHZ.length); - System.arraycopy(CHANNELS_5_GHZ, 0, expectedChannels, CHANNELS_24_GHZ.length, - CHANNELS_5_GHZ.length); - System.arraycopy(CHANNELS_DFS, 0, expectedChannels, - CHANNELS_24_GHZ.length + CHANNELS_5_GHZ.length, - CHANNELS_DFS.length); - testBand(expectedChannels, WifiScanner.WIFI_BAND_BOTH_WITH_DFS); - } - } - - /** - * Unit tests for - * {@link com.android.server.wifi.scanner.KnownBandsChannelHelper.settingsContainChannel}. - */ - @SmallTest - public static class SettingsContainChannelTest extends WifiBaseTest { - KnownBandsChannelHelper mChannelHelper; - - /** - * Called before each test - * Create a channel helper - */ - @Before - public void setUp() throws Exception { - mChannelHelper = new PresetKnownBandsChannelHelper( - CHANNELS_24_GHZ, - CHANNELS_5_GHZ, - CHANNELS_DFS, - CHANNELS_6_GHZ); - } - - /** - * check a settings object with no channels - */ - @Test - public void emptySettings() { - WifiScanner.ScanSettings testSettings = createRequest(channelsToSpec(), - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - - assertFalse(mChannelHelper.settingsContainChannel(testSettings, 2412)); - assertFalse(mChannelHelper.settingsContainChannel(testSettings, 5160)); - assertFalse(mChannelHelper.settingsContainChannel(testSettings, 5650)); - } - - /** - * check a settings object with some channels - */ - @Test - public void settingsWithChannels() { - WifiScanner.ScanSettings testSettings = createRequest(channelsToSpec(2412, 5650), - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - - assertTrue(mChannelHelper.settingsContainChannel(testSettings, 2412)); - assertFalse(mChannelHelper.settingsContainChannel(testSettings, 5160)); - assertTrue(mChannelHelper.settingsContainChannel(testSettings, 5650)); - } - - /** - * check a settings object with a band specified - */ - @Test - public void settingsWithBand() { - WifiScanner.ScanSettings testSettings = createRequest(WifiScanner.WIFI_BAND_24_GHZ, - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - - assertTrue(mChannelHelper.settingsContainChannel(testSettings, 2412)); - assertTrue(mChannelHelper.settingsContainChannel(testSettings, 2450)); - assertFalse(mChannelHelper.settingsContainChannel(testSettings, 5160)); - assertFalse(mChannelHelper.settingsContainChannel(testSettings, 5650)); - } - - /** - * check a settings object with multiple bands specified - */ - @Test - public void settingsWithMultiBand() { - WifiScanner.ScanSettings testSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, - 10000, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - - assertTrue(mChannelHelper.settingsContainChannel(testSettings, 2412)); - assertTrue(mChannelHelper.settingsContainChannel(testSettings, 2450)); - assertTrue(mChannelHelper.settingsContainChannel(testSettings, 5160)); - assertFalse(mChannelHelper.settingsContainChannel(testSettings, 5650)); - } - } - - /** - * Unit tests for - * {@link com.android.server.wifi.scanner.KnownBandsChannelHelper#equals(ChannelHelper)}. - */ - @SmallTest - public static class EqualsTest extends WifiBaseTest { - /** - * Creates 2 channel helper instances which are equal. - */ - @Test - public void channelHelpersAreSatisfiedBySame() { - KnownBandsChannelHelper channelHelper0 = new PresetKnownBandsChannelHelper( - CHANNELS_24_GHZ, - CHANNELS_5_GHZ, - CHANNELS_DFS, - CHANNELS_6_GHZ); - KnownBandsChannelHelper channelHelper1 = new PresetKnownBandsChannelHelper( - CHANNELS_24_GHZ, - CHANNELS_5_GHZ, - CHANNELS_DFS, - CHANNELS_6_GHZ); - assertTrue(channelHelper0.satisfies(channelHelper1)); - } - - /** - * Creates 2 channel helper instances which are equal. - */ - @Test - public void channelHelpersAreNotSatisfiedByDifferent() { - KnownBandsChannelHelper channelHelper0 = new PresetKnownBandsChannelHelper( - CHANNELS_24_GHZ, - CHANNELS_5_GHZ, - CHANNELS_DFS, - CHANNELS_6_GHZ); - KnownBandsChannelHelper channelHelper1 = new PresetKnownBandsChannelHelper( - CHANNELS_24_GHZ, - CHANNELS_5_GHZ, - CHANNELS_DFS_OTHER, - CHANNELS_6_GHZ); - assertFalse(channelHelper0.satisfies(channelHelper1)); - } - } - - /** - * Unit tests for - * {@link com.android.server.wifi.scanner.KnownBandsChannelHelper.KnownBandsChannelCollection}. - */ - @SmallTest - public static class KnownBandsChannelCollectionTest extends WifiBaseTest { - ChannelHelper.ChannelCollection mChannelCollection; - - /** - * Called before each test - * Create a collection to use for each test - */ - @Before - public void setUp() throws Exception { - KnownBandsChannelHelper channelHelper = new PresetKnownBandsChannelHelper( - CHANNELS_24_GHZ, - CHANNELS_5_GHZ, - CHANNELS_DFS, - CHANNELS_6_GHZ); - mChannelCollection = channelHelper.createChannelCollection(); - } - - /** - * Create an empty collection - */ - @Test - public void empty() { - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, channelsAre()); - - assertEquals(Collections.<Integer>emptySet(), - mChannelCollection.getScanFreqs()); - - assertTrue(mChannelCollection.isEmpty()); - assertFalse(mChannelCollection.containsChannel(2412)); - assertFalse(mChannelCollection.containsChannel(5160)); - assertFalse(mChannelCollection.isAllChannels()); - } - - /** - * Add something to a collection and then clear it and make sure nothing is in it - */ - @Test - public void clear() { - mChannelCollection.addBand(WifiScanner.WIFI_BAND_24_GHZ); - mChannelCollection.clear(); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, channelsAre()); - - assertEquals(Collections.<Integer>emptySet(), - mChannelCollection.getScanFreqs()); - - assertTrue(mChannelCollection.isEmpty()); - assertFalse(mChannelCollection.containsChannel(2412)); - assertFalse(mChannelCollection.containsChannel(5160)); - assertFalse(mChannelCollection.isAllChannels()); - } - - /** - * Add a single band to the collection - */ - @Test - public void addBand() { - mChannelCollection.addBand(WifiScanner.WIFI_BAND_24_GHZ); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, bandIs(WifiScanner.WIFI_BAND_24_GHZ)); - - assertEquals(new HashSet<Integer>(Arrays.asList(2412, 2450)), - mChannelCollection.getScanFreqs()); - - assertFalse(mChannelCollection.isEmpty()); - assertTrue(mChannelCollection.containsChannel(2412)); - assertFalse(mChannelCollection.containsChannel(5160)); - assertFalse(mChannelCollection.isAllChannels()); - } - - /** - * Add a single channel to the collection - */ - @Test - public void addChannel_single() { - mChannelCollection.addChannel(2412); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, channelsAre(2412)); - - assertEquals(new HashSet<Integer>(Arrays.asList(2412)), - mChannelCollection.getScanFreqs()); - - assertFalse(mChannelCollection.isEmpty()); - assertTrue(mChannelCollection.containsChannel(2412)); - assertFalse(mChannelCollection.containsChannel(5160)); - assertFalse(mChannelCollection.isAllChannels()); - } - - /** - * Add a multiple channels to the collection - */ - @Test - public void addChannel_multiple() { - mChannelCollection.addChannel(2412); - mChannelCollection.addChannel(2450); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, channelsAre(2412, 2450)); - - assertEquals(new HashSet<Integer>(Arrays.asList(2412, 2450)), - mChannelCollection.getScanFreqs()); - - assertFalse(mChannelCollection.isEmpty()); - assertTrue(mChannelCollection.containsChannel(2412)); - assertFalse(mChannelCollection.containsChannel(5160)); - assertFalse(mChannelCollection.isAllChannels()); - } - - /** - * Add a band and channel that is on that band - */ - @Test - public void addChannel_and_addBand_sameBand() { - mChannelCollection.addBand(WifiScanner.WIFI_BAND_24_GHZ); - mChannelCollection.addChannel(2412); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, bandIs(WifiScanner.WIFI_BAND_24_GHZ)); - - assertEquals(new HashSet<Integer>(Arrays.asList(2412, 2450)), - mChannelCollection.getScanFreqs()); - - assertFalse(mChannelCollection.isEmpty()); - assertTrue(mChannelCollection.containsChannel(2412)); - assertFalse(mChannelCollection.containsChannel(5160)); - assertFalse(mChannelCollection.isAllChannels()); - } - - /** - * Add a band and channel that is not that band - */ - @Test - public void addChannel_and_addBand_withDifferentBandChannel() { - mChannelCollection.addBand(WifiScanner.WIFI_BAND_24_GHZ); - mChannelCollection.addChannel(5160); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, channelsAre(2412, 2450, 5160)); - - assertEquals(new HashSet<Integer>(Arrays.asList(2412, 2450, 5160)), - mChannelCollection.getScanFreqs()); - - assertFalse(mChannelCollection.isEmpty()); - assertTrue(mChannelCollection.containsChannel(2412)); - assertTrue(mChannelCollection.containsChannel(5160)); - assertFalse(mChannelCollection.isAllChannels()); - } - - /** - * Add a band that should contain all channels - */ - @Test - public void addChannel_and_addBand_all() { - mChannelCollection.addBand(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ); - mChannelCollection.addChannel(5160); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, bandIs(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ)); - - assertNull(mChannelCollection.getScanFreqs()); - - assertFalse(mChannelCollection.isEmpty()); - assertTrue(mChannelCollection.containsChannel(2412)); - assertTrue(mChannelCollection.containsChannel(5160)); - assertTrue(mChannelCollection.containsChannel(5600)); - assertTrue(mChannelCollection.isAllChannels()); - } - - /** - * Add enough channels on a single band that the max channels is exceeded - */ - @Test - public void addChannel_exceedMaxChannels() { - mChannelCollection.addChannel(5600); - mChannelCollection.addChannel(5650); - mChannelCollection.addChannel(5660); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, 2); - assertThat(bucketSettings, bandIs(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY)); - assertFalse(mChannelCollection.isAllChannels()); - } - - /** - * Add enough channels across multiple bands that the max channels is exceeded - */ - @Test - public void addChannel_exceedMaxChannelsOnMultipleBands() { - mChannelCollection.addChannel(2412); - mChannelCollection.addChannel(2450); - mChannelCollection.addChannel(5160); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, 2); - assertThat(bucketSettings, bandIs(WifiScanner.WIFI_BAND_BOTH)); - assertFalse(mChannelCollection.isAllChannels()); - } - - - /** - * Add enough channels across all bands that the max channels is exceeded - */ - @Test - public void addChannel_addAllAvailableChannels() { - mChannelCollection.addChannel(2412); - mChannelCollection.addChannel(2450); - mChannelCollection.addChannel(5160); - mChannelCollection.addChannel(5175); - mChannelCollection.addChannel(5600); - mChannelCollection.addChannel(5650); - mChannelCollection.addChannel(5660); - mChannelCollection.addChannel(5945); - mChannelCollection.addChannel(5985); - - WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); - mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE); - assertThat(bucketSettings, - channelsAre(2412, 2450, 5160, 5175, 5600, 5650, 5660, 5945, 5985)); - assertTrue(mChannelCollection.isAllChannels()); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/ScanScheduleUtilFilterTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/ScanScheduleUtilFilterTest.java deleted file mode 100644 index 429da3f7f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/ScanScheduleUtilFilterTest.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import static com.android.server.wifi.ScanTestUtil.channelsToSpec; -import static com.android.server.wifi.ScanTestUtil.createRequest; -import static com.android.server.wifi.ScanTestUtil.createScanDatas; -import static com.android.server.wifi.ScanTestUtil.createScanResult; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiScanner.ScanSettings; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for filtering of scan results in - * {@link com.android.server.wifi.scanner.ScanScheduleUtil}. - */ -@SmallTest -public class ScanScheduleUtilFilterTest extends WifiBaseTest { - - private ChannelHelper mChannelHelper; - - @Before - public void setUp() throws Exception { - mChannelHelper = new PresetKnownBandsChannelHelper( - new int[]{2412, 2450}, - new int[]{5160, 5175}, - new int[]{5600, 5650}, - new int[]{5945, 5985}); - } - - @Test - public void reportFullResultTrueForBandsWithNoBucketInfo() { - ScanSettings settings = createRequest( - WifiScanner.WIFI_BAND_24_GHZ, 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - assertTrue(ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, - createScanResult(2412), 0, settings, -1)); - } - - @Test - public void reportFullResultFalseForBandsWithNoBucketInfo() { - ScanSettings settings = createRequest( - WifiScanner.WIFI_BAND_24_GHZ, 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - assertFalse(ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, - createScanResult(5160), 0, settings, 0)); - } - - @Test - public void reportFullResultTrueForChannelsWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - assertTrue(ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, - createScanResult(2412), 0, settings, 0)); - } - - @Test - public void reportFullResultFalseForChannelsWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - assertFalse(ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, - createScanResult(5175), 0, settings, 0)); - } - - @Test - public void reportFullResultTrueForChannelsWithBucketDefinitlyScanned() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - assertTrue(ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, - createScanResult(2412), 5, settings, 2)); - } - - @Test - public void reportFullResultFalseForChannelsWithBucketDefinitlyNotScanned() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - assertFalse(ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, - createScanResult(2412), 1, settings, 1)); - } - - @Test - public void filterScanDataEmptyWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - new ScanData[0], settings, -1); - assertScanDataFreqsEquals(null, results); - } - - @Test - public void filterScanDataSingleNotMatchingWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2450 } }), settings, 0); - assertScanDataFreqsEquals(null, results); - } - - @Test - public void filterScanDataSingleNotMatchingWithDefinitlyScannedBucketIndex() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2450 } }), settings, -1); - assertScanDataFreqsEquals(new int[][]{ { } }, results); - } - - @Test - public void filterScanDataSingleNotMatchingWithBucketDefinitlyScanned() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2450 } }, new int[]{ 2 }), settings, 1); - assertScanDataFreqsEquals(new int[][]{ { } }, results); - } - - @Test - public void filterScanDataSingleMatchingWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2412 } }), settings, 0); - - assertScanDataFreqsEquals(new int[][]{ { 2412 } }, results); - } - - @Test - public void filterScanDataSingleMatchingWithBucketDefinitlyNotScanned() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2412 } }, new int[] { 5 }), settings, 1); - - assertScanDataFreqsEquals(null, results); - } - - @Test - public void filterScanDataSinglePartialMatchingWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2412, 2450, 5160, 5175 } }), settings, 0); - - assertScanDataFreqsEquals(new int[][]{ { 2412, 5160 } }, results); - } - - @Test - public void filterScanDataMultipleNotMatchingWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2450 }, { 2450, 5175 } }), settings, 0); - assertScanDataFreqsEquals(null, results); - } - - @Test - public void filterScanDataMultipleNotMatchingWithOneDefinitlyScanned() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2450 }, { 2450, 5175 } }, new int[]{ 1, 8 }), - settings, 3); - assertScanDataFreqsEquals(new int[][]{ {} }, results); - } - - @Test - public void filterScanDataMultipleMatchingWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2412 }, {2412, 5160} }), settings, 0); - - assertScanDataFreqsEquals(new int[][]{ { 2412 }, {2412, 5160} }, results); - } - - @Test - public void filterScanDataMultiplePartialMatchingWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ { 2412, 2450, 5160, 5175 }, { 2412, 2450, 5175 } }), - settings, -1); - - assertScanDataFreqsEquals(new int[][]{ { 2412, 5160 }, { 2412 } }, results); - } - - @Test - public void filterScanDataMultipleDuplicateFrequenciesWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ - { 2412, 2450, 5160, 5175, 2412 }, - { 2412, 2450, 5175 }, - { 5175, 5175, 5160 } }), settings, 0); - - assertScanDataFreqsEquals(new int[][]{ { 2412, 5160, 2412 }, { 2412 }, { 5160 } }, results); - } - - @Test - public void filterScanDataMultipleSomeNotMatchingWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 20, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ - { 2412, 2450, 5160, 5175, 2412 }, - { 5175 }, - { 5175, 5175, 5160 } }), settings, 0); - - assertScanDataFreqsEquals(new int[][]{ { 2412, 5160, 2412 }, { 5160 } }, results); - } - - @Test - public void filterScanDataExceedMaxBssidsPerScanWithNoBucketInfo() { - ScanSettings settings = createRequest( - channelsToSpec(2412, 5160), 30000, 0, 3, - WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - ); - - ScanData[] results = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, - createScanDatas(new int[][]{ - { 2412, 2450, 5160, 5175, 2412, 2412}, - { 5175 }, - { 5175, 5175, 5160, 2412, 2412, 5160 } }), settings, 0); - - assertScanDataFreqsEquals(new int[][]{ { 2412, 5160, 2412 }, { 5160, 2412, 2412 } }, - results); - } - - - private static void assertScanDataFreqsEquals(int[][] expected, ScanData[] results) { - if (expected == null) { - assertNull("Expected no results", results); - } else { - assertNotNull("Expected some results", results); - assertEquals("num scans", expected.length, results.length); - for (int i = 0; i < expected.length; ++i) { - assertNotNull("scan[" + i + "] was null", results[i]); - assertEquals("num aps in scan[" + i + "]", expected[i].length, - results[i].getResults().length); - for (int j = 0; j < expected[i].length; ++j) { - assertNotNull("ap result[" + i + "][" + j + "] was null", - results[i].getResults()[j]); - assertEquals("ap freq in result[" + i + "][" + j + "]", expected[i][j], - results[i].getResults()[j].frequency); - } - } - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java deleted file mode 100644 index 0264bc261..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java +++ /dev/null @@ -1,3566 +0,0 @@ - /* - * Copyright (C) 2016 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.server.wifi.scanner; - -import static android.content.pm.PackageManager.PERMISSION_DENIED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.wifi.WifiScanner.GET_AVAILABLE_CHANNELS_EXTRA; - -import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder; -import static com.android.server.wifi.ScanTestUtil.assertNativePnoSettingsEquals; -import static com.android.server.wifi.ScanTestUtil.assertNativeScanSettingsEquals; -import static com.android.server.wifi.ScanTestUtil.assertScanDatasEquals; -import static com.android.server.wifi.ScanTestUtil.assertScanResultsEquals; -import static com.android.server.wifi.ScanTestUtil.channelsToSpec; -import static com.android.server.wifi.ScanTestUtil.computeSingleScanNativeSettings; -import static com.android.server.wifi.ScanTestUtil.createRequest; -import static com.android.server.wifi.ScanTestUtil.createSingleScanNativeSettingsForChannels; -import static com.android.server.wifi.scanner.WifiScanningServiceImpl.WifiSingleScanStateMachine.CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.argThat; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.validateMockitoUsage; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.app.test.TestAlarmManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiScanner; -import android.os.BatteryStatsManager; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.RemoteException; -import android.os.WorkSource; -import android.os.test.TestLooper; -import android.util.ArraySet; -import android.util.Pair; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.AsyncChannel; -import com.android.internal.util.Protocol; -import com.android.internal.util.test.BidirectionalAsyncChannel; -import com.android.server.wifi.Clock; -import com.android.server.wifi.DppMetrics; -import com.android.server.wifi.FakeWifiLog; -import com.android.server.wifi.FrameworkFacade; -import com.android.server.wifi.MockResources; -import com.android.server.wifi.ScanResults; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiInjector; -import com.android.server.wifi.WifiMetrics; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.WifiPowerMetrics; -import com.android.server.wifi.aware.WifiAwareMetrics; -import com.android.server.wifi.p2p.WifiP2pMetrics; -import com.android.server.wifi.proto.nano.WifiMetricsProto; -import com.android.server.wifi.rtt.RttMetrics; -import com.android.server.wifi.util.WifiAsyncChannel; -import com.android.server.wifi.util.WifiPermissionsUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.regex.Pattern; - -/** - * Unit tests for {@link com.android.server.wifi.scanner.WifiScanningServiceImpl}. - */ -@SmallTest -public class WifiScanningServiceTest extends WifiBaseTest { - public static final String TAG = "WifiScanningServiceTest"; - - private static final int TEST_MAX_SCAN_BUCKETS_IN_CAPABILITIES = 8; - private static final String TEST_PACKAGE_NAME = "com.test.123"; - private static final String TEST_FEATURE_ID = "test.feature"; - private static final String TEST_IFACE_NAME_0 = "wlan0"; - private static final String TEST_IFACE_NAME_1 = "wlan1"; - private static final WifiScanner.ScanData DUMMY_SCAN_DATA = - new WifiScanner.ScanData(0, 0, new ScanResult[0]); - - @Mock Context mContext; - TestAlarmManager mAlarmManager; - @Mock WifiScannerImpl mWifiScannerImpl0; - @Mock WifiScannerImpl mWifiScannerImpl1; - @Mock WifiScannerImpl.WifiScannerImplFactory mWifiScannerImplFactory; - @Mock BatteryStatsManager mBatteryStats; - @Mock WifiInjector mWifiInjector; - @Mock FrameworkFacade mFrameworkFacade; - @Mock Clock mClock; - @Spy FakeWifiLog mLog; - @Mock WifiPermissionsUtil mWifiPermissionsUtil; - @Mock DppMetrics mDppMetrics; - @Mock WifiNative mWifiNative; - ChannelHelper mChannelHelper0; - ChannelHelper mChannelHelper1; - WifiMetrics mWifiMetrics; - TestLooper mLooper; - WifiScanningServiceImpl mWifiScanningServiceImpl; - @Mock WifiP2pMetrics mWifiP2pMetrics; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mAlarmManager = new TestAlarmManager(); - when(mContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - when(mContext.getResources()).thenReturn(new MockResources()); - when(mWifiInjector.getWifiPermissionsUtil()) - .thenReturn(mWifiPermissionsUtil); - - mChannelHelper0 = new PresetKnownBandsChannelHelper( - new int[]{2412, 2450}, - new int[]{5160, 5175}, - new int[]{5600, 5650, 5660}, - new int[]{5945, 5985}); - mChannelHelper1 = new PresetKnownBandsChannelHelper( - new int[]{2412, 2450}, - new int[]{5160, 5175}, - new int[]{5600, 5660, 5680}, // 5650 is missing from channelHelper0 - new int[]{5945, 5985}); - mLooper = new TestLooper(); - mWifiMetrics = new WifiMetrics(mContext, mFrameworkFacade, mClock, mLooper.getLooper(), - new WifiAwareMetrics(mClock), new RttMetrics(mClock), - new WifiPowerMetrics(mBatteryStats), - mWifiP2pMetrics, mDppMetrics); - when(mWifiScannerImplFactory - .create(any(), any(), any(), eq(TEST_IFACE_NAME_0))) - .thenReturn(mWifiScannerImpl0); - when(mWifiScannerImpl0.getChannelHelper()).thenReturn(mChannelHelper0); - when(mWifiScannerImplFactory - .create(any(), any(), any(), eq(TEST_IFACE_NAME_1))) - .thenReturn(mWifiScannerImpl1); - when(mWifiScannerImpl1.getChannelHelper()).thenReturn(mChannelHelper1); - when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); - when(mWifiInjector.makeLog(anyString())).thenReturn(mLog); - WifiAsyncChannel mWifiAsyncChannel = new WifiAsyncChannel("ScanningServiceTest"); - mWifiAsyncChannel.setWifiLog(mLog); - when(mFrameworkFacade.makeWifiAsyncChannel(anyString())).thenReturn(mWifiAsyncChannel); - when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade); - when(mWifiInjector.getClock()).thenReturn(mClock); - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0))); - when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); - when(mContext.checkPermission(eq(Manifest.permission.NETWORK_STACK), - anyInt(), eq(Binder.getCallingUid()))) - .thenReturn(PERMISSION_GRANTED); - mWifiScanningServiceImpl = new WifiScanningServiceImpl(mContext, mLooper.getLooper(), - mWifiScannerImplFactory, mBatteryStats, mWifiInjector); - } - - @After - public void cleanup() { - validateMockitoUsage(); - } - - /** - * Internal BroadcastReceiver that WifiScanningServiceImpl uses to listen for broadcasts - * this is initialized by calling startServiceAndLoadDriver - */ - BroadcastReceiver mBroadcastReceiver; - - private WifiScanner.ScanSettings generateValidScanSettings() { - return createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - } - - private BidirectionalAsyncChannel connectChannel(Handler handler) { - BidirectionalAsyncChannel controlChannel = new BidirectionalAsyncChannel(); - controlChannel.connect(mLooper.getLooper(), mWifiScanningServiceImpl.getMessenger(), - handler); - mLooper.dispatchAll(); - controlChannel.assertConnected(); - return controlChannel; - } - - private static Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler) { - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - order.verify(handler).handleMessage(messageCaptor.capture()); - return messageCaptor.getValue(); - } - - private static class ConditionalMessageCaptor implements ArgumentMatcher<Message> { - private Message mLastValue; - private final int mWhat; - - private ConditionalMessageCaptor(int what) { - mWhat = what; - } - - public Message getLastValue() { - assertNotNull("Nothing captured yet", mLastValue); - - return mLastValue; - } - - public boolean matches(Message message) { - boolean isMatch = message.what == mWhat; - - if (isMatch) { - mLastValue = message; - } - - return isMatch; - } - } - - private static Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler, - final int what) { - ConditionalMessageCaptor messageMatcher = new ConditionalMessageCaptor(what); - - order.verify(handler).handleMessage(argThat(messageMatcher)); - return messageMatcher.getLastValue(); - } - - private static void verifyScanResultsReceived(InOrder order, Handler handler, int listenerId, - WifiScanner.ScanData... expected) { - Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler, - WifiScanner.CMD_SCAN_RESULT); - assertScanResultsMessage(listenerId, expected, scanResultMessage); - } - - private static void assertScanResultsMessage(int listenerId, WifiScanner.ScanData[] expected, - Message scanResultMessage) { - assertEquals("what", WifiScanner.CMD_SCAN_RESULT, scanResultMessage.what); - assertEquals("listenerId", listenerId, scanResultMessage.arg2); - assertScanDatasEquals(expected, - ((WifiScanner.ParcelableScanData) scanResultMessage.obj).getResults()); - } - - private static void verifySingleScanCompletedReceived(InOrder order, Handler handler, - int listenerId) { - Message completedMessage = verifyHandleMessageAndGetMessage(order, handler, - WifiScanner.CMD_SINGLE_SCAN_COMPLETED); - assertSingleScanCompletedMessage(listenerId, completedMessage); - } - - private static void assertSingleScanCompletedMessage(int listenerId, Message completedMessage) { - assertEquals("what", WifiScanner.CMD_SINGLE_SCAN_COMPLETED, completedMessage.what); - assertEquals("listenerId", listenerId, completedMessage.arg2); - } - - private static void sendBackgroundScanRequest(BidirectionalAsyncChannel controlChannel, - int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) { - Bundle scanParams = new Bundle(); - scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings); - scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN, 0, - scanRequestId, scanParams)); - } - - private static void sendSingleScanRequest(BidirectionalAsyncChannel controlChannel, - int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) { - Bundle scanParams = new Bundle(); - scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings); - scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_SINGLE_SCAN, 0, - scanRequestId, scanParams)); - } - - private static void registerScanListener(BidirectionalAsyncChannel controlChannel, - int listenerRequestId) { - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_REGISTER_SCAN_LISTENER, 0, - listenerRequestId, null)); - } - - private static void deregisterScanListener(BidirectionalAsyncChannel controlChannel, - int listenerRequestId) { - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DEREGISTER_SCAN_LISTENER, 0, - listenerRequestId, null)); - } - - private static void verifySuccessfulResponse(InOrder order, Handler handler, int arg2) { - Message response = verifyHandleMessageAndGetMessage(order, handler); - assertSuccessfulResponse(arg2, response); - } - - private static void assertSuccessfulResponse(int arg2, Message response) { - if (response.what == WifiScanner.CMD_OP_FAILED) { - WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj; - fail("response indicates failure, reason=" + result.reason - + ", description=" + result.description); - } else { - assertEquals("response.what", WifiScanner.CMD_OP_SUCCEEDED, response.what); - assertEquals("response.arg2", arg2, response.arg2); - } - } - - /** - * If multiple results are expected for a single hardware scan then the order that they are - * dispatched is dependant on the order which they are iterated through internally. This - * function validates that the order is either one way or the other. A scan listener can - * optionally be provided as well and will be checked after the after the single scan requests. - */ - private static void verifyMultipleSingleScanResults(InOrder handlerOrder, Handler handler, - int requestId1, ScanResults results1, int requestId2, ScanResults results2, - int listenerRequestId, ScanResults listenerResults) { - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - handlerOrder.verify(handler, times(listenerResults == null ? 4 : 5)) - .handleMessage(messageCaptor.capture()); - int firstListenerId = messageCaptor.getAllValues().get(0).arg2; - assertTrue(firstListenerId + " was neither " + requestId2 + " nor " + requestId1, - firstListenerId == requestId2 || firstListenerId == requestId1); - if (firstListenerId == requestId2) { - assertScanResultsMessage(requestId2, - new WifiScanner.ScanData[] {results2.getScanData()}, - messageCaptor.getAllValues().get(0)); - assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(1)); - assertScanResultsMessage(requestId1, - new WifiScanner.ScanData[] {results1.getScanData()}, - messageCaptor.getAllValues().get(2)); - assertSingleScanCompletedMessage(requestId1, messageCaptor.getAllValues().get(3)); - if (listenerResults != null) { - assertScanResultsMessage(listenerRequestId, - new WifiScanner.ScanData[] {listenerResults.getScanData()}, - messageCaptor.getAllValues().get(4)); - } - } else { - assertScanResultsMessage(requestId1, - new WifiScanner.ScanData[] {results1.getScanData()}, - messageCaptor.getAllValues().get(0)); - assertSingleScanCompletedMessage(requestId1, messageCaptor.getAllValues().get(1)); - assertScanResultsMessage(requestId2, - new WifiScanner.ScanData[] {results2.getScanData()}, - messageCaptor.getAllValues().get(2)); - assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(3)); - if (listenerResults != null) { - assertScanResultsMessage(listenerRequestId, - new WifiScanner.ScanData[] {listenerResults.getScanData()}, - messageCaptor.getAllValues().get(4)); - } - } - } - - private static void verifyMultipleSingleScanResults(InOrder handlerOrder, Handler handler, - int requestId1, ScanResults results1, int requestId2, ScanResults results2) { - verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId2, - results2, -1, null); - } - - private static void verifyFailedResponse(InOrder order, Handler handler, int arg2, - int expectedErrorReason, String expectedErrorDescription) { - Message response = verifyHandleMessageAndGetMessage(order, handler); - assertFailedResponse(arg2, expectedErrorReason, expectedErrorDescription, response); - } - - private static void assertFailedResponse(int arg2, int expectedErrorReason, - String expectedErrorDescription, Message response) { - if (response.what == WifiScanner.CMD_OP_SUCCEEDED) { - fail("response indicates success"); - } else { - assertEquals("response.what", WifiScanner.CMD_OP_FAILED, response.what); - assertEquals("response.arg2", arg2, response.arg2); - WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj; - assertEquals("response.obj.reason", - expectedErrorReason, result.reason); - assertEquals("response.obj.description", - expectedErrorDescription, result.description); - } - } - - private WifiNative.ScanEventHandler verifyStartSingleScan(InOrder order, - WifiNative.ScanSettings expected) { - return verifyStartSingleScanForImpl(mWifiScannerImpl0, order, expected); - } - - private WifiNative.ScanEventHandler verifyStartSingleScanForImpl( - WifiScannerImpl wifiScannerImpl, InOrder order, WifiNative.ScanSettings expected) { - ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor = - ArgumentCaptor.forClass(WifiNative.ScanSettings.class); - ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor = - ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class); - order.verify(wifiScannerImpl).startSingleScan(scanSettingsCaptor.capture(), - scanEventHandlerCaptor.capture()); - assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue()); - return scanEventHandlerCaptor.getValue(); - } - - private WifiNative.ScanEventHandler verifyStartBackgroundScan(InOrder order, - WifiNative.ScanSettings expected) { - ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor = - ArgumentCaptor.forClass(WifiNative.ScanSettings.class); - ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor = - ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class); - order.verify(mWifiScannerImpl0).startBatchedScan(scanSettingsCaptor.capture(), - scanEventHandlerCaptor.capture()); - assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue()); - return scanEventHandlerCaptor.getValue(); - } - - private static final int MAX_AP_PER_SCAN = 16; - private void startServiceAndLoadDriver() { - mWifiScanningServiceImpl.startService(); - mLooper.dispatchAll(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - setupAndLoadDriver(TEST_MAX_SCAN_BUCKETS_IN_CAPABILITIES); - } - - private void setupAndLoadDriver(int max_scan_buckets) { - when(mWifiScannerImpl0.getScanCapabilities(any(WifiNative.ScanCapabilities.class))) - .thenAnswer(new AnswerWithArguments() { - public boolean answer(WifiNative.ScanCapabilities capabilities) { - capabilities.max_scan_cache_size = Integer.MAX_VALUE; - capabilities.max_scan_buckets = max_scan_buckets; - capabilities.max_ap_cache_per_scan = MAX_AP_PER_SCAN; - capabilities.max_rssi_sample_size = 8; - capabilities.max_scan_reporting_threshold = 10; - return true; - } - }); - BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class)); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - } - - private String dumpService() { - StringWriter stringWriter = new StringWriter(); - mWifiScanningServiceImpl.dump(new FileDescriptor(), new PrintWriter(stringWriter), - new String[0]); - return stringWriter.toString(); - } - - private void assertDumpContainsRequestLog(String type, int id) { - String serviceDump = dumpService(); - Pattern logLineRegex = Pattern.compile("^.+" + type - + ": ClientInfo\\[uid=\\d+,android\\.os\\.Messenger@[a-f0-9]+\\],Id=" + id - + ".*$", Pattern.MULTILINE); - assertTrue("dump did not contain log with type=" + type + ", id=" + id + - ": " + serviceDump + "\n", - logLineRegex.matcher(serviceDump).find()); - } - - private void assertDumpContainsCallbackLog(String callback, int id, String extra) { - String serviceDump = dumpService(); - String extraPattern = extra == null ? "" : "," + extra; - Pattern logLineRegex = Pattern.compile("^.+" + callback - + ": ClientInfo\\[uid=\\d+,android\\.os\\.Messenger@[a-f0-9]+\\],Id=" + id - + extraPattern + "$", Pattern.MULTILINE); - assertTrue("dump did not contain callback log with callback=" + callback + ", id=" + id + - ", extra=" + extra + ": " + serviceDump + "\n", - logLineRegex.matcher(serviceDump).find()); - } - - @Test - public void construct() throws Exception { - verifyNoMoreInteractions(mWifiScannerImpl0, mWifiScannerImpl0, - mWifiScannerImplFactory, mBatteryStats); - dumpService(); // make sure this succeeds - } - - @Test - public void startService() throws Exception { - mWifiScanningServiceImpl.startService(); - mLooper.dispatchAll(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - verifyNoMoreInteractions(mWifiScannerImplFactory); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available"); - } - - @Test - public void disconnectClientBeforeWifiEnabled() throws Exception { - mWifiScanningServiceImpl.startService(); - mLooper.dispatchAll(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class)); - mLooper.dispatchAll(); - - controlChannel.disconnect(); - mLooper.dispatchAll(); - } - - @Test - public void loadDriver() throws Exception { - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), eq(TEST_IFACE_NAME_0)); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - when(mWifiScannerImpl0.startBatchedScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings(), null); - mLooper.dispatchAll(); - verifySuccessfulResponse(order, handler, 192); - assertDumpContainsRequestLog("addBackgroundScanRequest", 192); - } - - /** - * Verifies that duplicate scan enable is ignored. - */ - @Test - public void duplicateScanEnableIsIgnored() throws RemoteException { - startServiceAndLoadDriver(); - - // Send scan enable again. - BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class)); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - // Ensure we didn't create scanner instance twice. - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), any()); - } - - @Test - public void disconnectClientAfterStartingWifi() throws Exception { - mWifiScanningServiceImpl.startService(); - mLooper.dispatchAll(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class)); - mLooper.dispatchAll(); - - setupAndLoadDriver(TEST_MAX_SCAN_BUCKETS_IN_CAPABILITIES); - - controlChannel.disconnect(); - mLooper.dispatchAll(); - } - - @Test - public void connectAndDisconnectClientAfterStartingWifi() throws Exception { - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class)); - mLooper.dispatchAll(); - controlChannel.disconnect(); - mLooper.dispatchAll(); - } - - @Test - public void sendInvalidCommand() throws Exception { - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - controlChannel.sendMessage(Message.obtain(null, Protocol.BASE_WIFI_MANAGER)); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, 0, WifiScanner.REASON_INVALID_REQUEST, - "Invalid request"); - } - - @Test - public void rejectBackgroundScanRequestWhenHalReturnsInvalidCapabilities() throws Exception { - mWifiScanningServiceImpl.startService(); - mLooper.dispatchAll(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - setupAndLoadDriver(0); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available"); - } - - @Test - public void rejectBackgroundScanRequestWhenScannerImplCreateFails() throws Exception { - // Fail scanner impl creation. - when(mWifiScannerImplFactory.create(any(), any(), any(), any())).thenReturn(null); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available"); - } - - private void doSuccessfulSingleScan(WifiScanner.ScanSettings requestSettings, - WifiNative.ScanSettings nativeSettings, @NonNull ScanResults resultsForImpl0) - throws RemoteException { - doSuccessfulSingleScanOnImpls(requestSettings, nativeSettings, resultsForImpl0, null); - } - - private void doSuccessfulSingleScanOnImpls(WifiScanner.ScanSettings requestSettings, - WifiNative.ScanSettings nativeSettings, @NonNull ScanResults resultsForImpl0, - @Nullable ScanResults resultsForImpl1) throws RemoteException { - int requestId = 12; - WorkSource workSource = new WorkSource(2292); - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - if (resultsForImpl1 != null) { - when(mWifiScannerImpl1.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - } - - sendSingleScanRequest(controlChannel, requestId, requestSettings, workSource); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler0 = - verifyStartSingleScanForImpl(mWifiScannerImpl0, order, nativeSettings); - WifiNative.ScanEventHandler eventHandler1 = null; - if (resultsForImpl1 != null) { - eventHandler1 = verifyStartSingleScanForImpl(mWifiScannerImpl1, order, nativeSettings); - } - verifySuccessfulResponse(order, handler, requestId); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource)); - - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(resultsForImpl0.getScanData()); - eventHandler0.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - if (resultsForImpl1 != null) { - when(mWifiScannerImpl1.getLatestSingleScanResults()) - .thenReturn(resultsForImpl1.getScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - } - - mLooper.dispatchAll(); - ScanResults expectedResults = resultsForImpl0; - if (resultsForImpl1 != null) { - expectedResults = ScanResults.merge( - resultsForImpl0.getScanData().getBandScanned(), - resultsForImpl0, resultsForImpl1); - } - verifyScanResultsReceived(order, handler, requestId, expectedResults.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId); - verifyNoMoreInteractions(handler); - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource)); - assertDumpContainsRequestLog("addSingleScanRequest", requestId); - assertDumpContainsCallbackLog("singleScanResults", requestId, - "results=" + expectedResults.getScanData().getResults().length); - } - - /** - * Do a single scan for a band and verify that it is successful. - */ - @Test - public void sendSingleScanBandRequest() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 2412, 5160, 5175)); - } - - /** - * Do a single scan for a list of channels and verify that it is successful. - */ - @Test - public void sendSingleScanChannelsRequest() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2412, 5160, 5175), - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412, 5160, 5175)); - } - - /** - * Do a single scan for a list of all channels and verify that it is successful. - */ - @Test - public void sendSingleScanAllChannelsRequest() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest( - channelsToSpec(2412, 2450, 5160, 5175, 5600, 5650, 5660), - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412, 5160, 5175)); - } - - /** - * Do a single scan with no results and verify that it is successful. - */ - @Test - public void sendSingleScanRequestWithNoResults() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH, new int[0])); - } - - /** - * Do a single scan with results that do not match the requested scan and verify that it is - * still successful (and returns no results). - */ - @Test - public void sendSingleScanRequestWithBadRawResults() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_24_GHZ, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - // Create a set of scan results that has results not matching the request settings, but is - // limited to zero results for the expected results. - ScanResults results = ScanResults.createOverflowing(0, WifiScanner.WIFI_BAND_24_GHZ, 0, - ScanResults.generateNativeResults(0, 5160, 5171)); - doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), - results); - } - - /** - * Do a single scan from a non-privileged app with some privileged params set. - * Expect a scan failure. - */ - @Test - public void sendSingleScanRequestWithPrivilegedTypeParamsSetFromNonPrivilegedApp() - throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - requestSettings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set - - when(mContext.checkPermission( - Manifest.permission.NETWORK_STACK, -1, Binder.getCallingUid())) - .thenReturn(PERMISSION_DENIED); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // successful start - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - // Scan is successfully queued - mLooper.dispatchAll(); - - // but then fails to execute - verifyFailedResponse(order, handler, requestId, - WifiScanner.REASON_INVALID_REQUEST, "bad request"); - assertDumpContainsCallbackLog("singleScanInvalidRequest", requestId, - "bad request"); - - assertEquals(0, mWifiMetrics.getOneshotScanCount()); - assertEquals(mWifiMetrics.getScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION), 1); - - // Ensure that no scan was triggered to the lower layers. - verify(mBatteryStats, never()).reportWifiScanStoppedFromSource(eq(workSource)); - verify(mWifiScannerImpl0, never()).startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class)); - } - - /** - * Do a single scan from a non-privileged app with some privileged params set. - * Expect a scan failure. - */ - @Test - public void sendSingleScanRequestWithPrivilegedHiddenNetworkParamsSetFromNonPrivilegedApp() - throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - requestSettings.hiddenNetworks.clear(); - requestSettings.hiddenNetworks.add( - new WifiScanner.ScanSettings.HiddenNetwork("Test1")); - requestSettings.hiddenNetworks.add( - new WifiScanner.ScanSettings.HiddenNetwork("Test2")); - WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set - - when(mContext.checkPermission( - Manifest.permission.NETWORK_STACK, -1, Binder.getCallingUid())) - .thenReturn(PERMISSION_DENIED); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // successful start - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - // Scan is successfully queued - mLooper.dispatchAll(); - - // but then fails to execute - verifyFailedResponse(order, handler, requestId, - WifiScanner.REASON_INVALID_REQUEST, "bad request"); - assertDumpContainsCallbackLog("singleScanInvalidRequest", requestId, - "bad request"); - - assertEquals(0, mWifiMetrics.getOneshotScanCount()); - assertEquals(mWifiMetrics.getScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION), 1); - - // Ensure that no scan was triggered to the lower layers. - verify(mBatteryStats, never()).reportWifiScanStoppedFromSource(eq(workSource)); - verify(mWifiScannerImpl0, never()).startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class)); - } - - /** - * Do a single scan with invalid scan type set. - * Expect a scan failure. - */ - @Test - public void sendSingleScanRequestWithInvalidScanType() - throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - requestSettings.type = 100; // invalid scan type - WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // successful start - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - // Scan is successfully queued - mLooper.dispatchAll(); - - // but then fails to execute - verifyFailedResponse(order, handler, requestId, - WifiScanner.REASON_INVALID_REQUEST, "bad request"); - assertDumpContainsCallbackLog("singleScanInvalidRequest", requestId, - "bad request"); - - assertEquals(0, mWifiMetrics.getOneshotScanCount()); - assertEquals(mWifiMetrics.getScanReturnEntry( - WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION), 1); - - // Ensure that no scan was triggered to the lower layers. - verify(mBatteryStats, never()).reportWifiScanStoppedFromSource(eq(workSource)); - verify(mWifiScannerImpl0, never()).startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class)); - } - - /** - * Do a single scan from a non-privileged app with no privileged params set. - */ - @Test - public void sendSingleScanRequestWithNoPrivilegedParamsSetFromNonPrivilegedApp() - throws Exception { - when(mContext.checkPermission( - Manifest.permission.NETWORK_STACK, -1, Binder.getCallingUid())) - .thenReturn(PERMISSION_DENIED); - WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2412, 5160, 5175), - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, 2412, 5160, 5175)); - } - - /** - * Do a single scan, which the hardware fails to start, and verify that a failure response is - * delivered. - */ - @Test - public void sendSingleScanRequestWhichFailsToStart() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // scan fails - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(false); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - mLooper.dispatchAll(); - // Scan is successfully queue, but then fails to execute - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - order.verify(handler, times(2)).handleMessage(messageCaptor.capture()); - assertSuccessfulResponse(requestId, messageCaptor.getAllValues().get(0)); - assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED, - "Failed to start single scan", messageCaptor.getAllValues().get(1)); - verifyNoMoreInteractions(mBatteryStats); - - assertEquals(mWifiMetrics.getOneshotScanCount(), 1); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1); - assertDumpContainsRequestLog("addSingleScanRequest", requestId); - } - - /** - * Do a single scan, which successfully starts, but fails partway through and verify that a - * failure response is delivered. - */ - @Test - public void sendSingleScanRequestWhichFailsAfterStart() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // successful start - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - // Scan is successfully queue - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = - verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings)); - verifySuccessfulResponse(order, handler, requestId); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource)); - - // but then fails to execute - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, requestId, - WifiScanner.REASON_UNSPECIFIED, "Scan failed"); - assertDumpContainsCallbackLog("singleScanFailed", requestId, - "reason=" + WifiScanner.REASON_UNSPECIFIED + ", Scan failed"); - assertEquals(mWifiMetrics.getOneshotScanCount(), 1); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1); - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource)); - } - - /** - * Do a single scan that includes DFS channels and verify that both oneshot scan count and - * oneshot scan count with dfs are incremented. - */ - @Test - public void testMetricsForOneshotScanWithDFSIsIncremented() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest( - WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 0, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // successful start - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - assertEquals(0, mWifiMetrics.getOneshotScanCount()); - assertEquals(0, mWifiMetrics.getOneshotScanWithDfsCount()); - // Scan is successfully queue - mLooper.dispatchAll(); - assertEquals(1, mWifiMetrics.getOneshotScanCount()); - assertEquals(1, mWifiMetrics.getOneshotScanWithDfsCount()); - } - - /** - * Do a single scan that excludes DFS channels and verify that only oneshot scan count is - * incremented. - */ - @Test - public void testMetricsForOneshotScanWithDFSIsNotIncremented() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest( - WifiScanner.WIFI_BAND_5_GHZ, 0, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // successful start - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - assertEquals(0, mWifiMetrics.getOneshotScanCount()); - // Scan is successfully queue - mLooper.dispatchAll(); - assertEquals(1, mWifiMetrics.getOneshotScanCount()); - assertEquals(0, mWifiMetrics.getOneshotScanWithDfsCount()); - } - - /** - * Send a single scan request and then disable Wi-Fi before it completes - */ - @Test - public void sendSingleScanRequestThenDisableWifi() { - WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 2293; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(order, handler, requestId); - - // disable wifi - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DISABLE)); - - // validate failed response - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, requestId, WifiScanner.REASON_UNSPECIFIED, - "Scan was interrupted"); - verifyNoMoreInteractions(handler); - } - - /** - * Send a single scan request and then disable Wi-Fi before it completes - */ - @Test - public void sendSingleScanRequestThenDisableWifiAfterScanCompleteButBeforeReportingResults() { - WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults results = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412); - int requestId = 2293; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, - computeSingleScanNativeSettings(requestSettings)); - verifySuccessfulResponse(order, handler, requestId); - - // disable wifi - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DISABLE)); - // scan results complete event - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results.getScanData()); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, requestId, WifiScanner.REASON_UNSPECIFIED, - "Scan was interrupted"); - verifyNoMoreInteractions(handler); - } - - /** - * Send a single scan request, schedule a second pending scan and disable Wi-Fi before the first - * scan completes. - */ - @Test - public void sendSingleScanAndPendingScanAndListenerThenDisableWifi() { - WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId1 = 2293; - - WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId2 = 2294; - - int listenerRequestId = 2295; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - // Request scan 1 - sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(order, handler, requestId1); - - // Request scan 2 - sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(order, handler, requestId2); - - // Setup scan listener - registerScanListener(controlChannel, listenerRequestId); - mLooper.dispatchAll(); - verifySuccessfulResponse(order, handler, listenerRequestId); - - // disable wifi - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DISABLE)); - - // validate failed response - mLooper.dispatchAll(); - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - order.verify(handler, times(2)).handleMessage(messageCaptor.capture()); - assertFailedResponse(requestId1, WifiScanner.REASON_UNSPECIFIED, - "Scan was interrupted", messageCaptor.getAllValues().get(0)); - assertFailedResponse(requestId2, WifiScanner.REASON_UNSPECIFIED, - "Scan was interrupted", messageCaptor.getAllValues().get(1)); - // No additional callbacks for scan listener - verifyNoMoreInteractions(handler); - } - - /** - * Send a single scan request and then a second one after the first completes. - */ - @Test - public void sendSingleScanRequestAfterPreviousCompletes() { - WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId1 = 12; - ScanResults results1 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412); - - - WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId2 = 13; - ScanResults results2 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2450); - - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mContext); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order, - computeSingleScanNativeSettings(requestSettings1)); - verifySuccessfulResponse(order, handler, requestId1); - - // dispatch scan 1 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results1.getScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - // Note: The order of the following verification calls looks out of order if you compare to - // the source code of WifiScanningServiceImpl WifiSingleScanStateMachine.reportScanResults. - // This is due to the fact that verifyScanResultsReceived and - // verifySingleScanCompletedReceived require an additional call to handle the message that - // is created in reportScanResults. This handling is done in the two verify*Received calls - // that is run AFTER the reportScanResults method in WifiScanningServiceImpl completes. - verifyScanResultsReceived(order, handler, requestId1, results1.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId1); - - // Run scan 2 - sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order, - computeSingleScanNativeSettings(requestSettings2)); - verifySuccessfulResponse(order, handler, requestId2); - - // dispatch scan 2 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results2.getScanData()); - eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, requestId2, results2.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId2); - } - - /** - * Send a single scan request and then a second one not satisfied by the first before the first - * completes. Verify that both are scheduled and succeed. - */ - @Test - public void sendSingleScanRequestWhilePreviousScanRunning() { - WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId1 = 12; - ScanResults results1 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412); - - WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId2 = 13; - ScanResults results2 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2450); - - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder handlerOrder = inOrder(handler); - InOrder nativeOrder = inOrder(mWifiScannerImpl0); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings1)); - verifySuccessfulResponse(handlerOrder, handler, requestId1); - - // Queue scan 2 (will not run because previous is in progress) - sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId2); - - // dispatch scan 1 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results1.getScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData()); - verifySingleScanCompletedReceived(handlerOrder, handler, requestId1); - - // now that the first scan completed we expect the second one to start - WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings2)); - - // dispatch scan 2 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results2.getScanData()); - eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(handlerOrder, handler, requestId2, results2.getScanData()); - verifySingleScanCompletedReceived(handlerOrder, handler, requestId2); - assertEquals(mWifiMetrics.getOneshotScanCount(), 2); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2); - } - - /** - * Send a single scan request and then a second one not satisfied by the first before the first - * completes. Verify that both are scheduled and succeed. - * Validates that a high accuracy scan request is not satisfied by an ongoing low latency scan, - * while any other low latency/low power scan request is satisfied. - */ - @Test - public void sendSingleScanRequestWhilePreviousScanRunningWithTypesThatDoesNotSatisfy() { - // Create identitical scan requests other than the types being different. - WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - requestSettings1.type = WifiScanner.SCAN_TYPE_LOW_LATENCY; - int requestId1 = 12; - ScanResults results1 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412); - - WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - requestSettings2.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - int requestId2 = 13; - ScanResults results2 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder handlerOrder = inOrder(handler); - InOrder nativeOrder = inOrder(mWifiScannerImpl0); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings1)); - verifySuccessfulResponse(handlerOrder, handler, requestId1); - - // Queue scan 2 (will not run because previous is in progress) - sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId2); - - // dispatch scan 1 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results1.getScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData()); - verifySingleScanCompletedReceived(handlerOrder, handler, requestId1); - - // now that the first scan completed we expect the second one to start - WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings2)); - - // dispatch scan 2 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results2.getScanData()); - eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(handlerOrder, handler, requestId2, results2.getScanData()); - verifySingleScanCompletedReceived(handlerOrder, handler, requestId2); - assertEquals(mWifiMetrics.getOneshotScanCount(), 2); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2); - } - - - /** - * Send a single scan request and then two more before the first completes. Neither are - * satisfied by the first scan. Verify that the first completes and the second two are merged. - * Validates that a high accuracy scan is always preferred over the other types while merging. - */ - @Test - public void sendMultipleSingleScanRequestWhilePreviousScanRunning() throws RemoteException { - WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - requestSettings1.type = WifiScanner.SCAN_TYPE_LOW_LATENCY; - int requestId1 = 12; - WorkSource workSource1 = new WorkSource(1121); - ScanResults results1 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412); - - WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - requestSettings2.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - int requestId2 = 13; - WorkSource workSource2 = new WorkSource(Binder.getCallingUid()); // don't explicitly set - ScanResults results2 = - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2450, 5175, 2450); - - WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5160), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - requestSettings3.type = WifiScanner.SCAN_TYPE_LOW_POWER; - int requestId3 = 15; - // Let one of the WorkSources be a chained workSource. - WorkSource workSource3 = new WorkSource(); - workSource3.createWorkChain() - .addNode(2292, "tag1"); - ScanResults results3 = - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 5160, 5160, 5160, 5160); - - WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels( - WifiScanner.SCAN_TYPE_HIGH_ACCURACY, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - channelsToSpec(2450, 5175, 5160)); - ScanResults results2and3 = - ScanResults.merge(WifiScanner.WIFI_BAND_UNSPECIFIED, results2, results3); - WorkSource workSource2and3 = new WorkSource(); - workSource2and3.add(workSource2); - workSource2and3.add(workSource3); - - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder handlerOrder = inOrder(handler); - InOrder nativeOrder = inOrder(mWifiScannerImpl0); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId1, requestSettings1, workSource1); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings1)); - verifySuccessfulResponse(handlerOrder, handler, requestId1); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource1)); - - - // Queue scan 2 (will not run because previous is in progress) - // uses uid of calling process - sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId2); - - // Queue scan 3 (will not run because previous is in progress) - sendSingleScanRequest(controlChannel, requestId3, requestSettings3, workSource3); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId3); - - // dispatch scan 1 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results1.getScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData()); - verifySingleScanCompletedReceived(handlerOrder, handler, requestId1); - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource1)); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource2and3)); - - // now that the first scan completed we expect the second and third ones to start - WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder, - nativeSettings2and3); - - // dispatch scan 2 and 3 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results2and3.getScanData()); - eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - - verifyMultipleSingleScanResults(handlerOrder, handler, requestId2, results2, requestId3, - results3); - assertEquals(mWifiMetrics.getOneshotScanCount(), 3); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3); - - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource2and3)); - - assertDumpContainsRequestLog("addSingleScanRequest", requestId1); - assertDumpContainsRequestLog("addSingleScanRequest", requestId2); - assertDumpContainsRequestLog("addSingleScanRequest", requestId3); - assertDumpContainsCallbackLog("singleScanResults", requestId1, - "results=" + results1.getRawScanResults().length); - assertDumpContainsCallbackLog("singleScanResults", requestId2, - "results=" + results2.getRawScanResults().length); - assertDumpContainsCallbackLog("singleScanResults", requestId3, - "results=" + results3.getRawScanResults().length); - } - - /** - * Send a single scan request and then a second one satisfied by the first before the first - * completes. Verify that only one scan is scheduled. - * Validates that a low latency scan type request is satisfied by an ongoing high accuracy - * scan. - */ - @Test - public void sendSingleScanRequestWhilePreviousScanRunningAndMergeIntoFirstScan() { - // Split by frequency to make it easier to determine which results each request is expecting - ScanResults results24GHz = - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH, 2412, 2412, 2412, 2450); - ScanResults results5GHz = - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH, 5160, 5160, 5175); - ScanResults resultsBoth = - ScanResults.merge(WifiScanner.WIFI_BAND_BOTH, results24GHz, results5GHz); - - WifiScanner.ScanSettings requestSettings1 = createRequest( - WifiScanner.SCAN_TYPE_HIGH_ACCURACY, WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId1 = 12; - ScanResults results1 = resultsBoth; - - WifiScanner.ScanSettings requestSettings2 = createRequest( - WifiScanner.SCAN_TYPE_LOW_LATENCY, WifiScanner.WIFI_BAND_24_GHZ, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId2 = 13; - ScanResults results2 = results24GHz; - - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder handlerOrder = inOrder(handler); - InOrder nativeOrder = inOrder(mWifiScannerImpl0); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings1)); - verifySuccessfulResponse(handlerOrder, handler, requestId1); - - // Queue scan 2 (will be folded into ongoing scan) - sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId2); - - // dispatch scan 1 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(resultsBoth.getScanData()); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId2, - results2); - - assertEquals(mWifiMetrics.getOneshotScanCount(), 2); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2); - } - - /** - * Send a single scan request and then two more before the first completes, one of which is - * satisfied by the first scan. Verify that the first two complete together the second scan is - * just for the other scan. - * Validates that a high accuracy scan request is not satisfied by an ongoing low latency scan, - * while any other low latency/low power scan request is satisfied. - */ - @Test - public void sendMultipleSingleScanRequestWhilePreviousScanRunningAndMergeOneIntoFirstScan() - throws RemoteException { - // Split by frequency to make it easier to determine which results each request is expecting - ScanResults results2412 = - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412, 2412, 2412); - ScanResults results2450 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2450); - ScanResults results1and3 = - ScanResults.merge(WifiScanner.WIFI_BAND_UNSPECIFIED, results2412, results2450); - - WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2412, 2450), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - requestSettings1.type = WifiScanner.SCAN_TYPE_LOW_LATENCY; - int requestId1 = 12; - WorkSource workSource1 = new WorkSource(1121); - ScanResults results1 = results1and3; - - WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - requestSettings2.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - int requestId2 = 13; - WorkSource workSource2 = new WorkSource(Binder.getCallingUid()); // don't explicitly set - ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450); - - WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - requestSettings3.type = WifiScanner.SCAN_TYPE_LOW_POWER; - int requestId3 = 15; - WorkSource workSource3 = new WorkSource(2292); - ScanResults results3 = results2412; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder handlerOrder = inOrder(handler); - InOrder nativeOrder = inOrder(mWifiScannerImpl0); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId1, requestSettings1, workSource1); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings1)); - verifySuccessfulResponse(handlerOrder, handler, requestId1); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource1)); - - - // Queue scan 2 (will not run because previous is in progress) - // uses uid of calling process - sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId2); - - // Queue scan 3 (will be merged into the active scan) - sendSingleScanRequest(controlChannel, requestId3, requestSettings3, workSource3); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId3); - - // dispatch scan 1 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results1and3.getScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId3, - results3); - // only the requests know at the beginning of the scan get blamed - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource1)); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource2)); - - // now that the first scan completed we expect the second and third ones to start - WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings2)); - - // dispatch scan 2 and 3 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results2.getScanData()); - eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - - verifyScanResultsReceived(handlerOrder, handler, requestId2, results2.getScanData()); - verifySingleScanCompletedReceived(handlerOrder, handler, requestId2); - assertEquals(mWifiMetrics.getOneshotScanCount(), 3); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3); - - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource2)); - - assertDumpContainsRequestLog("addSingleScanRequest", requestId1); - assertDumpContainsRequestLog("addSingleScanRequest", requestId2); - assertDumpContainsRequestLog("addSingleScanRequest", requestId3); - assertDumpContainsCallbackLog("singleScanResults", requestId1, - "results=" + results1.getRawScanResults().length); - assertDumpContainsCallbackLog("singleScanResults", requestId2, - "results=" + results2.getRawScanResults().length); - assertDumpContainsCallbackLog("singleScanResults", requestId3, - "results=" + results3.getRawScanResults().length); - } - - /** - * Verify that WifiService provides a way to get the most recent SingleScan results. - */ - @Test - public void retrieveSingleScanResults() throws Exception { - WifiScanner.ScanSettings requestSettings = - createRequest(WifiScanner.WIFI_BAND_ALL, 0, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults expectedResults = - ScanResults.create(0, WifiScanner.WIFI_BAND_ALL, 2412, 5160, 5175); - doSuccessfulSingleScan(requestSettings, - computeSingleScanNativeSettings(requestSettings), - expectedResults); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response = verifyHandleMessageAndGetMessage(order, handler); - List<ScanResult> results = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response.obj).getResults()); - assertEquals(results.size(), expectedResults.getRawScanResults().length); - - // Make sure that we logged the scan results in the dump method. - String serviceDump = dumpService(); - Pattern logLineRegex = Pattern.compile("Latest scan results:"); - assertTrue("dump did not contain Latest scan results: " + serviceDump + "\n", - logLineRegex.matcher(serviceDump).find()); - } - - /** - * Verify that WifiService provides a way to get the most recent SingleScan results even when - * they are empty. - */ - @Test - public void retrieveSingleScanResultsEmpty() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH, new int[0])); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response.obj).getResults()); - assertEquals(results.size(), 0); - } - - /** - * Verify that WifiService will return empty SingleScan results if a scan has not been - * performed. - */ - @Test - public void retrieveSingleScanResultsBeforeAnySingleScans() throws Exception { - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response.obj).getResults()); - assertEquals(results.size(), 0); - } - - /** - * Verify that the newest full scan results are returned by WifiService.getSingleScanResults. - */ - @Test - public void retrieveMostRecentFullSingleScanResults() throws Exception { - int scanBand = WifiScanner.WIFI_BAND_ALL & ~WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY; - WifiScanner.ScanSettings requestSettings = createRequest(scanBand, 0, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults expectedResults = ScanResults.create(0, scanBand, 2412, 5160, 5175); - doSuccessfulSingleScan(requestSettings, - computeSingleScanNativeSettings(requestSettings), - expectedResults); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response.obj).getResults()); - assertEquals(results.size(), expectedResults.getRawScanResults().length); - - // now update with a new scan that only has one result - int secondScanRequestId = 35; - ScanResults expectedSingleResult = ScanResults.create(0, scanBand, 5160); - sendSingleScanRequest(controlChannel, secondScanRequestId, requestSettings, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, - computeSingleScanNativeSettings(requestSettings)); - verifySuccessfulResponse(order, handler, secondScanRequestId); - - // dispatch scan 2 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(expectedSingleResult.getScanData()); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, secondScanRequestId, - expectedSingleResult.getScanData()); - verifySingleScanCompletedReceived(order, handler, secondScanRequestId); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response2 = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results2 = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response2.obj).getResults()); - assertEquals(results2.size(), expectedSingleResult.getRawScanResults().length); - } - - /** - * Verify that the newest partial scan results are not returned by - * WifiService.getSingleScanResults. - */ - @Test - public void doesNotRetrieveMostRecentPartialSingleScanResults() throws Exception { - int scanBand = WifiScanner.WIFI_BAND_ALL & ~WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY; - WifiScanner.ScanSettings fullRequestSettings = createRequest(scanBand, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults expectedFullResults = - ScanResults.create(0, scanBand, 2412, 5160, 5175); - doSuccessfulSingleScan(fullRequestSettings, - computeSingleScanNativeSettings(fullRequestSettings), - expectedFullResults); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response.obj).getResults()); - assertEquals(results.size(), expectedFullResults.getRawScanResults().length); - - // now update with a new scan that only has one result - int secondScanRequestId = 35; - WifiScanner.ScanSettings partialRequestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults expectedPartialResults = - ScanResults.create(0, WifiScanner.WIFI_BAND_5_GHZ, 5160); - sendSingleScanRequest(controlChannel, secondScanRequestId, partialRequestSettings, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, - computeSingleScanNativeSettings(partialRequestSettings)); - verifySuccessfulResponse(order, handler, secondScanRequestId); - - // dispatch scan 2 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(expectedPartialResults.getScanData()); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, secondScanRequestId, - expectedPartialResults.getScanData()); - verifySingleScanCompletedReceived(order, handler, secondScanRequestId); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response2 = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results2 = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response2.obj).getResults()); - assertEquals(results2.size(), expectedFullResults.getRawScanResults().length); - } - - /** - * Verify that the scan results returned by WifiService.getSingleScanResults are not older - * than {@link com.android.server.wifi.scanner.WifiScanningServiceImpl - * .WifiSingleScanStateMachine#CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS}. - */ - @Test - public void doesNotRetrieveStaleScanResultsFromLastFullSingleScan() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_ALL, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults scanResults = - ScanResults.create(0, WifiScanner.WIFI_BAND_ALL, 2412, 5160, 5175); - - // Out of the 3 scan results, modify the timestamp of 2 of them to be within the expiration - // age and 1 out of it. - long currentTimeInMillis = CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS * 2; - when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeInMillis); - scanResults.getRawScanResults()[0].timestamp = (currentTimeInMillis - 1) * 1000; - scanResults.getRawScanResults()[1].timestamp = (currentTimeInMillis - 2) * 1000; - scanResults.getRawScanResults()[2].timestamp = - (currentTimeInMillis - CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS) * 1000; - List<ScanResult> expectedResults = new ArrayList<ScanResult>() {{ - add(scanResults.getRawScanResults()[0]); - add(scanResults.getRawScanResults()[1]); - }}; - - doSuccessfulSingleScan(requestSettings, - computeSingleScanNativeSettings(requestSettings), scanResults); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response = verifyHandleMessageAndGetMessage(order, handler); - - List<ScanResult> results = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response.obj).getResults()); - assertScanResultsEquals(expectedResults.toArray(new ScanResult[expectedResults.size()]), - results.toArray(new ScanResult[results.size()])); - } - - /** - * Cached scan results should be cleared after the driver is unloaded. - */ - @Test - public void validateScanResultsClearedAfterDriverUnloaded() throws Exception { - WifiScanner.ScanSettings requestSettings = - createRequest(WifiScanner.WIFI_BAND_ALL, - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults expectedResults = ScanResults.create( - 0, WifiScanner.WIFI_BAND_ALL, 2412, 5160, 5175); - doSuccessfulSingleScan(requestSettings, - computeSingleScanNativeSettings(requestSettings), - expectedResults); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response = verifyHandleMessageAndGetMessage(order, handler); - List<ScanResult> results = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response.obj).getResults()); - assertEquals(results.size(), expectedResults.getRawScanResults().length); - - // disable wifi - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DISABLE)); - // Now get scan results again. The returned list should be empty since we - // clear the cache when exiting the DriverLoaded state. - controlChannel.sendMessage( - Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0)); - mLooper.dispatchAll(); - Message response2 = verifyHandleMessageAndGetMessage(order, handler); - List<ScanResult> results2 = Arrays.asList( - ((WifiScanner.ParcelableScanResults) response2.obj).getResults()); - assertEquals(results2.size(), 0); - } - - /** - * Register a single scan listener and do a single scan - */ - @Test - public void registerScanListener() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - WifiNative.ScanSettings nativeSettings = computeSingleScanNativeSettings(requestSettings); - ScanResults results = ScanResults.create(0, 2412, 5160, 5175); - - int requestId = 12; - int listenerRequestId = 13; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - registerScanListener(controlChannel, listenerRequestId); - mLooper.dispatchAll(); - verifySuccessfulResponse(order, handler, listenerRequestId); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings); - verifySuccessfulResponse(order, handler, requestId); - - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results.getRawScanData()); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, requestId, results.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId); - verifyScanResultsReceived(order, handler, listenerRequestId, results.getScanData()); - verifyNoMoreInteractions(handler); - - assertDumpContainsRequestLog("registerScanListener", listenerRequestId); - assertDumpContainsCallbackLog("singleScanResults", listenerRequestId, - "results=" + results.getScanData().getResults().length); - } - - /** - * Register a single scan listener and do a single scan - */ - @Test - public void deregisterScanListener() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - WifiNative.ScanSettings nativeSettings = computeSingleScanNativeSettings(requestSettings); - ScanResults results = ScanResults.create(0, 2412, 5160, 5175); - - int requestId = 12; - int listenerRequestId = 13; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - registerScanListener(controlChannel, listenerRequestId); - mLooper.dispatchAll(); - verifySuccessfulResponse(order, handler, listenerRequestId); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings); - verifySuccessfulResponse(order, handler, requestId); - - deregisterScanListener(controlChannel, listenerRequestId); - mLooper.dispatchAll(); - - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results.getRawScanData()); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, requestId, results.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId); - verifyNoMoreInteractions(handler); - - assertDumpContainsRequestLog("registerScanListener", listenerRequestId); - assertDumpContainsRequestLog("deregisterScanListener", listenerRequestId); - } - - /** - * Send a single scan request and then two more before the first completes. Neither are - * satisfied by the first scan. Verify that the first completes and the second two are merged. - */ - @Test - public void scanListenerReceivesAllResults() throws RemoteException { - WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2412), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId1 = 12; - ScanResults results1 = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412); - - WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId2 = 13; - ScanResults results2 = - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2450, 5175, 2450); - - WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5160), 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId3 = 15; - ScanResults results3 = - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 5160, 5160, 5160, 5160); - - WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels( - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5160)); - ScanResults results2and3 = - ScanResults.merge(WifiScanner.WIFI_BAND_UNSPECIFIED, results2, results3); - - int listenerRequestId = 13; - - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder handlerOrder = inOrder(handler); - InOrder nativeOrder = inOrder(mWifiScannerImpl0); - - // Run scan 1 - sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder, - computeSingleScanNativeSettings(requestSettings1)); - verifySuccessfulResponse(handlerOrder, handler, requestId1); - - - // Queue scan 2 (will not run because previous is in progress) - sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId2); - - // Queue scan 3 (will not run because previous is in progress) - sendSingleScanRequest(controlChannel, requestId3, requestSettings3, null); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, requestId3); - - // Register scan listener - registerScanListener(controlChannel, listenerRequestId); - mLooper.dispatchAll(); - verifySuccessfulResponse(handlerOrder, handler, listenerRequestId); - - // dispatch scan 1 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results1.getScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData()); - verifySingleScanCompletedReceived(handlerOrder, handler, requestId1); - verifyScanResultsReceived(handlerOrder, handler, listenerRequestId, results1.getScanData()); - - // now that the first scan completed we expect the second and third ones to start - WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder, - nativeSettings2and3); - - // dispatch scan 2 and 3 results - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results2and3.getScanData()); - eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - - verifyMultipleSingleScanResults(handlerOrder, handler, requestId2, results2, requestId3, - results3, listenerRequestId, results2and3); - - assertDumpContainsRequestLog("registerScanListener", listenerRequestId); - assertDumpContainsCallbackLog("singleScanResults", listenerRequestId, - "results=" + results1.getRawScanResults().length); - assertDumpContainsCallbackLog("singleScanResults", listenerRequestId, - "results=" + results2and3.getRawScanResults().length); - } - - @Test - public void rejectSingleScanRequestWhenScannerGetIfaceNameFails() throws Exception { - // Failed to get client interface name. - when(mWifiNative.getClientInterfaceNames()).thenReturn(new ArraySet<>()); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - sendSingleScanRequest(controlChannel, 122, generateValidScanSettings(), null); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available"); - } - - @Test - public void rejectSingleScanRequestWhenScannerImplCreateFails() throws Exception { - // Fail scanner impl creation. - when(mWifiScannerImplFactory.create(any(), any(), any(), any())).thenReturn(null); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - sendSingleScanRequest(controlChannel, 122, generateValidScanSettings(), null); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available"); - } - - private void doSuccessfulBackgroundScan(WifiScanner.ScanSettings requestSettings, - WifiNative.ScanSettings nativeSettings) { - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - when(mWifiScannerImpl0.startBatchedScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendBackgroundScanRequest(controlChannel, 12, requestSettings, null); - mLooper.dispatchAll(); - verifyStartBackgroundScan(order, nativeSettings); - verifySuccessfulResponse(order, handler, 12); - verifyNoMoreInteractions(handler); - assertDumpContainsRequestLog("addBackgroundScanRequest", 12); - } - - /** - * Do a background scan for a band and verify that it is successful. - */ - @Test - public void sendBackgroundScanBandRequest() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder() - .withBasePeriod(30000) - .withMaxApPerScan(MAX_AP_PER_SCAN) - .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH) - .addBucketWithBand(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_BOTH) - .build(); - doSuccessfulBackgroundScan(requestSettings, nativeSettings); - assertEquals(mWifiMetrics.getBackgroundScanCount(), 1); - } - - /** - * Do a background scan for a list of channels and verify that it is successful. - */ - @Test - public void sendBackgroundScanChannelsRequest() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(5160), 30000, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder() - .withBasePeriod(30000) - .withMaxApPerScan(MAX_AP_PER_SCAN) - .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH) - .addBucketWithChannels(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5160) - .build(); - doSuccessfulBackgroundScan(requestSettings, nativeSettings); - } - - private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForHwPno() - throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest( - channelsToSpec(0, 2412, 5160, 5175), 30000, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder() - .withBasePeriod(30000) - .withMaxApPerScan(MAX_AP_PER_SCAN) - .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH) - .addBucketWithChannels(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - 0, 2412, 5160, 5175) - .build(); - return Pair.create(requestSettings, nativeSettings); - } - - private Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> createPnoSettings( - ScanResults results) - throws Exception { - WifiScanner.PnoSettings requestPnoSettings = new WifiScanner.PnoSettings(); - requestPnoSettings.networkList = - new WifiScanner.PnoSettings.PnoNetwork[results.getRawScanResults().length]; - int i = 0; - for (ScanResult scanResult : results.getRawScanResults()) { - requestPnoSettings.networkList[i++] = - new WifiScanner.PnoSettings.PnoNetwork(scanResult.SSID); - } - - WifiNative.PnoSettings nativePnoSettings = new WifiNative.PnoSettings(); - nativePnoSettings.min5GHzRssi = requestPnoSettings.min5GHzRssi; - nativePnoSettings.min24GHzRssi = requestPnoSettings.min24GHzRssi; - nativePnoSettings.min6GHzRssi = requestPnoSettings.min6GHzRssi; - nativePnoSettings.isConnected = requestPnoSettings.isConnected; - nativePnoSettings.networkList = - new WifiNative.PnoNetwork[requestPnoSettings.networkList.length]; - for (i = 0; i < requestPnoSettings.networkList.length; i++) { - nativePnoSettings.networkList[i] = new WifiNative.PnoNetwork(); - nativePnoSettings.networkList[i].ssid = requestPnoSettings.networkList[i].ssid; - nativePnoSettings.networkList[i].flags = requestPnoSettings.networkList[i].flags; - nativePnoSettings.networkList[i].auth_bit_field = - requestPnoSettings.networkList[i].authBitField; - } - return Pair.create(requestPnoSettings, nativePnoSettings); - } - - private ScanResults createScanResultsForPno() { - return ScanResults.create(0, 2412, 5160, 5175); - } - - private WifiNative.PnoEventHandler verifyHwPnoForImpl(WifiScannerImpl impl, InOrder order, - WifiNative.PnoSettings expected) { - ArgumentCaptor<WifiNative.PnoSettings> pnoSettingsCaptor = - ArgumentCaptor.forClass(WifiNative.PnoSettings.class); - ArgumentCaptor<WifiNative.PnoEventHandler> pnoEventHandlerCaptor = - ArgumentCaptor.forClass(WifiNative.PnoEventHandler.class); - order.verify(impl).setHwPnoList(pnoSettingsCaptor.capture(), - pnoEventHandlerCaptor.capture()); - assertNativePnoSettingsEquals(expected, pnoSettingsCaptor.getValue()); - return pnoEventHandlerCaptor.getValue(); - } - - private void sendPnoScanRequest(BidirectionalAsyncChannel controlChannel, - int scanRequestId, WifiScanner.ScanSettings scanSettings, - WifiScanner.PnoSettings pnoSettings) { - Bundle pnoParams = new Bundle(); - scanSettings.isPnoScan = true; - pnoParams.putParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings); - pnoParams.putParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_PNO_SCAN, 0, - scanRequestId, pnoParams)); - } - - private void assertPnoNetworkFoundMessage(int listenerId, ScanResult[] expected, - Message networkFoundMessage) { - assertEquals("what", WifiScanner.CMD_PNO_NETWORK_FOUND, networkFoundMessage.what); - assertEquals("listenerId", listenerId, networkFoundMessage.arg2); - assertScanResultsEquals(expected, - ((WifiScanner.ParcelableScanResults) networkFoundMessage.obj).getResults()); - } - - private void verifyPnoNetworkFoundReceived(InOrder order, Handler handler, int listenerId, - ScanResult[] expected) { - Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler, - WifiScanner.CMD_PNO_NETWORK_FOUND); - assertPnoNetworkFoundMessage(listenerId, expected, scanResultMessage); - } - - private void expectSuccessfulBackgroundScan(InOrder order, - WifiNative.ScanSettings nativeSettings, ScanResults results) { - when(mWifiScannerImpl0.startBatchedScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = verifyStartBackgroundScan(order, nativeSettings); - WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1]; - scanDatas[0] = results.getScanData(); - for (ScanResult fullScanResult : results.getRawScanResults()) { - eventHandler.onFullScanResult(fullScanResult, 0); - } - when(mWifiScannerImpl0.getLatestBatchedScanResults(anyBoolean())).thenReturn(scanDatas); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - mLooper.dispatchAll(); - } - - private void expectHwPnoScan(InOrder order, Handler handler, int requestId, - WifiNative.PnoSettings nativeSettings, ScanResults results) { - when(mWifiScannerImpl0.isHwPnoSupported(anyBoolean())).thenReturn(true); - - when(mWifiScannerImpl0.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(true); - mLooper.dispatchAll(); - WifiNative.PnoEventHandler eventHandler = - verifyHwPnoForImpl(mWifiScannerImpl0, order, nativeSettings); - verifySuccessfulResponse(order, handler, requestId); - eventHandler.onPnoNetworkFound(results.getRawScanResults()); - mLooper.dispatchAll(); - } - - private void expectHwPnoScanOnImpls(InOrder order, Handler handler, - int requestId, WifiNative.PnoSettings nativeSettings, - @Nullable ScanResults resultsForImpl0, @Nullable ScanResults resultsForImpl1) { - when(mWifiScannerImpl0.isHwPnoSupported(anyBoolean())).thenReturn(true); - when(mWifiScannerImpl1.isHwPnoSupported(anyBoolean())).thenReturn(true); - - when(mWifiScannerImpl0.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(true); - when(mWifiScannerImpl1.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(true); - mLooper.dispatchAll(); - WifiNative.PnoEventHandler eventHandler0 = - verifyHwPnoForImpl(mWifiScannerImpl0, order, nativeSettings); - WifiNative.PnoEventHandler eventHandler1 = - verifyHwPnoForImpl(mWifiScannerImpl1, order, nativeSettings); - verifySuccessfulResponse(order, handler, requestId); - if (resultsForImpl0 != null) { - eventHandler0.onPnoNetworkFound(resultsForImpl0.getRawScanResults()); - } else if (resultsForImpl1 != null) { - eventHandler1.onPnoNetworkFound(resultsForImpl1.getRawScanResults()); - } - mLooper.dispatchAll(); - } - - /** - * Tests wificond PNO scan. This ensures that the PNO scan results are plumbed back to the - * client as a PNO network found event. - */ - @Test - public void testSuccessfulHwPnoScanWithNoBackgroundScan() throws Exception { - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - int requestId = 12; - - ScanResults scanResults = createScanResultsForPno(); - Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings = - createScanSettingsForHwPno(); - Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings = - createPnoSettings(scanResults); - - sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first); - expectHwPnoScan(order, handler, requestId, pnoSettings.second, scanResults); - verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults()); - } - - @Test - public void rejectHwPnoScanRequestWhenScannerImplCreateFails() throws Exception { - // Fail scanner impl creation. - when(mWifiScannerImplFactory.create(any(), any(), any(), any())).thenReturn(null); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0); - - ScanResults scanResults = createScanResultsForPno(); - Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings = - createScanSettingsForHwPno(); - Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings = - createPnoSettings(scanResults); - - sendPnoScanRequest(controlChannel, 122, scanSettings.first, pnoSettings.first); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available"); - } - - /** - * Tries to simulate the race scenario where a client is disconnected immediately after single - * scan request is sent to |SingleScanStateMachine|. - */ - @Test - public void processSingleScanRequestAfterDisconnect() throws Exception { - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class)); - mLooper.dispatchAll(); - - // Send the single scan request and then send the disconnect immediately after. - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 10; - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - // Can't call |disconnect| here because that sends |CMD_CHANNEL_DISCONNECT| followed by - // |CMD_CHANNEL_DISCONNECTED|. - controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED, - AsyncChannel.STATUS_REMOTE_DISCONNECTION, 0, null)); - - // Now process the above 2 actions. This should result in first processing the single scan - // request (which forwards the request to SingleScanStateMachine) and then processing the - // disconnect after. - mLooper.dispatchAll(); - - // Now check that we logged the invalid request. - String serviceDump = dumpService(); - Pattern logLineRegex = Pattern.compile("^.+" + "singleScanInvalidRequest: " - + "ClientInfo\\[unknown\\],Id=" + requestId + ",bad request$", Pattern.MULTILINE); - assertTrue("dump did not contain log with ClientInfo[unknown]: " + serviceDump + "\n", - logLineRegex.matcher(serviceDump).find()); - } - - /** - * Tries to simulate the race scenario where a client is disconnected immediately after single - * scan request is sent to |SingleScanStateMachine|. - */ - @Test - public void sendScanRequestAfterUnsuccessfulSend() throws Exception { - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 9; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - mLooper.dispatchAll(); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - ScanResults results = ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH, 2412); - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results.getRawScanData()); - - InOrder order = inOrder(mWifiScannerImpl0, handler); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order, - computeSingleScanNativeSettings(requestSettings)); - verifySuccessfulResponse(order, handler, requestId); - - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, requestId, results.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId); - verifyNoMoreInteractions(handler); - - controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED, - AsyncChannel.STATUS_SEND_UNSUCCESSFUL, 0, null)); - mLooper.dispatchAll(); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order, - computeSingleScanNativeSettings(requestSettings)); - verifySuccessfulResponse(order, handler, requestId); - - eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, requestId, results.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId); - verifyNoMoreInteractions(handler); - } - - /** - * Verifies that background scan works after duplicate scan enable. - */ - @Test - public void backgroundScanAfterDuplicateScanEnable() throws RemoteException { - startServiceAndLoadDriver(); - - // Send scan enable again. - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - // Ensure we didn't create scanner instance twice. - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), any()); - - InOrder order = inOrder(handler); - when(mWifiScannerImpl0.startBatchedScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings(), null); - mLooper.dispatchAll(); - verifySuccessfulResponse(order, handler, 192); - assertDumpContainsRequestLog("addBackgroundScanRequest", 192); - } - - /** - * Verifies that single scan works after duplicate scan enable. - */ - @Test - public void singleScanScanAfterDuplicateScanEnable() throws RemoteException { - startServiceAndLoadDriver(); - - // Send scan enable again. - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - // Ensure we didn't create scanner instance twice. - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), any()); - - InOrder order = inOrder(handler, mWifiScannerImpl0); - - int requestId = 12; - WorkSource workSource = new WorkSource(2292); - WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2412, 5160, 5175), - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - ScanResults results = - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412, 5160, 5175); - - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, workSource); - - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler = - verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings)); - verifySuccessfulResponse(order, handler, requestId); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource)); - - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(results.getRawScanData()); - eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, requestId, results.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId); - verifyNoMoreInteractions(handler); - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource)); - assertDumpContainsRequestLog("addSingleScanRequest", requestId); - assertDumpContainsCallbackLog("singleScanResults", requestId, - "results=" + results.getScanData().getResults().length); - } - - /** - * Verifies that pno scan works after duplicate scan enable. - */ - @Test - public void hwPnoScanScanAfterDuplicateScanEnable() throws Exception { - startServiceAndLoadDriver(); - - // Send scan enable again. - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - // Ensure we didn't create scanner instance twice. - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), any()); - - InOrder order = inOrder(handler, mWifiScannerImpl0); - int requestId = 12; - - ScanResults scanResults = createScanResultsForPno(); - Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings = - createScanSettingsForHwPno(); - Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings = - createPnoSettings(scanResults); - - sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first); - expectHwPnoScan(order, handler, requestId, pnoSettings.second, scanResults); - verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults()); - } - - /** - * Verifies that only clients with NETWORK_STACK permission can issues restricted messages - * (from API's). - */ - @Test - public void rejectRestrictedMessagesFromNonPrivilegedApps() throws Exception { - mWifiScanningServiceImpl.startService(); - mLooper.dispatchAll(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - - // Client doesn't have NETWORK_STACK permission. - doThrow(new SecurityException()).when(mContext).enforcePermission( - eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); - - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DISABLE)); - mLooper.dispatchAll(); - - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_PNO_SCAN)); - mLooper.dispatchAll(); - - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_STOP_PNO_SCAN)); - mLooper.dispatchAll(); - - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_REGISTER_SCAN_LISTENER)); - mLooper.dispatchAll(); - - // All 4 of the above messages should have been rejected because the app doesn't have - // the required permissions. - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(handler, times(5)).handleMessage(messageCaptor.capture()); - assertFailedResponse(0, WifiScanner.REASON_NOT_AUTHORIZED, - "Not authorized", messageCaptor.getAllValues().get(0)); - assertFailedResponse(0, WifiScanner.REASON_NOT_AUTHORIZED, - "Not authorized", messageCaptor.getAllValues().get(1)); - assertFailedResponse(0, WifiScanner.REASON_NOT_AUTHORIZED, - "Not authorized", messageCaptor.getAllValues().get(2)); - assertFailedResponse(0, WifiScanner.REASON_NOT_AUTHORIZED, - "Not authorized", messageCaptor.getAllValues().get(3)); - assertFailedResponse(0, WifiScanner.REASON_NOT_AUTHORIZED, - "Not authorized", messageCaptor.getAllValues().get(4)); - - // Ensure we didn't create scanner instance. - verify(mWifiScannerImplFactory, never()).create(any(), any(), any(), any()); - - } - - /** - * Verifies that clients without NETWORK_STACK permission cannot issue any messages when they - * don't have the necessary location permissions & location is enabled. - */ - @Test - public void rejectAllMessagesFromNonPrivilegedAppsWithoutLocationPermission() throws Exception { - // Start service & initialize it. - startServiceAndLoadDriver(); - - // Location permission or mode check fail. - doThrow(new SecurityException()).when(mWifiPermissionsUtil) - .enforceCanAccessScanResultsForWifiScanner(any(), any(), eq(Binder.getCallingUid()), - eq(false), eq(false)); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - - // Client doesn't have NETWORK_STACK permission. - doThrow(new SecurityException()).when(mContext).enforcePermission( - eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); - - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_SINGLE_SCAN)); - mLooper.dispatchAll(); - - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_GET_SCAN_RESULTS)); - mLooper.dispatchAll(); - - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN)); - mLooper.dispatchAll(); - - // All the above messages should have been rejected because the app doesn't have - // the privileged permissions & location is turned off. - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(handler, times(3)).handleMessage(messageCaptor.capture()); - assertFailedResponse(0, WifiScanner.REASON_NOT_AUTHORIZED, - "Not authorized", messageCaptor.getAllValues().get(0)); - assertFailedResponse(0, WifiScanner.REASON_NOT_AUTHORIZED, - "Not authorized", messageCaptor.getAllValues().get(1)); - assertFailedResponse(0, WifiScanner.REASON_NOT_AUTHORIZED, - "Not authorized", messageCaptor.getAllValues().get(2)); - - // Validate the initialization sequence. - verify(mWifiScannerImpl0).getChannelHelper(); - verify(mWifiScannerImpl0).getScanCapabilities(any()); - - // Ensure we didn't start any scans after. - verifyNoMoreInteractions(mWifiScannerImpl0); - } - - /** - * Verifies that we ignore location settings when the single scan request settings sets - * {@link WifiScanner.ScanSettings#ignoreLocationSettings} - */ - @Test - public void verifyIgnoreLocationSettingsFromNonPrivilegedAppsForSingleScan() throws Exception { - // Start service & initialize it. - startServiceAndLoadDriver(); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - - // Client doesn't have NETWORK_STACK permission. - doThrow(new SecurityException()).when(mContext).enforcePermission( - eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); - - Bundle bundle = new Bundle(); - bundle.putString(WifiScanner.REQUEST_PACKAGE_NAME_KEY, TEST_PACKAGE_NAME); - bundle.putString(WifiScanner.REQUEST_FEATURE_ID_KEY, TEST_FEATURE_ID); - WifiScanner.ScanSettings scanSettings = new WifiScanner.ScanSettings(); - - // send single scan request (ignoreLocationSettings == true). - scanSettings.ignoreLocationSettings = true; - bundle.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, scanSettings); - Message message = Message.obtain(); - message.what = WifiScanner.CMD_START_SINGLE_SCAN; - message.obj = bundle; - controlChannel.sendMessage(message); - mLooper.dispatchAll(); - - // Verify the permission check params (ignoreLocationSettings == true). - verify(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), eq(Binder.getCallingUid()), eq(true), - eq(false)); - - // send single scan request (ignoreLocationSettings == false). - scanSettings.ignoreLocationSettings = false; - bundle.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, scanSettings); - message = Message.obtain(); - message.what = WifiScanner.CMD_START_SINGLE_SCAN; - message.obj = bundle; - controlChannel.sendMessage(message); - mLooper.dispatchAll(); - - // Verify the permission check params (ignoreLocationSettings == true). - verify(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), eq(Binder.getCallingUid()), eq(false), - eq(false)); - - // send background scan request (ignoreLocationSettings == true). - scanSettings.ignoreLocationSettings = true; - bundle.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, scanSettings); - message = Message.obtain(); - message.what = WifiScanner.CMD_START_BACKGROUND_SCAN; - controlChannel.sendMessage(message); - mLooper.dispatchAll(); - - // Verify the permission check params (ignoreLocationSettings == false), the field - // is ignored for any requests other than single scan. - verify(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), eq(Binder.getCallingUid()), eq(false), - eq(false)); - } - - /** - * Verifies that we hide from app-ops when the single scan request settings sets - * {@link WifiScanner.ScanSettings#hideFromAppOps} - */ - @Test - public void verifyHideFromAppOpsFromNonPrivilegedAppsForSingleScan() throws Exception { - // Start service & initialize it. - startServiceAndLoadDriver(); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - - // Client doesn't have NETWORK_STACK permission. - doThrow(new SecurityException()).when(mContext).enforcePermission( - eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); - - Bundle bundle = new Bundle(); - bundle.putString(WifiScanner.REQUEST_PACKAGE_NAME_KEY, TEST_PACKAGE_NAME); - bundle.putString(WifiScanner.REQUEST_FEATURE_ID_KEY, TEST_FEATURE_ID); - WifiScanner.ScanSettings scanSettings = new WifiScanner.ScanSettings(); - - // send single scan request (hideFromAppOps == true). - scanSettings.hideFromAppOps = true; - bundle.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, scanSettings); - Message message = Message.obtain(); - message.what = WifiScanner.CMD_START_SINGLE_SCAN; - message.obj = bundle; - controlChannel.sendMessage(message); - mLooper.dispatchAll(); - - // Verify the permission check params (hideFromAppOps == true). - verify(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), eq(Binder.getCallingUid()), eq(false), - eq(true)); - - // send single scan request (hideFromAppOps == false). - scanSettings.hideFromAppOps = false; - bundle.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, scanSettings); - message = Message.obtain(); - message.what = WifiScanner.CMD_START_SINGLE_SCAN; - message.obj = bundle; - controlChannel.sendMessage(message); - mLooper.dispatchAll(); - - // Verify the permission check params (hideFromAppOps == false). - verify(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), eq(Binder.getCallingUid()), eq(false), - eq(false)); - - // send background scan request (hideFromAppOps == true). - scanSettings.hideFromAppOps = true; - bundle.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, scanSettings); - message = Message.obtain(); - message.what = WifiScanner.CMD_START_BACKGROUND_SCAN; - controlChannel.sendMessage(message); - mLooper.dispatchAll(); - - // Verify the permission check params (hideFromAppOps == false), the field - // is ignored for any requests other than single scan. - verify(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), eq(Binder.getCallingUid()), eq(false), - eq(false)); - } - - /** - * Verifies that we don't invoke {@link WifiPermissionsUtil# - * enforceCanAccessScanResultsForWifiScanner(String, int, boolean, boolean)} for requests - * from privileged clients (i.e wifi service). - */ - @Test - public void verifyLocationPermissionCheckIsSkippedFromPrivilegedClientsForSingleScan() - throws Exception { - // Start service & initialize it. - startServiceAndLoadDriver(); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - - // Client does have NETWORK_STACK permission. - doNothing().when(mContext).enforcePermission( - eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); - - Bundle bundle = new Bundle(); - bundle.putString(WifiScanner.REQUEST_PACKAGE_NAME_KEY, TEST_PACKAGE_NAME); - bundle.putString(WifiScanner.REQUEST_FEATURE_ID_KEY, TEST_FEATURE_ID); - WifiScanner.ScanSettings scanSettings = new WifiScanner.ScanSettings(); - - // send single scan request (hideFromAppOps == true, ignoreLocationSettings = true). - scanSettings.hideFromAppOps = true; - scanSettings.ignoreLocationSettings = true; - bundle.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, scanSettings); - Message message = Message.obtain(); - message.what = WifiScanner.CMD_START_SINGLE_SCAN; - message.obj = bundle; - controlChannel.sendMessage(message); - mLooper.dispatchAll(); - - // Verify that we didn't invoke the location permission check. - verify(mWifiPermissionsUtil, never()).enforceCanAccessScanResultsForWifiScanner( - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), eq(Binder.getCallingUid()), - anyBoolean(), anyBoolean()); - } - - /** - * Setup/teardown a second scanner impl dynamically. - */ - @Test - public void setupAndTeardownSecondImpl() throws Exception { - // start up service with a single impl. - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), eq(TEST_IFACE_NAME_0)); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - - // Now setup an impl for second iface. - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), eq(TEST_IFACE_NAME_1)); - - // Now teardown the impl for second iface. - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0))); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - verify(mWifiScannerImpl1).cleanup(); - - // Now teardown everything. - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DISABLE)); - mLooper.dispatchAll(); - - verify(mWifiScannerImpl0).cleanup(); - } - - /** - * Setup/teardown a second scanner impl dynamically which satisfies the same set of channels - * as the existing one. - */ - @Test - public void setupAndTeardownSecondImplWhichSatisfiesExistingImpl() throws Exception { - // start up service with a single impl. - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), eq(TEST_IFACE_NAME_0)); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - - // Now setup an impl for second iface. - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - // Setup the second impl to contain the same set of channels as the first one. - when(mWifiScannerImpl1.getChannelHelper()).thenReturn(mChannelHelper0); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - // Verify that we created the new impl and immediately tore it down because it was - // satisfied by an existing impl. - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), eq(TEST_IFACE_NAME_1)); - verify(mWifiScannerImpl1, times(1)).getChannelHelper(); - verify(mWifiScannerImpl1, times(1)).cleanup(); - - // Now teardown the second iface. - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0))); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - // do nothing, since impl1 was never added to the active impl list. - verifyNoMoreInteractions(mWifiScannerImpl1); - - // Now teardown everything. - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DISABLE)); - mLooper.dispatchAll(); - - verify(mWifiScannerImpl0).cleanup(); - } - - /** - * Setup a second scanner impl and tearddown a existing scanning impl dynamically which - * satisfies the same set of channels as the existing one. - */ - @Test - public void setupSecondImplAndTeardownFirstImplWhichSatisfiesExistingImpl() throws Exception { - // start up service with a single impl. - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), eq(TEST_IFACE_NAME_0)); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler); - - - // Now setup an impl for second iface and teardown the first one. - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_1))); - // Setup the second impl to contain the same set of channels as the first one. - when(mWifiScannerImpl1.getChannelHelper()).thenReturn(mChannelHelper0); - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_ENABLE)); - mLooper.dispatchAll(); - - // tear down the first one because corresponding iface was brought down. - verify(mWifiScannerImpl0).cleanup(); - - // Verify that we created the new impl. - verify(mWifiScannerImplFactory, times(1)) - .create(any(), any(), any(), eq(TEST_IFACE_NAME_1)); - verify(mWifiScannerImpl1, never()).getChannelHelper(); - - // Now teardown everything. - controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DISABLE)); - mLooper.dispatchAll(); - - verify(mWifiScannerImpl1).cleanup(); - } - - /** - * Do a single scan for a band and verify that it is successful across multiple impls. - */ - @Test - public void sendSingleScanBandRequestOnMultipleImpls() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - WifiScanner.ScanSettings requestSettings = createRequest( - WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 0, 0, 20, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScanOnImpls(requestSettings, - computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 2412), - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 5160)); - } - - /** - * Do a single scan for a list of channels and verify that it is successful across multiple - * impls. - */ - @Test - public void sendSingleScanChannelsRequestOnMultipleImpls() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2412, 5160, 5175), - 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScanOnImpls(requestSettings, - computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412), - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 5175)); - } - - /** - * Do a single scan with no results and verify that it is successful across multiple - * impls. - */ - @Test - public void sendSingleScanRequestWithNoResultsOnMultipleImpls() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - doSuccessfulSingleScanOnImpls(requestSettings, - computeSingleScanNativeSettings(requestSettings), - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH, new int[0]), - ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH, new int[0])); - } - - /** - * Do a single scan, which the hardware fails to start across multiple impls, and verify that a - * failure response is delivered. - */ - @Test - public void sendSingleScanRequestWhichFailsToStartOnMultipleImpls() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - - // scan fails - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(false); - when(mWifiScannerImpl1.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(false); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - mLooper.dispatchAll(); - // Scan is successfully queue, but then fails to execute - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - order.verify(handler, times(2)).handleMessage(messageCaptor.capture()); - assertSuccessfulResponse(requestId, messageCaptor.getAllValues().get(0)); - assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED, - "Failed to start single scan", messageCaptor.getAllValues().get(1)); - verifyNoMoreInteractions(mBatteryStats); - - assertEquals(mWifiMetrics.getOneshotScanCount(), 1); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1); - assertDumpContainsRequestLog("addSingleScanRequest", requestId); - } - - /** - * Do a single scan, which the hardware fails to start on one of the impl, and verify that a - * successful response is delivered when other impls succeed. - */ - @Test - public void sendSingleScanRequestWhichFailsToStartOnOneImpl() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - WifiNative.ScanSettings nativeSettings = computeSingleScanNativeSettings(requestSettings); - ScanResults results = - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412, 5160, 5175); - int requestId = 33; - WorkSource workSource = new WorkSource(2292); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - - // scan fails on impl0 - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(false); - // scan succeeds on impl1 - when(mWifiScannerImpl1.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, workSource); - - mLooper.dispatchAll(); - - WifiNative.ScanEventHandler eventHandler0 = - verifyStartSingleScanForImpl(mWifiScannerImpl0, order, nativeSettings); - WifiNative.ScanEventHandler eventHandler1 = - verifyStartSingleScanForImpl(mWifiScannerImpl1, order, nativeSettings); - verifySuccessfulResponse(order, handler, requestId); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource)); - - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(new WifiScanner.ScanData(DUMMY_SCAN_DATA)); - // Send scan success on impl1 - when(mWifiScannerImpl1.getLatestSingleScanResults()) - .thenReturn(results.getRawScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, requestId, results.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId); - verifyNoMoreInteractions(handler); - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource)); - assertDumpContainsRequestLog("addSingleScanRequest", requestId); - assertDumpContainsCallbackLog("singleScanResults", requestId, - "results=" + results.getScanData().getResults().length); - } - - /** - * Do a single scan, which successfully starts, but fails across multiple impls partway through - * and verify that a failure response is delivered. - */ - @Test - public void sendSingleScanRequestWhichFailsAfterStartOnMultipleImpls() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - int requestId = 33; - WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - - // successful start - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - when(mWifiScannerImpl1.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - // Scan is successfully queue - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler0 = - verifyStartSingleScanForImpl(mWifiScannerImpl0, order, - computeSingleScanNativeSettings(requestSettings)); - WifiNative.ScanEventHandler eventHandler1 = - verifyStartSingleScanForImpl(mWifiScannerImpl1, order, - computeSingleScanNativeSettings(requestSettings)); - verifySuccessfulResponse(order, handler, requestId); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource)); - - // but then fails to execute - eventHandler0.onScanStatus(WifiNative.WIFI_SCAN_FAILED); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_FAILED); - mLooper.dispatchAll(); - verifyFailedResponse(order, handler, requestId, - WifiScanner.REASON_UNSPECIFIED, "Scan failed"); - assertDumpContainsCallbackLog("singleScanFailed", requestId, - "reason=" + WifiScanner.REASON_UNSPECIFIED + ", Scan failed"); - assertEquals(mWifiMetrics.getOneshotScanCount(), 1); - assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1); - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource)); - } - - /** - * Do a single scan, which successfully starts, but fails partway through on one of the impls - * and verify that a successful response is delivered. - */ - @Test - public void sendSingleScanRequestWhichFailsAfterStartOnOneImpl() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0, - 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); - WifiNative.ScanSettings nativeSettings = computeSingleScanNativeSettings(requestSettings); - ScanResults results = - ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412, 5160, 5175); - int requestId = 33; - WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - - // successful start - when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - when(mWifiScannerImpl1.startSingleScan(any(WifiNative.ScanSettings.class), - any(WifiNative.ScanEventHandler.class))).thenReturn(true); - - sendSingleScanRequest(controlChannel, requestId, requestSettings, null); - - // Scan is successfully queued - mLooper.dispatchAll(); - WifiNative.ScanEventHandler eventHandler0 = - verifyStartSingleScanForImpl(mWifiScannerImpl0, order, nativeSettings); - WifiNative.ScanEventHandler eventHandler1 = - verifyStartSingleScanForImpl(mWifiScannerImpl1, order, nativeSettings); - verifySuccessfulResponse(order, handler, requestId); - verify(mBatteryStats).reportWifiScanStartedFromSource(eq(workSource)); - - // then fails to execute on impl0 - when(mWifiScannerImpl0.getLatestSingleScanResults()) - .thenReturn(new WifiScanner.ScanData(DUMMY_SCAN_DATA)); - eventHandler0.onScanStatus(WifiNative.WIFI_SCAN_FAILED); - // but succeeds on impl1 - when(mWifiScannerImpl1.getLatestSingleScanResults()) - .thenReturn(results.getRawScanData()); - eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); - - mLooper.dispatchAll(); - verifyScanResultsReceived(order, handler, requestId, results.getScanData()); - verifySingleScanCompletedReceived(order, handler, requestId); - verifyNoMoreInteractions(handler); - verify(mBatteryStats).reportWifiScanStoppedFromSource(eq(workSource)); - assertDumpContainsRequestLog("addSingleScanRequest", requestId); - assertDumpContainsCallbackLog("singleScanResults", requestId, - "results=" + results.getScanData().getResults().length); - } - - /** - * Tests wificond PNO scan across multiple impls. This ensures that the - * PNO scan results are plumbed back to the client as a PNO network found event. - */ - @Test - public void testSuccessfulHwPnoScanOnMultipleImpls() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - int requestId = 12; - - ScanResults scanResults = createScanResultsForPno(); - Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings = - createScanSettingsForHwPno(); - Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings = - createPnoSettings(scanResults); - - // Results received on impl 0 - sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first); - expectHwPnoScanOnImpls(order, handler, requestId, pnoSettings.second, scanResults, null); - verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults()); - } - - /** - * Tests wificond PNO scan that fails to start on all impls. - */ - @Test - public void testFailedHwPnoScanWhichFailsToStartOnMultipleImpls() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - int requestId = 12; - - ScanResults scanResults = createScanResultsForPno(); - Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings = - createScanSettingsForHwPno(); - Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings = - createPnoSettings(scanResults); - - when(mWifiScannerImpl0.isHwPnoSupported(anyBoolean())).thenReturn(true); - when(mWifiScannerImpl1.isHwPnoSupported(anyBoolean())).thenReturn(true); - // pno scan fails on both impls - when(mWifiScannerImpl0.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(false); - when(mWifiScannerImpl1.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(false); - - sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first); - mLooper.dispatchAll(); - - verifyFailedResponse(order, handler, requestId, WifiScanner.REASON_INVALID_REQUEST, - "bad request"); - } - - /** - * Tests wificond PNO scan that fails to start on one of the impls. - */ - @Test - public void testSuccessfulHwPnoScanWhichFailsToStartOnOneImpl() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - int requestId = 12; - - ScanResults scanResults = createScanResultsForPno(); - Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings = - createScanSettingsForHwPno(); - Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings = - createPnoSettings(scanResults); - - when(mWifiScannerImpl0.isHwPnoSupported(anyBoolean())).thenReturn(true); - when(mWifiScannerImpl1.isHwPnoSupported(anyBoolean())).thenReturn(true); - // pno scan fails on impl0 - when(mWifiScannerImpl0.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(false); - // pno scan succeeds on impl1 - when(mWifiScannerImpl1.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(true); - - sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first); - mLooper.dispatchAll(); - - WifiNative.PnoEventHandler eventHandler0 = - verifyHwPnoForImpl(mWifiScannerImpl0, order, pnoSettings.second); - WifiNative.PnoEventHandler eventHandler1 = - verifyHwPnoForImpl(mWifiScannerImpl1, order, pnoSettings.second); - - verifySuccessfulResponse(order, handler, requestId); - - eventHandler1.onPnoNetworkFound(scanResults.getRawScanResults()); - mLooper.dispatchAll(); - - verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults()); - } - - /** - * Tests wificond PNO scan that fails after start on all impls. - */ - @Test - public void testFailedHwPnoScanWhichFailsAfterStartOnMultipleImpls() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - int requestId = 12; - - ScanResults scanResults = createScanResultsForPno(); - Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings = - createScanSettingsForHwPno(); - Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings = - createPnoSettings(scanResults); - - when(mWifiScannerImpl0.isHwPnoSupported(anyBoolean())).thenReturn(true); - when(mWifiScannerImpl1.isHwPnoSupported(anyBoolean())).thenReturn(true); - // pno scan succeeds - when(mWifiScannerImpl0.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(true); - when(mWifiScannerImpl1.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(true); - - sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first); - mLooper.dispatchAll(); - - WifiNative.PnoEventHandler eventHandler0 = - verifyHwPnoForImpl(mWifiScannerImpl0, order, pnoSettings.second); - WifiNative.PnoEventHandler eventHandler1 = - verifyHwPnoForImpl(mWifiScannerImpl1, order, pnoSettings.second); - - verifySuccessfulResponse(order, handler, requestId); - - // fails afterwards. - eventHandler0.onPnoScanFailed(); - eventHandler1.onPnoScanFailed(); - mLooper.dispatchAll(); - - // Scan is successfully queue, but then fails to execute - ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); - order.verify(handler).handleMessage(messageCaptor.capture()); - assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED, - "pno scan failed", messageCaptor.getValue()); - } - - /** - * Tests wificond PNO scan that fails after start on one impls. - */ - @Test - public void testSuccessfulHwPnoScanWhichFailsAfterStartOnOneImpl() throws Exception { - when(mWifiNative.getClientInterfaceNames()) - .thenReturn(new ArraySet<>(Arrays.asList(TEST_IFACE_NAME_0, TEST_IFACE_NAME_1))); - - startServiceAndLoadDriver(); - mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog); - Handler handler = mock(Handler.class); - BidirectionalAsyncChannel controlChannel = connectChannel(handler); - InOrder order = inOrder(handler, mWifiScannerImpl0, mWifiScannerImpl1); - int requestId = 12; - - ScanResults scanResults = createScanResultsForPno(); - Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings = - createScanSettingsForHwPno(); - Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings = - createPnoSettings(scanResults); - - when(mWifiScannerImpl0.isHwPnoSupported(anyBoolean())).thenReturn(true); - when(mWifiScannerImpl1.isHwPnoSupported(anyBoolean())).thenReturn(true); - // pno scan succeeds - when(mWifiScannerImpl0.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(true); - when(mWifiScannerImpl1.setHwPnoList(any(WifiNative.PnoSettings.class), - any(WifiNative.PnoEventHandler.class))).thenReturn(true); - - sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first); - mLooper.dispatchAll(); - - WifiNative.PnoEventHandler eventHandler0 = - verifyHwPnoForImpl(mWifiScannerImpl0, order, pnoSettings.second); - WifiNative.PnoEventHandler eventHandler1 = - verifyHwPnoForImpl(mWifiScannerImpl1, order, pnoSettings.second); - - verifySuccessfulResponse(order, handler, requestId); - - // fails afterwards on impl0. - eventHandler0.onPnoScanFailed(); - // pno match on impl1. - eventHandler1.onPnoNetworkFound(scanResults.getRawScanResults()); - mLooper.dispatchAll(); - - verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults()); - } - - /** - * Tests that {@link WifiScanningServiceImpl#getAvailableChannels(int, String)} throws a - * {@link SecurityException} if the caller doesn't hold the required permissions. - */ - @Test(expected = SecurityException.class) - public void getAvailableChannels_noPermission_throwsException() throws Exception { - startServiceAndLoadDriver(); - - // Client doesn't have NETWORK_STACK permission. - doThrow(new SecurityException()).when(mContext).enforcePermission( - eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); - - // Location permission or mode check fail. - doThrow(new SecurityException()) - .when(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - TEST_PACKAGE_NAME, TEST_FEATURE_ID, Binder.getCallingUid(), false, false); - - mWifiScanningServiceImpl.getAvailableChannels(WifiScanner.WIFI_BAND_24_GHZ, - TEST_PACKAGE_NAME, TEST_FEATURE_ID); - } - - /** - * Tests that {@link WifiScanningServiceImpl#getAvailableChannels(int, String)} returns - * the expected result if the caller does hold the required permissions. - */ - @Test - public void getAvailableChannels_hasPermission_returnsSuccessfully() throws Exception { - startServiceAndLoadDriver(); - - // Client doesn't have NETWORK_STACK permission. - doThrow(new SecurityException()).when(mContext).enforcePermission( - eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); - - // has access scan results permission - doNothing().when(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - TEST_PACKAGE_NAME, TEST_FEATURE_ID, Binder.getCallingUid(), false, false); - - mLooper.startAutoDispatch(); - Bundle bundle = mWifiScanningServiceImpl.getAvailableChannels( - WifiScanner.WIFI_BAND_24_GHZ, TEST_PACKAGE_NAME, TEST_FEATURE_ID); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - List<Integer> actual = bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA); - - List<Integer> expected = Arrays.asList(2412, 2450); - assertEquals(expected, actual); - } - - /** - * Tests that {@link WifiScanningServiceImpl#getAvailableChannels(int, String)} returns - * an empty array when wifi is off. - */ - @Test - public void getAvailableChannels_DoesNotCrashWhenWifiDisabled() throws Exception { - // Don't enable wifi. - - // Client doesn't have NETWORK_STACK permission. - doThrow(new SecurityException()).when(mContext).enforcePermission( - eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); - - // has access scan results permission - doNothing().when(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( - TEST_PACKAGE_NAME, TEST_FEATURE_ID, Binder.getCallingUid(), false, false); - - mLooper.startAutoDispatch(); - Bundle bundle = mWifiScanningServiceImpl.getAvailableChannels( - WifiScanner.WIFI_BAND_24_GHZ, TEST_PACKAGE_NAME, TEST_FEATURE_ID); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - List<Integer> actual = bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA); - - assertTrue(actual.isEmpty()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WificondPnoScannerTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WificondPnoScannerTest.java deleted file mode 100644 index 152095c8d..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/WificondPnoScannerTest.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.scanner; - -import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder; -import static com.android.server.wifi.ScanTestUtil.setupMockChannels; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.test.TestAlarmManager; -import android.content.Context; -import android.net.wifi.WifiScanner; -import android.os.SystemClock; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.MockResources; -import com.android.server.wifi.MockWifiMonitor; -import com.android.server.wifi.ScanResults; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiMonitor; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.List; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.scanner.WificondScannerImpl.setPnoList}. - */ -@SmallTest -public class WificondPnoScannerTest extends WifiBaseTest { - private static final String IFACE_NAME = "a_test_interface_name"; - - @Mock Context mContext; - TestAlarmManager mAlarmManager; - MockWifiMonitor mWifiMonitor; - TestLooper mLooper; - @Mock WifiNative mWifiNative; - MockResources mResources; - @Mock Clock mClock; - WificondScannerImpl mScanner; - - @Before - public void setup() throws Exception { - MockitoAnnotations.initMocks(this); - - mLooper = new TestLooper(); - mAlarmManager = new TestAlarmManager(); - mWifiMonitor = new MockWifiMonitor(); - mResources = new MockResources(); - - setupMockChannels(mWifiNative, - new int[]{2400, 2450}, - new int[]{5150, 5175}, - new int[]{5600, 5650}, - new int[]{5945, 5985}); - - when(mWifiNative.getClientInterfaceName()).thenReturn(IFACE_NAME); - when(mContext.getSystemService(Context.ALARM_SERVICE)) - .thenReturn(mAlarmManager.getAlarmManager()); - when(mContext.getResources()).thenReturn(mResources); - when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); - } - - /** - * Verify that the HW disconnected PNO scan triggers a wificond PNO scan and invokes the - * OnPnoNetworkFound callback when the scan results are received. - */ - @Test - public void startHwDisconnectedPnoScan() { - createScannerWithHwPnoScanSupport(); - - WifiNative.PnoEventHandler pnoEventHandler = mock(WifiNative.PnoEventHandler.class); - WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false); - ScanResults scanResults = createDummyScanResults(); - - InOrder order = inOrder(pnoEventHandler, mWifiNative); - // Start PNO scan - startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler); - expectSuccessfulHwDisconnectedPnoScan(order, pnoSettings, pnoEventHandler, scanResults); - verifyNoMoreInteractions(pnoEventHandler); - } - - /** - * Verify that the HW disconnected PNO scan triggers a wificond PNO scan and invokes the - * OnPnoScanFailed callback when the scan fails. - */ - @Test - public void startHwDisconnectedPnoScanFailure() { - createScannerWithHwPnoScanSupport(); - - WifiNative.PnoEventHandler pnoEventHandler = mock(WifiNative.PnoEventHandler.class); - WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false); - - InOrder order = inOrder(pnoEventHandler, mWifiNative); - - // Fail PNO scan - when(mWifiNative.startPnoScan(eq(IFACE_NAME), any(WifiNative.PnoSettings.class))) - .thenReturn(false); - assertTrue(mScanner.setHwPnoList(pnoSettings, pnoEventHandler)); - order.verify(mWifiNative).startPnoScan(any(), any(WifiNative.PnoSettings.class)); - order.verify(pnoEventHandler).onPnoScanFailed(); - verifyNoMoreInteractions(pnoEventHandler); - } - - /** - * Verify that the HW PNO scan stop failure still resets the PNO scan state. - * 1. Start Hw PNO. - * 2. Stop Hw PNO scan which raises a stop command to WifiNative which is failed. - * 3. Now restart a new PNO scan to ensure that the failure was cleanly handled. - */ - @Test - public void ignoreHwDisconnectedPnoScanStopFailure() { - createScannerWithHwPnoScanSupport(); - - WifiNative.PnoEventHandler pnoEventHandler = mock(WifiNative.PnoEventHandler.class); - WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false); - - // Start PNO scan - startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler); - - // Fail the PNO stop. - when(mWifiNative.stopPnoScan(IFACE_NAME)).thenReturn(false); - assertTrue(mScanner.resetHwPnoList()); - mLooper.dispatchAll(); - verify(mWifiNative).stopPnoScan(IFACE_NAME); - - // Add a new PNO scan request and ensure it runs successfully. - startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler); - mLooper.dispatchAll(); - InOrder order = inOrder(pnoEventHandler, mWifiNative); - ScanResults scanResults = createDummyScanResults(); - expectSuccessfulHwDisconnectedPnoScan(order, pnoSettings, pnoEventHandler, scanResults); - verifyNoMoreInteractions(pnoEventHandler); - } - - private void createScannerWithHwPnoScanSupport() { - mResources.setBoolean(R.bool.config_wifi_background_scan_support, true); - mScanner = new WificondScannerImpl(mContext, IFACE_NAME, mWifiNative, mWifiMonitor, - new WificondChannelHelper(mWifiNative), mLooper.getLooper(), mClock); - } - - private WifiNative.PnoNetwork createDummyPnoNetwork(String ssid) { - WifiNative.PnoNetwork pnoNetwork = new WifiNative.PnoNetwork(); - pnoNetwork.ssid = ssid; - return pnoNetwork; - } - - private WifiNative.PnoSettings createDummyPnoSettings(boolean isConnected) { - WifiNative.PnoSettings pnoSettings = new WifiNative.PnoSettings(); - pnoSettings.isConnected = isConnected; - pnoSettings.networkList = new WifiNative.PnoNetwork[2]; - pnoSettings.networkList[0] = createDummyPnoNetwork("ssid_pno_1"); - pnoSettings.networkList[1] = createDummyPnoNetwork("ssid_pno_2"); - return pnoSettings; - } - - private WifiNative.ScanSettings createDummyScanSettings(boolean allChannelsScanned) { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(10) - .addBucketWithBand( - 10000, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - allChannelsScanned - ? WifiScanner.WIFI_BAND_BOTH_WITH_DFS : WifiScanner.WIFI_BAND_24_GHZ) - .build(); - return settings; - } - - private ScanResults createDummyScanResults() { - return ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2400, 2450, 2450, 2400, - 2450, 2450, 2400, 2450, 2450); - } - - private void startSuccessfulPnoScan(WifiNative.ScanSettings scanSettings, - WifiNative.PnoSettings pnoSettings, WifiNative.ScanEventHandler scanEventHandler, - WifiNative.PnoEventHandler pnoEventHandler) { - // Scans succeed - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - when(mWifiNative.startPnoScan(eq(IFACE_NAME), any(WifiNative.PnoSettings.class))) - .thenReturn(true); - when(mWifiNative.stopPnoScan(IFACE_NAME)).thenReturn(true); - - assertTrue(mScanner.setHwPnoList(pnoSettings, pnoEventHandler)); - } - - private Set<Integer> expectedBandScanFreqs(int band) { - ChannelCollection collection = mScanner.getChannelHelper().createChannelCollection(); - collection.addBand(band); - return collection.getScanFreqs(); - } - - /** - * Verify that the PNO scan was successfully started. - */ - private void expectHwDisconnectedPnoScanStart(InOrder order, - WifiNative.PnoSettings pnoSettings) { - // Verify HW PNO scan started - order.verify(mWifiNative).startPnoScan(any(), any(WifiNative.PnoSettings.class)); - } - - /** - * - * 1. Verify that the PNO scan was successfully started. - * 2. Send scan results and ensure that the |onPnoNetworkFound| callback was called. - */ - private void expectSuccessfulHwDisconnectedPnoScan(InOrder order, - WifiNative.PnoSettings pnoSettings, WifiNative.PnoEventHandler eventHandler, - ScanResults scanResults) { - expectHwDisconnectedPnoScanStart(order, pnoSettings); - - // Setup scan results - when(mWifiNative.getPnoScanResults(IFACE_NAME)) - .thenReturn(scanResults.getScanDetailArrayList()); - when(mWifiNative.getScanResults(IFACE_NAME)) - .thenReturn(scanResults.getScanDetailArrayList()); - - // Notify scan has finished - mWifiMonitor.sendMessage(IFACE_NAME, WifiMonitor.PNO_SCAN_RESULTS_EVENT); - assertEquals("dispatch message after results event", 1, mLooper.dispatchAll()); - - order.verify(eventHandler).onPnoNetworkFound(scanResults.getRawScanResults()); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java deleted file mode 100644 index e256e443f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2015 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.server.wifi.scanner; - -import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder; -import static com.android.server.wifi.ScanTestUtil.setupMockChannels; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.net.wifi.WifiScanner; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.ScanDetail; -import com.android.server.wifi.ScanResults; -import com.android.server.wifi.WifiMonitor; -import com.android.server.wifi.WifiNative; -import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; - - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.regex.Pattern; - -/** - * Unit tests for {@link com.android.server.wifi.scanner.WificondScannerImpl}. - */ -@SmallTest -public class WificondScannerTest extends BaseWifiScannerImplTest { - private static final String NATIVE_SCAN_TITLE = "Latest native scan results:"; - private static final String NATIVE_PNO_SCAN_TITLE = "Latest native pno scan results:"; - private static final String NATIVE_SCAN_IE_TITLE = "Latest native scan results IEs:"; - - WifiMonitor mWifiMonitorSpy; - @Before - public void setup() throws Exception { - setupMockChannels(mWifiNative, - new int[]{2400, 2450}, - new int[]{5150, 5175}, - new int[]{5600, 5650}, - new int[]{5945, 5985}); - mWifiMonitorSpy = spy(mWifiMonitor); - mScanner = new WificondScannerImpl(mContext, BaseWifiScannerImplTest.IFACE_NAME, - mWifiNative, mWifiMonitorSpy, new WificondChannelHelper(mWifiNative), - mLooper.getLooper(), mClock); - } - - /** - * Test that WificondScannerImpl will not issue a scan and report scan failure - * when there is no channel to scan for. - */ - @Test - public void singleScanNotIssuedIfNoAvailableChannels() { - // Use mocked ChannelHelper and ChannelCollection to simulate the scenario - // that no channel is available for this request. - ChannelHelper channelHelper = mock(ChannelHelper.class); - ChannelCollection channelCollection = mock(ChannelCollection.class); - when(channelHelper.createChannelCollection()).thenReturn(channelCollection); - when(channelCollection.isEmpty()).thenReturn(true); - - mScanner = new WificondScannerImpl(mContext, BaseWifiScannerImplTest.IFACE_NAME, - mWifiNative, mWifiMonitor, channelHelper, mLooper.getLooper(), mClock); - - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) // ms - .withMaxApPerScan(10) - .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_5_GHZ) - .build(); - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - mScanner.startSingleScan(settings, eventHandler); - - mLooper.dispatchAll(); - - // No scan is issued to WifiNative. - verify(mWifiNative, never()).scan(any(), anyInt(), any(), any(List.class)); - // A scan failed event must be reported. - verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); - } - - @Test - public void externalScanResultsDoNotCauseSpuriousTimerCancellationOrCrash() { - mWifiMonitor.sendMessage(IFACE_NAME, WifiMonitor.SCAN_RESULTS_EVENT); - mLooper.dispatchAll(); - verify(mAlarmManager.getAlarmManager(), never()).cancel(any(PendingIntent.class)); - verify(mAlarmManager.getAlarmManager(), never()) - .cancel(any(AlarmManager.OnAlarmListener.class)); - verify(mAlarmManager.getAlarmManager(), never()).cancel(isNull(PendingIntent.class)); - verify(mAlarmManager.getAlarmManager(), never()) - .cancel(isNull(AlarmManager.OnAlarmListener.class)); - } - - @Test - public void externalScanResultsAfterOurScanDoNotCauseSpuriousTimerCancellationOrCrash() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) // ms - .withMaxApPerScan(10) - .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - - doSuccessfulSingleScanTest(settings, - expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), - new ArrayList<String>(), - ScanResults.create(0, WifiScanner.WIFI_BAND_24_GHZ, - 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), false); - - mWifiMonitor.sendMessage(IFACE_NAME, WifiMonitor.SCAN_RESULTS_EVENT); - mLooper.dispatchAll(); - verify(mAlarmManager.getAlarmManager(), never()).cancel(any(PendingIntent.class)); - verify(mAlarmManager.getAlarmManager(), times(1)) - .cancel(any(AlarmManager.OnAlarmListener.class)); - verify(mAlarmManager.getAlarmManager(), never()).cancel(isNull(PendingIntent.class)); - verify(mAlarmManager.getAlarmManager(), never()) - .cancel(isNull(AlarmManager.OnAlarmListener.class)); - } - - @Test - public void lateScanResultsDoNotCauseSpuriousTimerCancellationOrCrash() { - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) // ms - .withMaxApPerScan(10) - .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - - // Kick off a scan - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - mLooper.dispatchAll(); - - // Report a timeout - mAlarmManager.dispatch(WificondScannerImpl.TIMEOUT_ALARM_TAG); - mLooper.dispatchAll(); - - // Now report scan results (results lost the race with timeout) - mWifiMonitor.sendMessage(IFACE_NAME, WifiMonitor.SCAN_RESULTS_EVENT); - mLooper.dispatchAll(); - - verify(mAlarmManager.getAlarmManager(), never()).cancel(any(PendingIntent.class)); - verify(mAlarmManager.getAlarmManager(), never()) - .cancel(any(AlarmManager.OnAlarmListener.class)); - verify(mAlarmManager.getAlarmManager(), never()).cancel(isNull(PendingIntent.class)); - verify(mAlarmManager.getAlarmManager(), never()) - .cancel(isNull(AlarmManager.OnAlarmListener.class)); - } - - /** - * Test that dump() of WificondScannerImpl dumps native scan results with correct format when - * scan result is empty. - */ - @Test - public void testDumpWithCorrectFormatWithEmptyScanResult() { - // The format of scan dump when zero Ap in scan result. - // --------------------------------------------- - // "Latest native scan results:\n" : Key word can't modify. - // "Latest native pno scan results:\n": Key word can't modify. - // " ... \n": Any String and any line. No limited. - // "Latest native scan results IEs:\n": Key word can't modify. - // "\n" : Should be stop with "\n" - //--------------------------------------------- - Pattern zeroScanResultRegex = Pattern.compile( - "" + NATIVE_SCAN_TITLE + "\n" - + "" + NATIVE_PNO_SCAN_TITLE + "\n" - + "(.*\n)*" - + "" + NATIVE_SCAN_IE_TITLE + "\n" - + "\n"); - - String dump = dumpObject(); - - assertLogContainsRequestPattern(zeroScanResultRegex, dump); - - } - - /** - * Test that dump() of WificondScannerImpl dumps native scan results with correct format when - * the number of AP in the scan result is not zero. - */ - @Test - public void testDumpWithCorrectFormatWithScanResult() { - // Prepare the setting to trigger a scan. - WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() - .withBasePeriod(10000) - .withMaxApPerScan(2) - .addBucketWithBand(10000, - WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN - | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, - WifiScanner.WIFI_BAND_24_GHZ) - .build(); - long approxScanStartUs = mClock.getElapsedSinceBootMillis() * 1000; - ArrayList<ScanDetail> rawScanResults = new ArrayList<>(Arrays.asList( - ScanResults.generateNativeResults(0, 5150, 5171))); - WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); - InOrder order = inOrder(eventHandler, mWifiNative); - // scan succeeds - when(mWifiNative.scan(eq(IFACE_NAME), anyInt(), any(), any(List.class))).thenReturn(true); - when(mWifiNative.getScanResults(eq(IFACE_NAME))).thenReturn(rawScanResults); - - int ap_count = rawScanResults.size(); - // The format of scan dump when the number of AP in the scan result is not zero. - // --------------------------------------------- - // "Latest native scan results:\n" : Key word can't modify. - // " BSSID ... \n" : Must start with 4 spaces but only show when - // the number of AP in the scan result is not zero. - // " The APs information \n" : Must start with 2 spaces and show bssid first. - // " ... \n" : Continues to print AP information and - // total AP information line should be - // same as the number of AP in the scan result. - // "Latest native pno scan results:\n": Key word can't modify. - // " ... \n": Any String and any line. No limited. - // "Latest native scan results IEs:\n": Key word can't modify. - // ie raw data : loop to start print ie raw data, finish with "\n" - // ... : Continues to print ie raw data and - // total ie raw data line should be same as - // the number of AP in the scan result. - // "\n" : Should be stop with "\n" - //--------------------------------------------- - Pattern scanResultRegex = Pattern.compile( - "" + NATIVE_SCAN_TITLE + "\n" - + " .*\n" - + "( .{2}:.{2}:.{2}:.{2}:.{2}:.{2}.*\n){" + ap_count + "}" - + "" + NATIVE_PNO_SCAN_TITLE + "\n" - + "(.*\n)*" - + "" + NATIVE_SCAN_IE_TITLE + "\n" - + "(.*\n){" + ap_count + "}" - + "\n"); - - // Trigger a scan to update mNativeScanResults in WificondScannerImpl. - assertTrue(mScanner.startSingleScan(settings, eventHandler)); - Set<Integer> expectedScan = expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ); - order.verify(mWifiNative).scan(eq(IFACE_NAME), anyInt(), eq(expectedScan), any(List.class)); - - // Notify scan has finished - mWifiMonitor.sendMessage(eq(IFACE_NAME), WifiMonitor.SCAN_RESULTS_EVENT); - mLooper.dispatchAll(); - // Get the dump string. - String dump = dumpObject(); - - assertLogContainsRequestPattern(scanResultRegex, dump); - } - - @Test - public void cleanupDeregistersHandlers() { - mScanner.cleanup(); - verify(mWifiMonitorSpy, times(1)).deregisterHandler(anyString(), - eq(WifiMonitor.SCAN_FAILED_EVENT), any()); - verify(mWifiMonitorSpy, times(1)).deregisterHandler(anyString(), - eq(WifiMonitor.PNO_SCAN_RESULTS_EVENT), any()); - verify(mWifiMonitorSpy, times(1)).deregisterHandler(anyString(), - eq(WifiMonitor.SCAN_RESULTS_EVENT), any()); - } - - private void assertLogContainsRequestPattern(Pattern logLineRegex, String log) { - assertTrue("dump did not contain log = " + logLineRegex.toString() + "\n" + log + "\n", - logLineRegex.matcher(log).find()); - } - - private String dumpObject() { - StringWriter stringWriter = new StringWriter(); - mScanner.dump(new FileDescriptor(), new PrintWriter(stringWriter), - new String[0]); - return stringWriter.toString(); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java deleted file mode 100644 index 16c915729..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -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.mockito.Mockito.when; - -import android.content.Context; -import android.content.res.Resources; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.SoftApCapability; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApConfiguration.Builder; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiScanner; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiNative; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Unit tests for {@link com.android.server.wifi.util.ApConfigUtil}. - */ -@SmallTest -public class ApConfigUtilTest extends WifiBaseTest { - - private static final String TEST_COUNTRY_CODE = "TestCountry"; - - /** - * Frequency to channel map. This include some frequencies used outside the US. - * Representing it using a vector (instead of map) for simplification. Values at - * even indices are frequencies and odd indices are channels. - */ - private static final int[] FREQUENCY_TO_CHANNEL_MAP = { - 2412, SoftApConfiguration.BAND_2GHZ, 1, - 2417, SoftApConfiguration.BAND_2GHZ, 2, - 2422, SoftApConfiguration.BAND_2GHZ, 3, - 2427, SoftApConfiguration.BAND_2GHZ, 4, - 2432, SoftApConfiguration.BAND_2GHZ, 5, - 2437, SoftApConfiguration.BAND_2GHZ, 6, - 2442, SoftApConfiguration.BAND_2GHZ, 7, - 2447, SoftApConfiguration.BAND_2GHZ, 8, - 2452, SoftApConfiguration.BAND_2GHZ, 9, - 2457, SoftApConfiguration.BAND_2GHZ, 10, - 2462, SoftApConfiguration.BAND_2GHZ, 11, - /* 12, 13 are only legitimate outside the US. */ - 2467, SoftApConfiguration.BAND_2GHZ, 12, - 2472, SoftApConfiguration.BAND_2GHZ, 13, - /* 14 is for Japan, DSSS and CCK only. */ - 2484, SoftApConfiguration.BAND_2GHZ, 14, - /* 34 valid in Japan. */ - 5170, SoftApConfiguration.BAND_5GHZ, 34, - 5180, SoftApConfiguration.BAND_5GHZ, 36, - 5190, SoftApConfiguration.BAND_5GHZ, 38, - 5200, SoftApConfiguration.BAND_5GHZ, 40, - 5210, SoftApConfiguration.BAND_5GHZ, 42, - 5220, SoftApConfiguration.BAND_5GHZ, 44, - 5230, SoftApConfiguration.BAND_5GHZ, 46, - 5240, SoftApConfiguration.BAND_5GHZ, 48, - 5260, SoftApConfiguration.BAND_5GHZ, 52, - 5280, SoftApConfiguration.BAND_5GHZ, 56, - 5300, SoftApConfiguration.BAND_5GHZ, 60, - 5320, SoftApConfiguration.BAND_5GHZ, 64, - 5500, SoftApConfiguration.BAND_5GHZ, 100, - 5520, SoftApConfiguration.BAND_5GHZ, 104, - 5540, SoftApConfiguration.BAND_5GHZ, 108, - 5560, SoftApConfiguration.BAND_5GHZ, 112, - 5580, SoftApConfiguration.BAND_5GHZ, 116, - /* 120, 124, 128 valid in Europe/Japan. */ - 5600, SoftApConfiguration.BAND_5GHZ, 120, - 5620, SoftApConfiguration.BAND_5GHZ, 124, - 5640, SoftApConfiguration.BAND_5GHZ, 128, - /* 132+ valid in US. */ - 5660, SoftApConfiguration.BAND_5GHZ, 132, - 5680, SoftApConfiguration.BAND_5GHZ, 136, - 5700, SoftApConfiguration.BAND_5GHZ, 140, - /* 144 is supported by a subset of WiFi chips. */ - 5720, SoftApConfiguration.BAND_5GHZ, 144, - 5745, SoftApConfiguration.BAND_5GHZ, 149, - 5765, SoftApConfiguration.BAND_5GHZ, 153, - 5785, SoftApConfiguration.BAND_5GHZ, 157, - 5805, SoftApConfiguration.BAND_5GHZ, 161, - 5825, SoftApConfiguration.BAND_5GHZ, 165, - 5845, SoftApConfiguration.BAND_5GHZ, 169, - 5865, SoftApConfiguration.BAND_5GHZ, 173, - /* Now some 6GHz channels */ - 5945, SoftApConfiguration.BAND_6GHZ, 1, - 5960, SoftApConfiguration.BAND_6GHZ, 4, - 6100, SoftApConfiguration.BAND_6GHZ, 32 - }; - - private static final int[] EMPTY_CHANNEL_LIST = {}; - private static final int[] ALLOWED_2G_FREQS = {2462}; //ch# 11 - private static final int[] ALLOWED_5G_FREQS = {5745, 5765}; //ch# 149, 153 - private static final int[] ALLOWED_6G_FREQS = {5945, 5965}; - - @Mock Context mContext; - @Mock Resources mResources; - @Mock WifiNative mWifiNative; - - /** - * Setup test. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - - /** - * verify convert WifiConfiguration Band to SoftApConfigurationBand. - */ - @Test - public void convertWifiConfigBandToSoftapConfigBandTest() throws Exception { - assertEquals(SoftApConfiguration.BAND_2GHZ, ApConfigUtil - .convertWifiConfigBandToSoftApConfigBand(WifiConfiguration.AP_BAND_2GHZ)); - assertEquals(SoftApConfiguration.BAND_5GHZ, ApConfigUtil - .convertWifiConfigBandToSoftApConfigBand(WifiConfiguration.AP_BAND_5GHZ)); - assertEquals(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ, ApConfigUtil - .convertWifiConfigBandToSoftApConfigBand(WifiConfiguration.AP_BAND_ANY)); - } - - - - /** - * Verify isMultiband success - */ - @Test - public void isMultibandSuccess() throws Exception { - assertTrue(ApConfigUtil.isMultiband(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_6GHZ)); - assertTrue(ApConfigUtil.isMultiband(SoftApConfiguration.BAND_5GHZ - | SoftApConfiguration.BAND_6GHZ)); - assertTrue(ApConfigUtil.isMultiband(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_6GHZ)); - assertTrue(ApConfigUtil.isMultiband(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_6GHZ)); - } - - /** - * Verify isMultiband failure - */ - @Test - public void isMultibandFailure() throws Exception { - assertFalse(ApConfigUtil.isMultiband(SoftApConfiguration.BAND_2GHZ)); - assertFalse(ApConfigUtil.isMultiband(SoftApConfiguration.BAND_5GHZ)); - assertFalse(ApConfigUtil.isMultiband(SoftApConfiguration.BAND_6GHZ)); - } - - /** - * Verify containsBand success - */ - @Test - public void containsBandSuccess() throws Exception { - assertTrue(ApConfigUtil.containsBand(SoftApConfiguration.BAND_2GHZ, - SoftApConfiguration.BAND_2GHZ)); - assertTrue(ApConfigUtil.containsBand(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_6GHZ, SoftApConfiguration.BAND_2GHZ)); - assertTrue(ApConfigUtil.containsBand(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_6GHZ, - SoftApConfiguration.BAND_6GHZ)); - } - - /** - * Verify containsBand failure - */ - @Test - public void containsBandFailure() throws Exception { - assertFalse(ApConfigUtil.containsBand(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_5GHZ, SoftApConfiguration.BAND_6GHZ)); - assertFalse(ApConfigUtil.containsBand(SoftApConfiguration.BAND_5GHZ, - SoftApConfiguration.BAND_6GHZ)); - } - - /** - * Verify isBandValidSuccess - */ - @Test - public void isBandValidSuccess() throws Exception { - assertTrue(ApConfigUtil.isBandValid(SoftApConfiguration.BAND_2GHZ)); - assertTrue(ApConfigUtil.isBandValid(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_6GHZ)); - assertTrue(ApConfigUtil.isBandValid(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_6GHZ)); - } - - /** - * Verify isBandValidFailure - */ - @Test - public void isBandValidFailure() throws Exception { - assertFalse(ApConfigUtil.isBandValid(0)); - assertFalse(ApConfigUtil.isBandValid(SoftApConfiguration.BAND_2GHZ - | SoftApConfiguration.BAND_6GHZ | 0x0F)); - } - - /** - * verify frequency to band conversion for all possible frequencies. - */ - @Test - public void convertFrequencytoBand() throws Exception { - for (int i = 0; i < FREQUENCY_TO_CHANNEL_MAP.length; i += 3) { - assertEquals(FREQUENCY_TO_CHANNEL_MAP[i + 1], - ApConfigUtil.convertFrequencyToBand( - FREQUENCY_TO_CHANNEL_MAP[i])); - } - } - - /** - * verify channel/band to frequency conversion for all possible channels. - */ - @Test - public void convertChannelToFrequency() throws Exception { - for (int i = 0; i < FREQUENCY_TO_CHANNEL_MAP.length; i += 3) { - assertEquals(FREQUENCY_TO_CHANNEL_MAP[i], - ApConfigUtil.convertChannelToFrequency( - FREQUENCY_TO_CHANNEL_MAP[i + 2], FREQUENCY_TO_CHANNEL_MAP[i + 1])); - } - } - - /** - * Test convert string to channel list - */ - @Test - public void testConvertStringToChannelList() throws Exception { - assertEquals(Arrays.asList(1, 6, 11), ApConfigUtil.convertStringToChannelList("1, 6, 11")); - assertEquals(Arrays.asList(1, 6, 11), ApConfigUtil.convertStringToChannelList("1,6,11")); - assertEquals(Arrays.asList(1, 9, 10, 11), - ApConfigUtil.convertStringToChannelList("1, 9-11")); - assertEquals(Arrays.asList(1, 6, 7, 10, 11), - ApConfigUtil.convertStringToChannelList("1,6-7, 10-11")); - assertEquals(Arrays.asList(1, 11), - ApConfigUtil.convertStringToChannelList("1,6a,11")); - assertEquals(Arrays.asList(1, 11), ApConfigUtil.convertStringToChannelList("1,6-3,11")); - assertEquals(Arrays.asList(1), - ApConfigUtil.convertStringToChannelList("1, abc , def - rsv")); - } - - /** - * Test get available channel freq for band - */ - /** - * Verify default channel is used when picking a 2G channel without - * any allowed 2G channels. - */ - @Test - public void chooseApChannel2GBandWithNoAllowedChannel() throws Exception { - int[] allowed2gChannels = {}; - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ)) - .thenReturn(allowed2gChannels); - int freq = ApConfigUtil.chooseApChannel(SoftApConfiguration.BAND_2GHZ, mWifiNative, - mResources); - assertEquals(ApConfigUtil.DEFAULT_AP_CHANNEL, - ScanResult.convertFrequencyMhzToChannel(freq)); - } - - /** - * Verify a 2G channel is selected from the list of allowed channels. - */ - @Test - public void chooseApChannel2GBandWithAllowedChannels() throws Exception { - when(mResources.getString(R.string.config_wifiSoftap2gChannelList)) - .thenReturn("1, 6, 11"); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ)) - .thenReturn(ALLOWED_2G_FREQS); // ch#11 - - int freq = ApConfigUtil.chooseApChannel(SoftApConfiguration.BAND_2GHZ, mWifiNative, - mResources); - assertEquals(2462, freq); - } - - /** - * Verify a 5G channel is selected from the list of allowed channels. - */ - @Test - public void chooseApChannel5GBandWithAllowedChannels() throws Exception { - when(mResources.getString(R.string.config_wifiSoftap5gChannelList)) - .thenReturn("149, 36-100"); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)) - .thenReturn(ALLOWED_5G_FREQS); //ch# 149, 153 - - int freq = ApConfigUtil.chooseApChannel( - SoftApConfiguration.BAND_5GHZ, mWifiNative, mResources); - assertTrue(ArrayUtils.contains(ALLOWED_5G_FREQS, freq)); - } - - /** - * Verify chooseApChannel failed when selecting a channel in 5GHz band - * with no channels allowed. - */ - @Test - public void chooseApChannel5GBandWithNoAllowedChannels() throws Exception { - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)) - .thenReturn(EMPTY_CHANNEL_LIST); - assertEquals(-1, ApConfigUtil.chooseApChannel(SoftApConfiguration.BAND_5GHZ, mWifiNative, - mResources)); - } - - /** - * Verify chooseApChannel will select high band channel. - */ - @Test - public void chooseApChannelWillHighBandPrefer() throws Exception { - when(mResources.getString(R.string.config_wifiSoftap2gChannelList)) - .thenReturn("1, 6, 11"); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ)) - .thenReturn(ALLOWED_2G_FREQS); // ch#11 - when(mResources.getString(R.string.config_wifiSoftap5gChannelList)) - .thenReturn("149, 153"); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)) - .thenReturn(ALLOWED_5G_FREQS); //ch# 149, 153 - - int freq = ApConfigUtil.chooseApChannel( - SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ, - mWifiNative, mResources); - assertTrue(ArrayUtils.contains(ALLOWED_5G_FREQS, freq)); - } - - - /** - * Verify default band and channel is used when HAL support is - * not available. - */ - @Test - public void updateApChannelConfigWithoutHal() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setChannel(36, SoftApConfiguration.BAND_5GHZ); - - when(mWifiNative.isHalStarted()).thenReturn(false); - assertEquals(ApConfigUtil.SUCCESS, - ApConfigUtil.updateApChannelConfig(mWifiNative, mResources, TEST_COUNTRY_CODE, - configBuilder, configBuilder.build(), false)); - /* Verify default band and channel is used. */ - assertEquals(ApConfigUtil.DEFAULT_AP_BAND, configBuilder.build().getBand()); - assertEquals(ApConfigUtil.DEFAULT_AP_CHANNEL, configBuilder.build().getChannel()); - } - - /** - * Verify updateApChannelConfig will return an error when selecting channel - * for 5GHz band without country code. - */ - @Test - public void updateApChannelConfig5GBandNoCountryCode() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - when(mWifiNative.isHalStarted()).thenReturn(true); - assertEquals(ApConfigUtil.ERROR_GENERIC, - ApConfigUtil.updateApChannelConfig(mWifiNative, mResources, null, - configBuilder, configBuilder.build(), false)); - } - - /** - * Verify the AP band and channel is not updated if specified. - */ - @Test - public void updateApChannelConfigWithChannelSpecified() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setChannel(36, SoftApConfiguration.BAND_5GHZ); - when(mWifiNative.isHalStarted()).thenReturn(true); - assertEquals(ApConfigUtil.SUCCESS, - ApConfigUtil.updateApChannelConfig(mWifiNative, mResources, TEST_COUNTRY_CODE, - configBuilder, configBuilder.build(), false)); - assertEquals(SoftApConfiguration.BAND_5GHZ, configBuilder.build().getBand()); - assertEquals(36, configBuilder.build().getChannel()); - } - - /** - * Verify updateApChannelConfig will return an error when selecting 5GHz channel - * without any allowed channels. - */ - @Test - public void updateApChannelConfigWith5GBandNoChannelAllowed() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); - when(mWifiNative.isHalStarted()).thenReturn(true); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)) - .thenReturn(EMPTY_CHANNEL_LIST); - assertEquals(ApConfigUtil.ERROR_NO_CHANNEL, - ApConfigUtil.updateApChannelConfig(mWifiNative, mResources, TEST_COUNTRY_CODE, - configBuilder, configBuilder.build(), false)); - } - - /** - * Verify updateApChannelConfig will select a channel number that meets OEM restriction - * when acs is disabled. - */ - @Test - public void updateApChannelConfigWithAcsDisabledOemConfigured() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_2GHZ); - when(mResources.getString(R.string.config_wifiSoftap2gChannelList)) - .thenReturn("6"); - when(mResources.getString(R.string.config_wifiSoftap5gChannelList)) - .thenReturn("149, 36-100"); - when(mWifiNative.isHalStarted()).thenReturn(true); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ)) - .thenReturn(ALLOWED_2G_FREQS); // ch# 11 - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)) - .thenReturn(ALLOWED_5G_FREQS); // ch# 149, 153 - when(mWifiNative.isHalStarted()).thenReturn(true); - assertEquals(ApConfigUtil.SUCCESS, - ApConfigUtil.updateApChannelConfig(mWifiNative, mResources, TEST_COUNTRY_CODE, - configBuilder, configBuilder.build(), false)); - assertEquals(SoftApConfiguration.BAND_5GHZ, configBuilder.build().getBand()); - assertEquals(149, configBuilder.build().getChannel()); - } - - /** - * Verify updateApChannelConfig will not select a channel number and band when acs is - * enabled. - */ - @Test - public void updateApChannelConfigWithAcsEnabled() throws Exception { - Builder configBuilder = new SoftApConfiguration.Builder(); - configBuilder.setBand(SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_2GHZ); - when(mWifiNative.isHalStarted()).thenReturn(true); - assertEquals(ApConfigUtil.SUCCESS, - ApConfigUtil.updateApChannelConfig(mWifiNative, mResources, TEST_COUNTRY_CODE, - configBuilder, configBuilder.build(), true)); - assertEquals(SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_2GHZ, - configBuilder.build().getBand()); - assertEquals(0, configBuilder.build().getChannel()); - } - - @Test - public void testSoftApCapabilityInitWithResourceValue() throws Exception { - long testFeatures = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT; - SoftApCapability capability = new SoftApCapability(testFeatures); - int test_max_client = 10; - capability.setMaxSupportedClients(test_max_client); - - when(mContext.getResources()).thenReturn(mResources); - when(mResources.getInteger(R.integer.config_wifiHardwareSoftapMaxClientCount)) - .thenReturn(test_max_client); - when(mResources.getBoolean(R.bool.config_wifi_softap_acs_supported)) - .thenReturn(false); - when(mResources.getBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported)) - .thenReturn(true); - assertEquals(ApConfigUtil.updateCapabilityFromResource(mContext), - capability); - } - - @Test - public void testConvertInvalidWifiConfigurationToSoftApConfiguration() throws Exception { - WifiConfiguration wifiConfig = new WifiConfiguration(); - wifiConfig.SSID = "AndroidAP"; - wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK); - wifiConfig.preSharedKey = "1233443"; - assertNull(ApConfigUtil.fromWifiConfiguration(wifiConfig)); - } - - - @Test - public void testCheckConfigurationChangeNeedToRestart() throws Exception { - SoftApConfiguration currentConfig = new SoftApConfiguration.Builder() - .setSsid("TestSSid") - .setBssid(MacAddress.fromString("11:22:33:44:55:66")) - .setPassphrase("testpassphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .setBand(SoftApConfiguration.BAND_2GHZ) - .setChannel(11, SoftApConfiguration.BAND_2GHZ) - .setHiddenSsid(true) - .build(); - - // Test no changed - // DO NOT use copy constructor to copy to test since it's instance is the same. - SoftApConfiguration newConfig_noChange = new SoftApConfiguration.Builder() - .setSsid("TestSSid") - .setBssid(MacAddress.fromString("11:22:33:44:55:66")) - .setPassphrase("testpassphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) - .setBand(SoftApConfiguration.BAND_2GHZ) - .setChannel(11, SoftApConfiguration.BAND_2GHZ) - .setHiddenSsid(true) - .build(); - assertFalse(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_noChange)); - - // Test SSID changed - SoftApConfiguration newConfig_ssidChanged = new SoftApConfiguration - .Builder(newConfig_noChange) - .setSsid("NewTestSSid").build(); - assertTrue(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_ssidChanged)); - // Test BSSID changed - SoftApConfiguration newConfig_bssidChanged = new SoftApConfiguration - .Builder(newConfig_noChange) - .setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")).build(); - assertTrue(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_bssidChanged)); - // Test Passphrase Changed - SoftApConfiguration newConfig_passphraseChanged = new SoftApConfiguration - .Builder(newConfig_noChange) - .setPassphrase("newtestpassphrase", - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK).build(); - assertTrue(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_passphraseChanged)); - // Test Security Type Changed - SoftApConfiguration newConfig_securityeChanged = new SoftApConfiguration - .Builder(newConfig_noChange) - .setPassphrase("newtestpassphrase", - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE).build(); - assertTrue(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_securityeChanged)); - // Test Channel Changed - SoftApConfiguration newConfig_channelChanged = new SoftApConfiguration - .Builder(newConfig_noChange) - .setChannel(6, SoftApConfiguration.BAND_2GHZ).build(); - assertTrue(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_channelChanged)); - // Test Band Changed - SoftApConfiguration newConfig_bandChanged = new SoftApConfiguration - .Builder(newConfig_noChange) - .setBand(SoftApConfiguration.BAND_5GHZ).build(); - assertTrue(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_bandChanged)); - // Test isHidden Changed - SoftApConfiguration newConfig_hiddenChanged = new SoftApConfiguration - .Builder(newConfig_noChange) - .setHiddenSsid(false).build(); - assertTrue(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_hiddenChanged)); - // Test Others Changed - SoftApConfiguration newConfig_nonRevalentChanged = new SoftApConfiguration - .Builder(newConfig_noChange) - .setMaxNumberOfClients(10) - .setAutoShutdownEnabled(false) - .setShutdownTimeoutMillis(500000) - .setClientControlByUserEnabled(true) - .setBlockedClientList(new ArrayList<>()) - .setAllowedClientList(new ArrayList<>()) - .build(); - assertFalse(ApConfigUtil.checkConfigurationChangeNeedToRestart(currentConfig, - newConfig_nonRevalentChanged)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/BitMaskTest.java b/tests/wifitests/src/com/android/server/wifi/util/BitMaskTest.java deleted file mode 100644 index 83144de95..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/BitMaskTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.util; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Unit tests for {@link com.android.server.wifi.util.BitMask}. - */ -@SmallTest -public class BitMaskTest extends WifiBaseTest { - /** - * Test that checkoff.testAndClear works as advertised - */ - @Test - public void testBitMask() throws Exception { - - BitMask checkoff = new BitMask(0x53); - - Assert.assertTrue(checkoff.testAndClear(0x10)); // First time, bit should be there - Assert.assertFalse(checkoff.testAndClear(0x10)); // Second time, should be gone - Assert.assertFalse(checkoff.testAndClear(0x100)); // This bit was not set - Assert.assertEquals(0x43, checkoff.value); // These should be left - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/ByteArrayRingBufferTest.java b/tests/wifitests/src/com/android/server/wifi/util/ByteArrayRingBufferTest.java deleted file mode 100644 index d40321377..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/ByteArrayRingBufferTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -/** - * Unit tests for {@link com.android.server.wifi.util.ByteArrayRingBuffer}. - */ -@SmallTest -public class ByteArrayRingBufferTest extends WifiBaseTest { - private static final int MAX_BYTES = 10; - - @Test - public void ctorCreatesEmptyRingBuffer() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - assertEquals(0, rb.getNumBuffers()); - } - - @Test - public void canAddAndRetrieveSingleElement() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data = {0}; - assertTrue(rb.appendBuffer(data)); - assertEquals(1, rb.getNumBuffers()); - assertSame(data, rb.getBuffer(0)); - } - - @Test - public void canAddAndRetrieveMultipleElements() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data1 = {0}; - final byte[] data2 = {1}; - assertTrue(rb.appendBuffer(data1)); - assertTrue(rb.appendBuffer(data2)); - assertEquals(2, rb.getNumBuffers()); - assertSame(data1, rb.getBuffer(0)); - assertSame(data2, rb.getBuffer(1)); - } - - @Test - public void canFillToCapacityWithMultipleElements() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data1 = {1, 2, 3, 4, 5}; - final byte[] data2 = {6, 7, 8, 9, 10}; - assertEquals(MAX_BYTES, data1.length + data2.length); - assertTrue(rb.appendBuffer(data1)); - assertTrue(rb.appendBuffer(data2)); - assertEquals(2, rb.getNumBuffers()); - } - - @Test - public void canFillToCapacityWithSingleElement() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - assertEquals(MAX_BYTES, data.length); - assertTrue(rb.appendBuffer(data)); - } - - @Test - public void canNotOverfillWithSingleElement() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; - assertTrue(data.length > MAX_BYTES); - assertFalse(rb.appendBuffer(data)); - assertEquals(0, rb.getNumBuffers()); - } - - @Test - public void appendPrunesBufferIfNecessary() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - assertTrue(rb.appendBuffer(data1)); - - final byte[] data2 = {11}; - assertTrue(rb.appendBuffer(data2)); - assertEquals(1, rb.getNumBuffers()); - assertSame(data2, rb.getBuffer(0)); - } - - @Test - public void appendPrunesMultipleBuffersIfNecessary() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data1 = {1, 2, 3, 4, 5}; - final byte[] data2 = {6, 7, 8, 9, 10}; - assertTrue(rb.appendBuffer(data1)); - assertTrue(rb.appendBuffer(data2)); - - final byte[] data3 = {11, 12, 13, 14, 15, 16}; - assertTrue(rb.appendBuffer(data3)); - assertEquals(1, rb.getNumBuffers()); - assertSame(data3, rb.getBuffer(0)); - } - - @Test - public void appendPrunesOnlyWhenNecessary() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data1 = {1, 2, 3, 4, 5}; - assertTrue(rb.appendBuffer(data1)); - - final byte[] data2 = {6}; - assertTrue(rb.appendBuffer(data2)); - assertEquals(2, rb.getNumBuffers()); - } - - @Test - public void appendPrunesInFifoOrder() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data1 = {1, 2, 3, 4, 5}; - final byte[] data2 = {6, 7, 8, 9, 10}; - assertTrue(rb.appendBuffer(data1)); - assertTrue(rb.appendBuffer(data2)); - - final byte[] data3 = {11}; - assertTrue(rb.appendBuffer(data3)); - assertEquals(2, rb.getNumBuffers()); - assertSame(data2, rb.getBuffer(0)); - assertSame(data3, rb.getBuffer(1)); - } - - @Test - public void appendPrunesEvenWhenNewDataCanNotFit() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - final byte[] data1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - assertTrue(rb.appendBuffer(data1)); - - final byte[] data2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; - assertFalse(rb.appendBuffer(data2)); - assertEquals(0, rb.getNumBuffers()); - } - - /** Verifies resizes()'s behavior when shrinking the buffer: - * 1) Existing data is pruned. - * 2) We really do decrease the size limit. - */ - @Test - public void resizePrunesDataAndUpdatesSizeLimitOnShrink() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - assertTrue(rb.appendBuffer(new byte[MAX_BYTES])); - - final byte newSize = 1; - rb.resize(newSize); - assertEquals(0, rb.getNumBuffers()); - assertFalse(rb.appendBuffer(new byte[newSize + 1])); - } - - /** Verifies resize()'s behavior when growing the buffer: - * 1) Existing data is retained. - * 2) We really do increase the size limit. - */ - @Test - public void resizeRetainsExistingDataAndUpdatesSizeLimitOnGrow() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - assertTrue(rb.appendBuffer(new byte[MAX_BYTES])); - rb.resize(MAX_BYTES * 2); - assertTrue(rb.appendBuffer(new byte[MAX_BYTES])); - assertEquals(2, rb.getNumBuffers()); - } - - /** Verifies that we don't crash when shrinking an empty buffer. */ - @Test - public void shrinkingEmptyBufferSucceeds() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES * 2); - rb.resize(MAX_BYTES); - } - - /** Verifies that we don't crash when growing an empty buffer. */ - @Test - public void growingEmptyBufferSucceeds() { - final ByteArrayRingBuffer rb = new ByteArrayRingBuffer(MAX_BYTES); - rb.resize(MAX_BYTES * 2); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/ExternalCallbackTrackerTest.java b/tests/wifitests/src/com/android/server/wifi/util/ExternalCallbackTrackerTest.java deleted file mode 100644 index 4eee45233..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/ExternalCallbackTrackerTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.util; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; - -import android.net.wifi.ISoftApCallback; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.test.TestLooper; -import android.test.suitebuilder.annotation.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Unit tests for {@link com.android.server.wifi.util.ExternalCallbackTracker}. - */ -@SmallTest -public class ExternalCallbackTrackerTest extends WifiBaseTest { - private static final int TEST_CALLBACK_IDENTIFIER = 56; - @Mock Handler mHandler; - @Mock ISoftApCallback mCallback; - @Mock IBinder mBinder; - private TestLooper mTestLooper; - - private ExternalCallbackTracker<ISoftApCallback> mExternalCallbackTracker; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mTestLooper = new TestLooper(); - mHandler = new Handler(mTestLooper.getLooper()); - mExternalCallbackTracker = new ExternalCallbackTracker<ISoftApCallback>(mHandler); - } - - /** - * Test adding a callback. - */ - @Test - public void testAddCallback() throws Exception { - assertTrue(mExternalCallbackTracker.add(mBinder, mCallback, TEST_CALLBACK_IDENTIFIER)); - assertEquals(1, mExternalCallbackTracker.getNumCallbacks()); - assertEquals(mCallback, mExternalCallbackTracker.getCallbacks().get(0)); - verify(mBinder).linkToDeath(any(), anyInt()); - } - - /** - * Test that adding a callback returns failure when binder death linking fails. - */ - @Test - public void testAddCallbackFailureOnLinkToDeath() throws Exception { - doThrow(new RemoteException()).when(mBinder).linkToDeath(any(), anyInt()); - assertFalse(mExternalCallbackTracker.add(mBinder, mCallback, TEST_CALLBACK_IDENTIFIER)); - assertEquals(0, mExternalCallbackTracker.getNumCallbacks()); - assertTrue(mExternalCallbackTracker.getCallbacks().isEmpty()); - } - - /** - * Test removing a callback. - */ - @Test - public void testRemoveCallback() throws Exception { - testAddCallback(); - - assertNotNull(mExternalCallbackTracker.remove(TEST_CALLBACK_IDENTIFIER)); - assertEquals(0, mExternalCallbackTracker.getNumCallbacks()); - assertTrue(mExternalCallbackTracker.getCallbacks().isEmpty()); - verify(mBinder).unlinkToDeath(any(), anyInt()); - } - - /** - * Test removing a callback returns failure when the identifier provided doesn't match the one - * used to add the callback. - */ - @Test - public void testRemoveCallbackFailureOnWrongIdentifier() throws Exception { - testAddCallback(); - - assertNull(mExternalCallbackTracker.remove(TEST_CALLBACK_IDENTIFIER + 5)); - assertEquals(1, mExternalCallbackTracker.getNumCallbacks()); - assertEquals(mCallback, mExternalCallbackTracker.getCallbacks().get(0)); - } - - /** - * Test that the callback is automatically removed when the associated binder object is dead. - */ - @Test - public void testCallbackRemovalOnDeath() throws Exception { - assertTrue(mExternalCallbackTracker.add(mBinder, mCallback, TEST_CALLBACK_IDENTIFIER)); - - // Trigger the death. - ArgumentCaptor<IBinder.DeathRecipient> deathCaptor = - ArgumentCaptor.forClass(IBinder.DeathRecipient.class); - verify(mBinder).linkToDeath(deathCaptor.capture(), anyInt()); - deathCaptor.getValue().binderDied(); - mTestLooper.dispatchAll(); - - assertEquals(0, mExternalCallbackTracker.getNumCallbacks()); - assertTrue(mExternalCallbackTracker.getCallbacks().isEmpty()); - verify(mBinder).unlinkToDeath(any(), anyInt()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java b/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java deleted file mode 100644 index 42d44c1a2..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiLoggerHal; - -import org.junit.Test; - -/** - * Unit tests for {@link com.android.server.wifi.util.FrameParser}. - */ -@SmallTest -public class FrameParserTest extends WifiBaseTest { - - private static final byte[] TEST_EAPOL_1_OF_4_FRAME_BYTES = new byte[] { - (byte) 0x7C, (byte) 0x7D, (byte) 0x3D, (byte) 0x51, (byte) 0x10, (byte) 0xDC, - (byte) 0x08, (byte) 0x96, (byte) 0xD7, (byte) 0x8B, (byte) 0xE3, (byte) 0xFB, - (byte) 0x88, (byte) 0x8E, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x5F, - (byte) 0x02, (byte) 0x00, (byte) 0x8A, (byte) 0x00, (byte) 0x10, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x01, (byte) 0xF2, (byte) 0x0D, (byte) 0xFA, (byte) 0x35, (byte) 0x89, - (byte) 0x9C, (byte) 0xA8, (byte) 0x8C, (byte) 0x14, (byte) 0xD9, (byte) 0x3F, - (byte) 0xC9, (byte) 0x62, (byte) 0x11, (byte) 0x39, (byte) 0xC3, (byte) 0x34, - (byte) 0xE1, (byte) 0x00, (byte) 0x09, (byte) 0xE3, (byte) 0x9C, (byte) 0x0C, - (byte) 0x32, (byte) 0xFE, (byte) 0x7F, (byte) 0x79, (byte) 0x29, (byte) 0x3E, - (byte) 0x6C, (byte) 0xF2, (byte) 0x57, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}; - private static final byte TEST_EAPOL_1_OF_4_FRAME_TYPE = - WifiLoggerHal.FRAME_TYPE_ETHERNET_II; - private static final String TEST_EAPOL_1_OF_4_FRAME_PROTOCOL_STRING = "EAPOL"; - private static final String TEST_EAPOL_1_OF_4_FRAME_TYPE_STRING = "Pairwise Key message 1/4"; - - private static final byte[] TEST_EAPOL_2_OF_4_FRAME_BYTES = new byte[] { - (byte) 0x08, (byte) 0x96, (byte) 0xD7, (byte) 0x8B, (byte) 0xE3, (byte) 0xFB, - (byte) 0x7C, (byte) 0x7D, (byte) 0x3D, (byte) 0x51, (byte) 0x10, (byte) 0xDC, - (byte) 0x88, (byte) 0x8E, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x75, - (byte) 0x02, (byte) 0x01, (byte) 0x0A, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x01, (byte) 0x42, (byte) 0xAE, (byte) 0x33, (byte) 0x61, (byte) 0xF8, - (byte) 0x38, (byte) 0x28, (byte) 0x81, (byte) 0x70, (byte) 0xD8, (byte) 0xA5, - (byte) 0xDD, (byte) 0x90, (byte) 0xB1, (byte) 0x8E, (byte) 0xEB, (byte) 0x58, - (byte) 0xF1, (byte) 0x0A, (byte) 0xE4, (byte) 0xA1, (byte) 0x93, (byte) 0x34, - (byte) 0xE1, (byte) 0x4F, (byte) 0x90, (byte) 0x85, (byte) 0xA0, (byte) 0x21, - (byte) 0x95, (byte) 0xC8, (byte) 0xD8, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x53, - (byte) 0x12, (byte) 0xE4, (byte) 0x97, (byte) 0xBC, (byte) 0xFF, (byte) 0x15, - (byte) 0x45, (byte) 0xCF, (byte) 0x4C, (byte) 0xC0, (byte) 0xB8, (byte) 0xBA, - (byte) 0x30, (byte) 0x5F, (byte) 0x6C, (byte) 0x00, (byte) 0x16, (byte) 0x30, - (byte) 0x14, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, - (byte) 0x04, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, - (byte) 0x04, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, - (byte) 0x02, (byte) 0x80, (byte) 0x00}; - private static final byte TEST_EAPOL_2_OF_4_FRAME_TYPE = - WifiLoggerHal.FRAME_TYPE_ETHERNET_II; - private static final String TEST_EAPOL_2_OF_4_FRAME_PROTOCOL_STRING = "EAPOL"; - private static final String TEST_EAPOL_2_OF_4_FRAME_TYPE_STRING = "Pairwise Key message 2/4"; - - private static final byte[] TEST_PROBE_RESPONSE_FRAME_BYTES = new byte[] { - (byte) 0x50, (byte) 0x08, (byte) 0x3a, (byte) 0x01, (byte) 0x54, (byte) 0x27, - (byte) 0x1e, (byte) 0xf2, (byte) 0xcd, (byte) 0x0f, (byte) 0x10, (byte) 0x6f, - (byte) 0x3f, (byte) 0xf6, (byte) 0x89, (byte) 0x0e, (byte) 0x10, (byte) 0x6f, - (byte) 0x3f, (byte) 0xf6, (byte) 0x89, (byte) 0x0e, (byte) 0x60, (byte) 0xc4, - (byte) 0x4a, (byte) 0xaa, (byte) 0x2a, (byte) 0x0d, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x11, (byte) 0x04, - (byte) 0x00, (byte) 0x16, (byte) 0x77, (byte) 0x7a, (byte) 0x72, (byte) 0x5f, - (byte) 0x68, (byte) 0x70, (byte) 0x5f, (byte) 0x67, (byte) 0x34, (byte) 0x35, - (byte) 0x30, (byte) 0x68, (byte) 0x5f, (byte) 0x67, (byte) 0x5f, (byte) 0x63, - (byte) 0x68, (byte) 0x35, (byte) 0x5f, (byte) 0x77, (byte) 0x70, (byte) 0x61, - (byte) 0x01, (byte) 0x08, (byte) 0x82, (byte) 0x84, (byte) 0x8b, (byte) 0x96, - (byte) 0x0c, (byte) 0x12, (byte) 0x18, (byte) 0x24, (byte) 0x03, (byte) 0x01, - (byte) 0x05, (byte) 0x2a, (byte) 0x01, (byte) 0x04, (byte) 0x32, (byte) 0x04, - (byte) 0x30, (byte) 0x48, (byte) 0x60, (byte) 0x6c, (byte) 0x30, (byte) 0x18, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02, - (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x04, - (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02, (byte) 0x01, (byte) 0x00, - (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02, (byte) 0x0c, (byte) 0x00, - (byte) 0xdd, (byte) 0x18, (byte) 0x00, (byte) 0x50, (byte) 0xf2, (byte) 0x02, - (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0xa4, - (byte) 0x00, (byte) 0x00, (byte) 0x27, (byte) 0xa4, (byte) 0x00, (byte) 0x00, - (byte) 0x42, (byte) 0x43, (byte) 0x5e, (byte) 0x00, (byte) 0x62, (byte) 0x32, - (byte) 0x2f, (byte) 0x00, (byte) 0xdd, (byte) 0x70, (byte) 0x00, (byte) 0x50, - (byte) 0xf2, (byte) 0x04, (byte) 0x10, (byte) 0x4a, (byte) 0x00, (byte) 0x01, - (byte) 0x10, (byte) 0x10, (byte) 0x44, (byte) 0x00, (byte) 0x01, (byte) 0x02, - (byte) 0x10, (byte) 0x3b, (byte) 0x00, (byte) 0x01, (byte) 0x03, (byte) 0x10, - (byte) 0x47, (byte) 0x00, (byte) 0x10, (byte) 0xf3, (byte) 0x1b, (byte) 0x31, - (byte) 0x7f, (byte) 0x8c, (byte) 0x25, (byte) 0x56, (byte) 0x46, (byte) 0xb5, - (byte) 0xc9, (byte) 0x5f, (byte) 0x2f, (byte) 0x0b, (byte) 0xcf, (byte) 0x6a, - (byte) 0x14, (byte) 0x10, (byte) 0x21, (byte) 0x00, (byte) 0x06, (byte) 0x44, - (byte) 0x44, (byte) 0x2d, (byte) 0x57, (byte) 0x52, (byte) 0x54, (byte) 0x10, - (byte) 0x23, (byte) 0x00, (byte) 0x0c, (byte) 0x57, (byte) 0x5a, (byte) 0x52, - (byte) 0x2d, (byte) 0x48, (byte) 0x50, (byte) 0x2d, (byte) 0x47, (byte) 0x34, - (byte) 0x35, (byte) 0x30, (byte) 0x48, (byte) 0x10, (byte) 0x24, (byte) 0x00, - (byte) 0x01, (byte) 0x30, (byte) 0x10, (byte) 0x42, (byte) 0x00, (byte) 0x05, - (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35, (byte) 0x10, - (byte) 0x54, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x06, (byte) 0x00, - (byte) 0x50, (byte) 0xf2, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x10, - (byte) 0x11, (byte) 0x00, (byte) 0x06, (byte) 0x44, (byte) 0x44, (byte) 0x2d, - (byte) 0x57, (byte) 0x52, (byte) 0x54, (byte) 0x10, (byte) 0x08, (byte) 0x00, - (byte) 0x02, (byte) 0x01, (byte) 0x04, (byte) 0x10, (byte) 0x3c, (byte) 0x00, - (byte) 0x01, (byte) 0x01, (byte) 0x8a, (byte) 0x0e, (byte) 0x06, (byte) 0xcf}; - private static final byte TEST_PROBE_RESPONSE_FRAME_TYPE = WifiLoggerHal.FRAME_TYPE_80211_MGMT; - private static final String TEST_PROBE_RESPONSE_FRAME_PROTOCOL_STRING = "802.11 Mgmt"; - private static final String TEST_PROBE_RESPONSE_FRAME_TYPE_STRING = "Probe Response"; - - /** - * Test that a probe response frame is parsed correctly. - */ - @Test - public void parseProbeResponseFrame() { - FrameParser parser = new FrameParser( - TEST_PROBE_RESPONSE_FRAME_TYPE, TEST_PROBE_RESPONSE_FRAME_BYTES); - assertEquals(TEST_PROBE_RESPONSE_FRAME_PROTOCOL_STRING, parser.mMostSpecificProtocolString); - assertEquals(TEST_PROBE_RESPONSE_FRAME_TYPE_STRING, parser.mTypeString); - } - - /** - * Test that pairwise EAPOL 1/4 and 2/4 frames are parsed correctly. - */ - @Test - public void parseEapolFrames() { - FrameParser parser1 = new FrameParser( - TEST_EAPOL_1_OF_4_FRAME_TYPE, TEST_EAPOL_1_OF_4_FRAME_BYTES); - assertEquals(TEST_EAPOL_1_OF_4_FRAME_PROTOCOL_STRING, parser1.mMostSpecificProtocolString); - assertEquals(TEST_EAPOL_1_OF_4_FRAME_TYPE_STRING, parser1.mTypeString); - - FrameParser parser2 = new FrameParser( - TEST_EAPOL_2_OF_4_FRAME_TYPE, TEST_EAPOL_2_OF_4_FRAME_BYTES); - assertEquals(TEST_EAPOL_2_OF_4_FRAME_PROTOCOL_STRING, parser2.mMostSpecificProtocolString); - assertEquals(TEST_EAPOL_2_OF_4_FRAME_TYPE_STRING, parser2.mTypeString); - } - - /** Test that we parse the status code out of a non-HT authentication reply. */ - @Test - public void canParseStatusCodeOutOfNonHtOpenAuthenticationReply() { - FrameParser parser = new FrameParser( - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - new byte[] { - (byte) 0xb0, // type + subtype - 0x00, // flags - 0x3c, 0x00, // duration - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // addr1 -- RA - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // addr2 -- TA - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // addr3 -- BSSID - (byte) 0xa0, 0x3b, // sequence + control - 0x00, 0x00, // auth algorithm - 0x02, 0x00, // auth sequence num - 0x11, 0x00 // status code - }); - assertEquals("802.11 Mgmt", parser.mMostSpecificProtocolString); - assertEquals("Authentication", parser.mTypeString); - assertEquals("17: Association denied; too many STAs", parser.mResultString); - } - - /** Test that we parse the status code out of a non-HT association response. */ - @Test - public void canParseStatusCodeOutOfNonHtAssociationResponse() { - FrameParser parser = new FrameParser( - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - new byte[] { - 0x10, // type + subtype - 0x00, // flags - 0x3c, 0x00, // duration - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // addr1 (RA) - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // addr2 (TA) - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // addr3 (BSSID) - (byte) 0xb0, (byte) 0xbc, // sequence + control - 0x01, 0x01, // capabilities - 0x00, 0x00, // status code - 0x01, (byte) 0xc0, 0x01, 0x08, (byte) 0x8c, 0x12, (byte) 0x98, 0x24, - (byte) 0xb0, 0x48, 0x60, 0x6c, 0x2d, 0x1a, 0x6e, 0x00, 0x1b, (byte) 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x16, - 0x24, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xbf, - 0x0c, 0x00, 0x00, 0x00, 0x00, (byte) 0xfe, (byte) 0xff, 0x00, 0x00, - (byte) 0xfe, (byte) 0xff, 0x00, 0x00, (byte) 0xc0, 0x05, 0x00, 0x00, 0x00, - (byte) 0xfc, (byte) 0xff, 0x7f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, (byte) 0xdd, 0x18, 0x00, 0x50, (byte) 0xf2, 0x02, 0x01, 0x01, - 0x00, 0x00, 0x03, (byte) 0xa4, 0x00, 0x00, 0x27, (byte) 0xa4, 0x00, 0x00, - 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00 - }); - assertEquals("802.11 Mgmt", parser.mMostSpecificProtocolString); - assertEquals("Association Response", parser.mTypeString); - assertEquals("0: Success", parser.mResultString); - } - - /** Test that we do not parse the status code out of a non-HT authentication request. */ - @Test - public void doesNotParseStatusCodeOutOfNonHtOpenAuthenticationRequest() { - FrameParser parser = new FrameParser( - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - new byte[] { - (byte) 0xb0, // type + subtype - 0x00, // flags - 0x00, 0x00, // duration (from host; probably to be filled by firmware) - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // addr1 (RA) - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // addr2 (TA) - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // addr3 (BSSID) - 0x10, (byte) 0x80, // sequence + control - 0x00, 0x00, // auth algorithm - 0x01, 0x00, // auth sequence num - 0x00, 0x00, // status code; present but meaningless for first auth frame - - }); - assertEquals("802.11 Mgmt", parser.mMostSpecificProtocolString); - assertEquals("Authentication", parser.mTypeString); - assertEquals("N/A", parser.mResultString); - } - - /** Test that we do not parse the status code out of an association request. */ - @Test - public void doesNotParseStatusCodeOutOfNonHtOpenAssociationRequest() { - FrameParser parser = new FrameParser( - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - new byte[] { - 0x00, // type + subtype - 0x00, // flags - 0x00, 0x00, // duration (from host; probably to be filled by firmware) - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // addr1 (RA) - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // addr2 (TA) - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // addr3 (BSSID) - 0x20, (byte) 0x80, // sequence + control - 0x01, 0x11, 0x01, 0x00, 0x00, 0x0b, 0x71, 0x75, - 0x69, 0x63, 0x68, 0x65, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x01, 0x08, - (byte) 0x8c, 0x12, (byte) 0x98, 0x24, (byte) 0xb0, 0x48, 0x60, 0x6c, 0x21, - 0x02, 0x08, 0x18, 0x24, 0x32, 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, - 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, 0x64, 0x01, 0x68, - 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, - (byte) 0x80, 0x01, (byte) 0x84, 0x01, (byte) 0x88, 0x01, (byte) 0x8c, 0x01, - (byte) 0x90, 0x01, (byte) 0x95, 0x01, (byte) 0x99, 0x01, (byte) 0x9d, 0x01, - (byte) 0xa1, 0x01, (byte) 0xa5, 0x01, 0x2d, 0x1a, (byte) 0xef, 0x01, 0x1f, - (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, (byte) 0xdd, 0x07, 0x00, 0x50, (byte) 0xf2, 0x02, 0x00, 0x01, 0x00, - (byte) 0xbf, 0x0c, (byte) 0x92, 0x71, (byte) 0x90, 0x33, (byte) 0xfa, - (byte) 0xff, 0x0c, 0x03, (byte) 0xfa, (byte) 0xff, 0x0c, 0x03, 0x7f, 0x09, - 0x04, 0x00, 0x0a, 0x02, 0x01, 0x00, 0x00, 0x40, (byte) 0x80, - }); - assertEquals("802.11 Mgmt", parser.mMostSpecificProtocolString); - assertEquals("Association Request", parser.mTypeString); - assertEquals("N/A", parser.mResultString); - } - - /** Test that we parse the result code of a deauthentication frame */ - @Test - public void parseDeauthenticationResultCode() { - FrameParser parser = new FrameParser( - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - new byte[]{ - (byte) 0xc0, // type + subtype - 0x00, // flags - 0x00, 0x00, // duration (from host; probably to be filled by firmware) - // addr1 (RA): - (byte) 0xa0, 0x63, (byte) 0x91, (byte) 0xa9, (byte) 0xed, (byte) 0xa1, - // addr2 (TA): - (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09, - // addr3 (BSSID): - (byte) 0xa0, 0x63, (byte) 0x91, (byte) 0xa9, (byte) 0xed, (byte) 0xa1, - 0x70, (byte) 0x80, // sequence + control - 0x03, 0x00, // reason code - }); - assertEquals("802.11 Mgmt", parser.mMostSpecificProtocolString); - assertEquals("Deauthentication", parser.mTypeString); - assertEquals( - "3: Deauthenticated because sending STA is leaving (or has left) IBSS or ESS", - parser.mResultString); - } - - /** Test that we parse the result code of a disassociation frame */ - @Test - public void parseDisassociationResultCode() { - FrameParser parser = new FrameParser( - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - new byte[]{ - (byte) 0xa0, // type + subtype - 0x00, // flags - 0x00, 0x00, // duration (from host; probably to be filled by firmware) - // addr1 (RA): - (byte) 0xa0, 0x63, (byte) 0x91, (byte) 0xa9, (byte) 0xed, (byte) 0xa1, - // addr2 (TA): - (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09, - // addr3 (BSSID): - (byte) 0xa0, 0x63, (byte) 0x91, (byte) 0xa9, (byte) 0xed, (byte) 0xa1, - 0x70, (byte) 0x80, // sequence + control - 0x04, 0x00, // reason code - }); - assertEquals("802.11 Mgmt", parser.mMostSpecificProtocolString); - assertEquals("Disassociation", parser.mTypeString); - assertEquals("4: Disassociated due to inactivity", parser.mResultString); - } - - /** Test that we parse the subtype of an Action No Ack frame */ - @Test - public void parseActionNoAckSubtype() { - FrameParser parser = new FrameParser( - WifiLoggerHal.FRAME_TYPE_80211_MGMT, - new byte[]{ - (byte) 0xe0, // type + subtype - 0x00, // flags - 0x00, 0x00, // duration (from host; probably to be filled by firmware) - // addr1 (RA): - (byte) 0xa0, 0x63, (byte) 0x91, (byte) 0xa9, (byte) 0xed, (byte) 0xa1, - // addr2 (TA): - (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09, - // addr3 (BSSID): - (byte) 0xa0, 0x63, (byte) 0x91, (byte) 0xa9, (byte) 0xed, (byte) 0xa1, - 0x70, (byte) 0x80, // sequence + control - 0x00, 0x00, // action - }); - assertEquals("802.11 Mgmt", parser.mMostSpecificProtocolString); - assertEquals("Action No Ack", parser.mTypeString); - assertEquals("N/A", parser.mResultString); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java deleted file mode 100644 index a0d1da854..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java +++ /dev/null @@ -1,1744 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.net.wifi.ScanResult; -import android.net.wifi.ScanResult.InformationElement; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.MboOceConstants; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.hotspot2.NetworkDetail; -import com.android.server.wifi.util.InformationElementUtil.HeOperation; -import com.android.server.wifi.util.InformationElementUtil.HtOperation; -import com.android.server.wifi.util.InformationElementUtil.VhtOperation; - -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Arrays; - -/** - * Unit tests for {@link com.android.server.wifi.util.InformationElementUtil}. - */ -@SmallTest -public class InformationElementUtilTest extends WifiBaseTest { - - // SSID Information Element tags - private static final byte[] TEST_SSID_BYTES_TAG = new byte[] { (byte) 0x00, (byte) 0x0B }; - // SSID Information Element entry used for testing. - private static final byte[] TEST_SSID_BYTES = "GoogleGuest".getBytes(); - // Valid zero length tag. - private static final byte[] TEST_VALID_ZERO_LENGTH_TAG = - new byte[] { (byte) 0x0B, (byte) 0x00 }; - // BSS_LOAD Information Element entry used for testing. - private static final byte[] TEST_BSS_LOAD_BYTES_IE = - new byte[] { (byte) 0x0B, (byte) 0x01, (byte) 0x08 }; - - /* - * Function to provide SSID Information Element (SSID = "GoogleGuest"). - * - * @return byte[] Byte array representing the test SSID - */ - private byte[] getTestSsidIEBytes() throws IOException { - return concatenateByteArrays(TEST_SSID_BYTES_TAG, TEST_SSID_BYTES); - } - - /* - * Function used to set byte arrays used for testing. - * - * @param byteArrays variable number of byte arrays to concatenate - * @return byte[] Byte array resulting from concatenating the arrays passed to the function - */ - private static byte[] concatenateByteArrays(byte[]... byteArrays) throws IOException { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - for (byte[] b : byteArrays) { - baos.write(b); - } - baos.flush(); - return baos.toByteArray(); - } - - /** - * Test parseInformationElements with an empty byte array. - * Expect parseInformationElement to return an empty InformationElement array. - */ - @Test - public void parseInformationElements_withEmptyByteArray() throws IOException { - byte[] emptyBytes = new byte[0]; - InformationElement[] results = - InformationElementUtil.parseInformationElements(emptyBytes); - assertEquals("parsed results should be empty", 0, results.length); - } - - /** - * Test parseInformationElements called with a null parameter. - * Expect parseInformationElement to return an empty InformationElement array. - */ - @Test - public void parseInformationElements_withNullBytes() throws IOException { - byte[] nullBytes = null; - InformationElement[] results = - InformationElementUtil.parseInformationElements(nullBytes); - assertEquals("parsed results should be empty", 0, results.length); - } - - /** - * Test parseInformationElements called with a zero length, and extension id. - * Expect parseInformationElement to return an empty InformationElement array. - */ - @Test - public void parseInformationElements_withZeroLengthAndExtensionId() throws IOException { - byte[] bytes = { (byte) 0xFF, (byte) 0x00 }; - InformationElement[] results = - InformationElementUtil.parseInformationElements(bytes); - assertEquals("parsed results should be empty", 0, results.length); - } - - /** - * Test parseInformationElements called with a zero length, and extension id after - * other IEs. - * Expect parseInformationElement to parse the IEs prior to the malformed IE. - */ - @Test - public void parseInformationElements_withZeroLengthAndExtensionIdAfterAnotherIe() - throws IOException { - byte[] malFormedIEbytes = { (byte) 0xFF, (byte) 0x00 }; - byte[] bytes = concatenateByteArrays(TEST_BSS_LOAD_BYTES_IE, malFormedIEbytes); - InformationElement[] results = - InformationElementUtil.parseInformationElements(bytes); - assertEquals("parsed results should have 1 IE", 1, results.length); - assertEquals("Parsed element should be a BSS_LOAD tag", - InformationElement.EID_BSS_LOAD, results[0].id); - } - - /* - * Test parseInformationElements with a single element represented in the byte array. - * Expect a single element to be returned in the InformationElements array. The - * length of this array should be 1 and the contents should be valid. - * - * @throws java.io.IOException - */ - @Test - public void parseInformationElements_withSingleElement() throws IOException { - byte[] ssidBytes = getTestSsidIEBytes(); - - InformationElement[] results = - InformationElementUtil.parseInformationElements(ssidBytes); - assertEquals("Parsed results should have 1 IE", 1, results.length); - assertEquals("Parsed result should be a ssid", InformationElement.EID_SSID, results[0].id); - assertArrayEquals("parsed SSID does not match input", - TEST_SSID_BYTES, results[0].bytes); - } - - /* - * Test parseInformationElement with extra padding in the data to parse. - * Expect the function to return the SSID information element. - * - * Note: Experience shows that APs often pad messages with 0x00. This happens to be the tag for - * EID_SSID. This test checks if padding will be properly discarded. - * - * @throws java.io.IOException - */ - @Test - public void parseInformationElements_withExtraPadding() throws IOException { - byte[] paddingBytes = new byte[10]; - Arrays.fill(paddingBytes, (byte) 0x00); - byte[] ssidBytesWithPadding = concatenateByteArrays(getTestSsidIEBytes(), paddingBytes); - - InformationElement[] results = - InformationElementUtil.parseInformationElements(ssidBytesWithPadding); - assertEquals("Parsed results should have 1 IE", 1, results.length); - assertEquals("Parsed result should be a ssid", InformationElement.EID_SSID, results[0].id); - assertArrayEquals("parsed SSID does not match input", - TEST_SSID_BYTES, results[0].bytes); - } - - /* - * Test parseInformationElement with two elements where the second element has an invalid - * length. - * Expect the function to return the first valid entry and skip the remaining information. - * - * Note: This test partially exposes issues with blindly parsing the data. A higher level - * function to validate the parsed data may be added. - * - * @throws java.io.IOException - * */ - @Test - public void parseInformationElements_secondElementInvalidLength() throws IOException { - byte[] invalidTag = new byte[] { (byte) 0x01, (byte) 0x08, (byte) 0x08 }; - byte[] twoTagsSecondInvalidBytes = concatenateByteArrays(getTestSsidIEBytes(), invalidTag); - - InformationElement[] results = - InformationElementUtil.parseInformationElements(twoTagsSecondInvalidBytes); - assertEquals("Parsed results should have 1 IE", 1, results.length); - assertEquals("Parsed result should be a ssid.", InformationElement.EID_SSID, results[0].id); - assertArrayEquals("parsed SSID does not match input", - TEST_SSID_BYTES, results[0].bytes); - } - - /* - * Test parseInformationElements with two valid Information Element entries. - * Expect the function to return an InformationElement array with two entries containing valid - * data. - * - * @throws java.io.IOException - */ - @Test - public void parseInformationElements_twoElements() throws IOException { - byte[] twoValidTagsBytes = - concatenateByteArrays(getTestSsidIEBytes(), TEST_BSS_LOAD_BYTES_IE); - - InformationElement[] results = - InformationElementUtil.parseInformationElements(twoValidTagsBytes); - assertEquals("parsed results should have 2 elements", 2, results.length); - assertEquals("First parsed element should be a ssid", - InformationElement.EID_SSID, results[0].id); - assertArrayEquals("parsed SSID does not match input", - TEST_SSID_BYTES, results[0].bytes); - assertEquals("second element should be a BSS_LOAD tag", - InformationElement.EID_BSS_LOAD, results[1].id); - assertEquals("second element should have data of length 1", 1, results[1].bytes.length); - assertEquals("second element data was not parsed correctly.", - (byte) 0x08, results[1].bytes[0]); - } - - /* - * Test parseInformationElements with two elements where the first information element has a - * length of zero. - * Expect the function to return an InformationElement array with two entries containing valid - * data. - * - * @throws java.io.IOException - */ - @Test - public void parseInformationElements_firstElementZeroLength() throws IOException { - byte[] zeroLengthTagWithSSIDBytes = - concatenateByteArrays(TEST_VALID_ZERO_LENGTH_TAG, getTestSsidIEBytes()); - - InformationElement[] results = - InformationElementUtil.parseInformationElements(zeroLengthTagWithSSIDBytes); - assertEquals("Parsed results should have 2 elements.", 2, results.length); - assertEquals("First element tag should be EID_BSS_LOAD", - InformationElement.EID_BSS_LOAD, results[0].id); - assertEquals("First element should be length 0", 0, results[0].bytes.length); - - assertEquals("Second element should be a ssid", InformationElement.EID_SSID, results[1].id); - assertArrayEquals("parsed SSID does not match input", - TEST_SSID_BYTES, results[1].bytes); - } - - /* - * Test parseInformationElements with two elements where the first element has an invalid - * length. The invalid length in the first element causes us to miss the start of the second - * Infomation Element. This results in a single element in the returned array. - * Expect the function to return a single entry in an InformationElement array. This returned - * entry is not validated at this time and does not contain valid data (since the incorrect - * length was used). - * TODO: attempt to validate the data and recover as much as possible. When the follow-on CL - * is in development, this test will be updated to reflect the change. - * - * @throws java.io.IOException - */ - @Test - public void parseInformationElements_firstElementWrongLength() throws IOException { - byte[] invalidLengthTag = new byte[] {(byte) 0x0B, (byte) 0x01 }; - byte[] invalidLengthTagWithSSIDBytes = - concatenateByteArrays(invalidLengthTag, getTestSsidIEBytes()); - - InformationElement[] results = - InformationElementUtil.parseInformationElements(invalidLengthTagWithSSIDBytes); - assertEquals("Parsed results should have 1 element", 1, results.length); - assertEquals("First result should be a EID_BSS_LOAD tag.", - InformationElement.EID_BSS_LOAD, results[0].id); - assertEquals("First result should have data of 1 byte", 1, results[0].bytes.length); - assertEquals("First result should have data set to 0x00", - invalidLengthTagWithSSIDBytes[2], results[0].bytes[0]); - } - - /** - * Test parseInformationElement with an element that uses extension IE - */ - @Test - public void parseInformationElementWithExtensionId() throws IOException { - byte[] testByteArray = new byte[] {(byte) 0xFF, (byte) 0x02, (byte) 0x01, (byte) 0x40}; - InformationElement[] results = - InformationElementUtil.parseInformationElements(testByteArray); - assertEquals("Parsed results should have 1 element", 1, results.length); - assertEquals("First result should have id = EID_EXTENSION_PRESENT", - InformationElement.EID_EXTENSION_PRESENT, results[0].id); - assertEquals("First result should have idExt = 0x01", 0x01, results[0].idExt); - assertEquals("First result should have data of 1 byte", 1, results[0].bytes.length); - assertEquals("First result should have data set to 0x40", - testByteArray[3], results[0].bytes[0]); - } - - /** - * Test Capabilities.generateCapabilitiesString() with a RSN IE. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_rsnElement() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_RSN; - ie.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, - (byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00, - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, - (byte) 0xAC, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ie }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA2-PSK-CCMP+TKIP][RSN-PSK-CCMP+TKIP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with a RSN IE which is malformed. - * Expect the function to return a string with empty key management & pairswise cipher security - * information. - */ - @Test - public void buildCapabilities_malformedRsnElement() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_RSN; - ie.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, - (byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00, - (byte) 0x00, (byte) 0x0F, (byte) 0xAC }; - - InformationElement[] ies = new InformationElement[] { ie }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[RSN]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with a WPA type 1 IE. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_wpa1Element() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - ie.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, - (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, - (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04, - (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, - (byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ie }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA-PSK-CCMP+TKIP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with a WPA type 1 IE which is malformed. - * Expect the function to return a string with empty key management & pairswise cipher security - * information. - */ - @Test - public void buildCapabilities_malformedWpa1Element() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - ie.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, - (byte) 0x01, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ie }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with both RSN and WPA1 IE. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_rsnAndWpaElement() { - InformationElement ieRsn = new InformationElement(); - ieRsn.id = InformationElement.EID_RSN; - ieRsn.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, - (byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00, - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, - (byte) 0xAC, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; - - InformationElement ieWpa = new InformationElement(); - ieWpa.id = InformationElement.EID_VSA; - ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, - (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, - (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04, - (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, - (byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieWpa, ieRsn }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][RSN-PSK-CCMP+TKIP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with RSN IE, CCMP and PSK+SAE transition mode. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_rsnPskSaeTransitionElement() { - InformationElement ieRsn = new InformationElement(); - ieRsn.id = InformationElement.EID_RSN; - ieRsn.bytes = new byte[] { - // RSNE Version (0x0001) - (byte) 0x01, (byte) 0x00, - // Group cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of cipher suites (1) - (byte) 0x01, (byte) 0x00, - // Cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of AKMs (2) - (byte) 0x02, (byte) 0x00, - // PSK AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, - // SAE AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x08, - // Padding - (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieRsn }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, true); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA2-PSK-CCMP][RSN-PSK+SAE-CCMP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with RSN IE, CCMP and SAE+FT/SAE. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_rsnSaeFtSaeElement() { - InformationElement ieRsn = new InformationElement(); - ieRsn.id = InformationElement.EID_RSN; - ieRsn.bytes = new byte[] { - // RSNE Version (0x0001) - (byte) 0x01, (byte) 0x00, - // Group cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of cipher suites (1) - (byte) 0x01, (byte) 0x00, - // Cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of AKMs (2) - (byte) 0x02, (byte) 0x00, - // SAE AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x08, - // FT/SAE AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x09, - // Padding - (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieRsn }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, true); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[RSN-SAE+FT/SAE-CCMP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with RSN IE, CCMP and OWE. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_rsnOweElement() { - InformationElement ieRsn = new InformationElement(); - ieRsn.id = InformationElement.EID_RSN; - ieRsn.bytes = new byte[] { - // RSNE Version (0x0001) - (byte) 0x01, (byte) 0x00, - // Group cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of cipher suites (1) - (byte) 0x01, (byte) 0x00, - // Cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of AKMs (1) - (byte) 0x01, (byte) 0x00, - // OWE AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x12, - // Padding - (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieRsn }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, true); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[RSN-OWE-CCMP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with OWE IE. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_oweVsElementOweSupported() { - InformationElement ieOwe = new InformationElement(); - ieOwe.id = InformationElement.EID_VSA; - ieOwe.bytes = new byte[] { - // OWE vendor specific - (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x1C, - // OWE IE contains BSSID, SSID and channel of other BSS, but we don't parse it. - (byte) 0x00, (byte) 0x000, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieOwe }; - - int beaconCap = 0x1 << 0; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, true); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[RSN-OWE_TRANSITION-CCMP][ESS]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with OWE IE. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_oweVsElementOweNotSupported() { - InformationElement ieOwe = new InformationElement(); - ieOwe.id = InformationElement.EID_VSA; - ieOwe.bytes = new byte[] { - // OWE vendor specific - (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x1C, - // OWE IE contains BSSID, SSID and channel of other BSS, but we don't parse it. - (byte) 0x00, (byte) 0x000, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieOwe }; - - int beaconCap = 0x1 << 0; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[ESS]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with RSN IE, GCMP-256 and SUITE_B_192. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_rsnSuiteB192Element() { - InformationElement ieRsn = new InformationElement(); - ieRsn.id = InformationElement.EID_RSN; - ieRsn.bytes = new byte[] { - // RSNE Version (0x0001) - (byte) 0x01, (byte) 0x00, - // Group cipher suite: GCMP-256 - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x09, - // Number of cipher suites (1) - (byte) 0x01, (byte) 0x00, - // Cipher suite: GCMP-256 - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x09, - // Number of AKMs (1) - (byte) 0x01, (byte) 0x00, - // SUITE_B_192 AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x0C, - // Padding - (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieRsn }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[RSN-EAP_SUITE_B_192-GCMP-256]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with RSN IE, - * CCMP and FILS SHA256. Expect the function to return a string - * with the proper security information. - */ - @Test - public void buildCapabilities_rsnFilsSha256Element() { - InformationElement ieRsn = new InformationElement(); - ieRsn.id = InformationElement.EID_RSN; - ieRsn.bytes = new byte[] { - // RSNE Version (0x0001) - (byte) 0x01, (byte) 0x00, - // Group cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of cipher suites (1) - (byte) 0x01, (byte) 0x00, - // Cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of AKMs (3) - (byte) 0x03, (byte) 0x00, - // WPA AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01, - // WPA SHA256 AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x05, - // FILS SHA256 AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x0E, - // RSN capabilities - (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieRsn }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, true); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA2-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP]" - + "[RSN-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with RSN IE, - * CCMP and FILS SHA384. Expect the function to return a string - * with the proper security information. - */ - @Test - public void buildCapabilities_rsnFilsSha384Element() { - InformationElement ieRsn = new InformationElement(); - ieRsn.id = InformationElement.EID_RSN; - ieRsn.bytes = new byte[] { - // RSNE Version (0x0001) - (byte) 0x01, (byte) 0x00, - // Group cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of cipher suites (1) - (byte) 0x01, (byte) 0x00, - // Cipher suite: CCMP - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, - // Number of AKMs (3) - (byte) 0x03, (byte) 0x00, - // WPA AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01, - // WPA SHA256 AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x05, - // FILS SHA384 AKM - (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x0F, - // RSN capabilities - (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ieRsn }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, true); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA2-EAP+EAP-SHA256+EAP-FILS-SHA384-CCMP]" - + "[RSN-EAP+EAP-SHA256+EAP-FILS-SHA384-CCMP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with both RSN and WPA1 IE which are malformed. - * Expect the function to return a string with empty key management & pairswise cipher security - * information. - */ - @Test - public void buildCapabilities_malformedRsnAndWpaElement() { - InformationElement ieRsn = new InformationElement(); - ieRsn.id = InformationElement.EID_RSN; - ieRsn.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, - (byte) 0xAC, (byte) 0x02, (byte) 0x02 }; - - InformationElement ieWpa = new InformationElement(); - ieWpa.id = InformationElement.EID_VSA; - ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, - (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, - (byte) 0x00, (byte) 0x50 }; - - InformationElement[] ies = new InformationElement[] { ieWpa, ieRsn }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA][RSN]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with both WPS and WPA1 IE. - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_wpaAndWpsElement() { - InformationElement ieWpa = new InformationElement(); - ieWpa.id = InformationElement.EID_VSA; - ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, - (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, - (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04, - (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, - (byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; - - InformationElement ieWps = new InformationElement(); - ieWps.id = InformationElement.EID_VSA; - ieWps.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04 }; - - InformationElement[] ies = new InformationElement[] { ieWpa, ieWps }; - int beaconCap = 0x1 << 4; - - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[WPA-PSK-CCMP+TKIP][WPS]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with a vendor specific element which - * is not WPA type 1. Beacon Capability Information field has the Privacy - * bit set. - * - * Expect the function to return a string with the proper security information. - */ - @Test - public void buildCapabilities_nonRsnWpa1Element_privacySet() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01, - (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ie }; - int beaconCap = 0x1 << 4; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - - assertEquals("[WEP]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with a vendor specific element which - * is not WPA type 1. Beacon Capability Information field doesn't have the - * Privacy bit set. - * - * Expect the function to return an empty string. - */ - @Test - public void buildCapabilities_nonRsnWpa1Element_privacyClear() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01, - (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ie }; - int beaconCap = 0; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - - assertEquals("", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with a vendor specific element which - * is not WPA type 1. Beacon Capability Information field has the ESS bit set. - * - * Expect the function to return a string with [ESS] there. - */ - @Test - public void buildCapabilities_nonRsnWpa1Element_essSet() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01, - (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ie }; - int beaconCap = 0x1 << 0; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - - assertEquals("[ESS]", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with a vendor specific element which - * is not WPA type 1. Beacon Capability Information field doesn't have the - * ESS bit set. - * - * Expect the function to return an empty string. - */ - @Test - public void buildCapabilities_nonRsnWpa1Element_essClear() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01, - (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - - InformationElement[] ies = new InformationElement[] { ie }; - int beaconCap = 0; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("", result); - } - - /** - * Test Capabilities.generateCapabilitiesString() with the IBSS capability bit set. - * - * Expect the function to return a string with [IBSS] there. - */ - @Test - public void buildCapabilities_IbssCapabilitySet() { - int beaconCap = 0x1 << 1; - - InformationElementUtil.Capabilities capabilities = - new InformationElementUtil.Capabilities(); - capabilities.from(new InformationElement[0], beaconCap, false); - String result = capabilities.generateCapabilitiesString(); - - assertEquals("[IBSS]", result); - } - - /** - * Verify the expectations when building an ExtendedCapabilites IE from data with no bits set. - * Both ExtendedCapabilities#isStrictUtf8() and ExtendedCapabilites#is80211McRTTResponder() - * should return false. - */ - @Test - public void buildExtendedCapabilities_emptyBitSet() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_EXTENDED_CAPS; - ie.bytes = new byte[8]; - - InformationElementUtil.ExtendedCapabilities extendedCap = - new InformationElementUtil.ExtendedCapabilities(); - extendedCap.from(ie); - assertFalse(extendedCap.isStrictUtf8()); - assertFalse(extendedCap.is80211McRTTResponder()); - } - - /** - * Verify the expectations when building an ExtendedCapabilites IE from data with UTF-8 SSID - * bit set (bit 48). ExtendedCapabilities#isStrictUtf8() should return true. - */ - @Test - public void buildExtendedCapabilites_strictUtf8() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_EXTENDED_CAPS; - ie.bytes = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00 }; - - InformationElementUtil.ExtendedCapabilities extendedCap = - new InformationElementUtil.ExtendedCapabilities(); - extendedCap.from(ie); - assertTrue(extendedCap.isStrictUtf8()); - assertFalse(extendedCap.is80211McRTTResponder()); - } - - /** - * Verify the expectations when building an ExtendedCapabilites IE from data with RTT Response - * Enable bit set (bit 70). ExtendedCapabilities#is80211McRTTResponder() should return true. - */ - @Test - public void buildExtendedCapabilites_80211McRTTResponder() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_EXTENDED_CAPS; - ie.bytes = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x40 }; - - InformationElementUtil.ExtendedCapabilities extendedCap = - new InformationElementUtil.ExtendedCapabilities(); - extendedCap.from(ie); - assertFalse(extendedCap.isStrictUtf8()); - assertTrue(extendedCap.is80211McRTTResponder()); - } - - /** - * Test a that a correctly formed TIM Information Element is decoded into a valid TIM element, - * and the values are captured - */ - @Test - public void parseTrafficIndicationMapInformationElementValid() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_TIM; - ie.bytes = new byte[] { (byte) 0x03, (byte) 0x05, (byte) 0x00, (byte) 0x00}; - InformationElementUtil.TrafficIndicationMap trafficIndicationMap = - new InformationElementUtil.TrafficIndicationMap(); - trafficIndicationMap.from(ie); - assertEquals(trafficIndicationMap.mLength, 4); - assertEquals(trafficIndicationMap.mDtimCount, 3); - assertEquals(trafficIndicationMap.mDtimPeriod, 5); - assertEquals(trafficIndicationMap.mBitmapControl, 0); - assertEquals(trafficIndicationMap.isValid(), true); - } - - /** - * Test that a short invalid Information Element is marked as being an invalid TIM element when - * parsed as Traffic Indication Map. - */ - @Test - public void parseTrafficIndicationMapInformationElementInvalidTooShort() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_TIM; - ie.bytes = new byte[] { (byte) 0x01, (byte) 0x07 }; - InformationElementUtil.TrafficIndicationMap trafficIndicationMap = - new InformationElementUtil.TrafficIndicationMap(); - trafficIndicationMap.from(ie); - assertEquals(trafficIndicationMap.isValid(), false); - } - - /** - * Test that a too-large invalid Information Element is marked as an invalid TIM element when - * parsed as Traffic Indication Map. - */ - @Test - public void parseTrafficIndicationMapInformationElementInvalidTooLong() { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_TIM; - ie.bytes = new byte[255]; // bytes length of upto 254 is valid for TIM - Arrays.fill(ie.bytes, (byte) 7); - InformationElementUtil.TrafficIndicationMap trafficIndicationMap = - new InformationElementUtil.TrafficIndicationMap(); - trafficIndicationMap.from(ie); - assertEquals(trafficIndicationMap.isValid(), false); - } - - /** - * Verify that the expected Roaming Consortium information element is parsed and retrieved - * from the list of IEs. - * - * @throws Exception - */ - @Test - public void getRoamingConsortiumIE() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_ROAMING_CONSORTIUM; - /** - * Roaming Consortium Format; - * | Number of OIs | OI#1 and OI#2 Lengths | OI #1 | OI #2 (optional) | OI #3 (optional) | - * 1 1 variable variable variable - */ - ie.bytes = new byte[] { (byte) 0x01 /* number of OIs */, (byte) 0x03 /* OI Length */, - (byte) 0x11, (byte) 0x22, (byte) 0x33}; - InformationElementUtil.RoamingConsortium roamingConsortium = - InformationElementUtil.getRoamingConsortiumIE(new InformationElement[] {ie}); - assertEquals(1, roamingConsortium.anqpOICount); - assertEquals(1, roamingConsortium.getRoamingConsortiums().length); - assertEquals(0x112233, roamingConsortium.getRoamingConsortiums()[0]); - } - - /** - * Verify that the expected Hotspot 2.0 Vendor Specific information element is parsed and - * retrieved from the list of IEs. - * - * @throws Exception - */ - @Test - public void getHS2VendorSpecificIEWithDomainIdOnly() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - /** - * Vendor Specific OI Format: - * | OI | Type | Hotspot Configuration | PPS MO ID (optional) | ANQP Domain ID (optional) - * 3 1 1 2 2 - * - * With OI=0x506F9A and Type=0x10 for Hotspot 2.0 - * - * The Format of Hotspot Configuration: - * B0 B1 B2 B3 B4 B7 - * | DGAF Disabled | PPS MO ID Flag | ANQP Domain ID Flag | reserved | Release Number | - */ - ie.bytes = new byte[] { (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x10, - (byte) 0x14 /* Hotspot Configuration */, (byte) 0x11, (byte) 0x22}; - InformationElementUtil.Vsa vsa = - InformationElementUtil.getHS2VendorSpecificIE(new InformationElement[] {ie}); - assertEquals(NetworkDetail.HSRelease.R2, vsa.hsRelease); - assertEquals(0x2211, vsa.anqpDomainID); - } - - /** - * Verify that the expected Hotspot 2.0 Vendor Specific information element is parsed and - * retrieved from the list of IEs. - * - * @throws Exception - */ - @Test - public void getHS2VendorSpecificIEWithDomainIdAndPpsMoId() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - /** - * Vendor Specific OI Format: - * | OI | Type | Hotspot Configuration | PPS MO ID (optional) | ANQP Domain ID (optional) - * 3 1 1 2 2 - * - * With OI=0x506F9A and Type=0x10 for Hotspot 2.0 - * - * The Format of Hotspot Configuration: - * B0 B1 B2 B3 B4 B7 - * | DGAF Disabled | PPS MO ID Flag | ANQP Domain ID Flag | reserved | Release Number | - */ - ie.bytes = new byte[] { (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x10, - (byte) 0x16 /* Hotspot Configuration */, (byte) 0x44, (byte) 0x33 /* PPS MO */, - (byte) 0x11, (byte) 0x22 /* ANQP Domain */}; - InformationElementUtil.Vsa vsa = - InformationElementUtil.getHS2VendorSpecificIE(new InformationElement[] {ie}); - assertEquals(NetworkDetail.HSRelease.R2, vsa.hsRelease); - assertEquals(0x2211, vsa.anqpDomainID); - } - - /** - * Verify that the expected Hotspot 2.0 Vendor Specific information element is parsed and - * retrieved from the list of IEs. - * - * @throws Exception - */ - @Test - public void testHS2VendorSpecificIEWithDomainIdAndPpsMoIdBitsIncorrectSize() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - /** - * Vendor Specific OI Format: - * | OI | Type | Hotspot Configuration | PPS MO ID (optional) | ANQP Domain ID (optional) - * 3 1 1 2 2 - * - * With OI=0x506F9A and Type=0x10 for Hotspot 2.0 - * - * The Format of Hotspot Configuration: - * B0 B1 B2 B3 B4 B7 - * | DGAF Disabled | PPS MO ID Flag | ANQP Domain ID Flag | reserved | Release Number | - */ - ie.bytes = new byte[] { (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x10, - (byte) 0x16 /* Hotspot Configuration */, (byte) 0x44, (byte) 0x33 /* PPS MO */ - /* ANQP Domain missing */}; - InformationElementUtil.Vsa vsa = - InformationElementUtil.getHS2VendorSpecificIE(new InformationElement[] {ie}); - assertEquals(0, vsa.anqpDomainID); - } - - /** - * Verify that the expected Interworking information element is parsed and retrieved from the - * list of IEs. Uses an IE w/o the optional Venue Info. - * - * @throws Exception - */ - @Test - public void getInterworkingElementNoVenueIE() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_INTERWORKING; - /** - * Interworking Format: - * | Access Network Option | Venue Info (optional) | HESSID (optional) | - * 1 2 6 - * - * Access Network Option Format: - * - * B0 B3 B4 B5 B6 B7 - * | Access Network Type | Internet | ASRA | ESR | UESA | - */ - ie.bytes = new byte[] { (byte) 0x10, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, - (byte) 0x55, (byte) 0x66 }; - InformationElementUtil.Interworking interworking = - InformationElementUtil.getInterworkingIE(new InformationElement[] {ie}); - assertTrue(interworking.internet); - assertEquals(NetworkDetail.Ant.Private, interworking.ant); - assertEquals(0x112233445566L, interworking.hessid); - } - - /** - * Verify that the expected Interworking information element is parsed and retrieved from the - * list of IEs. Uses an IE with the optional Venue Info. - * - * @throws Exception - */ - @Test - public void getInterworkingElementWithVenueIE() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_INTERWORKING; - /** - * Interworking Format: - * | Access Network Option | Venue Info (optional) | HESSID (optional) | - * 1 2 6 - * - * Access Network Option Format: - * - * B0 B3 B4 B5 B6 B7 - * | Access Network Type | Internet | ASRA | ESR | UESA | - */ - ie.bytes = new byte[]{(byte) 0x10, (byte) 0xAA, (byte) 0xBB, (byte) 0x11, (byte) 0x22, - (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66}; - InformationElementUtil.Interworking interworking = - InformationElementUtil.getInterworkingIE(new InformationElement[] {ie}); - assertTrue(interworking.internet); - assertEquals(NetworkDetail.Ant.Private, interworking.ant); - assertEquals(0x112233445566L, interworking.hessid); - } - - /** - * Verify that the expected HT Operation information element is parsed and retrieved from the - * list of IEs. - * - * @throws Exception - */ - @Test - public void getHtOperationElement() throws Exception { - final int primaryFreq = 2467; - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_HT_OPERATION; - /** - * HT Operation Format: - * | Primary Channel | HT Operation Info | Basic HT-MCS Set | - * 1 5 16 - * - * HT Operation Info Format (relevant parts only): - * - * B0 B1 B2 ----- - * | Secondary Channel Offset | STA Channel Width | Other | - */ - ie.bytes = new byte[22]; - ie.bytes[0] = (byte) 11; - ie.bytes[1] = (byte) 0x83; //Setting Secondary channel offset = 3 - // Remaining bytes are not relevant - - HtOperation htOperation = new HtOperation(); - htOperation.from(ie); - - assertTrue(htOperation.isPresent()); - assertEquals(ScanResult.CHANNEL_WIDTH_40MHZ, htOperation.getChannelWidth()); - assertEquals(primaryFreq - 10, htOperation.getCenterFreq0(primaryFreq)); - } - - /** - * Verify that the expected VHT Operation information element is parsed and retrieved from the - * list of IEs. - * In this test case Channel BW is set to be 20/40 MHz - * - * @throws Exception - */ - @Test - public void getVhtOperationElement20_40Mhz() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VHT_OPERATION; - /** - * VHT Operation Format: - * | VHT Operation Info | Basic HT-MCS Set | - * 3 2 - * - * VHT Operation Info Format: - * | Channel Width | Channel Center Freq Seg 0 | Channel Center Freq Seg 1 | - * 1 1 1 - */ - ie.bytes = new byte[]{(byte) 0x00, (byte) 0xF0, (byte) 0xF1, (byte) 0x00, (byte) 0x00}; - - VhtOperation vhtOperation = new VhtOperation(); - vhtOperation.from(ie); - - assertTrue(vhtOperation.isPresent()); - assertEquals(ScanResult.UNSPECIFIED, vhtOperation.getChannelWidth()); - assertEquals(0, vhtOperation.getCenterFreq0()); - assertEquals(0, vhtOperation.getCenterFreq1()); - } - - /** - * Verify that the expected VHT Operation information element is parsed and retrieved from the - * list of IEs. - * In this test case Channel BW is set to be 80 MHz - * - * @throws Exception - */ - @Test - public void getVhtOperationElement80Mhz() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VHT_OPERATION; - /** - * VHT Operation Format: - * | VHT Operation Info | Basic HT-MCS Set | - * 3 2 - * - * VHT Operation Info Format: - * | Channel Width | Channel Center Freq Seg 0 | Channel Center Freq Seg 1 | - * 1 1 1 - */ - ie.bytes = new byte[]{(byte) 0x01, (byte) 36, (byte) 0x00, (byte) 0x00, (byte) 0x00}; - - VhtOperation vhtOperation = new VhtOperation(); - vhtOperation.from(ie); - - assertTrue(vhtOperation.isPresent()); - assertEquals(ScanResult.CHANNEL_WIDTH_80MHZ, vhtOperation.getChannelWidth()); - assertEquals(5180, vhtOperation.getCenterFreq0()); - assertEquals(0, vhtOperation.getCenterFreq1()); - } - - /** - * Verify that the expected VHT Operation information element is parsed and retrieved from the - * list of IEs. - * In this test case Channel BW is set to be 160 MHz - * - * @throws Exception - */ - @Test - public void getVhtOperationElement160Mhz() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VHT_OPERATION; - /** - * VHT Operation Format: - * | VHT Operation Info | Basic HT-MCS Set | - * 3 2 - * - * VHT Operation Info Format: - * | Channel Width | Channel Center Freq Seg 0 | Channel Center Freq Seg 1 | - * 1 1 1 - */ - ie.bytes = new byte[]{(byte) 0x01, (byte) 44, (byte) 36, (byte) 0x00, (byte) 0x00}; - - VhtOperation vhtOperation = new VhtOperation(); - vhtOperation.from(ie); - - assertTrue(vhtOperation.isPresent()); - assertEquals(ScanResult.CHANNEL_WIDTH_160MHZ, vhtOperation.getChannelWidth()); - assertEquals(5220, vhtOperation.getCenterFreq0()); - assertEquals(5180, vhtOperation.getCenterFreq1()); - } - - /** - * Verify that the expected VHT Operation information element is parsed and retrieved from the - * list of IEs. - * In this test case Channel BW is set to be 80+80 MHz - * - * @throws Exception - */ - @Test - public void getVhtOperationElement80PlusMhz() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VHT_OPERATION; - /** - * VHT Operation Format: - * | VHT Operation Info | Basic HT-MCS Set | - * 3 2 - * - * VHT Operation Info Format: - * | Channel Width | Channel Center Freq Seg 0 | Channel Center Freq Seg 1 | - * 1 1 1 - */ - ie.bytes = new byte[]{(byte) 0x01, (byte) 54, (byte) 36, (byte) 0x00, (byte) 0x00}; - - VhtOperation vhtOperation = new VhtOperation(); - vhtOperation.from(ie); - - assertTrue(vhtOperation.isPresent()); - assertEquals(ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ, vhtOperation.getChannelWidth()); - assertEquals(5270, vhtOperation.getCenterFreq0()); - assertEquals(5180, vhtOperation.getCenterFreq1()); - } - - /** - * Verify that the expected HE Operation information element is parsed and retrieved from the - * list of IEs. - * In this test case Channel is in 6GHz band and channel width is 80MHz - * - * @throws Exception - */ - @Test - public void getHeOperationElement80Mhz() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_EXTENSION_PRESENT; - ie.idExt = InformationElement.EID_EXT_HE_OPERATION; - /** - * HE Operation Format: - * | HE Operation Info | BSS Color | Basic HE-MCS | VHT Info | Cohosted BSS| 6GH Info | - * 3 1 2 0/3 0/1 0/5 - * - * HE Operation Info: - * | Misc | VHT Operatoin Info | Misc | 6 GHz Operation Info Present | reserved | - * bits: 14 1 2 1 6 - * - * 6GHz Info Format: - * | Primary Channel | Control | Center Freq Seg 0 | Center Freq Seg 1 | Min Rate | - * 1 1 1 1 1 - * - * Control Field: - * | Channel Width | Reserved | - * bits: 2 6 - * - */ - ie.bytes = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x02, //HE Operation Info - (byte) 0x00, (byte) 0x00, (byte) 0x00, // BSS Color and HE-MCS - (byte) 0x10, (byte) 0x02, (byte) 0x14, (byte) 0x00, (byte) 0x00}; - - HeOperation heOperation = new HeOperation(); - heOperation.from(ie); - - assertTrue(heOperation.isPresent()); - assertTrue(heOperation.is6GhzInfoPresent()); - assertFalse(heOperation.isVhtInfoPresent()); - assertEquals(ScanResult.CHANNEL_WIDTH_80MHZ, heOperation.getChannelWidth()); - assertEquals(6040, heOperation.getCenterFreq0()); - assertEquals(0, heOperation.getCenterFreq1()); - } - - /** - * Verify that the expected HE Operation information element is parsed and retrieved from the - * list of IEs. - * In this test case Channel is in 6GHz band and channel width is 160MHz - * - * @throws Exception - */ - @Test - public void getHeOperationElement160Mhz() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_EXTENSION_PRESENT; - ie.idExt = InformationElement.EID_EXT_HE_OPERATION; - /** - * HE Operation Format: - * | HE Operation Info | BSS Color | Basic HE-MCS | VHT Info | Cohosted BSS| 6GH Info | - * 3 1 2 0/3 0/1 0/5 - * - * HE Operation Info: - * | Misc | VHT Operatoin Info | Misc | 6 GHz Operation Info Present | reserved | - * bits: 14 1 2 1 6 - * - * 6GHz Info Format: - * | Primary Channel | Control | Center Freq Seg 0 | Center Freq Seg 1 | Min Rate | - * 1 1 1 1 1 - * - * Control Field: - * | Channel Width | Reserved | - * bits: 2 6 - * - */ - ie.bytes = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x02, //HE Operation Info - (byte) 0x00, (byte) 0x00, (byte) 0x00, // BSS Color and HE-MCS - (byte) 0x10, (byte) 0x03, (byte) 0x14, (byte) 0x1C, (byte) 0x00}; - - HeOperation heOperation = new HeOperation(); - heOperation.from(ie); - - assertTrue(heOperation.isPresent()); - assertTrue(heOperation.is6GhzInfoPresent()); - assertFalse(heOperation.isVhtInfoPresent()); - assertEquals(ScanResult.CHANNEL_WIDTH_160MHZ, heOperation.getChannelWidth()); - assertEquals(6040, heOperation.getCenterFreq0()); - assertEquals(6080, heOperation.getCenterFreq1()); - } - - /** - * Verify that the expected HE Operation information element is parsed and retrieved from the - * list of IEs. - * In this test case Channel is not in 6GHz band and VHT info not present - * - * @throws Exception - */ - @Test - public void getHeOperationElementNo6GHzNoVht() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_EXTENSION_PRESENT; - ie.idExt = InformationElement.EID_EXT_HE_OPERATION; - /** - * HE Operation Format: - * | HE Operation Info | BSS Color | Basic HE-MCS | VHT Info | Cohosted BSS| 6GH Info | - * 3 1 2 0/3 0/1 0/5 - * - * HE Operation Info: - * | Misc | VHT Operatoin Info | Misc | 6 GHz Operation Info Present | reserved | - * bits: 14 1 2 1 6 - * - */ - ie.bytes = new byte[] { - (byte) 0x00, (byte) 0x00, (byte) 0x00, //HE Operation Info - (byte) 0x00, (byte) 0x00, (byte) 0x00 // BSS Color and HE-MCS - }; - - HeOperation heOperation = new HeOperation(); - heOperation.from(ie); - - assertTrue(heOperation.isPresent()); - assertFalse(heOperation.is6GhzInfoPresent()); - assertFalse(heOperation.isVhtInfoPresent()); - assertEquals(ScanResult.UNSPECIFIED, heOperation.getChannelWidth()); - assertEquals(0, heOperation.getCenterFreq0()); - assertEquals(0, heOperation.getCenterFreq1()); - } - - /** - * Verify that the expected HE Operation information element is parsed and retrieved from the - * list of IEs. - * In this test case Channel is not in 6GHz band and VHT info is present - * channel width is 80 MHz - * - * @throws Exception - */ - @Test - public void getHeOperationElementNo6GHzWithVht() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_EXTENSION_PRESENT; - ie.idExt = InformationElement.EID_EXT_HE_OPERATION; - /** - * HE Operation Format: - * | HE Operation Info | BSS Color | Basic HE-MCS | VHT Info | Cohosted BSS| 6GH Info | - * 3 1 2 0/3 0/1 0/5 - * - * HE Operation Info: - * | Misc | VHT Operatoin Info | Misc | 6 GHz Operation Info Present | reserved | - * bits: 14 1 2 1 6 - * - * VHT Operation Info Format: - * | Channel Width | Channel Center Freq Seg 0 | Channel Center Freq Seg 1 | - * 1 1 1 - */ - ie.bytes = new byte[]{(byte) 0x00, (byte) 0x40, (byte) 0x00, //HE Operation Info - (byte) 0x00, (byte) 0x00, (byte) 0x00, // BSS Color and HE-MCS - (byte) 0x01, (byte) 0x28, (byte) 0x00}; - - HeOperation heOperation = new HeOperation(); - heOperation.from(ie); - - assertTrue(heOperation.isPresent()); - assertFalse(heOperation.is6GhzInfoPresent()); - assertTrue(heOperation.isVhtInfoPresent()); - assertEquals(ScanResult.UNSPECIFIED, heOperation.getChannelWidth()); - assertEquals(0, heOperation.getCenterFreq0()); - assertEquals(0, heOperation.getCenterFreq1()); - - VhtOperation vhtOperation = new VhtOperation(); - vhtOperation.from(heOperation.getVhtInfoElement()); - assertEquals(ScanResult.CHANNEL_WIDTH_80MHZ, vhtOperation.getChannelWidth()); - assertEquals(5200, vhtOperation.getCenterFreq0()); - assertEquals(0, vhtOperation.getCenterFreq1()); - } - /** - * Verify that the expected max number of spatial stream is parsed correctly from - * HT capabilities IE - * - * HT capabilities IE Format: - * | HT Capability Information | A-MPDU Parameters | Supported MCS Set - * 2 1 16 - * | HT Extended Capabilities | Transmit Beamforming Capabilities | ASEL Capabilities | - * 2 4 1 - * - * Supported MCS Set Format: - * B0 B8 B16 B23 - * | Rx MCS Bitmask 1SS | Rx MCS Bitmask 2SS | Rx MCS Bitmask 3SS | Rx MCS Bitmask 4SS - */ - @Test - public void getMaxNumberSpatialStreamsWithHtCapabilitiesIE() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_HT_CAPABILITIES; - ie.bytes = new byte[]{(byte) 0xee, (byte) 0x01, (byte) 0x17, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00}; - InformationElementUtil.HtCapabilities htCapabilities = - new InformationElementUtil.HtCapabilities(); - htCapabilities.from(ie); - assertEquals(3, htCapabilities.getMaxNumberSpatialStreams()); - assertEquals(true, htCapabilities.isPresent()); - } - - /** - * Verify that the expected max number of spatial stream is parsed correctly from - * VHT capabilities IE - */ - @Test - public void getMaxNumberSpatialStreamsWithVhtCapabilitiesIE() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VHT_CAPABILITIES; - /** - * VHT Capabilities IE Format: - * | VHT capabilities Info | Supported VHT-MCS and NSS Set | - * 4 8 - * - * Supported VHT-MCS set Format: - * B0 B2 B4 B6 - * | Max MCS For 1SS | Max MCS For 2SS | Max MCS For 3SS | Max MCS For 4SS - * B8 B10 B12 B14 - * | Max MCS For 5SS | Max MCS For 6SS | Max MCS For 7SS | Max MCS For 8SS - */ - ie.bytes = new byte[]{(byte) 0x92, (byte) 0x01, (byte) 0x80, (byte) 0x33, (byte) 0xaa, - (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0xaa, (byte) 0xff, (byte) 0x00, - (byte) 0x00}; - InformationElementUtil.VhtCapabilities vhtCapabilities = - new InformationElementUtil.VhtCapabilities(); - vhtCapabilities.from(ie); - assertEquals(4, vhtCapabilities.getMaxNumberSpatialStreams()); - assertEquals(true, vhtCapabilities.isPresent()); - } - - /** - * Verify that the expected max number of spatial stream is parsed correctly from - * HE capabilities IE - */ - @Test - public void getMaxNumberSpatialStreamsWithHeCapabilitiesIE() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_EXTENSION_PRESENT; - ie.idExt = InformationElement.EID_EXT_HE_CAPABILITIES; - /** - * HE Capabilities IE Format: - * | HE MAC Capabilities Info | HE PHY Capabilities Info | Supported HE-MCS and NSS Set | - * 6 11 4 - * - * Supported HE-MCS set Format: - * B0 B2 B4 B6 - * | Max MCS For 1SS | Max MCS For 2SS | Max MCS For 3SS | Max MCS For 4SS - * B8 B10 B12 B14 - * | Max MCS For 5SS | Max MCS For 6SS | Max MCS For 7SS | Max MCS For 8SS - */ - ie.bytes = new byte[]{(byte) 0x09, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x40, - (byte) 0x04, (byte) 0x70, (byte) 0x0c, (byte) 0x80, (byte) 0x00, (byte) 0x07, - (byte) 0x80, (byte) 0x04, (byte) 0x00, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, - (byte) 0xaa, (byte) 0x7f, (byte) 0x1c, (byte) 0xc7, (byte) 0x71, (byte) 0x1c, - (byte) 0xc7, (byte) 0x71}; - InformationElementUtil.HeCapabilities heCapabilities = - new InformationElementUtil.HeCapabilities(); - heCapabilities.from(ie); - assertEquals(8, heCapabilities.getMaxNumberSpatialStreams()); - assertEquals(true, heCapabilities.isPresent()); - } - - /** - * Verify that the expected MBO-OCE Vendor Specific information - * element is parsed and MBO AP Capability Indication is - * retrieved. - * - * @throws Exception - */ - @Test - public void parseMboOceIeWithApCapabilityIndicationAttr() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - /** - * Vendor Specific MBO-OCE IE Format: - * | OUI | OUI Type | MBO-OCE attributes | - * 3 1 Variable - * - * The Format of MBO Attribute: - * | Attribute ID | Attribute length | Attribute Body Field - * 1 1 Variable - * - * MBO AP capability indication attribute Body field: - * | MBO AP Capability Indication field values | - * 1 - * | Reserved | Cellular Data aware | Reserved - * Bits: 0x80(MSB) 0x40 0x20-0x01(LSB) - */ - ie.bytes = new byte[] { (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x16, - (byte) 0x01, (byte) 0x01, (byte) 0x40}; - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.from(ie); - assertEquals(true, vsa.IsMboCapable); - assertEquals(true, vsa.IsMboApCellularDataAware); - assertEquals(MboOceConstants.MBO_OCE_ATTRIBUTE_NOT_PRESENT, - vsa.mboAssociationDisallowedReasonCode); - assertEquals(false, vsa.IsOceCapable); - } - - /** - * Verify that the expected MBO-OCE Vendor Specific information - * element is parsed and MBO association disallowed reason code is - * retrieved. - * - * @throws Exception - */ - @Test - public void parseMboOceIeWithAssociationDisallowedAttr() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - /** - * Vendor Specific MBO-OCE IE Format: - * | OUI | OUI Type | MBO-OCE attributes | - * 3 1 Variable - * - * The Format of MBO Attribute: - * | Attribute ID | Attribute length | Attribute Body Field - * 1 1 Variable - * - * MBO AP capability indication attribute Body field: - * | MBO AP Capability Indication field values | - * 1 - * | Reserved | Cellular Data aware | Reserved - * Bits: 0x80(MSB) 0x40 0x20-0x01(LSB) - * - * MBO association disallowed attribute Body field: - * | Reason code | - * 1 - */ - ie.bytes = new byte[] { (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x16, - (byte) 0x01, (byte) 0x01, (byte) 0x40, - (byte) 0x04, (byte) 0x01, (byte) 0x03}; - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.from(ie); - assertEquals(0x03, vsa.mboAssociationDisallowedReasonCode); - } - - /** - * Verify that the expected MBO-OCE Vendor Specific information - * element is parsed and OCE capability indication attribute is - * retrieved. - * - * @throws Exception - */ - @Test - public void parseMboOceIeWithOceCapabilityIndicationAttr() throws Exception { - InformationElement ie = new InformationElement(); - ie.id = InformationElement.EID_VSA; - /** - * Vendor Specific MBO-OCE IE Format: - * | OUI | OUI Type | MBO-OCE attributes | - * 3 1 Variable - * - * The Format of MBO Attribute: - * | Attribute ID | Attribute length | Attribute Body Field - * 1 1 Variable - * - * MBO AP capability indication attribute Body field: - * | MBO AP Capability Indication field values | - * 1 - * | Reserved | Cellular Data aware | Reserved - * Bits: 0x80(MSB) 0x40 0x20-0x01(LSB) - * - * OCE capability indication attribute Body field: - * | OCE Control field | - * 1 - * | OCE ver | STA-CFON | 11b-only AP present | HLP Enabled | Non-OCE AP present | Rsvd | - * Bits: B0 B2 B3 B4 B5 B6 B7 - */ - ie.bytes = new byte[] { (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x16, - (byte) 0x01, (byte) 0x01, (byte) 0x40, - (byte) 0x65, (byte) 0x01, (byte) 0x01}; - InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa(); - vsa.from(ie); - assertEquals(true, vsa.IsOceCapable); - } - - /** - * verify determineMode for various combinations. - */ - @Test - public void determineMode() throws Exception { - assertEquals(InformationElementUtil.WifiMode.MODE_11B, - InformationElementUtil.WifiMode.determineMode( - 2412, 11000000, false, false, false, false)); - assertEquals(InformationElementUtil.WifiMode.MODE_11G, - InformationElementUtil.WifiMode.determineMode( - 2412, 54000000, false, false, false, false)); - assertEquals(InformationElementUtil.WifiMode.MODE_11A, - InformationElementUtil.WifiMode.determineMode( - 5180, 54000000, false, false, false, false)); - assertEquals(InformationElementUtil.WifiMode.MODE_11G, - InformationElementUtil.WifiMode.determineMode( - 2412, 54000000, false, false, false, true)); - assertEquals(InformationElementUtil.WifiMode.MODE_11N, - InformationElementUtil.WifiMode.determineMode( - 2412, 72000000, false, false, true, false)); - assertEquals(InformationElementUtil.WifiMode.MODE_11N, - InformationElementUtil.WifiMode.determineMode( - 2412, 72000000, false, true, true, false)); - assertEquals(InformationElementUtil.WifiMode.MODE_11AC, - InformationElementUtil.WifiMode.determineMode( - 5180, 866000000, false, true, true, false)); - assertEquals(InformationElementUtil.WifiMode.MODE_11AX, - InformationElementUtil.WifiMode.determineMode( - 5180, 866000000, true, true, true, false)); - assertEquals(InformationElementUtil.WifiMode.MODE_11AX, - InformationElementUtil.WifiMode.determineMode( - 2412, 72000000, true, true, true, false)); - } - - // TODO: SAE, OWN, SUITE_B -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/IntCounterTest.java b/tests/wifitests/src/com/android/server/wifi/util/IntCounterTest.java deleted file mode 100644 index e3029ea57..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/IntCounterTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import static com.android.server.wifi.WifiMetricsTestUtil.assertKeyCountsEqual; -import static com.android.server.wifi.WifiMetricsTestUtil.buildInt32Count; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.proto.nano.WifiMetricsProto.Int32Count; - -import org.junit.Test; - - -/** - * Unit tests for IntCounter. - */ -@SmallTest -public class IntCounterTest extends WifiBaseTest { - - private static final int[] TEST_KEYS = { - 100, 20, 34, 5656, 3535, 6456, -1231, -4235, 20, 3535, -5, 100, 6456, 34, -4235, -4235 - }; - - /** - * Tests when the counter is empty. - */ - @Test - public void testEmpty() { - IntCounter counter = new IntCounter(); - assertKeyCountsEqual(new Int32Count[0], counter.toProto()); - } - - /** - * Tests adding to the counter. - */ - @Test - public void testAddToCounter() { - IntCounter counter = new IntCounter(); - - for (int k : TEST_KEYS) { - counter.increment(k); - } - - Int32Count[] expected = { - buildInt32Count(-4235, 3), - buildInt32Count(-1231, 1), - buildInt32Count(-5, 1), - buildInt32Count(20, 2), - buildInt32Count(34, 2), - buildInt32Count(100, 2), - buildInt32Count(3535, 2), - buildInt32Count(5656, 1), - buildInt32Count(6456, 2), - }; - assertKeyCountsEqual(expected, counter.toProto()); - } - - /** - * Tests adding to clamped counter. - */ - @Test - public void testAddToClampedCounter() { - IntCounter counter = new IntCounter(-5, 100); - - for (int k : TEST_KEYS) { - counter.increment(k); - } - - Int32Count[] expected = { - buildInt32Count(-5, 5), - buildInt32Count(20, 2), - buildInt32Count(34, 2), - buildInt32Count(100, 7), - }; - assertKeyCountsEqual(expected, counter.toProto()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/IntHistogramTest.java b/tests/wifitests/src/com/android/server/wifi/util/IntHistogramTest.java deleted file mode 100644 index 193f011a1..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/IntHistogramTest.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import static com.android.server.wifi.WifiMetricsTestUtil.assertHistogramBucketsEqual; -import static com.android.server.wifi.WifiMetricsTestUtil.buildHistogramBucketInt32; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.proto.nano.WifiMetricsProto.HistogramBucketInt32; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.MockitoAnnotations; - - -/** - * Unit tests for IntHistogram. - */ -@SmallTest -public class IntHistogramTest extends WifiBaseTest { - - @Rule - public ErrorCollector collector = new ErrorCollector(); - - private static final int[] TEST_BUCKET_BOUNDARIES = {10, 30, 60, 100}; - private static final int[] TEST_NEGATIVE_BUCKET_BOUNDARIES = - {-100, -20, -1, 0, 1, 5, 60, 1000}; - - private IntHistogram mHistogram; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mHistogram = null; - } - - private void incrementValueAndVerify(int value, int expectedBucketIndex, int expectedCount) { - mHistogram.increment(value); - collector.checkThat(String.format("Unexpected bucket[%d] count!", expectedBucketIndex), - mHistogram.getBucketByIndex(expectedBucketIndex).count, equalTo(expectedCount)); - } - - /** - * Tests adding values to the histogram. - */ - @Test - public void testAddToHistogram() { - mHistogram = new IntHistogram(TEST_BUCKET_BOUNDARIES); - - incrementValueAndVerify(-5, 0, 1); - incrementValueAndVerify(0, 0, 2); - incrementValueAndVerify(1, 0, 3); - incrementValueAndVerify(9, 0, 4); - incrementValueAndVerify(10, 1, 1); - incrementValueAndVerify(20, 1, 2); - incrementValueAndVerify(30, 2, 1); - incrementValueAndVerify(40, 2, 2); - incrementValueAndVerify(50, 2, 3); - incrementValueAndVerify(60, 3, 1); - incrementValueAndVerify(70, 3, 2); - incrementValueAndVerify(80, 3, 3); - incrementValueAndVerify(90, 3, 4); - incrementValueAndVerify(100, 4, 1); - incrementValueAndVerify(110, 4, 2); - incrementValueAndVerify(98999, 4, 3); - - collector.checkThat("Unexpected number of non-empty buckets!", - mHistogram.numNonEmptyBuckets(), equalTo(TEST_BUCKET_BOUNDARIES.length + 1)); - - String expectedStr = "{[Integer.MIN_VALUE,10)=4, [10,30)=2, [30,60)=3, [60,100)=4, " - + "[100,Integer.MAX_VALUE]=3}"; - collector.checkThat("Unexpected toString() result", - mHistogram.toString(), equalTo(expectedStr)); - - HistogramBucketInt32[] actualProto = mHistogram.toProto(); - HistogramBucketInt32[] expectedProto = { - buildHistogramBucketInt32(Integer.MIN_VALUE, 10, 4), - buildHistogramBucketInt32(10, 30, 2), - buildHistogramBucketInt32(30, 60, 3), - buildHistogramBucketInt32(60, 100, 4), - buildHistogramBucketInt32(100, Integer.MAX_VALUE, 3) - }; - assertHistogramBucketsEqual(expectedProto, actualProto); - } - - /** - * Tests when a bucket was never incremented. Expect that bucket should not exist in - * toString() and toProto() results. - */ - @Test - public void testAddToHistogramWithGap() { - mHistogram = new IntHistogram(TEST_BUCKET_BOUNDARIES); - - incrementValueAndVerify(-5, 0, 1); - incrementValueAndVerify(0, 0, 2); - incrementValueAndVerify(1, 0, 3); - incrementValueAndVerify(9, 0, 4); - incrementValueAndVerify(30, 1, 1); - incrementValueAndVerify(40, 1, 2); - incrementValueAndVerify(50, 1, 3); - incrementValueAndVerify(60, 2, 1); - incrementValueAndVerify(70, 2, 2); - incrementValueAndVerify(80, 2, 3); - incrementValueAndVerify(90, 2, 4); - incrementValueAndVerify(100, 3, 1); - incrementValueAndVerify(110, 3, 2); - incrementValueAndVerify(98999, 3, 3); - - collector.checkThat("Unexpected number of non-empty buckets!", - mHistogram.numNonEmptyBuckets(), equalTo(4)); - - String expectedStr = "{[Integer.MIN_VALUE,10)=4, [30,60)=3, [60,100)=4, " - + "[100,Integer.MAX_VALUE]=3}"; - collector.checkThat("Unexpected toString() result", - mHistogram.toString(), equalTo(expectedStr)); - - HistogramBucketInt32[] actualProto = mHistogram.toProto(); - HistogramBucketInt32[] expectedProto = { - buildHistogramBucketInt32(Integer.MIN_VALUE, 10, 4), - buildHistogramBucketInt32(30, 60, 3), - buildHistogramBucketInt32(60, 100, 4), - buildHistogramBucketInt32(100, Integer.MAX_VALUE, 3) - }; - assertHistogramBucketsEqual(expectedProto, actualProto); - } - - /** - * Tests adding negative values to the histogram. - */ - @Test - public void testAddNegativeToHistogram() { - mHistogram = new IntHistogram(TEST_NEGATIVE_BUCKET_BOUNDARIES); - - incrementValueAndVerify(-99999, 0, 1); - incrementValueAndVerify(-101, 0, 2); - incrementValueAndVerify(-100, 1, 1); - incrementValueAndVerify(-99, 1, 2); - incrementValueAndVerify(-21, 1, 3); - incrementValueAndVerify(-20, 2, 1); - incrementValueAndVerify(-19, 2, 2); - incrementValueAndVerify(-2, 2, 3); - incrementValueAndVerify(-1, 3, 1); - incrementValueAndVerify(0, 4, 1); - incrementValueAndVerify(0, 4, 2); - incrementValueAndVerify(1, 5, 1); - incrementValueAndVerify(2, 5, 2); - incrementValueAndVerify(4, 5, 3); - incrementValueAndVerify(5, 6, 1); - incrementValueAndVerify(6, 6, 2); - incrementValueAndVerify(59, 6, 3); - incrementValueAndVerify(60, 7, 1); - incrementValueAndVerify(61, 7, 2); - incrementValueAndVerify(999, 7, 3); - incrementValueAndVerify(1000, 8, 1); - incrementValueAndVerify(1001, 8, 2); - incrementValueAndVerify(99999, 8, 3); - - collector.checkThat("Unexpected number of non-empty buckets!", - mHistogram.numNonEmptyBuckets(), - equalTo(TEST_NEGATIVE_BUCKET_BOUNDARIES.length + 1)); - - String expectedStr = "{[Integer.MIN_VALUE,-100)=2, [-100,-20)=3, [-20,-1)=3, [-1,0)=1, " - + "[0,1)=2, [1,5)=3, [5,60)=3, [60,1000)=3, [1000,Integer.MAX_VALUE]=3}"; - collector.checkThat("Unexpected toString() result", - mHistogram.toString(), equalTo(expectedStr)); - - HistogramBucketInt32[] actualProto = mHistogram.toProto(); - HistogramBucketInt32[] expectedProto = { - buildHistogramBucketInt32(Integer.MIN_VALUE, -100, 2), - buildHistogramBucketInt32(-100, -20, 3), - buildHistogramBucketInt32(-20, -1, 3), - buildHistogramBucketInt32(-1, 0, 1), - buildHistogramBucketInt32(0, 1, 2), - buildHistogramBucketInt32(1, 5, 3), - buildHistogramBucketInt32(5, 60, 3), - buildHistogramBucketInt32(60, 1000, 3), - buildHistogramBucketInt32(1000, Integer.MAX_VALUE, 3) - }; - assertHistogramBucketsEqual(expectedProto, actualProto); - } - - /** - * Tests when the histogram is empty. - */ - @Test - public void testEmptyHistogram() { - mHistogram = new IntHistogram(TEST_BUCKET_BOUNDARIES); - - collector.checkThat("Unexpected number of non-empty buckets!", - mHistogram.numNonEmptyBuckets(), equalTo(0)); - - String expectedStr = "{}"; - collector.checkThat("Unexpected toString() result", - mHistogram.toString(), equalTo(expectedStr)); - - HistogramBucketInt32[] expectedProto = {}; - assertHistogramBucketsEqual(expectedProto, mHistogram.toProto()); - } - - /** - * Tests when the histogram has length 1. - */ - @Test - public void testLength1Histogram() { - mHistogram = new IntHistogram(TEST_BUCKET_BOUNDARIES); - - incrementValueAndVerify(10, 0, 1); - incrementValueAndVerify(20, 0, 2); - - collector.checkThat("Unexpected number of non-empty buckets!", - mHistogram.numNonEmptyBuckets(), equalTo(1)); - - String expectedStr = "{[10,30)=2}"; - collector.checkThat("Unexpected toString() result", - mHistogram.toString(), equalTo(expectedStr)); - - HistogramBucketInt32[] expectedProto = { - buildHistogramBucketInt32(10, 30, 2) - }; - assertHistogramBucketsEqual(expectedProto, mHistogram.toProto()); - } - - /** - * Should throw exception for null boundary array. - */ - @Test(expected = IllegalArgumentException.class) - public void testNullBucketBoundary() { - new IntHistogram(null); - } - - /** - * Should throw exception for empty array of boundaries. - */ - @Test(expected = IllegalArgumentException.class) - public void testEmptyBucketBoundary() { - new IntHistogram(new int[] {}); - } - - /** - * Should throw exception for boundary values that are not monotonically increasing. - */ - @Test(expected = IllegalArgumentException.class) - public void testNonMonotonicBucketBoundaries() { - new IntHistogram(new int[] {1, 2, 3, 3}); - } - - @Test - public void testEmptyQuantile() { - mHistogram = new IntHistogram(TEST_BUCKET_BOUNDARIES); - double q = mHistogram.quantileFunction(0.2, 0, 50); - assertEquals(q, 10.0, 0.01); - } - - @Test - public void testQuantileUniformDistribution() { - mHistogram = new IntHistogram(TEST_BUCKET_BOUNDARIES); - for (int i = 0; i < 111; i++) { - mHistogram.increment(i); - } - String diagnose = mHistogram.toString(); - double q; - - for (double i = 0.0; i <= 111.0; i++) { - q = mHistogram.quantileFunction(i / 111.0, 0, 111); - assertEquals(diagnose, i, q, 0.01); - } - - q = mHistogram.quantileFunction(.8, 0, 42); - assertEquals(42.0, q, 0.01); - } - - @Test(expected = IllegalArgumentException.class) - public void backwardsBoundsShouldFail() { - new IntHistogram(TEST_BUCKET_BOUNDARIES).quantileFunction(0.5, 80, 40); - } - - @Test(expected = IllegalArgumentException.class) - public void negativeProbablilityShouldFail() { - new IntHistogram(TEST_BUCKET_BOUNDARIES).quantileFunction(-0.1, 0, 50); - } - - @Test(expected = IllegalArgumentException.class) - public void largerThanUnityProbablilityShouldFail() { - new IntHistogram(TEST_BUCKET_BOUNDARIES).quantileFunction(1.1, 0, 50); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/KalmanFilterTest.java b/tests/wifitests/src/com/android/server/wifi/util/KalmanFilterTest.java deleted file mode 100644 index c5ac0452b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/KalmanFilterTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.util; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.util.Random; - -/** - * Unit tests for {@link com.android.server.wifi.util.KalmanFilter}. - */ -@SmallTest -public class KalmanFilterTest extends WifiBaseTest { - /** - * Test that constructor works - */ - @Test - public void testConstructor() throws Exception { - KalmanFilter kf = new KalmanFilter(); - assertNotNull(kf); - } - - /** - * Sets up a Kalman filter to behave as as a phase-locked loop - * <p> - * Set up a 2-D model that generates sinusoidal output at a fixed frequency; the state - * transformation is just a rotation by a fixed angle, and the output matrix projects oen - * of the dimensions. - */ - private KalmanFilter initializePll(double stepSizeRadians, - double modelStandardDeviation, - double measurementStandardDeviation) { - KalmanFilter kf = new KalmanFilter(); - double cos = Math.cos(stepSizeRadians); - double sin = Math.sin(stepSizeRadians); - kf.mF = new Matrix(2, new double[]{ - cos, sin, - -sin, cos}); - double modelVariance = modelStandardDeviation * modelStandardDeviation; - kf.mQ = new Matrix(2, new double[]{ - modelVariance, 0.0, - 0.0, modelVariance}); - kf.mH = new Matrix(2, new double[]{1.0, 0.0}); - double measurementVariance = measurementStandardDeviation * measurementStandardDeviation; - kf.mR = new Matrix(1, new double[]{measurementVariance}); - double initialAPosterioriVariance = 10000.0; - kf.mP = new Matrix(2, new double[]{ - initialAPosterioriVariance, 0.0, - 0.0, initialAPosterioriVariance}); - kf.mx = new Matrix(2, 1); - return kf; - } - - private double mAmplitude = 10.0; - private double mStepSizeRadians = Math.PI / 17.01; - private int mTransitionPoint = 300; - - /** - * Generates the ideal signal at time step i. - * <p> - * Sinusoid, with an abrupt phase shift thrown in to test transient response - */ - private double idealSignal(int i) { - double phi = mStepSizeRadians * i; - if (i > mTransitionPoint) { - phi = phi + Math.PI * .75; - } - return mAmplitude * Math.sin(phi); - } - - private double mNoiseAmplitude = 3.0; - - private int mSteps = 500; - private int mSeed = 271828; - - /** - * Test that using the phase locked loop Kalman filter results in a residual that is - * a lot smaller than the noise in the signal. - */ - @Test - public void testPhaseLockedLoop() throws Exception { - Random random = new Random(mSeed); - double modelStandardDeviation = 0.5; - double [] noise = new double[mSteps]; - for (int i = 0; i < mSteps; i++) { - noise[i] = random.nextGaussian() * mNoiseAmplitude; - } - double [] filtered = new double[mSteps]; - double [] residual = new double[mSteps]; - KalmanFilter kf = initializePll(mStepSizeRadians, modelStandardDeviation, mNoiseAmplitude); - for (int i = 0; i < mSteps; i++) { - kf.predict(); - kf.update(new Matrix(1, new double[] {idealSignal(i) + noise[i]})); - filtered[i] = kf.mx.get(0, 0); - residual[i] = filtered[i] - idealSignal(i); - } - double sum = 0.0; - double sumSquares = 0.0; - double n = 0.0; - for (int i = 0; i < mSteps; i++) { - if (i < 5 || (i > mTransitionPoint && i < mTransitionPoint + 20)) continue; - sum += residual[i]; - sumSquares += residual[i] * residual[i]; - n += 1.0; - } - double mean = sum / n; - double variance = (sumSquares - sum * sum) / (n * n); - assertTrue(mean < 0.1); - assertTrue(variance < 1.5); - assertNotNull(kf.toString()); - } - - /** - * Test that the toString method works even if the matrices have not been set. - */ - @Test - public void testToStrinWithNullsInside() throws Exception { - assertNotNull(new KalmanFilter().toString()); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/LruConnectionTrackerTest.java b/tests/wifitests/src/com/android/server/wifi/util/LruConnectionTrackerTest.java deleted file mode 100644 index eb5ae5bdd..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/LruConnectionTrackerTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi.util; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.wifi.WifiConfiguration; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.MockResources; -import com.android.server.wifi.WifiConfigurationTestUtil; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@SmallTest -public class LruConnectionTrackerTest { - private static final int TEST_MAX_SIZE = 4; - private LruConnectionTracker mList; - private MockResources mResources; - - @Mock private Context mContext; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mResources = new MockResources(); - mResources.setInteger(R.integer.config_wifiMaxPnoSsidCount, TEST_MAX_SIZE - 1); - when(mContext.getResources()).thenReturn(mResources); - mList = new LruConnectionTracker(TEST_MAX_SIZE, mContext); - } - - @Test - public void testAddRemoveNetwork() { - WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork(); - assertEquals(Integer.MAX_VALUE, mList.getAgeIndexOfNetwork(network)); - mList.addNetwork(network); - assertEquals(0, mList.getAgeIndexOfNetwork(network)); - mList.removeNetwork(network); - assertEquals(Integer.MAX_VALUE, mList.getAgeIndexOfNetwork(network)); - } - - @Test - public void testConnectionOrderStore() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network4 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network5 = WifiConfigurationTestUtil.createOpenNetwork(); - mList.addNetwork(network1); - mList.addNetwork(network2); - mList.addNetwork(network3); - mList.addNetwork(network4); - // Expect reverse order of the added order - assertEquals(0, mList.getAgeIndexOfNetwork(network4)); - assertEquals(1, mList.getAgeIndexOfNetwork(network3)); - assertEquals(2, mList.getAgeIndexOfNetwork(network2)); - assertEquals(3, mList.getAgeIndexOfNetwork(network1)); - // Exceed the size of the list, should remove the oldest one. - mList.addNetwork(network5); - assertEquals(Integer.MAX_VALUE, mList.getAgeIndexOfNetwork(network1)); - assertEquals(0, mList.getAgeIndexOfNetwork(network5)); - // Add one already in the list, move it to the head of the list. - mList.addNetwork(network3); - assertEquals(0, mList.getAgeIndexOfNetwork(network3)); - assertEquals(1, mList.getAgeIndexOfNetwork(network5)); - assertEquals(2, mList.getAgeIndexOfNetwork(network4)); - assertEquals(3, mList.getAgeIndexOfNetwork(network2)); - } - - @Test - public void testIsMostRecentlyNetwork() { - WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network2 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network3 = WifiConfigurationTestUtil.createOpenNetwork(); - WifiConfiguration network4 = WifiConfigurationTestUtil.createOpenNetwork(); - mList.addNetwork(network1); - mList.addNetwork(network2); - mList.addNetwork(network3); - assertTrue(mList.isMostRecentlyConnected(network1)); - assertTrue(mList.isMostRecentlyConnected(network2)); - assertTrue(mList.isMostRecentlyConnected(network3)); - assertFalse(mList.isMostRecentlyConnected(network4)); - // network in the list is more than the threshold, will mark the oldest false. - mList.addNetwork(network4); - assertFalse(mList.isMostRecentlyConnected(network1)); - assertTrue(mList.isMostRecentlyConnected(network4)); - // Add network in the list and which is true. Should not change other network flag. - mList.addNetwork(network2); - assertFalse(mList.isMostRecentlyConnected(network1)); - assertTrue(mList.isMostRecentlyConnected(network2)); - assertTrue(mList.isMostRecentlyConnected(network3)); - assertTrue(mList.isMostRecentlyConnected(network4)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/LruListTest.java b/tests/wifitests/src/com/android/server/wifi/util/LruListTest.java deleted file mode 100644 index 00122b12a..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/LruListTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi.util; - -import static org.junit.Assert.*; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; - -import java.util.Arrays; -import java.util.List; - - -/** - * Unit tests for IntCounter. - */ -@SmallTest -public class LruListTest extends WifiBaseTest { - - private static final int TEST_MAX_SIZE = 3; - private LruList<Integer> mLruList; - - @Before - public void setUp() { - mLruList = new LruList<Integer>(TEST_MAX_SIZE); - } - - /** - * Verify that the least recent entry is removed when the Lru list becomes full. - * And also an existing element will get moved to the front of the list when added. - */ - @Test - public void testLeastRecentEntryIsRemoved() { - for (int i = 0; i < TEST_MAX_SIZE + 1; i++) { - mLruList.add(i); - } - mLruList.add(2); - assertEquals(TEST_MAX_SIZE, mLruList.size()); - List<Integer> expected = Arrays.asList(new Integer[] {2, 3, 1}); - assertEquals(expected, mLruList.getEntries()); - } - - /** - * Verify null input is no-op. - */ - @Test - public void testAddNull() { - mLruList.add(null); - assertEquals(0, mLruList.size()); - } - - @Test - public void getIndex() { - for (int i = 0; i < TEST_MAX_SIZE; i++) { - mLruList.add(i); - } - for (int i = 0; i < TEST_MAX_SIZE; i++) { - assertEquals(i, mLruList.indexOf(TEST_MAX_SIZE - i - 1)); - } - // Verify not in the list will return -1. - assertEquals(-1, mLruList.indexOf(3)); - mLruList.add(3); - // Verify add more elements more than list size, will remove oldest one. - assertEquals(0, mLruList.indexOf(3)); - assertEquals(-1, mLruList.indexOf(0)); - // Verify add an element in the list will make it the most recently one. - mLruList.add(1); - assertEquals(0, mLruList.indexOf(1)); - assertEquals(1, mLruList.indexOf(3)); - assertEquals(2, mLruList.indexOf(2)); - // Verify remove one element in the list, all element behind it index should decrease 1. - mLruList.remove(1); - assertEquals(-1, mLruList.indexOf(1)); - assertEquals(0, mLruList.indexOf(3)); - assertEquals(1, mLruList.indexOf(2)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/MatrixTest.java b/tests/wifitests/src/com/android/server/wifi/util/MatrixTest.java deleted file mode 100644 index 5fa95be9f..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/MatrixTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2017 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.server.wifi.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.fail; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Random; - -/** - * Unit tests for {@link com.android.server.wifi.util.Matrix}. - */ -@SmallTest -public class MatrixTest extends WifiBaseTest { - /** - * Test that both forms of constructor work - */ - @Test - public void testConstructors() throws Exception { - assertEquals(new Matrix(3, 2), new Matrix(2, new double[]{0, 0, 0, 0, 0, 0})); - } - - /** - * Test some degenerate cases - */ - @Test - public void testDegenerate() throws Exception { - Matrix m1 = new Matrix(0, 20); - Matrix m2 = new Matrix(20, 0); - assertEquals(m1, m2.transpose()); - } - - /** - * Test addition - */ - @Test - public void testAddition() throws Exception { - Matrix m1 = new Matrix(2, new double[]{1, 2, 3, 4}); - Matrix m2 = new Matrix(2, new double[]{10, 20, 30, 40}); - Matrix m3 = new Matrix(2, new double[]{11, 22, 33, 44}); - assertEquals(m3, m1.plus(m2)); - } - - /** - * Test subtraction. - */ - @Test - public void testSubtraction() throws Exception { - Matrix m1 = new Matrix(2, new double[]{1, 2, 3, 4}); - Matrix m2 = new Matrix(2, new double[]{10, 20, 30, 40}); - Matrix m3 = new Matrix(2, new double[]{11, 22, 33, 44}); - assertEquals(m1, m3.minus(m2)); - } - - /** - * Test scalar multiplication. - */ - @Test - public void testScalarMultiplication() throws Exception { - Matrix m1 = new Matrix(2, new double[]{1, 2, 3, 4}); - double x = 1001; - Matrix m2 = new Matrix(2, new double[]{x * 1, x * 2, x * 3, x * 4}); - assertEquals(m2, m1.times(x)); - } - - /** - * Test matrix multiplication. - */ - @Test - public void testMultiplication() throws Exception { - Matrix m1 = new Matrix(2, new double[]{1, 2, 3, 4}); - Matrix m2 = new Matrix(2, new double[]{-3, 3, 7, 1}); - Matrix m3 = new Matrix(2, new double[]{11, 5, 19, 13}); - assertEquals(m3, m1.dot(m2)); - } - - /** - * Test that matrix inverse works (non-singular case). - */ - @Test - public void testInverse() throws Exception { - Matrix i3 = new Matrix(3, new double[]{1, 0, 0, 0, 1, 0, 0, 0, 1}); - Matrix f = new Matrix(3, new double[]{100, 100, 100, 100, 100, 100, 100, 100, 100}); - Matrix m1 = new Matrix(3, new double[]{10, 1, -1, 2, 14, -1, 0, 2, 20}); - Matrix m2 = m1.inverse(); - Matrix m12 = m1.dot(m2); - Matrix m21 = m2.dot(m1); - // Add f here to wash out the roundoff errors - assertEquals(i3.plus(f), m12.plus(f)); - assertEquals(i3.plus(f), m21.plus(f)); - } - - /** - * Generates a random permuation matrix - */ - public Matrix generatePermutationMatrix(int size, Random random) { - Matrix matrix = new Matrix(size, size); - ArrayList<Integer> j = new ArrayList(size); - for (int i = 0; i < size; i++) { - j.add(i); - } - Collections.shuffle(j, random); - for (int i = 0; i < size; i++) { - matrix.put(i, j.get(i), 1.0); - } - return matrix; - } - - /** - * Test that inverting a random permutaion matrix works - */ - @Test - public void testInverseOfPermutation() throws Exception { - int size = 20; - Matrix m1 = generatePermutationMatrix(size, new Random(132)); - Matrix m2 = m1.inverse(); - Matrix m3 = m1.transpose(); - assertEquals(m3, m2); - } - - /** - * Test that attempting to invert a singular matrix throws an exception. - * @throws Exception - */ - @Test - public void testSingularity() throws Exception { - Matrix m1 = new Matrix(3, new double[]{10, 1, -1, 0, 0, 0, 0, 0, 0}); - try { - m1.inverse(); - fail("Expected ArithmeticException"); - } catch (ArithmeticException e) { - return; - } - } - - /** - * Test multiplication by a transpose - */ - @Test - public void testMultiplicationByTranspose() throws Exception { - Matrix m1 = new Matrix(2, new double[]{1, 2, 3, 4, 5, 6}); - Matrix m2 = new Matrix(2, new double[]{1, 2, 3, 4, 5, 6, 7, 8}); - assertEquals(m1.dot(m2.transpose()), m1.dotTranspose(m2)); - } - - /** - * Test that exception is thrown for non-conformable dotTranspose - */ - @Test - public void testMultiplicationByBadlyShapedTranspose() throws Exception { - Matrix m1 = new Matrix(2, new double[]{1, 2, 3, 4, 5, 6}); - Matrix m2 = m1.transpose(); - try { - m1.dotTranspose(m2); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - } - - /** - * Test that a copy is equal to the original, and that hash codes match, - * and that string versions match; exercise equals in various ways. - */ - @Test - public void testCopy() throws Exception { - Random random = new Random(); - Matrix m1 = new Matrix(3, 4); - for (int i = 0; i < m1.mem.length; i++) { - m1.mem[i] = random.nextDouble(); - } - assertEquals(m1, m1); - Matrix m2 = new Matrix(m1); - assertEquals(m1, m2); - assertEquals(m1.hashCode(), m2.hashCode()); - assertEquals(m1.toString(), m2.toString()); - m2.put(2, 2, 2.0); // guaranteed change, because nextDouble() is between 0 and 1. - assertNotEquals(m1, m2); - assertNotEquals(m1, m1.transpose()); - assertNotEquals(m1.toString(), m2.toString()); - assertNotEquals(m1, null); - assertNotEquals(m1, "a"); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/MetricsUtilsTest.java b/tests/wifitests/src/com/android/server/wifi/util/MetricsUtilsTest.java deleted file mode 100644 index e2f4d3d37..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/MetricsUtilsTest.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.util; - -import static org.hamcrest.core.IsEqual.equalTo; - -import android.util.SparseIntArray; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.mockito.MockitoAnnotations; - -/** - * Unit test harness for MetricsUtils. - */ -@SmallTest -public class MetricsUtilsTest extends WifiBaseTest { - @Rule - public ErrorCollector collector = new ErrorCollector(); - - /** - * Pre-test configuration. Initialize and install mocks. - */ - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - - /** - * Histogram of following buckets, start[i] = 0 + 1 * 10^i with 9 sub-buckets, i=0,...,5 - * 1 - 10: 9 sub-buckets each of width 1 - * 10 - 100: 10 - * 100 - 10e3: 10^2 - * 10e3 - 10e4: 10^3 - * 10e4 - 10e5: 10^4 - * 10e5 - 10e6: 10^5 - */ - private static final MetricsUtils.LogHistParms HIST1 = new MetricsUtils.LogHistParms(0, 1, 10, - 9, 6); - - /** - * Histogram of following buckets, start[i] = -20 + 2 * 5^i with 40 sub-buckets, i=0,...,2 - * -18 - -10: 40 sub-bucket each of width 0.2 - * -10 - 30: 1 - * 30 - 230: 5 - */ - private static final MetricsUtils.LogHistParms HIST2 = new MetricsUtils.LogHistParms(-20, 2, 5, - 40, 3); - - // Linear histogram of following buckets: - // <10 - // [10, 30) - // [30, 60) - // [60, 100) - // >100 - private static final int[] HIST_LINEAR = {10, 30, 60, 100}; - - /** - * Validate that a set of values are bucketed correctly into the histogram, and that they are - * converted to a primitive proto-buffer array correctly. - */ - @Test - public void testHistBucketing() { - SparseIntArray hist1 = new SparseIntArray(); - SparseIntArray hist2 = new SparseIntArray(); - - bucketValueAndVerify("HIST1: x=", -5, hist1, HIST1, 0, 1); - bucketValueAndVerify("HIST1: x=", 0, hist1, HIST1, 0, 2); - bucketValueAndVerify("HIST1: x=", 1, hist1, HIST1, 0, 3); - bucketValueAndVerify("HIST1: x=", 9, hist1, HIST1, 8, 1); - bucketValueAndVerify("HIST1: x=", 10, hist1, HIST1, 9, 1); - bucketValueAndVerify("HIST1: x=", 99, hist1, HIST1, 17, 1); - bucketValueAndVerify("HIST1: x=", 100, hist1, HIST1, 18, 1); - bucketValueAndVerify("HIST1: x=", 989, hist1, HIST1, 26, 1); - bucketValueAndVerify("HIST1: x=", 990, hist1, HIST1, 26, 2); - bucketValueAndVerify("HIST1: x=", 999, hist1, HIST1, 26, 3); - bucketValueAndVerify("HIST1: x=", 1000, hist1, HIST1, 27, 1); - bucketValueAndVerify("HIST1: x=", 9899, hist1, HIST1, 35, 1); - bucketValueAndVerify("HIST1: x=", 9900, hist1, HIST1, 35, 2); - bucketValueAndVerify("HIST1: x=", 9999, hist1, HIST1, 35, 3); - bucketValueAndVerify("HIST1: x=", 10000, hist1, HIST1, 36, 1); - bucketValueAndVerify("HIST1: x=", 98999, hist1, HIST1, 44, 1); - bucketValueAndVerify("HIST1: x=", 99000, hist1, HIST1, 44, 2); - bucketValueAndVerify("HIST1: x=", 99999, hist1, HIST1, 44, 3); - bucketValueAndVerify("HIST1: x=", 100000, hist1, HIST1, 45, 1); - bucketValueAndVerify("HIST1: x=", 989999, hist1, HIST1, 53, 1); - bucketValueAndVerify("HIST1: x=", 990000, hist1, HIST1, 53, 2); - bucketValueAndVerify("HIST1: x=", 999999, hist1, HIST1, 53, 3); - bucketValueAndVerify("HIST1: x=", 1000000, hist1, HIST1, 53, 4); - bucketValueAndVerify("HIST1: x=", 1000001, hist1, HIST1, 53, 5); - bucketValueAndVerify("HIST1: x=", 5000000, hist1, HIST1, 53, 6); - bucketValueAndVerify("HIST1: x=", 10000000, hist1, HIST1, 53, 7); - - MetricsUtils.GenericBucket[] phb1 = MetricsUtils.logHistogramToGenericBuckets(hist1, HIST1); - collector.checkThat("Number of buckets #1", phb1.length, equalTo(hist1.size())); - validateProtoHistBucket("Bucket1[0]", phb1[0], 1, 2, 3); - validateProtoHistBucket("Bucket1[1]", phb1[1], 9, 10, 1); - validateProtoHistBucket("Bucket1[2]", phb1[2], 10, 20, 1); - validateProtoHistBucket("Bucket1[3]", phb1[3], 90, 100, 1); - validateProtoHistBucket("Bucket1[4]", phb1[4], 100, 200, 1); - validateProtoHistBucket("Bucket1[5]", phb1[5], 900, 1000, 3); - validateProtoHistBucket("Bucket1[6]", phb1[6], 1000, 2000, 1); - validateProtoHistBucket("Bucket1[7]", phb1[7], 9000, 10000, 3); - validateProtoHistBucket("Bucket1[8]", phb1[8], 10000, 20000, 1); - validateProtoHistBucket("Bucket1[9]", phb1[9], 90000, 100000, 3); - validateProtoHistBucket("Bucket1[10]", phb1[10], 100000, 200000, 1); - validateProtoHistBucket("Bucket1[11]", phb1[11], 900000, 1000000, 7); - - bucketValueAndVerify("HIST2: x=", -20, hist2, HIST2, 0, 1); - bucketValueAndVerify("HIST2: x=", -18, hist2, HIST2, 0, 2); - bucketValueAndVerify("HIST2: x=", -17, hist2, HIST2, 5, 1); - bucketValueAndVerify("HIST2: x=", -11, hist2, HIST2, 35, 1); - bucketValueAndVerify("HIST2: x=", -10, hist2, HIST2, 40, 1); - bucketValueAndVerify("HIST2: x=", 29, hist2, HIST2, 79, 1); - bucketValueAndVerify("HIST2: x=", 30, hist2, HIST2, 80, 1); - bucketValueAndVerify("HIST2: x=", 229, hist2, HIST2, 119, 1); - bucketValueAndVerify("HIST2: x=", 230, hist2, HIST2, 119, 2); - bucketValueAndVerify("HIST2: x=", 300, hist2, HIST2, 119, 3); - bucketValueAndVerify("HIST2: x=", 1000000, hist2, HIST2, 119, 4); - - MetricsUtils.GenericBucket[] phb2 = MetricsUtils.logHistogramToGenericBuckets(hist2, HIST2); - collector.checkThat("Number of buckets #2", phb2.length, equalTo(hist2.size())); - validateProtoHistBucket("Bucket2[0]", phb2[0], -18, -17, 2); - validateProtoHistBucket("Bucket2[1]", phb2[1], -17, -16, 1); - validateProtoHistBucket("Bucket2[2]", phb2[2], -11, -10, 1); - validateProtoHistBucket("Bucket2[3]", phb2[3], -10, -9, 1); - validateProtoHistBucket("Bucket2[4]", phb2[4], 29, 30, 1); - validateProtoHistBucket("Bucket2[5]", phb2[5], 30, 35, 1); - validateProtoHistBucket("Bucket2[6]", phb2[6], 225, 230, 4); - } - - /** - * Validate that a set of values are bucketed correctly into the linear histogram, and that - * they are converted to a primitive proto-buffer array correctly. - */ - @Test - public void testLinearHistBucketing() { - SparseIntArray hist = new SparseIntArray(); - - bucketValueAndVerify("HIST_LINEAR: x=", -5, hist, HIST_LINEAR, 0, 1); - bucketValueAndVerify("HIST_LINEAR: x=", 0, hist, HIST_LINEAR, 0, 2); - bucketValueAndVerify("HIST_LINEAR: x=", 1, hist, HIST_LINEAR, 0, 3); - bucketValueAndVerify("HIST_LINEAR: x=", 9, hist, HIST_LINEAR, 0, 4); - bucketValueAndVerify("HIST_LINEAR: x=", 10, hist, HIST_LINEAR, 1, 1); - bucketValueAndVerify("HIST_LINEAR: x=", 20, hist, HIST_LINEAR, 1, 2); - bucketValueAndVerify("HIST_LINEAR: x=", 30, hist, HIST_LINEAR, 2, 1); - bucketValueAndVerify("HIST_LINEAR: x=", 40, hist, HIST_LINEAR, 2, 2); - bucketValueAndVerify("HIST_LINEAR: x=", 50, hist, HIST_LINEAR, 2, 3); - bucketValueAndVerify("HIST_LINEAR: x=", 60, hist, HIST_LINEAR, 3, 1); - bucketValueAndVerify("HIST_LINEAR: x=", 70, hist, HIST_LINEAR, 3, 2); - bucketValueAndVerify("HIST_LINEAR: x=", 80, hist, HIST_LINEAR, 3, 3); - bucketValueAndVerify("HIST_LINEAR: x=", 90, hist, HIST_LINEAR, 3, 4); - bucketValueAndVerify("HIST_LINEAR: x=", 100, hist, HIST_LINEAR, 4, 1); - bucketValueAndVerify("HIST_LINEAR: x=", 110, hist, HIST_LINEAR, 4, 2); - bucketValueAndVerify("HIST_LINEAR: x=", 98999, hist, HIST_LINEAR, 4, 3); - - MetricsUtils.GenericBucket[] phb = MetricsUtils.linearHistogramToGenericBuckets(hist, - HIST_LINEAR); - collector.checkThat("Number of buckets", phb.length, equalTo(hist.size())); - validateProtoHistBucket("Bucket[0]", phb[0], Integer.MIN_VALUE, 10, 4); - validateProtoHistBucket("Bucket[1]", phb[1], 10, 30, 2); - validateProtoHistBucket("Bucket[2]", phb[2], 30, 60, 3); - validateProtoHistBucket("Bucket[3]", phb[3], 60, 100, 4); - validateProtoHistBucket("Bucket[4]", phb[4], 100, Integer.MAX_VALUE, 3); - } - - // utilities - - private void bucketValueAndVerify(String prefix, long value, SparseIntArray h, - MetricsUtils.LogHistParms hp, int expectedKey, int expectedValue) { - MetricsUtils.addValueToLogHistogram(value, h, hp); - collector.checkThat(prefix + value, h.get(expectedKey), equalTo(expectedValue)); - } - - private void bucketValueAndVerify(String prefix, int value, SparseIntArray h, int[] hp, - int expectedKey, int expectedValue) { - MetricsUtils.addValueToLinearHistogram(value, h, hp); - collector.checkThat(prefix + value, h.get(expectedKey), equalTo(expectedValue)); - } - - private void validateProtoHistBucket(String prefix, MetricsUtils.GenericBucket bucket, - long start, long end, int count) { - collector.checkThat(prefix + ": start", bucket.start, equalTo(start)); - collector.checkThat(prefix + ": end", bucket.end, equalTo(end)); - collector.checkThat(prefix + ": count", bucket.count, equalTo(count)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/MissingCounterTimerLockListTest.java b/tests/wifitests/src/com/android/server/wifi/util/MissingCounterTimerLockListTest.java deleted file mode 100644 index c145f7fb7..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/MissingCounterTimerLockListTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2020 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.server.wifi.util; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.when; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.HashSet; -import java.util.Set; - -@SmallTest -public class MissingCounterTimerLockListTest extends WifiBaseTest { - private static final int TEST_MISSING_COUNT = 2; - private static final long BLOCKING_DURATION = 1000; - private static final String TEST_SSID = "testSSID"; - private static final String TEST_FQDN = "testFQDN"; - - private MissingCounterTimerLockList<String> mMissingCounterTimerLockList; - - @Mock Clock mClock; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mMissingCounterTimerLockList = - new MissingCounterTimerLockList<>(TEST_MISSING_COUNT, mClock); - } - - @Test - public void testAddRemove() { - mMissingCounterTimerLockList.add(TEST_SSID, BLOCKING_DURATION); - mMissingCounterTimerLockList.add(TEST_FQDN, BLOCKING_DURATION); - mMissingCounterTimerLockList.add(null, BLOCKING_DURATION); - assertEquals(2, mMissingCounterTimerLockList.size()); - assertTrue(mMissingCounterTimerLockList.isLocked(TEST_SSID)); - assertTrue(mMissingCounterTimerLockList.isLocked(TEST_FQDN)); - assertTrue(mMissingCounterTimerLockList.remove(TEST_SSID)); - assertEquals(1, mMissingCounterTimerLockList.size()); - assertFalse(mMissingCounterTimerLockList.isLocked(TEST_SSID)); - assertTrue(mMissingCounterTimerLockList.isLocked(TEST_FQDN)); - mMissingCounterTimerLockList.clear(); - assertEquals(0, mMissingCounterTimerLockList.size()); - } - - @Test - public void testUpdateAndTimer() { - mMissingCounterTimerLockList.add(TEST_SSID, BLOCKING_DURATION); - mMissingCounterTimerLockList.add(TEST_FQDN, BLOCKING_DURATION); - assertEquals(2, mMissingCounterTimerLockList.size()); - when(mClock.getWallClockMillis()).thenReturn((long) 0); - Set<String> updateSet = new HashSet<>(); - updateSet.add(TEST_FQDN); - mMissingCounterTimerLockList.update(updateSet); - assertEquals(2, mMissingCounterTimerLockList.size()); - mMissingCounterTimerLockList.update(updateSet); - assertEquals(2, mMissingCounterTimerLockList.size()); - when(mClock.getWallClockMillis()).thenReturn(BLOCKING_DURATION + 50); - assertEquals(2, mMissingCounterTimerLockList.size()); - assertFalse(mMissingCounterTimerLockList.isLocked(TEST_SSID)); - assertTrue(mMissingCounterTimerLockList.isLocked(TEST_FQDN)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java deleted file mode 100644 index 566a94b45..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import static org.junit.Assert.*; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Unit tests for {@link com.android.server.wifi.util.NativeUtil}. - */ -@SmallTest -public class NativeUtilTest extends WifiBaseTest { - /** - * Test that parsing a typical colon-delimited MAC address works. - */ - @Test - public void testMacAddressToByteArray() throws Exception { - assertArrayEquals(new byte[]{0x61, 0x52, 0x43, 0x34, 0x25, 0x16}, - NativeUtil.macAddressToByteArray("61:52:43:34:25:16")); - } - - /** - * Test that parsing an empty MAC address works. - */ - @Test - public void testEmptyMacAddressToByteArray() throws Exception { - assertArrayEquals(new byte[]{0, 0, 0, 0, 0, 0}, - NativeUtil.macAddressToByteArray("")); - assertArrayEquals(new byte[]{0, 0, 0, 0, 0, 0}, - NativeUtil.macAddressToByteArray(null)); - } - - /** - * Test that conversion of byte array of mac address to typical colon-delimited MAC address - * works. - */ - @Test - public void testByteArrayToMacAddress() throws Exception { - assertEquals("61:52:43:34:25:16", - NativeUtil.macAddressFromByteArray(new byte[]{0x61, 0x52, 0x43, 0x34, 0x25, 0x16})); - } - - /** - * Test that parsing a typical colon-delimited MAC OUI address works. - */ - @Test - public void testMacAddressOuiToByteArray() throws Exception { - assertArrayEquals(new byte[]{0x61, 0x52, 0x43}, - NativeUtil.macAddressOuiToByteArray("61:52:43")); - } - - /** - * Test that parsing a hex string to byte array works. - */ - @Test - public void testHexStringToByteArray() throws Exception { - assertArrayEquals(new byte[]{0x45, 0x12, 0x23, 0x34}, - NativeUtil.hexStringToByteArray("45122334")); - } - - /** - * Test that conversion of byte array to hexstring works. - */ - @Test - public void testHexStringFromByteArray() throws Exception { - assertEquals("45122334", - NativeUtil.hexStringFromByteArray(new byte[]{0x45, 0x12, 0x23, 0x34})); - } - - /** - * Test that conversion of ssid bytes to quoted ASCII string ssid works. - */ - @Test - public void testAsciiSsidDecode() throws Exception { - assertEquals( - new ArrayList<>( - Arrays.asList((byte) 's', (byte) 's', (byte) 'i', (byte) 'd', (byte) '_', - (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '1', - (byte) '2', (byte) '3')), - NativeUtil.decodeSsid("\"ssid_test123\"")); - } - - /** - * Test that conversion of ssid bytes to quoted UTF8 string ssid works. - */ - @Test - public void testUtf8SsidDecode() throws Exception { - assertEquals( - new ArrayList<>( - Arrays.asList((byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, - (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x41, (byte) 0x50, - (byte) 0xe3, (byte) 0x81, (byte) 0x8f, (byte) 0xe3, (byte) 0x81, - (byte) 0xa0, (byte) 0xe3, (byte) 0x81, (byte) 0x95, (byte) 0xe3, - (byte) 0x81, (byte) 0x84)), - NativeUtil.decodeSsid("\"AndroidAPください\"")); - } - - /** - * Test that conversion of non utf-8 SSID string to bytes fail. - */ - @Test - public void testNonUtf8SsidDecodeFails() throws Exception { - try { - NativeUtil.decodeSsid("\"\ud800\""); - fail("Expected ssid decode to fail"); - } catch (IllegalArgumentException e) { - } - } - - /** - * Test that conversion of SSID string with len > 32 to bytes fail. - */ - @Test - public void testLargeSsidDecodeFails() throws Exception { - try { - NativeUtil.decodeSsid("\"asdrewqdfgyuiopldsqwertyuiolhdergcv\""); - fail("Expected ssid decode to fail"); - } catch (IllegalArgumentException e) { - } - } - - /** - * Test that conversion of ssid bytes to hex string ssid works. - */ - @Test - public void testNonSsidDecode() throws Exception { - assertEquals( - new ArrayList<>( - Arrays.asList((byte) 0xf5, (byte) 0xe4, (byte) 0xab, (byte) 0x78, - (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a)), - NativeUtil.decodeSsid("f5e4ab78ab3432439a")); - } - - /** - * Test that conversion of ssid bytes to quoted string ssid works. - */ - @Test - public void testSsidEncode() throws Exception { - assertEquals( - "\"ssid_test123\"", - NativeUtil.encodeSsid(new ArrayList<>( - Arrays.asList((byte) 's', (byte) 's', (byte) 'i', (byte) 'd', (byte) '_', - (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '1', - (byte) '2', (byte) '3')))); - } - - /** - * Test that conversion of byte array to hex string works when the byte array contains 0. - */ - @Test - public void testNullCharInSsidEncode() throws Exception { - assertEquals( - "007369645f74657374313233", - NativeUtil.encodeSsid(new ArrayList<>( - Arrays.asList((byte) 0x00, (byte) 's', (byte) 'i', (byte) 'd', (byte) '_', - (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '1', - (byte) '2', (byte) '3')))); - } - - /** - * Test that conversion of byte array to hex string ssid works. - */ - @Test - public void testNonSsidEncode() throws Exception { - assertEquals( - "f5e4ab78ab3432439a", - NativeUtil.encodeSsid(new ArrayList<>( - Arrays.asList((byte) 0xf5, (byte) 0xe4, (byte) 0xab, (byte) 0x78, - (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a)))); - } - - /** - * Test that conversion of SSID bytes with len > 32 to string fail. - */ - @Test - public void testLargeSsidEncodeFails() throws Exception { - try { - NativeUtil.encodeSsid(new ArrayList<>( - Arrays.asList((byte) 0xf5, (byte) 0xe4, (byte) 0xab, (byte) 0x78, (byte) 0x78, - (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a, - (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a, - (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a, - (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a, - (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a, - (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a))); - fail("Expected ssid encode to fail"); - } catch (IllegalArgumentException e) { - } - } - - /** - * Test that parsing of quoted SSID to byte array and vice versa works. - */ - @Test - public void testSsidEncodeDecode() throws Exception { - String ssid = "\"ssid_test123\""; - assertEquals(ssid, NativeUtil.encodeSsid(NativeUtil.decodeSsid(ssid))); - } - - /** - * Test that the enclosing quotes are removed properly. - */ - @Test - public void testRemoveEnclosingQuotes() throws Exception { - assertEquals("abcdefgh", NativeUtil.removeEnclosingQuotes("\"abcdefgh\"")); - assertEquals("abcdefgh", NativeUtil.removeEnclosingQuotes("abcdefgh")); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/ObjectCounterTest.java b/tests/wifitests/src/com/android/server/wifi/util/ObjectCounterTest.java deleted file mode 100644 index b468a9a2b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/ObjectCounterTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertThat; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.util.ObjectCounter.ProtobufConverter; - -import org.hamcrest.collection.IsIterableContainingInAnyOrder; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Objects; - - -/** - * Unit test for ObjectCounter - */ -@SmallTest -public class ObjectCounterTest extends WifiBaseTest { - - /** - * Test Key type: composite key with 3 fields - */ - public static class TestKey { - public int key1; - public String key2; - public boolean key3; - - public TestKey(int key1, String key2, boolean key3) { - this.key1 = key1; - this.key2 = key2; - this.key3 = key3; - } - - // generated by IntelliJ - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TestKey testKey = (TestKey) o; - return key1 == testKey.key1 - && key3 == testKey.key3 - && Objects.equals(key2, testKey.key2); - } - - // generated by IntelliJ - @Override - public int hashCode() { - return Objects.hash(key1, key2, key3); - } - - // generated by IntelliJ - @Override - public String toString() { - return "TestKey{" - + "key1=" + key1 - + ", key2='" + key2 + '\'' - + ", key3=" + key3 - + '}'; - } - } - - /** - * Test Proto type with 3 keys and a count field - */ - public static class TestKeyProto { - public int key1; - public String key2; - public boolean key3; - public int count; - - public TestKeyProto(int key1, String key2, boolean key3, int count) { - this.key1 = key1; - this.key2 = key2; - this.key3 = key3; - this.count = count; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TestKeyProto that = (TestKeyProto) o; - return key1 == that.key1 - && key3 == that.key3 - && count == that.count - && Objects.equals(key2, that.key2); - } - - @Override - public int hashCode() { - return Objects.hash(key1, key2, key3, count); - } - } - - private static final TestKey[] TEST_KEYS = { - new TestKey(10, "asdf", false), - new TestKey(5, "qwer", true), - new TestKey(10, "asdf", false), - new TestKey(10, "asdf", false), - new TestKey(-1, "zxcv", true), - new TestKey(-1, "zxcv", true), - new TestKey(-1, "zxcv", true), - }; - - - private static final ProtobufConverter<TestKey, TestKeyProto> CONVERTER = - (TestKey key, int count) -> new TestKeyProto(key.key1, key.key2, key.key3, count); - - /** - * Tests when the counter is empty. - */ - @Test - public void testEmpty() { - assertArrayEquals(new TestKeyProto[0], - new ObjectCounter<TestKey>().toProto(TestKeyProto.class, CONVERTER)); - } - - /** - * Tests adding to the counter. - */ - @Test - public void testAddToCounter() { - ObjectCounter<TestKey> counter = new ObjectCounter<>(); - for (TestKey key : TEST_KEYS) { - counter.increment(key); - } - - TestKeyProto[] expected = { - new TestKeyProto(10, "asdf", false, 3), - new TestKeyProto(5, "qwer", true, 1), - new TestKeyProto(-1, "zxcv", true, 3) - }; - - TestKeyProto[] actual = counter.toProto(TestKeyProto.class, CONVERTER); - - assertThat("Unexpected output protobuf array (ignoring order)", - Arrays.asList(actual), IsIterableContainingInAnyOrder.containsInAnyOrder(expected)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/RssiUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/RssiUtilTest.java deleted file mode 100644 index d87d94c56..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/RssiUtilTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.res.Resources; -import android.net.wifi.IWifiManager; -import android.net.wifi.WifiManager; -import android.os.Build; -import android.os.Looper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; -import com.android.wifi.resources.R; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - - -/** Unit tests for {@link RssiUtil}. */ -@SmallTest -public class RssiUtilTest extends WifiBaseTest { - - public static final int[] RSSI_THRESHOLDS = {-88, -77, -66, -55}; - - @Mock private Context mContext; - @Mock private Resources mResources; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mContext.getResources()).thenReturn(mResources); - when(mResources.getIntArray(R.array.config_wifiRssiLevelThresholds)) - .thenReturn(RSSI_THRESHOLDS); - } - - /** - * Tests that our default RSSI thresholds matches what would be calculated by - * {@link WifiManager#calculateSignalLevel(int, int)}. - */ - @Test - public void testCalculateSignalLevelImplementationsConsistent() { - for (int rssi = -100; rssi <= 0; rssi++) { - int expected = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS); - int actual = RssiUtil.calculateSignalLevel(mContext, rssi); - assertWithMessage("RSSI: %s", rssi).that(actual).isEqualTo(expected); - } - } - - /** Tests the signal level at RSSIs at around the thresholds. */ - @Test - public void testCalculateSignalLevel() { - assertThat(RssiUtil.calculateSignalLevel(mContext, -100)).isEqualTo(0); - assertThat(RssiUtil.calculateSignalLevel(mContext, -89)).isEqualTo(0); - assertThat(RssiUtil.calculateSignalLevel(mContext, -88)).isEqualTo(1); - assertThat(RssiUtil.calculateSignalLevel(mContext, -78)).isEqualTo(1); - assertThat(RssiUtil.calculateSignalLevel(mContext, -77)).isEqualTo(2); - assertThat(RssiUtil.calculateSignalLevel(mContext, -67)).isEqualTo(2); - assertThat(RssiUtil.calculateSignalLevel(mContext, -66)).isEqualTo(3); - assertThat(RssiUtil.calculateSignalLevel(mContext, -56)).isEqualTo(3); - assertThat(RssiUtil.calculateSignalLevel(mContext, -55)).isEqualTo(4); - assertThat(RssiUtil.calculateSignalLevel(mContext, 0)).isEqualTo(4); - assertThat(RssiUtil.calculateSignalLevel(mContext, Integer.MAX_VALUE)).isEqualTo(4); - } - - /** Tests that an empty thresholds array always returns level 0. */ - @Test - public void testCalculateSignalLevelEmptyThresholdsArray() { - when(mResources.getIntArray(R.array.config_wifiRssiLevelThresholds)) - .thenReturn(new int[0]); - assertThat(RssiUtil.calculateSignalLevel(mContext, -100)).isEqualTo(0); - assertThat(RssiUtil.calculateSignalLevel(mContext, -50)).isEqualTo(0); - assertThat(RssiUtil.calculateSignalLevel(mContext, 0)).isEqualTo(0); - - assertThat(RssiUtil.calculateSignalLevel(mContext, Integer.MAX_VALUE)).isEqualTo(0); - } - - /** Tests that the expected default max signal level is returned. */ - @Test - public void testGetMaxSignalLevel() throws Exception { - IWifiManager iWifiManager = mock(IWifiManager.class); - - doAnswer(invocation -> { - int rssi = invocation.getArgument(0); - return RssiUtil.calculateSignalLevel(mContext, rssi); - }).when(iWifiManager).calculateSignalLevel(anyInt()); - - ApplicationInfo applicationInfo = mock(ApplicationInfo.class); - applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; - Context context = mock(Context.class); - when(context.getApplicationInfo()).thenReturn(applicationInfo); - when(context.getOpPackageName()).thenReturn("TestPackage"); - WifiManager wifiManager = new WifiManager( - context, iWifiManager, mock(Looper.class)); - - int level = wifiManager.getMaxSignalLevel(); - assertThat(level).isEqualTo(4); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java deleted file mode 100644 index 00e3a0bd2..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import static org.junit.Assert.*; - -import android.net.wifi.ScanResult; -import android.net.wifi.ScanResult.InformationElement; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiSsid; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.ScanDetail; -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.wifi.util.ScanResultUtil}. - */ -@SmallTest -public class ScanResultUtilTest extends WifiBaseTest { - - @Test - public void convertScanResult() { - final String ssid = "SOME SsId"; - - ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, "", -78, 2450, 1025, 22, 33, 20, 0, 0, true); - - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - - ScanDetail output = ScanResultUtil.toScanDetail(input); - - validateScanDetail(input, output); - } - - @Test - public void convertScanResultWithAnqpLines() { - final String ssid = "SOME SsId"; - - ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, "some caps", -78, 2450, 1025, 22, 33, 20, 0, 0, true); - - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - input.anqpLines = Arrays.asList("LINE 1", "line 2", "Line 3"); - - ScanDetail output = ScanResultUtil.toScanDetail(input); - - validateScanDetail(input, output); - } - - @Test - public void convertScanResultWithoutWifiSsid() { - final String ssid = "Another SSid"; - ScanResult input = new ScanResult(ssid, "ab:cd:01:ef:45:89", 1245, 0, "other caps", - -78, 2450, 1025, 22, 33, 20, 0, 0, true); - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - - ScanDetail output = ScanResultUtil.toScanDetail(input); - - validateScanDetail(input, output); - } - - @Test - public void testNetworkCreationFromScanResult() { - final String ssid = "Another SSid"; - ScanResult scanResult = new ScanResult(ssid, "ab:cd:01:ef:45:89", 1245, 0, "", - -78, 2450, 1025, 22, 33, 20, 0, 0, true); - WifiConfiguration config; - - scanResult.capabilities = ""; - config = ScanResultUtil.createNetworkFromScanResult(scanResult); - assertEquals(config.SSID, ScanResultUtil.createQuotedSSID(ssid)); - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)); - - scanResult.capabilities = "WEP"; - config = ScanResultUtil.createNetworkFromScanResult(scanResult); - assertEquals(config.SSID, ScanResultUtil.createQuotedSSID(ssid)); - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)); - assertTrue(config.allowedAuthAlgorithms.get(WifiConfiguration.AuthAlgorithm.OPEN)); - assertTrue(config.allowedAuthAlgorithms.get(WifiConfiguration.AuthAlgorithm.SHARED)); - - scanResult.capabilities = "PSK"; - config = ScanResultUtil.createNetworkFromScanResult(scanResult); - assertEquals(config.SSID, ScanResultUtil.createQuotedSSID(ssid)); - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)); - - scanResult.capabilities = "EAP"; - config = ScanResultUtil.createNetworkFromScanResult(scanResult); - assertEquals(config.SSID, ScanResultUtil.createQuotedSSID(ssid)); - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)); - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)); - - scanResult.capabilities = "WAPI-PSK"; - config = ScanResultUtil.createNetworkFromScanResult(scanResult); - assertEquals(config.SSID, ScanResultUtil.createQuotedSSID(ssid)); - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK)); - - scanResult.capabilities = "WAPI-CERT"; - config = ScanResultUtil.createNetworkFromScanResult(scanResult); - assertEquals(config.SSID, ScanResultUtil.createQuotedSSID(ssid)); - assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_CERT)); - } - - /** - * Test that a PSK-SHA256+SAE network is detected as transition mode - */ - @Test - public void testPskSha256SaeTransitionModeCheck() { - final String ssid = "WPA3-Transition"; - String caps = "[WPA2-FT/PSK-CCMP][RSN-FT/PSK+PSK-SHA256+SAE+FT/SAE-CCMP][ESS][WPS]"; - - ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, - 0, true); - - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - - assertTrue(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); - } - - /** - * Test that a PSK+SAE network is detected as transition mode - */ - @Test - public void testPskSaeTransitionModeCheck() { - final String ssid = "WPA3-Transition"; - String caps = "[WPA2-FT/PSK+PSK+SAE+FT/SAE-CCMP][ESS][WPS]"; - - ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, - 0, true); - - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - - assertTrue(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); - } - - /** - * Test that a PSK network is not detected as transition mode - */ - @Test - public void testPskNotInTransitionModeCheck() { - final String ssid = "WPA2-Network"; - String caps = "[WPA2-FT/PSK+PSK][ESS][WPS]"; - - ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, - 0, true); - - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - - assertFalse(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); - } - - /** - * Test that an SAE network is not detected as transition mode - */ - @Test - public void testSaeNotInTransitionModeCheck() { - final String ssid = "WPA3-Network"; - String caps = "[WPA2-FT/SAE+SAE][ESS][WPS]"; - - ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, - 0, true); - - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - - assertFalse(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); - } - - /** - * Test that provided network supports FILS SHA256 AKM. - */ - @Test - public void testFilsSha256AkmSupportedNetwork() { - final String ssid = "FILS-AP"; - String caps = "[WPA2-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP]" - + "[RSN-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP][ESS]"; - - ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, - 0, true); - - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - - assertTrue(ScanResultUtil.isScanResultForFilsSha256Network(input)); - } - - /** - * Test that provided network supports FILS SHA384 AKM. - */ - @Test - public void testFilsSha384AkmSupportedNetwork() { - final String ssid = "FILS-AP"; - String caps = "[WPA2-EAP+EAP-SHA384+EAP-FILS-SHA384-CCMP]" - + "[RSN-EAP+EAP-SHA384+EAP-FILS-SHA384-CCMP][ESS]"; - - ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, - "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, - 0, true); - - input.informationElements = new InformationElement[] { - createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) - }; - - assertTrue(ScanResultUtil.isScanResultForFilsSha384Network(input)); - } - - /** - * Verify ScanResultList validation. - */ - @Test - public void testValidateScanResultList() { - List<ScanResult> scanResults = new ArrayList<>(); - assertFalse(ScanResultUtil.validateScanResultList(null)); - assertFalse(ScanResultUtil.validateScanResultList(scanResults)); - scanResults.add(null); - assertFalse(ScanResultUtil.validateScanResultList(scanResults)); - ScanResult scanResult = new ScanResult(); - scanResults.clear(); - scanResults.add(scanResult); - assertFalse(ScanResultUtil.validateScanResultList(scanResults)); - scanResult.SSID = "test"; - scanResult.capabilities = "[RSN-PSK-CCMP]"; - scanResult.BSSID = "ab:cd:01:ef:45:89"; - assertTrue(ScanResultUtil.validateScanResultList(scanResults)); - } - - private static InformationElement createIE(int id, byte[] bytes) { - InformationElement ie = new InformationElement(); - ie.id = id; - ie.bytes = bytes; - return ie; - } - - private static void validateScanDetail(ScanResult input, ScanDetail output) { - assertNotNull("NetworkDetail was null", output.getNetworkDetail()); - assertNotNull("ScanResult was null", output.getScanResult()); - assertEquals("NetworkDetail SSID", input.SSID, - output.getNetworkDetail().getSSID()); - assertEquals("ScanResult SSID", input.SSID, - output.getScanResult().SSID); - assertEquals("ScanResult wifiSsid", input.wifiSsid, - output.getScanResult().wifiSsid); - assertEquals("getSSID", input.SSID, output.getSSID()); - assertEquals("NetworkDetail BSSID", input.BSSID, - output.getNetworkDetail().getBSSIDString()); - assertEquals("getBSSIDString", input.BSSID, output.getBSSIDString()); - assertEquals("ScanResult frequency", input.frequency, - output.getScanResult().frequency); - assertEquals("ScanResult level", input.level, - output.getScanResult().level); - assertEquals("ScanResult capabilities", input.capabilities, - output.getScanResult().capabilities); - assertEquals("ScanResult timestamp", input.timestamp, - output.getScanResult().timestamp); - assertArrayEquals("ScanResult information elements", input.informationElements, - output.getScanResult().informationElements); - assertEquals("ScanResult anqp lines", input.anqpLines, - output.getScanResult().anqpLines); - } - -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/StringUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/StringUtilTest.java deleted file mode 100644 index db6168699..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/StringUtilTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Test; - -/** - * Unit tests for {@link com.android.server.wifi.util.StringUtil}. - */ -@SmallTest -public class StringUtilTest extends WifiBaseTest { - static final byte ASCII_UNIT_SEPARATOR = 31; - static final byte ASCII_DEL = 127; - - /** Verifies that isAsciiPrintable() does not crash when passed a null array. */ - @Test - public void nullArrayDoesNotCauseCrash() { - assertTrue(StringUtil.isAsciiPrintable(null)); - } - - /** Verifies that isAsciiPrintable() considers an empty array to be printable. */ - @Test - public void emptyArrayIsPrintable() { - assertTrue(StringUtil.isAsciiPrintable(new byte[]{})); - } - - /** Verifies that isAsciiPrintable() considers a single printable byte to be printable. */ - @Test - public void arrayWithSinglePrintableByteIsPrintable() { - assertTrue(StringUtil.isAsciiPrintable(new byte[]{'a'})); - } - - /** - * Verifies that isAsciiPrintable() considers an array of multiple printable bytes to be - * printable. - */ - @Test - public void arrayWithMultiplePrintableBytesIsPrintable() { - assertTrue(StringUtil.isAsciiPrintable(new byte[]{'a', 'b'})); - } - - /** - * Verifies that isAsciiPrintable() considers bell, form feed, newline, horizontal tab, - * and vertical tab to be printable. - */ - @Test - public void printableControlCharactersAreConsideredPrintable() { - assertTrue(StringUtil.isAsciiPrintable(new byte[]{0x07})); // bell - assertTrue(StringUtil.isAsciiPrintable(new byte[]{'\f'})); // form feed - assertTrue(StringUtil.isAsciiPrintable(new byte[]{'\n'})); - assertTrue(StringUtil.isAsciiPrintable(new byte[]{'\t'})); - assertTrue(StringUtil.isAsciiPrintable(new byte[]{0x0b})); // vertical tab - } - - /** Verifies that isAsciiPrintable() considers a newline to be printable. */ - @Test - public void arrayWithNewlineIsPrintable() { - assertTrue(StringUtil.isAsciiPrintable(new byte[]{'\n'})); - } - - /** Verifies that isAsciiPrintable() considers a space to be printable. */ - @Test - public void arrayWithSpaceIsPrintable() { - assertTrue(StringUtil.isAsciiPrintable(new byte[]{' '})); - } - - /** Verifies that isAsciiPrintable() considers a tilde to be printable. */ - @Test - public void arrayWithTildeIsPrintable() { - assertTrue(StringUtil.isAsciiPrintable(new byte[]{'~'})); - } - - /** Verifies that isAsciiPrintable() considers a null to be unprintable. */ - @Test - public void arrayWithNullByteIsNotPrintable() { - assertFalse(StringUtil.isAsciiPrintable(new byte[]{0})); - } - - /** Verifies that isAsciiPrintable() considers (space-1) to be unprintable. */ - @Test - public void arrayWithUnitSeparatorIsNotPrintable() { - assertFalse(StringUtil.isAsciiPrintable(new byte[]{ASCII_UNIT_SEPARATOR})); - } - - /** Verifies that isAsciiPrintable() considers (tilde+1) to be unprintable. */ - @Test - public void arrayWithDelIsNotPrintable() { - assertFalse(StringUtil.isAsciiPrintable(new byte[]{ASCII_DEL})); - } - - /** - * Verifies that isAsciiPrintable() considers negative bytes to be unprintable. - * (In unsigned representation, these are values greater than DEL.) - */ - @Test - public void arrayWithNegativeByteIsNotPrintable() { - assertFalse(StringUtil.isAsciiPrintable(new byte[]{-128})); - assertFalse(StringUtil.isAsciiPrintable(new byte[]{-1})); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/TimedQuotaManagerTest.java b/tests/wifitests/src/com/android/server/wifi/util/TimedQuotaManagerTest.java deleted file mode 100644 index 4884ac927..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/TimedQuotaManagerTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2019 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.server.wifi.util; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.when; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.Clock; -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.time.Duration; - -/** - * Unit tests for {@link TimedQuotaManager}. - */ -@SmallTest -public class TimedQuotaManagerTest extends WifiBaseTest { - - private static final long DAY_MILLIS = Duration.ofDays(1).toMillis(); - - @Mock private Clock mClock; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mClock.getElapsedSinceBootMillis()).thenReturn(100000000L); - } - - /** - * Tests that {@link TimedQuotaManager#requestQuota()} returns true before the quota is exceeded - * and returns false after it is exceeded. Tests that upon entering a new time period, the quota - * is reset correctly. - */ - @Test - public void exhaustQuota_newDay_exhaustQuotaAgain() { - TimedQuotaManager qm = new TimedQuotaManager(mClock, 10, DAY_MILLIS); - - for (int i = 0; i < 10; i++) { - assertThat(qm.requestQuota()).isTrue(); - } - for (int i = 0; i < 10; i++) { - assertThat(qm.requestQuota()).isFalse(); - } - - long now = mClock.getElapsedSinceBootMillis(); - when(mClock.getElapsedSinceBootMillis()).thenReturn(now + DAY_MILLIS + 1000); - - for (int i = 0; i < 10; i++) { - assertThat(qm.requestQuota()).isTrue(); - } - for (int i = 0; i < 10; i++) { - assertThat(qm.requestQuota()).isFalse(); - } - } - - /** - * Tests that {@link TimedQuotaManager#requestQuota()} returns true before the quota is exceeded - * and returns false after it is exceeded. Tests when advancing time within the same time - * period, the quota is still enforced. - */ - @Test - public void exhaustQuota_sameDay_stillExhausted() { - TimedQuotaManager qm = new TimedQuotaManager(mClock, 10, DAY_MILLIS); - - for (int i = 0; i < 10; i++) { - assertThat(qm.requestQuota()).isTrue(); - } - for (int i = 0; i < 10; i++) { - assertThat(qm.requestQuota()).isFalse(); - } - - long now = mClock.getElapsedSinceBootMillis(); - when(mClock.getElapsedSinceBootMillis()).thenReturn(now + DAY_MILLIS - 1000); - for (int i = 0; i < 10; i++) { - assertThat(qm.requestQuota()).isFalse(); - } - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/WifiHandlerTest.java b/tests/wifitests/src/com/android/server/wifi/util/WifiHandlerTest.java deleted file mode 100644 index edbe39df3..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/WifiHandlerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import static org.mockito.Matchers.contains; -import static org.mockito.Mockito.verify; - -import android.os.Looper; -import android.os.Message; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.FakeWifiLog; -import com.android.server.wifi.WifiBaseTest; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -/** Unit tests for {@link WifiHandler}. */ -@RunWith(JUnit4.class) -@SmallTest -public class WifiHandlerTest extends WifiBaseTest { - private static final String TAG = "WifiHandlerTest"; - private WifiHandler mCodeUnderTest; - @Spy FakeWifiLog mWifiLog; - TestLooper mLooper; - - private class WifiHandlerTestClass extends WifiHandler { - WifiHandlerTestClass(String tag, Looper looper) { - super(tag, looper); - super.setWifiLog(mWifiLog); - } - } - - @Before public void setUp() { - MockitoAnnotations.initMocks(this); - mLooper = new TestLooper(); - mCodeUnderTest = new WifiHandlerTestClass(TAG, mLooper.getLooper()); - } - - @Test public void testHandleMessage() { - Message msg = Message.obtain(); - msg.what = 0; - msg.sendingUid = 0; - mCodeUnderTest.handleMessage(msg); - verify(mWifiLog).trace(contains("message")); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/WifiPermissionsUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/WifiPermissionsUtilTest.java deleted file mode 100644 index 799df547b..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/WifiPermissionsUtilTest.java +++ /dev/null @@ -1,1321 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -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.Manifest; -import android.app.AppOpsManager; -import android.app.admin.DevicePolicyManager; -import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.net.NetworkStack; -import android.os.Build; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; - -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.BinderUtil; -import com.android.server.wifi.FakeWifiLog; -import com.android.server.wifi.FrameworkFacade; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiInjector; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.util.HashMap; - -/** Unit tests for {@link WifiPermissionsUtil}. */ -@RunWith(JUnit4.class) -@SmallTest -public class WifiPermissionsUtilTest extends WifiBaseTest { - public static final String TAG = "WifiPermissionsUtilTest"; - - // Mock objects for testing - @Mock private WifiPermissionsWrapper mMockPermissionsWrapper; - @Mock private Context mMockContext; - @Mock private FrameworkFacade mMockFrameworkFacade; - @Mock private PackageManager mMockPkgMgr; - @Mock private ApplicationInfo mMockApplInfo; - @Mock private AppOpsManager mMockAppOps; - @Mock private UserManager mMockUserManager; - @Mock private ContentResolver mMockContentResolver; - @Mock private WifiInjector mWifiInjector; - @Mock private LocationManager mLocationManager; - @Mock private DevicePolicyManager mDevicePolicyManager; - @Spy private FakeWifiLog mWifiLog; - - private static final String TEST_WIFI_STACK_APK_NAME = "com.android.wifi"; - private static final String TEST_PACKAGE_NAME = "com.google.somePackage"; - private static final String TEST_FEATURE_ID = "com.google.someFeature"; - private static final String INVALID_PACKAGE = "BAD_PACKAGE"; - private static final int MANAGED_PROFILE_UID = 1100000; - private static final int OTHER_USER_UID = 1200000; - private static final boolean CHECK_LOCATION_SETTINGS = false; - private static final boolean IGNORE_LOCATION_SETTINGS = true; - private static final boolean DONT_HIDE_FROM_APP_OPS = false; - private static final boolean HIDE_FROM_APP_OPS = true; - - private final String mMacAddressPermission = "android.permission.PEERS_MAC_ADDRESS"; - private final String mInteractAcrossUsersFullPermission = - "android.permission.INTERACT_ACROSS_USERS_FULL"; - private final String mManifestStringCoarse = - Manifest.permission.ACCESS_COARSE_LOCATION; - private final String mManifestStringFine = - Manifest.permission.ACCESS_FINE_LOCATION; - private final String mManifestStringHardware = - Manifest.permission.LOCATION_HARDWARE; - - // Test variables - private int mWifiScanAllowApps; - private int mUid; - private int mCoarseLocationPermission; - private int mAllowCoarseLocationApps; - private int mFineLocationPermission; - private int mAllowFineLocationApps; - private int mHardwareLocationPermission; - private int mCurrentUser; - private boolean mIsLocationEnabled; - private boolean mThrowSecurityException; - private Answer<Integer> mReturnPermission; - private HashMap<String, Integer> mPermissionsList = new HashMap<String, Integer>(); - - /** - * Set up Mockito tests - */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - initTestVars(); - } - - private void setupTestCase() throws Exception { - setupMocks(); - setupMockInterface(); - } - - /** - * Verify we return true when the UID does have the override config permission - */ - @Test - public void testCheckConfigOverridePermissionApproved() throws Exception { - mUid = MANAGED_PROFILE_UID; // do not really care about this value - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - when(mMockPermissionsWrapper.getOverrideWifiConfigPermission(anyInt())) - .thenReturn(PackageManager.PERMISSION_GRANTED); - assertTrue(codeUnderTest.checkConfigOverridePermission(mUid)); - } - - /** - * Verify we return false when the UID does not have the override config permission. - */ - @Test - public void testCheckConfigOverridePermissionDenied() throws Exception { - mUid = OTHER_USER_UID; // do not really care about this value - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - when(mMockPermissionsWrapper.getOverrideWifiConfigPermission(anyInt())) - .thenReturn(PackageManager.PERMISSION_DENIED); - assertFalse(codeUnderTest.checkConfigOverridePermission(mUid)); - } - - /** - * Test case setting: Package is valid - * Location mode is enabled - * Caller can read peers mac address - * This App has permission to request WIFI_SCAN - * User is current - * Validate no Exceptions are thrown - * - User has all the permissions - */ - @Test - public void testCanReadPeersMacAddressCurrentUserAndAllPermissions() throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mCurrentUser = UserHandle.USER_SYSTEM; - mIsLocationEnabled = true; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Package is valid - * Location mode is enabled - * Caller can read peers mac address - * This App has permission to request WIFI_SCAN - * User profile is current - * Validate no Exceptions are thrown - * - User has all the permissions - */ - @Test - public void testCanReadPeersMacAddressCurrentProfileAndAllPermissions() throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mIsLocationEnabled = true; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Package is valid - * Caller can read peers mac address - * Validate that a SecurityException is thrown - * - This App doesn't have permission to request Wifi Scan - */ - @Test - public void testCannotAccessScanResult_AppNotAllowed() throws Exception { - mThrowSecurityException = false; - mPermissionsList.put(mMacAddressPermission, mUid); - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location mode is enabled - * Caller can read peers mac address - * This App has permission to request WIFI_SCAN - * User or profile is not current but the uid has - * permission to INTERACT_ACROSS_USERS_FULL - * Validate no Exceptions are thrown - * - User has all the permissions - */ - @Test - public void testenforceCanAccessScanResults_UserOrProfileNotCurrent() throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = true; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Package is valid - * Caller can read peers mac address - * This App has permission to request WIFI_SCAN - * User or profile is not Current - * Validate that a SecurityException is thrown - * - Calling uid doesn't have INTERACT_ACROSS_USERS_FULL permission - */ - @Test - public void testCannotAccessScanResults_NoInteractAcrossUsersFullPermission() throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case Setting: Package is valid - * Foreground - * This App has permission to request WIFI_SCAN - * User is current - * Validate that a SecurityException is thrown - app does not have location permission - */ - @Test - public void testLegacyForegroundAppWithOtherPermissionsDenied() throws Exception { - mThrowSecurityException = false; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - mCurrentUser = UserHandle.USER_SYSTEM; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case Setting: Package is valid - * Location Mode Enabled - * Coarse Location Access - * This App has permission to request WIFI_SCAN - * User profile is current - * Validate no Exceptions are thrown - has all permissions - */ - @Test - public void testLegacyAppHasLocationAndAllPermissions() throws Exception { - mThrowSecurityException = false; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; - mIsLocationEnabled = true; - mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Package is valid - * Location Mode Enabled - * Validate that a SecurityException is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is enabled but the uid - * - doesn't have Coarse Location Access - * - which implies No Location Permission - */ - @Test - public void testCannotAccessScanResults_NoCoarseLocationPermission() throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has location permission - * Validate an Exception is thrown - * - Uid is not an active network scorer - * - Uid doesn't have Coarse Location Access - * - which implies No Location Permission - */ - @Test - public void testCannotAccessScanResults_LocationModeDisabled() throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has location permisson - * Caller has CHANGE_WIFI_STATE - * Validate SecurityException is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - which implies no scan result access - */ - @Test - public void testEnforceCannotAccessScanResults_LocationModeDisabledHasChangeWifiState() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has location permisson - * Caller has ACCESS_WIFI_STATE - * Validate Exception is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - doesn't have Coarse Location Access - * - which implies no scan result access - */ - @Test - public void testEnforceCannotAccessScanResults_LocationModeDisabledHasAccessWifiState() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has location permisson - * Caller does not have NETWORK_SETTINGS - * Validate Exception is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - doesn't have Coarse Location Access - * - which implies no scan result access - */ - @Test - public void testEnforceCannotAccessScanResults_LocationModeDisabledHasNoNetworkSettings() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - when(mMockPermissionsWrapper.getUidPermission( - Manifest.permission.NETWORK_SETTINGS, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_DENIED); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has location permisson - * Caller has NETWORK_SETTINGS - * Validate Exception is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - doesn't have Coarse Location Access - * - which implies no scan result access - */ - @Test - public void testEnforceCanAccessScanResults_LocationModeDisabledHasNetworkSettings() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - when(mMockPermissionsWrapper.getUidPermission( - Manifest.permission.NETWORK_SETTINGS, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has location permisson - * Caller does not have NETWORK_SETUP_WIZARD - * Validate Exception is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - doesn't have Coarse Location Access - * - which implies no scan result access - */ - @Test - public void testEnforceCannotAccessScanResults_LocationModeDisabledHasNoNetworkSetupWizard() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - when(mMockPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_SETUP_WIZARD, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_DENIED); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has no location permisson - * Caller has NETWORK_SETUP_WIZARD - * Validate Exception is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - doesn't have Coarse Location Access - * - which implies no scan result access - */ - @Test - public void testEnforceCanAccessScanResults_LocationModeDisabledHasNetworkSetupWizard() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - when(mMockPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_SETUP_WIZARD, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has no location permisson - * Caller has NETWORK_MANAGED_PROVISIONING - * Validate Exception is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - doesn't have Coarse Location Access - * - which implies no scan result access - */ - @Test - public void testEnforceCanAccessScanResults_LocationModeDisabledHasNetworkManagedProvisioning() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - when(mMockPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has no location permisson - * Caller has NETWORK_STACK - * Validate Exception is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - doesn't have Coarse Location Access - * - which implies no scan result access - */ - @Test - public void testEnforceCanAccessScanResults_LocationModeDisabledHasNetworkStack() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - when(mMockPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_STACK, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Caller has no location permisson - * Caller has MAINLINE_NETWORK_STACK - * Validate Exception is thrown - * - Doesn't have Peer Mac Address read permission - * - Uid is not an active network scorer - * - Location Mode is disabled - * - doesn't have Coarse Location Access - * - which implies no scan result access - */ - @Test - public void testEnforceCanAccessScanResults_LocationModeDisabledHasMainlineNetworkStack() - throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mPermissionsList.put(mMacAddressPermission, mUid); - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - when(mMockPermissionsWrapper.getUidPermission( - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); - } - - /** - * Test case setting: Invalid Package - * Expect a securityException - */ - @Test - public void testInvalidPackage() throws Exception { - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, - null); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: legacy caller does have Coarse Location permission. - * A SecurityException should not be thrown. - */ - @Test - public void testEnforceCoarseLocationPermissionLegacyApp() throws Exception { - mThrowSecurityException = false; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; - mIsLocationEnabled = true; - mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid); - - // verify that checking FINE for legacy apps! - verify(mMockAppOps).noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), anyInt(), anyString(), - any(), any()); - } - - /** - * Test case setting: legacy caller does have Coarse Location permission. - * A SecurityException should not be thrown. - */ - @Test - public void testEnforceFineLocationPermissionNewQApp() throws Exception { - mThrowSecurityException = false; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid); - verify(mMockAppOps) - .noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), anyInt(), anyString(), any(), any()); - } - - /** - * Test case setting: legacy caller does have Coarse Location permission. - * A SecurityException should not be thrown. - */ - @Test - public void testEnforceFailureFineLocationPermissionNewQApp() throws Exception { - mThrowSecurityException = false; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q; - mIsLocationEnabled = true; - mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; - mFineLocationPermission = PackageManager.PERMISSION_DENIED; - mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; - mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid); - fail("Expected SecurityException not thrown"); - } catch (SecurityException e) { - // empty - } - verify(mMockAppOps, never()).noteOp(anyInt(), anyInt(), anyString()); - } - - /** - * Verifies the helper method exposed for checking NETWORK_SETUP_WIZARD permission. - */ - @Test - public void testCheckNetworkSetupWizard() throws Exception { - setupMocks(); - WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - - when(mMockPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_SETUP_WIZARD, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_DENIED); - assertFalse(wifiPermissionsUtil.checkNetworkSetupWizardPermission(MANAGED_PROFILE_UID)); - - when(mMockPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_SETUP_WIZARD, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - assertTrue(wifiPermissionsUtil.checkNetworkSetupWizardPermission(MANAGED_PROFILE_UID)); - } - - /** - * Verifies the helper method exposed for checking NETWORK_MANAGED_PROVISIONING permission. - */ - @Test - public void testCheckNetworkManagedProvisioning() throws Exception { - setupMocks(); - WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - - when(mMockPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_DENIED); - assertFalse(wifiPermissionsUtil.checkNetworkManagedProvisioningPermission( - MANAGED_PROFILE_UID)); - - when(mMockPermissionsWrapper.getUidPermission( - android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - assertTrue(wifiPermissionsUtil.checkNetworkManagedProvisioningPermission( - MANAGED_PROFILE_UID)); - } - - /** - * Verifies the helper method exposed for checking SYSTERM_ALERT_WINDOW permission. - */ - @Test - public void testCheckSystemAlertWindowPermissionWithModeDefaultAppOps() throws Exception { - setupMocks(); - WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - - when(mMockAppOps.noteOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID, - TEST_PACKAGE_NAME, null, null)) - .thenReturn(AppOpsManager.MODE_DEFAULT); - when(mMockPermissionsWrapper.getUidPermission( - Manifest.permission.SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_DENIED); - assertFalse(wifiPermissionsUtil.checkSystemAlertWindowPermission( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - - when(mMockAppOps.noteOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID, - TEST_PACKAGE_NAME, null, null)) - .thenReturn(AppOpsManager.MODE_DEFAULT); - when(mMockPermissionsWrapper.getUidPermission( - Manifest.permission.SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - assertTrue(wifiPermissionsUtil.checkSystemAlertWindowPermission( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - } - - /** - * Verifies the helper method exposed for checking SYSTERM_ALERT_WINDOW permission. - */ - @Test - public void testCheckSystemAlertWindowPermissionWithModeAllowedAppOps() throws Exception { - setupMocks(); - WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - - when(mMockAppOps.noteOp( - AppOpsManager.OP_SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)) - .thenReturn(AppOpsManager.MODE_ALLOWED); - assertTrue(wifiPermissionsUtil.checkSystemAlertWindowPermission( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - } - - /** - * Verifies the helper method exposed for checking if the app is a DeviceOwner. - */ - @Test - public void testIsDeviceOwnerApp() throws Exception { - setupMocks(); - WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - - when(mMockContext.getSystemService(DevicePolicyManager.class)) - .thenReturn(mDevicePolicyManager); - - when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) - .thenReturn(new ComponentName(TEST_PACKAGE_NAME, new String())); - when(mDevicePolicyManager.getDeviceOwnerUser()) - .thenReturn(UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); - assertTrue(wifiPermissionsUtil.isDeviceOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - - - // userId does not match - when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) - .thenReturn(new ComponentName(TEST_PACKAGE_NAME, new String())); - when(mDevicePolicyManager.getDeviceOwnerUser()) - .thenReturn(UserHandle.getUserHandleForUid(OTHER_USER_UID)); - assertFalse(wifiPermissionsUtil.isDeviceOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - - // Package Name does not match - when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) - .thenReturn(new ComponentName(INVALID_PACKAGE, new String())); - when(mDevicePolicyManager.getDeviceOwnerUser()) - .thenReturn(UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); - assertFalse(wifiPermissionsUtil.isDeviceOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - - // No device owner. - when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) - .thenReturn(null); - assertFalse(wifiPermissionsUtil.isDeviceOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - - // DevicePolicyManager does not exist. - when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) - .thenReturn(null); - assertFalse(wifiPermissionsUtil.isDeviceOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - } - - /** - * Verifies the helper method exposed for checking if the app is a ProfileOwner. - */ - @Test - public void testIsProfileOwnerApp() throws Exception { - setupMocks(); - WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - - when(mMockContext.createPackageContextAsUser( - TEST_WIFI_STACK_APK_NAME, 0, UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID))) - .thenReturn(mMockContext); - when(mMockContext.getSystemService(DevicePolicyManager.class)) - .thenReturn(mDevicePolicyManager); - - when(mDevicePolicyManager.isProfileOwnerApp(TEST_PACKAGE_NAME)) - .thenReturn(true); - assertTrue(wifiPermissionsUtil.isProfileOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - - when(mDevicePolicyManager.isProfileOwnerApp(TEST_PACKAGE_NAME)) - .thenReturn(false); - assertFalse(wifiPermissionsUtil.isProfileOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - - // DevicePolicyManager does not exist. - when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) - .thenReturn(null); - assertFalse(wifiPermissionsUtil.isProfileOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - - // Invalid package name. - doThrow(new PackageManager.NameNotFoundException()) - .when(mMockContext).createPackageContextAsUser( - TEST_WIFI_STACK_APK_NAME, 0, - UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); - assertFalse(wifiPermissionsUtil.isProfileOwner( - MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); - } - - /** - * Test case setting: caller does not have Location permission. - * Expect a SecurityException - */ - @Test(expected = SecurityException.class) - public void testEnforceLocationPermissionExpectSecurityException() throws Exception { - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid); - } - - /** - * Test case setting: Package is valid - * Location Mode Enabled - * Fine Location Access - * Location hardware Access - * This App has permission to request WIFI_SCAN - * Validate no Exceptions are thrown - has all permissions - */ - @Test - public void testCanAccessScanResultsForWifiScanner() throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, TEST_FEATURE_ID, - mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); - - verify(mMockAppOps, never()) - .unsafeCheckOp(AppOpsManager.OPSTR_FINE_LOCATION, mUid, TEST_PACKAGE_NAME); - verify(mMockAppOps).noteOp(AppOpsManager.OPSTR_FINE_LOCATION, mUid, TEST_PACKAGE_NAME, - TEST_FEATURE_ID, null); - } - - /** - * Test case setting: Package is valid - * Location Mode Enabled - * Fine Location Access - * Location hardware Access - * This App has permission to request WIFI_SCAN - * Validate no Exceptions are thrown - has all permissions & don't note in app-ops. - */ - @Test - public void testCannotAccessScanResultsForWifiScanner_HideFromAppOps() - throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, TEST_FEATURE_ID, - mUid, IGNORE_LOCATION_SETTINGS, HIDE_FROM_APP_OPS); - - verify(mMockAppOps).unsafeCheckOp(AppOpsManager.OPSTR_FINE_LOCATION, mUid, - TEST_PACKAGE_NAME); - verify(mMockAppOps, never()).noteOp( - AppOpsManager.OPSTR_FINE_LOCATION, mUid, TEST_PACKAGE_NAME, null, null); - } - - - /** - * Test case setting: Package is valid - * Location Mode Enabled - * Location hardware Access - * This App has permission to request WIFI_SCAN - * Validate that a SecurityException is thrown - * - Doesn't have fine location permission. - */ - @Test - public void testCannotAccessScanResultsForWifiScanner_NoFineLocationPermission() - throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_DENIED; - mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, - TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Enabled - * Fine Location Access - * This App has permission to request WIFI_SCAN - * Validate that a SecurityException is thrown - * - Doesn't have fine location app-ops. - */ - @Test - public void testCannotAccessScanResultsForWifiScanner_NoFineLocationAppOps() throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_IGNORED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, - TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Enabled - * Location hardware Access - * This App has permission to request WIFI_SCAN - * Validate that a SecurityException is thrown - * - Doesn't have hardware location permission. - */ - @Test - public void testCannotAccessScanResultsForWifiScanner_NoHardwareLocationPermission() - throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mHardwareLocationPermission = PackageManager.PERMISSION_DENIED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, - TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Enabled - * Fine Location Access - * Location hardware Access - * Validate that a SecurityException is thrown - * - This App does not have permission to request WIFI_SCAN. - */ - @Test - public void testCannotAccessScanResultsForWifiScanner_NoWifiScanAppOps() throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_IGNORED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, - TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Fine Location Access - * Location hardware Access - * This App has permission to request WIFI_SCAN - * Validate an Exception is thrown - * - Location is not enabled. - */ - @Test - public void testCannotAccessScanResultsForWifiScanner_LocationModeDisabled() throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = false; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, - TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Test case setting: Package is valid - * Location Mode Disabled - * Fine Location Access - * Location hardware Access - * This App has permission to request WIFI_SCAN - * Validate no Exceptions are thrown - has all permissions & ignores location settings. - */ - @Test - public void testCannotAccessScanResultsForWifiScanner_IgnoreLocationSettings() - throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = false; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, TEST_FEATURE_ID, - mUid, IGNORE_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); - } - - /** - * Test case setting: Location Mode Enabled - * Fine Location Access - * Location hardware Access - * This App has permission to request WIFI_SCAN - * Validate an Exception is thrown - * - Invalid package name. - */ - @Test - public void testCannotAccessScanResultsForWifiScanner_InvalidPackage() throws Exception { - mThrowSecurityException = true; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - try { - codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, - TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); - fail("Expected SecurityException is not thrown"); - } catch (SecurityException e) { - } - } - - /** - * Verify that we handle failures when trying to fetch location mode using LocationManager API. - * We should use the legacy setting to read the value if we encounter any failure. - */ - @Test - public void testIsLocationEnabledFallbackToLegacySetting() throws Exception { - mUid = OTHER_USER_UID; // do not really care about this value - setupTestCase(); - WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, - mMockContext, mMockUserManager, mWifiInjector); - doThrow(new RuntimeException()).when(mLocationManager).isLocationEnabledForUser(any()); - - when(mMockFrameworkFacade.getIntegerSetting( - any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt())) - .thenReturn(Settings.Secure.LOCATION_MODE_OFF); - assertFalse(codeUnderTest.isLocationModeEnabled()); - - when(mMockFrameworkFacade.getIntegerSetting( - any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt())) - .thenReturn(Settings.Secure.LOCATION_MODE_ON); - assertTrue(codeUnderTest.isLocationModeEnabled()); - - verify(mMockFrameworkFacade, times(2)).getIntegerSetting( - any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt()); - } - - private Answer<Integer> createPermissionAnswer() { - return new Answer<Integer>() { - @Override - public Integer answer(InvocationOnMock invocation) { - int myUid = (int) invocation.getArguments()[1]; - String myPermission = (String) invocation.getArguments()[0]; - mPermissionsList.get(myPermission); - if (mPermissionsList.containsKey(myPermission)) { - int uid = mPermissionsList.get(myPermission); - if (myUid == uid) { - return PackageManager.PERMISSION_GRANTED; - } - } - return PackageManager.PERMISSION_DENIED; - } - }; - } - - private void setupMocks() throws Exception { - when(mMockPkgMgr.getApplicationInfoAsUser(eq(TEST_PACKAGE_NAME), eq(0), any())) - .thenReturn(mMockApplInfo); - when(mMockContext.getPackageManager()).thenReturn(mMockPkgMgr); - when(mMockAppOps.noteOp(AppOpsManager.OPSTR_WIFI_SCAN, mUid, TEST_PACKAGE_NAME, - TEST_FEATURE_ID, null)).thenReturn(mWifiScanAllowApps); - when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_COARSE_LOCATION), eq(mUid), - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), nullable(String.class))) - .thenReturn(mAllowCoarseLocationApps); - when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), eq(mUid), - eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), nullable(String.class))) - .thenReturn(mAllowFineLocationApps); - when(mMockAppOps.unsafeCheckOp(AppOpsManager.OPSTR_FINE_LOCATION, mUid, TEST_PACKAGE_NAME)) - .thenReturn(mAllowFineLocationApps); - if (mThrowSecurityException) { - doThrow(new SecurityException("Package " + TEST_PACKAGE_NAME + " doesn't belong" - + " to application bound to user " + mUid)) - .when(mMockAppOps).checkPackage(mUid, TEST_PACKAGE_NAME); - } - when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)) - .thenReturn(mMockAppOps); - when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); - when(mMockContext.getSystemService(Context.USER_SERVICE)) - .thenReturn(mMockUserManager); - when(mWifiInjector.makeLog(anyString())).thenReturn(mWifiLog); - when(mWifiInjector.getFrameworkFacade()).thenReturn(mMockFrameworkFacade); - when(mMockContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); - when(mMockContext.getPackageName()).thenReturn(TEST_WIFI_STACK_APK_NAME); - } - - private void initTestVars() { - mPermissionsList.clear(); - mReturnPermission = createPermissionAnswer(); - mWifiScanAllowApps = AppOpsManager.MODE_ERRORED; - mUid = OTHER_USER_UID; - mThrowSecurityException = true; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.M; - mIsLocationEnabled = false; - mCurrentUser = UserHandle.USER_SYSTEM; - mCoarseLocationPermission = PackageManager.PERMISSION_DENIED; - mFineLocationPermission = PackageManager.PERMISSION_DENIED; - mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED; - mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; - } - - private void setupMockInterface() { - BinderUtil.setUid(mUid); - doAnswer(mReturnPermission).when(mMockPermissionsWrapper).getUidPermission( - anyString(), anyInt()); - doAnswer(mReturnPermission).when(mMockPermissionsWrapper).getUidPermission( - anyString(), anyInt()); - when(mMockUserManager.isSameProfileGroup(UserHandle.SYSTEM, - UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID))) - .thenReturn(true); - when(mMockPermissionsWrapper.getCurrentUser()).thenReturn(mCurrentUser); - when(mMockPermissionsWrapper.getUidPermission(mManifestStringCoarse, mUid)) - .thenReturn(mCoarseLocationPermission); - when(mMockPermissionsWrapper.getUidPermission(mManifestStringFine, mUid)) - .thenReturn(mFineLocationPermission); - when(mMockPermissionsWrapper.getUidPermission(mManifestStringHardware, mUid)) - .thenReturn(mHardwareLocationPermission); - when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java deleted file mode 100644 index 8f8c01de2..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Copyright (C) 2016 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.server.wifi.util; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.net.IpConfiguration; -import android.net.util.MacAddressUtils; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; -import android.net.wifi.WifiEnterpriseConfig; -import android.util.Pair; -import android.util.Xml; - -import androidx.test.filters.SmallTest; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.wifi.WifiBaseTest; -import com.android.server.wifi.WifiConfigurationTestUtil; -import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil; -import com.android.server.wifi.util.XmlUtil.NetworkSelectionStatusXmlUtil; -import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; -import com.android.server.wifi.util.XmlUtil.WifiEnterpriseConfigXmlUtil; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; - -/** - * Unit tests for {@link com.android.server.wifi.util.XmlUtil}. - */ -@SmallTest -public class XmlUtilTest extends WifiBaseTest { - public static final String XML_STRING_EAP_METHOD_REPLACE_FORMAT = - "<int name=\"EapMethod\" value=\"%d\" />"; - - private static final String TEST_PACKAGE_NAME = "XmlUtilPackage"; - private static final String TEST_STATIC_IP_GATEWAY_ADDRESS = "192.168.48.1"; - private static final String TEST_DUMMY_CONFIG_KEY = "XmlUtilDummyConfigKey"; - private static final String TEST_IDENTITY = "XmlUtilTestIdentity"; - private static final String TEST_ANON_IDENTITY = "XmlUtilTestAnonIdentity"; - private static final String TEST_PASSWORD = "XmlUtilTestPassword"; - private static final String TEST_CLIENT_CERT = "XmlUtilTestClientCert"; - private static final String TEST_CA_CERT = "XmlUtilTestCaCert"; - private static final String TEST_SUBJECT_MATCH = "XmlUtilTestSubjectMatch"; - private static final String TEST_ENGINE = "XmlUtilTestEngine"; - private static final String TEST_ENGINE_ID = "XmlUtilTestEngineId"; - private static final String TEST_PRIVATE_KEY_ID = "XmlUtilTestPrivateKeyId"; - private static final String TEST_ALTSUBJECT_MATCH = "XmlUtilTestAltSubjectMatch"; - private static final String TEST_DOM_SUFFIX_MATCH = "XmlUtilTestDomSuffixMatch"; - private static final String TEST_CA_PATH = "XmlUtilTestCaPath"; - private static final int TEST_EAP_METHOD = WifiEnterpriseConfig.Eap.PEAP; - private static final int TEST_PHASE2_METHOD = WifiEnterpriseConfig.Phase2.MSCHAPV2; - private final String mXmlDocHeader = "XmlUtilTest"; - - private WifiConfigStoreEncryptionUtil mWifiConfigStoreEncryptionUtil = null; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - - /** - * Verify that a open WifiConfiguration is serialized & deserialized correctly. - */ - @Test - public void testOpenWifiConfigurationSerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeWifiConfiguration(WifiConfigurationTestUtil.createOpenNetwork()); - } - - /** - * Verify that a open hidden WifiConfiguration is serialized & deserialized correctly. - */ - @Test - public void testOpenHiddenWifiConfigurationSerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeWifiConfiguration(WifiConfigurationTestUtil.createOpenHiddenNetwork()); - } - - /** - * Verify that a psk WifiConfiguration is serialized & deserialized correctly. - */ - @Test - public void testPskWifiConfigurationSerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeWifiConfiguration(WifiConfigurationTestUtil.createPskNetwork()); - } - - /** - * Verify that a psk WifiConfiguration is serialized & deserialized correctly. - */ - @Test - public void testPskWifiConfigurationSerializeDeserializeWithEncryption() - throws IOException, XmlPullParserException { - mWifiConfigStoreEncryptionUtil = mock(WifiConfigStoreEncryptionUtil.class); - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - EncryptedData encryptedData = new EncryptedData(new byte[0], new byte[0]); - when(mWifiConfigStoreEncryptionUtil.encrypt(pskNetwork.preSharedKey.getBytes())) - .thenReturn(encryptedData); - when(mWifiConfigStoreEncryptionUtil.decrypt(encryptedData)) - .thenReturn(pskNetwork.preSharedKey.getBytes()); - serializeDeserializeWifiConfiguration(pskNetwork); - } - - /** - * Verify that a psk hidden WifiConfiguration is serialized & deserialized correctly. - */ - @Test - public void testPskHiddenWifiConfigurationSerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeWifiConfiguration(WifiConfigurationTestUtil.createPskHiddenNetwork()); - } - - /** - * Verify that a WEP WifiConfiguration is serialized & deserialized correctly. - */ - @Test - public void testWepWifiConfigurationSerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeWifiConfiguration(WifiConfigurationTestUtil.createWepNetwork()); - } - - /** - * Verify that a EAP WifiConfiguration is serialized & deserialized correctly only for - * ConfigStore. - */ - @Test - public void testEapWifiConfigurationSerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeWifiConfigurationForConfigStore( - WifiConfigurationTestUtil.createEapNetwork()); - } - - /** - * Verify that a static IpConfiguration with PAC proxy is serialized & deserialized correctly. - */ - @Test - public void testStaticIpConfigurationWithPacProxySerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeIpConfiguration( - WifiConfigurationTestUtil.createStaticIpConfigurationWithPacProxy()); - } - - /** - * Verify that a static IpConfiguration with static proxy is serialized & deserialized correctly. - */ - @Test - public void testStaticIpConfigurationWithStaticProxySerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeIpConfiguration( - WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy()); - } - - /** - * Verify that a partial static IpConfiguration with PAC proxy is serialized & deserialized - * correctly. - */ - @Test - public void testPartialStaticIpConfigurationWithPacProxySerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeIpConfiguration( - WifiConfigurationTestUtil.createPartialStaticIpConfigurationWithPacProxy()); - } - - /** - * Verify that a DHCP IpConfiguration with PAC proxy is serialized & deserialized - * correctly. - */ - @Test - public void testDHCPIpConfigurationWithPacProxySerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy()); - } - - /** - * Verify that a DHCP IpConfiguration with Static proxy is serialized & deserialized - * correctly. - */ - @Test - public void testDHCPIpConfigurationWithStaticProxySerializeDeserialize() - throws IOException, XmlPullParserException { - serializeDeserializeIpConfiguration( - WifiConfigurationTestUtil.createDHCPIpConfigurationWithStaticProxy()); - } - - /** - * Verify that a EAP WifiConfiguration is serialized & deserialized correctly for config store. - * This basically exercises all the elements being serialized in config store. - */ - @Test - public void testEapWifiConfigurationSerializeDeserializeForConfigStore() - throws IOException, XmlPullParserException { - WifiConfiguration configuration = WifiConfigurationTestUtil.createEapNetwork(); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); - configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); - configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); - configuration.status = WifiConfiguration.Status.DISABLED; - configuration.linkedConfigurations = new HashMap<>(); - configuration.linkedConfigurations.put(TEST_DUMMY_CONFIG_KEY, Integer.valueOf(1)); - configuration.defaultGwMacAddress = TEST_STATIC_IP_GATEWAY_ADDRESS; - configuration.requirePmf = true; - configuration.validatedInternetAccess = true; - configuration.noInternetAccessExpected = true; - configuration.meteredHint = true; - configuration.useExternalScores = true; - configuration.numAssociation = 5; - configuration.lastUpdateUid = configuration.lastConnectUid = configuration.creatorUid; - configuration.creatorName = configuration.lastUpdateName = TEST_PACKAGE_NAME; - configuration.setRandomizedMacAddress(MacAddressUtils.createRandomUnicastAddress()); - configuration.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT; - - serializeDeserializeWifiConfigurationForConfigStore(configuration); - } - - /** - * Verify that a WifiConfiguration with status as CURRENT when serializing - * is deserialized as ENABLED. - */ - @Test - public void testCurrentStatusConfigurationSerializeDeserializeForConfigStore() - throws IOException, XmlPullParserException { - WifiConfiguration configuration = WifiConfigurationTestUtil.createEapNetwork(); - configuration.status = WifiConfiguration.Status.CURRENT; - byte[] xmlData = serializeWifiConfigurationForConfigStore(configuration); - Pair<String, WifiConfiguration> deserializedConfiguration = - deserializeWifiConfiguration(xmlData); - assertEquals(WifiConfiguration.Status.ENABLED, deserializedConfiguration.second.status); - } - - /** - * Verify that an enabled network selection status object is serialized & deserialized - * correctly. - */ - @Test - public void testEnabledNetworkSelectionStatusSerializeDeserialize() - throws IOException, XmlPullParserException { - NetworkSelectionStatus status = new NetworkSelectionStatus(); - status.setNetworkSelectionStatus(NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); - status.setNetworkSelectionDisableReason(NetworkSelectionStatus.DISABLED_NONE); - status.setConnectChoice(TEST_DUMMY_CONFIG_KEY); - status.setHasEverConnected(true); - serializeDeserializeNetworkSelectionStatus(status); - } - - /** - * Verify that a temporarily disabled network selection status object is serialized & - * deserialized correctly. - */ - @Test - public void testTemporarilyDisabledNetworkSelectionStatusSerializeDeserialize() - throws IOException, XmlPullParserException { - NetworkSelectionStatus status = new NetworkSelectionStatus(); - status.setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - status.setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION); - serializeDeserializeNetworkSelectionStatus(status); - } - - /** - * Verify that a network selection status deprecation is handled correctly during restore - * of data after upgrade. - * This test tries to simulate the scenario where we have a - * {@link NetworkSelectionStatus#getNetworkStatusString()} string stored - * in the XML file from a previous release which has now been deprecated. The network should - * be restored as enabled. - */ - @Test - public void testDeprecatedNetworkSelectionStatusDeserialize() - throws IOException, XmlPullParserException { - // Create a dummy network selection status. - NetworkSelectionStatus status = new NetworkSelectionStatus(); - status.setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - status.setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_DHCP_FAILURE); - status.setConnectChoice(TEST_DUMMY_CONFIG_KEY); - status.setHasEverConnected(true); - - // Serialize this to XML string. - byte[] xmlData = serializeNetworkSelectionStatus(status); - - // Now modify the status string with some invalid string in XML data.. - String xmlString = new String(xmlData); - String deprecatedXmlString = - xmlString.replaceAll( - status.getNetworkStatusString(), "NETWORK_SELECTION_DEPRECATED"); - // Ensure that the modification did take effect. - assertFalse(xmlString.equals(deprecatedXmlString)); - - // Now Deserialize the modified XML data. - byte[] deprecatedXmlData = xmlString.getBytes(); - NetworkSelectionStatus retrievedStatus = - deserializeNetworkSelectionStatus(deprecatedXmlData); - - // The status retrieved should have reset both the |Status| & |DisableReason| fields after - // deserialization, but should have restored all the other fields correctly. - NetworkSelectionStatus expectedStatus = new NetworkSelectionStatus(); - expectedStatus.copy(status); - expectedStatus.setNetworkSelectionStatus(NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); - expectedStatus.setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_NONE); - - WifiConfigurationTestUtil.assertNetworkSelectionStatusEqualForConfigStore( - expectedStatus, retrievedStatus); - } - - /** - * Verify that a network selection disable reason deprecation is handled correctly during - * restore of data after upgrade. - * This test tries to simulate the scenario where we have a - * {@link NetworkSelectionStatus#getNetworkSelectionDisableReasonString()} ()} string stored - * in the XML file from a previous release which has now been deprecated. The network should - * be restored as enabled. - */ - @Test - public void testDeprecatedNetworkSelectionDisableReasonDeserialize() - throws IOException, XmlPullParserException { - // Create a dummy network selection status. - NetworkSelectionStatus status = new NetworkSelectionStatus(); - status.setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - status.setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_DHCP_FAILURE); - status.setConnectChoice(TEST_DUMMY_CONFIG_KEY); - status.setHasEverConnected(true); - - // Serialize this to XML string. - byte[] xmlData = serializeNetworkSelectionStatus(status); - - // Now modify the disable reason string with some invalid string in XML data. - String xmlString = new String(xmlData); - String deprecatedXmlString = - xmlString.replaceAll(status.getNetworkSelectionDisableReasonString(), - "DISABLED_DEPRECATED"); - // Ensure that the modification did take effect. - assertFalse(xmlString.equals(deprecatedXmlString)); - - // Now Deserialize the modified XML data. - byte[] deprecatedXmlData = xmlString.getBytes(); - NetworkSelectionStatus retrievedStatus = - deserializeNetworkSelectionStatus(deprecatedXmlData); - - // The status retrieved should have reset both the |Status| & |DisableReason| fields after - // deserialization, but should have restored all the other fields correctly. - NetworkSelectionStatus expectedStatus = new NetworkSelectionStatus(); - expectedStatus.copy(status); - expectedStatus.setNetworkSelectionStatus(NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); - expectedStatus.setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_NONE); - - WifiConfigurationTestUtil.assertNetworkSelectionStatusEqualForConfigStore( - expectedStatus, retrievedStatus); - } - - /** - * Verify that a WifiEnterpriseConfig object is serialized & deserialized correctly. - */ - @Test - public void testWifiEnterpriseConfigSerializeDeserialize() - throws IOException, XmlPullParserException { - WifiEnterpriseConfig config = new WifiEnterpriseConfig(); - config.setFieldValue(WifiEnterpriseConfig.IDENTITY_KEY, TEST_IDENTITY); - config.setFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY, TEST_ANON_IDENTITY); - config.setFieldValue(WifiEnterpriseConfig.PASSWORD_KEY, TEST_PASSWORD); - config.setFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY, TEST_CLIENT_CERT); - config.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, TEST_CA_CERT); - config.setFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY, TEST_SUBJECT_MATCH); - config.setFieldValue(WifiEnterpriseConfig.ENGINE_KEY, TEST_ENGINE); - config.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, TEST_ENGINE_ID); - config.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, TEST_PRIVATE_KEY_ID); - config.setFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, TEST_ALTSUBJECT_MATCH); - config.setFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, TEST_DOM_SUFFIX_MATCH); - config.setFieldValue(WifiEnterpriseConfig.CA_PATH_KEY, TEST_CA_PATH); - config.setEapMethod(TEST_EAP_METHOD); - config.setPhase2Method(TEST_PHASE2_METHOD); - serializeDeserializeWifiEnterpriseConfig(config); - } - - /** - * Verify that a WifiEnterpriseConfig object is serialized & deserialized correctly. - */ - @Test - public void testWifiEnterpriseConfigSerializeDeserializeWithEncryption() - throws IOException, XmlPullParserException { - WifiEnterpriseConfig config = new WifiEnterpriseConfig(); - config.setFieldValue(WifiEnterpriseConfig.IDENTITY_KEY, TEST_IDENTITY); - config.setFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY, TEST_ANON_IDENTITY); - config.setFieldValue(WifiEnterpriseConfig.PASSWORD_KEY, TEST_PASSWORD); - config.setFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY, TEST_CLIENT_CERT); - config.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, TEST_CA_CERT); - config.setFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY, TEST_SUBJECT_MATCH); - config.setFieldValue(WifiEnterpriseConfig.ENGINE_KEY, TEST_ENGINE); - config.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, TEST_ENGINE_ID); - config.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, TEST_PRIVATE_KEY_ID); - config.setFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, TEST_ALTSUBJECT_MATCH); - config.setFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, TEST_DOM_SUFFIX_MATCH); - config.setFieldValue(WifiEnterpriseConfig.CA_PATH_KEY, TEST_CA_PATH); - config.setEapMethod(TEST_EAP_METHOD); - config.setPhase2Method(TEST_PHASE2_METHOD); - - mWifiConfigStoreEncryptionUtil = mock(WifiConfigStoreEncryptionUtil.class); - EncryptedData encryptedData = new EncryptedData(new byte[0], new byte[0]); - when(mWifiConfigStoreEncryptionUtil.encrypt(TEST_PASSWORD.getBytes())) - .thenReturn(encryptedData); - when(mWifiConfigStoreEncryptionUtil.decrypt(encryptedData)) - .thenReturn(TEST_PASSWORD.getBytes()); - serializeDeserializeWifiEnterpriseConfig(config); - } - - /** - * Verify that an illegal argument exception is thrown when trying to parse out a corrupted - * WifiEnterpriseConfig. - * - * @throws Exception - */ - @Test(expected = IllegalArgumentException.class) - public void testWifiEnterpriseConfigSerializeDeserializeThrowsIllegalArgException() - throws Exception { - WifiEnterpriseConfig config = new WifiEnterpriseConfig(); - config.setFieldValue(WifiEnterpriseConfig.IDENTITY_KEY, TEST_IDENTITY); - config.setFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY, TEST_ANON_IDENTITY); - config.setFieldValue(WifiEnterpriseConfig.PASSWORD_KEY, TEST_PASSWORD); - config.setFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY, TEST_CLIENT_CERT); - config.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, TEST_CA_CERT); - config.setFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY, TEST_SUBJECT_MATCH); - config.setFieldValue(WifiEnterpriseConfig.ENGINE_KEY, TEST_ENGINE); - config.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, TEST_ENGINE_ID); - config.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, TEST_PRIVATE_KEY_ID); - config.setFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, TEST_ALTSUBJECT_MATCH); - config.setFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, TEST_DOM_SUFFIX_MATCH); - config.setFieldValue(WifiEnterpriseConfig.CA_PATH_KEY, TEST_CA_PATH); - config.setEapMethod(TEST_EAP_METHOD); - config.setPhase2Method(TEST_PHASE2_METHOD); - String xmlString = new String(serializeWifiEnterpriseConfig(config)); - // Manipulate the XML data to set the EAP method to None, this should raise an Illegal - // argument exception in WifiEnterpriseConfig.setEapMethod(). - xmlString = xmlString.replaceAll( - String.format(XML_STRING_EAP_METHOD_REPLACE_FORMAT, TEST_EAP_METHOD), - String.format(XML_STRING_EAP_METHOD_REPLACE_FORMAT, WifiEnterpriseConfig.Eap.NONE)); - deserializeWifiEnterpriseConfig(xmlString.getBytes(StandardCharsets.UTF_8)); - } - - /** - * Verify that WifiConfiguration representation of a legacy Passpoint configuration is - * serialized & deserialized correctly. - * - *@throws Exception - */ - @Test - public void testLegacyPasspointConfigSerializeDeserialize() throws Exception { - WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork(); - config.isLegacyPasspointConfig = true; - config.setPasspointUniqueId(null); // Did not exist for legacy Passpoint - config.roamingConsortiumIds = new long[] {0x12345678}; - config.enterpriseConfig.setPlmn("1234"); - config.enterpriseConfig.setRealm("test.com"); - serializeDeserializeWifiConfigurationForConfigStore(config); - } - - /** - * Verify that when the macRandomizationSetting field is not found in the XML file, - * macRandomizationSetting is defaulted to RANDOMIZATION_NONE. - * @throws IOException - * @throws XmlPullParserException - */ - @Test - public void testMacRandomizationSettingDefaultToRandomizationNone() - throws IOException, XmlPullParserException { - // First generate XML data that only has the header filled in - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - XmlUtil.writeDocumentStart(out, mXmlDocHeader); - XmlUtil.writeDocumentEnd(out, mXmlDocHeader); - - // Deserialize the data - Pair<String, WifiConfiguration> retrieved = - deserializeWifiConfiguration(outputStream.toByteArray()); - - // Verify that macRandomizationSetting is set to |RANDOMIZATION_NONE| - assertEquals(WifiConfiguration.RANDOMIZATION_NONE, - retrieved.second.macRandomizationSetting); - } - - private byte[] serializeWifiConfigurationForBackup(WifiConfiguration configuration) - throws IOException, XmlPullParserException { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - XmlUtil.writeDocumentStart(out, mXmlDocHeader); - WifiConfigurationXmlUtil.writeToXmlForBackup(out, configuration); - XmlUtil.writeDocumentEnd(out, mXmlDocHeader); - return outputStream.toByteArray(); - } - - private byte[] serializeWifiConfigurationForConfigStore( - WifiConfiguration configuration) - throws IOException, XmlPullParserException { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - XmlUtil.writeDocumentStart(out, mXmlDocHeader); - WifiConfigurationXmlUtil.writeToXmlForConfigStore( - out, configuration, mWifiConfigStoreEncryptionUtil); - XmlUtil.writeDocumentEnd(out, mXmlDocHeader); - return outputStream.toByteArray(); - } - - private Pair<String, WifiConfiguration> deserializeWifiConfiguration(byte[] data) - throws IOException, XmlPullParserException { - // Deserialize the configuration object. - final XmlPullParser in = Xml.newPullParser(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - XmlUtil.gotoDocumentStart(in, mXmlDocHeader); - return WifiConfigurationXmlUtil.parseFromXml( - in, in.getDepth(), - mWifiConfigStoreEncryptionUtil != null, - mWifiConfigStoreEncryptionUtil); - } - - /** - * This helper method tests the serialization for backup/restore. - */ - private void serializeDeserializeWifiConfigurationForBackupRestore( - WifiConfiguration configuration) - throws IOException, XmlPullParserException { - Pair<String, WifiConfiguration> retrieved; - // Test serialization/deserialization for config store. - retrieved = - deserializeWifiConfiguration( - serializeWifiConfigurationForBackup(configuration)); - assertEquals(retrieved.first, retrieved.second.getKey()); - WifiConfigurationTestUtil.assertConfigurationEqualForBackup( - configuration, retrieved.second); - } - - /** - * This helper method tests the serialization for config store. - */ - private void serializeDeserializeWifiConfigurationForConfigStore( - WifiConfiguration configuration) - throws IOException, XmlPullParserException { - // Reset enterprise config because this needs to be serialized/deserialized separately. - configuration.enterpriseConfig = new WifiEnterpriseConfig(); - Pair<String, WifiConfiguration> retrieved; - // Test serialization/deserialization for config store. - retrieved = - deserializeWifiConfiguration( - serializeWifiConfigurationForConfigStore(configuration)); - assertEquals(retrieved.first, retrieved.second.getKey()); - WifiConfigurationTestUtil.assertConfigurationEqualForConfigStore( - configuration, retrieved.second); - } - - /** - * This helper method tests both the serialization for backup/restore and config store. - */ - private void serializeDeserializeWifiConfiguration(WifiConfiguration configuration) - throws IOException, XmlPullParserException { - Pair<String, WifiConfiguration> retrieved; - // Test serialization/deserialization for backup first. - serializeDeserializeWifiConfigurationForBackupRestore(configuration); - - // Test serialization/deserialization for config store. - serializeDeserializeWifiConfigurationForConfigStore(configuration); - } - - private void serializeDeserializeIpConfiguration(IpConfiguration configuration) - throws IOException, XmlPullParserException { - // Serialize the configuration object. - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - XmlUtil.writeDocumentStart(out, mXmlDocHeader); - IpConfigurationXmlUtil.writeToXml(out, configuration); - XmlUtil.writeDocumentEnd(out, mXmlDocHeader); - - // Deserialize the configuration object. - final XmlPullParser in = Xml.newPullParser(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - XmlUtil.gotoDocumentStart(in, mXmlDocHeader); - IpConfiguration retrievedConfiguration = - IpConfigurationXmlUtil.parseFromXml(in, in.getDepth()); - assertEquals(configuration, retrievedConfiguration); - } - - private byte[] serializeNetworkSelectionStatus(NetworkSelectionStatus status) - throws IOException, XmlPullParserException { - // Serialize the configuration object. - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - XmlUtil.writeDocumentStart(out, mXmlDocHeader); - NetworkSelectionStatusXmlUtil.writeToXml(out, status); - XmlUtil.writeDocumentEnd(out, mXmlDocHeader); - return outputStream.toByteArray(); - } - - private NetworkSelectionStatus deserializeNetworkSelectionStatus(byte[] data) - throws IOException, XmlPullParserException { - final XmlPullParser in = Xml.newPullParser(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - XmlUtil.gotoDocumentStart(in, mXmlDocHeader); - return NetworkSelectionStatusXmlUtil.parseFromXml(in, in.getDepth()); - } - - private void serializeDeserializeNetworkSelectionStatus(NetworkSelectionStatus status) - throws IOException, XmlPullParserException { - // Serialize the status object. - byte[] data = serializeNetworkSelectionStatus(status); - // Deserialize the status object. - NetworkSelectionStatus retrievedStatus = deserializeNetworkSelectionStatus(data); - - WifiConfigurationTestUtil.assertNetworkSelectionStatusEqualForConfigStore( - status, retrievedStatus); - } - - private byte[] serializeWifiEnterpriseConfig(WifiEnterpriseConfig config) - throws IOException, XmlPullParserException { - final XmlSerializer out = new FastXmlSerializer(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - XmlUtil.writeDocumentStart(out, mXmlDocHeader); - WifiEnterpriseConfigXmlUtil.writeToXml( - out, config, mWifiConfigStoreEncryptionUtil); - XmlUtil.writeDocumentEnd(out, mXmlDocHeader); - return outputStream.toByteArray(); - } - - private WifiEnterpriseConfig deserializeWifiEnterpriseConfig(byte[] data) - throws IOException, XmlPullParserException { - final XmlPullParser in = Xml.newPullParser(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(data); - in.setInput(inputStream, StandardCharsets.UTF_8.name()); - XmlUtil.gotoDocumentStart(in, mXmlDocHeader); - return WifiEnterpriseConfigXmlUtil.parseFromXml( - in, in.getDepth(), mWifiConfigStoreEncryptionUtil != null, - mWifiConfigStoreEncryptionUtil); - } - - private void serializeDeserializeWifiEnterpriseConfig(WifiEnterpriseConfig config) - throws IOException, XmlPullParserException { - WifiEnterpriseConfig retrievedConfig = - deserializeWifiEnterpriseConfig(serializeWifiEnterpriseConfig(config)); - WifiConfigurationTestUtil.assertWifiEnterpriseConfigEqualForConfigStore( - config, retrievedConfig); - } -} |